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