nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | Copyright (c) 2013, Jurriaan Bremer |
||
3 | All rights reserved. |
||
4 | |||
5 | Redistribution and use in source and binary forms, with or without |
||
6 | modification, are permitted provided that the following conditions are met: |
||
7 | |||
8 | * Redistributions of source code must retain the above copyright notice, |
||
9 | this list of conditions and the following disclaimer. |
||
10 | * Redistributions in binary form must reproduce the above copyright notice, |
||
11 | this list of conditions and the following disclaimer in the documentation |
||
12 | and/or other materials provided with the distribution. |
||
13 | * Neither the name of the darm developer(s) nor the names of its |
||
14 | contributors may be used to endorse or promote products derived from this |
||
15 | software without specific prior written permission. |
||
16 | |||
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
||
21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
27 | POSSIBILITY OF SUCH DAMAGE. |
||
28 | */ |
||
29 | |||
30 | #ifndef __DARM__ |
||
31 | #define __DARM__ |
||
32 | |||
33 | #include "armv7-tbl.h" |
||
34 | |||
35 | #ifndef ARRAYSIZE |
||
36 | #define ARRAYSIZE(arr) (sizeof(arr) / sizeof((arr)[0])) |
||
37 | #endif |
||
38 | |||
39 | #define B_UNSET 0 |
||
40 | #define B_SET 1 |
||
41 | #define B_INVLD 2 |
||
42 | |||
43 | typedef enum _darm_reg_t { |
||
44 | r0 = 0, r1 = 1, r2 = 2, r3 = 3, r4 = 4, r5 = 5, r6 = 6, r7 = 7, r8 = 8, |
||
45 | r9 = 9, r10 = 10, r11 = 11, r12 = 12, r13 = 13, r14 = 14, r15 = 15, |
||
46 | |||
47 | FP = 11, IP = 12, SP = 13, LR = 14, PC = 15, |
||
48 | |||
49 | cr0 = 0, cr1 = 1, cr2 = 2, cr3 = 3, cr4 = 4, cr5 = 5, cr6 = 6, cr7 = 7, |
||
50 | cr8 = 8, cr9 = 9, cr10 = 10, cr11 = 11, cr12 = 12, cr13 = 13, cr14 = 14, |
||
51 | cr15 = 15, |
||
52 | |||
53 | R_INVLD = -1 |
||
54 | } darm_reg_t; |
||
55 | |||
56 | typedef enum _darm_cond_t { |
||
57 | C_EQ = 0, C_NE = 1, C_CS = 2, C_CC = 3, C_MI = 4, |
||
58 | C_PL = 5, C_VS = 6, C_VC = 7, C_HI = 8, C_LS = 9, |
||
59 | C_GE = 10, C_LT = 11, C_GT = 12, C_LE = 13, C_AL = 14, |
||
60 | |||
61 | C_HS = C_CS, C_LO = C_CC, |
||
62 | C_UNCOND = 15, |
||
63 | |||
64 | C_INVLD = -1 |
||
65 | } darm_cond_t; |
||
66 | |||
67 | typedef enum _darm_shift_type_t { |
||
68 | S_LSL = 0, S_LSR = 1, S_ASR = 2, S_ROR = 3, |
||
69 | |||
70 | S_INVLD = -1, |
||
71 | } darm_shift_type_t; |
||
72 | |||
73 | typedef enum _darm_option_t { |
||
74 | O_SY = 15, // b1111 |
||
75 | O_ST = 14, // b1110 |
||
76 | O_ISH = 11, // b1011 |
||
77 | O_ISHST = 10, // b1010 |
||
78 | O_NSH = 7, // b0111 |
||
79 | O_NSHST = 6, // b0110 |
||
80 | O_OSH = 3, // b0011 |
||
81 | O_OSHST = 2, // b0010 |
||
82 | |||
83 | O_INVLD = -1, |
||
84 | } darm_option_t; |
||
85 | |||
86 | typedef struct _darm_t { |
||
87 | // the original encoded instruction |
||
88 | uint32_t w; |
||
89 | |||
90 | // the instruction label |
||
91 | darm_instr_t instr; |
||
92 | darm_enctype_t instr_type; |
||
93 | darm_enctype_t instr_imm_type; // thumb2 immediate type |
||
94 | darm_enctype_t instr_flag_type; // thumb2 flag type |
||
95 | |||
96 | // conditional flags, if any |
||
97 | darm_cond_t cond; |
||
98 | |||
99 | // if set, swap only one byte, otherwise swap four bytes |
||
100 | uint32_t B; |
||
101 | |||
102 | // does this instruction update the conditional flags? |
||
103 | uint32_t S; |
||
104 | |||
105 | // endian specifier for the SETEND instruction |
||
106 | uint32_t E; |
||
107 | |||
108 | // whether halfwords should be swapped before various signed |
||
109 | // multiplication operations |
||
110 | uint32_t M; |
||
111 | |||
112 | // specifies, together with the M flag, which half of the source |
||
113 | // operand is used to multiply |
||
114 | uint32_t N; |
||
115 | |||
116 | // option operand for the DMB, DSB and ISB instructions |
||
117 | darm_option_t option; |
||
118 | |||
119 | // to add or to subtract the immediate, this is used for instructions |
||
120 | // which take a relative offset to a pointer or to the program counter |
||
121 | uint32_t U; |
||
122 | |||
123 | // the bit for the unconditional BLX instruction which allows one to |
||
124 | // branch with link to a 2-byte aligned thumb2 instruction |
||
125 | uint32_t H; |
||
126 | |||
127 | // specifies whether this instruction uses pre-indexed addressing or |
||
128 | // post-indexed addressing |
||
129 | uint32_t P; |
||
130 | |||
131 | // specifies whether signed multiplication results should be rounded |
||
132 | // or not |
||
133 | uint32_t R; |
||
134 | |||
135 | // the PKH instruction has two variants, namely, PKHBT and PKHTB, the |
||
136 | // tbform is represented by T, i.e., if T = 1 then the instruction is |
||
137 | // PKHTB, otherwise it's PKHBT |
||
138 | uint32_t T; |
||
139 | |||
140 | // write-back bit |
||
141 | uint32_t W; |
||
142 | |||
143 | // flag which specifies whether an immediate has been set |
||
144 | uint32_t I; |
||
145 | |||
146 | // rotation value |
||
147 | uint32_t rotate; |
||
148 | |||
149 | // register operands |
||
150 | darm_reg_t Rd; // destination |
||
151 | darm_reg_t Rn; // first operand |
||
152 | darm_reg_t Rm; // second operand |
||
153 | darm_reg_t Ra; // accumulate operand |
||
154 | darm_reg_t Rt; // transferred operand |
||
155 | darm_reg_t Rt2; // second transferred operand |
||
156 | |||
157 | // for instructions which produce a 64bit output we have to specify a |
||
158 | // high and a low 32bits destination register |
||
159 | darm_reg_t RdHi; // high 32bits destination |
||
160 | darm_reg_t RdLo; // low 32bits destination |
||
161 | |||
162 | // immediate operand |
||
163 | uint32_t imm; |
||
164 | uint32_t sat_imm; |
||
165 | |||
166 | // register shift info |
||
167 | darm_shift_type_t shift_type; |
||
168 | darm_reg_t Rs; |
||
169 | uint32_t shift; |
||
170 | |||
171 | // certain instructions operate on bits, they specify the lowest or highest |
||
172 | // significant bit to be used, as well as the width, the amount of bits |
||
173 | // that are affected |
||
174 | uint32_t lsb; |
||
175 | uint32_t msb; |
||
176 | uint32_t width; |
||
177 | |||
178 | // bitmask of registers affected by the STM/LDM/PUSH/POP instruction |
||
179 | uint16_t reglist; |
||
180 | |||
181 | // special registers and values for the MRC/MCR/etc instructions |
||
182 | uint8_t coproc; |
||
183 | uint8_t opc1; |
||
184 | uint8_t opc2; |
||
185 | darm_reg_t CRd; |
||
186 | darm_reg_t CRn; |
||
187 | darm_reg_t CRm; |
||
188 | uint32_t D; |
||
189 | |||
190 | // condition and mask for the IT instruction |
||
191 | darm_cond_t firstcond; |
||
192 | uint8_t mask; |
||
193 | } darm_t; |
||
194 | |||
195 | typedef struct _darm_str_t { |
||
196 | // the full mnemonic, including extensions, flags, etc. |
||
197 | char mnemonic[12]; |
||
198 | |||
199 | // a representation of each argument in a separate string |
||
200 | char arg[6][32]; |
||
201 | |||
202 | // representation of shifting, if present |
||
203 | char shift[12]; |
||
204 | |||
205 | // the entire instruction |
||
206 | char total[64]; |
||
207 | } darm_str_t; |
||
208 | |||
209 | // reset a darm object, this function is internally called right before using |
||
210 | // any of the disassemble routines, hence a user is normally not required to |
||
211 | // call this function beforehand |
||
212 | void darm_init(darm_t *d); |
||
213 | |||
214 | // disassemble an armv7 instruction |
||
215 | int darm_armv7_disasm(darm_t *d, uint32_t w); |
||
216 | |||
217 | // disassemble a thumb instruction |
||
218 | int darm_thumb_disasm(darm_t *d, uint16_t w); |
||
219 | |||
220 | // disassemble a thumb2 instruction |
||
221 | int darm_thumb2_disasm(darm_t *d, uint16_t w, uint16_t w2); |
||
222 | |||
223 | // |
||
224 | // Disassembles an instruction - determines instruction set |
||
225 | // (ARMv7 or Thumb/Thumb2) based on the address and determines Thumb or |
||
226 | // Thumb2 mode based on the instruction itself. |
||
227 | // |
||
228 | // Takes two 16 bit words as input, the first representing the lower 16 bits |
||
229 | // and the second 16 bit word representing the upper 16 bits of the possibly |
||
230 | // full 32 bits. |
||
231 | // |
||
232 | // Returns 0 on failure, 1 for Thumb, 2 for Thumb2, and 2 for ARMv7. In other |
||
233 | // words, the function returns the amount of 16 bit words that were used to |
||
234 | // disassemble this instruction. |
||
235 | // |
||
236 | // Note that, in order to instruct the disassembler to disassemble a Thumb or |
||
237 | // Thumb2 instruction, the address has to have the least significant bit set. |
||
238 | // That is, given a 4-byte aligned addr, addr is disassembled as 32bit ARMv7 |
||
239 | // instruction, addr+1 is disassembled as Thumb or Thumb2 instruction, and |
||
240 | // addr+3 is also disassembled as Thumb/Thumb2. Furthermore, addr+2 is |
||
241 | // disassembled as ARMv7, but do not rely on this being defined behavior in |
||
242 | // the ARM CPU. |
||
243 | // |
||
244 | int darm_disasm(darm_t *d, uint16_t w, uint16_t w2, uint32_t addr); |
||
245 | |||
246 | int darm_immshift_decode(const darm_t *d, const char **type, |
||
247 | uint32_t *immediate); |
||
248 | |||
249 | const char *darm_mnemonic_name(darm_instr_t instr); |
||
250 | const char *darm_enctype_name(darm_enctype_t enctype); |
||
251 | const char *darm_register_name(darm_reg_t reg); |
||
252 | const char *darm_shift_type_name(darm_shift_type_t shifttype); |
||
253 | |||
254 | // postfix for each condition, e.g., EQ, NE |
||
255 | const char *darm_condition_name(darm_cond_t cond, int omit_always_execute); |
||
256 | |||
257 | // meaning if this condition is used for regular instructions |
||
258 | const char *darm_condition_meaning_int(darm_cond_t cond); |
||
259 | |||
260 | // meaning if this condition is used for floating point instructions |
||
261 | const char *darm_condition_meaning_fp(darm_cond_t cond); |
||
262 | |||
263 | // look up a condition code, e.g., "EQ" => C_EQ |
||
264 | darm_cond_t darm_condition_index(const char *condition_code); |
||
265 | |||
266 | int darm_reglist(uint16_t reglist, char *out); |
||
267 | void darm_dump(const darm_t *d); |
||
268 | |||
269 | int darm_str(const darm_t *d, darm_str_t *str); |
||
270 | int darm_str2(const darm_t *d, darm_str_t *str, int lowercase); |
||
271 | |||
272 | #endif |