diff options
author | DJ Delorie <dj@redhat.com> | 2008-06-06 19:18:15 +0000 |
---|---|---|
committer | DJ Delorie <dj@redhat.com> | 2008-06-06 19:18:15 +0000 |
commit | 3877a1459be9bdeb20ae891b3f68220b837a81cb (patch) | |
tree | 02fc0eea00e77cc6ff7e691bafebe6cd2e09d77f /sim/m32c | |
parent | ebfe2e3fb6a1078dcbbc4231ddd7ddec365bfe09 (diff) | |
download | gdb-3877a1459be9bdeb20ae891b3f68220b837a81cb.zip gdb-3877a1459be9bdeb20ae891b3f68220b837a81cb.tar.gz gdb-3877a1459be9bdeb20ae891b3f68220b837a81cb.tar.bz2 |
* Makefile.in: Add Timer A support.
* cpu.h (m32c_opcode_pc): New.
(in_gdb): New.
* gdb-if.c (sim_open): Add Timer A support. Support unbuffered
console.
* int.c (trigger_interrupt): Manage the U flag properly.
(trigger_based_interrupt): Likewise.
(trigger_fixed_interrupt): New.
(trigger_peripheral_interrupt): New.
* int.h (trigger_peripheral_interrupt): New.
* m32c.opc: Use m32c_opcode_pc throughout, as needed.
(decode_m32c): Detect jump-to-zero with traceback.
(BRK): Try to do the right thing, keeping track of whether we're
in gdb or not, and if the user has provided a handler or not.
(GBRK): Alternate break opcode for gdb, in case the user's app
needs to use BRK for itself.
(BRK2): Implement.
* main.c: Add Timer A support. Support TCP-based console.
(setup_tcp_console): New.
(main): Add Timer A support. Support TCP-based console.
* mem.c: Add Timer A support. Support TCP-based console.
(mem_ptr): Enhance NULL pointer detection.
(stdin_ready): New.
(m32c_sim_restore_console): New.
(mem_get_byte): Check for console input ready.
(update_timer_a): New.
* r8c.opc (SSTR): Use r0l, not r0h.
(REIT): Fix return frame logic.
* reg.c (print_flags): New.
(trace_register_changes): Use it.
(m32c_dump_all_registers): New.
* timer_a.h: New.
* load.c: Fix indentation.
* trace.c: Fix indentation.
* trace.h: Fix indentation.
Diffstat (limited to 'sim/m32c')
-rw-r--r-- | sim/m32c/ChangeLog | 39 | ||||
-rw-r--r-- | sim/m32c/Makefile.in | 2 | ||||
-rw-r--r-- | sim/m32c/cpu.h | 6 | ||||
-rw-r--r-- | sim/m32c/gdb-if.c | 16 | ||||
-rw-r--r-- | sim/m32c/int.c | 28 | ||||
-rw-r--r-- | sim/m32c/int.h | 1 | ||||
-rw-r--r-- | sim/m32c/load.c | 2 | ||||
-rw-r--r-- | sim/m32c/m32c.opc | 77 | ||||
-rw-r--r-- | sim/m32c/main.c | 90 | ||||
-rw-r--r-- | sim/m32c/mem.c | 232 | ||||
-rw-r--r-- | sim/m32c/opc2c.c | 4 | ||||
-rw-r--r-- | sim/m32c/r8c.opc | 6 | ||||
-rw-r--r-- | sim/m32c/reg.c | 59 | ||||
-rw-r--r-- | sim/m32c/safe-fgets.c | 2 | ||||
-rw-r--r-- | sim/m32c/safe-fgets.h | 2 | ||||
-rw-r--r-- | sim/m32c/timer_a.h | 12 | ||||
-rw-r--r-- | sim/m32c/trace.c | 6 | ||||
-rw-r--r-- | sim/m32c/trace.h | 2 |
18 files changed, 519 insertions, 67 deletions
diff --git a/sim/m32c/ChangeLog b/sim/m32c/ChangeLog index a3afdf0..121670d 100644 --- a/sim/m32c/ChangeLog +++ b/sim/m32c/ChangeLog @@ -1,3 +1,42 @@ +2008-06-06 DJ Delorie <dj@redhat.com> + + * Makefile.in: Add Timer A support. + * cpu.h (m32c_opcode_pc): New. + (in_gdb): New. + * gdb-if.c (sim_open): Add Timer A support. Support unbuffered + console. + * int.c (trigger_interrupt): Manage the U flag properly. + (trigger_based_interrupt): Likewise. + (trigger_fixed_interrupt): New. + (trigger_peripheral_interrupt): New. + * int.h (trigger_peripheral_interrupt): New. + * m32c.opc: Use m32c_opcode_pc throughout, as needed. + (decode_m32c): Detect jump-to-zero with traceback. + (BRK): Try to do the right thing, keeping track of whether we're + in gdb or not, and if the user has provided a handler or not. + (GBRK): Alternate break opcode for gdb, in case the user's app + needs to use BRK for itself. + (BRK2): Implement. + * main.c: Add Timer A support. Support TCP-based console. + (setup_tcp_console): New. + (main): Add Timer A support. Support TCP-based console. + * mem.c: Add Timer A support. Support TCP-based console. + (mem_ptr): Enhance NULL pointer detection. + (stdin_ready): New. + (m32c_sim_restore_console): New. + (mem_get_byte): Check for console input ready. + (update_timer_a): New. + * r8c.opc (SSTR): Use r0l, not r0h. + (REIT): Fix return frame logic. + * reg.c (print_flags): New. + (trace_register_changes): Use it. + (m32c_dump_all_registers): New. + * timer_a.h: New. + + * load.c: Fix indentation. + * trace.c: Fix indentation. + * trace.h: Fix indentation. + 2006-06-26 DJ Delorie <dj@redhat.com> * r8c.opc (decode_r8c): Don't bother reading the destination diff --git a/sim/m32c/Makefile.in b/sim/m32c/Makefile.in index f58de57..ab3781c 100644 --- a/sim/m32c/Makefile.in +++ b/sim/m32c/Makefile.in @@ -20,7 +20,7 @@ ## COMMON_PRE_CONFIG_FRAG -SIM_EXTRA_CFLAGS = -Wall +SIM_EXTRA_CFLAGS = -Wall -DTIMER_A SIM_RUN_OBJS = \ main.o \ diff --git a/sim/m32c/cpu.h b/sim/m32c/cpu.h index eae4cd5..e11d5ef 100644 --- a/sim/m32c/cpu.h +++ b/sim/m32c/cpu.h @@ -23,6 +23,8 @@ extern int verbose; extern int trace; extern int enable_counting; +extern int in_gdb; + typedef unsigned char QI; typedef unsigned short HI; typedef unsigned long SI; @@ -101,6 +103,10 @@ extern unsigned int b2signbit[]; extern int b2maxsigned[]; extern int b2minsigned[]; +/* address of the opcode that just decoded, and thus caused the + exception. */ +extern int m32c_opcode_pc; + void init_regs (void); void stack_heap_stats (void); void set_pointer_width (int bytes); diff --git a/sim/m32c/gdb-if.c b/sim/m32c/gdb-if.c index 3ed3221..a8ba392 100644 --- a/sim/m32c/gdb-if.c +++ b/sim/m32c/gdb-if.c @@ -58,6 +58,7 @@ sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *callback, struct bfd *abfd, char **argv) { + setbuf (stdout, 0); if (open) fprintf (stderr, "m32c minisim: re-opened sim\n"); @@ -124,7 +125,7 @@ open_objfile (const char *filename) SIM_RC -sim_load (SIM_DESC sd, char *prog, struct bfd *abfd, int from_tty) +sim_load (SIM_DESC sd, char *prog, struct bfd * abfd, int from_tty) { check_desc (sd); @@ -139,7 +140,7 @@ sim_load (SIM_DESC sd, char *prog, struct bfd *abfd, int from_tty) } SIM_RC -sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char **argv, char **env) +sim_create_inferior (SIM_DESC sd, struct bfd * abfd, char **argv, char **env) { check_desc (sd); @@ -608,7 +609,12 @@ sim_resume (SIM_DESC sd, int step, int sig_to_deliver) } if (step) - handle_step (decode_opcode ()); + { + handle_step (decode_opcode ()); +#ifdef TIMER_A + update_timer_a (); +#endif + } else { /* We don't clear 'stop' here, because then we would miss @@ -626,6 +632,9 @@ sim_resume (SIM_DESC sd, int step, int sig_to_deliver) } int rc = decode_opcode (); +#ifdef TIMER_A + update_timer_a (); +#endif if (!M32C_STEPPED (rc)) { @@ -634,6 +643,7 @@ sim_resume (SIM_DESC sd, int step, int sig_to_deliver) } } } + m32c_sim_restore_console (); } int diff --git a/sim/m32c/int.c b/sim/m32c/int.c index 1959c77..5556a12 100644 --- a/sim/m32c/int.c +++ b/sim/m32c/int.c @@ -23,13 +23,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "cpu.h" #include "mem.h" -void -trigger_fixed_interrupt (int addr) +static void +trigger_interrupt (int addr, int clear_u) { int s = get_reg (sp); int f = get_reg (flags); int p = get_reg (pc); + if (clear_u) + set_flags (FLAGBIT_U, 0); + set_flags (FLAGBIT_I | FLAGBIT_D, 0); + if (A16) { s -= 4; @@ -46,14 +50,26 @@ trigger_fixed_interrupt (int addr) mem_put_hi (s + 4, f); } put_reg (pc, mem_get_psi (addr)); - set_flags (FLAGBIT_U | FLAGBIT_I | FLAGBIT_D, 0); +} + +void +trigger_fixed_interrupt (int addr) +{ + trigger_interrupt (addr, 1); } void trigger_based_interrupt (int vector) { int addr = get_reg (intb) + vector * 4; - if (vector <= 31) - set_flags (FLAGBIT_U, 0); - trigger_fixed_interrupt (addr); + trigger_interrupt (addr, vector <= 31); +} + +void +trigger_peripheral_interrupt (int vector, int icaddr) +{ + unsigned char old_ic = mem_get_qi (icaddr); + int addr = get_reg (intb) + vector * 4; + trigger_interrupt (addr, 1); + put_reg (flags, (get_reg (flags) & 0x8fff) | ((old_ic & 7) << 12)); } diff --git a/sim/m32c/int.h b/sim/m32c/int.h index 3d36500..ef4bc27 100644 --- a/sim/m32c/int.h +++ b/sim/m32c/int.h @@ -21,3 +21,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ extern void trigger_fixed_interrupt (int addr); extern void trigger_based_interrupt (int vector); +extern void trigger_peripheral_interrupt (int vector, int icaddr); diff --git a/sim/m32c/load.c b/sim/m32c/load.c index 229bc0d..755c89a 100644 --- a/sim/m32c/load.c +++ b/sim/m32c/load.c @@ -54,7 +54,7 @@ m32c_set_mach (unsigned long mach) } void -m32c_load (bfd *prog) +m32c_load (bfd * prog) { asection *s; unsigned long mach = bfd_get_mach (prog); diff --git a/sim/m32c/m32c.opc b/sim/m32c/m32c.opc index da77f95..9f5bd4a 100644 --- a/sim/m32c/m32c.opc +++ b/sim/m32c/m32c.opc @@ -49,8 +49,8 @@ getbyte () #define GETBYTE() (op[opi++] = getbyte()) -#define UNSUPPORTED() unsupported("unsupported", orig_pc) -#define NOTYET() unsupported("unimplemented", orig_pc) +#define UNSUPPORTED() unsupported("unsupported", m32c_opcode_pc) +#define NOTYET() unsupported("unimplemented", m32c_opcode_pc) static void unsupported (char *tag, int orig_pc) @@ -390,12 +390,14 @@ shift_op (srcdest sd, int arith, int count, int setc) set_flags (FLAGBIT_O, o ? FLAGBIT_O : 0); } +static int pcs[16]; +static int ipcs = 0; + int decode_m32c() { unsigned char op[40]; int opi; - int orig_pc; int v, a, b; long long ll; srcdest sc, dc; @@ -411,9 +413,20 @@ decode_m32c() next_opcode: opi = 0; - orig_pc = get_reg (pc); + m32c_opcode_pc = get_reg (pc); + + tprintf("trace: decode pc = %06x\n", m32c_opcode_pc); - tprintf("trace: decode pc = %06x\n", orig_pc); + if (m32c_opcode_pc == 0) + { + int i; + printf("Abort: PC is zero, here from:\n"); + for (i=0; i<4; i++) + printf(" 0x%06x\n", pcs[(ipcs+15-i)%16]); + return M32C_MAKE_HIT_BREAK (); + } + pcs[ipcs++] = m32c_opcode_pc; + ipcs %= 16; /** VARY sss 000 001 010 011 100 */ /** VARY ddd 000 001 010 011 100 */ @@ -564,7 +577,7 @@ next_opcode: if ((v & (w ? 0xffff : 0xff)) != 0) { tprintf("jmp: %x + 2 + %d = ", get_reg (pc), a); - put_reg (pc, orig_pc + 2 + a); + put_reg (pc, m32c_opcode_pc + 2 + a); tprintf("%x\n", get_reg (pc)); } @@ -666,16 +679,41 @@ next_opcode: /* We report the break to our caller with the PC still pointing at the breakpoint instruction. */ - put_reg (pc, orig_pc); - if (verbose) + put_reg (pc, m32c_opcode_pc); + if (verbose || 1) printf("[break]\n"); + if (in_gdb || (regs.r_intbl == 0 && regs.r_intbh == 0)) + return M32C_MAKE_HIT_BREAK (); + if (mem_get_qi (0xFFFFE7) == 0xff) + trigger_based_interrupt (0); + else + trigger_fixed_interrupt (0xFFFFE4); + + /** 1111 1110 GBRK */ + + /* This alternate break, which is not part of the chip's opcode set, + is here in case you need to debug a program that itself uses the + chip's BRK opcode. You'll need to modify your copy of GDB to use + this opcode instead of the real BRK. */ + + /* GDB Break. */ + /* We report the break to our caller with the PC still pointing at the + breakpoint instruction. */ + put_reg (pc, m32c_opcode_pc); + if (verbose || 1) + printf("[gdb break]\n"); return M32C_MAKE_HIT_BREAK (); - /** 0000 1000 BRK */ + /** 0000 1000 BRK2 */ if (verbose) printf("[break2]\n"); - return M32C_MAKE_HIT_BREAK (); + if (in_gdb) + return M32C_MAKE_HIT_BREAK (); + if (mem_get_qi (0xFFFFE7) == 0xff) + trigger_based_interrupt (0); + else + trigger_fixed_interrupt (0xFFFFE4); /** 1101 ddd0 dd11 1bit BSET dest */ @@ -988,12 +1026,12 @@ next_opcode: prefix (0, 0, 0); v = sign_ext (IMM(1), 8); if (condition_true (ccc*2+c)) - put_reg (pc, orig_pc + 1 + v); + put_reg (pc, m32c_opcode_pc + 1 + v); /** 01dd 101d JMP.S label */ prefix (0, 0, 0); - put_reg (pc, orig_pc + (dd*2+d) + 2); + put_reg (pc, m32c_opcode_pc + (dd*2+d) + 2); /** 1011 1011 JMP.B label */ @@ -1005,13 +1043,13 @@ next_opcode: printf("[jmp-to-self detected as exit]\n"); return M32C_MAKE_HIT_BREAK (); } - put_reg (pc, orig_pc + 1 + imm); + put_reg (pc, m32c_opcode_pc + 1 + imm); /** 1100 1110 JMP.W label */ prefix (0, 0, 0); imm = sign_ext (IMM(2), 16); - put_reg (pc, orig_pc + 1 + imm); + put_reg (pc, m32c_opcode_pc + 1 + imm); /** 1100 1100 JMP.A label */ @@ -1025,7 +1063,7 @@ next_opcode: sc = decode_src23 (sss, ss, 2); a = get_src (sc); a = sign_ext (a, 16); - put_reg (pc, orig_pc + a); + put_reg (pc, m32c_opcode_pc + a); /** 1000 sss0 ss00 0001 JMPI.A src */ @@ -1047,7 +1085,7 @@ next_opcode: imm = sign_ext (IMM(2), 16); put_reg (sp, get_reg (sp) - 4); mem_put_si (get_reg (sp), get_reg (pc)); - put_reg (pc, orig_pc + imm + 1); + put_reg (pc, m32c_opcode_pc + imm + 1); /** 1100 1101 JSR.A label */ @@ -1065,7 +1103,7 @@ next_opcode: a = sign_ext (a, 16); put_reg (sp, get_reg (sp) - 4); mem_put_si (get_reg (sp), get_reg (pc)); - put_reg (pc, orig_pc + a); + put_reg (pc, m32c_opcode_pc + a); /** 1001 sss0 ss00 0001 JSRI.A src */ @@ -1917,12 +1955,13 @@ next_opcode: a = get_reg (a1); b = get_reg (r3); + v = get_reg (w ? r0 : r0l); for (;b;) { if (w) - mem_put_hi(a, r0); + mem_put_hi(a, v); else - mem_put_qi(a, r0 & 0xff); + mem_put_qi(a, v); a += w ? 2 : 1; b --; } diff --git a/sim/m32c/main.c b/sim/m32c/main.c index 7b54f4b..7187210 100644 --- a/sim/m32c/main.c +++ b/sim/m32c/main.c @@ -27,6 +27,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <setjmp.h> #include <signal.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> + + #include "bfd.h" #include "cpu.h" @@ -34,8 +40,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "misc.h" #include "load.h" #include "trace.h" +#ifdef TIMER_A +#include "int.h" +#include "timer_a.h" +#endif -static int disassemble = 0; +extern int m32c_console_ofd; +extern int m32c_console_ifd; + +int m32c_disassemble = 0; static unsigned int cycles = 0; static void @@ -50,24 +63,79 @@ done (int exit_code) exit (exit_code); } +static void +setup_tcp_console (char *portname) +{ + int port = atoi (portname); + struct sockaddr_in address; + int isocket; + socklen_t as; + unsigned char *a; + + if (port < 1024) + { + printf ("invalid port number %d\n", port); + exit (1); + } + printf ("waiting for tcp console on port %d\n", port); + + memset (&address, 0, sizeof (address)); + address.sin_family = AF_INET; + address.sin_port = htons (port); + + isocket = socket (AF_INET, SOCK_STREAM, 0); + if (isocket < 0) + { + perror ("socket"); + exit (1); + } + + if (bind (isocket, (struct sockaddr *) &address, sizeof (address))) + { + perror ("bind"); + exit (1); + } + listen (isocket, 2); + + printf ("waiting for connection...\n"); + as = sizeof (address); + m32c_console_ifd = accept (isocket, (struct sockaddr *) &address, &as); + if (m32c_console_ifd == -1) + { + perror ("accept"); + exit (1); + } + a = (unsigned char *) (&address.sin_addr.s_addr); + printf ("connection from %d.%d.%d.%d\n", a[0], a[1], a[2], a[3]); + m32c_console_ofd = m32c_console_ifd; +} + int main (int argc, char **argv) { int o; int save_trace; bfd *prog; + char *console_port_s = 0; + + setbuf (stdout, 0); + + in_gdb = 0; - while ((o = getopt (argc, argv, "tvdm:")) != -1) + while ((o = getopt (argc, argv, "tc:vdm:")) != -1) switch (o) { case 't': trace++; break; + case 'c': + console_port_s = optarg; + break; case 'v': verbose++; break; case 'd': - disassemble++; + m32c_disassemble++; break; case 'm': if (strcmp (optarg, "r8c") == 0 || strcmp (optarg, "m16c") == 0) @@ -83,8 +151,8 @@ main (int argc, char **argv) break; case '?': fprintf (stderr, - "usage: run [-v] [-t] [-d] [-m r8c|m16c|m32cm|m32c]" - " program\n"); + "usage: run [-v] [-t] [-d] [-m r8c|m16c|m32cm|m32c]" + " program\n"); exit (1); } @@ -106,8 +174,10 @@ main (int argc, char **argv) m32c_load (prog); trace = save_trace; - if (disassemble) - sim_disasm_init (prog); + if (console_port_s) + setup_tcp_console (console_port_s); + + sim_disasm_init (prog); while (1) { @@ -116,7 +186,7 @@ main (int argc, char **argv) if (trace) printf ("\n"); - if (disassemble) + if (m32c_disassemble) sim_disasm_one (); enable_counting = verbose; @@ -132,5 +202,9 @@ main (int argc, char **argv) assert (M32C_STEPPED (rc)); trace_register_changes (); + +#ifdef TIMER_A + update_timer_a (); +#endif } } diff --git a/sim/m32c/mem.c b/sim/m32c/mem.c index 4321629..a277787 100644 --- a/sim/m32c/mem.c +++ b/sim/m32c/mem.c @@ -22,11 +22,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <ctype.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/select.h> +#include <termios.h> #include "mem.h" #include "cpu.h" #include "syscalls.h" #include "misc.h" +#ifdef TIMER_A +#include "int.h" +#include "timer_a.h" +#endif #define L1_BITS (10) #define L2_BITS (10) @@ -38,8 +48,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ static unsigned char **pt[L1_LEN]; +int m32c_console_ifd = 0; +int m32c_console_ofd = 1; + +#ifdef TIMER_A +Timer_A timer_a; +#endif + /* [ get=0/put=1 ][ byte size ] */ -static unsigned int mem_counters[2][4]; +static unsigned int mem_counters[2][5]; #define COUNT(isput,bytes) \ if (verbose && enable_counting) mem_counters[isput][bytes]++ @@ -64,14 +81,23 @@ init_mem (void) static unsigned char * mem_ptr (address) { + static int recursing = 0; int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1); int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1); int pto = address & ((1 << OFF_BITS) - 1); - if (address == 0) + if (address == 0 && !recursing) { - printf ("NULL pointer dereference\n"); + recursing = 1; + put_reg (pc, m32c_opcode_pc); + printf ("NULL pointer dereference at pc=0x%x\n", get_reg (pc)); + step_result = M32C_MAKE_HIT_BREAK (); +#if 0 + /* This code can be re-enabled to help diagnose NULL pointer + bugs that aren't debuggable in GDB. */ + m32c_dump_all_registers (); exit (1); +#endif } if (pt[pt1] == 0) @@ -138,7 +164,7 @@ mem_usage_stats () /* mem foo: 123456789012 123456789012 123456789012 123456789012 123456789012 */ printf (" byte short pointer long" - " fetch\n"); + " fetch\n"); printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2), mcs (0, 3), mcs (0, 4), mcs (0, 0)); printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2), @@ -167,6 +193,8 @@ e () #define E() if (trace) e() +extern int m32c_disassemble; + void mem_put_byte (int address, unsigned char value) { @@ -199,21 +227,65 @@ mem_put_byte (int address, unsigned char value) } } break; +#ifdef TIMER_A + /* M32C Timer A */ + case 0x346: /* TA0low */ + timer_a.count = (timer_a.count & 0xff00) | value; + timer_a.reload = timer_a.count; + break; + case 0x347: /* TA0high */ + timer_a.count = (timer_a.count & 0x00ff) | (value << 8); + timer_a.reload = timer_a.count; + break; + case 0x340: /* TABSR */ + timer_a.bsr = value; + break; + case 0x356: /* TA0MR */ + timer_a.mode = value; + break; + case 0x35f: /* TCSPR */ + timer_a.tcspr = value; + break; + case 0x006c: /* TA0IC */ + timer_a.ic = value; + break; + + /* R8C Timer RA */ + case 0x100: /* TRACR */ + timer_a.bsr = value; + break; + case 0x102: /* TRAMR */ + timer_a.mode = value; + break; + case 0x104: /* TRA */ + timer_a.count = value; + timer_a.reload = value; + break; + case 0x103: /* TRAPRE */ + timer_a.tcspr = value; + break; + case 0x0056: /* TA0IC */ + timer_a.ic = value; + break; +#endif - case 0x3aa: /* uart1tx */ + case 0x2ea: /* m32c uart1tx */ + case 0x3aa: /* m16c uart1tx */ { static int pending_exit = 0; if (value == 0) { if (pending_exit) { - step_result = M32C_MAKE_EXITED(value); + step_result = M32C_MAKE_EXITED (value); return; } pending_exit = 1; } else - putchar(value); + { + write (m32c_console_ofd, &value, 1); + } } break; @@ -301,24 +373,94 @@ mem_get_pc () return *m; } +static int console_raw = 0; +static struct termios attr, oattr; + +static int +stdin_ready () +{ + fd_set ifd; + int n; + struct timeval t; + + t.tv_sec = 0; + t.tv_usec = 0; + FD_ZERO (&ifd); + FD_SET (m32c_console_ifd, &ifd); + n = select (1, &ifd, 0, 0, &t); + return n > 0; +} + +void +m32c_sim_restore_console () +{ + tcsetattr (m32c_console_ifd, TCSANOW, &oattr); + console_raw = 0; +} + static unsigned char mem_get_byte (int address) { unsigned char *m; address &= membus_mask; - S ("=>"); m = mem_ptr (address); switch (address) { - case 0x3ad: /* uart1c1 */ - E(); - return 2; /* transmitter empty */ - break; - default: - if (trace) - printf (" %02x", *m); - break; + case 0x2ed: /* m32c uart1c1 */ + case 0x3ad: /* m16c uart1c1 */ + +#if 0 + if (!console_raw) + { + tcgetattr (m32c_console_ifd, &attr); + tcgetattr (m32c_console_ifd, &oattr); + /* We want each key to be sent as the user presses them. */ + attr.c_lflag &= ~(ICANON | ECHO | ECHOE); + tcsetattr (m32c_console_ifd, TCSANOW, &attr); + console_raw = 1; + atexit (m32c_sim_restore_console); + } +#endif + + if (stdin_ready ()) + return 0x02; /* tx empty and rx full */ + else + return 0x0a; /* transmitter empty */ + + case 0x2ee: /* m32c uart1 rx */ + { + char c; + read (m32c_console_ifd, &c, 1); + if (m32c_console_ifd == 0 && c == 3) /* Ctrl-C */ + { + printf ("Ctrl-C!\n"); + exit (0); + } + + if (m32c_console_ifd != 1) + { + if (isgraph (c)) + printf ("\033[31m%c\033[0m", c); + else + printf ("\033[31m%02x\033[0m", c); + } + return c; + } + +#ifdef TIMER_A + case 0x346: /* TA0low */ + return timer_a.count & 0xff; + case 0x347: /* TA0high */ + return (timer_a.count >> 8) & 0xff; + case 0x104: /* TRA */ + return timer_a.count; +#endif + } + + S ("=>"); + if (trace) + printf (" %02x", *m); E (); return *m; } @@ -395,3 +537,61 @@ sign_ext (int v, int bits) } return v; } + +#if TIMER_A +void +update_timer_a () +{ + if (timer_a.bsr & 1) + { + timer_a.prescale--; + if (timer_a.prescale < 0) + { + if (A24) + { + switch (timer_a.mode & 0xc0) + { + case 0x00: + timer_a.prescale = 0; + break; + case 0x40: + timer_a.prescale = 8; + break; + case 0x80: + timer_a.prescale = timer_a.tcspr & 0x0f; + break; + case 0xc0: + timer_a.prescale = 32; + break; + } + } + else + { + timer_a.prescale = timer_a.tcspr; + } + timer_a.count--; + if (timer_a.count < 0) + { + timer_a.count = timer_a.reload; + if (timer_a.ic & 7) + { + if (A24) + mem_put_qi (0x6c, timer_a.ic | 0x08); + else + mem_put_qi (0x56, timer_a.ic | 0x08); + } + } + } + } + + if (regs.r_flags & FLAGBIT_I /* interrupts enabled */ + && timer_a.ic & 0x08 /* timer A interrupt triggered */ + && (timer_a.ic & 0x07) > ((regs.r_flags >> 12) & 0x07)) + { + if (A24) + trigger_peripheral_interrupt (12, 0x06c); + else + trigger_peripheral_interrupt (22, 0x056); + } +} +#endif diff --git a/sim/m32c/opc2c.c b/sim/m32c/opc2c.c index b1d1369..e7bfa91 100644 --- a/sim/m32c/opc2c.c +++ b/sim/m32c/opc2c.c @@ -472,8 +472,6 @@ log_indirect (Indirect * ind, int byte) for (i = 0; i < 256; i++) { - if (ind[i].type == T_unused) - continue; for (j = 0; j < byte; j++) fprintf (sim_log, "%s ", prmb (255, cur_bits[j])); @@ -490,7 +488,7 @@ log_indirect (Indirect * ind, int byte) last_c = ind[i].u.op->comment; break; case T_unused: - fprintf (sim_log, "-\n"); + fprintf (sim_log, "unused\n"); break; case T_indirect: fprintf (sim_log, "indirect\n"); diff --git a/sim/m32c/r8c.opc b/sim/m32c/r8c.opc index bc7f107..abfc7b9 100644 --- a/sim/m32c/r8c.opc +++ b/sim/m32c/r8c.opc @@ -1249,9 +1249,9 @@ decode_r8c() a = get_reg (sp); v = (mem_get_hi (a) - + 65536 * (mem_get_qi (a+3) & 0x0f)); + + 4096 * (mem_get_qi (a+3) & 0xf0)); b = (mem_get_qi (a+2) - + 16 * (mem_get_qi (a+3) & 0xf0)); + + 256 * (mem_get_qi (a+3) & 0xff)); put_reg (pc, v); put_reg (flags, b); put_reg (sp, get_reg (sp) + 4); @@ -1401,7 +1401,7 @@ decode_r8c() int count = get_reg (r3); int s1 = get_reg (a1); - v = get_reg (w ? r0 : r0h); + v = get_reg (w ? r0 : r0l); while (count) { diff --git a/sim/m32c/reg.c b/sim/m32c/reg.c index 912c32e..f553161 100644 --- a/sim/m32c/reg.c +++ b/sim/m32c/reg.c @@ -28,6 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ int verbose = 0; int trace = 0; int enable_counting = 0; +int in_gdb = 1; regs_type regs; int addr_mask = 0xffff; @@ -75,6 +76,8 @@ int b2minsigned[] = { 0, -128, -32768, -8388608, -2147483647 - 1 }; static regs_type oldregs; +int m32c_opcode_pc; + void init_regs (void) { @@ -581,6 +584,17 @@ put_reg_ll (reg_id id, DI v) } } +static void +print_flags (int f) +{ + int i; + static char fn[] = "CDZSBOIU"; + printf ("%d.", (f >> 12) & 7); + for (i = 7; i >= 0; i--) + if (f & (1 << i)) + putchar (fn[i]); +} + #define TRC(f,n, id) \ if (oldregs.f != regs.f) \ { \ @@ -617,6 +631,49 @@ trace_register_changes () TRC (r_usp, "usp", usp); TRC (r_isp, "isp", isp); TRC (r_pc, "pc", pc); - TRC (r_flags, "flags", flags); + if (oldregs.r_flags != regs.r_flags) + { + printf (" flags "); + print_flags (oldregs.r_flags); + printf (":"); + print_flags (regs.r_flags); + } + printf ("\033[0m\n"); +} + +#define DRC(f, n, id) \ + printf(" %-3s %0*x", n, \ + reg_bytes[id]*2, (unsigned int)regs.f); \ + +void +m32c_dump_all_registers () +{ + printf ("\033[36mREGS:"); + DRC (r[0].r_r0, "r0", r0); + DRC (r[0].r_r1, "r1", r1); + DRC (r[0].r_r2, "r2", r2); + DRC (r[0].r_r3, "r3", r3); + DRC (r[0].r_a0, "a0", a0); + DRC (r[0].r_a1, "a1", a1); + DRC (r[0].r_sb, "sb", sb); + DRC (r[0].r_fb, "fb", fb); + printf ("\n "); + DRC (r[1].r_r0, "r0'", r0); + DRC (r[1].r_r1, "r1'", r1); + DRC (r[1].r_r2, "r2'", r2); + DRC (r[1].r_r3, "r3'", r3); + DRC (r[1].r_a0, "a0'", a0); + DRC (r[1].r_a1, "a1'", a1); + DRC (r[1].r_sb, "sb'", sb); + DRC (r[1].r_fb, "fb'", fb); + printf (" \n"); + DRC (r_intbh, "intbh", intbh); + DRC (r_intbl, "intbl", intbl); + DRC (r_usp, "usp", usp); + DRC (r_isp, "isp", isp); + DRC (r_pc, "pc", pc); + printf (" flags "); + print_flags (regs.r_flags); printf ("\033[0m\n"); + /*sim_disasm_one (); */ } diff --git a/sim/m32c/safe-fgets.c b/sim/m32c/safe-fgets.c index ebe3285..cf748a2 100644 --- a/sim/m32c/safe-fgets.c +++ b/sim/m32c/safe-fgets.c @@ -30,7 +30,7 @@ static int line_buf_size = 0; #define LBUFINCR 100 char * -safe_fgets (FILE *f) +safe_fgets (FILE * f) { char *line_ptr; diff --git a/sim/m32c/safe-fgets.h b/sim/m32c/safe-fgets.h index b69c986..562f487 100644 --- a/sim/m32c/safe-fgets.h +++ b/sim/m32c/safe-fgets.h @@ -22,6 +22,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef _safe_gets_h_ #define _safe_gets_h_ -char *safe_fgets (FILE *f); +char *safe_fgets (FILE * f); #endif diff --git a/sim/m32c/timer_a.h b/sim/m32c/timer_a.h new file mode 100644 index 0000000..e1e7f21 --- /dev/null +++ b/sim/m32c/timer_a.h @@ -0,0 +1,12 @@ +typedef struct +{ + int count; + int reload; + int prescale; + int tcspr; + unsigned char bsr; + unsigned char mode; + unsigned char ic; +} Timer_A; + +extern Timer_A timer_a; diff --git a/sim/m32c/trace.c b/sim/m32c/trace.c index ec9ac39..14eb3bc 100644 --- a/sim/m32c/trace.c +++ b/sim/m32c/trace.c @@ -101,7 +101,7 @@ op_printf (char *buf, char *fmt, ...) static bfd *current_bfd; void -sim_disasm_init (bfd *prog) +sim_disasm_init (bfd * prog) { current_bfd = prog; } @@ -253,7 +253,7 @@ sim_disasm_one () slash++; printf ("========================================" - "=====================================\n"); + "=====================================\n"); printf ("\033[37;41m %s:%d: \033[33;40m %s\033[K\033[0m\n", slash, lineno, the_line); } @@ -271,7 +271,7 @@ sim_disasm_one () sym = (min + max) / 2; sa = bfd_asymbol_value (symtab[sym]); /*printf("checking %4d %08x %s\n", - sym, sa, bfd_asymbol_name (symtab[sym])); */ + sym, sa, bfd_asymbol_name (symtab[sym])); */ if (sa > mypc) max = sym; else if (sa < mypc) diff --git a/sim/m32c/trace.h b/sim/m32c/trace.h index 393a71d..aacc6ba 100644 --- a/sim/m32c/trace.h +++ b/sim/m32c/trace.h @@ -19,5 +19,5 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -void sim_disasm_init (bfd *prog); +void sim_disasm_init (bfd * prog); extern void sim_disasm_one (void); |