Index: include/gdb/sim-lm32.h =================================================================== RCS file: include/gdb/sim-lm32.h diff -N include/gdb/sim-lm32.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ include/gdb/sim-lm32.h 15 Apr 2009 17:41:22 -0000 @@ -0,0 +1,76 @@ +/* This file defines the interface between the LM32 simulator and GDB. + Contributed by Jon Beniston + + Copyright (C) 2009 Free Software Foundation, Inc. + + 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 . */ + +#ifndef SIM_LM32_H +#define SIM_LM32_H + +#ifdef __cplusplus +extern "C" { // } +#endif + +enum sim_lm32_regs +{ + SIM_LM32_R0_REGNUM, + SIM_LM32_R1_REGNUM, + SIM_LM32_R2_REGNUM, + SIM_LM32_R3_REGNUM, + SIM_LM32_R4_REGNUM, + SIM_LM32_R5_REGNUM, + SIM_LM32_R6_REGNUM, + SIM_LM32_R7_REGNUM, + SIM_LM32_R8_REGNUM, + SIM_LM32_R9_REGNUM, + SIM_LM32_R10_REGNUM, + SIM_LM32_R11_REGNUM, + SIM_LM32_R12_REGNUM, + SIM_LM32_R13_REGNUM, + SIM_LM32_R14_REGNUM, + SIM_LM32_R15_REGNUM, + SIM_LM32_R16_REGNUM, + SIM_LM32_R17_REGNUM, + SIM_LM32_R18_REGNUM, + SIM_LM32_R19_REGNUM, + SIM_LM32_R20_REGNUM, + SIM_LM32_R21_REGNUM, + SIM_LM32_R22_REGNUM, + SIM_LM32_R23_REGNUM, + SIM_LM32_R24_REGNUM, + SIM_LM32_R25_REGNUM, + SIM_LM32_GP_REGNUM, + SIM_LM32_FP_REGNUM, + SIM_LM32_SP_REGNUM, + SIM_LM32_RA_REGNUM, + SIM_LM32_BA_REGNUM, + SIM_LM32_EA_REGNUM, + SIM_LM32_PC_REGNUM, + SIM_LM32_EID_REGNUM, + SIM_LM32_EBA_REGNUM, + SIM_LM32_DEBA_REGNUM, + SIM_LM32_IE_REGNUM, + SIM_LM32_IM_REGNUM, + SIM_LM32_IP_REGNUM, + SIM_LM32_NUM_REGS +}; + +#ifdef __cplusplus +} +#endif + +#endif Index: sim/MAINTAINERS =================================================================== RCS file: /cvs/src/src/sim/MAINTAINERS,v retrieving revision 1.22 diff -u -p -r1.22 MAINTAINERS --- sim/MAINTAINERS 8 Apr 2008 07:15:39 -0000 1.22 +++ sim/MAINTAINERS 15 Apr 2009 17:41:22 -0000 @@ -14,6 +14,7 @@ cr16 M R Swami Reddy igen (igen simulators) ppc Andrew Cagney +lm32 Jon Beniston m68hc11 Stephane Carrez mips Thiemo Seufer sh (global maintainers) Index: sim/configure =================================================================== RCS file: /cvs/src/src/sim/configure,v retrieving revision 1.26 diff -u -p -r1.26 configure --- sim/configure 8 Apr 2008 09:15:56 -0000 1.26 +++ sim/configure 15 Apr 2009 17:41:24 -0000 @@ -279,6 +279,7 @@ ac_subdirs_all="$ac_subdirs_all d10v" ac_subdirs_all="$ac_subdirs_all frv" ac_subdirs_all="$ac_subdirs_all h8300" ac_subdirs_all="$ac_subdirs_all iq2000" +ac_subdirs_all="$ac_subdirs_all lm32" ac_subdirs_all="$ac_subdirs_all m32c" ac_subdirs_all="$ac_subdirs_all m32r" ac_subdirs_all="$ac_subdirs_all m68hc11" @@ -3465,6 +3466,13 @@ subdirs="$subdirs iq2000" testsuite=yes ;; + lm32-*-*) + + +subdirs="$subdirs lm32" + + testsuite=yes + ;; m32c-*-*) Index: sim/configure.ac =================================================================== RCS file: /cvs/src/src/sim/configure.ac,v retrieving revision 1.14 diff -u -p -r1.14 configure.ac --- sim/configure.ac 8 Apr 2008 09:15:56 -0000 1.14 +++ sim/configure.ac 15 Apr 2009 17:41:24 -0000 @@ -74,6 +74,10 @@ if test "${enable_sim}" != no; then AC_CONFIG_SUBDIRS(iq2000) testsuite=yes ;; + lm32-*-*) + AC_CONFIG_SUBDIRS(lm32) + testsuite=yes + ;; m32c-*-*) AC_CONFIG_SUBDIRS(m32c) ;; Index: sim/common/gennltvals.sh =================================================================== RCS file: /cvs/src/src/sim/common/gennltvals.sh,v retrieving revision 1.4 diff -u -p -r1.4 gennltvals.sh --- sim/common/gennltvals.sh 8 Apr 2008 08:44:51 -0000 1.4 +++ sim/common/gennltvals.sh 15 Apr 2009 17:41:24 -0000 @@ -73,3 +73,6 @@ dir=libgloss/v850/sys target=v850 $shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \ "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}" +dir=libgloss target=lm32 +$shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \ + "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}" Index: sim/common/nltvals.def =================================================================== RCS file: /cvs/src/src/sim/common/nltvals.def,v retrieving revision 1.4 diff -u -p -r1.4 nltvals.def --- sim/common/nltvals.def 8 Apr 2008 08:44:51 -0000 1.4 +++ sim/common/nltvals.def 15 Apr 2009 17:41:25 -0000 @@ -454,3 +454,30 @@ /* end cr16 sys target macros */ #endif #endif +#ifdef NL_TARGET_lm32 +#ifdef sys_defs +/* from syscall.h */ +/* begin lm32 sys target macros */ + { "SYS_argv", 13 }, + { "SYS_argvlen", 12 }, + { "SYS_chdir", 14 }, + { "SYS_chmod", 16 }, + { "SYS_close", 3 }, + { "SYS_exit", 1 }, + { "SYS_fstat", 10 }, + { "SYS_getpid", 8 }, + { "SYS_gettimeofday", 19 }, + { "SYS_kill", 9 }, + { "SYS_link", 21 }, + { "SYS_lseek", 6 }, + { "SYS_open", 2 }, + { "SYS_read", 4 }, + { "SYS_stat", 15 }, + { "SYS_time", 18 }, + { "SYS_times", 20 }, + { "SYS_unlink", 7 }, + { "SYS_utime", 17 }, + { "SYS_write", 5 }, +/* end lm32 sys target macros */ +#endif +#endif Index: sim/lm32/Makefile.in =================================================================== RCS file: sim/lm32/Makefile.in diff -N sim/lm32/Makefile.in --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/Makefile.in 15 Apr 2009 17:41:25 -0000 @@ -0,0 +1,90 @@ +# Makefile for Lattice Mico32 simulator. +# Contributed by Jon Beniston + +## COMMON_PRE_CONFIG_FRAG + +# List of object files, less common parts. +SIM_OBJS = \ + $(SIM_NEW_COMMON_OBJS) \ + sim-cpu.o \ + sim-hload.o \ + sim-hrw.o \ + sim-model.o \ + sim-reg.o \ + sim-signal.o \ + cgen-utils.o cgen-trace.o cgen-scache.o \ + cgen-run.o sim-reason.o sim-engine.o sim-stop.o \ + sim-if.o arch.o \ + cpu.o decode.o sem.o model.o mloop.o \ + lm32.o traps.o user.o + +# List of extra dependencies. +# Generally this consists of simulator specific files included by sim-main.h. +SIM_EXTRA_DEPS = $(CGEN_INCLUDE_DEPS) $(srcdir)/../../opcodes/lm32-desc.h + +# List of flags to always pass to $(CC). +#SIM_EXTRA_CFLAGS = + +# List of main object files for `run'. +SIM_RUN_OBJS = nrun.o + +SIM_EXTRA_CLEAN = lm32-clean + +# This selects the lm32 newlib/libgloss syscall definitions. +NL_TARGET = -DNL_TARGET_lm32 + +## COMMON_POST_CONFIG_FRAG + +arch = lm32 + +arch.o: arch.c $(SIM_MAIN_DEPS) + +sim-if.o: sim-if.c $(SIM_MAIN_DEPS) $(srcdir)/../common/sim-core.h + +LM32BF_INCLUDE_DEPS = \ + $(CGEN_MAIN_CPU_DEPS) \ + cpu.h decode.h eng.h + +lm32.o: lm32.c $(LM32BF_INCLUDE_DEPS) + +# FIXME: Use of `mono' is wip. +mloop.c eng.h: stamp-mloop +stamp-mloop: $(srcdir)/../common/genmloop.sh mloop.in Makefile + $(SHELL) $(srccom)/genmloop.sh \ + -mono -fast -pbb -switch sem-switch.c \ + -cpu lm32bf -infile $(srcdir)/mloop.in + $(SHELL) $(srcroot)/move-if-change eng.hin eng.h + $(SHELL) $(srcroot)/move-if-change mloop.cin mloop.c + touch stamp-mloop +mloop.o: mloop.c sem-switch.c + +cpu.o: cpu.c $(LM32BF_INCLUDE_DEPS) +decode.o: decode.c $(LM32BF_INCLUDE_DEPS) +sem.o: sem.c $(LM32BF_INCLUDE_DEPS) +model.o: model.c $(LM32BF_INCLUDE_DEPS) + +lm32-clean: + rm -f mloop.c eng.h stamp-mloop + rm -f stamp-arch stamp-cpu + rm -f tmp-* + +# cgen support, enable with --enable-cgen-maint +CGEN_MAINT = ; @true +# The following line is commented in or out depending upon --enable-cgen-maint. +@CGEN_MAINT@CGEN_MAINT = + +stamp-arch: $(CGEN_READ_SCM) $(CGEN_ARCH_SCM) $(CGEN_CPU_DIR)/lm32.cpu + $(MAKE) cgen-arch $(CGEN_FLAGS_TO_PASS) mach=all \ + archfile=$(CGEN_CPU_DIR)/lm32.cpu \ + FLAGS="with-scache with-profile=fn" + touch stamp-arch +arch.h arch.c cpuall.h: $(CGEN_MAINT) stamp-arch + +stamp-cpu: $(CGEN_READ_SCM) $(CGEN_CPU_SCM) $(CGEN_DECODE_SCM) $(CGEN_CPU_DIR)/lm32.cpu + $(MAKE) cgen-cpu-decode $(CGEN_FLAGS_TO_PASS) \ + cpu=lm32bf mach=lm32 SUFFIX= \ + archfile=$(CGEN_CPU_DIR)/lm32.cpu \ + FLAGS="with-scache with-profile=fn" \ + EXTRAFILES="$(CGEN_CPU_SEM) $(CGEN_CPU_SEMSW)" + touch stamp-cpu +cpu.h sem.c sem-switch.c model.c decode.c decode.h: $(CGEN_MAINT) stamp-cpu Index: sim/lm32/arch.c =================================================================== RCS file: sim/lm32/arch.c diff -N sim/lm32/arch.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/arch.c 15 Apr 2009 17:41:25 -0000 @@ -0,0 +1,35 @@ +/* Simulator support for lm32. + +THIS FILE IS MACHINE GENERATED WITH CGEN. + +Copyright 1996-2005 Free Software Foundation, Inc. + +This file is part of the GNU simulators. + +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 2, 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, write to the Free Software Foundation, Inc., +51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include "sim-main.h" +#include "bfd.h" + +const MACH *sim_machs[] = +{ +#ifdef HAVE_CPU_LM32BF + & lm32_mach, +#endif + 0 +}; + Index: sim/lm32/arch.h =================================================================== RCS file: sim/lm32/arch.h diff -N sim/lm32/arch.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/arch.h 15 Apr 2009 17:41:25 -0000 @@ -0,0 +1,44 @@ +/* Simulator header for lm32. + +THIS FILE IS MACHINE GENERATED WITH CGEN. + +Copyright 1996-2005 Free Software Foundation, Inc. + +This file is part of the GNU simulators. + +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 2, 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, write to the Free Software Foundation, Inc., +51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef LM32_ARCH_H +#define LM32_ARCH_H + +#define TARGET_BIG_ENDIAN 1 + +/* Enum declaration for model types. */ +typedef enum model_type { + MODEL_LM32, MODEL_MAX +} MODEL_TYPE; + +#define MAX_MODELS ((int) MODEL_MAX) + +/* Enum declaration for unit types. */ +typedef enum unit_type { + UNIT_NONE, UNIT_LM32_U_EXEC, UNIT_MAX +} UNIT_TYPE; + +#define MAX_UNITS (1) + +#endif /* LM32_ARCH_H */ Index: sim/lm32/config.in =================================================================== RCS file: sim/lm32/config.in diff -N sim/lm32/config.in --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/config.in 15 Apr 2009 17:41:25 -0000 @@ -0,0 +1,116 @@ +/* config.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#undef ENABLE_NLS + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FPU_CONTROL_H + +/* Define to 1 if you have the `getrusage' function. */ +#undef HAVE_GETRUSAGE + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the `time' function. */ +#undef HAVE_TIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ZLIB_H + +/* Define to 1 if you have the `__setfpucw' function. */ +#undef HAVE___SETFPUCW + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Additional package description */ +#undef PKGVERSION + +/* Bug reporting address */ +#undef REPORT_BUGS_TO + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif Index: sim/lm32/configure.ac =================================================================== RCS file: sim/lm32/configure.ac diff -N sim/lm32/configure.ac --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/configure.ac 15 Apr 2009 17:41:25 -0000 @@ -0,0 +1,21 @@ +dnl Process this file with autoconf to produce a configure script. +AC_PREREQ(2.59)dnl +AC_INIT(Makefile.in) +AC_CONFIG_HEADER(config.h:config.in) + +sinclude(../common/aclocal.m4) + +# Bugs in autoconf 2.59 break the call to SIM_AC_COMMON, hack around +# it by inlining the macro's contents. +sinclude(../common/common.m4) + +SIM_AC_OPTION_ENDIAN(BIG_ENDIAN) +SIM_AC_OPTION_ALIGNMENT(STRICT_ALIGNMENT,STRICT_ALIGNMENT) +SIM_AC_OPTION_HOSTENDIAN +SIM_AC_OPTION_SCACHE(16384) +SIM_AC_OPTION_DEFAULT_MODEL(lm32) +SIM_AC_OPTION_ENVIRONMENT +SIM_AC_OPTION_CGEN_MAINT +SIM_AC_OPTION_HARDWARE(yes,,lm32cpu lm32timer lm32uart) + +SIM_AC_OUTPUT Index: sim/lm32/cpu.c =================================================================== RCS file: sim/lm32/cpu.c diff -N sim/lm32/cpu.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/cpu.c 15 Apr 2009 17:41:25 -0000 @@ -0,0 +1,85 @@ +/* Misc. support for CPU family lm32bf. + +THIS FILE IS MACHINE GENERATED WITH CGEN. + +Copyright 1996-2005 Free Software Foundation, Inc. + +This file is part of the GNU simulators. + +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 2, 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, write to the Free Software Foundation, Inc., +51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#define WANT_CPU lm32bf +#define WANT_CPU_LM32BF + +#include "sim-main.h" +#include "cgen-ops.h" + +/* Get the value of h-pc. */ + +USI +lm32bf_h_pc_get (SIM_CPU *current_cpu) +{ + return CPU (h_pc); +} + +/* Set a value for h-pc. */ + +void +lm32bf_h_pc_set (SIM_CPU *current_cpu, USI newval) +{ + CPU (h_pc) = newval; +} + +/* Get the value of h-gr. */ + +SI +lm32bf_h_gr_get (SIM_CPU *current_cpu, UINT regno) +{ + return CPU (h_gr[regno]); +} + +/* Set a value for h-gr. */ + +void +lm32bf_h_gr_set (SIM_CPU *current_cpu, UINT regno, SI newval) +{ + CPU (h_gr[regno]) = newval; +} + +/* Get the value of h-csr. */ + +SI +lm32bf_h_csr_get (SIM_CPU *current_cpu, UINT regno) +{ + return CPU (h_csr[regno]); +} + +/* Set a value for h-csr. */ + +void +lm32bf_h_csr_set (SIM_CPU *current_cpu, UINT regno, SI newval) +{ + CPU (h_csr[regno]) = newval; +} + +/* Record trace results for INSN. */ + +void +lm32bf_record_trace_results (SIM_CPU *current_cpu, CGEN_INSN *insn, + int *indices, TRACE_RECORD *tr) +{ +} Index: sim/lm32/cpu.h =================================================================== RCS file: sim/lm32/cpu.h diff -N sim/lm32/cpu.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/cpu.h 15 Apr 2009 17:41:25 -0000 @@ -0,0 +1,349 @@ +/* CPU family header for lm32bf. + +THIS FILE IS MACHINE GENERATED WITH CGEN. + +Copyright 1996-2005 Free Software Foundation, Inc. + +This file is part of the GNU simulators. + +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 2, 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, write to the Free Software Foundation, Inc., +51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef CPU_LM32BF_H +#define CPU_LM32BF_H + +/* Maximum number of instructions that are fetched at a time. + This is for LIW type instructions sets (e.g. m32r). */ +#define MAX_LIW_INSNS 1 + +/* Maximum number of instructions that can be executed in parallel. */ +#define MAX_PARALLEL_INSNS 1 + +/* CPU state information. */ +typedef struct { + /* Hardware elements. */ + struct { + /* Program counter */ + USI h_pc; +#define GET_H_PC() CPU (h_pc) +#define SET_H_PC(x) (CPU (h_pc) = (x)) + /* General purpose registers */ + SI h_gr[32]; +#define GET_H_GR(a1) CPU (h_gr)[a1] +#define SET_H_GR(a1, x) (CPU (h_gr)[a1] = (x)) + /* Control and status registers */ + SI h_csr[32]; +#define GET_H_CSR(a1) CPU (h_csr)[a1] +#define SET_H_CSR(a1, x) (CPU (h_csr)[a1] = (x)) + } hardware; +#define CPU_CGEN_HW(cpu) (& (cpu)->cpu_data.hardware) +} LM32BF_CPU_DATA; + +/* Cover fns for register access. */ +USI lm32bf_h_pc_get (SIM_CPU *); +void lm32bf_h_pc_set (SIM_CPU *, USI); +SI lm32bf_h_gr_get (SIM_CPU *, UINT); +void lm32bf_h_gr_set (SIM_CPU *, UINT, SI); +SI lm32bf_h_csr_get (SIM_CPU *, UINT); +void lm32bf_h_csr_set (SIM_CPU *, UINT, SI); + +/* These must be hand-written. */ +extern CPUREG_FETCH_FN lm32bf_fetch_register; +extern CPUREG_STORE_FN lm32bf_store_register; + +typedef struct { + int empty; +} MODEL_LM32_DATA; + +/* Instruction argument buffer. */ + +union sem_fields { + struct { /* no operands */ + int empty; + } fmt_empty; + struct { /* */ + IADDR i_call; + } sfmt_bi; + struct { /* */ + UINT f_csr; + UINT f_r1; + } sfmt_wcsr; + struct { /* */ + UINT f_csr; + UINT f_r2; + } sfmt_rcsr; + struct { /* */ + IADDR i_branch; + UINT f_r0; + UINT f_r1; + } sfmt_be; + struct { /* */ + UINT f_r0; + UINT f_r1; + UINT f_uimm; + } sfmt_andi; + struct { /* */ + INT f_imm; + UINT f_r0; + UINT f_r1; + } sfmt_addi; + struct { /* */ + UINT f_r0; + UINT f_r1; + UINT f_r2; + UINT f_user; + } sfmt_user; +#if WITH_SCACHE_PBB + /* Writeback handler. */ + struct { + /* Pointer to argbuf entry for insn whose results need writing back. */ + const struct argbuf *abuf; + } write; + /* x-before handler */ + struct { + /*const SCACHE *insns[MAX_PARALLEL_INSNS];*/ + int first_p; + } before; + /* x-after handler */ + struct { + int empty; + } after; + /* This entry is used to terminate each pbb. */ + struct { + /* Number of insns in pbb. */ + int insn_count; + /* Next pbb to execute. */ + SCACHE *next; + SCACHE *branch_target; + } chain; +#endif +}; + +/* The ARGBUF struct. */ +struct argbuf { + /* These are the baseclass definitions. */ + IADDR addr; + const IDESC *idesc; + char trace_p; + char profile_p; + /* ??? Temporary hack for skip insns. */ + char skip_count; + char unused; + /* cpu specific data follows */ + union sem semantic; + int written; + union sem_fields fields; +}; + +/* A cached insn. + + ??? SCACHE used to contain more than just argbuf. We could delete the + type entirely and always just use ARGBUF, but for future concerns and as + a level of abstraction it is left in. */ + +struct scache { + struct argbuf argbuf; +}; + +/* Macros to simplify extraction, reading and semantic code. + These define and assign the local vars that contain the insn's fields. */ + +#define EXTRACT_IFMT_EMPTY_VARS \ + unsigned int length; +#define EXTRACT_IFMT_EMPTY_CODE \ + length = 0; \ + +#define EXTRACT_IFMT_ADD_VARS \ + UINT f_opcode; \ + UINT f_r0; \ + UINT f_r1; \ + UINT f_r2; \ + UINT f_resv0; \ + unsigned int length; +#define EXTRACT_IFMT_ADD_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); \ + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); \ + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); \ + f_resv0 = EXTRACT_LSB0_UINT (insn, 32, 10, 11); \ + +#define EXTRACT_IFMT_ADDI_VARS \ + UINT f_opcode; \ + UINT f_r0; \ + UINT f_r1; \ + INT f_imm; \ + unsigned int length; +#define EXTRACT_IFMT_ADDI_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); \ + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); \ + f_imm = EXTRACT_LSB0_INT (insn, 32, 15, 16); \ + +#define EXTRACT_IFMT_ANDI_VARS \ + UINT f_opcode; \ + UINT f_r0; \ + UINT f_r1; \ + UINT f_uimm; \ + unsigned int length; +#define EXTRACT_IFMT_ANDI_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); \ + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); \ + f_uimm = EXTRACT_LSB0_UINT (insn, 32, 15, 16); \ + +#define EXTRACT_IFMT_ANDHII_VARS \ + UINT f_opcode; \ + UINT f_r0; \ + UINT f_r1; \ + UINT f_uimm; \ + unsigned int length; +#define EXTRACT_IFMT_ANDHII_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); \ + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); \ + f_uimm = EXTRACT_LSB0_UINT (insn, 32, 15, 16); \ + +#define EXTRACT_IFMT_B_VARS \ + UINT f_opcode; \ + UINT f_r0; \ + UINT f_r1; \ + UINT f_r2; \ + UINT f_resv0; \ + unsigned int length; +#define EXTRACT_IFMT_B_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); \ + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); \ + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); \ + f_resv0 = EXTRACT_LSB0_UINT (insn, 32, 10, 11); \ + +#define EXTRACT_IFMT_BI_VARS \ + UINT f_opcode; \ + SI f_call; \ + unsigned int length; +#define EXTRACT_IFMT_BI_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_call = ((pc) + (((int) (((EXTRACT_LSB0_INT (insn, 32, 25, 26)) << (6))) >> (4)))); \ + +#define EXTRACT_IFMT_BE_VARS \ + UINT f_opcode; \ + UINT f_r0; \ + UINT f_r1; \ + SI f_branch; \ + unsigned int length; +#define EXTRACT_IFMT_BE_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); \ + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); \ + f_branch = ((pc) + (((int) (((EXTRACT_LSB0_INT (insn, 32, 15, 16)) << (16))) >> (14)))); \ + +#define EXTRACT_IFMT_ORI_VARS \ + UINT f_opcode; \ + UINT f_r0; \ + UINT f_r1; \ + UINT f_uimm; \ + unsigned int length; +#define EXTRACT_IFMT_ORI_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); \ + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); \ + f_uimm = EXTRACT_LSB0_UINT (insn, 32, 15, 16); \ + +#define EXTRACT_IFMT_RCSR_VARS \ + UINT f_opcode; \ + UINT f_csr; \ + UINT f_r1; \ + UINT f_r2; \ + UINT f_resv0; \ + unsigned int length; +#define EXTRACT_IFMT_RCSR_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_csr = EXTRACT_LSB0_UINT (insn, 32, 25, 5); \ + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); \ + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); \ + f_resv0 = EXTRACT_LSB0_UINT (insn, 32, 10, 11); \ + +#define EXTRACT_IFMT_SEXTB_VARS \ + UINT f_opcode; \ + UINT f_r0; \ + UINT f_r1; \ + UINT f_r2; \ + UINT f_resv0; \ + unsigned int length; +#define EXTRACT_IFMT_SEXTB_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); \ + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); \ + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); \ + f_resv0 = EXTRACT_LSB0_UINT (insn, 32, 10, 11); \ + +#define EXTRACT_IFMT_USER_VARS \ + UINT f_opcode; \ + UINT f_r0; \ + UINT f_r1; \ + UINT f_r2; \ + UINT f_user; \ + unsigned int length; +#define EXTRACT_IFMT_USER_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); \ + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); \ + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); \ + f_user = EXTRACT_LSB0_UINT (insn, 32, 10, 11); \ + +#define EXTRACT_IFMT_WCSR_VARS \ + UINT f_opcode; \ + UINT f_csr; \ + UINT f_r1; \ + UINT f_r2; \ + UINT f_resv0; \ + unsigned int length; +#define EXTRACT_IFMT_WCSR_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_csr = EXTRACT_LSB0_UINT (insn, 32, 25, 5); \ + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); \ + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); \ + f_resv0 = EXTRACT_LSB0_UINT (insn, 32, 10, 11); \ + +#define EXTRACT_IFMT_BREAK_VARS \ + UINT f_opcode; \ + UINT f_exception; \ + unsigned int length; +#define EXTRACT_IFMT_BREAK_CODE \ + length = 4; \ + f_opcode = EXTRACT_LSB0_UINT (insn, 32, 31, 6); \ + f_exception = EXTRACT_LSB0_UINT (insn, 32, 25, 26); \ + +/* Collection of various things for the trace handler to use. */ + +typedef struct trace_record { + IADDR pc; + /* FIXME:wip */ +} TRACE_RECORD; + +#endif /* CPU_LM32BF_H */ Index: sim/lm32/cpuall.h =================================================================== RCS file: sim/lm32/cpuall.h diff -N sim/lm32/cpuall.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/cpuall.h 15 Apr 2009 17:41:25 -0000 @@ -0,0 +1,66 @@ +/* Simulator CPU header for lm32. + +THIS FILE IS MACHINE GENERATED WITH CGEN. + +Copyright 1996-2005 Free Software Foundation, Inc. + +This file is part of the GNU simulators. + +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 2, 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, write to the Free Software Foundation, Inc., +51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef LM32_CPUALL_H +#define LM32_CPUALL_H + +/* Include files for each cpu family. */ + +#ifdef WANT_CPU_LM32BF +#include "eng.h" +#include "cgen-engine.h" +#include "cpu.h" +#include "decode.h" +#endif + +extern const MACH lm32_mach; + +#ifndef WANT_CPU +/* The ARGBUF struct. */ +struct argbuf { + /* These are the baseclass definitions. */ + IADDR addr; + const IDESC *idesc; + char trace_p; + char profile_p; + /* ??? Temporary hack for skip insns. */ + char skip_count; + char unused; + /* cpu specific data follows */ +}; +#endif + +#ifndef WANT_CPU +/* A cached insn. + + ??? SCACHE used to contain more than just argbuf. We could delete the + type entirely and always just use ARGBUF, but for future concerns and as + a level of abstraction it is left in. */ + +struct scache { + struct argbuf argbuf; +}; +#endif + +#endif /* LM32_CPUALL_H */ Index: sim/lm32/decode.c =================================================================== RCS file: sim/lm32/decode.c diff -N sim/lm32/decode.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/decode.c 15 Apr 2009 17:41:25 -0000 @@ -0,0 +1,955 @@ +/* Simulator instruction decoder for lm32bf. + +THIS FILE IS MACHINE GENERATED WITH CGEN. + +Copyright 1996-2005 Free Software Foundation, Inc. + +This file is part of the GNU simulators. + +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 2, 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, write to the Free Software Foundation, Inc., +51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#define WANT_CPU lm32bf +#define WANT_CPU_LM32BF + +#include "sim-main.h" +#include "sim-assert.h" + +/* The instruction descriptor array. + This is computed at runtime. Space for it is not malloc'd to save a + teensy bit of cpu in the decoder. Moving it to malloc space is trivial + but won't be done until necessary (we don't currently support the runtime + addition of instructions nor an SMP machine with different cpus). */ +static IDESC lm32bf_insn_data[LM32BF_INSN__MAX]; + +/* Commas between elements are contained in the macros. + Some of these are conditionally compiled out. */ + +static const struct insn_sem lm32bf_insn_sem[] = +{ + { VIRTUAL_INSN_X_INVALID, LM32BF_INSN_X_INVALID, LM32BF_SFMT_EMPTY }, + { VIRTUAL_INSN_X_AFTER, LM32BF_INSN_X_AFTER, LM32BF_SFMT_EMPTY }, + { VIRTUAL_INSN_X_BEFORE, LM32BF_INSN_X_BEFORE, LM32BF_SFMT_EMPTY }, + { VIRTUAL_INSN_X_CTI_CHAIN, LM32BF_INSN_X_CTI_CHAIN, LM32BF_SFMT_EMPTY }, + { VIRTUAL_INSN_X_CHAIN, LM32BF_INSN_X_CHAIN, LM32BF_SFMT_EMPTY }, + { VIRTUAL_INSN_X_BEGIN, LM32BF_INSN_X_BEGIN, LM32BF_SFMT_EMPTY }, + { LM32_INSN_ADD, LM32BF_INSN_ADD, LM32BF_SFMT_ADD }, + { LM32_INSN_ADDI, LM32BF_INSN_ADDI, LM32BF_SFMT_ADDI }, + { LM32_INSN_AND, LM32BF_INSN_AND, LM32BF_SFMT_ADD }, + { LM32_INSN_ANDI, LM32BF_INSN_ANDI, LM32BF_SFMT_ANDI }, + { LM32_INSN_ANDHII, LM32BF_INSN_ANDHII, LM32BF_SFMT_ANDHII }, + { LM32_INSN_B, LM32BF_INSN_B, LM32BF_SFMT_B }, + { LM32_INSN_BI, LM32BF_INSN_BI, LM32BF_SFMT_BI }, + { LM32_INSN_BE, LM32BF_INSN_BE, LM32BF_SFMT_BE }, + { LM32_INSN_BG, LM32BF_INSN_BG, LM32BF_SFMT_BE }, + { LM32_INSN_BGE, LM32BF_INSN_BGE, LM32BF_SFMT_BE }, + { LM32_INSN_BGEU, LM32BF_INSN_BGEU, LM32BF_SFMT_BE }, + { LM32_INSN_BGU, LM32BF_INSN_BGU, LM32BF_SFMT_BE }, + { LM32_INSN_BNE, LM32BF_INSN_BNE, LM32BF_SFMT_BE }, + { LM32_INSN_CALL, LM32BF_INSN_CALL, LM32BF_SFMT_CALL }, + { LM32_INSN_CALLI, LM32BF_INSN_CALLI, LM32BF_SFMT_CALLI }, + { LM32_INSN_CMPE, LM32BF_INSN_CMPE, LM32BF_SFMT_ADD }, + { LM32_INSN_CMPEI, LM32BF_INSN_CMPEI, LM32BF_SFMT_ADDI }, + { LM32_INSN_CMPG, LM32BF_INSN_CMPG, LM32BF_SFMT_ADD }, + { LM32_INSN_CMPGI, LM32BF_INSN_CMPGI, LM32BF_SFMT_ADDI }, + { LM32_INSN_CMPGE, LM32BF_INSN_CMPGE, LM32BF_SFMT_ADD }, + { LM32_INSN_CMPGEI, LM32BF_INSN_CMPGEI, LM32BF_SFMT_ADDI }, + { LM32_INSN_CMPGEU, LM32BF_INSN_CMPGEU, LM32BF_SFMT_ADD }, + { LM32_INSN_CMPGEUI, LM32BF_INSN_CMPGEUI, LM32BF_SFMT_ANDI }, + { LM32_INSN_CMPGU, LM32BF_INSN_CMPGU, LM32BF_SFMT_ADD }, + { LM32_INSN_CMPGUI, LM32BF_INSN_CMPGUI, LM32BF_SFMT_ANDI }, + { LM32_INSN_CMPNE, LM32BF_INSN_CMPNE, LM32BF_SFMT_ADD }, + { LM32_INSN_CMPNEI, LM32BF_INSN_CMPNEI, LM32BF_SFMT_ADDI }, + { LM32_INSN_DIVU, LM32BF_INSN_DIVU, LM32BF_SFMT_DIVU }, + { LM32_INSN_LB, LM32BF_INSN_LB, LM32BF_SFMT_LB }, + { LM32_INSN_LBU, LM32BF_INSN_LBU, LM32BF_SFMT_LB }, + { LM32_INSN_LH, LM32BF_INSN_LH, LM32BF_SFMT_LH }, + { LM32_INSN_LHU, LM32BF_INSN_LHU, LM32BF_SFMT_LH }, + { LM32_INSN_LW, LM32BF_INSN_LW, LM32BF_SFMT_LW }, + { LM32_INSN_MODU, LM32BF_INSN_MODU, LM32BF_SFMT_DIVU }, + { LM32_INSN_MUL, LM32BF_INSN_MUL, LM32BF_SFMT_ADD }, + { LM32_INSN_MULI, LM32BF_INSN_MULI, LM32BF_SFMT_ADDI }, + { LM32_INSN_NOR, LM32BF_INSN_NOR, LM32BF_SFMT_ADD }, + { LM32_INSN_NORI, LM32BF_INSN_NORI, LM32BF_SFMT_ANDI }, + { LM32_INSN_OR, LM32BF_INSN_OR, LM32BF_SFMT_ADD }, + { LM32_INSN_ORI, LM32BF_INSN_ORI, LM32BF_SFMT_ORI }, + { LM32_INSN_ORHII, LM32BF_INSN_ORHII, LM32BF_SFMT_ANDHII }, + { LM32_INSN_RCSR, LM32BF_INSN_RCSR, LM32BF_SFMT_RCSR }, + { LM32_INSN_SB, LM32BF_INSN_SB, LM32BF_SFMT_SB }, + { LM32_INSN_SEXTB, LM32BF_INSN_SEXTB, LM32BF_SFMT_SEXTB }, + { LM32_INSN_SEXTH, LM32BF_INSN_SEXTH, LM32BF_SFMT_SEXTB }, + { LM32_INSN_SH, LM32BF_INSN_SH, LM32BF_SFMT_SH }, + { LM32_INSN_SL, LM32BF_INSN_SL, LM32BF_SFMT_SL }, + { LM32_INSN_SLI, LM32BF_INSN_SLI, LM32BF_SFMT_ADDI }, + { LM32_INSN_SR, LM32BF_INSN_SR, LM32BF_SFMT_SL }, + { LM32_INSN_SRI, LM32BF_INSN_SRI, LM32BF_SFMT_ADDI }, + { LM32_INSN_SRU, LM32BF_INSN_SRU, LM32BF_SFMT_SL }, + { LM32_INSN_SRUI, LM32BF_INSN_SRUI, LM32BF_SFMT_ADDI }, + { LM32_INSN_SUB, LM32BF_INSN_SUB, LM32BF_SFMT_ADD }, + { LM32_INSN_SW, LM32BF_INSN_SW, LM32BF_SFMT_SW }, + { LM32_INSN_USER, LM32BF_INSN_USER, LM32BF_SFMT_USER }, + { LM32_INSN_WCSR, LM32BF_INSN_WCSR, LM32BF_SFMT_WCSR }, + { LM32_INSN_XOR, LM32BF_INSN_XOR, LM32BF_SFMT_ADD }, + { LM32_INSN_XORI, LM32BF_INSN_XORI, LM32BF_SFMT_ANDI }, + { LM32_INSN_XNOR, LM32BF_INSN_XNOR, LM32BF_SFMT_ADD }, + { LM32_INSN_XNORI, LM32BF_INSN_XNORI, LM32BF_SFMT_ANDI }, + { LM32_INSN_BREAK, LM32BF_INSN_BREAK, LM32BF_SFMT_BREAK }, + { LM32_INSN_SCALL, LM32BF_INSN_SCALL, LM32BF_SFMT_BREAK }, +}; + +static const struct insn_sem lm32bf_insn_sem_invalid = { + VIRTUAL_INSN_X_INVALID, LM32BF_INSN_X_INVALID, LM32BF_SFMT_EMPTY +}; + +/* Initialize an IDESC from the compile-time computable parts. */ + +static INLINE void +init_idesc (SIM_CPU *cpu, IDESC *id, const struct insn_sem *t) +{ + const CGEN_INSN *insn_table = CGEN_CPU_INSN_TABLE (CPU_CPU_DESC (cpu))->init_entries; + + id->num = t->index; + id->sfmt = t->sfmt; + if ((int) t->type <= 0) + id->idata = & cgen_virtual_insn_table[- (int) t->type]; + else + id->idata = & insn_table[t->type]; + id->attrs = CGEN_INSN_ATTRS (id->idata); + /* Oh my god, a magic number. */ + id->length = CGEN_INSN_BITSIZE (id->idata) / 8; + +#if WITH_PROFILE_MODEL_P + id->timing = & MODEL_TIMING (CPU_MODEL (cpu)) [t->index]; + { + SIM_DESC sd = CPU_STATE (cpu); + SIM_ASSERT (t->index == id->timing->num); + } +#endif + + /* Semantic pointers are initialized elsewhere. */ +} + +/* Initialize the instruction descriptor table. */ + +void +lm32bf_init_idesc_table (SIM_CPU *cpu) +{ + IDESC *id,*tabend; + const struct insn_sem *t,*tend; + int tabsize = LM32BF_INSN__MAX; + IDESC *table = lm32bf_insn_data; + + memset (table, 0, tabsize * sizeof (IDESC)); + + /* First set all entries to the `invalid insn'. */ + t = & lm32bf_insn_sem_invalid; + for (id = table, tabend = table + tabsize; id < tabend; ++id) + init_idesc (cpu, id, t); + + /* Now fill in the values for the chosen cpu. */ + for (t = lm32bf_insn_sem, tend = t + sizeof (lm32bf_insn_sem) / sizeof (*t); + t != tend; ++t) + { + init_idesc (cpu, & table[t->index], t); + } + + /* Link the IDESC table into the cpu. */ + CPU_IDESC (cpu) = table; +} + +/* Given an instruction, return a pointer to its IDESC entry. */ + +const IDESC * +lm32bf_decode (SIM_CPU *current_cpu, IADDR pc, + CGEN_INSN_INT base_insn, CGEN_INSN_INT entire_insn, + ARGBUF *abuf) +{ + /* Result of decoder. */ + LM32BF_INSN_TYPE itype; + + { + CGEN_INSN_INT insn = base_insn; + + { + unsigned int val = (((insn >> 26) & (63 << 0))); + switch (val) + { + case 0 : + if ((entire_insn & 0xfc000000) == 0x0) + { itype = LM32BF_INSN_SRUI; goto extract_sfmt_addi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 1 : + if ((entire_insn & 0xfc000000) == 0x4000000) + { itype = LM32BF_INSN_NORI; goto extract_sfmt_andi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 2 : + if ((entire_insn & 0xfc000000) == 0x8000000) + { itype = LM32BF_INSN_MULI; goto extract_sfmt_addi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 3 : + if ((entire_insn & 0xfc000000) == 0xc000000) + { itype = LM32BF_INSN_SH; goto extract_sfmt_sh; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 4 : + if ((entire_insn & 0xfc000000) == 0x10000000) + { itype = LM32BF_INSN_LB; goto extract_sfmt_lb; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 5 : + if ((entire_insn & 0xfc000000) == 0x14000000) + { itype = LM32BF_INSN_SRI; goto extract_sfmt_addi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 6 : + if ((entire_insn & 0xfc000000) == 0x18000000) + { itype = LM32BF_INSN_XORI; goto extract_sfmt_andi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 7 : + if ((entire_insn & 0xfc000000) == 0x1c000000) + { itype = LM32BF_INSN_LH; goto extract_sfmt_lh; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 8 : + if ((entire_insn & 0xfc000000) == 0x20000000) + { itype = LM32BF_INSN_ANDI; goto extract_sfmt_andi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 9 : + if ((entire_insn & 0xfc000000) == 0x24000000) + { itype = LM32BF_INSN_XNORI; goto extract_sfmt_andi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 10 : + if ((entire_insn & 0xfc000000) == 0x28000000) + { itype = LM32BF_INSN_LW; goto extract_sfmt_lw; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 11 : + if ((entire_insn & 0xfc000000) == 0x2c000000) + { itype = LM32BF_INSN_LHU; goto extract_sfmt_lh; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 12 : + if ((entire_insn & 0xfc000000) == 0x30000000) + { itype = LM32BF_INSN_SB; goto extract_sfmt_sb; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 13 : + if ((entire_insn & 0xfc000000) == 0x34000000) + { itype = LM32BF_INSN_ADDI; goto extract_sfmt_addi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 14 : + if ((entire_insn & 0xfc000000) == 0x38000000) + { itype = LM32BF_INSN_ORI; goto extract_sfmt_ori; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 15 : + if ((entire_insn & 0xfc000000) == 0x3c000000) + { itype = LM32BF_INSN_SLI; goto extract_sfmt_addi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 16 : + if ((entire_insn & 0xfc000000) == 0x40000000) + { itype = LM32BF_INSN_LBU; goto extract_sfmt_lb; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 17 : + if ((entire_insn & 0xfc000000) == 0x44000000) + { itype = LM32BF_INSN_BE; goto extract_sfmt_be; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 18 : + if ((entire_insn & 0xfc000000) == 0x48000000) + { itype = LM32BF_INSN_BG; goto extract_sfmt_be; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 19 : + if ((entire_insn & 0xfc000000) == 0x4c000000) + { itype = LM32BF_INSN_BGE; goto extract_sfmt_be; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 20 : + if ((entire_insn & 0xfc000000) == 0x50000000) + { itype = LM32BF_INSN_BGEU; goto extract_sfmt_be; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 21 : + if ((entire_insn & 0xfc000000) == 0x54000000) + { itype = LM32BF_INSN_BGU; goto extract_sfmt_be; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 22 : + if ((entire_insn & 0xfc000000) == 0x58000000) + { itype = LM32BF_INSN_SW; goto extract_sfmt_sw; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 23 : + if ((entire_insn & 0xfc000000) == 0x5c000000) + { itype = LM32BF_INSN_BNE; goto extract_sfmt_be; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 24 : + if ((entire_insn & 0xfc000000) == 0x60000000) + { itype = LM32BF_INSN_ANDHII; goto extract_sfmt_andhii; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 25 : + if ((entire_insn & 0xfc000000) == 0x64000000) + { itype = LM32BF_INSN_CMPEI; goto extract_sfmt_addi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 26 : + if ((entire_insn & 0xfc000000) == 0x68000000) + { itype = LM32BF_INSN_CMPGI; goto extract_sfmt_addi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 27 : + if ((entire_insn & 0xfc000000) == 0x6c000000) + { itype = LM32BF_INSN_CMPGEI; goto extract_sfmt_addi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 28 : + if ((entire_insn & 0xfc000000) == 0x70000000) + { itype = LM32BF_INSN_CMPGEUI; goto extract_sfmt_andi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 29 : + if ((entire_insn & 0xfc000000) == 0x74000000) + { itype = LM32BF_INSN_CMPGUI; goto extract_sfmt_andi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 30 : + if ((entire_insn & 0xfc000000) == 0x78000000) + { itype = LM32BF_INSN_ORHII; goto extract_sfmt_andhii; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 31 : + if ((entire_insn & 0xfc000000) == 0x7c000000) + { itype = LM32BF_INSN_CMPNEI; goto extract_sfmt_addi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 32 : + if ((entire_insn & 0xfc0007ff) == 0x80000000) + { itype = LM32BF_INSN_SRU; goto extract_sfmt_sl; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 33 : + if ((entire_insn & 0xfc0007ff) == 0x84000000) + { itype = LM32BF_INSN_NOR; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 34 : + if ((entire_insn & 0xfc0007ff) == 0x88000000) + { itype = LM32BF_INSN_MUL; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 35 : + if ((entire_insn & 0xfc0007ff) == 0x8c000000) + { itype = LM32BF_INSN_DIVU; goto extract_sfmt_divu; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 36 : + if ((entire_insn & 0xfc1f07ff) == 0x90000000) + { itype = LM32BF_INSN_RCSR; goto extract_sfmt_rcsr; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 37 : + if ((entire_insn & 0xfc0007ff) == 0x94000000) + { itype = LM32BF_INSN_SR; goto extract_sfmt_sl; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 38 : + if ((entire_insn & 0xfc0007ff) == 0x98000000) + { itype = LM32BF_INSN_XOR; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 40 : + if ((entire_insn & 0xfc0007ff) == 0xa0000000) + { itype = LM32BF_INSN_AND; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 41 : + if ((entire_insn & 0xfc0007ff) == 0xa4000000) + { itype = LM32BF_INSN_XNOR; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 43 : + { + unsigned int val = (((insn >> 1) & (1 << 1)) | ((insn >> 0) & (1 << 0))); + switch (val) + { + case 0 : + if ((entire_insn & 0xffffffff) == 0xac000002) + { itype = LM32BF_INSN_BREAK; goto extract_sfmt_break; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 3 : + if ((entire_insn & 0xffffffff) == 0xac000007) + { itype = LM32BF_INSN_SCALL; goto extract_sfmt_break; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + default : itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + } + } + case 44 : + if ((entire_insn & 0xfc1f07ff) == 0xb0000000) + { itype = LM32BF_INSN_SEXTB; goto extract_sfmt_sextb; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 45 : + if ((entire_insn & 0xfc0007ff) == 0xb4000000) + { itype = LM32BF_INSN_ADD; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 46 : + if ((entire_insn & 0xfc0007ff) == 0xb8000000) + { itype = LM32BF_INSN_OR; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 47 : + if ((entire_insn & 0xfc0007ff) == 0xbc000000) + { itype = LM32BF_INSN_SL; goto extract_sfmt_sl; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 48 : + if ((entire_insn & 0xfc1fffff) == 0xc0000000) + { itype = LM32BF_INSN_B; goto extract_sfmt_b; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 49 : + if ((entire_insn & 0xfc0007ff) == 0xc4000000) + { itype = LM32BF_INSN_MODU; goto extract_sfmt_divu; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 50 : + if ((entire_insn & 0xfc0007ff) == 0xc8000000) + { itype = LM32BF_INSN_SUB; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 51 : + if ((entire_insn & 0xfc000000) == 0xcc000000) + { itype = LM32BF_INSN_USER; goto extract_sfmt_user; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 52 : + if ((entire_insn & 0xfc00ffff) == 0xd0000000) + { itype = LM32BF_INSN_WCSR; goto extract_sfmt_wcsr; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 54 : + if ((entire_insn & 0xfc1fffff) == 0xd8000000) + { itype = LM32BF_INSN_CALL; goto extract_sfmt_call; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 55 : + if ((entire_insn & 0xfc1f07ff) == 0xdc000000) + { itype = LM32BF_INSN_SEXTH; goto extract_sfmt_sextb; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 56 : + if ((entire_insn & 0xfc000000) == 0xe0000000) + { itype = LM32BF_INSN_BI; goto extract_sfmt_bi; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 57 : + if ((entire_insn & 0xfc0007ff) == 0xe4000000) + { itype = LM32BF_INSN_CMPE; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 58 : + if ((entire_insn & 0xfc0007ff) == 0xe8000000) + { itype = LM32BF_INSN_CMPG; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 59 : + if ((entire_insn & 0xfc0007ff) == 0xec000000) + { itype = LM32BF_INSN_CMPGE; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 60 : + if ((entire_insn & 0xfc0007ff) == 0xf0000000) + { itype = LM32BF_INSN_CMPGEU; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 61 : + if ((entire_insn & 0xfc0007ff) == 0xf4000000) + { itype = LM32BF_INSN_CMPGU; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 62 : + if ((entire_insn & 0xfc000000) == 0xf8000000) + { itype = LM32BF_INSN_CALLI; goto extract_sfmt_calli; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + case 63 : + if ((entire_insn & 0xfc0007ff) == 0xfc000000) + { itype = LM32BF_INSN_CMPNE; goto extract_sfmt_add; } + itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + default : itype = LM32BF_INSN_X_INVALID; goto extract_sfmt_empty; + } + } + } + + /* The instruction has been decoded, now extract the fields. */ + + extract_sfmt_empty: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; +#define FLD(f) abuf->fields.fmt_empty.f + + + /* Record the fields for the semantic handler. */ + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_empty", (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_add: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_user.f + UINT f_r0; + UINT f_r1; + UINT f_r2; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); + + /* Record the fields for the semantic handler. */ + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + FLD (f_r2) = f_r2; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_add", "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, "f_r2 0x%x", 'x', f_r2, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_addi: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_addi.f + UINT f_r0; + UINT f_r1; + INT f_imm; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_imm = EXTRACT_LSB0_INT (insn, 32, 15, 16); + + /* Record the fields for the semantic handler. */ + FLD (f_imm) = f_imm; + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_addi", "f_imm 0x%x", 'x', f_imm, "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_andi: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_andi.f + UINT f_r0; + UINT f_r1; + UINT f_uimm; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_uimm = EXTRACT_LSB0_UINT (insn, 32, 15, 16); + + /* Record the fields for the semantic handler. */ + FLD (f_r0) = f_r0; + FLD (f_uimm) = f_uimm; + FLD (f_r1) = f_r1; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_andi", "f_r0 0x%x", 'x', f_r0, "f_uimm 0x%x", 'x', f_uimm, "f_r1 0x%x", 'x', f_r1, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_andhii: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_andi.f + UINT f_r0; + UINT f_r1; + UINT f_uimm; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_uimm = EXTRACT_LSB0_UINT (insn, 32, 15, 16); + + /* Record the fields for the semantic handler. */ + FLD (f_uimm) = f_uimm; + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_andhii", "f_uimm 0x%x", 'x', f_uimm, "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_b: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_be.f + UINT f_r0; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + + /* Record the fields for the semantic handler. */ + FLD (f_r0) = f_r0; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_b", "f_r0 0x%x", 'x', f_r0, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_bi: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_bi.f + SI f_call; + + f_call = ((pc) + (((int) (((EXTRACT_LSB0_INT (insn, 32, 25, 26)) << (6))) >> (4)))); + + /* Record the fields for the semantic handler. */ + FLD (i_call) = f_call; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_bi", "call 0x%x", 'x', f_call, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_be: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_be.f + UINT f_r0; + UINT f_r1; + SI f_branch; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_branch = ((pc) + (((int) (((EXTRACT_LSB0_INT (insn, 32, 15, 16)) << (16))) >> (14)))); + + /* Record the fields for the semantic handler. */ + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + FLD (i_branch) = f_branch; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_be", "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, "branch 0x%x", 'x', f_branch, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_call: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_be.f + UINT f_r0; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + + /* Record the fields for the semantic handler. */ + FLD (f_r0) = f_r0; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_call", "f_r0 0x%x", 'x', f_r0, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_calli: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_bi.f + SI f_call; + + f_call = ((pc) + (((int) (((EXTRACT_LSB0_INT (insn, 32, 25, 26)) << (6))) >> (4)))); + + /* Record the fields for the semantic handler. */ + FLD (i_call) = f_call; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_calli", "call 0x%x", 'x', f_call, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_divu: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_user.f + UINT f_r0; + UINT f_r1; + UINT f_r2; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); + + /* Record the fields for the semantic handler. */ + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + FLD (f_r2) = f_r2; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_divu", "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, "f_r2 0x%x", 'x', f_r2, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_lb: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_addi.f + UINT f_r0; + UINT f_r1; + INT f_imm; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_imm = EXTRACT_LSB0_INT (insn, 32, 15, 16); + + /* Record the fields for the semantic handler. */ + FLD (f_imm) = f_imm; + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_lb", "f_imm 0x%x", 'x', f_imm, "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_lh: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_addi.f + UINT f_r0; + UINT f_r1; + INT f_imm; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_imm = EXTRACT_LSB0_INT (insn, 32, 15, 16); + + /* Record the fields for the semantic handler. */ + FLD (f_imm) = f_imm; + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_lh", "f_imm 0x%x", 'x', f_imm, "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_lw: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_addi.f + UINT f_r0; + UINT f_r1; + INT f_imm; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_imm = EXTRACT_LSB0_INT (insn, 32, 15, 16); + + /* Record the fields for the semantic handler. */ + FLD (f_imm) = f_imm; + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_lw", "f_imm 0x%x", 'x', f_imm, "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_ori: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_andi.f + UINT f_r0; + UINT f_r1; + UINT f_uimm; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_uimm = EXTRACT_LSB0_UINT (insn, 32, 15, 16); + + /* Record the fields for the semantic handler. */ + FLD (f_uimm) = f_uimm; + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_ori", "f_uimm 0x%x", 'x', f_uimm, "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_rcsr: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_rcsr.f + UINT f_csr; + UINT f_r2; + + f_csr = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); + + /* Record the fields for the semantic handler. */ + FLD (f_csr) = f_csr; + FLD (f_r2) = f_r2; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_rcsr", "f_csr 0x%x", 'x', f_csr, "f_r2 0x%x", 'x', f_r2, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_sb: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_addi.f + UINT f_r0; + UINT f_r1; + INT f_imm; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_imm = EXTRACT_LSB0_INT (insn, 32, 15, 16); + + /* Record the fields for the semantic handler. */ + FLD (f_imm) = f_imm; + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_sb", "f_imm 0x%x", 'x', f_imm, "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_sextb: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_user.f + UINT f_r0; + UINT f_r2; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); + + /* Record the fields for the semantic handler. */ + FLD (f_r0) = f_r0; + FLD (f_r2) = f_r2; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_sextb", "f_r0 0x%x", 'x', f_r0, "f_r2 0x%x", 'x', f_r2, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_sh: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_addi.f + UINT f_r0; + UINT f_r1; + INT f_imm; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_imm = EXTRACT_LSB0_INT (insn, 32, 15, 16); + + /* Record the fields for the semantic handler. */ + FLD (f_imm) = f_imm; + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_sh", "f_imm 0x%x", 'x', f_imm, "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_sl: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_user.f + UINT f_r0; + UINT f_r1; + UINT f_r2; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); + + /* Record the fields for the semantic handler. */ + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + FLD (f_r2) = f_r2; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_sl", "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, "f_r2 0x%x", 'x', f_r2, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_sw: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_addi.f + UINT f_r0; + UINT f_r1; + INT f_imm; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_imm = EXTRACT_LSB0_INT (insn, 32, 15, 16); + + /* Record the fields for the semantic handler. */ + FLD (f_imm) = f_imm; + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_sw", "f_imm 0x%x", 'x', f_imm, "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_user: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_user.f + UINT f_r0; + UINT f_r1; + UINT f_r2; + UINT f_user; + + f_r0 = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + f_r2 = EXTRACT_LSB0_UINT (insn, 32, 15, 5); + f_user = EXTRACT_LSB0_UINT (insn, 32, 10, 11); + + /* Record the fields for the semantic handler. */ + FLD (f_r0) = f_r0; + FLD (f_r1) = f_r1; + FLD (f_user) = f_user; + FLD (f_r2) = f_r2; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_user", "f_r0 0x%x", 'x', f_r0, "f_r1 0x%x", 'x', f_r1, "f_user 0x%x", 'x', f_user, "f_r2 0x%x", 'x', f_r2, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_wcsr: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; + CGEN_INSN_INT insn = entire_insn; +#define FLD(f) abuf->fields.sfmt_wcsr.f + UINT f_csr; + UINT f_r1; + + f_csr = EXTRACT_LSB0_UINT (insn, 32, 25, 5); + f_r1 = EXTRACT_LSB0_UINT (insn, 32, 20, 5); + + /* Record the fields for the semantic handler. */ + FLD (f_csr) = f_csr; + FLD (f_r1) = f_r1; + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_wcsr", "f_csr 0x%x", 'x', f_csr, "f_r1 0x%x", 'x', f_r1, (char *) 0)); + +#undef FLD + return idesc; + } + + extract_sfmt_break: + { + const IDESC *idesc = &lm32bf_insn_data[itype]; +#define FLD(f) abuf->fields.fmt_empty.f + + + /* Record the fields for the semantic handler. */ + TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "sfmt_break", (char *) 0)); + +#undef FLD + return idesc; + } + +} Index: sim/lm32/decode.h =================================================================== RCS file: sim/lm32/decode.h diff -N sim/lm32/decode.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/decode.h 15 Apr 2009 17:41:25 -0000 @@ -0,0 +1,76 @@ +/* Decode header for lm32bf. + +THIS FILE IS MACHINE GENERATED WITH CGEN. + +Copyright 1996-2005 Free Software Foundation, Inc. + +This file is part of the GNU simulators. + +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 2, 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, write to the Free Software Foundation, Inc., +51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef LM32BF_DECODE_H +#define LM32BF_DECODE_H + +extern const IDESC *lm32bf_decode (SIM_CPU *, IADDR, + CGEN_INSN_INT, CGEN_INSN_INT, + ARGBUF *); +extern void lm32bf_init_idesc_table (SIM_CPU *); +extern void lm32bf_sem_init_idesc_table (SIM_CPU *); +extern void lm32bf_semf_init_idesc_table (SIM_CPU *); + +/* Enum declaration for instructions in cpu family lm32bf. */ +typedef enum lm32bf_insn_type { + LM32BF_INSN_X_INVALID, LM32BF_INSN_X_AFTER, LM32BF_INSN_X_BEFORE, LM32BF_INSN_X_CTI_CHAIN + , LM32BF_INSN_X_CHAIN, LM32BF_INSN_X_BEGIN, LM32BF_INSN_ADD, LM32BF_INSN_ADDI + , LM32BF_INSN_AND, LM32BF_INSN_ANDI, LM32BF_INSN_ANDHII, LM32BF_INSN_B + , LM32BF_INSN_BI, LM32BF_INSN_BE, LM32BF_INSN_BG, LM32BF_INSN_BGE + , LM32BF_INSN_BGEU, LM32BF_INSN_BGU, LM32BF_INSN_BNE, LM32BF_INSN_CALL + , LM32BF_INSN_CALLI, LM32BF_INSN_CMPE, LM32BF_INSN_CMPEI, LM32BF_INSN_CMPG + , LM32BF_INSN_CMPGI, LM32BF_INSN_CMPGE, LM32BF_INSN_CMPGEI, LM32BF_INSN_CMPGEU + , LM32BF_INSN_CMPGEUI, LM32BF_INSN_CMPGU, LM32BF_INSN_CMPGUI, LM32BF_INSN_CMPNE + , LM32BF_INSN_CMPNEI, LM32BF_INSN_DIVU, LM32BF_INSN_LB, LM32BF_INSN_LBU + , LM32BF_INSN_LH, LM32BF_INSN_LHU, LM32BF_INSN_LW, LM32BF_INSN_MODU + , LM32BF_INSN_MUL, LM32BF_INSN_MULI, LM32BF_INSN_NOR, LM32BF_INSN_NORI + , LM32BF_INSN_OR, LM32BF_INSN_ORI, LM32BF_INSN_ORHII, LM32BF_INSN_RCSR + , LM32BF_INSN_SB, LM32BF_INSN_SEXTB, LM32BF_INSN_SEXTH, LM32BF_INSN_SH + , LM32BF_INSN_SL, LM32BF_INSN_SLI, LM32BF_INSN_SR, LM32BF_INSN_SRI + , LM32BF_INSN_SRU, LM32BF_INSN_SRUI, LM32BF_INSN_SUB, LM32BF_INSN_SW + , LM32BF_INSN_USER, LM32BF_INSN_WCSR, LM32BF_INSN_XOR, LM32BF_INSN_XORI + , LM32BF_INSN_XNOR, LM32BF_INSN_XNORI, LM32BF_INSN_BREAK, LM32BF_INSN_SCALL + , LM32BF_INSN__MAX +} LM32BF_INSN_TYPE; + +/* Enum declaration for semantic formats in cpu family lm32bf. */ +typedef enum lm32bf_sfmt_type { + LM32BF_SFMT_EMPTY, LM32BF_SFMT_ADD, LM32BF_SFMT_ADDI, LM32BF_SFMT_ANDI + , LM32BF_SFMT_ANDHII, LM32BF_SFMT_B, LM32BF_SFMT_BI, LM32BF_SFMT_BE + , LM32BF_SFMT_CALL, LM32BF_SFMT_CALLI, LM32BF_SFMT_DIVU, LM32BF_SFMT_LB + , LM32BF_SFMT_LH, LM32BF_SFMT_LW, LM32BF_SFMT_ORI, LM32BF_SFMT_RCSR + , LM32BF_SFMT_SB, LM32BF_SFMT_SEXTB, LM32BF_SFMT_SH, LM32BF_SFMT_SL + , LM32BF_SFMT_SW, LM32BF_SFMT_USER, LM32BF_SFMT_WCSR, LM32BF_SFMT_BREAK +} LM32BF_SFMT_TYPE; + +/* Function unit handlers (user written). */ + +extern int lm32bf_model_lm32_u_exec (SIM_CPU *, const IDESC *, int /*unit_num*/, int /*referenced*/); + +/* Profiling before/after handlers (user written) */ + +extern void lm32bf_model_insn_before (SIM_CPU *, int /*first_p*/); +extern void lm32bf_model_insn_after (SIM_CPU *, int /*last_p*/, int /*cycles*/); + +#endif /* LM32BF_DECODE_H */ Index: sim/lm32/dv-lm32cpu.c =================================================================== RCS file: sim/lm32/dv-lm32cpu.c diff -N sim/lm32/dv-lm32cpu.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/dv-lm32cpu.c 15 Apr 2009 17:41:26 -0000 @@ -0,0 +1,247 @@ +/* Lattice Mico32 CPU model. + Contributed by Jon Beniston + + Copyright (C) 2009 Free Software Foundation, Inc. + + 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 "hw-main.h" +#include "sim-main.h" + + +struct lm32cpu +{ + struct hw_event *event; +}; + +/* input port ID's. */ + +enum +{ + INT0_PORT, + INT1_PORT, + INT2_PORT, + INT3_PORT, + INT4_PORT, + INT5_PORT, + INT6_PORT, + INT7_PORT, + INT8_PORT, + INT9_PORT, + INT10_PORT, + INT11_PORT, + INT12_PORT, + INT13_PORT, + INT14_PORT, + INT15_PORT, + INT16_PORT, + INT17_PORT, + INT18_PORT, + INT19_PORT, + INT20_PORT, + INT21_PORT, + INT22_PORT, + INT23_PORT, + INT24_PORT, + INT25_PORT, + INT26_PORT, + INT27_PORT, + INT28_PORT, + INT29_PORT, + INT30_PORT, + INT31_PORT, +}; + +static const struct hw_port_descriptor lm32cpu_ports[] = { + /* interrupt inputs. */ + {"int0", INT0_PORT, 0, input_port,}, + {"int1", INT1_PORT, 0, input_port,}, + {"int2", INT2_PORT, 0, input_port,}, + {"int3", INT3_PORT, 0, input_port,}, + {"int4", INT4_PORT, 0, input_port,}, + {"int5", INT5_PORT, 0, input_port,}, + {"int6", INT6_PORT, 0, input_port,}, + {"int7", INT7_PORT, 0, input_port,}, + {"int8", INT8_PORT, 0, input_port,}, + {"int9", INT9_PORT, 0, input_port,}, + {"int10", INT10_PORT, 0, input_port,}, + {"int11", INT11_PORT, 0, input_port,}, + {"int12", INT12_PORT, 0, input_port,}, + {"int13", INT13_PORT, 0, input_port,}, + {"int14", INT14_PORT, 0, input_port,}, + {"int15", INT15_PORT, 0, input_port,}, + {"int16", INT16_PORT, 0, input_port,}, + {"int17", INT17_PORT, 0, input_port,}, + {"int18", INT18_PORT, 0, input_port,}, + {"int19", INT19_PORT, 0, input_port,}, + {"int20", INT20_PORT, 0, input_port,}, + {"int21", INT21_PORT, 0, input_port,}, + {"int22", INT22_PORT, 0, input_port,}, + {"int23", INT23_PORT, 0, input_port,}, + {"int24", INT24_PORT, 0, input_port,}, + {"int25", INT25_PORT, 0, input_port,}, + {"int26", INT26_PORT, 0, input_port,}, + {"int27", INT27_PORT, 0, input_port,}, + {"int28", INT28_PORT, 0, input_port,}, + {"int29", INT29_PORT, 0, input_port,}, + {"int30", INT30_PORT, 0, input_port,}, + {"int31", INT31_PORT, 0, input_port,}, + {NULL,}, +}; + + + +/* + * Finish off the partially created hw device. Attach our local + * callbacks. Wire up our port names etc. + */ +static hw_port_event_method lm32cpu_port_event; + + +static void +lm32cpu_finish (struct hw *me) +{ + struct lm32cpu *controller; + + controller = HW_ZALLOC (me, struct lm32cpu); + set_hw_data (me, controller); + set_hw_ports (me, lm32cpu_ports); + set_hw_port_event (me, lm32cpu_port_event); + + /* Initialize the pending interrupt flags. */ + controller->event = NULL; +} + + +/* An event arrives on an interrupt port. */ +static unsigned int s_ui_ExtIntrs = 0; + + +static void +deliver_lm32cpu_interrupt (struct hw *me, void *data) +{ + static unsigned int ip, im, im_and_ip_result; + struct lm32cpu *controller = hw_data (me); + SIM_DESC sd = hw_system (me); + sim_cpu *cpu = STATE_CPU (sd, 0); /* NB: fix CPU 0. */ + address_word cia = CIA_GET (cpu); + int interrupt = (int) data; + + + HW_TRACE ((me, "interrupt-check event")); + + + /* + * Determine if an external interrupt is active + * and needs to cause an exception. + */ + im = lm32bf_h_csr_get (cpu, LM32_CSR_IM); + ip = lm32bf_h_csr_get (cpu, LM32_CSR_IP); + im_and_ip_result = im & ip; + + + if ((lm32bf_h_csr_get (cpu, LM32_CSR_IE) & 1) && (im_and_ip_result != 0)) + { + /* Save PC in exception address register. */ + lm32bf_h_gr_set (cpu, 30, lm32bf_h_pc_get (cpu)); + /* Restart at interrupt offset in handler exception table. */ + lm32bf_h_pc_set (cpu, + lm32bf_h_csr_get (cpu, + LM32_CSR_EBA) + + LM32_EID_INTERRUPT * 32); + /* Save interrupt enable and then clear. */ + lm32bf_h_csr_set (cpu, LM32_CSR_IE, 0x2); + } + + /* reschedule soon. */ + if (controller->event != NULL) + hw_event_queue_deschedule (me, controller->event); + controller->event = NULL; + + + /* if there are external interrupts, schedule an interrupt-check again. + * NOTE: THIS MAKES IT VERY INEFFICIENT. INSTEAD, TRIGGER THIS + * CHECk_EVENT WHEN THE USER ENABLES IE OR USER MODIFIES IM REGISTERS. + */ + if (s_ui_ExtIntrs != 0) + controller->event = + hw_event_queue_schedule (me, 1, deliver_lm32cpu_interrupt, data); +} + + + +/* Handle an event on one of the CPU's ports. */ +static void +lm32cpu_port_event (struct hw *me, + int my_port, + struct hw *source, int source_port, int level) +{ + struct lm32cpu *controller = hw_data (me); + SIM_DESC sd = hw_system (me); + sim_cpu *cpu = STATE_CPU (sd, 0); /* NB: fix CPU 0. */ + address_word cia = CIA_GET (cpu); + + + HW_TRACE ((me, "interrupt event on port %d, level %d", my_port, level)); + + + + /* + * Activate IP if the interrupt's activated; don't do anything if + * the interrupt's deactivated. + */ + if (level == 1) + { + /* + * save state of external interrupt. + */ + s_ui_ExtIntrs |= (1 << my_port); + + /* interrupt-activated so set IP. */ + lm32bf_h_csr_set (cpu, LM32_CSR_IP, + lm32bf_h_csr_get (cpu, LM32_CSR_IP) | (1 << my_port)); + + /* + * Since interrupt is activated, queue an immediate event + * to check if this interrupt is serviceable. + */ + if (controller->event != NULL) + hw_event_queue_deschedule (me, controller->event); + + + /* + * Queue an immediate event to check if this interrupt must be serviced; + * this will happen after the current instruction is complete. + */ + controller->event = hw_event_queue_schedule (me, + 0, + deliver_lm32cpu_interrupt, + 0); + } + else + { + /* + * save state of external interrupt. + */ + s_ui_ExtIntrs &= ~(1 << my_port); + } +} + + +const struct hw_descriptor dv_lm32cpu_descriptor[] = { + {"lm32cpu", lm32cpu_finish,}, + {NULL}, +}; Index: sim/lm32/dv-lm32timer.c =================================================================== RCS file: sim/lm32/dv-lm32timer.c diff -N sim/lm32/dv-lm32timer.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/dv-lm32timer.c 15 Apr 2009 17:41:26 -0000 @@ -0,0 +1,220 @@ +/* Lattice Mico32 timer model. + Contributed by Jon Beniston + + Copyright (C) 2009 Free Software Foundation, Inc. + + 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 "sim-main.h" +#include "hw-main.h" +#include "sim-assert.h" + +struct lm32timer +{ + unsigned base; /* Base address of this timer. */ + unsigned limit; /* Limit address of this timer. */ + unsigned int status; + unsigned int control; + unsigned int period; + unsigned int snapshot; + struct hw_event *event; +}; + +/* Timer registers. */ +#define LM32_TIMER_STATUS 0x0 +#define LM32_TIMER_CONTROL 0x4 +#define LM32_TIMER_PERIOD 0x8 +#define LM32_TIMER_SNAPSHOT 0xc + +/* Timer ports. */ + +enum +{ + INT_PORT +}; + +static const struct hw_port_descriptor lm32timer_ports[] = { + {"int", INT_PORT, 0, output_port}, + {} +}; + +static void +do_timer_event (struct hw *me, void *data) +{ + struct lm32timer *timer = hw_data (me); + + /* Is timer started? */ + if (timer->control & 0x4) + { + if (timer->snapshot) + { + /* Decrement timer. */ + timer->snapshot--; + } + else if (timer->control & 1) + { + /* Restart timer. */ + timer->snapshot = timer->period; + } + } + /* Generate interrupt when timer is at 0, and interrupt enable is 1. */ + if ((timer->snapshot == 0) && (timer->control & 1)) + { + /* Generate interrupt. */ + hw_port_event (me, INT_PORT, 1); + } + /* If timer is started, schedule another event to decrement the timer again. */ + if (timer->control & 4) + hw_event_queue_schedule (me, 1, do_timer_event, 0); +} + +static unsigned +lm32timer_io_write_buffer (struct hw *me, + const void *source, + int space, unsigned_word base, unsigned nr_bytes) +{ + struct lm32timer *timers = hw_data (me); + int timer_reg; + const unsigned char *source_bytes = source; + int value = 0; + + HW_TRACE ((me, "write to 0x%08lx length %d with 0x%x", (long) base, + (int) nr_bytes, value)); + + if (nr_bytes == 4) + value = (source_bytes[0] << 24) + | (source_bytes[1] << 16) | (source_bytes[2] << 8) | (source_bytes[3]); + else + hw_abort (me, "write with invalid number of bytes: %d", nr_bytes); + + timer_reg = base - timers->base; + + switch (timer_reg) + { + case LM32_TIMER_STATUS: + timers->status = value; + break; + case LM32_TIMER_CONTROL: + timers->control = value; + if (timers->control & 0x4) + { + /* Timer is started. */ + hw_event_queue_schedule (me, 1, do_timer_event, 0); + } + break; + case LM32_TIMER_PERIOD: + timers->period = value; + break; + default: + hw_abort (me, "invalid register address: 0x%x.", timer_reg); + } + + return nr_bytes; +} + +static unsigned +lm32timer_io_read_buffer (struct hw *me, + void *dest, + int space, unsigned_word base, unsigned nr_bytes) +{ + struct lm32timer *timers = hw_data (me); + int timer_reg; + int value; + unsigned char *dest_bytes = dest; + + HW_TRACE ((me, "read 0x%08lx length %d", (long) base, (int) nr_bytes)); + + timer_reg = base - timers->base; + + switch (timer_reg) + { + case LM32_TIMER_STATUS: + value = timers->status; + break; + case LM32_TIMER_CONTROL: + value = timers->control; + break; + case LM32_TIMER_PERIOD: + value = timers->period; + break; + case LM32_TIMER_SNAPSHOT: + value = timers->snapshot; + break; + default: + hw_abort (me, "invalid register address: 0x%x.", timer_reg); + } + + if (nr_bytes == 4) + { + dest_bytes[0] = value >> 24; + dest_bytes[1] = value >> 16; + dest_bytes[2] = value >> 8; + dest_bytes[3] = value; + } + else + hw_abort (me, "read of unsupported number of bytes: %d", nr_bytes); + + return nr_bytes; +} + +static void +attach_lm32timer_regs (struct hw *me, struct lm32timer *timers) +{ + unsigned_word attach_address; + int attach_space; + unsigned attach_size; + reg_property_spec reg; + + if (hw_find_property (me, "reg") == NULL) + hw_abort (me, "Missing \"reg\" property"); + if (!hw_find_reg_array_property (me, "reg", 0, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + timers->base = attach_address; + hw_unit_size_to_attach_size (hw_parent (me), ®.size, &attach_size, me); + timers->limit = attach_address + (attach_size - 1); + hw_attach_address (hw_parent (me), + 0, attach_space, attach_address, attach_size, me); +} + +static void +lm32timer_finish (struct hw *me) +{ + struct lm32timer *timers; + int i; + + timers = HW_ZALLOC (me, struct lm32timer); + set_hw_data (me, timers); + set_hw_io_read_buffer (me, lm32timer_io_read_buffer); + set_hw_io_write_buffer (me, lm32timer_io_write_buffer); + set_hw_ports (me, lm32timer_ports); + + /* Attach ourself to our parent bus. */ + attach_lm32timer_regs (me, timers); + + /* Initialize the timers. */ + timers->status = 0; + timers->control = 0; + timers->period = 0; + timers->snapshot = 0; +} + +const struct hw_descriptor dv_lm32timer_descriptor[] = { + {"lm32timer", lm32timer_finish,}, + {NULL}, +}; Index: sim/lm32/dv-lm32uart.c =================================================================== RCS file: sim/lm32/dv-lm32uart.c diff -N sim/lm32/dv-lm32uart.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/dv-lm32uart.c 15 Apr 2009 17:41:26 -0000 @@ -0,0 +1,317 @@ +/* Lattice Mico32 UART model. + Contributed by Jon Beniston + + Copyright (C) 2009 Free Software Foundation, Inc. + + 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 "sim-main.h" +#include "hw-main.h" +#include "sim-assert.h" + +#include +#include + +struct lm32uart +{ + unsigned base; /* Base address of this UART. */ + unsigned limit; /* Limit address of this UART. */ + unsigned char rbr; + unsigned char thr; + unsigned char ier; + unsigned char iir; + unsigned char lcr; + unsigned char mcr; + unsigned char lsr; + unsigned char msr; + unsigned char div; + struct hw_event *event; +}; + +/* UART registers. */ + +#define LM32_UART_RBR 0x0 +#define LM32_UART_THR 0x0 +#define LM32_UART_IER 0x4 +#define LM32_UART_IIR 0x8 +#define LM32_UART_LCR 0xc +#define LM32_UART_MCR 0x10 +#define LM32_UART_LSR 0x14 +#define LM32_UART_MSR 0x18 +#define LM32_UART_DIV 0x1c + +#define LM32_UART_IER_RX_INT 0x1 +#define LM32_UART_IER_TX_INT 0x2 + +#define MICOUART_IIR_TXRDY 0x2 +#define MICOUART_IIR_RXRDY 0x4 + +#define LM32_UART_LSR_RX_RDY 0x01 +#define LM32_UART_LSR_TX_RDY 0x20 + +#define LM32_UART_LCR_WLS_MASK 0x3 +#define LM32_UART_LCR_WLS_5 0x0 +#define LM32_UART_LCR_WLS_6 0x1 +#define LM32_UART_LCR_WLS_7 0x2 +#define LM32_UART_LCR_WLS_8 0x3 + +/* UART ports. */ + +enum +{ + INT_PORT +}; + +static const struct hw_port_descriptor lm32uart_ports[] = { + {"int", INT_PORT, 0, output_port}, + {} +}; + +static void +do_uart_tx_event (struct hw *me, void *data) +{ + struct lm32uart *uart = hw_data (me); + char c; + + /* Generate interrupt when transmission is complete. */ + if (uart->ier & LM32_UART_IER_TX_INT) + { + /* Generate interrupt */ + hw_port_event (me, INT_PORT, 1); + } + + /* Indicate which interrupt has occured. */ + uart->iir = MICOUART_IIR_TXRDY; + + /* Indicate THR is empty. */ + uart->lsr |= LM32_UART_LSR_TX_RDY; + + /* Output the character in the THR. */ + c = (char) uart->thr; + + /* WLS field in LCR register specifies the number of bits to output. */ + switch (uart->lcr & LM32_UART_LCR_WLS_MASK) + { + case LM32_UART_LCR_WLS_5: + c &= 0x1f; + break; + case LM32_UART_LCR_WLS_6: + c &= 0x3f; + break; + case LM32_UART_LCR_WLS_7: + c &= 0x7f; + break; + } + printf ("%c", c); +} + +static unsigned +lm32uart_io_write_buffer (struct hw *me, + const void *source, + int space, unsigned_word base, unsigned nr_bytes) +{ + struct lm32uart *uart = hw_data (me); + int uart_reg; + const unsigned char *source_bytes = source; + int value = 0; + + HW_TRACE ((me, "write to 0x%08lx length %d with 0x%x", (long) base, + (int) nr_bytes, value)); + + if (nr_bytes == 4) + value = (source_bytes[0] << 24) + | (source_bytes[1] << 16) | (source_bytes[2] << 8) | (source_bytes[3]); + else + hw_abort (me, "write of unsupported number of bytes: %d.", nr_bytes); + + uart_reg = base - uart->base; + + switch (uart_reg) + { + case LM32_UART_THR: + /* Buffer the character to output. */ + uart->thr = value; + + /* Indicate the THR is full. */ + uart->lsr &= ~LM32_UART_LSR_TX_RDY; + + /* deassert interrupt when IER is loaded. */ + uart->iir &= ~MICOUART_IIR_TXRDY; + + /* schedule an event to output the character. */ + hw_event_queue_schedule (me, 1, do_uart_tx_event, 0); + + break; + case LM32_UART_IER: + uart->ier = value; + if ((value & LM32_UART_IER_TX_INT) + && (uart->lsr & LM32_UART_LSR_TX_RDY)) + { + /* hw_event_queue_schedule (me, 1, do_uart_tx_event, 0); */ + uart->lsr |= LM32_UART_LSR_TX_RDY; + uart->iir |= MICOUART_IIR_TXRDY; + hw_port_event (me, INT_PORT, 1); + } + else if ((value & LM32_UART_IER_TX_INT) == 0) + { + hw_port_event (me, INT_PORT, 0); + } + break; + case LM32_UART_IIR: + uart->iir = value; + break; + case LM32_UART_LCR: + uart->lcr = value; + break; + case LM32_UART_MCR: + uart->mcr = value; + break; + case LM32_UART_LSR: + uart->lsr = value; + break; + case LM32_UART_MSR: + uart->msr = value; + break; + case LM32_UART_DIV: + uart->div = value; + break; + default: + hw_abort (me, "write to invalid register address: 0x%x.", uart_reg); + } + + return nr_bytes; +} + +static unsigned +lm32uart_io_read_buffer (struct hw *me, + void *dest, + int space, unsigned_word base, unsigned nr_bytes) +{ + struct lm32uart *uart = hw_data (me); + int uart_reg; + int value; + unsigned char *dest_bytes = dest; + fd_set fd; + struct timeval tv; + + HW_TRACE ((me, "read 0x%08lx length %d", (long) base, (int) nr_bytes)); + + uart_reg = base - uart->base; + + switch (uart_reg) + { + case LM32_UART_RBR: + value = getchar (); + uart->lsr &= ~LM32_UART_LSR_RX_RDY; + break; + case LM32_UART_IER: + value = uart->ier; + break; + case LM32_UART_IIR: + value = uart->iir; + break; + case LM32_UART_LCR: + value = uart->lcr; + break; + case LM32_UART_MCR: + value = uart->mcr; + break; + case LM32_UART_LSR: + /* Check to see if any data waiting in stdin. */ + FD_ZERO (&fd); + FD_SET (fileno (stdin), &fd); + tv.tv_sec = 0; + tv.tv_usec = 1; + if (select (fileno (stdin) + 1, &fd, NULL, NULL, &tv)) + uart->lsr |= LM32_UART_LSR_RX_RDY; + value = uart->lsr; + break; + case LM32_UART_MSR: + value = uart->msr; + break; + case LM32_UART_DIV: + value = uart->div; + break; + default: + hw_abort (me, "read from invalid register address: 0x%x.", uart_reg); + } + + if (nr_bytes == 4) + { + dest_bytes[0] = value >> 24; + dest_bytes[1] = value >> 16; + dest_bytes[2] = value >> 8; + dest_bytes[3] = value; + } + else + hw_abort (me, "read of unsupported number of bytes: %d", nr_bytes); + + return nr_bytes; +} + +static void +attach_lm32uart_regs (struct hw *me, struct lm32uart *uart) +{ + unsigned_word attach_address; + int attach_space; + unsigned attach_size; + reg_property_spec reg; + + if (hw_find_property (me, "reg") == NULL) + hw_abort (me, "Missing \"reg\" property"); + if (!hw_find_reg_array_property (me, "reg", 0, ®)) + hw_abort (me, "\"reg\" property must contain three addr/size entries"); + hw_unit_address_to_attach_address (hw_parent (me), + ®.address, + &attach_space, &attach_address, me); + uart->base = attach_address; + hw_unit_size_to_attach_size (hw_parent (me), ®.size, &attach_size, me); + uart->limit = attach_address + (attach_size - 1); + hw_attach_address (hw_parent (me), + 0, attach_space, attach_address, attach_size, me); +} + +static void +lm32uart_finish (struct hw *me) +{ + struct lm32uart *uart; + int i; + + uart = HW_ZALLOC (me, struct lm32uart); + set_hw_data (me, uart); + set_hw_io_read_buffer (me, lm32uart_io_read_buffer); + set_hw_io_write_buffer (me, lm32uart_io_write_buffer); + set_hw_ports (me, lm32uart_ports); + + /* Attach ourself to our parent bus. */ + attach_lm32uart_regs (me, uart); + + /* Initialize the UART. */ + uart->rbr = 0; + uart->thr = 0; + uart->ier = 0; + uart->iir = 0; + uart->lcr = 0; + uart->mcr = 0; + uart->lsr = LM32_UART_LSR_TX_RDY; + uart->msr = 0; + uart->div = 0; /* By setting to zero, characters are output immediately. */ +} + +const struct hw_descriptor dv_lm32uart_descriptor[] = { + {"lm32uart", lm32uart_finish,}, + {NULL}, +}; Index: sim/lm32/lm32-sim.h =================================================================== RCS file: sim/lm32/lm32-sim.h diff -N sim/lm32/lm32-sim.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/lm32-sim.h 15 Apr 2009 17:41:26 -0000 @@ -0,0 +1,57 @@ +/* Contributed by Jon Beniston + + Copyright (C) 2009 Free Software Foundation, Inc. + + 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 . */ + +#ifndef LM32_SIM_H +#define LM32_SIM_H + +#include "gdb/sim-lm32.h" + +/* CSRs. */ +#define LM32_CSR_IE 0 +#define LM32_CSR_IM 1 +#define LM32_CSR_IP 2 +#define LM32_CSR_ICC 3 +#define LM32_CSR_DCC 4 +#define LM32_CSR_CC 5 +#define LM32_CSR_CFG 6 +#define LM32_CSR_EBA 7 +#define LM32_CSR_DC 8 +#define LM32_CSR_DEBA 9 +#define LM32_CSR_JTX 0xe +#define LM32_CSR_JRX 0xf +#define LM32_CSR_BP0 0x10 +#define LM32_CSR_BP1 0x11 +#define LM32_CSR_BP2 0x12 +#define LM32_CSR_BP3 0x13 +#define LM32_CSR_WP0 0x18 +#define LM32_CSR_WP1 0x19 +#define LM32_CSR_WP2 0x1a +#define LM32_CSR_WP3 0x1b + +/* Exception IDs. */ +#define LM32_EID_RESET 0 +#define LM32_EID_BREAKPOINT 1 +#define LM32_EID_INSTRUCTION_BUS_ERROR 2 +#define LM32_EID_WATCHPOINT 3 +#define LM32_EID_DATA_BUS_ERROR 4 +#define LM32_EID_DIVIDE_BY_ZERO 5 +#define LM32_EID_INTERRUPT 6 +#define LM32_EID_SYSTEM_CALL 7 + +#endif /* LM32_SIM_H */ Index: sim/lm32/lm32.c =================================================================== RCS file: sim/lm32/lm32.c diff -N sim/lm32/lm32.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/lm32.c 15 Apr 2009 17:41:26 -0000 @@ -0,0 +1,100 @@ +/* Lattice Mico32 simulator support code. + Contributed by Jon Beniston + + Copyright (C) 2009 Free Software Foundation, Inc. + + 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 . */ + +#define WANT_CPU lm32bf +#define WANT_CPU_LM32BF + +#include "sim-main.h" +#include "cgen-mem.h" +#include "cgen-ops.h" + +/* The contents of BUF are in target byte order. */ + +int +lm32bf_fetch_register (SIM_CPU * current_cpu, int rn, unsigned char *buf, + int len) +{ + if (rn < 32) + SETTSI (buf, lm32bf_h_gr_get (current_cpu, rn)); + else + switch (rn) + { + case SIM_LM32_PC_REGNUM: + SETTSI (buf, lm32bf_h_pc_get (current_cpu)); + break; + default: + return 0; + } + + return -1; +} + +/* The contents of BUF are in target byte order. */ + +int +lm32bf_store_register (SIM_CPU * current_cpu, int rn, unsigned char *buf, + int len) +{ + if (rn < 32) + lm32bf_h_gr_set (current_cpu, rn, GETTSI (buf)); + else + switch (rn) + { + case SIM_LM32_PC_REGNUM: + lm32bf_h_pc_set (current_cpu, GETTSI (buf)); + break; + default: + return 0; + } + + return -1; +} + + + +#if WITH_PROFILE_MODEL_P + +/* Initialize cycle counting for an insn. + FIRST_P is non-zero if this is the first insn in a set of parallel + insns. */ + +void +lm32bf_model_insn_before (SIM_CPU * cpu, int first_p) +{ +} + +/* Record the cycles computed for an insn. + LAST_P is non-zero if this is the last insn in a set of parallel insns, + and we update the total cycle count. + CYCLES is the cycle count of the insn. */ + +void +lm32bf_model_insn_after (SIM_CPU * cpu, int last_p, int cycles) +{ +} + +int +lm32bf_model_lm32_u_exec (SIM_CPU * cpu, const IDESC * idesc, + int unit_num, int referenced) +{ + return idesc->timing->units[unit_num].done; +} + +#endif /* WITH_PROFILE_MODEL_P */ Index: sim/lm32/mloop.in =================================================================== RCS file: sim/lm32/mloop.in diff -N sim/lm32/mloop.in --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/mloop.in 15 Apr 2009 17:41:26 -0000 @@ -0,0 +1,203 @@ +# Simulator main loop for lm32. -*- C -*- +# Contributed by Jon Beniston +# +# This file is part of the GNU Simulators. +# +# 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 2, 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, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Syntax: +# /bin/sh mainloop.in command +# +# Command is one of: +# +# init +# support +# extract-{simple,scache,pbb} +# {full,fast}-exec-{simple,scache,pbb} +# + +case "x$1" in + +xsupport) + +cat <argbuf.semantic.sem_fast) (current_cpu, sc); +#else + vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf); +#endif +#else + abort (); +#endif /* WITH_SEM_SWITCH_FAST */ + } + else + { +#if ! WITH_SEM_SWITCH_FULL + ARGBUF *abuf = &sc->argbuf; + const IDESC *idesc = abuf->idesc; + const CGEN_INSN *idata = idesc->idata; +#if WITH_SCACHE_PBB + int virtual_p = CGEN_INSN_ATTR_VALUE (idata, CGEN_INSN_VIRTUAL); +#else + int virtual_p = 0; +#endif + if (! virtual_p) + { + /* FIXME: call x-before */ + if (ARGBUF_PROFILE_P (abuf)) + PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num); + /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ + if (PROFILE_MODEL_P (current_cpu) + && ARGBUF_PROFILE_P (abuf)) + @cpu@_model_insn_before (current_cpu, 1 /*first_p*/); + TRACE_INSN_INIT (current_cpu, abuf, 1); + TRACE_INSN (current_cpu, idata, + (const struct argbuf *) abuf, abuf->addr); + } +#if WITH_SCACHE + vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc); +#else + vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf); +#endif + if (! virtual_p) + { + /* FIXME: call x-after */ + if (PROFILE_MODEL_P (current_cpu) + && ARGBUF_PROFILE_P (abuf)) + { + int cycles; + + cycles = (*idesc->timing->model_fn) (current_cpu, sc); + @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles); + } + TRACE_INSN_FINI (current_cpu, abuf, 1); + } +#else + abort (); +#endif /* WITH_SEM_SWITCH_FULL */ + } + + return vpc; +} + +EOF + +;; + +xinit) + +# Nothing needed. + +;; + +xextract-simple | xextract-scache) + +cat < 0) + { + USI insn = GETIMEMUSI (current_cpu, pc); + + idesc = extract (current_cpu, pc, insn, &sc->argbuf, FAST_P); + ++sc; + --max_insns; + ++icount; + pc += idesc->length; + + if (IDESC_CTI_P (idesc)) + { + SET_CTI_VPC (sc - 1); + break; + } + } + + Finish: + SET_INSN_COUNT (icount); +} +EOF + +;; + +xfull-exec-* | xfast-exec-*) + +# Inputs: current_cpu, vpc, FAST_P +# Outputs: vpc + +cat <&2 + exit 1 + ;; + +esac Index: sim/lm32/model.c =================================================================== RCS file: sim/lm32/model.c diff -N sim/lm32/model.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/model.c 15 Apr 2009 17:41:26 -0000 @@ -0,0 +1,1176 @@ +/* Simulator model support for lm32bf. + +THIS FILE IS MACHINE GENERATED WITH CGEN. + +Copyright 1996-2005 Free Software Foundation, Inc. + +This file is part of the GNU simulators. + +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 2, 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, write to the Free Software Foundation, Inc., +51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#define WANT_CPU lm32bf +#define WANT_CPU_LM32BF + +#include "sim-main.h" + +/* The profiling data is recorded here, but is accessed via the profiling + mechanism. After all, this is information for profiling. */ + +#if WITH_PROFILE_MODEL_P + +/* Model handlers for each insn. */ + +static int +model_lm32_add (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_addi (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_and (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_andi (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_andhii (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_b (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_bi (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_bi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_be (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_bg (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_bge (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_bgeu (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_bgu (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_bne (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_call (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_calli (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_bi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpe (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpei (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpg (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpgi (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpge (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpgei (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpgeu (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpgeui (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpgu (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpgui (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpne (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_cmpnei (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_divu (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_lb (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_lbu (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_lh (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_lhu (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_lw (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_modu (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_mul (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_muli (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_nor (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_nori (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_or (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_ori (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_orhii (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_rcsr (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_rcsr.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_sb (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_sextb (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_sexth (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_sh (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_sl (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_sli (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_sr (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_sri (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_sru (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_srui (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_sub (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_sw (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_user (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_wcsr (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_wcsr.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_xor (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_xori (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_xnor (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_xnori (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_break (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.fmt_empty.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +static int +model_lm32_scall (SIM_CPU *current_cpu, void *sem_arg) +{ +#define FLD(f) abuf->fields.fmt_empty.f + const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg); + const IDESC * UNUSED idesc = abuf->idesc; + int cycles = 0; + { + int referenced = 0; + int UNUSED insn_referenced = abuf->written; + cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced); + } + return cycles; +#undef FLD +} + +/* We assume UNIT_NONE == 0 because the tables don't always terminate + entries with it. */ + +/* Model timing data for `lm32'. */ + +static const INSN_TIMING lm32_timing[] = { + { LM32BF_INSN_X_INVALID, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_X_AFTER, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_X_BEFORE, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_X_CTI_CHAIN, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_X_CHAIN, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_X_BEGIN, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_ADD, model_lm32_add, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_ADDI, model_lm32_addi, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_AND, model_lm32_and, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_ANDI, model_lm32_andi, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_ANDHII, model_lm32_andhii, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_B, model_lm32_b, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_BI, model_lm32_bi, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_BE, model_lm32_be, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_BG, model_lm32_bg, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_BGE, model_lm32_bge, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_BGEU, model_lm32_bgeu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_BGU, model_lm32_bgu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_BNE, model_lm32_bne, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CALL, model_lm32_call, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CALLI, model_lm32_calli, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPE, model_lm32_cmpe, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPEI, model_lm32_cmpei, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPG, model_lm32_cmpg, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPGI, model_lm32_cmpgi, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPGE, model_lm32_cmpge, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPGEI, model_lm32_cmpgei, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPGEU, model_lm32_cmpgeu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPGEUI, model_lm32_cmpgeui, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPGU, model_lm32_cmpgu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPGUI, model_lm32_cmpgui, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPNE, model_lm32_cmpne, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_CMPNEI, model_lm32_cmpnei, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_DIVU, model_lm32_divu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_LB, model_lm32_lb, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_LBU, model_lm32_lbu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_LH, model_lm32_lh, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_LHU, model_lm32_lhu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_LW, model_lm32_lw, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_MODU, model_lm32_modu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_MUL, model_lm32_mul, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_MULI, model_lm32_muli, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_NOR, model_lm32_nor, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_NORI, model_lm32_nori, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_OR, model_lm32_or, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_ORI, model_lm32_ori, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_ORHII, model_lm32_orhii, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_RCSR, model_lm32_rcsr, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SB, model_lm32_sb, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SEXTB, model_lm32_sextb, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SEXTH, model_lm32_sexth, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SH, model_lm32_sh, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SL, model_lm32_sl, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SLI, model_lm32_sli, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SR, model_lm32_sr, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SRI, model_lm32_sri, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SRU, model_lm32_sru, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SRUI, model_lm32_srui, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SUB, model_lm32_sub, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SW, model_lm32_sw, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_USER, model_lm32_user, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_WCSR, model_lm32_wcsr, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_XOR, model_lm32_xor, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_XORI, model_lm32_xori, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_XNOR, model_lm32_xnor, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_XNORI, model_lm32_xnori, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_BREAK, model_lm32_break, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, + { LM32BF_INSN_SCALL, model_lm32_scall, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } }, +}; + +#endif /* WITH_PROFILE_MODEL_P */ + +static void +lm32_model_init (SIM_CPU *cpu) +{ + CPU_MODEL_DATA (cpu) = (void *) zalloc (sizeof (MODEL_LM32_DATA)); +} + +#if WITH_PROFILE_MODEL_P +#define TIMING_DATA(td) td +#else +#define TIMING_DATA(td) 0 +#endif + +static const MODEL lm32_models[] = +{ + { "lm32", & lm32_mach, MODEL_LM32, TIMING_DATA (& lm32_timing[0]), lm32_model_init }, + { 0 } +}; + +/* The properties of this cpu's implementation. */ + +static const MACH_IMP_PROPERTIES lm32bf_imp_properties = +{ + sizeof (SIM_CPU), +#if WITH_SCACHE + sizeof (SCACHE) +#else + 0 +#endif +}; + + +static void +lm32bf_prepare_run (SIM_CPU *cpu) +{ + if (CPU_IDESC (cpu) == NULL) + lm32bf_init_idesc_table (cpu); +} + +static const CGEN_INSN * +lm32bf_get_idata (SIM_CPU *cpu, int inum) +{ + return CPU_IDESC (cpu) [inum].idata; +} + +static void +lm32_init_cpu (SIM_CPU *cpu) +{ + CPU_REG_FETCH (cpu) = lm32bf_fetch_register; + CPU_REG_STORE (cpu) = lm32bf_store_register; + CPU_PC_FETCH (cpu) = lm32bf_h_pc_get; + CPU_PC_STORE (cpu) = lm32bf_h_pc_set; + CPU_GET_IDATA (cpu) = lm32bf_get_idata; + CPU_MAX_INSNS (cpu) = LM32BF_INSN__MAX; + CPU_INSN_NAME (cpu) = cgen_insn_name; + CPU_FULL_ENGINE_FN (cpu) = lm32bf_engine_run_full; +#if WITH_FAST + CPU_FAST_ENGINE_FN (cpu) = lm32bf_engine_run_fast; +#else + CPU_FAST_ENGINE_FN (cpu) = lm32bf_engine_run_full; +#endif +} + +const MACH lm32_mach = +{ + "lm32", "lm32", MACH_LM32, + 32, 32, & lm32_models[0], & lm32bf_imp_properties, + lm32_init_cpu, + lm32bf_prepare_run +}; + Index: sim/lm32/sem-switch.c =================================================================== RCS file: sim/lm32/sem-switch.c diff -N sim/lm32/sem-switch.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/sem-switch.c 15 Apr 2009 17:41:27 -0000 @@ -0,0 +1,1554 @@ +/* Simulator instruction semantics for lm32bf. + +THIS FILE IS MACHINE GENERATED WITH CGEN. + +Copyright 1996-2005 Free Software Foundation, Inc. + +This file is part of the GNU simulators. + +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 2, 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, write to the Free Software Foundation, Inc., +51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifdef DEFINE_LABELS + + /* The labels have the case they have because the enum of insn types + is all uppercase and in the non-stdc case the insn symbol is built + into the enum name. */ + + static struct { + int index; + void *label; + } labels[] = { + { LM32BF_INSN_X_INVALID, && case_sem_INSN_X_INVALID }, + { LM32BF_INSN_X_AFTER, && case_sem_INSN_X_AFTER }, + { LM32BF_INSN_X_BEFORE, && case_sem_INSN_X_BEFORE }, + { LM32BF_INSN_X_CTI_CHAIN, && case_sem_INSN_X_CTI_CHAIN }, + { LM32BF_INSN_X_CHAIN, && case_sem_INSN_X_CHAIN }, + { LM32BF_INSN_X_BEGIN, && case_sem_INSN_X_BEGIN }, + { LM32BF_INSN_ADD, && case_sem_INSN_ADD }, + { LM32BF_INSN_ADDI, && case_sem_INSN_ADDI }, + { LM32BF_INSN_AND, && case_sem_INSN_AND }, + { LM32BF_INSN_ANDI, && case_sem_INSN_ANDI }, + { LM32BF_INSN_ANDHII, && case_sem_INSN_ANDHII }, + { LM32BF_INSN_B, && case_sem_INSN_B }, + { LM32BF_INSN_BI, && case_sem_INSN_BI }, + { LM32BF_INSN_BE, && case_sem_INSN_BE }, + { LM32BF_INSN_BG, && case_sem_INSN_BG }, + { LM32BF_INSN_BGE, && case_sem_INSN_BGE }, + { LM32BF_INSN_BGEU, && case_sem_INSN_BGEU }, + { LM32BF_INSN_BGU, && case_sem_INSN_BGU }, + { LM32BF_INSN_BNE, && case_sem_INSN_BNE }, + { LM32BF_INSN_CALL, && case_sem_INSN_CALL }, + { LM32BF_INSN_CALLI, && case_sem_INSN_CALLI }, + { LM32BF_INSN_CMPE, && case_sem_INSN_CMPE }, + { LM32BF_INSN_CMPEI, && case_sem_INSN_CMPEI }, + { LM32BF_INSN_CMPG, && case_sem_INSN_CMPG }, + { LM32BF_INSN_CMPGI, && case_sem_INSN_CMPGI }, + { LM32BF_INSN_CMPGE, && case_sem_INSN_CMPGE }, + { LM32BF_INSN_CMPGEI, && case_sem_INSN_CMPGEI }, + { LM32BF_INSN_CMPGEU, && case_sem_INSN_CMPGEU }, + { LM32BF_INSN_CMPGEUI, && case_sem_INSN_CMPGEUI }, + { LM32BF_INSN_CMPGU, && case_sem_INSN_CMPGU }, + { LM32BF_INSN_CMPGUI, && case_sem_INSN_CMPGUI }, + { LM32BF_INSN_CMPNE, && case_sem_INSN_CMPNE }, + { LM32BF_INSN_CMPNEI, && case_sem_INSN_CMPNEI }, + { LM32BF_INSN_DIVU, && case_sem_INSN_DIVU }, + { LM32BF_INSN_LB, && case_sem_INSN_LB }, + { LM32BF_INSN_LBU, && case_sem_INSN_LBU }, + { LM32BF_INSN_LH, && case_sem_INSN_LH }, + { LM32BF_INSN_LHU, && case_sem_INSN_LHU }, + { LM32BF_INSN_LW, && case_sem_INSN_LW }, + { LM32BF_INSN_MODU, && case_sem_INSN_MODU }, + { LM32BF_INSN_MUL, && case_sem_INSN_MUL }, + { LM32BF_INSN_MULI, && case_sem_INSN_MULI }, + { LM32BF_INSN_NOR, && case_sem_INSN_NOR }, + { LM32BF_INSN_NORI, && case_sem_INSN_NORI }, + { LM32BF_INSN_OR, && case_sem_INSN_OR }, + { LM32BF_INSN_ORI, && case_sem_INSN_ORI }, + { LM32BF_INSN_ORHII, && case_sem_INSN_ORHII }, + { LM32BF_INSN_RCSR, && case_sem_INSN_RCSR }, + { LM32BF_INSN_SB, && case_sem_INSN_SB }, + { LM32BF_INSN_SEXTB, && case_sem_INSN_SEXTB }, + { LM32BF_INSN_SEXTH, && case_sem_INSN_SEXTH }, + { LM32BF_INSN_SH, && case_sem_INSN_SH }, + { LM32BF_INSN_SL, && case_sem_INSN_SL }, + { LM32BF_INSN_SLI, && case_sem_INSN_SLI }, + { LM32BF_INSN_SR, && case_sem_INSN_SR }, + { LM32BF_INSN_SRI, && case_sem_INSN_SRI }, + { LM32BF_INSN_SRU, && case_sem_INSN_SRU }, + { LM32BF_INSN_SRUI, && case_sem_INSN_SRUI }, + { LM32BF_INSN_SUB, && case_sem_INSN_SUB }, + { LM32BF_INSN_SW, && case_sem_INSN_SW }, + { LM32BF_INSN_USER, && case_sem_INSN_USER }, + { LM32BF_INSN_WCSR, && case_sem_INSN_WCSR }, + { LM32BF_INSN_XOR, && case_sem_INSN_XOR }, + { LM32BF_INSN_XORI, && case_sem_INSN_XORI }, + { LM32BF_INSN_XNOR, && case_sem_INSN_XNOR }, + { LM32BF_INSN_XNORI, && case_sem_INSN_XNORI }, + { LM32BF_INSN_BREAK, && case_sem_INSN_BREAK }, + { LM32BF_INSN_SCALL, && case_sem_INSN_SCALL }, + { 0, 0 } + }; + int i; + + for (i = 0; labels[i].label != 0; ++i) + { +#if FAST_P + CPU_IDESC (current_cpu) [labels[i].index].sem_fast_lab = labels[i].label; +#else + CPU_IDESC (current_cpu) [labels[i].index].sem_full_lab = labels[i].label; +#endif + } + +#undef DEFINE_LABELS +#endif /* DEFINE_LABELS */ + +#ifdef DEFINE_SWITCH + +/* If hyper-fast [well not unnecessarily slow] execution is selected, turn + off frills like tracing and profiling. */ +/* FIXME: A better way would be to have TRACE_RESULT check for something + that can cause it to be optimized out. Another way would be to emit + special handlers into the instruction "stream". */ + +#if FAST_P +#undef TRACE_RESULT +#define TRACE_RESULT(cpu, abuf, name, type, val) +#endif + +#undef GET_ATTR +#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE) +#define GET_ATTR(cpu, num, attr) CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_##attr) +#else +#define GET_ATTR(cpu, num, attr) CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_/**/attr) +#endif + +{ + +#if WITH_SCACHE_PBB + +/* Branch to next handler without going around main loop. */ +#define NEXT(vpc) goto * SEM_ARGBUF (vpc) -> semantic.sem_case +SWITCH (sem, SEM_ARGBUF (vpc) -> semantic.sem_case) + +#else /* ! WITH_SCACHE_PBB */ + +#define NEXT(vpc) BREAK (sem) +#ifdef __GNUC__ +#if FAST_P + SWITCH (sem, SEM_ARGBUF (sc) -> idesc->sem_fast_lab) +#else + SWITCH (sem, SEM_ARGBUF (sc) -> idesc->sem_full_lab) +#endif +#else + SWITCH (sem, SEM_ARGBUF (sc) -> idesc->num) +#endif + +#endif /* ! WITH_SCACHE_PBB */ + + { + + CASE (sem, INSN_X_INVALID) : /* --invalid-- */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.fmt_empty.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { + /* Update the recorded pc in the cpu state struct. + Only necessary for WITH_SCACHE case, but to avoid the + conditional compilation .... */ + SET_H_PC (pc); + /* Virtual insns have zero size. Overwrite vpc with address of next insn + using the default-insn-bitsize spec. When executing insns in parallel + we may want to queue the fault and continue execution. */ + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + vpc = sim_engine_invalid_insn (current_cpu, pc, vpc); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_X_AFTER) : /* --after-- */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.fmt_empty.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { +#if WITH_SCACHE_PBB_LM32BF + lm32bf_pbb_after (current_cpu, sem_arg); +#endif + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_X_BEFORE) : /* --before-- */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.fmt_empty.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { +#if WITH_SCACHE_PBB_LM32BF + lm32bf_pbb_before (current_cpu, sem_arg); +#endif + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_X_CTI_CHAIN) : /* --cti-chain-- */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.fmt_empty.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { +#if WITH_SCACHE_PBB_LM32BF +#ifdef DEFINE_SWITCH + vpc = lm32bf_pbb_cti_chain (current_cpu, sem_arg, + pbb_br_type, pbb_br_npc); + BREAK (sem); +#else + /* FIXME: Allow provision of explicit ifmt spec in insn spec. */ + vpc = lm32bf_pbb_cti_chain (current_cpu, sem_arg, + CPU_PBB_BR_TYPE (current_cpu), + CPU_PBB_BR_NPC (current_cpu)); +#endif +#endif + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_X_CHAIN) : /* --chain-- */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.fmt_empty.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { +#if WITH_SCACHE_PBB_LM32BF + vpc = lm32bf_pbb_chain (current_cpu, sem_arg); +#ifdef DEFINE_SWITCH + BREAK (sem); +#endif +#endif + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_X_BEGIN) : /* --begin-- */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.fmt_empty.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { +#if WITH_SCACHE_PBB_LM32BF +#if defined DEFINE_SWITCH || defined FAST_P + /* In the switch case FAST_P is a constant, allowing several optimizations + in any called inline functions. */ + vpc = lm32bf_pbb_begin (current_cpu, FAST_P); +#else +#if 0 /* cgen engine can't handle dynamic fast/full switching yet. */ + vpc = lm32bf_pbb_begin (current_cpu, STATE_RUN_FAST_P (CPU_STATE (current_cpu))); +#else + vpc = lm32bf_pbb_begin (current_cpu, 0); +#endif +#endif +#endif + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_ADD) : /* add $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ADDSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_ADDI) : /* addi $r1,$r0,$imm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_AND) : /* and $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_ANDI) : /* andi $r1,$r0,$uimm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_andi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_ANDHII) : /* andhi $r1,$r0,$hi16 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_andi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), SLLSI (FLD (f_uimm), 16)); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_B) : /* b $r0 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_be.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = lm32bf_b_insn (current_cpu, CPU (h_gr[FLD (f_r0)]), FLD (f_r0)); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_BI) : /* bi $call */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_bi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = EXTSISI (FLD (i_call)); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_BE) : /* be $r0,$r1,$branch */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_be.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (EQSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_BG) : /* bg $r0,$r1,$branch */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_be.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (GTSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_BGE) : /* bge $r0,$r1,$branch */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_be.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (GESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_BGEU) : /* bgeu $r0,$r1,$branch */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_be.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (GEUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_BGU) : /* bgu $r0,$r1,$branch */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_be.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (GTUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_BNE) : /* bne $r0,$r1,$branch */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_be.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (NESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CALL) : /* call $r0 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_be.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +{ + { + SI opval = ADDSI (pc, 4); + CPU (h_gr[((UINT) 29)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + { + USI opval = CPU (h_gr[FLD (f_r0)]); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CALLI) : /* calli $call */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_bi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +{ + { + SI opval = ADDSI (pc, 4); + CPU (h_gr[((UINT) 29)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + { + USI opval = EXTSISI (FLD (i_call)); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPE) : /* cmpe $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EQSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPEI) : /* cmpei $r1,$r0,$imm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EQSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPG) : /* cmpg $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GTSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPGI) : /* cmpgi $r1,$r0,$imm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GTSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPGE) : /* cmpge $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPGEI) : /* cmpgei $r1,$r0,$imm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GESI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPGEU) : /* cmpgeu $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GEUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPGEUI) : /* cmpgeui $r1,$r0,$uimm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_andi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GEUSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPGU) : /* cmpgu $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GTUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPGUI) : /* cmpgui $r1,$r0,$uimm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_andi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GTUSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPNE) : /* cmpne $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = NESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_CMPNEI) : /* cmpnei $r1,$r0,$imm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = NESI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_DIVU) : /* divu $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = lm32bf_divu_insn (current_cpu, pc, FLD (f_r0), FLD (f_r1), FLD (f_r2)); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_LB) : /* lb $r1,($r0+$imm) */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EXTQISI (GETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_LBU) : /* lbu $r1,($r0+$imm) */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ZEXTQISI (GETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_LH) : /* lh $r1,($r0+$imm) */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EXTHISI (GETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_LHU) : /* lhu $r1,($r0+$imm) */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ZEXTHISI (GETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_LW) : /* lw $r1,($r0+$imm) */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GETMEMSI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_MODU) : /* modu $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = lm32bf_modu_insn (current_cpu, pc, FLD (f_r0), FLD (f_r1), FLD (f_r2)); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_MUL) : /* mul $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = MULSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_MULI) : /* muli $r1,$r0,$imm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = MULSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_NOR) : /* nor $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = INVSI (ORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_NORI) : /* nori $r1,$r0,$uimm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_andi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = INVSI (ORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_OR) : /* or $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_ORI) : /* ori $r1,$r0,$lo16 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_andi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_ORHII) : /* orhi $r1,$r0,$hi16 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_andi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), SLLSI (FLD (f_uimm), 16)); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_RCSR) : /* rcsr $r2,$csr */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_rcsr.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = CPU (h_csr[FLD (f_csr)]); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SB) : /* sb ($r0+$imm),$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + QI opval = CPU (h_gr[FLD (f_r1)]); + SETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval); + TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SEXTB) : /* sextb $r2,$r0 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EXTQISI (TRUNCSIQI (CPU (h_gr[FLD (f_r0)]))); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SEXTH) : /* sexth $r2,$r0 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EXTHISI (TRUNCSIHI (CPU (h_gr[FLD (f_r0)]))); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SH) : /* sh ($r0+$imm),$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + HI opval = CPU (h_gr[FLD (f_r1)]); + SETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval); + TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SL) : /* sl $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SLLSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SLI) : /* sli $r1,$r0,$imm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SLLSI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm)); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SR) : /* sr $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SRASI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SRI) : /* sri $r1,$r0,$imm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SRASI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm)); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SRU) : /* sru $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SRLSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SRUI) : /* srui $r1,$r0,$imm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SRLSI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm)); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SUB) : /* sub $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SUBSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SW) : /* sw ($r0+$imm),$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_addi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = CPU (h_gr[FLD (f_r1)]); + SETMEMSI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval); + TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_USER) : /* user $r2,$r0,$r1,$user */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = lm32bf_user_insn (current_cpu, CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]), FLD (f_user)); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_WCSR) : /* wcsr $csr,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_wcsr.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +lm32bf_wcsr_insn (current_cpu, FLD (f_csr), CPU (h_gr[FLD (f_r1)])); + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_XOR) : /* xor $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = XORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_XORI) : /* xori $r1,$r0,$uimm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_andi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = XORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_XNOR) : /* xnor $r2,$r0,$r1 */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_user.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = INVSI (XORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_XNORI) : /* xnori $r1,$r0,$uimm */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.sfmt_andi.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = INVSI (XORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_BREAK) : /* break */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.fmt_empty.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = lm32bf_break_insn (current_cpu, pc); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + CASE (sem, INSN_SCALL) : /* scall */ +{ + SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc); + ARGBUF *abuf = SEM_ARGBUF (sem_arg); +#define FLD(f) abuf->fields.fmt_empty.f + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = lm32bf_scall_insn (current_cpu, pc); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); +#undef FLD +} + NEXT (vpc); + + + } + ENDSWITCH (sem) /* End of semantic switch. */ + + /* At this point `vpc' contains the next insn to execute. */ +} + +#undef DEFINE_SWITCH +#endif /* DEFINE_SWITCH */ Index: sim/lm32/sem.c =================================================================== RCS file: sim/lm32/sem.c diff -N sim/lm32/sem.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/sem.c 15 Apr 2009 17:41:27 -0000 @@ -0,0 +1,1669 @@ +/* Simulator instruction semantics for lm32bf. + +THIS FILE IS MACHINE GENERATED WITH CGEN. + +Copyright 1996-2005 Free Software Foundation, Inc. + +This file is part of the GNU simulators. + +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 2, 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, write to the Free Software Foundation, Inc., +51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#define WANT_CPU lm32bf +#define WANT_CPU_LM32BF + +#include "sim-main.h" +#include "cgen-mem.h" +#include "cgen-ops.h" + +#undef GET_ATTR +#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE) +#define GET_ATTR(cpu, num, attr) CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_##attr) +#else +#define GET_ATTR(cpu, num, attr) CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_/**/attr) +#endif + +/* This is used so that we can compile two copies of the semantic code, + one with full feature support and one without that runs fast(er). + FAST_P, when desired, is defined on the command line, -DFAST_P=1. */ +#if FAST_P +#define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_semf_,fn) +#undef TRACE_RESULT +#define TRACE_RESULT(cpu, abuf, name, type, val) +#else +#define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn) +#endif + +/* x-invalid: --invalid-- */ + +static SEM_PC +SEM_FN_NAME (lm32bf,x_invalid) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.fmt_empty.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { + /* Update the recorded pc in the cpu state struct. + Only necessary for WITH_SCACHE case, but to avoid the + conditional compilation .... */ + SET_H_PC (pc); + /* Virtual insns have zero size. Overwrite vpc with address of next insn + using the default-insn-bitsize spec. When executing insns in parallel + we may want to queue the fault and continue execution. */ + vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + vpc = sim_engine_invalid_insn (current_cpu, pc, vpc); + } + + return vpc; +#undef FLD +} + +/* x-after: --after-- */ + +static SEM_PC +SEM_FN_NAME (lm32bf,x_after) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.fmt_empty.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { +#if WITH_SCACHE_PBB_LM32BF + lm32bf_pbb_after (current_cpu, sem_arg); +#endif + } + + return vpc; +#undef FLD +} + +/* x-before: --before-- */ + +static SEM_PC +SEM_FN_NAME (lm32bf,x_before) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.fmt_empty.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { +#if WITH_SCACHE_PBB_LM32BF + lm32bf_pbb_before (current_cpu, sem_arg); +#endif + } + + return vpc; +#undef FLD +} + +/* x-cti-chain: --cti-chain-- */ + +static SEM_PC +SEM_FN_NAME (lm32bf,x_cti_chain) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.fmt_empty.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { +#if WITH_SCACHE_PBB_LM32BF +#ifdef DEFINE_SWITCH + vpc = lm32bf_pbb_cti_chain (current_cpu, sem_arg, + pbb_br_type, pbb_br_npc); + BREAK (sem); +#else + /* FIXME: Allow provision of explicit ifmt spec in insn spec. */ + vpc = lm32bf_pbb_cti_chain (current_cpu, sem_arg, + CPU_PBB_BR_TYPE (current_cpu), + CPU_PBB_BR_NPC (current_cpu)); +#endif +#endif + } + + return vpc; +#undef FLD +} + +/* x-chain: --chain-- */ + +static SEM_PC +SEM_FN_NAME (lm32bf,x_chain) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.fmt_empty.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { +#if WITH_SCACHE_PBB_LM32BF + vpc = lm32bf_pbb_chain (current_cpu, sem_arg); +#ifdef DEFINE_SWITCH + BREAK (sem); +#endif +#endif + } + + return vpc; +#undef FLD +} + +/* x-begin: --begin-- */ + +static SEM_PC +SEM_FN_NAME (lm32bf,x_begin) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.fmt_empty.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0); + + { +#if WITH_SCACHE_PBB_LM32BF +#if defined DEFINE_SWITCH || defined FAST_P + /* In the switch case FAST_P is a constant, allowing several optimizations + in any called inline functions. */ + vpc = lm32bf_pbb_begin (current_cpu, FAST_P); +#else +#if 0 /* cgen engine can't handle dynamic fast/full switching yet. */ + vpc = lm32bf_pbb_begin (current_cpu, STATE_RUN_FAST_P (CPU_STATE (current_cpu))); +#else + vpc = lm32bf_pbb_begin (current_cpu, 0); +#endif +#endif +#endif + } + + return vpc; +#undef FLD +} + +/* add: add $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,add) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ADDSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* addi: addi $r1,$r0,$imm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,addi) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* and: and $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,and) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* andi: andi $r1,$r0,$uimm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,andi) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* andhii: andhi $r1,$r0,$hi16 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,andhii) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), SLLSI (FLD (f_uimm), 16)); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* b: b $r0 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,b) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = lm32bf_b_insn (current_cpu, CPU (h_gr[FLD (f_r0)]), FLD (f_r0)); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* bi: bi $call */ + +static SEM_PC +SEM_FN_NAME (lm32bf,bi) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_bi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = EXTSISI (FLD (i_call)); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* be: be $r0,$r1,$branch */ + +static SEM_PC +SEM_FN_NAME (lm32bf,be) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (EQSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* bg: bg $r0,$r1,$branch */ + +static SEM_PC +SEM_FN_NAME (lm32bf,bg) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (GTSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* bge: bge $r0,$r1,$branch */ + +static SEM_PC +SEM_FN_NAME (lm32bf,bge) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (GESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* bgeu: bgeu $r0,$r1,$branch */ + +static SEM_PC +SEM_FN_NAME (lm32bf,bgeu) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (GEUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* bgu: bgu $r0,$r1,$branch */ + +static SEM_PC +SEM_FN_NAME (lm32bf,bgu) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (GTUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* bne: bne $r0,$r1,$branch */ + +static SEM_PC +SEM_FN_NAME (lm32bf,bne) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +if (NESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) { + { + USI opval = FLD (i_branch); + SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc); + written |= (1 << 3); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + abuf->written = written; + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* call: call $r0 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,call) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_be.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +{ + { + SI opval = ADDSI (pc, 4); + CPU (h_gr[((UINT) 29)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + { + USI opval = CPU (h_gr[FLD (f_r0)]); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* calli: calli $call */ + +static SEM_PC +SEM_FN_NAME (lm32bf,calli) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_bi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +{ + { + SI opval = ADDSI (pc, 4); + CPU (h_gr[((UINT) 29)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + { + USI opval = EXTSISI (FLD (i_call)); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } +} + + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* cmpe: cmpe $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpe) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EQSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* cmpei: cmpei $r1,$r0,$imm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpei) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EQSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* cmpg: cmpg $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpg) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GTSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* cmpgi: cmpgi $r1,$r0,$imm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpgi) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GTSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* cmpge: cmpge $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpge) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* cmpgei: cmpgei $r1,$r0,$imm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpgei) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GESI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* cmpgeu: cmpgeu $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpgeu) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GEUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* cmpgeui: cmpgeui $r1,$r0,$uimm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpgeui) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GEUSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* cmpgu: cmpgu $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpgu) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GTUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* cmpgui: cmpgui $r1,$r0,$uimm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpgui) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GTUSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* cmpne: cmpne $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpne) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = NESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* cmpnei: cmpnei $r1,$r0,$imm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,cmpnei) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = NESI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* divu: divu $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,divu) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = lm32bf_divu_insn (current_cpu, pc, FLD (f_r0), FLD (f_r1), FLD (f_r2)); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* lb: lb $r1,($r0+$imm) */ + +static SEM_PC +SEM_FN_NAME (lm32bf,lb) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EXTQISI (GETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* lbu: lbu $r1,($r0+$imm) */ + +static SEM_PC +SEM_FN_NAME (lm32bf,lbu) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ZEXTQISI (GETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* lh: lh $r1,($r0+$imm) */ + +static SEM_PC +SEM_FN_NAME (lm32bf,lh) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EXTHISI (GETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* lhu: lhu $r1,($r0+$imm) */ + +static SEM_PC +SEM_FN_NAME (lm32bf,lhu) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ZEXTHISI (GETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* lw: lw $r1,($r0+$imm) */ + +static SEM_PC +SEM_FN_NAME (lm32bf,lw) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = GETMEMSI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* modu: modu $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,modu) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = lm32bf_modu_insn (current_cpu, pc, FLD (f_r0), FLD (f_r1), FLD (f_r2)); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* mul: mul $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,mul) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = MULSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* muli: muli $r1,$r0,$imm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,muli) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = MULSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* nor: nor $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,nor) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = INVSI (ORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* nori: nori $r1,$r0,$uimm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,nori) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = INVSI (ORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* or: or $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,or) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* ori: ori $r1,$r0,$lo16 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,ori) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* orhii: orhi $r1,$r0,$hi16 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,orhii) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), SLLSI (FLD (f_uimm), 16)); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* rcsr: rcsr $r2,$csr */ + +static SEM_PC +SEM_FN_NAME (lm32bf,rcsr) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_rcsr.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = CPU (h_csr[FLD (f_csr)]); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* sb: sb ($r0+$imm),$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,sb) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + QI opval = CPU (h_gr[FLD (f_r1)]); + SETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval); + TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* sextb: sextb $r2,$r0 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,sextb) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EXTQISI (TRUNCSIQI (CPU (h_gr[FLD (f_r0)]))); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* sexth: sexth $r2,$r0 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,sexth) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = EXTHISI (TRUNCSIHI (CPU (h_gr[FLD (f_r0)]))); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* sh: sh ($r0+$imm),$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,sh) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + HI opval = CPU (h_gr[FLD (f_r1)]); + SETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval); + TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* sl: sl $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,sl) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SLLSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* sli: sli $r1,$r0,$imm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,sli) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SLLSI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm)); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* sr: sr $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,sr) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SRASI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* sri: sri $r1,$r0,$imm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,sri) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SRASI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm)); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* sru: sru $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,sru) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SRLSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* srui: srui $r1,$r0,$imm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,srui) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SRLSI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm)); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* sub: sub $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,sub) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = SUBSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* sw: sw ($r0+$imm),$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,sw) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_addi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = CPU (h_gr[FLD (f_r1)]); + SETMEMSI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval); + TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* user: user $r2,$r0,$r1,$user */ + +static SEM_PC +SEM_FN_NAME (lm32bf,user) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = lm32bf_user_insn (current_cpu, CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]), FLD (f_user)); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* wcsr: wcsr $csr,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,wcsr) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_wcsr.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + +lm32bf_wcsr_insn (current_cpu, FLD (f_csr), CPU (h_gr[FLD (f_r1)])); + + return vpc; +#undef FLD +} + +/* xor: xor $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,xor) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = XORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* xori: xori $r1,$r0,$uimm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,xori) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = XORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* xnor: xnor $r2,$r0,$r1 */ + +static SEM_PC +SEM_FN_NAME (lm32bf,xnor) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_user.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = INVSI (XORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))); + CPU (h_gr[FLD (f_r2)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* xnori: xnori $r1,$r0,$uimm */ + +static SEM_PC +SEM_FN_NAME (lm32bf,xnori) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.sfmt_andi.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + SI opval = INVSI (XORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)))); + CPU (h_gr[FLD (f_r1)]) = opval; + TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval); + } + + return vpc; +#undef FLD +} + +/* break: break */ + +static SEM_PC +SEM_FN_NAME (lm32bf,break) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.fmt_empty.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = lm32bf_break_insn (current_cpu, pc); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* scall: scall */ + +static SEM_PC +SEM_FN_NAME (lm32bf,scall) (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ +#define FLD(f) abuf->fields.fmt_empty.f + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int UNUSED written = 0; + IADDR UNUSED pc = abuf->addr; + SEM_BRANCH_INIT + SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4); + + { + USI opval = lm32bf_scall_insn (current_cpu, pc); + SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc); + TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval); + } + + SEM_BRANCH_FINI (vpc); + return vpc; +#undef FLD +} + +/* Table of all semantic fns. */ + +static const struct sem_fn_desc sem_fns[] = { + { LM32BF_INSN_X_INVALID, SEM_FN_NAME (lm32bf,x_invalid) }, + { LM32BF_INSN_X_AFTER, SEM_FN_NAME (lm32bf,x_after) }, + { LM32BF_INSN_X_BEFORE, SEM_FN_NAME (lm32bf,x_before) }, + { LM32BF_INSN_X_CTI_CHAIN, SEM_FN_NAME (lm32bf,x_cti_chain) }, + { LM32BF_INSN_X_CHAIN, SEM_FN_NAME (lm32bf,x_chain) }, + { LM32BF_INSN_X_BEGIN, SEM_FN_NAME (lm32bf,x_begin) }, + { LM32BF_INSN_ADD, SEM_FN_NAME (lm32bf,add) }, + { LM32BF_INSN_ADDI, SEM_FN_NAME (lm32bf,addi) }, + { LM32BF_INSN_AND, SEM_FN_NAME (lm32bf,and) }, + { LM32BF_INSN_ANDI, SEM_FN_NAME (lm32bf,andi) }, + { LM32BF_INSN_ANDHII, SEM_FN_NAME (lm32bf,andhii) }, + { LM32BF_INSN_B, SEM_FN_NAME (lm32bf,b) }, + { LM32BF_INSN_BI, SEM_FN_NAME (lm32bf,bi) }, + { LM32BF_INSN_BE, SEM_FN_NAME (lm32bf,be) }, + { LM32BF_INSN_BG, SEM_FN_NAME (lm32bf,bg) }, + { LM32BF_INSN_BGE, SEM_FN_NAME (lm32bf,bge) }, + { LM32BF_INSN_BGEU, SEM_FN_NAME (lm32bf,bgeu) }, + { LM32BF_INSN_BGU, SEM_FN_NAME (lm32bf,bgu) }, + { LM32BF_INSN_BNE, SEM_FN_NAME (lm32bf,bne) }, + { LM32BF_INSN_CALL, SEM_FN_NAME (lm32bf,call) }, + { LM32BF_INSN_CALLI, SEM_FN_NAME (lm32bf,calli) }, + { LM32BF_INSN_CMPE, SEM_FN_NAME (lm32bf,cmpe) }, + { LM32BF_INSN_CMPEI, SEM_FN_NAME (lm32bf,cmpei) }, + { LM32BF_INSN_CMPG, SEM_FN_NAME (lm32bf,cmpg) }, + { LM32BF_INSN_CMPGI, SEM_FN_NAME (lm32bf,cmpgi) }, + { LM32BF_INSN_CMPGE, SEM_FN_NAME (lm32bf,cmpge) }, + { LM32BF_INSN_CMPGEI, SEM_FN_NAME (lm32bf,cmpgei) }, + { LM32BF_INSN_CMPGEU, SEM_FN_NAME (lm32bf,cmpgeu) }, + { LM32BF_INSN_CMPGEUI, SEM_FN_NAME (lm32bf,cmpgeui) }, + { LM32BF_INSN_CMPGU, SEM_FN_NAME (lm32bf,cmpgu) }, + { LM32BF_INSN_CMPGUI, SEM_FN_NAME (lm32bf,cmpgui) }, + { LM32BF_INSN_CMPNE, SEM_FN_NAME (lm32bf,cmpne) }, + { LM32BF_INSN_CMPNEI, SEM_FN_NAME (lm32bf,cmpnei) }, + { LM32BF_INSN_DIVU, SEM_FN_NAME (lm32bf,divu) }, + { LM32BF_INSN_LB, SEM_FN_NAME (lm32bf,lb) }, + { LM32BF_INSN_LBU, SEM_FN_NAME (lm32bf,lbu) }, + { LM32BF_INSN_LH, SEM_FN_NAME (lm32bf,lh) }, + { LM32BF_INSN_LHU, SEM_FN_NAME (lm32bf,lhu) }, + { LM32BF_INSN_LW, SEM_FN_NAME (lm32bf,lw) }, + { LM32BF_INSN_MODU, SEM_FN_NAME (lm32bf,modu) }, + { LM32BF_INSN_MUL, SEM_FN_NAME (lm32bf,mul) }, + { LM32BF_INSN_MULI, SEM_FN_NAME (lm32bf,muli) }, + { LM32BF_INSN_NOR, SEM_FN_NAME (lm32bf,nor) }, + { LM32BF_INSN_NORI, SEM_FN_NAME (lm32bf,nori) }, + { LM32BF_INSN_OR, SEM_FN_NAME (lm32bf,or) }, + { LM32BF_INSN_ORI, SEM_FN_NAME (lm32bf,ori) }, + { LM32BF_INSN_ORHII, SEM_FN_NAME (lm32bf,orhii) }, + { LM32BF_INSN_RCSR, SEM_FN_NAME (lm32bf,rcsr) }, + { LM32BF_INSN_SB, SEM_FN_NAME (lm32bf,sb) }, + { LM32BF_INSN_SEXTB, SEM_FN_NAME (lm32bf,sextb) }, + { LM32BF_INSN_SEXTH, SEM_FN_NAME (lm32bf,sexth) }, + { LM32BF_INSN_SH, SEM_FN_NAME (lm32bf,sh) }, + { LM32BF_INSN_SL, SEM_FN_NAME (lm32bf,sl) }, + { LM32BF_INSN_SLI, SEM_FN_NAME (lm32bf,sli) }, + { LM32BF_INSN_SR, SEM_FN_NAME (lm32bf,sr) }, + { LM32BF_INSN_SRI, SEM_FN_NAME (lm32bf,sri) }, + { LM32BF_INSN_SRU, SEM_FN_NAME (lm32bf,sru) }, + { LM32BF_INSN_SRUI, SEM_FN_NAME (lm32bf,srui) }, + { LM32BF_INSN_SUB, SEM_FN_NAME (lm32bf,sub) }, + { LM32BF_INSN_SW, SEM_FN_NAME (lm32bf,sw) }, + { LM32BF_INSN_USER, SEM_FN_NAME (lm32bf,user) }, + { LM32BF_INSN_WCSR, SEM_FN_NAME (lm32bf,wcsr) }, + { LM32BF_INSN_XOR, SEM_FN_NAME (lm32bf,xor) }, + { LM32BF_INSN_XORI, SEM_FN_NAME (lm32bf,xori) }, + { LM32BF_INSN_XNOR, SEM_FN_NAME (lm32bf,xnor) }, + { LM32BF_INSN_XNORI, SEM_FN_NAME (lm32bf,xnori) }, + { LM32BF_INSN_BREAK, SEM_FN_NAME (lm32bf,break) }, + { LM32BF_INSN_SCALL, SEM_FN_NAME (lm32bf,scall) }, + { 0, 0 } +}; + +/* Add the semantic fns to IDESC_TABLE. */ + +void +SEM_FN_NAME (lm32bf,init_idesc_table) (SIM_CPU *current_cpu) +{ + IDESC *idesc_table = CPU_IDESC (current_cpu); + const struct sem_fn_desc *sf; + int mach_num = MACH_NUM (CPU_MACH (current_cpu)); + + for (sf = &sem_fns[0]; sf->fn != 0; ++sf) + { + const CGEN_INSN *insn = idesc_table[sf->index].idata; + int valid_p = (CGEN_INSN_VIRTUAL_P (insn) + || CGEN_INSN_MACH_HAS_P (insn, mach_num)); +#if FAST_P + if (valid_p) + idesc_table[sf->index].sem_fast = sf->fn; + else + idesc_table[sf->index].sem_fast = SEM_FN_NAME (lm32bf,x_invalid); +#else + if (valid_p) + idesc_table[sf->index].sem_full = sf->fn; + else + idesc_table[sf->index].sem_full = SEM_FN_NAME (lm32bf,x_invalid); +#endif + } +} + Index: sim/lm32/sim-if.c =================================================================== RCS file: sim/lm32/sim-if.c diff -N sim/lm32/sim-if.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/sim-if.c 15 Apr 2009 17:41:28 -0000 @@ -0,0 +1,290 @@ +/* Main simulator entry points specific to Lattice Mico32. + Contributed by Jon Beniston + + Copyright (C) 2009 Free Software Foundation, Inc. + + 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 "sim-main.h" +#include "sim-options.h" +#include "libiberty.h" +#include "bfd.h" + +#ifdef HAVE_STDLIB_H +#include +#endif + +static void free_state (SIM_DESC); +static void print_lm32_misc_cpu (SIM_CPU * cpu, int verbose); +static DECLARE_OPTION_HANDLER (lm32_option_handler); + +enum +{ + OPTION_ENDIAN = OPTION_START, +}; + +/* GDB passes -E, even though it's fixed, so we have to handle it here. common code only handles it if SIM_HAVE_BIENDIAN is defined, which it isn't for lm32. */ +static const OPTION lm32_options[] = { + {{"endian", required_argument, NULL, OPTION_ENDIAN}, + 'E', "big", "Set endianness", + lm32_option_handler}, + {{NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL} +}; + +/* Records simulator descriptor so utilities like lm32_dump_regs can be + called from gdb. */ +SIM_DESC current_state; + +/* Cover function of sim_state_free to free the cpu buffers as well. */ + +static void +free_state (SIM_DESC sd) +{ + if (STATE_MODULES (sd) != NULL) + sim_module_uninstall (sd); + sim_cpu_free_all (sd); + sim_state_free (sd); +} + +/* Find memory range used by program. */ + +static unsigned long +find_base (bfd *prog_bfd) +{ + int found; + unsigned long base = ~(0UL); + asection *s; + + found = 0; + for (s = prog_bfd->sections; s; s = s->next) + { + if ((strcmp (bfd_get_section_name (prog_bfd, s), ".boot") == 0) + || (strcmp (bfd_get_section_name (prog_bfd, s), ".text") == 0) + || (strcmp (bfd_get_section_name (prog_bfd, s), ".data") == 0) + || (strcmp (bfd_get_section_name (prog_bfd, s), ".bss") == 0)) + { + if (!found) + { + base = bfd_get_section_vma (prog_bfd, s); + found = 1; + } + else + base = + bfd_get_section_vma (prog_bfd, + s) < base ? bfd_get_section_vma (prog_bfd, + s) : base; + } + } + return base & ~(0xffffUL); +} + +static unsigned long +find_limit (bfd *prog_bfd) +{ + struct bfd_symbol **asymbols; + long symsize; + long symbol_count; + long s; + + symsize = bfd_get_symtab_upper_bound (prog_bfd); + if (symsize < 0) + return 0; + asymbols = (asymbol **) xmalloc (symsize); + symbol_count = bfd_canonicalize_symtab (prog_bfd, asymbols); + if (symbol_count < 0) + return 0; + + for (s = 0; s < symbol_count; s++) + { + if (!strcmp (asymbols[s]->name, "_fstack")) + return (asymbols[s]->value + 65536) & ~(0xffffUL); + } + return 0; +} + +/* Handle lm32 specific options. */ + +static SIM_RC +lm32_option_handler (sd, cpu, opt, arg, is_command) + SIM_DESC sd; + sim_cpu *cpu; + int opt; + char *arg; + int is_command; +{ + return SIM_RC_OK; +} + +/* Create an instance of the simulator. */ + +SIM_DESC +sim_open (kind, callback, abfd, argv) + SIM_OPEN_KIND kind; + host_callback *callback; + struct bfd *abfd; + char **argv; +{ + SIM_DESC sd = sim_state_alloc (kind, callback); + char c; + int i; + unsigned long base, limit; + + /* The cpu data is kept in a separately allocated chunk of memory. */ + if (sim_cpu_alloc_all (sd, 1, cgen_cpu_max_extra_bytes ()) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + + if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + sim_add_option_table (sd, NULL, lm32_options); + + /* getopt will print the error message so we just have to exit if this fails. + FIXME: Hmmm... in the case of gdb we need getopt to call + print_filtered. */ + if (sim_parse_args (sd, argv) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + +#if 0 + /* Allocate a handler for I/O devices + if no memory for that range has been allocated by the user. + All are allocated in one chunk to keep things from being + unnecessarily complicated. */ + if (sim_core_read_buffer (sd, NULL, read_map, &c, LM32_DEVICE_ADDR, 1) == 0) + sim_core_attach (sd, NULL, 0 /*level */ , + access_read_write, 0 /*space ??? */ , + LM32_DEVICE_ADDR, LM32_DEVICE_LEN /*nr_bytes */ , + 0 /*modulo */ , + &lm32_devices, NULL /*buffer */ ); +#endif + + /* check for/establish the reference program image. */ + if (sim_analyze_program (sd, + (STATE_PROG_ARGV (sd) != NULL + ? *STATE_PROG_ARGV (sd) + : NULL), abfd) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + + /* Check to see if memory exists at programs start address. */ + if (sim_core_read_buffer (sd, NULL, read_map, &c, STATE_START_ADDR (sd), 1) + == 0) + { + if (STATE_PROG_BFD (sd) != NULL) + { + /* It doesn't, so we should try to allocate enough memory to hold program. */ + base = find_base (STATE_PROG_BFD (sd)); + limit = find_limit (STATE_PROG_BFD (sd)); + if (limit == 0) + { + sim_io_eprintf (sd, + "Failed to find symbol _fstack in program. You must specify memory regions with --memory-region.\n"); + free_state (sd); + return 0; + } + /*sim_io_printf (sd, "Allocating memory at 0x%x size 0x%x\n", base, limit); */ + sim_do_commandf (sd, "memory region 0x%x,0x%x", base, limit); + } + } + + /* Establish any remaining configuration options. */ + if (sim_config (sd) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + + if (sim_post_argv_init (sd) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + + /* Open a copy of the cpu descriptor table. */ + { + CGEN_CPU_DESC cd = + lm32_cgen_cpu_open_1 (STATE_ARCHITECTURE (sd)->printable_name, + CGEN_ENDIAN_BIG); + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + SIM_CPU *cpu = STATE_CPU (sd, i); + CPU_CPU_DESC (cpu) = cd; + CPU_DISASSEMBLER (cpu) = sim_cgen_disassemble_insn; + } + lm32_cgen_init_dis (cd); + } + + /* Initialize various cgen things not done by common framework. + Must be done after lm32_cgen_cpu_open. */ + cgen_init (sd); + + /* Store in a global so things like lm32_dump_regs can be invoked + from the gdb command line. */ + current_state = sd; + + return sd; +} + +void +sim_close (sd, quitting) + SIM_DESC sd; + int quitting; +{ + lm32_cgen_cpu_close (CPU_CPU_DESC (STATE_CPU (sd, 0))); + sim_module_uninstall (sd); +} + +SIM_RC +sim_create_inferior (sd, abfd, argv, envp) + SIM_DESC sd; + struct bfd *abfd; + char **argv; + char **envp; +{ + SIM_CPU *current_cpu = STATE_CPU (sd, 0); + SIM_ADDR addr; + + if (abfd != NULL) + addr = bfd_get_start_address (abfd); + else + addr = 0; + sim_pc_set (current_cpu, addr); + +#if 0 + STATE_ARGV (sd) = sim_copy_argv (argv); + STATE_ENVP (sd) = sim_copy_argv (envp); +#endif + + return SIM_RC_OK; +} + +void +sim_do_command (sd, cmd) + SIM_DESC sd; + char *cmd; +{ + if (sim_args_command (sd, cmd) != SIM_RC_OK) + sim_io_eprintf (sd, "Unknown command `%s'\n", cmd); +} Index: sim/lm32/sim-main.h =================================================================== RCS file: sim/lm32/sim-main.h diff -N sim/lm32/sim-main.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/sim-main.h 15 Apr 2009 17:41:28 -0000 @@ -0,0 +1,102 @@ +/* Lattice Mico32 simulator support code + Contributed by Jon Beniston + + Copyright (C) 2009 Free Software Foundation, Inc. + + 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 . */ + +/* Main header for the LM32 simulator. */ + +#ifndef SIM_MAIN_H +#define SIM_MAIN_H + +#define USING_SIM_BASE_H /* FIXME: quick hack */ + +struct _sim_cpu; /* FIXME: should be in sim-basics.h */ +typedef struct _sim_cpu SIM_CPU; + +#include "symcat.h" +#include "sim-basics.h" +#include "cgen-types.h" +#include "lm32-desc.h" +#include "lm32-opc.h" +#include "arch.h" + +/* These must be defined before sim-base.h. */ +typedef USI sim_cia; + +#define CIA_GET(cpu) CPU_PC_GET (cpu) +#define CIA_SET(cpu,val) CPU_PC_SET ((cpu), (val)) + +#define SIM_ENGINE_HALT_HOOK(sd, cpu, cia) \ +do { \ + if (cpu) /* null if ctrl-c */ \ + sim_pc_set ((cpu), (cia)); \ +} while (0) +#define SIM_ENGINE_RESTART_HOOK(sd, cpu, cia) \ +do { \ + sim_pc_set ((cpu), (cia)); \ +} while (0) + +#include "sim-base.h" +#include "cgen-sim.h" +#include "lm32-sim.h" +#include "opcode/cgen.h" + +/* The _sim_cpu struct. */ + +struct _sim_cpu +{ + /* sim/common cpu base. */ + sim_cpu_base base; + + /* Static parts of cgen. */ + CGEN_CPU cgen_cpu; + + /* CPU specific parts go here. + Note that in files that don't need to access these pieces WANT_CPU_FOO + won't be defined and thus these parts won't appear. This is ok in the + sense that things work. It is a source of bugs though. + One has to of course be careful to not take the size of this + struct and no structure members accessed in non-cpu specific files can + go after here. Oh for a better language. */ +#if defined (WANT_CPU_LM32BF) + LM32BF_CPU_DATA cpu_data; +#endif + +}; + +/* The sim_state struct. */ + +struct sim_state +{ + sim_cpu *cpu; +#define STATE_CPU(sd, n) (/*&*/ (sd)->cpu) + + CGEN_STATE cgen_state; + + sim_state_base base; +}; + +/* Misc. */ + +/* Catch address exceptions. */ +extern SIM_CORE_SIGNAL_FN lm32_core_signal; +#define SIM_CORE_SIGNAL(SD,CPU,CIA,MAP,NR_BYTES,ADDR,TRANSFER,ERROR) \ +lm32_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), \ + (TRANSFER), (ERROR)) + +#endif /* SIM_MAIN_H */ Index: sim/lm32/tconfig.in =================================================================== RCS file: sim/lm32/tconfig.in diff -N sim/lm32/tconfig.in --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/tconfig.in 15 Apr 2009 17:41:28 -0000 @@ -0,0 +1,27 @@ +/* Lattice Mico32 simulator configuration. + Contributed by Jon Beniston + + 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 . */ + +#ifndef LM32_TCONFIG_H +#define LM32_TCONFIG_H + +/* See sim-hload.c. We properly handle LMA. */ +#define SIM_HANDLES_LMA 1 + +#define WITH_SCACHE_PBB 1 + +#endif /* LM32_TCONFIG_H */ Index: sim/lm32/traps.c =================================================================== RCS file: sim/lm32/traps.c diff -N sim/lm32/traps.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/traps.c 15 Apr 2009 17:41:28 -0000 @@ -0,0 +1,268 @@ +/* Lattice Mico32 exception and system call support. + Contributed by Jon Beniston + + Copyright (C) 2009 Free Software Foundation, Inc. + + 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 . */ + +#define WANT_CPU lm32bf +#define WANT_CPU_LM32BF + +#include "sim-main.h" +#include "lm32-sim.h" +#include "targ-vals.h" + +/* Read memory function for system call interface. */ + +static int +syscall_read_mem (host_callback * cb, struct cb_syscall *sc, + unsigned long taddr, char *buf, int bytes) +{ + SIM_DESC sd = (SIM_DESC) sc->p1; + SIM_CPU *cpu = (SIM_CPU *) sc->p2; + + return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes); +} + +/* Write memory function for system call interface. */ + +static int +syscall_write_mem (host_callback * cb, struct cb_syscall *sc, + unsigned long taddr, const char *buf, int bytes) +{ + SIM_DESC sd = (SIM_DESC) sc->p1; + SIM_CPU *cpu = (SIM_CPU *) sc->p2; + + return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes); +} + +/* Handle invalid instructions. */ + +SEM_PC +sim_engine_invalid_insn (SIM_CPU * current_cpu, IADDR cia, SEM_PC pc) +{ + SIM_DESC sd = CPU_STATE (current_cpu); + + sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL); + + return pc; +} + +/* Handle divide instructions. */ + +USI +lm32bf_divu_insn (SIM_CPU * current_cpu, IADDR pc, USI r0, USI r1, USI r2) +{ + SIM_DESC sd = CPU_STATE (current_cpu); + host_callback *cb = STATE_CALLBACK (sd); + + /* Check for divide by zero */ + if (GET_H_GR (r1) == 0) + { + if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT) + sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE); + else + { + /* Save PC in exception address register. */ + SET_H_GR (30, pc); + /* Save and clear interrupt enable. */ + SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1); + /* Branch to divide by zero exception handler. */ + return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32; + } + } + else + { + SET_H_GR (r2, (USI) GET_H_GR (r0) / (USI) GET_H_GR (r1)); + return pc + 4; + } +} + +USI +lm32bf_modu_insn (SIM_CPU * current_cpu, IADDR pc, USI r0, USI r1, USI r2) +{ + SIM_DESC sd = CPU_STATE (current_cpu); + host_callback *cb = STATE_CALLBACK (sd); + + /* Check for divide by zero. */ + if (GET_H_GR (r1) == 0) + { + if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT) + sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE); + else + { + /* Save PC in exception address register. */ + SET_H_GR (30, pc); + /* Save and clear interrupt enable. */ + SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1); + /* Branch to divide by zero exception handler. */ + return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32; + } + } + else + { + SET_H_GR (r2, (USI) GET_H_GR (r0) % (USI) GET_H_GR (r1)); + return pc + 4; + } +} + +/* Handle break instructions. */ + +USI +lm32bf_break_insn (SIM_CPU * current_cpu, IADDR pc) +{ + SIM_DESC sd = CPU_STATE (current_cpu); + host_callback *cb = STATE_CALLBACK (sd); + /* Breakpoint. */ + if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT) + { + sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP); + return pc; + } + else + { + /* Save PC in breakpoint address register. */ + SET_H_GR (31, pc); + /* Save and clear interrupt enable. */ + SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 2); + /* Branch to breakpoint exception handler. */ + return GET_H_CSR (LM32_CSR_DEBA) + LM32_EID_BREAKPOINT * 32; + } +} + +/* Handle scall instructions. */ + +USI +lm32bf_scall_insn (SIM_CPU * current_cpu, IADDR pc) +{ + SIM_DESC sd = CPU_STATE (current_cpu); + host_callback *cb = STATE_CALLBACK (sd); + + if ((STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT) + || (GET_H_GR (8) == TARGET_SYS_exit)) + { + /* Delegate system call to host O/S. */ + CB_SYSCALL s; + CB_SYSCALL_INIT (&s); + s.p1 = (PTR) sd; + s.p2 = (PTR) current_cpu; + s.read_mem = syscall_read_mem; + s.write_mem = syscall_write_mem; + /* Extract parameters. */ + s.func = GET_H_GR (8); + s.arg1 = GET_H_GR (1); + s.arg2 = GET_H_GR (2); + s.arg3 = GET_H_GR (3); + /* Halt the simulator if the requested system call is _exit. */ + if (s.func == TARGET_SYS_exit) + sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1); + /* Perform the system call. */ + cb_syscall (cb, &s); + /* Store the return value in the CPU's registers. */ + SET_H_GR (1, s.result); + SET_H_GR (2, s.result2); + SET_H_GR (3, s.errcode); + /* Skip over scall instruction. */ + return pc + 4; + } + else + { + /* Save PC in exception address register. */ + SET_H_GR (30, pc); + /* Save and clear interrupt enable */ + SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1); + /* Branch to system call exception handler. */ + return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_SYSTEM_CALL * 32; + } +} + +/* Handle b instructions. */ + +USI +lm32bf_b_insn (SIM_CPU * current_cpu, USI r0, USI f_r0) +{ + SIM_DESC sd = CPU_STATE (current_cpu); + host_callback *cb = STATE_CALLBACK (sd); + + /* Restore interrupt enable. */ + if (f_r0 == 30) + SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 2) >> 1); + else if (f_r0 == 31) + SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 4) >> 2); + return r0; +} + +/* Handle wcsr instructions. */ + +void +lm32bf_wcsr_insn (SIM_CPU * current_cpu, USI f_csr, USI r1) +{ + SIM_DESC sd = CPU_STATE (current_cpu); + host_callback *cb = STATE_CALLBACK (sd); + + /* Writing a 1 to IP CSR clears a bit, writing 0 has no effect. */ + if (f_csr == LM32_CSR_IP) + SET_H_CSR (f_csr, GET_H_CSR (f_csr) & ~r1); + else + SET_H_CSR (f_csr, r1); +} + +/* Handle signals. */ + +void +lm32_core_signal (SIM_DESC sd, + sim_cpu * cpu, + sim_cia cia, + unsigned map, + int nr_bytes, + address_word addr, + transfer_type transfer, sim_core_signals sig) +{ + const char *copy = (transfer == read_transfer ? "read" : "write"); + address_word ip = CIA_ADDR (cia); + SIM_CPU *current_cpu = cpu; + + switch (sig) + { + case sim_core_unmapped_signal: + sim_io_eprintf (sd, + "core: %d byte %s to unmapped address 0x%lx at 0x%lx\n", + nr_bytes, copy, (unsigned long) addr, + (unsigned long) ip); + SET_H_GR (30, ip); + /* Save and clear interrupt enable. */ + SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1); + CIA_SET (cpu, GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DATA_BUS_ERROR * 32); + sim_engine_halt (sd, cpu, NULL, LM32_EID_DATA_BUS_ERROR * 32, + sim_stopped, SIM_SIGSEGV); + break; + case sim_core_unaligned_signal: + sim_io_eprintf (sd, + "core: %d byte misaligned %s to address 0x%lx at 0x%lx\n", + nr_bytes, copy, (unsigned long) addr, + (unsigned long) ip); + SET_H_GR (30, ip); + /* Save and clear interrupt enable. */ + SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1); + CIA_SET (cpu, GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DATA_BUS_ERROR * 32); + sim_engine_halt (sd, cpu, NULL, LM32_EID_DATA_BUS_ERROR * 32, + sim_stopped, SIM_SIGBUS); + break; + default: + sim_engine_abort (sd, cpu, cia, + "sim_core_signal - internal error - bad switch"); + } +} Index: sim/lm32/user.c =================================================================== RCS file: sim/lm32/user.c diff -N sim/lm32/user.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sim/lm32/user.c 15 Apr 2009 17:41:28 -0000 @@ -0,0 +1,30 @@ +/* Semantics for user defined instructions on the Lattice Mico32. + Contributed by Jon Beniston + + Copyright (C) 2009 Free Software Foundation, Inc. + + 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 "sim-main.h" + +/* Handle user defined instructions. */ + +UINT +lm32bf_user_insn (SIM_CPU * current_cpu, INT r0, INT r1, UINT imm) +{ + /* FIXME: Should probably call code in a user supplied library. */ + return 0; +}