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