X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=sim%2Fmcore%2Finterp.c;h=60931cd8801b90f69a34c7ee2cec52dbe1876c1a;hb=7b6bb8daaceb9ecf3f42dea57ae82733d6a3b2f6;hp=a5d188b255b11ccf061076188d2065b5a8af1d37;hpb=b83266a0e1813b7f4891d5d6b0ed6b7302a3fe98;p=thirdparty%2Fbinutils-gdb.git diff --git a/sim/mcore/interp.c b/sim/mcore/interp.c index a5d188b255b..60931cd8801 100644 --- a/sim/mcore/interp.c +++ b/sim/mcore/interp.c @@ -1,22 +1,22 @@ -/* Simulator for Motorolla's MCore processor - Copyright (C) 1999 Free Software Foundation, Inc. +/* Simulator for Motorola's MCore processor + Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010, 2011 + 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 modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +the Free Software Foundation; either version 3 of the License, 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 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 this program; if not, write to the Free Software Foundation, Inc., -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +You should have received a copy of the GNU General Public License +along with this program. If not, see . */ #include #include "sysdep.h" @@ -24,9 +24,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include /* for byte ordering macros */ #include "bfd.h" -#include "callback.h" +#include "gdb/callback.h" #include "libiberty.h" -#include "remote-sim.h" +#include "gdb/remote-sim.h" #ifndef NUM_ELEM #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0]) @@ -36,12 +36,11 @@ with this program; if not, write to the Free Software Foundation, Inc., typedef long int word; typedef unsigned long int uword; +static int target_big_endian = 0; static unsigned long heap_ptr = 0; host_callback * callback; -#define TARGET_BYTE_ORDER BIG_ENDIAN /* XXX */ - unsigned long mcore_extract_unsigned_integer (addr, len) unsigned char * addr; @@ -59,8 +58,17 @@ mcore_extract_unsigned_integer (addr, len) /* Start at the most significant end of the integer, and work towards the least significant. */ retval = 0; - for (p = startaddr; p < endaddr; ++p) - retval = (retval << 8) | * p; + + 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; } @@ -74,28 +82,33 @@ mcore_store_unsigned_integer (addr, len, val) unsigned char * p; unsigned char * startaddr = (unsigned char *)addr; unsigned char * endaddr = startaddr + len; - - /* Start at the least significant end of the integer, and work towards - the most significant. */ - for (p = endaddr - 1; p >= startaddr; --p) + + if (! target_big_endian) { - * p = val & 0xff; - val >>= 8; + 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 (for MCore this - is big-endian). Since we know that the MCore is always big-endian, - we cheat a bit and use the ntohl() and htonl() macros to - achieve this end. - + 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. */ + important. */ /* The ordering of the mcore_regset structure is matched in the gdb/config/mcore/tm-mcore.h file in the REGISTER_NAMES macro. */ @@ -121,8 +134,8 @@ union word asints [1]; /* but accessed larger... */ } cpu; -#define LAST_VALID_CREG 12 /* only 0..12 implemented */ -#define NUM_MCORE_REGS (16 + 16 + LAST_VALID_CREG) +#define LAST_VALID_CREG 32 /* only 0..12 implemented */ +#define NUM_MCORE_REGS (16 + 16 + LAST_VALID_CREG + 1) int memcycles = 1; @@ -149,12 +162,12 @@ static int issue_messages = 0; #define mem asregs.memory /* maniuplate the carry bit */ -#define C_ON() (cpu.sr & 1) +#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 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) @@ -219,6 +232,14 @@ wlat (x, v) 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; @@ -246,10 +267,17 @@ what (x, v) if ((x & 1) != 0) { if (issue_messages) - fprintf (stderr, "short write to unaligned memory address: 0x%x\n", x); + 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; @@ -259,7 +287,7 @@ what (x, v) } } -/* Read functions */ +/* Read functions. */ static int INLINE rbat (x) word x; @@ -301,6 +329,11 @@ rlat (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; @@ -331,6 +364,11 @@ rhat (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; @@ -351,7 +389,7 @@ IOMEM (addr, write, value) { } -/* default to a 8 Mbyte (== 2^23) memory space */ +/* Default to a 8 Mbyte (== 2^23) memory space. */ static int sim_memory_size = 23; #define MEM_SIZE_FLOOR 64 @@ -365,9 +403,9 @@ sim_size (power) 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 */ + /* 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); @@ -376,7 +414,8 @@ sim_size (power) { if (issue_messages) fprintf (stderr, - "Not enough VM for simulation of %d bytes of RAM\n", cpu.asregs.msize); + "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); @@ -481,7 +520,7 @@ handle_trap1 () { unsigned long a[3]; - switch ((unsigned long) (cpu.gr[TRAPCODE])) + switch ((unsigned long) (cpu.gr [TRAPCODE])) { case 3: a[0] = (unsigned long) (cpu.gr[PARM1]); @@ -506,7 +545,7 @@ handle_trap1 () break; case 6: - a[0] = (unsigned long) (cpu.gr[4]); + a[0] = (unsigned long) (cpu.gr[PARM1]); /* Watch out for debugger's files. */ if (is_opened (a[0])) { @@ -587,7 +626,8 @@ handle_trap1 () default: if (issue_messages) - fprintf (stderr, "WARNING: sys call %d unimplemented\n", cpu.gr[TRAPCODE]); + fprintf (stderr, "WARNING: sys call %d unimplemented\n", + cpu.gr[TRAPCODE]); break; } } @@ -600,6 +640,7 @@ process_stub (what) switch (what) { case 3: /* _read */ + case 4: /* _write */ case 5: /* _open */ case 6: /* _close */ case 10: /* _unlink */ @@ -660,7 +701,7 @@ util (what) break; case 0xFF: - process_stub (what); + process_stub (cpu.gr[1]); break; default: @@ -733,7 +774,7 @@ sim_resume (sd, step, siggnal) cpu.asregs.exception = step ? SIGTRAP: 0; pc = cpu.asregs.pc; - /* fetch the initial instructions that we'll decode */ + /* Fetch the initial instructions that we'll decode. */ ibuf = rlat (pc & 0xFFFFFFFC); needfetch = 0; @@ -755,16 +796,24 @@ sim_resume (sd, step, siggnal) do { + word oldpc; + insts ++; if (pc & 02) { - inst = ibuf & 0xFFFF; + if (! target_big_endian) + inst = ibuf >> 16; + else + inst = ibuf & 0xFFFF; needfetch = 1; } else { - inst = ibuf >> 16; + if (! target_big_endian) + inst = ibuf & 0xFFFF; + else + inst = ibuf >> 16; } #ifdef WATCHFUNCTIONS @@ -798,7 +847,7 @@ sim_resume (sd, step, siggnal) WLendpc = 0; } - /* optimize with a hash to speed loop */ + /* Optimize with a hash to speed loop. */ if (WLincyc == 0) { if ((WLhash == 0) || ((WLhash & pc) != 0)) @@ -822,7 +871,9 @@ sim_resume (sd, step, siggnal) if (tracing) fprintf (stderr, "%.4x: inst = %.4x ", pc, inst); - + + oldpc = pc; + pc += 2; switch (inst >> 8) @@ -835,6 +886,7 @@ sim_resume (sd, step, siggnal) { case 0x0: /* bkpt */ cpu.asregs.exception = SIGTRAP; + pc -= 2; break; case 0x1: /* sync */ @@ -845,7 +897,7 @@ sim_resume (sd, step, siggnal) cpu.sr = cpu.esr; needfetch = 1; - if (SR_AF()) + if (SR_AF ()) cpu.asregs.active_gregs = & cpu.asregs.alt_gregs[0]; else cpu.asregs.active_gregs = & cpu.asregs.gregs[0]; @@ -874,7 +926,7 @@ sim_resume (sd, step, siggnal) case 0x6: /* doze */ if (issue_messages) - fprintf (stderr, "WARNING: oze unimplemented\n"); + fprintf (stderr, "WARNING: doze unimplemented\n"); break; case 0x7: @@ -996,6 +1048,9 @@ sim_resume (sd, step, siggnal) break; case 0xC: /* jmp */ pc = cpu.gr[RD]; + if (tracing && RD == 15) + fprintf (stderr, "Func return, r2 = %x, r3 = %x\n", + cpu.gr[2], cpu.gr[3]); bonus_cycles++; needfetch = 1; break; @@ -1121,6 +1176,9 @@ sim_resume (sd, step, siggnal) bonus_cycles += ticks; } bonus_cycles += 2; /* min. is 3, so add 2, plus ticks above */ + if (tracing) + fprintf (stderr, " mult %x by %x to give %x", + cpu.gr[RD], cpu.gr[RS], cpu.gr[RD] * cpu.gr[RS]); cpu.gr[RD] = cpu.gr[RD] * cpu.gr[RS]; break; case 0x04: /* loopt */ @@ -1169,7 +1227,9 @@ sim_resume (sd, step, siggnal) unsigned long dst, src; dst = cpu.gr[RD]; src = cpu.gr[RS]; - dst = dst >> src; + /* We must not rely solely upon the native shift operations, since they + may not match the M*Core's behaviour on boundary conditions. */ + dst = src > 31 ? 0 : dst >> src; cpu.gr[RD] = dst; } break; @@ -1199,6 +1259,8 @@ sim_resume (sd, step, siggnal) case 0x12: /* mov */ cpu.gr[RD] = cpu.gr[RS]; + if (tracing) + fprintf (stderr, "MOV %x into reg %d", cpu.gr[RD], RD); break; case 0x13: /* bgenr */ @@ -1242,11 +1304,18 @@ sim_resume (sd, step, siggnal) break; case 0x1A: /* asr */ - cpu.gr[RD] = (long)cpu.gr[RD] >> cpu.gr[RS]; + /* We must not rely solely upon the native shift operations, since they + may not match the M*Core's behaviour on boundary conditions. */ + if (cpu.gr[RS] > 30) + cpu.gr[RD] = ((long) cpu.gr[RD]) < 0 ? -1 : 0; + else + cpu.gr[RD] = (long) cpu.gr[RD] >> cpu.gr[RS]; break; case 0x1B: /* lsl */ - cpu.gr[RD] = cpu.gr[RD] << cpu.gr[RS]; + /* We must not rely solely upon the native shift operations, since they + may not match the M*Core's behaviour on boundary conditions. */ + cpu.gr[RD] = cpu.gr[RS] > 31 ? 0 : cpu.gr[RD] << cpu.gr[RS]; break; case 0x1C: /* addu */ @@ -1507,6 +1576,9 @@ sim_resume (sd, step, siggnal) break; case 0x7F: /* jsri */ cpu.gr[15] = pc; + if (tracing) + fprintf (stderr, "func call: r2 = %x r3 = %x r4 = %x r5 = %x r6 = %x r7 = %x\n", + cpu.gr[2], cpu.gr[3], cpu.gr[4], cpu.gr[5], cpu.gr[6], cpu.gr[7]); case 0x70: /* jmpi */ pc = rlat ((pc + ((inst & 0xFF) << 2)) & 0xFFFFFFFC); memops++; @@ -1611,14 +1683,14 @@ sim_resume (sd, step, siggnal) if (tracing) fprintf (stderr, "\n"); - + if (needfetch) { /* Do not let him fetch from a bad address! */ if (((uword)pc) >= cpu.asregs.msize) { if (issue_messages) - fprintf (stderr, "PC outside of available memory! (%x)\n", pc); + fprintf (stderr, "PC loaded at 0x%x is outside of available memory! (0x%x)\n", oldpc, pc); cpu.asregs.exception = SIGSEGV; } @@ -1646,7 +1718,7 @@ int sim_write (sd, addr, buffer, size) SIM_DESC sd; SIM_ADDR addr; - unsigned char * buffer; + const unsigned char * buffer; int size; { int i; @@ -1686,11 +1758,10 @@ sim_store_register (sd, rn, memory, length) { if (length == 4) { - /* ival is in 'target' order, which we know to be big-endian. - Let's convert it to natural order. */ long ival; - - ival = mcore_extract_unsigned_integer (memory, 4);/* misalignment safe */ + + /* misalignment safe */ + ival = mcore_extract_unsigned_integer (memory, 4); cpu.asints[rn] = ival; } @@ -1713,11 +1784,10 @@ sim_fetch_register (sd, rn, memory, length) { if (length == 4) { - /* caller expects 'target order', which is big-endian. Convert - * the native order we used [to speed up simulation] to the - * byte order expected by the caller. */ long ival = cpu.asints[rn]; - mcore_store_unsigned_integer (memory, 4, ival);/* misalignment-safe */ + + /* misalignment-safe */ + mcore_store_unsigned_integer (memory, 4, ival); } return 4; @@ -1778,27 +1848,36 @@ sim_info (sd, verbose) #endif double virttime = cpu.asregs.cycles / 36.0e6; - callback->printf_filtered (callback, "\n\n# instructions executed %10d\n", cpu.asregs.insts); - callback->printf_filtered (callback, "# cycles %10d\n", cpu.asregs.cycles); - callback->printf_filtered (callback, "# pipeline stalls %10d\n", cpu.asregs.stalls); - callback->printf_filtered (callback, "# virtual time taken %10.4f\n", virttime); + callback->printf_filtered (callback, "\n\n# instructions executed %10d\n", + cpu.asregs.insts); + callback->printf_filtered (callback, "# cycles %10d\n", + cpu.asregs.cycles); + callback->printf_filtered (callback, "# pipeline stalls %10d\n", + cpu.asregs.stalls); + callback->printf_filtered (callback, "# virtual time taken %10.4f\n", + virttime); #ifdef WATCHFUNCTIONS - callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",ENDWL); + callback->printf_filtered (callback, "\nNumber of watched functions: %d\n", + ENDWL); wcyc = 0; for (w = 1; w <= ENDWL; w++) { callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]); - callback->printf_filtered (callback, " calls = %d, cycles = %d\n", WLcnts[w],WLcyc[w]); + callback->printf_filtered (callback, " calls = %d, cycles = %d\n", + WLcnts[w],WLcyc[w]); if (WLcnts[w] != 0) - callback->printf_filtered (callback, " maxcpc = %d, mincpc = %d, avecpc = %d\n",WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]); + callback->printf_filtered (callback, + " maxcpc = %d, mincpc = %d, avecpc = %d\n", + WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]); wcyc += WLcyc[w]; } - callback->printf_filtered (callback, "Total cycles for watched functions: %d\n",wcyc); + callback->printf_filtered (callback, + "Total cycles for watched functions: %d\n",wcyc); #endif } @@ -1822,7 +1901,7 @@ SIM_DESC sim_open (kind, cb, abfd, argv) SIM_OPEN_KIND kind; host_callback * cb; - struct _bfd * abfd; + struct bfd * abfd; char ** argv; { int osize = sim_memory_size; @@ -1886,7 +1965,7 @@ sim_load (sd, prog, abfd, from_tty) printf ("``%s'' is not appropriate object file.\n", prog); return SIM_RC_FAIL; } - + /* Look for that bss section. */ s_bss = bfd_get_section_by_name (handle, ".bss"); @@ -1902,9 +1981,11 @@ sim_load (sd, prog, abfd, from_tty) /* figure the end of the bss section */ #if 0 printf ("bss section at 0x%08x for 0x%08x bytes\n", - (unsigned long) s_bss->vma , (unsigned long) s_bss->_cooked_size); + (unsigned long) bfd_get_section_vma (handle, s_bss), + (unsigned long) bfd_section_size (handle, s_bss)); #endif - heap_ptr = (unsigned long) s_bss->vma + (unsigned long) s_bss->_cooked_size; + heap_ptr = ((unsigned long) bfd_get_section_vma (handle, s_bss) + + (unsigned long) bfd_section_size (handle, s_bss)); /* Clean up after ourselves. */ bfd_close (handle); @@ -1919,6 +2000,8 @@ sim_load (sd, prog, abfd, from_tty) if (prog_bfd == NULL) return SIM_RC_FAIL; + target_big_endian = bfd_big_endian (prog_bfd); + if (abfd == NULL) bfd_close (prog_bfd); @@ -1928,7 +2011,7 @@ sim_load (sd, prog, abfd, from_tty) SIM_RC sim_create_inferior (sd, prog_bfd, argv, env) SIM_DESC sd; - struct _bfd * prog_bfd; + struct bfd * prog_bfd; char ** argv; char ** env; {