all repos — mgba @ 66191ee92ad59de627c31d0219075df90f16b34a

mGBA Game Boy Advance Emulator

src/arm/decoder-thumb.c (view raw)

  1#include "decoder.h"
  2
  3#include "arm.h"
  4#include "decoder-inlines.h"
  5#include "emitter-thumb.h"
  6#include "isa-inlines.h"
  7
  8#include <stdio.h>
  9#include <string.h>
 10
 11#define DEFINE_THUMB_DECODER(NAME, MNEMONIC, BODY) \
 12	static void _ThumbDecode ## NAME (uint16_t opcode, struct ARMInstructionInfo* info) { \
 13		UNUSED(opcode); \
 14		info->mnemonic = ARM_MN_ ## MNEMONIC; \
 15		BODY; \
 16	}
 17
 18#define DEFINE_IMMEDIATE_5_DECODER_DATA_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \
 19	DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
 20		info->op3.immediate = IMMEDIATE; \
 21		info->op1.reg = opcode & 0x0007; \
 22		info->op2.reg = (opcode >> 3) & 0x0007; \
 23		info->affectsCPSR = 1; \
 24		info->operandFormat = ARM_OPERAND_REGISTER_1 | \
 25			ARM_OPERAND_AFFECTED_1 | \
 26			ARM_OPERAND_REGISTER_2 | \
 27			ARM_OPERAND_IMMEDIATE_3;)
 28
 29#define DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, CYCLES, WIDTH) \
 30	DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
 31		info->op1.reg = opcode & 0x0007; \
 32		info->memory.baseReg = (opcode >> 3) & 0x0007; \
 33		info->memory.offset.immediate = IMMEDIATE * WIDTH; \
 34		info->memory.width = (enum ARMMemoryAccessType) WIDTH; \
 35		info->operandFormat = ARM_OPERAND_REGISTER_1 | \
 36			ARM_OPERAND_AFFECTED_1 | \
 37			ARM_OPERAND_MEMORY_2; \
 38		info->memory.format = ARM_MEMORY_REGISTER_BASE | \
 39			ARM_MEMORY_IMMEDIATE_OFFSET; \
 40		CYCLES)
 41
 42#define DEFINE_IMMEDIATE_5_DECODER_MEM_LOAD_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \
 43	DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, LOAD_CYCLES, WIDTH)
 44
 45#define DEFINE_IMMEDIATE_5_DECODER_MEM_STORE_THUMB(NAME, IMMEDIATE, MNEMONIC, WIDTH) \
 46	DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, IMMEDIATE, MNEMONIC, STORE_CYCLES, WIDTH)
 47
 48#define DEFINE_IMMEDIATE_5_DECODER_THUMB(NAME, MNEMONIC, TYPE, WIDTH) \
 49	COUNT_5(DEFINE_IMMEDIATE_5_DECODER_ ## TYPE ## _THUMB, NAME ## _, MNEMONIC, WIDTH)
 50
 51DEFINE_IMMEDIATE_5_DECODER_THUMB(LSL1, LSL, DATA,)
 52DEFINE_IMMEDIATE_5_DECODER_THUMB(LSR1, LSR, DATA,)
 53DEFINE_IMMEDIATE_5_DECODER_THUMB(ASR1, ASR, DATA,)
 54DEFINE_IMMEDIATE_5_DECODER_THUMB(LDR1, LDR, MEM_LOAD, 4)
 55DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRB1, LDR, MEM_LOAD, 1)
 56DEFINE_IMMEDIATE_5_DECODER_THUMB(LDRH1, LDR, MEM_LOAD, 2)
 57DEFINE_IMMEDIATE_5_DECODER_THUMB(STR1, STR, MEM_STORE, 4)
 58DEFINE_IMMEDIATE_5_DECODER_THUMB(STRB1, STR, MEM_STORE, 1)
 59DEFINE_IMMEDIATE_5_DECODER_THUMB(STRH1, STR, MEM_STORE, 2)
 60
 61#define DEFINE_DATA_FORM_1_DECODER_EX_THUMB(NAME, RM, MNEMONIC) \
 62	DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
 63		info->op1.reg = opcode & 0x0007; \
 64		info->op2.reg = (opcode >> 3) & 0x0007; \
 65		info->op3.reg = RM; \
 66		info->affectsCPSR = 1; \
 67		info->operandFormat = ARM_OPERAND_REGISTER_1 | \
 68			ARM_OPERAND_AFFECTED_1 | \
 69			ARM_OPERAND_REGISTER_2 | \
 70			ARM_OPERAND_REGISTER_3;)
 71
 72#define DEFINE_DATA_FORM_1_DECODER_THUMB(NAME) \
 73	COUNT_3(DEFINE_DATA_FORM_1_DECODER_EX_THUMB, NAME ## 3_R, NAME)
 74
 75DEFINE_DATA_FORM_1_DECODER_THUMB(ADD)
 76DEFINE_DATA_FORM_1_DECODER_THUMB(SUB)
 77
 78#define DEFINE_DATA_FORM_2_DECODER_EX_THUMB(NAME, IMMEDIATE, MNEMONIC) \
 79	DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
 80		info->op1.reg = opcode & 0x0007; \
 81		info->op2.reg = (opcode >> 3) & 0x0007; \
 82		info->op3.immediate = IMMEDIATE; \
 83		info->affectsCPSR = 1; \
 84		info->operandFormat = ARM_OPERAND_REGISTER_1 | \
 85			ARM_OPERAND_AFFECTED_1 | \
 86			ARM_OPERAND_REGISTER_2 | \
 87			ARM_OPERAND_IMMEDIATE_3;)
 88
 89#define DEFINE_DATA_FORM_2_DECODER_THUMB(NAME) \
 90	COUNT_3(DEFINE_DATA_FORM_2_DECODER_EX_THUMB, NAME ## 1_, NAME)
 91
 92DEFINE_DATA_FORM_2_DECODER_THUMB(ADD)
 93DEFINE_DATA_FORM_2_DECODER_THUMB(SUB)
 94
 95#define DEFINE_DATA_FORM_3_DECODER_EX_THUMB(NAME, RD, MNEMONIC, AFFECTED) \
 96	DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
 97		info->op1.reg = RD; \
 98		info->op2.immediate = opcode & 0x00FF; \
 99		info->affectsCPSR = 1; \
100		info->operandFormat = ARM_OPERAND_REGISTER_1 | \
101			AFFECTED | \
102			ARM_OPERAND_IMMEDIATE_2;)
103
104#define DEFINE_DATA_FORM_3_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \
105	COUNT_3(DEFINE_DATA_FORM_3_DECODER_EX_THUMB, NAME ## _R, MNEMONIC, AFFECTED)
106
107DEFINE_DATA_FORM_3_DECODER_THUMB(ADD2, ADD, ARM_OPERAND_AFFECTED_1)
108DEFINE_DATA_FORM_3_DECODER_THUMB(CMP1, CMP, ARM_OPERAND_NONE)
109DEFINE_DATA_FORM_3_DECODER_THUMB(MOV1, MOV, ARM_OPERAND_AFFECTED_1)
110DEFINE_DATA_FORM_3_DECODER_THUMB(SUB2, SUB, ARM_OPERAND_AFFECTED_1)
111
112#define DEFINE_DATA_FORM_5_DECODER_THUMB(NAME, MNEMONIC, AFFECTED) \
113	DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
114		info->op1.reg = opcode & 0x0007; \
115		info->op2.reg = (opcode >> 3) & 0x0007; \
116		info->affectsCPSR = 1; \
117		info->operandFormat = ARM_OPERAND_REGISTER_1 | \
118			AFFECTED | \
119			ARM_OPERAND_REGISTER_2;)
120
121DEFINE_DATA_FORM_5_DECODER_THUMB(AND, AND, ARM_OPERAND_AFFECTED_1)
122DEFINE_DATA_FORM_5_DECODER_THUMB(EOR, EOR, ARM_OPERAND_AFFECTED_1)
123DEFINE_DATA_FORM_5_DECODER_THUMB(LSL2, LSL, ARM_OPERAND_AFFECTED_1)
124DEFINE_DATA_FORM_5_DECODER_THUMB(LSR2, LSR, ARM_OPERAND_AFFECTED_1)
125DEFINE_DATA_FORM_5_DECODER_THUMB(ASR2, ASR, ARM_OPERAND_AFFECTED_1)
126DEFINE_DATA_FORM_5_DECODER_THUMB(ADC, ADC, ARM_OPERAND_AFFECTED_1)
127DEFINE_DATA_FORM_5_DECODER_THUMB(SBC, SBC, ARM_OPERAND_AFFECTED_1)
128DEFINE_DATA_FORM_5_DECODER_THUMB(ROR, ROR, ARM_OPERAND_AFFECTED_1)
129DEFINE_DATA_FORM_5_DECODER_THUMB(TST, TST, ARM_OPERAND_NONE)
130DEFINE_DATA_FORM_5_DECODER_THUMB(NEG, NEG, ARM_OPERAND_AFFECTED_1)
131DEFINE_DATA_FORM_5_DECODER_THUMB(CMP2, CMP, ARM_OPERAND_NONE)
132DEFINE_DATA_FORM_5_DECODER_THUMB(CMN, CMN, ARM_OPERAND_NONE)
133DEFINE_DATA_FORM_5_DECODER_THUMB(ORR, ORR, ARM_OPERAND_AFFECTED_1)
134DEFINE_DATA_FORM_5_DECODER_THUMB(MUL, MUL, ARM_OPERAND_AFFECTED_1)
135DEFINE_DATA_FORM_5_DECODER_THUMB(BIC, BIC, ARM_OPERAND_AFFECTED_1)
136DEFINE_DATA_FORM_5_DECODER_THUMB(MVN, MVN, ARM_OPERAND_AFFECTED_1)
137
138#define DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME, H1, H2, MNEMONIC, AFFECTED, CPSR) \
139	DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
140		info->op1.reg = (opcode & 0x0007) | H1; \
141		info->op2.reg = ((opcode >> 3) & 0x0007) | H2; \
142		info->branches = info->op1.reg == ARM_PC; \
143		info->affectsCPSR = CPSR; \
144		info->operandFormat = ARM_OPERAND_REGISTER_1 | \
145			AFFECTED | \
146			ARM_OPERAND_REGISTER_2;)
147
148
149#define DEFINE_DECODER_WITH_HIGH_THUMB(NAME, MNEMONIC, AFFECTED, CPSR) \
150	DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 00, 0, 0, MNEMONIC, AFFECTED, CPSR) \
151	DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 01, 0, 8, MNEMONIC, AFFECTED, CPSR) \
152	DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 10, 8, 0, MNEMONIC, AFFECTED, CPSR) \
153	DEFINE_DECODER_WITH_HIGH_EX_THUMB(NAME ## 11, 8, 8, MNEMONIC, AFFECTED, CPSR)
154
155DEFINE_DECODER_WITH_HIGH_THUMB(ADD4, ADD, ARM_OPERAND_AFFECTED_1, 0)
156DEFINE_DECODER_WITH_HIGH_THUMB(CMP3, CMP, ARM_OPERAND_NONE, 1)
157DEFINE_DECODER_WITH_HIGH_THUMB(MOV3, MOV, ARM_OPERAND_AFFECTED_1, 0)
158
159#define DEFINE_IMMEDIATE_WITH_REGISTER_DATA_THUMB(NAME, RD, MNEMONIC, REG) \
160	DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
161		info->op1.reg = RD; \
162		info->op2.reg = REG; \
163		info->op3.immediate = (opcode & 0x00FF) << 2; \
164		info->operandFormat = ARM_OPERAND_REGISTER_1 | \
165			ARM_OPERAND_AFFECTED_1 | \
166			ARM_OPERAND_REGISTER_2 | \
167			ARM_OPERAND_IMMEDIATE_3;)
168
169#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, CYCLES) \
170	DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
171		info->op1.reg = RD; \
172		info->memory.baseReg = REG; \
173		info->memory.offset.immediate = (opcode & 0x00FF) << 2; \
174		info->memory.width = ARM_ACCESS_WORD; \
175		info->operandFormat = ARM_OPERAND_REGISTER_1 | \
176			ARM_OPERAND_AFFECTED_1 | \
177			ARM_OPERAND_MEMORY_2; \
178		info->memory.format = ARM_MEMORY_REGISTER_BASE | \
179			ARM_MEMORY_IMMEDIATE_OFFSET; \
180		CYCLES;)
181
182#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_LOAD_THUMB(NAME, RD, MNEMONIC, REG) \
183	DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, LOAD_CYCLES)
184
185#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_STORE_THUMB(NAME, RD, MNEMONIC, REG) \
186	DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, RD, MNEMONIC, REG, STORE_CYCLES)
187
188#define DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(NAME, MNEMONIC, TYPE, REG) \
189	COUNT_3(DEFINE_IMMEDIATE_WITH_REGISTER_ ## TYPE ## _THUMB, NAME ## _R, MNEMONIC, REG)
190
191DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR3, LDR, MEM_LOAD, ARM_PC)
192DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(LDR4, LDR, MEM_LOAD, ARM_SP)
193DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(STR3, STR, MEM_STORE, ARM_SP)
194
195DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD5, ADD, DATA, ARM_PC)
196DEFINE_IMMEDIATE_WITH_REGISTER_THUMB(ADD6, ADD, DATA, ARM_SP)
197
198#define DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB(NAME, RM, MNEMONIC, CYCLES, TYPE) \
199	DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
200		info->memory.offset.reg = RM; \
201		info->op1.reg = opcode & 0x0007; \
202		info->memory.baseReg = (opcode >> 3) & 0x0007; \
203		info->memory.width = TYPE; \
204		info->operandFormat = ARM_OPERAND_REGISTER_1 | \
205			ARM_OPERAND_AFFECTED_1 | /* TODO: Remove this for STR */ \
206			ARM_OPERAND_MEMORY_2; \
207		info->memory.format = ARM_MEMORY_REGISTER_BASE | \
208			ARM_MEMORY_REGISTER_OFFSET; \
209		CYCLES;)
210
211#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, MNEMONIC, CYCLES, TYPE) \
212	COUNT_3(DEFINE_LOAD_STORE_WITH_REGISTER_EX_THUMB, NAME ## _R, MNEMONIC, CYCLES, TYPE)
213
214DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, LDR, LOAD_CYCLES, ARM_ACCESS_WORD)
215DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, LDR, LOAD_CYCLES, ARM_ACCESS_BYTE)
216DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, LDR, LOAD_CYCLES, ARM_ACCESS_HALFWORD)
217DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_BYTE)
218DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_HALFWORD)
219DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, STR, STORE_CYCLES, ARM_ACCESS_WORD)
220DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, STR, STORE_CYCLES, ARM_ACCESS_BYTE)
221DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STR, STORE_CYCLES, ARM_ACCESS_HALFWORD)
222
223// TODO: Estimate memory cycles
224#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, MNEMONIC, DIRECTION, ADDITIONAL_REG) \
225	DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
226		info->memory.baseReg = RN; \
227		info->op1.immediate = (opcode & 0xFF) | ADDITIONAL_REG; \
228		info->branches = info->op1.immediate & (1 << ARM_PC); \
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_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->branches = 1; \
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->branches = 1;)
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->branches = 1;)
297
298DEFINE_THUMB_DECODER(BX, BX,
299	info->op1.reg = (opcode >> 3) & 0xF;
300	info->operandFormat = ARM_OPERAND_REGISTER_1;
301	info->branches = 1;)
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->branches = 0;
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}