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