1 #include <assert.h>
2 #include <stdexcept>
3 #include "AArch32Assembler.h"
4
5 #define OPCODE_BKPT (0xE1200070)
6
CAArch32Assembler()7 CAArch32Assembler::CAArch32Assembler()
8 {
9
10 }
11
~CAArch32Assembler()12 CAArch32Assembler::~CAArch32Assembler()
13 {
14
15 }
16
SetStream(Framework::CStream * stream)17 void CAArch32Assembler::SetStream(Framework::CStream* stream)
18 {
19 m_stream = stream;
20 }
21
MakeImmediateLdrAddress(int32 immediate)22 CAArch32Assembler::LdrAddress CAArch32Assembler::MakeImmediateLdrAddress(int32 immediate)
23 {
24 LdrAddress result;
25 memset(&result, 0, sizeof(result));
26 result.isImmediate = true;
27 if(immediate < 0)
28 {
29 result.isNegative = (immediate < 0);
30 immediate = -immediate;
31 }
32 assert((immediate & ~0xFFF) == 0);
33 result.immediate = static_cast<uint16>(immediate);
34 return result;
35 }
36
MakeImmediateAluOperand(uint8 immediate,uint8 rotateAmount)37 CAArch32Assembler::ImmediateAluOperand CAArch32Assembler::MakeImmediateAluOperand(uint8 immediate, uint8 rotateAmount)
38 {
39 ImmediateAluOperand operand;
40 operand.immediate = immediate;
41 operand.rotate = rotateAmount;
42 return operand;
43 }
44
MakeRegisterAluOperand(CAArch32Assembler::REGISTER registerId,const AluLdrShift & shift)45 CAArch32Assembler::RegisterAluOperand CAArch32Assembler::MakeRegisterAluOperand(CAArch32Assembler::REGISTER registerId, const AluLdrShift& shift)
46 {
47 RegisterAluOperand result;
48 result.rm = registerId;
49 result.shift = *reinterpret_cast<const uint8*>(&shift);
50 return result;
51 }
52
MakeConstantShift(SHIFT shiftType,uint8 amount)53 CAArch32Assembler::AluLdrShift CAArch32Assembler::MakeConstantShift(SHIFT shiftType, uint8 amount)
54 {
55 assert(!(shiftType == SHIFT_ASR && amount == 0));
56 assert(!(shiftType == SHIFT_LSR && amount == 0));
57
58 AluLdrShift result;
59 result.typeBit = 0;
60 result.type = shiftType;
61 result.amount = amount;
62 return result;
63 }
64
MakeVariableShift(SHIFT shiftType,CAArch32Assembler::REGISTER registerId)65 CAArch32Assembler::AluLdrShift CAArch32Assembler::MakeVariableShift(SHIFT shiftType, CAArch32Assembler::REGISTER registerId)
66 {
67 AluLdrShift result;
68 result.typeBit = 1;
69 result.type = shiftType;
70 result.amount = registerId << 1;
71 return result;
72 }
73
CreateLabel()74 CAArch32Assembler::LABEL CAArch32Assembler::CreateLabel()
75 {
76 return m_nextLabelId++;
77 }
78
ClearLabels()79 void CAArch32Assembler::ClearLabels()
80 {
81 m_labels.clear();
82 }
83
MarkLabel(LABEL label)84 void CAArch32Assembler::MarkLabel(LABEL label)
85 {
86 m_labels[label] = static_cast<size_t>(m_stream->Tell());
87 }
88
ResolveLabelReferences()89 void CAArch32Assembler::ResolveLabelReferences()
90 {
91 for(const auto& labelReferencePair : m_labelReferences)
92 {
93 auto label(m_labels.find(labelReferencePair.first));
94 if(label == m_labels.end())
95 {
96 throw std::runtime_error("Invalid label.");
97 }
98 size_t referencePos = labelReferencePair.second;
99 size_t labelPos = label->second;
100 int offset = static_cast<int>(labelPos - referencePos) / 4;
101 offset -= 2;
102
103 m_stream->Seek(referencePos, Framework::STREAM_SEEK_SET);
104 m_stream->Write8(static_cast<uint8>(offset >> 0));
105 m_stream->Write8(static_cast<uint8>(offset >> 8));
106 m_stream->Write8(static_cast<uint8>(offset >> 16));
107 m_stream->Seek(0, Framework::STREAM_SEEK_END);
108 }
109 m_labelReferences.clear();
110 }
111
GenericAlu(ALU_OPCODE op,bool setFlags,REGISTER rd,REGISTER rn,REGISTER rm)112 void CAArch32Assembler::GenericAlu(ALU_OPCODE op, bool setFlags, REGISTER rd, REGISTER rn, REGISTER rm)
113 {
114 InstructionAlu instruction;
115 instruction.operand = rm;
116 instruction.rn = rn;
117 instruction.rd = rd;
118 instruction.setFlags = setFlags ? 1 : 0;
119 instruction.opcode = op;
120 instruction.immediate = 0;
121 instruction.condition = CONDITION_AL;
122 uint32 opcode = *reinterpret_cast<uint32*>(&instruction);
123 WriteWord(opcode);
124 }
125
GenericAlu(ALU_OPCODE op,bool setFlags,REGISTER rd,REGISTER rn,const ImmediateAluOperand & operand,CONDITION conditionCode)126 void CAArch32Assembler::GenericAlu(ALU_OPCODE op, bool setFlags, REGISTER rd, REGISTER rn,
127 const ImmediateAluOperand& operand, CONDITION conditionCode)
128 {
129 InstructionAlu instruction;
130 instruction.operand = *reinterpret_cast<const unsigned int*>(&operand);
131 instruction.rd = rd;
132 instruction.rn = rn;
133 instruction.setFlags = setFlags ? 1 : 0;
134 instruction.opcode = op;
135 instruction.immediate = 1;
136 instruction.condition = conditionCode;
137 uint32 opcode = *reinterpret_cast<uint32*>(&instruction);
138 WriteWord(opcode);
139 }
140
CreateLabelReference(LABEL label)141 void CAArch32Assembler::CreateLabelReference(LABEL label)
142 {
143 LABELREF reference = static_cast<size_t>(m_stream->Tell());
144 m_labelReferences.insert(LabelReferenceMapType::value_type(label, reference));
145 }
146
Adc(REGISTER rd,REGISTER rn,REGISTER rm)147 void CAArch32Assembler::Adc(REGISTER rd, REGISTER rn, REGISTER rm)
148 {
149 GenericAlu(ALU_OPCODE_ADC, false, rd, rn, rm);
150 }
151
Add(REGISTER rd,REGISTER rn,REGISTER rm)152 void CAArch32Assembler::Add(REGISTER rd, REGISTER rn, REGISTER rm)
153 {
154 GenericAlu(ALU_OPCODE_ADD, false, rd, rn, rm);
155 }
156
Add(REGISTER rd,REGISTER rn,const ImmediateAluOperand & operand)157 void CAArch32Assembler::Add(REGISTER rd, REGISTER rn, const ImmediateAluOperand& operand)
158 {
159 GenericAlu(ALU_OPCODE_ADD, false, rd, rn, operand);
160 }
161
Adds(REGISTER rd,REGISTER rn,REGISTER rm)162 void CAArch32Assembler::Adds(REGISTER rd, REGISTER rn, REGISTER rm)
163 {
164 GenericAlu(ALU_OPCODE_ADD, true, rd, rn, rm);
165 }
166
And(REGISTER rd,REGISTER rn,REGISTER rm)167 void CAArch32Assembler::And(REGISTER rd, REGISTER rn, REGISTER rm)
168 {
169 GenericAlu(ALU_OPCODE_AND, false, rd, rn, rm);
170 }
171
And(REGISTER rd,REGISTER rn,const ImmediateAluOperand & operand)172 void CAArch32Assembler::And(REGISTER rd, REGISTER rn, const ImmediateAluOperand& operand)
173 {
174 GenericAlu(ALU_OPCODE_AND, false, rd, rn, operand);
175 }
176
BCc(CONDITION condition,LABEL label)177 void CAArch32Assembler::BCc(CONDITION condition, LABEL label)
178 {
179 CreateLabelReference(label);
180 uint32 opcode = (condition << 28) | (0x0A000000);
181 WriteWord(opcode);
182 }
183
Bic(REGISTER rd,REGISTER rn,const ImmediateAluOperand & operand)184 void CAArch32Assembler::Bic(REGISTER rd, REGISTER rn, const ImmediateAluOperand& operand)
185 {
186 GenericAlu(ALU_OPCODE_BIC, false, rd, rn, operand);
187 }
188
Bx(REGISTER rn)189 void CAArch32Assembler::Bx(REGISTER rn)
190 {
191 uint32 opcode = 0;
192 opcode = (CONDITION_AL << 28) | (0x12FFF10) | (rn);
193 WriteWord(opcode);
194 }
195
Blx(REGISTER rn)196 void CAArch32Assembler::Blx(REGISTER rn)
197 {
198 uint32 opcode = 0;
199 opcode = (CONDITION_AL << 28) | (0x12FFF30) | (rn);
200 WriteWord(opcode);
201 }
202
Clz(REGISTER rd,REGISTER rm)203 void CAArch32Assembler::Clz(REGISTER rd, REGISTER rm)
204 {
205 uint32 opcode = 0x016F0F10;
206 opcode |= CONDITION_AL << 28;
207 opcode |= rm;
208 opcode |= (rd << 12);
209 WriteWord(opcode);
210 }
211
Cmn(REGISTER rn,const ImmediateAluOperand & operand)212 void CAArch32Assembler::Cmn(REGISTER rn, const ImmediateAluOperand& operand)
213 {
214 InstructionAlu instruction;
215 instruction.operand = *reinterpret_cast<const unsigned int*>(&operand);
216 instruction.rn = rn;
217 instruction.rd = 0;
218 instruction.setFlags = 1;
219 instruction.opcode = ALU_OPCODE_CMN;
220 instruction.immediate = 1;
221 instruction.condition = CONDITION_AL;
222 uint32 opcode = *reinterpret_cast<uint32*>(&instruction);
223 WriteWord(opcode);
224 }
225
Cmp(REGISTER rn,REGISTER rm)226 void CAArch32Assembler::Cmp(REGISTER rn, REGISTER rm)
227 {
228 InstructionAlu instruction;
229 instruction.operand = rm;
230 instruction.rn = rn;
231 instruction.rd = 0;
232 instruction.setFlags = 1;
233 instruction.opcode = ALU_OPCODE_CMP;
234 instruction.immediate = 0;
235 instruction.condition = CONDITION_AL;
236 uint32 opcode = *reinterpret_cast<uint32*>(&instruction);
237 WriteWord(opcode);
238 }
239
Cmp(REGISTER rn,const ImmediateAluOperand & operand)240 void CAArch32Assembler::Cmp(REGISTER rn, const ImmediateAluOperand& operand)
241 {
242 InstructionAlu instruction;
243 instruction.operand = *reinterpret_cast<const unsigned int*>(&operand);
244 instruction.rn = rn;
245 instruction.rd = 0;
246 instruction.setFlags = 1;
247 instruction.opcode = ALU_OPCODE_CMP;
248 instruction.immediate = 1;
249 instruction.condition = CONDITION_AL;
250 uint32 opcode = *reinterpret_cast<uint32*>(&instruction);
251 WriteWord(opcode);
252 }
253
Eor(REGISTER rd,REGISTER rn,REGISTER rm)254 void CAArch32Assembler::Eor(REGISTER rd, REGISTER rn, REGISTER rm)
255 {
256 GenericAlu(ALU_OPCODE_EOR, false, rd, rn, rm);
257 }
258
Eor(REGISTER rd,REGISTER rn,const ImmediateAluOperand & operand)259 void CAArch32Assembler::Eor(REGISTER rd, REGISTER rn, const ImmediateAluOperand& operand)
260 {
261 GenericAlu(ALU_OPCODE_EOR, false, rd, rn, operand);
262 }
263
Ldmia(REGISTER rbase,uint16 regList)264 void CAArch32Assembler::Ldmia(REGISTER rbase, uint16 regList)
265 {
266 //20 - Load
267 //21 - Writeback
268 //22 - User bit
269 //23 - Down/Up (0/1)
270 //24 - Post/Pre (0/1)
271 uint32 opcode = (CONDITION_AL << 28) | (4 << 25) | (1 << 23) | (1 << 21) | (1 << 20) | (static_cast<uint32>(rbase) << 16) | regList;
272 WriteWord(opcode);
273 }
274
Ldr(REGISTER rd,REGISTER rbase,const LdrAddress & address)275 void CAArch32Assembler::Ldr(REGISTER rd, REGISTER rbase, const LdrAddress& address)
276 {
277 uint32 opcode = 0;
278 assert(address.isImmediate);
279 assert(!address.isNegative);
280 opcode = (CONDITION_AL << 28) | (1 << 26) | (1 << 24) | (1 << 23) | (1 << 20) | (static_cast<uint32>(rbase) << 16) | (static_cast<uint32>(rd) << 12) | (static_cast<uint32>(address.immediate));
281 WriteWord(opcode);
282 }
283
Ldrd(REGISTER rt,REGISTER rn,const LdrAddress & address)284 void CAArch32Assembler::Ldrd(REGISTER rt, REGISTER rn, const LdrAddress& address)
285 {
286 assert(address.isImmediate);
287 assert(!address.isNegative);
288 assert(address.immediate < 0x100);
289 uint32 opcode = 0x01C000D0;
290 opcode |= (CONDITION_AL << 28);
291 opcode |= (rn << 16);
292 opcode |= (rt << 12);
293 opcode |= (address.immediate >> 4) << 8;
294 opcode |= (address.immediate & 0xF);
295 WriteWord(opcode);
296 }
297
Mov(REGISTER rd,REGISTER rm)298 void CAArch32Assembler::Mov(REGISTER rd, REGISTER rm)
299 {
300 InstructionAlu instruction;
301 instruction.operand = rm;
302 instruction.rd = rd;
303 instruction.setFlags = 0;
304 instruction.opcode = ALU_OPCODE_MOV;
305 instruction.immediate = 0;
306 instruction.condition = CONDITION_AL;
307 uint32 opcode = *reinterpret_cast<uint32*>(&instruction);
308 WriteWord(opcode);
309 }
310
Mov(REGISTER rd,const RegisterAluOperand & operand)311 void CAArch32Assembler::Mov(REGISTER rd, const RegisterAluOperand& operand)
312 {
313 InstructionAlu instruction;
314 instruction.operand = *reinterpret_cast<const unsigned int*>(&operand);
315 instruction.rd = rd;
316 instruction.setFlags = 0;
317 instruction.opcode = ALU_OPCODE_MOV;
318 instruction.immediate = 0;
319 instruction.condition = CONDITION_AL;
320 uint32 opcode = *reinterpret_cast<uint32*>(&instruction);
321 WriteWord(opcode);
322 }
323
Mov(REGISTER rd,const ImmediateAluOperand & operand)324 void CAArch32Assembler::Mov(REGISTER rd, const ImmediateAluOperand& operand)
325 {
326 MovCc(CONDITION_AL, rd, operand);
327 }
328
MovCc(CONDITION condition,REGISTER rd,const ImmediateAluOperand & operand)329 void CAArch32Assembler::MovCc(CONDITION condition, REGISTER rd, const ImmediateAluOperand& operand)
330 {
331 InstructionAlu instruction;
332 instruction.operand = *reinterpret_cast<const unsigned int*>(&operand);
333 instruction.rd = rd;
334 instruction.rn = 0;
335 instruction.setFlags = 0;
336 instruction.opcode = ALU_OPCODE_MOV;
337 instruction.immediate = 1;
338 instruction.condition = condition;
339 uint32 opcode = *reinterpret_cast<uint32*>(&instruction);
340 WriteWord(opcode);
341 }
342
Movw(REGISTER rd,uint16 value)343 void CAArch32Assembler::Movw(REGISTER rd, uint16 value)
344 {
345 uint32 opcode = 0x03000000;
346 opcode |= (CONDITION_AL << 28);
347 opcode |= (value >> 12) << 16;
348 opcode |= (rd << 12);
349 opcode |= (value & 0xFFF);
350 WriteWord(opcode);
351 }
352
Movt(REGISTER rd,uint16 value)353 void CAArch32Assembler::Movt(REGISTER rd, uint16 value)
354 {
355 uint32 opcode = 0x03400000;
356 opcode |= (CONDITION_AL << 28);
357 opcode |= (value >> 12) << 16;
358 opcode |= (rd << 12);
359 opcode |= (value & 0xFFF);
360 WriteWord(opcode);
361 }
362
Mvn(REGISTER rd,REGISTER rm)363 void CAArch32Assembler::Mvn(REGISTER rd, REGISTER rm)
364 {
365 InstructionAlu instruction;
366 instruction.operand = rm;
367 instruction.rd = rd;
368 instruction.setFlags = 0;
369 instruction.opcode = ALU_OPCODE_MVN;
370 instruction.immediate = 0;
371 instruction.condition = CONDITION_AL;
372 uint32 opcode = *reinterpret_cast<uint32*>(&instruction);
373 WriteWord(opcode);
374 }
375
Mvn(REGISTER rd,const ImmediateAluOperand & operand)376 void CAArch32Assembler::Mvn(REGISTER rd, const ImmediateAluOperand& operand)
377 {
378 InstructionAlu instruction;
379 instruction.operand = *reinterpret_cast<const unsigned int*>(&operand);
380 instruction.rd = rd;
381 instruction.rn = 0;
382 instruction.setFlags = 0;
383 instruction.opcode = ALU_OPCODE_MVN;
384 instruction.immediate = 1;
385 instruction.condition = CONDITION_AL;
386 uint32 opcode = *reinterpret_cast<uint32*>(&instruction);
387 WriteWord(opcode);
388 }
389
Or(REGISTER rd,REGISTER rn,REGISTER rm)390 void CAArch32Assembler::Or(REGISTER rd, REGISTER rn, REGISTER rm)
391 {
392 GenericAlu(ALU_OPCODE_ORR, false, rd, rn, rm);
393 }
394
Or(REGISTER rd,REGISTER rn,const ImmediateAluOperand & operand)395 void CAArch32Assembler::Or(REGISTER rd, REGISTER rn, const ImmediateAluOperand& operand)
396 {
397 GenericAlu(ALU_OPCODE_ORR, false, rd, rn, operand);
398 }
399
Or(CONDITION cc,REGISTER rd,REGISTER rn,const ImmediateAluOperand & operand)400 void CAArch32Assembler::Or(CONDITION cc, REGISTER rd, REGISTER rn, const ImmediateAluOperand& operand)
401 {
402 GenericAlu(ALU_OPCODE_ORR, false, rd, rn, operand, cc);
403 }
404
Rsb(REGISTER rd,REGISTER rn,const ImmediateAluOperand & operand)405 void CAArch32Assembler::Rsb(REGISTER rd, REGISTER rn, const ImmediateAluOperand& operand)
406 {
407 GenericAlu(ALU_OPCODE_RSB, false, rd, rn, operand);
408 }
409
Sbc(REGISTER rd,REGISTER rn,REGISTER rm)410 void CAArch32Assembler::Sbc(REGISTER rd, REGISTER rn, REGISTER rm)
411 {
412 GenericAlu(ALU_OPCODE_SBC, false, rd, rn, rm);
413 }
414
Sdiv(REGISTER rd,REGISTER rn,REGISTER rm)415 void CAArch32Assembler::Sdiv(REGISTER rd, REGISTER rn, REGISTER rm)
416 {
417 uint32 opcode = 0x0710F010;
418 opcode |= (CONDITION_AL << 28);
419 opcode |= (rd << 16);
420 opcode |= (rm << 8);
421 opcode |= (rn << 0);
422 WriteWord(opcode);
423 }
424
Smull(REGISTER rdLow,REGISTER rdHigh,REGISTER rn,REGISTER rm)425 void CAArch32Assembler::Smull(REGISTER rdLow, REGISTER rdHigh, REGISTER rn, REGISTER rm)
426 {
427 uint32 opcode = 0;
428 opcode = (CONDITION_AL << 28) | (0x06 << 21) | (rdHigh << 16) | (rdLow << 12) | (rm << 8) | (0x9 << 4) | (rn << 0);
429 WriteWord(opcode);
430 }
431
Stmdb(REGISTER rbase,uint16 regList)432 void CAArch32Assembler::Stmdb(REGISTER rbase, uint16 regList)
433 {
434 //20 - Load
435 //21 - Writeback
436 //22 - User bit
437 //23 - Down/Up (0/1)
438 //24 - Post/Pre (0/1)
439 uint32 opcode = (CONDITION_AL << 28) | (4 << 25) | (1 << 24) | (1 << 21) | (static_cast<uint32>(rbase) << 16) | regList;
440 WriteWord(opcode);
441 }
442
Str(REGISTER rd,REGISTER rbase,const LdrAddress & address)443 void CAArch32Assembler::Str(REGISTER rd, REGISTER rbase, const LdrAddress& address)
444 {
445 assert(address.isImmediate);
446 uint32 opcode = (CONDITION_AL << 28) | (1 << 26) | (1 << 24) | (0 << 20);
447 opcode |= (address.isNegative) ? 0 : (1 << 23);
448 opcode |= static_cast<uint32>(rbase) << 16;
449 opcode |= static_cast<uint32>(rd) << 12;
450 opcode |= static_cast<uint32>(address.immediate);
451 WriteWord(opcode);
452 }
453
Strd(REGISTER rt,REGISTER rn,const LdrAddress & address)454 void CAArch32Assembler::Strd(REGISTER rt, REGISTER rn, const LdrAddress& address)
455 {
456 assert(address.isImmediate);
457 assert(!address.isNegative);
458 assert(address.immediate < 0x100);
459 uint32 opcode = 0x01C000F0;
460 opcode |= (CONDITION_AL << 28);
461 opcode |= (rn << 16);
462 opcode |= (rt << 12);
463 opcode |= (address.immediate >> 4) << 8;
464 opcode |= (address.immediate & 0xF);
465 WriteWord(opcode);
466 }
467
Sub(REGISTER rd,REGISTER rn,REGISTER rm)468 void CAArch32Assembler::Sub(REGISTER rd, REGISTER rn, REGISTER rm)
469 {
470 GenericAlu(ALU_OPCODE_SUB, false, rd, rn, rm);
471 }
472
Sub(REGISTER rd,REGISTER rn,const ImmediateAluOperand & operand)473 void CAArch32Assembler::Sub(REGISTER rd, REGISTER rn, const ImmediateAluOperand& operand)
474 {
475 GenericAlu(ALU_OPCODE_SUB, false, rd, rn, operand);
476 }
477
Subs(REGISTER rd,REGISTER rn,REGISTER rm)478 void CAArch32Assembler::Subs(REGISTER rd, REGISTER rn, REGISTER rm)
479 {
480 GenericAlu(ALU_OPCODE_SUB, true, rd, rn, rm);
481 }
482
Teq(REGISTER rn,const ImmediateAluOperand & operand)483 void CAArch32Assembler::Teq(REGISTER rn, const ImmediateAluOperand& operand)
484 {
485 InstructionAlu instruction;
486 instruction.operand = *reinterpret_cast<const unsigned int*>(&operand);
487 instruction.rd = 0;
488 instruction.rn = rn;
489 instruction.setFlags = 1;
490 instruction.opcode = ALU_OPCODE_TEQ;
491 instruction.immediate = 1;
492 instruction.condition = CONDITION_AL;
493 uint32 opcode = *reinterpret_cast<uint32*>(&instruction);
494 WriteWord(opcode);
495 }
496
Tst(REGISTER rn,REGISTER rm)497 void CAArch32Assembler::Tst(REGISTER rn, REGISTER rm)
498 {
499 GenericAlu(ALU_OPCODE_TST, true, CAArch32Assembler::r0, rn, rm);
500 }
501
Udiv(REGISTER rd,REGISTER rn,REGISTER rm)502 void CAArch32Assembler::Udiv(REGISTER rd, REGISTER rn, REGISTER rm)
503 {
504 uint32 opcode = 0x0730F010;
505 opcode |= (CONDITION_AL << 28);
506 opcode |= (rd << 16);
507 opcode |= (rm << 8);
508 opcode |= (rn << 0);
509 WriteWord(opcode);
510 }
511
Umull(REGISTER rdLow,REGISTER rdHigh,REGISTER rn,REGISTER rm)512 void CAArch32Assembler::Umull(REGISTER rdLow, REGISTER rdHigh, REGISTER rn, REGISTER rm)
513 {
514 uint32 opcode = 0;
515 opcode = (CONDITION_AL << 28) | (0x04 << 21) | (rdHigh << 16) | (rdLow << 12) | (rm << 8) | (0x9 << 4) | (rn << 0);
516 WriteWord(opcode);
517 }
518
519 //////////////////////////////////////////////////
520 // VFP/NEON Stuff
521 //////////////////////////////////////////////////
522
FPSIMD_EncodeSd(SINGLE_REGISTER sd)523 uint32 CAArch32Assembler::FPSIMD_EncodeSd(SINGLE_REGISTER sd)
524 {
525 return ((sd >> 1) << 12) | ((sd & 1) << 22);
526 }
527
FPSIMD_EncodeSn(SINGLE_REGISTER sn)528 uint32 CAArch32Assembler::FPSIMD_EncodeSn(SINGLE_REGISTER sn)
529 {
530 return ((sn >> 1) << 16) | ((sn & 1) << 7);
531 }
532
FPSIMD_EncodeSm(SINGLE_REGISTER sm)533 uint32 CAArch32Assembler::FPSIMD_EncodeSm(SINGLE_REGISTER sm)
534 {
535 return ((sm >> 1) << 0) | ((sm & 1) << 5);
536 }
537
FPSIMD_EncodeDd(DOUBLE_REGISTER dd)538 uint32 CAArch32Assembler::FPSIMD_EncodeDd(DOUBLE_REGISTER dd)
539 {
540 return ((dd & 0xF) << 12) | ((dd >> 4) << 22);
541 }
542
FPSIMD_EncodeDn(DOUBLE_REGISTER dn)543 uint32 CAArch32Assembler::FPSIMD_EncodeDn(DOUBLE_REGISTER dn)
544 {
545 return ((dn & 0xF) << 16) | ((dn >> 4) << 7);
546 }
547
FPSIMD_EncodeDm(DOUBLE_REGISTER dm)548 uint32 CAArch32Assembler::FPSIMD_EncodeDm(DOUBLE_REGISTER dm)
549 {
550 return ((dm & 0x0F) << 0) | ((dm >> 4) << 5);
551 }
552
FPSIMD_EncodeQd(QUAD_REGISTER qd)553 uint32 CAArch32Assembler::FPSIMD_EncodeQd(QUAD_REGISTER qd)
554 {
555 assert((qd & 1) == 0);
556 return ((qd & 0xF) << 12) | ((qd >> 4) << 22);
557 }
558
FPSIMD_EncodeQn(QUAD_REGISTER qn)559 uint32 CAArch32Assembler::FPSIMD_EncodeQn(QUAD_REGISTER qn)
560 {
561 assert((qn & 1) == 0);
562 return ((qn & 0xF) << 16) | ((qn >> 4) << 7);
563 }
564
FPSIMD_EncodeQm(QUAD_REGISTER qm)565 uint32 CAArch32Assembler::FPSIMD_EncodeQm(QUAD_REGISTER qm)
566 {
567 assert((qm & 1) == 0);
568 return ((qm & 0x0F) << 0) | ((qm >> 4) << 5);
569 }
570
Vldr(SINGLE_REGISTER sd,REGISTER rbase,const LdrAddress & address)571 void CAArch32Assembler::Vldr(SINGLE_REGISTER sd, REGISTER rbase, const LdrAddress& address)
572 {
573 assert(address.isImmediate);
574 assert(!address.isNegative);
575 assert((address.immediate / 4) <= 0xFF);
576
577 uint32 opcode = 0x0D900A00;
578 opcode |= (CONDITION_AL << 28);
579 opcode |= FPSIMD_EncodeSd(sd);
580 opcode |= (static_cast<uint32>(rbase) << 16) | (static_cast<uint32>(address.immediate / 4));
581 WriteWord(opcode);
582 }
583
Vld1_32x2(DOUBLE_REGISTER dd,REGISTER rn)584 void CAArch32Assembler::Vld1_32x2(DOUBLE_REGISTER dd, REGISTER rn)
585 {
586 //TODO: Make this aligned
587
588 uint32 opcode = 0xF420078F;
589 opcode |= FPSIMD_EncodeDd(dd);
590 opcode |= static_cast<uint32>(rn) << 16;
591 WriteWord(opcode);
592 }
593
Vld1_32x4(QUAD_REGISTER qd,REGISTER rn)594 void CAArch32Assembler::Vld1_32x4(QUAD_REGISTER qd, REGISTER rn)
595 {
596 uint32 opcode = 0xF4200AAF;
597 opcode |= FPSIMD_EncodeQd(qd);
598 opcode |= static_cast<uint32>(rn) << 16;
599 WriteWord(opcode);
600 }
601
Vld1_32x4_u(QUAD_REGISTER qd,REGISTER rn)602 void CAArch32Assembler::Vld1_32x4_u(QUAD_REGISTER qd, REGISTER rn)
603 {
604 //Unaligned variant
605 uint32 opcode = 0xF4200A8F;
606 opcode |= FPSIMD_EncodeQd(qd);
607 opcode |= static_cast<uint32>(rn) << 16;
608 WriteWord(opcode);
609 }
610
Vstr(SINGLE_REGISTER sd,REGISTER rbase,const LdrAddress & address)611 void CAArch32Assembler::Vstr(SINGLE_REGISTER sd, REGISTER rbase, const LdrAddress& address)
612 {
613 assert(address.isImmediate);
614 assert(!address.isNegative);
615 assert((address.immediate / 4) <= 0xFF);
616
617 uint32 opcode = 0x0D800A00;
618 opcode |= (CONDITION_AL << 28);
619 opcode |= FPSIMD_EncodeSd(sd);
620 opcode |= (static_cast<uint32>(rbase) << 16) | (static_cast<uint32>(address.immediate / 4));
621 WriteWord(opcode);
622 }
623
Vst1_32x4(QUAD_REGISTER qd,REGISTER rn)624 void CAArch32Assembler::Vst1_32x4(QUAD_REGISTER qd, REGISTER rn)
625 {
626 uint32 opcode = 0xF4000AAF;
627 opcode |= FPSIMD_EncodeQd(qd);
628 opcode |= static_cast<uint32>(rn) << 16;
629 WriteWord(opcode);
630 }
631
Vmov(DOUBLE_REGISTER dd,REGISTER rt,uint8 offset)632 void CAArch32Assembler::Vmov(DOUBLE_REGISTER dd, REGISTER rt, uint8 offset)
633 {
634 uint32 opcode = 0x0E000B10;
635 opcode |= (CONDITION_AL << 28);
636 opcode |= (offset != 0) ? 0x00200000 : 0;
637 opcode |= FPSIMD_EncodeDn(dd);
638 opcode |= (rt << 12);
639 WriteWord(opcode);
640 }
641
Vmov(REGISTER rt,DOUBLE_REGISTER dn,uint8 offset)642 void CAArch32Assembler::Vmov(REGISTER rt, DOUBLE_REGISTER dn, uint8 offset)
643 {
644 uint32 opcode = 0x0E100B10;
645 opcode |= (CONDITION_AL << 28);
646 opcode |= (offset != 0) ? 0x00200000 : 0;
647 opcode |= FPSIMD_EncodeDn(dn);
648 opcode |= (rt << 12);
649 WriteWord(opcode);
650 }
651
Vmovn_I16(DOUBLE_REGISTER dd,QUAD_REGISTER qm)652 void CAArch32Assembler::Vmovn_I16(DOUBLE_REGISTER dd, QUAD_REGISTER qm)
653 {
654 uint32 opcode = 0xF3B20200;
655 opcode |= FPSIMD_EncodeDd(dd);
656 opcode |= FPSIMD_EncodeQm(qm);
657 WriteWord(opcode);
658 }
659
Vmovn_I32(DOUBLE_REGISTER dd,QUAD_REGISTER qm)660 void CAArch32Assembler::Vmovn_I32(DOUBLE_REGISTER dd, QUAD_REGISTER qm)
661 {
662 uint32 opcode = 0xF3B60200;
663 opcode |= FPSIMD_EncodeDd(dd);
664 opcode |= FPSIMD_EncodeQm(qm);
665 WriteWord(opcode);
666 }
667
Vdup(QUAD_REGISTER qd,REGISTER rt)668 void CAArch32Assembler::Vdup(QUAD_REGISTER qd, REGISTER rt)
669 {
670 uint32 opcode = 0x0EA00B10;
671 opcode |= (CONDITION_AL << 28);
672 opcode |= FPSIMD_EncodeQn(qd);
673 opcode |= (rt << 12);
674 WriteWord(opcode);
675 }
676
Vzip_I8(DOUBLE_REGISTER dd,DOUBLE_REGISTER dm)677 void CAArch32Assembler::Vzip_I8(DOUBLE_REGISTER dd, DOUBLE_REGISTER dm)
678 {
679 uint32 opcode = 0xF3B20180;
680 opcode |= FPSIMD_EncodeDd(dd);
681 opcode |= FPSIMD_EncodeDm(dm);
682 WriteWord(opcode);
683 }
684
Vzip_I16(DOUBLE_REGISTER dd,DOUBLE_REGISTER dm)685 void CAArch32Assembler::Vzip_I16(DOUBLE_REGISTER dd, DOUBLE_REGISTER dm)
686 {
687 uint32 opcode = 0xF3B60180;
688 opcode |= FPSIMD_EncodeDd(dd);
689 opcode |= FPSIMD_EncodeDm(dm);
690 WriteWord(opcode);
691 }
692
Vzip_I32(QUAD_REGISTER qd,QUAD_REGISTER qm)693 void CAArch32Assembler::Vzip_I32(QUAD_REGISTER qd, QUAD_REGISTER qm)
694 {
695 uint32 opcode = 0xF3BA01C0;
696 opcode |= FPSIMD_EncodeQd(qd);
697 opcode |= FPSIMD_EncodeQm(qm);
698 WriteWord(opcode);
699 }
700
Vadd_F32(SINGLE_REGISTER sd,SINGLE_REGISTER sn,SINGLE_REGISTER sm)701 void CAArch32Assembler::Vadd_F32(SINGLE_REGISTER sd, SINGLE_REGISTER sn, SINGLE_REGISTER sm)
702 {
703 uint32 opcode = 0x0E300A00;
704 opcode |= (CONDITION_AL << 28);
705 opcode |= FPSIMD_EncodeSd(sd);
706 opcode |= FPSIMD_EncodeSn(sn);
707 opcode |= FPSIMD_EncodeSm(sm);
708 WriteWord(opcode);
709 }
710
Vadd_F32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)711 void CAArch32Assembler::Vadd_F32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
712 {
713 uint32 opcode = 0xF2000D40;
714 opcode |= FPSIMD_EncodeQd(qd);
715 opcode |= FPSIMD_EncodeQn(qn);
716 opcode |= FPSIMD_EncodeQm(qm);
717 WriteWord(opcode);
718 }
719
Vadd_I8(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)720 void CAArch32Assembler::Vadd_I8(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
721 {
722 uint32 opcode = 0xF2000840;
723 opcode |= FPSIMD_EncodeQd(qd);
724 opcode |= FPSIMD_EncodeQn(qn);
725 opcode |= FPSIMD_EncodeQm(qm);
726 WriteWord(opcode);
727 }
728
Vadd_I16(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)729 void CAArch32Assembler::Vadd_I16(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
730 {
731 uint32 opcode = 0xF2100840;
732 opcode |= FPSIMD_EncodeQd(qd);
733 opcode |= FPSIMD_EncodeQn(qn);
734 opcode |= FPSIMD_EncodeQm(qm);
735 WriteWord(opcode);
736 }
737
Vadd_I32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)738 void CAArch32Assembler::Vadd_I32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
739 {
740 uint32 opcode = 0xF2200840;
741 opcode |= FPSIMD_EncodeQd(qd);
742 opcode |= FPSIMD_EncodeQn(qn);
743 opcode |= FPSIMD_EncodeQm(qm);
744 WriteWord(opcode);
745 }
746
Vqadd_U8(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)747 void CAArch32Assembler::Vqadd_U8(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
748 {
749 uint32 opcode = 0xF3000050;
750 opcode |= FPSIMD_EncodeQd(qd);
751 opcode |= FPSIMD_EncodeQn(qn);
752 opcode |= FPSIMD_EncodeQm(qm);
753 WriteWord(opcode);
754 }
755
Vqadd_U16(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)756 void CAArch32Assembler::Vqadd_U16(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
757 {
758 uint32 opcode = 0xF3100050;
759 opcode |= FPSIMD_EncodeQd(qd);
760 opcode |= FPSIMD_EncodeQn(qn);
761 opcode |= FPSIMD_EncodeQm(qm);
762 WriteWord(opcode);
763 }
764
Vqadd_U32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)765 void CAArch32Assembler::Vqadd_U32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
766 {
767 uint32 opcode = 0xF3200050;
768 opcode |= FPSIMD_EncodeQd(qd);
769 opcode |= FPSIMD_EncodeQn(qn);
770 opcode |= FPSIMD_EncodeQm(qm);
771 WriteWord(opcode);
772 }
773
Vqadd_I16(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)774 void CAArch32Assembler::Vqadd_I16(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
775 {
776 uint32 opcode = 0xF2100050;
777 opcode |= FPSIMD_EncodeQd(qd);
778 opcode |= FPSIMD_EncodeQn(qn);
779 opcode |= FPSIMD_EncodeQm(qm);
780 WriteWord(opcode);
781 }
782
Vqadd_I32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)783 void CAArch32Assembler::Vqadd_I32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
784 {
785 uint32 opcode = 0xF2200050;
786 opcode |= FPSIMD_EncodeQd(qd);
787 opcode |= FPSIMD_EncodeQn(qn);
788 opcode |= FPSIMD_EncodeQm(qm);
789 WriteWord(opcode);
790 }
791
Vsub_F32(SINGLE_REGISTER sd,SINGLE_REGISTER sn,SINGLE_REGISTER sm)792 void CAArch32Assembler::Vsub_F32(SINGLE_REGISTER sd, SINGLE_REGISTER sn, SINGLE_REGISTER sm)
793 {
794 uint32 opcode = 0x0E300A40;
795 opcode |= (CONDITION_AL << 28);
796 opcode |= FPSIMD_EncodeSd(sd);
797 opcode |= FPSIMD_EncodeSn(sn);
798 opcode |= FPSIMD_EncodeSm(sm);
799 WriteWord(opcode);
800 }
801
Vsub_F32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)802 void CAArch32Assembler::Vsub_F32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
803 {
804 uint32 opcode = 0xF2200D40;
805 opcode |= FPSIMD_EncodeQd(qd);
806 opcode |= FPSIMD_EncodeQn(qn);
807 opcode |= FPSIMD_EncodeQm(qm);
808 WriteWord(opcode);
809 }
810
Vsub_I8(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)811 void CAArch32Assembler::Vsub_I8(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
812 {
813 uint32 opcode = 0xF3000840;
814 opcode |= FPSIMD_EncodeQd(qd);
815 opcode |= FPSIMD_EncodeQn(qn);
816 opcode |= FPSIMD_EncodeQm(qm);
817 WriteWord(opcode);
818 }
819
Vsub_I16(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)820 void CAArch32Assembler::Vsub_I16(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
821 {
822 uint32 opcode = 0xF3100840;
823 opcode |= FPSIMD_EncodeQd(qd);
824 opcode |= FPSIMD_EncodeQn(qn);
825 opcode |= FPSIMD_EncodeQm(qm);
826 WriteWord(opcode);
827 }
828
Vsub_I32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)829 void CAArch32Assembler::Vsub_I32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
830 {
831 uint32 opcode = 0xF3200840;
832 opcode |= FPSIMD_EncodeQd(qd);
833 opcode |= FPSIMD_EncodeQn(qn);
834 opcode |= FPSIMD_EncodeQm(qm);
835 WriteWord(opcode);
836 }
837
Vqsub_U8(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)838 void CAArch32Assembler::Vqsub_U8(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
839 {
840 uint32 opcode = 0xF3000250;
841 opcode |= FPSIMD_EncodeQd(qd);
842 opcode |= FPSIMD_EncodeQn(qn);
843 opcode |= FPSIMD_EncodeQm(qm);
844 WriteWord(opcode);
845 }
846
Vqsub_U16(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)847 void CAArch32Assembler::Vqsub_U16(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
848 {
849 uint32 opcode = 0xF3100250;
850 opcode |= FPSIMD_EncodeQd(qd);
851 opcode |= FPSIMD_EncodeQn(qn);
852 opcode |= FPSIMD_EncodeQm(qm);
853 WriteWord(opcode);
854 }
855
Vqsub_I16(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)856 void CAArch32Assembler::Vqsub_I16(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
857 {
858 uint32 opcode = 0xF2100250;
859 opcode |= FPSIMD_EncodeQd(qd);
860 opcode |= FPSIMD_EncodeQn(qn);
861 opcode |= FPSIMD_EncodeQm(qm);
862 WriteWord(opcode);
863 }
864
Vqsub_I32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)865 void CAArch32Assembler::Vqsub_I32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
866 {
867 uint32 opcode = 0xF2200250;
868 opcode |= FPSIMD_EncodeQd(qd);
869 opcode |= FPSIMD_EncodeQn(qn);
870 opcode |= FPSIMD_EncodeQm(qm);
871 WriteWord(opcode);
872 }
873
Vmul_F32(SINGLE_REGISTER sd,SINGLE_REGISTER sn,SINGLE_REGISTER sm)874 void CAArch32Assembler::Vmul_F32(SINGLE_REGISTER sd, SINGLE_REGISTER sn, SINGLE_REGISTER sm)
875 {
876 uint32 opcode = 0x0E200A00;
877 opcode |= (CONDITION_AL << 28);
878 opcode |= FPSIMD_EncodeSd(sd);
879 opcode |= FPSIMD_EncodeSn(sn);
880 opcode |= FPSIMD_EncodeSm(sm);
881 WriteWord(opcode);
882 }
883
Vmul_F32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)884 void CAArch32Assembler::Vmul_F32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
885 {
886 uint32 opcode = 0xF3000D50;
887 opcode |= FPSIMD_EncodeQd(qd);
888 opcode |= FPSIMD_EncodeQn(qn);
889 opcode |= FPSIMD_EncodeQm(qm);
890 WriteWord(opcode);
891 }
892
Vdiv_F32(SINGLE_REGISTER sd,SINGLE_REGISTER sn,SINGLE_REGISTER sm)893 void CAArch32Assembler::Vdiv_F32(SINGLE_REGISTER sd, SINGLE_REGISTER sn, SINGLE_REGISTER sm)
894 {
895 uint32 opcode = 0x0E800A00;
896 opcode |= (CONDITION_AL << 28);
897 opcode |= FPSIMD_EncodeSd(sd);
898 opcode |= FPSIMD_EncodeSn(sn);
899 opcode |= FPSIMD_EncodeSm(sm);
900 WriteWord(opcode);
901 }
902
Vand(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)903 void CAArch32Assembler::Vand(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
904 {
905 uint32 opcode = 0xF2000150;
906 opcode |= FPSIMD_EncodeQd(qd);
907 opcode |= FPSIMD_EncodeQn(qn);
908 opcode |= FPSIMD_EncodeQm(qm);
909 WriteWord(opcode);
910 }
911
Vorn(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)912 void CAArch32Assembler::Vorn(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
913 {
914 uint32 opcode = 0xF2300150;
915 opcode |= FPSIMD_EncodeQd(qd);
916 opcode |= FPSIMD_EncodeQn(qn);
917 opcode |= FPSIMD_EncodeQm(qm);
918 WriteWord(opcode);
919 }
920
Vorr(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)921 void CAArch32Assembler::Vorr(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
922 {
923 uint32 opcode = 0xF2200150;
924 opcode |= FPSIMD_EncodeQd(qd);
925 opcode |= FPSIMD_EncodeQn(qn);
926 opcode |= FPSIMD_EncodeQm(qm);
927 WriteWord(opcode);
928 }
929
Veor(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)930 void CAArch32Assembler::Veor(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
931 {
932 uint32 opcode = 0xF3000150;
933 opcode |= FPSIMD_EncodeQd(qd);
934 opcode |= FPSIMD_EncodeQn(qn);
935 opcode |= FPSIMD_EncodeQm(qm);
936 WriteWord(opcode);
937 }
938
Vshl_I16(QUAD_REGISTER qd,QUAD_REGISTER qm,uint8 shiftAmount)939 void CAArch32Assembler::Vshl_I16(QUAD_REGISTER qd, QUAD_REGISTER qm, uint8 shiftAmount)
940 {
941 uint32 opcode = 0xF2800550;
942 opcode |= (0x10 + (shiftAmount & 0xF)) << 16;
943 opcode |= FPSIMD_EncodeQd(qd);
944 opcode |= FPSIMD_EncodeQm(qm);
945 WriteWord(opcode);
946 }
947
Vshl_I32(QUAD_REGISTER qd,QUAD_REGISTER qm,uint8 shiftAmount)948 void CAArch32Assembler::Vshl_I32(QUAD_REGISTER qd, QUAD_REGISTER qm, uint8 shiftAmount)
949 {
950 uint32 opcode = 0xF2800550;
951 opcode |= (0x20 + (shiftAmount & 0x1F)) << 16;
952 opcode |= FPSIMD_EncodeQd(qd);
953 opcode |= FPSIMD_EncodeQm(qm);
954 WriteWord(opcode);
955 }
956
Vshr_U16(QUAD_REGISTER qd,QUAD_REGISTER qm,uint8 shiftAmount)957 void CAArch32Assembler::Vshr_U16(QUAD_REGISTER qd, QUAD_REGISTER qm, uint8 shiftAmount)
958 {
959 uint32 opcode = 0xF3800050;
960 opcode |= (0x20 - (shiftAmount & 0xF)) << 16;
961 opcode |= FPSIMD_EncodeQd(qd);
962 opcode |= FPSIMD_EncodeQm(qm);
963 WriteWord(opcode);
964 }
965
Vshr_U32(QUAD_REGISTER qd,QUAD_REGISTER qm,uint8 shiftAmount)966 void CAArch32Assembler::Vshr_U32(QUAD_REGISTER qd, QUAD_REGISTER qm, uint8 shiftAmount)
967 {
968 uint32 opcode = 0xF3800050;
969 opcode |= (0x40 - (shiftAmount & 0x1F)) << 16;
970 opcode |= FPSIMD_EncodeQd(qd);
971 opcode |= FPSIMD_EncodeQm(qm);
972 WriteWord(opcode);
973 }
974
Vshr_I16(QUAD_REGISTER qd,QUAD_REGISTER qm,uint8 shiftAmount)975 void CAArch32Assembler::Vshr_I16(QUAD_REGISTER qd, QUAD_REGISTER qm, uint8 shiftAmount)
976 {
977 uint32 opcode = 0xF2800050;
978 opcode |= (0x20 - (shiftAmount & 0xF)) << 16;
979 opcode |= FPSIMD_EncodeQd(qd);
980 opcode |= FPSIMD_EncodeQm(qm);
981 WriteWord(opcode);
982 }
983
Vshr_I32(QUAD_REGISTER qd,QUAD_REGISTER qm,uint8 shiftAmount)984 void CAArch32Assembler::Vshr_I32(QUAD_REGISTER qd, QUAD_REGISTER qm, uint8 shiftAmount)
985 {
986 uint32 opcode = 0xF2800050;
987 opcode |= (0x40 - (shiftAmount & 0x1F)) << 16;
988 opcode |= FPSIMD_EncodeQd(qd);
989 opcode |= FPSIMD_EncodeQm(qm);
990 WriteWord(opcode);
991 }
992
Vabs_F32(SINGLE_REGISTER sd,SINGLE_REGISTER sm)993 void CAArch32Assembler::Vabs_F32(SINGLE_REGISTER sd, SINGLE_REGISTER sm)
994 {
995 uint32 opcode = 0x0EB00AC0;
996 opcode |= (CONDITION_AL << 28);
997 opcode |= FPSIMD_EncodeSd(sd);
998 opcode |= FPSIMD_EncodeSm(sm);
999 WriteWord(opcode);
1000 }
1001
Vabs_F32(QUAD_REGISTER qd,QUAD_REGISTER qm)1002 void CAArch32Assembler::Vabs_F32(QUAD_REGISTER qd, QUAD_REGISTER qm)
1003 {
1004 uint32 opcode = 0xF3B90740;
1005 opcode |= FPSIMD_EncodeQd(qd);
1006 opcode |= FPSIMD_EncodeQm(qm);
1007 WriteWord(opcode);
1008 }
1009
Vneg_F32(SINGLE_REGISTER sd,SINGLE_REGISTER sm)1010 void CAArch32Assembler::Vneg_F32(SINGLE_REGISTER sd, SINGLE_REGISTER sm)
1011 {
1012 uint32 opcode = 0x0EB10A40;
1013 opcode |= (CONDITION_AL << 28);
1014 opcode |= FPSIMD_EncodeSd(sd);
1015 opcode |= FPSIMD_EncodeSm(sm);
1016 WriteWord(opcode);
1017 }
1018
Vsqrt_F32(SINGLE_REGISTER sd,SINGLE_REGISTER sm)1019 void CAArch32Assembler::Vsqrt_F32(SINGLE_REGISTER sd, SINGLE_REGISTER sm)
1020 {
1021 uint32 opcode = 0x0EB10AC0;
1022 opcode |= (CONDITION_AL << 28);
1023 opcode |= FPSIMD_EncodeSd(sd);
1024 opcode |= FPSIMD_EncodeSm(sm);
1025 WriteWord(opcode);
1026 }
1027
Vceq_I32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)1028 void CAArch32Assembler::Vceq_I32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
1029 {
1030 uint32 opcode = 0xF3200850;
1031 opcode |= FPSIMD_EncodeQd(qd);
1032 opcode |= FPSIMD_EncodeQn(qn);
1033 opcode |= FPSIMD_EncodeQm(qm);
1034 WriteWord(opcode);
1035 }
1036
Vcgt_I16(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)1037 void CAArch32Assembler::Vcgt_I16(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
1038 {
1039 uint32 opcode = 0xF2100340;
1040 opcode |= FPSIMD_EncodeQd(qd);
1041 opcode |= FPSIMD_EncodeQn(qn);
1042 opcode |= FPSIMD_EncodeQm(qm);
1043 WriteWord(opcode);
1044 }
1045
Vcmp_F32(SINGLE_REGISTER sd,SINGLE_REGISTER sm)1046 void CAArch32Assembler::Vcmp_F32(SINGLE_REGISTER sd, SINGLE_REGISTER sm)
1047 {
1048 uint32 opcode = 0x0EB40A40;
1049 opcode |= (CONDITION_AL << 28);
1050 opcode |= FPSIMD_EncodeSd(sd);
1051 opcode |= FPSIMD_EncodeSm(sm);
1052 WriteWord(opcode);
1053 }
1054
Vcvt_F32_S32(SINGLE_REGISTER sd,SINGLE_REGISTER sm)1055 void CAArch32Assembler::Vcvt_F32_S32(SINGLE_REGISTER sd, SINGLE_REGISTER sm)
1056 {
1057 uint32 opcode = 0x0EB80AC0;
1058 opcode |= (CONDITION_AL << 28);
1059 opcode |= FPSIMD_EncodeSd(sd);
1060 opcode |= FPSIMD_EncodeSm(sm);
1061 WriteWord(opcode);
1062 }
1063
Vcvt_F32_S32(QUAD_REGISTER qd,QUAD_REGISTER qm)1064 void CAArch32Assembler::Vcvt_F32_S32(QUAD_REGISTER qd, QUAD_REGISTER qm)
1065 {
1066 uint32 opcode = 0xF3BB0640;
1067 opcode |= FPSIMD_EncodeQd(qd);
1068 opcode |= FPSIMD_EncodeQm(qm);
1069 WriteWord(opcode);
1070 }
1071
Vcvt_S32_F32(SINGLE_REGISTER sd,SINGLE_REGISTER sm)1072 void CAArch32Assembler::Vcvt_S32_F32(SINGLE_REGISTER sd, SINGLE_REGISTER sm)
1073 {
1074 uint32 opcode = 0x0EBD0AC0;
1075 opcode |= (CONDITION_AL << 28);
1076 opcode |= FPSIMD_EncodeSd(sd);
1077 opcode |= FPSIMD_EncodeSm(sm);
1078 WriteWord(opcode);
1079 }
1080
Vcvt_S32_F32(QUAD_REGISTER qd,QUAD_REGISTER qm)1081 void CAArch32Assembler::Vcvt_S32_F32(QUAD_REGISTER qd, QUAD_REGISTER qm)
1082 {
1083 uint32 opcode = 0xF3BB0740;
1084 opcode |= FPSIMD_EncodeQd(qd);
1085 opcode |= FPSIMD_EncodeQm(qm);
1086 WriteWord(opcode);
1087 }
1088
Vmrs(REGISTER rt)1089 void CAArch32Assembler::Vmrs(REGISTER rt)
1090 {
1091 uint32 opcode = 0x0EF10A10;
1092 opcode |= (CONDITION_AL << 28);
1093 opcode |= (rt << 12);
1094 WriteWord(opcode);
1095 }
1096
Vrecpe_F32(QUAD_REGISTER qd,QUAD_REGISTER qm)1097 void CAArch32Assembler::Vrecpe_F32(QUAD_REGISTER qd, QUAD_REGISTER qm)
1098 {
1099 uint32 opcode = 0xF3BB0540;
1100 opcode |= FPSIMD_EncodeQd(qd);
1101 opcode |= FPSIMD_EncodeQm(qm);
1102 WriteWord(opcode);
1103 }
1104
Vrecps_F32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)1105 void CAArch32Assembler::Vrecps_F32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
1106 {
1107 uint32 opcode = 0xF2000F50;
1108 opcode |= FPSIMD_EncodeQd(qd);
1109 opcode |= FPSIMD_EncodeQn(qn);
1110 opcode |= FPSIMD_EncodeQm(qm);
1111 WriteWord(opcode);
1112 }
1113
Vrsqrte_F32(QUAD_REGISTER qd,QUAD_REGISTER qm)1114 void CAArch32Assembler::Vrsqrte_F32(QUAD_REGISTER qd, QUAD_REGISTER qm)
1115 {
1116 uint32 opcode = 0xF3BB05C0;
1117 opcode |= FPSIMD_EncodeQd(qd);
1118 opcode |= FPSIMD_EncodeQm(qm);
1119 WriteWord(opcode);
1120 }
1121
Vrsqrts_F32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)1122 void CAArch32Assembler::Vrsqrts_F32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
1123 {
1124 uint32 opcode = 0xF2200F50;
1125 opcode |= FPSIMD_EncodeQd(qd);
1126 opcode |= FPSIMD_EncodeQn(qn);
1127 opcode |= FPSIMD_EncodeQm(qm);
1128 WriteWord(opcode);
1129 }
1130
Vmin_F32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)1131 void CAArch32Assembler::Vmin_F32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
1132 {
1133 uint32 opcode = 0xF2200F40;
1134 opcode |= FPSIMD_EncodeQd(qd);
1135 opcode |= FPSIMD_EncodeQn(qn);
1136 opcode |= FPSIMD_EncodeQm(qm);
1137 WriteWord(opcode);
1138 }
1139
Vmin_I16(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)1140 void CAArch32Assembler::Vmin_I16(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
1141 {
1142 uint32 opcode = 0xF2100650;
1143 opcode |= FPSIMD_EncodeQd(qd);
1144 opcode |= FPSIMD_EncodeQn(qn);
1145 opcode |= FPSIMD_EncodeQm(qm);
1146 WriteWord(opcode);
1147 }
1148
Vmin_I32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)1149 void CAArch32Assembler::Vmin_I32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
1150 {
1151 uint32 opcode = 0xF2200650;
1152 opcode |= FPSIMD_EncodeQd(qd);
1153 opcode |= FPSIMD_EncodeQn(qn);
1154 opcode |= FPSIMD_EncodeQm(qm);
1155 WriteWord(opcode);
1156 }
1157
Vmax_F32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)1158 void CAArch32Assembler::Vmax_F32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
1159 {
1160 uint32 opcode = 0xF2000F40;
1161 opcode |= FPSIMD_EncodeQd(qd);
1162 opcode |= FPSIMD_EncodeQn(qn);
1163 opcode |= FPSIMD_EncodeQm(qm);
1164 WriteWord(opcode);
1165 }
1166
Vmax_I16(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)1167 void CAArch32Assembler::Vmax_I16(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
1168 {
1169 uint32 opcode = 0xF2100640;
1170 opcode |= FPSIMD_EncodeQd(qd);
1171 opcode |= FPSIMD_EncodeQn(qn);
1172 opcode |= FPSIMD_EncodeQm(qm);
1173 WriteWord(opcode);
1174 }
1175
Vmax_I32(QUAD_REGISTER qd,QUAD_REGISTER qn,QUAD_REGISTER qm)1176 void CAArch32Assembler::Vmax_I32(QUAD_REGISTER qd, QUAD_REGISTER qn, QUAD_REGISTER qm)
1177 {
1178 uint32 opcode = 0xF2200640;
1179 opcode |= FPSIMD_EncodeQd(qd);
1180 opcode |= FPSIMD_EncodeQn(qn);
1181 opcode |= FPSIMD_EncodeQm(qm);
1182 WriteWord(opcode);
1183 }
1184
WriteWord(uint32 value)1185 void CAArch32Assembler::WriteWord(uint32 value)
1186 {
1187 m_stream->Write32(value);
1188 }
1189