/[gxemul]/trunk/src/cpus/cpu_arm.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 /trunk/src/cpus/cpu_arm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 16 - (show annotations)
Mon Oct 8 16:19:01 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 31697 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.988 2005/10/11 03:53:57 debug Exp $

==============  RELEASE 0.3.6  ==============

20051008	The bug was not because of faulty ARM documentation after all,
		but it was related to those parts of the code.
		Fixing the RTC (dev_mc146818) to work with CATS.
20051009	Rewriting the R() function; now there are 8192 automatically
		generated smaller functions doing the same thing, but hopefully
		faster. This also fixes some bugs which were triggered when
		trying to compile GXemul inside itself. :-)
		Adding a dummy dev_lpt.
20051010	Small hack to not update virtual translation tables if memory
		accesses are done with the NO_EXCEPTION flag; a time reduction
		of almost a factor 2 for a full NetBSD/cats install. :-)
20051011	Passing -A as the default boot arg for CATS (works fine with
		OpenBSD/cats).

==============  RELEASE 0.3.6.1  ==============


1 /*
2 * Copyright (C) 2005 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_arm.c,v 1.29 2005/10/08 01:09:51 debug Exp $
29 *
30 * ARM CPU emulation.
31 *
32 * A good source of quick info on ARM instruction encoding:
33 *
34 * http://www.pinknoise.demon.co.uk/ARMinstrs/ARMinstrs.html
35 *
36 * (Most "xxxx0101..." and similar strings in this file are from that URL,
37 * or from the ARM manual.)
38 */
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <ctype.h>
44
45 #include "arm_cpu_types.h"
46 #include "cpu.h"
47 #include "machine.h"
48 #include "memory.h"
49 #include "misc.h"
50 #include "symbol.h"
51
52 #define DYNTRANS_32
53 #include "tmp_arm_head.c"
54
55
56 /* ARM symbolic register names and condition strings: */
57 static char *arm_regname[N_ARM_REGS] = ARM_REG_NAMES;
58 static char *arm_condition_string[16] = ARM_CONDITION_STRINGS;
59
60 /* Data Processing Instructions: */
61 static char *arm_dpiname[16] = ARM_DPI_NAMES;
62 static int arm_dpi_uses_d[16] = { 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1 };
63 static int arm_dpi_uses_n[16] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0 };
64
65 /* Forward reference: */
66 void arm_pc_to_pointers(struct cpu *cpu);
67
68
69 /*
70 * arm_cpu_new():
71 *
72 * Create a new ARM cpu object by filling the CPU struct.
73 * Return 1 on success, 0 if cpu_type_name isn't a valid ARM processor.
74 */
75 int arm_cpu_new(struct cpu *cpu, struct memory *mem,
76 struct machine *machine, int cpu_id, char *cpu_type_name)
77 {
78 int any_cache = 0, i, found;
79 struct arm_cpu_type_def cpu_type_defs[] = ARM_CPU_TYPE_DEFS;
80
81 /* Scan the list for this cpu type: */
82 i = 0; found = -1;
83 while (i >= 0 && cpu_type_defs[i].name != NULL) {
84 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
85 found = i;
86 break;
87 }
88 i++;
89 }
90 if (found == -1)
91 return 0;
92
93 cpu->memory_rw = arm_memory_rw;
94 cpu->update_translation_table = arm_update_translation_table;
95 cpu->invalidate_translation_caches_paddr =
96 arm_invalidate_translation_caches_paddr;
97 cpu->invalidate_code_translation = arm_invalidate_code_translation;
98 cpu->translate_address = arm_translate_address;
99
100 cpu->cd.arm.cpu_type = cpu_type_defs[found];
101 cpu->name = cpu->cd.arm.cpu_type.name;
102 cpu->is_32bit = 1;
103
104 cpu->cd.arm.cpsr = ARM_FLAG_I | ARM_FLAG_F;
105 cpu->cd.arm.control = ARM_CONTROL_PROG32 | ARM_CONTROL_DATA32
106 | ARM_CONTROL_CACHE | ARM_CONTROL_ICACHE | ARM_CONTROL_ALIGN;
107
108 if (cpu->machine->prom_emulation) {
109 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
110 cpu->cd.arm.control |= ARM_CONTROL_S;
111 } else {
112 cpu->cd.arm.cpsr |= ARM_MODE_USR32;
113 cpu->cd.arm.control |= ARM_CONTROL_S | ARM_CONTROL_R;
114 }
115
116 /* Only show name and caches etc for CPU nr 0: */
117 if (cpu_id == 0) {
118 debug("%s", cpu->name);
119 if (cpu->cd.arm.cpu_type.icache_shift != 0)
120 any_cache = 1;
121 if (cpu->cd.arm.cpu_type.dcache_shift != 0)
122 any_cache = 1;
123 if (any_cache) {
124 debug(" (I+D = %i+%i KB",
125 (int)(1 << (cpu->cd.arm.cpu_type.icache_shift-10)),
126 (int)(1 << (cpu->cd.arm.cpu_type.dcache_shift-10)));
127 debug(")");
128 }
129 }
130
131 /* Coprocessor 15 = the system control coprocessor. */
132 cpu->cd.arm.coproc[15] = arm_coproc_15;
133
134 /*
135 * NOTE/TODO: Ugly hack for OpenFirmware emulation:
136 */
137 if (cpu->machine->prom_emulation) {
138 cpu->cd.arm.of_emul_addr = cpu->machine->physical_ram_in_mb
139 * 1048576 - 8;
140 store_32bit_word(cpu, cpu->cd.arm.of_emul_addr, 0xef8c64be);
141 }
142
143 return 1;
144 }
145
146
147 /*
148 * arm_setup_initial_translation_table():
149 *
150 * When booting kernels (such as OpenBSD or NetBSD) directly, it is assumed
151 * that the MMU is already enabled by the boot-loader. This function tries
152 * to emulate that.
153 */
154 void arm_setup_initial_translation_table(struct cpu *cpu, uint32_t ttb_addr)
155 {
156 unsigned char nothing[16384];
157 unsigned int i, j;
158
159 if (cpu->machine->userland_emul != NULL) {
160 fatal("arm_setup_initial_translation_table(): should not "
161 "be called for userland emulation!\n");
162 exit(1);
163 }
164
165 cpu->cd.arm.control |= ARM_CONTROL_MMU;
166 cpu->cd.arm.dacr |= 0x00000003;
167 cpu->cd.arm.ttb = ttb_addr;
168
169 memset(nothing, 0, sizeof(nothing));
170 cpu->memory_rw(cpu, cpu->mem, cpu->cd.arm.ttb, nothing,
171 sizeof(nothing), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
172 for (i=0; i<256; i++)
173 for (j=0x0; j<=0xf; j++) {
174 unsigned char descr[4];
175 uint32_t addr = cpu->cd.arm.ttb +
176 (((j << 28) + (i << 20)) >> 18);
177 uint32_t d = (1048576*i) | 0xc02;
178 /*
179 d = (1048576 * (i + (j==12? 10 : j)*256)) | 2;
180 */
181 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
182 descr[0] = d; descr[1] = d >> 8;
183 descr[2] = d >> 16; descr[3] = d >> 24;
184 } else {
185 descr[3] = d; descr[2] = d >> 8;
186 descr[1] = d >> 16; descr[0] = d >> 24;
187 }
188 cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
189 sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
190 }
191 }
192
193
194 /*
195 * arm_cpu_dumpinfo():
196 */
197 void arm_cpu_dumpinfo(struct cpu *cpu)
198 {
199 struct arm_cpu_type_def *ct = &cpu->cd.arm.cpu_type;
200
201 debug(" (I+D = %i+%i KB)\n",
202 (1 << ct->icache_shift) / 1024, (1 << ct->dcache_shift) / 1024);
203 }
204
205
206 /*
207 * arm_cpu_list_available_types():
208 *
209 * Print a list of available ARM CPU types.
210 */
211 void arm_cpu_list_available_types(void)
212 {
213 int i, j;
214 struct arm_cpu_type_def tdefs[] = ARM_CPU_TYPE_DEFS;
215
216 i = 0;
217 while (tdefs[i].name != NULL) {
218 debug("%s", tdefs[i].name);
219 for (j=13 - strlen(tdefs[i].name); j>0; j--)
220 debug(" ");
221 i++;
222 if ((i % 5) == 0 || tdefs[i].name == NULL)
223 debug("\n");
224 }
225 }
226
227
228 /*
229 * arm_cpu_register_match():
230 */
231 void arm_cpu_register_match(struct machine *m, char *name,
232 int writeflag, uint64_t *valuep, int *match_register)
233 {
234 int i, cpunr = 0;
235
236 /* CPU number: */
237
238 /* TODO */
239
240 /* Register names: */
241 for (i=0; i<N_ARM_REGS; i++) {
242 if (strcasecmp(name, arm_regname[i]) == 0) {
243 if (writeflag) {
244 m->cpus[cpunr]->cd.arm.r[i] = *valuep;
245 if (i == ARM_PC)
246 m->cpus[cpunr]->pc = *valuep;
247 } else
248 *valuep = m->cpus[cpunr]->cd.arm.r[i];
249 *match_register = 1;
250 }
251 }
252 }
253
254
255 /*
256 * arm_cpu_register_dump():
257 *
258 * Dump cpu registers in a relatively readable format.
259 *
260 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
261 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
262 */
263 void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
264 {
265 char *symbol;
266 uint64_t offset;
267 int mode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
268 int i, x = cpu->cpu_id;
269
270 if (gprs) {
271 symbol = get_symbol_name(&cpu->machine->symbol_context,
272 cpu->cd.arm.r[ARM_PC], &offset);
273 debug("cpu%i: cpsr = ", x);
274 debug("%s%s%s%s%s%s",
275 (cpu->cd.arm.cpsr & ARM_FLAG_N)? "N" : "n",
276 (cpu->cd.arm.cpsr & ARM_FLAG_Z)? "Z" : "z",
277 (cpu->cd.arm.cpsr & ARM_FLAG_C)? "C" : "c",
278 (cpu->cd.arm.cpsr & ARM_FLAG_V)? "V" : "v",
279 (cpu->cd.arm.cpsr & ARM_FLAG_I)? "I" : "i",
280 (cpu->cd.arm.cpsr & ARM_FLAG_F)? "F" : "f");
281 if (mode < ARM_MODE_USR32)
282 debug(" pc = 0x%07x",
283 (int)(cpu->cd.arm.r[ARM_PC] & 0x03ffffff));
284 else
285 debug(" pc = 0x%08x", (int)cpu->cd.arm.r[ARM_PC]);
286
287 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
288
289 for (i=0; i<N_ARM_REGS; i++) {
290 if ((i % 4) == 0)
291 debug("cpu%i:", x);
292 if (i != ARM_PC)
293 debug(" %s = 0x%08x", arm_regname[i],
294 (int)cpu->cd.arm.r[i]);
295 if ((i % 4) == 3)
296 debug("\n");
297 }
298 }
299
300 if (coprocs & 1) {
301 int m = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
302 debug("cpu%i: cpsr = 0x%08x (", x, cpu->cd.arm.cpsr);
303 switch (m) {
304 case ARM_MODE_USR32:
305 debug("USR32)\n"); break;
306 case ARM_MODE_SYS32:
307 debug("SYS32)\n"); break;
308 case ARM_MODE_FIQ32:
309 debug("FIQ32)\n"); break;
310 case ARM_MODE_IRQ32:
311 debug("IRQ32)\n"); break;
312 case ARM_MODE_SVC32:
313 debug("SVC32)\n"); break;
314 case ARM_MODE_ABT32:
315 debug("ABT32)\n"); break;
316 case ARM_MODE_UND32:
317 debug("UND32)\n"); break;
318 default:debug("unimplemented)\n");
319 }
320
321 if (m != ARM_MODE_USR32 && m != ARM_MODE_SYS32) {
322 debug("cpu%i: usr r8..r14 =", x);
323 for (i=0; i<7; i++)
324 debug(" %08x", cpu->cd.arm.default_r8_r14[i]);
325 debug("\n");
326 }
327
328 if (m != ARM_MODE_FIQ32) {
329 debug("cpu%i: fiq r8..r14 =", x);
330 for (i=0; i<7; i++)
331 debug(" %08x", cpu->cd.arm.fiq_r8_r14[i]);
332 debug("\n");
333 }
334
335 if (m != ARM_MODE_IRQ32) {
336 debug("cpu%i: irq r13..r14 =", x);
337 for (i=0; i<2; i++)
338 debug(" %08x", cpu->cd.arm.irq_r13_r14[i]);
339 debug("\n");
340 }
341
342 if (m != ARM_MODE_SVC32) {
343 debug("cpu%i: svc r13..r14 =", x);
344 for (i=0; i<2; i++)
345 debug(" %08x", cpu->cd.arm.svc_r13_r14[i]);
346 debug("\n");
347 }
348
349 if (m != ARM_MODE_ABT32) {
350 debug("cpu%i: abt r13..r14 =", x);
351 for (i=0; i<2; i++)
352 debug(" %08x", cpu->cd.arm.abt_r13_r14[i]);
353 debug("\n");
354 }
355
356 if (m != ARM_MODE_UND32) {
357 debug("cpu%i: und r13..r14 =", x);
358 for (i=0; i<2; i++)
359 debug(" %08x", cpu->cd.arm.und_r13_r14[i]);
360 debug("\n");
361 }
362 }
363
364 if (coprocs & 2) {
365 debug("cpu%i: control = 0x%08x\n", x, cpu->cd.arm.control);
366 debug("cpu%i: MMU: %s\n", x,
367 cpu->cd.arm.control &
368 ARM_CONTROL_MMU? "enabled" : "disabled");
369 debug("cpu%i: alignment checks: %s\n", x,
370 cpu->cd.arm.control &
371 ARM_CONTROL_ALIGN? "enabled" : "disabled");
372 debug("cpu%i: [data] cache: %s\n", x,
373 cpu->cd.arm.control &
374 ARM_CONTROL_CACHE? "enabled" : "disabled");
375 debug("cpu%i: instruction cache: %s\n", x,
376 cpu->cd.arm.control &
377 ARM_CONTROL_ICACHE? "enabled" : "disabled");
378 debug("cpu%i: write buffer: %s\n", x,
379 cpu->cd.arm.control &
380 ARM_CONTROL_WBUFFER? "enabled" : "disabled");
381 debug("cpu%i: prog32: %s\n", x,
382 cpu->cd.arm.control &
383 ARM_CONTROL_PROG32? "yes" : "no (using prog26)");
384 debug("cpu%i: data32: %s\n", x,
385 cpu->cd.arm.control &
386 ARM_CONTROL_DATA32? "yes" : "no (using data26)");
387 debug("cpu%i: endianness: %s\n", x,
388 cpu->cd.arm.control &
389 ARM_CONTROL_BIG? "big endian" : "little endian");
390 debug("cpu%i: high vectors: %s\n", x,
391 cpu->cd.arm.control &
392 ARM_CONTROL_V? "yes (0xffff0000)" : "no");
393
394 debug("cpu%i: ttb = 0x%08x dacr = 0x%08x\n", x,
395 cpu->cd.arm.ttb, cpu->cd.arm.dacr);
396 debug("cpu%i: fsr = 0x%08x far = 0x%08x\n", x,
397 cpu->cd.arm.fsr, cpu->cd.arm.far);
398 }
399 }
400
401
402 /*
403 * arm_cpu_show_full_statistics():
404 *
405 * Show detailed statistics on opcode usage on each cpu.
406 */
407 void arm_cpu_show_full_statistics(struct machine *m)
408 {
409 fatal("arm_cpu_show_full_statistics(): TODO\n");
410 }
411
412
413 /*
414 * arm_cpu_tlbdump():
415 *
416 * Called from the debugger to dump the TLB in a readable format.
417 * x is the cpu number to dump, or -1 to dump all CPUs.
418 *
419 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
420 * just dumped.
421 */
422 void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
423 {
424 fatal("arm_cpu_tlbdump(): TODO\n");
425 }
426
427
428 /*
429 * arm_save_register_bank():
430 */
431 void arm_save_register_bank(struct cpu *cpu)
432 {
433 /* Save away current registers: */
434 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
435 case ARM_MODE_USR32:
436 case ARM_MODE_SYS32:
437 memcpy(cpu->cd.arm.default_r8_r14,
438 &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
439 break;
440 case ARM_MODE_FIQ32:
441 memcpy(cpu->cd.arm.fiq_r8_r14,
442 &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
443 break;
444 case ARM_MODE_IRQ32:
445 memcpy(cpu->cd.arm.default_r8_r14,
446 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
447 cpu->cd.arm.irq_r13_r14[0] = cpu->cd.arm.r[13];
448 cpu->cd.arm.irq_r13_r14[1] = cpu->cd.arm.r[14];
449 break;
450 case ARM_MODE_SVC32:
451 memcpy(cpu->cd.arm.default_r8_r14,
452 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
453 cpu->cd.arm.svc_r13_r14[0] = cpu->cd.arm.r[13];
454 cpu->cd.arm.svc_r13_r14[1] = cpu->cd.arm.r[14];
455 break;
456 case ARM_MODE_ABT32:
457 memcpy(cpu->cd.arm.default_r8_r14,
458 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
459 cpu->cd.arm.abt_r13_r14[0] = cpu->cd.arm.r[13];
460 cpu->cd.arm.abt_r13_r14[1] = cpu->cd.arm.r[14];
461 break;
462 case ARM_MODE_UND32:
463 memcpy(cpu->cd.arm.default_r8_r14,
464 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
465 cpu->cd.arm.und_r13_r14[0] = cpu->cd.arm.r[13];
466 cpu->cd.arm.und_r13_r14[1] = cpu->cd.arm.r[14];
467 break;
468 default:fatal("arm_save_register_bank: unimplemented mode %i\n",
469 cpu->cd.arm.cpsr & ARM_FLAG_MODE);
470 exit(1);
471 }
472 }
473
474
475 /*
476 * arm_load_register_bank():
477 */
478 void arm_load_register_bank(struct cpu *cpu)
479 {
480 /* Load new registers: */
481 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
482 case ARM_MODE_USR32:
483 case ARM_MODE_SYS32:
484 memcpy(&cpu->cd.arm.r[8],
485 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 7);
486 break;
487 case ARM_MODE_FIQ32:
488 memcpy(&cpu->cd.arm.r[8], cpu->cd.arm.fiq_r8_r14,
489 sizeof(uint32_t) * 7);
490 break;
491 case ARM_MODE_IRQ32:
492 memcpy(&cpu->cd.arm.r[8],
493 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
494 cpu->cd.arm.r[13] = cpu->cd.arm.irq_r13_r14[0];
495 cpu->cd.arm.r[14] = cpu->cd.arm.irq_r13_r14[1];
496 break;
497 case ARM_MODE_SVC32:
498 memcpy(&cpu->cd.arm.r[8],
499 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
500 cpu->cd.arm.r[13] = cpu->cd.arm.svc_r13_r14[0];
501 cpu->cd.arm.r[14] = cpu->cd.arm.svc_r13_r14[1];
502 break;
503 case ARM_MODE_ABT32:
504 memcpy(&cpu->cd.arm.r[8],
505 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
506 cpu->cd.arm.r[13] = cpu->cd.arm.abt_r13_r14[0];
507 cpu->cd.arm.r[14] = cpu->cd.arm.abt_r13_r14[1];
508 break;
509 case ARM_MODE_UND32:
510 memcpy(&cpu->cd.arm.r[8],
511 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
512 cpu->cd.arm.r[13] = cpu->cd.arm.und_r13_r14[0];
513 cpu->cd.arm.r[14] = cpu->cd.arm.und_r13_r14[1];
514 break;
515 default:fatal("arm_load_register_bank: unimplemented mode %i\n",
516 cpu->cd.arm.cpsr & ARM_FLAG_MODE);
517 exit(1);
518 }
519 }
520
521
522 /*
523 * arm_exception():
524 */
525 void arm_exception(struct cpu *cpu, int exception_nr)
526 {
527 int arm_exception_to_mode[N_ARM_EXCEPTIONS] = ARM_EXCEPTION_TO_MODE;
528 int oldmode, newmode;
529 uint32_t retaddr;
530
531 if (exception_nr < 0 || exception_nr >= N_ARM_EXCEPTIONS) {
532 fatal("arm_exception(): exception_nr = %i\n", exception_nr);
533 exit(1);
534 }
535
536 retaddr = cpu->pc;
537
538 debug("[ arm_exception(): ");
539
540 switch (exception_nr) {
541 case ARM_EXCEPTION_RESET:
542 cpu->running = 0;
543 fatal("RESET: TODO");
544 exit(1);
545 case ARM_EXCEPTION_UND:
546 debug("UNDEFINED");
547 retaddr += 4;
548 break;
549 case ARM_EXCEPTION_SWI:
550 debug("SWI");
551 retaddr += 4;
552 break;
553 case ARM_EXCEPTION_PREF_ABT:
554 debug("PREFETCH ABORT");
555 retaddr += 4;
556 break;
557 case ARM_EXCEPTION_IRQ:
558 debug("IRQ");
559 retaddr += 4;
560 break;
561 case ARM_EXCEPTION_FIQ:
562 debug("FIQ");
563 retaddr += 4;
564 break;
565 case ARM_EXCEPTION_DATA_ABT:
566 debug("DATA ABORT, far=0x%08x fsr=0x%02x",
567 cpu->cd.arm.far, cpu->cd.arm.fsr);
568 retaddr += 8;
569 break;
570 }
571
572 debug(" ]\n");
573
574 arm_save_register_bank(cpu);
575
576 switch (arm_exception_to_mode[exception_nr]) {
577 case ARM_MODE_SVC32:
578 cpu->cd.arm.spsr_svc = cpu->cd.arm.cpsr; break;
579 case ARM_MODE_ABT32:
580 cpu->cd.arm.spsr_abt = cpu->cd.arm.cpsr; break;
581 case ARM_MODE_UND32:
582 cpu->cd.arm.spsr_und = cpu->cd.arm.cpsr; break;
583 case ARM_MODE_IRQ32:
584 cpu->cd.arm.spsr_irq = cpu->cd.arm.cpsr; break;
585 case ARM_MODE_FIQ32:
586 cpu->cd.arm.spsr_fiq = cpu->cd.arm.cpsr; break;
587 default:fatal("arm_exception(): unimplemented exception nr\n");
588 exit(1);
589 }
590
591 /*
592 * Disable Thumb mode (because exception handlers always execute
593 * in ARM mode), set the exception mode, and disable interrupts:
594 */
595 cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
596
597 oldmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
598
599 cpu->cd.arm.cpsr &= ~ARM_FLAG_MODE;
600 cpu->cd.arm.cpsr |= arm_exception_to_mode[exception_nr];
601
602 newmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
603 if (oldmode == newmode) {
604 fatal("Exception caused no mode change? TODO\n");
605 exit(1);
606 }
607
608 cpu->cd.arm.cpsr |= ARM_FLAG_I;
609 if (exception_nr == ARM_EXCEPTION_RESET ||
610 exception_nr == ARM_EXCEPTION_FIQ)
611 cpu->cd.arm.cpsr |= ARM_FLAG_F;
612
613 /* Load the new register bank, if we switched: */
614 arm_load_register_bank(cpu);
615
616 /* Set the return address and new PC: */
617 cpu->cd.arm.r[ARM_LR] = retaddr;
618
619 cpu->pc = cpu->cd.arm.r[ARM_PC] = exception_nr * 4 +
620 ((cpu->cd.arm.control & ARM_CONTROL_V)? 0xffff0000 : 0);
621 arm_pc_to_pointers(cpu);
622 }
623
624
625 /*
626 * arm_cpu_interrupt():
627 *
628 * 0..31 are used as footbridge interrupt numbers, 32..47 = ISA,
629 * 64 is used as a "re-assert" signal to cpu->machine->md_interrupt().
630 *
631 * TODO: don't hardcode to footbridge!
632 */
633 int arm_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
634 {
635 /* fatal("arm_cpu_interrupt(): 0x%llx\n", (int)irq_nr); */
636 if (irq_nr <= 64) {
637 if (cpu->machine->md_interrupt != NULL)
638 cpu->machine->md_interrupt(cpu->machine,
639 cpu, irq_nr, 1);
640 else
641 fatal("arm_cpu_interrupt(): md_interrupt == NULL\n");
642 } else {
643 /* Assert ARM IRQs: */
644 cpu->cd.arm.irq_asserted = 1;
645 }
646
647 return 1;
648 }
649
650
651 /*
652 * arm_cpu_interrupt_ack():
653 */
654 int arm_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
655 {
656 if (irq_nr <= 64) {
657 if (cpu->machine->md_interrupt != NULL)
658 cpu->machine->md_interrupt(cpu->machine,
659 cpu, irq_nr, 0);
660 } else {
661 /* De-assert ARM IRQs: */
662 cpu->cd.arm.irq_asserted = 0;
663 }
664
665 return 1;
666 }
667
668
669 /*
670 * arm_cpu_disassemble_instr():
671 *
672 * Convert an instruction word into human readable format, for instruction
673 * tracing.
674 *
675 * If running is 1, cpu->pc should be the address of the instruction.
676 *
677 * If running is 0, things that depend on the runtime environment (eg.
678 * register contents) will not be shown, and addr will be used instead of
679 * cpu->pc for relative addresses.
680 */
681 int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
682 int running, uint64_t dumpaddr, int bintrans)
683 {
684 uint32_t iw, tmp;
685 int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
686 int i, n, p_bit, u_bit, b_bit, w_bit, l_bit;
687 char *symbol, *condition;
688 uint64_t offset;
689
690 if (running)
691 dumpaddr = cpu->pc;
692
693 symbol = get_symbol_name(&cpu->machine->symbol_context,
694 dumpaddr, &offset);
695 if (symbol != NULL && offset == 0)
696 debug("<%s>\n", symbol);
697
698 if (cpu->machine->ncpus > 1 && running)
699 debug("cpu%i:\t", cpu->cpu_id);
700
701 debug("%08x: ", (int)dumpaddr);
702
703 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
704 iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
705 else
706 iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
707 debug("%08x\t", (int)iw);
708
709 condition = arm_condition_string[iw >> 28];
710 main_opcode = (iw >> 24) & 15;
711 secondary_opcode = (iw >> 21) & 15;
712 u_bit = (iw >> 23) & 1;
713 b_bit = (iw >> 22) & 1;
714 w_bit = (iw >> 21) & 1;
715 s_bit = l_bit = (iw >> 20) & 1;
716 r16 = (iw >> 16) & 15;
717 r12 = (iw >> 12) & 15;
718 r8 = (iw >> 8) & 15;
719
720 switch (main_opcode) {
721 case 0x0:
722 case 0x1:
723 case 0x2:
724 case 0x3:
725 /*
726 * Special cases first:
727 */
728
729 /*
730 * Multiplication:
731 * xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd, Rm, Rs [,Rn])
732 */
733 if ((iw & 0x0fc000f0) == 0x00000090) {
734 int a_bit = (iw >> 21) & 1;
735 debug("%s%s%s\t", a_bit? "mla" : "mul",
736 condition, s_bit? "s" : "");
737 debug("%s,", arm_regname[r16]);
738 debug("%s,", arm_regname[iw & 15]);
739 debug("%s", arm_regname[r8]);
740 if (a_bit)
741 debug(",%s", arm_regname[r12]);
742 debug("\n");
743 break;
744 }
745
746 /*
747 * Long multiplication:
748 * xxxx0000 1UAShhhh llllssss 1001mmmm (Rl,Rh,Rm,Rs)
749 */
750 if ((iw & 0x0f8000f0) == 0x00800090) {
751 int u_bit = (iw >> 22) & 1;
752 int a_bit = (iw >> 21) & 1;
753 debug("%s%sl%s%s\t", u_bit? "s" : "u",
754 a_bit? "mla" : "mul", condition, s_bit? "s" : "");
755 debug("%s,", arm_regname[r12]);
756 debug("%s,", arm_regname[r16]);
757 debug("%s,", arm_regname[iw & 15]);
758 debug("%s\n", arm_regname[r8]);
759 break;
760 }
761
762 /*
763 * xxxx0001 0010.... ........ 00L1mmmm bx/blx rm
764 */
765 if ((iw & 0x0ff000d0) == 0x01200010) {
766 int l_bit = iw & 0x20;
767 debug("b%sx%s\t%s\n", l_bit? "l" : "", condition,
768 arm_regname[iw & 15]);
769 break;
770 }
771
772 /*
773 * xxxx0001 0s10aaaa 11110000 0000mmmm MSR Regform
774 * xxxx0011 0s10aaaa 1111rrrr bbbbbbbb MSR Immform
775 * xxxx0001 0s001111 dddd0000 00000000 MRS
776 */
777 if ((iw & 0x0fb0fff0) == 0x0120f000 ||
778 (iw & 0x0fb0f000) == 0x0320f000) {
779 int a = (iw >> 16) & 15;
780 debug("msr%s\t%s", condition, (iw&0x400000)? "S":"C");
781 debug("PSR_");
782 switch (a) {
783 case 1: debug("ctl"); break;
784 case 8: debug("flg"); break;
785 case 9: debug("all"); break;
786 default:debug(" UNIMPLEMENTED (a=%i)", a);
787 }
788 if (iw & 0x02000000) {
789 int r = (iw >> 7) & 30;
790 uint32_t b = iw & 0xff;
791 while (r-- > 0)
792 b = (b >> 1) | ((b & 1) << 31);
793 debug(",#0x%x\n", b);
794 } else
795 debug(",%s\n", arm_regname[iw & 15]);
796 break;
797 }
798 if ((iw & 0x0fbf0fff) == 0x010f0000) {
799 debug("mrs%s\t", condition);
800 debug("%s,%sPSR\n", arm_regname[r12],
801 (iw&0x400000)? "S":"C");
802 break;
803 }
804
805 /*
806 * xxxx0001 0B00nnnn dddd0000 1001mmmm SWP Rd,Rm,[Rn]
807 */
808 if ((iw & 0x0fb00ff0) == 0x01000090) {
809 debug("swp%s%s\t", condition, (iw&0x400000)? "b":"");
810 debug("%s,%s,[%s]\n", arm_regname[r12],
811 arm_regname[iw & 15], arm_regname[r16]);
812 break;
813 }
814
815 /*
816 * xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn)
817 */
818 if ((iw & 0x0e000090) == 0x00000090) {
819 int imm = ((iw >> 4) & 0xf0) | (iw & 0xf);
820 int regform = !(iw & 0x00400000);
821 p_bit = main_opcode & 1;
822 /*
823 * TODO: detect some illegal variants:
824 * signed store, or unsigned byte load/store
825 */
826 if (!l_bit && (iw & 0xd0) == 0xd0 && (r12 & 1)) {
827 debug("TODO: r12 odd, not load/store\n");
828 break;
829 }
830 /* Semi-generic case: */
831 debug("%sr%s", iw & 0x00100000? "ld" : "st",
832 condition);
833 if (!l_bit && (iw & 0xd0) == 0xd0) {
834 debug("d"); /* Double-register */
835 } else {
836 if (iw & 0x40)
837 debug("s"); /* signed */
838 if (iw & 0x20)
839 debug("h"); /* half-word */
840 else
841 debug("b"); /* byte */
842 }
843 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
844 if (p_bit) {
845 /* Pre-index: */
846 if (regform)
847 debug(",%s%s", u_bit? "" : "-",
848 arm_regname[iw & 15]);
849 else {
850 if (imm != 0)
851 debug(",#%s%i", u_bit? "" : "-",
852 imm);
853 }
854 debug("]%s\n", w_bit? "!" : "");
855 } else {
856 /* Post-index: */
857 debug("],");
858 if (regform)
859 debug("%s%s\n", u_bit? "" : "-",
860 arm_regname[iw & 15]);
861 else
862 debug("#%s%i\n", u_bit? "" : "-", imm);
863 }
864 break;
865 }
866
867 /* Other special cases: */
868 if (iw & 0x80 && !(main_opcode & 2) && iw & 0x10) {
869 debug("UNIMPLEMENTED reg (c!=0), t odd\n");
870 break;
871 }
872
873 /*
874 * Generic Data Processing Instructions:
875 *
876 * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
877 * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
878 */
879
880 debug("%s%s%s\t", arm_dpiname[secondary_opcode],
881 condition, s_bit? "s" : "");
882 if (arm_dpi_uses_d[secondary_opcode])
883 debug("%s,", arm_regname[r12]);
884 if (arm_dpi_uses_n[secondary_opcode])
885 debug("%s,", arm_regname[r16]);
886
887 if (main_opcode & 2) {
888 /* Immediate form: */
889 int r = (iw >> 7) & 30;
890 uint32_t b = iw & 0xff;
891 while (r-- > 0)
892 b = (b >> 1) | ((b & 1) << 31);
893 if (b < 15)
894 debug("#%i", b);
895 else
896 debug("#0x%x", b);
897 } else {
898 /* Register form: */
899 int t = (iw >> 4) & 7;
900 int c = (iw >> 7) & 31;
901 debug("%s", arm_regname[iw & 15]);
902 switch (t) {
903 case 0: if (c != 0)
904 debug(", lsl #%i", c);
905 break;
906 case 1: debug(", lsl %s", arm_regname[c >> 1]);
907 break;
908 case 2: debug(", lsr #%i", c? c : 32);
909 break;
910 case 3: debug(", lsr %s", arm_regname[c >> 1]);
911 break;
912 case 4: debug(", asr #%i", c? c : 32);
913 break;
914 case 5: debug(", asr %s", arm_regname[c >> 1]);
915 break;
916 case 6: if (c != 0)
917 debug(", ror #%i", c);
918 else
919 debug(", rrx");
920 break;
921 case 7: debug(", ror %s", arm_regname[c >> 1]);
922 break;
923 }
924
925 /* mov pc,reg: */
926 if (running && t == 0 && c == 0 && secondary_opcode
927 == 0xd && r12 == ARM_PC && (iw&15)!=ARM_PC) {
928 symbol = get_symbol_name(&cpu->machine->
929 symbol_context, cpu->cd.arm.r[iw & 15],
930 &offset);
931 if (symbol != NULL)
932 debug(" \t<%s>", symbol);
933 }
934 }
935 debug("\n");
936 break;
937 case 0x4: /* Single Data Transfer */
938 case 0x5:
939 case 0x6:
940 case 0x7:
941 /* Special case first: */
942 if ((iw & 0xfc70f000) == 0xf450f000) {
943 /* Preload: */
944 debug("pld\t[%s]\n", arm_regname[r16]);
945 break;
946 }
947
948 /*
949 * xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form
950 * xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form
951 */
952 p_bit = main_opcode & 1;
953 if (main_opcode >= 6 && iw & 0x10) {
954 debug("TODO: single data transf. but 0x10\n");
955 break;
956 }
957 debug("%s%s%s", l_bit? "ldr" : "str",
958 condition, b_bit? "b" : "");
959 if (!p_bit && w_bit)
960 debug("t");
961 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
962 if ((iw & 0x0e000000) == 0x04000000) {
963 /* Immediate form: */
964 uint32_t imm = iw & 0xfff;
965 if (!p_bit)
966 debug("]");
967 if (imm != 0)
968 debug(",#%s%i", u_bit? "" : "-", imm);
969 if (p_bit)
970 debug("]");
971 } else if ((iw & 0x0e000010) == 0x06000000) {
972 /* Register form: */
973 if (!p_bit)
974 debug("]");
975 if ((iw & 0xfff) != 0)
976 debug(",%s%s", u_bit? "" : "-",
977 arm_regname[iw & 15]);
978 if ((iw & 0xff0) != 0x000) {
979 int c = (iw >> 7) & 31;
980 int t = (iw >> 4) & 7;
981 switch (t) {
982 case 0: if (c != 0)
983 debug(", lsl #%i", c);
984 break;
985 case 2: debug(", lsr #%i", c? c : 32);
986 break;
987 case 4: debug(", asr #%i", c? c : 32);
988 break;
989 case 6: if (c != 0)
990 debug(", ror #%i", c);
991 else
992 debug(", rrx");
993 break;
994 }
995 }
996 if (p_bit)
997 debug("]");
998 } else {
999 debug("UNKNOWN\n");
1000 break;
1001 }
1002 debug("%s", (p_bit && w_bit)? "!" : "");
1003 if ((iw & 0x0f000000) == 0x05000000 &&
1004 (r16 == ARM_PC || running)) {
1005 unsigned char tmpw[4];
1006 uint32_t imm = iw & 0xfff;
1007 uint32_t addr = (u_bit? imm : -imm);
1008 if (r16 == ARM_PC)
1009 addr += dumpaddr + 8;
1010 else
1011 addr += cpu->cd.arm.r[r16];
1012 symbol = get_symbol_name(&cpu->machine->symbol_context,
1013 addr, &offset);
1014 if (symbol != NULL)
1015 debug(" \t<%s", symbol);
1016 else
1017 debug(" \t<0x%08x", addr);
1018 if ((l_bit && cpu->memory_rw(cpu, cpu->mem, addr, tmpw,
1019 b_bit? 1 : sizeof(tmpw), MEM_READ, NO_EXCEPTIONS))
1020 || (!l_bit && running)) {
1021 if (l_bit) {
1022 if (cpu->byte_order ==
1023 EMUL_LITTLE_ENDIAN)
1024 addr = tmpw[0] +(tmpw[1] << 8) +
1025 (tmpw[2]<<16)+(tmpw[3]<<24);
1026 else
1027 addr = tmpw[3] + (tmpw[2]<<8) +
1028 (tmpw[1]<<16)+(tmpw[0]<<24);
1029 } else {
1030 tmpw[0] = addr = cpu->cd.arm.r[r12];
1031 if (r12 == ARM_PC)
1032 addr += 8;
1033 }
1034 debug(": ");
1035 if (b_bit)
1036 debug("%i", tmpw[0]);
1037 else {
1038 symbol = get_symbol_name(&cpu->machine->
1039 symbol_context, addr, &offset);
1040 if (symbol != NULL)
1041 debug("%s", symbol);
1042 else if ((int32_t)addr > -256 &&
1043 (int32_t)addr < 256)
1044 debug("%i", addr);
1045 else
1046 debug("0x%x", addr);
1047 }
1048 }
1049 debug(">");
1050 }
1051 debug("\n");
1052 break;
1053 case 0x8: /* Block Data Transfer */
1054 case 0x9:
1055 /* xxxx100P USWLnnnn llllllll llllllll */
1056 p_bit = main_opcode & 1;
1057 s_bit = b_bit;
1058 debug("%s%s", l_bit? "ldm" : "stm", condition);
1059 switch (u_bit * 2 + p_bit) {
1060 case 0: debug("da"); break;
1061 case 1: debug("db"); break;
1062 case 2: debug("ia"); break;
1063 case 3: debug("ib"); break;
1064 }
1065 debug("\t%s", arm_regname[r16]);
1066 if (w_bit)
1067 debug("!");
1068 debug(",{");
1069 n = 0;
1070 for (i=0; i<16; i++)
1071 if ((iw >> i) & 1) {
1072 debug("%s%s", (n > 0)? ",":"", arm_regname[i]);
1073 n++;
1074 }
1075 debug("}");
1076 if (s_bit)
1077 debug("^");
1078 debug("\n");
1079 break;
1080 case 0xa: /* B: branch */
1081 case 0xb: /* BL: branch and link */
1082 debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
1083 tmp = (iw & 0x00ffffff) << 2;
1084 if (tmp & 0x02000000)
1085 tmp |= 0xfc000000;
1086 tmp = (int32_t)(dumpaddr + tmp + 8);
1087 debug("0x%x", (int)tmp);
1088 symbol = get_symbol_name(&cpu->machine->symbol_context,
1089 tmp, &offset);
1090 if (symbol != NULL)
1091 debug(" \t<%s>", symbol);
1092 debug("\n");
1093 break;
1094 case 0xc: /* Coprocessor */
1095 case 0xd: /* LDC/STC */
1096 /* xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC */
1097 debug("TODO: coprocessor LDC/STC\n");
1098 break;
1099 case 0xe: /* CDP (Coprocessor Op) */
1100 /* or MRC/MCR!
1101 * xxxx1110 oooonnnn ddddpppp qqq0mmmm CDP
1102 * xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR
1103 */
1104 if (iw & 0x10) {
1105 debug("%s%s\t",
1106 (iw & 0x00100000)? "mrc" : "mcr", condition);
1107 debug("%i,%i,r%i,cr%i,cr%i,%i",
1108 (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
1109 (int)((iw >>12) & 15), (int)((iw >>16) & 15),
1110 (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
1111 } else {
1112 debug("cdp%s\t", condition);
1113 debug("%i,%i,cr%i,cr%i,cr%i",
1114 (int)((iw >> 8) & 15),
1115 (int)((iw >>20) & 15),
1116 (int)((iw >>12) & 15),
1117 (int)((iw >>16) & 15),
1118 (int)((iw >> 0) & 15));
1119 if ((iw >> 5) & 7)
1120 debug(",0x%x", (int)((iw >> 5) & 7));
1121 }
1122 debug("\n");
1123 break;
1124 case 0xf: /* SWI */
1125 debug("swi%s\t", condition);
1126 debug("0x%x\n", (int)(iw & 0x00ffffff));
1127 break;
1128 default:debug("UNIMPLEMENTED\n");
1129 }
1130
1131 return sizeof(uint32_t);
1132 }
1133
1134
1135 /*****************************************************************************/
1136
1137
1138 /*
1139 * arm_mcr_mrc():
1140 *
1141 * Coprocessor register move.
1142 *
1143 * The program counter should be synched before calling this function (to
1144 * make debug output with the correct PC value possible).
1145 */
1146 void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
1147 {
1148 int opcode1 = (iword >> 21) & 7;
1149 int l_bit = (iword >> 20) & 1;
1150 int crn = (iword >> 16) & 15;
1151 int rd = (iword >> 12) & 15;
1152 int cp_num = (iword >> 8) & 15;
1153 int opcode2 = (iword >> 5) & 7;
1154 int crm = iword & 15;
1155
1156 if (cpu->cd.arm.coproc[cp_num] != NULL)
1157 cpu->cd.arm.coproc[cp_num](cpu, opcode1, opcode2, l_bit,
1158 crn, crm, rd);
1159 else {
1160 fatal("arm_mcr_mrc: pc=0x%08x, iword=0x%08x: "
1161 "cp_num=%i\n", (int)cpu->pc, iword, cp_num);
1162 exit(1);
1163 }
1164 }
1165
1166
1167 /*
1168 * arm_cdp():
1169 *
1170 * Coprocessor operations.
1171 *
1172 * The program counter should be synched before calling this function (to
1173 * make debug output with the correct PC value possible).
1174 */
1175 void arm_cdp(struct cpu *cpu, uint32_t iword)
1176 {
1177 fatal("arm_cdp: pc=0x%08x, iword=0x%08x\n", (int)cpu->pc, iword);
1178 exit(1);
1179 }
1180
1181
1182 /*****************************************************************************/
1183
1184
1185 #include "tmp_arm_tail.c"
1186

  ViewVC Help
Powered by ViewVC 1.1.26