aboutsummaryrefslogtreecommitdiff
path: root/sim/m32c/mem.c
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2008-06-06 19:18:15 +0000
committerDJ Delorie <dj@redhat.com>2008-06-06 19:18:15 +0000
commit3877a1459be9bdeb20ae891b3f68220b837a81cb (patch)
tree02fc0eea00e77cc6ff7e691bafebe6cd2e09d77f /sim/m32c/mem.c
parentebfe2e3fb6a1078dcbbc4231ddd7ddec365bfe09 (diff)
downloadgdb-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/mem.c')
-rw-r--r--sim/m32c/mem.c232
1 files changed, 216 insertions, 16 deletions
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