Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* 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, &reg))
+     hw_abort (me, "\"reg\" property must contain three addr/size entries");
+   hw_unit_address_to_attach_address (hw_parent (me),
+ 					 &reg.address,
+ 					 &attach_space,
+ 					 &attach_address,
+ 					 me);
+   timers->base = attach_address;
+   hw_unit_size_to_attach_size (hw_parent (me),
+ 				   &reg.size,
+ 				   &attach_size, me);
+   timers->limit = attach_address + (attach_size - 1);
+   hw_attach_address (hw_parent (me),
+ 			 0,
+ 			 attach_space, attach_address, attach_size,
+ 			 me); 
+ }
+ 
+ static void
+ lm32timer_finish (struct hw *me)
+ {
+   struct lm32timer *timers;
+   int i;
+ 
+   timers = HW_ZALLOC (me, struct lm32timer);
+   set_hw_data (me, timers);
+   set_hw_io_read_buffer (me, lm32timer_io_read_buffer);
+   set_hw_io_write_buffer (me, lm32timer_io_write_buffer);
+   set_hw_ports (me, lm32timer_ports);
+ 
+   /* Attach ourself to our parent bus */
+   attach_lm32timer_regs (me, timers);
+ 
+   /* Initialize the timers */
+   timers->status = 0;
+   timers->control = 0;
+   timers->period = 0;
+   timers->snapshot = 0;
+ }
+ 
+ const struct hw_descriptor dv_lm32timer_descriptor[] = {
+   { "lm32timer", lm32timer_finish, },
+   { NULL },
+ };
Index: sim/lm32/dv-lm32uart.c
===================================================================
RCS file: sim/lm32/dv-lm32uart.c
diff -N sim/lm32/dv-lm32uart.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/dv-lm32uart.c	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, &reg))
+     hw_abort (me, "\"reg\" property must contain three addr/size entries");
+   hw_unit_address_to_attach_address (hw_parent (me),
+ 					 &reg.address,
+ 					 &attach_space,
+ 					 &attach_address,
+ 					 me);
+   uart->base = attach_address;
+   hw_unit_size_to_attach_size (hw_parent (me),
+ 				   &reg.size,
+ 				   &attach_size, me);
+   uart->limit = attach_address + (attach_size - 1);
+   hw_attach_address (hw_parent (me),
+ 			 0,
+ 			 attach_space, attach_address, attach_size,
+ 			 me); 
+ }
+ 
+ static void
+ lm32uart_finish (struct hw *me)
+ {
+   struct lm32uart *uart;
+   int i;
+ 
+   uart = HW_ZALLOC (me, struct lm32uart);
+   set_hw_data (me, uart);
+   set_hw_io_read_buffer (me, lm32uart_io_read_buffer);
+   set_hw_io_write_buffer (me, lm32uart_io_write_buffer);
+   set_hw_ports (me, lm32uart_ports);
+ 
+   /* Attach ourself to our parent bus */
+   attach_lm32uart_regs (me, uart);
+ 
+   /* Initialize the UART */
+   uart->rbr = 0;
+   uart->thr = 0;
+   uart->ier = 0;
+   uart->iir = 0;
+   uart->lcr = 0;
+   uart->mcr = 0;
+   uart->lsr = LM32_UART_LSR_TX_RDY;
+   uart->msr = 0;
+   uart->div = 0;  /* By setting to zero, characters are output immediately */
+ }
+ 
+ const struct hw_descriptor dv_lm32uart_descriptor[] = {
+   { "lm32uart", lm32uart_finish, },
+   { NULL },
+ };
+ 
Index: sim/lm32/lm32-sim.h
===================================================================
RCS file: sim/lm32/lm32-sim.h
diff -N sim/lm32/lm32-sim.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/lm32-sim.h	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
* [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, &reg))
+     hw_abort (me, "\"reg\" property must contain three addr/size entries");
+   hw_unit_address_to_attach_address (hw_parent (me),
+ 					 &reg.address,
+ 					 &attach_space,
+ 					 &attach_address,
+ 					 me);
+   timers->base = attach_address;
+   hw_unit_size_to_attach_size (hw_parent (me),
+ 				   &reg.size,
+ 				   &attach_size, me);
+   timers->limit = attach_address + (attach_size - 1);
+   hw_attach_address (hw_parent (me),
+ 			 0,
+ 			 attach_space, attach_address, attach_size,
+ 			 me); 
+ }
+ 
+ static void
+ lm32timer_finish (struct hw *me)
+ {
+   struct lm32timer *timers;
+   int i;
+ 
+   timers = HW_ZALLOC (me, struct lm32timer);
+   set_hw_data (me, timers);
+   set_hw_io_read_buffer (me, lm32timer_io_read_buffer);
+   set_hw_io_write_buffer (me, lm32timer_io_write_buffer);
+   set_hw_ports (me, lm32timer_ports);
+ 
+   /* Attach ourself to our parent bus */
+   attach_lm32timer_regs (me, timers);
+ 
+   /* Initialize the timers */
+   timers->status = 0;
+   timers->control = 0;
+   timers->period = 0;
+   timers->snapshot = 0;
+ }
+ 
+ const struct hw_descriptor dv_lm32timer_descriptor[] = {
+   { "lm32timer", lm32timer_finish, },
+   { NULL },
+ };
Index: sim/lm32/dv-lm32uart.c
===================================================================
RCS file: sim/lm32/dv-lm32uart.c
diff -N sim/lm32/dv-lm32uart.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/dv-lm32uart.c	16 Dec 2008 00:41:34 -0000
***************
*** 0 ****
--- 1,322 ----
+ /*  Lattice Mico32 UART model.
+     Contributed by Jon Beniston <jon@beniston.com>
+     
+     This file is part of the program GDB, the GNU debugger.    
+     
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation; either version 2 of the License, or
+     (at your option) any later version.
+     
+     This program is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+     GNU General Public License for more details.
+     
+     You should have received a copy of the GNU General Public License along 
+     with this program; if not, write to the Free Software Foundation, Inc., 
+     59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 
+ #include "sim-main.h"
+ #include "hw-main.h"
+ #include "sim-assert.h"
+ 
+ #include <stdio.h>
+ #include <sys/time.h>
+ 
+ struct lm32uart {
+   unsigned base;        /* Base address of this UART */
+   unsigned limit;       /* Limit address of this UART */
+   unsigned char rbr;
+   unsigned char thr;
+   unsigned char ier;
+   unsigned char iir;
+   unsigned char lcr;
+   unsigned char mcr;
+   unsigned char lsr;
+   unsigned char msr;
+   unsigned char div;  
+   struct hw_event* event; 
+ };
+ 
+ /* UART registers */
+ 
+ #define LM32_UART_RBR           0x0
+ #define LM32_UART_THR           0x0
+ #define LM32_UART_IER           0x4
+ #define LM32_UART_IIR           0x8
+ #define LM32_UART_LCR           0xc
+ #define LM32_UART_MCR           0x10
+ #define LM32_UART_LSR           0x14
+ #define LM32_UART_MSR           0x18
+ #define LM32_UART_DIV           0x1c
+ 
+ #define LM32_UART_IER_RX_INT    0x1
+ #define LM32_UART_IER_TX_INT    0x2
+ 
+ #define MICOUART_IIR_TXRDY      0x2
+ #define MICOUART_IIR_RXRDY      0x4
+ 
+ #define LM32_UART_LSR_RX_RDY    0x01
+ #define LM32_UART_LSR_TX_RDY    0x20
+ 
+ #define LM32_UART_LCR_WLS_MASK  0x3
+ #define LM32_UART_LCR_WLS_5     0x0
+ #define LM32_UART_LCR_WLS_6     0x1
+ #define LM32_UART_LCR_WLS_7     0x2
+ #define LM32_UART_LCR_WLS_8     0x3
+ 
+ /* UART ports */
+ 
+ enum {
+     INT_PORT
+   };
+ 
+ static const struct hw_port_descriptor lm32uart_ports[] = {
+   { "int", INT_PORT, 0, output_port },
+   {}
+ };
+ 
+ static void
+ do_uart_tx_event (struct hw *me, void *data)
+ {
+   struct lm32uart *uart = hw_data (me);
+   char c;
+   
+   /* Generate interrupt when transmission is complete */
+   if (uart->ier & LM32_UART_IER_TX_INT) {
+       /* Generate interrupt */
+       hw_port_event (me, INT_PORT, 1);
+   }
+ 
+   /* Indicate which interrupt has occured */  
+   uart->iir = MICOUART_IIR_TXRDY;
+ 
+   /* Indicate THR is empty */
+   uart->lsr |= LM32_UART_LSR_TX_RDY;
+ 
+   /* Output the character in the THR */
+   c = (char)uart->thr;
+ 
+   /* WLS field in LCR register specifies the number of bits to output */
+   switch (uart->lcr & LM32_UART_LCR_WLS_MASK) 
+     {
+     case LM32_UART_LCR_WLS_5:
+       c &= 0x1f;
+       break;
+     case LM32_UART_LCR_WLS_6:
+       c &= 0x3f;
+       break;
+     case LM32_UART_LCR_WLS_7: 
+       c &= 0x7f;
+       break;
+     }
+   printf ("%c", c);
+ }
+ 
+ static unsigned
+ lm32uart_io_write_buffer (struct hw *me,
+ 			  const void *source,
+ 			  int space,
+ 			  unsigned_word base,
+ 			  unsigned nr_bytes)
+ {
+   struct lm32uart *uart = hw_data (me);
+   int uart_reg;
+   const unsigned char *source_bytes = source;
+   int value = 0;
+   
+   HW_TRACE ((me, "write to 0x%08lx length %d with 0x%x", (long) base,
+ 	     (int) nr_bytes, value));
+ 
+   if (nr_bytes == 4)
+     value = (source_bytes[0] << 24)
+           | (source_bytes[1] << 16)
+           | (source_bytes[2] << 8)
+           | (source_bytes[3]);
+   else 
+     hw_abort (me, "write of unsupported number of bytes: %d.", nr_bytes);
+   
+   uart_reg = base - uart->base;
+ 
+   switch (uart_reg) 
+     {
+       case LM32_UART_THR:
+         /* Buffer the character to output */
+         uart->thr = value;
+ 
+         /* Indicate the THR is full */
+         uart->lsr &= ~LM32_UART_LSR_TX_RDY;
+ 
+         /* deassert interrupt when IER is loaded */
+         uart->iir &= ~MICOUART_IIR_TXRDY;
+ 
+         /* schedule an event to output the character */
+         hw_event_queue_schedule (me, 1, do_uart_tx_event, 0);
+ 
+         break;
+       case LM32_UART_IER:
+         uart->ier = value;
+ 	if((value & LM32_UART_IER_TX_INT) && (uart->lsr & LM32_UART_LSR_TX_RDY)){
+             /* hw_event_queue_schedule (me, 1, do_uart_tx_event, 0); */
+             uart->lsr |= LM32_UART_LSR_TX_RDY;
+             uart->iir |= MICOUART_IIR_TXRDY;
+             hw_port_event (me, INT_PORT, 1);
+         }else if((value & LM32_UART_IER_TX_INT) == 0){
+             hw_port_event (me, INT_PORT, 0);
+         }
+         break;
+       case LM32_UART_IIR:
+         uart->iir = value;
+         break;  
+       case LM32_UART_LCR:
+         uart->lcr = value;
+         break;
+       case LM32_UART_MCR:
+         uart->mcr = value;
+         break;
+       case LM32_UART_LSR:
+         uart->lsr = value;
+         break;
+       case LM32_UART_MSR:
+         uart->msr = value;
+         break;
+       case LM32_UART_DIV:
+         uart->div = value;
+         break;        
+       default: 
+         hw_abort (me, "write to invalid register address: 0x%x.", uart_reg);  
+     }
+ 
+   return nr_bytes;
+ }     
+ 
+ static unsigned
+ lm32uart_io_read_buffer (struct hw *me,
+ 			 void *dest,
+ 			 int space,
+ 			 unsigned_word base,
+ 			 unsigned nr_bytes)
+ {			
+   struct lm32uart *uart = hw_data (me);
+   int uart_reg;
+   int value;
+   unsigned char *dest_bytes = dest;
+   fd_set fd;
+   struct timeval tv;
+ 
+   HW_TRACE ((me, "read 0x%08lx length %d", (long) base, (int) nr_bytes));
+ 
+   uart_reg = base - uart->base;
+ 
+   switch (uart_reg) 
+     {
+       case LM32_UART_RBR:
+         value = getchar ();
+         uart->lsr &= ~LM32_UART_LSR_RX_RDY;
+         break;
+       case LM32_UART_IER:
+         value = uart->ier;
+         break; 
+       case LM32_UART_IIR:
+         value = uart->iir;
+         break;  
+       case LM32_UART_LCR:
+         value = uart->lcr;
+         break;
+       case LM32_UART_MCR:
+         value = uart->mcr;
+         break;
+       case LM32_UART_LSR:
+         /* Check to see if any data waiting in stdin */
+         FD_ZERO (&fd);
+         FD_SET (fileno (stdin), &fd);
+         tv.tv_sec = 0;
+         tv.tv_usec = 1;
+         if (select (fileno (stdin) + 1, &fd, NULL, NULL, &tv)) 
+           uart->lsr |= LM32_UART_LSR_RX_RDY;
+         value = uart->lsr;
+         break;
+       case LM32_UART_MSR:
+         value = uart->msr;
+         break;
+       case LM32_UART_DIV:
+         value = uart->div;
+         break;        
+       default: 
+         hw_abort (me, "read from invalid register address: 0x%x.", uart_reg);  
+     }
+ 
+   if (nr_bytes == 4)
+     {
+       dest_bytes[0] = value >> 24;
+       dest_bytes[1] = value >> 16;
+       dest_bytes[2] = value >> 8;
+       dest_bytes[3] = value;
+     }
+   else 
+     hw_abort (me, "read of unsupported number of bytes: %d", nr_bytes);
+     
+   return nr_bytes;
+ }     
+ 
+ static void
+ attach_lm32uart_regs (struct hw *me, struct lm32uart *uart)
+ {
+   unsigned_word attach_address;
+   int attach_space;
+   unsigned attach_size;
+   reg_property_spec reg;
+ 
+   if (hw_find_property (me, "reg") == NULL) 
+     hw_abort (me, "Missing \"reg\" property");
+   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
+     hw_abort (me, "\"reg\" property must contain three addr/size entries");
+   hw_unit_address_to_attach_address (hw_parent (me),
+ 					 &reg.address,
+ 					 &attach_space,
+ 					 &attach_address,
+ 					 me);
+   uart->base = attach_address;
+   hw_unit_size_to_attach_size (hw_parent (me),
+ 				   &reg.size,
+ 				   &attach_size, me);
+   uart->limit = attach_address + (attach_size - 1);
+   hw_attach_address (hw_parent (me),
+ 			 0,
+ 			 attach_space, attach_address, attach_size,
+ 			 me); 
+ }
+ 
+ static void
+ lm32uart_finish (struct hw *me)
+ {
+   struct lm32uart *uart;
+   int i;
+ 
+   uart = HW_ZALLOC (me, struct lm32uart);
+   set_hw_data (me, uart);
+   set_hw_io_read_buffer (me, lm32uart_io_read_buffer);
+   set_hw_io_write_buffer (me, lm32uart_io_write_buffer);
+   set_hw_ports (me, lm32uart_ports);
+ 
+   /* Attach ourself to our parent bus */
+   attach_lm32uart_regs (me, uart);
+ 
+   /* Initialize the UART */
+   uart->rbr = 0;
+   uart->thr = 0;
+   uart->ier = 0;
+   uart->iir = 0;
+   uart->lcr = 0;
+   uart->mcr = 0;
+   uart->lsr = LM32_UART_LSR_TX_RDY;
+   uart->msr = 0;
+   uart->div = 0;  /* By setting to zero, characters are output immediately */
+ }
+ 
+ const struct hw_descriptor dv_lm32uart_descriptor[] = {
+   { "lm32uart", lm32uart_finish, },
+   { NULL },
+ };
+ 
Index: sim/lm32/lm32-sim.h
===================================================================
RCS file: sim/lm32/lm32-sim.h
diff -N sim/lm32/lm32-sim.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/lm32-sim.h	16 Dec 2008 00:41:34 -0000
***************
*** 0 ****
--- 1,56 ----
+ /* Contributed by Jon Beniston <jon@beniston.com>
+ 
+    This file is part of GDB, the GNU debugger.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ #ifndef LM32_SIM_H
+ #define LM32_SIM_H
+ 
+ #include "gdb/sim-lm32.h"
+ 
+ /* CSRs */
+ #define LM32_CSR_IE             0
+ #define LM32_CSR_IM             1
+ #define LM32_CSR_IP             2
+ #define LM32_CSR_ICC            3
+ #define LM32_CSR_DCC            4
+ #define LM32_CSR_CC             5
+ #define LM32_CSR_CFG            6
+ #define LM32_CSR_EBA            7
+ #define LM32_CSR_DC             8
+ #define LM32_CSR_DEBA           9
+ #define LM32_CSR_JTX            0xe
+ #define LM32_CSR_JRX            0xf
+ #define LM32_CSR_BP0            0x10
+ #define LM32_CSR_BP1            0x11
+ #define LM32_CSR_BP2            0x12
+ #define LM32_CSR_BP3            0x13
+ #define LM32_CSR_WP0            0x18
+ #define LM32_CSR_WP1            0x19
+ #define LM32_CSR_WP2            0x1a
+ #define LM32_CSR_WP3            0x1b
+ 
+ /* Exception IDs */
+ #define LM32_EID_RESET                  0
+ #define LM32_EID_BREAKPOINT             1
+ #define LM32_EID_INSTRUCTION_BUS_ERROR  2
+ #define LM32_EID_WATCHPOINT             3
+ #define LM32_EID_DATA_BUS_ERROR         4
+ #define LM32_EID_DIVIDE_BY_ZERO         5
+ #define LM32_EID_INTERRUPT              6
+ #define LM32_EID_SYSTEM_CALL            7
+ 
+ #endif /* LM32_SIM_H */
Index: sim/lm32/lm32.c
===================================================================
RCS file: sim/lm32/lm32.c
diff -N sim/lm32/lm32.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/lm32.c	16 Dec 2008 00:41:34 -0000
***************
*** 0 ****
--- 1,97 ----
+ /* Lattice Mico32 simulator support code.
+    Contributed by Jon Beniston <jon@beniston.com>
+ 
+    This file is part of GDB, the GNU debugger.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ #define WANT_CPU lm32bf
+ #define WANT_CPU_LM32BF
+ 
+ #include "sim-main.h"
+ #include "cgen-mem.h"
+ #include "cgen-ops.h"
+ 
+ /* The contents of BUF are in target byte order.  */
+ 
+ int
+ lm32bf_fetch_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
+ {
+   if (rn < 32)
+     SETTSI (buf, lm32bf_h_gr_get (current_cpu, rn));
+   else
+     switch (rn)
+       {
+       case SIM_LM32_PC_REGNUM :
+ 	SETTSI (buf, lm32bf_h_pc_get (current_cpu));
+ 	break;
+       default :
+ 	return 0;
+       }
+ 
+   return -1; /*FIXME*/
+ }
+ 
+ /* The contents of BUF are in target byte order.  */
+ 
+ int
+ lm32bf_store_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
+ {
+   if (rn < 32)
+     lm32bf_h_gr_set (current_cpu, rn, GETTSI (buf));
+   else
+     switch (rn)
+       {
+       case SIM_LM32_PC_REGNUM :
+ 	lm32bf_h_pc_set (current_cpu, GETTSI (buf));
+ 	break;
+       default :
+ 	return 0;
+       }
+ 
+   return -1; /*FIXME*/
+ }
+ 
+ 
+ 
+ #if WITH_PROFILE_MODEL_P
+ 
+ /* Initialize cycle counting for an insn.
+    FIRST_P is non-zero if this is the first insn in a set of parallel
+    insns.  */
+ 
+ void
+ lm32bf_model_insn_before (SIM_CPU *cpu, int first_p)
+ {
+ }
+ 
+ /* Record the cycles computed for an insn.
+    LAST_P is non-zero if this is the last insn in a set of parallel insns,
+    and we update the total cycle count.
+    CYCLES is the cycle count of the insn.  */
+ 
+ void
+ lm32bf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles)
+ {
+ }
+ 
+ int
+ lm32bf_model_lm32_u_exec (SIM_CPU *cpu, const IDESC *idesc,
+ 			    int unit_num, int referenced)
+ {
+   return idesc->timing->units[unit_num].done;
+ }
+ 
+ #endif /* WITH_PROFILE_MODEL_P */
Index: sim/lm32/mloop.in
===================================================================
RCS file: sim/lm32/mloop.in
diff -N sim/lm32/mloop.in
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/mloop.in	16 Dec 2008 00:41:35 -0000
***************
*** 0 ****
--- 1,203 ----
+ # Simulator main loop for lm32. -*- C -*-
+ # Contributed by Jon Beniston <jon@beniston.com>
+ #
+ # This file is part of the GNU Simulators.
+ #
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 2, or (at your option)
+ # any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License along
+ # with this program; if not, write to the Free Software Foundation, Inc.,
+ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+ # Syntax:
+ # /bin/sh mainloop.in command
+ #
+ # Command is one of:
+ #
+ # init
+ # support
+ # extract-{simple,scache,pbb}
+ # {full,fast}-exec-{simple,scache,pbb}
+ #
+ 
+ case "x$1" in
+ 
+ xsupport)
+ 
+ cat <<EOF
+ 
+ static INLINE const IDESC *
+ extract (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
+ 	   ARGBUF *abuf, int fast_p)
+ {
+   const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
+ 
+   @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
+   if (! fast_p)
+     {
+       int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
+       int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
+       @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p);
+     }
+   return id;
+ }
+ 
+ static INLINE SEM_PC
+ execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p)
+ {
+   SEM_PC vpc;
+ 
+   if (fast_p)
+     {
+ #if ! WITH_SEM_SWITCH_FAST
+ #if WITH_SCACHE
+       vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc);
+ #else
+       vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf);
+ #endif
+ #else
+       abort ();
+ #endif /* WITH_SEM_SWITCH_FAST */
+     }
+   else
+     {
+ #if ! WITH_SEM_SWITCH_FULL
+       ARGBUF *abuf = &sc->argbuf;
+       const IDESC *idesc = abuf->idesc;
+       const CGEN_INSN *idata = idesc->idata;
+ #if WITH_SCACHE_PBB
+       int virtual_p = CGEN_INSN_ATTR_VALUE (idata, CGEN_INSN_VIRTUAL);
+ #else
+       int virtual_p = 0;
+ #endif
+       if (! virtual_p)
+ 	{
+ 	  /* FIXME: call x-before */
+ 	  if (ARGBUF_PROFILE_P (abuf))
+ 	    PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num);
+ 	  /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}.  */
+ 	  if (PROFILE_MODEL_P (current_cpu)
+ 	      && ARGBUF_PROFILE_P (abuf))
+ 	    @cpu@_model_insn_before (current_cpu, 1 /*first_p*/);
+ 	  TRACE_INSN_INIT (current_cpu, abuf, 1);
+ 	  TRACE_INSN (current_cpu, idata,
+ 		      (const struct argbuf *) abuf, abuf->addr);
+ 	}
+ #if WITH_SCACHE
+       vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc);
+ #else
+       vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf);
+ #endif
+       if (! virtual_p)
+ 	{
+ 	  /* FIXME: call x-after */
+ 	  if (PROFILE_MODEL_P (current_cpu)
+ 	      && ARGBUF_PROFILE_P (abuf))
+ 	    {
+ 	      int cycles;
+ 
+ 	      cycles = (*idesc->timing->model_fn) (current_cpu, sc);
+ 	      @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
+ 	    }
+ 	  TRACE_INSN_FINI (current_cpu, abuf, 1);
+ 	}
+ #else
+       abort ();
+ #endif /* WITH_SEM_SWITCH_FULL */
+     }
+ 
+   return vpc;
+ }
+ 
+ EOF
+ 
+ ;;
+ 
+ xinit)
+ 
+ # Nothing needed.
+ 
+ ;;
+ 
+ xextract-simple | xextract-scache)
+ 
+ cat <<EOF
+ {
+   CGEN_INSN_INT insn = GETIMEMUSI (current_cpu, vpc);
+   extract (current_cpu, vpc, insn, SEM_ARGBUF (sc), FAST_P);
+ }
+ EOF
+ 
+ ;;
+ 
+ xextract-pbb)
+ 
+ # Inputs:  current_cpu, pc, sc, max_insns, FAST_P
+ # Outputs: sc, pc
+ # sc must be left pointing past the last created entry.
+ # pc must be left pointing past the last created entry.
+ # If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called
+ # to record the vpc of the cti insn.
+ # SET_INSN_COUNT(n) must be called to record number of real insns.
+ 
+ cat <<EOF
+ {
+   const IDESC *idesc;
+   int icount = 0;
+ 
+   while (max_insns > 0)
+     {
+       USI insn = GETIMEMUSI (current_cpu, pc);
+       
+       idesc = extract (current_cpu, pc, insn, &sc->argbuf, FAST_P);
+       ++sc;
+       --max_insns;
+       ++icount;
+       pc += idesc->length;
+ 
+       if (IDESC_CTI_P (idesc))
+         {
+           SET_CTI_VPC (sc - 1);
+           break;
+         }
+     }
+ 
+  Finish:
+   SET_INSN_COUNT (icount);
+ }
+ EOF
+ 
+ ;;
+ 
+ xfull-exec-* | xfast-exec-*)
+ 
+ # Inputs: current_cpu, vpc, FAST_P
+ # Outputs: vpc
+ 
+ cat <<EOF
+   /* Update cycle counter */
+   SET_H_CSR (LM32_CSR_CC, GET_H_CSR (LM32_CSR_CC) + 1);
+ #if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST)
+ #define DEFINE_SWITCH
+ #include "sem-switch.c"
+ #else
+   vpc = execute (current_cpu, vpc, FAST_P);
+ #endif
+ EOF
+ 
+ ;;
+ 
+ *)
+   echo "Invalid argument to mainloop.in: $1" >&2
+   exit 1
+   ;;
+ 
+ esac
Index: sim/lm32/model.c
===================================================================
RCS file: sim/lm32/model.c
diff -N sim/lm32/model.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/model.c	16 Dec 2008 00:41:35 -0000
***************
*** 0 ****
--- 1,1176 ----
+ /* Simulator model support for lm32bf.
+ 
+ THIS FILE IS MACHINE GENERATED WITH CGEN.
+ 
+ Copyright 1996-2005 Free Software Foundation, Inc.
+ 
+ This file is part of the GNU simulators.
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+ 
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ 
+ */
+ 
+ #define WANT_CPU lm32bf
+ #define WANT_CPU_LM32BF
+ 
+ #include "sim-main.h"
+ 
+ /* The profiling data is recorded here, but is accessed via the profiling
+    mechanism.  After all, this is information for profiling.  */
+ 
+ #if WITH_PROFILE_MODEL_P
+ 
+ /* Model handlers for each insn.  */
+ 
+ static int
+ model_lm32_add (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_addi (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_and (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_andi (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_andhii (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_b (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_bi (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_bi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_be (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_bg (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_bge (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_bgeu (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_bgu (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_bne (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_call (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_calli (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_bi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpe (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpei (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpg (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpgi (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpge (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpgei (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpgeu (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpgeui (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpgu (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpgui (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpne (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_cmpnei (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_divu (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_lb (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_lbu (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_lh (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_lhu (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_lw (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_modu (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_mul (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_muli (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_nor (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_nori (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_or (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_ori (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_orhii (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_rcsr (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_rcsr.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_sb (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_sextb (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_sexth (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_sh (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_sl (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_sli (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_sr (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_sri (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_sru (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_srui (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_sub (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_sw (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_user (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_wcsr (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_wcsr.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_xor (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_xori (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_xnor (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_xnori (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_break (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.fmt_empty.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ static int
+ model_lm32_scall (SIM_CPU *current_cpu, void *sem_arg)
+ {
+ #define FLD(f) abuf->fields.fmt_empty.f
+   const ARGBUF * UNUSED abuf = SEM_ARGBUF ((SEM_ARG) sem_arg);
+   const IDESC * UNUSED idesc = abuf->idesc;
+   int cycles = 0;
+   {
+     int referenced = 0;
+     int UNUSED insn_referenced = abuf->written;
+     cycles += lm32bf_model_lm32_u_exec (current_cpu, idesc, 0, referenced);
+   }
+   return cycles;
+ #undef FLD
+ }
+ 
+ /* We assume UNIT_NONE == 0 because the tables don't always terminate
+    entries with it.  */
+ 
+ /* Model timing data for `lm32'.  */
+ 
+ static const INSN_TIMING lm32_timing[] = {
+   { LM32BF_INSN_X_INVALID, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_X_AFTER, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_X_BEFORE, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_X_CTI_CHAIN, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_X_CHAIN, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_X_BEGIN, 0, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_ADD, model_lm32_add, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_ADDI, model_lm32_addi, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_AND, model_lm32_and, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_ANDI, model_lm32_andi, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_ANDHII, model_lm32_andhii, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_B, model_lm32_b, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_BI, model_lm32_bi, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_BE, model_lm32_be, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_BG, model_lm32_bg, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_BGE, model_lm32_bge, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_BGEU, model_lm32_bgeu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_BGU, model_lm32_bgu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_BNE, model_lm32_bne, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CALL, model_lm32_call, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CALLI, model_lm32_calli, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPE, model_lm32_cmpe, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPEI, model_lm32_cmpei, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPG, model_lm32_cmpg, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPGI, model_lm32_cmpgi, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPGE, model_lm32_cmpge, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPGEI, model_lm32_cmpgei, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPGEU, model_lm32_cmpgeu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPGEUI, model_lm32_cmpgeui, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPGU, model_lm32_cmpgu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPGUI, model_lm32_cmpgui, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPNE, model_lm32_cmpne, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_CMPNEI, model_lm32_cmpnei, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_DIVU, model_lm32_divu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_LB, model_lm32_lb, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_LBU, model_lm32_lbu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_LH, model_lm32_lh, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_LHU, model_lm32_lhu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_LW, model_lm32_lw, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_MODU, model_lm32_modu, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_MUL, model_lm32_mul, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_MULI, model_lm32_muli, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_NOR, model_lm32_nor, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_NORI, model_lm32_nori, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_OR, model_lm32_or, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_ORI, model_lm32_ori, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_ORHII, model_lm32_orhii, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_RCSR, model_lm32_rcsr, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SB, model_lm32_sb, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SEXTB, model_lm32_sextb, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SEXTH, model_lm32_sexth, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SH, model_lm32_sh, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SL, model_lm32_sl, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SLI, model_lm32_sli, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SR, model_lm32_sr, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SRI, model_lm32_sri, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SRU, model_lm32_sru, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SRUI, model_lm32_srui, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SUB, model_lm32_sub, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SW, model_lm32_sw, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_USER, model_lm32_user, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_WCSR, model_lm32_wcsr, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_XOR, model_lm32_xor, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_XORI, model_lm32_xori, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_XNOR, model_lm32_xnor, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_XNORI, model_lm32_xnori, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_BREAK, model_lm32_break, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+   { LM32BF_INSN_SCALL, model_lm32_scall, { { (int) UNIT_LM32_U_EXEC, 1, 1 } } },
+ };
+ 
+ #endif /* WITH_PROFILE_MODEL_P */
+ 
+ static void
+ lm32_model_init (SIM_CPU *cpu)
+ {
+   CPU_MODEL_DATA (cpu) = (void *) zalloc (sizeof (MODEL_LM32_DATA));
+ }
+ 
+ #if WITH_PROFILE_MODEL_P
+ #define TIMING_DATA(td) td
+ #else
+ #define TIMING_DATA(td) 0
+ #endif
+ 
+ static const MODEL lm32_models[] =
+ {
+   { "lm32", & lm32_mach, MODEL_LM32, TIMING_DATA (& lm32_timing[0]), lm32_model_init },
+   { 0 }
+ };
+ 
+ /* The properties of this cpu's implementation.  */
+ 
+ static const MACH_IMP_PROPERTIES lm32bf_imp_properties =
+ {
+   sizeof (SIM_CPU),
+ #if WITH_SCACHE
+   sizeof (SCACHE)
+ #else
+   0
+ #endif
+ };
+ 
+ 
+ static void
+ lm32bf_prepare_run (SIM_CPU *cpu)
+ {
+   if (CPU_IDESC (cpu) == NULL)
+     lm32bf_init_idesc_table (cpu);
+ }
+ 
+ static const CGEN_INSN *
+ lm32bf_get_idata (SIM_CPU *cpu, int inum)
+ {
+   return CPU_IDESC (cpu) [inum].idata;
+ }
+ 
+ static void
+ lm32_init_cpu (SIM_CPU *cpu)
+ {
+   CPU_REG_FETCH (cpu) = lm32bf_fetch_register;
+   CPU_REG_STORE (cpu) = lm32bf_store_register;
+   CPU_PC_FETCH (cpu) = lm32bf_h_pc_get;
+   CPU_PC_STORE (cpu) = lm32bf_h_pc_set;
+   CPU_GET_IDATA (cpu) = lm32bf_get_idata;
+   CPU_MAX_INSNS (cpu) = LM32BF_INSN__MAX;
+   CPU_INSN_NAME (cpu) = cgen_insn_name;
+   CPU_FULL_ENGINE_FN (cpu) = lm32bf_engine_run_full;
+ #if WITH_FAST
+   CPU_FAST_ENGINE_FN (cpu) = lm32bf_engine_run_fast;
+ #else
+   CPU_FAST_ENGINE_FN (cpu) = lm32bf_engine_run_full;
+ #endif
+ }
+ 
+ const MACH lm32_mach =
+ {
+   "lm32", "lm32", MACH_LM32,
+   32, 32, & lm32_models[0], & lm32bf_imp_properties,
+   lm32_init_cpu,
+   lm32bf_prepare_run
+ };
+ 
Index: sim/lm32/sem-switch.c
===================================================================
RCS file: sim/lm32/sem-switch.c
diff -N sim/lm32/sem-switch.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/sem-switch.c	16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,1554 ----
+ /* Simulator instruction semantics for lm32bf.
+ 
+ THIS FILE IS MACHINE GENERATED WITH CGEN.
+ 
+ Copyright 1996-2005 Free Software Foundation, Inc.
+ 
+ This file is part of the GNU simulators.
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+ 
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ 
+ */
+ 
+ #ifdef DEFINE_LABELS
+ 
+   /* The labels have the case they have because the enum of insn types
+      is all uppercase and in the non-stdc case the insn symbol is built
+      into the enum name.  */
+ 
+   static struct {
+     int index;
+     void *label;
+   } labels[] = {
+     { LM32BF_INSN_X_INVALID, && case_sem_INSN_X_INVALID },
+     { LM32BF_INSN_X_AFTER, && case_sem_INSN_X_AFTER },
+     { LM32BF_INSN_X_BEFORE, && case_sem_INSN_X_BEFORE },
+     { LM32BF_INSN_X_CTI_CHAIN, && case_sem_INSN_X_CTI_CHAIN },
+     { LM32BF_INSN_X_CHAIN, && case_sem_INSN_X_CHAIN },
+     { LM32BF_INSN_X_BEGIN, && case_sem_INSN_X_BEGIN },
+     { LM32BF_INSN_ADD, && case_sem_INSN_ADD },
+     { LM32BF_INSN_ADDI, && case_sem_INSN_ADDI },
+     { LM32BF_INSN_AND, && case_sem_INSN_AND },
+     { LM32BF_INSN_ANDI, && case_sem_INSN_ANDI },
+     { LM32BF_INSN_ANDHII, && case_sem_INSN_ANDHII },
+     { LM32BF_INSN_B, && case_sem_INSN_B },
+     { LM32BF_INSN_BI, && case_sem_INSN_BI },
+     { LM32BF_INSN_BE, && case_sem_INSN_BE },
+     { LM32BF_INSN_BG, && case_sem_INSN_BG },
+     { LM32BF_INSN_BGE, && case_sem_INSN_BGE },
+     { LM32BF_INSN_BGEU, && case_sem_INSN_BGEU },
+     { LM32BF_INSN_BGU, && case_sem_INSN_BGU },
+     { LM32BF_INSN_BNE, && case_sem_INSN_BNE },
+     { LM32BF_INSN_CALL, && case_sem_INSN_CALL },
+     { LM32BF_INSN_CALLI, && case_sem_INSN_CALLI },
+     { LM32BF_INSN_CMPE, && case_sem_INSN_CMPE },
+     { LM32BF_INSN_CMPEI, && case_sem_INSN_CMPEI },
+     { LM32BF_INSN_CMPG, && case_sem_INSN_CMPG },
+     { LM32BF_INSN_CMPGI, && case_sem_INSN_CMPGI },
+     { LM32BF_INSN_CMPGE, && case_sem_INSN_CMPGE },
+     { LM32BF_INSN_CMPGEI, && case_sem_INSN_CMPGEI },
+     { LM32BF_INSN_CMPGEU, && case_sem_INSN_CMPGEU },
+     { LM32BF_INSN_CMPGEUI, && case_sem_INSN_CMPGEUI },
+     { LM32BF_INSN_CMPGU, && case_sem_INSN_CMPGU },
+     { LM32BF_INSN_CMPGUI, && case_sem_INSN_CMPGUI },
+     { LM32BF_INSN_CMPNE, && case_sem_INSN_CMPNE },
+     { LM32BF_INSN_CMPNEI, && case_sem_INSN_CMPNEI },
+     { LM32BF_INSN_DIVU, && case_sem_INSN_DIVU },
+     { LM32BF_INSN_LB, && case_sem_INSN_LB },
+     { LM32BF_INSN_LBU, && case_sem_INSN_LBU },
+     { LM32BF_INSN_LH, && case_sem_INSN_LH },
+     { LM32BF_INSN_LHU, && case_sem_INSN_LHU },
+     { LM32BF_INSN_LW, && case_sem_INSN_LW },
+     { LM32BF_INSN_MODU, && case_sem_INSN_MODU },
+     { LM32BF_INSN_MUL, && case_sem_INSN_MUL },
+     { LM32BF_INSN_MULI, && case_sem_INSN_MULI },
+     { LM32BF_INSN_NOR, && case_sem_INSN_NOR },
+     { LM32BF_INSN_NORI, && case_sem_INSN_NORI },
+     { LM32BF_INSN_OR, && case_sem_INSN_OR },
+     { LM32BF_INSN_ORI, && case_sem_INSN_ORI },
+     { LM32BF_INSN_ORHII, && case_sem_INSN_ORHII },
+     { LM32BF_INSN_RCSR, && case_sem_INSN_RCSR },
+     { LM32BF_INSN_SB, && case_sem_INSN_SB },
+     { LM32BF_INSN_SEXTB, && case_sem_INSN_SEXTB },
+     { LM32BF_INSN_SEXTH, && case_sem_INSN_SEXTH },
+     { LM32BF_INSN_SH, && case_sem_INSN_SH },
+     { LM32BF_INSN_SL, && case_sem_INSN_SL },
+     { LM32BF_INSN_SLI, && case_sem_INSN_SLI },
+     { LM32BF_INSN_SR, && case_sem_INSN_SR },
+     { LM32BF_INSN_SRI, && case_sem_INSN_SRI },
+     { LM32BF_INSN_SRU, && case_sem_INSN_SRU },
+     { LM32BF_INSN_SRUI, && case_sem_INSN_SRUI },
+     { LM32BF_INSN_SUB, && case_sem_INSN_SUB },
+     { LM32BF_INSN_SW, && case_sem_INSN_SW },
+     { LM32BF_INSN_USER, && case_sem_INSN_USER },
+     { LM32BF_INSN_WCSR, && case_sem_INSN_WCSR },
+     { LM32BF_INSN_XOR, && case_sem_INSN_XOR },
+     { LM32BF_INSN_XORI, && case_sem_INSN_XORI },
+     { LM32BF_INSN_XNOR, && case_sem_INSN_XNOR },
+     { LM32BF_INSN_XNORI, && case_sem_INSN_XNORI },
+     { LM32BF_INSN_BREAK, && case_sem_INSN_BREAK },
+     { LM32BF_INSN_SCALL, && case_sem_INSN_SCALL },
+     { 0, 0 }
+   };
+   int i;
+ 
+   for (i = 0; labels[i].label != 0; ++i)
+     {
+ #if FAST_P
+       CPU_IDESC (current_cpu) [labels[i].index].sem_fast_lab = labels[i].label;
+ #else
+       CPU_IDESC (current_cpu) [labels[i].index].sem_full_lab = labels[i].label;
+ #endif
+     }
+ 
+ #undef DEFINE_LABELS
+ #endif /* DEFINE_LABELS */
+ 
+ #ifdef DEFINE_SWITCH
+ 
+ /* If hyper-fast [well not unnecessarily slow] execution is selected, turn
+    off frills like tracing and profiling.  */
+ /* FIXME: A better way would be to have TRACE_RESULT check for something
+    that can cause it to be optimized out.  Another way would be to emit
+    special handlers into the instruction "stream".  */
+ 
+ #if FAST_P
+ #undef TRACE_RESULT
+ #define TRACE_RESULT(cpu, abuf, name, type, val)
+ #endif
+ 
+ #undef GET_ATTR
+ #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+ #define GET_ATTR(cpu, num, attr) CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_##attr)
+ #else
+ #define GET_ATTR(cpu, num, attr) CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_/**/attr)
+ #endif
+ 
+ {
+ 
+ #if WITH_SCACHE_PBB
+ 
+ /* Branch to next handler without going around main loop.  */
+ #define NEXT(vpc) goto * SEM_ARGBUF (vpc) -> semantic.sem_case
+ SWITCH (sem, SEM_ARGBUF (vpc) -> semantic.sem_case)
+ 
+ #else /* ! WITH_SCACHE_PBB */
+ 
+ #define NEXT(vpc) BREAK (sem)
+ #ifdef __GNUC__
+ #if FAST_P
+   SWITCH (sem, SEM_ARGBUF (sc) -> idesc->sem_fast_lab)
+ #else
+   SWITCH (sem, SEM_ARGBUF (sc) -> idesc->sem_full_lab)
+ #endif
+ #else
+   SWITCH (sem, SEM_ARGBUF (sc) -> idesc->num)
+ #endif
+ 
+ #endif /* ! WITH_SCACHE_PBB */
+ 
+     {
+ 
+   CASE (sem, INSN_X_INVALID) : /* --invalid-- */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.fmt_empty.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+     /* Update the recorded pc in the cpu state struct.
+        Only necessary for WITH_SCACHE case, but to avoid the
+        conditional compilation ....  */
+     SET_H_PC (pc);
+     /* Virtual insns have zero size.  Overwrite vpc with address of next insn
+        using the default-insn-bitsize spec.  When executing insns in parallel
+        we may want to queue the fault and continue execution.  */
+     vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+     vpc = sim_engine_invalid_insn (current_cpu, pc, vpc);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_X_AFTER) : /* --after-- */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.fmt_empty.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+ #if WITH_SCACHE_PBB_LM32BF
+     lm32bf_pbb_after (current_cpu, sem_arg);
+ #endif
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_X_BEFORE) : /* --before-- */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.fmt_empty.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+ #if WITH_SCACHE_PBB_LM32BF
+     lm32bf_pbb_before (current_cpu, sem_arg);
+ #endif
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_X_CTI_CHAIN) : /* --cti-chain-- */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.fmt_empty.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+ #if WITH_SCACHE_PBB_LM32BF
+ #ifdef DEFINE_SWITCH
+     vpc = lm32bf_pbb_cti_chain (current_cpu, sem_arg,
+ 			       pbb_br_type, pbb_br_npc);
+     BREAK (sem);
+ #else
+     /* FIXME: Allow provision of explicit ifmt spec in insn spec.  */
+     vpc = lm32bf_pbb_cti_chain (current_cpu, sem_arg,
+ 			       CPU_PBB_BR_TYPE (current_cpu),
+ 			       CPU_PBB_BR_NPC (current_cpu));
+ #endif
+ #endif
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_X_CHAIN) : /* --chain-- */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.fmt_empty.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+ #if WITH_SCACHE_PBB_LM32BF
+     vpc = lm32bf_pbb_chain (current_cpu, sem_arg);
+ #ifdef DEFINE_SWITCH
+     BREAK (sem);
+ #endif
+ #endif
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_X_BEGIN) : /* --begin-- */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.fmt_empty.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+ #if WITH_SCACHE_PBB_LM32BF
+ #if defined DEFINE_SWITCH || defined FAST_P
+     /* In the switch case FAST_P is a constant, allowing several optimizations
+        in any called inline functions.  */
+     vpc = lm32bf_pbb_begin (current_cpu, FAST_P);
+ #else
+ #if 0 /* cgen engine can't handle dynamic fast/full switching yet.  */
+     vpc = lm32bf_pbb_begin (current_cpu, STATE_RUN_FAST_P (CPU_STATE (current_cpu)));
+ #else
+     vpc = lm32bf_pbb_begin (current_cpu, 0);
+ #endif
+ #endif
+ #endif
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_ADD) : /* add $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ADDSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_ADDI) : /* addi $r1,$r0,$imm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_AND) : /* and $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_ANDI) : /* andi $r1,$r0,$uimm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_ANDHII) : /* andhi $r1,$r0,$hi16 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), SLLSI (FLD (f_uimm), 16));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_B) : /* b $r0 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_be.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = lm32bf_b_insn (current_cpu, CPU (h_gr[FLD (f_r0)]), FLD (f_r0));
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_BI) : /* bi $call */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_bi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = EXTSISI (FLD (i_call));
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_BE) : /* be $r0,$r1,$branch */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_be.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (EQSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_BG) : /* bg $r0,$r1,$branch */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_be.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (GTSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_BGE) : /* bge $r0,$r1,$branch */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_be.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (GESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_BGEU) : /* bgeu $r0,$r1,$branch */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_be.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (GEUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_BGU) : /* bgu $r0,$r1,$branch */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_be.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (GTUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_BNE) : /* bne $r0,$r1,$branch */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_be.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (NESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CALL) : /* call $r0 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_be.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ {
+   {
+     SI opval = ADDSI (pc, 4);
+     CPU (h_gr[((UINT) 29)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+   {
+     USI opval = CPU (h_gr[FLD (f_r0)]);
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CALLI) : /* calli $call */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_bi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ {
+   {
+     SI opval = ADDSI (pc, 4);
+     CPU (h_gr[((UINT) 29)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+   {
+     USI opval = EXTSISI (FLD (i_call));
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPE) : /* cmpe $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EQSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPEI) : /* cmpei $r1,$r0,$imm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EQSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPG) : /* cmpg $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GTSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPGI) : /* cmpgi $r1,$r0,$imm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GTSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPGE) : /* cmpge $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPGEI) : /* cmpgei $r1,$r0,$imm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GESI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPGEU) : /* cmpgeu $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GEUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPGEUI) : /* cmpgeui $r1,$r0,$uimm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GEUSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPGU) : /* cmpgu $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GTUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPGUI) : /* cmpgui $r1,$r0,$uimm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GTUSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPNE) : /* cmpne $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = NESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_CMPNEI) : /* cmpnei $r1,$r0,$imm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = NESI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_DIVU) : /* divu $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = lm32bf_divu_insn (current_cpu, pc, FLD (f_r0), FLD (f_r1), FLD (f_r2));
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_LB) : /* lb $r1,($r0+$imm) */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EXTQISI (GETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_LBU) : /* lbu $r1,($r0+$imm) */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ZEXTQISI (GETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_LH) : /* lh $r1,($r0+$imm) */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EXTHISI (GETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_LHU) : /* lhu $r1,($r0+$imm) */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ZEXTHISI (GETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_LW) : /* lw $r1,($r0+$imm) */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GETMEMSI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_MODU) : /* modu $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = lm32bf_modu_insn (current_cpu, pc, FLD (f_r0), FLD (f_r1), FLD (f_r2));
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_MUL) : /* mul $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = MULSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_MULI) : /* muli $r1,$r0,$imm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = MULSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_NOR) : /* nor $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = INVSI (ORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_NORI) : /* nori $r1,$r0,$uimm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = INVSI (ORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_OR) : /* or $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_ORI) : /* ori $r1,$r0,$lo16 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_ORHII) : /* orhi $r1,$r0,$hi16 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), SLLSI (FLD (f_uimm), 16));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_RCSR) : /* rcsr $r2,$csr */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_rcsr.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = CPU (h_csr[FLD (f_csr)]);
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SB) : /* sb ($r0+$imm),$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     QI opval = CPU (h_gr[FLD (f_r1)]);
+     SETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval);
+     TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SEXTB) : /* sextb $r2,$r0 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EXTQISI (TRUNCSIQI (CPU (h_gr[FLD (f_r0)])));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SEXTH) : /* sexth $r2,$r0 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EXTHISI (TRUNCSIHI (CPU (h_gr[FLD (f_r0)])));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SH) : /* sh ($r0+$imm),$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     HI opval = CPU (h_gr[FLD (f_r1)]);
+     SETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval);
+     TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SL) : /* sl $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SLLSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SLI) : /* sli $r1,$r0,$imm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SLLSI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SR) : /* sr $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SRASI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SRI) : /* sri $r1,$r0,$imm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SRASI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SRU) : /* sru $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SRLSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SRUI) : /* srui $r1,$r0,$imm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SRLSI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SUB) : /* sub $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SUBSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SW) : /* sw ($r0+$imm),$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = CPU (h_gr[FLD (f_r1)]);
+     SETMEMSI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval);
+     TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_USER) : /* user $r2,$r0,$r1,$user */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = lm32bf_user_insn (current_cpu, CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]), FLD (f_user));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_WCSR) : /* wcsr $csr,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_wcsr.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ lm32bf_wcsr_insn (current_cpu, FLD (f_csr), CPU (h_gr[FLD (f_r1)]));
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_XOR) : /* xor $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = XORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_XORI) : /* xori $r1,$r0,$uimm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = XORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_XNOR) : /* xnor $r2,$r0,$r1 */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_user.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = INVSI (XORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_XNORI) : /* xnori $r1,$r0,$uimm */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = INVSI (XORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_BREAK) : /* break */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.fmt_empty.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = lm32bf_break_insn (current_cpu, pc);
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+   CASE (sem, INSN_SCALL) : /* scall */
+ {
+   SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+ #define FLD(f) abuf->fields.fmt_empty.f
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = lm32bf_scall_insn (current_cpu, pc);
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+ #undef FLD
+ }
+   NEXT (vpc);
+ 
+ 
+     }
+   ENDSWITCH (sem) /* End of semantic switch.  */
+ 
+   /* At this point `vpc' contains the next insn to execute.  */
+ }
+ 
+ #undef DEFINE_SWITCH
+ #endif /* DEFINE_SWITCH */
Index: sim/lm32/sem.c
===================================================================
RCS file: sim/lm32/sem.c
diff -N sim/lm32/sem.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/sem.c	16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,1669 ----
+ /* Simulator instruction semantics for lm32bf.
+ 
+ THIS FILE IS MACHINE GENERATED WITH CGEN.
+ 
+ Copyright 1996-2005 Free Software Foundation, Inc.
+ 
+ This file is part of the GNU simulators.
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+ 
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ 
+ */
+ 
+ #define WANT_CPU lm32bf
+ #define WANT_CPU_LM32BF
+ 
+ #include "sim-main.h"
+ #include "cgen-mem.h"
+ #include "cgen-ops.h"
+ 
+ #undef GET_ATTR
+ #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+ #define GET_ATTR(cpu, num, attr) CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_##attr)
+ #else
+ #define GET_ATTR(cpu, num, attr) CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_/**/attr)
+ #endif
+ 
+ /* This is used so that we can compile two copies of the semantic code,
+    one with full feature support and one without that runs fast(er).
+    FAST_P, when desired, is defined on the command line, -DFAST_P=1.  */
+ #if FAST_P
+ #define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_semf_,fn)
+ #undef TRACE_RESULT
+ #define TRACE_RESULT(cpu, abuf, name, type, val)
+ #else
+ #define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn)
+ #endif
+ 
+ /* x-invalid: --invalid-- */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,x_invalid) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.fmt_empty.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+     /* Update the recorded pc in the cpu state struct.
+        Only necessary for WITH_SCACHE case, but to avoid the
+        conditional compilation ....  */
+     SET_H_PC (pc);
+     /* Virtual insns have zero size.  Overwrite vpc with address of next insn
+        using the default-insn-bitsize spec.  When executing insns in parallel
+        we may want to queue the fault and continue execution.  */
+     vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+     vpc = sim_engine_invalid_insn (current_cpu, pc, vpc);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* x-after: --after-- */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,x_after) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.fmt_empty.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+ #if WITH_SCACHE_PBB_LM32BF
+     lm32bf_pbb_after (current_cpu, sem_arg);
+ #endif
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* x-before: --before-- */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,x_before) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.fmt_empty.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+ #if WITH_SCACHE_PBB_LM32BF
+     lm32bf_pbb_before (current_cpu, sem_arg);
+ #endif
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* x-cti-chain: --cti-chain-- */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,x_cti_chain) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.fmt_empty.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+ #if WITH_SCACHE_PBB_LM32BF
+ #ifdef DEFINE_SWITCH
+     vpc = lm32bf_pbb_cti_chain (current_cpu, sem_arg,
+ 			       pbb_br_type, pbb_br_npc);
+     BREAK (sem);
+ #else
+     /* FIXME: Allow provision of explicit ifmt spec in insn spec.  */
+     vpc = lm32bf_pbb_cti_chain (current_cpu, sem_arg,
+ 			       CPU_PBB_BR_TYPE (current_cpu),
+ 			       CPU_PBB_BR_NPC (current_cpu));
+ #endif
+ #endif
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* x-chain: --chain-- */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,x_chain) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.fmt_empty.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+ #if WITH_SCACHE_PBB_LM32BF
+     vpc = lm32bf_pbb_chain (current_cpu, sem_arg);
+ #ifdef DEFINE_SWITCH
+     BREAK (sem);
+ #endif
+ #endif
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* x-begin: --begin-- */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,x_begin) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.fmt_empty.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0);
+ 
+   {
+ #if WITH_SCACHE_PBB_LM32BF
+ #if defined DEFINE_SWITCH || defined FAST_P
+     /* In the switch case FAST_P is a constant, allowing several optimizations
+        in any called inline functions.  */
+     vpc = lm32bf_pbb_begin (current_cpu, FAST_P);
+ #else
+ #if 0 /* cgen engine can't handle dynamic fast/full switching yet.  */
+     vpc = lm32bf_pbb_begin (current_cpu, STATE_RUN_FAST_P (CPU_STATE (current_cpu)));
+ #else
+     vpc = lm32bf_pbb_begin (current_cpu, 0);
+ #endif
+ #endif
+ #endif
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* add: add $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,add) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ADDSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* addi: addi $r1,$r0,$imm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,addi) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* and: and $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,and) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* andi: andi $r1,$r0,$uimm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,andi) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* andhii: andhi $r1,$r0,$hi16 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,andhii) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ANDSI (CPU (h_gr[FLD (f_r0)]), SLLSI (FLD (f_uimm), 16));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* b: b $r0 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,b) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = lm32bf_b_insn (current_cpu, CPU (h_gr[FLD (f_r0)]), FLD (f_r0));
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* bi: bi $call */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,bi) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_bi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = EXTSISI (FLD (i_call));
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* be: be $r0,$r1,$branch */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,be) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (EQSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* bg: bg $r0,$r1,$branch */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,bg) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (GTSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* bge: bge $r0,$r1,$branch */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,bge) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (GESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* bgeu: bgeu $r0,$r1,$branch */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,bgeu) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (GEUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* bgu: bgu $r0,$r1,$branch */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,bgu) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (GTUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* bne: bne $r0,$r1,$branch */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,bne) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ if (NESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]))) {
+   {
+     USI opval = FLD (i_branch);
+     SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, opval, vpc);
+     written |= (1 << 3);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   abuf->written = written;
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* call: call $r0 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,call) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_be.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ {
+   {
+     SI opval = ADDSI (pc, 4);
+     CPU (h_gr[((UINT) 29)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+   {
+     USI opval = CPU (h_gr[FLD (f_r0)]);
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* calli: calli $call */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,calli) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_bi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ {
+   {
+     SI opval = ADDSI (pc, 4);
+     CPU (h_gr[((UINT) 29)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+   {
+     USI opval = EXTSISI (FLD (i_call));
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ }
+ 
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpe: cmpe $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpe) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EQSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpei: cmpei $r1,$r0,$imm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpei) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EQSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpg: cmpg $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpg) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GTSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpgi: cmpgi $r1,$r0,$imm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpgi) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GTSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpge: cmpge $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpge) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpgei: cmpgei $r1,$r0,$imm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpgei) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GESI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpgeu: cmpgeu $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpgeu) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GEUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpgeui: cmpgeui $r1,$r0,$uimm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpgeui) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GEUSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpgu: cmpgu $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpgu) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GTUSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpgui: cmpgui $r1,$r0,$uimm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpgui) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GTUSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpne: cmpne $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpne) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = NESI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* cmpnei: cmpnei $r1,$r0,$imm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,cmpnei) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = NESI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* divu: divu $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,divu) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = lm32bf_divu_insn (current_cpu, pc, FLD (f_r0), FLD (f_r1), FLD (f_r2));
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* lb: lb $r1,($r0+$imm) */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,lb) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EXTQISI (GETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* lbu: lbu $r1,($r0+$imm) */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,lbu) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ZEXTQISI (GETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* lh: lh $r1,($r0+$imm) */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,lh) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EXTHISI (GETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* lhu: lhu $r1,($r0+$imm) */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,lhu) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ZEXTHISI (GETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* lw: lw $r1,($r0+$imm) */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,lw) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = GETMEMSI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* modu: modu $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,modu) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = lm32bf_modu_insn (current_cpu, pc, FLD (f_r0), FLD (f_r1), FLD (f_r2));
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* mul: mul $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,mul) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = MULSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* muli: muli $r1,$r0,$imm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,muli) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = MULSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* nor: nor $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,nor) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = INVSI (ORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* nori: nori $r1,$r0,$uimm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,nori) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = INVSI (ORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* or: or $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,or) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* ori: ori $r1,$r0,$lo16 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,ori) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* orhii: orhi $r1,$r0,$hi16 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,orhii) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = ORSI (CPU (h_gr[FLD (f_r0)]), SLLSI (FLD (f_uimm), 16));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* rcsr: rcsr $r2,$csr */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,rcsr) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_rcsr.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = CPU (h_csr[FLD (f_csr)]);
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* sb: sb ($r0+$imm),$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,sb) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     QI opval = CPU (h_gr[FLD (f_r1)]);
+     SETMEMQI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval);
+     TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* sextb: sextb $r2,$r0 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,sextb) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EXTQISI (TRUNCSIQI (CPU (h_gr[FLD (f_r0)])));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* sexth: sexth $r2,$r0 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,sexth) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = EXTHISI (TRUNCSIHI (CPU (h_gr[FLD (f_r0)])));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* sh: sh ($r0+$imm),$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,sh) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     HI opval = CPU (h_gr[FLD (f_r1)]);
+     SETMEMHI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval);
+     TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* sl: sl $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,sl) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SLLSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* sli: sli $r1,$r0,$imm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,sli) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SLLSI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* sr: sr $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,sr) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SRASI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* sri: sri $r1,$r0,$imm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,sri) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SRASI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* sru: sru $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,sru) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SRLSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* srui: srui $r1,$r0,$imm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,srui) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SRLSI (CPU (h_gr[FLD (f_r0)]), FLD (f_imm));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* sub: sub $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,sub) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = SUBSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* sw: sw ($r0+$imm),$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,sw) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_addi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = CPU (h_gr[FLD (f_r1)]);
+     SETMEMSI (current_cpu, pc, ADDSI (CPU (h_gr[FLD (f_r0)]), EXTHISI (TRUNCSIHI (FLD (f_imm)))), opval);
+     TRACE_RESULT (current_cpu, abuf, "memory", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* user: user $r2,$r0,$r1,$user */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,user) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = lm32bf_user_insn (current_cpu, CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]), FLD (f_user));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* wcsr: wcsr $csr,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,wcsr) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_wcsr.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+ lm32bf_wcsr_insn (current_cpu, FLD (f_csr), CPU (h_gr[FLD (f_r1)]));
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* xor: xor $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,xor) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = XORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)]));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* xori: xori $r1,$r0,$uimm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,xori) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = XORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm)));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* xnor: xnor $r2,$r0,$r1 */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,xnor) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_user.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = INVSI (XORSI (CPU (h_gr[FLD (f_r0)]), CPU (h_gr[FLD (f_r1)])));
+     CPU (h_gr[FLD (f_r2)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* xnori: xnori $r1,$r0,$uimm */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,xnori) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.sfmt_andi.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     SI opval = INVSI (XORSI (CPU (h_gr[FLD (f_r0)]), ZEXTSISI (FLD (f_uimm))));
+     CPU (h_gr[FLD (f_r1)]) = opval;
+     TRACE_RESULT (current_cpu, abuf, "gr", 'x', opval);
+   }
+ 
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* break: break */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,break) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.fmt_empty.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = lm32bf_break_insn (current_cpu, pc);
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* scall: scall */
+ 
+ static SEM_PC
+ SEM_FN_NAME (lm32bf,scall) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
+ {
+ #define FLD(f) abuf->fields.fmt_empty.f
+   ARGBUF *abuf = SEM_ARGBUF (sem_arg);
+   int UNUSED written = 0;
+   IADDR UNUSED pc = abuf->addr;
+   SEM_BRANCH_INIT
+   SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
+ 
+   {
+     USI opval = lm32bf_scall_insn (current_cpu, pc);
+     SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, opval, vpc);
+     TRACE_RESULT (current_cpu, abuf, "pc", 'x', opval);
+   }
+ 
+   SEM_BRANCH_FINI (vpc);
+   return vpc;
+ #undef FLD
+ }
+ 
+ /* Table of all semantic fns.  */
+ 
+ static const struct sem_fn_desc sem_fns[] = {
+   { LM32BF_INSN_X_INVALID, SEM_FN_NAME (lm32bf,x_invalid) },
+   { LM32BF_INSN_X_AFTER, SEM_FN_NAME (lm32bf,x_after) },
+   { LM32BF_INSN_X_BEFORE, SEM_FN_NAME (lm32bf,x_before) },
+   { LM32BF_INSN_X_CTI_CHAIN, SEM_FN_NAME (lm32bf,x_cti_chain) },
+   { LM32BF_INSN_X_CHAIN, SEM_FN_NAME (lm32bf,x_chain) },
+   { LM32BF_INSN_X_BEGIN, SEM_FN_NAME (lm32bf,x_begin) },
+   { LM32BF_INSN_ADD, SEM_FN_NAME (lm32bf,add) },
+   { LM32BF_INSN_ADDI, SEM_FN_NAME (lm32bf,addi) },
+   { LM32BF_INSN_AND, SEM_FN_NAME (lm32bf,and) },
+   { LM32BF_INSN_ANDI, SEM_FN_NAME (lm32bf,andi) },
+   { LM32BF_INSN_ANDHII, SEM_FN_NAME (lm32bf,andhii) },
+   { LM32BF_INSN_B, SEM_FN_NAME (lm32bf,b) },
+   { LM32BF_INSN_BI, SEM_FN_NAME (lm32bf,bi) },
+   { LM32BF_INSN_BE, SEM_FN_NAME (lm32bf,be) },
+   { LM32BF_INSN_BG, SEM_FN_NAME (lm32bf,bg) },
+   { LM32BF_INSN_BGE, SEM_FN_NAME (lm32bf,bge) },
+   { LM32BF_INSN_BGEU, SEM_FN_NAME (lm32bf,bgeu) },
+   { LM32BF_INSN_BGU, SEM_FN_NAME (lm32bf,bgu) },
+   { LM32BF_INSN_BNE, SEM_FN_NAME (lm32bf,bne) },
+   { LM32BF_INSN_CALL, SEM_FN_NAME (lm32bf,call) },
+   { LM32BF_INSN_CALLI, SEM_FN_NAME (lm32bf,calli) },
+   { LM32BF_INSN_CMPE, SEM_FN_NAME (lm32bf,cmpe) },
+   { LM32BF_INSN_CMPEI, SEM_FN_NAME (lm32bf,cmpei) },
+   { LM32BF_INSN_CMPG, SEM_FN_NAME (lm32bf,cmpg) },
+   { LM32BF_INSN_CMPGI, SEM_FN_NAME (lm32bf,cmpgi) },
+   { LM32BF_INSN_CMPGE, SEM_FN_NAME (lm32bf,cmpge) },
+   { LM32BF_INSN_CMPGEI, SEM_FN_NAME (lm32bf,cmpgei) },
+   { LM32BF_INSN_CMPGEU, SEM_FN_NAME (lm32bf,cmpgeu) },
+   { LM32BF_INSN_CMPGEUI, SEM_FN_NAME (lm32bf,cmpgeui) },
+   { LM32BF_INSN_CMPGU, SEM_FN_NAME (lm32bf,cmpgu) },
+   { LM32BF_INSN_CMPGUI, SEM_FN_NAME (lm32bf,cmpgui) },
+   { LM32BF_INSN_CMPNE, SEM_FN_NAME (lm32bf,cmpne) },
+   { LM32BF_INSN_CMPNEI, SEM_FN_NAME (lm32bf,cmpnei) },
+   { LM32BF_INSN_DIVU, SEM_FN_NAME (lm32bf,divu) },
+   { LM32BF_INSN_LB, SEM_FN_NAME (lm32bf,lb) },
+   { LM32BF_INSN_LBU, SEM_FN_NAME (lm32bf,lbu) },
+   { LM32BF_INSN_LH, SEM_FN_NAME (lm32bf,lh) },
+   { LM32BF_INSN_LHU, SEM_FN_NAME (lm32bf,lhu) },
+   { LM32BF_INSN_LW, SEM_FN_NAME (lm32bf,lw) },
+   { LM32BF_INSN_MODU, SEM_FN_NAME (lm32bf,modu) },
+   { LM32BF_INSN_MUL, SEM_FN_NAME (lm32bf,mul) },
+   { LM32BF_INSN_MULI, SEM_FN_NAME (lm32bf,muli) },
+   { LM32BF_INSN_NOR, SEM_FN_NAME (lm32bf,nor) },
+   { LM32BF_INSN_NORI, SEM_FN_NAME (lm32bf,nori) },
+   { LM32BF_INSN_OR, SEM_FN_NAME (lm32bf,or) },
+   { LM32BF_INSN_ORI, SEM_FN_NAME (lm32bf,ori) },
+   { LM32BF_INSN_ORHII, SEM_FN_NAME (lm32bf,orhii) },
+   { LM32BF_INSN_RCSR, SEM_FN_NAME (lm32bf,rcsr) },
+   { LM32BF_INSN_SB, SEM_FN_NAME (lm32bf,sb) },
+   { LM32BF_INSN_SEXTB, SEM_FN_NAME (lm32bf,sextb) },
+   { LM32BF_INSN_SEXTH, SEM_FN_NAME (lm32bf,sexth) },
+   { LM32BF_INSN_SH, SEM_FN_NAME (lm32bf,sh) },
+   { LM32BF_INSN_SL, SEM_FN_NAME (lm32bf,sl) },
+   { LM32BF_INSN_SLI, SEM_FN_NAME (lm32bf,sli) },
+   { LM32BF_INSN_SR, SEM_FN_NAME (lm32bf,sr) },
+   { LM32BF_INSN_SRI, SEM_FN_NAME (lm32bf,sri) },
+   { LM32BF_INSN_SRU, SEM_FN_NAME (lm32bf,sru) },
+   { LM32BF_INSN_SRUI, SEM_FN_NAME (lm32bf,srui) },
+   { LM32BF_INSN_SUB, SEM_FN_NAME (lm32bf,sub) },
+   { LM32BF_INSN_SW, SEM_FN_NAME (lm32bf,sw) },
+   { LM32BF_INSN_USER, SEM_FN_NAME (lm32bf,user) },
+   { LM32BF_INSN_WCSR, SEM_FN_NAME (lm32bf,wcsr) },
+   { LM32BF_INSN_XOR, SEM_FN_NAME (lm32bf,xor) },
+   { LM32BF_INSN_XORI, SEM_FN_NAME (lm32bf,xori) },
+   { LM32BF_INSN_XNOR, SEM_FN_NAME (lm32bf,xnor) },
+   { LM32BF_INSN_XNORI, SEM_FN_NAME (lm32bf,xnori) },
+   { LM32BF_INSN_BREAK, SEM_FN_NAME (lm32bf,break) },
+   { LM32BF_INSN_SCALL, SEM_FN_NAME (lm32bf,scall) },
+   { 0, 0 }
+ };
+ 
+ /* Add the semantic fns to IDESC_TABLE.  */
+ 
+ void
+ SEM_FN_NAME (lm32bf,init_idesc_table) (SIM_CPU *current_cpu)
+ {
+   IDESC *idesc_table = CPU_IDESC (current_cpu);
+   const struct sem_fn_desc *sf;
+   int mach_num = MACH_NUM (CPU_MACH (current_cpu));
+ 
+   for (sf = &sem_fns[0]; sf->fn != 0; ++sf)
+     {
+       const CGEN_INSN *insn = idesc_table[sf->index].idata;
+       int valid_p = (CGEN_INSN_VIRTUAL_P (insn)
+ 		     || CGEN_INSN_MACH_HAS_P (insn, mach_num));
+ #if FAST_P
+       if (valid_p)
+ 	idesc_table[sf->index].sem_fast = sf->fn;
+       else
+ 	idesc_table[sf->index].sem_fast = SEM_FN_NAME (lm32bf,x_invalid);
+ #else
+       if (valid_p)
+ 	idesc_table[sf->index].sem_full = sf->fn;
+       else
+ 	idesc_table[sf->index].sem_full = SEM_FN_NAME (lm32bf,x_invalid);
+ #endif
+     }
+ }
+ 
Index: sim/lm32/sim-if.c
===================================================================
RCS file: sim/lm32/sim-if.c
diff -N sim/lm32/sim-if.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/sim-if.c	16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,287 ----
+ /* Main simulator entry points specific to Lattice Mico32.
+    Written by Jon Beniston <jon@beniston.com>
+    
+    This file is part of GDB, the GNU debugger.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ #include "sim-main.h"
+ #include "sim-options.h"
+ #include "libiberty.h"
+ #include "bfd.h"
+ 
+ #ifdef HAVE_STDLIB_H
+ #include <stdlib.h>
+ #endif
+ 
+ static void free_state (SIM_DESC);
+ static void print_lm32_misc_cpu (SIM_CPU *cpu, int verbose);
+ static DECLARE_OPTION_HANDLER (lm32_option_handler);
+ 
+ enum {
+   OPTION_ENDIAN = OPTION_START,
+ };
+ 
+ /* GDB passes -E, even though it's fixed, so we have to handle it here. common code only handles it if SIM_HAVE_BIENDIAN is defined, which it isn't for lm32 */
+ static const OPTION lm32_options[] =
+ {
+   { {"endian", required_argument, NULL, OPTION_ENDIAN},
+       'E', "big", "Set endianness",
+       lm32_option_handler },
+   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
+ };
+ 
+ /* Records simulator descriptor so utilities like lm32_dump_regs can be
+    called from gdb.  */
+ SIM_DESC current_state;
+ \f
+ /* Cover function of sim_state_free to free the cpu buffers as well.  */
+ 
+ static void
+ free_state (SIM_DESC sd)
+ {
+   if (STATE_MODULES (sd) != NULL)
+     sim_module_uninstall (sd);
+   sim_cpu_free_all (sd);
+   sim_state_free (sd);
+ }
+ 
+ /* Find memory range used by program */
+ 
+ static unsigned long 
+ find_base (bfd *prog_bfd)
+ {
+   int found;
+   unsigned long base = ~(0UL);
+   asection *s;
+ 
+   found = 0;
+   for (s = prog_bfd->sections; s; s = s->next)
+     {
+       if (   (strcmp (bfd_get_section_name (prog_bfd, s), ".boot") == 0)
+           || (strcmp (bfd_get_section_name (prog_bfd, s), ".text") == 0)
+           || (strcmp (bfd_get_section_name (prog_bfd, s), ".data") == 0)
+           || (strcmp (bfd_get_section_name (prog_bfd, s), ".bss") == 0)
+          ) 
+         {
+           if (!found) 
+             {
+               base = bfd_get_section_vma (prog_bfd, s);
+               found = 1;
+             } 
+           else 
+             base = bfd_get_section_vma (prog_bfd, s) < base ? bfd_get_section_vma (prog_bfd, s) : base;
+         }
+     }
+   return base & ~(0xffffUL);
+ }
+ 
+ static unsigned long 
+ find_limit (bfd *prog_bfd)
+ {
+   struct bfd_symbol **asymbols;
+   long symsize;
+   long symbol_count;
+   long s;
+ 
+   symsize = bfd_get_symtab_upper_bound (prog_bfd);
+   if (symsize < 0)
+     return 0;
+   asymbols = (asymbol **) xmalloc (symsize);
+   symbol_count = bfd_canonicalize_symtab (prog_bfd, asymbols);
+   if (symbol_count < 0)
+     return 0;
+ 		
+   for (s = 0; s < symbol_count; s++) 
+     {
+       if (!strcmp (asymbols[s]->name, "_fstack")) 
+         return (asymbols[s]->value + 65536) & ~(0xffffUL);
+     }
+   return 0;
+ }
+ 
+ /* Handle lm32 specific options */
+ 
+ static SIM_RC
+ lm32_option_handler (sd, cpu, opt, arg, is_command)
+      SIM_DESC sd;
+      sim_cpu *cpu;
+      int opt;
+      char *arg;
+      int is_command;
+ {
+   return SIM_RC_OK;
+ }
+ 
+ /* Create an instance of the simulator.  */
+ 
+ SIM_DESC
+ sim_open (kind, callback, abfd, argv)
+      SIM_OPEN_KIND kind;
+      host_callback *callback;
+      struct bfd *abfd;
+      char **argv;
+ {
+   SIM_DESC sd = sim_state_alloc (kind, callback);
+   char c;
+   int i;
+   unsigned long base, limit;
+ 
+   /* The cpu data is kept in a separately allocated chunk of memory.  */
+   if (sim_cpu_alloc_all (sd, 1, cgen_cpu_max_extra_bytes ()) != SIM_RC_OK)
+     {
+       free_state (sd);
+       return 0;
+     }
+ 
+   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
+     {
+       free_state (sd);
+       return 0;
+     }
+   sim_add_option_table (sd, NULL, lm32_options);
+ 
+   /* getopt will print the error message so we just have to exit if this fails.
+      FIXME: Hmmm...  in the case of gdb we need getopt to call
+      print_filtered.  */
+   if (sim_parse_args (sd, argv) != SIM_RC_OK)
+     {
+       free_state (sd);
+       return 0;
+     }
+ 
+ #if 0
+   /* Allocate a handler for I/O devices
+      if no memory for that range has been allocated by the user.
+      All are allocated in one chunk to keep things from being
+      unnecessarily complicated.  */
+   if (sim_core_read_buffer (sd, NULL, read_map, &c, LM32_DEVICE_ADDR, 1) == 0)
+     sim_core_attach (sd, NULL,
+ 		     0 /*level*/,
+ 		     access_read_write,
+ 		     0 /*space ???*/,
+ 		     LM32_DEVICE_ADDR, LM32_DEVICE_LEN /*nr_bytes*/,
+ 		     0 /*modulo*/,
+ 		     &lm32_devices,
+ 		     NULL /*buffer*/);
+ #endif
+ 
+   /* check for/establish the reference program image */
+   if (sim_analyze_program (sd,
+ 			   (STATE_PROG_ARGV (sd) != NULL
+ 			    ? *STATE_PROG_ARGV (sd)
+ 			    : NULL),
+ 			   abfd) != SIM_RC_OK)
+     {
+       free_state (sd);
+       return 0;
+     }
+ 
+   /* Check to see if memory exists at programs start address */
+   if (sim_core_read_buffer (sd, NULL, read_map, &c, STATE_START_ADDR (sd), 1) == 0)
+     {
+       if (STATE_PROG_BFD (sd) != NULL) {
+         /* It doesn't, so we should try to allocate enough memory to hold program */
+         base = find_base (STATE_PROG_BFD (sd));
+         limit = find_limit (STATE_PROG_BFD (sd));
+         if (limit == 0) 
+           {
+             sim_io_eprintf (sd, "Failed to find symbol _fstack in program. You must specify memory regions with --memory-region.\n");
+             free_state (sd);
+             return 0;
+           }
+         /*sim_io_printf (sd, "Allocating memory at 0x%x size 0x%x\n", base, limit);*/
+         sim_do_commandf (sd, "memory region 0x%x,0x%x", base, limit);
+       }
+     }
+ 
+   /* Establish any remaining configuration options.  */
+   if (sim_config (sd) != SIM_RC_OK)
+     {
+       free_state (sd);
+       return 0;
+     }
+ 
+   if (sim_post_argv_init (sd) != SIM_RC_OK)
+     {
+       free_state (sd);
+       return 0;
+     }
+ 
+   /* Open a copy of the cpu descriptor table.  */
+   {
+     CGEN_CPU_DESC cd = lm32_cgen_cpu_open_1 (STATE_ARCHITECTURE (sd)->printable_name,
+ 					     CGEN_ENDIAN_BIG);
+     for (i = 0; i < MAX_NR_PROCESSORS; ++i)
+       {
+ 	SIM_CPU *cpu = STATE_CPU (sd, i);
+ 	CPU_CPU_DESC (cpu) = cd;
+ 	CPU_DISASSEMBLER (cpu) = sim_cgen_disassemble_insn;
+       }
+     lm32_cgen_init_dis (cd);
+   }
+ 
+   /* Initialize various cgen things not done by common framework.
+      Must be done after lm32_cgen_cpu_open.  */
+   cgen_init (sd);
+ 
+   /* Store in a global so things like lm32_dump_regs can be invoked
+      from the gdb command line.  */
+   current_state = sd;
+ 
+   return sd;
+ }
+ 
+ void
+ sim_close (sd, quitting)
+      SIM_DESC sd;
+      int quitting;
+ {
+   lm32_cgen_cpu_close (CPU_CPU_DESC (STATE_CPU (sd, 0)));
+   sim_module_uninstall (sd);
+ }
+ \f
+ SIM_RC
+ sim_create_inferior (sd, abfd, argv, envp)
+      SIM_DESC sd;
+      struct bfd *abfd;
+      char **argv;
+      char **envp;
+ {
+   SIM_CPU *current_cpu = STATE_CPU (sd, 0);
+   SIM_ADDR addr;
+ 
+   if (abfd != NULL)
+     addr = bfd_get_start_address (abfd);
+   else
+     addr = 0;
+   sim_pc_set (current_cpu, addr);
+ 
+ #if 0
+   STATE_ARGV (sd) = sim_copy_argv (argv);
+   STATE_ENVP (sd) = sim_copy_argv (envp);
+ #endif
+ 
+   return SIM_RC_OK;
+ }
+ 
+ void
+ sim_do_command (sd, cmd)
+      SIM_DESC sd;
+      char *cmd;
+ { 
+   if (sim_args_command (sd, cmd) != SIM_RC_OK)
+     sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
+ }
Index: sim/lm32/sim-main.h
===================================================================
RCS file: sim/lm32/sim-main.h
diff -N sim/lm32/sim-main.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/sim-main.h	16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,99 ----
+ /* LM32 simulator support code
+    Written by Jon Beniston <jon@beniston.com>
+ 
+ This file is part of the GNU simulators.
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+ 
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ /* Main header for the LM32 simulator.  */
+ 
+ #ifndef SIM_MAIN_H
+ #define SIM_MAIN_H
+ 
+ #define USING_SIM_BASE_H /* FIXME: quick hack */
+ 
+ struct _sim_cpu; /* FIXME: should be in sim-basics.h */
+ typedef struct _sim_cpu SIM_CPU;
+ 
+ #include "symcat.h"
+ #include "sim-basics.h"
+ #include "cgen-types.h"
+ #include "lm32-desc.h"
+ #include "lm32-opc.h"
+ #include "arch.h"
+ 
+ /* These must be defined before sim-base.h.  */
+ typedef USI sim_cia;
+ 
+ #define CIA_GET(cpu)     CPU_PC_GET (cpu)
+ #define CIA_SET(cpu,val) CPU_PC_SET ((cpu), (val))
+ 
+ #define SIM_ENGINE_HALT_HOOK(sd, cpu, cia) \
+ do { \
+   if (cpu) /* null if ctrl-c */ \
+     sim_pc_set ((cpu), (cia)); \
+ } while (0)
+ #define SIM_ENGINE_RESTART_HOOK(sd, cpu, cia) \
+ do { \
+   sim_pc_set ((cpu), (cia)); \
+ } while (0)
+ 
+ #include "sim-base.h"
+ #include "cgen-sim.h"
+ #include "lm32-sim.h"
+ #include "opcode/cgen.h"
+ \f
+ /* The _sim_cpu struct.  */
+ 
+ struct _sim_cpu {
+   /* sim/common cpu base.  */
+   sim_cpu_base base;
+ 
+   /* Static parts of cgen.  */
+   CGEN_CPU cgen_cpu;
+ 
+   /* CPU specific parts go here.
+      Note that in files that don't need to access these pieces WANT_CPU_FOO
+      won't be defined and thus these parts won't appear.  This is ok in the
+      sense that things work.  It is a source of bugs though.
+      One has to of course be careful to not take the size of this
+      struct and no structure members accessed in non-cpu specific files can
+      go after here.  Oh for a better language.  */
+ #if defined (WANT_CPU_LM32BF)
+   LM32BF_CPU_DATA cpu_data;
+ #endif
+  
+ };
+ \f
+ /* The sim_state struct.  */
+ 
+ struct sim_state {
+   sim_cpu *cpu;
+ #define STATE_CPU(sd, n) (/*&*/ (sd)->cpu)
+ 
+   CGEN_STATE cgen_state;
+ 
+   sim_state_base base;
+ };
+ \f
+ /* Misc.  */
+ 
+ /* Catch address exceptions.  */
+ extern SIM_CORE_SIGNAL_FN lm32_core_signal;
+ #define SIM_CORE_SIGNAL(SD,CPU,CIA,MAP,NR_BYTES,ADDR,TRANSFER,ERROR) \
+ lm32_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), \
+ 		  (TRANSFER), (ERROR))
+ 
+ #endif /* SIM_MAIN_H */
Index: sim/lm32/tconfig.in
===================================================================
RCS file: sim/lm32/tconfig.in
diff -N sim/lm32/tconfig.in
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/tconfig.in	16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,28 ----
+ /* LatticeMico32 simulator configuration.
+    Contributed by Jon Beniston <jon@beniston.com>
+ 
+    This file is part of GDB, the GNU debugger.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ #ifndef LM32_TCONFIG_H
+ #define LM32_TCONFIG_H
+ 
+ /* See sim-hload.c.  We properly handle LMA.  */
+ #define SIM_HANDLES_LMA 1
+ 
+ #define WITH_SCACHE_PBB 1
+ 
+ #endif /* LM32_TCONFIG_H */
Index: sim/lm32/traps.c
===================================================================
RCS file: sim/lm32/traps.c
diff -N sim/lm32/traps.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/traps.c	16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,264 ----
+ /* Lattice Mico32 exception and system call support.
+    Contributed by Jon Beniston <jon@beniston.com>
+ 
+    This file is part of GDB, the GNU debugger.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ #define WANT_CPU lm32bf
+ #define WANT_CPU_LM32BF
+ 
+ #include "sim-main.h"
+ #include "lm32-sim.h"
+ #include "targ-vals.h"
+    
+ /* Read memory function for system call interface.  */
+ 
+ static int
+ syscall_read_mem (host_callback *cb, struct cb_syscall *sc,
+ 		  unsigned long taddr, char *buf, int bytes)
+ {
+   SIM_DESC sd = (SIM_DESC) sc->p1;
+   SIM_CPU *cpu = (SIM_CPU *) sc->p2;
+ 
+   return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
+ }
+ 
+ /* Write memory function for system call interface.  */
+ 
+ static int
+ syscall_write_mem (host_callback *cb, struct cb_syscall *sc,
+ 		   unsigned long taddr, const char *buf, int bytes)
+ {
+   SIM_DESC sd = (SIM_DESC) sc->p1;
+   SIM_CPU *cpu = (SIM_CPU *) sc->p2;
+ 
+   return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
+ }
+ 
+ /* Handle invalid instructions.  */ 
+    
+ SEM_PC
+ sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC pc)
+ {
+   SIM_DESC sd = CPU_STATE (current_cpu);
+ 
+   sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
+ 
+   return pc;
+ }
+ 
+ /* Handle divide instructions. */
+ 
+ USI
+ lm32bf_divu_insn (SIM_CPU *current_cpu, IADDR pc, USI r0, USI r1, USI r2)
+ {
+   SIM_DESC sd = CPU_STATE (current_cpu);
+   host_callback *cb = STATE_CALLBACK (sd);
+ 
+   /* Check for divide by zero */
+   if (GET_H_GR (r1) == 0)
+     {
+       if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
+         sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE);
+       else 
+         {
+           /* Save PC in exception address register.  */
+           SET_H_GR (30, pc);
+           /* Save and clear interrupt enable */
+           SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
+           /* Branch to divide by zero exception handler.  */
+           return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32;
+         }
+     }
+   else
+     {
+       SET_H_GR (r2, (USI)GET_H_GR (r0) / (USI)GET_H_GR (r1));
+       return pc + 4;
+     }
+ }
+ 
+ USI
+ lm32bf_modu_insn (SIM_CPU *current_cpu, IADDR pc, USI r0, USI r1, USI r2)
+ {
+   SIM_DESC sd = CPU_STATE (current_cpu);
+   host_callback *cb = STATE_CALLBACK (sd);
+ 
+   /* Check for divide by zero */
+   if (GET_H_GR (r1) == 0)
+     {
+       if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
+         sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE);
+       else 
+         {
+           /* Save PC in exception address register.  */
+           SET_H_GR (30, pc);
+           /* Save and clear interrupt enable */
+           SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
+           /* Branch to divide by zero exception handler.  */
+           return  GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32;
+         }
+     }
+   else
+     {
+       SET_H_GR (r2, (USI)GET_H_GR (r0) % (USI)GET_H_GR (r1));
+       return pc + 4;
+     }
+ }
+ 
+ /* Handle break instructions.  */
+ 
+ USI
+ lm32bf_break_insn (SIM_CPU *current_cpu, IADDR pc)
+ {
+   SIM_DESC sd = CPU_STATE (current_cpu);
+   host_callback *cb = STATE_CALLBACK (sd);
+   /* Breakpoint.  */
+   if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
+     { 
+       sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
+       return pc;
+     }
+   else
+     {
+       /* Save PC in breakpoint address register.  */
+       SET_H_GR (31, pc);
+       /* Save and clear interrupt enable */
+       SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 2);
+       /* Branch to breakpoint exception handler.  */
+       return  GET_H_CSR (LM32_CSR_DEBA) + LM32_EID_BREAKPOINT * 32;
+     }
+ }
+ 
+ /* Handle scall instructions.  */
+ 
+ USI
+ lm32bf_scall_insn (SIM_CPU *current_cpu, IADDR pc)
+ {
+   SIM_DESC sd = CPU_STATE (current_cpu);
+   host_callback *cb = STATE_CALLBACK (sd);
+ 
+   if (   (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
+       || (GET_H_GR (8) == TARGET_SYS_exit)
+      ) 
+     {
+       /* Delegate system call to host O/S.  */
+       CB_SYSCALL s;
+       CB_SYSCALL_INIT (&s);
+       s.p1 = (PTR)sd;
+       s.p2 = (PTR)current_cpu;
+       s.read_mem = syscall_read_mem;
+       s.write_mem = syscall_write_mem;
+       /* Extract parameters.  */
+       s.func = GET_H_GR (8);
+       s.arg1 = GET_H_GR (1);
+       s.arg2 = GET_H_GR (2);
+       s.arg3 = GET_H_GR (3);
+       /* Halt the simulator if the requested system call is _exit.  */
+       if (s.func == TARGET_SYS_exit) 
+         sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1);
+       /* Perform the system call.  */
+       cb_syscall (cb, &s);
+       /* Store the return value in the CPU's registers.  */
+       SET_H_GR (1, s.result);
+       SET_H_GR (2, s.result2);
+       SET_H_GR (3, s.errcode);
+       /* Skip over scall instruction.  */
+       return pc + 4;      
+     }
+   else 
+     {
+       /* Save PC in exception address register.  */
+       SET_H_GR (30, pc);
+       /* Save and clear interrupt enable */
+       SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
+       /* Branch to system call exception handler.  */
+       return  GET_H_CSR (LM32_CSR_EBA) + LM32_EID_SYSTEM_CALL * 32;
+     }
+ }
+ 
+ /* Handle b instructions.  */
+ 
+ USI
+ lm32bf_b_insn (SIM_CPU *current_cpu, USI r0, USI f_r0)
+ {
+   SIM_DESC sd = CPU_STATE (current_cpu);
+   host_callback *cb = STATE_CALLBACK (sd);
+   
+   /* Restore interrupt enable */
+   if (f_r0 == 30) 
+     SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 2) >> 1);
+   else if (f_r0 == 31) 
+     SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 4) >> 2);
+   return r0;  
+ }
+ 
+ /* Handle wcsr instructions.  */
+ 
+ void
+ lm32bf_wcsr_insn (SIM_CPU *current_cpu, USI f_csr, USI r1)
+ {
+   SIM_DESC sd = CPU_STATE (current_cpu);
+   host_callback *cb = STATE_CALLBACK (sd);
+ 
+   /* Writing a 1 to IP CSR clears a bit, writing 0 has no effect */
+   if (f_csr == LM32_CSR_IP) 
+     SET_H_CSR (f_csr, GET_H_CSR (f_csr) & ~r1);
+   else
+     SET_H_CSR (f_csr, r1);
+ }
+ 
+ /* Handle signals.  */
+ 
+ void
+ lm32_core_signal (SIM_DESC sd,
+ 		 sim_cpu *cpu,
+ 		 sim_cia cia,
+ 		 unsigned map,
+ 		 int nr_bytes,
+ 		 address_word addr,
+ 		 transfer_type transfer,
+ 		 sim_core_signals sig)
+ {
+   const char *copy = (transfer == read_transfer ? "read" : "write");
+   address_word ip = CIA_ADDR (cia);
+   SIM_CPU *current_cpu = cpu;
+   
+   switch (sig)
+     {
+     case sim_core_unmapped_signal:
+       sim_io_eprintf (sd, "core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
+ 		      nr_bytes, copy, (unsigned long) addr, (unsigned long) ip);
+       SET_H_GR (30, ip);
+       /* Save and clear interrupt enable */
+       SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
+       CIA_SET (cpu,  GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DATA_BUS_ERROR * 32);
+       sim_engine_halt (sd, cpu, NULL, LM32_EID_DATA_BUS_ERROR * 32, sim_stopped, SIM_SIGSEGV);
+       break;
+     case sim_core_unaligned_signal:
+       sim_io_eprintf (sd, "core: %d byte misaligned %s to address 0x%lx at 0x%lx\n",
+ 		      nr_bytes, copy, (unsigned long) addr, (unsigned long) ip);
+       SET_H_GR (30, ip);
+       /* Save and clear interrupt enable */
+       SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
+       CIA_SET (cpu,  GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DATA_BUS_ERROR * 32);
+       sim_engine_halt (sd, cpu, NULL, LM32_EID_DATA_BUS_ERROR * 32, sim_stopped, SIM_SIGBUS);
+       break;
+     default:
+       sim_engine_abort (sd, cpu, cia,
+ 			"sim_core_signal - internal error - bad switch");
+     }
+ }
+ 
Index: sim/lm32/user.c
===================================================================
RCS file: sim/lm32/user.c
diff -N sim/lm32/user.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sim/lm32/user.c	16 Dec 2008 00:41:36 -0000
***************
*** 0 ****
--- 1,29 ----
+ /* Semantics for user defined instructions on the Lattice Mico32.
+    Contributed by Jon Beniston <jon@beniston.com>
+ 
+    This file is part of GDB, the GNU debugger.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ #include "sim-main.h"
+    
+ /* Handle user defined instructions */
+ 
+ UINT
+ lm32bf_user_insn (SIM_CPU *current_cpu, INT r0, INT r1, UINT imm)
+ {
+   /* FIXME: Should probably call code in a user supplied library.  */   
+   return 0;
+ }

^ 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-22 12:06 [PATCH] Add support for the Lattice Mico32 (LM32) architecture 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
  -- strict thread matches above, loose matches on Subject: below --
2008-12-16  0:52 Jon Beniston

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox