diff options
-rw-r--r-- | sim/erc32/ChangeLog | 22 | ||||
-rw-r--r-- | sim/erc32/erc32.c | 175 | ||||
-rw-r--r-- | sim/erc32/exec.c | 58 | ||||
-rw-r--r-- | sim/erc32/func.c | 69 | ||||
-rw-r--r-- | sim/erc32/interf.c | 39 | ||||
-rw-r--r-- | sim/erc32/sis.c | 4 | ||||
-rw-r--r-- | sim/erc32/sis.h | 2 |
7 files changed, 159 insertions, 210 deletions
diff --git a/sim/erc32/ChangeLog b/sim/erc32/ChangeLog index 57c1932..109a13b 100644 --- a/sim/erc32/ChangeLog +++ b/sim/erc32/ChangeLog @@ -1,3 +1,25 @@ +2015-04-19 Jiri Gaisler <jiri@gaisler.se> + + * erc32.c (current_target_byte_order): Delete. + (fetch_bytes): Remove. + (store_bytes): Remove byte twisting. + (memory_read, memory_write): Access memory directly. + (extract_short, extract_short_signed, extract_byte, + extract_byte_signed): New function for for sub-word LD instructions. + * exec.c (extract_short, extract_short_signed, extract_byte, + extract_byte_signed): New functions. + (dispatch_instruction): Update memory reads. + * func.c (current_target_byte_order): Delete. + (get_regi): Delete little endian handling. + (disp_ctrl, dis_mem): Adjust print-out to new data endian. + (bfd_load): Delete little endian handling. + * interf.c (current_target_byte_order): Delete. + (sim_open): Set dinfo to host endian to get correct disassembly. + (sim_write, sim_read): Convert endian when gdb reads or writes + memory. + * sis.c (main): Set endian. + * sis.h (EBT): Define. + 2015-04-13 Mike Frysinger <vapier@gentoo.org> * configure: Regenerate. diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c index 7f24fb0..4d4ad04 100644 --- a/sim/erc32/erc32.c +++ b/sim/erc32/erc32.c @@ -54,11 +54,6 @@ int dumbio = 0; /* normal, smart, terminal oriented IO by default */ extern int errmec; #endif -/* The target's byte order is big-endian by default until we load a - little-endian program. */ - -int current_target_byte_order = BIG_ENDIAN; - #define MEC_WS 0 /* Waitstates per MEC access (0 ws) */ #define MOK 0 @@ -296,11 +291,8 @@ static void gpt_reload_set (uint32 val); static void timer_ctrl (uint32 val); static unsigned char * get_mem_ptr (uint32 addr, uint32 size); - -static void fetch_bytes (int asi, unsigned char *mem, - uint32 *data, int sz); - -static void store_bytes (unsigned char *mem, uint32 *data, int sz); +static void store_bytes (unsigned char *mem, uint32 waddr, + uint32 *data, int sz, int32 *ws); extern int ext_irl; @@ -1524,123 +1516,38 @@ timer_ctrl(val) gpt_start(); } - -/* Retrieve data from target memory. MEM points to location from which - to read the data; DATA points to words where retrieved data will be - stored in host byte order. SZ contains log(2) of the number of bytes - to retrieve, and can be 0 (1 byte), 1 (one half-word), 2 (one word), - or 3 (two words). */ +/* Store data in host byte order. MEM points to the beginning of the + emulated memory; WADDR contains the index the emulated memory, + DATA points to words in host byte order to be stored. SZ contains log(2) + of the number of bytes to retrieve, and can be 0 (1 byte), 1 (one half-word), + 2 (one word), or 3 (two words); WS should return the number of + wait-states. */ static void -fetch_bytes (asi, mem, data, sz) - int asi; - unsigned char *mem; - uint32 *data; - int sz; +store_bytes (unsigned char *mem, uint32 waddr, uint32 *data, int32 sz, + int32 *ws) { - if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN - || asi == 8 || asi == 9) { - switch (sz) { - case 3: - data[1] = (((uint32) mem[7]) & 0xff) | - ((((uint32) mem[6]) & 0xff) << 8) | - ((((uint32) mem[5]) & 0xff) << 16) | - ((((uint32) mem[4]) & 0xff) << 24); - /* Fall through to 2 */ - case 2: - data[0] = (((uint32) mem[3]) & 0xff) | - ((((uint32) mem[2]) & 0xff) << 8) | - ((((uint32) mem[1]) & 0xff) << 16) | - ((((uint32) mem[0]) & 0xff) << 24); - break; - case 1: - data[0] = (((uint32) mem[1]) & 0xff) | - ((((uint32) mem[0]) & 0xff) << 8); - break; + switch (sz) { case 0: - data[0] = mem[0] & 0xff; - break; - - } - } else { - switch (sz) { - case 3: - data[1] = ((((uint32) mem[7]) & 0xff) << 24) | - ((((uint32) mem[6]) & 0xff) << 16) | - ((((uint32) mem[5]) & 0xff) << 8) | - (((uint32) mem[4]) & 0xff); - /* Fall through to 4 */ - case 2: - data[0] = ((((uint32) mem[3]) & 0xff) << 24) | - ((((uint32) mem[2]) & 0xff) << 16) | - ((((uint32) mem[1]) & 0xff) << 8) | - (((uint32) mem[0]) & 0xff); + waddr ^= EBT; + mem[waddr] = *data & 0x0ff; + *ws = mem_ramw_ws + 3; break; case 1: - data[0] = ((((uint32) mem[1]) & 0xff) << 8) | - (((uint32) mem[0]) & 0xff); - break; - case 0: - data[0] = mem[0] & 0xff; +#ifdef HOST_LITTLE_ENDIAN + waddr ^= 2; +#endif + memcpy (&mem[waddr], data, 2); + *ws = mem_ramw_ws + 3; break; - } - } -} - - -/* Store data in target byte order. MEM points to location to store data; - DATA points to words in host byte order to be stored. SZ contains log(2) - of the number of bytes to retrieve, and can be 0 (1 byte), 1 (one half-word), - 2 (one word), or 3 (two words). */ - -static void -store_bytes (mem, data, sz) - unsigned char *mem; - uint32 *data; - int sz; -{ - if (CURRENT_TARGET_BYTE_ORDER == LITTLE_ENDIAN) { - switch (sz) { - case 3: - mem[7] = (data[1] >> 24) & 0xff; - mem[6] = (data[1] >> 16) & 0xff; - mem[5] = (data[1] >> 8) & 0xff; - mem[4] = data[1] & 0xff; - /* Fall through to 2 */ case 2: - mem[3] = (data[0] >> 24) & 0xff; - mem[2] = (data[0] >> 16) & 0xff; - /* Fall through to 1 */ - case 1: - mem[1] = (data[0] >> 8) & 0xff; - /* Fall through to 0 */ - case 0: - mem[0] = data[0] & 0xff; + memcpy (&mem[waddr], data, 4); + *ws = mem_ramw_ws; break; - } - } else { - switch (sz) { case 3: - mem[7] = data[1] & 0xff; - mem[6] = (data[1] >> 8) & 0xff; - mem[5] = (data[1] >> 16) & 0xff; - mem[4] = (data[1] >> 24) & 0xff; - /* Fall through to 2 */ - case 2: - mem[3] = data[0] & 0xff; - mem[2] = (data[0] >> 8) & 0xff; - mem[1] = (data[0] >> 16) & 0xff; - mem[0] = (data[0] >> 24) & 0xff; - break; - case 1: - mem[1] = data[0] & 0xff; - mem[0] = (data[0] >> 8) & 0xff; - break; - case 0: - mem[0] = data[0] & 0xff; + memcpy (&mem[waddr], data, 8); + *ws = 2 * mem_ramw_ws + STD_WS; break; - - } } } @@ -1695,7 +1602,7 @@ memory_read(asi, addr, data, sz, ws) #endif if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) { - fetch_bytes (asi, &ramb[addr & mem_rammask], data, sz); + memcpy (data, &ramb[addr & mem_rammask & ~3], 4); *ws = mem_ramr_ws; return 0; } else if ((addr >= MEC_START) && (addr < MEC_END)) { @@ -1713,7 +1620,7 @@ memory_read(asi, addr, data, sz, ws) } else if (era) { if ((addr < 0x100000) || ((addr>= 0x80000000) && (addr < 0x80100000))) { - fetch_bytes (asi, &romb[addr & ROM_MASK], data, sz); + memcpy (data, &romb[addr & ROM_MASK & ~3], 4); *ws = 4; return 0; } else if ((addr >= 0x10000000) && @@ -1724,13 +1631,12 @@ memory_read(asi, addr, data, sz, ws) } } else if (addr < mem_romsz) { - fetch_bytes (asi, &romb[addr], data, sz); - *ws = mem_romr_ws; - return 0; - + memcpy (data, &romb[addr & ~3], 4); + *ws = mem_romr_ws; + return 0; #else } else if (addr < mem_romsz) { - fetch_bytes (asi, &romb[addr], data, sz); + memcpy (data, &romb[addr & ~3], 4); *ws = mem_romr_ws; return 0; #endif @@ -1793,21 +1699,8 @@ memory_write(asi, addr, data, sz, ws) return 1; } } - - store_bytes (&ramb[addr & mem_rammask], data, sz); - - switch (sz) { - case 0: - case 1: - *ws = mem_ramw_ws + 3; - break; - case 2: - *ws = mem_ramw_ws; - break; - case 3: - *ws = 2 * mem_ramw_ws + STD_WS; - break; - } + waddr = addr & mem_rammask; + store_bytes (ramb, waddr, data, sz, ws); return 0; } else if ((addr >= MEC_START) && (addr < MEC_END)) { if ((sz != 2) || (asi != 0xb)) { @@ -1831,7 +1724,7 @@ memory_write(asi, addr, data, sz, ws) ((addr < 0x100000) || ((addr >= 0x80000000) && (addr < 0x80100000)))) { addr &= ROM_MASK; *ws = sz == 3 ? 8 : 4; - store_bytes (&romb[addr], data, sz); + store_bytes (romb, addr, data, sz, ws); return 0; } else if ((addr >= 0x10000000) && (addr < (0x10000000 + (512 << (mec_iocr & 0x0f)))) && @@ -1847,7 +1740,7 @@ memory_write(asi, addr, data, sz, ws) *ws = mem_romw_ws + 1; if (sz == 3) *ws += mem_romw_ws + STD_WS; - store_bytes (&romb[addr], data, sz); + store_bytes (romb, addr, data, sz, ws); return 0; #else @@ -1858,7 +1751,7 @@ memory_write(asi, addr, data, sz, ws) *ws = mem_romw_ws + 1; if (sz == 3) *ws += mem_romw_ws + STD_WS; - store_bytes (&romb[addr], data, sz); + store_bytes (romb, addr, data, sz, ws); return 0; #endif diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c index e6ce6c5..d31032b 100644 --- a/sim/erc32/exec.c +++ b/sim/erc32/exec.c @@ -370,6 +370,36 @@ div64 (uint32 n1_hi, uint32 n1_low, uint32 n2, uint32 *result, int msigned) } +static int +extract_short (uint32 data, uint32 address) +{ + return ((data >> ((2 - (address & 2)) * 8)) & 0xffff); +} + +static int +extract_short_signed (uint32 data, uint32 address) +{ + uint32 tmp = ((data >> ((2 - (address & 2)) * 8)) & 0xffff); + if (tmp & 0x8000) + tmp |= 0xffff0000; + return tmp; +} + +static int +extract_byte (uint32 data, uint32 address) +{ + return ((data >> ((3 - (address & 3)) * 8)) & 0xff); +} + +static int +extract_byte_signed (uint32 data, uint32 address) +{ + uint32 tmp = ((data >> ((3 - (address & 3)) * 8)) & 0xff); + if (tmp & 0x80) + tmp |= 0xffffff00; + return tmp; +} + int dispatch_instruction(sregs) struct pstate *sregs; @@ -1077,7 +1107,8 @@ dispatch_instruction(sregs) sregs->trap = TRAP_PRIVI; break; } - sregs->psr = (rs1 ^ operand2) & 0x00f03fff; + sregs->psr = (sregs->psr & 0xff000000) | + (rs1 ^ operand2) & 0x00f03fff; break; case WRWIM: if (!(sregs->psr & PSR_S)) { @@ -1213,8 +1244,10 @@ dispatch_instruction(sregs) else rdd = &(sregs->g[rd]); } - mexc = memory_read(asi, address, ddata, 3, &ws); - sregs->hold += ws * 2; + mexc = memory_read (asi, address, ddata, 2, &ws); + sregs->hold += ws; + mexc |= memory_read (asi, address+4, &ddata[1], 2, &ws); + sregs->hold += ws; sregs->icnt = T_LDD; if (mexc) { sregs->trap = TRAP_DEXC; @@ -1252,6 +1285,7 @@ dispatch_instruction(sregs) sregs->trap = TRAP_DEXC; break; } + data = extract_byte (data, address); *rdd = data; data = 0x0ff; mexc = memory_write(asi, address, &data, 0, &ws); @@ -1274,8 +1308,10 @@ dispatch_instruction(sregs) sregs->trap = TRAP_DEXC; break; } - if ((op3 == LDSB) && (data & 0x80)) - data |= 0xffffff00; + if (op3 == LDSB) + data = extract_byte_signed (data, address); + else + data = extract_byte (data, address); *rdd = data; break; case LDSHA: @@ -1293,8 +1329,10 @@ dispatch_instruction(sregs) sregs->trap = TRAP_DEXC; break; } - if ((op3 == LDSH) && (data & 0x8000)) - data |= 0xffff0000; + if (op3 == LDSH) + data = extract_short_signed (data, address); + else + data = extract_short (data, address); *rdd = data; break; case LDF: @@ -1337,8 +1375,10 @@ dispatch_instruction(sregs) ((sregs->frs2 >> 1) == (rd >> 1))) sregs->fhold += (sregs->ftime - ebase.simtime); } - mexc = memory_read(asi, address, ddata, 3, &ws); - sregs->hold += ws * 2; + mexc = memory_read (asi, address, ddata, 2, &ws); + sregs->hold += ws; + mexc |= memory_read (asi, address+4, &ddata[1], 2, &ws); + sregs->hold += ws; sregs->icnt = T_LDD; if (mexc) { sregs->trap = TRAP_DEXC; diff --git a/sim/erc32/func.c b/sim/erc32/func.c index 479c5ee..9297e07 100644 --- a/sim/erc32/func.c +++ b/sim/erc32/func.c @@ -30,10 +30,8 @@ #include "sim-config.h" #include <inttypes.h> - #define VAL(x) strtoul(x,(char **)NULL,0) -extern int current_target_byte_order; struct disassemble_info dinfo; struct pstate sregs; extern struct estate ebase; @@ -184,18 +182,10 @@ get_regi(struct pstate * sregs, int32 reg, char *buf) default:break; } } - if (current_target_byte_order == BIG_ENDIAN) { - buf[0] = (rval >> 24) & 0x0ff; - buf[1] = (rval >> 16) & 0x0ff; - buf[2] = (rval >> 8) & 0x0ff; - buf[3] = rval & 0x0ff; - } - else { - buf[3] = (rval >> 24) & 0x0ff; - buf[2] = (rval >> 16) & 0x0ff; - buf[1] = (rval >> 8) & 0x0ff; - buf[0] = rval & 0x0ff; - } + buf[0] = (rval >> 24) & 0x0ff; + buf[1] = (rval >> 16) & 0x0ff; + buf[2] = (rval >> 8) & 0x0ff; + buf[3] = rval & 0x0ff; } @@ -787,15 +777,15 @@ disp_ctrl(sregs) struct pstate *sregs; { - unsigned char i[4]; + uint32 i; printf("\n psr: %08X wim: %08X tbr: %08X y: %08X\n", sregs->psr, sregs->wim, sregs->tbr, sregs->y); - sis_memory_read(sregs->pc, i, 4); - printf("\n pc: %08X = %02X%02X%02X%02X ", sregs->pc,i[0],i[1],i[2],i[3]); + sis_memory_read (sregs->pc, (char *) &i, 4); + printf ("\n pc: %08X = %08X ", sregs->pc, i); print_insn_sparc_sis(sregs->pc, &dinfo); - sis_memory_read(sregs->npc, i, 4); - printf("\n npc: %08X = %02X%02X%02X%02X ",sregs->npc,i[0],i[1],i[2],i[3]); + sis_memory_read (sregs->npc, (char *) &i, 4); + printf ("\n npc: %08X = %08X ", sregs->npc, i); print_insn_sparc_sis(sregs->npc, &dinfo); if (sregs->err_mode) printf("\n IU in error mode"); @@ -809,22 +799,25 @@ disp_mem(addr, len) { uint32 i; - unsigned char data[4]; + union { + unsigned char u8[4]; + uint32 u32; + } data; uint32 mem[4], j; char *p; for (i = addr & ~3; i < ((addr + len) & ~3); i += 16) { printf("\n %8X ", i); for (j = 0; j < 4; j++) { - sis_memory_read((i + (j * 4)), data, 4); - printf("%02x%02x%02x%02x ", data[0],data[1],data[2],data[3]); - mem[j] = *((int *) &data); + sis_memory_read ((i + (j * 4)), data.u8, 4); + printf ("%08x ", data.u32); + mem[j] = data.u32; } printf(" "); p = (char *) mem; for (j = 0; j < 16; j++) { - if (isprint(p[j])) - putchar(p[j]); + if (isprint (p[j ^ EBT])) + putchar (p[j ^ EBT]); else putchar('.'); } @@ -839,11 +832,14 @@ dis_mem(addr, len, info) struct disassemble_info *info; { uint32 i; - unsigned char data[4]; + union { + unsigned char u8[4]; + uint32 u32; + } data; for (i = addr & -3; i < ((addr & -3) + (len << 2)); i += 4) { - sis_memory_read(i, data, 4); - printf(" %08x %02x%02x%02x%02x ", i, data[0],data[1],data[2],data[3]); + sis_memory_read (i, data.u8, 4); + printf (" %08x %08x ", i, data.u32); print_insn_sparc_sis(i, info); if (i >= 0xfffffffc) break; printf("\n"); @@ -1041,6 +1037,7 @@ bfd_load (const char *fname) asection *section; bfd *pbfd; const bfd_arch_info_type *arch; + int i; pbfd = bfd_openr(fname, 0); @@ -1054,14 +1051,6 @@ bfd_load (const char *fname) } arch = bfd_get_arch_info (pbfd); - if (bfd_little_endian (pbfd) || arch->mach == bfd_mach_sparc_sparclite_le) - current_target_byte_order = LITTLE_ENDIAN; - else - current_target_byte_order = BIG_ENDIAN; - if (sis_verbose) - printf("file %s is %s-endian.\n", fname, - current_target_byte_order == BIG_ENDIAN ? "big" : "little"); - if (sis_verbose) printf("loading %s:", fname); for (section = pbfd->sections; section; section = section->next) { @@ -1093,10 +1082,7 @@ bfd_load (const char *fname) sizeof (marker)); if (strncmp (marker.signature, "DaTa", 4) == 0) { - if (current_target_byte_order == BIG_ENDIAN) - section_address = bfd_getb32 (marker.sdata); - else - section_address = bfd_getl32 (marker.sdata); + section_address = bfd_getb32 (marker.sdata); } } } @@ -1121,7 +1107,8 @@ bfd_load (const char *fname) bfd_get_section_contents(pbfd, section, buffer, fptr, count); - sis_memory_write(section_address, buffer, count); + for (i = 0; i < count; i++) + sis_memory_write ((section_address + i) ^ EBT, &buffer[i], 1); section_address += count; fptr += count; diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c index 59fb635..235af8b 100644 --- a/sim/erc32/interf.c +++ b/sim/erc32/interf.c @@ -40,7 +40,6 @@ extern struct disassemble_info dinfo; extern struct pstate sregs; extern struct estate ebase; -extern int current_target_byte_order; extern int ctrl_c; extern int nfp; extern int ift; @@ -252,7 +251,11 @@ sim_open (kind, callback, abfd, argv) sregs.freq = freq ? freq : 15; termsave = fcntl(0, F_GETFL, 0); INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf); +#ifdef HOST_LITTLE_ENDIAN + dinfo.endian = BFD_ENDIAN_LITTLE; +#else dinfo.endian = BFD_ENDIAN_BIG; +#endif reset_all(); ebase.simtime = 0; init_sim(); @@ -311,14 +314,10 @@ sim_store_register(sd, regno, value, length) unsigned char *value; int length; { - /* FIXME: Review the computation of regval. */ int regval; - if (current_target_byte_order == BIG_ENDIAN) - regval = (value[0] << 24) | (value[1] << 16) + + regval = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3]; - else - regval = (value[3] << 24) | (value[2] << 16) - | (value[1] << 8) | value[0]; set_regi(&sregs, regno, regval); return length; } @@ -336,23 +335,25 @@ sim_fetch_register(sd, regno, buf, length) } int -sim_write(sd, mem, buf, length) - SIM_DESC sd; - SIM_ADDR mem; - const unsigned char *buf; - int length; +sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length) { - return sis_memory_write (mem, buf, length); + int i, len; + + for (i = 0; i < length; i++) { + sis_memory_write ((mem + i) ^ EBT, &buf[i], 1); + } + return length; } int -sim_read(sd, mem, buf, length) - SIM_DESC sd; - SIM_ADDR mem; - unsigned char *buf; - int length; +sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length) { - return sis_memory_read (mem, buf, length); + int i, len; + + for (i = 0; i < length; i++) { + sis_memory_read ((mem + i) ^ EBT, &buf[i], 1); + } + return length; } void diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c index 6259067..92880e1 100644 --- a/sim/erc32/sis.c +++ b/sim/erc32/sis.c @@ -223,7 +223,11 @@ main(argc, argv) sregs.freq = freq; INIT_DISASSEMBLE_INFO(dinfo, stdout, (fprintf_ftype) fprintf); +#ifdef HOST_LITTLE_ENDIAN + dinfo.endian = BFD_ENDIAN_LITTLE; +#else dinfo.endian = BFD_ENDIAN_BIG; +#endif termsave = fcntl(0, F_GETFL, 0); using_history(); diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h index ae39ad1..99ae347 100644 --- a/sim/erc32/sis.h +++ b/sim/erc32/sis.h @@ -28,8 +28,10 @@ #if WITH_HOST_BYTE_ORDER == BIG_ENDIAN #define HOST_BIG_ENDIAN +#define EBT 0 #else #define HOST_LITTLE_ENDIAN +#define EBT 3 #endif #define I_ACC_EXC 1 |