]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/db_disasm.c
xnu-344.21.74.tar.gz
[apple/xnu.git] / osfmk / ppc / db_disasm.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
d7e50217 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
d7e50217
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
d7e50217
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
26 * @OSF_COPYRIGHT@
27 */
28
29/*
30 * Instruction disassembler.
31 */
32
33#include <mach/boolean.h>
34#include <machine/db_machdep.h>
35
36#include <ddb/db_access.h>
37#include <ddb/db_sym.h>
38#include <ddb/db_output.h>
39
40#include <kern/task.h>
41#include <kern/misc_protos.h>
42
43#include "ppc_disasm.h"
44
45db_addr_t db_disasm_pc, db_disasm_symaddr;
46boolean_t db_disasm_print_symaddr;
47
48/*
49 * Disassemble instruction at 'loc'. 'altfmt' specifies an
50 * (optional) alternate format. Return address of start of
51 * next instruction.
52 */
53db_addr_t
54db_disasm(
55 db_addr_t loc,
56 boolean_t altfmt,
57 task_t task)
58{
59 int inst;
60 char *p;
61
62 inst = db_get_task_value(loc, 4, FALSE, task);
63 db_disasm_pc = loc;
64 db_disasm_print_symaddr = FALSE;
65 p = in(inst);
66 db_printf("%s", p);
67 if (db_disasm_print_symaddr) {
68 db_printf(" <");
69 db_task_printsym(db_disasm_symaddr, DB_STGY_ANY, task);
70 db_printf(">");
71 }
d7e50217 72 db_printf("\n"); /* Make sure we have a new line for multiline displays */
1c79356b
A
73 dis_done();
74 return (loc+4);
75}
76
77/*
78 * Given four bytes of instruction (stored as an int, not an
79 * array of characters), compute if the instruction reads
80 * memory.
81 */
82int
83db_inst_load(
84 unsigned long insw)
85{
86#if 1
87 db_printf("db_inst_load: coming soon in a debugger near you!\n");
88 return 0;
89#else
90 unsigned char insb, bits;
91
92 insb = insw & 0xff;
93 insw >>= 8;
94 bits = db_ldstrtab[insb];
95 if (!(bits & DBLS_LOAD))
96 return (0);
97 while (1) {
98 switch (bits & DBLS_MODS) {
99 case 0:
100 return (1);
101 case DBLS_MODRM:
102 insb = insw & 0xff;
103 return ((insb & 0xc0) != 0xc0);
104 case DBLS_SECOND|DBLS_MODRM:
105 insb = insw & 0xff;
106 return ((insb & 0xc0) != 0xc0 ? 2 : 0);
107 case DBLS_SECOND:
108 return (2);
109 case DBLS_ESCAPE:
110 insb = insw & 0xff;
111 insw >>= 8;
112 bits = db_ldstrtab0f[insb];
113 break;
114 case DBLS_SWREG:
115 return (db_inst_swreg(TRUE, insw, insb));
116 default:
117 panic ("db_inst_load: unknown mod bits");
118 }
119 }
120#endif
121}
122
123/*
124 * Given four bytes of instruction (stored as an int, not an
125 * array of characters), compute if the instruction writes
126 * memory.
127 */
128int
129db_inst_store(
130 unsigned long insw)
131{
132#if 1
133 db_printf("db_inst_store: coming soon in a debugger near you!\n");
134 return 0;
135#else
136 unsigned char insb, bits;
137
138 insb = insw & 0xff;
139 insw >>= 8;
140 bits = db_ldstrtab[insb];
141 if (!(bits & DBLS_STORE))
142 return (0);
143 while (1) {
144 switch (bits & DBLS_MODS) {
145 case 0:
146 return (1);
147 case DBLS_MODRM:
148 insb = insw & 0xff;
149 return ((insb & 0xc0) != 0xc0);
150 case DBLS_SECOND|DBLS_MODRM:
151 insb = insw & 0xff;
152 return ((insb & 0xc0) != 0xc0 ? 2 : 0);
153 case DBLS_SECOND:
154 return (2);
155 case DBLS_ESCAPE:
156 insb = insw & 0xff;
157 insw >>= 8;
158 bits = db_ldstrtab0f[insb];
159 break;
160 case DBLS_SWREG:
161 return (db_inst_swreg(FALSE, insw, insb));
162 default:
163 panic ("db_inst_store: unknown mod bits");
164 }
165 }
166#endif
167}
168
169/*
170 * Extra routines for the automatically generated disassembler
171 */
172char *
173hex(
174 bits n)
175{
176 char *p;
177
178 if (n < 10)
179 return dec(n);
180 p = dis_alloc(11);
181 sprintf(p, "0x%lx", n);
182 return p;
183}
184
185char *
186dec(
187 bits n)
188{
189 char *p = dis_alloc(11);
190 sprintf(p, "%lu", n);
191 return p;
192}
193
194char *
195brdispl(
196 bits displ,
197 bits nbits)
198{
199 int sign, extended;
200
201 sign = 1 << (nbits - 1);
202 extended = (displ & sign ? displ - (sign << 1) : displ);
203 db_disasm_symaddr = db_disasm_pc + (extended << 2);
204 db_disasm_print_symaddr = TRUE;
205 return hex(extended << 2);
206}
207
208char *
209mbz(
210 bits n)
211{
212 return n ? "[reserved bits not zero]" : "";
213}
214
215size_t db_disasm_string_size = 0;
216#define DB_DISASM_STRING_MAXSIZE 4096
217char db_disasm_string[DB_DISASM_STRING_MAXSIZE];
218
219void *db_disasm_malloc(size_t size); /* forward */
220void *
221db_disasm_malloc(
222 size_t size)
223{
224 void * new_buf;
225
226 if (db_disasm_string_size + size <= DB_DISASM_STRING_MAXSIZE) {
227 new_buf = (void *) (db_disasm_string + db_disasm_string_size);
228 db_disasm_string_size += size;
229 return new_buf;
230 }
231 db_printf("db_disasm_malloc(size=%d) failed: %d left !\n",
232 size,
233 DB_DISASM_STRING_MAXSIZE - db_disasm_string_size);
234 return (void *) 0;
235}