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