sim/erc32: Switched emulated memory to host endian order.

Change data ordering in emulated memory from target order (big endian)
to host order. Improves performance and simplifies most memory
operations. Requires some byte twisting during stores on little
endian hosts (intel). Also removed support for little-endian binaries.
This commit is contained in:
Jiri Gaisler 2015-04-03 22:35:48 +02:00 committed by Mike Frysinger
parent 09b29ece9a
commit d3e9b40afb
7 changed files with 160 additions and 211 deletions

View File

@ -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.

View File

@ -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). */
static void
fetch_bytes (asi, mem, data, sz)
int asi;
unsigned char *mem;
uint32 *data;
int sz;
{
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;
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);
break;
case 1:
data[0] = ((((uint32) mem[1]) & 0xff) << 8) |
(((uint32) mem[0]) & 0xff);
break;
case 0:
data[0] = mem[0] & 0xff;
break;
}
}
}
/* Store data in target byte order. MEM points to location to store data;
/* 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). */
2 (one word), or 3 (two words); WS should return the number of
wait-states. */
static void
store_bytes (mem, data, sz)
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 == 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 */
switch (sz) {
case 0:
mem[0] = data[0] & 0xff;
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;
waddr ^= EBT;
mem[waddr] = *data & 0x0ff;
*ws = mem_ramw_ws + 3;
break;
case 1:
mem[1] = data[0] & 0xff;
mem[0] = (data[0] >> 8) & 0xff;
#ifdef HOST_LITTLE_ENDIAN
waddr ^= 2;
#endif
memcpy (&mem[waddr], data, 2);
*ws = mem_ramw_ws + 3;
break;
case 0:
mem[0] = data[0] & 0xff;
case 2:
memcpy (&mem[waddr], data, 4);
*ws = mem_ramw_ws;
break;
case 3:
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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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