src/arm/decoder-thumb.c (view raw)
1#include "decoder.h"
2
3#include "decoder-inlines.h"
4#include "emitter-thumb.h"
5#include "isa-inlines.h"
6
7#define DEFINE_THUMB_DECODER(NAME, MNEMONIC, BODY) \
8 static void _ThumbDecode ## NAME (uint16_t opcode, struct ARMInstructionInfo* info) { \
9 UNUSED(opcode); \
10 info->mnemonic = ARM_MN_ ## MNEMONIC; \
11 BODY; \
12 }
13
14#define DEFINE_IMMEDIATE_5_DECODER_DATA_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \
15 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
16 info->op3.immediate = IMMEDIATE; \
17 info->op1.reg = opcode & 0x0007; \
18 info->op2.reg = (opcode >> 3) & 0x0007; \
19 info->affectsCPSR = 1; \
20 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
21 ARM_OPERAND_AFFECTED_1 | \
22 ARM_OPERAND_REGISTER_2 | \
23 ARM_OPERAND_IMMEDIATE_3;)
24
25#define DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, CYCLES, WIDTH) \
26 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
27 info->op1.reg = opcode & 0x0007; \
28 info->memory.baseReg = (opcode >> 3) & 0x0007; \
29 info->memory.offset.immediate = IMMEDIATE * WIDTH; \
30 info->memory.width = (enum ARMMemoryAccessType) WIDTH; \
31 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
32 ARM_OPERAND_AFFECTED_1 | \
33 ARM_OPERAND_MEMORY_2; \
34 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
35 ARM_MEMORY_IMMEDIATE_OFFSET; \
36 CYCLES)
37
38#define DEFINE_IMMEDIATE_5_DECODER_MEM_LOAD_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \
39 DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, LOAD_CYCLES, WIDTH)
40
41#define DEFINE_IMMEDIATE_5_DECODER_MEM_STORE_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \
42 DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, STORE_CYCLES, WIDTH)
43
44#define DEFINE_IMMEDIATE_5_DECODER_THUMB(NAME, MNEMONIC, TYPE, WIDTH) \
45 COUNT_CALL_5(DEFINE_IMMEDIATE_5_DECODER_ ## TYPE ## _THUMB, NAME ## _, MNEMONIC, WIDTH)
46
47DEFINE_IMMEDIATE_5_DECODER_THUMB(LSL1, LSL, DATA,)
48DEFINE_IMMEDIATE_5_DECODER_THUMB(LSR1, LSR, DATA,)
49DEFINE_IMMEDIATE_5_DECODER_THUMB(ASR1, ASR, DATA,)
50DEFINE_IMMEDIATE_5_DECODER_THUMB(LDR1, LDR, MEM_LOAD, 4)
51DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRB1, LDR, MEM_LOAD, 1)
52DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRH1, LDR, MEM_LOAD, 2)
53DEFINE_IMMEDIATE_5_DECODER_THUMB(STR1, STR, MEM_STORE, 4)
54DEFINE_IMMEDIATE_5_DECODER_THUMB(STRB1, STR, MEM_STORE, 1)
55DEFINE_IMMEDIATE_5_DECODER_THUMB(STRH1, STR, MEM_STORE, 2)
56
57#define DEFINE_DATA_FORM_1_DECODER_EX_THUMB(NAME, RM, MNEMONIC) \
58 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
59 info->op1.reg = opcode & 0x0007; \
60 info->op2.reg = (opcode >> 3) & 0x0007; \
61 info->op3.reg = RM; \
62 info->affectsCPSR = 1; \
63 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
64 ARM_OPERAND_AFFECTED_1 | \
65 ARM_OPERAND_REGISTER_2 | \
66 ARM_OPERAND_REGISTER_3;)
67
68#define DEFINE_DATA_FORM_1_DECODER_THUMB(NAME) \
69 COUNT_CALL_3(DEFINE_DATA_FORM_1_DECODER_EX_THUMB, NAME ## 3_R, NAME)
70
71DEFINE_DATA_FORM_1_DECODER_THUMB(ADD)
72DEFINE_DATA_FORM_1_DECODER_THUMB(SUB)
73
74#define DEFINE_DATA_FORM_2_DECODER_EX_THUMB(NAME, IMMEDIATE, MNEMONIC) \
75 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
76 info->op1.reg = opcode & 0x0007; \
77 info->op2.reg = (opcode >> 3) & 0x0007; \
78 info->op3.immediate = IMMEDIATE; \
79 info->affectsCPSR = 1; \
80 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
81 ARM_OPERAND_AFFECTED_1 | \
82 ARM_OPERAND_REGISTER_2 | \
83 ARM_OPERAND_IMMEDIATE_3;)
84
85#define DEFINE_DATA_FORM_2_DECODER_THUMB(NAME) \
86 COUNT_CALL_3(DEFINE_DATA_FORM_2_DECODER_EX_THUMB, NAME ## 1_, NAME)
87
88DEFINE_DATA_FORM_2_DECODER_THUMB(ADD)
89DEFINE_DATA_FORM_2_DECODER_THUMB(SUB)
90
91#define DEFINE_DATA_FORM_3_DECODER_EX_THUMB(NAME, RD, MNEMONIC, AFFECTED) \
92 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
93 info->op1.reg = RD; \
94 info->op2.immediate = opcode & 0x00FF; \
95 info->affectsCPSR = 1; \
96 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
97 AFFECTED | \
98 ARM_OPERAND_IMMEDIATE_2;)
99
100#define DEFINE_DATA_FORM_3_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \
101 COUNT_CALL_3(DEFINE_DATA_FORM_3_DECODER_EX_THUMB, NAME ## _R, MNEMONIC, AFFECTED)
102
103DEFINE_DATA_FORM_3_DECODER_THUMB(ADD2, ADD, ARM_OPERAND_AFFECTED_1)
104DEFINE_DATA_FORM_3_DECODER_THUMB(CMP1, CMP, ARM_OPERAND_NONE)
105DEFINE_DATA_FORM_3_DECODER_THUMB(MOV1, MOV, ARM_OPERAND_AFFECTED_1)
106DEFINE_DATA_FORM_3_DECODER_THUMB(SUB2, SUB, ARM_OPERAND_AFFECTED_1)
107
108#define DEFINE_DATA_FORM_5_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \
109 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
110 info->op1.reg = opcode & 0x0007; \
111 info->op2.reg = (opcode >> 3) & 0x0007; \
112 info->affectsCPSR = 1; \
113 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
114 AFFECTED | \
115 ARM_OPERAND_REGISTER_2;)
116
117DEFINE_DATA_FORM_5_DECODER_THUMB(AND, AND, ARM_OPERAND_AFFECTED_1)
118DEFINE_DATA_FORM_5_DECODER_THUMB(EOR, EOR, ARM_OPERAND_AFFECTED_1)
119DEFINE_DATA_FORM_5_DECODER_THUMB(LSL2, LSL, ARM_OPERAND_AFFECTED_1)
120DEFINE_DATA_FORM_5_DECODER_THUMB(LSR2, LSR, ARM_OPERAND_AFFECTED_1)
121DEFINE_DATA_FORM_5_DECODER_THUMB(ASR2, ASR, ARM_OPERAND_AFFECTED_1)
122DEFINE_DATA_FORM_5_DECODER_THUMB(ADC, ADC, ARM_OPERAND_AFFECTED_1)
123DEFINE_DATA_FORM_5_DECODER_THUMB(SBC, SBC, ARM_OPERAND_AFFECTED_1)
124DEFINE_DATA_FORM_5_DECODER_THUMB(ROR, ROR, ARM_OPERAND_AFFECTED_1)
125DEFINE_DATA_FORM_5_DECODER_THUMB(TST, TST, ARM_OPERAND_NONE)
126DEFINE_DATA_FORM_5_DECODER_THUMB(NEG, NEG, ARM_OPERAND_AFFECTED_1)
127DEFINE_DATA_FORM_5_DECODER_THUMB(CMP2, CMP, ARM_OPERAND_NONE)
128DEFINE_DATA_FORM_5_DECODER_THUMB(CMN, CMN, ARM_OPERAND_NONE)
129DEFINE_DATA_FORM_5_DECODER_THUMB(ORR, ORR, ARM_OPERAND_AFFECTED_1)
130DEFINE_DATA_FORM_5_DECODER_THUMB(MUL, MUL, ARM_OPERAND_AFFECTED_1)
131DEFINE_DATA_FORM_5_DECODER_THUMB(BIC, BIC, ARM_OPERAND_AFFECTED_1)
132DEFINE_DATA_FORM_5_DECODER_THUMB(MVN, MVN, ARM_OPERAND_AFFECTED_1)
133
134#define DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME, H1, H2, MNEMONIC, AFFECTED, CPSR) \
135 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
136 info->op1.reg = (opcode & 0x0007) | H1; \
137 info->op2.reg = ((opcode >> 3) & 0x0007) | H2; \
138 if (info->op1.reg == ARM_PC) { \
139 info->branchType = ARM_BRANCH_INDIRECT; \
140 } \
141 info->affectsCPSR = CPSR; \
142 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
143 AFFECTED | \
144 ARM_OPERAND_REGISTER_2;)
145
146
147#define DEFINE_DECODER_WITH_HIGH_THUMB(NAME, MNEMONIC, AFFECTED, CPSR) \
148 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 00, 0, 0, MNEMONIC, AFFECTED, CPSR) \
149 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 01, 0, 8, MNEMONIC, AFFECTED, CPSR) \
150 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 10, 8, 0, MNEMONIC, AFFECTED, CPSR) \
151 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 11, 8, 8, MNEMONIC, AFFECTED, CPSR)
152
153DEFINE_DECODER_WITH_HIGH_THUMB(ADD4, ADD, ARM_OPERAND_AFFECTED_1, 0)
154DEFINE_DECODER_WITH_HIGH_THUMB(CMP3, CMP, ARM_OPERAND_NONE, 1)
155DEFINE_DECODER_WITH_HIGH_THUMB(MOV3, MOV, ARM_OPERAND_AFFECTED_1, 0)
156
157#define DEFINE_IMMEDIATE_WITH_REGISTER_DATA_THUMB(NAME, RD, MNEMONIC, REG) \
158 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
159 info->op1.reg = RD; \
160 info->op2.reg = REG; \
161 info->op3.immediate = (opcode & 0x00FF) << 2; \
162 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
163 ARM_OPERAND_AFFECTED_1 | \
164 ARM_OPERAND_REGISTER_2 | \
165 ARM_OPERAND_IMMEDIATE_3;)
166
167#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, CYCLES) \
168 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
169 info->op1.reg = RD; \
170 info->memory.baseReg = REG; \
171 info->memory.offset.immediate = (opcode & 0x00FF) << 2; \
172 info->memory.width = ARM_ACCESS_WORD; \
173 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
174 ARM_OPERAND_AFFECTED_1 | \
175 ARM_OPERAND_MEMORY_2; \
176 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
177 ARM_MEMORY_IMMEDIATE_OFFSET; \
178 CYCLES;)
179
180#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_LOAD_THUMB(NAME, RD, MNEMONIC, REG) \
181 DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, LOAD_CYCLES)
182
183#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_STORE_THUMB(NAME, RD, MNEMONIC, REG) \
184 DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, STORE_CYCLES)
185
186#define DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(NAME, MNEMONIC, TYPE, REG) \
187 COUNT_CALL_3(DEFINE_IMMEDIATE_WITH_REGISTER_ ## TYPE ## _THUMB, NAME ## _R, MNEMONIC, REG)
188
189DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR3, LDR, MEM_LOAD, ARM_PC)
190DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR4, LDR, MEM_LOAD, ARM_SP)
191DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(STR3, STR, MEM_STORE, ARM_SP)
192
193DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD5, ADD, DATA, ARM_PC)
194DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD6, ADD, DATA, ARM_SP)
195
196#define DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB(NAME, RM, MNEMONIC, CYCLES, TYPE) \
197 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
198 info->memory.offset.reg = RM; \
199 info->op1.reg = opcode & 0x0007; \
200 info->memory.baseReg = (opcode >> 3) & 0x0007; \
201 info->memory.width = TYPE; \
202 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
203 ARM_OPERAND_AFFECTED_1 | /* TODO: Remove this for STR */ \
204 ARM_OPERAND_MEMORY_2; \
205 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
206 ARM_MEMORY_REGISTER_OFFSET; \
207 CYCLES;)
208
209#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, MNEMONIC, CYCLES, TYPE) \
210 COUNT_CALL_3(DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB, NAME ## _R, MNEMONIC, CYCLES, TYPE)
211
212DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, LDR, LOAD_CYCLES, ARM_ACCESS_WORD)
213DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, LDR, LOAD_CYCLES, ARM_ACCESS_BYTE)
214DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, LDR, LOAD_CYCLES, ARM_ACCESS_HALFWORD)
215DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_BYTE)
216DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_HALFWORD)
217DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, STR, STORE_CYCLES, ARM_ACCESS_WORD)
218DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, STR, STORE_CYCLES, ARM_ACCESS_BYTE)
219DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STR, STORE_CYCLES, ARM_ACCESS_HALFWORD)
220
221// TODO: Estimate memory cycles
222#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, MNEMONIC, DIRECTION, ADDITIONAL_REG) \
223 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
224 info->memory.baseReg = RN; \
225 info->op1.immediate = (opcode & 0xFF) | ADDITIONAL_REG; \
226 if (info->op1.immediate & (1 << ARM_PC)) { \
227 info->branchType = ARM_BRANCH_INDIRECT; \
228 } \
229 info->operandFormat = ARM_OPERAND_MEMORY_1; \
230 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
231 ARM_MEMORY_WRITEBACK | \
232 DIRECTION;)
233
234#define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME) \
235 COUNT_CALL_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## IA_R, NAME, ARM_MEMORY_INCREMENT_AFTER, 0)
236
237DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDM)
238DEFINE_LOAD_STORE_MULTIPLE_THUMB(STM)
239
240#define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \
241 DEFINE_THUMB_DECODER(B ## COND, B, \
242 int8_t immediate = opcode; \
243 info->op1.immediate = immediate << 1; \
244 info->branchType = ARM_BRANCH; \
245 info->condition = ARM_CONDITION_ ## COND; \
246 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;)
247
248DEFINE_CONDITIONAL_BRANCH_THUMB(EQ)
249DEFINE_CONDITIONAL_BRANCH_THUMB(NE)
250DEFINE_CONDITIONAL_BRANCH_THUMB(CS)
251DEFINE_CONDITIONAL_BRANCH_THUMB(CC)
252DEFINE_CONDITIONAL_BRANCH_THUMB(MI)
253DEFINE_CONDITIONAL_BRANCH_THUMB(PL)
254DEFINE_CONDITIONAL_BRANCH_THUMB(VS)
255DEFINE_CONDITIONAL_BRANCH_THUMB(VC)
256DEFINE_CONDITIONAL_BRANCH_THUMB(LS)
257DEFINE_CONDITIONAL_BRANCH_THUMB(HI)
258DEFINE_CONDITIONAL_BRANCH_THUMB(GE)
259DEFINE_CONDITIONAL_BRANCH_THUMB(LT)
260DEFINE_CONDITIONAL_BRANCH_THUMB(GT)
261DEFINE_CONDITIONAL_BRANCH_THUMB(LE)
262
263#define DEFINE_SP_MODIFY_THUMB(NAME, MNEMONIC) \
264 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
265 info->op1.reg = ARM_SP; \
266 info->op2.immediate = (opcode & 0x7F) << 2; \
267 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
268 ARM_OPERAND_AFFECTED_1 | \
269 ARM_OPERAND_IMMEDIATE_2;)
270
271DEFINE_SP_MODIFY_THUMB(ADD7, ADD)
272DEFINE_SP_MODIFY_THUMB(SUB4, SUB)
273
274DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 0)
275DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 1 << ARM_PC)
276DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 0)
277DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 1 << ARM_LR)
278
279DEFINE_THUMB_DECODER(ILL, ILL, info->traps = 1;)
280DEFINE_THUMB_DECODER(BKPT, BKPT, info->traps = 1;)
281
282DEFINE_THUMB_DECODER(B, B,
283 int16_t immediate = (opcode & 0x07FF) << 5;
284 info->op1.immediate = (((int32_t) immediate) >> 4);
285 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
286 info->branchType = ARM_BRANCH;)
287
288DEFINE_THUMB_DECODER(BL1, BLH,
289 int16_t immediate = (opcode & 0x07FF) << 5;
290 info->op1.immediate = (((int32_t) immediate) << 7);
291 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;)
292
293DEFINE_THUMB_DECODER(BL2, BL,
294 info->op1.immediate = (opcode & 0x07FF) << 1;
295 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
296 info->branchType = ARM_BRANCH_LINKED;)
297
298DEFINE_THUMB_DECODER(BX, BX,
299 info->op1.reg = (opcode >> 3) & 0xF;
300 info->operandFormat = ARM_OPERAND_REGISTER_1;
301 info->branchType = ARM_BRANCH_INDIRECT;)
302
303DEFINE_THUMB_DECODER(SWI, SWI,
304 info->op1.immediate = opcode & 0xFF;
305 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
306 info->traps = 1;)
307
308typedef void (*ThumbDecoder)(uint16_t opcode, struct ARMInstructionInfo* info);
309
310static const ThumbDecoder _thumbDecoderTable[0x400] = {
311 DECLARE_THUMB_EMITTER_BLOCK(_ThumbDecode)
312};
313
314void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info) {
315 info->execMode = MODE_THUMB;
316 info->opcode = opcode;
317 info->branchType = ARM_BRANCH_NONE;
318 info->traps = 0;
319 info->affectsCPSR = 0;
320 info->condition = ARM_CONDITION_AL;
321 info->sDataCycles = 0;
322 info->nDataCycles = 0;
323 info->sInstructionCycles = 1;
324 info->nInstructionCycles = 0;
325 info->iCycles = 0;
326 info->cCycles = 0;
327 ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6];
328 decoder(opcode, info);
329}