From patchwork Tue Mar 17 21:02:40 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Gaisler X-Patchwork-Id: 5665 Received: (qmail 40139 invoked by alias); 17 Mar 2015 21:03:09 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 39938 invoked by uid 89); 17 Mar 2015 21:03:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 X-HELO: bin-vsp-out-03.atm.binero.net Received: from vsp-authed01.binero.net (HELO bin-vsp-out-03.atm.binero.net) (195.74.38.224) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 17 Mar 2015 21:03:04 +0000 X-Halon-ID: fc5e3c2d-cce8-11e4-9958-0050569116f7 Authorized-sender: jiri@gaisler.se Received: from localhost.localdomain (unknown [46.246.62.93]) by bin-vsp-out-03.atm.binero.net (Halon Mail Gateway) with ESMTPSA; Tue, 17 Mar 2015 22:02:56 +0100 (CET) From: Jiri Gaisler To: gdb-patches@sourceware.org Cc: Jiri Gaisler Subject: [PATCH v4 03/13] sim/erc32: Switched emulated memory to host endian order. Date: Tue, 17 Mar 2015 22:02:40 +0100 Message-Id: <1426626170-21401-4-git-send-email-jiri@gaisler.se> In-Reply-To: <1426626170-21401-1-git-send-email-jiri@gaisler.se> References: <1426626170-21401-1-git-send-email-jiri@gaisler.se> X-IsSubscribed: yes 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 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 #include "sim-config.h" #include - +#include #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 #include "sim-config.h" +#include #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 . */ + + +#include +#undef ASSERT +#define ASSERT(x) if (0) {} +#include 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();