* [PATCH] Add support for the Lattice Mico32 (LM32) architecture
@ 2008-12-16 0:52 Jon Beniston
0 siblings, 0 replies; 15+ messages in thread
From: Jon Beniston @ 2008-12-16 0:52 UTC (permalink / raw)
To: gdb-patches
[-- 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, ®))
+ hw_abort (me, "\"reg\" property must contain three addr/size entries");
+ hw_unit_address_to_attach_address (hw_parent (me),
+ ®.address,
+ &attach_space,
+ &attach_address,
+ me);
+ timers->base = attach_address;
+ hw_unit_size_to_attach_size (hw_parent (me),
+ ®.size,
+ &attach_size, me);
+ timers->limit = attach_address + (attach_size - 1);
+ hw_attach_address (hw_parent (me),
+ 0,
+ attach_space, attach_address, attach_size,
+ me);
+ }
+
+ static void
+ lm32timer_finish (struct hw *me)
+ {
+ struct lm32timer *timers;
+ int i;
+
+ timers = HW_ZALLOC (me, struct lm32timer);
+ set_hw_data (me, timers);
+ set_hw_io_read_buffer (me, lm32timer_io_read_buffer);
+ set_hw_io_write_buffer (me, lm32timer_io_write_buffer);
+ set_hw_ports (me, lm32timer_ports);
+
+ /* Attach ourself to our parent bus */
+ attach_lm32timer_regs (me, timers);
+
+ /* Initialize the timers */
+ timers->status = 0;
+ timers->control = 0;
+ timers->period = 0;
+ timers->snapshot = 0;
+ }
+
+ const struct hw_descriptor dv_lm32timer_descriptor[] = {
+ { "lm32timer", lm32timer_finish, },
+ { NULL },
+ };
Index: sim/lm32/dv-lm32uart.c
===================================================================
RCS file: sim/lm32/dv-lm32uart.c
diff -N sim/lm32/dv-lm32uart.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- sim/lm32/dv-lm32uart.c 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, ®))
+ hw_abort (me, "\"reg\" property must contain three addr/size entries");
+ hw_unit_address_to_attach_address (hw_parent (me),
+ ®.address,
+ &attach_space,
+ &attach_address,
+ me);
+ uart->base = attach_address;
+ hw_unit_size_to_attach_size (hw_parent (me),
+ ®.size,
+ &attach_size, me);
+ uart->limit = attach_address + (attach_size - 1);
+ hw_attach_address (hw_parent (me),
+ 0,
+ attach_space, attach_address, attach_size,
+ me);
+ }
+
+ static void
+ lm32uart_finish (struct hw *me)
+ {
+ struct lm32uart *uart;
+ int i;
+
+ uart = HW_ZALLOC (me, struct lm32uart);
+ set_hw_data (me, uart);
+ set_hw_io_read_buffer (me, lm32uart_io_read_buffer);
+ set_hw_io_write_buffer (me, lm32uart_io_write_buffer);
+ set_hw_ports (me, lm32uart_ports);
+
+ /* Attach ourself to our parent bus */
+ attach_lm32uart_regs (me, uart);
+
+ /* Initialize the UART */
+ uart->rbr = 0;
+ uart->thr = 0;
+ uart->ier = 0;
+ uart->iir = 0;
+ uart->lcr = 0;
+ uart->mcr = 0;
+ uart->lsr = LM32_UART_LSR_TX_RDY;
+ uart->msr = 0;
+ uart->div = 0; /* By setting to zero, characters are output immediately */
+ }
+
+ const struct hw_descriptor dv_lm32uart_descriptor[] = {
+ { "lm32uart", lm32uart_finish, },
+ { NULL },
+ };
+
Index: sim/lm32/lm32-sim.h
===================================================================
RCS file: sim/lm32/lm32-sim.h
diff -N sim/lm32/lm32-sim.h
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- sim/lm32/lm32-sim.h 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;
+ }
^ permalink raw reply [flat|nested] 15+ messages in thread* RE: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
@ 2008-12-22 12:06 Jon Beniston
2009-02-07 4:14 ` Joel Brobecker
0 siblings, 1 reply; 15+ messages in thread
From: Jon Beniston @ 2008-12-22 12:06 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 2002 bytes --]
Hi,
The attached patch superceeds the patch I sent last week to add support for
Lattice Mico32. It fixes a bug and addresses some comments I have received
with regard to copyright headers etc.
Cheers,
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: 318309 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 20 Dec 2008 22:02:19 -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 20 Dec 2008 22:02:20 -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 20 Dec 2008 22:02:22 -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 20 Dec 2008 22:02:22 -0000
*************** iq2000-*-*)
*** 231,236 ****
--- 231,245 ----
gdb_sim=../sim/iq2000/libsim.a
;;
+ lm32*-*-uclinux*)
+ 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 20 Dec 2008 22:02:23 -0000
***************
*** 0 ****
--- 1,772 ----
+ /* Target-dependent code for GNU/Linux running on the Lattice Mico32.
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #include "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));
+ }
+
+ 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 = get_frame_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 CORE_ADDR
+ lm32_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+ {
+ /* Align to the size of an instruction (so that they can safely be
+ pushed onto the stack. */
+ return sp & ~3;
+ }
+
+ 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 */
+ set_gdbarch_frame_align (gdbarch, lm32_frame_align);
+ 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 20 Dec 2008 22:02:23 -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 20 Dec 2008 22:02:23 -0000
***************
*** 0 ****
--- 1,677 ----
+ /* 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #include "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 = get_frame_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 CORE_ADDR
+ lm32_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+ {
+ /* Align to the size of an instruction (so that they can safely be
+ pushed onto the stack. */
+ return sp & ~3;
+ }
+
+ 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 */
+ set_gdbarch_frame_align (gdbarch, lm32_frame_align);
+ 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 20 Dec 2008 22:02:24 -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 20 Dec 2008 22:02:25 -0000
***************
*** 0 ****
--- 1,74 ----
+ /* 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #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 20 Dec 2008 22:02:33 -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 20 Dec 2008 22:02:35 -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 20 Dec 2008 22:02:35 -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 20 Dec 2008 22:02:35 -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 20 Dec 2008 22:02:35 -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 20 Dec 2008 22:02:35 -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 20 Dec 2008 22:02:35 -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 20 Dec 2008 22:02:35 -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 20 Dec 2008 22:02:35 -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 20 Dec 2008 22:02:35 -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 20 Dec 2008 22:02:35 -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 20 Dec 2008 22:02:35 -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 20 Dec 2008 22:02:36 -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 20 Dec 2008 22:02:36 -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 20 Dec 2008 22:02:36 -0000
***************
*** 0 ****
--- 1,239 ----
+ /* Lattice Mico32 CPU model.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #include "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 20 Dec 2008 22:02:36 -0000
***************
*** 0 ****
--- 1,228 ----
+ /* Lattice Mico32 timer model.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #include "sim-main.h"
+ #include "hw-main.h"
+ #include "sim-assert.h"
+
+ struct lm32timer {
+ unsigned base; /* Base address of this timer */
+ unsigned limit; /* Limit address of this timer */
+ unsigned int status;
+ unsigned int control;
+ unsigned int period;
+ unsigned int snapshot;
+ struct hw_event* event;
+ };
+
+ /* Timer registers */
+ #define LM32_TIMER_STATUS 0x0
+ #define LM32_TIMER_CONTROL 0x4
+ #define LM32_TIMER_PERIOD 0x8
+ #define LM32_TIMER_SNAPSHOT 0xc
+
+ /* Timer ports */
+
+ enum {
+ INT_PORT
+ };
+
+ static const struct hw_port_descriptor lm32timer_ports[] = {
+ { "int", INT_PORT, 0, output_port },
+ {}
+ };
+
+ static void
+ do_timer_event (struct hw *me, void *data)
+ {
+ struct lm32timer *timer = hw_data (me);
+
+ /* Is timer started? */
+ if (timer->control & 0x4)
+ {
+ if (timer->snapshot)
+ {
+ /* Decrement timer */
+ timer->snapshot--;
+ }
+ else if (timer->control & 1)
+ {
+ /* Restart timer */
+ timer->snapshot = timer->period;
+ }
+ }
+ /* Generate interrupt when timer is at 0, and interrupt enable is 1 */
+ if ((timer->snapshot == 0) && (timer->control & 1))
+ {
+ /* Generate interrupt */
+ hw_port_event (me, INT_PORT, 1);
+ }
+ /* If timer is started, schedule another event to decrement the timer again */
+ if (timer->control & 4)
+ hw_event_queue_schedule (me, 1, do_timer_event, 0);
+ }
+
+ static unsigned
+ lm32timer_io_write_buffer (struct hw *me,
+ const void *source,
+ int space,
+ unsigned_word base,
+ unsigned nr_bytes)
+ {
+ struct lm32timer *timers = hw_data (me);
+ int timer_reg;
+ const unsigned char *source_bytes = source;
+ int value = 0;
+
+ HW_TRACE ((me, "write to 0x%08lx length %d with 0x%x", (long) base,
+ (int) nr_bytes, value));
+
+ if (nr_bytes == 4)
+ value = (source_bytes[0] << 24)
+ | (source_bytes[1] << 16)
+ | (source_bytes[2] << 8)
+ | (source_bytes[3]);
+ else
+ hw_abort (me, "write with invalid number of bytes: %d", nr_bytes);
+
+ timer_reg = base - timers->base;
+
+ switch (timer_reg)
+ {
+ case LM32_TIMER_STATUS:
+ timers->status = value;
+ break;
+ case LM32_TIMER_CONTROL:
+ timers->control = value;
+ if (timers->control & 0x4)
+ {
+ /* Timer is started */
+ hw_event_queue_schedule (me, 1, do_timer_event, 0);
+ }
+ break;
+ case LM32_TIMER_PERIOD:
+ timers->period = value;
+ break;
+ default:
+ hw_abort (me, "invalid register address: 0x%x.", timer_reg);
+ }
+
+ return nr_bytes;
+ }
+
+ static unsigned
+ lm32timer_io_read_buffer (struct hw *me,
+ void *dest,
+ int space,
+ unsigned_word base,
+ unsigned nr_bytes)
+ {
+ struct lm32timer *timers = hw_data (me);
+ int timer_reg;
+ int value;
+ unsigned char *dest_bytes = dest;
+
+ HW_TRACE ((me, "read 0x%08lx length %d", (long) base, (int) nr_bytes));
+
+ timer_reg = base - timers->base;
+
+ switch (timer_reg)
+ {
+ case LM32_TIMER_STATUS:
+ value = timers->status;
+ break;
+ case LM32_TIMER_CONTROL:
+ value = timers->control;
+ break;
+ case LM32_TIMER_PERIOD:
+ value = timers->period;
+ break;
+ case LM32_TIMER_SNAPSHOT:
+ value = timers->snapshot;
+ break;
+ default:
+ hw_abort (me, "invalid register address: 0x%x.", timer_reg);
+ }
+
+ if (nr_bytes == 4)
+ {
+ dest_bytes[0] = value >> 24;
+ dest_bytes[1] = value >> 16;
+ dest_bytes[2] = value >> 8;
+ dest_bytes[3] = value;
+ }
+ else
+ hw_abort (me, "read of unsupported number of bytes: %d", nr_bytes);
+
+ return nr_bytes;
+ }
+
+ static void
+ attach_lm32timer_regs (struct hw *me, struct lm32timer *timers)
+ {
+ unsigned_word attach_address;
+ int attach_space;
+ unsigned attach_size;
+ reg_property_spec reg;
+
+ if (hw_find_property (me, "reg") == NULL)
+ hw_abort (me, "Missing \"reg\" property");
+ if (!hw_find_reg_array_property (me, "reg", 0, ®))
+ hw_abort (me, "\"reg\" property must contain three addr/size entries");
+ hw_unit_address_to_attach_address (hw_parent (me),
+ ®.address,
+ &attach_space,
+ &attach_address,
+ me);
+ timers->base = attach_address;
+ hw_unit_size_to_attach_size (hw_parent (me),
+ ®.size,
+ &attach_size, me);
+ timers->limit = attach_address + (attach_size - 1);
+ hw_attach_address (hw_parent (me),
+ 0,
+ attach_space, attach_address, attach_size,
+ me);
+ }
+
+ static void
+ lm32timer_finish (struct hw *me)
+ {
+ struct lm32timer *timers;
+ int i;
+
+ timers = HW_ZALLOC (me, struct lm32timer);
+ set_hw_data (me, timers);
+ set_hw_io_read_buffer (me, lm32timer_io_read_buffer);
+ set_hw_io_write_buffer (me, lm32timer_io_write_buffer);
+ set_hw_ports (me, lm32timer_ports);
+
+ /* Attach ourself to our parent bus */
+ attach_lm32timer_regs (me, timers);
+
+ /* Initialize the timers */
+ timers->status = 0;
+ timers->control = 0;
+ timers->period = 0;
+ timers->snapshot = 0;
+ }
+
+ const struct hw_descriptor dv_lm32timer_descriptor[] = {
+ { "lm32timer", lm32timer_finish, },
+ { NULL },
+ };
Index: sim/lm32/dv-lm32uart.c
===================================================================
RCS file: sim/lm32/dv-lm32uart.c
diff -N sim/lm32/dv-lm32uart.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- sim/lm32/dv-lm32uart.c 20 Dec 2008 22:02:36 -0000
***************
*** 0 ****
--- 1,321 ----
+ /* Lattice Mico32 UART model.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #include "sim-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, ®))
+ hw_abort (me, "\"reg\" property must contain three addr/size entries");
+ hw_unit_address_to_attach_address (hw_parent (me),
+ ®.address,
+ &attach_space,
+ &attach_address,
+ me);
+ uart->base = attach_address;
+ hw_unit_size_to_attach_size (hw_parent (me),
+ ®.size,
+ &attach_size, me);
+ uart->limit = attach_address + (attach_size - 1);
+ hw_attach_address (hw_parent (me),
+ 0,
+ attach_space, attach_address, attach_size,
+ me);
+ }
+
+ static void
+ lm32uart_finish (struct hw *me)
+ {
+ struct lm32uart *uart;
+ int i;
+
+ uart = HW_ZALLOC (me, struct lm32uart);
+ set_hw_data (me, uart);
+ set_hw_io_read_buffer (me, lm32uart_io_read_buffer);
+ set_hw_io_write_buffer (me, lm32uart_io_write_buffer);
+ set_hw_ports (me, lm32uart_ports);
+
+ /* Attach ourself to our parent bus */
+ attach_lm32uart_regs (me, uart);
+
+ /* Initialize the UART */
+ uart->rbr = 0;
+ uart->thr = 0;
+ uart->ier = 0;
+ uart->iir = 0;
+ uart->lcr = 0;
+ uart->mcr = 0;
+ uart->lsr = LM32_UART_LSR_TX_RDY;
+ uart->msr = 0;
+ uart->div = 0; /* By setting to zero, characters are output immediately */
+ }
+
+ const struct hw_descriptor dv_lm32uart_descriptor[] = {
+ { "lm32uart", lm32uart_finish, },
+ { NULL },
+ };
+
Index: sim/lm32/lm32-sim.h
===================================================================
RCS file: sim/lm32/lm32-sim.h
diff -N sim/lm32/lm32-sim.h
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- sim/lm32/lm32-sim.h 20 Dec 2008 22:02:36 -0000
***************
*** 0 ****
--- 1,55 ----
+ /* Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #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 20 Dec 2008 22:02:36 -0000
***************
*** 0 ****
--- 1,96 ----
+ /* Lattice Mico32 simulator support code.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #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 20 Dec 2008 22:02:36 -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 20 Dec 2008 22:02:37 -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 20 Dec 2008 22:02:37 -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 20 Dec 2008 22:02:38 -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 20 Dec 2008 22:02:38 -0000
***************
*** 0 ****
--- 1,286 ----
+ /* Main simulator entry points specific to Lattice Mico32.
+ Written by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #include "sim-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 20 Dec 2008 22:02:38 -0000
***************
*** 0 ****
--- 1,98 ----
+ /* Lattice Mico32 simulator support code
+ Written by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ /* 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 20 Dec 2008 22:02:38 -0000
***************
*** 0 ****
--- 1,27 ----
+ /* Lattice Mico32 simulator configuration.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #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 20 Dec 2008 22:02:38 -0000
***************
*** 0 ****
--- 1,263 ----
+ /* Lattice Mico32 exception and system call support.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #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 20 Dec 2008 22:02:38 -0000
***************
*** 0 ****
--- 1,28 ----
+ /* Semantics for user defined instructions on the Lattice Mico32.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #include "sim-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;
+ }
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2008-12-22 12:06 Jon Beniston
@ 2009-02-07 4:14 ` Joel Brobecker
2009-04-15 18:09 ` Jon Beniston
0 siblings, 1 reply; 15+ messages in thread
From: Joel Brobecker @ 2009-02-07 4:14 UTC (permalink / raw)
To: Jon Beniston; +Cc: gdb-patches
Jon,
Sorry for the delay in reviewing this patch. This is a fairly big one,
and it's not often that one has a big enough window to fit in this
review :). On a side note, could you use "unified" diffs instead of
using "context" diffs. Most of us here find the latter much harder
to review (thanks!).
First off, I'll say that I can't review the changes to the simulator.
But I think we have a few fairly active maintainers for the simulator.
I'd just resend this part as a separate patch with an explicit subject
that says this is a simulator patch (with maybe a PING, this tends to
wake people up).
> gdb/
> 2008-12-15 Jon Beniston <jon@beniston.com>
>
> * MAINTAINERS: Add Jon Beniston as lm32 maintainer.
I cannot approve this part yet, as I haven't had the change before
this patch to review your code and make sure that you're able to
follow the GDB conventions in your code. As you'll see, there
are a few things that you didn't follow, so I think that it will
be beneficial for you if we continue reviewing your patches before
you commit. Given the nature of the issues I found, most are easy
to learn and we should be able to nominate you soon.
Also, I'll say it now: I had a lot of comments, and maybe it'll feel
bad, but it should not feel that way. I don't think you're very far
away from having something I can approve. A lot of it looks good to
me in principle, and you're been commented on issues that should be
easy to fix.
> gdb/testsuite
> 2008-12-15 Jon Beniston <jon@beniston.com>
>
> * gdb.asm/asm-source.exp: Add lm32 target.
This part is fine.
> include/gdb/
> 2008-12-15 Jon Beniston <jon@beniston.com>
>
> * sim-lm32.h: New file.
Please make sure to ask the sim maintainer to approve this part...
> ia64 --target=ia64-linux-gnu ,-Werror
> (--target=ia64-elf broken)
>
> + lm32 --target=lm32-elf ,-Werror
> + Jon Beniston, jon@beniston.com
As much as it pains me to say this (I **HATE** tabs, I absolutely
abhore tabs, I cannot believe that we're still using them. Aaaahhh,
I feel better now): You need to use tabs in this case to be consistent
with the rest of this section. Tabs before "lm32", and tabs between
"lm32" and the --target.
> --- 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 \
You should replace the spaces on the second line by a tab.
> + lm32*-*-uclinux*)
This is really nit-picking, but I looked at other GNU tools, and
it looks like their configure scripts only recognize "lm32". I think
we should be consistent and remove the first "*".
Also, I'm wondering about only accepting "uclinux", as opposed to
"*linux*". BFD, for instance, does not treat linux and uclinux
differently. Unless you think that GDB will have to treat the two
systems differently, perhaps it would make sense to follow BFD's
example.
> + gdb_target_obs="lm32-tdep.o lm32-linux-tdep.o"
Tab instead of spaces...
> + gdb_target_obs="lm32-tdep.o"
Same here...
I started reviewing this patch while reading it, and after reviewing
the first file, I finally realized that this first file on the list
is called lm32-linux-tdep.c. Purely from the contents of that file,
I was convinced that I was reviewing lm32-tdep.c. I don't think
there is anything in that file that is specific to linux. Is there?
> + Copyright (C) 2008 Free Software Foundation, Inc.
It's already 2009, so you'll need to add 2009 to the copyright date.
> + #include <signal.h>
Can you explain what this is for? Intuitively, I don't think this
can be correct since you are including the signal.h from the host,
which might be different from the one on the target...
> + #include <string.h>
For portability reasons, GDB always includes "gdb_string.h".
> + int lm32_software_single_step (struct frame_info *frame);
I can't find the body for this function. Looks like your patch
is incomplete??? I'm also a little bit surprised that this is
unilaterally needed. Doesn't uclinux provide single-stepping,
for instance? How about the simulator?
> + enum {
> + NORMAL_SIGTRAMP = 1,
> + /* RT_SIGTRAMP = 2 */
> + };
As far as I can tell, this isn't really useful. I can only see
this enum being used in one place, which is lm32_linux_pc_in_sigtramp,
which is unused. It looks like either this is a left over that is
no longer needed, or, as I suspect, there is a piece missing in your
patch.
> + #define LM32_ELF_NGREG 32
> + typedef unsigned char lm32_elf_greg_t[4];
I think that you might want to use gdb_byte instead of "unsigned char".
> + #define LM32_UIMM16(insn) (insn & 0xffff)
> + #define LM32_IMM26(insn) ((((long)insn & 0x3ffffff) << 6) >> 6)
These two macros seem to be unused at the moment. It's OK to leave them
if you think they might become useful at one point. Otherwise, let's
delete them.
> + struct lm32_unwind_cache
To be consistent with GDB's usual naming conventions, would you mind
renaming this structure to lm32_frame_cache, please?
> + {
> + /* The previous frame's inner most stack address. Used as this
> + frame ID's stack_addr. */
> + CORE_ADDR prev_sp;
This looked suspicious to me, and indeed, it looks like it's unused
(apart from being computed). Contrary to what your comment implies,
we usually use the cache->base as the frame's stack_addr... (which is
why I found this field a little strange)
> + /* Size of frame */
> + int size;
Similarly, it looks like this information is only needed to compute
the frame prev_sp. If this is the case, and assuming that prev_sp
can go too, then this can been jettisoned as well.
> + /* Whether the function uses fp as a frame pointer */
> + int uses_fp;
Same here. This field is set, but doesn't seem to be ever used.
> + static int
> + lm32_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
As said above, I suspect that you are missing a piece of code that
uses this function. Otherwise, this function is unused and should
be deleted.
> + static void
> + lm32_linux_supply_gregset (const struct regset *regset,
> + struct regcache *regcache,
> + int regnum, const void *gregs, size_t len)
Tabs issue here again...
> + fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
I suspect that this trace wasn't supposed to be in this patch.
If you find such traces occasionally useful, you might want to consider
introducing traces conditional on a "debug" setting. See how we use
"debug_infrun" inside infrun.c for instance.
> + for (regi = 1; regi <= 32; regi++)
> + {
> + regcache_raw_supply (regcache, regi, &gregsetp->reg[regi]);
> + }
A minor style issue: The curly braces are not used when there is
only one statement in the body of the loop.
> + 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);
This commented-out code should be removed.
> + set_gdbarch_regset_from_core_section (gdbarch,
> + lm32_linux_regset_from_core_section);
Tabs vs space... (sorry about that, it annoys me at least as much
as it must be annoying you right now)
> + 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
The "else" is incorrectly indented.
> + static int
> + lm32_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
> + struct reggroup *group)
Indentation issue...
> + if (group == general_reggroup)
> + {
Can you remove the unnecessary curly braces, please?
> + return ((regnum >= LM32_R0_REGNUM) && (regnum <= LM32_RA_REGNUM))
> + || (regnum == LM32_PC_REGNUM);
The formatting is strange, and will be destroyed if we run gdb_indent.sh.
The GNU Coding Standards (GCS) recommend that this be formatted as follow:
return ((regnum >= LM32_R0_REGNUM && regnum <= LM32_RA_REGNUM)
|| regnum == LM32_PC_REGNUM);
(watchout for tabs, as you'll probably need them for the second line).
> + else if (group == system_reggroup)
> + {
> + return ( (regnum >= LM32_EA_REGNUM)
> + && (regnum <= LM32_BA_REGNUM)
> + );
> + }
Same here:
else if (group == system_reggroup)
return (regnum >= LM32_EA_REGNUM && regnum <= LM32_BA_REGNUM);
> + /* Return a name that corresponds to the given register number */
Can you add a '.' at the end of your sentence, followed by two spaces,
please? I realize this can be annoying to fix these, but we try to be
consistent and follow the GCS.
> + if ((reg_nr < 0) || (reg_nr >= sizeof (register_names) / sizeof (register_names[0])))
> + return NULL;
Formatting: The condition needs to be split in two lines to fit in
80 characters. Or better yet, use the ARRAY_SIZE macro defined for us
in libiberty.h (already included by defs.h).
> + /* Parse a functions prologue */
Typo: No 's' at the end of "function". Also, a period needs to be
added at the end of the sentence. However, when I looked at the
implementation, the function turned out to be completely different
from what I expected!
Traditionally, we call this function "..._analyze_prologue" and this
function usually performs two things:
- analyze the prologue instructions to build a frame_cache object;
- return the address where the last prologue instruction was found.
> + static CORE_ADDR
> + lm32_parse_prologue (CORE_ADDR pc)
With this in mind, it's a shame that you have two separate functions
for parsing and analyzing... You can have a look at i386-tdep.c to
see how it uses the same function to perform both tasks.
I'm not going to review the body of this function assuming that
you'll be able to merge it with the function that analyzes the function,
which you can extract from your "lm32_frame_unwind_cache" function,
I think.
> + /* 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;
> + }
This part of the code can be replaced by a call to
skip_prologue_using_sal.
> + /* Create a breakpoint instruction */
Period and two spaces at the end of the sentence...
> + 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};
"unsigned char" should be replaced by gdb_byte (same for the function
return type).
> + /* Setup registers and stack for faking a call to a function in the inferior */
period and spaces at the end of the sentence...
> + /* Set the return address */
> + /* If we're returning a large struct, a pointer to the address to
> + store it at is passed as a first hidden parameter */
> + /* Setup parameters */
> + /* Promote small integer types to int */
> + /* FIXME: Handle structures */
> + /* Update stack pointer */
> + /* Extract return value after calling a function in the inferior */
> + /* Return value is returned in a single register */
Ditto.
> + if (TYPE_LENGTH (arg_type) < 4)
> + {
> + arg_type = builtin_type_int32;
> + arg = value_cast (arg_type, arg);
The last two lines are incorrectly formatted. You're also mixing
spaces and tabs, but I'm just about ready to give up on this one :-(.
> + contents = (char *) value_contents (arg);
I think that contents needs to be declared as a gdb_byte *, and that
this will allow the cast to go away.
> + /* First num_arg_regs parameters go in registers, rest go on stack */
I should say that I really appreciate it when people make an effort
to comment their code as you did. I do personally follow a strict
rule when it comes to comments, as I try to write them in real English
as opposed to abbreviated English. The reason why I do this is because
I find that abbreviated English often makes it harder to read a comment,
thus reducing its effectiveness.
I was ready to let the comment above go, except that I noticed that the
second "go" should be "goes" and that you're missing the period at the
end of your sentence... I suggest:
/* The First num_arg_regs parameters are passed by registers,
and the rest as passed on the stack. */
> + if (i < num_arg_regs)
> + {
> + regcache_cooked_write_unsigned (regcache, first_arg_reg + i, val);
> + }
Can you remove the unnecessary curly braces, please?
> + static void
> + lm32_extract_return_value (struct type *type, struct regcache *regcache,
> + gdb_byte *valbuf)
Tabs instead of spaces...
> + if ( TYPE_CODE(type) != TYPE_CODE_STRUCT
> + && TYPE_CODE(type) != TYPE_CODE_UNION
> + && TYPE_CODE(type) != TYPE_CODE_ARRAY
> + && TYPE_LENGTH (type) <= 4
> + )
Formatting... I think this is the last time I'm going to mention
this. I'll let you fix the formatting everywhere else.
> + /* 64-bit values are returned in a register pair */
Same for the missing periods at the end of your sentences. Can you
fix them throughout your patch, please?
> + /* Aggregate types greater than a single register are returned in memory:
I think that a period instead of a colon is better in this case.
But that's just a suggestion.
> + static void
> + lm32_store_return_value (struct type *type, struct regcache *regcache,
> + const gdb_byte *valbuf)
You're missing one space at the beginning of the second line.
Otherwise, the argument is not aligned...
> + val = extract_unsigned_integer ((char *)valbuf + 4, len - 4);
I think the cast should be removed.
> + static enum return_value_convention
> + lm32_return_value (struct gdbarch *gdbarch, struct type *func_type,
> + struct type *valtype, struct regcache *regcache,
One space too many...
> + gdb_byte *readbuf, const gdb_byte *writebuf)
Tabs vs spaces...
> + if ((code == TYPE_CODE_STRUCT
> + || code == TYPE_CODE_UNION
> + || code == TYPE_CODE_ARRAY
> + || TYPE_LENGTH (valtype) > 8))
Can you remove the extra parens?
> + static struct frame_id
> + lm32_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
> + {
> + CORE_ADDR sp = lm32_unwind_sp (gdbarch, this_frame);
I don't think this is correct, but I often get confused. In this case,
I think you're using the SP of the caller of THIS_FRAME. I think you
want to use the SP of this frame, in which case you need to call
get_frame_register_unsigned.
> + struct lm32_unwind_cache *
> + lm32_frame_unwind_cache (struct frame_info *this_frame,
> + void **this_prologue_cache)
I think that this function should be made static.
Also as discussed earlier, you should extract out the prologue
analyzing portion in order to factorize a little bit your code.
One last thing, just to make it consistent across GDB, can you
drop the "unwind" in the name of the function?
> + /* The FUNC is easy. */
> + func = get_frame_func (this_frame);
Usually, the frame_func address is saved in the frame cache to avoid
having to recompute again. You've already needed to compute it while
computing the frame cache, so might as well avoid the recomputing...
For instance, the i386 frame code stores this address in a field
called "pc".
> + /* 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;
You're also using a lot of local variables that we usually don't
introduce for this function. I usually don't really care one way
or the other, but this made your function implementation look
different from the others. This is one of these functions that
are implemented in pretty much every -tdep file, so consistency
with the rest if we can would be nice. See i386-tdep.c...
> + 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);
Minor style nit: Can you add an empty line after your declaration?
We like to have this empty line between the declaration block and
the statements.
> + /* None found, create a new architecture from the information provided. */
Missing space at the end...
> Index: gdb/lm32-linux-tdep.h
I think that this file should be renamed lm32-tdep.h. There doesn't
seem to be anything that's specific to Linux in that file. For instance,
I see:
> + enum lm32_linux_regs
This should only depend on the CPU, not the OS...
> + /* 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);
Never actually implemented...
> Index: gdb/lm32-tdep.c
I'm not going to review that file. I assume that the contents should
be very close to what lm32-linux-tdep.c contained. I'll review this
file again once the duplication between lm32-linux-tdep.c and lm32-tdep
is taken care of.
--
Joel
^ permalink raw reply [flat|nested] 15+ messages in thread* RE: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-02-07 4:14 ` Joel Brobecker
@ 2009-04-15 18:09 ` Jon Beniston
2009-04-15 19:24 ` Eli Zaretskii
2009-05-07 16:49 ` Joel Brobecker
0 siblings, 2 replies; 15+ messages in thread
From: Jon Beniston @ 2009-04-15 18:09 UTC (permalink / raw)
To: 'Joel Brobecker'; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 674 bytes --]
Hi Joel,
Thanks for the comments. Hopefully I have addressed them all in the attached
updated patch. This doesn't include the simulator part as requested. I will
post that shortly. I've also omitted the Linux port for now as that needs
some more work.
Regards,
Jon
ChangeLog
gdb/
2009-04-15 Jon Beniston <jon@beniston.com>
* MAINTAINERS: Add lm32 target.
* Makefile.in: Add lm32 dependencies.
* NEWS: Indicate lm32 is a new target.
* configure.tgt: Add lm32 targets.
* lm32-tdep.c: New file.
gdb/testsuite
2009-04-15 Jon Beniston <jon@beniston.com>
* gdb.asm/asm-source.exp: Add lm32 target.
[-- Attachment #2: lm32.patch.2 --]
[-- Type: application/octet-stream, Size: 22427 bytes --]
Index: gdb/MAINTAINERS
===================================================================
RCS file: /cvs/src/src/gdb/MAINTAINERS,v
retrieving revision 1.413
diff -u -p -r1.413 MAINTAINERS
--- gdb/MAINTAINERS 27 Feb 2009 15:03:47 -0000 1.413
+++ gdb/MAINTAINERS 15 Apr 2009 17:21:19 -0000
@@ -270,6 +270,8 @@ the native maintainer when resolving ABI
ia64 --target=ia64-linux-gnu ,-Werror
(--target=ia64-elf broken)
+ lm32 --target=lm32-elf ,-Werror
+
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.1076
diff -u -p -r1.1076 Makefile.in
--- gdb/Makefile.in 30 Mar 2009 19:54:19 -0000 1.1076
+++ gdb/Makefile.in 15 Apr 2009 17:21:19 -0000
@@ -485,6 +485,7 @@ ALL_TARGET_OBS = \
i386-dicos-tdep.o \
iq2000-tdep.o \
linux-tdep.o \
+ lm32-tdep.o \
m32c-tdep.o \
m32r-linux-tdep.o m32r-tdep.o \
m68hc11-tdep.o \
@@ -1308,6 +1309,7 @@ ALLDEPFILES = \
libunwind-frame.c \
linux-fork.c \
linux-tdep.c \
+ lm32-tdep.c \
m68hc11-tdep.c \
m32r-tdep.c \
m32r-linux-nat.c m32r-linux-tdep.c \
Index: gdb/NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.305
diff -u -p -r1.305 NEWS
--- gdb/NEWS 31 Mar 2009 20:21:06 -0000 1.305
+++ gdb/NEWS 15 Apr 2009 17:21:21 -0000
@@ -234,6 +234,7 @@ x86_64 MinGW x86_64-*-mingw*
* New targets
+Lattice Mico32 lm32-*
x86 DICOS i[34567]86-*-dicos*
x86_64 DICOS x86_64-*-dicos*
Index: gdb/configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.213
diff -u -p -r1.213 configure.tgt
--- gdb/configure.tgt 16 Mar 2009 15:04:14 -0000 1.213
+++ gdb/configure.tgt 15 Apr 2009 17:21:22 -0000
@@ -231,6 +231,11 @@ iq2000-*-*)
gdb_sim=../sim/iq2000/libsim.a
;;
+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-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 15 Apr 2009 17:21:22 -0000
@@ -0,0 +1,585 @@
+/* Target-dependent code for Lattice Mico32 processor, for GDB.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#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 "gdb_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_IMM16(insn) ((((long)insn & 0xffff) << 16) >> 16)
+
+struct gdbarch_tdep
+{
+ /* gdbarch target dependent data here. Currently unused for LM32. */
+};
+
+struct lm32_frame_cache
+{
+ /* The frame's base. Used when constructing a frame ID. */
+ CORE_ADDR base;
+ CORE_ADDR pc;
+ /* Size of frame. */
+ int size;
+ /* 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_IP_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", "IM", "IP"
+ };
+
+ if ((reg_nr < 0) || (reg_nr >= ARRAY_SIZE (register_names)))
+ 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);
+}
+
+/* Analyze a function's prologue. */
+
+static CORE_ADDR
+lm32_analyze_prologue (CORE_ADDR pc, CORE_ADDR limit,
+ struct lm32_frame_cache *info)
+{
+ unsigned long instruction;
+
+ /* Keep reading though instructions, until we come across an instruction
+ that isn't likely to be part of the prologue. */
+ info->size = 0;
+ for (; pc < limit; pc += 4)
+ {
+
+ /* Read an instruction. */
+ instruction = read_memory_integer (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);
+ }
+ 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)))
+ {
+ /* Likely to be in the prologue for functions that require
+ a frame pointer. */
+ }
+ else
+ {
+ /* Any other instruction is likely not to be part of the prologue. */
+ break;
+ }
+ }
+
+ 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, limit_pc;
+ struct symtab_and_line sal;
+ struct lm32_frame_cache frame_info;
+ struct trad_frame_saved_reg saved_regs[SIM_LM32_NUM_REGS];
+
+ /* See if we can determine the end of the prologue via the symbol table.
+ If so, then return either PC, or the PC after the prologue, whichever
+ is greater. */
+ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ {
+ CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);
+ }
+
+ /* Can't determine prologue from the symbol table, need to examine
+ instructions. */
+
+ /* Find an upper limit on the function prologue using the debug
+ information. If the debug information could not be used to provide
+ that bound, then use an arbitrary large number as the upper bound. */
+ limit_pc = skip_prologue_using_sal (pc);
+ if (limit_pc == 0)
+ limit_pc = pc + 100; /* Magic. */
+
+ frame_info.saved_regs = saved_regs;
+ return lm32_analyze_prologue (pc, limit_pc, &frame_info);
+}
+
+/* Create a breakpoint instruction. */
+
+static const gdb_byte *
+lm32_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
+ int *lenptr)
+{
+ static const gdb_byte 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));
+ gdb_byte *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 = (gdb_byte *) value_contents (arg);
+ len = TYPE_LENGTH (arg_type);
+ val = extract_unsigned_integer (contents, len);
+
+ /* First num_arg_regs parameters are passed by registers,
+ and the rest are passed on the 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 (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 = get_frame_register_unsigned (this_frame, SIM_LM32_SP_REGNUM);
+
+ 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. */
+
+static struct lm32_frame_cache *
+lm32_frame_cache (struct frame_info *this_frame, void **this_prologue_cache)
+{
+ CORE_ADDR prologue_pc;
+ CORE_ADDR current_pc;
+ ULONGEST prev_sp;
+ ULONGEST this_base;
+ struct lm32_frame_cache *info;
+ int prefixed;
+ unsigned long instruction;
+ int op;
+ int offsets[32];
+ int i;
+ long immediate;
+
+ if ((*this_prologue_cache))
+ return (*this_prologue_cache);
+
+ info = FRAME_OBSTACK_ZALLOC (struct lm32_frame_cache);
+ (*this_prologue_cache) = info;
+ info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+ info->pc = get_frame_func (this_frame);
+ current_pc = get_frame_pc (this_frame);
+ lm32_analyze_prologue (info->pc, current_pc, info);
+
+ /* Compute the frame's base, and the previous frame's SP. */
+ this_base = get_frame_register_unsigned (this_frame, SIM_LM32_SP_REGNUM);
+ prev_sp = this_base + info->size;
+ info->base = this_base;
+
+ /* 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, prev_sp);
+
+ return info;
+}
+
+static void
+lm32_frame_this_id (struct frame_info *this_frame, void **this_cache,
+ struct frame_id *this_id)
+{
+ struct lm32_frame_cache *cache = lm32_frame_cache (this_frame, this_cache);
+
+ /* This marks the outermost frame. */
+ if (cache->base == 0)
+ return;
+
+ (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static struct value *
+lm32_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
+{
+ struct lm32_frame_cache *info;
+
+ info = lm32_frame_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_frame_cache *info = lm32_frame_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 CORE_ADDR
+lm32_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+{
+ /* Align to the size of an instruction (so that they can safely be
+ pushed onto the stack. */
+ return sp & ~3;
+}
+
+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. */
+ set_gdbarch_frame_align (gdbarch, lm32_frame_align);
+ 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.73
diff -u -p -r1.73 asm-source.exp
--- gdb/testsuite/gdb.asm/asm-source.exp 3 Jan 2009 05:58:03 -0000 1.73
+++ gdb/testsuite/gdb.asm/asm-source.exp 15 Apr 2009 17:21:23 -0000
@@ -64,6 +64,9 @@ switch -glob -- [istarget] {
"i\[3456\]86-*-*" {
set asm-arch i386
}
+ "lm32-*" {
+ set asm-arch lm32
+ }
"m32r*-linux*" {
set asm-arch m32r-linux
}
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-04-15 18:09 ` Jon Beniston
@ 2009-04-15 19:24 ` Eli Zaretskii
2009-05-07 16:49 ` Joel Brobecker
1 sibling, 0 replies; 15+ messages in thread
From: Eli Zaretskii @ 2009-04-15 19:24 UTC (permalink / raw)
To: Jon Beniston; +Cc: brobecker, gdb-patches
> From: "Jon Beniston" <jon@beniston.com>
> Cc: <gdb-patches@sourceware.org>
> Date: Wed, 15 Apr 2009 19:09:07 +0100
>
> * NEWS: Indicate lm32 is a new target.
This part is fine with me, thanks.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-04-15 18:09 ` Jon Beniston
2009-04-15 19:24 ` Eli Zaretskii
@ 2009-05-07 16:49 ` Joel Brobecker
2009-05-07 18:35 ` Eli Zaretskii
2009-05-07 23:13 ` Jon Beniston
1 sibling, 2 replies; 15+ messages in thread
From: Joel Brobecker @ 2009-05-07 16:49 UTC (permalink / raw)
To: Jon Beniston; +Cc: gdb-patches
Jon,
> 2009-04-15 Jon Beniston <jon@beniston.com>
>
> * MAINTAINERS: Add lm32 target.
> * Makefile.in: Add lm32 dependencies.
> * NEWS: Indicate lm32 is a new target.
> * configure.tgt: Add lm32 targets.
> * lm32-tdep.c: New file.
>
> gdb/testsuite
> 2009-04-15 Jon Beniston <jon@beniston.com>
>
> * gdb.asm/asm-source.exp: Add lm32 target.
This looks good overall. I just had one tiny observation. Please also
double-check with Eli that the NEWS update is OK.
That being said, I'm afraid that you won't be able to commit this patch
until the sim counterpart is approved. This is due to the two dependencies
(one in configure.tgt, and one in lm32-tdep.c) that you have. Have you
heard from the sim maintainers?
> /* 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, limit_pc;
> struct symtab_and_line sal;
> struct lm32_frame_cache frame_info;
> struct trad_frame_saved_reg saved_regs[SIM_LM32_NUM_REGS];
>
> /* See if we can determine the end of the prologue via the symbol table.
> If so, then return either PC, or the PC after the prologue, whichever
> is greater. */
> if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
You don't need the func_end variable, here, as you can just pass NULL
instead.
--
Joel
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-05-07 16:49 ` Joel Brobecker
@ 2009-05-07 18:35 ` Eli Zaretskii
2009-05-07 23:13 ` Jon Beniston
1 sibling, 0 replies; 15+ messages in thread
From: Eli Zaretskii @ 2009-05-07 18:35 UTC (permalink / raw)
To: Joel Brobecker; +Cc: jon, gdb-patches
> Date: Thu, 7 May 2009 09:48:53 -0700
> From: Joel Brobecker <brobecker@adacore.com>
> Cc: gdb-patches@sourceware.org
>
> > 2009-04-15 Jon Beniston <jon@beniston.com>
> >
> > * MAINTAINERS: Add lm32 target.
> > * Makefile.in: Add lm32 dependencies.
> > * NEWS: Indicate lm32 is a new target.
> > * configure.tgt: Add lm32 targets.
> > * lm32-tdep.c: New file.
> >
> > gdb/testsuite
> > 2009-04-15 Jon Beniston <jon@beniston.com>
> >
> > * gdb.asm/asm-source.exp: Add lm32 target.
>
> This looks good overall. I just had one tiny observation. Please also
> double-check with Eli that the NEWS update is OK.
I approved it back then.
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-05-07 16:49 ` Joel Brobecker
2009-05-07 18:35 ` Eli Zaretskii
@ 2009-05-07 23:13 ` Jon Beniston
2009-05-08 15:32 ` Joel Brobecker
1 sibling, 1 reply; 15+ messages in thread
From: Jon Beniston @ 2009-05-07 23:13 UTC (permalink / raw)
To: 'Joel Brobecker'; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 869 bytes --]
Hi Joel,
Thanks for the second review.
> You don't need the func_end variable, here, as you can just pass NULL
instead.
Ok, I've updated that.
> That being said, I'm afraid that you won't be
> able to commit this patch until the sim
> counterpart is approved. This is due to the
> two dependencies (one in configure.tgt, and one
> in lm32-tdep.c) that you have. Have you
> heard from the sim maintainers?
I haven't heard anything yet.
Cheers,
Jon
ChangeLog
gdb
2009-05-08 Jon Beniston <jon@beniston.com>
* MAINTAINERS: Add lm32 target.
* Makefile.in: Add lm32 dependencies.
* NEWS: Indicate lm32 is a new target.
* configure.tgt: Add lm32 targets.
* lm32-tdep.c: New file.
gdb/testsuite
2009-05-08 Jon Beniston <jon@beniston.com>
* gdb.asm/asm-source.exp: Add lm32 target.
[-- Attachment #2: lm32.patch.2 --]
[-- Type: application/octet-stream, Size: 22412 bytes --]
Index: gdb/MAINTAINERS
===================================================================
RCS file: /cvs/src/src/gdb/MAINTAINERS,v
retrieving revision 1.413
diff -u -p -r1.413 MAINTAINERS
--- gdb/MAINTAINERS 27 Feb 2009 15:03:47 -0000 1.413
+++ gdb/MAINTAINERS 15 Apr 2009 17:21:19 -0000
@@ -270,6 +270,8 @@ the native maintainer when resolving ABI
ia64 --target=ia64-linux-gnu ,-Werror
(--target=ia64-elf broken)
+ lm32 --target=lm32-elf ,-Werror
+
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.1076
diff -u -p -r1.1076 Makefile.in
--- gdb/Makefile.in 30 Mar 2009 19:54:19 -0000 1.1076
+++ gdb/Makefile.in 15 Apr 2009 17:21:19 -0000
@@ -485,6 +485,7 @@ ALL_TARGET_OBS = \
i386-dicos-tdep.o \
iq2000-tdep.o \
linux-tdep.o \
+ lm32-tdep.o \
m32c-tdep.o \
m32r-linux-tdep.o m32r-tdep.o \
m68hc11-tdep.o \
@@ -1308,6 +1309,7 @@ ALLDEPFILES = \
libunwind-frame.c \
linux-fork.c \
linux-tdep.c \
+ lm32-tdep.c \
m68hc11-tdep.c \
m32r-tdep.c \
m32r-linux-nat.c m32r-linux-tdep.c \
Index: gdb/NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.305
diff -u -p -r1.305 NEWS
--- gdb/NEWS 31 Mar 2009 20:21:06 -0000 1.305
+++ gdb/NEWS 15 Apr 2009 17:21:21 -0000
@@ -234,6 +234,7 @@ x86_64 MinGW x86_64-*-mingw*
* New targets
+Lattice Mico32 lm32-*
x86 DICOS i[34567]86-*-dicos*
x86_64 DICOS x86_64-*-dicos*
Index: gdb/configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.213
diff -u -p -r1.213 configure.tgt
--- gdb/configure.tgt 16 Mar 2009 15:04:14 -0000 1.213
+++ gdb/configure.tgt 15 Apr 2009 17:21:22 -0000
@@ -231,6 +231,11 @@ iq2000-*-*)
gdb_sim=../sim/iq2000/libsim.a
;;
+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-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 15 Apr 2009 17:21:22 -0000
@@ -0,0 +1,585 @@
+/* Target-dependent code for Lattice Mico32 processor, for GDB.
+ Contributed by Jon Beniston <jon@beniston.com>
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#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 "gdb_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_IMM16(insn) ((((long)insn & 0xffff) << 16) >> 16)
+
+struct gdbarch_tdep
+{
+ /* gdbarch target dependent data here. Currently unused for LM32. */
+};
+
+struct lm32_frame_cache
+{
+ /* The frame's base. Used when constructing a frame ID. */
+ CORE_ADDR base;
+ CORE_ADDR pc;
+ /* Size of frame. */
+ int size;
+ /* 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_IP_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", "IM", "IP"
+ };
+
+ if ((reg_nr < 0) || (reg_nr >= ARRAY_SIZE (register_names)))
+ 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);
+}
+
+/* Analyze a function's prologue. */
+
+static CORE_ADDR
+lm32_analyze_prologue (CORE_ADDR pc, CORE_ADDR limit,
+ struct lm32_frame_cache *info)
+{
+ unsigned long instruction;
+
+ /* Keep reading though instructions, until we come across an instruction
+ that isn't likely to be part of the prologue. */
+ info->size = 0;
+ for (; pc < limit; pc += 4)
+ {
+
+ /* Read an instruction. */
+ instruction = read_memory_integer (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);
+ }
+ 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)))
+ {
+ /* Likely to be in the prologue for functions that require
+ a frame pointer. */
+ }
+ else
+ {
+ /* Any other instruction is likely not to be part of the prologue. */
+ break;
+ }
+ }
+
+ 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, limit_pc;
+ struct symtab_and_line sal;
+ struct lm32_frame_cache frame_info;
+ struct trad_frame_saved_reg saved_regs[SIM_LM32_NUM_REGS];
+
+ /* See if we can determine the end of the prologue via the symbol table.
+ If so, then return either PC, or the PC after the prologue, whichever
+ is greater. */
+ if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
+ {
+ CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);
+ }
+
+ /* Can't determine prologue from the symbol table, need to examine
+ instructions. */
+
+ /* Find an upper limit on the function prologue using the debug
+ information. If the debug information could not be used to provide
+ that bound, then use an arbitrary large number as the upper bound. */
+ limit_pc = skip_prologue_using_sal (pc);
+ if (limit_pc == 0)
+ limit_pc = pc + 100; /* Magic. */
+
+ frame_info.saved_regs = saved_regs;
+ return lm32_analyze_prologue (pc, limit_pc, &frame_info);
+}
+
+/* Create a breakpoint instruction. */
+
+static const gdb_byte *
+lm32_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
+ int *lenptr)
+{
+ static const gdb_byte 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));
+ gdb_byte *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 = (gdb_byte *) value_contents (arg);
+ len = TYPE_LENGTH (arg_type);
+ val = extract_unsigned_integer (contents, len);
+
+ /* First num_arg_regs parameters are passed by registers,
+ and the rest are passed on the 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 (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 = get_frame_register_unsigned (this_frame, SIM_LM32_SP_REGNUM);
+
+ 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. */
+
+static struct lm32_frame_cache *
+lm32_frame_cache (struct frame_info *this_frame, void **this_prologue_cache)
+{
+ CORE_ADDR prologue_pc;
+ CORE_ADDR current_pc;
+ ULONGEST prev_sp;
+ ULONGEST this_base;
+ struct lm32_frame_cache *info;
+ int prefixed;
+ unsigned long instruction;
+ int op;
+ int offsets[32];
+ int i;
+ long immediate;
+
+ if ((*this_prologue_cache))
+ return (*this_prologue_cache);
+
+ info = FRAME_OBSTACK_ZALLOC (struct lm32_frame_cache);
+ (*this_prologue_cache) = info;
+ info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+ info->pc = get_frame_func (this_frame);
+ current_pc = get_frame_pc (this_frame);
+ lm32_analyze_prologue (info->pc, current_pc, info);
+
+ /* Compute the frame's base, and the previous frame's SP. */
+ this_base = get_frame_register_unsigned (this_frame, SIM_LM32_SP_REGNUM);
+ prev_sp = this_base + info->size;
+ info->base = this_base;
+
+ /* 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, prev_sp);
+
+ return info;
+}
+
+static void
+lm32_frame_this_id (struct frame_info *this_frame, void **this_cache,
+ struct frame_id *this_id)
+{
+ struct lm32_frame_cache *cache = lm32_frame_cache (this_frame, this_cache);
+
+ /* This marks the outermost frame. */
+ if (cache->base == 0)
+ return;
+
+ (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static struct value *
+lm32_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
+{
+ struct lm32_frame_cache *info;
+
+ info = lm32_frame_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_frame_cache *info = lm32_frame_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 CORE_ADDR
+lm32_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+{
+ /* Align to the size of an instruction (so that they can safely be
+ pushed onto the stack. */
+ return sp & ~3;
+}
+
+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. */
+ set_gdbarch_frame_align (gdbarch, lm32_frame_align);
+ 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.73
diff -u -p -r1.73 asm-source.exp
--- gdb/testsuite/gdb.asm/asm-source.exp 3 Jan 2009 05:58:03 -0000 1.73
+++ gdb/testsuite/gdb.asm/asm-source.exp 15 Apr 2009 17:21:23 -0000
@@ -64,6 +64,9 @@ switch -glob -- [istarget] {
"i\[3456\]86-*-*" {
set asm-arch i386
}
+ "lm32-*" {
+ set asm-arch lm32
+ }
"m32r*-linux*" {
set asm-arch m32r-linux
}
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-05-07 23:13 ` Jon Beniston
@ 2009-05-08 15:32 ` Joel Brobecker
2009-05-11 16:24 ` Jon Beniston
0 siblings, 1 reply; 15+ messages in thread
From: Joel Brobecker @ 2009-05-08 15:32 UTC (permalink / raw)
To: Jon Beniston; +Cc: gdb-patches
> > That being said, I'm afraid that you won't be able to commit this
> > patch until the sim counterpart is approved. This is due to the two
> > dependencies (one in configure.tgt, and one in lm32-tdep.c) that you
> > have. Have you heard from the sim maintainers?
>
> I haven't heard anything yet.
I recommend that you ping:
Ben Elliston <bje@gnu.org>
Frank Ch. Eigler <fche@redhat.com>
Your GDB patch can go in as soon as your sim patch is in.
--
Joel
^ permalink raw reply [flat|nested] 15+ messages in thread* RE: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-05-08 15:32 ` Joel Brobecker
@ 2009-05-11 16:24 ` Jon Beniston
2009-05-11 16:39 ` Joel Brobecker
0 siblings, 1 reply; 15+ messages in thread
From: Jon Beniston @ 2009-05-11 16:24 UTC (permalink / raw)
To: 'Joel Brobecker'; +Cc: gdb-patches
Hi Joel,
Frank has approved the simulator code.
Cheers,
Jon
-----Original Message-----
From: Frank Ch. Eigler [mailto:fche@redhat.com]
Sent: 11 May 2009 16:21
To: Jon Beniston
Cc: bje@gnu.org
Subject: Re: Lattice Mico32 simulator patch
A brief scan of the hand-written portions of the code showed nothing
alarming, so if your testing shows the code works well enough, go ahead.
- FChE
-----Original Message-----
From: Joel Brobecker [mailto:brobecker@adacore.com]
Sent: 08 May 2009 16:32
To: Jon Beniston
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
> > That being said, I'm afraid that you won't be able to commit this
> > patch until the sim counterpart is approved. This is due to the two
> > dependencies (one in configure.tgt, and one in lm32-tdep.c) that you
> > have. Have you heard from the sim maintainers?
>
> I haven't heard anything yet.
I recommend that you ping:
Ben Elliston <bje@gnu.org>
Frank Ch. Eigler <fche@redhat.com>
Your GDB patch can go in as soon as your sim patch is in.
--
Joel
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-05-11 16:24 ` Jon Beniston
@ 2009-05-11 16:39 ` Joel Brobecker
2009-05-13 14:49 ` Jon Beniston
0 siblings, 1 reply; 15+ messages in thread
From: Joel Brobecker @ 2009-05-11 16:39 UTC (permalink / raw)
To: Jon Beniston; +Cc: gdb-patches
> Frank has approved the simulator code.
Perfect. So it seems that all portions of your code have been approved,
and you can commit. Right?
(You'll probably also need to commit a patch to MAINTAINERS in the
WRITE AFTER APROVAL section if you're not listed there yet - please
remember to send an email with the usual format containing the patch)
--
Joel
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-05-11 16:39 ` Joel Brobecker
@ 2009-05-13 14:49 ` Jon Beniston
2009-05-13 15:29 ` Joel Brobecker
2009-05-18 15:57 ` Pierre Muller
0 siblings, 2 replies; 15+ messages in thread
From: Jon Beniston @ 2009-05-13 14:49 UTC (permalink / raw)
To: 'Joel Brobecker'; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 370 bytes --]
Hi,
> Perfect. So it seems that all portions of
> your code have been approved, and you can commit. Right?
How do I get write access to CVS? Is the account name picked up from the
MAINTAINERS file?
If so, attached is a patch for MAINTAINERS.
Cheers,
Jon
2009-05-13 Jon Beniston <jon@beniston.com>
* MAINTAINERS: Add Jon Beniston to write after approval list.
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 633 bytes --]
Index: MAINTAINERS
===================================================================
RCS file: /cvs/src/src/gdb/MAINTAINERS,v
retrieving revision 1.416
diff -u -p -r1.416 MAINTAINERS
--- MAINTAINERS 12 May 2009 23:55:25 -0000 1.416
+++ MAINTAINERS 13 May 2009 14:45:39 -0000
@@ -459,6 +459,7 @@ John David Anglin dave.anglin@nrc-cnr
Shrinivas Atre shrinivasa@kpitcummins.com
Scott Bambrough scottb@netwinder.org
Thiago Jung Bauermann bauerman@br.ibm.com
+Jon Beniston jon@beniston.com
Jan Beulich jbeulich@novell.com
Jim Blandy jimb@codesourcery.com
Philip Blundell philb@gnu.org
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-05-13 14:49 ` Jon Beniston
@ 2009-05-13 15:29 ` Joel Brobecker
2009-05-18 15:57 ` Pierre Muller
1 sibling, 0 replies; 15+ messages in thread
From: Joel Brobecker @ 2009-05-13 15:29 UTC (permalink / raw)
To: Jon Beniston; +Cc: gdb-patches
> How do I get write access to CVS? Is the account name picked up from the
> MAINTAINERS file?
You qualify because you posted at least one good patch. In order to
gain CVS access, you'll need to fill in the following form:
http://www.sourceware.org/cgi-bin/pdw/ps_form.cgi
You can list me as the approver. Once you have confirmation that
your account has been created, then commit this to MAINTAINERS,
to verify that things are working fine.
--
Joel
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-05-13 14:49 ` Jon Beniston
2009-05-13 15:29 ` Joel Brobecker
@ 2009-05-18 15:57 ` Pierre Muller
2009-05-18 16:09 ` Pierre Muller
1 sibling, 1 reply; 15+ messages in thread
From: Pierre Muller @ 2009-05-18 15:57 UTC (permalink / raw)
To: 'Jon Beniston', 'Joel Brobecker'; +Cc: gdb-patches
Hi Jon,
your commit seems to have broken something:
cygwin compilation with --enable-targets=all
fails with this message.
I suspect that you have a local file name sim-lm32.h
that you forgot to add to cvs...
But I don't see it in the patches that you sent to the mailing
list either.
Could you please try to fix this?
Pierre Muller
Pascal language support maintainer for GDB
gcc -gstabs+ -O0 -I. -I../../purecvs/gdb -I../../purecvs/gdb/common
-I../../pu
recvs/gdb/config -DLOCALEDIR="\"/usr/local/share/locale\"" -DHAVE_CONFIG_H
-I../
../purecvs/gdb/../include/opcode -I../../purecvs/gdb/../readline/.. -I../bfd
-I.
./../purecvs/gdb/../bfd -I../../purecvs/gdb/../include -I../libdecnumber
-I../..
/purecvs/gdb/../libdecnumber -I../../purecvs/gdb/gnulib -Ignulib
-DMI_OUT=1 -D
TUI=1 -Wall -Wdeclaration-after-statement -Wpointer-arith
-Wformat-nonliteral
-Wno-unused -Wno-switch -Wno-char-subscripts -Werror -c -o lm32-tdep.o -MT
lm32-
tdep.o -MMD -MP -MF .deps/lm32-tdep.Tpo ../../purecvs/gdb/lm32-tdep.c
../../purecvs/gdb/lm32-tdep.c:30:26: gdb/sim-lm32.h: No such file or
directory
../../purecvs/gdb/lm32-tdep.c: In function `lm32_register_reggroup_p':
../../purecvs/gdb/lm32-tdep.c:82: error: `SIM_LM32_R0_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:82: error: (Each undeclared identifier is
reported
only once
../../purecvs/gdb/lm32-tdep.c:82: error: for each function it appears in.)
../../purecvs/gdb/lm32-tdep.c:82: error: `SIM_LM32_RA_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:83: error: `SIM_LM32_PC_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:85: error: `SIM_LM32_EA_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:85: error: `SIM_LM32_BA_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:86: error: `SIM_LM32_EID_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:86: error: `SIM_LM32_IP_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c: In function `lm32_cannot_store_register':
../../purecvs/gdb/lm32-tdep.c:122: error: `SIM_LM32_R0_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:122: error: `SIM_LM32_EID_REGNUM' undeclared
(firs
t use in this function)
../../purecvs/gdb/lm32-tdep.c: In function `lm32_analyze_prologue':
../../purecvs/gdb/lm32-tdep.c:143: error: `SIM_LM32_SP_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:160: error: `SIM_LM32_FP_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:166: error: `SIM_LM32_R0_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c: In function `lm32_skip_prologue':
../../purecvs/gdb/lm32-tdep.c:190: error: `SIM_LM32_NUM_REGS' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c: In function `lm32_push_dummy_call':
../../purecvs/gdb/lm32-tdep.c:237: error: `SIM_LM32_R1_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:242: error: `SIM_LM32_RA_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:299: error: `SIM_LM32_SP_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c: In function `lm32_extract_return_value':
../../purecvs/gdb/lm32-tdep.c:320: error: `SIM_LM32_R1_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:328: error: `SIM_LM32_R2_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c: In function `lm32_store_return_value':
../../purecvs/gdb/lm32-tdep.c:353: error: `SIM_LM32_R1_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:360: error: `SIM_LM32_R2_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c: In function `lm32_unwind_pc':
../../purecvs/gdb/lm32-tdep.c:390: error: `SIM_LM32_PC_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c: In function `lm32_unwind_sp':
../../purecvs/gdb/lm32-tdep.c:396: error: `SIM_LM32_SP_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c: In function `lm32_dummy_id':
../../purecvs/gdb/lm32-tdep.c:402: error: `SIM_LM32_SP_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c: In function `lm32_frame_cache':
../../purecvs/gdb/lm32-tdep.c:440: error: `SIM_LM32_SP_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:455: error: `SIM_LM32_PC_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:455: error: `SIM_LM32_RA_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c: In function `lm32_gdbarch_init':
../../purecvs/gdb/lm32-tdep.c:543: error: `SIM_LM32_NUM_REGS' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:544: error: `SIM_LM32_SP_REGNUM' undeclared
(first
use in this function)
../../purecvs/gdb/lm32-tdep.c:545: error: `SIM_LM32_PC_REGNUM' undeclared
(first
use in this function)
make[1]: *** [lm32-tdep.o] Error 1
make[1]: Leaving directory `/usr/local/src/gdbcvs/multibuild/gdb'
make: *** [all-gdb] Error 2
> -----Message d'origine-----
> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] De la part de Jon Beniston
> Envoyé : Wednesday, May 13, 2009 4:49 PM
> À : 'Joel Brobecker'
> Cc : gdb-patches@sourceware.org
> Objet : RE: [PATCH] Add support for the Lattice Mico32 (LM32)
> architecture
>
> Hi,
>
> > Perfect. So it seems that all portions of your code have been
> > approved, and you can commit. Right?
>
> How do I get write access to CVS? Is the account name picked up from
> the MAINTAINERS file?
>
> If so, attached is a patch for MAINTAINERS.
>
> Cheers,
> Jon
>
> 2009-05-13 Jon Beniston <jon@beniston.com>
>
> * MAINTAINERS: Add Jon Beniston to write after approval list.
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH] Add support for the Lattice Mico32 (LM32) architecture
2009-05-18 15:57 ` Pierre Muller
@ 2009-05-18 16:09 ` Pierre Muller
0 siblings, 0 replies; 15+ messages in thread
From: Pierre Muller @ 2009-05-18 16:09 UTC (permalink / raw)
To: 'Jon Beniston', 'Joel Brobecker'; +Cc: gdb-patches
Sorry, false alarm...
The problem is that I didn't run
cvs update -d
in the include directory.
Please excuse me for the noise.
Pierre Muller
Pascal language support maintainer for GDB
> -----Message d'origine-----
> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] De la part de Pierre Muller
> Envoyé : Monday, May 18, 2009 5:56 PM
> À : 'Jon Beniston'; 'Joel Brobecker'
> Cc : gdb-patches@sourceware.org
> Objet : RE: [PATCH] Add support for the Lattice Mico32 (LM32)
> architecture
>
> Hi Jon,
>
> your commit seems to have broken something:
>
> cygwin compilation with --enable-targets=all
> fails with this message.
>
> I suspect that you have a local file name sim-lm32.h
> that you forgot to add to cvs...
> But I don't see it in the patches that you sent to the mailing
> list either.
>
> Could you please try to fix this?
>
> Pierre Muller
> Pascal language support maintainer for GDB
>
>
> gcc -gstabs+ -O0 -I. -I../../purecvs/gdb -I../../purecvs/gdb/common
> -I../../pu
> recvs/gdb/config -DLOCALEDIR="\"/usr/local/share/locale\"" -
> DHAVE_CONFIG_H
> -I../
> ../purecvs/gdb/../include/opcode -I../../purecvs/gdb/../readline/.. -
> I../bfd
> -I.
> ./../purecvs/gdb/../bfd -I../../purecvs/gdb/../include -
> I../libdecnumber
> -I../..
> /purecvs/gdb/../libdecnumber -I../../purecvs/gdb/gnulib -Ignulib
> -DMI_OUT=1 -D
> TUI=1 -Wall -Wdeclaration-after-statement -Wpointer-arith
> -Wformat-nonliteral
> -Wno-unused -Wno-switch -Wno-char-subscripts -Werror -c -o lm32-tdep.o
> -MT
> lm32-
> tdep.o -MMD -MP -MF .deps/lm32-tdep.Tpo ../../purecvs/gdb/lm32-tdep.c
> ../../purecvs/gdb/lm32-tdep.c:30:26: gdb/sim-lm32.h: No such file or
> directory
> ../../purecvs/gdb/lm32-tdep.c: In function `lm32_register_reggroup_p':
> ../../purecvs/gdb/lm32-tdep.c:82: error: `SIM_LM32_R0_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:82: error: (Each undeclared identifier is
> reported
> only once
> ../../purecvs/gdb/lm32-tdep.c:82: error: for each function it appears
> in.)
> ../../purecvs/gdb/lm32-tdep.c:82: error: `SIM_LM32_RA_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:83: error: `SIM_LM32_PC_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:85: error: `SIM_LM32_EA_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:85: error: `SIM_LM32_BA_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:86: error: `SIM_LM32_EID_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:86: error: `SIM_LM32_IP_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c: In function
> `lm32_cannot_store_register':
> ../../purecvs/gdb/lm32-tdep.c:122: error: `SIM_LM32_R0_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:122: error: `SIM_LM32_EID_REGNUM'
> undeclared
> (firs
> t use in this function)
> ../../purecvs/gdb/lm32-tdep.c: In function `lm32_analyze_prologue':
> ../../purecvs/gdb/lm32-tdep.c:143: error: `SIM_LM32_SP_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:160: error: `SIM_LM32_FP_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:166: error: `SIM_LM32_R0_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c: In function `lm32_skip_prologue':
> ../../purecvs/gdb/lm32-tdep.c:190: error: `SIM_LM32_NUM_REGS'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c: In function `lm32_push_dummy_call':
> ../../purecvs/gdb/lm32-tdep.c:237: error: `SIM_LM32_R1_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:242: error: `SIM_LM32_RA_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:299: error: `SIM_LM32_SP_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c: In function `lm32_extract_return_value':
> ../../purecvs/gdb/lm32-tdep.c:320: error: `SIM_LM32_R1_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:328: error: `SIM_LM32_R2_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c: In function `lm32_store_return_value':
> ../../purecvs/gdb/lm32-tdep.c:353: error: `SIM_LM32_R1_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:360: error: `SIM_LM32_R2_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c: In function `lm32_unwind_pc':
> ../../purecvs/gdb/lm32-tdep.c:390: error: `SIM_LM32_PC_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c: In function `lm32_unwind_sp':
> ../../purecvs/gdb/lm32-tdep.c:396: error: `SIM_LM32_SP_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c: In function `lm32_dummy_id':
> ../../purecvs/gdb/lm32-tdep.c:402: error: `SIM_LM32_SP_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c: In function `lm32_frame_cache':
> ../../purecvs/gdb/lm32-tdep.c:440: error: `SIM_LM32_SP_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:455: error: `SIM_LM32_PC_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:455: error: `SIM_LM32_RA_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c: In function `lm32_gdbarch_init':
> ../../purecvs/gdb/lm32-tdep.c:543: error: `SIM_LM32_NUM_REGS'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:544: error: `SIM_LM32_SP_REGNUM'
> undeclared
> (first
> use in this function)
> ../../purecvs/gdb/lm32-tdep.c:545: error: `SIM_LM32_PC_REGNUM'
> undeclared
> (first
> use in this function)
> make[1]: *** [lm32-tdep.o] Error 1
> make[1]: Leaving directory `/usr/local/src/gdbcvs/multibuild/gdb'
> make: *** [all-gdb] Error 2
>
> > -----Message d'origine-----
> > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> > owner@sourceware.org] De la part de Jon Beniston
> > Envoyé : Wednesday, May 13, 2009 4:49 PM
> > À : 'Joel Brobecker'
> > Cc : gdb-patches@sourceware.org
> > Objet : RE: [PATCH] Add support for the Lattice Mico32 (LM32)
> > architecture
> >
> > Hi,
> >
> > > Perfect. So it seems that all portions of your code have been
> > > approved, and you can commit. Right?
> >
> > How do I get write access to CVS? Is the account name picked up from
> > the MAINTAINERS file?
> >
> > If so, attached is a patch for MAINTAINERS.
> >
> > Cheers,
> > Jon
> >
> > 2009-05-13 Jon Beniston <jon@beniston.com>
> >
> > * MAINTAINERS: Add Jon Beniston to write after approval list.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2009-05-18 16:09 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-12-16 0:52 [PATCH] Add support for the Lattice Mico32 (LM32) architecture Jon Beniston
2008-12-22 12:06 Jon Beniston
2009-02-07 4:14 ` Joel Brobecker
2009-04-15 18:09 ` Jon Beniston
2009-04-15 19:24 ` Eli Zaretskii
2009-05-07 16:49 ` Joel Brobecker
2009-05-07 18:35 ` Eli Zaretskii
2009-05-07 23:13 ` Jon Beniston
2009-05-08 15:32 ` Joel Brobecker
2009-05-11 16:24 ` Jon Beniston
2009-05-11 16:39 ` Joel Brobecker
2009-05-13 14:49 ` Jon Beniston
2009-05-13 15:29 ` Joel Brobecker
2009-05-18 15:57 ` Pierre Muller
2009-05-18 16:09 ` Pierre Muller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox