#include "CodeGenerator.hpp"

#include "Error.hpp"

#include <stdio.h>

namespace SoftWire
{
	int CodeGenerator::Variable::stack = 4;

	CodeGenerator *CodeGenerator::cg = 0;

	CodeGenerator::Variable::Variable()
	{
	}

	CodeGenerator::Variable::~Variable()
	{
		cg->free((OperandREF)(esp-reference));

		for(int i = 0; i < 8; i++)
		{
			if(ERX[i].reference.baseReg == Encoding::ESP && -ERX[i].reference.displacement > reference) return;
			if(MM[i].reference.baseReg  == Encoding::ESP && -MM[i].reference.displacement  > reference) return;
			if(XMM[i].reference.baseReg == Encoding::ESP && -XMM[i].reference.displacement > reference) return;
		}
		
		stack = reference;   // Free stack space when allocated at top of stack

		// Reset stack when no more variables allocated
		for(int i = 0; i < 8; i++)
		{
			if(ERX[i].reference.baseReg == Encoding::ESP) return;
			if(MM[i].reference.baseReg  == Encoding::ESP) return;
			if(XMM[i].reference.baseReg == Encoding::ESP) return;
		}

		stack = 4;
	}

	CodeGenerator::Byte::Byte()
	{
		reference = stack;
		stack += 1;
	}

	CodeGenerator::Byte::Byte(char byte)
	{
		reference = stack;
		stack += 1;
		cg->mov(*this, byte);
	}

	CodeGenerator::Byte::Byte(Byte &byte)
	{
		reference = stack;
		stack += 1;
		cg->mov(*this, byte);
	}

