all repos — mgba @ c62d913e233e7ea3bb23a3f52fcb7b481f2faed5

mGBA Game Boy Advance Emulator

include/mgba/internal/arm/decoder.h (view raw)

  1/* Copyright (c) 2013-2014 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#ifndef ARM_DECODER_H
  7#define ARM_DECODER_H
  8
  9#include <mgba-util/common.h>
 10
 11CXX_GUARD_START
 12
 13#include <mgba/internal/arm/arm.h>
 14
 15// Bit 0: a register is involved with this operand
 16// Bit 1: an immediate is invovled with this operand
 17// Bit 2: a memory access is involved with this operand
 18// Bit 3: the destination of this operand is affected by this opcode
 19// Bit 4: this operand is shifted by a register
 20// Bit 5: this operand is shifted by an immediate
 21// Bit 6: a coprocessor register is involved with this command
 22#define ARM_OPERAND_NONE                0x00000000
 23#define ARM_OPERAND_REGISTER_1          0x00000001
 24#define ARM_OPERAND_IMMEDIATE_1         0x00000002
 25#define ARM_OPERAND_MEMORY_1            0x00000004
 26#define ARM_OPERAND_AFFECTED_1          0x00000008
 27#define ARM_OPERAND_SHIFT_REGISTER_1    0x00000010
 28#define ARM_OPERAND_SHIFT_IMMEDIATE_1   0x00000020
 29#define ARM_OPERAND_COPROCESSOR_REG_1   0x00000040
 30#define ARM_OPERAND_1                   0x000000FF
 31
 32#define ARM_OPERAND_REGISTER_2          0x00000100
 33#define ARM_OPERAND_IMMEDIATE_2         0x00000200
 34#define ARM_OPERAND_MEMORY_2            0x00000400
 35#define ARM_OPERAND_AFFECTED_2          0x00000800
 36#define ARM_OPERAND_SHIFT_REGISTER_2    0x00001000
 37#define ARM_OPERAND_SHIFT_IMMEDIATE_2   0x00002000
 38#define ARM_OPERAND_COPROCESSOR_REG_2   0x00004000
 39#define ARM_OPERAND_2                   0x0000FF00
 40
 41#define ARM_OPERAND_REGISTER_3          0x00010000
 42#define ARM_OPERAND_IMMEDIATE_3         0x00020000
 43#define ARM_OPERAND_MEMORY_3            0x00040000
 44#define ARM_OPERAND_AFFECTED_3          0x00080000
 45#define ARM_OPERAND_SHIFT_REGISTER_3    0x00100000
 46#define ARM_OPERAND_SHIFT_IMMEDIATE_3   0x00200000
 47#define ARM_OPERAND_COPROCESSOR_REG_3   0x00400000
 48#define ARM_OPERAND_3                   0x00FF0000
 49
 50#define ARM_OPERAND_REGISTER_4          0x01000000
 51#define ARM_OPERAND_IMMEDIATE_4         0x02000000
 52#define ARM_OPERAND_MEMORY_4            0x04000000
 53#define ARM_OPERAND_AFFECTED_4          0x08000000
 54#define ARM_OPERAND_SHIFT_REGISTER_4    0x10000000
 55#define ARM_OPERAND_SHIFT_IMMEDIATE_4   0x20000000
 56#define ARM_OPERAND_COPROCESSOR_REG_4   0x40000000
 57#define ARM_OPERAND_4                   0xFF000000
 58
 59#define ARM_OPERAND_MEMORY (ARM_OPERAND_MEMORY_1 | ARM_OPERAND_MEMORY_2 | ARM_OPERAND_MEMORY_3 | ARM_OPERAND_MEMORY_4)
 60#define ARM_OPERAND_COPROCESSOR (ARM_OPERAND_COPROCESSOR_REG_1 | ARM_OPERAND_COPROCESSOR_REG_2 | ARM_OPERAND_COPROCESSOR_REG_3 | ARM_OPERAND_COPROCESSOR_REG_4)
 61
 62#define ARM_MEMORY_REGISTER_BASE     0x0001
 63#define ARM_MEMORY_IMMEDIATE_OFFSET  0x0002
 64#define ARM_MEMORY_REGISTER_OFFSET   0x0004
 65#define ARM_MEMORY_SHIFTED_OFFSET    0x0008
 66#define ARM_MEMORY_PRE_INCREMENT     0x0010
 67#define ARM_MEMORY_POST_INCREMENT    0x0020
 68#define ARM_MEMORY_OFFSET_SUBTRACT   0x0040
 69#define ARM_MEMORY_WRITEBACK         0x0080
 70#define ARM_MEMORY_DECREMENT_AFTER   0x0000
 71#define ARM_MEMORY_INCREMENT_AFTER   0x0100
 72#define ARM_MEMORY_DECREMENT_BEFORE  0x0200
 73#define ARM_MEMORY_INCREMENT_BEFORE  0x0300
 74#define ARM_MEMORY_SPSR_SWAP         0x0400
 75
 76#define ARM_PSR_C 1
 77#define ARM_PSR_X 2
 78#define ARM_PSR_S 4
 79#define ARM_PSR_F 8
 80#define ARM_PSR_MASK 0xF
 81
 82#define MEMORY_FORMAT_TO_DIRECTION(F) (((F) >> 8) & 0x3)
 83
 84enum ARMCondition {
 85	ARM_CONDITION_EQ = 0x0,
 86	ARM_CONDITION_NE = 0x1,
 87	ARM_CONDITION_CS = 0x2,
 88	ARM_CONDITION_CC = 0x3,
 89	ARM_CONDITION_MI = 0x4,
 90	ARM_CONDITION_PL = 0x5,
 91	ARM_CONDITION_VS = 0x6,
 92	ARM_CONDITION_VC = 0x7,
 93	ARM_CONDITION_HI = 0x8,
 94	ARM_CONDITION_LS = 0x9,
 95	ARM_CONDITION_GE = 0xA,
 96	ARM_CONDITION_LT = 0xB,
 97	ARM_CONDITION_GT = 0xC,
 98	ARM_CONDITION_LE = 0xD,
 99	ARM_CONDITION_AL = 0xE,
100	ARM_CONDITION_NV = 0xF
101};
102
103enum ARMShifterOperation {
104	ARM_SHIFT_NONE = 0,
105	ARM_SHIFT_LSL,
106	ARM_SHIFT_LSR,
107	ARM_SHIFT_ASR,
108	ARM_SHIFT_ROR,
109	ARM_SHIFT_RRX
110};
111
112union ARMOperand {
113	struct {
114		uint8_t reg;
115		uint8_t shifterOp;
116		union {
117			uint8_t shifterReg;
118			uint8_t shifterImm;
119			uint8_t psrBits;
120		};
121	};
122	int32_t immediate;
123};
124
125struct ARMCoprocessor {
126	uint8_t cp : 4;
127	uint8_t op1 : 4;
128	uint8_t op2 : 3;
129};
130
131enum ARMMemoryAccessType {
132	ARM_ACCESS_WORD = 4,
133	ARM_ACCESS_HALFWORD = 2,
134	ARM_ACCESS_SIGNED_HALFWORD = 10,
135	ARM_ACCESS_BYTE = 1,
136	ARM_ACCESS_SIGNED_BYTE = 9,
137	ARM_ACCESS_TRANSLATED_WORD = 20,
138	ARM_ACCESS_TRANSLATED_BYTE = 17,
139	ARM_ACCESS_DUALWORD = 32,
140};
141
142enum ARMBranchType {
143	ARM_BRANCH_NONE = 0,
144	ARM_BRANCH = 1,
145	ARM_BRANCH_INDIRECT = 2,
146	ARM_BRANCH_LINKED = 4
147};
148
149struct ARMMemoryAccess {
150	uint8_t baseReg;
151	uint8_t width;
152	uint16_t format;
153	union ARMOperand offset;
154};
155
156enum ARMMnemonic {
157	ARM_MN_ILL = 0,
158	ARM_MN_ADC,
159	ARM_MN_ADD,
160	ARM_MN_AND,
161	ARM_MN_ASR,
162	ARM_MN_B,
163	ARM_MN_BIC,
164	ARM_MN_BKPT,
165	ARM_MN_BL,
166	ARM_MN_BLX,
167	ARM_MN_BX,
168	ARM_MN_CDP,
169	ARM_MN_CLZ,
170	ARM_MN_CMN,
171	ARM_MN_CMP,
172	ARM_MN_EOR,
173	ARM_MN_LDC,
174	ARM_MN_LDM,
175	ARM_MN_LDR,
176	ARM_MN_LSL,
177	ARM_MN_LSR,
178	ARM_MN_MCR,
179	ARM_MN_MLA,
180	ARM_MN_MOV,
181	ARM_MN_MRC,
182	ARM_MN_MRS,
183	ARM_MN_MSR,
184	ARM_MN_MUL,
185	ARM_MN_MVN,
186	ARM_MN_NEG,
187	ARM_MN_ORR,
188	ARM_MN_ROR,
189	ARM_MN_RSB,
190	ARM_MN_RSC,
191	ARM_MN_SBC,
192	ARM_MN_SMLABB,
193	ARM_MN_SMLABT,
194	ARM_MN_SMLAL,
195	ARM_MN_SMLATB,
196	ARM_MN_SMLATT,
197	ARM_MN_SMLAWB,
198	ARM_MN_SMLAWT,
199	ARM_MN_SMULBB,
200	ARM_MN_SMULBT,
201	ARM_MN_SMULL,
202	ARM_MN_SMULTB,
203	ARM_MN_SMULTT,
204	ARM_MN_SMULWB,
205	ARM_MN_SMULWT,
206	ARM_MN_STC,
207	ARM_MN_STM,
208	ARM_MN_STR,
209	ARM_MN_SUB,
210	ARM_MN_SWI,
211	ARM_MN_SWP,
212	ARM_MN_TEQ,
213	ARM_MN_TST,
214	ARM_MN_UMLAL,
215	ARM_MN_UMULL,
216
217	ARM_MN_MAX
218};
219
220enum {
221	ARM_CPSR = 16,
222	ARM_SPSR = 17
223};
224
225struct ARMInstructionInfo {
226	uint32_t opcode;
227	union ARMOperand op1;
228	union ARMOperand op2;
229	union ARMOperand op3;
230	union ARMOperand op4;
231	struct ARMMemoryAccess memory;
232	int operandFormat;
233	unsigned execMode : 1;
234	bool traps : 1;
235	bool affectsCPSR : 1;
236	unsigned branchType : 3;
237	unsigned condition : 4;
238	unsigned mnemonic : 6;
239	unsigned iCycles : 3;
240	unsigned cCycles : 4;
241	unsigned sInstructionCycles : 4;
242	unsigned nInstructionCycles : 4;
243	unsigned sDataCycles : 10;
244	unsigned nDataCycles : 10;
245	struct ARMCoprocessor cp;
246};
247
248void ARMDecodeARM(uint32_t opcode, struct ARMInstructionInfo* info);
249void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info);
250bool ARMDecodeThumbCombine(struct ARMInstructionInfo* info1, struct ARMInstructionInfo* info2,
251                           struct ARMInstructionInfo* out);
252int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, int blen);
253
254CXX_GUARD_END
255
256#endif