diff options
author | Michael Meissner <gnu@the-meissners.org> | 1995-11-13 16:07:30 +0000 |
---|---|---|
committer | Michael Meissner <gnu@the-meissners.org> | 1995-11-13 16:07:30 +0000 |
commit | 1dc7c0ed844311c321e68f23209f4d51ef475fdc (patch) | |
tree | 8e1765a07044abb451a489c56658861119b2616d | |
parent | 125d37c4719b9df1d7b60614bd310ac1c7828f8d (diff) | |
download | gdb-1dc7c0ed844311c321e68f23209f4d51ef475fdc.zip gdb-1dc7c0ed844311c321e68f23209f4d51ef475fdc.tar.gz gdb-1dc7c0ed844311c321e68f23209f4d51ef475fdc.tar.bz2 |
checkpoint
-rw-r--r-- | sim/ppc/ChangeLog | 188 | ||||
-rw-r--r-- | sim/ppc/Makefile.in | 4 | ||||
-rw-r--r-- | sim/ppc/configure.in | 15 | ||||
-rw-r--r-- | sim/ppc/device_tree.c | 230 | ||||
-rw-r--r-- | sim/ppc/device_tree.h | 60 | ||||
-rw-r--r-- | sim/ppc/devices.c | 217 | ||||
-rw-r--r-- | sim/ppc/igen.c | 582 | ||||
-rw-r--r-- | sim/ppc/main.c | 2 |
8 files changed, 893 insertions, 405 deletions
diff --git a/sim/ppc/ChangeLog b/sim/ppc/ChangeLog index d3e2ab4..aae1bc2 100644 --- a/sim/ppc/ChangeLog +++ b/sim/ppc/ChangeLog @@ -1,3 +1,179 @@ +Mon Nov 13 09:14:13 1995 Michael Meissner <meissner@tiktok.cygnus.com> + + * igen.c ({insn,model}_table_fields): Spell mnemonic correctly. + (gen_itable_h,itable_c_insn): Ditto. + (model support): Move model support around, add support for + model-data, model-internal. Use annex field for model-macros + now. + + * configure.in (--enable-sim-inline): If --enable-sim-inline=no, + also define INLINE as nothing. + * configure: Regenerate. + + * std-config.h (INLINE): Rather than nuking INLINE, only define it + as __inline__ if any of the INLINE flags are non-zero. + + * options.c (print_options): Print out WITH_XOR_ENDAIN. + +Mon Nov 13 23:03:45 1995 Andrew Cagney <cagneyhighland.com.au> + + * ppc-instructions (rfi): Add missing code. + + * cpu.c (cpu_get_time_base): Fix calculation of current value of + time base register. + + * ppc-spr-table (TBL, TBU): Fix TBL/TBU entries - was confusing + m[tf]tb with m[tf]spr. + + * ppc-instructions (mtspr, mfspr): Fix mttbl - wasn't storing + lower word. + +Mon Nov 13 21:35:37 1995 Andrew Cagney <cagneyhighland.com.au> + + * std-config.h (INLINE, STATIC_INLINE): Was being set to static + inline.. Only problem being that with ppc-opcode-simple this gave + it the chance to inline all the idecode functions with potentially + disasterous results on a 16mb PC. For moment hobble INLINE. + + * configure.in, std-config.h (WITH_SMP): Make that 5 processors by + default ... + + * configure.in: Tweek flags passed to gcc for --with-sim-warnings. + Firstly make them errors and secondly remove the options gcc-245 + doesn't reconize. + +Mon Nov 13 17:57:24 1995 Andrew Cagney <cagney@highland.com.au> + + * misc.c (zalloc), cpu.c (cpu_init), devices + (console_io_read_buffer_callback, icu_io_read_buffer_callback, + vm_io_read_buffer_callback), main.c (zalloc), mon.c (memset), + sim_calls.c (zalloc) : replace bzero() with memset(). + + * emul_netbsd.c (write_direntries), psim.c (psim_read_register, + psim_write_register): replace bcopy() with memcpy(). + +Sun Nov 12 20:55:41 1995 Andrew Cagney <cagneyhighland.com.au> + + * configure.in: for --disable-sim-inline (--enable-sim-inline=no), + force DEFAULT_INLINE to 0 rather then trusting the std + configuration. + +Sun Nov 12 20:55:41 1995 Andrew Cagney <cagneyhighland.com.au> + + * igen.c (lf_print_idecode_table, idecode_table_leaf): Fix + generation of switch entries in tables - treat the same as + cracking/semantic functions. + + * igen.c (idecode_switch_end, idecode_switch_leaf): Fix generation + of a boolean switch statement (field zero or non-zero). + + * ppc-opcode-test-1, ppc-opcode-test-2: New files. These test the + switch/table generation ability of igen. + + * igen.c (idecode_switch_leaf): Fix code output when a switch + statement needs to look up a table. + + * igen.c (idecode_declare_if_switch): New function called from + gen_idecode_c - need to declare any idecode switch functions + before they are used in idecode tables. + + * igen.c (lf_print_c_cracker_function, idecode_crack_leaf, + idecode_crack_insn): Add is_inline_function argument to code + printing cracker functions which indicates if STATIC_IDECODE or + STATIC_INLINE_IDECODE should be used for definition. For + idecode_crack_insn (which implies not duplicating/expanding) don't + declare function as inline - we assume that the only time this is + code is generated is when things are being tested. For + idecode_crack_leaf, make static (instead of INLINE) if the + instructions parent is a table as function will always be called + via a table. + + * igen.c (idecode_expand_if_switch): Declare as STATIC_IDECODE not + STATIC_INLINE_IDECODE. Only the outermost idecode switch will be + called directly, all others are called via a table. + + * igen.c (lf_print_semantic_function_header, semantics_h_leaf, + semantics_h_insn, semantics_h_function, + lf_print_c_semantic_function, semantics_c_function): Add + is_inline_function argument to lf_print_semantic_function_header + to indicate if an inline or static function declaration/definition + should be output. Depending on situtation call accordingly: + functions (not instruction semantic routines) are always inline; + Semantic routines are made inline when there is no icache (cache + will contain the function address) and are duplicating (see above) + and the parent of the instruction is a switch statement. + + * igen.c (opcode_field_new): Delete. Code changed to use ZALLOC + and moved to insn_table_find_opcode_field. + + * table.c (table_open): Fix typo (nr_model_fields vs nr_fields). + + * igen.c (model_c_insn): Suggestion - document the name of the + instruction on each line of the instruction model table. + +Fri Nov 10 00:44:38 1995 Andrew Cagney <cagneyhighland.com.au> + + * emul_netbsd.c (do_ioctl): Cleanup compilation. + + * sim_callbacks.h (__attribute__): Only define if not defined (was + already defined on NetBSD host). + +Wed Nov 8 21:49:52 1995 Andrew Cagney <cagneyhighland.com.au> + + * std-config.h (WITH_XOR_ENDIAN), configure.in, Makefile.in: New + macro, indicates if the PowerPC's horrible XOR endian mode should + be suported. Add to configure and make. + + * vm_n.h (vm_data_map_read_N, vm_data_map_write_N), vm.c + (vm_instruction_map_read): If XOR endian, xor the address + with a value from an xor table (indexed by size of access). + + * vm.c (vm_synchronize_context), cpu.c (cpu_synchronize_context): + set up xor table to xor if there is a conflict between the + CURRENT_TARGET_ENDIAN and the endian indicated in the MSR. Move + check of suported change of endian mode from cpu.c to vm.c. + + * vm.c (vm_data_map_write_buffer, vm_data_map_read_buffer): + Hopefully added correct hack to handle XOR endian mode. + + FIXME: If NONSTRICT alignment and XOR ENDIAN and MSR indicates + little endian mode, the model accepts miss aligned transfers. + + FIXME: Need to create an `init' device that, during + initializatioin for XOR mode, it mushes (XOR address) all the dma + data before passing it on to the core for storage. Just like the + real thing really. + +Wed Nov 8 21:49:52 1995 Andrew Cagney <cagneyhighland.com.au> + + * devices.c (halt_io_write_buffer_callback): Use value written to + halt device to determine exit status. Thus allowing + success/failure of OEA tests. + +Wed Nov 8 00:10:38 1995 Andrew Cagney <cagneyhighland.com.au> + + * ppc-instructions (icbi): If icache present flush it. + +Tue Nov 7 23:36:31 1995 Andrew Cagney <cagneyhighland.com.au> + + * devices.c (htab_init_callback): Add code to create htab/pte. + + * devices.c (dma_file, file_init_callback, htab_init_callback): + New function - Dma the named file into memory at the specified + address. Use. + + * device_tree.h, device_tree.c (scand_*): New functions. + +Tue Nov 7 23:36:31 1995 Andrew Cagney <cagneyhighland.com.au> + + * filter_filename.c, Makefile.in: Change so that only dependant on + a very limited nr of files. Stops an unnecessary dependency. + +Tue Nov 7 15:44:33 1995 Andrew Cagney <cagney@highland.com.au> + + * core.c (core_map_find_mapping): Use cpu_halt rather than error + to abort an access to an undefined address. + Sun Nov 12 07:58:09 1995 Michael Meissner <meissner@tiktok.cygnus.com> * igen.c (model_table_insert_{macro,function}): New functions. @@ -439,7 +615,7 @@ Thu Nov 2 08:54:04 1995 Michael Meissner <meissner@tiktok.cygnus.com> * configure.in: Add support for --enable-sim-opcode=stupid. * configure: Regenerate. -Wed Nov 1 23:46:59 1995 Andrew Cagney - aka Noid <cagney@highland.com.au> +Wed Nov 1 23:46:59 1995 Andrew Cagney <cagney@highland.com.au> * std-config (INLINE_DEVICE_TREE): Don't inline either of device_tree.c or devices.c. There is no significant gain. @@ -447,7 +623,7 @@ Wed Nov 1 23:46:59 1995 Andrew Cagney - aka Noid <cagney@highland.com.au> * configure.in, Makefile.in: add --enable-sim-icache=[0-9]* and IGEN_ICACHE macro. -Wed Nov 1 23:46:59 1995 Andrew Cagney - aka Noid <cagney@highland.com.au> +Wed Nov 1 23:46:59 1995 Andrew Cagney <cagney@highland.com.au> * igen.c (main), misc.h (target_a2i, i2target), misc.c: Add functions to convert between target and igen internal bit numbers. @@ -455,17 +631,17 @@ Wed Nov 1 23:46:59 1995 Andrew Cagney - aka Noid <cagney@highland.com.au> bit nr) options to igen. Typical usage would be: ./igen -b 16 -h 15 for a 16 bit instruction format with the msb given a number 15. -Wed Nov 1 22:17:32 1995 Andrew Cagney - aka Noid <cagney@highland.com.au> +Wed Nov 1 22:17:32 1995 Andrew Cagney <cagney@highland.com.au> * dgen.c (main): Was outputting optarg even when it was NULL. -Tue Oct 31 23:48:33 1995 Andrew Cagney - aka Noid <cagney@highland.com.au> +Tue Oct 31 23:48:33 1995 Andrew Cagney <cagney@highland.com.au> * vm_n.h (vm_data_map_load_N, vm_data_map_store_n), debug.h, debug.c: Add tracing of load/store unit (virtual) with -t load-store. -Tue Oct 31 21:44:01 1995 Andrew Cagney - aka Noid <cagney@highland.com.au> +Tue Oct 31 21:44:01 1995 Andrew Cagney <cagney@highland.com.au> * std-config.h (WITH_ENVIRONMENT): Add USER_ENVIRONMENT which does not include things such as the time base and events. @@ -477,7 +653,7 @@ Tue Oct 31 21:44:01 1995 Andrew Cagney - aka Noid <cagney@highland.com.au> /options/environment-architecture with values user, virtual and operating. -Tue Oct 31 21:31:32 1995 Andrew Cagney - aka Noid <cagney@highland.com.au> +Tue Oct 31 21:31:32 1995 Andrew Cagney <cagney@highland.com.au> * ppc-opcode-stupid: Third example of use of opcode table - this one expands all mtspr/mfspr and branch instructions. Appears to diff --git a/sim/ppc/Makefile.in b/sim/ppc/Makefile.in index 48d9452..ccf0ab2 100644 --- a/sim/ppc/Makefile.in +++ b/sim/ppc/Makefile.in @@ -72,6 +72,7 @@ BSWAP_CFLAGS = @sim_bswap@ ENDIAN_CFLAGS = @sim_endian@ HOSTENDIAN_CFLAGS = @sim_hostendian@ SMP_CFLAGS = @sim_smp@ +XOR_ENDIAN_CFLAGS = @sim_xor_endian@ BITSIZE_CFLAGS = @sim_bitsize@ HOSTBITSIZE_CFLAGS = @sim_hostbitsize@ ENV_CFLAGS = @sim_env@ @@ -89,6 +90,7 @@ CONFIG_CFLAGS = $(BSWAP_CFLAGS) \ $(ENDIAN_CFLAGS) \ $(HOSTENDIAN_CFLAGS) \ $(SMP_CFLAGS) \ + $(XOR_ENDIAN_CFLAGS) \ $(BITSIZE_CFLAGS) \ $(HOSTBITSIZE_CFLAGS) \ $(ENV_CFLAGS) \ @@ -281,7 +283,7 @@ psim.o: psim.c psim.h $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC) bits.o: bits.c $(BASICS_H) debug.o: debug.c $(BASICS_H) -filter_filename.o: filter_filename.c config.h ppc-config.h +filter_filename.o: filter_filename.c filter_filename.h config.h ppc-config.h sim-endian.o: sim-endian.c sim-endian-n.h $(BASICS_H) diff --git a/sim/ppc/configure.in b/sim/ppc/configure.in index b2a0ee4..acb0442 100644 --- a/sim/ppc/configure.in +++ b/sim/ppc/configure.in @@ -16,7 +16,7 @@ fi],[sim_cflags=""])dnl AC_ARG_ENABLE(sim-warnings, [ --enable-sim-warnings=opts Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o], [case "${enableval}" in - yes) sim_warnings="-Wall -Wpointer-arith -Wbad-function-cast -Wmissing-prototypes -Wmissing-declarations";; + yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes";; no) sim_warnings="-w";; *) sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;; esac @@ -125,7 +125,7 @@ AC_ARG_ENABLE(sim-inline, [ --enable-sim-inline=inlines Specify which functions should be inlined.], [sim_inline="" case "$enableval" in - no) sim_inline="";; + no) sim_inline="-DDEFAULT_INLINE=0 -DINLINE=";; 0) sim_inline="-DDEFAULT_INLINE=0";; yes | 2) sim_inline="-DDEFAULT_INLINE=2";; 1) sim_inline="-DDEFAULT_INLINE=1";; @@ -198,7 +198,7 @@ fi],[sim_hostendian=""])dnl AC_ARG_ENABLE(sim-smp, [ --enable-sim-smp=n Specify number of processors to configure for.], [case "${enableval}" in - yes) sim_smp="-DWITH_SMP=2";; + yes) sim_smp="-DWITH_SMP=5";; no) sim_smp="-DWITH_SMP=0";; *) sim_smp="-DWITH_SMP=$enableval";; esac @@ -209,6 +209,14 @@ if test x"$silent" != x"yes"; then echo "Setting smp flags = $sim_smp" 6>&1 fi])dnl +AC_ARG_ENABLE(sim-xor-endian, +[ --enable-sim-xor-endian=n Specify number bytes involved in PowerPC XOR bi-endian mode (default 8).], +[case "${enableval}" in + yes) sim_xor_endian="-DWITH_XOR_ENDIAN=8";; + no) sim_xor_endian="-DWITH_XOR_ENDIAN=0";; + *) sim_xor_endian="-DWITH_XOR_ENDIAN=$enableval";; +esac],[sim_xor_endian=""])dnl + AC_ARG_ENABLE(sim-bitsize, [ --enable-sim-bitsize=n Specify target bitsize (32 or 64).], [case "${enableval}" in @@ -377,6 +385,7 @@ AC_SUBST(sim_icache) AC_SUBST(sim_inline) AC_SUBST(sim_bswap) AC_SUBST(sim_endian) +AC_SUBST(sim_xor_endian) AC_SUBST(sim_hostendian) AC_SUBST(sim_smp) AC_SUBST(sim_bitsize) diff --git a/sim/ppc/device_tree.c b/sim/ppc/device_tree.c index 0fb019b..51d828c 100644 --- a/sim/ppc/device_tree.c +++ b/sim/ppc/device_tree.c @@ -464,43 +464,49 @@ device_tree_dump(device_tree *device, /* Parse a device name, various formats */ -#define SCAN_INIT(START, END, COUNT, NAME) \ - char *START = NULL; \ - char *END = strchr(NAME, '@'); \ - int COUNT = 0; \ - if (END == NULL) \ - return 0; \ +#define SCAN_INIT(NAME) \ + char *START = (char*)0; \ + char *END = (char*)0; \ + int COUNT = -1; \ + /* find the first element */ \ + END = strchr(NAME, '@'); \ + if (END == (char*)0) \ + return COUNT; \ + COUNT += 1; \ START = END + 1 -#define SCAN_U(START, END, COUNT, U) \ +#define SCAN_END \ + return COUNT + +#define SCAN_U(U) \ do { \ *U = strtoul(START, &END, 0); \ if (START == END) \ return COUNT; \ - COUNT++; \ + COUNT += 1; \ if (*END != ',') \ return COUNT; \ START = END + 1; \ } while (0) -#define SCAN_P(START, END, COUNT, P) \ +#define SCAN_P(P) \ do { \ - *P = (void*)(unsigned)strtouq(START, &END, 0); \ + *P = (void*)(unsigned)strtouq(START, END, 0); \ if (START == END) \ return COUNT; \ - COUNT++; \ + COUNT += 1; \ if (*END != ',') \ return COUNT; \ START = END + 1; \ } while (0) -#define SCAN_C(START, END, COUNT, C, SIZE) \ +#define SCAN_C(C, SIZE) \ do { \ char *chp = C; \ END = START; \ while (*END != '\0' && *END != ',') { \ if (*END == '\\') \ - END++; \ + END += 1; \ *chp = *END; \ chp += 1; \ END += 1; \ @@ -510,19 +516,55 @@ do { \ *chp = '\0'; \ if (START == END) \ return COUNT; \ - COUNT++; \ + COUNT += 1; \ if (*END != ',') \ return COUNT; \ START = END + 1; \ } while (0) INLINE_DEVICE_TREE int +scand_c(const char *name, + char *c1, + unsigned c1size) +{ + SCAN_INIT(name); + SCAN_C(c1, c1size); + SCAN_END; +} + +INLINE_DEVICE_TREE int +scand_c_uw_u(const char *name, + char *c1, + unsigned c1size, + unsigned_word *uw2, + unsigned *u3) +{ + SCAN_INIT(name); + SCAN_C(c1, c1size); + SCAN_U(uw2); + SCAN_U(u3); + SCAN_END; +} + +INLINE_DEVICE_TREE int scand_uw(const char *name, unsigned_word *uw1) { - SCAN_INIT(start, end, count, name); - SCAN_U(start, end, count, uw1); - return count; + SCAN_INIT(name); + SCAN_U(uw1); + SCAN_END; +} + +INLINE_DEVICE_TREE int +scand_uw_c(const char *name, + unsigned_word *uw1, + char *c2, + unsigned c2size) +{ + SCAN_INIT(name); + SCAN_U(uw1); + SCAN_C(c2, c2size); + SCAN_END; } INLINE_DEVICE_TREE int @@ -530,10 +572,10 @@ scand_uw_u(const char *name, unsigned_word *uw1, unsigned *u2) { - SCAN_INIT(start, end, count, name); - SCAN_U(start, end, count, uw1); - SCAN_U(start, end, count, u2); - return count; + SCAN_INIT(name); + SCAN_U(uw1); + SCAN_U(u2); + SCAN_END; } INLINE_DEVICE_TREE int @@ -542,11 +584,22 @@ scand_uw_u_u(const char *name, unsigned *u2, unsigned *u3) { - SCAN_INIT(start, end, count, name); - SCAN_U(start, end, count, uw1); - SCAN_U(start, end, count, u2); - SCAN_U(start, end, count, u3); - return count; + SCAN_INIT(name); + SCAN_U(uw1); + SCAN_U(u2); + SCAN_U(u3); + SCAN_END; +} + +INLINE_DEVICE_TREE int +scand_uw_uw(const char *name, + unsigned_word *uw1, + unsigned_word *uw2) +{ + SCAN_INIT(name); + SCAN_U(uw1); + SCAN_U(uw2); + SCAN_END; } INLINE_DEVICE_TREE int @@ -555,33 +608,46 @@ scand_uw_uw_u(const char *name, unsigned_word *uw2, unsigned *u3) { - SCAN_INIT(start, end, count, name); - SCAN_U(start, end, count, uw1); - SCAN_U(start, end, count, uw2); - SCAN_U(start, end, count, u3); - return count; + SCAN_INIT(name); + SCAN_U(uw1); + SCAN_U(uw2); + SCAN_U(u3); + SCAN_END; } INLINE_DEVICE_TREE int -scand_c(const char *name, - char *c1, int c1size) +scand_uw_uw_u_u_c(const char *name, + unsigned_word *uw1, + unsigned_word *uw2, + unsigned *u3, + unsigned *u4, + char *c5, + unsigned c5size) { - SCAN_INIT(start, end, count, name); - SCAN_C(start, end, count, c1, c1size); - return count; + SCAN_INIT(name); + SCAN_U(uw1); + SCAN_U(uw2); + SCAN_U(u3); + SCAN_U(u4); + SCAN_C(c5, c5size); + SCAN_END; } INLINE_DEVICE_TREE int -scand_c_uw_u(const char *name, - char *c1, int c1size, - unsigned_word *uw2, - unsigned *u3) +scand_uw_uw_u_u_u(const char *name, + unsigned_word *uw1, + unsigned_word *uw2, + unsigned *u3, + unsigned *u4, + unsigned *u5) { - SCAN_INIT(start, end, count, name); - SCAN_C(start, end, count, c1, c1size); - SCAN_U(start, end, count, uw2); - SCAN_U(start, end, count, u3); - return count; + SCAN_INIT(name); + SCAN_U(uw1); + SCAN_U(uw2); + SCAN_U(u3); + SCAN_U(u4); + SCAN_U(u5); + SCAN_END; } @@ -634,6 +700,43 @@ enum { }; INLINE_DEVICE_TREE char * +printd_c(const char *name, + const char *c1) +{ + int sizeof_buf = (strlen(name) + + strlen("@") + + c_strlen(c1) + + 1); + char *buf = (char*)zalloc(sizeof_buf); + strcpy(buf, name); + strcat(buf, "@"); + c_strcat(buf, c1); + ASSERT(strlen(buf) < sizeof_buf); + return buf; +} + +INLINE_DEVICE_TREE char * +printd_c_uw(const char *name, + const char *c1, + unsigned_word uw2) +{ + int sizeof_buf = (strlen(name) + + strlen("@") + + c_strlen(c1) + + strlen(",") + + strlen_unsigned_word + + 1); + char *buf = (char*)zalloc(sizeof_buf); + strcpy(buf, name); + strcat(buf, "@"); + c_strcat(buf, c1); + strcat(buf, ","); + u_strcat(buf, uw2); + ASSERT(strlen(buf) < sizeof_buf); + return buf; +} + +INLINE_DEVICE_TREE char * printd_uw_u(const char *name, unsigned_word uw1, unsigned u2) @@ -711,41 +814,4 @@ printd_uw_u_u_c(const char *name, return buf; } -INLINE_DEVICE_TREE char * -printd_c(const char *name, - const char *c1) -{ - int sizeof_buf = (strlen(name) - + strlen("@") - + c_strlen(c1) - + 1); - char *buf = (char*)zalloc(sizeof_buf); - strcpy(buf, name); - strcat(buf, "@"); - c_strcat(buf, c1); - ASSERT(strlen(buf) < sizeof_buf); - return buf; -} - -INLINE_DEVICE_TREE char * -printd_c_uw(const char *name, - const char *c1, - unsigned_word uw2) -{ - int sizeof_buf = (strlen(name) - + strlen("@") - + c_strlen(c1) - + strlen(",") - + strlen_unsigned_word - + 1); - char *buf = (char*)zalloc(sizeof_buf); - strcpy(buf, name); - strcat(buf, "@"); - c_strcat(buf, c1); - strcat(buf, ","); - u_strcat(buf, uw2); - ASSERT(strlen(buf) < sizeof_buf); - return buf; -} - #endif /* _DEVICE_TREE_C_ */ diff --git a/sim/ppc/device_tree.h b/sim/ppc/device_tree.h index bcd9bea..765c20e 100644 --- a/sim/ppc/device_tree.h +++ b/sim/ppc/device_tree.h @@ -116,10 +116,28 @@ INLINE_DEVICE_TREE void device_tree_dump u: unsigned c: string */ +INLINE_DEVICE_TREE int scand_c +(const char *name, + char *c1, + unsigned c1size); + +INLINE_DEVICE_TREE int scand_c_uw_u +(const char *name, + char *c1, + unsigned c1size, + unsigned_word *uw2, + unsigned *u3); + INLINE_DEVICE_TREE int scand_uw (const char *name, unsigned_word *uw1); +INLINE_DEVICE_TREE int scand_uw_c +(const char *name, + unsigned_word *uw1, + char *c2, + unsigned c2size); + INLINE_DEVICE_TREE int scand_uw_u (const char *name, unsigned_word *uw1, @@ -131,21 +149,42 @@ INLINE_DEVICE_TREE int scand_uw_u_u unsigned *u2, unsigned *u3); +INLINE_DEVICE_TREE int scand_uw_uw +(const char *name, + unsigned_word *uw1, + unsigned_word *uw2); + INLINE_DEVICE_TREE int scand_uw_uw_u (const char *name, unsigned_word *uw1, unsigned_word *uw2, unsigned *u3); -INLINE_DEVICE_TREE int scand_c +INLINE_DEVICE_TREE int scand_uw_uw_u_u_c (const char *name, - char *c1, int c1size); - -INLINE_DEVICE_TREE int scand_c_uw_u + unsigned_word *uw1, + unsigned_word *uw2, + unsigned *u3, + unsigned *u4, + char *c5, + unsigned c5size); + +INLINE_DEVICE_TREE int scand_uw_uw_u_u_u (const char *name, - char *c1, int c1size, + unsigned_word *uw1, unsigned_word *uw2, - unsigned *u3); + unsigned *u3, + unsigned *u4, + unsigned *u5); + +INLINE_DEVICE_TREE char *printd_c +(const char *name, + const char *c1); + +INLINE_DEVICE_TREE char *printd_c_uw +(const char *name, + const char *c1, + unsigned_word uw2); INLINE_DEVICE_TREE char *printd_uw_u (const char *name, @@ -165,13 +204,4 @@ INLINE_DEVICE_TREE char *printd_uw_u_u_c unsigned u3, const char *c4); -INLINE_DEVICE_TREE char *printd_c -(const char *name, - const char *c1); - -INLINE_DEVICE_TREE char *printd_c_uw -(const char *name, - const char *c1, - unsigned_word uw2); - #endif /* _DEVICE_TREE_H_ */ diff --git a/sim/ppc/devices.c b/sim/ppc/devices.c index 257b8eb..39f6103 100644 --- a/sim/ppc/devices.c +++ b/sim/ppc/devices.c @@ -80,6 +80,47 @@ generic_init_callback(const device *me, } +/* DMA a file into memory */ +STATIC_INLINE_DEVICES int +dma_file(const device *me, + const char *file_name, + unsigned_word addr) +{ + int count; + int inc; + FILE *image; + char buf[1024]; + + /* get it open */ + image = fopen(file_name, "r"); + if (image == NULL) + return -1; + + /* read it in slowly */ + count = 0; + while (1) { + inc = fread(buf, sizeof(buf), 1, image); + if (inc <= 0) + break; + if (me->parent->callback->dma_write_buffer(me->parent, + buf, + 0 /*address-space*/, + addr+count, + inc /*nr-bytes*/, + 1 /*violate ro*/) != inc) { + fclose(image); + return -1; + } + count += inc; + } + + /* close down again */ + fclose(image); + + return count; +} + + /* inimplemented versions of each function */ @@ -319,7 +360,7 @@ pass_device_interrupt(const device *me, -/* Simple console device: console@)x<address>,16 +/* Simple console device: console@<address>,16 Input characters are taken from the keyboard, output characters sent to the terminal. Echoing of characters is not disabled. @@ -423,7 +464,7 @@ console_io_read_buffer_callback(const device *me, } - bzero(dest, nr_bytes); + memset(dest, 0, nr_bytes); *(unsigned_1*)dest = val; return nr_bytes; } @@ -438,7 +479,7 @@ console_io_write_buffer_callback(const device *me, unsigned_word cia) { console_device *console = (console_device*)me->data; - unsigned_1 val = *(unsigned8*)source; + unsigned_1 val = *(unsigned_1*)source; DTRACE_IO_WRITE_BUFFER(console); switch ((int)addr) { @@ -529,7 +570,7 @@ icu_io_read_buffer_callback(const device *me, unsigned_1 val; DTRACE_IO_READ_BUFFER(icu); val = cpu_nr(processor); - bzero(dest, nr_bytes); + memset(dest, 0, nr_bytes); *(unsigned_1*)dest = val; return nr_bytes; } @@ -605,7 +646,7 @@ halt_io_write_buffer_callback(const device *me, unsigned_word cia) { DTRACE_IO_WRITE_BUFFER(halt); - cpu_halt(processor, cia, was_exited, 0); + cpu_halt(processor, cia, was_exited, *(unsigned_1*)source); return 0; } @@ -820,7 +861,7 @@ vm_io_read_buffer_callback(const device *me, { DTRACE_IO_READ_BUFFER(vm); if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) { - bzero(dest, nr_bytes); /* always initialized to zero */ + memset(dest, 0, nr_bytes); /* always initialized to zero */ return nr_bytes; } else @@ -1062,38 +1103,17 @@ file_init_callback(const device *me, psim *system) { unsigned_word addr; - unsigned count; - char *file_name; - char buf; - FILE *image; + int count; + char file_name[1024]; DTRACE_INIT(file); - if ((file_name = strchr(me->name, ',')) == NULL - || scand_uw(me->name, &addr) != 1) - error("file_init_callback() invalid file device %s\n", me->name); - - /* open the file to load */ - file_name++; /* skip the `,' */ - image = fopen(file_name, "r"); - if (image == NULL) - error("file_init_callback() file open failed for %s\n", me->name); - - /* read it in slowly */ - count = 0; - while (fread(&buf, 1, 1, image) > 0) { - if (me->parent->callback->dma_write_buffer(me->parent, - &buf, - 0 /*address-space*/, - addr+count, - 1 /*nr-bytes*/, - 1 /*violate ro*/) != 1) - error("file_init_callback() failed to write to address 0x%x, offset %d\n", - addr+count, count); - count++; - } - - /* close down again */ - fclose(image); + if (scand_uw_c(me->name, &addr, file_name, sizeof(file_name)) != 2) + error("devices/file - Usage: file@<address>,<file-name>\n"); + + /* load the file */ + count = dma_file(me, file_name, addr); + if (count < 0) + error("devices/%s - Problem loading file %s\n", me->name, file_name); } @@ -1114,8 +1134,9 @@ static device_callbacks const file_callbacks = { -/* HTAB: htab@0x<address>,<nr_bytes> - PTE: pte@0x<effective-address>,0x<real-address>,<nr_bytes> +/* HTAB: htab@<address>,<nr_bytes> + PTE: pte@<virtual-address>,<real-address>,<wimg>,<pp>,<nr_bytes> + PTE: pte@<virtual-address>,<real-address>,<wimg>,<pp>,<file> HTAB defines the location (in physical memory) of a HASH table. PTE (as a child of HTAB) defines a mapping that is to be entered @@ -1131,22 +1152,115 @@ htab_init_callback(const device *me, psim *system) { DTRACE_INIT(htab); + if (WITH_TARGET_WORD_BITSIZE != 32) + error("devices/htab: only 32bit targets currently suported\n"); /* only the pte does work */ if (strncmp(me->name, "pte@", strlen("pte@")) == 0) { - unsigned_word htab_ra; + unsigned32 htab_ra; unsigned htab_nr_bytes; - unsigned_word pte_ea; - unsigned_word pte_ra; + signed32 pte_va; /* so that 0xff...0 is make 0xffffff00 */ + unsigned32 pte_ra; unsigned pte_nr_bytes; + unsigned pte_wimg; + unsigned pte_pp; + unsigned32 ra; + unsigned64 va; + unsigned32 htaborg; + unsigned32 htabmask; + unsigned32 n; + /* determine the location/size of the hash table */ + if (me->parent == NULL + || strncmp(me->parent->name, "htab@", strlen("htab@")) != 0) + error("devices/%s - Parent is not a htab device\n", me->name); if (scand_uw_u(me->parent->name, &htab_ra, &htab_nr_bytes) != 2) - error("htab_init_callback() htab entry %s invalid\n", + error("devices/%s - Usage: htab@<real-addr>,<nr_bytes>\n", me->parent->name); + htabmask = EXTRACTED32(htab_nr_bytes - 1, 7, 15); + for (n = htab_nr_bytes; n > 1; n = n / 2) { + if (n % 2 != 0) + error("devices/%s - htabmask 0x%x (size 0x%x) not a power of two\n", + me->parent->name, htabmask, htab_nr_bytes); + } + htaborg = htab_ra; + if ((htaborg & INSERTED32(htabmask, 7, 15)) != 0) { + error("devices/%s - htaborg 0x%x not aligned to htabmask 0x%x\n", + me->parent->name, htaborg, htabmask); + } + /* determine the location/size of the mapping */ - if (scand_uw_uw_u(me->name, &pte_ea, &pte_ra, &pte_nr_bytes) != 3) - error("htab_init_callback() pte entry %s invalid\n", me->name); - error("Map ea=0x%x, ra=0x%x, nr_bytes=%d using htab=0x%x, nr_bytes=%d\n", - pte_ea, pte_ra, pte_nr_bytes, htab_ra, htab_nr_bytes); + if (scand_uw_uw_u_u_u(me->name, &pte_va, &pte_ra, + &pte_wimg, &pte_pp, &pte_nr_bytes) != 5) { + int nr_bytes; + char file_name[1024]; + if (scand_uw_uw_u_u_c(me->name, &pte_va, &pte_ra, &pte_wimg, &pte_pp, + file_name, sizeof(file_name)) != 5) + error("devices/%s - Usage: %s\nor\t%s\n", + me->name, + "pte@<virtual-addr>,<real-addr>,<wimg>,<pp>,<nr-bytes>", + "pte@<virtual-addr>,<real-addr>,<wimg>,<pp>,<file>"); + /* load/validate it */ + nr_bytes = dma_file(me, file_name, pte_ra); + if (nr_bytes < 0) + error("devices/%s - problem loading file %s\n", me->name, file_name); + pte_nr_bytes = nr_bytes; + } + + /* go through all pages and create a pte for each */ + for (ra = pte_ra, va = (signed32)pte_va; + ra < pte_ra + pte_nr_bytes; + ra += 1024, va += 1024) { + unsigned64 vpn = va << 12; + unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23); + unsigned32 page = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15); + unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23) + ^ EXTRACTED32(page, 0, 15), + 0, 18); + int h; + for (h = 0; h < 2; h++) { + unsigned32 pteg = (htaborg + | INSERTED32(EXTRACTED32(hash, 0, 8) & htabmask, 7, 15) + | INSERTED32(EXTRACTED32(hash, 9, 18), 16, 25)); + int pti; + for (pti = 0; pti < 8; pti++, pteg += 8) { + unsigned32 pte0; + if (me->parent->callback->dma_read_buffer(me->parent, + &pte0, + 0, /*space*/ + pteg, + sizeof(pte0)) != 4) + error("htab_init_callback() failed to read a pte at 0x%x\n", + pteg); + if (!MASKED32(pte0, 0, 0)) { + /* empty pte fill it */ + unsigned32 pte0 = (MASK32(0, 0) + | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24) + | INSERTED32(h, 25, 25) + | INSERTED32(EXTRACTED32(page, 0, 5), 26, 31)); + unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19) + | INSERTED32(pte_wimg, 25, 28) + | INSERTED32(pte_pp, 30, 31)); + if (me->parent->callback->dma_write_buffer(me->parent, + &pte0, + 0, /*space*/ + pteg, + sizeof(pte0), + 1/*ro?*/) != 4 + || me->parent->callback->dma_write_buffer(me->parent, + &pte1, + 0, /*space*/ + pteg + 4, + sizeof(pte1), + 1/*ro?*/) != 4) + error("htab_init_callback() failed to write a pte a 0x%x\n", + pteg); + return; + } + } + /* re-hash */ + hash = MASKED32(~hash, 0, 18); + } + } } } @@ -1194,7 +1308,7 @@ static device_callbacks const sim_callbacks = { -/* Load device: *binary@<file-name> +/* Load device: binary@<file-name> Assuming that <file-name> is an executable file understood by BFD, this device loads or maps the relevant text/data segments into @@ -1281,20 +1395,19 @@ STATIC_INLINE_DEVICES void binary_init_callback(const device *me, psim *system) { - char file_name[100]; + char file_name[1024]; bfd *image; DTRACE_INIT(binary); /* get a file name */ if (scand_c(me->name, file_name, sizeof(file_name)) != 1) - error("load_binary_init_callback() invalid load-binary device %s\n", - me->name); + error("devices/binary - Usage: binary@<file-name>\n"); /* open the file */ image = bfd_openr(file_name, NULL); if (image == NULL) { - bfd_perror("open failed:"); - error("nothing loaded\n"); + bfd_perror("devices/binary"); + error("devices/%s - the file %s not loaded\n", me->name, file_name); } /* check it is valid */ diff --git a/sim/ppc/igen.c b/sim/ppc/igen.c index c1ec541..4eb2310 100644 --- a/sim/ppc/igen.c +++ b/sim/ppc/igen.c @@ -513,16 +513,6 @@ struct _opcode_field { opcode_field *parent; }; -static opcode_field * -opcode_field_new(void) -{ - opcode_field *new_field = (opcode_field*)zalloc(sizeof(opcode_field)); - ASSERT(new_field != NULL); - new_field->first = insn_size; - new_field->last = -1; - return new_field; -} - static void dump_opcode_field(opcode_field *field, int indent, int levels) { @@ -575,7 +565,7 @@ typedef enum { insn_format, insn_form, insn_flags, - insn_nmemonic, + insn_mnemonic, insn_name, insn_comment, nr_insn_table_fields @@ -588,7 +578,8 @@ typedef enum { } function_table_fields; typedef enum { - model_name = insn_nmemonic, + model_default = insn_form, + model_name = insn_mnemonic, model_identifer = insn_name, model_func = insn_comment, } model_table_fields; @@ -654,6 +645,12 @@ static insn *last_model_macro; static insn *model_functions; static insn *last_model_function; +static insn *model_internal; +static insn *last_model_internal; + +static insn *model_data; +static insn *last_model_data; + static void insn_table_insert_function(insn_table *table, table_entry *file_entry) @@ -670,159 +667,6 @@ insn_table_insert_function(insn_table *table, table->last_function = new_function; } - -static void -model_table_insert(insn_table *table, - table_entry *file_entry) -{ - /* create a new model */ - model *new_model = ZALLOC(model); - model_func_unit *func_unit; - char *ptr, *end, *end_name, *comment, *name; - int ch; - int name_len; - int func_name_len; - unsigned unit, mask; - int number; - - new_model->name = file_entry->fields[model_identifer]; - new_model->printable_name = file_entry->fields[model_name]; - name_len = strlen(new_model->name); - - /* append it to the end of the model list */ - if (last_model) - last_model->next = new_model; - else - models = new_model; - last_model = new_model; - - /* Parse the function units separated by commas */ - unit = 1; - for (ptr = file_entry->fields[model_func]; - ((ch = *ptr) != '\0') && (ch != '\n'); - ptr = (*end == ',') ? end+1 : end) { - - while (ch == ' ' || ch == '\t') - ch = *++ptr; - - if (!ch || ch == '\n') - break; - - /* Search for comma or newline ending field */ - end = ptr; - end_name = (char *)0; - - if (ch == ',') - continue; - - while (ch != '\0' && ch != ',' && ch != '\n') { - if (end_name == (char *)0 && (ch == '=' || isspace(ch))) - end_name = end; - - ch = *++end; - } - if (!end_name) - end_name = end; - - func_unit = ZALLOC(model_func_unit); - if (new_model->func_unit_end) - new_model->func_unit_end->next = func_unit; - else - new_model->func_unit_start = func_unit; - - new_model->func_unit_end = func_unit; - - /* Record function unit name as model name _ unit name */ - func_name_len = name_len + end_name - ptr + 2; - if (table->max_func_unit_name_len < func_name_len) - table->max_func_unit_name_len = func_name_len; - - func_unit->name = name = (char *)zalloc(func_name_len); - memcpy(name, new_model->name, name_len); - name[name_len] = '_'; - memcpy(name + name_len + 1, ptr, end_name - ptr); - - /* See if there are multiple functional units */ - if (*end_name == '=') { - number = 0; - for(end_name++; end_name < end && isdigit(*end_name); end_name++) - number = number * 10 + (*end_name - '0'); - } else { - number = 1; - } - - /* Now figure out the mask for these unit(s) */ - func_unit->number = number; - mask = 0; - while (number--) { - ASSERT(unit != 0); - mask |= unit; - unit <<= 1; - } - func_unit->mask = mask; - table->max_func_unit_mask |= mask; - - /* Now figure out comments */ - for (comment = end_name; comment < end && ((ch = *comment) == ' ' || ch == '\t'); comment++) - ; - - if (comment < end) { - func_unit->comment = (char *)zalloc(end - comment + 1); - memcpy(func_unit->comment, comment, end - comment); - } - } - - /* Add an 'sentinel' function unit at the end to simpify the loop */ - func_unit = ZALLOC(model_func_unit); - if (new_model->func_unit_end) - new_model->func_unit_end->next = func_unit; - else - new_model->func_unit_start = func_unit; - - new_model->func_unit_end = func_unit; - - /* Record function unit name as model name _ unit name */ - func_name_len = name_len + sizeof("_SENTINEL"); - if (table->max_func_unit_name_len < func_name_len) - table->max_func_unit_name_len = func_name_len; - - func_unit->name = name = (char *)zalloc(func_name_len); - func_unit->number = 0; - func_unit->mask = unit; - func_unit->comment = "dummy"; - table->max_func_unit_mask |= unit; - - memcpy(name, new_model->name, name_len); - strcpy(name + name_len, "_SENTINEL"); -} - -static void -model_table_insert_macro(insn_table *table, - table_entry *file_entry) -{ - insn *macro = ZALLOC(insn); - macro->file_entry = file_entry; - if (last_model_macro) - last_model_macro->next = macro; - else - model_macros = macro; - last_model_macro = macro; -} - -static void -model_table_insert_function(insn_table *table, - table_entry *file_entry) -{ - insn *func = ZALLOC(insn); - func->file_entry = file_entry; - if (last_model_function) - last_model_function->next = func; - else - model_functions = func; - last_model_function = func; -} - - static void insn_table_insert_insn(insn_table *table, table_entry *file_entry, @@ -877,11 +721,12 @@ insn_table_find_opcode_field(insn *insns, opcode_rules *rule, int string_only) { - opcode_field *curr_opcode = opcode_field_new(); + opcode_field *curr_opcode = ZALLOC(opcode_field); insn *entry; - ASSERT(rule); + curr_opcode->first = insn_size; + curr_opcode->last = -1; for (entry = insns; entry != NULL; entry = entry->next) { insn_fields *fields = entry->fields; opcode_field new_opcode; @@ -1121,6 +966,147 @@ insn_table_expand_insns(insn_table *table) } +static void +model_table_insert(insn_table *table, + table_entry *file_entry) +{ + /* create a new model */ + model *new_model = ZALLOC(model); + model_func_unit *func_unit; + char *ptr, *end, *end_name, *comment, *name; + int ch; + int name_len; + int func_name_len; + unsigned unit, mask; + int number; + + new_model->name = file_entry->fields[model_identifer]; + new_model->printable_name = file_entry->fields[model_name]; + name_len = strlen(new_model->name); + + /* append it to the end of the model list */ + if (last_model) + last_model->next = new_model; + else + models = new_model; + last_model = new_model; + + /* Parse the function units separated by commas */ + unit = 1; + for (ptr = file_entry->fields[model_func]; + ((ch = *ptr) != '\0') && (ch != '\n'); + ptr = (*end == ',') ? end+1 : end) { + + while (ch == ' ' || ch == '\t') + ch = *++ptr; + + if (!ch || ch == '\n') + break; + + /* Search for comma or newline ending field */ + end = ptr; + end_name = (char *)0; + + if (ch == ',') + continue; + + while (ch != '\0' && ch != ',' && ch != '\n') { + if (end_name == (char *)0 && (ch == '=' || isspace(ch))) + end_name = end; + + ch = *++end; + } + if (!end_name) + end_name = end; + + func_unit = ZALLOC(model_func_unit); + if (new_model->func_unit_end) + new_model->func_unit_end->next = func_unit; + else + new_model->func_unit_start = func_unit; + + new_model->func_unit_end = func_unit; + + /* Record function unit name as model name _ unit name */ + func_name_len = name_len + end_name - ptr + 2; + if (table->max_func_unit_name_len < func_name_len) + table->max_func_unit_name_len = func_name_len; + + func_unit->name = name = (char *)zalloc(func_name_len); + memcpy(name, new_model->name, name_len); + name[name_len] = '_'; + memcpy(name + name_len + 1, ptr, end_name - ptr); + + /* See if there are multiple functional units */ + if (*end_name == '=') { + number = 0; + for(end_name++; end_name < end && isdigit(*end_name); end_name++) + number = number * 10 + (*end_name - '0'); + } else { + number = 1; + } + + /* Now figure out the mask for these unit(s) */ + func_unit->number = number; + mask = 0; + while (number--) { + ASSERT(unit != 0); + mask |= unit; + unit <<= 1; + } + func_unit->mask = mask; + table->max_func_unit_mask |= mask; + + /* Now figure out comments */ + for (comment = end_name; comment < end && ((ch = *comment) == ' ' || ch == '\t'); comment++) + ; + + if (comment < end) { + func_unit->comment = (char *)zalloc(end - comment + 1); + memcpy(func_unit->comment, comment, end - comment); + } + } + + /* Add an 'sentinel' function unit at the end to simpify the loop */ + func_unit = ZALLOC(model_func_unit); + if (new_model->func_unit_end) + new_model->func_unit_end->next = func_unit; + else + new_model->func_unit_start = func_unit; + + new_model->func_unit_end = func_unit; + + /* Record function unit name as model name _ unit name */ + func_name_len = name_len + sizeof("_SENTINEL"); + if (table->max_func_unit_name_len < func_name_len) + table->max_func_unit_name_len = func_name_len; + + func_unit->name = name = (char *)zalloc(func_name_len); + func_unit->number = 0; + func_unit->mask = unit; + func_unit->comment = "dummy"; + table->max_func_unit_mask |= unit; + + memcpy(name, new_model->name, name_len); + strcpy(name + name_len, "_SENTINEL"); +} + +static void +model_table_insert_specific(insn_table *table, + table_entry *file_entry, + insn **start_ptr, + insn **end_ptr) +{ + insn *ptr = ZALLOC(insn); + ptr->file_entry = file_entry; + if (*end_ptr) + (*end_ptr)->next = ptr; + else + (*start_ptr) = ptr; + (*end_ptr) = ptr; +} + + static insn_table * insn_table_load_insns(char *file_name) @@ -1139,10 +1125,16 @@ insn_table_load_insns(char *file_name) model_table_insert(table, file_entry); } else if (it_is("model-macro", file_entry->fields[insn_flags])) { - model_table_insert_macro(table, file_entry); + model_table_insert_specific(table, file_entry, &model_macros, &last_model_macro); } else if (it_is("model-function", file_entry->fields[insn_flags])) { - model_table_insert_function(table, file_entry); + model_table_insert_specific(table, file_entry, &model_functions, &last_model_function); + } + else if (it_is("model-internal", file_entry->fields[insn_flags])) { + model_table_insert_specific(table, file_entry, &model_internal, &last_model_internal); + } + else if (it_is("model-data", file_entry->fields[insn_flags])) { + model_table_insert_specific(table, file_entry, &model_data, &last_model_data); } else { insn_fields *fields; @@ -1367,6 +1359,7 @@ lf_print_idecode_table(lf *file, lf_printf(file, "while (1) {\n"); lf_indent(file, +2); { + lf_printf(file, "/* nonzero mask -> another table */\n"); lf_printf(file, "while (table_entry->mask != 0) {\n"); lf_indent(file, +2); { @@ -1378,24 +1371,26 @@ lf_print_idecode_table(lf *file, } lf_indent(file, -2); lf_printf(file, "}\n"); - if (!idecode_cache && can_assume_leaf) { - lf_printf(file, "return (((idecode_semantic*)\n"); - lf_printf(file, " table_entry->function_or_table)\n"); - lf_printf(file, " (%s));\n", semantic_actual); + lf_printf(file, "ASSERT(table_entry->mask == 0);\n"); + if (can_assume_leaf) + lf_printf(file, "ASSERT(table_entry->shift == 0);\n"); + else { + lf_printf(file, "if (table_entry->shift == 0)\n"); + lf_indent(file, +2); } - else if (!idecode_cache && !can_assume_leaf) { - lf_printf(file, "if (table_entry->shift == 0)"); - lf_printf(file, " return (((idecode_semantic*)\n"); - lf_printf(file, " table_entry->function_or_table)\n"); - lf_printf(file, " (%s));\n", semantic_actual); + if (idecode_cache) { + lf_printf(file, "return (((idecode_crack*)\n"); + lf_printf(file, " table_entry->function_or_table)\n"); + lf_printf(file, " (%s));\n", cache_idecode_actual); } else { - lf_printf(file, "if (table_entry->shift == 0)\n"); - lf_printf(file, " return (((idecode_crack*)\n"); - lf_printf(file, " table_entry->function_or_table)\n"); - lf_printf(file, " (%s));\n", cache_idecode_actual); + lf_printf(file, "return (((idecode_semantic*)\n"); + lf_printf(file, " table_entry->function_or_table)\n"); + lf_printf(file, " (%s));\n", semantic_actual); } if (!can_assume_leaf) { + lf_indent(file, -2); + lf_printf(file, "/* must be a boolean */\n"); lf_printf(file, "opcode = (instruction & table_entry->shift) != 0;\n"); lf_printf(file, "table = ((idecode_table_entry*)\n"); lf_printf(file, " table_entry->function_or_table);\n"); @@ -1616,9 +1611,11 @@ dump_traverse(insn_table *table) static void -semantics_h_print_function(lf *file, - char *basename, - insn_bits *expanded_bits) +lf_print_semantic_function_header(lf *file, + char *basename, + insn_bits *expanded_bits, + int is_function_definition, + int is_inline_function) { lf_printf(file, "\n"); lf_printf(file, "STATIC_SEMANTICS unsigned_word "); @@ -1626,8 +1623,11 @@ semantics_h_print_function(lf *file, basename, expanded_bits, function_name_prefix_semantics); - lf_printf(file, "\n(%s);\n", + lf_printf(file, "\n(%s)", (idecode_cache ? cache_semantic_formal : semantic_formal)); + if (!is_function_definition) + lf_printf(file, ";"); + lf_printf(file, "\n"); } @@ -1638,9 +1638,11 @@ semantics_h_leaf(insn_table *entry, { lf *file = (lf*)data; ASSERT(entry->nr_insn == 1); - semantics_h_print_function(file, - entry->insns->file_entry->fields[insn_name], - entry->expanded_bits); + lf_print_semantic_function_header(file, + entry->insns->file_entry->fields[insn_name], + entry->expanded_bits, + 0/* isnt function definition*/, + !idecode_cache && entry->parent->opcode_rule->use_switch); } static void @@ -1649,9 +1651,11 @@ semantics_h_insn(insn_table *entry, insn *instruction) { lf *file = (lf*)data; - semantics_h_print_function(file, - instruction->file_entry->fields[insn_name], - NULL); + lf_print_semantic_function_header(file, + instruction->file_entry->fields[insn_name], + NULL, + 0/*isnt function definition*/, + 0/*isnt inline function*/); } static void @@ -1662,9 +1666,11 @@ semantics_h_function(insn_table *entry, lf *file = (lf*)data; if (function->fields[function_type] == NULL || function->fields[function_type][0] == '\0') { - semantics_h_print_function(file, - function->fields[function_name], - NULL); + lf_print_semantic_function_header(file, + function->fields[function_name], + NULL, + 0/*isnt function definition*/, + 1/*is inline function*/); } else { lf_printf(file, "\n"); @@ -2280,13 +2286,16 @@ static void lf_print_c_semantic_function(lf *file, insn *instruction, insn_bits *expanded_bits, - opcode_field *opcodes) + opcode_field *opcodes, + int is_inline_function) { /* build the semantic routine to execute the instruction */ - lf_print_c_semantic_function_header(file, - instruction->file_entry->fields[insn_name], - expanded_bits); + lf_print_semantic_function_header(file, + instruction->file_entry->fields[insn_name], + expanded_bits, + 1/*is-function-definition*/, + is_inline_function); lf_print_c_semantic(file, instruction, expanded_bits, @@ -2307,7 +2316,8 @@ semantics_c_leaf(insn_table *entry, lf_print_c_semantic_function(file, entry->insns, entry->expanded_bits, - entry->parent->opcode); + entry->parent->opcode, + !idecode_cache && entry->parent->opcode_rule->use_switch); } static void @@ -2317,7 +2327,8 @@ semantics_c_insn(insn_table *table, { lf *file = (lf*)data; lf_print_c_semantic_function(file, instruction, - NULL, NULL); + NULL, NULL, + 0/*isnt_inline_function*/); } static void @@ -2328,9 +2339,11 @@ semantics_c_function(insn_table *table, lf *file = (lf*)data; if (function->fields[function_type] == NULL || function->fields[function_type][0] == '\0') { - lf_print_c_semantic_function_header(file, - function->fields[function_name], - NULL); + lf_print_semantic_function_header(file, + function->fields[function_name], + NULL, + 1/*is function definition*/, + 1/*is inline function*/); } else { lf_printf(file, "\n"); @@ -2468,7 +2481,7 @@ idecode_table_leaf(insn_table *entry, } else if (entry->opcode_rule->use_switch) { /* table calling switch statement */ - lf_printf(file, " /*%d*/ { -1, 0, ", + lf_printf(file, " /*%d*/ { 0, 0, ", entry->opcode_nr); lf_print_table_name(file, entry); lf_printf(file, " },\n"); @@ -2552,8 +2565,13 @@ idecode_switch_leaf(insn_table *entry, ASSERT(entry->parent != NULL); ASSERT(depth == 0); ASSERT(entry->parent->opcode_rule->use_switch); + ASSERT(entry->parent->opcode); - lf_printf(file, "case %d:\n", entry->opcode_nr); + if (!entry->parent->opcode->is_boolean + || entry->opcode_nr == 0) + lf_printf(file, "case %d:\n", entry->opcode_nr); + else + lf_printf(file, "default:\n"); lf_indent(file, +2); { if (entry->opcode == NULL) { @@ -2575,8 +2593,7 @@ idecode_switch_leaf(insn_table *entry, lf_print_idecode_switch(file, entry); } else { - /* switch calling table */ - lf_printf(file, "return "); + /* switch looking up a table */ lf_print_idecode_table(file, entry); } lf_printf(file, "break;\n"); @@ -2602,8 +2619,10 @@ idecode_switch_end(insn_table *table, lf *file = (lf*)data; ASSERT(depth == 0); ASSERT(table->opcode_rule->use_switch); + ASSERT(table->opcode); - if (table->opcode_rule->use_switch == 1) { + if (table->opcode_rule->use_switch == 1 + && !table->opcode->is_boolean) { lf_printf(file, "default:\n"); lf_print_idecode_switch_illegal(file); } @@ -2643,6 +2662,47 @@ lf_print_idecode_switch(lf *file, static void +lf_print_idecode_switch_function_header(lf *file, + insn_table *table, + int is_function_definition) +{ + lf_printf(file, "\n"); + lf_printf(file, "static "); + if (idecode_cache) + lf_printf(file, "idecode_semantic *"); + else + lf_printf(file, "unsigned_word"); + if (is_function_definition) + lf_printf(file, "\n"); + else + lf_printf(file, " "); + lf_print_table_name(file, table); + lf_printf(file, "\n(%s)", + (idecode_cache ? cache_idecode_formal : semantic_formal)); + if (!is_function_definition) + lf_printf(file, ";"); + lf_printf(file, "\n"); +} + + +static void +idecode_declare_if_switch(insn_table *table, + void *data, + int depth) +{ + lf *file = (lf*)data; + + if (table->opcode_rule->use_switch + && table->parent != NULL /* don't declare the top one yet */ + && !table->parent->opcode_rule->use_switch) { + lf_print_idecode_switch_function_header(file, + table, + 0/*isnt function definition*/); + } +} + + +static void idecode_expand_if_switch(insn_table *table, void *data, int depth) @@ -2652,11 +2712,9 @@ idecode_expand_if_switch(insn_table *table, if (table->opcode_rule->use_switch && table->parent != NULL /* don't expand the top one yet */ && !table->parent->opcode_rule->use_switch) { - lf_printf(file, "\n"); - lf_printf(file, "STATIC_INLINE_IDECODE void\n"); - lf_print_table_name(file, table); - lf_printf(file, "\n(%s)\n", - (idecode_cache ? cache_idecode_formal : semantic_formal)); + lf_print_idecode_switch_function_header(file, + table, + 1/*is function definition*/); lf_printf(file, "{\n"); { lf_indent(file, +2); @@ -2672,7 +2730,8 @@ static void lf_print_c_cracker_function(lf *file, insn *instruction, insn_bits *expanded_bits, - opcode_field *opcodes) + opcode_field *opcodes, + int is_inline_function) { /* if needed, generate code to enter this routine into a cache */ lf_printf(file, "\n"); @@ -2698,11 +2757,13 @@ idecode_crack_leaf(insn_table *entry, ASSERT(entry->nr_insn == 1 && entry->opcode == NULL && entry->parent != NULL - && entry->parent->opcode != NULL); + && entry->parent->opcode != NULL + && entry->parent->opcode_rule != NULL); lf_print_c_cracker_function(file, entry->insns, entry->expanded_bits, - entry->opcode); + entry->opcode, + entry->parent->opcode_rule->use_switch); } static void @@ -2714,7 +2775,8 @@ idecode_crack_insn(insn_table *entry, lf_print_c_cracker_function(file, instruction, NULL, - NULL); + NULL, + 0/*isnt inline function*/); } static void @@ -2812,6 +2874,12 @@ gen_idecode_c(insn_table *table, lf *file) idecode_crack_insn); } + /* output switch function declarations where needed by tables */ + insn_table_traverse_tree(table, + file, + 1, + idecode_declare_if_switch, /* START */ + NULL, NULL, NULL); /* output tables where needed */ for (depth = insn_table_depth(table); @@ -2850,7 +2918,7 @@ gen_idecode_c(insn_table *table, lf *file) lf_indent(file, -2); lf_printf(file, "}\n"); lf_printf(file, "\n"); - lf_printf(file, "#endif\n"); + lf_printf(file, "#endif /* _IDECODE_C_ */\n"); } @@ -2901,7 +2969,7 @@ gen_itable_h(insn_table *table, lf *file) lf_printf(file, " char *format;\n"); lf_printf(file, " char *form;\n"); lf_printf(file, " char *flags;\n"); - lf_printf(file, " char *nmemonic;\n"); + lf_printf(file, " char *mnemonic;\n"); lf_printf(file, " char *name;\n"); lf_printf(file, "} itable_info;\n"); lf_printf(file, "\n"); @@ -2930,7 +2998,7 @@ itable_c_insn(insn_table *entry, lf_printf(file, " \"%s\",\n", fields[insn_format]); lf_printf(file, " \"%s\",\n", fields[insn_form]); lf_printf(file, " \"%s\",\n", fields[insn_flags]); - lf_printf(file, " \"%s\",\n", fields[insn_nmemonic]); + lf_printf(file, " \"%s\",\n", fields[insn_mnemonic]); lf_printf(file, " \"%s\",\n", fields[insn_name]); lf_printf(file, " },\n"); } @@ -2967,23 +3035,37 @@ gen_itable_c(insn_table *table, lf *file) /****************************************************************/ static void -model_h_function(insn_table *entry, - lf *file, - table_entry *function) +model_c_or_h_data(insn_table *table, + lf *file, + table_entry *data) +{ + if (data->annex) { + table_entry_lf_c_line_nr(file, data); + lf_print_c_code(file, data->annex); + lf_print_lf_c_line_nr(file); + lf_printf(file, "\n"); + } +} + +static void +model_c_or_h_function(insn_table *entry, + lf *file, + table_entry *function, + char *prefix) { if (function->fields[function_type] == NULL || function->fields[function_type][0] == '\0') { - semantics_h_print_function(file, - function->fields[function_name], - NULL); + error("Model function type not specified for %s", function->fields[function_name]); } else { lf_printf(file, "\n"); - lf_printf(file, "INLINE_MODEL %s %s\n(%s);\n", + lf_printf(file, "%s %s %s\n(%s);\n", + prefix, function->fields[function_type], function->fields[function_name], function->fields[function_param]); } + lf_printf(file, "\n"); } static void @@ -3001,10 +3083,8 @@ gen_model_h(insn_table *table, lf *file) lf_printf(file, "#define _MODEL_H_\n"); lf_printf(file, "\n"); - if (model_macros) { - for(macro = model_macros; macro; macro = macro->next) - lf_printf(file, "%s\n", macro->file_entry->fields[insn_comment]); - lf_printf(file, "\n"); + for(macro = model_macros; macro; macro = macro->next) { + model_c_or_h_data(table, file, insn_ptr->file_entry); } lf_printf(file, "#ifndef INLINE_MODEL\n"); @@ -3090,7 +3170,7 @@ gen_model_h(insn_table *table, lf *file) lf_printf(file, "(const char *name);\n"); for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) { - model_h_function(table, file, insn_ptr->file_entry); + model_c_or_h_function(table, file, insn_ptr->file_entry, "INLINE_MODEL"); lf_printf(file, "\n"); } @@ -3100,8 +3180,8 @@ gen_model_h(insn_table *table, lf *file) /****************************************************************/ -typedef struct _model_c_data model_c_data; -struct _model_c_data { +typedef struct _model_c_passed_data model_c_passed_data; +struct _model_c_passed_data { lf *file; model *model_ptr; }; @@ -3111,7 +3191,7 @@ model_c_insn(insn_table *entry, void *data, insn *instruction) { - model_c_data *data_ptr = (model_c_data *)data; + model_c_passed_data *data_ptr = (model_c_passed_data *)data; lf *file = data_ptr->file; char *current_name = data_ptr->model_ptr->name; table_model_entry *model_ptr = instruction->file_entry->model_first; @@ -3123,7 +3203,7 @@ model_c_insn(insn_table *entry, for(i = insn_model_unit; i < nr_insn_model_table_fields; i++) { lf_printf(file, " %s,", model_ptr->fields[i]); } - lf_printf(file, " },\n"); + lf_printf(file, " }, /* %s */\n", instruction->file_entry->fields[insn_name]); return; } @@ -3136,17 +3216,17 @@ model_c_insn(insn_table *entry, static void model_c_function(insn_table *table, lf *file, - table_entry *function) + table_entry *function, + const char *prefix) { if (function->fields[function_type] == NULL || function->fields[function_type][0] == '\0') { - lf_print_c_semantic_function_header(file, - function->fields[function_name], - NULL); + error("Model function return type not specified for %s", function->fields[function_name]); } else { lf_printf(file, "\n"); - lf_printf(file, "INLINE_MODEL %s\n%s(%s)\n", + lf_printf(file, "%s %s\n%s(%s)\n", + prefix, function->fields[function_type], function->fields[function_name], function->fields[function_param]); @@ -3160,6 +3240,7 @@ model_c_function(insn_table *table, } lf_printf(file, "}\n"); lf_print_lf_c_line_nr(file); + lf_printf(file, "\n"); } static void @@ -3178,6 +3259,14 @@ gen_model_c(insn_table *table, lf *file) lf_printf(file, "#include \"cpu.h\"\n"); lf_printf(file, "\n"); + for(insn_ptr = model_data; insn_ptr; insn_ptr = insn_ptr->next) { + model_c_or_h_data(table, file, insn_ptr->file_entry); + } + + for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) { + model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL"); + } + lf_printf(file, "/* map model enumeration into printable string */\n"); lf_printf(file, "const char *model_name[ (int)nr_models ] = {\n"); lf_printf(file, " \"NONE\",\n"); @@ -3230,7 +3319,7 @@ gen_model_c(insn_table *table, lf *file) lf_printf(file, "/* Insn functional unit info */\n"); for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) { - model_c_data data; + model_c_passed_data data; lf_printf(file, "static const model_time model_time_%s[] = {\n", model_ptr->name); data.file = file; @@ -3252,9 +3341,12 @@ gen_model_c(insn_table *table, lf *file) lf_printf(file, "};\n"); lf_printf(file, "\n"); + for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) { + model_c_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL"); + } + for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) { - model_c_function(table, file, insn_ptr->file_entry); - lf_printf(file, "\n"); + model_c_function(table, file, insn_ptr->file_entry, "INLINE_MODEL"); } lf_printf(file, "INLINE_MODEL void\n"); diff --git a/sim/ppc/main.c b/sim/ppc/main.c index 0b3ad07..8df9276 100644 --- a/sim/ppc/main.c +++ b/sim/ppc/main.c @@ -73,7 +73,7 @@ zalloc(long size) void *memory = malloc(size); if (memory == NULL) error("zmalloc failed\n"); - bzero(memory, size); + memset(memory, 0, size); return memory; } |