[v4,03/13] sim/erc32: Switched emulated memory to host endian order.

Message ID 1426626170-21401-4-git-send-email-jiri@gaisler.se
State Superseded
Headers

Commit Message

Jiri Gaisler March 17, 2015, 9:02 p.m. UTC
  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).

	* erc32.c (fetch_bytes): Remove. (store_bytes) Remove byte twisting.
	(memory_read) Access memory directly. (extract_short,
	extract_short_signed, extract_byte, extract_byte_signed) New
	function for for sub-word LD instructions.

	* func.c (disp_ctrl, dis_mem): Ajust print-out to new data endian.

	* interf.c (sim_open): Convert endian when gdb writes to memory.

	* sim-main.c : New file. Pull in sim-endian.c to use common endian conversions.
---
 sim/erc32/Makefile.in |   8 +--
 sim/erc32/erc32.c     | 168 ++++++++++++--------------------------------------
 sim/erc32/exec.c      |  60 +++++++++++++++---
 sim/erc32/func.c      |  55 +++++++++++------
 sim/erc32/interf.c    |  30 +++++++++
 sim/erc32/sim-main.c  |  26 ++++++++
 sim/erc32/sis.c       |   4 ++
 7 files changed, 189 insertions(+), 162 deletions(-)
 create mode 100644 sim/erc32/sim-main.c
  

Comments

Mike Frysinger March 23, 2015, 2:45 a.m. UTC | #1
On 17 Mar 2015 22:02, Jiri Gaisler wrote:
> --- a/sim/erc32/erc32.c
> +++ b/sim/erc32/erc32.c
>  
>  static void
> -fetch_bytes (asi, mem, data, sz)
> +store_bytes (mem, waddr, data, sz, ws)

as some point we'll want to switch over to sim-core.c and then all these 
accessor funcs you have would go away.  but we don't need to do that now.

> +#ifdef HOST_LITTLE_ENDIAN
> +	    waddr ^= 3;
> +#endif
> +	    mem[waddr] = *data & 0x0ff;

doesn't this assume the target is big endian ?  this shows up a few times in 
the changes to this file.

> +	    memcpy(&mem[waddr], data, 2);

