1 #include "Jitter_CodeGen_x86_32.h"
2 #include <algorithm>
3 
4 using namespace Jitter;
5 
6 CX86Assembler::REGISTER CCodeGen_x86_32::g_registers[MAX_REGISTERS] =
7 {
8 	CX86Assembler::rBX,
9 	CX86Assembler::rSI,
10 	CX86Assembler::rDI,
11 };
12 
13 CX86Assembler::XMMREGISTER CCodeGen_x86_32::g_mdRegisters[MAX_MDREGISTERS] =
14 {
15 	CX86Assembler::xMM4,
16 	CX86Assembler::xMM5,
17 	CX86Assembler::xMM6,
18 	CX86Assembler::xMM7
19 };
20 
21 CCodeGen_x86_32::CONSTMATCHER CCodeGen_x86_32::g_constMatchers[] =
22 {
23 	{ OP_PARAM,			MATCH_NIL,			MATCH_CONTEXT,		MATCH_NIL,			&CCodeGen_x86_32::Emit_Param_Ctx				},
24 	{ OP_PARAM,			MATCH_NIL,			MATCH_MEMORY,		MATCH_NIL,			&CCodeGen_x86_32::Emit_Param_Mem				},
25 	{ OP_PARAM,			MATCH_NIL,			MATCH_CONSTANT,		MATCH_NIL,			&CCodeGen_x86_32::Emit_Param_Cst				},
26 	{ OP_PARAM,			MATCH_NIL,			MATCH_REGISTER,		MATCH_NIL,			&CCodeGen_x86_32::Emit_Param_Reg				},
27 	{ OP_PARAM,			MATCH_NIL,			MATCH_MEMORY64,		MATCH_NIL,			&CCodeGen_x86_32::Emit_Param_Mem64				},
28 	{ OP_PARAM,			MATCH_NIL,			MATCH_CONSTANT64,	MATCH_NIL,			&CCodeGen_x86_32::Emit_Param_Cst64				},
29 	{ OP_PARAM,			MATCH_NIL,			MATCH_REGISTER128,	MATCH_NIL,			&CCodeGen_x86_32::Emit_Param_Reg128				},
30 	{ OP_PARAM,			MATCH_NIL,			MATCH_MEMORY128,	MATCH_NIL,			&CCodeGen_x86_32::Emit_Param_Mem128				},
31 
32 	{ OP_PARAM_RET,		MATCH_NIL,			MATCH_MEMORY128,	MATCH_NIL,			&CCodeGen_x86_32::Emit_ParamRet_Mem128			},
33 
34 	{ OP_CALL,			MATCH_NIL,			MATCH_CONSTANTPTR,	MATCH_CONSTANT,		&CCodeGen_x86_32::Emit_Call						},
35 
36 	{ OP_RETVAL,		MATCH_TEMPORARY,	MATCH_NIL,			MATCH_NIL,			&CCodeGen_x86_32::Emit_RetVal_Tmp				},
37 	{ OP_RETVAL,		MATCH_REGISTER,		MATCH_NIL,			MATCH_NIL,			&CCodeGen_x86_32::Emit_RetVal_Reg				},
38 	{ OP_RETVAL,		MATCH_MEMORY64,		MATCH_NIL,			MATCH_NIL,			&CCodeGen_x86_32::Emit_RetVal_Mem64				},
39 
40 	{ OP_MOV,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_NIL,			&CCodeGen_x86_32::Emit_Mov_Mem64Mem64			},
41 	{ OP_MOV,			MATCH_MEMORY64,		MATCH_CONSTANT64,	MATCH_NIL,			&CCodeGen_x86_32::Emit_Mov_Mem64Cst64			},
42 
43 	{ OP_ADD64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_MEMORY64,		&CCodeGen_x86_32::Emit_Add64_MemMemMem			},
44 	{ OP_ADD64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_CONSTANT64,	&CCodeGen_x86_32::Emit_Add64_MemMemCst			},
45 
46 	{ OP_SUB64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_MEMORY64,		&CCodeGen_x86_32::Emit_Sub64_MemMemMem			},
47 	{ OP_SUB64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_CONSTANT64,	&CCodeGen_x86_32::Emit_Sub64_MemMemCst			},
48 	{ OP_SUB64,			MATCH_MEMORY64,		MATCH_CONSTANT64,	MATCH_MEMORY64,		&CCodeGen_x86_32::Emit_Sub64_MemCstMem			},
49 
50 	{ OP_AND64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_MEMORY64,		&CCodeGen_x86_32::Emit_And64_MemMemMem			},
51 
52 	{ OP_SRL64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_REGISTER,		&CCodeGen_x86_32::Emit_Srl64_MemMemReg			},
53 	{ OP_SRL64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_MEMORY,		&CCodeGen_x86_32::Emit_Srl64_MemMemMem			},
54 	{ OP_SRL64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_CONSTANT,		&CCodeGen_x86_32::Emit_Srl64_MemMemCst			},
55 
56 	{ OP_SRA64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_REGISTER,		&CCodeGen_x86_32::Emit_Sra64_MemMemReg			},
57 	{ OP_SRA64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_MEMORY,		&CCodeGen_x86_32::Emit_Sra64_MemMemMem			},
58 	{ OP_SRA64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_CONSTANT,		&CCodeGen_x86_32::Emit_Sra64_MemMemCst			},
59 
60 	{ OP_SLL64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_REGISTER,		&CCodeGen_x86_32::Emit_Sll64_MemMemReg			},
61 	{ OP_SLL64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_MEMORY,		&CCodeGen_x86_32::Emit_Sll64_MemMemMem			},
62 	{ OP_SLL64,			MATCH_MEMORY64,		MATCH_MEMORY64,		MATCH_CONSTANT,		&CCodeGen_x86_32::Emit_Sll64_MemMemCst			},
63 
64 	{ OP_CMP64,			MATCH_REGISTER,		MATCH_RELATIVE64,	MATCH_RELATIVE64,	&CCodeGen_x86_32::Emit_Cmp64_RegRelRel			},
65 	{ OP_CMP64,			MATCH_RELATIVE,		MATCH_RELATIVE64,	MATCH_RELATIVE64,	&CCodeGen_x86_32::Emit_Cmp64_RelRelRel			},
66 	{ OP_CMP64,			MATCH_REGISTER,		MATCH_RELATIVE64,	MATCH_CONSTANT64,	&CCodeGen_x86_32::Emit_Cmp64_RegRelCst			},
67 	{ OP_CMP64,			MATCH_RELATIVE,		MATCH_RELATIVE64,	MATCH_CONSTANT64,	&CCodeGen_x86_32::Emit_Cmp64_RelRelCst			},
68 	{ OP_CMP64,			MATCH_TEMPORARY,	MATCH_RELATIVE64,	MATCH_RELATIVE64,	&CCodeGen_x86_32::Emit_Cmp64_TmpRelRoc			},
69 	{ OP_CMP64,			MATCH_TEMPORARY,	MATCH_RELATIVE64,	MATCH_CONSTANT64,	&CCodeGen_x86_32::Emit_Cmp64_TmpRelRoc			},
70 
71 	{ OP_RELTOREF,		MATCH_TMP_REF,		MATCH_CONSTANT,		MATCH_NIL,			&CCodeGen_x86_32::Emit_RelToRef_TmpCst			},
72 
73 	{ OP_ADDREF,		MATCH_MEM_REF,		MATCH_MEM_REF,		MATCH_REGISTER,		&CCodeGen_x86_32::Emit_AddRef_MemMemReg			},
74 	{ OP_ADDREF,		MATCH_MEM_REF,		MATCH_MEM_REF,		MATCH_MEMORY,		&CCodeGen_x86_32::Emit_AddRef_MemMemMem			},
75 	{ OP_ADDREF,		MATCH_MEM_REF,		MATCH_MEM_REF,		MATCH_CONSTANT,		&CCodeGen_x86_32::Emit_AddRef_MemMemCst			},
76 
77 	{ OP_LOADFROMREF,	MATCH_REGISTER,		MATCH_TMP_REF,		MATCH_NIL,			&CCodeGen_x86_32::Emit_LoadFromRef_RegTmp		},
78 	{ OP_LOADFROMREF,	MATCH_MEMORY,		MATCH_TMP_REF,		MATCH_NIL,			&CCodeGen_x86_32::Emit_LoadFromRef_MemTmp		},
79 	{ OP_LOADFROMREF,	MATCH_REGISTER128,	MATCH_MEM_REF,		MATCH_NIL,			&CCodeGen_x86_32::Emit_LoadFromRef_Md_RegMem	},
80 	{ OP_LOADFROMREF,	MATCH_MEMORY128,	MATCH_MEM_REF,		MATCH_NIL,			&CCodeGen_x86_32::Emit_LoadFromRef_Md_MemMem	},
81 
82 	{ OP_STOREATREF,	MATCH_NIL,			MATCH_TMP_REF,		MATCH_REGISTER,		&CCodeGen_x86_32::Emit_StoreAtRef_TmpReg		},
83 	{ OP_STOREATREF,	MATCH_NIL,			MATCH_TMP_REF,		MATCH_MEMORY,		&CCodeGen_x86_32::Emit_StoreAtRef_TmpMem		},
84 	{ OP_STOREATREF,	MATCH_NIL,			MATCH_TMP_REF,		MATCH_CONSTANT,		&CCodeGen_x86_32::Emit_StoreAtRef_TmpCst		},
85 	{ OP_STOREATREF,	MATCH_NIL,			MATCH_MEM_REF,		MATCH_REGISTER128,	&CCodeGen_x86_32::Emit_StoreAtRef_Md_MemReg		},
86 	{ OP_STOREATREF,	MATCH_NIL,			MATCH_MEM_REF,		MATCH_MEMORY128,	&CCodeGen_x86_32::Emit_StoreAtRef_Md_MemMem		},
87 
88 	{ OP_MOV,			MATCH_NIL,			MATCH_NIL,			MATCH_NIL,			NULL											},
89 };
90 
CCodeGen_x86_32()91 CCodeGen_x86_32::CCodeGen_x86_32()
92 {
93 	CCodeGen_x86::m_registers = g_registers;
94 	CCodeGen_x86::m_mdRegisters = g_mdRegisters;
95 
96 	for(CONSTMATCHER* constMatcher = g_constMatchers; constMatcher->emitter != NULL; constMatcher++)
97 	{
98 		MATCHER matcher;
99 		matcher.op			= constMatcher->op;
100 		matcher.dstType		= constMatcher->dstType;
101 		matcher.src1Type	= constMatcher->src1Type;
102 		matcher.src2Type	= constMatcher->src2Type;
103 		matcher.emitter		= std::bind(constMatcher->emitter, this, std::placeholders::_1);
104 		m_matchers.insert(MatcherMapType::value_type(matcher.op, matcher));
105 	}
106 }
107 
~CCodeGen_x86_32()108 CCodeGen_x86_32::~CCodeGen_x86_32()
109 {
110 
111 }
112 
SetImplicitRetValueParamFixUpRequired(bool implicitRetValueParamFixUpRequired)113 void CCodeGen_x86_32::SetImplicitRetValueParamFixUpRequired(bool implicitRetValueParamFixUpRequired)
114 {
115 	m_implicitRetValueParamFixUpRequired = implicitRetValueParamFixUpRequired;
116 }
117 
Emit_Prolog(const StatementList & statements,unsigned int stackSize,uint32 registerUsage)118 void CCodeGen_x86_32::Emit_Prolog(const StatementList& statements, unsigned int stackSize, uint32 registerUsage)
119 {
120 	//Compute the size needed to store all function call parameters
121 	uint32 maxParamSize = 0;
122 	uint32 maxParamSpillSize = 0;
123 	{
124 		uint32 currParamSize = 0;
125 		uint32 currParamSpillSize = 0;
126 		for(const auto& statement : statements)
127 		{
128 			switch(statement.op)
129 			{
130 			case OP_PARAM:
131 			case OP_PARAM_RET:
132 				{
133 					CSymbol* src1 = statement.src1->GetSymbol().get();
134 					switch(src1->m_type)
135 					{
136 						case SYM_CONTEXT:
137 						case SYM_REGISTER:
138 						case SYM_RELATIVE:
139 						case SYM_CONSTANT:
140 						case SYM_TEMPORARY:
141 						case SYM_RELATIVE128:
142 						case SYM_TEMPORARY128:
143 							currParamSize += 4;
144 							break;
145 						case SYM_REGISTER128:
146 							currParamSize += 4;
147 							currParamSpillSize += 16;
148 							break;
149 						case SYM_CONSTANT64:
150 						case SYM_TEMPORARY64:
151 						case SYM_RELATIVE64:
152 							currParamSize += 8;
153 							break;
154 						default:
155 							assert(0);
156 							break;
157 					}
158 				}
159 				break;
160 			case OP_CALL:
161 				maxParamSize = std::max<uint32>(currParamSize, maxParamSize);
162 				maxParamSpillSize = std::max<uint32>(currParamSpillSize, maxParamSpillSize);
163 				currParamSize = 0;
164 				currParamSpillSize = 0;
165 				break;
166 			}
167 		}
168 	}
169 
170 	assert((stackSize & 0x0F) == 0);
171 	assert((maxParamSpillSize & 0x0F) == 0);
172 	maxParamSize = ((maxParamSize + 0xF) & ~0xF);
173 
174 	//Fetch parameter
175 	m_assembler.Push(CX86Assembler::rBP);
176 	m_assembler.MovEd(CX86Assembler::rBP, CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, 8));
177 
178 	//Save registers
179 	for(unsigned int i = 0; i < MAX_REGISTERS; i++)
180 	{
181 		if(registerUsage & (1 << i))
182 		{
183 			m_assembler.Push(m_registers[i]);
184 		}
185 	}
186 
187 	//Align stack
188 	m_assembler.MovEd(CX86Assembler::rAX, CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP));
189 	m_assembler.AndId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP), ~0x0F);
190 	m_assembler.SubId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP), 0x0C);
191 	m_assembler.Push(CX86Assembler::rAX);
192 
193 	//Allocate stack space for temps
194 	m_totalStackAlloc = stackSize + maxParamSize + maxParamSpillSize;
195 	m_paramSpillBase = stackSize + maxParamSize;
196 	m_stackLevel = maxParamSize;
197 
198 	//Allocate stack space
199 	if(m_totalStackAlloc != 0)
200 	{
201 		m_assembler.SubId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP), m_totalStackAlloc);
202 	}
203 
204 	//-------------------------------
205 	//Stack Frame
206 	//-------------------------------
207 	//(High address)
208 	//------------------
209 	//Saved registers + alignment adjustment
210 	//------------------
211 	//Saved rSP
212 	//------------------			<----- aligned on 0x10
213 	//Params spill space
214 	//------------------			<----- rSP + m_paramSpillBase
215 	//Temporary symbols (stackSize) + alignment adjustment
216 	//------------------			<----- rSP + m_stackLevel
217 	//Param space for callee
218 	//------------------			<----- rSP
219 	//(Low address)
220 }
221 
Emit_Epilog(unsigned int stackSize,uint32 registerUsage)222 void CCodeGen_x86_32::Emit_Epilog(unsigned int stackSize, uint32 registerUsage)
223 {
224 	if(m_totalStackAlloc != 0)
225 	{
226 		m_assembler.AddId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP), m_totalStackAlloc);
227 	}
228 
229 	m_assembler.Pop(CX86Assembler::rSP);
230 
231 	for(int i = MAX_REGISTERS - 1; i >= 0; i--)
232 	{
233 		if(registerUsage & (1 << i))
234 		{
235 			m_assembler.Pop(m_registers[i]);
236 		}
237 	}
238 
239 	m_assembler.Pop(CX86Assembler::rBP);
240 	m_assembler.Ret();
241 }
242 
GetAvailableRegisterCount() const243 unsigned int CCodeGen_x86_32::GetAvailableRegisterCount() const
244 {
245 	return MAX_REGISTERS;
246 }
247 
GetAvailableMdRegisterCount() const248 unsigned int CCodeGen_x86_32::GetAvailableMdRegisterCount() const
249 {
250 	return MAX_MDREGISTERS;
251 }
252 
CanHold128BitsReturnValueInRegisters() const253 bool CCodeGen_x86_32::CanHold128BitsReturnValueInRegisters() const
254 {
255 	return false;
256 }
257 
Emit_Param_Ctx(const STATEMENT & statement)258 void CCodeGen_x86_32::Emit_Param_Ctx(const STATEMENT& statement)
259 {
260 	m_params.push_back(
261 		[this] (CALL_STATE& state)
262 		{
263 			m_assembler.MovGd(CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, state.paramOffset), CX86Assembler::rBP);
264 			state.paramOffset += 4;
265 		}
266 	);
267 }
268 
Emit_Param_Reg(const STATEMENT & statement)269 void CCodeGen_x86_32::Emit_Param_Reg(const STATEMENT& statement)
270 {
271 	auto src1 = statement.src1->GetSymbol().get();
272 	m_params.push_back(
273 		[this, src1] (CALL_STATE& state)
274 		{
275 			m_assembler.MovGd(CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, state.paramOffset), m_registers[src1->m_valueLow]);
276 			state.paramOffset += 4;
277 		}
278 	);
279 }
280 
Emit_Param_Mem(const STATEMENT & statement)281 void CCodeGen_x86_32::Emit_Param_Mem(const STATEMENT& statement)
282 {
283 	auto src1 = statement.src1->GetSymbol().get();
284 	m_params.push_back(
285 		[this, src1] (CALL_STATE& state)
286 		{
287 			m_assembler.MovEd(CX86Assembler::rAX, MakeMemorySymbolAddress(src1));
288 			m_assembler.MovGd(CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, state.paramOffset), CX86Assembler::rAX);
289 			state.paramOffset += 4;
290 		}
291 	);
292 }
293 
Emit_Param_Cst(const STATEMENT & statement)294 void CCodeGen_x86_32::Emit_Param_Cst(const STATEMENT& statement)
295 {
296 	auto src1 = statement.src1->GetSymbol().get();
297 	m_params.push_back(
298 		[this, src1] (CALL_STATE& state)
299 		{
300 			m_assembler.MovId(CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, state.paramOffset), src1->m_valueLow);
301 			state.paramOffset += 4;
302 		}
303 	);
304 }
305 
Emit_Param_Mem64(const STATEMENT & statement)306 void CCodeGen_x86_32::Emit_Param_Mem64(const STATEMENT& statement)
307 {
308 	auto src1 = statement.src1->GetSymbol().get();
309 	m_params.push_back(
310 		[this, src1] (CALL_STATE& state)
311 		{
312 			m_assembler.MovEd(CX86Assembler::rAX, MakeMemory64SymbolLoAddress(src1));
313 			m_assembler.MovEd(CX86Assembler::rDX, MakeMemory64SymbolHiAddress(src1));
314 			m_assembler.MovGd(CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, state.paramOffset + 0), CX86Assembler::rAX);
315 			m_assembler.MovGd(CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, state.paramOffset + 4), CX86Assembler::rDX);
316 			state.paramOffset += 8;
317 		}
318 	);
319 }
320 
Emit_Param_Cst64(const STATEMENT & statement)321 void CCodeGen_x86_32::Emit_Param_Cst64(const STATEMENT& statement)
322 {
323 	auto src1 = statement.src1->GetSymbol().get();
324 	m_params.push_back(
325 		[this, src1] (CALL_STATE& state)
326 		{
327 			m_assembler.MovId(CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, state.paramOffset + 0), src1->m_valueLow);
328 			m_assembler.MovId(CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, state.paramOffset + 4), src1->m_valueHigh);
329 			state.paramOffset += 8;
330 		}
331 	);
332 }
333 
Emit_Param_Reg128(const STATEMENT & statement)334 void CCodeGen_x86_32::Emit_Param_Reg128(const STATEMENT& statement)
335 {
336 	auto src1 = statement.src1->GetSymbol().get();
337 	m_params.push_back(
338 		[this, src1] (CALL_STATE& state)
339 		{
340 			auto paramTempAddr = CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, m_paramSpillBase + state.paramSpillOffset);
341 
342 			m_assembler.MovapsVo(paramTempAddr, m_mdRegisters[src1->m_valueLow]);
343 			m_assembler.LeaGd(CX86Assembler::rAX, paramTempAddr);
344 			m_assembler.MovGd(CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, state.paramOffset), CX86Assembler::rAX);
345 
346 			state.paramOffset += 4;
347 			state.paramSpillOffset += 0x10;
348 		}
349 	);
350 }
351 
Emit_Param_Mem128(const STATEMENT & statement)352 void CCodeGen_x86_32::Emit_Param_Mem128(const STATEMENT& statement)
353 {
354 	auto src1 = statement.src1->GetSymbol().get();
355 	m_params.push_back(
356 		[this, src1] (CALL_STATE& state)
357 		{
358 			m_assembler.LeaGd(CX86Assembler::rAX, MakeMemory128SymbolAddress(src1));
359 			m_assembler.MovGd(CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, state.paramOffset), CX86Assembler::rAX);
360 			state.paramOffset += 4;
361 		}
362 	);
363 }
364 
Emit_ParamRet_Mem128(const STATEMENT & statement)365 void CCodeGen_x86_32::Emit_ParamRet_Mem128(const STATEMENT& statement)
366 {
367 	//Basically the same as Param_Mem128, but special care must be taken
368 	//as System V ABI automatically cleans up that extra parameter that's
369 	//used as return value
370 	Emit_Param_Mem128(statement);
371 	assert(!m_hasImplicitRetValueParam);
372 	m_hasImplicitRetValueParam = true;
373 }
374 
Emit_Call(const STATEMENT & statement)375 void CCodeGen_x86_32::Emit_Call(const STATEMENT& statement)
376 {
377 	auto src1 = statement.src1->GetSymbol().get();
378 	auto src2 = statement.src2->GetSymbol().get();
379 
380 	uint32 paramCount = src2->m_valueLow;
381 	CALL_STATE callState;
382 	for(unsigned int i = 0; i < paramCount; i++)
383 	{
384 		auto emitter(m_params.back());
385 		m_params.pop_back();
386 		emitter(callState);
387 	}
388 
389 	m_assembler.MovId(CX86Assembler::rAX, src1->m_valueLow);
390 	auto symbolRefLabel = m_assembler.CreateLabel();
391 	m_assembler.MarkLabel(symbolRefLabel, -4);
392 	m_symbolReferenceLabels.push_back(std::make_pair(src1->GetConstantPtr(), symbolRefLabel));
393 	m_assembler.CallEd(CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX));
394 
395 	if(m_hasImplicitRetValueParam && m_implicitRetValueParamFixUpRequired)
396 	{
397 		//Allocated stack space for the extra parameter is cleaned up by the callee.
398 		//So adjust the amount of stack space we free up after the call
399 		m_assembler.SubId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP), 4);
400 	}
401 
402 	m_hasImplicitRetValueParam = false;
403 }
404 
Emit_RetVal_Tmp(const STATEMENT & statement)405 void CCodeGen_x86_32::Emit_RetVal_Tmp(const STATEMENT& statement)
406 {
407 	CSymbol* dst = statement.dst->GetSymbol().get();
408 
409 	m_assembler.MovGd(MakeTemporarySymbolAddress(dst), CX86Assembler::rAX);
410 }
411 
Emit_RetVal_Reg(const STATEMENT & statement)412 void CCodeGen_x86_32::Emit_RetVal_Reg(const STATEMENT& statement)
413 {
414 	CSymbol* dst = statement.dst->GetSymbol().get();
415 
416 	assert(dst->m_type == SYM_REGISTER);
417 
418 	m_assembler.MovGd(CX86Assembler::MakeRegisterAddress(m_registers[dst->m_valueLow]), CX86Assembler::rAX);
419 }
420 
Emit_RetVal_Mem64(const STATEMENT & statement)421 void CCodeGen_x86_32::Emit_RetVal_Mem64(const STATEMENT& statement)
422 {
423 	CSymbol* dst = statement.dst->GetSymbol().get();
424 
425 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
426 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), CX86Assembler::rDX);
427 }
428 
Emit_Mov_Mem64Mem64(const STATEMENT & statement)429 void CCodeGen_x86_32::Emit_Mov_Mem64Mem64(const STATEMENT& statement)
430 {
431 	auto dst = statement.dst->GetSymbol().get();
432 	auto src1 = statement.src1->GetSymbol().get();
433 
434 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemory64SymbolLoAddress(src1));
435 	m_assembler.MovEd(CX86Assembler::rDX, MakeMemory64SymbolHiAddress(src1));
436 
437 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
438 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), CX86Assembler::rDX);
439 }
440 
Emit_Mov_Mem64Cst64(const STATEMENT & statement)441 void CCodeGen_x86_32::Emit_Mov_Mem64Cst64(const STATEMENT& statement)
442 {
443 	auto dst = statement.dst->GetSymbol().get();
444 	auto src1 = statement.src1->GetSymbol().get();
445 
446 	assert(src1->m_type == SYM_CONSTANT64);
447 
448 	m_assembler.MovId(MakeMemory64SymbolLoAddress(dst), src1->m_valueLow);
449 	m_assembler.MovId(MakeMemory64SymbolHiAddress(dst), src1->m_valueHigh);
450 }
451 
Emit_Add64_MemMemMem(const STATEMENT & statement)452 void CCodeGen_x86_32::Emit_Add64_MemMemMem(const STATEMENT& statement)
453 {
454 	auto dst = statement.dst->GetSymbol().get();
455 	auto src1 = statement.src1->GetSymbol().get();
456 	auto src2 = statement.src2->GetSymbol().get();
457 
458 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemory64SymbolLoAddress(src1));
459 	m_assembler.MovEd(CX86Assembler::rDX, MakeMemory64SymbolHiAddress(src1));
460 
461 	m_assembler.AddEd(CX86Assembler::rAX, MakeMemory64SymbolLoAddress(src2));
462 	m_assembler.AdcEd(CX86Assembler::rDX, MakeMemory64SymbolHiAddress(src2));
463 
464 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
465 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), CX86Assembler::rDX);
466 }
467 
Emit_Add64_MemMemCst(const STATEMENT & statement)468 void CCodeGen_x86_32::Emit_Add64_MemMemCst(const STATEMENT& statement)
469 {
470 	auto dst = statement.dst->GetSymbol().get();
471 	auto src1 = statement.src1->GetSymbol().get();
472 	auto src2 = statement.src2->GetSymbol().get();
473 
474 	assert(src2->m_type == SYM_CONSTANT64);
475 
476 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemory64SymbolLoAddress(src1));
477 	m_assembler.MovEd(CX86Assembler::rDX, MakeMemory64SymbolHiAddress(src1));
478 
479 	m_assembler.AddId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX), src2->m_valueLow);
480 	m_assembler.AdcId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rDX), src2->m_valueHigh);
481 
482 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
483 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), CX86Assembler::rDX);
484 }
485 
Emit_Sub64_MemMemMem(const STATEMENT & statement)486 void CCodeGen_x86_32::Emit_Sub64_MemMemMem(const STATEMENT& statement)
487 {
488 	auto dst = statement.dst->GetSymbol().get();
489 	auto src1 = statement.src1->GetSymbol().get();
490 	auto src2 = statement.src2->GetSymbol().get();
491 
492 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemory64SymbolLoAddress(src1));
493 	m_assembler.MovEd(CX86Assembler::rDX, MakeMemory64SymbolHiAddress(src1));
494 
495 	m_assembler.SubEd(CX86Assembler::rAX, MakeMemory64SymbolLoAddress(src2));
496 	m_assembler.SbbEd(CX86Assembler::rDX, MakeMemory64SymbolHiAddress(src2));
497 
498 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
499 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), CX86Assembler::rDX);
500 }
501 
Emit_Sub64_MemMemCst(const STATEMENT & statement)502 void CCodeGen_x86_32::Emit_Sub64_MemMemCst(const STATEMENT& statement)
503 {
504 	auto dst = statement.dst->GetSymbol().get();
505 	auto src1 = statement.src1->GetSymbol().get();
506 	auto src2 = statement.src2->GetSymbol().get();
507 
508 	assert(src2->m_type == SYM_CONSTANT64);
509 
510 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemory64SymbolLoAddress(src1));
511 	m_assembler.MovEd(CX86Assembler::rDX, MakeMemory64SymbolHiAddress(src1));
512 
513 	m_assembler.SubId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX), src2->m_valueLow);
514 	m_assembler.SbbId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rDX), src2->m_valueHigh);
515 
516 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
517 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), CX86Assembler::rDX);
518 }
519 
Emit_Sub64_MemCstMem(const STATEMENT & statement)520 void CCodeGen_x86_32::Emit_Sub64_MemCstMem(const STATEMENT& statement)
521 {
522 	auto dst = statement.dst->GetSymbol().get();
523 	auto src1 = statement.src1->GetSymbol().get();
524 	auto src2 = statement.src2->GetSymbol().get();
525 
526 	assert(src1->m_type == SYM_CONSTANT64);
527 
528 	m_assembler.MovId(CX86Assembler::rAX, src1->m_valueLow);
529 	m_assembler.MovId(CX86Assembler::rDX, src1->m_valueHigh);
530 
531 	m_assembler.SubEd(CX86Assembler::rAX, MakeMemory64SymbolLoAddress(src2));
532 	m_assembler.SbbEd(CX86Assembler::rDX, MakeMemory64SymbolHiAddress(src2));
533 
534 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
535 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), CX86Assembler::rDX);
536 }
537 
Emit_And64_MemMemMem(const STATEMENT & statement)538 void CCodeGen_x86_32::Emit_And64_MemMemMem(const STATEMENT& statement)
539 {
540 	auto dst = statement.dst->GetSymbol().get();
541 	auto src1 = statement.src1->GetSymbol().get();
542 	auto src2 = statement.src2->GetSymbol().get();
543 
544 	m_assembler.MovEd(CX86Assembler::rAX, MakeMemory64SymbolLoAddress(src1));
545 	m_assembler.MovEd(CX86Assembler::rDX, MakeMemory64SymbolHiAddress(src1));
546 
547 	m_assembler.AndEd(CX86Assembler::rAX, MakeMemory64SymbolLoAddress(src2));
548 	m_assembler.AndEd(CX86Assembler::rDX, MakeMemory64SymbolHiAddress(src2));
549 
550 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), CX86Assembler::rAX);
551 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), CX86Assembler::rDX);
552 }
553 
554 //---------------------------------------------------------------------------------
555 //SR64
556 //---------------------------------------------------------------------------------
557 
Emit_Sr64Var_MemMem(CSymbol * dst,CSymbol * src1,CX86Assembler::REGISTER shiftRegister,SHIFTRIGHT_TYPE shiftType)558 void CCodeGen_x86_32::Emit_Sr64Var_MemMem(CSymbol* dst, CSymbol* src1, CX86Assembler::REGISTER shiftRegister, SHIFTRIGHT_TYPE shiftType)
559 {
560 	auto regLo = CX86Assembler::rAX;
561 	auto regHi = CX86Assembler::rDX;
562 	auto regSa = CX86Assembler::rCX;
563 
564 	auto lessThan32Label = m_assembler.CreateLabel();
565 	auto endLabel = m_assembler.CreateLabel();
566 
567 	if(shiftRegister != regSa)
568 	{
569 		m_assembler.MovEd(regSa, CX86Assembler::MakeRegisterAddress(shiftRegister));
570 	}
571 
572 	m_assembler.AndId(CX86Assembler::MakeRegisterAddress(regSa), 0x3F);
573 	m_assembler.CmpId(CX86Assembler::MakeRegisterAddress(regSa), 32);
574 	m_assembler.JbJx(lessThan32Label);
575 
576 	//greaterOrEqual:
577 	//---------------------------------------------
578 	m_assembler.MovEd(regLo, MakeMemory64SymbolHiAddress(src1));
579 	m_assembler.AndId(CX86Assembler::MakeRegisterAddress(regSa), 0x1F);
580 
581 	if(shiftType == SHIFTRIGHT_LOGICAL)
582 	{
583 		m_assembler.ShrEd(CX86Assembler::MakeRegisterAddress(regLo));
584 		m_assembler.XorEd(regHi, CX86Assembler::MakeRegisterAddress(regHi));
585 	}
586 	else if(shiftType == SHIFTRIGHT_ARITHMETIC)
587 	{
588 		m_assembler.MovEd(regHi, CX86Assembler::MakeRegisterAddress(regLo));
589 		m_assembler.SarEd(CX86Assembler::MakeRegisterAddress(regHi), 31);
590 		m_assembler.SarEd(CX86Assembler::MakeRegisterAddress(regLo));
591 	}
592 	else
593 	{
594 		assert(false);
595 	}
596 
597 	m_assembler.JmpJx(endLabel);
598 
599 	//lessThan:
600 	//---------------------------------------------
601 	m_assembler.MarkLabel(lessThan32Label);
602 
603 	m_assembler.MovEd(regLo, MakeMemory64SymbolLoAddress(src1));
604 	m_assembler.MovEd(regHi, MakeMemory64SymbolHiAddress(src1));
605 
606 	m_assembler.ShrdEd(CX86Assembler::MakeRegisterAddress(regLo), regHi);
607 	if(shiftType == SHIFTRIGHT_LOGICAL)
608 	{
609 		m_assembler.ShrEd(CX86Assembler::MakeRegisterAddress(regHi));
610 	}
611 	else if(shiftType == SHIFTRIGHT_ARITHMETIC)
612 	{
613 		m_assembler.SarEd(CX86Assembler::MakeRegisterAddress(regHi));
614 	}
615 	else
616 	{
617 		assert(false);
618 	}
619 
620 	//end:
621 	//---------------------------------------------
622 	m_assembler.MarkLabel(endLabel);
623 
624 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), regLo);
625 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), regHi);
626 }
627 
Emit_Sr64Cst_MemMem(CSymbol * dst,CSymbol * src1,uint32 shiftAmount,SHIFTRIGHT_TYPE shiftType)628 void CCodeGen_x86_32::Emit_Sr64Cst_MemMem(CSymbol* dst, CSymbol* src1, uint32 shiftAmount, SHIFTRIGHT_TYPE shiftType)
629 {
630 	assert(dst->m_type  == SYM_RELATIVE64);
631 	assert(src1->m_type == SYM_RELATIVE64);
632 
633 	shiftAmount = shiftAmount & 0x3F;
634 
635 	auto regLo = CX86Assembler::rAX;
636 	auto regHi = CX86Assembler::rDX;
637 
638 	if(shiftAmount >= 32)
639 	{
640 		m_assembler.MovEd(regLo, MakeMemory64SymbolHiAddress(src1));
641 
642 		if(shiftType == SHIFTRIGHT_LOGICAL)
643 		{
644 			if(shiftAmount != 32)
645 			{
646 				//shr reg, amount
647 				m_assembler.ShrEd(CX86Assembler::MakeRegisterAddress(regLo), shiftAmount & 0x1F);
648 			}
649 
650 			m_assembler.XorEd(regHi, CX86Assembler::MakeRegisterAddress(regHi));
651 		}
652 		else if(shiftType == SHIFTRIGHT_ARITHMETIC)
653 		{
654 			if(shiftAmount != 32)
655 			{
656 				//sar reg, amount
657 				m_assembler.SarEd(CX86Assembler::MakeRegisterAddress(regLo), shiftAmount & 0x1F);
658 			}
659 
660 			m_assembler.MovEd(regHi, CX86Assembler::MakeRegisterAddress(regLo));
661 			m_assembler.SarEd(CX86Assembler::MakeRegisterAddress(regHi), 31);
662 		}
663 		else
664 		{
665 			assert(false);
666 		}
667 	}
668 	else //Amount < 32
669 	{
670 		m_assembler.MovEd(regLo, MakeMemory64SymbolLoAddress(src1));
671 		m_assembler.MovEd(regHi, MakeMemory64SymbolHiAddress(src1));
672 
673 		if(shiftAmount != 0)
674 		{
675 			//shrd nReg1, nReg2, nAmount
676 			m_assembler.ShrdEd(CX86Assembler::MakeRegisterAddress(regLo), regHi, shiftAmount);
677 
678 			if(shiftType == SHIFTRIGHT_LOGICAL)
679 			{
680 				//shr nReg2, nAmount
681 				m_assembler.ShrEd(CX86Assembler::MakeRegisterAddress(regHi), shiftAmount);
682 			}
683 			else if(shiftType == SHIFTRIGHT_ARITHMETIC)
684 			{
685 				//sar nReg2, nAmount
686 				m_assembler.SarEd(CX86Assembler::MakeRegisterAddress(regHi), shiftAmount);
687 			}
688 			else
689 			{
690 				assert(false);
691 			}
692 		}
693 	}
694 
695 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), regLo);
696 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), regHi);
697 }
698 
699 //---------------------------------------------------------------------------------
700 //SRL64
701 //---------------------------------------------------------------------------------
702 
Emit_Srl64_MemMemReg(const STATEMENT & statement)703 void CCodeGen_x86_32::Emit_Srl64_MemMemReg(const STATEMENT& statement)
704 {
705 	auto dst = statement.dst->GetSymbol().get();
706 	auto src1 = statement.src1->GetSymbol().get();
707 	auto src2 = statement.src2->GetSymbol().get();
708 
709 	assert(src2->m_type == SYM_REGISTER);
710 
711 	Emit_Sr64Var_MemMem(dst, src1, g_registers[src2->m_valueLow], SHIFTRIGHT_LOGICAL);
712 }
713 
Emit_Srl64_MemMemMem(const STATEMENT & statement)714 void CCodeGen_x86_32::Emit_Srl64_MemMemMem(const STATEMENT& statement)
715 {
716 	auto dst = statement.dst->GetSymbol().get();
717 	auto src1 = statement.src1->GetSymbol().get();
718 	auto src2 = statement.src2->GetSymbol().get();
719 
720 	auto shiftAmount = CX86Assembler::rCX;
721 	m_assembler.MovEd(shiftAmount, MakeMemorySymbolAddress(src2));
722 
723 	Emit_Sr64Var_MemMem(dst, src1, shiftAmount, SHIFTRIGHT_LOGICAL);
724 }
725 
Emit_Srl64_MemMemCst(const STATEMENT & statement)726 void CCodeGen_x86_32::Emit_Srl64_MemMemCst(const STATEMENT& statement)
727 {
728 	auto dst = statement.dst->GetSymbol().get();
729 	auto src1 = statement.src1->GetSymbol().get();
730 	auto src2 = statement.src2->GetSymbol().get();
731 
732 	Emit_Sr64Cst_MemMem(dst, src1, src2->m_valueLow, SHIFTRIGHT_LOGICAL);
733 }
734 
735 //---------------------------------------------------------------------------------
736 //SRA64
737 //---------------------------------------------------------------------------------
738 
Emit_Sra64_MemMemReg(const STATEMENT & statement)739 void CCodeGen_x86_32::Emit_Sra64_MemMemReg(const STATEMENT& statement)
740 {
741 	auto dst = statement.dst->GetSymbol().get();
742 	auto src1 = statement.src1->GetSymbol().get();
743 	auto src2 = statement.src2->GetSymbol().get();
744 
745 	assert(src2->m_type == SYM_REGISTER);
746 
747 	Emit_Sr64Var_MemMem(dst, src1, g_registers[src2->m_valueLow], SHIFTRIGHT_ARITHMETIC);
748 }
749 
Emit_Sra64_MemMemMem(const STATEMENT & statement)750 void CCodeGen_x86_32::Emit_Sra64_MemMemMem(const STATEMENT& statement)
751 {
752 	auto dst = statement.dst->GetSymbol().get();
753 	auto src1 = statement.src1->GetSymbol().get();
754 	auto src2 = statement.src2->GetSymbol().get();
755 
756 	auto shiftAmount = CX86Assembler::rCX;
757 	m_assembler.MovEd(shiftAmount, MakeMemorySymbolAddress(src2));
758 
759 	Emit_Sr64Var_MemMem(dst, src1, shiftAmount, SHIFTRIGHT_ARITHMETIC);
760 }
761 
Emit_Sra64_MemMemCst(const STATEMENT & statement)762 void CCodeGen_x86_32::Emit_Sra64_MemMemCst(const STATEMENT& statement)
763 {
764 	auto dst = statement.dst->GetSymbol().get();
765 	auto src1 = statement.src1->GetSymbol().get();
766 	auto src2 = statement.src2->GetSymbol().get();
767 
768 	Emit_Sr64Cst_MemMem(dst, src1, src2->m_valueLow, SHIFTRIGHT_ARITHMETIC);
769 }
770 
771 //---------------------------------------------------------------------------------
772 //SLL64
773 //---------------------------------------------------------------------------------
774 
Emit_Sll64_MemMemVar(const STATEMENT & statement,CX86Assembler::REGISTER shiftRegister)775 void CCodeGen_x86_32::Emit_Sll64_MemMemVar(const STATEMENT& statement, CX86Assembler::REGISTER shiftRegister)
776 {
777 	CSymbol* dst = statement.dst->GetSymbol().get();
778 	CSymbol* src1 = statement.src1->GetSymbol().get();
779 
780 	CX86Assembler::LABEL doneLabel = m_assembler.CreateLabel();
781 	CX86Assembler::LABEL more32Label = m_assembler.CreateLabel();
782 
783 	CX86Assembler::REGISTER amountReg = CX86Assembler::rCX;
784 	CX86Assembler::REGISTER resultLow = CX86Assembler::rAX;
785 	CX86Assembler::REGISTER resultHigh = CX86Assembler::rDX;
786 
787 	if(shiftRegister != amountReg)
788 	{
789 		m_assembler.MovEd(amountReg, CX86Assembler::MakeRegisterAddress(shiftRegister));
790 	}
791 
792 	m_assembler.MovEd(resultLow, MakeMemory64SymbolLoAddress(src1));
793 	m_assembler.MovEd(resultHigh, MakeMemory64SymbolHiAddress(src1));
794 
795 	m_assembler.AndIb(CX86Assembler::MakeByteRegisterAddress(amountReg), 0x3F);
796 	m_assembler.TestEb(amountReg, CX86Assembler::MakeByteRegisterAddress(amountReg));
797 	m_assembler.JzJx(doneLabel);
798 
799 	m_assembler.CmpIb(CX86Assembler::MakeByteRegisterAddress(amountReg), 0x20);
800 	m_assembler.JnbJx(more32Label);
801 
802 	m_assembler.ShldEd(CX86Assembler::MakeRegisterAddress(resultHigh), resultLow);
803 	m_assembler.ShlEd(CX86Assembler::MakeRegisterAddress(resultLow));
804 	m_assembler.JmpJx(doneLabel);
805 
806 //$more32
807 	m_assembler.MarkLabel(more32Label);
808 
809 	m_assembler.MovEd(resultHigh, CX86Assembler::MakeRegisterAddress(resultLow));
810 	m_assembler.XorEd(resultLow, CX86Assembler::MakeRegisterAddress(resultLow));
811 	m_assembler.AndIb(CX86Assembler::MakeByteRegisterAddress(amountReg), 0x1F);
812 	m_assembler.ShlEd(CX86Assembler::MakeRegisterAddress(resultHigh));
813 
814 //$done
815 	m_assembler.MarkLabel(doneLabel);
816 
817 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), resultLow);
818 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), resultHigh);
819 }
820 
Emit_Sll64_MemMemReg(const STATEMENT & statement)821 void CCodeGen_x86_32::Emit_Sll64_MemMemReg(const STATEMENT& statement)
822 {
823 	CSymbol* src2 = statement.src2->GetSymbol().get();
824 
825 	assert(src2->m_type == SYM_REGISTER);
826 
827 	Emit_Sll64_MemMemVar(statement, g_registers[src2->m_valueLow]);
828 }
829 
Emit_Sll64_MemMemMem(const STATEMENT & statement)830 void CCodeGen_x86_32::Emit_Sll64_MemMemMem(const STATEMENT& statement)
831 {
832 	CSymbol* src2 = statement.src2->GetSymbol().get();
833 
834 	CX86Assembler::REGISTER shiftAmount = CX86Assembler::rCX;
835 
836 	m_assembler.MovEd(shiftAmount, MakeMemorySymbolAddress(src2));
837 
838 	Emit_Sll64_MemMemVar(statement, shiftAmount);
839 }
840 
Emit_Sll64_MemMemCst(const STATEMENT & statement)841 void CCodeGen_x86_32::Emit_Sll64_MemMemCst(const STATEMENT& statement)
842 {
843 	auto dst = statement.dst->GetSymbol().get();
844 	auto src1 = statement.src1->GetSymbol().get();
845 	auto src2 = statement.src2->GetSymbol().get();
846 
847 	assert(src2->m_type == SYM_CONSTANT);
848 
849 	uint8 shiftAmount = static_cast<uint8>(src2->m_valueLow & 0x3F);
850 
851 	auto regLo = CX86Assembler::rAX;
852 	auto regHi = CX86Assembler::rDX;
853 
854 	if(shiftAmount >= 32)
855 	{
856 		m_assembler.MovEd(regHi, MakeMemory64SymbolLoAddress(src1));
857 
858 		if(shiftAmount != 0)
859 		{
860 			//shl reg, amount
861 			m_assembler.ShlEd(CX86Assembler::MakeRegisterAddress(regHi), shiftAmount & 0x1F);
862 		}
863 
864 		m_assembler.XorEd(regLo, CX86Assembler::MakeRegisterAddress(regLo));
865 	}
866 	else //Amount < 32
867 	{
868 		m_assembler.MovEd(regLo, MakeMemory64SymbolLoAddress(src1));
869 		m_assembler.MovEd(regHi, MakeMemory64SymbolHiAddress(src1));
870 
871 		//shld nReg2, nReg1, nAmount
872 		m_assembler.ShldEd(CX86Assembler::MakeRegisterAddress(regHi), regLo, shiftAmount);
873 
874 		//shl nReg1, nAmount
875 		m_assembler.ShlEd(CX86Assembler::MakeRegisterAddress(regLo), shiftAmount);
876 	}
877 
878 	m_assembler.MovGd(MakeMemory64SymbolLoAddress(dst), regLo);
879 	m_assembler.MovGd(MakeMemory64SymbolHiAddress(dst), regHi);
880 }
881 
882 //---------------------------------------------------------------------------------
883 //CMP64
884 //---------------------------------------------------------------------------------
885 
Cmp64_Equal(const STATEMENT & statement)886 void CCodeGen_x86_32::Cmp64_Equal(const STATEMENT& statement)
887 {
888 	auto src1 = statement.src1->GetSymbol().get();
889 	auto src2 = statement.src2->GetSymbol().get();
890 
891 	const auto cmpLo =
892 		[this](CX86Assembler::REGISTER registerId, CSymbol* symbol)
893 		{
894 			switch(symbol->m_type)
895 			{
896 			case SYM_RELATIVE64:
897 				m_assembler.CmpEd(registerId, MakeMemory64SymbolLoAddress(symbol));
898 				break;
899 			case SYM_CONSTANT64:
900 				if(symbol->m_valueLow == 0)
901 				{
902 					m_assembler.TestEd(registerId, CX86Assembler::MakeRegisterAddress(registerId));
903 				}
904 				else
905 				{
906 					m_assembler.CmpId(CX86Assembler::MakeRegisterAddress(registerId), symbol->m_valueLow);
907 				}
908 				break;
909 			default:
910 				assert(0);
911 				break;
912 			}
913 		};
914 
915 	const auto cmpHi =
916 		[this](CX86Assembler::REGISTER registerId, CSymbol* symbol)
917 		{
918 			switch(symbol->m_type)
919 			{
920 			case SYM_RELATIVE64:
921 				m_assembler.CmpEd(registerId, MakeMemory64SymbolHiAddress(symbol));
922 				break;
923 			case SYM_CONSTANT64:
924 				if(symbol->m_valueHigh == 0)
925 				{
926 					m_assembler.TestEd(registerId, CX86Assembler::MakeRegisterAddress(registerId));
927 				}
928 				else
929 				{
930 					m_assembler.CmpId(CX86Assembler::MakeRegisterAddress(registerId), symbol->m_valueHigh);
931 				}
932 				break;
933 			default:
934 				assert(0);
935 				break;
936 			}
937 		};
938 
939 	assert(src1->m_type == SYM_RELATIVE64);
940 
941 	bool isEqual	= (statement.jmpCondition == CONDITION_EQ);
942 
943 	CX86Assembler::REGISTER valReg = CX86Assembler::rDX;
944 	CX86Assembler::REGISTER res1Reg = CX86Assembler::rAX;
945 	CX86Assembler::REGISTER res2Reg = CX86Assembler::rCX;
946 
947 	m_assembler.MovEd(valReg, MakeMemory64SymbolLoAddress(src1));
948 	cmpLo(valReg, src2);
949 
950 	if(isEqual)
951 	{
952 		m_assembler.SeteEb(CX86Assembler::MakeRegisterAddress(res1Reg));
953 	}
954 	else
955 	{
956 		m_assembler.SetneEb(CX86Assembler::MakeRegisterAddress(res1Reg));
957 	}
958 
959 	m_assembler.MovEd(valReg, MakeMemory64SymbolHiAddress(src1));
960 	cmpHi(valReg, src2);
961 
962 	if(isEqual)
963 	{
964 		m_assembler.SeteEb(CX86Assembler::MakeRegisterAddress(res2Reg));
965 	}
966 	else
967 	{
968 		m_assembler.SetneEb(CX86Assembler::MakeRegisterAddress(res2Reg));
969 	}
970 
971 	if(isEqual)
972 	{
973 		m_assembler.AndEd(res1Reg, CX86Assembler::MakeRegisterAddress(res2Reg));
974 	}
975 	else
976 	{
977 		m_assembler.OrEd(res1Reg, CX86Assembler::MakeRegisterAddress(res2Reg));
978 	}
979 
980 	m_assembler.MovzxEb(res1Reg, CX86Assembler::MakeRegisterAddress(res1Reg));
981 }
982 
983 struct CompareOrder64Less
984 {
985 	typedef void (CX86Assembler::*OrderCheckFunction)(const CX86Assembler::CAddress&);
986 
IsSignedCompareOrder64Less987 	static bool IsSigned(Jitter::CONDITION condition)
988 	{
989 		return (condition == CONDITION_LE) || (condition == CONDITION_LT);
990 	}
991 
OrEqualCompareOrder64Less992 	static bool OrEqual(Jitter::CONDITION condition)
993 	{
994 		return (condition == CONDITION_LE) || (condition == CONDITION_BE);
995 	}
996 
CheckOrderSignedCompareOrder64Less997 	static OrderCheckFunction CheckOrderSigned()
998 	{
999 		return &CX86Assembler::SetlEb;
1000 	}
1001 
CheckOrderUnsignedCompareOrder64Less1002 	static OrderCheckFunction CheckOrderUnsigned()
1003 	{
1004 		return &CX86Assembler::SetbEb;
1005 	}
1006 
CheckOrderOrEqualUnsignedCompareOrder64Less1007 	static OrderCheckFunction CheckOrderOrEqualUnsigned()
1008 	{
1009 		return &CX86Assembler::SetbeEb;
1010 	}
1011 };
1012 
1013 struct CompareOrder64Greater
1014 {
1015 	typedef void (CX86Assembler::*OrderCheckFunction)(const CX86Assembler::CAddress&);
1016 
IsSignedCompareOrder64Greater1017 	static bool IsSigned(Jitter::CONDITION condition)
1018 	{
1019 		return (condition == CONDITION_GE) || (condition == CONDITION_GT);
1020 	}
1021 
OrEqualCompareOrder64Greater1022 	static bool OrEqual(Jitter::CONDITION condition)
1023 	{
1024 		return (condition == CONDITION_GE) || (condition == CONDITION_AE);
1025 	}
1026 
CheckOrderSignedCompareOrder64Greater1027 	static OrderCheckFunction CheckOrderSigned()
1028 	{
1029 		return &CX86Assembler::SetgEb;
1030 	}
1031 
CheckOrderUnsignedCompareOrder64Greater1032 	static OrderCheckFunction CheckOrderUnsigned()
1033 	{
1034 		return &CX86Assembler::SetaEb;
1035 	}
1036 
CheckOrderOrEqualUnsignedCompareOrder64Greater1037 	static OrderCheckFunction CheckOrderOrEqualUnsigned()
1038 	{
1039 		return &CX86Assembler::SetaeEb;
1040 	}
1041 };
1042 
1043 template <typename CompareTraits>
Cmp64_Order(const STATEMENT & statement)1044 void CCodeGen_x86_32::Cmp64_Order(const STATEMENT& statement)
1045 {
1046 	auto src1 = statement.src1->GetSymbol().get();
1047 	auto src2 = statement.src2->GetSymbol().get();
1048 
1049 	CompareTraits compareTraits;
1050 	(void)compareTraits;
1051 
1052 	const auto cmpLo =
1053 		[this](CX86Assembler::REGISTER registerId, CSymbol* symbol)
1054 		{
1055 			switch(symbol->m_type)
1056 			{
1057 			case SYM_RELATIVE64:
1058 				m_assembler.CmpEd(registerId, MakeMemory64SymbolLoAddress(symbol));
1059 				break;
1060 			case SYM_CONSTANT64:
1061 				m_assembler.CmpId(CX86Assembler::MakeRegisterAddress(registerId), symbol->m_valueLow);
1062 				break;
1063 			default:
1064 				assert(0);
1065 				break;
1066 			}
1067 		};
1068 
1069 	const auto cmpHi =
1070 		[this](CX86Assembler::REGISTER registerId, CSymbol* symbol)
1071 		{
1072 			switch(symbol->m_type)
1073 			{
1074 			case SYM_RELATIVE64:
1075 				m_assembler.CmpEd(registerId, MakeMemory64SymbolHiAddress(symbol));
1076 				break;
1077 			case SYM_CONSTANT64:
1078 				m_assembler.CmpId(CX86Assembler::MakeRegisterAddress(registerId), symbol->m_valueHigh);
1079 				break;
1080 			default:
1081 				assert(0);
1082 				break;
1083 			}
1084 		};
1085 
1086 	assert(src1->m_type == SYM_RELATIVE64);
1087 
1088 	CX86Assembler::REGISTER regLo = CX86Assembler::rAX;
1089 	CX86Assembler::REGISTER regHi = CX86Assembler::rDX;
1090 
1091 	bool isSigned	= compareTraits.IsSigned(statement.jmpCondition);
1092 	bool orEqual	= compareTraits.OrEqual(statement.jmpCondition);
1093 
1094 	CX86Assembler::LABEL highOrderEqualLabel = m_assembler.CreateLabel();
1095 	CX86Assembler::LABEL doneLabel = m_assembler.CreateLabel();
1096 
1097 	/////////////////////////////////////////
1098 	//Check high order word if equal
1099 
1100 	m_assembler.MovEd(regHi, MakeMemory64SymbolHiAddress(src1));
1101 	cmpHi(regHi, src2);
1102 
1103 	//je highOrderEqual
1104 	m_assembler.JzJx(highOrderEqualLabel);
1105 
1106 	///////////////////////////////////////////////////////////
1107 	//If they aren't equal, this comparaison decides of result
1108 
1109 	//setb/l reg[l]
1110 	if(isSigned)
1111 	{
1112 		((m_assembler).*(compareTraits.CheckOrderSigned()))(CX86Assembler::MakeByteRegisterAddress(regLo));
1113 	}
1114 	else
1115 	{
1116 		((m_assembler).*(compareTraits.CheckOrderUnsigned()))(CX86Assembler::MakeByteRegisterAddress(regLo));
1117 	}
1118 
1119 	//movzx reg, reg[l]
1120 	m_assembler.MovzxEb(regLo, CX86Assembler::MakeByteRegisterAddress(regLo));
1121 
1122 	//jmp done
1123 	m_assembler.JmpJx(doneLabel);
1124 
1125 	//highOrderEqual: /////////////////////////////////////
1126 	m_assembler.MarkLabel(highOrderEqualLabel);
1127 	//If they are equal, next comparaison decides of result
1128 
1129 	m_assembler.MovEd(regLo, MakeMemory64SymbolLoAddress(src1));
1130 	cmpLo(regLo, src2);
1131 
1132 	//setb/be reg[l]
1133 	if(orEqual)
1134 	{
1135 		((m_assembler).*(compareTraits.CheckOrderOrEqualUnsigned()))(CX86Assembler::MakeByteRegisterAddress(regLo));
1136 	}
1137 	else
1138 	{
1139 		((m_assembler).*(compareTraits.CheckOrderUnsigned()))(CX86Assembler::MakeByteRegisterAddress(regLo));
1140 	}
1141 
1142 	//movzx reg, reg[l]
1143 	m_assembler.MovzxEb(regLo, CX86Assembler::MakeByteRegisterAddress(regLo));
1144 
1145 	//done: ///////////////////////////////////////////////
1146 	m_assembler.MarkLabel(doneLabel);
1147 }
1148 
Cmp64_GenericRel(const STATEMENT & statement)1149 void CCodeGen_x86_32::Cmp64_GenericRel(const STATEMENT& statement)
1150 {
1151 	switch(statement.jmpCondition)
1152 	{
1153 	case CONDITION_BL:
1154 	case CONDITION_LT:
1155 	case CONDITION_LE:
1156 		Cmp64_Order<CompareOrder64Less>(statement);
1157 		break;
1158 	case CONDITION_AB:
1159 	case CONDITION_GT:
1160 	case CONDITION_GE:
1161 		Cmp64_Order<CompareOrder64Greater>(statement);
1162 		break;
1163 	case CONDITION_NE:
1164 	case CONDITION_EQ:
1165 		Cmp64_Equal(statement);
1166 		break;
1167 	default:
1168 		assert(0);
1169 		break;
1170 	}
1171 }
1172 
Emit_Cmp64_RegRelRel(const STATEMENT & statement)1173 void CCodeGen_x86_32::Emit_Cmp64_RegRelRel(const STATEMENT& statement)
1174 {
1175 	CSymbol* dst = statement.dst->GetSymbol().get();
1176 
1177 	assert(dst->m_type == SYM_REGISTER);
1178 
1179 	Cmp64_GenericRel(statement);
1180 	m_assembler.MovGd(CX86Assembler::MakeRegisterAddress(m_registers[dst->m_valueLow]), CX86Assembler::rAX);
1181 }
1182 
Emit_Cmp64_RelRelRel(const STATEMENT & statement)1183 void CCodeGen_x86_32::Emit_Cmp64_RelRelRel(const STATEMENT& statement)
1184 {
1185 	CSymbol* dst = statement.dst->GetSymbol().get();
1186 
1187 	assert(dst->m_type == SYM_RELATIVE);
1188 
1189 	Cmp64_GenericRel(statement);
1190 	m_assembler.MovGd(MakeRelativeSymbolAddress(dst), CX86Assembler::rAX);
1191 }
1192 
Emit_Cmp64_RegRelCst(const STATEMENT & statement)1193 void CCodeGen_x86_32::Emit_Cmp64_RegRelCst(const STATEMENT& statement)
1194 {
1195 	CSymbol* dst = statement.dst->GetSymbol().get();
1196 
1197 	assert(dst->m_type == SYM_REGISTER);
1198 
1199 	Cmp64_GenericRel(statement);
1200 	m_assembler.MovGd(CX86Assembler::MakeRegisterAddress(m_registers[dst->m_valueLow]), CX86Assembler::rAX);
1201 }
1202 
Emit_Cmp64_RelRelCst(const STATEMENT & statement)1203 void CCodeGen_x86_32::Emit_Cmp64_RelRelCst(const STATEMENT& statement)
1204 {
1205 	CSymbol* dst = statement.dst->GetSymbol().get();
1206 
1207 	assert(dst->m_type == SYM_RELATIVE);
1208 
1209 	Cmp64_GenericRel(statement);
1210 	m_assembler.MovGd(MakeRelativeSymbolAddress(dst), CX86Assembler::rAX);
1211 }
1212 
Emit_Cmp64_TmpRelRoc(const STATEMENT & statement)1213 void CCodeGen_x86_32::Emit_Cmp64_TmpRelRoc(const STATEMENT& statement)
1214 {
1215 	CSymbol* dst = statement.dst->GetSymbol().get();
1216 
1217 	assert(dst->m_type == SYM_TEMPORARY);
1218 
1219 	Cmp64_GenericRel(statement);
1220 	m_assembler.MovGd(MakeTemporarySymbolAddress(dst), CX86Assembler::rAX);
1221 }
1222 
Emit_RelToRef_TmpCst(const STATEMENT & statement)1223 void CCodeGen_x86_32::Emit_RelToRef_TmpCst(const STATEMENT& statement)
1224 {
1225 	CSymbol* dst = statement.dst->GetSymbol().get();
1226 	CSymbol* src1 = statement.src1->GetSymbol().get();
1227 
1228 	assert(dst->m_type  == SYM_TMP_REFERENCE);
1229 	assert(src1->m_type == SYM_CONSTANT);
1230 
1231 	CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
1232 	m_assembler.LeaGd(tmpReg, CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rBP, src1->m_valueLow));
1233 	m_assembler.MovGd(MakeTemporaryReferenceSymbolAddress(dst), tmpReg);
1234 }
1235 
Emit_AddRef_MemMemReg(const STATEMENT & statement)1236 void CCodeGen_x86_32::Emit_AddRef_MemMemReg(const STATEMENT& statement)
1237 {
1238 	CSymbol* dst = statement.dst->GetSymbol().get();
1239 	CSymbol* src1 = statement.src1->GetSymbol().get();
1240 	CSymbol* src2 = statement.src2->GetSymbol().get();
1241 
1242 	assert(src2->m_type == SYM_REGISTER);
1243 
1244 	CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
1245 	m_assembler.MovEd(tmpReg, MakeMemoryReferenceSymbolAddress(src1));
1246 	m_assembler.AddEd(tmpReg, CX86Assembler::MakeRegisterAddress(m_registers[src2->m_valueLow]));
1247 	m_assembler.MovGd(MakeMemoryReferenceSymbolAddress(dst), tmpReg);
1248 }
1249 
Emit_AddRef_MemMemMem(const STATEMENT & statement)1250 void CCodeGen_x86_32::Emit_AddRef_MemMemMem(const STATEMENT& statement)
1251 {
1252 	CSymbol* dst = statement.dst->GetSymbol().get();
1253 	CSymbol* src1 = statement.src1->GetSymbol().get();
1254 	CSymbol* src2 = statement.src2->GetSymbol().get();
1255 
1256 	auto tmpReg = CX86Assembler::rAX;
1257 	m_assembler.MovEd(tmpReg, MakeMemoryReferenceSymbolAddress(src1));
1258 	m_assembler.AddEd(tmpReg, MakeMemorySymbolAddress(src2));
1259 	m_assembler.MovGd(MakeMemoryReferenceSymbolAddress(dst), tmpReg);
1260 }
1261 
Emit_AddRef_MemMemCst(const STATEMENT & statement)1262 void CCodeGen_x86_32::Emit_AddRef_MemMemCst(const STATEMENT& statement)
1263 {
1264 	CSymbol* dst = statement.dst->GetSymbol().get();
1265 	CSymbol* src1 = statement.src1->GetSymbol().get();
1266 	CSymbol* src2 = statement.src2->GetSymbol().get();
1267 
1268 	assert(src2->m_type == SYM_CONSTANT);
1269 
1270 	CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
1271 	m_assembler.MovEd(tmpReg, MakeMemoryReferenceSymbolAddress(src1));
1272 	m_assembler.AddId(CX86Assembler::MakeRegisterAddress(tmpReg), src2->m_valueLow);
1273 	m_assembler.MovGd(MakeMemoryReferenceSymbolAddress(dst), tmpReg);
1274 }
1275 
Emit_LoadFromRef_RegTmp(const STATEMENT & statement)1276 void CCodeGen_x86_32::Emit_LoadFromRef_RegTmp(const STATEMENT& statement)
1277 {
1278 	CSymbol* dst = statement.dst->GetSymbol().get();
1279 	CSymbol* src1 = statement.src1->GetSymbol().get();
1280 
1281 	assert(dst->m_type  == SYM_REGISTER);
1282 	assert(src1->m_type == SYM_TMP_REFERENCE);
1283 
1284 	CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
1285 	m_assembler.MovEd(tmpReg, MakeTemporaryReferenceSymbolAddress(src1));
1286 	m_assembler.MovEd(m_registers[dst->m_valueLow], CX86Assembler::MakeIndRegAddress(tmpReg));
1287 }
1288 
Emit_LoadFromRef_MemTmp(const STATEMENT & statement)1289 void CCodeGen_x86_32::Emit_LoadFromRef_MemTmp(const STATEMENT& statement)
1290 {
1291 	CSymbol* dst = statement.dst->GetSymbol().get();
1292 	CSymbol* src1 = statement.src1->GetSymbol().get();
1293 
1294 	assert(src1->m_type == SYM_TMP_REFERENCE);
1295 
1296 	CX86Assembler::REGISTER addressReg = CX86Assembler::rAX;
1297 	CX86Assembler::REGISTER valueReg = CX86Assembler::rDX;
1298 
1299 	m_assembler.MovEd(addressReg, MakeTemporaryReferenceSymbolAddress(src1));
1300 	m_assembler.MovEd(valueReg, CX86Assembler::MakeIndRegAddress(addressReg));
1301 	m_assembler.MovGd(MakeMemorySymbolAddress(dst), valueReg);
1302 }
1303 
Emit_LoadFromRef_Md_RegMem(const STATEMENT & statement)1304 void CCodeGen_x86_32::Emit_LoadFromRef_Md_RegMem(const STATEMENT& statement)
1305 {
1306 	auto dst = statement.dst->GetSymbol().get();
1307 	auto src1 = statement.src1->GetSymbol().get();
1308 
1309 	auto addressReg = CX86Assembler::rAX;
1310 
1311 	m_assembler.MovEd(addressReg, MakeMemoryReferenceSymbolAddress(src1));
1312 	m_assembler.MovapsVo(g_mdRegisters[dst->m_valueLow], CX86Assembler::MakeIndRegAddress(addressReg));
1313 }
1314 
Emit_LoadFromRef_Md_MemMem(const STATEMENT & statement)1315 void CCodeGen_x86_32::Emit_LoadFromRef_Md_MemMem(const STATEMENT& statement)
1316 {
1317 	auto dst = statement.dst->GetSymbol().get();
1318 	auto src1 = statement.src1->GetSymbol().get();
1319 
1320 	auto addressReg = CX86Assembler::rAX;
1321 	auto valueReg = CX86Assembler::xMM0;
1322 
1323 	m_assembler.MovEd(addressReg, MakeMemoryReferenceSymbolAddress(src1));
1324 	m_assembler.MovapsVo(valueReg, CX86Assembler::MakeIndRegAddress(addressReg));
1325 	m_assembler.MovapsVo(MakeMemory128SymbolAddress(dst), valueReg);
1326 }
1327 
Emit_StoreAtRef_TmpReg(const STATEMENT & statement)1328 void CCodeGen_x86_32::Emit_StoreAtRef_TmpReg(const STATEMENT& statement)
1329 {
1330 	CSymbol* src1 = statement.src1->GetSymbol().get();
1331 	CSymbol* src2 = statement.src2->GetSymbol().get();
1332 
1333 	assert(src1->m_type == SYM_TMP_REFERENCE);
1334 	assert(src2->m_type == SYM_REGISTER);
1335 
1336 	CX86Assembler::REGISTER addressReg = CX86Assembler::rAX;
1337 
1338 	m_assembler.MovEd(addressReg, MakeTemporaryReferenceSymbolAddress(src1));
1339 	m_assembler.MovGd(CX86Assembler::MakeIndRegAddress(addressReg), m_registers[src2->m_valueLow]);
1340 }
1341 
Emit_StoreAtRef_TmpMem(const STATEMENT & statement)1342 void CCodeGen_x86_32::Emit_StoreAtRef_TmpMem(const STATEMENT& statement)
1343 {
1344 	CSymbol* src1 = statement.src1->GetSymbol().get();
1345 	CSymbol* src2 = statement.src2->GetSymbol().get();
1346 
1347 	assert(src1->m_type == SYM_TMP_REFERENCE);
1348 
1349 	CX86Assembler::REGISTER addressReg = CX86Assembler::rAX;
1350 	CX86Assembler::REGISTER valueReg = CX86Assembler::rDX;
1351 
1352 	m_assembler.MovEd(addressReg, MakeTemporaryReferenceSymbolAddress(src1));
1353 	m_assembler.MovEd(valueReg, MakeMemorySymbolAddress(src2));
1354 	m_assembler.MovGd(CX86Assembler::MakeIndRegAddress(addressReg), valueReg);
1355 }
1356 
Emit_StoreAtRef_TmpCst(const STATEMENT & statement)1357 void CCodeGen_x86_32::Emit_StoreAtRef_TmpCst(const STATEMENT& statement)
1358 {
1359 	CSymbol* src1 = statement.src1->GetSymbol().get();
1360 	CSymbol* src2 = statement.src2->GetSymbol().get();
1361 
1362 	assert(src1->m_type == SYM_TMP_REFERENCE);
1363 	assert(src2->m_type == SYM_CONSTANT);
1364 
1365 	CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
1366 	m_assembler.MovEd(tmpReg, MakeTemporaryReferenceSymbolAddress(src1));
1367 	m_assembler.MovId(CX86Assembler::MakeIndRegAddress(tmpReg), src2->m_valueLow);
1368 }
1369 
Emit_StoreAtRef_Md_MemReg(const STATEMENT & statement)1370 void CCodeGen_x86_32::Emit_StoreAtRef_Md_MemReg(const STATEMENT& statement)
1371 {
1372 	auto src1 = statement.src1->GetSymbol().get();
1373 	auto src2 = statement.src2->GetSymbol().get();
1374 
1375 	auto addressReg = CX86Assembler::rAX;
1376 
1377 	m_assembler.MovEd(addressReg, MakeMemoryReferenceSymbolAddress(src1));
1378 	m_assembler.MovapsVo(CX86Assembler::MakeIndRegAddress(addressReg), g_mdRegisters[src2->m_valueLow]);
1379 }
1380 
Emit_StoreAtRef_Md_MemMem(const STATEMENT & statement)1381 void CCodeGen_x86_32::Emit_StoreAtRef_Md_MemMem(const STATEMENT& statement)
1382 {
1383 	auto src1 = statement.src1->GetSymbol().get();
1384 	auto src2 = statement.src2->GetSymbol().get();
1385 
1386 	auto addressReg = CX86Assembler::rAX;
1387 	auto valueReg = CX86Assembler::xMM0;
1388 
1389 	m_assembler.MovEd(addressReg, MakeMemoryReferenceSymbolAddress(src1));
1390 	m_assembler.MovapsVo(valueReg, MakeMemory128SymbolAddress(src2));
1391 	m_assembler.MovapsVo(CX86Assembler::MakeIndRegAddress(addressReg), valueReg);
1392 }
1393