2 * Debugger ARM specific functions
4 * Copyright 2010-2013 André Hentschel
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #if defined(__arm__) && !defined(__ARMEB__)
26 * Switch to disassemble Thumb code.
28 static BOOL db_disasm_thumb
= FALSE
;
31 * Flag to indicate whether we need to display instruction,
32 * or whether we just need to know the address of the next
35 static BOOL db_display
= FALSE
;
37 #define ARM_INSN_SIZE 4
38 #define THUMB_INSN_SIZE 2
39 #define THUMB2_INSN_SIZE 4
41 #define ROR32(n, r) (((n) >> (r)) | ((n) << (32 - (r))))
43 #define get_cond(ins) tbl_cond[(ins >> 28) & 0x0f]
44 #define get_nibble(ins, num) ((ins >> (num * 4)) & 0x0f)
46 static char const tbl_regs
[][4] = {
47 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
48 "fp", "ip", "sp", "lr", "pc", "cpsr"
51 static char const tbl_addrmode
[][3] = {
52 "da", "ia", "db", "ib"
55 static char const tbl_cond
[][3] = {
56 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "", ""
59 static char const tbl_dataops
[][4] = {
60 "and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc", "tst", "teq", "cmp", "cmn", "orr",
64 static char const tbl_shifts
[][4] = {
65 "lsl", "lsr", "asr", "ror"
68 static char const tbl_hiops_t
[][4] = {
69 "add", "cmp", "mov", "bx"
72 static char const tbl_aluops_t
[][4] = {
73 "and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror", "tst", "neg", "cmp", "cmn", "orr",
77 static char const tbl_immops_t
[][4] = {
78 "mov", "cmp", "add", "sub"
81 static char const tbl_sregops_t
[][5] = {
82 "strh", "ldsb", "ldrh", "ldsh"
85 static char const tbl_miscops_t2
[][6] = {
86 "rev", "rev16", "rbit", "revsh"
89 static char const tbl_width_t2
[][2] = {
93 static char const tbl_special_regs_t2
[][12] = {
94 "apsr", "iapsr", "eapsr", "xpsr", "rsvd", "ipsr", "epsr", "iepsr", "msp", "psp", "rsvd", "rsvd",
95 "rsvd", "rsvd", "rsvd", "rsvd", "primask", "basepri", "basepri_max", "faultmask", "control"
98 static char const tbl_hints_t2
[][6] = {
99 "nop", "yield", "wfe", "wfi", "sev"
102 static UINT
db_get_inst(void* addr
, int size
)
107 if (dbg_read_memory(addr
, buffer
, size
))
112 result
= *(UINT
*)buffer
;
115 result
= *(WORD
*)buffer
;
122 static void db_printsym(unsigned int addr
)
126 a
.Mode
= AddrModeFlat
;
129 print_address(&a
, TRUE
);
132 static UINT
arm_disasm_branch(UINT inst
, ADDRESS64
*addr
)
134 short link
= (inst
>> 24) & 0x01;
135 int offset
= (inst
<< 2) & 0x03ffffff;
137 if (offset
& 0x02000000) offset
|= 0xfc000000;
140 dbg_printf("\n\tb%s%s\t", link
? "l" : "", get_cond(inst
));
141 db_printsym(addr
->Offset
+ offset
);
145 static UINT
arm_disasm_mul(UINT inst
, ADDRESS64
*addr
)
147 short accu
= (inst
>> 21) & 0x01;
148 short condcodes
= (inst
>> 20) & 0x01;
151 dbg_printf("\n\tmla%s%s\t%s, %s, %s, %s", get_cond(inst
), condcodes
? "s" : "",
152 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)],
153 tbl_regs
[get_nibble(inst
, 2)], tbl_regs
[get_nibble(inst
, 3)]);
155 dbg_printf("\n\tmul%s%s\t%s, %s, %s", get_cond(inst
), condcodes
? "s" : "",
156 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)],
157 tbl_regs
[get_nibble(inst
, 2)]);
161 static UINT
arm_disasm_longmul(UINT inst
, ADDRESS64
*addr
)
163 short sign
= (inst
>> 22) & 0x01;
164 short accu
= (inst
>> 21) & 0x01;
165 short condcodes
= (inst
>> 20) & 0x01;
167 dbg_printf("\n\t%s%s%s%s\t%s, %s, %s, %s", sign
? "s" : "u", accu
? "mlal" : "mull",
168 get_cond(inst
), condcodes
? "s" : "",
169 tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 4)],
170 tbl_regs
[get_nibble(inst
, 0)], tbl_regs
[get_nibble(inst
, 2)]);
174 static UINT
arm_disasm_swp(UINT inst
, ADDRESS64
*addr
)
176 short byte
= (inst
>> 22) & 0x01;
178 dbg_printf("\n\tswp%s%s\t%s, %s, [%s]", get_cond(inst
), byte
? "b" : "",
179 tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 0)],
180 tbl_regs
[get_nibble(inst
, 4)]);
184 static UINT
arm_disasm_halfwordtrans(UINT inst
, ADDRESS64
*addr
)
186 short halfword
= (inst
>> 5) & 0x01;
187 short sign
= (inst
>> 6) & 0x01;
188 short load
= (inst
>> 20) & 0x01;
189 short writeback
= (inst
>> 21) & 0x01;
190 short immediate
= (inst
>> 22) & 0x01;
191 short direction
= (inst
>> 23) & 0x01;
192 short indexing
= (inst
>> 24) & 0x01;
193 short offset
= ((inst
>> 4) & 0xf0) + (inst
& 0x0f);
195 if (!direction
) offset
*= -1;
197 dbg_printf("\n\t%s%s%s%s%s", load
? "ldr" : "str", sign
? "s" : "",
198 halfword
? "h" : (sign
? "b" : ""), writeback
? "t" : "", get_cond(inst
));
199 dbg_printf("\t%s, ", tbl_regs
[get_nibble(inst
, 3)]);
203 dbg_printf("[%s, #%d]", tbl_regs
[get_nibble(inst
, 4)], offset
);
205 dbg_printf("[%s, %s]", tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
210 dbg_printf("[%s], #%d", tbl_regs
[get_nibble(inst
, 4)], offset
);
212 dbg_printf("[%s], %s", tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
217 static UINT
arm_disasm_branchreg(UINT inst
, ADDRESS64
*addr
)
219 dbg_printf("\n\tb%s\t%s", get_cond(inst
), tbl_regs
[get_nibble(inst
, 0)]);
223 static UINT
arm_disasm_branchxchg(UINT inst
, ADDRESS64
*addr
)
225 dbg_printf("\n\tbx%s\t%s", get_cond(inst
), tbl_regs
[get_nibble(inst
, 0)]);
229 static UINT
arm_disasm_mrstrans(UINT inst
, ADDRESS64
*addr
)
231 short src
= (inst
>> 22) & 0x01;
233 dbg_printf("\n\tmrs%s\t%s, %s", get_cond(inst
), tbl_regs
[get_nibble(inst
, 3)],
234 src
? "spsr" : "cpsr");
238 static UINT
arm_disasm_msrtrans(UINT inst
, ADDRESS64
*addr
)
240 short immediate
= (inst
>> 25) & 0x01;
241 short dst
= (inst
>> 22) & 0x01;
242 short simple
= (inst
>> 16) & 0x01;
244 if (simple
|| !immediate
)
246 dbg_printf("\n\tmsr%s\t%s, %s", get_cond(inst
), dst
? "spsr" : "cpsr",
247 tbl_regs
[get_nibble(inst
, 0)]);
251 dbg_printf("\n\tmsr%s\t%s, #%u", get_cond(inst
), dst
? "spsr" : "cpsr",
252 ROR32(inst
& 0xff, 2 * get_nibble(inst
, 2)));
256 static UINT
arm_disasm_wordmov(UINT inst
, ADDRESS64
*addr
)
258 short top
= (inst
>> 22) & 0x01;
260 dbg_printf("\n\tmov%s%s\t%s, #%u", top
? "t" : "w", get_cond(inst
),
261 tbl_regs
[get_nibble(inst
, 3)], (get_nibble(inst
, 4) << 12) | (inst
& 0x0fff));
265 static UINT
arm_disasm_nop(UINT inst
, ADDRESS64
*addr
)
267 dbg_printf("\n\tnop%s", get_cond(inst
));
271 static UINT
arm_disasm_dataprocessing(UINT inst
, ADDRESS64
*addr
)
273 short condcodes
= (inst
>> 20) & 0x01;
274 short opcode
= (inst
>> 21) & 0x0f;
275 short immediate
= (inst
>> 25) & 0x01;
276 short no_op1
= (opcode
& 0x0d) == 0x0d;
277 short no_dst
= (opcode
& 0x0c) == 0x08;
279 dbg_printf("\n\t%s%s%s", tbl_dataops
[opcode
], condcodes
? "s" : "", get_cond(inst
));
280 if (!no_dst
) dbg_printf("\t%s, ", tbl_regs
[get_nibble(inst
, 3)]);
281 else dbg_printf("\t");
286 dbg_printf("#%u", ROR32(inst
& 0xff, 2 * get_nibble(inst
, 2)));
288 dbg_printf("%s", tbl_regs
[get_nibble(inst
, 0)]);
293 dbg_printf("%s, #%u", tbl_regs
[get_nibble(inst
, 4)],
294 ROR32(inst
& 0xff, 2 * get_nibble(inst
, 2)));
295 else if (((inst
>> 4) & 0xff) == 0x00) /* no shift */
296 dbg_printf("%s, %s", tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
297 else if (((inst
>> 4) & 0x09) == 0x01) /* register shift */
298 dbg_printf("%s, %s, %s %s", tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)],
299 tbl_shifts
[(inst
>> 5) & 0x03], tbl_regs
[(inst
>> 8) & 0x0f]);
300 else if (((inst
>> 4) & 0x01) == 0x00) /* immediate shift */
301 dbg_printf("%s, %s, %s #%d", tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)],
302 tbl_shifts
[(inst
>> 5) & 0x03], (inst
>> 7) & 0x1f);
309 static UINT
arm_disasm_singletrans(UINT inst
, ADDRESS64
*addr
)
311 short load
= (inst
>> 20) & 0x01;
312 short writeback
= (inst
>> 21) & 0x01;
313 short byte
= (inst
>> 22) & 0x01;
314 short direction
= (inst
>> 23) & 0x01;
315 short indexing
= (inst
>> 24) & 0x01;
316 short immediate
= !((inst
>> 25) & 0x01);
317 short offset
= inst
& 0x0fff;
319 if (!direction
) offset
*= -1;
321 dbg_printf("\n\t%s%s%s%s", load
? "ldr" : "str", byte
? "b" : "", writeback
? "t" : "",
323 dbg_printf("\t%s, ", tbl_regs
[get_nibble(inst
, 3)]);
327 dbg_printf("[%s, #%d]", tbl_regs
[get_nibble(inst
, 4)], offset
);
328 else if (((inst
>> 4) & 0xff) == 0x00) /* no shift */
329 dbg_printf("[%s, %s]", tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
330 else if (((inst
>> 4) & 0x01) == 0x00) /* immediate shift (there's no register shift) */
331 dbg_printf("[%s, %s, %s #%d]", tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)],
332 tbl_shifts
[(inst
>> 5) & 0x03], (inst
>> 7) & 0x1f);
339 dbg_printf("[%s], #%d", tbl_regs
[get_nibble(inst
, 4)], offset
);
340 else if (((inst
>> 4) & 0xff) == 0x00) /* no shift */
341 dbg_printf("[%s], %s", tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
342 else if (((inst
>> 4) & 0x01) == 0x00) /* immediate shift (there's no register shift) */
343 dbg_printf("[%s], %s, %s #%d", tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)],
344 tbl_shifts
[(inst
>> 5) & 0x03], (inst
>> 7) & 0x1f);
351 static UINT
arm_disasm_blocktrans(UINT inst
, ADDRESS64
*addr
)
353 short load
= (inst
>> 20) & 0x01;
354 short writeback
= (inst
>> 21) & 0x01;
355 short psr
= (inst
>> 22) & 0x01;
356 short addrmode
= (inst
>> 23) & 0x03;
366 dbg_printf("\n\t%s%s%s\t%s%s, {", load
? "ldm" : "stm", tbl_addrmode
[addrmode
], get_cond(inst
),
367 tbl_regs
[get_nibble(inst
, 4)], writeback
? "!" : "");
371 if (i
== last
) dbg_printf("%s", tbl_regs
[i
]);
372 else dbg_printf("%s, ", tbl_regs
[i
]);
374 dbg_printf("}%s", psr
? "^" : "");
378 static UINT
arm_disasm_swi(UINT inst
, ADDRESS64
*addr
)
380 dbg_printf("\n\tswi%s\t#%d", get_cond(inst
), inst
& 0x00ffffff);
384 static UINT
arm_disasm_coproctrans(UINT inst
, ADDRESS64
*addr
)
386 WORD CRm
= inst
& 0x0f;
387 WORD CP
= (inst
>> 5) & 0x07;
388 WORD CPnum
= (inst
>> 8) & 0x0f;
389 WORD CRn
= (inst
>> 16) & 0x0f;
390 WORD load
= (inst
>> 20) & 0x01;
391 WORD CP_Opc
= (inst
>> 21) & 0x07;
393 dbg_printf("\n\t%s%s\t%u, %u, %s, cr%u, cr%u, {%u}", load
? "mrc" : "mcr", get_cond(inst
), CPnum
,
394 CP
, tbl_regs
[get_nibble(inst
, 3)], CRn
, CRm
, CP_Opc
);
398 static UINT
arm_disasm_coprocdataop(UINT inst
, ADDRESS64
*addr
)
400 WORD CRm
= inst
& 0x0f;
401 WORD CP
= (inst
>> 5) & 0x07;
402 WORD CPnum
= (inst
>> 8) & 0x0f;
403 WORD CRd
= (inst
>> 12) & 0x0f;
404 WORD CRn
= (inst
>> 16) & 0x0f;
405 WORD CP_Opc
= (inst
>> 20) & 0x0f;
407 dbg_printf("\n\tcdp%s\t%u, %u, cr%u, cr%u, cr%u, {%u}", get_cond(inst
),
408 CPnum
, CP
, CRd
, CRn
, CRm
, CP_Opc
);
412 static UINT
arm_disasm_coprocdatatrans(UINT inst
, ADDRESS64
*addr
)
414 WORD CPnum
= (inst
>> 8) & 0x0f;
415 WORD CRd
= (inst
>> 12) & 0x0f;
416 WORD load
= (inst
>> 20) & 0x01;
417 WORD writeback
= (inst
>> 21) & 0x01;
418 WORD translen
= (inst
>> 22) & 0x01;
419 WORD direction
= (inst
>> 23) & 0x01;
420 WORD indexing
= (inst
>> 24) & 0x01;
421 short offset
= (inst
& 0xff) << 2;
423 if (!direction
) offset
*= -1;
425 dbg_printf("\n\t%s%s%s", load
? "ldc" : "stc", translen
? "l" : "", get_cond(inst
));
427 dbg_printf("\t%u, cr%u, [%s, #%d]%s", CPnum
, CRd
, tbl_regs
[get_nibble(inst
, 4)], offset
, writeback
?"!":"");
429 dbg_printf("\t%u, cr%u, [%s], #%d", CPnum
, CRd
, tbl_regs
[get_nibble(inst
, 4)], offset
);
433 static WORD
thumb_disasm_hireg(WORD inst
, ADDRESS64
*addr
)
435 short dst
= inst
& 0x07;
436 short src
= (inst
>> 3) & 0x07;
437 short h2
= (inst
>> 6) & 0x01;
438 short h1
= (inst
>> 7) & 0x01;
439 short op
= (inst
>> 8) & 0x03;
444 if (op
== 2 && dst
== src
) /* mov rx, rx */
446 dbg_printf("\n\tnop");
451 dbg_printf("\n\tb%sx\t%s", h1
?"l":"", tbl_regs
[src
]);
453 dbg_printf("\n\t%s\t%s, %s", tbl_hiops_t
[op
], tbl_regs
[dst
], tbl_regs
[src
]);
458 static WORD
thumb_disasm_aluop(WORD inst
, ADDRESS64
*addr
)
460 short dst
= inst
& 0x07;
461 short src
= (inst
>> 3) & 0x07;
462 short op
= (inst
>> 6) & 0x0f;
464 dbg_printf("\n\t%s\t%s, %s", tbl_aluops_t
[op
], tbl_regs
[dst
], tbl_regs
[src
]);
469 static WORD
thumb_disasm_pushpop(WORD inst
, ADDRESS64
*addr
)
471 short lrpc
= (inst
>> 8) & 0x01;
472 short load
= (inst
>> 11) & 0x01;
477 if ((inst
>>i
) & 1) break;
480 dbg_printf("\n\t%s\t{", load
? "pop" : "push");
485 if (i
== last
) dbg_printf("%s", tbl_regs
[i
]);
486 else dbg_printf("%s, ", tbl_regs
[i
]);
489 dbg_printf("%s%s", last
? ", " : "", load
? "pc" : "lr");
495 static WORD
thumb_disasm_blocktrans(WORD inst
, ADDRESS64
*addr
)
497 short load
= (inst
>> 11) & 0x01;
502 if ((inst
>>i
) & 1) break;
505 dbg_printf("\n\t%s\t%s!, {", load
? "ldmia" : "stmia", tbl_regs
[(inst
>> 8) & 0x07]);
510 if (i
== last
) dbg_printf("%s", tbl_regs
[i
]);
511 else dbg_printf("%s, ", tbl_regs
[i
]);
518 static WORD
thumb_disasm_swi(WORD inst
, ADDRESS64
*addr
)
520 dbg_printf("\n\tswi\t#%d", inst
& 0x00ff);
524 static WORD
thumb_disasm_condbranch(WORD inst
, ADDRESS64
*addr
)
526 WORD offset
= inst
& 0x00ff;
527 dbg_printf("\n\tb%s\t", tbl_cond
[(inst
>> 8) & 0x0f]);
528 db_printsym(addr
->Offset
+ offset
);
532 static WORD
thumb_disasm_uncondbranch(WORD inst
, ADDRESS64
*addr
)
534 short offset
= (inst
& 0x07ff) << 1;
536 if (offset
& 0x0800) offset
|= 0xf000;
539 dbg_printf("\n\tb\t");
540 db_printsym(addr
->Offset
+ offset
);
544 static WORD
thumb_disasm_loadadr(WORD inst
, ADDRESS64
*addr
)
546 WORD src
= (inst
>> 11) & 0x01;
547 WORD offset
= (inst
& 0xff) << 2;
549 dbg_printf("\n\tadd\t%s, %s, #%d", tbl_regs
[(inst
>> 8) & 0x07], src
? "sp" : "pc", offset
);
553 static WORD
thumb_disasm_ldrpcrel(WORD inst
, ADDRESS64
*addr
)
555 WORD offset
= (inst
& 0xff) << 2;
556 dbg_printf("\n\tldr\t%s, [pc, #%u]", tbl_regs
[(inst
>> 8) & 0x07], offset
);
560 static WORD
thumb_disasm_ldrsprel(WORD inst
, ADDRESS64
*addr
)
562 WORD offset
= (inst
& 0xff) << 2;
563 dbg_printf("\n\t%s\t%s, [sp, #%u]", (inst
& 0x0800)?"ldr":"str", tbl_regs
[(inst
>> 8) & 0x07], offset
);
567 static WORD
thumb_disasm_addsprel(WORD inst
, ADDRESS64
*addr
)
569 WORD offset
= (inst
& 0x7f) << 2;
570 if ((inst
>> 7) & 0x01)
571 dbg_printf("\n\tsub\tsp, sp, #%u", offset
);
573 dbg_printf("\n\tadd\tsp, sp, #%u", offset
);
577 static WORD
thumb_disasm_ldrimm(WORD inst
, ADDRESS64
*addr
)
579 WORD offset
= (inst
& 0x07c0) >> 6;
580 dbg_printf("\n\t%s%s\t%s, [%s, #%u]", (inst
& 0x0800)?"ldr":"str", (inst
& 0x1000)?"b":"",
581 tbl_regs
[inst
& 0x07], tbl_regs
[(inst
>> 3) & 0x07], (inst
& 0x1000)?offset
:(offset
<< 2));
585 static WORD
thumb_disasm_ldrhimm(WORD inst
, ADDRESS64
*addr
)
587 WORD offset
= (inst
& 0x07c0) >> 5;
588 dbg_printf("\n\t%s\t%s, [%s, #%u]", (inst
& 0x0800)?"ldrh":"strh",
589 tbl_regs
[inst
& 0x07], tbl_regs
[(inst
>> 3) & 0x07], offset
);
593 static WORD
thumb_disasm_ldrreg(WORD inst
, ADDRESS64
*addr
)
595 dbg_printf("\n\t%s%s\t%s, [%s, %s]", (inst
& 0x0800)?"ldr":"str", (inst
& 0x0400)?"b":"",
596 tbl_regs
[inst
& 0x07], tbl_regs
[(inst
>> 3) & 0x07], tbl_regs
[(inst
>> 6) & 0x07]);
600 static WORD
thumb_disasm_ldrsreg(WORD inst
, ADDRESS64
*addr
)
602 dbg_printf("\n\t%s\t%s, [%s, %s]", tbl_sregops_t
[(inst
>> 10) & 0x03],
603 tbl_regs
[inst
& 0x07], tbl_regs
[(inst
>> 3) & 0x07], tbl_regs
[(inst
>> 6) & 0x07]);
607 static WORD
thumb_disasm_immop(WORD inst
, ADDRESS64
*addr
)
609 WORD op
= (inst
>> 11) & 0x03;
610 dbg_printf("\n\t%s\t%s, #%u", tbl_immops_t
[op
], tbl_regs
[(inst
>> 8) & 0x07], inst
& 0xff);
614 static WORD
thumb_disasm_nop(WORD inst
, ADDRESS64
*addr
)
616 dbg_printf("\n\tnop");
620 static WORD
thumb_disasm_addsub(WORD inst
, ADDRESS64
*addr
)
622 WORD op
= (inst
>> 9) & 0x01;
623 WORD immediate
= (inst
>> 10) & 0x01;
625 dbg_printf("\n\t%s\t%s, %s, ", op
? "sub" : "add",
626 tbl_regs
[inst
& 0x07], tbl_regs
[(inst
>> 3) & 0x07]);
628 dbg_printf("#%d", (inst
>> 6) & 0x07);
630 dbg_printf("%s", tbl_regs
[(inst
>> 6) & 0x07]);
634 static WORD
thumb_disasm_movshift(WORD inst
, ADDRESS64
*addr
)
636 WORD op
= (inst
>> 11) & 0x03;
637 dbg_printf("\n\t%s\t%s, %s, #%u", tbl_shifts
[op
],
638 tbl_regs
[inst
& 0x07], tbl_regs
[(inst
>> 3) & 0x07], (inst
>> 6) & 0x1f);
642 static UINT
thumb2_disasm_srtrans(UINT inst
, ADDRESS64
*addr
)
644 UINT fromsr
= (inst
>> 21) & 0x03;
645 UINT sysreg
= inst
& 0xff;
647 if (fromsr
== 3 && get_nibble(inst
,4) == 0x0f && sysreg
<= 20)
649 dbg_printf("\n\tmrs\t%s, %s", tbl_regs
[get_nibble(inst
, 2)], tbl_special_regs_t2
[sysreg
]);
653 if (fromsr
== 0 && sysreg
<= 20)
655 dbg_printf("\n\tmsr\t%s, %s", tbl_special_regs_t2
[sysreg
], tbl_regs
[get_nibble(inst
, 4)]);
662 static UINT
thumb2_disasm_hint(UINT inst
, ADDRESS64
*addr
)
664 WORD op1
= (inst
>> 8) & 0x07;
665 WORD op2
= inst
& 0xff;
667 if (op1
) return inst
;
671 dbg_printf("\n\t%s", tbl_hints_t2
[op2
]);
677 dbg_printf("\n\tdbg\t#%u", get_nibble(inst
, 0));
684 static UINT
thumb2_disasm_miscctrl(UINT inst
, ADDRESS64
*addr
)
686 WORD op
= (inst
>> 4) & 0x0f;
691 dbg_printf("\n\tclrex");
694 dbg_printf("\n\tdsb\t#%u", get_nibble(inst
, 0));
697 dbg_printf("\n\tdmb\t#%u", get_nibble(inst
, 0));
700 dbg_printf("\n\tisb\t#%u", get_nibble(inst
, 0));
709 static UINT
thumb2_disasm_branch(UINT inst
, ADDRESS64
*addr
)
711 UINT S
= (inst
>> 26) & 0x01;
712 UINT L
= (inst
>> 14) & 0x01;
713 UINT I1
= !(((inst
>> 13) & 0x01) ^ S
);
714 UINT C
= !((inst
>> 12) & 0x01);
715 UINT I2
= !(((inst
>> 11) & 0x01) ^ S
);
716 UINT offset
= (inst
& 0x000007ff) << 1;
720 offset
|= I1
<< 19 | I2
<< 18 | (inst
& 0x003f0000) >> 4;
721 if (S
) offset
|= 0x0fff << 20;
725 offset
|= I1
<< 23 | I2
<< 22 | (inst
& 0x03ff0000) >> 4;
726 if (S
) offset
|= 0xff << 24;
729 dbg_printf("\n\tb%s%s\t", L
? "l" : "", C
? tbl_cond
[(inst
>> 22) & 0x0f] : "");
730 db_printsym(addr
->Offset
+ offset
+ 4);
734 static UINT
thumb2_disasm_misc(UINT inst
, ADDRESS64
*addr
)
736 WORD op1
= (inst
>> 20) & 0x03;
737 WORD op2
= (inst
>> 4) & 0x03;
739 if (get_nibble(inst
, 4) != get_nibble(inst
, 0))
742 if (op1
== 3 && op2
== 0)
744 dbg_printf("\n\tclz\t%s, %s", tbl_regs
[get_nibble(inst
, 2)], tbl_regs
[get_nibble(inst
, 0)]);
750 dbg_printf("\n\t%s\t%s, %s", tbl_miscops_t2
[op2
], tbl_regs
[get_nibble(inst
, 2)],
751 tbl_regs
[get_nibble(inst
, 0)]);
758 static UINT
thumb2_disasm_dataprocessingreg(UINT inst
, ADDRESS64
*addr
)
760 WORD op1
= (inst
>> 20) & 0x07;
761 WORD op2
= (inst
>> 4) & 0x0f;
765 dbg_printf("\n\t%s%s\t%s, %s, %s", tbl_shifts
[op1
>> 1], (op1
& 1)?"s":"",
766 tbl_regs
[get_nibble(inst
, 2)], tbl_regs
[get_nibble(inst
, 4)],
767 tbl_regs
[get_nibble(inst
, 0)]);
771 if ((op2
& 0x0C) == 0x08 && get_nibble(inst
, 4) == 0x0f)
773 dbg_printf("\n\t%sxt%s\t%s, %s", (op1
& 1)?"u":"s", (op1
& 4)?"b":"h",
774 tbl_regs
[get_nibble(inst
, 2)], tbl_regs
[get_nibble(inst
, 0)]);
776 dbg_printf(", ROR #%u", (op2
& 3) * 8);
783 static UINT
thumb2_disasm_mul(UINT inst
, ADDRESS64
*addr
)
785 WORD op1
= (inst
>> 20) & 0x07;
786 WORD op2
= (inst
>> 4) & 0x03;
791 if (op2
== 0 && get_nibble(inst
, 3) != 0xf)
793 dbg_printf("\n\tmla\t%s, %s, %s, %s", tbl_regs
[get_nibble(inst
, 2)],
794 tbl_regs
[get_nibble(inst
, 4)],
795 tbl_regs
[get_nibble(inst
, 0)],
796 tbl_regs
[get_nibble(inst
, 3)]);
800 if (op2
== 0 && get_nibble(inst
, 3) == 0xf)
802 dbg_printf("\n\tmul\t%s, %s, %s", tbl_regs
[get_nibble(inst
, 2)],
803 tbl_regs
[get_nibble(inst
, 4)],
804 tbl_regs
[get_nibble(inst
, 0)]);
810 dbg_printf("\n\tmls\t%s, %s, %s, %s", tbl_regs
[get_nibble(inst
, 2)],
811 tbl_regs
[get_nibble(inst
, 4)],
812 tbl_regs
[get_nibble(inst
, 0)],
813 tbl_regs
[get_nibble(inst
, 3)]);
820 static UINT
thumb2_disasm_longmuldiv(UINT inst
, ADDRESS64
*addr
)
822 WORD op1
= (inst
>> 20) & 0x07;
823 WORD op2
= (inst
>> 4) & 0x0f;
830 dbg_printf("\n\tsmull\t");
833 dbg_printf("\n\tumull\t");
836 dbg_printf("\n\tsmlal\t");
839 dbg_printf("\n\tumlal\t");
844 dbg_printf("%s, %s, %s, %s", tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 2)],
845 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
854 dbg_printf("\n\tsdiv\t");
857 dbg_printf("\n\tudiv\t");
862 dbg_printf("%s, %s, %s", tbl_regs
[get_nibble(inst
, 2)], tbl_regs
[get_nibble(inst
, 4)],
863 tbl_regs
[get_nibble(inst
, 0)]);
870 static UINT
thumb2_disasm_str(UINT inst
, ADDRESS64
*addr
)
872 WORD op1
= (inst
>> 21) & 0x07;
873 WORD op2
= (inst
>> 6) & 0x3f;
875 if ((op1
& 0x03) == 3) return inst
;
877 if (!(op1
& 0x04) && inst
& 0x0800)
880 dbg_printf("\n\tstr%s\t%s, [%s", tbl_width_t2
[op1
& 0x03], tbl_regs
[get_nibble(inst
, 3)],
881 tbl_regs
[get_nibble(inst
, 4)]);
883 offset
= inst
& 0xff;
884 if (!(inst
& 0x0200)) offset
*= -1;
886 if (!(inst
& 0x0400) && (inst
& 0x0100)) dbg_printf("], #%i", offset
);
887 else if (inst
& 0x0400) dbg_printf(", #%i]%s", offset
, (inst
& 0x0100)?"!":"");
892 if (!(op1
& 0x04) && !op2
)
894 dbg_printf("\n\tstr%s\t%s, [%s, %s, LSL #%u]", tbl_width_t2
[op1
& 0x03],
895 tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 4)],
896 tbl_regs
[get_nibble(inst
, 0)], (inst
>> 4) & 0x3);
902 dbg_printf("\n\tstr%s\t%s, [%s, #%u]", tbl_width_t2
[op1
& 0x03],
903 tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 4)], inst
& 0x0fff);
910 static UINT
thumb2_disasm_ldrword(UINT inst
, ADDRESS64
*addr
)
912 WORD op1
= (inst
>> 23) & 0x01;
913 WORD op2
= (inst
>> 6) & 0x3f;
916 if (get_nibble(inst
, 4) == 0x0f)
918 offset
= inst
& 0x0fff;
920 if (!op1
) offset
*= -1;
923 dbg_printf("\n\tldr\t%s, ", tbl_regs
[get_nibble(inst
, 3)]);
924 db_printsym(addr
->Offset
+ offset
);
930 dbg_printf("\n\tldr\t%s, [%s, %s, LSL #%u]", tbl_regs
[get_nibble(inst
, 3)],
931 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)], (inst
>> 4) & 0x3);
935 if (!op1
&& (op2
& 0x3c) == 0x38)
937 dbg_printf("\n\tldrt\t%s, [%s, #%u]", tbl_regs
[get_nibble(inst
, 3)],
938 tbl_regs
[get_nibble(inst
, 4)], inst
& 0xff);
942 dbg_printf("\n\tldr\t%s, [%s", tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 4)]);
946 dbg_printf(", #%u]", inst
& 0x0fff);
950 offset
= inst
& 0xff;
951 if (!(inst
& 0x0200)) offset
*= -1;
953 if (!(inst
& 0x0400) && (inst
& 0x0100)) dbg_printf("], #%i", offset
);
954 else if (inst
& 0x0400) dbg_printf(", #%i]%s", offset
, (inst
& 0x0100)?"!":"");
960 static UINT
thumb2_disasm_preload(UINT inst
, ADDRESS64
*addr
)
962 WORD op1
= (inst
>> 23) & 0x03;
964 if (!(op1
& 0x01) && !((inst
>> 6) & 0x3f) && get_nibble(inst
, 4) != 15)
966 WORD shift
= (inst
>> 4) & 0x03;
967 dbg_printf("\n\t%s\t[%s, %s", op1
?"pli":"pld", tbl_regs
[get_nibble(inst
, 4)],
968 tbl_regs
[get_nibble(inst
, 0)]);
969 if (shift
) dbg_printf(", lsl #%u]", shift
);
970 else dbg_printf("]");
974 if (get_nibble(inst
, 4) != 15)
976 dbg_printf("\n\t%s\t[%s, #%d]", (op1
& 0x02)?"pli":"pld", tbl_regs
[get_nibble(inst
, 4)],
977 (op1
& 0x01)?(inst
& 0x0fff):(-1 * (inst
& 0xff)));
981 if (get_nibble(inst
, 4) == 15)
983 int offset
= inst
& 0x0fff;
984 if (!op1
) offset
*= -1;
985 dbg_printf("\n\t%s\t", (op1
& 0x02)?"pli":"pld");
986 db_printsym(addr
->Offset
+ offset
+ 4);
993 static UINT
thumb2_disasm_ldrnonword(UINT inst
, ADDRESS64
*addr
)
995 WORD op1
= (inst
>> 23) & 0x03;
996 WORD hw
= (inst
>> 21) & 0x01;
998 if (!(op1
& 0x01) && !((inst
>> 6) & 0x3f) && get_nibble(inst
, 4) != 15)
1000 WORD shift
= (inst
>> 4) & 0x03;
1001 dbg_printf("\n\t%s%s\t%s, [%s, %s", op1
?"ldrs":"ldr", hw
?"h":"b",
1002 tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 4)],
1003 tbl_regs
[get_nibble(inst
, 0)]);
1004 if (shift
) dbg_printf(", lsl #%u]", shift
);
1005 else dbg_printf("]");
1009 if (!(op1
& 0x01) && ((inst
>> 8) & 0x0f) == 14 && get_nibble(inst
, 4) != 15)
1011 WORD offset
= inst
& 0xff;
1012 dbg_printf("\n\t%s%s\t%s, [%s", op1
?"ldrs":"ldr", hw
?"ht":"bt",
1013 tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 4)]);
1014 if (offset
) dbg_printf(", #%u]", offset
);
1015 else dbg_printf("]");
1019 if (get_nibble(inst
, 4) != 15)
1023 dbg_printf("\n\t%s%s\t%s, [%s", (op1
& 0x02)?"ldrs":"ldr", hw
?"h":"b",
1024 tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 4)]);
1028 dbg_printf(", #%u]", inst
& 0x0fff);
1032 offset
= inst
& 0xff;
1033 if (!(inst
& 0x0200)) offset
*= -1;
1035 if (!(inst
& 0x0400) && (inst
& 0x0100)) dbg_printf("], #%i", offset
);
1036 else if (inst
& 0x0400) dbg_printf(", #%i]%s", offset
, (inst
& 0x0100)?"!":"");
1042 if (get_nibble(inst
, 4) == 15)
1044 int offset
= inst
& 0x0fff;
1045 if (!op1
) offset
*= -1;
1046 dbg_printf("\n\t%s%s\t%s, ", (op1
& 0x02)?"ldrs":"ldr", hw
?"h":"b",
1047 tbl_regs
[get_nibble(inst
, 3)]);
1048 db_printsym(addr
->Offset
+ offset
+ 4);
1055 static UINT
thumb2_disasm_dataprocessing(UINT inst
, ADDRESS64
*addr
)
1057 WORD op
= (inst
>> 20) & 0x1f;
1058 WORD imm5
= ((inst
>> 10) & 0x1c) + ((inst
>> 6) & 0x03);
1064 WORD offset
= ((inst
>> 15) & 0x0800) + ((inst
>> 4) & 0x0700) + (inst
& 0xff);
1065 if (get_nibble(inst
, 4) == 15)
1067 dbg_printf("\n\tadr\t%s, ", tbl_regs
[get_nibble(inst
, 2)]);
1068 db_printsym(addr
->Offset
+ offset
+ 4);
1071 dbg_printf("\n\taddw\t%s, %s, #%u", tbl_regs
[get_nibble(inst
, 2)],
1072 tbl_regs
[get_nibble(inst
, 4)], offset
);
1078 WORD offset
= ((inst
>> 15) & 0x0800) + ((inst
>> 4) & 0xf000) +
1079 ((inst
>> 4) & 0x0700) + (inst
& 0xff);
1080 dbg_printf("\n\t%s\t%s, #%u", op
== 12 ? "movt" : "movw", tbl_regs
[get_nibble(inst
, 2)],
1086 int offset
= ((inst
>> 15) & 0x0800) + ((inst
>> 4) & 0x0700) + (inst
& 0xff);
1087 if (get_nibble(inst
, 4) == 15)
1090 dbg_printf("\n\tadr\t%s, ", tbl_regs
[get_nibble(inst
, 2)]);
1091 db_printsym(addr
->Offset
+ offset
+ 4);
1094 dbg_printf("\n\tsubw\t%s, %s, #%u", tbl_regs
[get_nibble(inst
, 2)],
1095 tbl_regs
[get_nibble(inst
, 4)], offset
);
1103 BOOL sign
= op
< 24;
1104 WORD sh
= (inst
>> 21) & 0x01;
1105 WORD sat
= (inst
& 0x1f);
1108 dbg_printf("\n\t%s\t%s, #%u, %s, %s #%u", sign
? "ssat" : "usat",
1109 tbl_regs
[get_nibble(inst
, 2)], sat
, tbl_regs
[get_nibble(inst
, 4)],
1110 sh
? "asr" : "lsl", imm5
);
1112 dbg_printf("\n\t%s\t%s, #%u, %s", sign
? "ssat" : "usat", tbl_regs
[get_nibble(inst
, 2)],
1113 sat
, tbl_regs
[get_nibble(inst
, 4)]);
1119 WORD width
= (inst
& 0x1f) + 1;
1120 dbg_printf("\n\t%s\t%s, %s, #%u, #%u", op
== 28 ? "ubfx" : "sbfx",
1121 tbl_regs
[get_nibble(inst
, 2)], tbl_regs
[get_nibble(inst
, 4)], imm5
, width
);
1126 WORD msb
= (inst
& 0x1f) + 1 - imm5
;
1127 if (get_nibble(inst
, 4) == 15)
1128 dbg_printf("\n\tbfc\t%s, #%u, #%u", tbl_regs
[get_nibble(inst
, 2)], imm5
, msb
);
1130 dbg_printf("\n\tbfi\t%s, %s, #%u, #%u", tbl_regs
[get_nibble(inst
, 2)],
1131 tbl_regs
[get_nibble(inst
, 4)], imm5
, msb
);
1139 static UINT
thumb2_disasm_dataprocessingmod(UINT inst
, ADDRESS64
*addr
)
1141 WORD op
= (inst
>> 21) & 0x0f;
1142 WORD sf
= (inst
>> 20) & 0x01;
1143 WORD offset
= ((inst
>> 15) & 0x0800) + ((inst
>> 4) & 0x0700) + (inst
& 0xff);
1145 /* FIXME: use ThumbExpandImm_C */
1150 if (get_nibble(inst
, 2) == 15)
1151 dbg_printf("\n\ttst\t%s, #%u", tbl_regs
[get_nibble(inst
, 4)], offset
);
1153 dbg_printf("\n\tand%s\t%s, %s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1154 tbl_regs
[get_nibble(inst
, 4)], offset
);
1157 dbg_printf("\n\tbic%s\t%s, %s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1158 tbl_regs
[get_nibble(inst
, 4)], offset
);
1161 if (get_nibble(inst
, 4) == 15)
1162 dbg_printf("\n\tmov%s\t%s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)], offset
);
1164 dbg_printf("\n\torr%s\t%s, %s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1165 tbl_regs
[get_nibble(inst
, 4)], offset
);
1168 if (get_nibble(inst
, 4) == 15)
1169 dbg_printf("\n\tmvn%s\t%s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)], offset
);
1171 dbg_printf("\n\torn%s\t%s, %s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1172 tbl_regs
[get_nibble(inst
, 4)], offset
);
1175 if (get_nibble(inst
, 2) == 15)
1176 dbg_printf("\n\tteq\t%s, #%u", tbl_regs
[get_nibble(inst
, 4)], offset
);
1178 dbg_printf("\n\teor%s\t%s, %s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1179 tbl_regs
[get_nibble(inst
, 4)], offset
);
1182 if (get_nibble(inst
, 2) == 15)
1183 dbg_printf("\n\tcmn\t%s, #%u", tbl_regs
[get_nibble(inst
, 4)], offset
);
1185 dbg_printf("\n\tadd%s\t%s, %s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1186 tbl_regs
[get_nibble(inst
, 4)], offset
);
1189 dbg_printf("\n\tadc%s\t%s, %s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1190 tbl_regs
[get_nibble(inst
, 4)], offset
);
1193 dbg_printf("\n\tsbc%s\t%s, %s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1194 tbl_regs
[get_nibble(inst
, 4)], offset
);
1197 if (get_nibble(inst
, 2) == 15)
1198 dbg_printf("\n\tcmp\t%s, #%u", tbl_regs
[get_nibble(inst
, 4)], offset
);
1200 dbg_printf("\n\tsub%s\t%s, %s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1201 tbl_regs
[get_nibble(inst
, 4)], offset
);
1204 dbg_printf("\n\trsb%s\t%s, %s, #%u", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1205 tbl_regs
[get_nibble(inst
, 4)], offset
);
1212 static UINT
thumb2_disasm_dataprocessingshift(UINT inst
, ADDRESS64
*addr
)
1214 WORD op
= (inst
>> 21) & 0x0f;
1215 WORD sf
= (inst
>> 20) & 0x01;
1216 WORD imm5
= ((inst
>> 10) & 0x1c) + ((inst
>> 6) & 0x03);
1217 WORD type
= (inst
>> 4) & 0x03;
1219 if (!imm5
&& (type
== 1 || type
== 2)) imm5
= 32;
1220 else if (!imm5
&& type
== 3) type
= 4;
1225 if (get_nibble(inst
, 2) == 15)
1226 dbg_printf("\n\ttst\t%s, %s", tbl_regs
[get_nibble(inst
, 4)],
1227 tbl_regs
[get_nibble(inst
, 0)]);
1229 dbg_printf("\n\tand%s\t%s, %s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1230 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
1233 dbg_printf("\n\tbic%s\t%s, %s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1234 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
1237 if (get_nibble(inst
, 4) == 15)
1240 dbg_printf("\n\trrx%s\t%s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)], tbl_regs
[get_nibble(inst
, 0)]);
1241 else if (!type
&& !imm5
)
1242 dbg_printf("\n\tmov%s\t%s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)], tbl_regs
[get_nibble(inst
, 0)]);
1244 dbg_printf("\n\t%s%s\t%s, %s, #%u", tbl_shifts
[type
], sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)], tbl_regs
[get_nibble(inst
, 0)], imm5
);
1248 dbg_printf("\n\torr%s\t%s, %s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1249 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
1252 if (get_nibble(inst
, 4) == 15)
1253 dbg_printf("\n\tmvn%s\t%s, %s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1254 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
1256 dbg_printf("\n\torn%s\t%s, %s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1257 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
1260 if (get_nibble(inst
, 2) == 15)
1261 dbg_printf("\n\tteq\t%s, %s", tbl_regs
[get_nibble(inst
, 4)],
1262 tbl_regs
[get_nibble(inst
, 0)]);
1264 dbg_printf("\n\teor%s\t%s, %s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1265 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
1268 if (get_nibble(inst
, 2) == 15)
1269 dbg_printf("\n\tcmn\t%s, %s", tbl_regs
[get_nibble(inst
, 4)],
1270 tbl_regs
[get_nibble(inst
, 0)]);
1272 dbg_printf("\n\tadd%s\t%s, %s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1273 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
1276 dbg_printf("\n\tadc%s\t%s, %s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1277 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
1280 dbg_printf("\n\tsbc%s\t%s, %s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1281 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
1284 if (get_nibble(inst
, 2) == 15)
1285 dbg_printf("\n\tcmp\t%s, %s", tbl_regs
[get_nibble(inst
, 4)],
1286 tbl_regs
[get_nibble(inst
, 0)]);
1288 dbg_printf("\n\tsub%s\t%s, %s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1289 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
1292 dbg_printf("\n\trsb%s\t%s, %s, %s", sf
? "s" : "", tbl_regs
[get_nibble(inst
, 2)],
1293 tbl_regs
[get_nibble(inst
, 4)], tbl_regs
[get_nibble(inst
, 0)]);
1300 dbg_printf(", rrx");
1301 else if (type
|| imm5
)
1302 dbg_printf(", %s #%u", tbl_shifts
[type
], imm5
);
1306 static UINT
thumb2_disasm_coprocdat(UINT inst
, ADDRESS64
*addr
)
1308 WORD opc2
= (inst
>> 5) & 0x07;
1310 dbg_printf("\n\tcdp%s\tp%u, #%u, cr%u, cr%u, cr%u", (inst
& 0x10000000)?"2":"",
1311 get_nibble(inst
, 2), get_nibble(inst
, 5), get_nibble(inst
, 3),
1312 get_nibble(inst
, 4), get_nibble(inst
, 0));
1314 if (opc2
) dbg_printf(", #%u", opc2
);
1318 static UINT
thumb2_disasm_coprocmov1(UINT inst
, ADDRESS64
*addr
)
1320 WORD opc1
= (inst
>> 21) & 0x07;
1321 WORD opc2
= (inst
>> 5) & 0x07;
1323 dbg_printf("\n\t%s%s\tp%u, #%u, %s, cr%u, cr%u", (inst
& 0x00100000)?"mrc":"mcr",
1324 (inst
& 0x10000000)?"2":"", get_nibble(inst
, 2), opc1
,
1325 tbl_regs
[get_nibble(inst
, 3)], get_nibble(inst
, 4), get_nibble(inst
, 0));
1327 if (opc2
) dbg_printf(", #%u", opc2
);
1331 static UINT
thumb2_disasm_coprocmov2(UINT inst
, ADDRESS64
*addr
)
1333 dbg_printf("\n\t%s%s\tp%u, #%u, %s, %s, cr%u", (inst
& 0x00100000)?"mrrc":"mcrr",
1334 (inst
& 0x10000000)?"2":"", get_nibble(inst
, 2), get_nibble(inst
, 1),
1335 tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 4)], get_nibble(inst
, 0));
1340 static UINT
thumb2_disasm_coprocdatatrans(UINT inst
, ADDRESS64
*addr
)
1342 WORD indexing
= (inst
>> 24) & 0x01;
1343 WORD direction
= (inst
>> 23) & 0x01;
1344 WORD translen
= (inst
>> 22) & 0x01;
1345 WORD writeback
= (inst
>> 21) & 0x01;
1346 WORD load
= (inst
>> 20) & 0x01;
1347 short offset
= (inst
& 0xff) << 2;
1349 if (!direction
) offset
*= -1;
1351 dbg_printf("\n\t%s%s%s", load
? "ldc" : "stc", (inst
& 0x10000000)?"2":"", translen
? "l" : "");
1354 if (load
&& get_nibble(inst
, 4) == 15)
1356 dbg_printf("\tp%u, cr%u, ", get_nibble(inst
, 2), get_nibble(inst
, 3));
1357 db_printsym(addr
->Offset
+ offset
+ 4);
1360 dbg_printf("\tp%u, cr%u, [%s, #%d]%s", get_nibble(inst
, 2), get_nibble(inst
, 3), tbl_regs
[get_nibble(inst
, 4)], offset
, writeback
?"!":"");
1365 dbg_printf("\tp%u, cr%u, [%s], #%d", get_nibble(inst
, 2), get_nibble(inst
, 3), tbl_regs
[get_nibble(inst
, 4)], offset
);
1367 dbg_printf("\tp%u, cr%u, [%s], {%u}", get_nibble(inst
, 2), get_nibble(inst
, 3), tbl_regs
[get_nibble(inst
, 4)], inst
& 0xff);
1372 static UINT
thumb2_disasm_ldrstrmul(UINT inst
, ADDRESS64
*addr
)
1374 short load
= (inst
>> 20) & 0x01;
1375 short writeback
= (inst
>> 21) & 0x01;
1376 short decbefore
= (inst
>> 24) & 0x01;
1386 if (writeback
&& get_nibble(inst
, 4) == 13)
1387 dbg_printf("\n\t%s\t{", load
? "pop" : "push");
1389 dbg_printf("\n\t%s%s\t%s%s, {", load
? "ldm" : "stm", decbefore
? "db" : "ia",
1390 tbl_regs
[get_nibble(inst
, 4)], writeback
? "!" : "");
1394 if (i
== last
) dbg_printf("%s", tbl_regs
[i
]);
1395 else dbg_printf("%s, ", tbl_regs
[i
]);
1401 static UINT
thumb2_disasm_ldrstrextbr(UINT inst
, ADDRESS64
*addr
)
1403 WORD op1
= (inst
>> 23) & 0x03;
1404 WORD op2
= (inst
>> 20) & 0x03;
1405 WORD op3
= (inst
>> 4) & 0x0f;
1406 WORD indexing
= (inst
>> 24) & 0x01;
1407 WORD direction
= (inst
>> 23) & 0x01;
1408 WORD writeback
= (inst
>> 21) & 0x01;
1409 WORD load
= (inst
>> 20) & 0x01;
1410 short offset
= (inst
& 0xff) << 2;
1412 if (op1
== 1 && op2
== 1 && op3
< 2)
1414 WORD halfword
= (inst
>> 4) & 0x01;
1416 dbg_printf("\n\ttbh\t [%s, %s, lsl #1]", tbl_regs
[get_nibble(inst
, 4)],
1417 tbl_regs
[get_nibble(inst
, 0)]);
1419 dbg_printf("\n\ttbb\t [%s, %s]", tbl_regs
[get_nibble(inst
, 4)],
1420 tbl_regs
[get_nibble(inst
, 0)]);
1424 if (op1
== 0 && op2
< 2)
1426 if (get_nibble(inst
, 2) == 15)
1427 dbg_printf("\n\tldrex\t %s, [%s, #%u]", tbl_regs
[get_nibble(inst
, 3)],
1428 tbl_regs
[get_nibble(inst
, 4)], offset
);
1430 dbg_printf("\n\tstrex\t %s, %s, [%s, #%u]", tbl_regs
[get_nibble(inst
, 2)],
1431 tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 4)], offset
);
1435 if (op1
== 1 && op2
< 2)
1437 WORD halfword
= (inst
>> 4) & 0x01;
1438 if (get_nibble(inst
, 0) == 15)
1439 dbg_printf("\n\tldrex%s\t %s, [%s]", halfword
? "h" : "b",
1440 tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 4)]);
1442 dbg_printf("\n\tstrex%s\t %s, %s, [%s]", halfword
? "h" : "b",
1443 tbl_regs
[get_nibble(inst
, 0)], tbl_regs
[get_nibble(inst
, 3)],
1444 tbl_regs
[get_nibble(inst
, 4)]);
1448 if (!direction
) offset
*= -1;
1449 dbg_printf("\n\t%s\t", load
? "ldrd" : "strd");
1452 if (load
&& get_nibble(inst
, 4) == 15)
1454 dbg_printf("%s, %s, ", tbl_regs
[get_nibble(inst
, 3)], tbl_regs
[get_nibble(inst
, 2)]);
1455 db_printsym(addr
->Offset
+ offset
+ 4);
1458 dbg_printf("%s, %s, [%s, #%d]%s", tbl_regs
[get_nibble(inst
, 3)],
1459 tbl_regs
[get_nibble(inst
, 2)], tbl_regs
[get_nibble(inst
, 4)], offset
,
1463 dbg_printf("%s, %s, [%s], #%d", tbl_regs
[get_nibble(inst
, 3)],
1464 tbl_regs
[get_nibble(inst
, 2)], tbl_regs
[get_nibble(inst
, 4)], offset
);
1472 UINT (*func
)(UINT
, ADDRESS64
*);
1475 static const struct inst_arm tbl_arm
[] = {
1476 { 0x0e000000, 0x0a000000, arm_disasm_branch
},
1477 { 0x0fc000f0, 0x00000090, arm_disasm_mul
},
1478 { 0x0f8000f0, 0x00800090, arm_disasm_longmul
},
1479 { 0x0fb00ff0, 0x01000090, arm_disasm_swp
},
1480 { 0x0e000090, 0x00000090, arm_disasm_halfwordtrans
},
1481 { 0x0ffffff0, 0x012fff00, arm_disasm_branchreg
},
1482 { 0x0ffffff0, 0x012fff10, arm_disasm_branchxchg
},
1483 { 0x0fbf0fff, 0x010f0000, arm_disasm_mrstrans
},
1484 { 0x0dbef000, 0x0128f000, arm_disasm_msrtrans
},
1485 { 0x0fb00000, 0x03000000, arm_disasm_wordmov
},
1486 { 0x0fffffff, 0x0320f000, arm_disasm_nop
},
1487 { 0x0c000000, 0x00000000, arm_disasm_dataprocessing
},
1488 { 0x0c000000, 0x04000000, arm_disasm_singletrans
},
1489 { 0x0e000000, 0x08000000, arm_disasm_blocktrans
},
1490 { 0x0f000000, 0x0f000000, arm_disasm_swi
},
1491 { 0x0f000010, 0x0e000010, arm_disasm_coproctrans
},
1492 { 0x0f000010, 0x0e000000, arm_disasm_coprocdataop
},
1493 { 0x0e000000, 0x0c000000, arm_disasm_coprocdatatrans
},
1494 { 0x00000000, 0x00000000, NULL
}
1501 WORD (*func
)(WORD
, ADDRESS64
*);
1504 static const struct inst_thumb16 tbl_thumb16
[] = {
1505 { 0xfc00, 0x4400, thumb_disasm_hireg
},
1506 { 0xfc00, 0x4000, thumb_disasm_aluop
},
1507 { 0xf600, 0xb400, thumb_disasm_pushpop
},
1508 { 0xf000, 0xc000, thumb_disasm_blocktrans
},
1509 { 0xff00, 0xdf00, thumb_disasm_swi
},
1510 { 0xf000, 0xd000, thumb_disasm_condbranch
},
1511 { 0xf800, 0xe000, thumb_disasm_uncondbranch
},
1512 { 0xf000, 0xa000, thumb_disasm_loadadr
},
1513 { 0xf800, 0x4800, thumb_disasm_ldrpcrel
},
1514 { 0xf000, 0x9000, thumb_disasm_ldrsprel
},
1515 { 0xff00, 0xb000, thumb_disasm_addsprel
},
1516 { 0xe000, 0x6000, thumb_disasm_ldrimm
},
1517 { 0xf000, 0x8000, thumb_disasm_ldrhimm
},
1518 { 0xf200, 0x5000, thumb_disasm_ldrreg
},
1519 { 0xf200, 0x5200, thumb_disasm_ldrsreg
},
1520 { 0xe000, 0x2000, thumb_disasm_immop
},
1521 { 0xff00, 0xbf00, thumb_disasm_nop
},
1522 { 0xf800, 0x1800, thumb_disasm_addsub
},
1523 { 0xe000, 0x0000, thumb_disasm_movshift
},
1524 { 0x0000, 0x0000, NULL
}
1527 static const struct inst_arm tbl_thumb32
[] = {
1528 { 0xfff0f000, 0xf3e08000, thumb2_disasm_srtrans
},
1529 { 0xfff0f000, 0xf3808000, thumb2_disasm_srtrans
},
1530 { 0xfff0d000, 0xf3a08000, thumb2_disasm_hint
},
1531 { 0xfff0d000, 0xf3b08000, thumb2_disasm_miscctrl
},
1532 { 0xf8008000, 0xf0008000, thumb2_disasm_branch
},
1533 { 0xffc0f0c0, 0xfa80f080, thumb2_disasm_misc
},
1534 { 0xff80f000, 0xfa00f000, thumb2_disasm_dataprocessingreg
},
1535 { 0xff8000c0, 0xfb000000, thumb2_disasm_mul
},
1536 { 0xff8000f0, 0xfb800000, thumb2_disasm_longmuldiv
},
1537 { 0xff8000f0, 0xfb8000f0, thumb2_disasm_longmuldiv
},
1538 { 0xff100000, 0xf8000000, thumb2_disasm_str
},
1539 { 0xff700000, 0xf8500000, thumb2_disasm_ldrword
},
1540 { 0xfe70f000, 0xf810f000, thumb2_disasm_preload
},
1541 { 0xfe500000, 0xf8100000, thumb2_disasm_ldrnonword
},
1542 { 0xfa008000, 0xf2000000, thumb2_disasm_dataprocessing
},
1543 { 0xfa008000, 0xf0000000, thumb2_disasm_dataprocessingmod
},
1544 { 0xfe008000, 0xea000000, thumb2_disasm_dataprocessingshift
},
1545 { 0xef000010, 0xee000000, thumb2_disasm_coprocdat
},
1546 { 0xef000010, 0xee000010, thumb2_disasm_coprocmov1
},
1547 { 0xefe00000, 0xec400000, thumb2_disasm_coprocmov2
},
1548 { 0xee000000, 0xec000000, thumb2_disasm_coprocdatatrans
},
1549 { 0xfe402000, 0xe8000000, thumb2_disasm_ldrstrmul
},
1550 { 0xfe400000, 0xe8400000, thumb2_disasm_ldrstrextbr
},
1551 { 0x00000000, 0x00000000, NULL
}
1554 /***********************************************************************
1557 * Disassemble instruction at 'addr'. addr is changed to point to the
1558 * start of the next instruction.
1560 void be_arm_disasm_one_insn(ADDRESS64
*addr
, int display
)
1562 struct inst_arm
*a_ptr
= (struct inst_arm
*)&tbl_arm
;
1563 struct inst_thumb16
*t_ptr
= (struct inst_thumb16
*)&tbl_thumb16
;
1564 struct inst_arm
*t2_ptr
= (struct inst_arm
*)&tbl_thumb32
;
1573 if (!memory_get_register(CV_ARM_CPSR
, &pval
, tmp
, sizeof(tmp
)))
1574 dbg_printf("\n\tmemory_get_register failed: %s", tmp
);
1576 db_disasm_thumb
= (*pval
& 0x20) != 0;
1578 db_display
= display
;
1580 if (!db_disasm_thumb
)
1582 size
= ARM_INSN_SIZE
;
1583 inst
= db_get_inst( memory_to_linear_addr(addr
), size
);
1584 while (a_ptr
->func
) {
1585 if ((inst
& a_ptr
->mask
) == a_ptr
->pattern
) {
1593 dbg_printf("\n\tUnknown ARM Instruction: %08x", inst
);
1594 addr
->Offset
+= size
;
1598 if (!a_ptr
->func(inst
, addr
))
1599 addr
->Offset
+= size
;
1605 WORD
*taddr
= memory_to_linear_addr(addr
);
1606 tinst
= db_get_inst( taddr
, THUMB_INSN_SIZE
);
1607 switch (tinst
& 0xf800)
1612 size
= THUMB2_INSN_SIZE
;
1614 inst
= db_get_inst( taddr
, THUMB_INSN_SIZE
);
1615 inst
|= (tinst
<< 16);
1617 while (t2_ptr
->func
) {
1618 if ((inst
& t2_ptr
->mask
) == t2_ptr
->pattern
) {
1626 dbg_printf("\n\tUnknown Thumb2 Instruction: %08x", inst
);
1627 addr
->Offset
+= size
;
1631 if (!t2_ptr
->func(inst
, addr
))
1632 addr
->Offset
+= size
;
1639 size
= THUMB_INSN_SIZE
;
1640 while (t_ptr
->func
) {
1641 if ((tinst
& t_ptr
->mask
) == t_ptr
->pattern
) {
1649 dbg_printf("\n\tUnknown Thumb Instruction: %04x", tinst
);
1650 addr
->Offset
+= size
;
1654 if (!t_ptr
->func(tinst
, addr
))
1655 addr
->Offset
+= size
;
1661 static BOOL
be_arm_get_addr(HANDLE hThread
, const dbg_ctx_t
*ctx
,
1662 enum be_cpu_addr bca
, ADDRESS64
* addr
)
1666 case be_cpu_addr_pc
:
1667 return be_cpu_build_addr(hThread
, ctx
, addr
, 0, ctx
->ctx
.Pc
);
1668 case be_cpu_addr_stack
:
1669 return be_cpu_build_addr(hThread
, ctx
, addr
, 0, ctx
->ctx
.Sp
);
1670 case be_cpu_addr_frame
:
1671 return be_cpu_build_addr(hThread
, ctx
, addr
, 0, ctx
->ctx
.R11
);
1676 static BOOL
be_arm_get_register_info(int regno
, enum be_cpu_addr
* kind
)
1680 case CV_ARM_PC
: *kind
= be_cpu_addr_pc
; return TRUE
;
1681 case CV_ARM_R0
+ 11: *kind
= be_cpu_addr_frame
; return TRUE
;
1682 case CV_ARM_SP
: *kind
= be_cpu_addr_stack
; return TRUE
;
1687 static void be_arm_single_step(dbg_ctx_t
*ctx
, BOOL enable
)
1691 static void be_arm_print_context(HANDLE hThread
, const dbg_ctx_t
*ctx
, int all_regs
)
1693 static const char condflags
[] = "NZCV";
1697 switch (ctx
->ctx
.Cpsr
& 0x1F)
1699 case 0: strcpy(buf
, "User26"); break;
1700 case 1: strcpy(buf
, "FIQ26"); break;
1701 case 2: strcpy(buf
, "IRQ26"); break;
1702 case 3: strcpy(buf
, "SVC26"); break;
1703 case 16: strcpy(buf
, "User"); break;
1704 case 17: strcpy(buf
, "FIQ"); break;
1705 case 18: strcpy(buf
, "IRQ"); break;
1706 case 19: strcpy(buf
, "SVC"); break;
1707 case 23: strcpy(buf
, "ABT"); break;
1708 case 27: strcpy(buf
, "UND"); break;
1709 default: strcpy(buf
, "UNKNWN"); break;
1712 dbg_printf("Register dump:\n");
1713 dbg_printf("%s %s Mode\n", (ctx
->ctx
.Cpsr
& 0x20) ? "Thumb" : "ARM", buf
);
1715 strcpy(buf
, condflags
);
1716 for (i
= 0; buf
[i
]; i
++)
1717 if (!((ctx
->ctx
.Cpsr
>> 26) & (1 << (sizeof(condflags
) - i
))))
1720 dbg_printf(" Pc:%08x Sp:%08x Lr:%08x Cpsr:%08x(%s)\n",
1721 ctx
->ctx
.Pc
, ctx
->ctx
.Sp
, ctx
->ctx
.Lr
, ctx
->ctx
.Cpsr
, buf
);
1722 dbg_printf(" r0:%08x r1:%08x r2:%08x r3:%08x\n",
1723 ctx
->ctx
.R0
, ctx
->ctx
.R1
, ctx
->ctx
.R2
, ctx
->ctx
.R3
);
1724 dbg_printf(" r4:%08x r5:%08x r6:%08x r7:%08x\n",
1725 ctx
->ctx
.R4
, ctx
->ctx
.R5
, ctx
->ctx
.R6
, ctx
->ctx
.R7
);
1726 dbg_printf(" r8:%08x r9:%08x r10:%08x r11:%08x r12:%08x\n",
1727 ctx
->ctx
.R8
, ctx
->ctx
.R9
, ctx
->ctx
.R10
, ctx
->ctx
.R11
, ctx
->ctx
.R12
);
1729 if (all_regs
) dbg_printf( "Floating point ARM dump not implemented\n" );
1732 static void be_arm_print_segment_info(HANDLE hThread
, const dbg_ctx_t
*ctx
)
1736 static struct dbg_internal_var be_arm_ctx
[] =
1738 {CV_ARM_R0
+ 0, "r0", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R0
), dbg_itype_unsigned_int
},
1739 {CV_ARM_R0
+ 1, "r1", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R1
), dbg_itype_unsigned_int
},
1740 {CV_ARM_R0
+ 2, "r2", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R2
), dbg_itype_unsigned_int
},
1741 {CV_ARM_R0
+ 3, "r3", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R3
), dbg_itype_unsigned_int
},
1742 {CV_ARM_R0
+ 4, "r4", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R4
), dbg_itype_unsigned_int
},
1743 {CV_ARM_R0
+ 5, "r5", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R5
), dbg_itype_unsigned_int
},
1744 {CV_ARM_R0
+ 6, "r6", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R6
), dbg_itype_unsigned_int
},
1745 {CV_ARM_R0
+ 7, "r7", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R7
), dbg_itype_unsigned_int
},
1746 {CV_ARM_R0
+ 8, "r8", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R8
), dbg_itype_unsigned_int
},
1747 {CV_ARM_R0
+ 9, "r9", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R9
), dbg_itype_unsigned_int
},
1748 {CV_ARM_R0
+ 10, "r10", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R10
), dbg_itype_unsigned_int
},
1749 {CV_ARM_R0
+ 11, "r11", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R11
), dbg_itype_unsigned_int
},
1750 {CV_ARM_R0
+ 12, "r12", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, R12
), dbg_itype_unsigned_int
},
1751 {CV_ARM_SP
, "sp", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, Sp
), dbg_itype_unsigned_int
},
1752 {CV_ARM_LR
, "lr", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, Lr
), dbg_itype_unsigned_int
},
1753 {CV_ARM_PC
, "pc", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, Pc
), dbg_itype_unsigned_int
},
1754 {CV_ARM_CPSR
, "cpsr", (DWORD_PTR
*)FIELD_OFFSET(CONTEXT
, Cpsr
), dbg_itype_unsigned_int
},
1755 {0, NULL
, 0, dbg_itype_none
}
1758 static BOOL
be_arm_is_step_over_insn(const void* insn
)
1760 dbg_printf("be_arm_is_step_over_insn: not done\n");
1764 static BOOL
be_arm_is_function_return(const void* insn
)
1766 dbg_printf("be_arm_is_function_return: not done\n");
1770 static BOOL
be_arm_is_break_insn(const void* insn
)
1772 dbg_printf("be_arm_is_break_insn: not done\n");
1776 static BOOL
be_arm_is_func_call(const void* insn
, ADDRESS64
* callee
)
1781 static BOOL
be_arm_is_jump(const void* insn
, ADDRESS64
* jumpee
)
1786 static BOOL
be_arm_insert_Xpoint(HANDLE hProcess
, const struct be_process_io
* pio
,
1787 dbg_ctx_t
*ctx
, enum be_xpoint_type type
,
1788 void* addr
, unsigned long* val
, unsigned size
)
1794 case be_xpoint_break
:
1795 if (!size
) return FALSE
;
1796 if (!pio
->read(hProcess
, addr
, val
, 4, &sz
) || sz
!= 4) return FALSE
;
1798 dbg_printf("Unknown/unsupported bp type %c\n", type
);
1804 static BOOL
be_arm_remove_Xpoint(HANDLE hProcess
, const struct be_process_io
* pio
,
1805 dbg_ctx_t
*ctx
, enum be_xpoint_type type
,
1806 void* addr
, unsigned long val
, unsigned size
)
1812 case be_xpoint_break
:
1813 if (!size
) return FALSE
;
1814 if (!pio
->write(hProcess
, addr
, &val
, 4, &sz
) || sz
== 4) return FALSE
;
1817 dbg_printf("Unknown/unsupported bp type %c\n", type
);
1823 static BOOL
be_arm_is_watchpoint_set(const dbg_ctx_t
*ctx
, unsigned idx
)
1825 dbg_printf("be_arm_is_watchpoint_set: not done\n");
1829 static void be_arm_clear_watchpoint(dbg_ctx_t
*ctx
, unsigned idx
)
1831 dbg_printf("be_arm_clear_watchpoint: not done\n");
1834 static int be_arm_adjust_pc_for_break(dbg_ctx_t
*ctx
, BOOL way
)
1836 INT step
= (ctx
->ctx
.Cpsr
& 0x20) ? 2 : 4;
1840 ctx
->ctx
.Pc
-= step
;
1843 ctx
->ctx
.Pc
+= step
;
1847 static BOOL
be_arm_fetch_integer(const struct dbg_lvalue
* lvalue
, unsigned size
,
1848 BOOL is_signed
, LONGLONG
* ret
)
1850 if (size
!= 1 && size
!= 2 && size
!= 4 && size
!= 8) return FALSE
;
1852 memset(ret
, 0, sizeof(*ret
)); /* clear unread bytes */
1853 /* FIXME: this assumes that debuggee and debugger use the same
1854 * integral representation
1856 if (!memory_read_value(lvalue
, size
, ret
)) return FALSE
;
1858 /* propagate sign information */
1859 if (is_signed
&& size
< 8 && (*ret
>> (size
* 8 - 1)) != 0)
1862 *ret
|= neg
<< (size
* 8);
1867 static BOOL
be_arm_fetch_float(const struct dbg_lvalue
* lvalue
, unsigned size
,
1870 char tmp
[sizeof(long double)];
1872 /* FIXME: this assumes that debuggee and debugger use the same
1873 * representation for reals
1875 if (!memory_read_value(lvalue
, size
, tmp
)) return FALSE
;
1877 if (size
== sizeof(float)) *ret
= *(float*)tmp
;
1878 else if (size
== sizeof(double)) *ret
= *(double*)tmp
;
1879 else if (size
== sizeof(long double)) *ret
= *(long double*)tmp
;
1885 static BOOL
be_arm_store_integer(const struct dbg_lvalue
* lvalue
, unsigned size
,
1886 BOOL is_signed
, LONGLONG val
)
1888 /* this is simple if we're on a little endian CPU */
1889 return memory_write_value(lvalue
, size
, &val
);
1892 static BOOL
be_arm_get_context(HANDLE thread
, dbg_ctx_t
*ctx
)
1894 ctx
->ctx
.ContextFlags
= CONTEXT_ALL
;
1895 return GetThreadContext(thread
, &ctx
->ctx
);
1898 static BOOL
be_arm_set_context(HANDLE thread
, const dbg_ctx_t
*ctx
)
1900 return SetThreadContext(thread
, &ctx
->ctx
);
1903 #define REG(f,n,t,r) {f, n, t, FIELD_OFFSET(CONTEXT, r), sizeof(((CONTEXT*)NULL)->r)}
1905 static struct gdb_register be_arm_gdb_register_map
[] = {
1906 REG("core", "r0", NULL
, R0
),
1907 REG(NULL
, "r1", NULL
, R1
),
1908 REG(NULL
, "r2", NULL
, R2
),
1909 REG(NULL
, "r3", NULL
, R3
),
1910 REG(NULL
, "r4", NULL
, R4
),
1911 REG(NULL
, "r5", NULL
, R5
),
1912 REG(NULL
, "r6", NULL
, R6
),
1913 REG(NULL
, "r7", NULL
, R7
),
1914 REG(NULL
, "r8", NULL
, R8
),
1915 REG(NULL
, "r9", NULL
, R9
),
1916 REG(NULL
, "r10", NULL
, R10
),
1917 REG(NULL
, "r11", NULL
, R11
),
1918 REG(NULL
, "r12", NULL
, R12
),
1919 REG(NULL
, "sp", "data_ptr", Sp
),
1920 REG(NULL
, "lr", "code_ptr", Lr
),
1921 REG(NULL
, "pc", "code_ptr", Pc
),
1922 REG(NULL
, "cpsr", NULL
, Cpsr
),
1925 struct backend_cpu be_arm
=
1927 IMAGE_FILE_MACHINE_ARMNT
,
1932 be_arm_get_register_info
,
1934 be_arm_print_context
,
1935 be_arm_print_segment_info
,
1937 be_arm_is_step_over_insn
,
1938 be_arm_is_function_return
,
1939 be_arm_is_break_insn
,
1940 be_arm_is_func_call
,
1942 be_arm_disasm_one_insn
,
1943 be_arm_insert_Xpoint
,
1944 be_arm_remove_Xpoint
,
1945 be_arm_is_watchpoint_set
,
1946 be_arm_clear_watchpoint
,
1947 be_arm_adjust_pc_for_break
,
1948 be_arm_fetch_integer
,
1950 be_arm_store_integer
,
1953 be_arm_gdb_register_map
,
1954 ARRAY_SIZE(be_arm_gdb_register_map
),