space before the (.  this shows up a few times in the changes to this file.

> +            *data = *((uint32 *) & (romb[addr & ~3]));

broken indentation, and you need to use the union/memcpy logic.  this shows up a 
few times in the changes to this file.

> +	    mexc = memory_read(asi, address, ddata, 2, &ws);

you should scan the whole change for new lines that are missing the space before 
the (

>      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

can't you get the target endian info via the bfd library ?

> +#ifdef HOST_LITTLE_ENDIAN
> +    int *ibufp = (int *) buf;

needs a union

> +    int ibuf[8192];
> +    int i, len;
> +
> +    if (length >= 4)
> +      for (i = 0; i < length; i += 4) {
> +        ibuf[i] = T2H_4(ibufp[i]);
> +      }
> +    return (sis_memory_write(mem, (char *) ibuf, length));
> +#else
>      return (sis_memory_write(mem, buf, length));
> +#endif

the point of using sim-endian is that you wouldn't have any ifdefs.  code the 
loop and let gcc optimize away the "nothing to do" case.
-mike
  
Jiri Gaisler March 23, 2015, 9 a.m. UTC | #2
On 23/03/15 03:45, Mike Frysinger wrote:
> On 17 Mar 2015 22:02, Jiri Gaisler wrote:
>> --- a/sim/erc32/erc32.c
>> +++ b/sim/erc32/erc32.c
>> +#ifdef HOST_LITTLE_ENDIAN
>> +	    waddr ^= 3;
>> +#endif
>> +	    mem[waddr] = *data & 0x0ff;
> 
> doesn't this assume the target is big endian ?  this shows up a few times in 
> the changes to this file.
> 

The target (SPARC) is always big endian, so I believe this is correct.

I will fix the rest of your comments and resend.

Jiri.
  
Jiri Gaisler March 24, 2015, 9:39 a.m. UTC | #3
On 23/03/15 03:45, Mike Frysinger wrote:
> On 17 Mar 2015 22:02, Jiri Gaisler wrote:
>> --- a/sim/erc32/erc32.c
>> +++ b/sim/erc32/erc32.c

>>      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
> 
> can't you get the target endian info via the bfd library ?

bfd can tell me the byte order of the data sections in a file,
but not how the data is actually stored in the memory of the host.
Since sis always stores in host order, dinfo.endian must have
the order of the host, and not the bfd order of a file.

Jiri.
  
Mike Frysinger March 28, 2015, 7:41 a.m. UTC | #4
On 23 Mar 2015 10:00, Jiri Gaisler wrote:
> On 23/03/15 03:45, Mike Frysinger wrote:
> > On 17 Mar 2015 22:02, Jiri Gaisler wrote:
> >> --- a/sim/erc32/erc32.c
> >> +++ b/sim/erc32/erc32.c
> >> +#ifdef HOST_LITTLE_ENDIAN
> >> +	    waddr ^= 3;
> >> +#endif
> >> +	    mem[waddr] = *data & 0x0ff;
> > 
> > doesn't this assume the target is big endian ?  this shows up a few times in 
> > the changes to this file.
> 
> The target (SPARC) is always big endian, so I believe this is correct.

wikipedia says:
The endianness of the 32-bit SPARC V8 architecture is purely big-endian. The 
64-bit SPARC V9 architecture uses big-endian instructions, but can access data 
in either big-endian or little-endian byte order, chosen either at the 
application instruction (load/store) level or at the memory page level (via an 
MMU setting). The latter is often used for accessing data from inherently 
little-endian devices, such as those on PCI buses.

but i guess that'll need quite a bit of work to fix up ?
-mike
  
Jiri Gaisler March 28, 2015, 8:21 a.m. UTC | #5
On 28/03/15 08:41, Mike Frysinger wrote:
> On 23 Mar 2015 10:00, Jiri Gaisler wrote:
>> On 23/03/15 03:45, Mike Frysinger wrote:
>>> On 17 Mar 2015 22:02, Jiri Gaisler wrote:
>>>> --- a/sim/erc32/erc32.c
>>>> +++ b/sim/erc32/erc32.c
>>>> +#ifdef HOST_LITTLE_ENDIAN
>>>> +	    waddr ^= 3;
>>>> +#endif
>>>> +	    mem[waddr] = *data & 0x0ff;
>>>
>>> doesn't this assume the target is big endian ?  this shows up a few times in 
>>> the changes to this file.
>>
>> The target (SPARC) is always big endian, so I believe this is correct.
> 
> wikipedia says:
> The endianness of the 32-bit SPARC V8 architecture is purely big-endian. The 
> 64-bit SPARC V9 architecture uses big-endian instructions, but can access data 
> in either big-endian or little-endian byte order, chosen either at the 
> application instruction (load/store) level or at the memory page level (via an 
> MMU setting). The latter is often used for accessing data from inherently 
> little-endian devices, such as those on PCI buses.
> 
> but i guess that'll need quite a bit of work to fix up ?

The sis simulator is strictly SPARC V8 (32-bit), so there is nothing to fix up really.
I have no plans to add V9 (64-bit) so staying big endian should be safe.

Jiri.

> -mike
>
  

Patch

diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
index 108e8b6..e8a8f18 100644
--- a/sim/erc32/Makefile.in
+++ b/sim/erc32/Makefile.in
@@ -21,7 +21,10 @@ 
 TERMCAP_LIB = @TERMCAP@
 READLINE_LIB = @READLINE@
 
-SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o
+# `sis' doesn't need interf.o.
+SIS_OFILES = exec.o erc32.o func.o help.o float.o sim-main.o
+
+SIM_OBJS = $(SIS_OFILES) interf.o
 SIM_RUN_OBJS = sis.o
 SIM_EXTRA_LIBS = $(READLINE_LIB) $(TERMCAP_LIB) -lm
 SIM_EXTRA_ALL = sis
@@ -35,9 +38,6 @@  SIM_EXTRA_CFLAGS = -DFAST_UART -I$(srcroot)
 
 ## COMMON_POST_CONFIG_FRAG
 
-# `sis' doesn't need interf.o.
-SIS_OFILES = exec.o erc32.o func.o help.o float.o
-
 sis: sis.o $(SIS_OFILES) $(COMMON_OBJS) $(LIBDEPS)
 	$(CC) $(ALL_CFLAGS) -o sis \
 	  sis.o $(SIS_OFILES) $(COMMON_OBJS) $(EXTRA_LIBS)
diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
index 6b771b4..8c0ddd3 100644
--- a/sim/erc32/erc32.c
+++ b/sim/erc32/erc32.c
@@ -296,11 +296,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 +1521,43 @@  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;
+store_bytes (mem, waddr, data, sz, ws)
     unsigned char  *mem;
+    uint32	   waddr;
     uint32	   *data;
-    int		    sz;
+    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);
+#ifdef HOST_LITTLE_ENDIAN
+	    waddr ^= 3;
+#endif
+	    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;
-	    
-	}
     }
 }
 
@@ -1670,7 +1587,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)) {
@@ -1688,7 +1605,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) && 
@@ -1699,13 +1616,15 @@  memory_read(asi, addr, data, sz, ws)
 	}
 	
     } else  if (addr < mem_romsz) {
-	    fetch_bytes (asi, &romb[addr], data, sz);
+            *data = *((uint32 *) & (romb[addr & ~3]));
+	    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);
+        *data = *((uint32 *) & (romb[addr & ~3]));
+	memcpy(data, &romb[addr & ~3], 4);
 	*ws = mem_romr_ws;
 	return (0);
 #endif
