1 #include <functional>
2 #include <array>
3 #include <assert.h>
4 #include <stdexcept>
5 #include "Jitter_CodeGen_x86.h"
6 
7 //Check if CPUID is available
8 #ifdef _WIN32
9 #define HAS_CPUID
10 #define HAS_CPUID_MSVC
11 #include <intrin.h>
12 #endif
13 
14 #if defined(__linux__)
15 #if defined(__i386__) || defined(__x86_64__)
16 #define HAS_CPUID
17 #define HAS_CPUID_GCC
18 #include <cpuid.h>
19 #endif
20 #endif
21 
22 #if defined(__APPLE__)
23 #include <TargetConditionals.h>
24 #if TARGET_CPU_X86 || TARGET_CPU_X86_64
25 #define HAS_CPUID
26 #define HAS_CPUID_GCC
27 #include <cpuid.h>
28 #endif
29 #endif
30 
31 using namespace Jitter;
32 
33 #include "Jitter_CodeGen_x86_Alu.h"
34 #include "Jitter_CodeGen_x86_Shift.h"
35 #include "Jitter_CodeGen_x86_Mul.h"
36 #include "Jitter_CodeGen_x86_Div.h"
37 
38 CX86Assembler::REGISTER CCodeGen_x86::g_baseRegister = CX86Assembler::rBP;
39 
40 CCodeGen_x86::CONSTMATCHER CCodeGen_x86::g_constMatchers[] =
41 {
42 	{ OP_LABEL, MATCH_NIL, MATCH_NIL, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::MarkLabel  },
43 
44 	{ OP_NOP,   MATCH_NIL, MATCH_NIL, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Nop   },
45 	{ OP_BREAK, MATCH_NIL, MATCH_NIL, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Break },
46 
47 	ALU_CONST_MATCHERS(OP_ADD, ALUOP_ADD)
48 	ALU_CONST_MATCHERS(OP_SUB, ALUOP_SUB)
49 	ALU_CONST_MATCHERS(OP_AND, ALUOP_AND)
50 	ALU_CONST_MATCHERS(OP_OR,  ALUOP_OR)
51 	ALU_CONST_MATCHERS(OP_XOR, ALUOP_XOR)
52 
53 	{ OP_NOT, MATCH_REGISTER, MATCH_REGISTER, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Not_RegReg },
54 	{ OP_NOT, MATCH_REGISTER, MATCH_MEMORY,   MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Not_RegMem },
55 	{ OP_NOT, MATCH_MEMORY,   MATCH_REGISTER, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Not_MemReg },
56 	{ OP_NOT, MATCH_MEMORY,   MATCH_MEMORY,   MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Not_MemMem },
57 
58 	{ OP_LZC, MATCH_REGISTER, MATCH_VARIABLE, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Lzc_RegVar },
59 	{ OP_LZC, MATCH_MEMORY,   MATCH_VARIABLE, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Lzc_MemVar },
60 
61 	SHIFT_CONST_MATCHERS(OP_SRL, SHIFTOP_SRL)
62 	SHIFT_CONST_MATCHERS(OP_SRA, SHIFTOP_SRA)
63 	SHIFT_CONST_MATCHERS(OP_SLL, SHIFTOP_SLL)
64 
65 	{ OP_MOV, MATCH_REGISTER, MATCH_REGISTER, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Mov_RegReg },
66 	{ OP_MOV, MATCH_REGISTER, MATCH_MEMORY,   MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Mov_RegMem },
67 	{ OP_MOV, MATCH_REGISTER, MATCH_CONSTANT, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Mov_RegCst },
68 	{ OP_MOV, MATCH_MEMORY,   MATCH_REGISTER, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Mov_MemReg },
69 	{ OP_MOV, MATCH_MEMORY,   MATCH_MEMORY,   MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Mov_MemMem },
70 	{ OP_MOV, MATCH_MEMORY,   MATCH_CONSTANT, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Mov_MemCst },
71 
72 	{ OP_JMP, MATCH_NIL, MATCH_NIL, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Jmp },
73 
74 	{ OP_CONDJMP, MATCH_NIL, MATCH_REGISTER, MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_CondJmp_RegReg },
75 	{ OP_CONDJMP, MATCH_NIL, MATCH_REGISTER, MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_CondJmp_RegMem },
76 	{ OP_CONDJMP, MATCH_NIL, MATCH_REGISTER, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_CondJmp_RegCst },
77 	{ OP_CONDJMP, MATCH_NIL, MATCH_MEMORY,   MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_CondJmp_MemMem },
78 	{ OP_CONDJMP, MATCH_NIL, MATCH_MEMORY,   MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_CondJmp_MemCst },
79 
80 	{ OP_DIV, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64RegReg<false> },
81 	{ OP_DIV, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64RegMem<false> },
82 	{ OP_DIV, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64RegCst<false> },
83 	{ OP_DIV, MATCH_TEMPORARY64, MATCH_MEMORY,   MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64MemReg<false> },
84 	{ OP_DIV, MATCH_TEMPORARY64, MATCH_MEMORY,   MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64MemMem<false> },
85 	{ OP_DIV, MATCH_TEMPORARY64, MATCH_MEMORY,   MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64MemCst<false> },
86 	{ OP_DIV, MATCH_TEMPORARY64, MATCH_CONSTANT, MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64CstReg<false> },
87 	{ OP_DIV, MATCH_TEMPORARY64, MATCH_CONSTANT, MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64CstMem<false> },
88 
89 	{ OP_DIVS, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64RegReg<true> },
90 	{ OP_DIVS, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64RegMem<true> },
91 	{ OP_DIVS, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64RegCst<true> },
92 	{ OP_DIVS, MATCH_TEMPORARY64, MATCH_MEMORY,   MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64MemReg<true> },
93 	{ OP_DIVS, MATCH_TEMPORARY64, MATCH_MEMORY,   MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64MemMem<true> },
94 	{ OP_DIVS, MATCH_TEMPORARY64, MATCH_MEMORY,   MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64MemCst<true> },
95 	{ OP_DIVS, MATCH_TEMPORARY64, MATCH_CONSTANT, MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64CstReg<true> },
96 	{ OP_DIVS, MATCH_TEMPORARY64, MATCH_CONSTANT, MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_DivTmp64CstMem<true> },
97 
98 	{ OP_MUL, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_MulTmp64RegReg<false> },
99 	{ OP_MUL, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_MulTmp64RegMem<false> },
100 	{ OP_MUL, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_MulTmp64RegCst<false> },
101 	{ OP_MUL, MATCH_TEMPORARY64, MATCH_MEMORY,   MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_MulTmp64MemMem<false> },
102 	{ OP_MUL, MATCH_TEMPORARY64, MATCH_MEMORY,   MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_MulTmp64MemCst<false> },
103 
104 	{ OP_MULS, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_MulTmp64RegReg<true> },
105 	{ OP_MULS, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_MulTmp64RegMem<true> },
106 	{ OP_MULS, MATCH_TEMPORARY64, MATCH_REGISTER, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_MulTmp64RegCst<true> },
107 	{ OP_MULS, MATCH_TEMPORARY64, MATCH_MEMORY,   MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_MulTmp64MemMem<true> },
108 	{ OP_MULS, MATCH_TEMPORARY64, MATCH_MEMORY,   MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_MulTmp64MemCst<true> },
109 
110 	{ OP_MERGETO64, MATCH_MEMORY64, MATCH_REGISTER, MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_MergeTo64_Mem64RegReg },
111 	{ OP_MERGETO64, MATCH_MEMORY64, MATCH_REGISTER, MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_MergeTo64_Mem64RegMem },
112 	{ OP_MERGETO64, MATCH_MEMORY64, MATCH_MEMORY,   MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_MergeTo64_Mem64MemReg },
113 	{ OP_MERGETO64, MATCH_MEMORY64, MATCH_MEMORY,   MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_MergeTo64_Mem64MemMem },
114 	{ OP_MERGETO64, MATCH_MEMORY64, MATCH_CONSTANT, MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86::Emit_MergeTo64_Mem64CstReg },
115 	{ OP_MERGETO64, MATCH_MEMORY64, MATCH_CONSTANT, MATCH_MEMORY,   MATCH_NIL, &CCodeGen_x86::Emit_MergeTo64_Mem64CstMem },
116 
117 	{ OP_EXTLOW64, MATCH_REGISTER, MATCH_TEMPORARY64, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_ExtLow64RegTmp64 },
118 	{ OP_EXTLOW64, MATCH_MEMORY,   MATCH_TEMPORARY64, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_ExtLow64MemTmp64 },
119 
120 	{ OP_EXTHIGH64, MATCH_REGISTER, MATCH_TEMPORARY64, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_ExtHigh64RegTmp64 },
121 	{ OP_EXTHIGH64, MATCH_MEMORY,   MATCH_TEMPORARY64, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_ExtHigh64MemTmp64 },
122 
123 	{ OP_LOADFROMREF, MATCH_VARIABLE,    MATCH_VAR_REF, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_LoadFromRef_VarVar    },
124 	{ OP_LOADFROMREF, MATCH_REGISTER128, MATCH_VAR_REF, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_LoadFromRef_Md_RegVar },
125 	{ OP_LOADFROMREF, MATCH_MEMORY128,   MATCH_VAR_REF, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_LoadFromRef_Md_MemVar },
126 
127 	{ OP_LOADFROMREFIDX, MATCH_VARIABLE, MATCH_VAR_REF, MATCH_VARIABLE, MATCH_NIL, &CCodeGen_x86::Emit_LoadFromRefIdx_VarVarVar },
128 	{ OP_LOADFROMREFIDX, MATCH_VARIABLE, MATCH_VAR_REF, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_LoadFromRefIdx_VarVarCst },
129 
130 	{ OP_LOAD8FROMREF, MATCH_VARIABLE, MATCH_VAR_REF, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Load8FromRef_VarVar },
131 
132 	{ OP_LOAD16FROMREF, MATCH_VARIABLE, MATCH_VAR_REF, MATCH_NIL, MATCH_NIL, &CCodeGen_x86::Emit_Load16FromRef_VarVar },
133 
134 	{ OP_STOREATREF, MATCH_NIL, MATCH_VAR_REF, MATCH_VARIABLE,    MATCH_NIL, &CCodeGen_x86::Emit_StoreAtRef_VarVar    },
135 	{ OP_STOREATREF, MATCH_NIL, MATCH_VAR_REF, MATCH_CONSTANT,    MATCH_NIL, &CCodeGen_x86::Emit_StoreAtRef_VarCst    },
136 	{ OP_STOREATREF, MATCH_NIL, MATCH_VAR_REF, MATCH_REGISTER128, MATCH_NIL, &CCodeGen_x86::Emit_StoreAtRef_Md_VarReg },
137 	{ OP_STOREATREF, MATCH_NIL, MATCH_VAR_REF, MATCH_MEMORY128,   MATCH_NIL, &CCodeGen_x86::Emit_StoreAtRef_Md_VarMem },
138 
139 	{ OP_STOREATREFIDX, MATCH_NIL, MATCH_VAR_REF, MATCH_VARIABLE, MATCH_VARIABLE, &CCodeGen_x86::Emit_StoreAtRefIdx_VarVarVar },
140 	{ OP_STOREATREFIDX, MATCH_NIL, MATCH_VAR_REF, MATCH_VARIABLE, MATCH_CONSTANT, &CCodeGen_x86::Emit_StoreAtRefIdx_VarVarCst },
141 	{ OP_STOREATREFIDX, MATCH_NIL, MATCH_VAR_REF, MATCH_CONSTANT, MATCH_VARIABLE, &CCodeGen_x86::Emit_StoreAtRefIdx_VarCstVar },
142 	{ OP_STOREATREFIDX, MATCH_NIL, MATCH_VAR_REF, MATCH_CONSTANT, MATCH_CONSTANT, &CCodeGen_x86::Emit_StoreAtRefIdx_VarCstCst },
143 
144 	{ OP_STORE8ATREF, MATCH_NIL, MATCH_VAR_REF, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_Store8AtRef_VarCst },
145 
146 	{ OP_STORE16ATREF, MATCH_NIL, MATCH_VAR_REF, MATCH_VARIABLE, MATCH_NIL, &CCodeGen_x86::Emit_Store16AtRef_VarVar },
147 	{ OP_STORE16ATREF, MATCH_NIL, MATCH_VAR_REF, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86::Emit_Store16AtRef_VarCst },
148 
149 	{ OP_MOV, MATCH_NIL, MATCH_NIL, MATCH_NIL, MATCH_NIL, nullptr },
150 };
151 
CCodeGen_x86()152 CCodeGen_x86::CCodeGen_x86()
153 {
154 	SetGenerationFlags();
155 
156 	InsertMatchers(g_constMatchers);
157 	InsertMatchers(g_fpuConstMatchers);
158 
159 	if(m_hasAvx)
160 	{
161 		InsertMatchers(g_fpuAvxConstMatchers);
162 		InsertMatchers(g_mdAvxConstMatchers);
163 	}
164 	else
165 	{
166 		InsertMatchers(g_fpuSseConstMatchers);
167 		InsertMatchers(g_mdConstMatchers);
168 
169 		if(m_hasSsse3)
170 		{
171 			InsertMatchers(g_mdFpFlagSsse3ConstMatchers);
172 		}
173 		else
174 		{
175 			InsertMatchers(g_mdFpFlagConstMatchers);
176 		}
177 
178 		if(m_hasSse41)
179 		{
180 			InsertMatchers(g_mdMinMaxWSse41ConstMatchers);
181 			InsertMatchers(g_mdMovMaskedSse41ConstMatchers);
182 		}
183 		else
184 		{
185 			InsertMatchers(g_mdMinMaxWConstMatchers);
186 			InsertMatchers(g_mdMovMaskedConstMatchers);
187 		}
188 	}
189 }
190 
GenerateCode(const StatementList & statements,unsigned int stackSize)191 void CCodeGen_x86::GenerateCode(const StatementList& statements, unsigned int stackSize)
192 {
193 	assert(m_registers != nullptr);
194 	assert(m_mdRegisters != nullptr);
195 	assert(m_labels.empty());
196 
197 	m_registerUsage = GetRegisterUsage(statements);
198 
199 	//Align stacksize
200 	stackSize = (stackSize + 0xF) & ~0xF;
201 	m_stackLevel = 0;
202 
203 	m_assembler.Begin();
204 	{
205 		CX86Assembler::LABEL rootLabel = m_assembler.CreateLabel();
206 		m_assembler.MarkLabel(rootLabel);
207 
208 		Emit_Prolog(statements, stackSize);
209 
210 		for(const auto& statement : statements)
211 		{
212 			bool found = false;
213 			auto begin = m_matchers.lower_bound(statement.op);
214 			auto end = m_matchers.upper_bound(statement.op);
215 
216 			for(auto matchIterator(begin); matchIterator != end; matchIterator++)
217 			{
218 				const auto& matcher(matchIterator->second);
219 				if(!SymbolMatches(matcher.dstType, statement.dst)) continue;
220 				if(!SymbolMatches(matcher.src1Type, statement.src1)) continue;
221 				if(!SymbolMatches(matcher.src2Type, statement.src2)) continue;
222 				if(!SymbolMatches(matcher.src3Type, statement.src3)) continue;
223 				matcher.emitter(statement);
224 				found = true;
225 				break;
226 			}
227 			assert(found);
228 			if(!found)
229 			{
230 				throw std::exception();
231 			}
232 		}
233 
234 		Emit_Epilog();
235 		m_assembler.Ret();
236 	}
237 	m_assembler.End();
238 
239 	if(m_externalSymbolReferencedHandler)
240 	{
241 		for(const auto& symbolRefLabel : m_symbolReferenceLabels)
242 		{
243 			uint32 offset = m_assembler.GetLabelOffset(symbolRefLabel.second);
244 			m_externalSymbolReferencedHandler(symbolRefLabel.first, offset, CCodeGen::SYMBOL_REF_TYPE::NATIVE_POINTER);
245 		}
246 	}
247 
248 	m_labels.clear();
249 	m_symbolReferenceLabels.clear();
250 }
251 
InsertMatchers(const CONSTMATCHER * constMatchers)252 void CCodeGen_x86::InsertMatchers(const CONSTMATCHER* constMatchers)
253 {
254 	for(auto* constMatcher = constMatchers; constMatcher->emitter != nullptr; constMatcher++)
255 	{
256 		MATCHER matcher;
257 		matcher.op       = constMatcher->op;
258 		matcher.dstType  = constMatcher->dstType;
259 		matcher.src1Type = constMatcher->src1Type;
260 		matcher.src2Type = constMatcher->src2Type;
261 		matcher.src3Type = constMatcher->src3Type;
262 		matcher.emitter  = std::bind(constMatcher->emitter, this, std::placeholders::_1);
263 		m_matchers.insert(MatcherMapType::value_type(matcher.op, matcher));
264 	}
265 }
266 
SetGenerationFlags()267 void CCodeGen_x86::SetGenerationFlags()
268 {
269 	static const uint32 CPUID_FLAG_SSSE3 = 0x000200;
270 	static const uint32 CPUID_FLAG_SSE41 = 0x080000;
271 	static const uint32 CPUID_FLAG_AVX = 0x10000000;
272 
273 #ifdef HAS_CPUID
274 
275 #ifdef HAS_CPUID_MSVC
276 	std::array<int, 4> cpuInfo;
277 	__cpuid(cpuInfo.data(), 1);
278 #endif //HAS_CPUID_MSVC
279 
280 #ifdef HAS_CPUID_GCC
281 	std::array<unsigned int, 4> cpuInfo;
282 	__get_cpuid(1, &cpuInfo[0], &cpuInfo[1], &cpuInfo[2], &cpuInfo[3]);
283 #endif //HAS_CPUID_GCC
284 
285 	m_hasSsse3 = (cpuInfo[2] & CPUID_FLAG_SSSE3) != 0;
286 	m_hasSse41 = (cpuInfo[2] & CPUID_FLAG_SSE41) != 0;
287 	m_hasAvx = (cpuInfo[2] & CPUID_FLAG_AVX) != 0;
288 
289 #endif //HAS_CPUID
290 
291 }
292 
SetStream(Framework::CStream * stream)293 void CCodeGen_x86::SetStream(Framework::CStream* stream)
294 {
295 	m_assembler.SetStream(stream);
296 }
297 
RegisterExternalSymbols(CObjectFile *) const298 void CCodeGen_x86::RegisterExternalSymbols(CObjectFile*) const
299 {
300 	//Nothing to register
301 }
302 
GetLabel(uint32 blockId)303 CX86Assembler::LABEL CCodeGen_x86::GetLabel(uint32 blockId)
304 {
305 	CX86Assembler::LABEL result;
306 	LabelMapType::const_iterator labelIterator(m_labels.find(blockId));
307 	if(labelIterator == m_labels.end())
308 	{
309 		result = m_assembler.CreateLabel();
310 		m_labels[blockId] = result;
311 	}
312 	else
313 	{
314 		result = labelIterator->second;
315 	}
316 	return result;
317 }
318 
MakeTemporarySymbolAddress(CSymbol * symbol)319 CX86Assembler::CAddress CCodeGen_x86::MakeTemporarySymbolAddress(CSymbol* symbol)
320 {
321 	assert(symbol->m_type == SYM_TEMPORARY);
322 	assert(((symbol->m_stackLocation + m_stackLevel) & 3) == 0);
323 	return CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, symbol->m_stackLocation + m_stackLevel);
324 }
325 
MakeRelativeSymbolAddress(CSymbol * symbol)326 CX86Assembler::CAddress CCodeGen_x86::MakeRelativeSymbolAddress(CSymbol* symbol)
327 {
328 	assert(symbol->m_type == SYM_RELATIVE);
329 	assert((symbol->m_valueLow & 3) == 0);
330 	return CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rBP, symbol->m_valueLow);
331 }
332 
MakeMemorySymbolAddress(CSymbol * symbol)333 CX86Assembler::CAddress CCodeGen_x86::MakeMemorySymbolAddress(CSymbol* symbol)
334 {
335 	switch(symbol->m_type)
336 	{
337 	case SYM_RELATIVE:
338 		return MakeRelativeSymbolAddress(symbol);
339 		break;
340 	case SYM_TEMPORARY:
341 		return MakeTemporarySymbolAddress(symbol);
342 		break;
343 	default:
344 		throw std::exception();
345 		break;
346 	}
347 }
348 
MakeVariableSymbolAddress(CSymbol * symbol)349 CX86Assembler::CAddress CCodeGen_x86::MakeVariableSymbolAddress(CSymbol* symbol)
350 {
351 	switch(symbol->m_type)
352 	{
353 	case SYM_REGISTER:
354 		return CX86Assembler::MakeRegisterAddress(m_registers[symbol->m_valueLow]);
355 		break;
356 	case SYM_RELATIVE:
357 		return MakeRelativeSymbolAddress(symbol);
358 		break;
359 	case SYM_TEMPORARY:
360 		return MakeTemporarySymbolAddress(symbol);
361 		break;
362 	default:
363 		throw std::exception();
364 		break;
365 	}
366 }
367 
MakeRelativeReferenceSymbolAddress(CSymbol * symbol)368 CX86Assembler::CAddress CCodeGen_x86::MakeRelativeReferenceSymbolAddress(CSymbol* symbol)
369 {
370 	size_t symbolMask = sizeof(void*) - 1;
371 	assert(symbol->m_type == SYM_REL_REFERENCE);
372 	assert((symbol->m_valueLow & symbolMask) == 0);
373 	return CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rBP, symbol->m_valueLow);
374 }
375 
MakeTemporaryReferenceSymbolAddress(CSymbol * symbol)376 CX86Assembler::CAddress CCodeGen_x86::MakeTemporaryReferenceSymbolAddress(CSymbol* symbol)
377 {
378 	size_t symbolMask = sizeof(void*) - 1;
379 	assert(symbol->m_type == SYM_TMP_REFERENCE);
380 	assert(((symbol->m_stackLocation + m_stackLevel) & symbolMask) == 0);
381 	return CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, symbol->m_stackLocation + m_stackLevel);
382 }
383 
MakeMemoryReferenceSymbolAddress(CSymbol * symbol)384 CX86Assembler::CAddress CCodeGen_x86::MakeMemoryReferenceSymbolAddress(CSymbol* symbol)
385 {
386 	switch(symbol->m_type)
387 	{
388 	case SYM_REL_REFERENCE:
389 		return MakeRelativeReferenceSymbolAddress(symbol);
390 		break;
391 	case SYM_TMP_REFERENCE:
392 		return MakeTemporaryReferenceSymbolAddress(symbol);
393 		break;
394 	default:
395 		throw std::exception();
396 		break;
397 	}
398 }
399 
MakeVariableReferenceSymbolAddress(CSymbol * symbol)400 CX86Assembler::CAddress CCodeGen_x86::MakeVariableReferenceSymbolAddress(CSymbol* symbol)
401 {
402 	switch(symbol->m_type)
403 	{
404 	case SYM_REG_REFERENCE:
405 		return CX86Assembler::MakeRegisterAddress(m_registers[symbol->m_valueLow]);
406 		break;
407 	case SYM_REL_REFERENCE:
408 		return MakeRelativeReferenceSymbolAddress(symbol);
409 		break;
410 	case SYM_TMP_REFERENCE:
411 		return MakeTemporaryReferenceSymbolAddress(symbol);
412 		break;
413 	default:
414 		throw std::exception();
415 		break;
416 	}
417 }
418 
MakeRelative64SymbolAddress(CSymbol * symbol)419 CX86Assembler::CAddress CCodeGen_x86::MakeRelative64SymbolAddress(CSymbol* symbol)
420 {
421 	assert(symbol->m_type == SYM_RELATIVE64);
422 	assert((symbol->m_valueLow & 7) == 0);
423 	return CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rBP, symbol->m_valueLow);
424 }
425 
MakeRelative64SymbolLoAddress(CSymbol * symbol)426 CX86Assembler::CAddress CCodeGen_x86::MakeRelative64SymbolLoAddress(CSymbol* symbol)
427 {
428 	assert(symbol->m_type == SYM_RELATIVE64);
429 	assert((symbol->m_valueLow & 7) == 0);
430 	return CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rBP, symbol->m_valueLow + 0);
431 }
432 
MakeRelative64SymbolHiAddress(CSymbol * symbol)433 CX86Assembler::CAddress CCodeGen_x86::MakeRelative64SymbolHiAddress(CSymbol* symbol)
434 {
435 	assert(symbol->m_type == SYM_RELATIVE64);
436 	assert((symbol->m_valueLow & 7) == 0);
437 	return CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rBP, symbol->m_valueLow + 4);
438 }
439 
MakeTemporary64SymbolAddress(CSymbol * symbol)440 CX86Assembler::CAddress CCodeGen_x86::MakeTemporary64SymbolAddress(CSymbol* symbol)
441 {
442 	assert(symbol->m_type == SYM_TEMPORARY64);
443 	assert(((symbol->m_stackLocation + m_stackLevel) & 7) == 0);
444 	return CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, symbol->m_stackLocation + m_stackLevel);
445 }
446 
MakeTemporary64SymbolLoAddress(CSymbol * symbol)447 CX86Assembler::CAddress CCodeGen_x86::MakeTemporary64SymbolLoAddress(CSymbol* symbol)
448 {
449 	assert(symbol->m_type == SYM_TEMPORARY64);
450 	assert(((symbol->m_stackLocation + m_stackLevel) & 7) == 0);
451 	return CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, symbol->m_stackLocation + m_stackLevel + 0);
452 }
453 
MakeTemporary64SymbolHiAddress(CSymbol * symbol)454 CX86Assembler::CAddress CCodeGen_x86::MakeTemporary64SymbolHiAddress(CSymbol* symbol)
455 {
456 	assert(symbol->m_type == SYM_TEMPORARY64);
457 	assert(((symbol->m_stackLocation + m_stackLevel) & 7) == 0);
458 	return CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, symbol->m_stackLocation + m_stackLevel + 4);
459 }
460 
MakeMemory64SymbolAddress(CSymbol * symbol)461 CX86Assembler::CAddress CCodeGen_x86::MakeMemory64SymbolAddress(CSymbol* symbol)
462 {
463 	switch(symbol->m_type)
464 	{
465 	case SYM_RELATIVE64:
466 		return MakeRelative64SymbolAddress(symbol);
467 		break;
468 	case SYM_TEMPORARY64:
469 		return MakeTemporary64SymbolAddress(symbol);
470 		break;
471 	default:
472 		throw std::exception();
473 		break;
474 	}
475 }
476 
MakeMemory64SymbolLoAddress(CSymbol * symbol)477 CX86Assembler::CAddress CCodeGen_x86::MakeMemory64SymbolLoAddress(CSymbol* symbol)
478 {
479 	switch(symbol->m_type)
480 	{
481 	case SYM_RELATIVE64:
482 		return MakeRelative64SymbolLoAddress(symbol);
483 		break;
484 	case SYM_TEMPORARY64:
485 		return MakeTemporary64SymbolLoAddress(symbol);
486 		break;
487 	default:
488 		throw std::exception();
489 		break;
490 	}
491 }
492 
MakeMemory64SymbolHiAddress(CSymbol * symbol)493 CX86Assembler::CAddress CCodeGen_x86::MakeMemory64SymbolHiAddress(CSymbol* symbol)
494 {
495 	switch(symbol->m_type)
496 	{
497 	case SYM_RELATIVE64:
498 		return MakeRelative64SymbolHiAddress(symbol);
499 		break;
500 	case SYM_TEMPORARY64:
501 		return MakeTemporary64SymbolHiAddress(symbol);
502 		break;
503 	default:
504 		throw std::exception();
505 		break;
506 	}
507 }
508 
MarkLabel(const STATEMENT & statement)509 void CCodeGen_x86::MarkLabel(const STATEMENT& statement)
510 {
511 	CX86Assembler::LABEL label = GetLabel(statement.jmpBlock);
512 	m_assembler.MarkLabel(label);
513 }
514 
Emit_Nop(const STATEMENT & statement)515 void CCodeGen_x86::Emit_Nop(const STATEMENT& statement)
516 {
517 
518 }
519 
Emit_Break(const STATEMENT & statement)520 void CCodeGen_x86::Emit_Break(const STATEMENT& statement)
521 {
522 	m_assembler.Int3();
523 }
524 
Emit_Not_RegReg(const STATEMENT & statement)525 void CCodeGen_x86::Emit_Not_RegReg(const STATEMENT& statement)
526 {
527 	CSymbol* dst = statement.dst->GetSymbol().get();
528 	CSymbol* src1 = statement.src1->GetSymbol().get();
529 
530 	if(!dst->Equals(src1))
531 	{
532 		m_assembler.MovEd(m_registers[dst->m_valueLow], CX86Assembler::MakeRegisterAddress(m_registers[src1->m_valueLow]));
533 	}
534 
535 	m_assembler.NotEd(CX86Assembler::MakeRegisterAddress(m_registers[dst->m_valueLow]));
536 }
537 
Emit_Not_RegMem(const STATEMENT & statement)538 void CCodeGen_x86::Emit_Not_RegMem(const STATEMENT& statement)
539 {
540 	auto dst = statement.dst->GetSymbol().get();
541 	auto src1 = statement.src1->GetSymbol().get();
542 
543 	assert(dst->m_type == SYM_REGISTER);
544 
545 	m_assembler.MovEd(m_registers[dst->m_valueLow], MakeMemorySymbolAddress(src1));
546 	m_assembler.NotEd(CX86Assembler::MakeRegisterAddress(m_registers[dst->m_valueLow]));
547 }
548 
Emit_Not_MemReg(const STATEMENT & statement)549 void CCodeGen_x86::Emit_Not_MemReg(const STATEMENT& statement)
550 {
551 	auto dst = statement.dst->GetSymbol().get();
552 	auto src1 = statement.src1->GetSymbol().get();
553 
554 	assert(src1->m_type == SYM_REGISTER);
555 
556 	m_assembler.MovEd(CX86Assembler::rAX, CX86Assembler::MakeRegisterAddress(m_registers[src1->m_valueLow]));
557 	m_assembler.NotEd(CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX));
558 	m_assembler.MovGd(MakeMemorySymbolAddress(dst), CX86Assembler::rAX);
559 }
560 
Emit_Not_MemMem(const STATEMENT & statement)561 void CCodeGen_x86::Emit_Not_MemMem(const STATEMENT& statement)
562 {
563 	CSymbol* dst = statement.dst->GetSymbol().get();
564 	CSymbol* src1 = statement.src1->GetSymbol().get();
565 
566 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemorySymbolAddress(src1));
567 	m_assembler.NotEd(CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX));
568 	m_assembler.MovGd(MakeMemorySymbolAddress(dst), CX86Assembler::rAX);
569 }
570 
Emit_Lzc(CX86Assembler::REGISTER dstRegister,const CX86Assembler::CAddress & srcAddress)571 void CCodeGen_x86::Emit_Lzc(CX86Assembler::REGISTER dstRegister, const CX86Assembler::CAddress& srcAddress)
572 {
573 	auto set32Label = m_assembler.CreateLabel();
574 	auto startCountLabel = m_assembler.CreateLabel();
575 	auto doneLabel = m_assembler.CreateLabel();
576 
577 	auto tmpRegister = CX86Assembler::rAX;
578 
579 	m_assembler.MovEd(tmpRegister, srcAddress);
580 	m_assembler.TestEd(tmpRegister, CX86Assembler::MakeRegisterAddress(tmpRegister));
581 	m_assembler.JzJx(set32Label);
582 	m_assembler.JnsJx(startCountLabel);
583 
584 	//reverse:
585 	m_assembler.NotEd(CX86Assembler::MakeRegisterAddress(tmpRegister));
586 	m_assembler.TestEd(tmpRegister, CX86Assembler::MakeRegisterAddress(tmpRegister));
587 	m_assembler.JzJx(set32Label);
588 
589 	//startCount:
590 	m_assembler.MarkLabel(startCountLabel);
591 	m_assembler.BsrEd(dstRegister, CX86Assembler::MakeRegisterAddress(tmpRegister));
592 	m_assembler.NegEd(CX86Assembler::MakeRegisterAddress(dstRegister));
593 	m_assembler.AddId(CX86Assembler::MakeRegisterAddress(dstRegister), 0x1E);
594 	m_assembler.JmpJx(doneLabel);
595 
596 	//set32
597 	m_assembler.MarkLabel(set32Label);
598 	m_assembler.MovId(dstRegister, 0x1F);
599 
600 	//done
601 	m_assembler.MarkLabel(doneLabel);
602 }
603 
Emit_Lzc_RegVar(const STATEMENT & statement)604 void CCodeGen_x86::Emit_Lzc_RegVar(const STATEMENT& statement)
605 {
606 	auto dst = statement.dst->GetSymbol().get();
607 	auto src1 = statement.src1->GetSymbol().get();
608 
609 	Emit_Lzc(m_registers[dst->m_valueLow], MakeVariableSymbolAddress(src1));
610 }
611 
Emit_Lzc_MemVar(const STATEMENT & statement)612 void CCodeGen_x86::Emit_Lzc_MemVar(const STATEMENT& statement)
613 {
614 	auto dst = statement.dst->GetSymbol().get();
615 	auto src1 = statement.src1->GetSymbol().get();
616 
617 	auto dstRegister = CX86Assembler::rAX;
618 
619 	Emit_Lzc(dstRegister, MakeVariableSymbolAddress(src1));
620 	m_assembler.MovGd(MakeMemorySymbolAddress(dst), dstRegister);
621 }
622 
Emit_Mov_RegReg(const STATEMENT & statement)623 void CCodeGen_x86::Emit_Mov_RegReg(const STATEMENT& statement)
624 {
625 	auto dst = statement.dst->GetSymbol().get();
626 	auto src1 = statement.src1->GetSymbol().get();
627 
628 	assert(!dst->Equals(src1));
629 
630 	m_assembler.MovEd(m_registers[dst->m_valueLow], CX86Assembler::MakeRegisterAddress(m_registers[src1->m_valueLow]));
631 }
632 
Emit_Mov_RegMem(const STATEMENT & statement)633 void CCodeGen_x86::Emit_Mov_RegMem(const STATEMENT& statement)
634 {
635 	auto dst = statement.dst->GetSymbol().get();
636 	auto src1 = statement.src1->GetSymbol().get();
637 
638 	m_assembler.MovEd(m_registers[dst->m_valueLow], MakeMemorySymbolAddress(src1));
639 }
640 
Emit_Mov_RegCst(const STATEMENT & statement)641 void CCodeGen_x86::Emit_Mov_RegCst(const STATEMENT& statement)
642 {
643 	auto dst = statement.dst->GetSymbol().get();
644 	auto src1 = statement.src1->GetSymbol().get();
645 
646 	if(src1->m_valueLow == 0)
647 	{
648 		m_assembler.XorEd(m_registers[dst->m_valueLow], CX86Assembler::MakeRegisterAddress(m_registers[dst->m_valueLow]));
649 	}
650 	else
651 	{
652 		m_assembler.MovId(m_registers[dst->m_valueLow], src1->m_valueLow);
653 	}
654 }
655 
Emit_Mov_MemReg(const STATEMENT & statement)656 void CCodeGen_x86::Emit_Mov_MemReg(const STATEMENT& statement)
657 {
658 	auto dst = statement.dst->GetSymbol().get();
659 	auto src1 = statement.src1->GetSymbol().get();
660 
661 	assert(src1->m_type == SYM_REGISTER);
662 
663 	m_assembler.MovGd(MakeMemorySymbolAddress(dst), m_registers[src1->m_valueLow]);
664 }
665 
Emit_Mov_MemMem(const STATEMENT & statement)666 void CCodeGen_x86::Emit_Mov_MemMem(const STATEMENT& statement)
667 {
668 	auto dst = statement.dst->GetSymbol().get();
669 	auto src1 = statement.src1->GetSymbol().get();
670 
671 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemorySymbolAddress(src1));
672 	m_assembler.MovGd(MakeMemorySymbolAddress(dst), CX86Assembler::rAX);
673 }
674 
Emit_Mov_MemCst(const STATEMENT & statement)675 void CCodeGen_x86::Emit_Mov_MemCst(const STATEMENT& statement)
676 {
677 	auto dst = statement.dst->GetSymbol().get();
678 	auto src1 = statement.src1->GetSymbol().get();
679 
680 	assert(src1->m_type == SYM_CONSTANT);
681 
682 	m_assembler.MovId(MakeMemorySymbolAddress(dst), src1->m_valueLow);
683 }
684 
Emit_Jmp(const STATEMENT & statement)685 void CCodeGen_x86::Emit_Jmp(const STATEMENT& statement)
686 {
687 	m_assembler.JmpJx(GetLabel(statement.jmpBlock));
688 }
689 
Emit_MergeTo64_Mem64RegReg(const STATEMENT & statement)690 void CCodeGen_x86::Emit_MergeTo64_Mem64RegReg(const STATEMENT& statement)
691 {
692 	CSymbol* dst = statement.dst->GetSymbol().get();
693 	CSymbol* src1 = statement.src1->GetSymbol().get();
694 	CSymbol* src2 = statement.src2->GetSymbol().get();
695 
696 	assert(src1->m_type == SYM_REGISTER);
697 	assert(src2->m_type == SYM_REGISTER);
698 
699 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), m_registers[src1->m_valueLow]);
700 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), m_registers[src2->m_valueLow]);
701 }
702 
Emit_MergeTo64_Mem64RegMem(const STATEMENT & statement)703 void CCodeGen_x86::Emit_MergeTo64_Mem64RegMem(const STATEMENT& statement)
704 {
705 	CSymbol* dst = statement.dst->GetSymbol().get();
706 	CSymbol* src1 = statement.src1->GetSymbol().get();
707 	CSymbol* src2 = statement.src2->GetSymbol().get();
708 
709 	assert(src1->m_type == SYM_REGISTER);
710 
711 	m_assembler.MovEd(CX86Assembler::rDX, MakeMemorySymbolAddress(src2));
712 
713 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), m_registers[src1->m_valueLow]);
714 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), CX86Assembler::rDX);
715 }
716 
Emit_MergeTo64_Mem64MemReg(const STATEMENT & statement)717 void CCodeGen_x86::Emit_MergeTo64_Mem64MemReg(const STATEMENT& statement)
718 {
719 	auto dst = statement.dst->GetSymbol().get();
720 	auto src1 = statement.src1->GetSymbol().get();
721 	auto src2 = statement.src2->GetSymbol().get();
722 
723 	assert(src2->m_type == SYM_REGISTER);
724 
725 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemorySymbolAddress(src1));
726 
727 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
728 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), m_registers[src2->m_valueLow]);
729 }
730 
Emit_MergeTo64_Mem64MemMem(const STATEMENT & statement)731 void CCodeGen_x86::Emit_MergeTo64_Mem64MemMem(const STATEMENT& statement)
732 {
733 	CSymbol* dst = statement.dst->GetSymbol().get();
734 	CSymbol* src1 = statement.src1->GetSymbol().get();
735 	CSymbol* src2 = statement.src2->GetSymbol().get();
736 
737 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemorySymbolAddress(src1));
738 	m_assembler.MovEd(CX86Assembler::rDX, MakeMemorySymbolAddress(src2));
739 
740 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
741 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), CX86Assembler::rDX);
742 }
743 
Emit_MergeTo64_Mem64CstReg(const STATEMENT & statement)744 void CCodeGen_x86::Emit_MergeTo64_Mem64CstReg(const STATEMENT& statement)
745 {
746 	CSymbol* dst = statement.dst->GetSymbol().get();
747 	CSymbol* src1 = statement.src1->GetSymbol().get();
748 	CSymbol* src2 = statement.src2->GetSymbol().get();
749 
750 	assert(src1->m_type == SYM_CONSTANT);
751 	assert(src2->m_type == SYM_REGISTER);
752 
753 	m_assembler.MovId(CX86Assembler::rAX, src1->m_valueLow);
754 
755 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
756 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), m_registers[src2->m_valueLow]);
757 }
758 
Emit_MergeTo64_Mem64CstMem(const STATEMENT & statement)759 void CCodeGen_x86::Emit_MergeTo64_Mem64CstMem(const STATEMENT& statement)
760 {
761 	CSymbol* dst = statement.dst->GetSymbol().get();
762 	CSymbol* src1 = statement.src1->GetSymbol().get();
763 	CSymbol* src2 = statement.src2->GetSymbol().get();
764 
765 	assert(src1->m_type == SYM_CONSTANT);
766 
767 	m_assembler.MovId(CX86Assembler::rAX, src1->m_valueLow);
768 	m_assembler.MovEd(CX86Assembler::rDX, MakeMemorySymbolAddress(src2));
769 
770 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
771 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), CX86Assembler::rDX);
772 }
773 
Emit_ExtLow64RegTmp64(const STATEMENT & statement)774 void CCodeGen_x86::Emit_ExtLow64RegTmp64(const STATEMENT& statement)
775 {
776 	CSymbol* dst = statement.dst->GetSymbol().get();
777 	CSymbol* src1 = statement.src1->GetSymbol().get();
778 
779 	assert(dst->m_type  == SYM_REGISTER);
780 	assert(src1->m_type == SYM_TEMPORARY64);
781 
782 	m_assembler.MovEd(m_registers[dst->m_valueLow], CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, src1->m_stackLocation + m_stackLevel + 0));
783 }
784 
Emit_ExtLow64MemTmp64(const STATEMENT & statement)785 void CCodeGen_x86::Emit_ExtLow64MemTmp64(const STATEMENT& statement)
786 {
787 	auto dst = statement.dst->GetSymbol().get();
788 	auto src1 = statement.src1->GetSymbol().get();
789 
790 	assert(src1->m_type == SYM_TEMPORARY64);
791 
792 	m_assembler.MovEd(CX86Assembler::rAX, CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, src1->m_stackLocation + m_stackLevel + 0));
793 	m_assembler.MovGd(MakeMemorySymbolAddress(dst), CX86Assembler::rAX);
794 }
795 
Emit_ExtHigh64RegTmp64(const STATEMENT & statement)796 void CCodeGen_x86::Emit_ExtHigh64RegTmp64(const STATEMENT& statement)
797 {
798 	CSymbol* dst = statement.dst->GetSymbol().get();
799 	CSymbol* src1 = statement.src1->GetSymbol().get();
800 
801 	assert(dst->m_type  == SYM_REGISTER);
802 	assert(src1->m_type == SYM_TEMPORARY64);
803 
804 	m_assembler.MovEd(m_registers[dst->m_valueLow], CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, src1->m_stackLocation + m_stackLevel + 4));
805 }
806 
Emit_ExtHigh64MemTmp64(const STATEMENT & statement)807 void CCodeGen_x86::Emit_ExtHigh64MemTmp64(const STATEMENT& statement)
808 {
809 	auto dst = statement.dst->GetSymbol().get();
810 	auto src1 = statement.src1->GetSymbol().get();
811 
812 	assert(src1->m_type == SYM_TEMPORARY64);
813 
814 	m_assembler.MovEd(CX86Assembler::rAX, CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, src1->m_stackLocation + m_stackLevel + 4));
815 	m_assembler.MovGd(MakeMemorySymbolAddress(dst), CX86Assembler::rAX);
816 }
817 
Emit_LoadFromRef_VarVar(const STATEMENT & statement)818 void CCodeGen_x86::Emit_LoadFromRef_VarVar(const STATEMENT& statement)
819 {
820 	auto dst = statement.dst->GetSymbol().get();
821 	auto src1 = statement.src1->GetSymbol().get();
822 
823 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
824 	auto dstReg = PrepareSymbolRegisterDef(dst, CX86Assembler::rDX);
825 
826 	m_assembler.MovEd(dstReg, CX86Assembler::MakeIndRegAddress(addressReg));
827 
828 	CommitSymbolRegister(dst, dstReg);
829 }
830 
Emit_LoadFromRef_Md_RegVar(const STATEMENT & statement)831 void CCodeGen_x86::Emit_LoadFromRef_Md_RegVar(const STATEMENT& statement)
832 {
833 	auto dst = statement.dst->GetSymbol().get();
834 	auto src1 = statement.src1->GetSymbol().get();
835 
836 	assert(dst->m_type == SYM_REGISTER128);
837 
838 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
839 
840 	m_assembler.MovapsVo(m_mdRegisters[dst->m_valueLow], CX86Assembler::MakeIndRegAddress(addressReg));
841 }
842 
Emit_LoadFromRef_Md_MemVar(const STATEMENT & statement)843 void CCodeGen_x86::Emit_LoadFromRef_Md_MemVar(const STATEMENT& statement)
844 {
845 	auto dst = statement.dst->GetSymbol().get();
846 	auto src1 = statement.src1->GetSymbol().get();
847 
848 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
849 	auto valueReg = CX86Assembler::xMM0;
850 
851 	m_assembler.MovapsVo(valueReg, CX86Assembler::MakeIndRegAddress(addressReg));
852 	m_assembler.MovapsVo(MakeMemory128SymbolAddress(dst), valueReg);
853 }
854 
Emit_LoadFromRefIdx_VarVarVar(const STATEMENT & statement)855 void CCodeGen_x86::Emit_LoadFromRefIdx_VarVarVar(const STATEMENT& statement)
856 {
857 	auto dst = statement.dst->GetSymbol().get();
858 	auto src1 = statement.src1->GetSymbol().get();
859 	auto src2 = statement.src2->GetSymbol().get();
860 
861 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
862 	auto indexReg = PrepareSymbolRegisterUse(src2, CX86Assembler::rCX);
863 	auto dstReg = PrepareSymbolRegisterDef(dst, CX86Assembler::rDX);
864 
865 	uint8 scale = static_cast<uint8>(statement.jmpCondition);
866 	assert(scale == 1);
867 
868 	m_assembler.MovEd(dstReg, CX86Assembler::MakeBaseIndexScaleAddress(addressReg, indexReg, scale));
869 
870 	CommitSymbolRegister(dst, dstReg);
871 }
872 
Emit_LoadFromRefIdx_VarVarCst(const STATEMENT & statement)873 void CCodeGen_x86::Emit_LoadFromRefIdx_VarVarCst(const STATEMENT& statement)
874 {
875 	auto dst = statement.dst->GetSymbol().get();
876 	auto src1 = statement.src1->GetSymbol().get();
877 	auto src2 = statement.src2->GetSymbol().get();
878 
879 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
880 	auto dstReg = PrepareSymbolRegisterDef(dst, CX86Assembler::rDX);
881 
882 	uint8 scale = static_cast<uint8>(statement.jmpCondition);
883 	assert(scale == 1);
884 
885 	m_assembler.MovEd(dstReg, CX86Assembler::MakeIndRegOffAddress(addressReg, src2->m_valueLow));
886 
887 	CommitSymbolRegister(dst, dstReg);
888 }
889 
Emit_Load8FromRef_VarVar(const STATEMENT & statement)890 void CCodeGen_x86::Emit_Load8FromRef_VarVar(const STATEMENT& statement)
891 {
892 	auto dst = statement.dst->GetSymbol().get();
893 	auto src1 = statement.src1->GetSymbol().get();
894 
895 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
896 	auto dstReg = PrepareSymbolRegisterDef(dst, CX86Assembler::rDX);
897 
898 	m_assembler.MovzxEb(dstReg, CX86Assembler::MakeIndRegAddress(addressReg));
899 
900 	CommitSymbolRegister(dst, dstReg);
901 }
902 
Emit_Load16FromRef_VarVar(const STATEMENT & statement)903 void CCodeGen_x86::Emit_Load16FromRef_VarVar(const STATEMENT& statement)
904 {
905 	auto dst = statement.dst->GetSymbol().get();
906 	auto src1 = statement.src1->GetSymbol().get();
907 
908 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
909 	auto dstReg = PrepareSymbolRegisterDef(dst, CX86Assembler::rDX);
910 
911 	m_assembler.MovzxEw(dstReg, CX86Assembler::MakeIndRegAddress(addressReg));
912 
913 	CommitSymbolRegister(dst, dstReg);
914 }
915 
Emit_StoreAtRef_VarVar(const STATEMENT & statement)916 void CCodeGen_x86::Emit_StoreAtRef_VarVar(const STATEMENT& statement)
917 {
918 	auto src1 = statement.src1->GetSymbol().get();
919 	auto src2 = statement.src2->GetSymbol().get();
920 
921 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
922 	auto valueReg = PrepareSymbolRegisterUse(src2, CX86Assembler::rDX);
923 	m_assembler.MovGd(CX86Assembler::MakeIndRegAddress(addressReg), valueReg);
924 }
925 
Emit_StoreAtRef_VarCst(const STATEMENT & statement)926 void CCodeGen_x86::Emit_StoreAtRef_VarCst(const STATEMENT& statement)
927 {
928 	auto src1 = statement.src1->GetSymbol().get();
929 	auto src2 = statement.src2->GetSymbol().get();
930 
931 	assert(src2->m_type == SYM_CONSTANT);
932 
933 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
934 	m_assembler.MovId(CX86Assembler::MakeIndRegAddress(addressReg), src2->m_valueLow);
935 }
936 
Emit_StoreAtRef_Md_VarReg(const STATEMENT & statement)937 void CCodeGen_x86::Emit_StoreAtRef_Md_VarReg(const STATEMENT& statement)
938 {
939 	auto src1 = statement.src1->GetSymbol().get();
940 	auto src2 = statement.src2->GetSymbol().get();
941 
942 	assert(src2->m_type == SYM_REGISTER128);
943 
944 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
945 	m_assembler.MovapsVo(CX86Assembler::MakeIndRegAddress(addressReg), m_mdRegisters[src2->m_valueLow]);
946 }
947 
Emit_StoreAtRef_Md_VarMem(const STATEMENT & statement)948 void CCodeGen_x86::Emit_StoreAtRef_Md_VarMem(const STATEMENT& statement)
949 {
950 	auto src1 = statement.src1->GetSymbol().get();
951 	auto src2 = statement.src2->GetSymbol().get();
952 
953 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
954 	auto valueReg = CX86Assembler::xMM0;
955 
956 	m_assembler.MovapsVo(valueReg, MakeMemory128SymbolAddress(src2));
957 	m_assembler.MovapsVo(CX86Assembler::MakeIndRegAddress(addressReg), valueReg);
958 }
959 
Emit_StoreAtRefIdx_VarVarVar(const STATEMENT & statement)960 void CCodeGen_x86::Emit_StoreAtRefIdx_VarVarVar(const STATEMENT& statement)
961 {
962 	auto src1 = statement.src1->GetSymbol().get();
963 	auto src2 = statement.src2->GetSymbol().get();
964 	auto src3 = statement.src3->GetSymbol().get();
965 
966 	uint8 scale = static_cast<uint8>(statement.jmpCondition);
967 
968 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
969 	auto indexReg = PrepareSymbolRegisterUse(src2, CX86Assembler::rDX);
970 	auto valueReg = PrepareSymbolRegisterUse(src3, CX86Assembler::rCX);
971 
972 	m_assembler.MovGd(CX86Assembler::MakeBaseIndexScaleAddress(addressReg, indexReg, scale), valueReg);
973 }
974 
Emit_StoreAtRefIdx_VarVarCst(const STATEMENT & statement)975 void CCodeGen_x86::Emit_StoreAtRefIdx_VarVarCst(const STATEMENT& statement)
976 {
977 	auto src1 = statement.src1->GetSymbol().get();
978 	auto src2 = statement.src2->GetSymbol().get();
979 	auto src3 = statement.src3->GetSymbol().get();
980 
981 	assert(src3->m_type == SYM_CONSTANT);
982 
983 	uint8 scale = static_cast<uint8>(statement.jmpCondition);
984 
985 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
986 	auto indexReg = PrepareSymbolRegisterUse(src2, CX86Assembler::rDX);
987 
988 	m_assembler.MovId(CX86Assembler::MakeBaseIndexScaleAddress(addressReg, indexReg, scale), src3->m_valueLow);
989 }
990 
Emit_StoreAtRefIdx_VarCstVar(const STATEMENT & statement)991 void CCodeGen_x86::Emit_StoreAtRefIdx_VarCstVar(const STATEMENT& statement)
992 {
993 	auto src1 = statement.src1->GetSymbol().get();
994 	auto src2 = statement.src2->GetSymbol().get();
995 	auto src3 = statement.src3->GetSymbol().get();
996 
997 	uint8 scale = static_cast<uint8>(statement.jmpCondition);
998 	assert(scale == 1);
999 
1000 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
1001 	auto valueReg = PrepareSymbolRegisterUse(src3, CX86Assembler::rCX);
1002 
1003 	m_assembler.MovGd(CX86Assembler::MakeIndRegOffAddress(addressReg, src2->m_valueLow), valueReg);
1004 }
1005 
Emit_StoreAtRefIdx_VarCstCst(const STATEMENT & statement)1006 void CCodeGen_x86::Emit_StoreAtRefIdx_VarCstCst(const STATEMENT& statement)
1007 {
1008 	auto src1 = statement.src1->GetSymbol().get();
1009 	auto src2 = statement.src2->GetSymbol().get();
1010 	auto src3 = statement.src3->GetSymbol().get();
1011 
1012 	assert(src2->m_type == SYM_CONSTANT);
1013 	assert(src3->m_type == SYM_CONSTANT);
1014 
1015 	uint8 scale = static_cast<uint8>(statement.jmpCondition);
1016 	assert(scale == 1);
1017 
1018 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
1019 
1020 	m_assembler.MovId(CX86Assembler::MakeIndRegOffAddress(addressReg, src2->m_valueLow), src3->m_valueLow);
1021 }
1022 
Emit_Store8AtRef_VarCst(const STATEMENT & statement)1023 void CCodeGen_x86::Emit_Store8AtRef_VarCst(const STATEMENT& statement)
1024 {
1025 	auto src1 = statement.src1->GetSymbol().get();
1026 	auto src2 = statement.src2->GetSymbol().get();
1027 
1028 	assert(src2->m_type == SYM_CONSTANT);
1029 
1030 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
1031 	m_assembler.MovIb(CX86Assembler::MakeIndRegAddress(addressReg), static_cast<uint8>(src2->m_valueLow));
1032 }
1033 
Emit_Store16AtRef_VarVar(const STATEMENT & statement)1034 void CCodeGen_x86::Emit_Store16AtRef_VarVar(const STATEMENT& statement)
1035 {
1036 	auto src1 = statement.src1->GetSymbol().get();
1037 	auto src2 = statement.src2->GetSymbol().get();
1038 
1039 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
1040 	auto valueReg = PrepareSymbolRegisterUse(src2, CX86Assembler::rDX);
1041 	m_assembler.MovGw(CX86Assembler::MakeIndRegAddress(addressReg), valueReg);
1042 }
1043 
Emit_Store16AtRef_VarCst(const STATEMENT & statement)1044 void CCodeGen_x86::Emit_Store16AtRef_VarCst(const STATEMENT& statement)
1045 {
1046 	auto src1 = statement.src1->GetSymbol().get();
1047 	auto src2 = statement.src2->GetSymbol().get();
1048 
1049 	assert(src2->m_type == SYM_CONSTANT);
1050 
1051 	auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
1052 	m_assembler.MovIw(CX86Assembler::MakeIndRegAddress(addressReg), static_cast<uint16>(src2->m_valueLow));
1053 }
1054 
Cmp_GetFlag(const CX86Assembler::CAddress & dst,CONDITION flag)1055 void CCodeGen_x86::Cmp_GetFlag(const CX86Assembler::CAddress& dst, CONDITION flag)
1056 {
1057 	switch(flag)
1058 	{
1059 	case CONDITION_LT:
1060 		m_assembler.SetlEb(dst);
1061 		break;
1062 	case CONDITION_LE:
1063 		m_assembler.SetleEb(dst);
1064 		break;
1065 	case CONDITION_GT:
1066 		m_assembler.SetgEb(dst);
1067 		break;
1068 	case CONDITION_EQ:
1069 		m_assembler.SeteEb(dst);
1070 		break;
1071 	case CONDITION_NE:
1072 		m_assembler.SetneEb(dst);
1073 		break;
1074 	case CONDITION_BL:
1075 		m_assembler.SetbEb(dst);
1076 		break;
1077 	case CONDITION_AB:
1078 		m_assembler.SetaEb(dst);
1079 		break;
1080 	default:
1081 		assert(0);
1082 		break;
1083 	}
1084 }
1085 
CondJmp_JumpTo(CX86Assembler::LABEL label,Jitter::CONDITION condition)1086 void CCodeGen_x86::CondJmp_JumpTo(CX86Assembler::LABEL label, Jitter::CONDITION condition)
1087 {
1088 	switch(condition)
1089 	{
1090 	case CONDITION_EQ:
1091 		m_assembler.JzJx(label);
1092 		break;
1093 	case CONDITION_NE:
1094 		m_assembler.JnzJx(label);
1095 		break;
1096 	case CONDITION_BL:
1097 		m_assembler.JbJx(label);
1098 		break;
1099 	case CONDITION_BE:
1100 		m_assembler.JbeJx(label);
1101 		break;
1102 	case CONDITION_AB:
1103 		m_assembler.JnbeJx(label);
1104 		break;
1105 	case CONDITION_AE:
1106 		m_assembler.JnbJx(label);
1107 		break;
1108 	case CONDITION_LT:
1109 		m_assembler.JlJx(label);
1110 		break;
1111 	case CONDITION_LE:
1112 		m_assembler.JleJx(label);
1113 		break;
1114 	case CONDITION_GT:
1115 		m_assembler.JnleJx(label);
1116 		break;
1117 	case CONDITION_GE:
1118 		m_assembler.JnlJx(label);
1119 		break;
1120 	default:
1121 		assert(0);
1122 		break;
1123 	}
1124 }
1125 
Emit_CondJmp_RegReg(const STATEMENT & statement)1126 void CCodeGen_x86::Emit_CondJmp_RegReg(const STATEMENT& statement)
1127 {
1128 	CSymbol* src1 = statement.src1->GetSymbol().get();
1129 	CSymbol* src2 = statement.src2->GetSymbol().get();
1130 
1131 	assert(src1->m_type == SYM_REGISTER);
1132 	assert(src2->m_type == SYM_REGISTER);
1133 
1134 	m_assembler.CmpEd(m_registers[src1->m_valueLow], CX86Assembler::MakeRegisterAddress(m_registers[src2->m_valueLow]));
1135 
1136 	CondJmp_JumpTo(GetLabel(statement.jmpBlock), statement.jmpCondition);
1137 }
1138 
Emit_CondJmp_RegMem(const STATEMENT & statement)1139 void CCodeGen_x86::Emit_CondJmp_RegMem(const STATEMENT& statement)
1140 {
1141 	CSymbol* src1 = statement.src1->GetSymbol().get();
1142 	CSymbol* src2 = statement.src2->GetSymbol().get();
1143 
1144 	assert(src1->m_type == SYM_REGISTER);
1145 
1146 	m_assembler.CmpEd(m_registers[src1->m_valueLow], MakeMemorySymbolAddress(src2));
1147 
1148 	CondJmp_JumpTo(GetLabel(statement.jmpBlock), statement.jmpCondition);
1149 }
1150 
Emit_CondJmp_RegCst(const STATEMENT & statement)1151 void CCodeGen_x86::Emit_CondJmp_RegCst(const STATEMENT& statement)
1152 {
1153 	CSymbol* src1 = statement.src1->GetSymbol().get();
1154 	CSymbol* src2 = statement.src2->GetSymbol().get();
1155 
1156 	assert(src1->m_type == SYM_REGISTER);
1157 	assert(src2->m_type == SYM_CONSTANT);
1158 
1159 	if((src2->m_valueLow == 0) && (statement.jmpCondition == CONDITION_NE || statement.jmpCondition == CONDITION_EQ))
1160 	{
1161 		m_assembler.TestEd(m_registers[src1->m_valueLow], CX86Assembler::MakeRegisterAddress(m_registers[src1->m_valueLow]));
1162 	}
1163 	else
1164 	{
1165 		m_assembler.CmpId(CX86Assembler::MakeRegisterAddress(m_registers[src1->m_valueLow]), src2->m_valueLow);
1166 	}
1167 
1168 	CondJmp_JumpTo(GetLabel(statement.jmpBlock), statement.jmpCondition);
1169 }
1170 
Emit_CondJmp_MemMem(const STATEMENT & statement)1171 void CCodeGen_x86::Emit_CondJmp_MemMem(const STATEMENT& statement)
1172 {
1173 	auto src1 = statement.src1->GetSymbol().get();
1174 	auto src2 = statement.src2->GetSymbol().get();
1175 
1176 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemorySymbolAddress(src1));
1177 	m_assembler.CmpEd(CX86Assembler::rAX, MakeMemorySymbolAddress(src2));
1178 
1179 	CondJmp_JumpTo(GetLabel(statement.jmpBlock), statement.jmpCondition);
1180 }
1181 
Emit_CondJmp_MemCst(const STATEMENT & statement)1182 void CCodeGen_x86::Emit_CondJmp_MemCst(const STATEMENT& statement)
1183 {
1184 	CSymbol* src1 = statement.src1->GetSymbol().get();
1185 	CSymbol* src2 = statement.src2->GetSymbol().get();
1186 
1187 	assert(src2->m_type == SYM_CONSTANT);
1188 
1189 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemorySymbolAddress(src1));
1190 
1191 	if((src2->m_valueLow == 0) && (statement.jmpCondition == CONDITION_NE || statement.jmpCondition == CONDITION_EQ))
1192 	{
1193 		m_assembler.TestEd(CX86Assembler::rAX, CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX));
1194 	}
1195 	else
1196 	{
1197 		m_assembler.CmpId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX), src2->m_valueLow);
1198 	}
1199 
1200 	CondJmp_JumpTo(GetLabel(statement.jmpBlock), statement.jmpCondition);
1201 }
1202 
PrepareSymbolRegisterDef(CSymbol * symbol,CX86Assembler::REGISTER preferedRegister)1203 CX86Assembler::REGISTER CCodeGen_x86::PrepareSymbolRegisterDef(CSymbol* symbol, CX86Assembler::REGISTER preferedRegister)
1204 {
1205 	switch(symbol->m_type)
1206 	{
1207 	case SYM_REGISTER:
1208 		return m_registers[symbol->m_valueLow];
1209 		break;
1210 	case SYM_TEMPORARY:
1211 	case SYM_RELATIVE:
1212 		return preferedRegister;
1213 		break;
1214 	default:
1215 		throw std::runtime_error("Invalid symbol type.");
1216 		break;
1217 	}
1218 }
1219 
PrepareSymbolRegisterUse(CSymbol * symbol,CX86Assembler::REGISTER preferedRegister)1220 CX86Assembler::REGISTER CCodeGen_x86::PrepareSymbolRegisterUse(CSymbol* symbol, CX86Assembler::REGISTER preferedRegister)
1221 {
1222 	switch(symbol->m_type)
1223 	{
1224 	case SYM_REGISTER:
1225 		return m_registers[symbol->m_valueLow];
1226 		break;
1227 	case SYM_TEMPORARY:
1228 	case SYM_RELATIVE:
1229 		m_assembler.MovEd(preferedRegister, MakeMemorySymbolAddress(symbol));
1230 		return preferedRegister;
1231 		break;
1232 	case SYM_CONSTANT:
1233 		m_assembler.MovId(preferedRegister, symbol->m_valueLow);
1234 		return preferedRegister;
1235 		break;
1236 	default:
1237 		throw std::runtime_error("Invalid symbol type.");
1238 		break;
1239 	}
1240 }
1241 
PrepareSymbolByteRegisterUse(CSymbol * symbol,CX86Assembler::REGISTER preferedRegister)1242 CX86Assembler::BYTEREGISTER CCodeGen_x86::PrepareSymbolByteRegisterUse(CSymbol* symbol, CX86Assembler::REGISTER preferedRegister)
1243 {
1244 	assert(CX86Assembler::HasByteRegister(preferedRegister));
1245 	auto preferedByteRegister = CX86Assembler::GetByteRegister(preferedRegister);
1246 	switch(symbol->m_type)
1247 	{
1248 	case SYM_REGISTER:
1249 		{
1250 			auto srcRegister = m_registers[symbol->m_valueLow];
1251 			if(CX86Assembler::HasByteRegister(srcRegister))
1252 			{
1253 				return CX86Assembler::GetByteRegister(srcRegister);
1254 			}
1255 			else
1256 			{
1257 				m_assembler.MovEd(preferedRegister, CX86Assembler::MakeRegisterAddress(srcRegister));
1258 				return preferedByteRegister;
1259 			}
1260 		}
1261 		break;
1262 	case SYM_TEMPORARY:
1263 	case SYM_RELATIVE:
1264 		m_assembler.MovEd(preferedRegister, MakeMemorySymbolAddress(symbol));
1265 		return preferedByteRegister;
1266 		break;
1267 	case SYM_CONSTANT:
1268 		m_assembler.MovId(preferedRegister, symbol->m_valueLow);
1269 		return preferedByteRegister;
1270 		break;
1271 	default:
1272 		throw std::runtime_error("Invalid symbol type.");
1273 		break;
1274 	}
1275 }
1276 
CommitSymbolRegister(CSymbol * symbol,CX86Assembler::REGISTER usedRegister)1277 void CCodeGen_x86::CommitSymbolRegister(CSymbol* symbol, CX86Assembler::REGISTER usedRegister)
1278 {
1279 	switch(symbol->m_type)
1280 	{
1281 	case SYM_REGISTER:
1282 		assert(usedRegister == m_registers[symbol->m_valueLow]);
1283 		break;
1284 	case SYM_TEMPORARY:
1285 	case SYM_RELATIVE:
1286 		m_assembler.MovGd(MakeMemorySymbolAddress(symbol), usedRegister);
1287 		break;
1288 	default:
1289 		throw std::runtime_error("Invalid symbol type.");
1290 		break;
1291 	}
1292 }
1293 
PrepareSymbolRegisterDefMd(CSymbol * symbol,CX86Assembler::XMMREGISTER preferedRegister)1294 CX86Assembler::XMMREGISTER CCodeGen_x86::PrepareSymbolRegisterDefMd(CSymbol* symbol, CX86Assembler::XMMREGISTER preferedRegister)
1295 {
1296 	switch(symbol->m_type)
1297 	{
1298 	case SYM_REGISTER128:
1299 		return m_mdRegisters[symbol->m_valueLow];
1300 		break;
1301 	case SYM_TEMPORARY128:
1302 	case SYM_RELATIVE128:
1303 		return preferedRegister;
1304 		break;
1305 	default:
1306 		throw std::runtime_error("Invalid symbol type.");
1307 		break;
1308 	}
1309 }
1310 
PrepareSymbolRegisterUseMdAvx(CSymbol * symbol,CX86Assembler::XMMREGISTER preferedRegister)1311 CX86Assembler::XMMREGISTER CCodeGen_x86::PrepareSymbolRegisterUseMdAvx(CSymbol* symbol, CX86Assembler::XMMREGISTER preferedRegister)
1312 {
1313 	switch(symbol->m_type)
1314 	{
1315 	case SYM_REGISTER128:
1316 		return m_mdRegisters[symbol->m_valueLow];
1317 		break;
1318 	case SYM_TEMPORARY128:
1319 	case SYM_RELATIVE128:
1320 		m_assembler.VmovapsVo(preferedRegister, MakeMemory128SymbolAddress(symbol));
1321 		return preferedRegister;
1322 		break;
1323 	default:
1324 		throw std::runtime_error("Invalid symbol type.");
1325 		break;
1326 	}
1327 }
1328 
CommitSymbolRegisterMdAvx(CSymbol * symbol,CX86Assembler::XMMREGISTER usedRegister)1329 void CCodeGen_x86::CommitSymbolRegisterMdAvx(CSymbol* symbol, CX86Assembler::XMMREGISTER usedRegister)
1330 {
1331 	switch(symbol->m_type)
1332 	{
1333 	case SYM_REGISTER128:
1334 		assert(usedRegister == m_mdRegisters[symbol->m_valueLow]);
1335 		break;
1336 	case SYM_TEMPORARY128:
1337 	case SYM_RELATIVE128:
1338 		m_assembler.VmovapsVo(MakeMemory128SymbolAddress(symbol), usedRegister);
1339 		break;
1340 	default:
1341 		throw std::runtime_error("Invalid symbol type.");
1342 		break;
1343 	}
1344 }
1345