summaryrefslogtreecommitdiff
path: root/utils/disassembler/arm
diff options
context:
space:
mode:
Diffstat (limited to 'utils/disassembler/arm')
-rw-r--r--utils/disassembler/arm/disasm_arm.c375
-rw-r--r--utils/disassembler/arm/main.c118
2 files changed, 493 insertions, 0 deletions
diff --git a/utils/disassembler/arm/disasm_arm.c b/utils/disassembler/arm/disasm_arm.c
new file mode 100644
index 0000000000..4664d0f3b2
--- /dev/null
+++ b/utils/disassembler/arm/disasm_arm.c
@@ -0,0 +1,375 @@
1#include <stdio.h>
2#include <string.h>
3
4#define ULONG unsigned long
5#define UCHAR unsigned char
6
7#define FRMT "0x%x" // "0x%x"
8#define SHFTFRMC "%s %s #%d" // "%s %s %d"
9#define SHFTFRMR "%s %s %s" // "%s %s %s"
10//#define FRMT "0x%x"
11//#define SHFTFRMC "%s %s %d"
12//#define SHFTFRMR "%s %s %s"
13
14char *cond[16] = { "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "", "nv" };
15char *cnd1[16] = { "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", " ", "nv" };
16char *opcd[16] = {"and","eor","sub","rsb","add","adc","sbc","rsc","tst","teq","cmp","cmn","orr","mov","bic","mvn" };
17char setc[32] = {0,115,0,115,0,115,0,115,0,115,0,115,0,115,0,115,0, 0 ,0, 0 ,0, 0 ,0, 0 ,0,115,0,115,0,115,0,115 };
18char *regs[16] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" };
19
20char *shfts[4] = { "lsl", "lsr", "asr", "ror" };
21
22/*
2331-28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
24Cond 0 0 I ---Opcode--- S |----Rn----- ----Rd----- --------Operand 2-------- Data Processing /PSR Transfer
25Cond 0 0 0 0 | 0 0 A S |----Rd----- ----Rn----- ---Rs---- 1 0 0 1 --Rm--- Multiply
26Cond 0 0 0 0 | 1 U A S |---RdHi---- ---RdLo---- ---Rn---- 1 0 0 1 --Rm--- Multiply Long
27Cond 0 0 0 1 | 0 B 0 0 |----Rn----- ----Rd----- 0 0 0 0 1 0 0 1 --Rm--- Single Data Swap
28Cond 0 0 0 1 | 0 0 1 0 |1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 --Rn--- Branch and Exchange
29Cond 0 0 0 P | U 0 W L |----Rn----- ----Rd----- 0 0 0 0 1 S H 1 --Rm--- Halfword Data Transfer: register offset
30Cond 0 0 0 P | U 1 W L |----Rn----- ----Rd----- --Offset- 1 S H 1 -Offset Halfword Data Transfer: immediate offset
31Cond 0 1 I P | U B W L |----Rn----- ----Rd----- --------Offset----------- Single Data Transfer
32Cond 0 1 1 1 | x x x x |x x x x x x x x x x x x x x x 1 x x x x Undefined
33Cond 1 0 0 P | U S W L |----Rn----- -----------Register List------------- Block Data Transfer
34Cond 1 0 1 L | -------------------------Offset------------------------------ Branch
35Cond 1 1 0 P | U N W L |----Rn----- ----CRd---- ---CP#--- -----Offset---- Coprocessor Data Transfer
36Cond 1 1 1 0 | --CP Opc---|----CRn---- ----CRd---- ---CP#--- -CP-- 0 --CRm-- Coprocessor Data Operation
37Cond 1 1 1 0 | CP Opc L |----CRn---- ----Rd----- ---CP#--- -CP-- 1 --CRm-- Coprocessor Register Transfer
38Cond 1 1 1 1 | x x x x |x x x x x x x x x x x x x x x x x x x x Software Interrupt
39
400x04200000
410001 0 0 0 0 0 1 1 0 6 e 1 1 1 0 1 8
42================================================================================
43Cond 0 1 I P | U B W L |----Rn----- ----Rd----- --------Offset----------- Single Data Transfer
44
45
46EQ 0 Z set equal
47NE 1 Z clear not equal
48CS 2 C set unsigned higher or same
49CC 3 C clear unsigned lower
50MI 4 N set negative
51PL 5 N clear positive or zero
52VS 6 V set overflow
53VC 7 V clear no overflow
54HI 8 C set and Z clear unsigned higher
55LS 9 C clear or Z set unsigned lower or same
56GE A N equals V greater or equal
57LT B N not equal to V less than
58GT C Z clear AND (N equals V) greater than
59LE D Z set OR (N not equal to V) less than or equal
60AL E (ignored) always
61
62AND 0 operand1 AND operand2
63EOR 1 operand1 EOR operand2
64SUB 2 operand1 - operand2
65RSB 3 operand2 - operand1
66ADD 4 operand1 + operand2
67ADC 5 operand1 + operand2 + carry
68SBC 6 operand1 - operand2 + carry - 1
69RSC 7 operand2 - operand1 + carry - 1
70TST 8 AND, but result is not written
71TEQ 9 as EOR, but result is not written
72CMP A as SUB, but result is not written
73CMN B as ADD, but result is not written
74ORR C operand1 OR operand2
75MOV D operand2 (operand1 is ignored)
76BIC E operand1 AND NOT operand2 (Bit clear)
77MVN F NOT operand2 (operand1 is ignored)
78*/
79
80void multiply_stg(char *stg, ULONG val)
81{
82 if((val&0xc00000) == 0) // simple mul
83 {
84 if(val & 0x100000) // set condition flags
85 if(val & 0x200000) sprintf(stg+strlen(stg), "mla%ss ", cond[val>>28]);
86 else sprintf(stg+strlen(stg), "mul%ss ", cond[val>>28]);
87 else
88 if(val & 0x200000) sprintf(stg+strlen(stg), "mla%s ", cnd1[val>>28]);
89 else sprintf(stg+strlen(stg), "mul%s ", cnd1[val>>28]);
90
91 if(val & 0x200000) // accumulate
92 sprintf(stg+strlen(stg), "%s, %s, %s, %s", regs[(val>>16)&15], regs[(val>>0)&15], regs[(val>>8)&15], regs[(val>>12)&15]);
93 else
94 sprintf(stg+strlen(stg), "%s, %s, %s", regs[(val>>16)&15], regs[(val>>0)&15], regs[(val>>8)&15]);
95 }
96 else
97 {
98 if(val & 0x100000) // set condition flags
99 if(val & 0x200000) // accumulate
100 if(val & 0x400000) sprintf(stg+strlen(stg), "smlal%ss ", cond[val>>28]);
101 else sprintf(stg+strlen(stg), "umlal%ss ", cond[val>>28]);
102 else
103 if(val & 0x400000) sprintf(stg+strlen(stg), "smull%ss ", cond[val>>28]);
104 else sprintf(stg+strlen(stg), "umull%ss ", cond[val>>28]);
105 else
106 if(val & 0x200000)
107 if(val & 0x400000) sprintf(stg+strlen(stg), "smlal%s ", cond[val>>28]);
108 else sprintf(stg+strlen(stg), "umlal%s ", cond[val>>28]);
109 else
110 if(val & 0x400000) sprintf(stg+strlen(stg), "smull%s ", cond[val>>28]);
111 else sprintf(stg+strlen(stg), "umull%s ", cond[val>>28]);
112
113 sprintf(stg+strlen(stg), "%s, %s, %s, %s", regs[(val>>12)&15], regs[(val>>16)&15], regs[(val>>0)&15], regs[(val>>8)&15]);
114 }
115}
116
117void halfword_stg(char *stg, ULONG val)
118{
119 ULONG off = ((val>>4) & 0xf0) + (val & 0x0f);
120
121 if(val & 0x100000) sprintf(stg+strlen(stg), "ldr%s", cond[val>>28]);
122 else sprintf(stg+strlen(stg), "str%s", cond[val>>28]);
123
124 switch((val>>5) & 3) // SWP, HW, SB, SH
125 {
126 case 0: sprintf(stg+strlen(stg), "error: SWP"); break;
127 case 1: sprintf(stg+strlen(stg), "h "); break;
128 case 2: sprintf(stg+strlen(stg), "sb "); break;
129 case 3: sprintf(stg+strlen(stg), "sh "); break;
130 }
131
132 if(val & 0x400000) // immidiate offset
133 if(val & 0x1000000) // pre index
134 if(val & 0x200000) // write back
135 if(val & 0x800000) sprintf(stg+strlen(stg), "%s, [%s, "FRMT"]!", regs[(val>>12)&15], regs[(val>>16)&15], off);
136 else sprintf(stg+strlen(stg), "%s, [%s, -"FRMT"]!", regs[(val>>12)&15], regs[(val>>16)&15], off);
137 else
138 if(val & 0x800000) sprintf(stg+strlen(stg), "%s, [%s, "FRMT"]", regs[(val>>12)&15], regs[(val>>16)&15], off);
139 else sprintf(stg+strlen(stg), "%s, [%s, -"FRMT"]", regs[(val>>12)&15], regs[(val>>16)&15], off);
140 else
141 if(val & 0x200000) // write back
142 sprintf(stg+strlen(stg), "error 'write back' on post indexed");
143 else
144 if(val & 0x800000) sprintf(stg+strlen(stg), "%s, [%s], "FRMT, regs[(val>>12)&15], regs[(val>>16)&15], off);
145 else sprintf(stg+strlen(stg), "%s, [%s], -"FRMT, regs[(val>>12)&15], regs[(val>>16)&15], off);
146 else
147 if(val & 0x1000000) // pre index
148 if(val & 0x200000) // write back
149 if(val & 0x800000) sprintf(stg+strlen(stg), "%s, [%s, %s]!", regs[(val>>12)&15], regs[(val>>16)&15], regs[val&15]);
150 else sprintf(stg+strlen(stg), "%s, [%s, -%s]!", regs[(val>>12)&15], regs[(val>>16)&15], regs[val&15]);
151 else
152 if(val & 0x800000) sprintf(stg+strlen(stg), "%s, [%s, %s]", regs[(val>>12)&15], regs[(val>>16)&15], regs[val&15]);
153 else sprintf(stg+strlen(stg), "%s, [%s, -%s]", regs[(val>>12)&15], regs[(val>>16)&15], regs[val&15]);
154 else
155 if(val & 0x200000) // write back
156 sprintf(stg+strlen(stg), "error 'write back' on post indexed");
157 else
158 if(val & 0x800000) sprintf(stg+strlen(stg), "%s, [%s], %s", regs[(val>>12)&15], regs[(val>>16)&15], regs[val&15]);
159 else sprintf(stg+strlen(stg), "%s, [%s], -%s", regs[(val>>12)&15], regs[(val>>16)&15], regs[val&15]);
160}
161
162void branch_stg(char *stg, ULONG val, ULONG pos)
163{
164 ULONG off = pos + ((int)val*256) / 64 + 8;
165
166 if((val & 0x0ffffff0) == 0x012fff10) // bx instruction
167 { sprintf(stg+strlen(stg), "bx%s %s", cond[val>>28], regs[val&15]); }
168 else
169 {
170 if(((val>>24)&15) == 10) sprintf(stg+strlen(stg), "b%s ", cond[val>>28]);
171 else sprintf(stg+strlen(stg), "bl%s ", cond[val>>28]);
172
173 sprintf(stg+strlen(stg), "0x%x", off);
174 }
175}
176
177void opcode_stg(char *stg, ULONG val, ULONG off)
178{
179 ULONG des, op1;
180 char op2[80];
181 char *st = stg + strlen(stg);
182
183 if(((val & 0x0ffffff0) == 0x012fff10) && (val & 16))
184 { branch_stg(stg, val, off); return; }
185 else if(((val & 0x0f000000) == 0x00000000) && ((val & 0xf0) == 0x90))
186 { multiply_stg(stg, val); return; }
187 else if(((val & 0x0f000000) <= 0x01000000) && ((val & 0x90) == 0x90) && ((val & 0xf0) > 0x90) && ((val & 0x01200000) != 0x00200000))
188 { halfword_stg(stg, val); return; }
189
190 sprintf(stg+strlen(stg), "%s%s%s ", opcd[(val>>21) & 15], cond[val>>28], setc[(val>>20) & 31]?"s":" ");
191
192 des = (val>>12) & 15;
193 op1 = (val>>16) & 15;
194
195 if(val & 0x2000000) // immidiate
196 {
197 off = (ULONG)((unsigned __int64)(val&0xff) << (32 - 2 * ((val >> 8) & 15))) | ((val&0xff) >> 2 * ((val >> 8) & 15));
198 sprintf(op2, FRMT" ", off);
199 }
200 else
201 {
202 if(val & 16) // shift type
203 sprintf(op2, SHFTFRMR, regs[val&15], shfts[(val>>5)&3], regs[(val>>8)&15]);
204 else
205 if((val>>7) & 31)
206 sprintf(op2, SHFTFRMC, regs[val&15], shfts[(val>>5)&3], (val>>7) & 31);
207 else
208 sprintf(op2, "%s ", regs[val&15]);
209 }
210
211 switch((val>>21) & 15)
212 {
213 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 12:
214 case 14: sprintf(stg+strlen(stg), "%s, %s, %s", regs[des], regs[op1], op2); break;
215
216 case 8: case 9: case 10:
217 case 11: if(val & 0x100000) // set status
218 sprintf(stg+strlen(stg), "%s, %s", regs[op1], op2); // standard TEQ,TST,CMP,CMN
219 else
220 { //special MRS/MSR opcodes
221 if((((val>>23) & 31) == 2) && ((val & 0x3f0fff) == 0x0f0000))
222 { sprintf(st, "mrs%s %s, %s", cnd1[val>>28], regs[des], val&0x400000?"SPSR_xx":"CPSR"); }
223 else
224 if((((val>>23) & 31) == 2) && ((val & 0x30fff0) == 0x20f000))
225 { sprintf(st, "msr%s %s, %s", cnd1[val>>28], val&0x400000?"SPSR_xx":"CPSR", regs[val&15]); }
226 else
227 if((((val>>23) & 31) == 6) && ((val & 0x30f000) == 0x20f000))
228 { sprintf(st, "msr%s %s, 0x%x", cnd1[val>>28], val&0x400000?"SPSR_xx":"CPSR_cf", op2); }
229 else
230 if((((val>>23) & 31) == 2) && ((val & 0x300ff0) == 0x000090))
231 { sprintf(st, "swp%s%s %s, %s, [%s]", val&0x400000?"b":"", cnd1[val>>28], regs[(val>>12)&15], regs[val&15], regs[(val>>16)&15]); }
232 else
233 { sprintf(stg+strlen(stg), "??????????????"); }
234 } break;
235 case 13:
236 case 15: sprintf(stg+strlen(stg), "%s, %s", regs[des], op2); break;
237 }
238}
239
240void single_data(char *stg, ULONG val)
241{
242 char op2[80];
243
244 if(((val & 0x0e000000) == 0x06000000) && (val & 16))
245 { sprintf(stg+strlen(stg), "undef%s", cond[val>>28]);
246 return;
247 }
248
249 if(val & 0x400000)
250 if(val & 0x100000) sprintf(stg+strlen(stg), "ldr%sb ", cond[val>>28]);
251 else sprintf(stg+strlen(stg), "str%sb ", cond[val>>28]);
252 else
253 if(val & 0x100000) sprintf(stg+strlen(stg), "ldr%s ", cnd1[val>>28]);
254 else sprintf(stg+strlen(stg), "str%s ", cnd1[val>>28]);
255
256 if(val & 0x2000000) // reg offset
257 if(val & 16) // shift type
258 sprintf(op2, "error: reg defined shift");
259 else
260 if((val>>7) & 31)
261 sprintf(op2, SHFTFRMC, regs[val&15], shfts[(val>>5)&3], (val>>7) & 31);
262 else
263 sprintf(op2, "%s", regs[val&15]);
264
265 if(val & 0x2000000) // reg offset
266 if(val & 0x1000000) // pre index
267 if(val & 0x800000) // up offset (+)
268 if(val & 0x200000) // write back
269 sprintf(stg+strlen(stg), "%s, [%s, %s]!", regs[(val>>12)&15], regs[(val>>16)&15], op2);
270 else
271 sprintf(stg+strlen(stg), "%s, [%s, %s]", regs[(val>>12)&15], regs[(val>>16)&15], op2);
272 else
273 if(val & 0x200000) // write back
274 sprintf(stg+strlen(stg), "%s, [%s, -%s]!", regs[(val>>12)&15], regs[(val>>16)&15], op2);
275 else
276 sprintf(stg+strlen(stg), "%s, [%s, -%s]", regs[(val>>12)&15], regs[(val>>16)&15], op2);
277 else
278 if(val & 0x200000) // write back
279 sprintf(stg+strlen(stg), "error 'write back' set");
280 else
281 if(val & 0x800000) // up offset (+)
282 sprintf(stg+strlen(stg), "%s, [%s], %s", regs[(val>>12)&15], regs[(val>>16)&15], op2);
283 else
284 sprintf(stg+strlen(stg), "%s, [%s], -%s", regs[(val>>12)&15], regs[(val>>16)&15], op2);
285 else
286 if(val & 0x1000000) // pre index
287 if(val & 0x800000) // up offset (+)
288 if(val & 0x200000) // write back
289 if(val & 0xfff) sprintf(stg+strlen(stg), "%s, [%s, "FRMT"]!", regs[(val>>12)&15], regs[(val>>16)&15], val & 0xfff);
290 else sprintf(stg+strlen(stg), "%s, [%s]!", regs[(val>>12)&15], regs[(val>>16)&15]);
291 else
292 if(val & 0xfff) sprintf(stg+strlen(stg), "%s, [%s, "FRMT"]", regs[(val>>12)&15], regs[(val>>16)&15], val & 0xfff);
293 else sprintf(stg+strlen(stg), "%s, [%s]", regs[(val>>12)&15], regs[(val>>16)&15]);
294 else
295 if(val & 0x200000) // write back
296 if(val & 0xfff) sprintf(stg+strlen(stg), "%s, [%s, -"FRMT"]!", regs[(val>>12)&15], regs[(val>>16)&15], val & 0xfff);
297 else sprintf(stg+strlen(stg), "%s, [%s]!", regs[(val>>12)&15], regs[(val>>16)&15]);
298 else
299 if(val & 0xfff) sprintf(stg+strlen(stg), "%s, [%s, -"FRMT"]", regs[(val>>12)&15], regs[(val>>16)&15], val & 0xfff);
300 else sprintf(stg+strlen(stg), "%s, [%s]", regs[(val>>12)&15], regs[(val>>16)&15]);
301 else
302 if(val & 0x200000) // write back
303 sprintf(stg+strlen(stg), "error 'write back' set");
304 else
305 if(val & 0x800000) // up offset (+)
306 if(val & 0xfff) sprintf(stg+strlen(stg), "%s, [%s], "FRMT, regs[(val>>12)&15], regs[(val>>16)&15], val & 0xfff);
307 else sprintf(stg+strlen(stg), "%s, [%s]", regs[(val>>12)&15], regs[(val>>16)&15]);
308 else
309 if(val & 0xfff) sprintf(stg+strlen(stg), "%s, [%s], -"FRMT, regs[(val>>12)&15], regs[(val>>16)&15], val & 0xfff);
310 else sprintf(stg+strlen(stg), "%s, [%s]", regs[(val>>12)&15], regs[(val>>16)&15]);
311}
312
313void block_data(char *stg, ULONG val)
314{
315 char lst[80];
316 int i;
317
318 strcpy(lst, "{");
319 for(i=0; i<16; i++)
320 if(val & (1<<i))
321 sprintf(lst+strlen(lst), "%s, ", regs[i]);
322 strcpy(lst+strlen(lst)-2, "}");
323
324 if(val & 0x400000) // load psr or force user mode
325 strcpy(lst+strlen(lst), "^");
326
327
328 if(val & 0x100000) // load
329 if(val & 0x1000000) // pre offset
330 if(val & 0x800000) sprintf(stg+strlen(stg), "ldm%sib ", cond[val>>28]);
331 else sprintf(stg+strlen(stg), "ldm%sdb ", cond[val>>28]);
332 else
333 if(val & 0x800000) sprintf(stg+strlen(stg), "ldm%sia ", cond[val>>28]);
334 else sprintf(stg+strlen(stg), "ldm%sda ", cond[val>>28]);
335 else
336 if(val & 0x1000000)
337 if(val & 0x800000) sprintf(stg+strlen(stg), "stm%sib ", cond[val>>28]);
338 else sprintf(stg+strlen(stg), "stm%sdb ", cond[val>>28]);
339 else
340 if(val & 0x800000) sprintf(stg+strlen(stg), "stm%sia ", cond[val>>28]);
341 else sprintf(stg+strlen(stg), "stm%sda ", cond[val>>28]);
342
343 switch((val>>21)&3)
344 {
345 case 0: sprintf(stg+strlen(stg), "%s, %s", regs[(val>>16)&15], lst); break;
346 case 1: sprintf(stg+strlen(stg), "%s!, %s", regs[(val>>16)&15], lst); break;
347 case 2: sprintf(stg+strlen(stg), "%s, %s", regs[(val>>16)&15], lst); break;
348 case 3: sprintf(stg+strlen(stg), "%s!, %s", regs[(val>>16)&15], lst); break;
349 }
350}
351
352void dis_asm(ULONG off, ULONG val, char *stg)
353{
354 sprintf(stg, "%6x: %08x ", off, val);
355
356 switch((val >> 24) & 15)
357 {
358 case 0:
359 case 1:
360 case 2:
361 case 3: opcode_stg(stg, val, off); break;
362 case 4:
363 case 5:
364 case 6:
365 case 7: single_data(stg, val); break;
366 case 8:
367 case 9: block_data(stg, val); break;
368 case 10:
369 case 11: branch_stg(stg, val, off); break;
370 case 12:
371 case 13:
372 case 14: sprintf(stg+strlen(stg), "cop%s", cnd1[val>>28]); break;
373 case 15: sprintf(stg+strlen(stg), "swi%s", cnd1[val>>28]); break;
374 }
375}
diff --git a/utils/disassembler/arm/main.c b/utils/disassembler/arm/main.c
new file mode 100644
index 0000000000..834dc5ff93
--- /dev/null
+++ b/utils/disassembler/arm/main.c
@@ -0,0 +1,118 @@
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4
5#define ULONG unsigned long
6#define USHORT unsigned short
7#define UCHAR unsigned char
8
9ULONG isdata[1000000]; /* each bit defines one byte as: code=0, data=1 */
10
11extern void dis_asm(ULONG off, ULONG val, char *stg);
12
13void main(int argc, char **argv)
14{
15 FILE *in, *out;
16 char *ptr, stg[256];
17 ULONG pos, sz, val, loop;
18 int offset, offset1;
19 USHORT regid;
20
21 if(argc == 1 || strcmp(argv[1], "--help") == 0)
22 { printf("Usage: arm_disass [input file]\n");
23 printf(" disassembles input file to 'disasm.txt'");
24 exit(-1);
25 }
26
27 in = fopen(argv[1], "rb");
28 if(in == NULL)
29 { printf("Cannot open %s", argv[1]);
30 exit(-1);
31 }
32
33 out = fopen("disasm.txt", "w");
34 if(out == NULL) exit(-1);
35
36 fseek(in, 0, SEEK_END);
37 sz = ftell(in);
38
39 /* first loop only sets data/code tags */
40 for(loop=0; loop<2; loop++)
41 {
42 for(pos=0; pos<sz; pos+=4)
43 {
44 /* clear disassembler string start */
45 memset(stg, 0, 40);
46 /* read next code dword */
47 fseek(in, pos, SEEK_SET);
48 fread(&val, 4, 1, in);
49
50 /* check for data tag set: if 1 byte out of 4 is marked => assume data */
51 if((isdata[pos>>5] & (0xf << (pos & 31))) || (val & 0xffff0000) == 0)
52 {
53 sprintf(stg, "%6x: %08x", pos, val);
54 }
55 else
56 {
57 dis_asm(pos, val, stg);
58
59 /* check for instant mov operation */
60 if(memcmp(stg+17, "mov ", 4) == 0 && (ptr=strstr(stg, "0x")) != NULL)
61 {
62 regid = *(USHORT*)(stg+22);
63
64 sscanf(ptr+2, "%x", &offset);
65 if(ptr[-1] == '-')
66 offset = -offset;
67 }
68 else
69 /* check for add/sub operation */
70 if((ptr=strstr(stg, "0x")) != NULL
71 && (memcmp(stg+17, "add ", 4) == 0 || memcmp(stg+17, "sub ", 4) == 0))
72 {
73 if(regid == *(USHORT*)(stg+22) && regid == *(USHORT*)(stg+26))
74 {
75 sscanf(ptr+2, "%x", &offset1);
76 if(ptr[-1] == '-')
77 offset1 = -offset1;
78
79 if(memcmp(stg+17, "add ", 4) == 0) offset += offset1;
80 else offset -= offset1;
81
82 /* add result to disassembler string */
83 sprintf(stg+strlen(stg), " <- 0x%x", offset);
84 }
85 else
86 regid = 0;
87 }
88 else
89 regid = 0;
90
91 /* check for const data */
92 if(memcmp(stg+26, "[pc, ", 5) == 0 && (ptr=strstr(stg, "0x")) != NULL)
93 {
94 sscanf(ptr+2, "%x", &offset);
95 if(ptr[-1] == '-')
96 offset = -offset;
97
98 /* add data tag */
99 isdata[(pos+offset+8)>>5] |= 1 << ((pos+offset+8) & 31);
100
101 /* add const data to disassembler string */
102 fseek(in, pos+offset+8, SEEK_SET);
103 fread(&offset, 4, 1, in);
104 sprintf(stg+strlen(stg), " <- 0x%x", offset);
105 }
106 }
107
108 /* remove trailing spaces */
109 while(stg[strlen(stg)-1] == 32)
110 stg[strlen(stg)-1] = 0;
111
112 if(loop == 1)
113 fprintf(out, "%s\n", stg);
114 }
115 }
116
117 fclose(in);
118} \ No newline at end of file