/[gxemul]/upstream/0.4.4.1/src/cpus/cpu_m68k.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.4.1/src/cpus/cpu_m68k.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 37 - (show annotations)
Mon Oct 8 16:21:43 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 8139 byte(s)
0.4.4.1
1 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_m68k.c,v 1.16 2006/12/30 13:30:54 debug Exp $
29 *
30 * Motorola 68K CPU emulation.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37
38 #include "cpu.h"
39 #include "machine.h"
40 #include "memory.h"
41 #include "misc.h"
42 #include "settings.h"
43 #include "symbol.h"
44
45
46 #define DYNTRANS_32
47 #define DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
48 #include "tmp_m68k_head.c"
49
50
51 static char *m68k_aname[] = { "a0", "a1", "a2", "a3", "a4", "a5", "fp", "a7" };
52 static char *m68k_dname[] = { "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7" };
53
54
55 /*
56 * m68k_cpu_new():
57 *
58 * Create a new M68K cpu object.
59 *
60 * Returns 1 on success, 0 if there was no matching M68K processor with
61 * this cpu_type_name.
62 */
63 int m68k_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
64 int cpu_id, char *cpu_type_name)
65 {
66 int i = 0;
67 struct m68k_cpu_type_def cpu_type_defs[] = M68K_CPU_TYPE_DEFS;
68
69 /* Scan the cpu_type_defs list for this cpu type: */
70 while (cpu_type_defs[i].name != NULL) {
71 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
72 break;
73 }
74 i++;
75 }
76 if (cpu_type_defs[i].name == NULL)
77 return 0;
78
79 cpu->run_instr = m68k_run_instr;
80 cpu->memory_rw = m68k_memory_rw;
81 cpu->update_translation_table = m68k_update_translation_table;
82 cpu->invalidate_translation_caches =
83 m68k_invalidate_translation_caches;
84 cpu->invalidate_code_translation = m68k_invalidate_code_translation;
85 cpu->is_32bit = 1;
86 cpu->byte_order = EMUL_BIG_ENDIAN;
87
88 cpu->cd.m68k.cpu_type = cpu_type_defs[i];
89
90 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
91 if (cpu_id == 0) {
92 debug("%s", cpu->name);
93 }
94
95 /* Add all register names to the settings: */
96 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
97 for (i=0; i<N_M68K_AREGS; i++)
98 CPU_SETTINGS_ADD_REGISTER32(m68k_aname[i], cpu->cd.m68k.a[i]);
99 /* Both "fp" and "a6" should map to the same register: */
100 CPU_SETTINGS_ADD_REGISTER32("a6", cpu->cd.m68k.a[6]);
101 for (i=0; i<N_M68K_DREGS; i++)
102 CPU_SETTINGS_ADD_REGISTER32(m68k_dname[i], cpu->cd.m68k.d[i]);
103
104 return 1;
105 }
106
107
108 /*
109 * m68k_cpu_list_available_types():
110 *
111 * Print a list of available M68K CPU types.
112 */
113 void m68k_cpu_list_available_types(void)
114 {
115 int i = 0, j;
116 struct m68k_cpu_type_def tdefs[] = M68K_CPU_TYPE_DEFS;
117
118 while (tdefs[i].name != NULL) {
119 debug("%s", tdefs[i].name);
120 for (j=10 - strlen(tdefs[i].name); j>0; j--)
121 debug(" ");
122 i++;
123 if ((i % 6) == 0 || tdefs[i].name == NULL)
124 debug("\n");
125 }
126 }
127
128
129 /*
130 * m68k_cpu_dumpinfo():
131 */
132 void m68k_cpu_dumpinfo(struct cpu *cpu)
133 {
134 /* TODO */
135 debug("\n");
136 }
137
138
139 /*
140 * m68k_cpu_register_dump():
141 *
142 * Dump cpu registers in a relatively readable format.
143 *
144 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
145 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
146 */
147 void m68k_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
148 {
149 char *symbol;
150 uint64_t offset;
151 int x = cpu->cpu_id, i;
152
153 if (gprs) {
154 /* Special registers (pc, ...) first: */
155 symbol = get_symbol_name(&cpu->machine->symbol_context,
156 cpu->pc, &offset);
157
158 debug("cpu%i: pc = 0x%08"PRIx32, x, (uint32_t)cpu->pc);
159 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
160
161 for (i=0; i<N_M68K_AREGS; i++) {
162 if ((i % 4) == 0)
163 debug("cpu%i:", x);
164 debug(" %s = 0x%08"PRIx32" ",
165 m68k_aname[i], cpu->cd.m68k.a[i]);
166 if ((i % 4) == 3)
167 debug("\n");
168 }
169
170 for (i=0; i<N_M68K_DREGS; i++) {
171 if ((i % 4) == 0)
172 debug("cpu%i:", x);
173 debug(" %s = 0x%08"PRIx32" ",
174 m68k_dname[i], cpu->cd.m68k.d[i]);
175 if ((i % 4) == 3)
176 debug("\n");
177 }
178 }
179 }
180
181
182 /*
183 * m68k_cpu_tlbdump():
184 *
185 * Called from the debugger to dump the TLB in a readable format.
186 * x is the cpu number to dump, or -1 to dump all CPUs.
187 *
188 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
189 * just dumped.
190 */
191 void m68k_cpu_tlbdump(struct machine *m, int x, int rawflag)
192 {
193 }
194
195
196 /*
197 * m68k_cpu_gdb_stub():
198 *
199 * Execute a "remote GDB" command. Returns a newly allocated response string
200 * on success, NULL on failure.
201 */
202 char *m68k_cpu_gdb_stub(struct cpu *cpu, char *cmd)
203 {
204 fatal("m68k_cpu_gdb_stub(): TODO\n");
205 return NULL;
206 }
207
208
209 /*
210 * m68k_cpu_interrupt():
211 */
212 int m68k_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
213 {
214 fatal("m68k_cpu_interrupt(): TODO\n");
215 return 0;
216 }
217
218
219 /*
220 * m68k_cpu_interrupt_ack():
221 */
222 int m68k_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
223 {
224 /* fatal("m68k_cpu_interrupt_ack(): TODO\n"); */
225 return 0;
226 }
227
228
229 /* Helper functions: */
230 static void print_two(unsigned char *instr, int *len)
231 { debug(" %02x%02x", instr[*len], instr[*len+1]); (*len) += 2; }
232 static void print_spaces(int len) { int i; debug(" "); for (i=0; i<16-len/2*5;
233 i++) debug(" "); }
234
235
236 /*
237 * m68k_cpu_disassemble_instr():
238 *
239 * Convert an instruction word into human readable format, for instruction
240 * tracing.
241 *
242 * If running is 1, cpu->pc should be the address of the instruction.
243 *
244 * If running is 0, things that depend on the runtime environment (eg.
245 * register contents) will not be shown, and addr will be used instead of
246 * cpu->pc for relative addresses.
247 */
248 int m68k_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
249 int running, uint64_t dumpaddr)
250 {
251 uint64_t offset;
252 int len = 0;
253 char *symbol;
254
255 if (running)
256 dumpaddr = cpu->pc;
257
258 symbol = get_symbol_name(&cpu->machine->symbol_context,
259 dumpaddr, &offset);
260 if (symbol != NULL && offset==0)
261 debug("<%s>\n", symbol);
262
263 if (cpu->machine->ncpus > 1 && running)
264 debug("cpu%i: ", cpu->cpu_id);
265
266 debug("0x%08x: ", (int)dumpaddr);
267
268 print_two(ib, &len);
269
270 switch (ib[0] >> 4) {
271
272 case 0x4:
273 switch (ib[0] & 0xf) {
274
275 case 0xe:
276 if (ib[1] >= 0x50 && ib[1] <= 0x57) {
277 print_two(ib, &len);
278 print_spaces(len);
279 debug("linkw\t%%%s,#%i\n",
280 m68k_aname[ib[1] & 7],
281 ((ib[2] << 8) + ib[3]));
282 } else if (ib[1] >= 0x58 && ib[1] <= 0x5f) {
283 print_spaces(len);
284 debug("unlk\t%%%s\n", m68k_aname[ib[1] & 7]);
285 } else if (ib[1] == 0x71) {
286 print_spaces(len);
287 debug("nop\n");
288 } else if (ib[1] == 0x73) {
289 print_spaces(len);
290 debug("rte\n");
291 } else if (ib[1] == 0x74) {
292 print_two(ib, &len);
293 print_spaces(len);
294 debug("rtd\t#0x%04x\n", ((ib[2] << 8) + ib[3]));
295 } else if (ib[1] == 0x75) {
296 print_spaces(len);
297 debug("rts\n");
298 } else {
299 print_spaces(len);
300 debug("UNIMPLEMENTED\n");
301 }
302 break;
303
304 default:print_spaces(len);
305 debug("UNIMPLEMENTED\n");
306 }
307 break;
308
309 default:print_spaces(len);
310 debug("UNIMPLEMENTED\n");
311 }
312
313 return len;
314 }
315
316
317 #include "tmp_m68k_tail.c"
318

  ViewVC Help
Powered by ViewVC 1.1.26