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