	CodeGenerator::Byte::operator OperandREG8() const
	{
		return cg->r8(esp-reference);
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator=(const Byte &byte)
	{
		cg->mov(*this, cg->m8(esp-byte.reference));
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator+=(const Byte &byte)
	{
		cg->add(*this, cg->m8(esp-byte.reference));
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator-=(const Byte &byte)
	{
		cg->sub(*this, cg->m8(esp-byte.reference));
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator*=(const Byte &byte)
	{
		cg->spill(eax);
		cg->mov(al, cg->m8(esp-this->reference));
		cg->imul(byte);
		cg->mov(*this, al);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator/=(const Byte &byte)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(al, cg->m8(esp-this->reference));
		cg->mov(dl, cg->m8(esp-byte.reference));
		cg->idiv(dl);
		cg->mov(*this, al);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator%=(const Byte &byte)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(al, cg->m8(esp-this->reference));
		cg->mov(dl, cg->m8(esp-byte.reference));
		cg->idiv(dl);
		cg->mov(*this, dl);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator<<=(const Byte &byte)
	{
		cg->spill(ecx);
		cg->mov(cl, cg->m8(esp-byte.reference));
		cg->shl(*this, cl);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator>>=(const Byte &byte)
	{
		cg->spill(ecx);
		cg->mov(cl, cg->m8(esp-byte.reference));
		cg->shr(*this, cl);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator&=(const Byte &byte)
	{
		cg->and(*this, cg->m8(esp-byte.reference));
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator^=(const Byte &byte)
	{
		cg->xor(*this, cg->m8(esp-byte.reference));
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator|=(const Byte &byte)
	{
		cg->or(*this, cg->m8(esp-byte.reference));
		return *this;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator+(const Byte &byte)
	{
		Byte temp;
		temp = *this;
		temp += byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator-(const Byte &byte)
	{
		Byte temp;
		temp = *this;
		temp -= byte;
		return temp;		
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator*(const Byte &byte)
	{
		Byte temp;
		temp = *this;
		temp *= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator/(const Byte &byte)
	{
		Byte temp;
		temp = *this;
		temp /= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator%(const Byte &byte)
	{
		Byte temp;
		temp = *this;
		temp %= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator<<(const Byte &byte)
	{
		Byte temp;
		temp = *this;
		temp <<= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator>>(const Byte &byte)
	{
		Byte temp;
		temp = *this;
		temp >>= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator&(const Byte &byte)
	{
		Byte temp;
		temp = *this;
		temp &= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator^(const Byte &byte)
	{
		Byte temp;
		temp = *this;
		temp ^= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator|(const Byte &byte)
	{
		Byte temp;
		temp = *this;
		temp |= byte;
		return temp;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator+=(char byte)
	{
		cg->add(*this, byte);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator-=(char byte)
	{
		cg->sub(*this, byte);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator*=(char byte)
	{
		cg->spill(eax);
		cg->mov(al, *this);
		cg->imul(eax, byte);
		cg->mov(*this, al);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator/=(char byte)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(al, *this);
		cg->mov(dl, byte);
		cg->idiv(dl);
		cg->mov(*this, al);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator%=(char byte)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(al, *this);
		cg->mov(dl, byte);
		cg->idiv(dl);
		cg->mov(*this, dl);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator<<=(char byte)
	{
		cg->spill(ecx);
		cg->spill(edx);
		cg->mov(cl, byte);
		cg->mov(cl, *this);
		cg->shl(*this, cl);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator>>=(char byte)
	{
		cg->spill(ecx);
		cg->spill(edx);
		cg->mov(cl, byte);
		cg->mov(cl, *this);
		cg->shr(*this, cl);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator&=(char byte)
	{
		cg->and(*this, byte);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator^=(char byte)
	{
		cg->xor(*this, byte);
		return *this;
	}

	CodeGenerator::Byte &CodeGenerator::Byte::operator|=(char byte)
	{
		cg->or(*this, byte);
		return *this;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator+(char byte)
	{
		Byte temp;
		temp = *this;
		temp += byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator-(char byte)
	{
		Byte temp;
		temp = *this;
		temp -= byte;
		return temp;		
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator*(char byte)
	{
		Byte temp;
		temp = *this;
		temp *= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator/(char byte)
	{
		Byte temp;
		temp = *this;
		temp /= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator%(char byte)
	{
		Byte temp;
		temp = *this;
		temp %= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator<<(char byte)
	{
		Byte temp;
		temp = *this;
		temp <<= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator>>(char byte)
	{
		Byte temp;
		temp = *this;
		temp >>= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator&(char byte)
	{
		Byte temp;
		temp = *this;
		temp &= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator^(char byte)
	{
		Byte temp;
		temp = *this;
		temp ^= byte;
		return temp;
	}

	CodeGenerator::Byte CodeGenerator::Byte::operator|(char byte)
	{
		Byte temp;
		temp = *this;
		temp |= byte;
		return temp;
	}

	CodeGenerator::Word::Word()
	{
		reference = stack;
		stack = (stack + 3) & ~1;
	}

	CodeGenerator::Word::Word(short word)
	{
		reference = stack;
		stack = (stack + 3) & ~1;
		cg->mov(*this, word);
	}

	CodeGenerator::Word::Word(Word &word)
	{
		reference = stack;
		stack += (stack + 3) & ~1;
		cg->mov(*this, word);
	}

	CodeGenerator::Word::operator OperandREG16() const
	{
		return cg->r16(esp-reference);
	}

	CodeGenerator::Word &CodeGenerator::Word::operator=(const Word &word)
	{
		cg->mov(*this, cg->m16(esp-word.reference));
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator+=(const Word &word)
	{
		cg->add(*this, cg->m16(esp-word.reference));
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator-=(const Word &word)
	{
		cg->sub(*this, cg->m16(esp-word.reference));
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator*=(const Word &word)
	{
		cg->imul(*this, cg->m16(esp-word.reference));
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator/=(const Word &word)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(ax, cg->m16(esp-this->reference));
		cg->mov(dx, cg->m16(esp-word.reference));
		cg->idiv(dx);
		cg->mov(*this, ax);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator%=(const Word &word)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(ax, cg->m16(esp-this->reference));
		cg->mov(dx, cg->m16(esp-word.reference));
		cg->idiv(dx);
		cg->mov(*this, dx);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator<<=(const Word &word)
	{
		cg->spill(ecx);
		cg->mov(cx, cg->m16(esp-word.reference));
		cg->shl(*this, cl);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator>>=(const Word &word)
	{
		cg->spill(ecx);
		cg->mov(cx, cg->m16(esp-word.reference));
		cg->shr(*this, cl);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator&=(const Word &word)
	{
		cg->and(*this, cg->m16(esp-word.reference));
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator^=(const Word &word)
	{
		cg->xor(*this, cg->m16(esp-word.reference));
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator|=(const Word &word)
	{
		cg->or(*this, cg->m16(esp-word.reference));
		return *this;
	}

	CodeGenerator::Word CodeGenerator::Word::operator+(const Word &word)
	{
		Word temp;
		temp = *this;
		temp += word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator-(const Word &word)
	{
		Word temp;
		temp = *this;
		temp -= word;
		return temp;		
	}

	CodeGenerator::Word CodeGenerator::Word::operator*(const Word &word)
	{
		Word temp;
		temp = *this;
		temp *= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator/(const Word &word)
	{
		Word temp;
		temp = *this;
		temp /= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator%(const Word &word)
	{
		Word temp;
		temp = *this;
		temp %= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator<<(const Word &word)
	{
		Word temp;
		temp = *this;
		temp <<= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator>>(const Word &word)
	{
		Word temp;
		temp = *this;
		temp >>= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator&(const Word &word)
	{
		Word temp;
		temp = *this;
		temp &= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator^(const Word &word)
	{
		Word temp;
		temp = *this;
		temp ^= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator|(const Word &word)
	{
		Word temp;
		temp = *this;
		temp |= word;
		return temp;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator+=(short word)
	{
		cg->add(*this, word);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator-=(short word)
	{
		cg->sub(*this, word);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator*=(short word)
	{
		cg->imul(*this, word);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator/=(short word)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(ax, *this);
		cg->mov(dx, word);
		cg->idiv(dx);
		cg->mov(*this, ax);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator%=(short word)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(ax, *this);
		cg->mov(dx, word);
		cg->idiv(dx);
		cg->mov(*this, dx);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator<<=(short word)
	{
		cg->spill(ecx);
		cg->spill(edx);
		cg->mov(cx, word);
		cg->mov(dx, *this);
		cg->shl(*this, cl);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator>>=(short word)
	{
		cg->spill(ecx);
		cg->spill(edx);
		cg->mov(cx, word);
		cg->mov(dx, *this);
		cg->shr(*this, cl);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator&=(short word)
	{
		cg->and(*this, word);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator^=(short word)
	{
		cg->xor(*this, word);
		return *this;
	}

	CodeGenerator::Word &CodeGenerator::Word::operator|=(short word)
	{
		cg->or(*this, word);
		return *this;
	}

	CodeGenerator::Word CodeGenerator::Word::operator+(short word)
	{
		Word temp;
		temp = *this;
		temp += word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator-(short word)
	{
		Word temp;
		temp = *this;
		temp -= word;
		return temp;		
	}

	CodeGenerator::Word CodeGenerator::Word::operator*(short word)
	{
		Word temp;
		temp = *this;
		temp *= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator/(short word)
	{
		Word temp;
		temp = *this;
		temp /= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator%(short word)
	{
		Word temp;
		temp = *this;
		temp %= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator<<(short word)
	{
		Word temp;
		temp = *this;
		temp <<= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator>>(short word)
	{
		Word temp;
		temp = *this;
		temp >>= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator&(short word)
	{
		Word temp;
		temp = *this;
		temp &= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator^(short word)
	{
		Word temp;
		temp = *this;
		temp ^= word;
		return temp;
	}

	CodeGenerator::Word CodeGenerator::Word::operator|(short word)
	{
		Word temp;
		temp = *this;
		temp |= word;
		return temp;
	}

	CodeGenerator::Dword::Dword()
	{
		reference = stack;
		stack = (stack + 7) & ~3;
	}

	CodeGenerator::Dword::Dword(int dword)
	{
		reference = stack;
		stack = (stack + 7) & ~3;
		cg->mov(*this, dword);
	}

	CodeGenerator::Dword::Dword(Dword &dword)
	{
		reference = stack;
		stack += (stack + 7) & ~3;
		cg->mov(*this, dword);
	}

	CodeGenerator::Dword::operator OperandREG32() const
	{
		return cg->r32(esp-reference);
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator=(const Dword &dword)
	{
		cg->mov(*this, cg->m32(esp-dword.reference));
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator+=(const Dword &dword)
	{
		cg->add(*this, cg->m32(esp-dword.reference));
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator-=(const Dword &dword)
	{
		cg->sub(*this, cg->m32(esp-dword.reference));
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator*=(const Dword &dword)
	{
		cg->imul(*this, cg->m32(esp-dword.reference));
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator/=(const Dword &dword)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(eax, cg->m32(esp-this->reference));
		cg->mov(edx, cg->m32(esp-dword.reference));
		cg->idiv(edx);
		cg->mov(*this, eax);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator%=(const Dword &dword)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(eax, cg->m32(esp-this->reference));
		cg->mov(edx, cg->m32(esp-dword.reference));
		cg->idiv(edx);
		cg->mov(*this, edx);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator<<=(const Dword &dword)
	{
		cg->spill(ecx);
		cg->mov(ecx, cg->m32(esp-this->reference));
		cg->shl(*this, cl);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator>>=(const Dword &dword)
	{
		cg->spill(ecx);
		cg->mov(ecx, cg->m32(esp-this->reference));
		cg->shr(*this, cl);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator&=(const Dword &dword)
	{
		cg->and(*this, cg->m32(esp-dword.reference));
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator^=(const Dword &dword)
	{
		cg->xor(*this, cg->m32(esp-dword.reference));
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator|=(const Dword &dword)
	{
		cg->or(*this, cg->m32(esp-dword.reference));
		return *this;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator+(const Dword &dword)
	{
		Dword temp;
		temp = *this;
		temp += dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator-(const Dword &dword)
	{
		Dword temp;
		temp = *this;
		temp -= dword;
		return temp;		
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator*(const Dword &dword)
	{
		Dword temp;
		temp = *this;
		temp *= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator/(const Dword &dword)
	{
		Dword temp;
		temp = *this;
		temp /= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator%(const Dword &dword)
	{
		Dword temp;
		temp = *this;
		temp %= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator<<(const Dword &dword)
	{
		Dword temp;
		temp = *this;
		temp <<= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator>>(const Dword &dword)
	{
		Dword temp;
		temp = *this;
		temp >>= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator&(const Dword &dword)
	{
		Dword temp;
		temp = *this;
		temp &= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator^(const Dword &dword)
	{
		Dword temp;
		temp = *this;
		temp ^= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator|(const Dword &dword)
	{
		Dword temp;
		temp = *this;
		temp |= dword;
		return temp;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator+=(int dword)
	{
		cg->add(*this, dword);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator-=(int dword)
	{
		cg->sub(*this, dword);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator*=(int dword)
	{
		cg->imul(*this, dword);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator/=(int dword)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(eax, *this);
		cg->mov(edx, dword);
		cg->idiv(edx);
		cg->mov(*this, eax);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator%=(int dword)
	{
		cg->spill(eax);
		cg->spill(edx);
		cg->mov(eax, *this);
		cg->mov(edx, dword);
		cg->idiv(edx);
		cg->mov(*this, edx);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator<<=(int dword)
	{
		cg->spill(ecx);
		cg->spill(edx);
		cg->mov(ecx, dword);
		cg->mov(edx, *this);
		cg->shl(*this, cl);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator>>=(int dword)
	{
		cg->spill(ecx);
		cg->spill(edx);
		cg->mov(ecx, dword);
		cg->mov(edx, *this);
		cg->shr(*this, cl);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator&=(int dword)
	{
		cg->and(*this, dword);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator^=(int dword)
	{
		cg->xor(*this, dword);
		return *this;
	}

	CodeGenerator::Dword &CodeGenerator::Dword::operator|=(int dword)
	{
		cg->or(*this, dword);
		return *this;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator+(int dword)
	{
		Dword temp;
		temp = *this;
		temp += dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator-(int dword)
	{
		Dword temp;
		temp = *this;
		temp -= dword;
		return temp;		
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator*(int dword)
	{
		Dword temp;
		temp = *this;
		temp *= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator/(int dword)
	{
		Dword temp;
		temp = *this;
		temp /= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator%(int dword)
	{
		Dword temp;
		temp = *this;
		temp %= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator<<(int dword)
	{
		Dword temp;
		temp = *this;
		temp <<= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator>>(int dword)
	{
		Dword temp;
		temp = *this;
		temp >>= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator&(int dword)
	{
		Dword temp;
		temp = *this;
		temp &= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator^(int dword)
	{
		Dword temp;
		temp = *this;
		temp ^= dword;
		return temp;
	}

	CodeGenerator::Dword CodeGenerator::Dword::operator|(int dword)
	{
		Dword temp;
		temp = *this;
		temp |= dword;
		return temp;
	}

	CodeGenerator::Qword::Qword()
	{
		reference = stack;
		stack = (stack + 15) & ~7;
	}

	CodeGenerator::Qword::Qword(Qword &qword)
	{
		reference = stack;
		stack += (stack + 15) & ~7;
		cg->movq(*this, qword);
	}

	CodeGenerator::Qword::operator OperandMMREG() const
	{
		return cg->r64(esp-reference);
	}

	CodeGenerator::Qword &CodeGenerator::Qword::operator=(const Qword &qword)
	{
		cg->movq(*this, cg->m64(esp-qword.reference));
		return *this;
	}

	CodeGenerator::Qword &CodeGenerator::Qword::operator+=(const Qword &qword)
	{
		cg->paddq(*this, cg->m64(esp-qword.reference));
		return *this;
	}

	CodeGenerator::Qword &CodeGenerator::Qword::operator-=(const Qword &qword)
	{
		cg->psubq(*this, cg->m64(esp-qword.reference));
		return *this;
	}

	CodeGenerator::Qword &CodeGenerator::Qword::operator<<=(const Qword &qword)
	{
		cg->psllq(*this, cg->m64(esp-qword.reference));
		return *this;
	}

	CodeGenerator::Qword &CodeGenerator::Qword::operator&=(const Qword &qword)
	{
		cg->pand(*this, cg->m64(esp-qword.reference));
		return *this;
	}

	CodeGenerator::Qword &CodeGenerator::Qword::operator^=(const Qword &qword)
	{
		cg->pxor(*this, cg->m64(esp-qword.reference));
		return *this;
	}

	CodeGenerator::Qword &CodeGenerator::Qword::operator|=(const Qword &qword)
	{
		cg->por(*this, cg->m64(esp-qword.reference));
		return *this;
	}

	CodeGenerator::Qword CodeGenerator::Qword::operator+(const Qword &qword)
	{
		Qword temp;
		temp = *this;
		temp += qword;
		return temp;
	}

	CodeGenerator::Qword CodeGenerator::Qword::operator-(const Qword &qword)
	{
		Qword temp;
		temp = *this;
		temp -= qword;
		return temp;
	}

	CodeGenerator::Qword CodeGenerator::Qword::operator<<(const Qword &qword)
	{
		Qword temp;
		temp = *this;
		temp <<= qword;
		return temp;
	}

	CodeGenerator::Qword CodeGenerator::Qword::operator&(const Qword &qword)
	{
		Qword temp;
		temp = *this;
		temp &= qword;
		return temp;
	}

	CodeGenerator::Qword CodeGenerator::Qword::operator^(const Qword &qword)
	{
		Qword temp;
		temp = *this;
		temp ^= qword;
		return temp;
	}

	CodeGenerator::Qword CodeGenerator::Qword::operator|(const Qword &qword)
	{
		Qword temp;
		temp = *this;
		temp |= qword;
		return temp;
	}

	CodeGenerator::Qword &CodeGenerator::Qword::operator<<=(char imm)
	{
		cg->psllq(*this, imm);
		return *this;
	}

	CodeGenerator::Qword CodeGenerator::Qword::operator<<(char imm)
	{
		Qword temp;
		temp = *this;
		temp <<= imm;
		return temp;
	}

	CodeGenerator::Word4::Word4()
	{
		reference = stack;
		stack = (stack + 15) & ~7;
	}

	CodeGenerator::Word4::Word4(Word4 &word4)
	{
		reference = stack;
		stack += (stack + 15) & ~7;
		cg->movq(*this, word4);
	}

	CodeGenerator::Word4::operator OperandMMREG() const
	{
		return cg->r64(esp-reference);
	}

	CodeGenerator::Word4 &CodeGenerator::Word4::operator=(const Word4 &word4)
	{
		cg->movq(*this, cg->m64(esp-word4.reference));
		return *this;
	}

	CodeGenerator::Word4 &CodeGenerator::Word4::operator+=(const Word4 &word4)
	{
		cg->paddw(*this, cg->m64(esp-word4.reference));
		return *this;
	}

	CodeGenerator::Word4 &CodeGenerator::Word4::operator-=(const Word4 &word4)
	{
		cg->psubw(*this, cg->m64(esp-word4.reference));
		return *this;
	}

	CodeGenerator::Word4 &CodeGenerator::Word4::operator<<=(const Qword &qword)
	{
		cg->psllw(*this, cg->m64(esp-qword.reference));
		return *this;
	}

	CodeGenerator::Word4 &CodeGenerator::Word4::operator>>=(const Qword &qword)
	{
		cg->psraw(*this, cg->m64(esp-qword.reference));
		return *this;
	}

	CodeGenerator::Word4 &CodeGenerator::Word4::operator&=(const Word4 &word4)
	{
		cg->pand(*this, cg->m64(esp-word4.reference));
		return *this;
	}

	CodeGenerator::Word4 &CodeGenerator::Word4::operator^=(const Word4 &word4)
	{
		cg->pxor(*this, cg->m64(esp-word4.reference));
		return *this;
	}

	CodeGenerator::Word4 &CodeGenerator::Word4::operator|=(const Word4 &word4)
	{
		cg->por(*this, cg->m64(esp-word4.reference));
		return *this;
	}

	CodeGenerator::Word4 CodeGenerator::Word4::operator+(const Word4 &word4)
	{
		Word4 temp;
		temp = *this;
		temp += word4;
		return temp;
	}

	CodeGenerator::Word4 CodeGenerator::Word4::operator-(const Word4 &word4)
	{
		Word4 temp;
		temp = *this;
		temp -= word4;
		return temp;
	}

	CodeGenerator::Word4 CodeGenerator::Word4::operator<<(const Qword &qword)
	{
		Word4 temp;
		temp = *this;
		temp <<= qword;
		return temp;
	}

	CodeGenerator::Word4 CodeGenerator::Word4::operator>>(const Qword &qword)
	{
		Word4 temp;
		temp = *this;
		temp >>= qword;
		return temp;
	}

	CodeGenerator::Word4 CodeGenerator::Word4::operator&(const Word4 &word4)
	{
		Word4 temp;
		temp = *this;
		temp &= word4;
		return temp;
	}

	CodeGenerator::Word4 CodeGenerator::Word4::operator^(const Word4 &word4)
	{
		Word4 temp;
		temp = *this;
		temp ^= word4;
		return temp;
	}

	CodeGenerator::Word4 CodeGenerator::Word4::operator|(const Word4 &word4)
	{
		Word4 temp;
		temp = *this;
		temp |= word4;
		return temp;
	}

	CodeGenerator::Word4 &CodeGenerator::Word4::operator<<=(char imm)
	{
		cg->psllw(*this, imm);
		return *this;
	}

	CodeGenerator::Word4 &CodeGenerator::Word4::operator>>=(char imm)
	{
		cg->psraw(*this, imm);
		return *this;
	}

	CodeGenerator::Word4 CodeGenerator::Word4::operator<<(char imm)
	{
		Word4 temp;
		temp = *this;
		temp <<= imm;
		return temp;
	}

	CodeGenerator::Word4 CodeGenerator::Word4::operator>>(char imm)
	{
		Word4 temp;
		temp = *this;
		temp >>= imm;
		return temp;
	}

	CodeGenerator::Dword2::Dword2()
	{
		reference = stack;
		stack = (stack + 15) & ~7;
	}

	CodeGenerator::Dword2::Dword2(Dword2 &dword2)
	{
		reference = stack;
		stack += (stack + 15) & ~7;
		cg->movq(*this, dword2);
	}

	CodeGenerator::Dword2::operator OperandMMREG() const
	{
		return cg->r64(esp-reference);
	}

	CodeGenerator::Dword2 &CodeGenerator::Dword2::operator=(const Dword2 &dword2)
	{
		cg->movq(*this, cg->m64(esp-dword2.reference));
		return *this;
	}

	CodeGenerator::Dword2 &CodeGenerator::Dword2::operator+=(const Dword2 &dword2)
	{
		cg->paddd(*this, cg->m64(esp-dword2.reference));
		return *this;
	}

	CodeGenerator::Dword2 &CodeGenerator::Dword2::operator-=(const Dword2 &dword2)
	{
		cg->psubd(*this, cg->m64(esp-dword2.reference));
		return *this;
	}

	CodeGenerator::Dword2 &CodeGenerator::Dword2::operator<<=(const Qword &qword)
	{
		cg->pslld(*this, cg->m64(esp-qword.reference));
		return *this;
	}

	CodeGenerator::Dword2 &CodeGenerator::Dword2::operator>>=(const Qword &qword)
	{
		cg->psrad(*this, cg->m64(esp-qword.reference));
		return *this;
	}

	CodeGenerator::Dword2 &CodeGenerator::Dword2::operator&=(const Dword2 &dword2)
	{
		cg->pand(*this, cg->m64(esp-dword2.reference));
		return *this;
	}

	CodeGenerator::Dword2 &CodeGenerator::Dword2::operator^=(const Dword2 &dword2)
	{
		cg->pxor(*this, cg->m64(esp-dword2.reference));
		return *this;
	}

	CodeGenerator::Dword2 &CodeGenerator::Dword2::operator|=(const Dword2 &dword2)
	{
		cg->por(*this, cg->m64(esp-dword2.reference));
		return *this;
	}

	CodeGenerator::Dword2 CodeGenerator::Dword2::operator+(const Dword2 &dword2)
	{
		Dword2 temp;
		temp = *this;
		temp += dword2;
		return temp;
	}

	CodeGenerator::Dword2 CodeGenerator::Dword2::operator-(const Dword2 &dword2)
	{
		Dword2 temp;
		temp = *this;
		temp -= dword2;
		return temp;
	}

	CodeGenerator::Dword2 CodeGenerator::Dword2::operator<<(const Qword &qword)
	{
		Dword2 temp;
		temp = *this;
		temp <<= qword;
		return temp;
	}

	CodeGenerator::Dword2 CodeGenerator::Dword2::operator>>(const Qword &qword)
	{
		Dword2 temp;
		temp = *this;
		temp >>= qword;
		return temp;
	}

	CodeGenerator::Dword2 CodeGenerator::Dword2::operator&(const Dword2 &dword2)
	{
		Dword2 temp;
		temp = *this;
		temp &= dword2;
		return temp;
	}

	CodeGenerator::Dword2 CodeGenerator::Dword2::operator^(const Dword2 &dword2)
	{
		Dword2 temp;
		temp = *this;
		temp ^= dword2;
		return temp;
	}

	CodeGenerator::Dword2 CodeGenerator::Dword2::operator|(const Dword2 &dword2)
	{
		Dword2 temp;
		temp = *this;
		temp |= dword2;
		return temp;
	}

	CodeGenerator::Dword2 &CodeGenerator::Dword2::operator<<=(char imm)
	{
		cg->pslld(*this, imm);
		return *this;
	}

	CodeGenerator::Dword2 &CodeGenerator::Dword2::operator>>=(char imm)
	{
		cg->psrad(*this, imm);
		return *this;
	}

	CodeGenerator::Dword2 CodeGenerator::Dword2::operator<<(char imm)
	{
		Dword2 temp;
		temp = *this;
		temp <<= imm;
		return temp;
	}

	CodeGenerator::Dword2 CodeGenerator::Dword2::operator>>(char imm)
	{
		Dword2 temp;
		temp = *this;
		temp >>= imm;
		return temp;
	}

	CodeGenerator::Float::Float()
	{
		reference = stack;
		stack = (stack + 7) & ~3;
	}

	CodeGenerator::Float::Float(Float &f)
	{
		reference = stack;
		stack += (stack + 7) & ~3;
		cg->movss(*this, f);
	}

	CodeGenerator::Float::operator OperandXMMREG() const
	{
		return cg->rSS(esp-reference);
	}

	CodeGenerator::Float &CodeGenerator::Float::operator=(const Float &f)
	{
		cg->movss(*this, cg->mSS(esp-f.reference));
		return *this;
	}

	CodeGenerator::Float &CodeGenerator::Float::operator+=(const Float &f)
	{
		cg->movss(*this, cg->mSS(esp-f.reference));
		return *this;
	}

	CodeGenerator::Float &CodeGenerator::Float::operator-=(const Float &f)
	{
		cg->subss(*this, cg->mSS(esp-f.reference));
		return *this;
	}

	CodeGenerator::Float &CodeGenerator::Float::operator*=(const Float &f)
	{
		cg->mulss(*this, cg->mSS(esp-f.reference));
		return *this;
	}

	CodeGenerator::Float &CodeGenerator::Float::operator/=(const Float &f)
	{
		cg->divss(*this, cg->mSS(esp-f.reference));
		return *this;
	}

	CodeGenerator::Float CodeGenerator::Float::operator+(const Float &f)
	{
		Float temp;
		temp = *this;
		temp += f;
		return temp;
	}

	CodeGenerator::Float CodeGenerator::Float::operator-(const Float &f)
	{
		Float temp;
		temp = *this;
		temp -= f;
		return temp;
	}

	CodeGenerator::Float CodeGenerator::Float::operator*(const Float &f)
	{
		Float temp;
		temp = *this;
		temp *= f;
		return temp;
	}

	CodeGenerator::Float CodeGenerator::Float::operator/(const Float &f)
	{
		Float temp;
		temp = *this;
		temp /= f;
		return temp;
	}

	CodeGenerator::Float4::Float4()
	{
		reference = stack;
		stack = (stack + 31) & ~15;
	}

	CodeGenerator::Float4::Float4(Float4 &float4)
	{
		reference = stack;
		stack += (stack + 31) & ~15;
		cg->movaps(*this, float4);
	}

	CodeGenerator::Float4::operator OperandXMMREG() const
	{
		return cg->r128(esp-reference);
	}

	CodeGenerator::Float4 &CodeGenerator::Float4::operator=(const Float4 &float4)
	{
		cg->movaps(*this, cg->m128(esp-float4.reference));
		return *this;
	}

	CodeGenerator::Float4 &CodeGenerator::Float4::operator+=(const Float4 &float4)
	{
		cg->addps(*this, cg->m128(esp-float4.reference));
		return *this;
	}

	CodeGenerator::Float4 &CodeGenerator::Float4::operator-=(const Float4 &float4)
	{
		cg->subps(*this, cg->m128(esp-float4.reference));
		return *this;
	}

	CodeGenerator::Float4 &CodeGenerator::Float4::operator*=(const Float4 &float4)
	{
		cg->mulps(*this, cg->m128(esp-float4.reference));
		return *this;
	}

	CodeGenerator::Float4 &CodeGenerator::Float4::operator/=(const Float4 &float4)
	{
		cg->divps(*this, cg->m128(esp-float4.reference));
		return *this;
	}

	CodeGenerator::Float4 &CodeGenerator::Float4::operator&=(const Float4 &float4)
	{
		cg->andps(*this, cg->m128(esp-float4.reference));
		return *this;
	}

	CodeGenerator::Float4 &CodeGenerator::Float4::operator^=(const Float4 &float4)
	{
		cg->xorps(*this, cg->m128(esp-float4.reference));
		return *this;
	}

	CodeGenerator::Float4 &CodeGenerator::Float4::operator|=(const Float4 &float4)
	{
		cg->orps(*this, cg->m128(esp-float4.reference));
		return *this;
	}

	CodeGenerator::Float4 CodeGenerator::Float4::operator+(const Float4 &float4)
	{
		Float4 temp;
		temp = *this;
		temp += float4;
		return temp;
	}

	CodeGenerator::Float4 CodeGenerator::Float4::operator-(const Float4 &float4)
	{
		Float4 temp;
		temp = *this;
		temp -= float4;
		return temp;
	}

	CodeGenerator::Float4 CodeGenerator::Float4::operator*(const Float4 &float4)
	{
		Float4 temp;
		temp = *this;
		temp *= float4;
		return temp;
	}

	CodeGenerator::Float4 CodeGenerator::Float4::operator/(const Float4 &float4)
	{
		Float4 temp;
		temp = *this;
		temp /= float4;
		return temp;
	}

	CodeGenerator::Float4 CodeGenerator::Float4::operator&(const Float4 &float4)
	{
		Float4 temp;
		temp = *this;
		temp &= float4;
		return temp;
	}
	
	CodeGenerator::Float4 CodeGenerator::Float4::operator^(const Float4 &float4)
	{
		Float4 temp;
		temp = *this;
		temp ^= float4;
		return temp;
	}

	CodeGenerator::Float4 CodeGenerator::Float4::operator|(const Float4 &float4)
	{
		Float4 temp;
		temp = *this;
		temp |= float4;
		return temp;
	}

	CodeGenerator::CodeGenerator()
	{
		cg = this;
	}

	CodeGenerator::~CodeGenerator()
	{
	}

	Encoding *CodeGenerator::x86(int instructionID, const Operand &firstOperand, const Operand &secondOperand, const Operand &thirdOperand)
	{
		cg = this;

		return Emulator::x86(instructionID, firstOperand, secondOperand, thirdOperand);
	}
}
