[PATCH] Add support for the Lattice Mico32 (LM32) architecture

Jon Beniston
2008-12-16T00:52:45Z

[-- Attachment #1: Type: text/plain, Size: 2114 bytes --]

Hi,

The following patch adds support for the Lattice Mico32 CPU. Mico32 is an
Open Source 32-bit embedded CPU developed by Lattice Semi. I'm happy to be
listed as the maintainer of this port. I haven't included patches for the
bfd or opcodes directories. They have been sent to the binutils mailing
list.

Regards,
Jon

ChangeLog

gdb/
2008-12-15 Jon Beniston <jon@beniston.com>

* MAINTAINERS: Add Jon Beniston as lm32 maintainer.
* Makefile.in: Add lm32 dependencies.
* NEWS: Indicate lm32 is a new target.
* configure.tgt: Add lm32 targets.
* lm32-linux-tdep.c: New file.
* lm32-linux-tdep.h: New file.
* lm32-tdep.c: New file.

gdb/testsuite
2008-12-15 Jon Beniston <jon@beniston.com>

* gdb.asm/asm-source.exp: Add lm32 target.

include/gdb/
2008-12-15 Jon Beniston <jon@beniston.com>

* sim-lm32.h: New file.

sim/
2008-12-15 Jon Beniston <jon@beniston.com>

* MAINTAINERS: Add Jon Beniston as maintainer of lm32 sim.
* configure.ac: Add lm32 target.
* lm32: New directory.

sim/common
2008-12-15 Jon Beniston <jon@beniston.com>

* gennltvals.sh: Add lm32 target.
* nltvals.def: Add lm32 syscall definitions.

sim/lm32/
2008-12-15 Jon Beniston <jon@beniston.com>

* Makefile.in: New file.
* arch.c: New file.
* arch.h: New file.
* config.in: New file.
* configure: New file.
* configure.ac: New file.
* cpu.c: New file.
* cpu.h: New file.
* cpuall.h: New file.
* decode.c: New file.
* decode.h: New file.
* dv-lm32cpu.c: New file.
* dv-lm32timer.c: New file.
* dv-lm32uart.c: New file.
* lm32.c: New file.
* lm32-sim.h: New file.
* mloop.in: New file.
* model.c: New file.
* sem.c: New file.
* sem-switch.c: New file.
* sim-if.c: New file.
* sim-main.c: New file.
* tconfig.in: New file.
* traps.c: New file.
* user.c: New file.

[-- Attachment #2: lm32.patch --]
[-- Type: application/octet-stream, Size: 318667 bytes --]

Index: gdb/MAINTAINERS
===================================================================
RCS file: /cvs/src/src/gdb/MAINTAINERS,v
retrieving revision 1.407
diff -c -p -r1.407 MAINTAINERS
*** gdb/MAINTAINERS 26 Nov 2008 16:32:59 -0000 1.407
--- gdb/MAINTAINERS 16 Dec 2008 00:41:18 -0000
*************** the native maintainer when resolving ABI
*** 269,274 ****
--- 269,277 ----
ia64 --target=ia64-linux-gnu ,-Werror
(--target=ia64-elf broken)

+ lm32 --target=lm32-elf ,-Werror
+ Jon Beniston, jon@beniston.com
+
m32c --target=m32c-elf ,-Werror
Jim Blandy, jimb@codesourcery.com

Index: gdb/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.1061
diff -c -p -r1.1061 Makefile.in
*** gdb/Makefile.in 2 Dec 2008 07:57:36 -0000 1.1061
--- gdb/Makefile.in 16 Dec 2008 00:41:19 -0000
*************** ALL_TARGET_OBS = \
*** 481,486 ****
--- 481,487 ----
i386-sol2-tdep.o i386-tdep.o i387-tdep.o \
i386-dicos-tdep.o \
iq2000-tdep.o \
+ lm32-linux-tdep.o lm32-tdep.o \
m32c-tdep.o \
m32r-linux-tdep.o m32r-tdep.o \
m68hc11-tdep.o \
*************** ALLDEPFILES = \
*** 1298,1304 ****
irix5-nat.c \
libunwind-frame.c \
linux-fork.c \
! m68hc11-tdep.c \
m32r-tdep.c \
m32r-linux-nat.c m32r-linux-tdep.c \
m68k-tdep.c \
--- 1299,1306 ----
irix5-nat.c \
libunwind-frame.c \
linux-fork.c \
! lm32-linux-tdep.c lm32-tdep.c \
! m68hc11-tdep.c \
m32r-tdep.c \
m32r-linux-nat.c m32r-linux-tdep.c \
m68k-tdep.c \
Index: gdb/NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.296
diff -c -p -r1.296 NEWS
*** gdb/NEWS 2 Dec 2008 07:57:36 -0000 1.296
--- gdb/NEWS 16 Dec 2008 00:41:20 -0000
*************** info os processes
*** 185,190 ****
--- 185,191 ----
* New targets

x86 DICOS i[34567]86-*-dicos*
+ Lattice Mico32 lm32-*

* Removed commands

Index: gdb/configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.206
diff -c -p -r1.206 configure.tgt
*** gdb/configure.tgt 27 Nov 2008 09:23:01 -0000 1.206
--- gdb/configure.tgt 16 Dec 2008 00:41:21 -0000
*************** iq2000-*-*)
*** 231,236 ****
--- 231,245 ----
gdb_sim=../sim/iq2000/libsim.a
;;

+ lm32*-linux-*)
+ gdb_target_obs="lm32-tdep.o lm32-linux-tdep.o"
+ gdb_sim=../sim/lm32/libsim.a
+ build_gdbserver=yes
+ ;;
+ lm32*-*-*)
+ gdb_target_obs="lm32-tdep.o"
+ gdb_sim=../sim/lm32/libsim.a
+ ;;
m32c-*-*)
# Target: Renesas M32C family
gdb_target_obs="m32c-tdep.o prologue-value.o"
Index: gdb/lm32-linux-tdep.c
===================================================================
RCS file: gdb/lm32-linux-tdep.c
diff -N gdb/lm32-linux-tdep.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gdb/lm32-linux-tdep.c 16 Dec 2008 00:41:21 -0000
***************
*** 0 ****
--- 1,759 ----
+ /* Target-dependent code for GNU/Linux running on the LM32.
+
+ Copyright (C) 2008 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 2 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, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+ #include "defs.h"
+ #include "gdbcore.h"
+ #include "target.h"
+ #include "frame.h"
+ #include "osabi.h"
+ #include "elf-bfd.h"
+ #include "frame-unwind.h"
+ #include "regset.h"
+ #include "gdb_string.h"
+ #include "frame-base.h"
+ #include "inferior.h"
+ #include "dis-asm.h"
+ #include "symfile.h"
+ #include "remote.h"
+ #include "arch-utils.h"
+ #include "regcache.h"
+ #include "trad-frame.h"
+ #include "reggroups.h"
+
+ #include "elf/lm32.h"
+ #include "lm32-linux-tdep.h"
+ #include "opcodes/lm32-desc.h"
+
+ #include <signal.h>
+ #include <string.h>
+
+ int lm32_software_single_step (struct frame_info *frame);
+
+ /* Define the size (in bytes) of an lm32 instruction. */
+ static const int lm32_instr_size = 4;
+
+ enum {
+ NORMAL_SIGTRAMP = 1,
+ /* RT_SIGTRAMP = 2 */
+ };
+
+ #define LM32_ELF_NGREG 32
+ typedef unsigned char lm32_elf_greg_t[4];
+ typedef struct { lm32_elf_greg_t reg[LM32_ELF_NGREG]; } lm32_elf_gregset_t;
+
+ /* Macros to extract fields from an instruction */
+ #define LM32_OPCODE(insn) ((insn >> 26) & 0x3f)
+ #define LM32_REG0(insn) ((insn >> 21) & 0x1f)
+ #define LM32_REG1(insn) ((insn >> 16) & 0x1f)
+ #define LM32_REG2(insn) ((insn >> 11) & 0x1f)
+ #define LM32_UIMM16(insn) (insn & 0xffff)
+ #define LM32_IMM16(insn) ((((long)insn & 0xffff) << 16) >> 16)
+ #define LM32_IMM26(insn) ((((long)insn & 0x3ffffff) << 6) >> 6)
+
+ struct gdbarch_tdep
+ {
+ /* gdbarch target dependent data here. Currently unused for LM32. */
+ };
+
+ struct lm32_unwind_cache
+ {
+ /* The previous frame's inner most stack address. Used as this
+ frame ID's stack_addr. */
+ CORE_ADDR prev_sp;
+ /* The frame's base. Used when constructing a frame ID. */
+ CORE_ADDR base;
+ /* Size of frame */
+ int size;
+ /* Whether the function uses fp as a frame pointer */
+ int uses_fp;
+ /* Table indicating the location of each and every register. */
+ struct trad_frame_saved_reg *saved_regs;
+ };
+
+ static int
+ lm32_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
+ {
+ char buf[lm32_instr_size];
+ LONGEST instr;
+ int retval = 0;
+
+ if (target_read_memory (pc, buf, sizeof buf) != 0)
+ return 0;
+
+ instr = extract_unsigned_integer (buf, sizeof buf);
+
+ if (instr == 0x34080077) /* mvi r8, __NR_sigreturn = addi r8, r0, __NR_sigreturn */
+ retval = NORMAL_SIGTRAMP;
+ else
+ return 0;
+
+ if (target_read_memory (pc + lm32_instr_size, buf, sizeof buf) != 0)
+ return 0;
+ instr = extract_unsigned_integer (buf, sizeof buf);
+ if (instr != 0xac000007) /* scall */
+ return 0;
+
+ /* If we get this far, we'll return a non-zero value, this means NORMAL_SIGTRAMP */
+ return retval;
+ }
+
+ static void
+ lm32_linux_supply_gregset (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *gregs, size_t len)
+ {
+ int regi;
+ char zerobuf[MAX_REGISTER_SIZE];
+ const lm32_elf_gregset_t *gregsetp = gregs;
+
+ fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
+ memset (zerobuf, 0, MAX_REGISTER_SIZE);
+
+ regcache_raw_supply (regcache, LM32_R0_REGNUM, zerobuf);
+
+ for (regi = 1; regi <= 32; regi++)
+ {
+ regcache_raw_supply (regcache, regi, &gregsetp->reg[regi]);
+ }
+ }
+
+ static struct regset lm32_linux_gregset =
+ {
+ NULL,
+ lm32_linux_supply_gregset
+ };
+
+ static const struct regset *
+ lm32_linux_regset_from_core_section (struct gdbarch *gdbarch,
+ const char *sect_name, size_t sect_size)
+ {
+ if (strcmp (sect_name, ".reg") == 0
+ && sect_size >= sizeof (lm32_elf_gregset_t))
+ return &lm32_linux_gregset;
+
+ return NULL;
+ }
+
+ static void
+ lm32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+ {
+ /* Set the sigtramp frame sniffer. */
+ //frame_unwind_append_sniffer (gdbarch, lm32_linux_sigtramp_frame_sniffer);
+ set_gdbarch_regset_from_core_section (gdbarch,
+ lm32_linux_regset_from_core_section);
+ }
+
+ static enum gdb_osabi
+ lm32_linux_elf_osabi_sniffer (bfd *abfd)
+ {
+ int elf_flags;
+
+ elf_flags = elf_elfheader (abfd)->e_flags;
+
+ if (elf_flags & EF_LM32_MACH)
+ return GDB_OSABI_LINUX;
+ else
+ return GDB_OSABI_UNKNOWN;
+ }
+ /* Add the available register groups */
+
+ static void
+ lm32_add_reggroups (struct gdbarch *gdbarch)
+ {
+ reggroup_add (gdbarch, general_reggroup);
+ reggroup_add (gdbarch, all_reggroup);
+ reggroup_add (gdbarch, system_reggroup);
+ }
+
+ /* Return whether a given register is in a given group */
+
+ static int
+ lm32_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+ struct reggroup *group)
+ {
+ if (group == general_reggroup)
+ {
+ return ((regnum >= LM32_R0_REGNUM) && (regnum <= LM32_RA_REGNUM))
+ || (regnum == LM32_PC_REGNUM);
+ }
+ else if (group == system_reggroup)
+ {
+ return ( (regnum >= LM32_EA_REGNUM)
+ && (regnum <= LM32_BA_REGNUM)
+ );
+ }
+ return default_register_reggroup_p (gdbarch, regnum, group);
+ }
+
+ /* Return a name that corresponds to the given register number */
+
+ static const char *
+ lm32_register_name (struct gdbarch *gdbarch, int reg_nr)
+ {
+ static char *register_names[] =
+ {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "gp", "fp", "sp", "ra", "ea", "ba",
+ "PC", "EID", "EBA", "DEBA", "IE"
+ };
+
+ if ((reg_nr < 0) || (reg_nr >= sizeof (register_names) / sizeof (register_names[0])))
+ return NULL;
+ else
+ return register_names[reg_nr];
+ }
+
+ /* Return type of register */
+
+ static struct type *
+ lm32_register_type (struct gdbarch *gdbarch, int reg_nr)
+ {
+ return builtin_type_int32;
+ }
+
+ /* Return non-zero if a register can't be written */
+
+ static int
+ lm32_cannot_store_register (struct gdbarch *gdbarch, int regno)
+ {
+ return (regno == LM32_R0_REGNUM);
+ }
+
+ /* Parse a functions prologue */
+
+ static CORE_ADDR
+ lm32_parse_prologue (CORE_ADDR pc)
+ {
+ CORE_ADDR prologue_pc;
+ unsigned long instruction;
+ int done;
+ int op;
+ int i;
+ int literal;
+
+ /* Keep reading though instructions, until we come accross an instruction
+ that isn't likely to be part of the prologue */
+ prologue_pc = pc;
+ done = 0;
+ while (!done)
+ {
+
+ /* Read an instruction */
+ instruction = read_memory_integer (prologue_pc, 4);
+ prologue_pc += 4;
+
+ if ((LM32_OPCODE(instruction) == OP_SW) && (LM32_REG0(instruction) == LM32_SP_REGNUM))
+ {
+ /* Any stack displaced store is likely part of the prologue */
+ pc = prologue_pc;
+ }
+ else if ((LM32_OPCODE(instruction) == OP_ADDI) && (LM32_REG1(instruction) == LM32_SP_REGNUM))
+ {
+ /* An add to the SP is likely to be part of the prologue */
+ pc = prologue_pc;
+ }
+ else if ( /* add fp,fp,sp */
+ ( (LM32_OPCODE(instruction) == OP_ADD)
+ && (LM32_REG2(instruction) == LM32_FP_REGNUM)
+ && (LM32_REG0(instruction) == LM32_FP_REGNUM)
+ && (LM32_REG1(instruction) == LM32_SP_REGNUM)
+ )
+ /* mv fp,imm */
+ || ( (LM32_OPCODE(instruction) == OP_ADDI)
+ && (LM32_REG1(instruction) == LM32_FP_REGNUM)
+ && (LM32_REG0(instruction) == LM32_R0_REGNUM)
+ )
+ )
+ {
+ /* Likely to be in the prologue for functions that require a frame pointer */
+ pc = prologue_pc;
+ }
+ else
+ done = 1;
+ }
+
+ return pc;
+ }
+
+ /* Return PC of first non prologue instruction, for the function at the specified address */
+
+ static CORE_ADDR
+ lm32_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+ {
+ CORE_ADDR func_addr, func_end;
+ struct symtab_and_line sal;
+
+ /* If we have line debugging information, then the end of the
+ prologue should the first assembly instruction of the first source line */
+ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ {
+ sal = find_pc_line (func_addr, 0);
+ if (sal.end && sal.end < func_end)
+ return sal.end;
+ }
+
+ return lm32_parse_prologue (pc);
+ }
+
+ /* Create a breakpoint instruction */
+
+ static const unsigned char *
+ lm32_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
+ {
+ static const unsigned char breakpoint[4] = {OP_RAISE << 2, 0, 0, 2};
+ *lenptr = sizeof (breakpoint);
+ return breakpoint;
+ }
+
+ /* Setup registers and stack for faking a call to a function in the inferior */
+
+ static CORE_ADDR
+ lm32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+ struct regcache *regcache, CORE_ADDR bp_addr,
+ int nargs, struct value **args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr)
+ {
+ int first_arg_reg = LM32_R1_REGNUM;
+ int num_arg_regs = 8;
+ int i;
+
+ /* Set the return address */
+ regcache_cooked_write_signed (regcache, LM32_RA_REGNUM, bp_addr);
+
+ /* If we're returning a large struct, a pointer to the address to
+ store it at is passed as a first hidden parameter */
+ if (struct_return)
+ {
+ regcache_cooked_write_unsigned (regcache, first_arg_reg, struct_addr);
+ first_arg_reg++;
+ num_arg_regs--;
+ sp -= 4;
+ }
+
+ /* Setup parameters */
+ for (i = 0; i < nargs; i++)
+ {
+ struct value *arg = args[i];
+ struct type *arg_type = check_typedef (value_type (arg));
+ char *contents;
+ int len;
+ int j;
+ int reg;
+ ULONGEST val;
+
+ /* Promote small integer types to int */
+ switch (TYPE_CODE (arg_type))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_ENUM:
+ if (TYPE_LENGTH (arg_type) < 4)
+ {
+ arg_type = builtin_type_int32;
+ arg = value_cast (arg_type, arg);
+ }
+ break;
+ }
+
+ /* FIXME: Handle structures */
+
+ contents = (char *) value_contents (arg);
+ len = TYPE_LENGTH (arg_type);
+ val = extract_unsigned_integer (contents, len);
+
+ /* First num_arg_regs parameters go in registers, rest go on stack */
+ if (i < num_arg_regs)
+ {
+ regcache_cooked_write_unsigned (regcache, first_arg_reg + i, val);
+ }
+ else
+ {
+ write_memory (sp, (void *)&val, len);
+ sp -= 4;
+ }
+ }
+
+ /* Update stack pointer */
+ regcache_cooked_write_signed (regcache, LM32_SP_REGNUM, sp);
+
+ /* Return adjusted stack pointer. */
+ return sp;
+ }
+
+ /* Extract return value after calling a function in the inferior */
+
+ static void
+ lm32_extract_return_value (struct type *type, struct regcache *regcache, gdb_byte *valbuf)
+ {
+ int offset;
+ ULONGEST l;
+ CORE_ADDR return_buffer;
+
+ if ( TYPE_CODE(type) != TYPE_CODE_STRUCT
+ && TYPE_CODE(type) != TYPE_CODE_UNION
+ && TYPE_CODE(type) != TYPE_CODE_ARRAY
+ && TYPE_LENGTH (type) <= 4
+ )
+ {
+ /* Return value is returned in a single register */
+ regcache_cooked_read_unsigned (regcache, LM32_R1_REGNUM, &l);
+ store_unsigned_integer (valbuf, TYPE_LENGTH (type), l);
+ }
+ else if ( (TYPE_CODE(type) == TYPE_CODE_INT)
+ && (TYPE_LENGTH (type) == 8)
+ )
+ {
+ /* 64-bit values are returned in a register pair */
+ regcache_cooked_read_unsigned (regcache, LM32_R1_REGNUM, &l);
+ memcpy (valbuf, &l, 4);
+ regcache_cooked_read_unsigned (regcache, LM32_R2_REGNUM, &l);
+ memcpy (valbuf + 4, &l, 4);
+ }
+ else
+ {
+ /* Aggregate types greater than a single register are returned in memory: FIXME: Unless they are only 2 regs? */
+ regcache_cooked_read_unsigned (regcache, LM32_R1_REGNUM, &l);
+ return_buffer = l;
+ read_memory (return_buffer, valbuf, TYPE_LENGTH (type));
+ }
+ }
+
+ /* Write into appropriate registers a function return value of type
+ TYPE, given in virtual format. */
+ static void
+ lm32_store_return_value (struct type *type, struct regcache *regcache,
+ const gdb_byte *valbuf)
+ {
+ ULONGEST val;
+ int len = TYPE_LENGTH (type);
+
+ if (len <= 4)
+ {
+ val = extract_unsigned_integer (valbuf, len);
+ regcache_cooked_write_unsigned (regcache, LM32_R1_REGNUM, val);
+ }
+ else if (len <= 8)
+ {
+ val = extract_unsigned_integer (valbuf, 4);
+ regcache_cooked_write_unsigned (regcache, LM32_R1_REGNUM, val);
+ val = extract_unsigned_integer ((char *)valbuf + 4, len - 4);
+ regcache_cooked_write_unsigned (regcache, LM32_R2_REGNUM, val);
+ }
+ else
+ error (_("lm32_store_return_value: type length too large."));
+ }
+
+ /* Determine whether a functions return value is in a register or memory */
+ static enum return_value_convention
+ lm32_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ struct type *valtype, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
+ {
+ enum type_code code = TYPE_CODE (valtype);
+
+ if ((code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION
+ || code == TYPE_CODE_ARRAY
+ || TYPE_LENGTH (valtype) > 8))
+ return RETURN_VALUE_STRUCT_CONVENTION;
+
+ if (readbuf)
+ lm32_extract_return_value (valtype, regcache, readbuf);
+ if (writebuf)
+ lm32_store_return_value (valtype, regcache, writebuf);
+
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+
+ static CORE_ADDR
+ lm32_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+ {
+ return frame_unwind_register_unsigned (next_frame, LM32_PC_REGNUM);
+ }
+
+ static CORE_ADDR
+ lm32_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+ {
+ return frame_unwind_register_unsigned (next_frame, LM32_SP_REGNUM);
+ }
+
+ static struct frame_id
+ lm32_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+ {
+ CORE_ADDR sp = lm32_unwind_sp (gdbarch, this_frame);
+ return frame_id_build (sp, get_frame_pc (this_frame));
+ }
+
+ /* Put here the code to store, into fi->saved_regs, the addresses of
+ the saved registers of frame described by FRAME_INFO. This
+ includes special registers such as pc and fp saved in special ways
+ in the stack frame. sp is even more special: the address we return
+ for it IS the sp for the next frame. */
+
+ struct lm32_unwind_cache *
+ lm32_frame_unwind_cache (struct frame_info *this_frame, void **this_prologue_cache)
+ {
+ CORE_ADDR start_pc;
+ CORE_ADDR prologue_pc;
+ CORE_ADDR current_pc;
+ ULONGEST prev_sp;
+ ULONGEST this_base;
+ struct lm32_unwind_cache *info;
+ int done;
+ int prefixed;
+ unsigned long instruction;
+ int op;
+ int offsets[32];
+ int i;
+ long immediate;
+ int ra_on_stack;
+
+ if (*this_prologue_cache)
+ return *this_prologue_cache;
+
+ info = FRAME_OBSTACK_ZALLOC (struct lm32_unwind_cache);
+ (*this_prologue_cache) = info;
+ info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+ info->size = 0;
+ info->uses_fp = 0;
+
+ start_pc = get_frame_func (this_frame);
+ current_pc = get_frame_pc (this_frame);
+
+ /* Keep reading through instructions, until we come accross an instruction
+ that isn't likely to be part of the prologue */
+ prologue_pc = start_pc;
+ ra_on_stack = 0;
+ done = 0;
+
+ while (!done && (current_pc > prologue_pc))
+ {
+
+ /* Read an instruction */
+ instruction = read_memory_integer (prologue_pc, 4);
+
+ if ((LM32_OPCODE(instruction) == OP_SW) && (LM32_REG0(instruction) == LM32_SP_REGNUM))
+ {
+ /* Any stack displaced store is likely part of the prologue. */
+ /* Record that the register is being saved, and the offset into the stack. */
+ info->saved_regs[LM32_REG1(instruction)].addr = LM32_IMM16(instruction);
+ /* Check to see if the return address register is being stored on the stack. */
+ if ((LM32_REG1(instruction) == LM32_RA_REGNUM) && (current_pc > prologue_pc))
+ ra_on_stack = 1;
+ }
+ else if ((LM32_OPCODE(instruction) == OP_ADDI) && (LM32_REG1(instruction) == LM32_SP_REGNUM))
+ {
+ /* An add to the SP is likely to be part of the prologue. */
+ /* Adjust stack size by whatever the instruction adds to the sp. */
+ info->size -= LM32_IMM16(instruction);
+ }
+ else if ( /* add fp,fp,sp */
+ ( (LM32_OPCODE(instruction) == OP_ADD)
+ && (LM32_REG2(instruction) == LM32_FP_REGNUM)
+ && (LM32_REG0(instruction) == LM32_FP_REGNUM)
+ && (LM32_REG1(instruction) == LM32_SP_REGNUM)
+ )
+ /* mv fp,imm */
+ || ( (LM32_OPCODE(instruction) == OP_ADDI)
+ && (LM32_REG1(instruction) == LM32_FP_REGNUM)
+ && (LM32_REG0(instruction) == LM32_R0_REGNUM)
+ )
+ )
+ {
+ /* Used in functions with a frame pointer. */
+ info->uses_fp = 1;
+ }
+ else
+ {
+ /* Any other instruction is likely not to be part of the prologue */
+ done = 1;
+ }
+
+ prologue_pc += 4;
+
+ }
+
+ /* Compute the frame's base, and the previous frame's SP. */
+ this_base = frame_unwind_register_unsigned (this_frame, LM32_SP_REGNUM);
+ prev_sp = this_base + info->size;
+ info->base = this_base;
+ info->prev_sp = prev_sp;
+
+ /* Convert callee save offsets into addresses */
+ for (i = 0; i < gdbarch_num_regs (get_frame_arch (this_frame)) - 1; i++)
+ {
+ if (trad_frame_addr_p (info->saved_regs, i))
+ info->saved_regs[i].addr = this_base + info->saved_regs[i].addr;
+ }
+
+ /* The call instruction moves the caller's PC in the callee's RA register.
+ Since this is an unwind, do the reverse. Copy the location of RA register
+ into PC (the address / regnum) so that a request for PC will be
+ converted into a request for the RA register. */
+ info->saved_regs[LM32_PC_REGNUM] = info->saved_regs[LM32_RA_REGNUM];
+
+ /* The previous frame's SP needed to be computed. Save the computed value. */
+ trad_frame_set_value (info->saved_regs, LM32_SP_REGNUM, info->prev_sp);
+
+ return info;
+ }
+
+ /* Given a GDB frame, determine the address of the calling function's
+ frame. This will be used to create a new GDB frame struct. */
+
+ static void
+ lm32_frame_this_id (struct frame_info *this_frame,
+ void **this_prologue_cache,
+ struct frame_id *this_id)
+ {
+ struct lm32_unwind_cache *info;
+ CORE_ADDR base;
+ CORE_ADDR func;
+ struct frame_id id;
+
+ info = lm32_frame_unwind_cache (this_frame, this_prologue_cache);
+
+ /* The FUNC is easy. */
+ func = get_frame_func (this_frame);
+
+ /* Hopefully the prologue analysis either correctly determined the
+ frame's base (which is the SP from the previous frame), or set
+ that base to "NULL". */
+ base = info->base;
+ if (base == 0)
+ return;
+
+ id = frame_id_build (base, func);
+ (*this_id) = id;
+ }
+
+ static struct value *
+ lm32_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache,
+ int regnum)
+ {
+ struct lm32_unwind_cache *info;
+ info = lm32_frame_unwind_cache (this_frame, this_prologue_cache);
+ return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
+ }
+
+ static const struct frame_unwind lm32_frame_unwind = {
+ NORMAL_FRAME,
+ lm32_frame_this_id,
+ lm32_frame_prev_register,
+ NULL,
+ default_frame_sniffer
+ };
+
+ static CORE_ADDR
+ lm32_frame_base_address (struct frame_info *this_frame, void **this_cache)
+ {
+ struct lm32_unwind_cache *info
+ = lm32_frame_unwind_cache (this_frame, this_cache);
+
+ return info->base;
+ }
+
+ static const struct frame_base lm32_frame_base = {
+ &lm32_frame_unwind,
+ lm32_frame_base_address,
+ lm32_frame_base_address,
+ lm32_frame_base_address
+ };
+
+ static struct gdbarch *
+ lm32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ {
+ struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
+
+ /* If there is already a candidate, use it. */
+ arches = gdbarch_list_lookup_by_info (arches, &info);
+ if (arches != NULL)
+ return arches->gdbarch;
+
+ /* None found, create a new architecture from the information provided. */
+ tdep = XMALLOC (struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
+
+ /* Type sizes */
+ set_gdbarch_short_bit (gdbarch, 16);
+ set_gdbarch_int_bit (gdbarch, 32);
+ set_gdbarch_long_bit (gdbarch, 32);
+ set_gdbarch_long_long_bit (gdbarch, 64);
+ set_gdbarch_float_bit (gdbarch, 32);
+ set_gdbarch_double_bit (gdbarch, 64);
+ set_gdbarch_long_double_bit (gdbarch, 64);
+ set_gdbarch_ptr_bit (gdbarch, 32);
+
+ /* Register info */
+ set_gdbarch_num_regs (gdbarch, LM32_NUM_REGS);
+ set_gdbarch_sp_regnum (gdbarch, LM32_SP_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, LM32_PC_REGNUM);
+ set_gdbarch_register_name (gdbarch, lm32_register_name);
+ set_gdbarch_register_type (gdbarch, lm32_register_type);
+ set_gdbarch_cannot_store_register (gdbarch, lm32_cannot_store_register);
+
+ /* Frame info */
+ set_gdbarch_skip_prologue (gdbarch, lm32_skip_prologue);
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ set_gdbarch_decr_pc_after_break (gdbarch, 0);
+ set_gdbarch_frame_args_skip (gdbarch, 0);
+
+ /* Frame unwinding */
+ frame_base_set_default (gdbarch, &lm32_frame_base);
+ set_gdbarch_unwind_pc (gdbarch, lm32_unwind_pc);
+ set_gdbarch_unwind_sp (gdbarch, lm32_unwind_sp);
+ set_gdbarch_dummy_id (gdbarch, lm32_dummy_id);
+ frame_unwind_append_unwinder (gdbarch, &lm32_frame_unwind);
+
+ /* Breakpoints */
+ set_gdbarch_breakpoint_from_pc (gdbarch, lm32_breakpoint_from_pc);
+ set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
+ set_gdbarch_software_single_step (gdbarch, lm32_software_single_step);
+
+ /* Calling functions in the inferior */
+ set_gdbarch_push_dummy_call (gdbarch, lm32_push_dummy_call);
+ set_gdbarch_return_value (gdbarch, lm32_return_value);
+
+ /* Instruction disassembler */
+ set_gdbarch_print_insn (gdbarch, print_insn_lm32);
+
+ lm32_add_reggroups (gdbarch);
+ set_gdbarch_register_reggroup_p (gdbarch, lm32_register_reggroup_p);
+
+ return gdbarch;
+ }
+
+ void
+ _initialize_lm32_tdep (void)
+ {
+ register_gdbarch_init (bfd_arch_lm32, lm32_gdbarch_init);
+ gdbarch_register_osabi (bfd_arch_lm32, 0, GDB_OSABI_LINUX, lm32_linux_init_abi);
+ gdbarch_register_osabi_sniffer (bfd_arch_lm32,
+ bfd_target_elf_flavour,
+ lm32_linux_elf_osabi_sniffer);
+ }
Index: gdb/lm32-linux-tdep.h
===================================================================
RCS file: gdb/lm32-linux-tdep.h
diff -N gdb/lm32-linux-tdep.h
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gdb/lm32-linux-tdep.h 16 Dec 2008 00:41:21 -0000
***************
*** 0 ****
--- 1,68 ----
+ /* Target-dependent code for GNU/Linux running on the LM32.
+
+ Copyright (C) 2008 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 2 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, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+ #ifndef LINUX_TDEP_LM32_H
+ #define LINUX_TDEP_LM32_H
+
+ enum lm32_linux_regs
+ {
+ LM32_R0_REGNUM = 0,
+ LM32_R1_REGNUM,
+ LM32_R2_REGNUM,
+ LM32_R3_REGNUM,
+ LM32_R4_REGNUM,
+ LM32_R5_REGNUM,
+ LM32_R6_REGNUM,
+ LM32_R7_REGNUM,
+ LM32_R8_REGNUM,
+ LM32_R9_REGNUM,
+ LM32_R10_REGNUM,
+ LM32_R11_REGNUM,
+ LM32_R12_REGNUM,
+ LM32_R13_REGNUM,
+ LM32_R14_REGNUM,
+ LM32_R15_REGNUM,
+ LM32_R16_REGNUM,
+ LM32_R17_REGNUM,
+ LM32_R18_REGNUM,
+ LM32_R19_REGNUM,
+ LM32_R20_REGNUM,
+ LM32_R21_REGNUM,
+ LM32_R22_REGNUM,
+ LM32_R23_REGNUM,
+ LM32_R24_REGNUM,
+ LM32_R25_REGNUM,
+ LM32_GP_REGNUM,
+ LM32_FP_REGNUM,
+ LM32_SP_REGNUM,
+ LM32_RA_REGNUM,
+ LM32_EA_REGNUM, /* 30 = 0x1e */
+ LM32_BA_REGNUM,
+ LM32_PC_REGNUM,
+ LM32_NUM_REGS
+ };
+
+ /* Fetch the executable load address for the PIC/FDPIC ABI.
+ Return 0 if successful, -1 if not. */
+ int lm32_load_address(struct gdbarch *gdbarch,
+ CORE_ADDR *load_addr);
+
+ #endif
Index: gdb/lm32-tdep.c
===================================================================
RCS file: gdb/lm32-tdep.c
diff -N gdb/lm32-tdep.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gdb/lm32-tdep.c 16 Dec 2008 00:41:21 -0000
***************
*** 0 ****
--- 1,657 ----
+ /* Target-dependent code for Lattice Mico32 processor, for GDB.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ Copyright (C) 2008 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ #include "defs.h"
+ #include "frame.h"
+ #include "frame-unwind.h"
+ #include "frame-base.h"
+ #include "inferior.h"
+ #include "dis-asm.h"
+ #include "symfile.h"
+ #include "remote.h"
+ #include "gdbcore.h"
+ #include "gdb/sim-lm32.h"
+ #include "gdb/callback.h"
+ #include "gdb/remote-sim.h"
+ #include "sim-regno.h"
+ #include "arch-utils.h"
+ #include "regcache.h"
+ #include "trad-frame.h"
+ #include "reggroups.h"
+ #include "opcodes/lm32-desc.h"
+
+ #include <signal.h>
+ #include <string.h>
+
+ /* Macros to extract fields from an instruction */
+ #define LM32_OPCODE(insn) ((insn >> 26) & 0x3f)
+ #define LM32_REG0(insn) ((insn >> 21) & 0x1f)
+ #define LM32_REG1(insn) ((insn >> 16) & 0x1f)
+ #define LM32_REG2(insn) ((insn >> 11) & 0x1f)
+ #define LM32_UIMM16(insn) (insn & 0xffff)
+ #define LM32_IMM16(insn) ((((long)insn & 0xffff) << 16) >> 16)
+ #define LM32_IMM26(insn) ((((long)insn & 0x3ffffff) << 6) >> 6)
+
+ struct gdbarch_tdep
+ {
+ /* gdbarch target dependent data here. Currently unused for LM32. */
+ };
+
+ struct lm32_unwind_cache
+ {
+ /* The previous frame's inner most stack address. Used as this
+ frame ID's stack_addr. */
+ CORE_ADDR prev_sp;
+ /* The frame's base. Used when constructing a frame ID. */
+ CORE_ADDR base;
+ /* Size of frame */
+ int size;
+ /* Whether the function uses fp as a frame pointer */
+ int uses_fp;
+ /* Table indicating the location of each and every register. */
+ struct trad_frame_saved_reg *saved_regs;
+ };
+
+ /* Add the available register groups */
+
+ static void
+ lm32_add_reggroups (struct gdbarch *gdbarch)
+ {
+ reggroup_add (gdbarch, general_reggroup);
+ reggroup_add (gdbarch, all_reggroup);
+ reggroup_add (gdbarch, system_reggroup);
+ }
+
+ /* Return whether a given register is in a given group */
+
+ static int
+ lm32_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+ struct reggroup *group)
+ {
+ if (group == general_reggroup)
+ {
+ return ((regnum >= SIM_LM32_R0_REGNUM) && (regnum <= SIM_LM32_RA_REGNUM))
+ || (regnum == SIM_LM32_PC_REGNUM);
+ }
+ else if (group == system_reggroup)
+ {
+ return ( (regnum >= SIM_LM32_EA_REGNUM)
+ && (regnum <= SIM_LM32_BA_REGNUM)
+ )
+ || ( (regnum >= SIM_LM32_EID_REGNUM)
+ && (regnum <= SIM_LM32_IE_REGNUM)
+ )
+ ;
+ }
+ return default_register_reggroup_p (gdbarch, regnum, group);
+ }
+
+ /* Return a name that corresponds to the given register number */
+
+ static const char *
+ lm32_register_name (struct gdbarch *gdbarch, int reg_nr)
+ {
+ static char *register_names[] =
+ {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "gp", "fp", "sp", "ra", "ea", "ba",
+ "PC", "EID", "EBA", "DEBA", "IE"
+ };
+
+ if ((reg_nr < 0) || (reg_nr >= sizeof (register_names) / sizeof (register_names[0])))
+ return NULL;
+ else
+ return register_names[reg_nr];
+ }
+
+ /* Return type of register */
+
+ static struct type *
+ lm32_register_type (struct gdbarch *gdbarch, int reg_nr)
+ {
+ return builtin_type_int32;
+ }
+
+ /* Return non-zero if a register can't be written */
+
+ static int
+ lm32_cannot_store_register (struct gdbarch *gdbarch, int regno)
+ {
+ return (regno == SIM_LM32_R0_REGNUM) || (regno == SIM_LM32_EID_REGNUM);
+ }
+
+ /* Parse a functions prologue */
+
+ static CORE_ADDR
+ lm32_parse_prologue (CORE_ADDR pc)
+ {
+ CORE_ADDR prologue_pc;
+ unsigned long instruction;
+ int done;
+ int op;
+ int i;
+ int literal;
+
+ /* Keep reading though instructions, until we come accross an instruction
+ that isn't likely to be part of the prologue */
+ prologue_pc = pc;
+ done = 0;
+ while (!done)
+ {
+
+ /* Read an instruction */
+ instruction = read_memory_integer (prologue_pc, 4);
+ prologue_pc += 4;
+
+ if ((LM32_OPCODE(instruction) == OP_SW) && (LM32_REG0(instruction) == SIM_LM32_SP_REGNUM))
+ {
+ /* Any stack displaced store is likely part of the prologue */
+ pc = prologue_pc;
+ }
+ else if ((LM32_OPCODE(instruction) == OP_ADDI) && (LM32_REG1(instruction) == SIM_LM32_SP_REGNUM))
+ {
+ /* An add to the SP is likely to be part of the prologue */
+ pc = prologue_pc;
+ }
+ else if ( /* add fp,fp,sp */
+ ( (LM32_OPCODE(instruction) == OP_ADD)
+ && (LM32_REG2(instruction) == SIM_LM32_FP_REGNUM)
+ && (LM32_REG0(instruction) == SIM_LM32_FP_REGNUM)
+ && (LM32_REG1(instruction) == SIM_LM32_SP_REGNUM)
+ )
+ /* mv fp,imm */
+ || ( (LM32_OPCODE(instruction) == OP_ADDI)
+ && (LM32_REG1(instruction) == SIM_LM32_FP_REGNUM)
+ && (LM32_REG0(instruction) == SIM_LM32_R0_REGNUM)
+ )
+ )
+ {
+ /* Likely to be in the prologue for functions that require a frame pointer */
+ pc = prologue_pc;
+ }
+ else
+ done = 1;
+ }
+
+ return pc;
+ }
+
+ /* Return PC of first non prologue instruction, for the function at the specified address */
+
+ static CORE_ADDR
+ lm32_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+ {
+ CORE_ADDR func_addr, func_end;
+ struct symtab_and_line sal;
+
+ /* If we have line debugging information, then the end of the
+ prologue should the first assembly instruction of the first source line */
+ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ {
+ sal = find_pc_line (func_addr, 0);
+ if (sal.end && sal.end < func_end)
+ return sal.end;
+ }
+
+ return lm32_parse_prologue (pc);
+ }
+
+ /* Create a breakpoint instruction */
+
+ static const unsigned char *
+ lm32_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
+ {
+ static const unsigned char breakpoint[4] = {OP_RAISE << 2, 0, 0, 2};
+ *lenptr = sizeof (breakpoint);
+ return breakpoint;
+ }
+
+ /* Setup registers and stack for faking a call to a function in the inferior */
+
+ static CORE_ADDR
+ lm32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+ struct regcache *regcache, CORE_ADDR bp_addr,
+ int nargs, struct value **args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr)
+ {
+ int first_arg_reg = SIM_LM32_R1_REGNUM;
+ int num_arg_regs = 8;
+ int i;
+
+ /* Set the return address */
+ regcache_cooked_write_signed (regcache, SIM_LM32_RA_REGNUM, bp_addr);
+
+ /* If we're returning a large struct, a pointer to the address to
+ store it at is passed as a first hidden parameter */
+ if (struct_return)
+ {
+ regcache_cooked_write_unsigned (regcache, first_arg_reg, struct_addr);
+ first_arg_reg++;
+ num_arg_regs--;
+ sp -= 4;
+ }
+
+ /* Setup parameters */
+ for (i = 0; i < nargs; i++)
+ {
+ struct value *arg = args[i];
+ struct type *arg_type = check_typedef (value_type (arg));
+ char *contents;
+ int len;
+ int j;
+ int reg;
+ ULONGEST val;
+
+ /* Promote small integer types to int */
+ switch (TYPE_CODE (arg_type))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_ENUM:
+ if (TYPE_LENGTH (arg_type) < 4)
+ {
+ arg_type = builtin_type_int32;
+ arg = value_cast (arg_type, arg);
+ }
+ break;
+ }
+
+ /* FIXME: Handle structures */
+
+ contents = (char *) value_contents (arg);
+ len = TYPE_LENGTH (arg_type);
+ val = extract_unsigned_integer (contents, len);
+
+ /* First num_arg_regs parameters go in registers, rest go on stack */
+ if (i < num_arg_regs)
+ {
+ regcache_cooked_write_unsigned (regcache, first_arg_reg + i, val);
+ }
+ else
+ {
+ write_memory (sp, (void *)&val, len);
+ sp -= 4;
+ }
+ }
+
+ /* Update stack pointer */
+ regcache_cooked_write_signed (regcache, SIM_LM32_SP_REGNUM, sp);
+
+ /* Return adjusted stack pointer. */
+ return sp;
+ }
+
+ /* Extract return value after calling a function in the inferior */
+
+ static void
+ lm32_extract_return_value (struct type *type, struct regcache *regcache, gdb_byte *valbuf)
+ {
+ int offset;
+ ULONGEST l;
+ CORE_ADDR return_buffer;
+
+ if ( TYPE_CODE(type) != TYPE_CODE_STRUCT
+ && TYPE_CODE(type) != TYPE_CODE_UNION
+ && TYPE_CODE(type) != TYPE_CODE_ARRAY
+ && TYPE_LENGTH (type) <= 4
+ )
+ {
+ /* Return value is returned in a single register */
+ regcache_cooked_read_unsigned (regcache, SIM_LM32_R1_REGNUM, &l);
+ store_unsigned_integer (valbuf, TYPE_LENGTH (type), l);
+ }
+ else if ( (TYPE_CODE(type) == TYPE_CODE_INT)
+ && (TYPE_LENGTH (type) == 8)
+ )
+ {
+ /* 64-bit values are returned in a register pair */
+ regcache_cooked_read_unsigned (regcache, SIM_LM32_R1_REGNUM, &l);
+ memcpy (valbuf, &l, 4);
+ regcache_cooked_read_unsigned (regcache, SIM_LM32_R2_REGNUM, &l);
+ memcpy (valbuf + 4, &l, 4);
+ }
+ else
+ {
+ /* Aggregate types greater than a single register are returned in memory: FIXME: Unless they are only 2 regs? */
+ regcache_cooked_read_unsigned (regcache, SIM_LM32_R1_REGNUM, &l);
+ return_buffer = l;
+ read_memory (return_buffer, valbuf, TYPE_LENGTH (type));
+ }
+ }
+
+ /* Write into appropriate registers a function return value of type
+ TYPE, given in virtual format. */
+ static void
+ lm32_store_return_value (struct type *type, struct regcache *regcache,
+ const gdb_byte *valbuf)
+ {
+ ULONGEST val;
+ int len = TYPE_LENGTH (type);
+
+ if (len <= 4)
+ {
+ val = extract_unsigned_integer (valbuf, len);
+ regcache_cooked_write_unsigned (regcache, SIM_LM32_R1_REGNUM, val);
+ }
+ else if (len <= 8)
+ {
+ val = extract_unsigned_integer (valbuf, 4);
+ regcache_cooked_write_unsigned (regcache, SIM_LM32_R1_REGNUM, val);
+ val = extract_unsigned_integer ((char *)valbuf + 4, len - 4);
+ regcache_cooked_write_unsigned (regcache, SIM_LM32_R2_REGNUM, val);
+ }
+ else
+ error (_("lm32_store_return_value: type length too large."));
+ }
+
+ /* Determine whether a functions return value is in a register or memory */
+ static enum return_value_convention
+ lm32_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ struct type *valtype, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
+ {
+ enum type_code code = TYPE_CODE (valtype);
+
+ if ((code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION
+ || code == TYPE_CODE_ARRAY
+ || TYPE_LENGTH (valtype) > 8))
+ return RETURN_VALUE_STRUCT_CONVENTION;
+
+ if (readbuf)
+ lm32_extract_return_value (valtype, regcache, readbuf);
+ if (writebuf)
+ lm32_store_return_value (valtype, regcache, writebuf);
+
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+
+ static CORE_ADDR
+ lm32_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+ {
+ return frame_unwind_register_unsigned (next_frame, SIM_LM32_PC_REGNUM);
+ }
+
+ static CORE_ADDR
+ lm32_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+ {
+ return frame_unwind_register_unsigned (next_frame, SIM_LM32_SP_REGNUM);
+ }
+
+ static struct frame_id
+ lm32_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+ {
+ CORE_ADDR sp = lm32_unwind_sp (gdbarch, this_frame);
+ return frame_id_build (sp, get_frame_pc (this_frame));
+ }
+
+ /* Put here the code to store, into fi->saved_regs, the addresses of
+ the saved registers of frame described by FRAME_INFO. This
+ includes special registers such as pc and fp saved in special ways
+ in the stack frame. sp is even more special: the address we return
+ for it IS the sp for the next frame. */
+
+ struct lm32_unwind_cache *
+ lm32_frame_unwind_cache (struct frame_info *this_frame, void **this_prologue_cache)
+ {
+ CORE_ADDR start_pc;
+ CORE_ADDR prologue_pc;
+ CORE_ADDR current_pc;
+ ULONGEST prev_sp;
+ ULONGEST this_base;
+ struct lm32_unwind_cache *info;
+ int done;
+ int prefixed;
+ unsigned long instruction;
+ int op;
+ int offsets[32];
+ int i;
+ long immediate;
+ int ra_on_stack;
+
+ if (*this_prologue_cache)
+ return *this_prologue_cache;
+
+ info = FRAME_OBSTACK_ZALLOC (struct lm32_unwind_cache);
+ (*this_prologue_cache) = info;
+ info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+ info->size = 0;
+ info->uses_fp = 0;
+
+ start_pc = get_frame_func (this_frame);
+ current_pc = get_frame_pc (this_frame);
+
+ /* Keep reading through instructions, until we come accross an instruction
+ that isn't likely to be part of the prologue */
+ prologue_pc = start_pc;
+ ra_on_stack = 0;
+ done = 0;
+
+ while (!done && (current_pc > prologue_pc))
+ {
+
+ /* Read an instruction */
+ instruction = read_memory_integer (prologue_pc, 4);
+
+ if ((LM32_OPCODE(instruction) == OP_SW) && (LM32_REG0(instruction) == SIM_LM32_SP_REGNUM))
+ {
+ /* Any stack displaced store is likely part of the prologue. */
+ /* Record that the register is being saved, and the offset into the stack. */
+ info->saved_regs[LM32_REG1(instruction)].addr = LM32_IMM16(instruction);
+ /* Check to see if the return address register is being stored on the stack. */
+ if ((LM32_REG1(instruction) == SIM_LM32_RA_REGNUM) && (current_pc > prologue_pc))
+ ra_on_stack = 1;
+ }
+ else if ((LM32_OPCODE(instruction) == OP_ADDI) && (LM32_REG1(instruction) == SIM_LM32_SP_REGNUM))
+ {
+ /* An add to the SP is likely to be part of the prologue. */
+ /* Adjust stack size by whatever the instruction adds to the sp. */
+ info->size -= LM32_IMM16(instruction);
+ }
+ else if ( /* add fp,fp,sp */
+ ( (LM32_OPCODE(instruction) == OP_ADD)
+ && (LM32_REG2(instruction) == SIM_LM32_FP_REGNUM)
+ && (LM32_REG0(instruction) == SIM_LM32_FP_REGNUM)
+ && (LM32_REG1(instruction) == SIM_LM32_SP_REGNUM)
+ )
+ /* mv fp,imm */
+ || ( (LM32_OPCODE(instruction) == OP_ADDI)
+ && (LM32_REG1(instruction) == SIM_LM32_FP_REGNUM)
+ && (LM32_REG0(instruction) == SIM_LM32_R0_REGNUM)
+ )
+ )
+ {
+ /* Used in functions with a frame pointer. */
+ info->uses_fp = 1;
+ }
+ else
+ {
+ /* Any other instruction is likely not to be part of the prologue */
+ done = 1;
+ }
+
+ prologue_pc += 4;
+
+ }
+
+ /* Compute the frame's base, and the previous frame's SP. */
+ this_base = frame_unwind_register_unsigned (this_frame, SIM_LM32_SP_REGNUM);
+ prev_sp = this_base + info->size;
+ info->base = this_base;
+ info->prev_sp = prev_sp;
+
+ /* Convert callee save offsets into addresses */
+ for (i = 0; i < gdbarch_num_regs (get_frame_arch (this_frame)) - 1; i++)
+ {
+ if (trad_frame_addr_p (info->saved_regs, i))
+ info->saved_regs[i].addr = this_base + info->saved_regs[i].addr;
+ }
+
+ /* The call instruction moves the caller's PC in the callee's RA register.
+ Since this is an unwind, do the reverse. Copy the location of RA register
+ into PC (the address / regnum) so that a request for PC will be
+ converted into a request for the RA register. */
+ info->saved_regs[SIM_LM32_PC_REGNUM] = info->saved_regs[SIM_LM32_RA_REGNUM];
+
+ /* The previous frame's SP needed to be computed. Save the computed value. */
+ trad_frame_set_value (info->saved_regs, SIM_LM32_SP_REGNUM, info->prev_sp);
+
+ return info;
+ }
+
+ /* Given a GDB frame, determine the address of the calling function's
+ frame. This will be used to create a new GDB frame struct. */
+
+ static void
+ lm32_frame_this_id (struct frame_info *this_frame,
+ void **this_prologue_cache,
+ struct frame_id *this_id)
+ {
+ struct lm32_unwind_cache *info;
+ CORE_ADDR base;
+ CORE_ADDR func;
+ struct frame_id id;
+
+ info = lm32_frame_unwind_cache (this_frame, this_prologue_cache);
+
+ /* The FUNC is easy. */
+ func = get_frame_func (this_frame);
+
+ /* Hopefully the prologue analysis either correctly determined the
+ frame's base (which is the SP from the previous frame), or set
+ that base to "NULL". */
+ base = info->base;
+ if (base == 0)
+ return;
+
+ id = frame_id_build (base, func);
+ (*this_id) = id;
+ }
+
+ static struct value *
+ lm32_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache,
+ int regnum)
+ {
+ struct lm32_unwind_cache *info;
+ info = lm32_frame_unwind_cache (this_frame, this_prologue_cache);
+ return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
+ }
+
+ static const struct frame_unwind lm32_frame_unwind = {
+ NORMAL_FRAME,
+ lm32_frame_this_id,
+ lm32_frame_prev_register,
+ NULL,
+ default_frame_sniffer
+ };
+
+ static CORE_ADDR
+ lm32_frame_base_address (struct frame_info *this_frame, void **this_cache)
+ {
+ struct lm32_unwind_cache *info
+ = lm32_frame_unwind_cache (this_frame, this_cache);
+
+ return info->base;
+ }
+
+ static const struct frame_base lm32_frame_base = {
+ &lm32_frame_unwind,
+ lm32_frame_base_address,
+ lm32_frame_base_address,
+ lm32_frame_base_address
+ };
+
+ static struct gdbarch *
+ lm32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ {
+ struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
+
+ /* If there is already a candidate, use it. */
+ arches = gdbarch_list_lookup_by_info (arches, &info);
+ if (arches != NULL)
+ return arches->gdbarch;
+
+ /* None found, create a new architecture from the information provided. */
+ tdep = XMALLOC (struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
+
+ /* Type sizes */
+ set_gdbarch_short_bit (gdbarch, 16);
+ set_gdbarch_int_bit (gdbarch, 32);
+ set_gdbarch_long_bit (gdbarch, 32);
+ set_gdbarch_long_long_bit (gdbarch, 64);
+ set_gdbarch_float_bit (gdbarch, 32);
+ set_gdbarch_double_bit (gdbarch, 64);
+ set_gdbarch_long_double_bit (gdbarch, 64);
+ set_gdbarch_ptr_bit (gdbarch, 32);
+
+ /* Register info */
+ set_gdbarch_num_regs (gdbarch, SIM_LM32_NUM_REGS);
+ set_gdbarch_sp_regnum (gdbarch, SIM_LM32_SP_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, SIM_LM32_PC_REGNUM);
+ set_gdbarch_register_name (gdbarch, lm32_register_name);
+ set_gdbarch_register_type (gdbarch, lm32_register_type);
+ set_gdbarch_cannot_store_register (gdbarch, lm32_cannot_store_register);
+
+ /* Frame info */
+ set_gdbarch_skip_prologue (gdbarch, lm32_skip_prologue);
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ set_gdbarch_decr_pc_after_break (gdbarch, 0);
+ set_gdbarch_frame_args_skip (gdbarch, 0);
+
+ /* Frame unwinding */
+ frame_base_set_default (gdbarch, &lm32_frame_base);
+ set_gdbarch_unwind_pc (gdbarch, lm32_unwind_pc);
+ set_gdbarch_unwind_sp (gdbarch, lm32_unwind_sp);
+ set_gdbarch_dummy_id (gdbarch, lm32_dummy_id);
+ frame_unwind_append_unwinder (gdbarch, &lm32_frame_unwind);
+
+ /* Breakpoints */
+ set_gdbarch_breakpoint_from_pc (gdbarch, lm32_breakpoint_from_pc);
+ set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
+
+ /* Calling functions in the inferior */
+ set_gdbarch_push_dummy_call (gdbarch, lm32_push_dummy_call);
+ set_gdbarch_return_value (gdbarch, lm32_return_value);
+
+ /* Instruction disassembler */
+ set_gdbarch_print_insn (gdbarch, print_insn_lm32);
+
+ lm32_add_reggroups (gdbarch);
+ set_gdbarch_register_reggroup_p (gdbarch, lm32_register_reggroup_p);
+
+ return gdbarch;
+ }
+
+ void
+ _initialize_lm32_tdep (void)
+ {
+ register_gdbarch_init (bfd_arch_lm32, lm32_gdbarch_init);
+ }
+
Index: gdb/testsuite/gdb.asm/asm-source.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.asm/asm-source.exp,v
retrieving revision 1.72
diff -c -p -r1.72 asm-source.exp
*** gdb/testsuite/gdb.asm/asm-source.exp 6 Aug 2008 12:52:06 -0000 1.72
--- gdb/testsuite/gdb.asm/asm-source.exp 16 Dec 2008 00:41:22 -0000
*************** switch -glob -- [istarget] {
*** 64,69 ****
--- 64,72 ----
"i\[3456\]86-*-*" {
set asm-arch i386
}
+ "lm32-*" {
+ set asm-arch lm32
+ }
"m32r*-linux*" {
set asm-arch m32r-linux
}
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 16 Dec 2008 00:41:23 -0000
***************
*** 0 ****
--- 1,75 ----
+ /* This file defines the interface between the LM32 simulator and GDB.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ Copyright (C) 2008 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA */
+
+ #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_NUM_REGS
+ };
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ #endif
Index: sim/MAINTAINERS
===================================================================
RCS file: /cvs/src/src/sim/MAINTAINERS,v
retrieving revision 1.22
diff -c -p -r1.22 MAINTAINERS
*** sim/MAINTAINERS 8 Apr 2008 07:15:39 -0000 1.22
--- sim/MAINTAINERS 16 Dec 2008 00:41:31 -0000
*************** cr16 M R Swami Reddy <MR.Swami.R
*** 14,19 ****
--- 14,20 ----
frv Dave Brolley <brolley@redhat.com>
igen (igen simulators)
ppc Andrew Cagney <ac131313@redhat.com>
+ lm32 Jon Beniston <jon@beniston.com>
m68hc11 Stephane Carrez <stcarrez@nerim.fr>
mips Thiemo Seufer <ths@networkno.de>
sh (global maintainers)
Index: sim/configure.ac
===================================================================
RCS file: /cvs/src/src/sim/configure.ac,v
retrieving revision 1.14
diff -c -p -r1.14 configure.ac
*** sim/configure.ac 8 Apr 2008 09:15:56 -0000 1.14
--- sim/configure.ac 16 Dec 2008 00:41:33 -0000
*************** if test "${enable_sim}" != no; then
*** 74,79 ****
--- 74,83 ----
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 -c -p -r1.4 gennltvals.sh
*** sim/common/gennltvals.sh 8 Apr 2008 08:44:51 -0000 1.4
--- sim/common/gennltvals.sh 16 Dec 2008 00:41:33 -0000
*************** dir=libgloss/v850/sys target=v850
*** 73,75 ****
--- 73,78 ----
$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 -c -p -r1.4 nltvals.def
*** sim/common/nltvals.def 8 Apr 2008 08:44:51 -0000 1.4
--- sim/common/nltvals.def 16 Dec 2008 00:41:33 -0000
***************
*** 454,456 ****
--- 454,483 ----
/* 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 16 Dec 2008 00:41:33 -0000
***************
*** 0 ****
--- 1,90 ----
+ # Makefile for Lattice Mico32 simulator.
+ # Contributed by Jon Beniston <jon@beniston.com>
+
+ ## 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 16 Dec 2008 00:41:33 -0000
***************
*** 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 16 Dec 2008 00:41:33 -0000
***************
*** 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 16 Dec 2008 00:41:33 -0000
***************
*** 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 <dlfcn.h> header file. */
+ #undef HAVE_DLFCN_H
+
+ /* Define to 1 if you have the <errno.h> header file. */
+ #undef HAVE_ERRNO_H
+
+ /* Define to 1 if you have the <fcntl.h> header file. */
+ #undef HAVE_FCNTL_H
+
+ /* Define to 1 if you have the <fpu_control.h> 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 <inttypes.h> 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 <memory.h> 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 <stdint.h> header file. */
+ #undef HAVE_STDINT_H
+
+ /* Define to 1 if you have the <stdlib.h> header file. */
+ #undef HAVE_STDLIB_H
+
+ /* Define to 1 if you have the <strings.h> header file. */
+ #undef HAVE_STRINGS_H
+
+ /* Define to 1 if you have the <string.h> header file. */
+ #undef HAVE_STRING_H
+
+ /* Define to 1 if you have the <sys/resource.h> header file. */
+ #undef HAVE_SYS_RESOURCE_H
+
+ /* Define to 1 if you have the <sys/stat.h> header file. */
+ #undef HAVE_SYS_STAT_H
+
+ /* Define to 1 if you have the <sys/time.h> header file. */
+ #undef HAVE_SYS_TIME_H
+
+ /* Define to 1 if you have the <sys/types.h> 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 <time.h> header file. */
+ #undef HAVE_TIME_H
+
+ /* Define to 1 if you have the <unistd.h> header file. */
+ #undef HAVE_UNISTD_H
+
+ /* Define to 1 if you have the <zlib.h> 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 16 Dec 2008 00:41:33 -0000
***************
*** 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 16 Dec 2008 00:41:33 -0000
***************
*** 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 16 Dec 2008 00:41:33 -0000
***************
*** 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 16 Dec 2008 00:41:33 -0000
***************
*** 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 16 Dec 2008 00:41:34 -0000
***************
*** 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 16 Dec 2008 00:41:34 -0000
***************
*** 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 16 Dec 2008 00:41:34 -0000
***************
*** 0 ****
--- 1,240 ----
+ /* Lattice Mico32 CPU model.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of the program GDB, the GNU debugger.
+
+ 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 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, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+ #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 16 Dec 2008 00:41:34 -0000
***************
*** 0 ****
--- 1,229 ----
+ /* Lattice Mico32 timer model.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of the program GDB, the GNU debugger.
+
+ 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 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, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+ #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, &reg))
+ hw_abort (me, "\"reg\" property must contain three addr/size entries");
+ hw_unit_address_to_attach_address (hw_parent (me),
+ &reg.address,
+ &attach_space,
+ &attach_address,
+ me);
+ timers->base = attach_address;
+ hw_unit_size_to_attach_size (hw_parent (me),
+ &reg.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 16 Dec 2008 00:41:34 -0000
***************
*** 0 ****
--- 1,322 ----
+ /* Lattice Mico32 UART model.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of the program GDB, the GNU debugger.
+
+ 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 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, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+ #include "sim-main.h"
+ #include "hw-main.h"
+ #include "sim-assert.h"
+
+ #include <stdio.h>
+ #include <sys/time.h>
+
+ 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, &reg))
+ hw_abort (me, "\"reg\" property must contain three addr/size entries");
+ hw_unit_address_to_attach_address (hw_parent (me),
+ &reg.address,
+ &attach_space,
+ &attach_address,
+ me);
+ uart->base = attach_address;
+ hw_unit_size_to_attach_size (hw_parent (me),
+ &reg.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 16 Dec 2008 00:41:34 -0000
***************
*** 0 ****
--- 1,56 ----
+ /* Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB, the GNU debugger.
+
+ 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. */
+
+ #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 16 Dec 2008 00:41:34 -0000
***************
*** 0 ****
--- 1,97 ----
+ /* Lattice Mico32 simulator support code.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB, the GNU debugger.
+
+ 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. */
+
+ #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; /*FIXME*/
+ }
+
+ /* 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; /*FIXME*/
+ }
+
+
+
+ #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 16 Dec 2008 00:41:35 -0000
***************
*** 0 ****
--- 1,203 ----
+ # Simulator main loop for lm32. -*- C -*-
+ # Contributed by Jon Beniston <jon@beniston.com>
+ #
+ # 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 <<EOF
+
+ static INLINE const IDESC *
+ extract (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
+ ARGBUF *abuf, int fast_p)
+ {
+ const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
+
+ @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
+ if (! fast_p)
+ {
+ int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
+ int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
+ @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p);
+ }
+ return id;
+ }
+
+ static INLINE SEM_PC
+ execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p)
+ {
+ SEM_PC vpc;
+
+ if (fast_p)
+ {
+ #if ! WITH_SEM_SWITCH_FAST
+ #if WITH_SCACHE
+ vpc = (*sc->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 <<EOF
+ {
+ CGEN_INSN_INT insn = GETIMEMUSI (current_cpu, vpc);
+ extract (current_cpu, vpc, insn, SEM_ARGBUF (sc), FAST_P);
+ }
+ EOF
+
+ ;;
+
+ xextract-pbb)
+
+ # Inputs: current_cpu, pc, sc, max_insns, FAST_P
+ # Outputs: sc, pc
+ # sc must be left pointing past the last created entry.
+ # pc must be left pointing past the last created entry.
+ # If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called
+ # to record the vpc of the cti insn.
+ # SET_INSN_COUNT(n) must be called to record number of real insns.
+
+ cat <<EOF
+ {
+ const IDESC *idesc;
+ int icount = 0;
+
+ while (max_insns > 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 <<EOF
+ /* Update cycle counter */
+ SET_H_CSR (LM32_CSR_CC, GET_H_CSR (LM32_CSR_CC) + 1);
+ #if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST)
+ #define DEFINE_SWITCH
+ #include "sem-switch.c"
+ #else
+ vpc = execute (current_cpu, vpc, FAST_P);
+ #endif
+ EOF
+
+ ;;
+
+ *)
+ echo "Invalid argument to mainloop.in: $1" >&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 16 Dec 2008 00:41:35 -0000
***************
*** 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 16 Dec 2008 00:41:36 -0000
***************
*** 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 16 Dec 2008 00:41:36 -0000
***************
*** 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 16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,287 ----
+ /* Main simulator entry points specific to Lattice Mico32.
+ Written by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB, the GNU debugger.
+
+ 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. */
+
+ #include "sim-main.h"
+ #include "sim-options.h"
+ #include "libiberty.h"
+ #include "bfd.h"
+
+ #ifdef HAVE_STDLIB_H
+ #include <stdlib.h>
+ #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;
+ \f
+ /* 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);
+ }
+ \f
+ 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 16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,99 ----
+ /* LM32 simulator support code
+ Written by Jon Beniston <jon@beniston.com>
+
+ 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. */
+
+ /* 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"
+ \f
+ /* 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
+
+ };
+ \f
+ /* 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;
+ };
+ \f
+ /* 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 16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,28 ----
+ /* LatticeMico32 simulator configuration.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB, the GNU debugger.
+
+ 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. */
+
+ #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 16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,264 ----
+ /* Lattice Mico32 exception and system call support.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB, the GNU debugger.
+
+ 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. */
+
+ #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 16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,29 ----
+ /* Semantics for user defined instructions on the Lattice Mico32.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB, the GNU debugger.
+
+ 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. */
+
+ #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;
+ }