X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fm32c%2Fmem.c;h=d7e26828ebb5c287a805f9d51242104366b9ac48;hb=5fd104addfddb68844fb8df67be832ee98ad9888;hp=6b6cbdcc646552cd31affc3be07adb01f92c1cfb;hpb=6aba47ca06d9150c6196a374b745c2711b46e045;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/m32c/mem.c b/sim/m32c/mem.c index 6b6cbdcc64..d7e26828eb 100644 --- a/sim/m32c/mem.c +++ b/sim/m32c/mem.c @@ -1,34 +1,47 @@ /* mem.c --- memory for M32C simulator. -Copyright (C) 2005, 2007 Free Software Foundation, Inc. +Copyright (C) 2005-2020 Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of the GNU simulators. -The GNU simulators are free software; you can redistribute them and/or -modify them under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. -The GNU simulators are distributed in the hope that they will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with the GNU simulators; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA */ +along with this program. If not, see . */ +#include "config.h" #include #include #include +#include +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_TERMIOS_H +#include +#endif #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) @@ -40,8 +53,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA static unsigned char **pt[L1_LEN]; +#ifdef HAVE_TERMIOS_H +int m32c_console_ifd = 0; +#endif +int m32c_console_ofd = 1; +#ifdef HAVE_TERMIOS_H +int m32c_use_raw_console = 0; +#endif + +#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,16 +89,25 @@ init_mem (void) } static unsigned char * -mem_ptr (address) +mem_ptr (int 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) @@ -105,7 +139,7 @@ mcs (int isput, int bytes) } void -mem_usage_stats () +mem_usage_stats (void) { int i, j; int rstart = 0; @@ -140,7 +174,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), @@ -158,7 +192,7 @@ s (int address, char *dir) #define S(d) if (trace) s(address, d) static void -e () +e (void) { if (!trace) return; @@ -169,7 +203,9 @@ e () #define E() if (trace) e() -void +extern int m32c_disassemble; + +static void mem_put_byte (int address, unsigned char value) { unsigned char *m; @@ -201,21 +237,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; @@ -285,42 +365,119 @@ mem_put_si (int address, unsigned long value) } void -mem_put_blk (int address, void *bufptr, int nbytes) +mem_put_blk (int address, const void *bufptr, int nbytes) { S ("<="); if (enable_counting) mem_counters[1][1] += nbytes; while (nbytes--) - mem_put_byte (address++, *(unsigned char *) bufptr++); + mem_put_byte (address++, *(const unsigned char *) bufptr++); E (); } unsigned char -mem_get_pc () +mem_get_pc (void) { unsigned char *m = mem_ptr (regs.r_pc & membus_mask); COUNT (0, 0); return *m; } +#ifdef HAVE_TERMIOS_H +static int console_raw = 0; +static struct termios oattr; + +static int +stdin_ready (void) +{ + 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 (void) +{ + if (console_raw) + tcsetattr (m32c_console_ifd, TCSANOW, &oattr); + console_raw = 0; +} +#endif + 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; +#ifdef HAVE_TERMIOS_H + case 0x2ed: /* m32c uart1c1 */ + case 0x3ad: /* m16c uart1c1 */ + + if (!console_raw && m32c_use_raw_console) + { + struct termios attr; + 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); + } + + 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; + } +#endif + +#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 + + default: + /* In case both cases above are not included. */ + ; } + + S ("=>"); + if (trace) + printf (" %02x", *m); E (); return *m; } @@ -397,3 +554,61 @@ sign_ext (int v, int bits) } return v; } + +#if TIMER_A +void +update_timer_a (void) +{ + 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