1 #pragma once
2 
3 #include <deque>
4 #include "Jitter_CodeGen.h"
5 #include "AArch64Assembler.h"
6 
7 namespace Jitter
8 {
9 	class CCodeGen_AArch64 : public CCodeGen
10 	{
11 	public:
12 		           CCodeGen_AArch64();
13 		virtual    ~CCodeGen_AArch64();
14 
15 		void            SetGenerateRelocatableCalls(bool);
16 
17 		void            GenerateCode(const StatementList&, unsigned int) override;
18 		void            SetStream(Framework::CStream*) override;
19 		void            RegisterExternalSymbols(CObjectFile*) const override;
20 		unsigned int    GetAvailableRegisterCount() const override;
21 		unsigned int    GetAvailableMdRegisterCount() const override;
22 		bool            CanHold128BitsReturnValueInRegisters() const override;
23 
24 	private:
25 		typedef std::map<uint32, CAArch64Assembler::LABEL> LabelMapType;
26 		typedef void (CCodeGen_AArch64::*ConstCodeEmitterType)(const STATEMENT&);
27 
28 		struct ADDSUB_IMM_PARAMS
29 		{
30 			uint16                                      imm = 0;
31 			CAArch64Assembler::ADDSUB_IMM_SHIFT_TYPE    shiftType = CAArch64Assembler::ADDSUB_IMM_SHIFT_LSL0;
32 		};
33 
34 		struct LOGICAL_IMM_PARAMS
35 		{
36 			uint8 n;
37 			uint8 immr;
38 			uint8 imms;
39 		};
40 
41 		struct PARAM_STATE
42 		{
43 			bool prepared = false;
44 			unsigned int index = 0;
45 			uint32 spillOffset = 0;
46 		};
47 
48 		typedef std::function<void (PARAM_STATE&)> ParamEmitterFunction;
49 		typedef std::deque<ParamEmitterFunction> ParamStack;
50 
51 		enum
52 		{
53 			MAX_REGISTERS = 9,
54 		};
55 
56 		enum
57 		{
58 			MAX_MDREGISTERS = 28,
59 		};
60 
61 		enum MAX_PARAM_REGS
62 		{
63 			MAX_PARAM_REGS = 8,
64 		};
65 
66 		enum MAX_TEMP_REGS
67 		{
68 			MAX_TEMP_REGS = 7,
69 		};
70 
71 		enum MAX_TEMP_MD_REGS
72 		{
73 			MAX_TEMP_MD_REGS = 4,
74 		};
75 
76 		struct CONSTMATCHER
77 		{
78 			OPERATION               op;
79 			MATCHTYPE               dstType;
80 			MATCHTYPE               src1Type;
81 			MATCHTYPE               src2Type;
82 			ConstCodeEmitterType    emitter;
83 		};
84 
85 		static uint32    GetMaxParamSpillSize(const StatementList&);
86 
87 		CAArch64Assembler::REGISTER32    GetNextTempRegister();
88 		CAArch64Assembler::REGISTER64    GetNextTempRegister64();
89 		CAArch64Assembler::REGISTERMD    GetNextTempRegisterMd();
90 
91 		uint32    GetMemory64Offset(CSymbol*) const;
92 
93 		void    LoadMemoryInRegister(CAArch64Assembler::REGISTER32, CSymbol*);
94 		void    StoreRegisterInMemory(CSymbol*, CAArch64Assembler::REGISTER32);
95 
96 		void    LoadMemory64InRegister(CAArch64Assembler::REGISTER64, CSymbol*);
97 		void    StoreRegisterInMemory64(CSymbol*, CAArch64Assembler::REGISTER64);
98 
99 		void    LoadConstantInRegister(CAArch64Assembler::REGISTER32, uint32);
100 		void    LoadConstant64InRegister(CAArch64Assembler::REGISTER64, uint64);
101 
102 		void    LoadMemory64LowInRegister(CAArch64Assembler::REGISTER32, CSymbol*);
103 		void    LoadMemory64HighInRegister(CAArch64Assembler::REGISTER32, CSymbol*);
104 
105 		void    LoadSymbol64InRegister(CAArch64Assembler::REGISTER64, CSymbol*);
106 
107 		void    StoreRegistersInMemory64(CSymbol*, CAArch64Assembler::REGISTER32, CAArch64Assembler::REGISTER32);
108 
109 		void    LoadMemoryReferenceInRegister(CAArch64Assembler::REGISTER64, CSymbol*);
110 		void    StoreRegisterInTemporaryReference(CSymbol*, CAArch64Assembler::REGISTER64);
111 
112 		void    LoadMemoryFpSingleInRegister(CAArch64Assembler::REGISTERMD, CSymbol*);
113 		void    StoreRegisterInMemoryFpSingle(CSymbol*, CAArch64Assembler::REGISTERMD);
114 
115 		void    LoadMemory128InRegister(CAArch64Assembler::REGISTERMD, CSymbol*);
116 		void    StoreRegisterInMemory128(CSymbol*, CAArch64Assembler::REGISTERMD);
117 
118 		void    LoadMemory128AddressInRegister(CAArch64Assembler::REGISTER64, CSymbol*, uint32 = 0);
119 		void    LoadRelative128AddressInRegister(CAArch64Assembler::REGISTER64, CSymbol*, uint32);
120 		void    LoadTemporary128AddressInRegister(CAArch64Assembler::REGISTER64, CSymbol*, uint32);
121 
122 		void    LoadTemporary256ElementAddressInRegister(CAArch64Assembler::REGISTER64, CSymbol*, uint32);
123 
124 		CAArch64Assembler::REGISTER32    PrepareSymbolRegisterDef(CSymbol*, CAArch64Assembler::REGISTER32);
125 		CAArch64Assembler::REGISTER32    PrepareSymbolRegisterUse(CSymbol*, CAArch64Assembler::REGISTER32);
126 		void                             CommitSymbolRegister(CSymbol*, CAArch64Assembler::REGISTER32);
127 
128 		CAArch64Assembler::REGISTERMD    PrepareSymbolRegisterDefMd(CSymbol*, CAArch64Assembler::REGISTERMD);
129 		CAArch64Assembler::REGISTERMD    PrepareSymbolRegisterUseMd(CSymbol*, CAArch64Assembler::REGISTERMD);
130 		void                             CommitSymbolRegisterMd(CSymbol*, CAArch64Assembler::REGISTERMD);
131 
132 		CAArch64Assembler::REGISTER32    PrepareParam(PARAM_STATE&);
133 		CAArch64Assembler::REGISTER64    PrepareParam64(PARAM_STATE&);
134 		void                             CommitParam(PARAM_STATE&);
135 		void                             CommitParam64(PARAM_STATE&);
136 
137 		bool TryGetAddSubImmParams(uint32, ADDSUB_IMM_PARAMS&);
138 		bool TryGetAddSub64ImmParams(uint64, ADDSUB_IMM_PARAMS&);
139 		bool TryGetLogicalImmParams(uint32, LOGICAL_IMM_PARAMS&);
140 
141 		//SHIFTOP ----------------------------------------------------------
142 		struct SHIFTOP_BASE
143 		{
144 			typedef void (CAArch64Assembler::*OpImmType)(CAArch64Assembler::REGISTER32, CAArch64Assembler::REGISTER32, uint8);
145 			typedef void (CAArch64Assembler::*OpRegType)(CAArch64Assembler::REGISTER32, CAArch64Assembler::REGISTER32, CAArch64Assembler::REGISTER32);
146 		};
147 
148 		struct SHIFTOP_ASR : public SHIFTOP_BASE
149 		{
OpImmSHIFTOP_ASR150 			static OpImmType    OpImm()    { return &CAArch64Assembler::Asr; }
OpRegSHIFTOP_ASR151 			static OpRegType    OpReg()    { return &CAArch64Assembler::Asrv; }
152 		};
153 
154 		struct SHIFTOP_LSL : public SHIFTOP_BASE
155 		{
OpImmSHIFTOP_LSL156 			static OpImmType    OpImm()    { return &CAArch64Assembler::Lsl; }
OpRegSHIFTOP_LSL157 			static OpRegType    OpReg()    { return &CAArch64Assembler::Lslv; }
158 		};
159 
160 		struct SHIFTOP_LSR : public SHIFTOP_BASE
161 		{
OpImmSHIFTOP_LSR162 			static OpImmType    OpImm()    { return &CAArch64Assembler::Lsr; }
OpRegSHIFTOP_LSR163 			static OpRegType    OpReg()    { return &CAArch64Assembler::Lsrv; }
164 		};
165 
166 		//LOGICOP ----------------------------------------------------------
167 		struct LOGICOP_BASE
168 		{
169 			typedef void (CAArch64Assembler::*OpRegType)(CAArch64Assembler::REGISTER32, CAArch64Assembler::REGISTER32, CAArch64Assembler::REGISTER32);
170 			typedef void (CAArch64Assembler::*OpImmType)(CAArch64Assembler::REGISTER32, CAArch64Assembler::REGISTER32, uint8, uint8, uint8);
171 		};
172 
173 		struct LOGICOP_AND : public LOGICOP_BASE
174 		{
OpRegLOGICOP_AND175 			static OpRegType    OpReg()    { return &CAArch64Assembler::And; }
OpImmLOGICOP_AND176 			static OpImmType    OpImm()    { return &CAArch64Assembler::And; }
177 		};
178 
179 		struct LOGICOP_OR : public LOGICOP_BASE
180 		{
OpRegLOGICOP_OR181 			static OpRegType    OpReg()    { return &CAArch64Assembler::Orr; }
OpImmLOGICOP_OR182 			static OpImmType    OpImm()    { return &CAArch64Assembler::Orr; }
183 		};
184 
185 		struct LOGICOP_XOR : public LOGICOP_BASE
186 		{
OpRegLOGICOP_XOR187 			static OpRegType    OpReg()    { return &CAArch64Assembler::Eor; }
OpImmLOGICOP_XOR188 			static OpImmType    OpImm()    { return &CAArch64Assembler::Eor; }
189 		};
190 
191 		//ADDSUBOP ----------------------------------------------------------
192 		struct ADDSUBOP_BASE
193 		{
194 			typedef void (CAArch64Assembler::*OpImmType)(CAArch64Assembler::REGISTER32, CAArch64Assembler::REGISTER32, uint16 imm, CAArch64Assembler::ADDSUB_IMM_SHIFT_TYPE);
195 			typedef void (CAArch64Assembler::*OpRegType)(CAArch64Assembler::REGISTER32, CAArch64Assembler::REGISTER32, CAArch64Assembler::REGISTER32);
196 		};
197 
198 		struct ADDSUBOP_ADD : public ADDSUBOP_BASE
199 		{
OpImmADDSUBOP_ADD200 			static OpImmType    OpImm()       { return &CAArch64Assembler::Add; }
OpRegADDSUBOP_ADD201 			static OpRegType    OpReg()       { return &CAArch64Assembler::Add; }
OpImmRevADDSUBOP_ADD202 			static OpImmType    OpImmRev()    { return &CAArch64Assembler::Sub; }
203 		};
204 
205 		struct ADDSUBOP_SUB : public ADDSUBOP_BASE
206 		{
OpImmADDSUBOP_SUB207 			static OpImmType    OpImm()       { return &CAArch64Assembler::Sub; }
OpRegADDSUBOP_SUB208 			static OpRegType    OpReg()       { return &CAArch64Assembler::Sub; }
OpImmRevADDSUBOP_SUB209 			static OpImmType    OpImmRev()    { return &CAArch64Assembler::Add; }
210 		};
211 
212 		//SHIFT64OP ----------------------------------------------------------
213 		struct SHIFT64OP_BASE
214 		{
215 			typedef void (CAArch64Assembler::*OpImmType)(CAArch64Assembler::REGISTER64, CAArch64Assembler::REGISTER64, uint8);
216 			typedef void (CAArch64Assembler::*OpRegType)(CAArch64Assembler::REGISTER64, CAArch64Assembler::REGISTER64, CAArch64Assembler::REGISTER64);
217 		};
218 
219 		struct SHIFT64OP_ASR : public SHIFT64OP_BASE
220 		{
OpImmSHIFT64OP_ASR221 			static OpImmType    OpImm()    { return &CAArch64Assembler::Asr; }
OpRegSHIFT64OP_ASR222 			static OpRegType    OpReg()    { return &CAArch64Assembler::Asrv; }
223 		};
224 
225 		struct SHIFT64OP_LSL : public SHIFT64OP_BASE
226 		{
OpImmSHIFT64OP_LSL227 			static OpImmType    OpImm()    { return &CAArch64Assembler::Lsl; }
OpRegSHIFT64OP_LSL228 			static OpRegType    OpReg()    { return &CAArch64Assembler::Lslv; }
229 		};
230 
231 		struct SHIFT64OP_LSR : public SHIFT64OP_BASE
232 		{
OpImmSHIFT64OP_LSR233 			static OpImmType    OpImm()    { return &CAArch64Assembler::Lsr; }
OpRegSHIFT64OP_LSR234 			static OpRegType    OpReg()    { return &CAArch64Assembler::Lsrv; }
235 		};
236 
237 		//FPUOP ----------------------------------------------------------
238 		struct FPUOP_BASE2
239 		{
240 			typedef void (CAArch64Assembler::*OpRegType)(CAArch64Assembler::REGISTERMD, CAArch64Assembler::REGISTERMD);
241 		};
242 
243 		struct FPUOP_BASE3
244 		{
245 			typedef void (CAArch64Assembler::*OpRegType)(CAArch64Assembler::REGISTERMD, CAArch64Assembler::REGISTERMD, CAArch64Assembler::REGISTERMD);
246 		};
247 
248 		struct FPUOP_ADD : public FPUOP_BASE3
249 		{
OpRegFPUOP_ADD250 			static OpRegType OpReg() { return &CAArch64Assembler::Fadd_1s; }
251 		};
252 
253 		struct FPUOP_SUB : public FPUOP_BASE3
254 		{
OpRegFPUOP_SUB255 			static OpRegType OpReg() { return &CAArch64Assembler::Fsub_1s; }
256 		};
257 
258 		struct FPUOP_MUL : public FPUOP_BASE3
259 		{
OpRegFPUOP_MUL260 			static OpRegType OpReg() { return &CAArch64Assembler::Fmul_1s; }
261 		};
262 
263 		struct FPUOP_DIV : public FPUOP_BASE3
264 		{
OpRegFPUOP_DIV265 			static OpRegType OpReg() { return &CAArch64Assembler::Fdiv_1s; }
266 		};
267 
268 		struct FPUOP_MIN : public FPUOP_BASE3
269 		{
OpRegFPUOP_MIN270 			static OpRegType OpReg() { return &CAArch64Assembler::Fmin_1s; }
271 		};
272 
273 		struct FPUOP_MAX : public FPUOP_BASE3
274 		{
OpRegFPUOP_MAX275 			static OpRegType OpReg() { return &CAArch64Assembler::Fmax_1s; }
276 		};
277 
278 		struct FPUOP_ABS : public FPUOP_BASE2
279 		{
OpRegFPUOP_ABS280 			static OpRegType OpReg() { return &CAArch64Assembler::Fabs_1s; }
281 		};
282 
283 		struct FPUOP_NEG : public FPUOP_BASE2
284 		{
OpRegFPUOP_NEG285 			static OpRegType OpReg() { return &CAArch64Assembler::Fneg_1s; }
286 		};
287 
288 		struct FPUOP_SQRT : public FPUOP_BASE2
289 		{
OpRegFPUOP_SQRT290 			static OpRegType OpReg() { return &CAArch64Assembler::Fsqrt_1s; }
291 		};
292 
293 		//MDOP -----------------------------------------------------------
294 		struct MDOP_BASE2
295 		{
296 			typedef void (CAArch64Assembler::*OpRegType)(CAArch64Assembler::REGISTERMD, CAArch64Assembler::REGISTERMD);
297 		};
298 
299 		struct MDOP_BASE3
300 		{
301 			typedef void (CAArch64Assembler::*OpRegType)(CAArch64Assembler::REGISTERMD, CAArch64Assembler::REGISTERMD, CAArch64Assembler::REGISTERMD);
302 		};
303 
304 		struct MDOP_SHIFT
305 		{
306 			typedef void (CAArch64Assembler::*OpRegType)(CAArch64Assembler::REGISTERMD, CAArch64Assembler::REGISTERMD, uint8);
307 		};
308 
309 		struct MDOP_ADDB : public MDOP_BASE3
310 		{
OpRegMDOP_ADDB311 			static OpRegType OpReg() { return &CAArch64Assembler::Add_16b; }
312 		};
313 
314 		struct MDOP_ADDH : public MDOP_BASE3
315 		{
OpRegMDOP_ADDH316 			static OpRegType OpReg() { return &CAArch64Assembler::Add_8h; }
317 		};
318 
319 		struct MDOP_ADDW : public MDOP_BASE3
320 		{
OpRegMDOP_ADDW321 			static OpRegType OpReg() { return &CAArch64Assembler::Add_4s; }
322 		};
323 
324 		struct MDOP_ADDBUS : public MDOP_BASE3
325 		{
OpRegMDOP_ADDBUS326 			static OpRegType OpReg() { return &CAArch64Assembler::Uqadd_16b; }
327 		};
328 
329 		struct MDOP_ADDHUS : public MDOP_BASE3
330 		{
OpRegMDOP_ADDHUS331 			static OpRegType OpReg() { return &CAArch64Assembler::Uqadd_8h; }
332 		};
333 
334 		struct MDOP_ADDWUS : public MDOP_BASE3
335 		{
OpRegMDOP_ADDWUS336 			static OpRegType OpReg() { return &CAArch64Assembler::Uqadd_4s; }
337 		};
338 
339 		struct MDOP_ADDHSS : public MDOP_BASE3
340 		{
OpRegMDOP_ADDHSS341 			static OpRegType OpReg() { return &CAArch64Assembler::Sqadd_8h; }
342 		};
343 
344 		struct MDOP_ADDWSS : public MDOP_BASE3
345 		{
OpRegMDOP_ADDWSS346 			static OpRegType OpReg() { return &CAArch64Assembler::Sqadd_4s; }
347 		};
348 
349 		struct MDOP_SUBB : public MDOP_BASE3
350 		{
OpRegMDOP_SUBB351 			static OpRegType OpReg() { return &CAArch64Assembler::Sub_16b; }
352 		};
353 
354 		struct MDOP_SUBH : public MDOP_BASE3
355 		{
OpRegMDOP_SUBH356 			static OpRegType OpReg() { return &CAArch64Assembler::Sub_8h; }
357 		};
358 
359 		struct MDOP_SUBW : public MDOP_BASE3
360 		{
OpRegMDOP_SUBW361 			static OpRegType OpReg() { return &CAArch64Assembler::Sub_4s; }
362 		};
363 
364 		struct MDOP_SUBBUS : public MDOP_BASE3
365 		{
OpRegMDOP_SUBBUS366 			static OpRegType OpReg() { return &CAArch64Assembler::Uqsub_16b; }
367 		};
368 
369 		struct MDOP_SUBHUS : public MDOP_BASE3
370 		{
OpRegMDOP_SUBHUS371 			static OpRegType OpReg() { return &CAArch64Assembler::Uqsub_8h; }
372 		};
373 
374 		struct MDOP_SUBHSS : public MDOP_BASE3
375 		{
OpRegMDOP_SUBHSS376 			static OpRegType OpReg() { return &CAArch64Assembler::Sqsub_8h; }
377 		};
378 
379 		struct MDOP_SUBWSS : public MDOP_BASE3
380 		{
OpRegMDOP_SUBWSS381 			static OpRegType OpReg() { return &CAArch64Assembler::Sqsub_4s; }
382 		};
383 
384 		struct MDOP_CMPEQW : public MDOP_BASE3
385 		{
OpRegMDOP_CMPEQW386 			static OpRegType OpReg() { return &CAArch64Assembler::Cmeq_4s; }
387 		};
388 
389 		struct MDOP_CMPGTH : public MDOP_BASE3
390 		{
OpRegMDOP_CMPGTH391 			static OpRegType OpReg() { return &CAArch64Assembler::Cmgt_4s; }
392 		};
393 
394 		struct MDOP_MINH : public MDOP_BASE3
395 		{
OpRegMDOP_MINH396 			static OpRegType OpReg() { return &CAArch64Assembler::Smin_8h; }
397 		};
398 
399 		struct MDOP_MINW : public MDOP_BASE3
400 		{
OpRegMDOP_MINW401 			static OpRegType OpReg() { return &CAArch64Assembler::Smin_4s; }
402 		};
403 
404 		struct MDOP_MAXH : public MDOP_BASE3
405 		{
OpRegMDOP_MAXH406 			static OpRegType OpReg() { return &CAArch64Assembler::Smax_8h; }
407 		};
408 
409 		struct MDOP_MAXW : public MDOP_BASE3
410 		{
OpRegMDOP_MAXW411 			static OpRegType OpReg() { return &CAArch64Assembler::Smax_4s; }
412 		};
413 
414 		struct MDOP_ADDS : public MDOP_BASE3
415 		{
OpRegMDOP_ADDS416 			static OpRegType OpReg() { return &CAArch64Assembler::Fadd_4s; }
417 		};
418 
419 		struct MDOP_SUBS : public MDOP_BASE3
420 		{
OpRegMDOP_SUBS421 			static OpRegType OpReg() { return &CAArch64Assembler::Fsub_4s; }
422 		};
423 
424 		struct MDOP_MULS : public MDOP_BASE3
425 		{
OpRegMDOP_MULS426 			static OpRegType OpReg() { return &CAArch64Assembler::Fmul_4s; }
427 		};
428 
429 		struct MDOP_DIVS : public MDOP_BASE3
430 		{
OpRegMDOP_DIVS431 			static OpRegType OpReg() { return &CAArch64Assembler::Fdiv_4s; }
432 		};
433 
434 		struct MDOP_ABSS : public MDOP_BASE2
435 		{
OpRegMDOP_ABSS436 			static OpRegType OpReg() { return &CAArch64Assembler::Fabs_4s; }
437 		};
438 
439 		struct MDOP_MINS : public MDOP_BASE3
440 		{
OpRegMDOP_MINS441 			static OpRegType OpReg() { return &CAArch64Assembler::Fmin_4s; }
442 		};
443 
444 		struct MDOP_MAXS : public MDOP_BASE3
445 		{
OpRegMDOP_MAXS446 			static OpRegType OpReg() { return &CAArch64Assembler::Fmax_4s; }
447 		};
448 
449 		struct MDOP_TOSINGLE : public MDOP_BASE2
450 		{
OpRegMDOP_TOSINGLE451 			static OpRegType OpReg() { return &CAArch64Assembler::Scvtf_4s; }
452 		};
453 
454 		struct MDOP_TOWORD : public MDOP_BASE2
455 		{
OpRegMDOP_TOWORD456 			static OpRegType OpReg() { return &CAArch64Assembler::Fcvtzs_4s; }
457 		};
458 
459 		struct MDOP_AND : public MDOP_BASE3
460 		{
OpRegMDOP_AND461 			static OpRegType OpReg() { return &CAArch64Assembler::And_16b; }
462 		};
463 
464 		struct MDOP_OR : public MDOP_BASE3
465 		{
OpRegMDOP_OR466 			static OpRegType OpReg() { return &CAArch64Assembler::Orr_16b; }
467 		};
468 
469 		struct MDOP_XOR : public MDOP_BASE3
470 		{
OpRegMDOP_XOR471 			static OpRegType OpReg() { return &CAArch64Assembler::Eor_16b; }
472 		};
473 
474 		struct MDOP_UNPACK_LOWER_BH : public MDOP_BASE3
475 		{
OpRegMDOP_UNPACK_LOWER_BH476 			static OpRegType OpReg() { return &CAArch64Assembler::Zip1_16b; }
477 		};
478 
479 		struct MDOP_UNPACK_LOWER_HW : public MDOP_BASE3
480 		{
OpRegMDOP_UNPACK_LOWER_HW481 			static OpRegType OpReg() { return &CAArch64Assembler::Zip1_8h; }
482 		};
483 
484 		struct MDOP_UNPACK_LOWER_WD : public MDOP_BASE3
485 		{
OpRegMDOP_UNPACK_LOWER_WD486 			static OpRegType OpReg() { return &CAArch64Assembler::Zip1_4s; }
487 		};
488 
489 		struct MDOP_UNPACK_UPPER_BH : public MDOP_BASE3
490 		{
OpRegMDOP_UNPACK_UPPER_BH491 			static OpRegType OpReg() { return &CAArch64Assembler::Zip2_16b; }
492 		};
493 
494 		struct MDOP_UNPACK_UPPER_HW : public MDOP_BASE3
495 		{
OpRegMDOP_UNPACK_UPPER_HW496 			static OpRegType OpReg() { return &CAArch64Assembler::Zip2_8h; }
497 		};
498 
499 		struct MDOP_UNPACK_UPPER_WD : public MDOP_BASE3
500 		{
OpRegMDOP_UNPACK_UPPER_WD501 			static OpRegType OpReg() { return &CAArch64Assembler::Zip2_4s; }
502 		};
503 
504 		struct MDOP_CMPEQZS : public MDOP_BASE2
505 		{
OpRegMDOP_CMPEQZS506 			static OpRegType OpReg() { return &CAArch64Assembler::Fcmeq_4s; }
507 		};
508 
509 		struct MDOP_CMPLTZS : public MDOP_BASE2
510 		{
OpRegMDOP_CMPLTZS511 			static OpRegType OpReg() { return &CAArch64Assembler::Fcmlt_4s; }
512 		};
513 
514 		struct MDOP_SLLH : public MDOP_SHIFT
515 		{
OpRegMDOP_SLLH516 			static OpRegType OpReg() { return &CAArch64Assembler::Shl_8h; }
517 		};
518 
519 		struct MDOP_SLLW : public MDOP_SHIFT
520 		{
OpRegMDOP_SLLW521 			static OpRegType OpReg() { return &CAArch64Assembler::Shl_4s; }
522 		};
523 
524 		struct MDOP_SRLH : public MDOP_SHIFT
525 		{
OpRegMDOP_SRLH526 			static OpRegType OpReg() { return &CAArch64Assembler::Ushr_8h; }
527 		};
528 
529 		struct MDOP_SRLW : public MDOP_SHIFT
530 		{
OpRegMDOP_SRLW531 			static OpRegType OpReg() { return &CAArch64Assembler::Ushr_4s; }
532 		};
533 
534 		struct MDOP_SRAH : public MDOP_SHIFT
535 		{
OpRegMDOP_SRAH536 			static OpRegType OpReg() { return &CAArch64Assembler::Sshr_8h; }
537 		};
538 
539 		struct MDOP_SRAW : public MDOP_SHIFT
540 		{
OpRegMDOP_SRAW541 			static OpRegType OpReg() { return &CAArch64Assembler::Sshr_4s; }
542 		};
543 
544 		uint16    GetSavedRegisterList(uint32);
545 		void      Emit_Prolog(const StatementList&, uint32, uint16);
546 		void      Emit_Epilog(uint32, uint16);
547 
548 		CAArch64Assembler::LABEL GetLabel(uint32);
549 		void                     MarkLabel(const STATEMENT&);
550 
551 		void    Emit_Nop(const STATEMENT&);
552 
553 		void    Emit_Mov_RegReg(const STATEMENT&);
554 		void    Emit_Mov_RegMem(const STATEMENT&);
555 		void    Emit_Mov_RegCst(const STATEMENT&);
556 		void    Emit_Mov_MemReg(const STATEMENT&);
557 		void    Emit_Mov_MemMem(const STATEMENT&);
558 		void    Emit_Mov_MemCst(const STATEMENT&);
559 
560 		void    Emit_Not_VarVar(const STATEMENT&);
561 		void    Emit_Lzc_VarVar(const STATEMENT&);
562 
563 		void    Emit_Mov_Mem64Mem64(const STATEMENT&);
564 		void    Emit_Mov_Mem64Cst64(const STATEMENT&);
565 
566 		void    Emit_ExtLow64VarMem64(const STATEMENT&);
567 		void    Emit_ExtHigh64VarMem64(const STATEMENT&);
568 		void    Emit_MergeTo64_Mem64AnyAny(const STATEMENT&);
569 
570 		void    Emit_RelToRef_TmpCst(const STATEMENT&);
571 		void    Emit_AddRef_TmpMemAny(const STATEMENT&);
572 		void    Emit_LoadFromRef_VarMem(const STATEMENT&);
573 		void    Emit_StoreAtRef_MemAny(const STATEMENT&);
574 
575 		void    Emit_Param_Ctx(const STATEMENT&);
576 		void    Emit_Param_Reg(const STATEMENT&);
577 		void    Emit_Param_Mem(const STATEMENT&);
578 		void    Emit_Param_Cst(const STATEMENT&);
579 		void    Emit_Param_Mem64(const STATEMENT&);
580 		void    Emit_Param_Cst64(const STATEMENT&);
581 		void    Emit_Param_Reg128(const STATEMENT&);
582 		void    Emit_Param_Mem128(const STATEMENT&);
583 
584 		void    Emit_Call(const STATEMENT&);
585 		void    Emit_RetVal_Reg(const STATEMENT&);
586 		void    Emit_RetVal_Tmp(const STATEMENT&);
587 		void    Emit_RetVal_Mem64(const STATEMENT&);
588 		void    Emit_RetVal_Reg128(const STATEMENT&);
589 		void    Emit_RetVal_Mem128(const STATEMENT&);
590 
591 		void    Emit_Jmp(const STATEMENT&);
592 
593 		void    Emit_CondJmp(const STATEMENT&);
594 		void    Emit_CondJmp_AnyVar(const STATEMENT&);
595 		void    Emit_CondJmp_VarCst(const STATEMENT&);
596 
597 		void    Cmp_GetFlag(CAArch64Assembler::REGISTER32, Jitter::CONDITION);
598 		void    Emit_Cmp_VarAnyVar(const STATEMENT&);
599 		void    Emit_Cmp_VarVarCst(const STATEMENT&);
600 
601 		void    Emit_Add64_MemMemMem(const STATEMENT&);
602 		void    Emit_Add64_MemMemCst(const STATEMENT&);
603 
604 		void    Emit_Sub64_MemAnyMem(const STATEMENT&);
605 		void    Emit_Sub64_MemMemCst(const STATEMENT&);
606 
607 		void    Emit_Cmp64_VarAnyMem(const STATEMENT&);
608 		void    Emit_Cmp64_VarMemCst(const STATEMENT&);
609 
610 		void    Emit_And64_MemMemMem(const STATEMENT&);
611 
612 		//ADDSUB
613 		template <typename> void    Emit_AddSub_VarAnyVar(const STATEMENT&);
614 		template <typename> void    Emit_AddSub_VarVarCst(const STATEMENT&);
615 
616 		//SHIFT
617 		template <typename> void    Emit_Shift_VarAnyVar(const STATEMENT&);
618 		template <typename> void    Emit_Shift_VarVarCst(const STATEMENT&);
619 
620 		//LOGIC
621 		template <typename> void    Emit_Logic_VarAnyVar(const STATEMENT&);
622 		template <typename> void    Emit_Logic_VarVarCst(const STATEMENT&);
623 
624 		//MUL
625 		template <bool> void Emit_Mul_Tmp64AnyAny(const STATEMENT&);
626 
627 		//DIV
628 		template <bool> void Emit_Div_Tmp64AnyAny(const STATEMENT&);
629 
630 		//SHIFT64
631 		template <typename> void    Emit_Shift64_MemMemVar(const STATEMENT&);
632 		template <typename> void    Emit_Shift64_MemMemCst(const STATEMENT&);
633 
634 		//FPU
635 		template <typename> void    Emit_Fpu_MemMem(const STATEMENT&);
636 		template <typename> void    Emit_Fpu_MemMemMem(const STATEMENT&);
637 
638 		void    Emit_Fp_Cmp_AnyMemMem(const STATEMENT&);
639 		void    Emit_Fp_Rcpl_MemMem(const STATEMENT&);
640 		void    Emit_Fp_Rsqrt_MemMem(const STATEMENT&);
641 		void    Emit_Fp_Mov_MemSRelI32(const STATEMENT&);
642 		void    Emit_Fp_ToIntTrunc_MemMem(const STATEMENT&);
643 		void    Emit_Fp_LdCst_TmpCst(const STATEMENT&);
644 
645 		//MD
646 		template <typename> void    Emit_Md_VarVar(const STATEMENT&);
647 		template <typename> void    Emit_Md_VarVarVar(const STATEMENT&);
648 		template <typename> void    Emit_Md_VarVarVarRev(const STATEMENT&);
649 		template <typename> void    Emit_Md_Shift_VarVarCst(const STATEMENT&);
650 		template <typename> void    Emit_Md_Test_VarVar(const STATEMENT&);
651 
652 		void    Emit_Md_Mov_RegReg(const STATEMENT&);
653 		void    Emit_Md_Mov_RegMem(const STATEMENT&);
654 		void    Emit_Md_Mov_MemReg(const STATEMENT&);
655 		void    Emit_Md_Mov_MemMem(const STATEMENT&);
656 
657 		void    Emit_Md_Not_VarVar(const STATEMENT&);
658 
659 		void    Emit_Md_LoadFromRef_VarMem(const STATEMENT&);
660 		void    Emit_Md_StoreAtRef_MemVar(const STATEMENT&);
661 
662 		void    Emit_Md_MovMasked_VarVarVar(const STATEMENT&);
663 		void    Emit_Md_Expand_VarReg(const STATEMENT&);
664 		void    Emit_Md_Expand_VarMem(const STATEMENT&);
665 		void    Emit_Md_Expand_VarCst(const STATEMENT&);
666 
667 		void    Emit_Md_PackHB_VarVarVar(const STATEMENT&);
668 		void    Emit_Md_PackWH_VarVarVar(const STATEMENT&);
669 
670 		void    Emit_MergeTo256_MemVarVar(const STATEMENT&);
671 		void    Emit_Md_Srl256_VarMemVar(const STATEMENT&);
672 		void    Emit_Md_Srl256_VarMemCst(const STATEMENT&);
673 
674 		static CONSTMATCHER    g_constMatchers[];
675 		static CONSTMATCHER    g_64ConstMatchers[];
676 		static CONSTMATCHER    g_fpuConstMatchers[];
677 		static CONSTMATCHER    g_mdConstMatchers[];
678 
679 		static CAArch64Assembler::REGISTER32    g_registers[MAX_REGISTERS];
680 		static CAArch64Assembler::REGISTERMD    g_registersMd[MAX_MDREGISTERS];
681 		static CAArch64Assembler::REGISTER32    g_tempRegisters[MAX_TEMP_REGS];
682 		static CAArch64Assembler::REGISTER64    g_tempRegisters64[MAX_TEMP_REGS];
683 		static CAArch64Assembler::REGISTERMD    g_tempRegistersMd[MAX_TEMP_MD_REGS];
684 		static CAArch64Assembler::REGISTER32    g_paramRegisters[MAX_PARAM_REGS];
685 		static CAArch64Assembler::REGISTER64    g_paramRegisters64[MAX_PARAM_REGS];
686 		static CAArch64Assembler::REGISTER64    g_baseRegister;
687 
688 		Framework::CStream*    m_stream = nullptr;
689 		CAArch64Assembler      m_assembler;
690 		LabelMapType           m_labels;
691 		ParamStack             m_params;
692 		uint32                 m_nextTempRegister = 0;
693 		uint32                 m_nextTempRegisterMd = 0;
694 		uint32                 m_paramSpillBase = 0;
695 
696 		bool    m_generateRelocatableCalls = false;
697 	};
698 };
699