@@ -1768,21 +1687,10 @@  memory_write(asi, addr, data, sz, ws)
 	    }
 	}
 
-	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)) {
 	    set_sfsr(MEC_ACC, addr, asi, 0);
@@ -1805,7 +1713,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)))) &&
@@ -1821,7 +1729,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
@@ -1832,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);
 
 #endif
diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
index 275218a..38e1045 100644
--- a/sim/erc32/exec.c
+++ b/sim/erc32/exec.c
@@ -370,8 +370,38 @@  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)
+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 e42b0ec..122ce64 100644
--- a/sim/erc32/func.c
+++ b/sim/erc32/func.c
@@ -29,7 +29,7 @@ 
 #include <dis-asm.h>
 #include "sim-config.h"
 #include <inttypes.h>
-
+#include <sim-basics.h>
 
 #define	VAL(x)	strtoul(x,(char **)NULL,0)
 
@@ -787,15 +787,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 +809,31 @@  disp_mem(addr, len)
 {
 
     uint32          i;
-    unsigned char   data[4];
+    union {
+	    unsigned char u8[4];
+	    uint32 u32;
+    } data;
     uint32          mem[4], j;
     char           *p;
+    int		   end;
 
+#ifdef HOST_LITTLE_ENDIAN
+    end = 3;
+#else
+    end = 0;
+#endif
     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 ^ end]))
+		putchar(p[j ^ end]);
 	    else
 		putchar('.');
 	}
@@ -839,11 +848,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");
@@ -1042,6 +1054,7 @@  bfd_load(fname)
     asection       *section;
     bfd            *pbfd;
     const bfd_arch_info_type *arch;
+    int            i;
 
     pbfd = bfd_openr(fname, 0);
 
@@ -1115,14 +1128,20 @@  bfd_load(fname)
 		fptr = 0;
 
 		while (section_size > 0) {
-		    char            buffer[1024];
 		    int             count;
+		    union {
+			unsigned char u8[1024];
+			uint32 u32[256];
+		    } buffer;
 
 		    count = min(section_size, 1024);
 
-		    bfd_get_section_contents(pbfd, section, buffer, fptr, count);
+		    bfd_get_section_contents(pbfd, section, buffer.u8, fptr, count);
 
-		    sis_memory_write(section_address, buffer, count);
+#ifdef HOST_LITTLE_ENDIAN
+		    for (i = 0; i < (count / 4); i++) buffer.u32[i] = T2H_4(buffer.u32[i]); // endian swap
+#endif
+		    sis_memory_write(section_address, buffer.u8, count);
 
 		    section_address += count;
 		    fptr += count;
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index 608b224..97540a9 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -30,6 +30,7 @@ 
 #include "bfd.h"
 #include <dis-asm.h>
 #include "sim-config.h"
+#include <sim-basics.h>
 
 #include "gdb/remote-sim.h"
 #include "gdb/signals.h"
@@ -266,7 +267,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();
@@ -356,7 +361,19 @@  sim_write(sd, mem, buf, length)
     const unsigned char  *buf;
     int             length;
 {
+#ifdef HOST_LITTLE_ENDIAN
+    int *ibufp = (int *) buf;
+    int ibuf[8192];
+    int i, len;
+
+    if (length >= 4)
+      for (i = 0; i < length; i += 4) {
+        ibuf[i] = T2H_4(ibufp[i]);
+      }
+    return (sis_memory_write(mem, (char *) ibuf, length));
+#else
     return (sis_memory_write(mem, buf, length));
+#endif
 }
 
 int
@@ -366,7 +383,20 @@  sim_read(sd, mem, buf, length)
      unsigned char *buf;
      int length;
 {
+#ifdef HOST_LITTLE_ENDIAN
+    int *ibuf = (int *) buf;
+    int i, len;
+
+    len = sis_memory_read(mem, buf, length);
+    if (length >= 4)
+      for (i = 0; i < length; i += 4) {
+        *ibuf = H2T_4(*ibuf);
+        ibuf++;
+      }
+    return (len);
+#else
     return (sis_memory_read(mem, buf, length));
+#endif
 }
 
 void
diff --git a/sim/erc32/sim-main.c b/sim/erc32/sim-main.c
new file mode 100644
index 0000000..860e7db
--- /dev/null
+++ b/sim/erc32/sim-main.c
@@ -0,0 +1,26 @@ 
+/* SIS, SPARC instruction simulator
+
+   Copyright 2002-2015 Free Software Foundation, Inc.
+
+   Contributed by Jiri Gaisler.
+
+   This file is part of GDB.
+
+   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 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, see <http://www.gnu.org/licenses/>.  */
+
+
+#include <sim-assert.h>
+#undef  ASSERT
+#define ASSERT(x) if (0) {}
+#include <sim-endian.c>
diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
index 931e3f3..dcb5ebf 100644
--- a/sim/erc32/sis.c
+++ b/sim/erc32/sis.c
@@ -227,7 +227,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();