1 #include <assert.h>
2 #include <stdexcept>
3 #include "AArch64Assembler.h"
4 #include "LiteralPool.h"
5 
SetStream(Framework::CStream * stream)6 void CAArch64Assembler::SetStream(Framework::CStream* stream)
7 {
8 	m_stream = stream;
9 }
10 
CreateLabel()11 CAArch64Assembler::LABEL CAArch64Assembler::CreateLabel()
12 {
13 	return m_nextLabelId++;
14 }
15 
ClearLabels()16 void CAArch64Assembler::ClearLabels()
17 {
18 	m_labels.clear();
19 }
20 
MarkLabel(LABEL label)21 void CAArch64Assembler::MarkLabel(LABEL label)
22 {
23 	m_labels[label] = static_cast<size_t>(m_stream->Tell());
24 }
25 
CreateBranchLabelReference(LABEL label,CONDITION condition)26 void CAArch64Assembler::CreateBranchLabelReference(LABEL label, CONDITION condition)
27 {
28 	LABELREF reference;
29 	reference.offset    = static_cast<size_t>(m_stream->Tell());
30 	reference.condition = condition;
31 	m_labelReferences.insert(std::make_pair(label, reference));
32 }
33 
CreateCompareBranchLabelReference(LABEL label,CONDITION condition,REGISTER32 cbRegister)34 void CAArch64Assembler::CreateCompareBranchLabelReference(LABEL label, CONDITION condition, REGISTER32 cbRegister)
35 {
36 	LABELREF reference;
37 	reference.offset     = static_cast<size_t>(m_stream->Tell());
38 	reference.condition  = condition;
39 	reference.cbz        = true;
40 	reference.cbRegister = cbRegister;
41 	m_labelReferences.insert(std::make_pair(label, reference));
42 }
43 
CreateCompareBranchLabelReference(LABEL label,CONDITION condition,REGISTER64 cbRegister)44 void CAArch64Assembler::CreateCompareBranchLabelReference(LABEL label, CONDITION condition, REGISTER64 cbRegister)
45 {
46 	LABELREF reference;
47 	reference.offset     = static_cast<size_t>(m_stream->Tell());
48 	reference.condition  = condition;
49 	reference.cbz64      = true;
50 	reference.cbRegister = static_cast<REGISTER32>(cbRegister);
51 	m_labelReferences.insert(std::make_pair(label, reference));
52 }
53 
ResolveLabelReferences()54 void CAArch64Assembler::ResolveLabelReferences()
55 {
56 	for(const auto& labelReferencePair : m_labelReferences)
57 	{
58 		auto label(m_labels.find(labelReferencePair.first));
59 		if(label == m_labels.end())
60 		{
61 			throw std::runtime_error("Invalid label.");
62 		}
63 		const auto& labelReference = labelReferencePair.second;
64 		size_t labelPos = label->second;
65 		int offset = static_cast<int>(labelPos - labelReference.offset) / 4;
66 
67 		m_stream->Seek(labelReference.offset, Framework::STREAM_SEEK_SET);
68 		if(labelReference.condition == CONDITION_AL)
69 		{
70 			uint32 opcode = 0x14000000;
71 			opcode |= (offset & 0x3FFFFFF);
72 			WriteWord(opcode);
73 		}
74 		else
75 		{
76 			if(labelReference.cbz || labelReference.cbz64)
77 			{
78 				assert((labelReference.condition == CONDITION_EQ) || (labelReference.condition == CONDITION_NE));
79 				uint32 opcode = [&labelReference]()
80 					{
81 						uint32 sf = labelReference.cbz64 ? 0x80000000 : 0;
82 						switch(labelReference.condition)
83 						{
84 						case CONDITION_EQ:
85 							return 0x34000000 | sf;
86 							break;
87 						case CONDITION_NE:
88 							return 0x35000000 | sf;
89 							break;
90 						default:
91 							assert(false);
92 							return 0U;
93 						}
94 					}();
95 				opcode |= (offset & 0x7FFFF) << 5;
96 				opcode |= labelReference.cbRegister;
97 				WriteWord(opcode);
98 			}
99 			else
100 			{
101 				uint32 opcode = 0x54000000;
102 				opcode |= (offset & 0x7FFFF) << 5;
103 				opcode |= labelReference.condition;
104 				WriteWord(opcode);
105 			}
106 		}
107 	}
108 	m_stream->Seek(0, Framework::STREAM_SEEK_END);
109 	m_labelReferences.clear();
110 }
111 
ResolveLiteralReferences()112 void CAArch64Assembler::ResolveLiteralReferences()
113 {
114 	if(m_literal128Refs.empty()) return;
115 
116 	CLiteralPool literalPool(m_stream);
117 	literalPool.AlignPool();
118 
119 	for(const auto& literalRef : m_literal128Refs)
120 	{
121 		auto literalPos = static_cast<uint32>(literalPool.GetLiteralPosition(literalRef.value));
122 		m_stream->Seek(literalRef.offset, Framework::STREAM_SEEK_SET);
123 		auto offset = literalPos - literalRef.offset;
124 		assert((offset & 0x03) == 0);
125 		assert(offset < 0x100000);
126 		offset /= 4;
127 		m_stream->Write32(0x9C000000 | static_cast<uint32>(offset << 5) | literalRef.rt);
128 	}
129 	m_literal128Refs.clear();
130 	m_stream->Seek(0, Framework::STREAM_SEEK_END);
131 }
132 
Add(REGISTER32 rd,REGISTER32 rn,REGISTER32 rm)133 void CAArch64Assembler::Add(REGISTER32 rd, REGISTER32 rn, REGISTER32 rm)
134 {
135 	uint32 opcode = 0x0B000000;
136 	opcode |= (rd <<  0);
137 	opcode |= (rn <<  5);
138 	opcode |= (rm << 16);
139 	WriteWord(opcode);
140 }
141 
Add(REGISTER64 rd,REGISTER64 rn,REGISTER64 rm)142 void CAArch64Assembler::Add(REGISTER64 rd, REGISTER64 rn, REGISTER64 rm)
143 {
144 	uint32 opcode = 0x8B000000;
145 	opcode |= (rd <<  0);
146 	opcode |= (rn <<  5);
147 	opcode |= (rm << 16);
148 	WriteWord(opcode);
149 }
150 
Add(REGISTER32 rd,REGISTER32 rn,uint16 imm,ADDSUB_IMM_SHIFT_TYPE shift)151 void CAArch64Assembler::Add(REGISTER32 rd, REGISTER32 rn, uint16 imm, ADDSUB_IMM_SHIFT_TYPE shift)
152 {
153 	WriteAddSubOpImm(0x11000000, shift, imm, rn, rd);
154 }
155 
Add(REGISTER64 rd,REGISTER64 rn,uint16 imm,ADDSUB_IMM_SHIFT_TYPE shift)156 void CAArch64Assembler::Add(REGISTER64 rd, REGISTER64 rn, uint16 imm, ADDSUB_IMM_SHIFT_TYPE shift)
157 {
158 	WriteAddSubOpImm(0x91000000, shift, imm, rn, rd);
159 }
160 
Add_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)161 void CAArch64Assembler::Add_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
162 {
163 	uint32 opcode = 0x4EA08400;
164 	opcode |= (rd <<  0);
165 	opcode |= (rn <<  5);
166 	opcode |= (rm << 16);
167 	WriteWord(opcode);
168 }
169 
Add_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)170 void CAArch64Assembler::Add_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
171 {
172 	uint32 opcode = 0x4E608400;
173 	opcode |= (rd <<  0);
174 	opcode |= (rn <<  5);
175 	opcode |= (rm << 16);
176 	WriteWord(opcode);
177 }
178 
Add_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)179 void CAArch64Assembler::Add_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
180 {
181 	uint32 opcode = 0x4E208400;
182 	opcode |= (rd <<  0);
183 	opcode |= (rn <<  5);
184 	opcode |= (rm << 16);
185 	WriteWord(opcode);
186 }
187 
And(REGISTER32 rd,REGISTER32 rn,REGISTER32 rm)188 void CAArch64Assembler::And(REGISTER32 rd, REGISTER32 rn, REGISTER32 rm)
189 {
190 	uint32 opcode = 0x0A000000;
191 	opcode |= (rd <<  0);
192 	opcode |= (rn <<  5);
193 	opcode |= (rm << 16);
194 	WriteWord(opcode);
195 }
196 
And(REGISTER64 rd,REGISTER64 rn,REGISTER64 rm)197 void CAArch64Assembler::And(REGISTER64 rd, REGISTER64 rn, REGISTER64 rm)
198 {
199 	uint32 opcode = 0x8A000000;
200 	opcode |= (rd <<  0);
201 	opcode |= (rn <<  5);
202 	opcode |= (rm << 16);
203 	WriteWord(opcode);
204 }
205 
And(REGISTER32 rd,REGISTER32 rn,uint8 n,uint8 immr,uint8 imms)206 void CAArch64Assembler::And(REGISTER32 rd, REGISTER32 rn, uint8 n, uint8 immr, uint8 imms)
207 {
208 	WriteLogicalOpImm(0x12000000, n, immr, imms, rn, rd);
209 }
210 
And_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)211 void CAArch64Assembler::And_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
212 {
213 	uint32 opcode = 0x4E201C00;
214 	opcode |= (rd <<  0);
215 	opcode |= (rn <<  5);
216 	opcode |= (rm << 16);
217 	WriteWord(opcode);
218 }
219 
Asr(REGISTER32 rd,REGISTER32 rn,uint8 sa)220 void CAArch64Assembler::Asr(REGISTER32 rd, REGISTER32 rn, uint8 sa)
221 {
222 	uint32 imms = 0x1F;
223 	uint32 immr = sa & 0x1F;
224 	WriteLogicalOpImm(0x13000000, 0, immr, imms, rn, rd);
225 }
226 
Asr(REGISTER64 rd,REGISTER64 rn,uint8 sa)227 void CAArch64Assembler::Asr(REGISTER64 rd, REGISTER64 rn, uint8 sa)
228 {
229 	uint32 imms = 0x3F;
230 	uint32 immr = sa & 0x3F;
231 	WriteLogicalOpImm(0x93400000, 0, immr, imms, rn, rd);
232 }
233 
Asrv(REGISTER32 rd,REGISTER32 rn,REGISTER32 rm)234 void CAArch64Assembler::Asrv(REGISTER32 rd, REGISTER32 rn, REGISTER32 rm)
235 {
236 	WriteDataProcOpReg2(0x1AC02800, rm, rn, rd);
237 }
238 
Asrv(REGISTER64 rd,REGISTER64 rn,REGISTER64 rm)239 void CAArch64Assembler::Asrv(REGISTER64 rd, REGISTER64 rn, REGISTER64 rm)
240 {
241 	WriteDataProcOpReg2(0x9AC02800, rm, rn, rd);
242 }
243 
B(LABEL label)244 void CAArch64Assembler::B(LABEL label)
245 {
246 	CreateBranchLabelReference(label, CONDITION_AL);
247 	WriteWord(0);
248 }
249 
B_offset(uint32 offset)250 void CAArch64Assembler::B_offset(uint32 offset)
251 {
252 	assert((offset & 0x3) == 0);
253 	offset /= 4;
254 	assert(offset < 0x40000000);
255 	uint32 opcode = 0x14000000;
256 	opcode |= offset;
257 	WriteWord(opcode);
258 }
259 
Bl(uint32 offset)260 void CAArch64Assembler::Bl(uint32 offset)
261 {
262 	assert((offset & 0x3) == 0);
263 	offset /= 4;
264 	assert(offset < 0x40000000);
265 	uint32 opcode = 0x94000000;
266 	opcode |= offset;
267 	WriteWord(opcode);
268 }
269 
Br(REGISTER64 rn)270 void CAArch64Assembler::Br(REGISTER64 rn)
271 {
272 	uint32 opcode = 0xD61F0000;
273 	opcode |= (rn << 5);
274 	WriteWord(opcode);
275 }
276 
BCc(CONDITION condition,LABEL label)277 void CAArch64Assembler::BCc(CONDITION condition, LABEL label)
278 {
279 	CreateBranchLabelReference(label, condition);
280 	WriteWord(0);
281 }
282 
Blr(REGISTER64 rn)283 void CAArch64Assembler::Blr(REGISTER64 rn)
284 {
285 	uint32 opcode = 0xD63F0000;
286 	opcode |= (rn << 5);
287 	WriteWord(opcode);
288 }
289 
Cbnz(REGISTER32 rt,LABEL label)290 void CAArch64Assembler::Cbnz(REGISTER32 rt, LABEL label)
291 {
292 	CreateCompareBranchLabelReference(label, CONDITION_NE, rt);
293 	WriteWord(0);
294 }
295 
Cbnz(REGISTER64 rt,LABEL label)296 void CAArch64Assembler::Cbnz(REGISTER64 rt, LABEL label)
297 {
298 	CreateCompareBranchLabelReference(label, CONDITION_NE, rt);
299 	WriteWord(0);
300 }
301 
Cbz(REGISTER32 rt,LABEL label)302 void CAArch64Assembler::Cbz(REGISTER32 rt, LABEL label)
303 {
304 	CreateCompareBranchLabelReference(label, CONDITION_EQ, rt);
305 	WriteWord(0);
306 }
307 
Cbz(REGISTER64 rt,LABEL label)308 void CAArch64Assembler::Cbz(REGISTER64 rt, LABEL label)
309 {
310 	CreateCompareBranchLabelReference(label, CONDITION_EQ, rt);
311 	WriteWord(0);
312 }
313 
Clz(REGISTER32 rd,REGISTER32 rn)314 void CAArch64Assembler::Clz(REGISTER32 rd, REGISTER32 rn)
315 {
316 	uint32 opcode = 0x5AC01000;
317 	opcode |= (rd << 0);
318 	opcode |= (rn << 5);
319 	WriteWord(opcode);
320 }
321 
Cmeq_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)322 void CAArch64Assembler::Cmeq_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
323 {
324 	uint32 opcode = 0x6E208C00;
325 	opcode |= (rd <<  0);
326 	opcode |= (rn <<  5);
327 	opcode |= (rm << 16);
328 	WriteWord(opcode);
329 }
330 
Cmeq_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)331 void CAArch64Assembler::Cmeq_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
332 {
333 	uint32 opcode = 0x6E608C00;
334 	opcode |= (rd <<  0);
335 	opcode |= (rn <<  5);
336 	opcode |= (rm << 16);
337 	WriteWord(opcode);
338 }
339 
Cmeq_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)340 void CAArch64Assembler::Cmeq_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
341 {
342 	uint32 opcode = 0x6EA08C00;
343 	opcode |= (rd <<  0);
344 	opcode |= (rn <<  5);
345 	opcode |= (rm << 16);
346 	WriteWord(opcode);
347 }
348 
Cmgt_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)349 void CAArch64Assembler::Cmgt_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
350 {
351 	uint32 opcode = 0x4E203400;
352 	opcode |= (rd <<  0);
353 	opcode |= (rn <<  5);
354 	opcode |= (rm << 16);
355 	WriteWord(opcode);
356 }
357 
Cmgt_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)358 void CAArch64Assembler::Cmgt_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
359 {
360 	uint32 opcode = 0x4E603400;
361 	opcode |= (rd <<  0);
362 	opcode |= (rn <<  5);
363 	opcode |= (rm << 16);
364 	WriteWord(opcode);
365 }
366 
Cmgt_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)367 void CAArch64Assembler::Cmgt_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
368 {
369 	uint32 opcode = 0x4EA03400;
370 	opcode |= (rd <<  0);
371 	opcode |= (rn <<  5);
372 	opcode |= (rm << 16);
373 	WriteWord(opcode);
374 }
375 
Cmltz_4s(REGISTERMD rd,REGISTERMD rn)376 void CAArch64Assembler::Cmltz_4s(REGISTERMD rd, REGISTERMD rn)
377 {
378 	uint32 opcode = 0x4EA0A800;
379 	opcode |= (rd <<  0);
380 	opcode |= (rn <<  5);
381 	WriteWord(opcode);
382 }
383 
Cmn(REGISTER32 rn,uint16 imm,ADDSUB_IMM_SHIFT_TYPE shift)384 void CAArch64Assembler::Cmn(REGISTER32 rn, uint16 imm, ADDSUB_IMM_SHIFT_TYPE shift)
385 {
386 	WriteAddSubOpImm(0x31000000, shift, imm, rn, wZR);
387 }
388 
Cmn(REGISTER64 rn,uint16 imm,ADDSUB_IMM_SHIFT_TYPE shift)389 void CAArch64Assembler::Cmn(REGISTER64 rn, uint16 imm, ADDSUB_IMM_SHIFT_TYPE shift)
390 {
391 	WriteAddSubOpImm(0xB1000000, shift, imm, rn, wZR);
392 }
393 
Cmp(REGISTER32 rn,REGISTER32 rm)394 void CAArch64Assembler::Cmp(REGISTER32 rn, REGISTER32 rm)
395 {
396 	uint32 opcode = 0x6B000000;
397 	opcode |= (wZR << 0);
398 	opcode |= (rn  << 5);
399 	opcode |= (rm  << 16);
400 	WriteWord(opcode);
401 }
402 
Cmp(REGISTER64 rn,REGISTER64 rm)403 void CAArch64Assembler::Cmp(REGISTER64 rn, REGISTER64 rm)
404 {
405 	uint32 opcode = 0xEB000000;
406 	opcode |= (wZR << 0);
407 	opcode |= (rn  << 5);
408 	opcode |= (rm  << 16);
409 	WriteWord(opcode);
410 }
411 
Cmp(REGISTER32 rn,uint16 imm,ADDSUB_IMM_SHIFT_TYPE shift)412 void CAArch64Assembler::Cmp(REGISTER32 rn, uint16 imm, ADDSUB_IMM_SHIFT_TYPE shift)
413 {
414 	WriteAddSubOpImm(0x71000000, shift, imm, rn, wZR);
415 }
416 
Cmp(REGISTER64 rn,uint16 imm,ADDSUB_IMM_SHIFT_TYPE shift)417 void CAArch64Assembler::Cmp(REGISTER64 rn, uint16 imm, ADDSUB_IMM_SHIFT_TYPE shift)
418 {
419 	WriteAddSubOpImm(0xF1000000, shift, imm, rn, wZR);
420 }
421 
Cset(REGISTER32 rd,CONDITION condition)422 void CAArch64Assembler::Cset(REGISTER32 rd, CONDITION condition)
423 {
424 	uint32 opcode = 0x1A800400;
425 	opcode |= (rd  << 0);
426 	opcode |= (wZR << 5);
427 	opcode |= ((condition ^ 1) << 12);	//Inverting lsb inverts condition
428 	opcode |= (wZR << 16);
429 	WriteWord(opcode);
430 }
431 
Dup_4s(REGISTERMD rd,REGISTER32 rn)432 void CAArch64Assembler::Dup_4s(REGISTERMD rd, REGISTER32 rn)
433 {
434 	uint32 opcode = 0x4E040C00;
435 	opcode |= (rd <<  0);
436 	opcode |= (rn <<  5);
437 	WriteWord(opcode);
438 }
439 
Eor(REGISTER32 rd,REGISTER32 rn,REGISTER32 rm)440 void CAArch64Assembler::Eor(REGISTER32 rd, REGISTER32 rn, REGISTER32 rm)
441 {
442 	uint32 opcode = 0x4A000000;
443 	opcode |= (rd <<  0);
444 	opcode |= (rn <<  5);
445 	opcode |= (rm << 16);
446 	WriteWord(opcode);
447 }
448 
Eor(REGISTER32 rd,REGISTER32 rn,uint8 n,uint8 immr,uint8 imms)449 void CAArch64Assembler::Eor(REGISTER32 rd, REGISTER32 rn, uint8 n, uint8 immr, uint8 imms)
450 {
451 	WriteLogicalOpImm(0x52000000, n, immr, imms, rn, rd);
452 }
453 
Eor_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)454 void CAArch64Assembler::Eor_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
455 {
456 	uint32 opcode = 0x6E201C00;
457 	opcode |= (rd <<  0);
458 	opcode |= (rn <<  5);
459 	opcode |= (rm << 16);
460 	WriteWord(opcode);
461 }
462 
Fabs_1s(REGISTERMD rd,REGISTERMD rn)463 void CAArch64Assembler::Fabs_1s(REGISTERMD rd, REGISTERMD rn)
464 {
465 	uint32 opcode = 0x1E20C000;
466 	opcode |= (rd <<  0);
467 	opcode |= (rn <<  5);
468 	WriteWord(opcode);
469 }
470 
Fabs_4s(REGISTERMD rd,REGISTERMD rn)471 void CAArch64Assembler::Fabs_4s(REGISTERMD rd, REGISTERMD rn)
472 {
473 	uint32 opcode = 0x4EA0F800;
474 	opcode |= (rd <<  0);
475 	opcode |= (rn <<  5);
476 	WriteWord(opcode);
477 }
478 
Fadd_1s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)479 void CAArch64Assembler::Fadd_1s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
480 {
481 	uint32 opcode = 0x1E202800;
482 	opcode |= (rd <<  0);
483 	opcode |= (rn <<  5);
484 	opcode |= (rm << 16);
485 	WriteWord(opcode);
486 }
487 
Fadd_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)488 void CAArch64Assembler::Fadd_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
489 {
490 	uint32 opcode = 0x4E20D400;
491 	opcode |= (rd <<  0);
492 	opcode |= (rn <<  5);
493 	opcode |= (rm << 16);
494 	WriteWord(opcode);
495 }
496 
Fcmeqz_4s(REGISTERMD rd,REGISTERMD rn)497 void CAArch64Assembler::Fcmeqz_4s(REGISTERMD rd, REGISTERMD rn)
498 {
499 	uint32 opcode = 0x4EA0D800;
500 	opcode |= (rd <<  0);
501 	opcode |= (rn <<  5);
502 	WriteWord(opcode);
503 }
504 
Fcmge_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)505 void CAArch64Assembler::Fcmge_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
506 {
507 	uint32 opcode = 0x6E20E400;
508 	opcode |= (rd <<  0);
509 	opcode |= (rn <<  5);
510 	opcode |= (rm << 16);
511 	WriteWord(opcode);
512 }
513 
Fcmgt_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)514 void CAArch64Assembler::Fcmgt_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
515 {
516 	uint32 opcode = 0x6EA0E400;
517 	opcode |= (rd <<  0);
518 	opcode |= (rn <<  5);
519 	opcode |= (rm << 16);
520 	WriteWord(opcode);
521 }
522 
Fcmltz_4s(REGISTERMD rd,REGISTERMD rn)523 void CAArch64Assembler::Fcmltz_4s(REGISTERMD rd, REGISTERMD rn)
524 {
525 	uint32 opcode = 0x4EA0E800;
526 	opcode |= (rd <<  0);
527 	opcode |= (rn <<  5);
528 	WriteWord(opcode);
529 }
530 
Fcmp_1s(REGISTERMD rn,REGISTERMD rm)531 void CAArch64Assembler::Fcmp_1s(REGISTERMD rn, REGISTERMD rm)
532 {
533 	uint32 opcode = 0x1E202000;
534 	opcode |= (rn <<  5);
535 	opcode |= (rm << 16);
536 	WriteWord(opcode);
537 }
538 
Fcvtzs_1s(REGISTERMD rd,REGISTERMD rn)539 void CAArch64Assembler::Fcvtzs_1s(REGISTERMD rd, REGISTERMD rn)
540 {
541 	uint32 opcode = 0x5EA1B800;
542 	opcode |= (rd <<  0);
543 	opcode |= (rn <<  5);
544 	WriteWord(opcode);
545 }
546 
Fcvtzs_4s(REGISTERMD rd,REGISTERMD rn)547 void CAArch64Assembler::Fcvtzs_4s(REGISTERMD rd, REGISTERMD rn)
548 {
549 	uint32 opcode = 0x4EA1B800;
550 	opcode |= (rd <<  0);
551 	opcode |= (rn <<  5);
552 	WriteWord(opcode);
553 }
554 
Fdiv_1s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)555 void CAArch64Assembler::Fdiv_1s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
556 {
557 	uint32 opcode = 0x1E201800;
558 	opcode |= (rd <<  0);
559 	opcode |= (rn <<  5);
560 	opcode |= (rm << 16);
561 	WriteWord(opcode);
562 }
563 
Fdiv_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)564 void CAArch64Assembler::Fdiv_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
565 {
566 	uint32 opcode = 0x6E20FC00;
567 	opcode |= (rd <<  0);
568 	opcode |= (rn <<  5);
569 	opcode |= (rm << 16);
570 	WriteWord(opcode);
571 }
572 
Fmov_1s(REGISTERMD rd,uint8 imm)573 void CAArch64Assembler::Fmov_1s(REGISTERMD rd, uint8 imm)
574 {
575 	uint32 opcode = 0x1E201000;
576 	opcode |= (rd <<   0);
577 	opcode |= (imm << 13);
578 	WriteWord(opcode);
579 }
580 
Fmul_1s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)581 void CAArch64Assembler::Fmul_1s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
582 {
583 	uint32 opcode = 0x1E200800;
584 	opcode |= (rd <<  0);
585 	opcode |= (rn <<  5);
586 	opcode |= (rm << 16);
587 	WriteWord(opcode);
588 }
589 
Fmul_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)590 void CAArch64Assembler::Fmul_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
591 {
592 	uint32 opcode = 0x6E20DC00;
593 	opcode |= (rd <<  0);
594 	opcode |= (rn <<  5);
595 	opcode |= (rm << 16);
596 	WriteWord(opcode);
597 }
598 
Fmax_1s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)599 void CAArch64Assembler::Fmax_1s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
600 {
601 	uint32 opcode = 0x1E204800;
602 	opcode |= (rd <<  0);
603 	opcode |= (rn <<  5);
604 	opcode |= (rm << 16);
605 	WriteWord(opcode);
606 }
607 
Fmax_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)608 void CAArch64Assembler::Fmax_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
609 {
610 	uint32 opcode = 0x4E20F400;
611 	opcode |= (rd <<  0);
612 	opcode |= (rn <<  5);
613 	opcode |= (rm << 16);
614 	WriteWord(opcode);
615 }
616 
Fneg_1s(REGISTERMD rd,REGISTERMD rn)617 void CAArch64Assembler::Fneg_1s(REGISTERMD rd, REGISTERMD rn)
618 {
619 	uint32 opcode = 0x1E214000;
620 	opcode |= (rd <<  0);
621 	opcode |= (rn <<  5);
622 	WriteWord(opcode);
623 }
624 
Fmin_1s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)625 void CAArch64Assembler::Fmin_1s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
626 {
627 	uint32 opcode = 0x1E205800;
628 	opcode |= (rd <<  0);
629 	opcode |= (rn <<  5);
630 	opcode |= (rm << 16);
631 	WriteWord(opcode);
632 }
633 
Fmin_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)634 void CAArch64Assembler::Fmin_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
635 {
636 	uint32 opcode = 0x4EA0F400;
637 	opcode |= (rd <<  0);
638 	opcode |= (rn <<  5);
639 	opcode |= (rm << 16);
640 	WriteWord(opcode);
641 }
642 
Fsqrt_1s(REGISTERMD rd,REGISTERMD rn)643 void CAArch64Assembler::Fsqrt_1s(REGISTERMD rd, REGISTERMD rn)
644 {
645 	uint32 opcode = 0x1E21C000;
646 	opcode |= (rd <<  0);
647 	opcode |= (rn <<  5);
648 	WriteWord(opcode);
649 }
650 
Fsub_1s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)651 void CAArch64Assembler::Fsub_1s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
652 {
653 	uint32 opcode = 0x1E203800;
654 	opcode |= (rd <<  0);
655 	opcode |= (rn <<  5);
656 	opcode |= (rm << 16);
657 	WriteWord(opcode);
658 }
659 
Fsub_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)660 void CAArch64Assembler::Fsub_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
661 {
662 	uint32 opcode = 0x4EA0D400;
663 	opcode |= (rd <<  0);
664 	opcode |= (rn <<  5);
665 	opcode |= (rm << 16);
666 	WriteWord(opcode);
667 }
668 
Ins_1s(REGISTERMD rd,uint8 index1,REGISTERMD rn,uint8 index2)669 void CAArch64Assembler::Ins_1s(REGISTERMD rd, uint8 index1, REGISTERMD rn, uint8 index2)
670 {
671 	assert(index1 < 4);
672 	assert(index2 < 4);
673 	index1 &= 0x3;
674 	index2 &= 0x3;
675 	uint32 opcode = 0x6E040400;
676 	opcode |= (rd <<  0);
677 	opcode |= (rn <<  5);
678 	opcode |= (index2 << 13);
679 	opcode |= (index1 << 19);
680 	WriteWord(opcode);
681 }
682 
Ins_1d(REGISTERMD rd,uint8 index,REGISTER64 rn)683 void CAArch64Assembler::Ins_1d(REGISTERMD rd, uint8 index, REGISTER64 rn)
684 {
685 	assert(index < 2);
686 	index &= 0x1;
687 	uint8 imm5 = (index << 4) | 0x8;
688 	uint32 opcode = 0x4E001C00;
689 	opcode |= (rd << 0);
690 	opcode |= (rn << 5);
691 	opcode |= (imm5 << 16);
692 	WriteWord(opcode);
693 }
694 
Ld1_4s(REGISTERMD rt,REGISTER64 rn)695 void CAArch64Assembler::Ld1_4s(REGISTERMD rt, REGISTER64 rn)
696 {
697 	uint32 opcode = 0x4C407800;
698 	opcode |= (rt <<  0);
699 	opcode |= (rn <<  5);
700 	WriteWord(opcode);
701 }
702 
Ldp_PostIdx(REGISTER64 rt,REGISTER64 rt2,REGISTER64 rn,int32 offset)703 void CAArch64Assembler::Ldp_PostIdx(REGISTER64 rt, REGISTER64 rt2, REGISTER64 rn, int32 offset)
704 {
705 	assert((offset & 0x07) == 0);
706 	int32 scaledOffset = offset / 8;
707 	assert(scaledOffset >= -64 && scaledOffset <= 63);
708 	uint32 opcode = 0xA8C00000;
709 	opcode |= (rt  <<  0);
710 	opcode |= (rn  <<  5);
711 	opcode |= (rt2 << 10);
712 	opcode |= ((scaledOffset & 0x7F) << 15);
713 	WriteWord(opcode);
714 }
715 
Ldr(REGISTER32 rt,REGISTER64 rn,uint32 offset)716 void CAArch64Assembler::Ldr(REGISTER32 rt, REGISTER64 rn, uint32 offset)
717 {
718 	assert((offset & 0x03) == 0);
719 	uint32 scaledOffset = offset / 4;
720 	assert(scaledOffset < 0x1000);
721 	WriteLoadStoreOpImm(0xB9400000, scaledOffset, rn, rt);
722 }
723 
Ldr(REGISTER32 rt,REGISTER64 rn,REGISTER64 rm,bool scaled)724 void CAArch64Assembler::Ldr(REGISTER32 rt, REGISTER64 rn, REGISTER64 rm, bool scaled)
725 {
726 	uint32 opcode = 0xB8606800;
727 	opcode |= (rt << 0);
728 	opcode |= (rn << 5);
729 	opcode |= scaled ? (1 << 12) : 0;
730 	opcode |= (rm << 16);
731 	WriteWord(opcode);
732 }
733 
Ldr(REGISTER64 rt,REGISTER64 rn,uint32 offset)734 void CAArch64Assembler::Ldr(REGISTER64 rt, REGISTER64 rn, uint32 offset)
735 {
736 	assert((offset & 0x07) == 0);
737 	uint32 scaledOffset = offset / 8;
738 	assert(scaledOffset < 0x1000);
739 	WriteLoadStoreOpImm(0xF9400000, scaledOffset, rn, rt);
740 }
741 
Ldrb(REGISTER32 rt,REGISTER64 rn,uint32 offset)742 void CAArch64Assembler::Ldrb(REGISTER32 rt, REGISTER64 rn, uint32 offset)
743 {
744 	uint32 scaledOffset = offset;
745 	assert(scaledOffset < 0x1000);
746 	WriteLoadStoreOpImm(0x39400000, scaledOffset, rn, rt);
747 }
748 
Ldrh(REGISTER32 rt,REGISTER64 rn,uint32 offset)749 void CAArch64Assembler::Ldrh(REGISTER32 rt, REGISTER64 rn, uint32 offset)
750 {
751 	assert((offset & 0x01) == 0);
752 	uint32 scaledOffset = offset / 2;
753 	assert(scaledOffset < 0x1000);
754 	WriteLoadStoreOpImm(0x79400000, scaledOffset, rn, rt);
755 }
756 
Ldr_Pc(REGISTER64 rt,uint32 offset)757 void CAArch64Assembler::Ldr_Pc(REGISTER64 rt, uint32 offset)
758 {
759 	assert((offset & 0x03) == 0);
760 	uint32 scaledOffset = offset / 4;
761 	assert(scaledOffset < 0x40000);
762 	uint32 opcode = 0x58000000;
763 	opcode |= (rt <<  0);
764 	opcode |= scaledOffset << 5;
765 	WriteWord(opcode);
766 }
767 
Ldr_Pc(REGISTERMD rt,const LITERAL128 & literal)768 void CAArch64Assembler::Ldr_Pc(REGISTERMD rt, const LITERAL128& literal)
769 {
770 	LITERAL128REF literalRef;
771 	literalRef.offset = static_cast<size_t>(m_stream->Tell());
772 	literalRef.value = literal;
773 	literalRef.rt = rt;
774 	m_literal128Refs.push_back(literalRef);
775 	WriteWord(0);
776 }
777 
Ldr_1s(REGISTERMD rt,REGISTER64 rn,uint32 offset)778 void CAArch64Assembler::Ldr_1s(REGISTERMD rt, REGISTER64 rn, uint32 offset)
779 {
780 	assert((offset & 0x03) == 0);
781 	uint32 scaledOffset = offset / 4;
782 	assert(scaledOffset < 0x1000);
783 	WriteLoadStoreOpImm(0xBD400000, scaledOffset, rn, rt);
784 }
785 
Ldr_1q(REGISTERMD rt,REGISTER64 rn,uint32 offset)786 void CAArch64Assembler::Ldr_1q(REGISTERMD rt, REGISTER64 rn, uint32 offset)
787 {
788 	assert((offset & 0x0F) == 0);
789 	uint32 scaledOffset = offset / 0x10;
790 	assert(scaledOffset < 0x1000);
791 	WriteLoadStoreOpImm(0x3DC00000, scaledOffset, rn, rt);
792 }
793 
Lsl(REGISTER32 rd,REGISTER32 rn,uint8 sa)794 void CAArch64Assembler::Lsl(REGISTER32 rd, REGISTER32 rn, uint8 sa)
795 {
796 	uint32 imms = 0x1F - (sa & 0x1F);
797 	uint32 immr = -sa & 0x1F;
798 	WriteLogicalOpImm(0x53000000, 0, immr, imms, rn, rd);
799 }
800 
Lsl(REGISTER64 rd,REGISTER64 rn,uint8 sa)801 void CAArch64Assembler::Lsl(REGISTER64 rd, REGISTER64 rn, uint8 sa)
802 {
803 	uint32 imms = 0x3F - (sa & 0x3F);
804 	uint32 immr = -sa & 0x3F;
805 	WriteLogicalOpImm(0xD3400000, 0, immr, imms, rn, rd);
806 }
807 
Lslv(REGISTER32 rd,REGISTER32 rn,REGISTER32 rm)808 void CAArch64Assembler::Lslv(REGISTER32 rd, REGISTER32 rn, REGISTER32 rm)
809 {
810 	WriteDataProcOpReg2(0x1AC02000, rm, rn, rd);
811 }
812 
Lslv(REGISTER64 rd,REGISTER64 rn,REGISTER64 rm)813 void CAArch64Assembler::Lslv(REGISTER64 rd, REGISTER64 rn, REGISTER64 rm)
814 {
815 	WriteDataProcOpReg2(0x9AC02000, rm, rn, rd);
816 }
817 
Lsr(REGISTER32 rd,REGISTER32 rn,uint8 sa)818 void CAArch64Assembler::Lsr(REGISTER32 rd, REGISTER32 rn, uint8 sa)
819 {
820 	uint32 imms = 0x1F;
821 	uint32 immr = sa & 0x1F;
822 	WriteLogicalOpImm(0x53000000, 0, immr, imms, rn, rd);
823 }
824 
Lsr(REGISTER64 rd,REGISTER64 rn,uint8 sa)825 void CAArch64Assembler::Lsr(REGISTER64 rd, REGISTER64 rn, uint8 sa)
826 {
827 	uint32 imms = 0x3F;
828 	uint32 immr = sa & 0x3F;
829 	WriteLogicalOpImm(0xD3400000, 0, immr, imms, rn, rd);
830 }
831 
Lsrv(REGISTER32 rd,REGISTER32 rn,REGISTER32 rm)832 void CAArch64Assembler::Lsrv(REGISTER32 rd, REGISTER32 rn, REGISTER32 rm)
833 {
834 	WriteDataProcOpReg2(0x1AC02400, rm, rn, rd);
835 }
836 
Lsrv(REGISTER64 rd,REGISTER64 rn,REGISTER64 rm)837 void CAArch64Assembler::Lsrv(REGISTER64 rd, REGISTER64 rn, REGISTER64 rm)
838 {
839 	WriteDataProcOpReg2(0x9AC02400, rm, rn, rd);
840 }
841 
Mov(REGISTER32 rd,REGISTER32 rm)842 void CAArch64Assembler::Mov(REGISTER32 rd, REGISTER32 rm)
843 {
844 	uint32 opcode = 0x2A0003E0;
845 	opcode |= (rd <<  0);
846 	opcode |= (rm << 16);
847 	WriteWord(opcode);
848 }
849 
Mov(REGISTER64 rd,REGISTER64 rm)850 void CAArch64Assembler::Mov(REGISTER64 rd, REGISTER64 rm)
851 {
852 	uint32 opcode = 0xAA0003E0;
853 	opcode |= (rd <<  0);
854 	opcode |= (rm << 16);
855 	WriteWord(opcode);
856 }
857 
Mov(REGISTERMD rd,REGISTERMD rn)858 void CAArch64Assembler::Mov(REGISTERMD rd, REGISTERMD rn)
859 {
860 	Orr_16b(rd, rn, rn);
861 }
862 
Mov_Sp(REGISTER64 rd,REGISTER64 rn)863 void CAArch64Assembler::Mov_Sp(REGISTER64 rd, REGISTER64 rn)
864 {
865 	uint32 opcode = 0x91000000;
866 	opcode |= (rd << 0);
867 	opcode |= (rn << 5);
868 	WriteWord(opcode);
869 }
870 
Movn(REGISTER32 rd,uint16 imm,uint8 pos)871 void CAArch64Assembler::Movn(REGISTER32 rd, uint16 imm, uint8 pos)
872 {
873 	assert(pos < 2);
874 	WriteMoveWideOpImm(0x12800000, pos, imm, rd);
875 }
876 
Movk(REGISTER32 rd,uint16 imm,uint8 pos)877 void CAArch64Assembler::Movk(REGISTER32 rd, uint16 imm, uint8 pos)
878 {
879 	assert(pos < 2);
880 	WriteMoveWideOpImm(0x72800000, pos, imm, rd);
881 }
882 
Movk(REGISTER64 rd,uint16 imm,uint8 pos)883 void CAArch64Assembler::Movk(REGISTER64 rd, uint16 imm, uint8 pos)
884 {
885 	assert(pos < 4);
886 	WriteMoveWideOpImm(0xF2800000, pos, imm, rd);
887 }
888 
Movz(REGISTER32 rd,uint16 imm,uint8 pos)889 void CAArch64Assembler::Movz(REGISTER32 rd, uint16 imm, uint8 pos)
890 {
891 	assert(pos < 2);
892 	WriteMoveWideOpImm(0x52800000, pos, imm, rd);
893 }
894 
Movz(REGISTER64 rd,uint16 imm,uint8 pos)895 void CAArch64Assembler::Movz(REGISTER64 rd, uint16 imm, uint8 pos)
896 {
897 	assert(pos < 4);
898 	WriteMoveWideOpImm(0xD2800000, pos, imm, rd);
899 }
900 
Msub(REGISTER32 rd,REGISTER32 rn,REGISTER32 rm,REGISTER32 ra)901 void CAArch64Assembler::Msub(REGISTER32 rd, REGISTER32 rn, REGISTER32 rm, REGISTER32 ra)
902 {
903 	uint32 opcode = 0x1B008000;
904 	opcode |= (rd << 0);
905 	opcode |= (rn << 5);
906 	opcode |= (ra << 10);
907 	opcode |= (rm << 16);
908 	WriteWord(opcode);
909 }
910 
Mvn(REGISTER32 rd,REGISTER32 rm)911 void CAArch64Assembler::Mvn(REGISTER32 rd, REGISTER32 rm)
912 {
913 	uint32 opcode = 0x2A200000;
914 	opcode |= (rd  << 0);
915 	opcode |= (wZR << 5);
916 	opcode |= (rm  << 16);
917 	WriteWord(opcode);
918 }
919 
Mvn_16b(REGISTERMD rd,REGISTERMD rn)920 void CAArch64Assembler::Mvn_16b(REGISTERMD rd, REGISTERMD rn)
921 {
922 	uint32 opcode = 0x6E205800;
923 	opcode |= (rd <<  0);
924 	opcode |= (rn <<  5);
925 	WriteWord(opcode);
926 }
927 
Orn_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)928 void CAArch64Assembler::Orn_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
929 {
930 	uint32 opcode = 0x4EE01C00;
931 	opcode |= (rd <<  0);
932 	opcode |= (rn <<  5);
933 	opcode |= (rm << 16);
934 	WriteWord(opcode);
935 }
936 
Orr(REGISTER32 rd,REGISTER32 rn,REGISTER32 rm)937 void CAArch64Assembler::Orr(REGISTER32 rd, REGISTER32 rn, REGISTER32 rm)
938 {
939 	uint32 opcode = 0x2A000000;
940 	opcode |= (rd <<  0);
941 	opcode |= (rn <<  5);
942 	opcode |= (rm << 16);
943 	WriteWord(opcode);
944 }
945 
Orr(REGISTER32 rd,REGISTER32 rn,uint8 n,uint8 immr,uint8 imms)946 void CAArch64Assembler::Orr(REGISTER32 rd, REGISTER32 rn, uint8 n, uint8 immr, uint8 imms)
947 {
948 	WriteLogicalOpImm(0x32000000, n, immr, imms, rn, rd);
949 }
950 
Orr_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)951 void CAArch64Assembler::Orr_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
952 {
953 	uint32 opcode = 0x4EA01C00;
954 	opcode |= (rd <<  0);
955 	opcode |= (rn <<  5);
956 	opcode |= (rm << 16);
957 	WriteWord(opcode);
958 }
959 
Ret(REGISTER64 rn)960 void CAArch64Assembler::Ret(REGISTER64 rn)
961 {
962 	uint32 opcode = 0xD65F0000;
963 	opcode |= (rn << 5);
964 	WriteWord(opcode);
965 }
966 
Scvtf_1s(REGISTERMD rd,REGISTERMD rn)967 void CAArch64Assembler::Scvtf_1s(REGISTERMD rd, REGISTERMD rn)
968 {
969 	uint32 opcode = 0x5E21D800;
970 	opcode |= (rd <<  0);
971 	opcode |= (rn <<  5);
972 	WriteWord(opcode);
973 }
974 
Scvtf_4s(REGISTERMD rd,REGISTERMD rn)975 void CAArch64Assembler::Scvtf_4s(REGISTERMD rd, REGISTERMD rn)
976 {
977 	uint32 opcode = 0x4E21D800;
978 	opcode |= (rd <<  0);
979 	opcode |= (rn <<  5);
980 	WriteWord(opcode);
981 }
982 
Sdiv(REGISTER32 rd,REGISTER32 rn,REGISTER32 rm)983 void CAArch64Assembler::Sdiv(REGISTER32 rd, REGISTER32 rn, REGISTER32 rm)
984 {
985 	uint32 opcode = 0x1AC00C00;
986 	opcode |= (rd <<  0);
987 	opcode |= (rn <<  5);
988 	opcode |= (rm << 16);
989 	WriteWord(opcode);
990 }
991 
Shl_4s(REGISTERMD rd,REGISTERMD rn,uint8 sa)992 void CAArch64Assembler::Shl_4s(REGISTERMD rd, REGISTERMD rn, uint8 sa)
993 {
994 	uint8 immhb = (sa & 0x1F) + 32;
995 	uint32 opcode = 0x4F005400;
996 	opcode |= (rd    <<  0);
997 	opcode |= (rn    <<  5);
998 	opcode |= (immhb << 16);
999 	WriteWord(opcode);
1000 }
1001 
Shl_8h(REGISTERMD rd,REGISTERMD rn,uint8 sa)1002 void CAArch64Assembler::Shl_8h(REGISTERMD rd, REGISTERMD rn, uint8 sa)
1003 {
1004 	uint8 immhb = (sa & 0xF) + 16;
1005 	uint32 opcode = 0x4F005400;
1006 	opcode |= (rd    <<  0);
1007 	opcode |= (rn    <<  5);
1008 	opcode |= (immhb << 16);
1009 	WriteWord(opcode);
1010 }
1011 
Smax_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1012 void CAArch64Assembler::Smax_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1013 {
1014 	uint32 opcode = 0x4EA06400;
1015 	opcode |= (rd  <<  0);
1016 	opcode |= (rn  <<  5);
1017 	opcode |= (rm  << 16);
1018 	WriteWord(opcode);
1019 }
1020 
Smax_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1021 void CAArch64Assembler::Smax_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1022 {
1023 	uint32 opcode = 0x4E606400;
1024 	opcode |= (rd  <<  0);
1025 	opcode |= (rn  <<  5);
1026 	opcode |= (rm  << 16);
1027 	WriteWord(opcode);
1028 }
1029 
Smin_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1030 void CAArch64Assembler::Smin_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1031 {
1032 	uint32 opcode = 0x4EA06C00;
1033 	opcode |= (rd  <<  0);
1034 	opcode |= (rn  <<  5);
1035 	opcode |= (rm  << 16);
1036 	WriteWord(opcode);
1037 }
1038 
Smin_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1039 void CAArch64Assembler::Smin_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1040 {
1041 	uint32 opcode = 0x4E606C00;
1042 	opcode |= (rd  <<  0);
1043 	opcode |= (rn  <<  5);
1044 	opcode |= (rm  << 16);
1045 	WriteWord(opcode);
1046 }
1047 
Smull(REGISTER64 rd,REGISTER32 rn,REGISTER32 rm)1048 void CAArch64Assembler::Smull(REGISTER64 rd, REGISTER32 rn, REGISTER32 rm)
1049 {
1050 	uint32 opcode = 0x9B200000;
1051 	opcode |= (rd  <<  0);
1052 	opcode |= (rn  <<  5);
1053 	opcode |= (wZR << 10);
1054 	opcode |= (rm  << 16);
1055 	WriteWord(opcode);
1056 }
1057 
Sshr_4s(REGISTERMD rd,REGISTERMD rn,uint8 sa)1058 void CAArch64Assembler::Sshr_4s(REGISTERMD rd, REGISTERMD rn, uint8 sa)
1059 {
1060 	uint8 immhb = (32 * 2) - (sa & 0x1F);
1061 	uint32 opcode = 0x4F000400;
1062 	opcode |= (rd    <<  0);
1063 	opcode |= (rn    <<  5);
1064 	opcode |= (immhb << 16);
1065 	WriteWord(opcode);
1066 }
1067 
Sshr_8h(REGISTERMD rd,REGISTERMD rn,uint8 sa)1068 void CAArch64Assembler::Sshr_8h(REGISTERMD rd, REGISTERMD rn, uint8 sa)
1069 {
1070 	uint8 immhb = (16 * 2) - (sa & 0xF);
1071 	uint32 opcode = 0x4F000400;
1072 	opcode |= (rd    <<  0);
1073 	opcode |= (rn    <<  5);
1074 	opcode |= (immhb << 16);
1075 	WriteWord(opcode);
1076 }
1077 
Sqadd_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1078 void CAArch64Assembler::Sqadd_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1079 {
1080 	uint32 opcode = 0x4EA00C00;
1081 	opcode |= (rd  <<  0);
1082 	opcode |= (rn  <<  5);
1083 	opcode |= (rm  << 16);
1084 	WriteWord(opcode);
1085 }
1086 
Sqadd_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1087 void CAArch64Assembler::Sqadd_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1088 {
1089 	uint32 opcode = 0x4E600C00;
1090 	opcode |= (rd  <<  0);
1091 	opcode |= (rn  <<  5);
1092 	opcode |= (rm  << 16);
1093 	WriteWord(opcode);
1094 }
1095 
Sqadd_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1096 void CAArch64Assembler::Sqadd_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1097 {
1098 	uint32 opcode = 0x4E200C00;
1099 	opcode |= (rd <<  0);
1100 	opcode |= (rn <<  5);
1101 	opcode |= (rm << 16);
1102 	WriteWord(opcode);
1103 }
1104 
Sqsub_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1105 void CAArch64Assembler::Sqsub_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1106 {
1107 	uint32 opcode = 0x4EA02C00;
1108 	opcode |= (rd  <<  0);
1109 	opcode |= (rn  <<  5);
1110 	opcode |= (rm  << 16);
1111 	WriteWord(opcode);
1112 }
1113 
Sqsub_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1114 void CAArch64Assembler::Sqsub_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1115 {
1116 	uint32 opcode = 0x4E602C00;
1117 	opcode |= (rd  <<  0);
1118 	opcode |= (rn  <<  5);
1119 	opcode |= (rm  << 16);
1120 	WriteWord(opcode);
1121 }
1122 
St1_4s(REGISTERMD rt,REGISTER64 rn)1123 void CAArch64Assembler::St1_4s(REGISTERMD rt, REGISTER64 rn)
1124 {
1125 	uint32 opcode = 0x4C007800;
1126 	opcode |= (rt <<  0);
1127 	opcode |= (rn <<  5);
1128 	WriteWord(opcode);
1129 }
1130 
Stp(REGISTER32 rt,REGISTER32 rt2,REGISTER64 rn,int32 offset)1131 void CAArch64Assembler::Stp(REGISTER32 rt, REGISTER32 rt2, REGISTER64 rn, int32 offset)
1132 {
1133 	assert((offset & 0x03) == 0);
1134 	int32 scaledOffset = offset / 4;
1135 	assert(scaledOffset >= -64 && scaledOffset <= 63);
1136 	uint32 opcode = 0x29000000;
1137 	opcode |= (rt  <<  0);
1138 	opcode |= (rn  <<  5);
1139 	opcode |= (rt2 << 10);
1140 	opcode |= ((scaledOffset & 0x7F) << 15);
1141 	WriteWord(opcode);
1142 }
1143 
Stp_PreIdx(REGISTER64 rt,REGISTER64 rt2,REGISTER64 rn,int32 offset)1144 void CAArch64Assembler::Stp_PreIdx(REGISTER64 rt, REGISTER64 rt2, REGISTER64 rn, int32 offset)
1145 {
1146 	assert((offset & 0x07) == 0);
1147 	int32 scaledOffset = offset / 8;
1148 	assert(scaledOffset >= -64 && scaledOffset <= 63);
1149 	uint32 opcode = 0xA9800000;
1150 	opcode |= (rt  <<  0);
1151 	opcode |= (rn  <<  5);
1152 	opcode |= (rt2 << 10);
1153 	opcode |= ((scaledOffset & 0x7F) << 15);
1154 	WriteWord(opcode);
1155 }
1156 
Str(REGISTER32 rt,REGISTER64 rn,uint32 offset)1157 void CAArch64Assembler::Str(REGISTER32 rt, REGISTER64 rn, uint32 offset)
1158 {
1159 	assert((offset & 0x03) == 0);
1160 	uint32 scaledOffset = offset / 4;
1161 	assert(scaledOffset < 0x1000);
1162 	WriteLoadStoreOpImm(0xB9000000, scaledOffset, rn, rt);
1163 }
1164 
Str(REGISTER32 rt,REGISTER64 rn,REGISTER64 rm,bool scaled)1165 void CAArch64Assembler::Str(REGISTER32 rt, REGISTER64 rn, REGISTER64 rm, bool scaled)
1166 {
1167 	uint32 opcode = 0xB8206800;
1168 	opcode |= (rt << 0);
1169 	opcode |= (rn << 5);
1170 	opcode |= scaled ? (1 << 12) : 0;
1171 	opcode |= (rm << 16);
1172 	WriteWord(opcode);
1173 }
1174 
Str(REGISTER64 rt,REGISTER64 rn,uint32 offset)1175 void CAArch64Assembler::Str(REGISTER64 rt, REGISTER64 rn, uint32 offset)
1176 {
1177 	assert((offset & 0x07) == 0);
1178 	uint32 scaledOffset = offset / 8;
1179 	assert(scaledOffset < 0x1000);
1180 	WriteLoadStoreOpImm(0xF9000000, scaledOffset, rn, rt);
1181 }
1182 
Strb(REGISTER32 rt,REGISTER64 rn,uint32 offset)1183 void CAArch64Assembler::Strb(REGISTER32 rt, REGISTER64 rn, uint32 offset)
1184 {
1185 	uint32 scaledOffset = offset;
1186 	assert(scaledOffset < 0x1000);
1187 	WriteLoadStoreOpImm(0x39000000, scaledOffset, rn, rt);
1188 }
1189 
Strh(REGISTER32 rt,REGISTER64 rn,uint32 offset)1190 void CAArch64Assembler::Strh(REGISTER32 rt, REGISTER64 rn, uint32 offset)
1191 {
1192 	assert((offset & 0x01) == 0);
1193 	uint32 scaledOffset = offset / 2;
1194 	assert(scaledOffset < 0x1000);
1195 	WriteLoadStoreOpImm(0x79000000, scaledOffset, rn, rt);
1196 }
1197 
Str_1s(REGISTERMD rt,REGISTER64 rn,uint32 offset)1198 void CAArch64Assembler::Str_1s(REGISTERMD rt, REGISTER64 rn, uint32 offset)
1199 {
1200 	assert((offset & 0x03) == 0);
1201 	uint32 scaledOffset = offset / 4;
1202 	assert(scaledOffset < 0x1000);
1203 	WriteLoadStoreOpImm(0xBD000000, scaledOffset, rn, rt);
1204 }
1205 
Str_1q(REGISTERMD rt,REGISTER64 rn,uint32 offset)1206 void CAArch64Assembler::Str_1q(REGISTERMD rt, REGISTER64 rn, uint32 offset)
1207 {
1208 	assert((offset & 0x0F) == 0);
1209 	uint32 scaledOffset = offset / 0x10;
1210 	assert(scaledOffset < 0x1000);
1211 	WriteLoadStoreOpImm(0x3D800000, scaledOffset, rn, rt);
1212 }
1213 
Sub(REGISTER32 rd,REGISTER32 rn,REGISTER32 rm)1214 void CAArch64Assembler::Sub(REGISTER32 rd, REGISTER32 rn, REGISTER32 rm)
1215 {
1216 	uint32 opcode = 0x4B000000;
1217 	opcode |= (rd << 0);
1218 	opcode |= (rn << 5);
1219 	opcode |= (rm << 16);
1220 	WriteWord(opcode);
1221 }
1222 
Sub(REGISTER64 rd,REGISTER64 rn,REGISTER64 rm)1223 void CAArch64Assembler::Sub(REGISTER64 rd, REGISTER64 rn, REGISTER64 rm)
1224 {
1225 	uint32 opcode = 0xCB000000;
1226 	opcode |= (rd << 0);
1227 	opcode |= (rn << 5);
1228 	opcode |= (rm << 16);
1229 	WriteWord(opcode);
1230 }
1231 
Sub(REGISTER32 rd,REGISTER32 rn,uint16 imm,ADDSUB_IMM_SHIFT_TYPE shift)1232 void CAArch64Assembler::Sub(REGISTER32 rd, REGISTER32 rn, uint16 imm, ADDSUB_IMM_SHIFT_TYPE shift)
1233 {
1234 	WriteAddSubOpImm(0x51000000, shift, imm, rn, rd);
1235 }
1236 
Sub(REGISTER64 rd,REGISTER64 rn,uint16 imm,ADDSUB_IMM_SHIFT_TYPE shift)1237 void CAArch64Assembler::Sub(REGISTER64 rd, REGISTER64 rn, uint16 imm, ADDSUB_IMM_SHIFT_TYPE shift)
1238 {
1239 	WriteAddSubOpImm(0xD1000000, shift, imm, rn, rd);
1240 }
1241 
Sub_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1242 void CAArch64Assembler::Sub_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1243 {
1244 	uint32 opcode = 0x6EA08400;
1245 	opcode |= (rd  <<  0);
1246 	opcode |= (rn  <<  5);
1247 	opcode |= (rm  << 16);
1248 	WriteWord(opcode);
1249 }
1250 
Sub_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1251 void CAArch64Assembler::Sub_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1252 {
1253 	uint32 opcode = 0x6E608400;
1254 	opcode |= (rd  <<  0);
1255 	opcode |= (rn  <<  5);
1256 	opcode |= (rm  << 16);
1257 	WriteWord(opcode);
1258 }
1259 
Sub_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1260 void CAArch64Assembler::Sub_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1261 {
1262 	uint32 opcode = 0x6E208400;
1263 	opcode |= (rd  <<  0);
1264 	opcode |= (rn  <<  5);
1265 	opcode |= (rm  << 16);
1266 	WriteWord(opcode);
1267 }
1268 
Tbl(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1269 void CAArch64Assembler::Tbl(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1270 {
1271 	uint32 opcode = 0x4E002000;
1272 	opcode |= (rd <<  0);
1273 	opcode |= (rn <<  5);
1274 	opcode |= (rm << 16);
1275 	WriteWord(opcode);
1276 }
1277 
Tst(REGISTER32 rn,REGISTER32 rm)1278 void CAArch64Assembler::Tst(REGISTER32 rn, REGISTER32 rm)
1279 {
1280 	uint32 opcode = 0x6A000000;
1281 	opcode |= (wZR << 0);
1282 	opcode |= (rn <<  5);
1283 	opcode |= (rm << 16);
1284 	WriteWord(opcode);
1285 }
1286 
Tst(REGISTER64 rn,REGISTER64 rm)1287 void CAArch64Assembler::Tst(REGISTER64 rn, REGISTER64 rm)
1288 {
1289 	uint32 opcode = 0xEA000000;
1290 	opcode |= (wZR << 0);
1291 	opcode |= (rn <<  5);
1292 	opcode |= (rm << 16);
1293 	WriteWord(opcode);
1294 }
1295 
Uaddlv_16b(REGISTERMD rd,REGISTERMD rn)1296 void CAArch64Assembler::Uaddlv_16b(REGISTERMD rd, REGISTERMD rn)
1297 {
1298 	uint32 opcode = 0x6E303800;
1299 	opcode |= (rd <<  0);
1300 	opcode |= (rn <<  5);
1301 	WriteWord(opcode);
1302 }
1303 
Udiv(REGISTER32 rd,REGISTER32 rn,REGISTER32 rm)1304 void CAArch64Assembler::Udiv(REGISTER32 rd, REGISTER32 rn, REGISTER32 rm)
1305 {
1306 	uint32 opcode = 0x1AC00800;
1307 	opcode |= (rd <<  0);
1308 	opcode |= (rn <<  5);
1309 	opcode |= (rm << 16);
1310 	WriteWord(opcode);
1311 }
1312 
Umov_1s(REGISTER32 rd,REGISTERMD rn,uint8 index)1313 void CAArch64Assembler::Umov_1s(REGISTER32 rd, REGISTERMD rn, uint8 index)
1314 {
1315 	assert(index < 4);
1316 	uint8 imm5 = 0x4 | ((index & 3) << 3);
1317 	uint32 opcode = 0x0E003C00;
1318 	opcode |= (rd   <<  0);
1319 	opcode |= (rn   <<  5);
1320 	opcode |= (imm5 << 16);
1321 	WriteWord(opcode);
1322 }
1323 
Umull(REGISTER64 rd,REGISTER32 rn,REGISTER32 rm)1324 void CAArch64Assembler::Umull(REGISTER64 rd, REGISTER32 rn, REGISTER32 rm)
1325 {
1326 	uint32 opcode = 0x9BA00000;
1327 	opcode |= (rd  <<  0);
1328 	opcode |= (rn  <<  5);
1329 	opcode |= (wZR << 10);
1330 	opcode |= (rm  << 16);
1331 	WriteWord(opcode);
1332 }
1333 
Uqadd_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1334 void CAArch64Assembler::Uqadd_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1335 {
1336 	uint32 opcode = 0x6EA00C00;
1337 	opcode |= (rd  <<  0);
1338 	opcode |= (rn  <<  5);
1339 	opcode |= (rm  << 16);
1340 	WriteWord(opcode);
1341 }
1342 
Uqadd_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1343 void CAArch64Assembler::Uqadd_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1344 {
1345 	uint32 opcode = 0x6E600C00;
1346 	opcode |= (rd  <<  0);
1347 	opcode |= (rn  <<  5);
1348 	opcode |= (rm  << 16);
1349 	WriteWord(opcode);
1350 }
1351 
Uqadd_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1352 void CAArch64Assembler::Uqadd_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1353 {
1354 	uint32 opcode = 0x6E200C00;
1355 	opcode |= (rd  <<  0);
1356 	opcode |= (rn  <<  5);
1357 	opcode |= (rm  << 16);
1358 	WriteWord(opcode);
1359 }
1360 
Uqsub_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1361 void CAArch64Assembler::Uqsub_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1362 {
1363 	uint32 opcode = 0x6EA02C00;
1364 	opcode |= (rd  <<  0);
1365 	opcode |= (rn  <<  5);
1366 	opcode |= (rm  << 16);
1367 	WriteWord(opcode);
1368 }
1369 
Uqsub_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1370 void CAArch64Assembler::Uqsub_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1371 {
1372 	uint32 opcode = 0x6E602C00;
1373 	opcode |= (rd  <<  0);
1374 	opcode |= (rn  <<  5);
1375 	opcode |= (rm  << 16);
1376 	WriteWord(opcode);
1377 }
1378 
Uqsub_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1379 void CAArch64Assembler::Uqsub_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1380 {
1381 	uint32 opcode = 0x6E202C00;
1382 	opcode |= (rd  <<  0);
1383 	opcode |= (rn  <<  5);
1384 	opcode |= (rm  << 16);
1385 	WriteWord(opcode);
1386 }
1387 
Ushr_4s(REGISTERMD rd,REGISTERMD rn,uint8 sa)1388 void CAArch64Assembler::Ushr_4s(REGISTERMD rd, REGISTERMD rn, uint8 sa)
1389 {
1390 	uint8 immhb = (32 * 2) - (sa & 0x1F);
1391 	uint32 opcode = 0x6F000400;
1392 	opcode |= (rd    <<  0);
1393 	opcode |= (rn    <<  5);
1394 	opcode |= (immhb << 16);
1395 	WriteWord(opcode);
1396 }
1397 
Ushr_8h(REGISTERMD rd,REGISTERMD rn,uint8 sa)1398 void CAArch64Assembler::Ushr_8h(REGISTERMD rd, REGISTERMD rn, uint8 sa)
1399 {
1400 	uint8 immhb = (16 * 2) - (sa & 0xF);
1401 	uint32 opcode = 0x6F000400;
1402 	opcode |= (rd    <<  0);
1403 	opcode |= (rn    <<  5);
1404 	opcode |= (immhb << 16);
1405 	WriteWord(opcode);
1406 }
1407 
Xtn1_4h(REGISTERMD rd,REGISTERMD rn)1408 void CAArch64Assembler::Xtn1_4h(REGISTERMD rd, REGISTERMD rn)
1409 {
1410 	uint32 opcode = 0x0E612800;
1411 	opcode |= (rd << 0);
1412 	opcode |= (rn << 5);
1413 	WriteWord(opcode);
1414 }
1415 
Xtn1_8b(REGISTERMD rd,REGISTERMD rn)1416 void CAArch64Assembler::Xtn1_8b(REGISTERMD rd, REGISTERMD rn)
1417 {
1418 	uint32 opcode = 0x0E212800;
1419 	opcode |= (rd << 0);
1420 	opcode |= (rn << 5);
1421 	WriteWord(opcode);
1422 }
1423 
Xtn2_8h(REGISTERMD rd,REGISTERMD rn)1424 void CAArch64Assembler::Xtn2_8h(REGISTERMD rd, REGISTERMD rn)
1425 {
1426 	uint32 opcode = 0x4E612800;
1427 	opcode |= (rd << 0);
1428 	opcode |= (rn << 5);
1429 	WriteWord(opcode);
1430 }
1431 
Xtn2_16b(REGISTERMD rd,REGISTERMD rn)1432 void CAArch64Assembler::Xtn2_16b(REGISTERMD rd, REGISTERMD rn)
1433 {
1434 	uint32 opcode = 0x4E212800;
1435 	opcode |= (rd << 0);
1436 	opcode |= (rn << 5);
1437 	WriteWord(opcode);
1438 }
1439 
Zip1_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1440 void CAArch64Assembler::Zip1_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1441 {
1442 	uint32 opcode = 0x4E803800;
1443 	opcode |= (rd  <<  0);
1444 	opcode |= (rn  <<  5);
1445 	opcode |= (rm  << 16);
1446 	WriteWord(opcode);
1447 }
1448 
Zip1_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1449 void CAArch64Assembler::Zip1_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1450 {
1451 	uint32 opcode = 0x4E403800;
1452 	opcode |= (rd  <<  0);
1453 	opcode |= (rn  <<  5);
1454 	opcode |= (rm  << 16);
1455 	WriteWord(opcode);
1456 }
1457 
Zip1_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1458 void CAArch64Assembler::Zip1_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1459 {
1460 	uint32 opcode = 0x4E003800;
1461 	opcode |= (rd  <<  0);
1462 	opcode |= (rn  <<  5);
1463 	opcode |= (rm  << 16);
1464 	WriteWord(opcode);
1465 }
1466 
Zip2_4s(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1467 void CAArch64Assembler::Zip2_4s(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1468 {
1469 	uint32 opcode = 0x4E807800;
1470 	opcode |= (rd  <<  0);
1471 	opcode |= (rn  <<  5);
1472 	opcode |= (rm  << 16);
1473 	WriteWord(opcode);
1474 }
1475 
Zip2_8h(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1476 void CAArch64Assembler::Zip2_8h(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1477 {
1478 	uint32 opcode = 0x4E407800;
1479 	opcode |= (rd  <<  0);
1480 	opcode |= (rn  <<  5);
1481 	opcode |= (rm  << 16);
1482 	WriteWord(opcode);
1483 }
1484 
Zip2_16b(REGISTERMD rd,REGISTERMD rn,REGISTERMD rm)1485 void CAArch64Assembler::Zip2_16b(REGISTERMD rd, REGISTERMD rn, REGISTERMD rm)
1486 {
1487 	uint32 opcode = 0x4E007800;
1488 	opcode |= (rd  <<  0);
1489 	opcode |= (rn  <<  5);
1490 	opcode |= (rm  << 16);
1491 	WriteWord(opcode);
1492 }
1493 
WriteAddSubOpImm(uint32 opcode,uint32 shift,uint32 imm,uint32 rn,uint32 rd)1494 void CAArch64Assembler::WriteAddSubOpImm(uint32 opcode, uint32 shift, uint32 imm, uint32 rn, uint32 rd)
1495 {
1496 	assert(imm < 0x1000);
1497 	opcode |= (rd << 0);
1498 	opcode |= (rn << 5);
1499 	opcode |= ((imm & 0xFFF) << 10);
1500 	opcode |= (shift << 22);
1501 	WriteWord(opcode);
1502 }
1503 
WriteDataProcOpReg2(uint32 opcode,uint32 rm,uint32 rn,uint32 rd)1504 void CAArch64Assembler::WriteDataProcOpReg2(uint32 opcode, uint32 rm, uint32 rn, uint32 rd)
1505 {
1506 	opcode |= (rd <<  0);
1507 	opcode |= (rn <<  5);
1508 	opcode |= (rm << 16);
1509 	WriteWord(opcode);
1510 }
1511 
WriteLogicalOpImm(uint32 opcode,uint32 n,uint32 immr,uint32 imms,uint32 rn,uint32 rd)1512 void CAArch64Assembler::WriteLogicalOpImm(uint32 opcode, uint32 n, uint32 immr, uint32 imms, uint32 rn, uint32 rd)
1513 {
1514 	opcode |= (rd << 0);
1515 	opcode |= (rn << 5);
1516 	opcode |= (imms << 10);
1517 	opcode |= (immr << 16);
1518 	opcode |= (n << 22);
1519 	WriteWord(opcode);
1520 }
1521 
WriteLoadStoreOpImm(uint32 opcode,uint32 imm,uint32 rn,uint32 rt)1522 void CAArch64Assembler::WriteLoadStoreOpImm(uint32 opcode, uint32 imm, uint32 rn, uint32 rt)
1523 {
1524 	opcode |= (rt << 0);
1525 	opcode |= (rn << 5);
1526 	opcode |= (imm << 10);
1527 	WriteWord(opcode);
1528 }
1529 
WriteMoveWideOpImm(uint32 opcode,uint32 hw,uint32 imm,uint32 rd)1530 void CAArch64Assembler::WriteMoveWideOpImm(uint32 opcode, uint32 hw, uint32 imm, uint32 rd)
1531 {
1532 	opcode |= (rd << 0);
1533 	opcode |= (imm << 5);
1534 	opcode |= (hw << 21);
1535 	WriteWord(opcode);
1536 }
1537 
WriteWord(uint32 value)1538 void CAArch64Assembler::WriteWord(uint32 value)
1539 {
1540 	m_stream->Write32(value);
1541 }
1542