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