📄 interp.c
字号:
/* Simulator for Motorola's MCore processor Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc. Contributed by Cygnus Solutions.This file is part of GDB, the GNU debugger.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <signal.h>#include "sysdep.h"#include <sys/times.h>#include <sys/param.h>#include <netinet/in.h> /* for byte ordering macros */#include "bfd.h"#include "gdb/callback.h"#include "libiberty.h"#include "gdb/remote-sim.h"#ifndef NUM_ELEM#define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])#endiftypedef long int word;typedef unsigned long int uword;static int target_big_endian = 0;static unsigned long heap_ptr = 0;host_callback * callback;unsigned longmcore_extract_unsigned_integer (addr, len) unsigned char * addr; int len;{ unsigned long retval; unsigned char * p; unsigned char * startaddr = (unsigned char *)addr; unsigned char * endaddr = startaddr + len; if (len > (int) sizeof (unsigned long)) printf ("That operation is not available on integers of more than %d bytes.", sizeof (unsigned long)); /* Start at the most significant end of the integer, and work towards the least significant. */ retval = 0; if (! target_big_endian) { for (p = endaddr; p > startaddr;) retval = (retval << 8) | * -- p; } else { for (p = startaddr; p < endaddr;) retval = (retval << 8) | * p ++; } return retval;}voidmcore_store_unsigned_integer (addr, len, val) unsigned char * addr; int len; unsigned long val;{ unsigned char * p; unsigned char * startaddr = (unsigned char *)addr; unsigned char * endaddr = startaddr + len; if (! target_big_endian) { for (p = startaddr; p < endaddr;) { * p ++ = val & 0xff; val >>= 8; } } else { for (p = endaddr; p > startaddr;) { * -- p = val & 0xff; val >>= 8; } }}/* The machine state. This state is maintained in host byte order. The fetch/store register functions must translate between host byte order and the target processor byte order. Keeping this data in target byte order simplifies the register read/write functions. Keeping this data in native order improves the performance of the simulator. Simulation speed is deemed more important. *//* The ordering of the mcore_regset structure is matched in the gdb/config/mcore/tm-mcore.h file in the REGISTER_NAMES macro. */struct mcore_regset{ word gregs [16]; /* primary registers */ word alt_gregs [16]; /* alt register file */ word cregs [32]; /* control registers */ word pc; /* the pc */ int ticks; int stalls; int cycles; int insts; int exception; unsigned long msize; unsigned char * memory; word * active_gregs;};union{ struct mcore_regset asregs; word asints [1]; /* but accessed larger... */} cpu;#define LAST_VALID_CREG 32 /* only 0..12 implemented */#define NUM_MCORE_REGS (16 + 16 + LAST_VALID_CREG + 1)int memcycles = 1;static SIM_OPEN_KIND sim_kind;static char * myname;static int issue_messages = 0;#define gr asregs.active_gregs#define cr asregs.cregs#define sr asregs.cregs[0]#define vbr asregs.cregs[1]#define esr asregs.cregs[2]#define fsr asregs.cregs[3]#define epc asregs.cregs[4]#define fpc asregs.cregs[5]#define ss0 asregs.cregs[6]#define ss1 asregs.cregs[7]#define ss2 asregs.cregs[8]#define ss3 asregs.cregs[9]#define ss4 asregs.cregs[10]#define gcr asregs.cregs[11]#define gsr asregs.cregs[12]#define mem asregs.memory/* maniuplate the carry bit */#define C_ON() (cpu.sr & 1)#define C_VALUE() (cpu.sr & 1)#define C_OFF() ((cpu.sr & 1) == 0)#define SET_C() {cpu.sr |= 1;}#define CLR_C() {cpu.sr &= 0xfffffffe;}#define NEW_C(v) {CLR_C(); cpu.sr |= ((v) & 1);}#define SR_AF() ((cpu.sr >> 1) & 1)#define TRAPCODE 1 /* r1 holds which function we want */#define PARM1 2 /* first parameter */#define PARM2 3#define PARM3 4#define PARM4 5#define RET1 2 /* register for return values. */longint_sbrk (inc_bytes) int inc_bytes;{ long addr; addr = heap_ptr; heap_ptr += inc_bytes; if (issue_messages && heap_ptr>cpu.gr[0]) fprintf (stderr, "Warning: heap_ptr overlaps stack!\n"); return addr;}static void INLINE wbat (x, v) word x, v;{ if (((uword)x) >= cpu.asregs.msize) { if (issue_messages) fprintf (stderr, "byte write to 0x%x outside memory range\n", x); cpu.asregs.exception = SIGSEGV; } else { unsigned char *p = cpu.mem + x; p[0] = v; }}static void INLINE wlat (x, v) word x, v;{ if (((uword)x) >= cpu.asregs.msize) { if (issue_messages) fprintf (stderr, "word write to 0x%x outside memory range\n", x); cpu.asregs.exception = SIGSEGV; } else { if ((x & 3) != 0) { if (issue_messages) fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x); cpu.asregs.exception = SIGBUS; } else if (! target_big_endian) { unsigned char * p = cpu.mem + x; p[3] = v >> 24; p[2] = v >> 16; p[1] = v >> 8; p[0] = v; } else { unsigned char * p = cpu.mem + x; p[0] = v >> 24; p[1] = v >> 16; p[2] = v >> 8; p[3] = v; } }}static void INLINE what (x, v) word x, v;{ if (((uword)x) >= cpu.asregs.msize) { if (issue_messages) fprintf (stderr, "short write to 0x%x outside memory range\n", x); cpu.asregs.exception = SIGSEGV; } else { if ((x & 1) != 0) { if (issue_messages) fprintf (stderr, "short write to unaligned memory address: 0x%x\n", x); cpu.asregs.exception = SIGBUS; } else if (! target_big_endian) { unsigned char * p = cpu.mem + x; p[1] = v >> 8; p[0] = v; } else { unsigned char * p = cpu.mem + x; p[0] = v >> 8; p[1] = v; } }}/* Read functions. */static int INLINE rbat (x) word x;{ if (((uword)x) >= cpu.asregs.msize) { if (issue_messages) fprintf (stderr, "byte read from 0x%x outside memory range\n", x); cpu.asregs.exception = SIGSEGV; return 0; } else { unsigned char * p = cpu.mem + x; return p[0]; }}static int INLINE rlat (x) word x;{ if (((uword) x) >= cpu.asregs.msize) { if (issue_messages) fprintf (stderr, "word read from 0x%x outside memory range\n", x); cpu.asregs.exception = SIGSEGV; return 0; } else { if ((x & 3) != 0) { if (issue_messages) fprintf (stderr, "word read from unaligned address: 0x%x\n", x); cpu.asregs.exception = SIGBUS; return 0; } else if (! target_big_endian) { unsigned char * p = cpu.mem + x; return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]; } else { unsigned char * p = cpu.mem + x; return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; } }}static int INLINE rhat (x) word x;{ if (((uword)x) >= cpu.asregs.msize) { if (issue_messages) fprintf (stderr, "short read from 0x%x outside memory range\n", x); cpu.asregs.exception = SIGSEGV; return 0; } else { if ((x & 1) != 0) { if (issue_messages) fprintf (stderr, "short read from unaligned address: 0x%x\n", x); cpu.asregs.exception = SIGBUS; return 0; } else if (! target_big_endian) { unsigned char * p = cpu.mem + x; return (p[1] << 8) | p[0]; } else { unsigned char * p = cpu.mem + x; return (p[0] << 8) | p[1]; } }}#define SEXTB(x) (((x & 0xff) ^ (~ 0x7f)) + 0x80)#define SEXTW(y) ((int)((short)y))static intIOMEM (addr, write, value) int addr; int write; int value;{}/* Default to a 8 Mbyte (== 2^23) memory space. */static int sim_memory_size = 23;#define MEM_SIZE_FLOOR 64voidsim_size (power) int power;{ sim_memory_size = power; cpu.asregs.msize = 1 << sim_memory_size; if (cpu.mem) free (cpu.mem); /* Watch out for the '0 count' problem. There's probably a better way.. e.g., why do we use 64 here? */ if (cpu.asregs.msize < 64) /* Ensure a boundary. */ cpu.mem = (unsigned char *) calloc (64, (64 + cpu.asregs.msize) / 64); else cpu.mem = (unsigned char *) calloc (64, cpu.asregs.msize / 64); if (!cpu.mem) { if (issue_messages) fprintf (stderr, "Not enough VM for simulation of %d bytes of RAM\n", cpu.asregs.msize); cpu.asregs.msize = 1; cpu.mem = (unsigned char *) calloc (1, 1); }}static voidinit_pointers (){ if (cpu.asregs.msize != (1 << sim_memory_size)) sim_size (sim_memory_size);}static voidset_initial_gprs (){ int i; long space; unsigned long memsize; init_pointers (); /* Set up machine just out of reset. */ cpu.asregs.pc = 0; cpu.sr = 0; memsize = cpu.asregs.msize / (1024 * 1024); if (issue_messages > 1) fprintf (stderr, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n", memsize, cpu.asregs.msize - 1); /* Clean out the GPRs and alternate GPRs. */ for (i = 0; i < 16; i++) { cpu.asregs.gregs[i] = 0; cpu.asregs.alt_gregs[i] = 0; } /* Make our register set point to the right place. */ if (SR_AF()) cpu.asregs.active_gregs = &cpu.asregs.alt_gregs[0]; else cpu.asregs.active_gregs = &cpu.asregs.gregs[0]; /* ABI specifies initial values for these registers. */ cpu.gr[0] = cpu.asregs.msize - 4; /* dac fix, the stack address must be 8-byte aligned! */ cpu.gr[0] = cpu.gr[0] - cpu.gr[0] % 8; cpu.gr[PARM1] = 0; cpu.gr[PARM2] = 0; cpu.gr[PARM3] = 0; cpu.gr[PARM4] = cpu.gr[0];}static voidinterrupt (){ cpu.asregs.exception = SIGINT;}/* Functions so that trapped open/close don't interfere with the parent's functions. We say that we can't close the descriptors that we didn't open. exit() and cleanup() get in trouble here, to some extent. That's the price of emulation. */unsigned char opened[100];static voidlog_open (fd) int fd;{ if (fd < 0 || fd > NUM_ELEM (opened)) return; opened[fd] = 1;}static voidlog_close (fd) int fd;{ if (fd < 0 || fd > NUM_ELEM (opened)) return; opened[fd] = 0;}static intis_opened (fd) int fd;{ if (fd < 0 || fd > NUM_ELEM (opened)) return 0; return opened[fd];}static voidhandle_trap1 (){ unsigned long a[3]; switch ((unsigned long) (cpu.gr [TRAPCODE])) { case 3: a[0] = (unsigned long) (cpu.gr[PARM1]); a[1] = (unsigned long) (cpu.mem + cpu.gr[PARM2]); a[2] = (unsigned long) (cpu.gr[PARM3]); cpu.gr[RET1] = callback->read (callback, a[0], (char *) a[1], a[2]); break; case 4: a[0] = (unsigned long) (cpu.gr[PARM1]); a[1] = (unsigned long) (cpu.mem + cpu.gr[PARM2]); a[2] = (unsigned long) (cpu.gr[PARM3]); cpu.gr[RET1] = (int)callback->write (callback, a[0], (char *) a[1], a[2]); break; case 5: a[0] = (unsigned long) (cpu.mem + cpu.gr[PARM1]); a[1] = (unsigned long) (cpu.gr[PARM2]); /* a[2] = (unsigned long) (cpu.gr[PARM3]); */ cpu.gr[RET1] = callback->open (callback, (char *) a[0], a[1]); log_open (cpu.gr[RET1]); break; case 6: a[0] = (unsigned long) (cpu.gr[PARM1]); /* Watch out for debugger's files. */ if (is_opened (a[0])) { log_close (a[0]); cpu.gr[RET1] = callback->close (callback, a[0]); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -