all repos — mgba @ e7bd5f9ade967c2bea151633b9336144b246576b

mGBA Game Boy Advance Emulator

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}