1 #pragma once
2 
3 #include <string.h>
4 #include <functional>
5 #include <map>
6 #include <vector>
7 #include "Literal128.h"
8 #include "Stream.h"
9 #include "Types.h"
10 
11 class CAArch32Assembler
12 {
13 public:
14 	enum REGISTER
15 	{
16 		r0 = 0,
17 		r1 = 1,
18 		r2 = 2,
19 		r3 = 3,
20 		r4 = 4,
21 		r5 = 5,
22 		r6 = 6,
23 		r7 = 7,
24 		r8 = 8,
25 		r9 = 9,
26 		r10 = 10,
27 		r11 = 11,
28 		r12 = 12,
29 		r13 = 13,
30 		r14 = 14,
31 		r15 = 15,
32 
33 		rIP = 12,
34 		rSP = 13,
35 		rLR = 14,
36 		rPC = 15,
37 	};
38 
39 	enum SINGLE_REGISTER
40 	{
41 		s0,		s1,		s2,		s3,
42 		s4,		s5,		s6,		s7,
43 		s8,		s9,		s10,	s11,
44 		s12,	s13,	s14,	s15,
45 
46 		s16,	s17,	s18,	s19,
47 		s20,	s21,	s22,	s23,
48 		s24,	s25,	s26,	s27,
49 		s28,	s29,	s30,	s31,
50 	};
51 
52 	enum DOUBLE_REGISTER
53 	{
54 		d0,		d1,		d2,		d3,
55 		d4,		d5,		d6,		d7,
56 		d8,		d9,		d10,	d11,
57 		d12,	d13,	d14,	d15,
58 
59 		d16,	d17,	d18,	d19,
60 		d20,	d21,	d22,	d23,
61 		d24,	d25,	d26,	d27,
62 		d28,	d29,	d30,	d31,
63 	};
64 
65 	enum QUAD_REGISTER
66 	{
67 		q0 = 0,		q1 = 2,		q2 = 4,		q3 = 6,
68 		q4 = 8,		q5 = 10,	q6 = 12,	q7 = 14,
69 		q8 = 16,	q9 = 18,	q10 = 20,	q11 = 22,
70 		q12 = 24,	q13 = 26,	q14 = 28,	q15 = 30,
71 	};
72 
73 	enum ALU_OPCODE
74 	{
75 		ALU_OPCODE_AND = 0x00,
76 		ALU_OPCODE_EOR = 0x01,
77 		ALU_OPCODE_SUB = 0x02,
78 		ALU_OPCODE_RSB = 0x03,
79 		ALU_OPCODE_ADD = 0x04,
80 		ALU_OPCODE_ADC = 0x05,
81 		ALU_OPCODE_SBC = 0x06,
82 		ALU_OPCODE_RSC = 0x07,
83 		ALU_OPCODE_TST = 0x08,
84 		ALU_OPCODE_TEQ = 0x09,
85 		ALU_OPCODE_CMP = 0x0A,
86 		ALU_OPCODE_CMN = 0x0B,
87 		ALU_OPCODE_ORR = 0x0C,
88 		ALU_OPCODE_MOV = 0x0D,
89 		ALU_OPCODE_BIC = 0x0E,
90 		ALU_OPCODE_MVN = 0x0F,
91 	};
92 
93 	enum CONDITION
94 	{
95 		CONDITION_EQ = 0x00,
96 		CONDITION_NE = 0x01,
97 		CONDITION_CS = 0x02,
98 		CONDITION_CC = 0x03,
99 		CONDITION_MI = 0x04,
100 		CONDITION_PL = 0x05,
101 		CONDITION_VS = 0x06,
102 		CONDITION_VC = 0x07,
103 		CONDITION_HI = 0x08,
104 		CONDITION_LS = 0x09,
105 		CONDITION_GE = 0x0A,
106 		CONDITION_LT = 0x0B,
107 		CONDITION_GT = 0x0C,
108 		CONDITION_LE = 0x0D,
109 		CONDITION_AL = 0x0E,
110 		CONDITION_NV = 0x0F
111 	};
112 
113 	enum SHIFT
114 	{
115 		SHIFT_LSL = 0x00,
116 		SHIFT_LSR = 0x01,
117 		SHIFT_ASR = 0x02,
118 		SHIFT_ROR = 0x03,
119 	};
120 
121 	struct InstructionAlu
122 	{
InstructionAluInstructionAlu123 		InstructionAlu()
124 		{
125 			memset(this, 0, sizeof(InstructionAlu));
126 		}
127 
128 		unsigned int		operand		: 12;
129 		unsigned int		rd			: 4;
130 		unsigned int		rn			: 4;
131 		unsigned int		setFlags	: 1;
132 		unsigned int		opcode		: 4;
133 		unsigned int		immediate	: 1;
134 		unsigned int		reserved	: 2;
135 		unsigned int		condition	: 4;
136 	};
137 
138 	struct ImmediateAluOperand
139 	{
140 		unsigned int	immediate	: 8;
141 		unsigned int	rotate		: 4;
142 	};
143 
144 	struct RegisterAluOperand
145 	{
146 		unsigned int	rm			: 4;
147 		unsigned int	shift		: 8;
148 	};
149 
150 	struct AluLdrShift
151 	{
152 		unsigned int	typeBit		: 1;
153 		unsigned int	type		: 2;
154 		unsigned int	amount		: 5;
155 	};
156 
157 	struct ShiftRmAddress
158 	{
159 		union
160 		{
161 			struct
162 			{
163 				unsigned int	rm			: 4;
164 				unsigned int	isConstant	: 1;
165 				unsigned int	shiftType	: 2;
166 				unsigned int	constant	: 5;
167 			} immediateShift;
168 			struct
169 			{
170 				unsigned int	rm			: 4;
171 				unsigned int	isConstant	: 1;
172 				unsigned int	shiftType	: 2;
173 				unsigned int	zero		: 1;
174 				unsigned int	rs			: 4;
175 			} registerShift;
176 		};
177 	};
178 
179 	struct LdrAddress
180 	{
181 		union
182 		{
183 			uint16			immediate;
184 			ShiftRmAddress	shiftRm;
185 		};
186 		bool isImmediate = false;
187 		bool isNegative = false;
188 	};
189 
190 	typedef unsigned int LABEL;
191 
192 
193 	virtual									~CAArch32Assembler() = default;
194 
195 	void									SetStream(Framework::CStream*);
196 
197 	LABEL									CreateLabel();
198 	void									ClearLabels();
199 	void									MarkLabel(LABEL);
200 	void									ResolveLabelReferences();
201 
202 	void									ResolveLiteralReferences();
203 
204 	void									Adc(REGISTER, REGISTER, REGISTER);
205 	void									Add(REGISTER, REGISTER, REGISTER);
206 	void									Add(REGISTER, REGISTER, const ImmediateAluOperand&);
207 	void									Adds(REGISTER, REGISTER, REGISTER);
208 	void									Adrl(REGISTER, const LITERAL128&);
209 	void									And(REGISTER, REGISTER, REGISTER);
210 	void									And(REGISTER, REGISTER, const ImmediateAluOperand&);
211 	void									BCc(CONDITION, LABEL);
212 	void									Bic(REGISTER, REGISTER, const ImmediateAluOperand&);
213 	void									Bx(REGISTER);
214 	void									Blx(REGISTER);
215 	void									Clz(REGISTER, REGISTER);
216 	void									Cmn(REGISTER, const ImmediateAluOperand&);
217 	void									Cmp(REGISTER, REGISTER);
218 	void									Cmp(REGISTER, const ImmediateAluOperand&);
219 	void									Eor(REGISTER, REGISTER, REGISTER);
220 	void									Eor(REGISTER, REGISTER, const ImmediateAluOperand&);
221 	void									Ldmia(REGISTER, uint16);
222 	void									Ldr(REGISTER, REGISTER, const LdrAddress&);
223 	void									Ldrb(REGISTER, REGISTER, const LdrAddress&);
224 	void									Ldrh(REGISTER, REGISTER, const LdrAddress&);
225 	void									Ldr_Pc(REGISTER, int32);
226 	void									Ldrd(REGISTER, REGISTER, const LdrAddress&);
227 	void									Mov(REGISTER, REGISTER);
228 	void									Mov(REGISTER, const RegisterAluOperand&);
229 	void									Mov(REGISTER, const ImmediateAluOperand&);
230 	void									MovCc(CONDITION, REGISTER, const ImmediateAluOperand&);
231 	void									Movw(REGISTER, uint16);
232 	void									Movt(REGISTER, uint16);
233 	void									Mvn(REGISTER, REGISTER);
234 	void									Mvn(REGISTER, const ImmediateAluOperand&);
235 	void									Or(REGISTER, REGISTER, REGISTER);
236 	void									Or(REGISTER, REGISTER, const ImmediateAluOperand&);
237 	void									Or(CONDITION, REGISTER, REGISTER, const ImmediateAluOperand&);
238 	void									Rsb(REGISTER, REGISTER, const ImmediateAluOperand&);
239 	void									Sbc(REGISTER, REGISTER, REGISTER);
240 	void									Sdiv(REGISTER, REGISTER, REGISTER);
241 	void									Smull(REGISTER, REGISTER, REGISTER, REGISTER);
242 	void									Stmdb(REGISTER, uint16);
243 	void									Str(REGISTER, REGISTER, const LdrAddress&);
244 	void									Strb(REGISTER, REGISTER, const LdrAddress&);
245 	void									Strh(REGISTER, REGISTER, const LdrAddress&);
246 	void									Strd(REGISTER, REGISTER, const LdrAddress&);
247 	void									Sub(REGISTER, REGISTER, REGISTER);
248 	void									Sub(REGISTER, REGISTER, const ImmediateAluOperand&);
249 	void									Subs(REGISTER, REGISTER, REGISTER);
250 	void									Teq(REGISTER, const ImmediateAluOperand&);
251 	void									Tst(REGISTER, REGISTER);
252 	void									Udiv(REGISTER, REGISTER, REGISTER);
253 	void									Umull(REGISTER, REGISTER, REGISTER, REGISTER);
254 
255 	//VFP/NEON
256 	void									Vldr(SINGLE_REGISTER, REGISTER, const LdrAddress&);
257 	void									Vld1_32x2(DOUBLE_REGISTER, REGISTER);
258 	void									Vld1_32x4(QUAD_REGISTER, REGISTER);
259 	void									Vld1_32x4_u(QUAD_REGISTER, REGISTER);
260 	void									Vstr(SINGLE_REGISTER, REGISTER, const LdrAddress&);
261 	void									Vst1_32x4(QUAD_REGISTER, REGISTER);
262 	void									Vmov(DOUBLE_REGISTER, REGISTER, uint8);
263 	void									Vmov(REGISTER, DOUBLE_REGISTER, uint8);
264 	void									Vmovn_I16(DOUBLE_REGISTER, QUAD_REGISTER);
265 	void									Vmovn_I32(DOUBLE_REGISTER, QUAD_REGISTER);
266 	void									Vdup(QUAD_REGISTER, REGISTER);
267 	void									Vzip_I8(DOUBLE_REGISTER, DOUBLE_REGISTER);
268 	void									Vzip_I16(DOUBLE_REGISTER, DOUBLE_REGISTER);
269 	void									Vzip_I32(QUAD_REGISTER, QUAD_REGISTER);
270 	void									Vtbl(DOUBLE_REGISTER, DOUBLE_REGISTER, DOUBLE_REGISTER);
271 	void									Vadd_F32(SINGLE_REGISTER, SINGLE_REGISTER, SINGLE_REGISTER);
272 	void									Vadd_F32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
273 	void									Vadd_I8(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
274 	void									Vadd_I16(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
275 	void									Vadd_I32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
276 	void									Vpaddl_I8(QUAD_REGISTER, QUAD_REGISTER);
277 	void									Vpaddl_I16(QUAD_REGISTER, QUAD_REGISTER);
278 	void									Vpaddl_I32(QUAD_REGISTER, QUAD_REGISTER);
279 	void									Vqadd_U8(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
280 	void									Vqadd_U16(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
281 	void									Vqadd_U32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
282 	void									Vqadd_I8(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
283 	void									Vqadd_I16(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
284 	void									Vqadd_I32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
285 	void									Vsub_F32(SINGLE_REGISTER, SINGLE_REGISTER, SINGLE_REGISTER);
286 	void									Vsub_F32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
287 	void									Vsub_I8(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
288 	void									Vsub_I16(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
289 	void									Vsub_I32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
290 	void									Vqsub_U8(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
291 	void									Vqsub_U16(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
292 	void									Vqsub_U32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
293 	void									Vqsub_I16(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
294 	void									Vqsub_I32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
295 	void									Vmul_F32(SINGLE_REGISTER, SINGLE_REGISTER, SINGLE_REGISTER);
296 	void									Vmul_F32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
297 	void									Vdiv_F32(SINGLE_REGISTER, SINGLE_REGISTER, SINGLE_REGISTER);
298 	void									Vand(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
299 	void									Vorn(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
300 	void									Vorr(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
301 	void									Veor(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
302 	void									Vmvn(QUAD_REGISTER, QUAD_REGISTER);
303 	void									Vshl_I16(QUAD_REGISTER, QUAD_REGISTER, uint8);
304 	void									Vshl_I32(QUAD_REGISTER, QUAD_REGISTER, uint8);
305 	void									Vshr_U16(QUAD_REGISTER, QUAD_REGISTER, uint8);
306 	void									Vshr_U32(QUAD_REGISTER, QUAD_REGISTER, uint8);
307 	void									Vshr_I16(QUAD_REGISTER, QUAD_REGISTER, uint8);
308 	void									Vshr_I32(QUAD_REGISTER, QUAD_REGISTER, uint8);
309 	void									Vabs_F32(SINGLE_REGISTER, SINGLE_REGISTER);
310 	void									Vabs_F32(QUAD_REGISTER, QUAD_REGISTER);
311 	void									Vneg_F32(SINGLE_REGISTER, SINGLE_REGISTER);
312 	void									Vsqrt_F32(SINGLE_REGISTER, SINGLE_REGISTER);
313 	void									Vceq_I8(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
314 	void									Vceq_I16(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
315 	void									Vceq_I32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
316 	void									Vceqz_F32(QUAD_REGISTER, QUAD_REGISTER);
317 	void									Vcge_F32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
318 	void									Vcgt_I8(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
319 	void									Vcgt_I16(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
320 	void									Vcgt_I32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
321 	void									Vcgt_F32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
322 	void									Vcltz_I32(QUAD_REGISTER, QUAD_REGISTER);
323 	void									Vcmp_F32(SINGLE_REGISTER, SINGLE_REGISTER);
324 	void									Vcmpz_F32(SINGLE_REGISTER);
325 	void									Vcvt_F32_S32(SINGLE_REGISTER, SINGLE_REGISTER);
326 	void									Vcvt_F32_S32(QUAD_REGISTER, QUAD_REGISTER);
327 	void									Vcvt_S32_F32(SINGLE_REGISTER, SINGLE_REGISTER);
328 	void									Vcvt_S32_F32(QUAD_REGISTER, QUAD_REGISTER);
329 	void									Vmrs(REGISTER);
330 
331 	void									Vrecpe_F32(QUAD_REGISTER, QUAD_REGISTER);
332 	void									Vrecps_F32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
333 	void									Vrsqrte_F32(QUAD_REGISTER, QUAD_REGISTER);
334 	void									Vrsqrts_F32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
335 	void									Vmin_F32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
336 	void									Vmin_I16(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
337 	void									Vmin_I32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
338 	void									Vmax_F32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
339 	void									Vmax_I16(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
340 	void									Vmax_I32(QUAD_REGISTER, QUAD_REGISTER, QUAD_REGISTER);
341 
342 	static LdrAddress						MakeImmediateLdrAddress(int32);
343 	static LdrAddress						MakeRegisterLdrAddress(REGISTER, SHIFT = SHIFT_LSL, uint8 = 0);
344 
345 	static ImmediateAluOperand				MakeImmediateAluOperand(uint8, uint8);
346 	static RegisterAluOperand				MakeRegisterAluOperand(CAArch32Assembler::REGISTER, const AluLdrShift&);
347 
348 	static AluLdrShift						MakeConstantShift(CAArch32Assembler::SHIFT, uint8);
349 	static AluLdrShift						MakeVariableShift(CAArch32Assembler::SHIFT, CAArch32Assembler::REGISTER);
350 
351 private:
352 	typedef size_t LABELREF;
353 
354 	struct LITERAL128REF
355 	{
356 		size_t offset = 0;
357 		REGISTER rd = CAArch32Assembler::r0;
358 		LITERAL128 value = LITERAL128(0, 0);
359 	};
360 
361 	typedef std::map<LABEL, size_t> LabelMapType;
362 	typedef std::multimap<LABEL, LABELREF> LabelReferenceMapType;
363 
364 	typedef std::vector<LITERAL128REF> Literal128ArrayType;
365 
366 	void									GenericAlu(ALU_OPCODE, bool, REGISTER, REGISTER, REGISTER);
367 	void									GenericAlu(ALU_OPCODE, bool, REGISTER, REGISTER, const ImmediateAluOperand&, CONDITION = CONDITION_AL);
368 
369 	void									CreateLabelReference(LABEL);
370 	void									WriteWord(uint32);
371 
372 	static uint32							FPSIMD_EncodeSd(SINGLE_REGISTER);
373 	static uint32							FPSIMD_EncodeSn(SINGLE_REGISTER);
374 	static uint32							FPSIMD_EncodeSm(SINGLE_REGISTER);
375 	static uint32							FPSIMD_EncodeDd(DOUBLE_REGISTER);
376 	static uint32							FPSIMD_EncodeDn(DOUBLE_REGISTER);
377 	static uint32							FPSIMD_EncodeDm(DOUBLE_REGISTER);
378 	static uint32							FPSIMD_EncodeQd(QUAD_REGISTER);
379 	static uint32							FPSIMD_EncodeQn(QUAD_REGISTER);
380 	static uint32							FPSIMD_EncodeQm(QUAD_REGISTER);
381 
382 	unsigned int							m_nextLabelId = 1;
383 	LabelMapType							m_labels;
384 	LabelReferenceMapType					m_labelReferences;
385 	Literal128ArrayType						m_literal128Refs;
386 
387 	Framework::CStream*						m_stream = nullptr;
388 };
389