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/mem.c | |
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/mem.c')
-rw-r--r-- | sim/m32c/mem.c | 232 |
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 |