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 info->branches = info->op1.reg == ARM_PC; \
139 info->affectsCPSR = CPSR; \
140 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
141 AFFECTED | \
142 ARM_OPERAND_REGISTER_2;)
143
144
145#define DEFINE_DECODER_WITH_HIGH_THUMB(NAME, MNEMONIC, AFFECTED, CPSR) \
146 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 00, 0, 0, MNEMONIC, AFFECTED, CPSR) \
147 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 01, 0, 8, MNEMONIC, AFFECTED, CPSR) \
148 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 10, 8, 0, MNEMONIC, AFFECTED, CPSR) \
149 DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 11, 8, 8, MNEMONIC, AFFECTED, CPSR)
150
151DEFINE_DECODER_WITH_HIGH_THUMB(ADD4, ADD, ARM_OPERAND_AFFECTED_1, 0)
152DEFINE_DECODER_WITH_HIGH_THUMB(CMP3, CMP, ARM_OPERAND_NONE, 1)
153DEFINE_DECODER_WITH_HIGH_THUMB(MOV3, MOV, ARM_OPERAND_AFFECTED_1, 0)
154
155#define DEFINE_IMMEDIATE_WITH_REGISTER_DATA_THUMB(NAME, RD, MNEMONIC, REG) \
156 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
157 info->op1.reg = RD; \
158 info->op2.reg = REG; \
159 info->op3.immediate = (opcode & 0x00FF) << 2; \
160 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
161 ARM_OPERAND_AFFECTED_1 | \
162 ARM_OPERAND_REGISTER_2 | \
163 ARM_OPERAND_IMMEDIATE_3;)
164
165#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, CYCLES) \
166 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
167 info->op1.reg = RD; \
168 info->memory.baseReg = REG; \
169 info->memory.offset.immediate = (opcode & 0x00FF) << 2; \
170 info->memory.width = ARM_ACCESS_WORD; \
171 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
172 ARM_OPERAND_AFFECTED_1 | \
173 ARM_OPERAND_MEMORY_2; \
174 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
175 ARM_MEMORY_IMMEDIATE_OFFSET; \
176 CYCLES;)
177
178#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_LOAD_THUMB(NAME, RD, MNEMONIC, REG) \
179 DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, LOAD_CYCLES)
180
181#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_STORE_THUMB(NAME, RD, MNEMONIC, REG) \
182 DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, STORE_CYCLES)
183
184#define DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(NAME, MNEMONIC, TYPE, REG) \
185 COUNT_CALL_3(DEFINE_IMMEDIATE_WITH_REGISTER_ ## TYPE ## _THUMB, NAME ## _R, MNEMONIC, REG)
186
187DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR3, LDR, MEM_LOAD, ARM_PC)
188DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR4, LDR, MEM_LOAD, ARM_SP)
189DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(STR3, STR, MEM_STORE, ARM_SP)
190
191DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD5, ADD, DATA, ARM_PC)
192DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD6, ADD, DATA, ARM_SP)
193
194#define DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB(NAME, RM, MNEMONIC, CYCLES, TYPE) \
195 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
196 info->memory.offset.reg = RM; \
197 info->op1.reg = opcode & 0x0007; \
198 info->memory.baseReg = (opcode >> 3) & 0x0007; \
199 info->memory.width = TYPE; \
200 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
201 ARM_OPERAND_AFFECTED_1 | /* TODO: Remove this for STR */ \
202 ARM_OPERAND_MEMORY_2; \
203 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
204 ARM_MEMORY_REGISTER_OFFSET; \
205 CYCLES;)
206
207#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, MNEMONIC, CYCLES, TYPE) \
208 COUNT_CALL_3(DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB, NAME ## _R, MNEMONIC, CYCLES, TYPE)
209
210DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, LDR, LOAD_CYCLES, ARM_ACCESS_WORD)
211DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, LDR, LOAD_CYCLES, ARM_ACCESS_BYTE)
212DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, LDR, LOAD_CYCLES, ARM_ACCESS_HALFWORD)
213DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_BYTE)
214DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_HALFWORD)
215DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, STR, STORE_CYCLES, ARM_ACCESS_WORD)
216DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, STR, STORE_CYCLES, ARM_ACCESS_BYTE)
217DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STR, STORE_CYCLES, ARM_ACCESS_HALFWORD)
218
219// TODO: Estimate memory cycles
220#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, MNEMONIC, DIRECTION, ADDITIONAL_REG) \
221 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
222 info->memory.baseReg = RN; \
223 info->op1.immediate = (opcode & 0xFF) | ADDITIONAL_REG; \
224 info->branches = info->op1.immediate & (1 << ARM_PC); \
225 info->operandFormat = ARM_OPERAND_MEMORY_1; \
226 info->memory.format = ARM_MEMORY_REGISTER_BASE | \
227 ARM_MEMORY_WRITEBACK | \
228 DIRECTION;)
229
230#define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME) \
231 COUNT_CALL_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## IA_R, NAME, ARM_MEMORY_INCREMENT_AFTER, 0)
232
233DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDM)
234DEFINE_LOAD_STORE_MULTIPLE_THUMB(STM)
235
236#define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \
237 DEFINE_THUMB_DECODER(B ## COND, B, \
238 int8_t immediate = opcode; \
239 info->op1.immediate = immediate << 1; \
240 info->branches = 1; \
241 info->condition = ARM_CONDITION_ ## COND; \
242 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;)
243
244DEFINE_CONDITIONAL_BRANCH_THUMB(EQ)
245DEFINE_CONDITIONAL_BRANCH_THUMB(NE)
246DEFINE_CONDITIONAL_BRANCH_THUMB(CS)
247DEFINE_CONDITIONAL_BRANCH_THUMB(CC)
248DEFINE_CONDITIONAL_BRANCH_THUMB(MI)
249DEFINE_CONDITIONAL_BRANCH_THUMB(PL)
250DEFINE_CONDITIONAL_BRANCH_THUMB(VS)
251DEFINE_CONDITIONAL_BRANCH_THUMB(VC)
252DEFINE_CONDITIONAL_BRANCH_THUMB(LS)
253DEFINE_CONDITIONAL_BRANCH_THUMB(HI)
254DEFINE_CONDITIONAL_BRANCH_THUMB(GE)
255DEFINE_CONDITIONAL_BRANCH_THUMB(LT)
256DEFINE_CONDITIONAL_BRANCH_THUMB(GT)
257DEFINE_CONDITIONAL_BRANCH_THUMB(LE)
258
259#define DEFINE_SP_MODIFY_THUMB(NAME, MNEMONIC) \
260 DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
261 info->op1.reg = ARM_SP; \
262 info->op2.immediate = (opcode & 0x7F) << 2; \
263 info->operandFormat = ARM_OPERAND_REGISTER_1 | \
264 ARM_OPERAND_AFFECTED_1 | \
265 ARM_OPERAND_IMMEDIATE_2;)
266
267DEFINE_SP_MODIFY_THUMB(ADD7, ADD)
268DEFINE_SP_MODIFY_THUMB(SUB4, SUB)
269
270DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 0)
271DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 1 << ARM_PC)
272DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 0)
273DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 1 << ARM_LR)
274
275DEFINE_THUMB_DECODER(ILL, ILL, info->traps = 1;)
276DEFINE_THUMB_DECODER(BKPT, BKPT, info->traps = 1;)
277
278DEFINE_THUMB_DECODER(B, B,
279 int16_t immediate = (opcode & 0x07FF) << 5;
280 info->op1.immediate = (((int32_t) immediate) >> 4);
281 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
282 info->branches = 1;)
283
284DEFINE_THUMB_DECODER(BL1, BLH,
285 int16_t immediate = (opcode & 0x07FF) << 5;
286 info->op1.immediate = (((int32_t) immediate) << 7);
287 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;)
288
289DEFINE_THUMB_DECODER(BL2, BL,
290 info->op1.immediate = (opcode & 0x07FF) << 1;
291 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
292 info->branches = 1;)
293
294DEFINE_THUMB_DECODER(BX, BX,
295 info->op1.reg = (opcode >> 3) & 0xF;
296 info->operandFormat = ARM_OPERAND_REGISTER_1;
297 info->branches = 1;)
298
299DEFINE_THUMB_DECODER(SWI, SWI,
300 info->op1.immediate = opcode & 0xFF;
301 info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
302 info->traps = 1;)
303
304typedef void (*ThumbDecoder)(uint16_t opcode, struct ARMInstructionInfo* info);
305
306static const ThumbDecoder _thumbDecoderTable[0x400] = {
307 DECLARE_THUMB_EMITTER_BLOCK(_ThumbDecode)
308};
309
310void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info) {
311 info->execMode = MODE_THUMB;
312 info->opcode = opcode;
313 info->branches = 0;
314 info->traps = 0;
315 info->affectsCPSR = 0;
316 info->condition = ARM_CONDITION_AL;
317 info->sDataCycles = 0;
318 info->nDataCycles = 0;
319 info->sInstructionCycles = 1;
320 info->nInstructionCycles = 0;
321 info->iCycles = 0;
322 info->cCycles = 0;
323 ThumbDecoder decoder = _thumbDecoderTable[opcode >> 6];
324 decoder(opcode, info);
325}