mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-26 12:25:31 +00:00
* 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.
This commit is contained in:
parent
ebfe2e3fb6
commit
3877a1459b
@ -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
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
## COMMON_PRE_CONFIG_FRAG
|
||||
|
||||
SIM_EXTRA_CFLAGS = -Wall
|
||||
SIM_EXTRA_CFLAGS = -Wall -DTIMER_A
|
||||
|
||||
SIM_RUN_OBJS = \
|
||||
main.o \
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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", orig_pc);
|
||||
tprintf("trace: decode pc = %06x\n", m32c_opcode_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 --;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
while ((o = getopt (argc, argv, "tvdm:")) != -1)
|
||||
setbuf (stdout, 0);
|
||||
|
||||
in_gdb = 0;
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
232
sim/m32c/mem.c
232
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;
|
||||
|
||||
case 0x3aa: /* uart1tx */
|
||||
/* 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 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
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 (); */
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
12
sim/m32c/timer_a.h
Normal file
12
sim/m32c/timer_a.h
Normal file
@ -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;
|
@ -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)
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user