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