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