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