summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDJ Delorie <dj@delorie.com>2008-06-06 19:18:15 +0000
committerDJ Delorie <dj@delorie.com>2008-06-06 19:18:15 +0000
commit39fdefc740531885a90c7db8b36c2942da0064d0 (patch)
treecfc55429ea3352fa974d2ae6004d05febeffe34c
parentdf876cf4bd4a2e9d24430b6609091a8bd05ebb90 (diff)
downloadgdb-39fdefc740531885a90c7db8b36c2942da0064d0.tar.gz
* 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.
-rw-r--r--sim/m32c/ChangeLog39
-rw-r--r--sim/m32c/Makefile.in2
-rw-r--r--sim/m32c/cpu.h6
-rw-r--r--sim/m32c/gdb-if.c16
-rw-r--r--sim/m32c/int.c28
-rw-r--r--sim/m32c/int.h1
-rw-r--r--sim/m32c/load.c2
-rw-r--r--sim/m32c/m32c.opc77
-rw-r--r--sim/m32c/main.c90
-rw-r--r--sim/m32c/mem.c232
-rw-r--r--sim/m32c/opc2c.c4
-rw-r--r--sim/m32c/r8c.opc6
-rw-r--r--sim/m32c/reg.c59
-rw-r--r--sim/m32c/safe-fgets.c2
-rw-r--r--sim/m32c/safe-fgets.h2
-rw-r--r--sim/m32c/timer_a.h12
-rw-r--r--sim/m32c/trace.c6
-rw-r--r--sim/m32c/trace.h2
18 files changed, 519 insertions, 67 deletions
diff --git a/sim/m32c/ChangeLog b/sim/m32c/ChangeLog
index a3afdf00c74..121670d12e9 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 f58de57e71c..ab3781cace2 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 eae4cd54b29..e11d5ef6940 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 3ed3221f27d..a8ba3920cd4 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 1959c77f374..5556a120dc8 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 3d36500f8d2..ef4bc274290 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 229bc0da9b9..755c89af0d5 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 da77f950a2e..9f5bd4ab4e7 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 7b54f4beb91..7187210ce5f 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 432162916bb..a277787e3c6 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 b1d13690e84..e7bfa918c81 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 bc7f1073fe5..abfc7b9a26d 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 912c32e2e6b..f55316116f4 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 ebe32856e68..cf748a246ba 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 b69c986853f..562f4878ad1 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 00000000000..e1e7f216bf2
--- /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 ec9ac391711..14eb3bc20e6 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 393a71dd86f..aacc6badbd4 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);