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