1 #include <algorithm>
2 #include "Jitter_CodeGen_x86_64.h"
3 #include <stdexcept>
4
5 using namespace Jitter;
6
7 CX86Assembler::REGISTER CCodeGen_x86_64::g_systemVRegisters[SYSTEMV_MAX_REGISTERS] =
8 {
9 CX86Assembler::rBX,
10 CX86Assembler::r12,
11 CX86Assembler::r13,
12 CX86Assembler::r14,
13 CX86Assembler::r15,
14 };
15
16 CX86Assembler::REGISTER CCodeGen_x86_64::g_systemVParamRegs[SYSTEMV_MAX_PARAMS] =
17 {
18 CX86Assembler::rDI,
19 CX86Assembler::rSI,
20 CX86Assembler::rDX,
21 CX86Assembler::rCX,
22 CX86Assembler::r8,
23 CX86Assembler::r9,
24 };
25
26 CX86Assembler::REGISTER CCodeGen_x86_64::g_win32Registers[WIN32_MAX_REGISTERS] =
27 {
28 CX86Assembler::rBX,
29 CX86Assembler::rSI,
30 CX86Assembler::rDI,
31 CX86Assembler::r12,
32 CX86Assembler::r13,
33 CX86Assembler::r14,
34 CX86Assembler::r15,
35 };
36
37 CX86Assembler::REGISTER CCodeGen_x86_64::g_win32ParamRegs[WIN32_MAX_PARAMS] =
38 {
39 CX86Assembler::rCX,
40 CX86Assembler::rDX,
41 CX86Assembler::r8,
42 CX86Assembler::r9,
43 };
44
45 //xMM0->xMM3 are used internally for temporary uses
46 CX86Assembler::XMMREGISTER CCodeGen_x86_64::g_mdRegisters[MAX_MDREGISTERS] =
47 {
48 CX86Assembler::xMM4,
49 CX86Assembler::xMM5,
50 CX86Assembler::xMM6,
51 CX86Assembler::xMM7,
52 CX86Assembler::xMM8,
53 CX86Assembler::xMM9,
54 CX86Assembler::xMM10,
55 CX86Assembler::xMM11,
56 CX86Assembler::xMM12,
57 CX86Assembler::xMM13,
58 CX86Assembler::xMM14,
59 CX86Assembler::xMM15
60 };
61
CombineConstant64(uint32 cstLow,uint32 cstHigh)62 static uint64 CombineConstant64(uint32 cstLow, uint32 cstHigh)
63 {
64 return (static_cast<uint64>(cstHigh) << 32) | static_cast<uint64>(cstLow);
65 }
66
67 //ALUOP
68 //-------------------------------------------------------------------
69
70 template <typename ALUOP>
Emit_Alu64_MemMemMem(const STATEMENT & statement)71 void CCodeGen_x86_64::Emit_Alu64_MemMemMem(const STATEMENT& statement)
72 {
73 CSymbol* dst = statement.dst->GetSymbol().get();
74 CSymbol* src1 = statement.src1->GetSymbol().get();
75 CSymbol* src2 = statement.src2->GetSymbol().get();
76
77 CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
78
79 m_assembler.MovEq(tmpReg, MakeMemory64SymbolAddress(src1));
80 ((m_assembler).*(ALUOP::OpEq()))(tmpReg, MakeMemory64SymbolAddress(src2));
81 m_assembler.MovGq(MakeMemory64SymbolAddress(dst), tmpReg);
82 }
83
84 template <typename ALUOP>
Emit_Alu64_MemMemCst(const STATEMENT & statement)85 void CCodeGen_x86_64::Emit_Alu64_MemMemCst(const STATEMENT& statement)
86 {
87 CSymbol* dst = statement.dst->GetSymbol().get();
88 CSymbol* src1 = statement.src1->GetSymbol().get();
89 CSymbol* src2 = statement.src2->GetSymbol().get();
90
91 assert(src2->m_type == SYM_CONSTANT64);
92
93 CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
94 uint64 constant = CombineConstant64(src2->m_valueLow, src2->m_valueHigh);
95
96 m_assembler.MovEq(tmpReg, MakeMemory64SymbolAddress(src1));
97 if(CX86Assembler::GetMinimumConstantSize64(constant) >= 4)
98 {
99 auto cstReg = CX86Assembler::rCX;
100 m_assembler.MovIq(cstReg, constant);
101 ((m_assembler).*(ALUOP::OpEq()))(tmpReg, CX86Assembler::MakeRegisterAddress(cstReg));
102 }
103 else
104 {
105 ((m_assembler).*(ALUOP::OpIq()))(CX86Assembler::MakeRegisterAddress(tmpReg), constant);
106 }
107 m_assembler.MovGq(MakeMemory64SymbolAddress(dst), tmpReg);
108 }
109
110 template <typename ALUOP>
Emit_Alu64_MemCstMem(const STATEMENT & statement)111 void CCodeGen_x86_64::Emit_Alu64_MemCstMem(const STATEMENT& statement)
112 {
113 CSymbol* dst = statement.dst->GetSymbol().get();
114 CSymbol* src1 = statement.src1->GetSymbol().get();
115 CSymbol* src2 = statement.src2->GetSymbol().get();
116
117 assert(src1->m_type == SYM_CONSTANT64);
118
119 CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
120 uint64 constant = CombineConstant64(src1->m_valueLow, src1->m_valueHigh);
121
122 m_assembler.MovIq(tmpReg, constant);
123 ((m_assembler).*(ALUOP::OpEq()))(tmpReg, MakeMemory64SymbolAddress(src2));
124 m_assembler.MovGq(MakeMemory64SymbolAddress(dst), tmpReg);
125 }
126
127 #define ALU64_CONST_MATCHERS(ALUOP_CST, ALUOP) \
128 { ALUOP_CST, MATCH_MEMORY64, MATCH_MEMORY64, MATCH_MEMORY64, MATCH_NIL, &CCodeGen_x86_64::Emit_Alu64_MemMemMem<ALUOP> }, \
129 { ALUOP_CST, MATCH_MEMORY64, MATCH_MEMORY64, MATCH_CONSTANT64, MATCH_NIL, &CCodeGen_x86_64::Emit_Alu64_MemMemCst<ALUOP> }, \
130 { ALUOP_CST, MATCH_MEMORY64, MATCH_CONSTANT64, MATCH_MEMORY64, MATCH_NIL, &CCodeGen_x86_64::Emit_Alu64_MemCstMem<ALUOP> },
131
132 //SHIFTOP
133 //-------------------------------------------------------------------
134
135 template <typename SHIFTOP>
Emit_Shift64_RelRelReg(const STATEMENT & statement)136 void CCodeGen_x86_64::Emit_Shift64_RelRelReg(const STATEMENT& statement)
137 {
138 CSymbol* dst = statement.dst->GetSymbol().get();
139 CSymbol* src1 = statement.src1->GetSymbol().get();
140 CSymbol* src2 = statement.src2->GetSymbol().get();
141
142 assert(dst->m_type == SYM_RELATIVE64);
143 assert(src1->m_type == SYM_RELATIVE64);
144 assert(src2->m_type == SYM_REGISTER);
145
146 CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
147 CX86Assembler::REGISTER shiftReg = CX86Assembler::rCX;
148
149 m_assembler.MovEq(tmpReg, MakeRelative64SymbolAddress(src1));
150 m_assembler.MovEd(shiftReg, CX86Assembler::MakeRegisterAddress(m_registers[src2->m_valueLow]));
151 ((m_assembler).*(SHIFTOP::OpVar()))(CX86Assembler::MakeRegisterAddress(tmpReg));
152 m_assembler.MovGq(MakeRelative64SymbolAddress(dst), tmpReg);
153 }
154
155 template <typename SHIFTOP>
Emit_Shift64_RelRelMem(const STATEMENT & statement)156 void CCodeGen_x86_64::Emit_Shift64_RelRelMem(const STATEMENT& statement)
157 {
158 CSymbol* dst = statement.dst->GetSymbol().get();
159 CSymbol* src1 = statement.src1->GetSymbol().get();
160 CSymbol* src2 = statement.src2->GetSymbol().get();
161
162 assert(dst->m_type == SYM_RELATIVE64);
163 assert(src1->m_type == SYM_RELATIVE64);
164
165 CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
166 CX86Assembler::REGISTER shiftReg = CX86Assembler::rCX;
167
168 m_assembler.MovEq(tmpReg, MakeRelative64SymbolAddress(src1));
169 m_assembler.MovEd(shiftReg, MakeMemorySymbolAddress(src2));
170 ((m_assembler).*(SHIFTOP::OpVar()))(CX86Assembler::MakeRegisterAddress(tmpReg));
171 m_assembler.MovGq(MakeRelative64SymbolAddress(dst), tmpReg);
172 }
173
174 template <typename SHIFTOP>
Emit_Shift64_RelRelCst(const STATEMENT & statement)175 void CCodeGen_x86_64::Emit_Shift64_RelRelCst(const STATEMENT& statement)
176 {
177 CSymbol* dst = statement.dst->GetSymbol().get();
178 CSymbol* src1 = statement.src1->GetSymbol().get();
179 CSymbol* src2 = statement.src2->GetSymbol().get();
180
181 assert(dst->m_type == SYM_RELATIVE64);
182 assert(src1->m_type == SYM_RELATIVE64);
183 assert(src2->m_type == SYM_CONSTANT);
184
185 CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
186
187 m_assembler.MovEq(tmpReg, MakeRelative64SymbolAddress(src1));
188 ((m_assembler).*(SHIFTOP::OpCst()))(CX86Assembler::MakeRegisterAddress(tmpReg), static_cast<uint8>(src2->m_valueLow));
189 m_assembler.MovGq(MakeRelative64SymbolAddress(dst), tmpReg);
190 }
191
192 #define SHIFT64_CONST_MATCHERS(SHIFTOP_CST, SHIFTOP) \
193 { SHIFTOP_CST, MATCH_RELATIVE64, MATCH_RELATIVE64, MATCH_REGISTER, MATCH_NIL, &CCodeGen_x86_64::Emit_Shift64_RelRelReg<SHIFTOP> }, \
194 { SHIFTOP_CST, MATCH_RELATIVE64, MATCH_RELATIVE64, MATCH_MEMORY, MATCH_NIL, &CCodeGen_x86_64::Emit_Shift64_RelRelMem<SHIFTOP> }, \
195 { SHIFTOP_CST, MATCH_RELATIVE64, MATCH_RELATIVE64, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86_64::Emit_Shift64_RelRelCst<SHIFTOP> },
196
197 CCodeGen_x86_64::CONSTMATCHER CCodeGen_x86_64::g_constMatchers[] =
198 {
199 { OP_PARAM, MATCH_NIL, MATCH_CONTEXT, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Param_Ctx },
200 { OP_PARAM, MATCH_NIL, MATCH_REGISTER, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Param_Reg },
201 { OP_PARAM, MATCH_NIL, MATCH_MEMORY, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Param_Mem },
202 { OP_PARAM, MATCH_NIL, MATCH_CONSTANT, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Param_Cst },
203 { OP_PARAM, MATCH_NIL, MATCH_MEMORY64, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Param_Mem64 },
204 { OP_PARAM, MATCH_NIL, MATCH_CONSTANT64, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Param_Cst64 },
205 { OP_PARAM, MATCH_NIL, MATCH_REGISTER128, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Param_Reg128 },
206 { OP_PARAM, MATCH_NIL, MATCH_MEMORY128, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Param_Mem128 },
207
208 { OP_PARAM_RET, MATCH_NIL, MATCH_MEMORY128, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Param_Mem128 },
209
210 { OP_CALL, MATCH_NIL, MATCH_CONSTANTPTR, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86_64::Emit_Call },
211
212 { OP_RETVAL, MATCH_REGISTER, MATCH_NIL, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_RetVal_Reg },
213 { OP_RETVAL, MATCH_MEMORY, MATCH_NIL, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_RetVal_Mem },
214 { OP_RETVAL, MATCH_MEMORY64, MATCH_NIL, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_RetVal_Mem64 },
215 { OP_RETVAL, MATCH_REGISTER128, MATCH_NIL, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_RetVal_Reg128 },
216 { OP_RETVAL, MATCH_MEMORY128, MATCH_NIL, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_RetVal_Mem128 },
217
218 { OP_EXTERNJMP, MATCH_NIL, MATCH_CONSTANTPTR, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_ExternJmp },
219 { OP_EXTERNJMP_DYN, MATCH_NIL, MATCH_CONSTANTPTR, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_ExternJmp },
220
221 { OP_MOV, MATCH_MEMORY64, MATCH_MEMORY64, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Mov_Mem64Mem64 },
222 { OP_MOV, MATCH_RELATIVE64, MATCH_CONSTANT64, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Mov_Rel64Cst64 },
223
224 { OP_MOV, MATCH_REG_REF, MATCH_MEM_REF, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_Mov_RegRefMemRef },
225
226 ALU64_CONST_MATCHERS(OP_ADD64, ALUOP64_ADD)
227 ALU64_CONST_MATCHERS(OP_SUB64, ALUOP64_SUB)
228 ALU64_CONST_MATCHERS(OP_AND64, ALUOP64_AND)
229
230 SHIFT64_CONST_MATCHERS(OP_SLL64, SHIFTOP64_SLL)
231 SHIFT64_CONST_MATCHERS(OP_SRL64, SHIFTOP64_SRL)
232 SHIFT64_CONST_MATCHERS(OP_SRA64, SHIFTOP64_SRA)
233
234 { OP_CMP, MATCH_VARIABLE, MATCH_VARIABLE, MATCH_VARIABLE, MATCH_NIL, &CCodeGen_x86_64::Emit_Cmp_VarVarVar },
235 { OP_CMP, MATCH_VARIABLE, MATCH_VARIABLE, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86_64::Emit_Cmp_VarVarCst },
236
237 { OP_CMP64, MATCH_REGISTER, MATCH_RELATIVE64, MATCH_RELATIVE64, MATCH_NIL, &CCodeGen_x86_64::Emit_Cmp64_RegRelRel },
238 { OP_CMP64, MATCH_REGISTER, MATCH_RELATIVE64, MATCH_CONSTANT64, MATCH_NIL, &CCodeGen_x86_64::Emit_Cmp64_RegRelCst },
239 { OP_CMP64, MATCH_MEMORY, MATCH_RELATIVE64, MATCH_RELATIVE64, MATCH_NIL, &CCodeGen_x86_64::Emit_Cmp64_MemRelRel },
240 { OP_CMP64, MATCH_MEMORY, MATCH_RELATIVE64, MATCH_CONSTANT64, MATCH_NIL, &CCodeGen_x86_64::Emit_Cmp64_MemRelCst },
241
242 { OP_RELTOREF, MATCH_VAR_REF, MATCH_CONSTANT, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_RelToRef_VarCst },
243
244 { OP_ADDREF, MATCH_VAR_REF, MATCH_VAR_REF, MATCH_VARIABLE, MATCH_NIL, &CCodeGen_x86_64::Emit_AddRef_VarVarVar },
245 { OP_ADDREF, MATCH_VAR_REF, MATCH_VAR_REF, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86_64::Emit_AddRef_VarVarCst },
246
247 { OP_ISREFNULL, MATCH_VARIABLE, MATCH_VAR_REF, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_IsRefNull_VarVar },
248
249 { OP_LOADFROMREF, MATCH_MEMORY64, MATCH_VAR_REF, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_LoadFromRef_64_MemVar },
250 { OP_LOADFROMREF, MATCH_VAR_REF, MATCH_VAR_REF, MATCH_NIL, MATCH_NIL, &CCodeGen_x86_64::Emit_LoadFromRef_Ref_VarVar },
251
252 { OP_STOREATREF, MATCH_NIL, MATCH_VAR_REF, MATCH_MEMORY64, MATCH_NIL, &CCodeGen_x86_64::Emit_StoreAtRef_64_VarMem },
253 { OP_STOREATREF, MATCH_NIL, MATCH_VAR_REF, MATCH_CONSTANT64, MATCH_NIL, &CCodeGen_x86_64::Emit_StoreAtRef_64_VarCst },
254
255 { OP_STORE8ATREF, MATCH_NIL, MATCH_VAR_REF, MATCH_VARIABLE, MATCH_NIL, &CCodeGen_x86_64::Emit_Store8AtRef_VarVar },
256
257 { OP_CONDJMP, MATCH_NIL, MATCH_VAR_REF, MATCH_CONSTANT, MATCH_NIL, &CCodeGen_x86_64::Emit_CondJmp_Ref_VarCst },
258
259 { OP_MOV, MATCH_NIL, MATCH_NIL, MATCH_NIL, MATCH_NIL, nullptr },
260 };
261
CCodeGen_x86_64()262 CCodeGen_x86_64::CCodeGen_x86_64()
263 {
264 SetPlatformAbi(PLATFORM_ABI_SYSTEMV);
265 CCodeGen_x86::m_mdRegisters = g_mdRegisters;
266
267 for(CONSTMATCHER* constMatcher = g_constMatchers; constMatcher->emitter != NULL; constMatcher++)
268 {
269 MATCHER matcher;
270 matcher.op = constMatcher->op;
271 matcher.dstType = constMatcher->dstType;
272 matcher.src1Type = constMatcher->src1Type;
273 matcher.src2Type = constMatcher->src2Type;
274 matcher.src3Type = constMatcher->src3Type;
275 matcher.emitter = std::bind(constMatcher->emitter, this, std::placeholders::_1);
276 m_matchers.insert(MatcherMapType::value_type(matcher.op, matcher));
277 }
278 }
279
SetPlatformAbi(PLATFORM_ABI platformAbi)280 void CCodeGen_x86_64::SetPlatformAbi(PLATFORM_ABI platformAbi)
281 {
282 m_platformAbi = platformAbi;
283 switch(m_platformAbi)
284 {
285 case PLATFORM_ABI_SYSTEMV:
286 CCodeGen_x86::m_registers = g_systemVRegisters;
287 m_paramRegs = g_systemVParamRegs;
288 m_maxRegisters = SYSTEMV_MAX_REGISTERS;
289 m_maxParams = SYSTEMV_MAX_PARAMS;
290 m_hasMdRegRetValues = true;
291 break;
292 case PLATFORM_ABI_WIN32:
293 CCodeGen_x86::m_registers = g_win32Registers;
294 m_paramRegs = g_win32ParamRegs;
295 m_maxRegisters = WIN32_MAX_REGISTERS;
296 m_maxParams = WIN32_MAX_PARAMS;
297 m_hasMdRegRetValues = false;
298 break;
299 default:
300 throw std::runtime_error("Unsupported ABI.");
301 break;
302 }
303 }
304
GetAvailableRegisterCount() const305 unsigned int CCodeGen_x86_64::GetAvailableRegisterCount() const
306 {
307 return m_maxRegisters;
308 }
309
GetAvailableMdRegisterCount() const310 unsigned int CCodeGen_x86_64::GetAvailableMdRegisterCount() const
311 {
312 return MAX_MDREGISTERS;
313 }
314
CanHold128BitsReturnValueInRegisters() const315 bool CCodeGen_x86_64::CanHold128BitsReturnValueInRegisters() const
316 {
317 return m_hasMdRegRetValues;
318 }
319
GetPointerSize() const320 uint32 CCodeGen_x86_64::GetPointerSize() const
321 {
322 return 8;
323 }
324
Emit_Prolog(const StatementList & statements,unsigned int stackSize)325 void CCodeGen_x86_64::Emit_Prolog(const StatementList& statements, unsigned int stackSize)
326 {
327 m_params.clear();
328
329 //Compute the size needed to store all function call parameters
330 uint32 maxParamSpillSize = 0;
331 {
332 uint32 currParamSpillSize = 0;
333 for(const auto& statement : statements)
334 {
335 switch(statement.op)
336 {
337 case OP_PARAM:
338 case OP_PARAM_RET:
339 {
340 CSymbol* src1 = statement.src1->GetSymbol().get();
341 switch(src1->m_type)
342 {
343 case SYM_REGISTER128:
344 currParamSpillSize += 16;
345 break;
346 }
347 }
348 break;
349 case OP_CALL:
350 maxParamSpillSize = std::max<uint32>(currParamSpillSize, maxParamSpillSize);
351 currParamSpillSize = 0;
352 break;
353 default:
354 break;
355 }
356 }
357 }
358
359 assert((maxParamSpillSize & 0x0F) == 0);
360 assert((stackSize & 0x0F) == 0);
361
362 m_assembler.Push(CX86Assembler::rBP);
363 m_assembler.MovEq(CX86Assembler::rBP, CX86Assembler::MakeRegisterAddress(m_paramRegs[0]));
364
365 uint32 savedSize = 0;
366 for(unsigned int i = 0; i < m_maxRegisters; i++)
367 {
368 if(m_registerUsage & (1 << i))
369 {
370 m_assembler.Push(m_registers[i]);
371 savedSize += 8;
372 }
373 }
374
375 uint32 savedRegAlignAdjust = (savedSize != 0) ? (0x10 - (savedSize & 0xF)) : 0;
376
377 m_totalStackAlloc = savedRegAlignAdjust + maxParamSpillSize + stackSize;
378 m_totalStackAlloc += 0x20;
379
380 m_stackLevel = 0x20;
381 m_paramSpillBase = 0x20 + stackSize;
382
383 m_assembler.SubIq(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP), m_totalStackAlloc);
384
385 //-------------------------------
386 //Stack Frame
387 //-------------------------------
388 //(High address)
389 //------------------
390 //Saved registers + align adjustment
391 //------------------
392 //Params spill space
393 //------------------ <----- rSP + m_paramSpillBase
394 //Temporary symbols (stackSize) + align adjustment
395 //------------------ <----- rSP + m_stackLevel
396 //Param spill area for callee (0x20 bytes)
397 //------------------ <----- rSP
398 //(Low address)
399 }
400
Emit_Epilog()401 void CCodeGen_x86_64::Emit_Epilog()
402 {
403 m_assembler.AddIq(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP), m_totalStackAlloc);
404
405 for(int i = m_maxRegisters - 1; i >= 0; i--)
406 {
407 if(m_registerUsage & (1 << i))
408 {
409 m_assembler.Pop(m_registers[i]);
410 }
411 }
412
413 m_assembler.Pop(CX86Assembler::rBP);
414 }
415
MakeConstant128Address(const LITERAL128 & constant)416 CX86Assembler::CAddress CCodeGen_x86_64::MakeConstant128Address(const LITERAL128& constant)
417 {
418 auto literalId = m_assembler.CreateLiteral128(constant);
419 return CX86Assembler::MakeLiteral128Address(literalId);
420 }
421
Emit_Param_Ctx(const STATEMENT & statement)422 void CCodeGen_x86_64::Emit_Param_Ctx(const STATEMENT& statement)
423 {
424 assert(m_params.size() < m_maxParams);
425
426 m_params.push_back(
427 [this] (CX86Assembler::REGISTER paramReg, uint32)
428 {
429 m_assembler.MovEq(paramReg, CX86Assembler::MakeRegisterAddress(CX86Assembler::rBP));
430 return 0;
431 }
432 );
433 }
434
Emit_Param_Reg(const STATEMENT & statement)435 void CCodeGen_x86_64::Emit_Param_Reg(const STATEMENT& statement)
436 {
437 assert(m_params.size() < m_maxParams);
438
439 auto src1 = statement.src1->GetSymbol().get();
440
441 m_params.push_back(
442 [this, src1] (CX86Assembler::REGISTER paramReg, uint32)
443 {
444 m_assembler.MovEd(paramReg, CX86Assembler::MakeRegisterAddress(m_registers[src1->m_valueLow]));
445 return 0;
446 }
447 );
448 }
449
Emit_Param_Mem(const STATEMENT & statement)450 void CCodeGen_x86_64::Emit_Param_Mem(const STATEMENT& statement)
451 {
452 assert(m_params.size() < m_maxParams);
453
454 auto src1 = statement.src1->GetSymbol().get();
455
456 m_params.push_back(
457 [this, src1] (CX86Assembler::REGISTER paramReg, uint32)
458 {
459 m_assembler.MovEd(paramReg, MakeMemorySymbolAddress(src1));
460 return 0;
461 }
462 );
463 }
464
Emit_Param_Cst(const STATEMENT & statement)465 void CCodeGen_x86_64::Emit_Param_Cst(const STATEMENT& statement)
466 {
467 assert(m_params.size() < m_maxParams);
468
469 auto src1 = statement.src1->GetSymbol().get();
470
471 m_params.push_back(
472 [this, src1] (CX86Assembler::REGISTER paramReg, uint32)
473 {
474 m_assembler.MovId(paramReg, src1->m_valueLow);
475 return 0;
476 }
477 );
478 }
479
Emit_Param_Mem64(const STATEMENT & statement)480 void CCodeGen_x86_64::Emit_Param_Mem64(const STATEMENT& statement)
481 {
482 assert(m_params.size() < m_maxParams);
483
484 auto src1 = statement.src1->GetSymbol().get();
485
486 m_params.push_back(
487 [this, src1] (CX86Assembler::REGISTER paramReg, uint32)
488 {
489 m_assembler.MovEq(paramReg, MakeMemory64SymbolAddress(src1));
490 return 0;
491 }
492 );
493 }
494
Emit_Param_Cst64(const STATEMENT & statement)495 void CCodeGen_x86_64::Emit_Param_Cst64(const STATEMENT& statement)
496 {
497 assert(m_params.size() < m_maxParams);
498
499 auto src1 = statement.src1->GetSymbol().get();
500
501 m_params.push_back(
502 [this, src1] (CX86Assembler::REGISTER paramReg, uint32)
503 {
504 m_assembler.MovIq(paramReg, CombineConstant64(src1->m_valueLow, src1->m_valueHigh));
505 return 0;
506 }
507 );
508 }
509
Emit_Param_Reg128(const STATEMENT & statement)510 void CCodeGen_x86_64::Emit_Param_Reg128(const STATEMENT& statement)
511 {
512 assert(m_params.size() < m_maxParams);
513
514 auto src1 = statement.src1->GetSymbol().get();
515
516 m_params.push_back(
517 [this, src1] (CX86Assembler::REGISTER paramReg, uint32 paramSpillOffset)
518 {
519 auto paramTempAddr = CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, m_paramSpillBase + paramSpillOffset);
520 m_assembler.MovapsVo(paramTempAddr, m_mdRegisters[src1->m_valueLow]);
521 m_assembler.LeaGq(paramReg, paramTempAddr);
522 return 0x10;
523 }
524 );
525 }
526
Emit_Param_Mem128(const STATEMENT & statement)527 void CCodeGen_x86_64::Emit_Param_Mem128(const STATEMENT& statement)
528 {
529 assert(m_params.size() < m_maxParams);
530
531 auto src1 = statement.src1->GetSymbol().get();
532
533 m_params.push_back(
534 [this, src1] (CX86Assembler::REGISTER paramReg, uint32)
535 {
536 m_assembler.LeaGq(paramReg, MakeMemory128SymbolAddress(src1));
537 return 0;
538 }
539 );
540 }
541
Emit_Call(const STATEMENT & statement)542 void CCodeGen_x86_64::Emit_Call(const STATEMENT& statement)
543 {
544 const auto& src1 = statement.src1->GetSymbol().get();
545 const auto& src2 = statement.src2->GetSymbol().get();
546
547 unsigned int paramCount = src2->m_valueLow;
548 uint32 paramSpillOffset = 0;
549
550 for(unsigned int i = 0; i < paramCount; i++)
551 {
552 auto emitter(m_params.back());
553 m_params.pop_back();
554 paramSpillOffset += emitter(m_paramRegs[i], paramSpillOffset);
555 }
556
557 m_assembler.MovIq(CX86Assembler::rAX, CombineConstant64(src1->m_valueLow, src1->m_valueHigh));
558 auto symbolRefLabel = m_assembler.CreateLabel();
559 m_assembler.MarkLabel(symbolRefLabel, -8);
560 m_symbolReferenceLabels.push_back(std::make_pair(src1->GetConstantPtr(), symbolRefLabel));
561 m_assembler.CallEd(CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX));
562 }
563
Emit_RetVal_Reg(const STATEMENT & statement)564 void CCodeGen_x86_64::Emit_RetVal_Reg(const STATEMENT& statement)
565 {
566 CSymbol* dst = statement.dst->GetSymbol().get();
567
568 assert(dst->m_type == SYM_REGISTER);
569
570 m_assembler.MovGd(CX86Assembler::MakeRegisterAddress(m_registers[dst->m_valueLow]), CX86Assembler::rAX);
571 }
572
Emit_RetVal_Mem(const STATEMENT & statement)573 void CCodeGen_x86_64::Emit_RetVal_Mem(const STATEMENT& statement)
574 {
575 CSymbol* dst = statement.dst->GetSymbol().get();
576 m_assembler.MovGd(MakeMemorySymbolAddress(dst), CX86Assembler::rAX);
577 }
578
Emit_RetVal_Mem64(const STATEMENT & statement)579 void CCodeGen_x86_64::Emit_RetVal_Mem64(const STATEMENT& statement)
580 {
581 CSymbol* dst = statement.dst->GetSymbol().get();
582 m_assembler.MovGq(MakeMemory64SymbolAddress(dst), CX86Assembler::rAX);
583 }
584
Emit_RetVal_Reg128(const STATEMENT & statement)585 void CCodeGen_x86_64::Emit_RetVal_Reg128(const STATEMENT& statement)
586 {
587 auto dst = statement.dst->GetSymbol().get();
588
589 //TODO: Use only integer operations
590 m_assembler.MovqVo(m_mdRegisters[dst->m_valueLow], CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX));
591 m_assembler.MovqVo(CX86Assembler::xMM0, CX86Assembler::MakeRegisterAddress(CX86Assembler::rDX));
592 m_assembler.ShufpsVo(m_mdRegisters[dst->m_valueLow], CX86Assembler::MakeXmmRegisterAddress(CX86Assembler::xMM0), 0x44);
593 }
594
Emit_RetVal_Mem128(const STATEMENT & statement)595 void CCodeGen_x86_64::Emit_RetVal_Mem128(const STATEMENT& statement)
596 {
597 CSymbol* dst = statement.dst->GetSymbol().get();
598 m_assembler.MovGq(MakeMemory128SymbolElementAddress(dst, 0), CX86Assembler::rAX);
599 m_assembler.MovGq(MakeMemory128SymbolElementAddress(dst, 2), CX86Assembler::rDX);
600 }
601
Emit_ExternJmp(const STATEMENT & statement)602 void CCodeGen_x86_64::Emit_ExternJmp(const STATEMENT& statement)
603 {
604 auto src1 = statement.src1->GetSymbol().get();
605
606 m_assembler.MovEq(m_paramRegs[0], CX86Assembler::MakeRegisterAddress(g_baseRegister));
607 Emit_Epilog();
608 m_assembler.MovIq(CX86Assembler::rAX, CombineConstant64(src1->m_valueLow, src1->m_valueHigh));
609 auto symbolRefLabel = m_assembler.CreateLabel();
610 m_assembler.MarkLabel(symbolRefLabel, -8);
611 m_symbolReferenceLabels.push_back(std::make_pair(src1->GetConstantPtr(), symbolRefLabel));
612 m_assembler.JmpEd(CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX));
613 }
614
Emit_Mov_Mem64Mem64(const STATEMENT & statement)615 void CCodeGen_x86_64::Emit_Mov_Mem64Mem64(const STATEMENT& statement)
616 {
617 CSymbol* dst = statement.dst->GetSymbol().get();
618 CSymbol* src1 = statement.src1->GetSymbol().get();
619
620 m_assembler.MovEq(CX86Assembler::rAX, MakeMemory64SymbolAddress(src1));
621 m_assembler.MovGq(MakeMemory64SymbolAddress(dst), CX86Assembler::rAX);
622 }
623
Emit_Mov_Rel64Cst64(const STATEMENT & statement)624 void CCodeGen_x86_64::Emit_Mov_Rel64Cst64(const STATEMENT& statement)
625 {
626 CSymbol* dst = statement.dst->GetSymbol().get();
627 CSymbol* src1 = statement.src1->GetSymbol().get();
628
629 assert(dst->m_type == SYM_RELATIVE64);
630 assert(src1->m_type == SYM_CONSTANT64);
631
632 uint64 constant = CombineConstant64(src1->m_valueLow, src1->m_valueHigh);
633 CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
634
635 if(constant == 0)
636 {
637 m_assembler.XorGq(CX86Assembler::MakeRegisterAddress(tmpReg), tmpReg);
638 }
639 else
640 {
641 m_assembler.MovIq(tmpReg, constant);
642 }
643 m_assembler.MovGq(MakeRelative64SymbolAddress(dst), tmpReg);
644 }
645
Emit_Mov_RegRefMemRef(const STATEMENT & statement)646 void CCodeGen_x86_64::Emit_Mov_RegRefMemRef(const STATEMENT& statement)
647 {
648 auto dst = statement.dst->GetSymbol().get();
649 auto src1 = statement.src1->GetSymbol().get();
650
651 assert(dst->m_type == SYM_REG_REFERENCE);
652
653 m_assembler.MovEq(m_registers[dst->m_valueLow], MakeMemoryReferenceSymbolAddress(src1));
654 }
655
Emit_Cmp_VarVarVar(const STATEMENT & statement)656 void CCodeGen_x86_64::Emit_Cmp_VarVarVar(const STATEMENT& statement)
657 {
658 auto dst = statement.dst->GetSymbol().get();
659 auto src1 = statement.src1->GetSymbol().get();
660 auto src2 = statement.src2->GetSymbol().get();
661
662 auto dstReg = PrepareSymbolRegisterDef(dst, CX86Assembler::rCX);
663 auto src1Reg = PrepareSymbolRegisterUse(src1, CX86Assembler::rDX);
664
665 m_assembler.CmpEd(src1Reg, MakeVariableSymbolAddress(src2));
666 Cmp_GetFlag(CX86Assembler::MakeRegisterAddress(dstReg), statement.jmpCondition);
667 m_assembler.MovzxEb(dstReg, CX86Assembler::MakeRegisterAddress(dstReg));
668
669 CommitSymbolRegister(dst, dstReg);
670 }
671
Emit_Cmp_VarVarCst(const STATEMENT & statement)672 void CCodeGen_x86_64::Emit_Cmp_VarVarCst(const STATEMENT& statement)
673 {
674 auto dst = statement.dst->GetSymbol().get();
675 auto src1 = statement.src1->GetSymbol().get();
676 auto src2 = statement.src2->GetSymbol().get();
677
678 auto dstReg = PrepareSymbolRegisterDef(dst, CX86Assembler::rCX);
679
680 m_assembler.CmpId(MakeVariableSymbolAddress(src1), src2->m_valueLow);
681 Cmp_GetFlag(CX86Assembler::MakeRegisterAddress(dstReg), statement.jmpCondition);
682 m_assembler.MovzxEb(dstReg, CX86Assembler::MakeRegisterAddress(dstReg));
683
684 CommitSymbolRegister(dst, dstReg);
685 }
686
Cmp64_RelRel(CX86Assembler::REGISTER dstReg,const STATEMENT & statement)687 void CCodeGen_x86_64::Cmp64_RelRel(CX86Assembler::REGISTER dstReg, const STATEMENT& statement)
688 {
689 auto src1 = statement.src1->GetSymbol().get();
690 auto src2 = statement.src2->GetSymbol().get();
691
692 assert(src1->m_type == SYM_RELATIVE64);
693 assert(src2->m_type == SYM_RELATIVE64);
694
695 m_assembler.XorEd(dstReg, CX86Assembler::MakeRegisterAddress(dstReg));
696
697 auto tmpReg = CX86Assembler::rCX;
698 m_assembler.MovEq(tmpReg, MakeRelative64SymbolAddress(src1));
699 m_assembler.CmpEq(tmpReg, MakeRelative64SymbolAddress(src2));
700
701 Cmp_GetFlag(CX86Assembler::MakeRegisterAddress(dstReg), statement.jmpCondition);
702 }
703
Cmp64_RelCst(CX86Assembler::REGISTER dstReg,const STATEMENT & statement)704 void CCodeGen_x86_64::Cmp64_RelCst(CX86Assembler::REGISTER dstReg, const STATEMENT& statement)
705 {
706 auto src1 = statement.src1->GetSymbol().get();
707 auto src2 = statement.src2->GetSymbol().get();
708
709 assert(src1->m_type == SYM_RELATIVE64);
710 assert(src2->m_type == SYM_CONSTANT64);
711
712 uint64 constant = CombineConstant64(src2->m_valueLow, src2->m_valueHigh);
713
714 m_assembler.XorEd(dstReg, CX86Assembler::MakeRegisterAddress(dstReg));
715
716 auto tmpReg = CX86Assembler::rCX;
717 m_assembler.MovEq(tmpReg, MakeRelative64SymbolAddress(src1));
718 if(constant == 0)
719 {
720 auto cstReg = CX86Assembler::rDX;
721 m_assembler.XorGq(CX86Assembler::MakeRegisterAddress(cstReg), cstReg);
722 m_assembler.CmpEq(tmpReg, CX86Assembler::MakeRegisterAddress(cstReg));
723 }
724 else if(CX86Assembler::GetMinimumConstantSize64(constant) == 8)
725 {
726 auto cstReg = CX86Assembler::rDX;
727 m_assembler.MovIq(cstReg, constant);
728 m_assembler.CmpEq(tmpReg, CX86Assembler::MakeRegisterAddress(cstReg));
729 }
730 else
731 {
732 m_assembler.CmpIq(CX86Assembler::MakeRegisterAddress(tmpReg), constant);
733 }
734
735 Cmp_GetFlag(CX86Assembler::MakeRegisterAddress(dstReg), statement.jmpCondition);
736 }
737
Emit_Cmp64_RegRelRel(const STATEMENT & statement)738 void CCodeGen_x86_64::Emit_Cmp64_RegRelRel(const STATEMENT& statement)
739 {
740 CSymbol* dst = statement.dst->GetSymbol().get();
741 assert(dst->m_type == SYM_REGISTER);
742 Cmp64_RelRel(m_registers[dst->m_valueLow], statement);
743 }
744
Emit_Cmp64_RegRelCst(const STATEMENT & statement)745 void CCodeGen_x86_64::Emit_Cmp64_RegRelCst(const STATEMENT& statement)
746 {
747 CSymbol* dst = statement.dst->GetSymbol().get();
748 assert(dst->m_type == SYM_REGISTER);
749 Cmp64_RelCst(m_registers[dst->m_valueLow], statement);
750 }
751
Emit_Cmp64_MemRelRel(const STATEMENT & statement)752 void CCodeGen_x86_64::Emit_Cmp64_MemRelRel(const STATEMENT& statement)
753 {
754 CSymbol* dst = statement.dst->GetSymbol().get();
755 CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
756 Cmp64_RelRel(tmpReg, statement);
757 m_assembler.MovGd(MakeMemorySymbolAddress(dst), tmpReg);
758 }
759
Emit_Cmp64_MemRelCst(const STATEMENT & statement)760 void CCodeGen_x86_64::Emit_Cmp64_MemRelCst(const STATEMENT& statement)
761 {
762 CSymbol* dst = statement.dst->GetSymbol().get();
763 CX86Assembler::REGISTER tmpReg = CX86Assembler::rAX;
764 Cmp64_RelCst(tmpReg, statement);
765 m_assembler.MovGd(MakeMemorySymbolAddress(dst), tmpReg);
766 }
767
Emit_RelToRef_VarCst(const STATEMENT & statement)768 void CCodeGen_x86_64::Emit_RelToRef_VarCst(const STATEMENT& statement)
769 {
770 auto dst = statement.dst->GetSymbol().get();
771 auto src1 = statement.src1->GetSymbol().get();
772
773 assert(src1->m_type == SYM_CONSTANT);
774
775 auto dstReg = PrepareRefSymbolRegisterDef(dst, CX86Assembler::rAX);
776 m_assembler.LeaGq(dstReg, CX86Assembler::MakeIndRegOffAddress(g_baseRegister, src1->m_valueLow));
777 CommitRefSymbolRegister(dst, dstReg);
778 }
779
Emit_AddRef_VarVarVar(const STATEMENT & statement)780 void CCodeGen_x86_64::Emit_AddRef_VarVarVar(const STATEMENT& statement)
781 {
782 auto dst = statement.dst->GetSymbol().get();
783 auto src1 = statement.src1->GetSymbol().get();
784 auto src2 = statement.src2->GetSymbol().get();
785
786 //TODO: Sign extend this, or we might get in trouble
787 auto offsetReg = PrepareSymbolRegisterUse(src2, CX86Assembler::rCX);
788 auto dstReg = PrepareRefSymbolRegisterDef(dst, CX86Assembler::rAX);
789
790 if(!dst->Equals(src1))
791 {
792 m_assembler.MovEq(dstReg, MakeVariableReferenceSymbolAddress(src1));
793 }
794
795 m_assembler.AddEq(dstReg, CX86Assembler::MakeRegisterAddress(offsetReg));
796 CommitRefSymbolRegister(dst, dstReg);
797 }
798
Emit_AddRef_VarVarCst(const STATEMENT & statement)799 void CCodeGen_x86_64::Emit_AddRef_VarVarCst(const STATEMENT& statement)
800 {
801 auto dst = statement.dst->GetSymbol().get();
802 auto src1 = statement.src1->GetSymbol().get();
803 auto src2 = statement.src2->GetSymbol().get();
804
805 assert(src2->m_type == SYM_CONSTANT);
806
807 auto dstReg = PrepareRefSymbolRegisterDef(dst, CX86Assembler::rAX);
808
809 if(!dst->Equals(src1))
810 {
811 m_assembler.MovEq(dstReg, MakeVariableReferenceSymbolAddress(src1));
812 }
813
814 m_assembler.AddIq(CX86Assembler::MakeRegisterAddress(dstReg), src2->m_valueLow);
815 CommitRefSymbolRegister(dst, dstReg);
816 }
817
Emit_IsRefNull_VarVar(const STATEMENT & statement)818 void CCodeGen_x86_64::Emit_IsRefNull_VarVar(const STATEMENT& statement)
819 {
820 auto dst = statement.dst->GetSymbol().get();
821 auto src1 = statement.src1->GetSymbol().get();
822
823 auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
824 auto dstReg = PrepareSymbolRegisterDef(dst, CX86Assembler::rDX);
825
826 m_assembler.XorEd(dstReg, CX86Assembler::MakeRegisterAddress(dstReg));
827 m_assembler.TestEq(addressReg, CX86Assembler::MakeRegisterAddress(addressReg));
828 m_assembler.SeteEb(CX86Assembler::MakeRegisterAddress(dstReg));
829
830 CommitSymbolRegister(dst, dstReg);
831 }
832
Emit_LoadFromRef_64_MemVar(const STATEMENT & statement)833 void CCodeGen_x86_64::Emit_LoadFromRef_64_MemVar(const STATEMENT& statement)
834 {
835 auto dst = statement.dst->GetSymbol().get();
836 auto src1 = statement.src1->GetSymbol().get();
837
838 auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
839 auto dstReg = CX86Assembler::rCX;
840
841 m_assembler.MovEq(dstReg, CX86Assembler::MakeIndRegAddress(addressReg));
842 m_assembler.MovGq(MakeMemory64SymbolAddress(dst), dstReg);
843 }
844
Emit_LoadFromRef_Ref_VarVar(const STATEMENT & statement)845 void CCodeGen_x86_64::Emit_LoadFromRef_Ref_VarVar(const STATEMENT& statement)
846 {
847 auto dst = statement.dst->GetSymbol().get();
848 auto src1 = statement.src1->GetSymbol().get();
849
850 auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
851 auto dstReg = PrepareRefSymbolRegisterDef(dst, CX86Assembler::rDX);
852
853 m_assembler.MovEq(dstReg, CX86Assembler::MakeIndRegAddress(addressReg));
854
855 CommitRefSymbolRegister(dst, dstReg);
856 }
857
Emit_StoreAtRef_64_VarMem(const STATEMENT & statement)858 void CCodeGen_x86_64::Emit_StoreAtRef_64_VarMem(const STATEMENT& statement)
859 {
860 auto src1 = statement.src1->GetSymbol().get();
861 auto src2 = statement.src2->GetSymbol().get();
862
863 auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
864 auto valueReg = CX86Assembler::rDX;
865
866 m_assembler.MovEq(valueReg, MakeMemory64SymbolAddress(src2));
867 m_assembler.MovGq(CX86Assembler::MakeIndRegAddress(addressReg), valueReg);
868 }
869
Emit_StoreAtRef_64_VarCst(const STATEMENT & statement)870 void CCodeGen_x86_64::Emit_StoreAtRef_64_VarCst(const STATEMENT& statement)
871 {
872 auto src1 = statement.src1->GetSymbol().get();
873 auto src2 = statement.src2->GetSymbol().get();
874
875 auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
876 auto valueReg = CX86Assembler::rDX;
877
878 m_assembler.MovIq(valueReg, src2->GetConstant64());
879 m_assembler.MovGq(CX86Assembler::MakeIndRegAddress(addressReg), valueReg);
880 }
881
Emit_Store8AtRef_VarVar(const STATEMENT & statement)882 void CCodeGen_x86_64::Emit_Store8AtRef_VarVar(const STATEMENT& statement)
883 {
884 auto src1 = statement.src1->GetSymbol().get();
885 auto src2 = statement.src2->GetSymbol().get();
886
887 auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
888 auto valueReg = PrepareSymbolRegisterUse(src2, CX86Assembler::rDX);
889 m_assembler.MovGb(CX86Assembler::MakeIndRegAddress(addressReg), valueReg);
890 }
891
Emit_CondJmp_Ref_VarCst(const STATEMENT & statement)892 void CCodeGen_x86_64::Emit_CondJmp_Ref_VarCst(const STATEMENT& statement)
893 {
894 auto src1 = statement.src1->GetSymbol().get();
895 auto src2 = statement.src2->GetSymbol().get();
896
897 assert(src2->m_type == SYM_CONSTANT);
898 assert(src2->m_valueLow == 0);
899 assert((statement.jmpCondition == CONDITION_NE) || (statement.jmpCondition == CONDITION_EQ));
900
901 auto addressReg = PrepareRefSymbolRegisterUse(src1, CX86Assembler::rAX);
902
903 m_assembler.TestEq(addressReg, CX86Assembler::MakeRegisterAddress(addressReg));
904
905 CondJmp_JumpTo(GetLabel(statement.jmpBlock), statement.jmpCondition);
906 }
907
PrepareRefSymbolRegisterDef(CSymbol * symbol,CX86Assembler::REGISTER preferedRegister)908 CX86Assembler::REGISTER CCodeGen_x86_64::PrepareRefSymbolRegisterDef(CSymbol* symbol, CX86Assembler::REGISTER preferedRegister)
909 {
910 switch(symbol->m_type)
911 {
912 case SYM_REG_REFERENCE:
913 return m_registers[symbol->m_valueLow];
914 break;
915 case SYM_TMP_REFERENCE:
916 case SYM_REL_REFERENCE:
917 return preferedRegister;
918 break;
919 default:
920 throw std::runtime_error("Invalid symbol type.");
921 break;
922 }
923 }
924
PrepareRefSymbolRegisterUse(CSymbol * symbol,CX86Assembler::REGISTER preferedRegister)925 CX86Assembler::REGISTER CCodeGen_x86_64::PrepareRefSymbolRegisterUse(CSymbol* symbol, CX86Assembler::REGISTER preferedRegister)
926 {
927 switch(symbol->m_type)
928 {
929 case SYM_REG_REFERENCE:
930 return m_registers[symbol->m_valueLow];
931 break;
932 case SYM_TMP_REFERENCE:
933 case SYM_REL_REFERENCE:
934 m_assembler.MovEq(preferedRegister, MakeMemoryReferenceSymbolAddress(symbol));
935 return preferedRegister;
936 break;
937 default:
938 throw std::runtime_error("Invalid symbol type.");
939 break;
940 }
941 }
942
CommitRefSymbolRegister(CSymbol * symbol,CX86Assembler::REGISTER usedRegister)943 void CCodeGen_x86_64::CommitRefSymbolRegister(CSymbol* symbol, CX86Assembler::REGISTER usedRegister)
944 {
945 switch(symbol->m_type)
946 {
947 case SYM_REG_REFERENCE:
948 assert(usedRegister == m_registers[symbol->m_valueLow]);
949 break;
950 case SYM_TMP_REFERENCE:
951 case SYM_REL_REFERENCE:
952 m_assembler.MovGq(MakeMemoryReferenceSymbolAddress(symbol), usedRegister);
953 break;
954 default:
955 throw std::runtime_error("Invalid symbol type.");
956 break;
957 }
958 }
959