]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - sim/d10v/simops.c
Add DM (bit 4) to PSW. See 7-1 for more info.
[thirdparty/binutils-gdb.git] / sim / d10v / simops.c
index bb8b913bcffec4f2355c72e6360ce1f87571dac9..b085c148c715c18c54935d451fb9f24b1814987f 100644 (file)
@@ -1,13 +1,19 @@
+#include "config.h"
+
 #include <signal.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 
 #include "d10v_sim.h"
 #include "simops.h"
 #include "sys/syscall.h"
 
+extern char *strrchr ();
+
 enum op_types {
   OP_VOID,
   OP_REG,
@@ -21,38 +27,60 @@ enum op_types {
   OP_CR_OUTPUT,
   OP_CR_REVERSE,
   OP_FLAG,
+  OP_FLAG_OUTPUT,
   OP_CONSTANT16,
+  OP_CONSTANT8,
   OP_CONSTANT3,
   OP_CONSTANT4,
   OP_MEMREF,
   OP_MEMREF2,
   OP_POSTDEC,
   OP_POSTINC,
-  OP_PREDEC
+  OP_PREDEC,
+  OP_R2,
+  OP_R3,
+  OP_R4,
+  OP_R2R3
 };
 
 #ifdef DEBUG
-static void trace_input PARAMS ((char *name,
-                                enum op_types in1,
-                                enum op_types in2,
-                                enum op_types in3));
+static void trace_input_func PARAMS ((char *name,
+                                     enum op_types in1,
+                                     enum op_types in2,
+                                     enum op_types in3));
+
+#define trace_input(name, in1, in2, in3) do { if (d10v_debug) trace_input_func (name, in1, in2, in3); } while (0)
 
-static void trace_output PARAMS ((enum op_types result));
+static void trace_output_func PARAMS ((enum op_types result));
+
+#define trace_output(result) do { if (d10v_debug) trace_output_func (result); } while (0)
 
 #ifndef SIZE_INSTRUCTION
-#define SIZE_INSTRUCTION 10
+#define SIZE_INSTRUCTION 8
 #endif
 
 #ifndef SIZE_OPERANDS
-#define SIZE_OPERANDS 24
+#define SIZE_OPERANDS 18
 #endif
 
 #ifndef SIZE_VALUES
 #define SIZE_VALUES 13
 #endif
 
+#ifndef SIZE_LOCATION
+#define SIZE_LOCATION 20
+#endif
+
+#ifndef SIZE_PC
+#define SIZE_PC 6
+#endif
+
+#ifndef SIZE_LINE_NUMBER
+#define SIZE_LINE_NUMBER 4
+#endif
+
 static void
-trace_input (name, in1, in2, in3)
+trace_input_func (name, in1, in2, in3)
      char *name;
      enum op_types in1;
      enum op_types in2;
@@ -61,10 +89,14 @@ trace_input (name, in1, in2, in3)
   char *comma;
   enum op_types in[3];
   int i;
-  char buf[80];
+  char buf[1024];
   char *p;
   long tmp;
   char *type;
+  const char *filename;
+  const char *functionname;
+  unsigned int linenumber;
+  bfd_vma byte_pc;
 
   if ((d10v_debug & DEBUG_TRACE) == 0)
     return;
@@ -77,13 +109,68 @@ trace_input (name, in1, in2, in3)
     case INS_RIGHT:            type = " R"; break;
     case INS_LEFT_PARALLEL:    type = "*L"; break;
     case INS_RIGHT_PARALLEL:   type = "*R"; break;
+    case INS_LEFT_COND_TEST:   type = "?L"; break;
+    case INS_RIGHT_COND_TEST:  type = "?R"; break;
+    case INS_LEFT_COND_EXE:    type = "&L"; break;
+    case INS_RIGHT_COND_EXE:   type = "&R"; break;
     case INS_LONG:             type = " B"; break;
     }
 
-  (*d10v_callback->printf_filtered) (d10v_callback,
-                                    "0x%.6x %s:  %-*s",
-                                    (unsigned)PC, type,
-                                    SIZE_INSTRUCTION, name);
+  if ((d10v_debug & DEBUG_LINE_NUMBER) == 0)
+    (*d10v_callback->printf_filtered) (d10v_callback,
+                                      "0x%.*x %s: %-*s ",
+                                      SIZE_PC, (unsigned)PC,
+                                      type,
+                                      SIZE_INSTRUCTION, name);
+
+  else
+    {
+      buf[0] = '\0';
+      byte_pc = decode_pc ();
+      if (text && byte_pc >= text_start && byte_pc < text_end)
+       {
+         filename = (const char *)0;
+         functionname = (const char *)0;
+         linenumber = 0;
+         if (bfd_find_nearest_line (prog_bfd, text, (struct symbol_cache_entry **)0, byte_pc - text_start,
+                                    &filename, &functionname, &linenumber))
+           {
+             p = buf;
+             if (linenumber)
+               {
+                 sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, linenumber);
+                 p += strlen (p);
+               }
+             else
+               {
+                 sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
+                 p += SIZE_LINE_NUMBER+2;
+               }
+
+             if (functionname)
+               {
+                 sprintf (p, "%s ", functionname);
+                 p += strlen (p);
+               }
+             else if (filename)
+               {
+                 char *q = strrchr (filename, '/');
+                 sprintf (p, "%s ", (q) ? q+1 : filename);
+                 p += strlen (p);
+               }
+
+             if (*p == ' ')
+               *p = '\0';
+           }
+       }
+
+      (*d10v_callback->printf_filtered) (d10v_callback,
+                                        "0x%.*x %s: %-*.*s %-*s ",
+                                        SIZE_PC, (unsigned)PC,
+                                        type,
+                                        SIZE_LOCATION, SIZE_LOCATION, buf,
+                                        SIZE_INSTRUCTION, name);
+    }
 
   in[0] = in1;
   in[1] = in2;
@@ -95,6 +182,10 @@ trace_input (name, in1, in2, in3)
       switch (in[i])
        {
        case OP_VOID:
+       case OP_R2:
+       case OP_R3:
+       case OP_R4:
+       case OP_R2R3:
          break;
 
        case OP_REG:
@@ -128,6 +219,12 @@ trace_input (name, in1, in2, in3)
          comma = ",";
          break;
 
+       case OP_CONSTANT8:
+         sprintf (p, "%s%d", comma, SEXT8(OP[i]));
+         p += strlen (p);
+         comma = ",";
+         break;
+
        case OP_CONSTANT4:
          sprintf (p, "%s%d", comma, SEXT4(OP[i]));
          p += strlen (p);
@@ -171,6 +268,7 @@ trace_input (name, in1, in2, in3)
          break;
 
        case OP_FLAG:
+       case OP_FLAG_OUTPUT:
          if (OP[i] == 0)
            sprintf (p, "%sf0", comma);
 
@@ -178,7 +276,7 @@ trace_input (name, in1, in2, in3)
            sprintf (p, "%sf1", comma);
 
          else
-           sprintf (p, "%scarry", comma);
+           sprintf (p, "%sc", comma);
 
          p += strlen (p);
          comma = ",";
@@ -211,6 +309,7 @@ trace_input (name, in1, in2, in3)
            case OP_DREG_OUTPUT:
            case OP_CR_OUTPUT:
            case OP_ACCUM_OUTPUT:
+           case OP_FLAG_OUTPUT:
              (*d10v_callback->printf_filtered) (d10v_callback, "%*s", SIZE_VALUES, "---");
              break;
 
@@ -251,6 +350,11 @@ trace_input (name, in1, in2, in3)
                                                 (uint16)SEXT4(OP[i]));
              break;
 
+           case OP_CONSTANT8:
+             (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+                                                (uint16)SEXT8(OP[i]));
+             break;
+
            case OP_CONSTANT3:
              (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
                                                 (uint16)SEXT3(OP[i]));
@@ -277,13 +381,38 @@ trace_input (name, in1, in2, in3)
              (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
                                                 (uint16)State.regs[OP[++i]]);
              break;
+
+           case OP_R2:
+             (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+                                                (uint16)State.regs[2]);
+             break;
+
+           case OP_R3:
+             (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+                                                (uint16)State.regs[3]);
+             break;
+
+           case OP_R4:
+             (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+                                                (uint16)State.regs[4]);
+             break;
+
+           case OP_R2R3:
+             (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+                                                (uint16)State.regs[2]);
+             (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "",
+                                                (uint16)State.regs[3]);
+             i++;
+             break;
            }
        }
     }
+
+  (*d10v_callback->flush_stdout) (d10v_callback);
 }
 
 static void
-trace_output (result)
+trace_output_func (result)
      enum op_types result;
 {
   if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES))
@@ -339,11 +468,26 @@ trace_output (result)
          break;
 
        case OP_FLAG:
+       case OP_FLAG_OUTPUT:
          (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s F0=%d F1=%d C=%d\n", SIZE_VALUES, "",
                                             State.F0 != 0, State.F1 != 0, State.C != 0);
          break;
+
+       case OP_R2:
+         (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-6, "",
+                                            (uint16)State.regs[2],
+                                            State.F0 != 0, State.F1 != 0, State.C != 0);
+         break;
+
+       case OP_R2R3:
+         (*d10v_callback->printf_filtered) (d10v_callback, " :: %*s0x%.4x%.4x F0=%d F1=%d C=%d\n", SIZE_VALUES-10, "",
+                                            (uint16)State.regs[2], (uint16)State.regs[3],
+                                            State.F0 != 0, State.F1 != 0, State.C != 0);
+         break;
        }
     }
+
+  (*d10v_callback->flush_stdout) (d10v_callback);
 }
 
 #else
@@ -461,15 +605,12 @@ void
 OP_1200 ()
 {
   uint32 tmp;
-  uint32 tmp1 = (State.regs[OP[0]]) << 16 | State.regs[OP[0]+1];
-  uint32 tmp2 = (State.regs[OP[1]]) << 16 | State.regs[OP[1]+1];
+  uint32 a = (State.regs[OP[0]]) << 16 | State.regs[OP[0]+1];
+  uint32 b = (State.regs[OP[1]]) << 16 | State.regs[OP[1]+1];
 
   trace_input ("add2w", OP_DREG, OP_DREG, OP_VOID);
-  tmp = tmp1 + tmp2;
-  if ( (tmp < tmp1) || (tmp < tmp2) )
-    State.C = 1;
-  else
-    State.C = 0;
+  tmp = a + b;
+  State.C = (tmp < a);
   State.regs[OP[0]] = tmp >> 16;
   State.regs[OP[0]+1] = tmp & 0xFFFF;
   trace_output (OP_DREG);
@@ -479,14 +620,11 @@ OP_1200 ()
 void
 OP_1000000 ()
 {
-  uint16 tmp = State.regs[OP[0]];
-  State.regs[OP[0]] = State.regs[OP[1]] + OP[2];
+  uint16 tmp = State.regs[OP[1]];
+  State.regs[OP[0]] = tmp + OP[2];
 
   trace_input ("add3", OP_REG_OUTPUT, OP_REG, OP_CONSTANT16);
-  if ( tmp > State.regs[OP[0]])
-    State.C = 1;
-  else
-    State.C = 0;
+  State.C = (State.regs[OP[0]] < tmp);
   trace_output (OP_REG);
 }
 
@@ -580,10 +718,13 @@ OP_17001202 ()
 void
 OP_201 ()
 {
+  uint tmp = State.regs[OP[0]];
   if (OP[1] == 0)
     OP[1] = 16;
+
   trace_input ("addi", OP_REG, OP_CONSTANT16, OP_VOID);
   State.regs[OP[0]] += OP[1];
+  State.C = (State.regs[OP[0]] < tmp);
   trace_output (OP_REG);
 }
 
@@ -618,9 +759,9 @@ OP_C01 ()
 void
 OP_4900 ()
 {
-  trace_input ("bl.s", OP_CONSTANT16, OP_VOID, OP_VOID);
+  trace_input ("bl.s", OP_CONSTANT8, OP_R2, OP_R3);
   State.regs[13] = PC+1;
-  PC += SEXT8 (OP[0]);
+  JMP( PC + SEXT8 (OP[0]));
   trace_output (OP_VOID);
 }
 
@@ -628,9 +769,9 @@ OP_4900 ()
 void
 OP_24800000 ()
 {
-  trace_input ("bl.l", OP_CONSTANT16, OP_VOID, OP_VOID);
+  trace_input ("bl.l", OP_CONSTANT16, OP_R2, OP_R3);
   State.regs[13] = PC+1;
-  PC += OP[0];
+  JMP (PC + OP[0]);
   trace_output (OP_VOID);
 }
 
@@ -647,8 +788,8 @@ OP_A01 ()
 void
 OP_4800 ()
 {
-  trace_input ("bra.s", OP_CONSTANT16, OP_VOID, OP_VOID);
-  PC += SEXT8 (OP[0]);
+  trace_input ("bra.s", OP_CONSTANT8, OP_VOID, OP_VOID);
+  JMP (PC + SEXT8 (OP[0]));
   trace_output (OP_VOID);
 }
 
@@ -657,7 +798,7 @@ void
 OP_24000000 ()
 {
   trace_input ("bra.l", OP_CONSTANT16, OP_VOID, OP_VOID);
-  PC += OP[0];
+  JMP (PC + OP[0]);
   trace_output (OP_VOID);
 }
 
@@ -665,9 +806,9 @@ OP_24000000 ()
 void
 OP_4A00 ()
 {
-  trace_input ("brf0f.s", OP_CONSTANT16, OP_VOID, OP_VOID);
+  trace_input ("brf0f.s", OP_CONSTANT8, OP_VOID, OP_VOID);
   if (State.F0 == 0)
-    PC += SEXT8 (OP[0]);
+    JMP (PC + SEXT8 (OP[0]));
   trace_output (OP_FLAG);
 }
 
@@ -677,7 +818,7 @@ OP_25000000 ()
 {
   trace_input ("brf0f.l", OP_CONSTANT16, OP_VOID, OP_VOID);
   if (State.F0 == 0)
-    PC += OP[0];
+    JMP (PC + OP[0]);
   trace_output (OP_FLAG);
 }
 
@@ -685,9 +826,9 @@ OP_25000000 ()
 void
 OP_4B00 ()
 {
-  trace_input ("brf0t.s", OP_CONSTANT16, OP_VOID, OP_VOID);
+  trace_input ("brf0t.s", OP_CONSTANT8, OP_VOID, OP_VOID);
   if (State.F0)
-    PC += SEXT8 (OP[0]);
+    JMP (PC + SEXT8 (OP[0]));
   trace_output (OP_FLAG);
 }
 
@@ -697,7 +838,7 @@ OP_25800000 ()
 {
   trace_input ("brf0t.l", OP_CONSTANT16, OP_VOID, OP_VOID);
   if (State.F0)
-    PC += OP[0];
+    JMP (PC + OP[0]);
   trace_output (OP_FLAG);
 }
 
@@ -765,7 +906,7 @@ OP_1403 ()
 {
   trace_input ("cmpeq", OP_ACCUM, OP_ACCUM, OP_VOID);
   State.F1 = State.F0;
-  State.F0 = (State.a[OP[0]] == State.a[OP[1]]) ? 1 : 0;
+  State.F0 = ((State.a[OP[0]] & MASK40) == (State.a[OP[1]] & MASK40)) ? 1 : 0;
   trace_output (OP_FLAG);
 }
 
@@ -773,9 +914,9 @@ OP_1403 ()
 void
 OP_401 ()
 {
-  trace_input ("cmpeqi.s", OP_REG, OP_CONSTANT16, OP_VOID);
+  trace_input ("cmpeqi.s", OP_REG, OP_CONSTANT4, OP_VOID);
   State.F1 = State.F0;
-  State.F0 = (State.regs[OP[0]] == SEXT4(OP[1])) ? 1 : 0;  
+  State.F0 = (State.regs[OP[0]] == (reg_t)SEXT4(OP[1])) ? 1 : 0;  
   trace_output (OP_FLAG);
 }
 
@@ -785,7 +926,7 @@ OP_2000000 ()
 {
   trace_input ("cmpeqi.l", OP_REG, OP_CONSTANT16, OP_VOID);
   State.F1 = State.F0;
-  State.F0 = (State.regs[OP[0]] == OP[1]) ? 1 : 0;  
+  State.F0 = (State.regs[OP[0]] == (reg_t)OP[1]) ? 1 : 0;  
   trace_output (OP_FLAG);
 }
 
@@ -795,7 +936,7 @@ OP_601 ()
 {
   trace_input ("cmpi.s", OP_REG, OP_CONSTANT4, OP_VOID);
   State.F1 = State.F0;
-  State.F0 = ((int16)(State.regs[OP[0]]) < SEXT4(OP[1])) ? 1 : 0;  
+  State.F0 = ((int16)(State.regs[OP[0]]) < (int16)SEXT4(OP[1])) ? 1 : 0;  
   trace_output (OP_FLAG);
 }
 
@@ -825,7 +966,7 @@ OP_23000000 ()
 {
   trace_input ("cmpui", OP_REG, OP_CONSTANT16, OP_VOID);
   State.F1 = State.F0;
-  State.F0 = (State.regs[OP[0]] < OP[1]) ? 1 : 0;  
+  State.F0 = (State.regs[OP[0]] < (reg_t)OP[1]) ? 1 : 0;  
   trace_output (OP_FLAG);
 }
 
@@ -835,7 +976,7 @@ OP_4E09 ()
 {
   uint8 *src, *dst;
   
-  trace_input ("cpfg", OP_FLAG, OP_VOID, OP_VOID);
+  trace_input ("cpfg", OP_FLAG_OUTPUT, OP_FLAG, OP_VOID);
   if (OP[0] == 0)
     dst = &State.F0;
   else
@@ -856,7 +997,7 @@ OP_4E09 ()
 void
 OP_5F20 ()
 {
-  d10v_callback->printf_filtered(d10v_callback, "***** DBT *****  PC=%x\n",PC);
+  /* d10v_callback->printf_filtered(d10v_callback, "***** DBT *****  PC=%x\n",PC); */
   State.exception = SIGTRAP;
 }
 
@@ -983,10 +1124,9 @@ OP_15002A02 ()
   int i;
 
   trace_input ("exp", OP_REG_OUTPUT, OP_ACCUM, OP_VOID);
-  if (SEXT40(State.a[OP[1]]) >= 0)
-    tmp = State.a[OP[1]];
-  else
-    tmp = ~(State.a[OP[1]]);
+  tmp = SEXT40(State.a[OP[1]]);
+  if (tmp < 0)
+    tmp = ~tmp & MASK40;
   
   foo = 0x4000000000LL;
   for (i=1;i<25;i++)
@@ -1007,9 +1147,9 @@ OP_15002A02 ()
 void
 OP_4D00 ()
 {
-  trace_input ("jl", OP_REG, OP_VOID, OP_VOID);
+  trace_input ("jl", OP_REG, OP_R2, OP_R3);
   State.regs[13] = PC+1;
-  PC = State.regs[OP[0]]; 
+  JMP (State.regs[OP[0]]);
   trace_output (OP_VOID);
 }
 
@@ -1017,8 +1157,11 @@ OP_4D00 ()
 void
 OP_4C00 ()
 {
-  trace_input ("jmp", OP_REG, OP_VOID, OP_VOID);
-  PC = State.regs[OP[0]]; 
+  trace_input ("jmp", OP_REG,
+              (OP[0] == 13) ? OP_R2 : OP_VOID,
+              (OP[0] == 13) ? OP_R3 : OP_VOID);
+
+  JMP (State.regs[OP[0]]);
   trace_output (OP_VOID);
 }
 
@@ -1064,9 +1207,10 @@ OP_6000 ()
 void
 OP_31000000 ()
 {
-  trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
-  State.regs[OP[0]] = RW (OP[1] + State.regs[OP[2]]);
-  State.regs[OP[0]+1] = RW (OP[1] + State.regs[OP[2]] + 2);
+  uint16 addr = State.regs[OP[2]];
+  trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID);
+  State.regs[OP[0]] = RW (OP[1] + addr);
+  State.regs[OP[0]+1] = RW (OP[1] + addr + 2);
   trace_output (OP_DREG);
 }
 
@@ -1074,9 +1218,10 @@ OP_31000000 ()
 void
 OP_6601 ()
 {
+  uint16 addr = State.regs[OP[1]];
   trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTDEC, OP_VOID);
-  State.regs[OP[0]] = RW (State.regs[OP[1]]);
-  State.regs[OP[0]+1] = RW (State.regs[OP[1]]+2);
+  State.regs[OP[0]] = RW (addr);
+  State.regs[OP[0]+1] = RW (addr+2);
   INC_ADDR(State.regs[OP[1]],-4);
   trace_output (OP_DREG);
 }
@@ -1085,21 +1230,23 @@ OP_6601 ()
 void
 OP_6201 ()
 {
+  uint16 addr = State.regs[OP[1]];
   trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTINC, OP_VOID);
-  State.regs[OP[0]] = RW (State.regs[OP[1]]);
-  State.regs[OP[0]+1] = RW (State.regs[OP[1]]+2);
+  State.regs[OP[0]] = RW (addr);
+  State.regs[OP[0]+1] = RW (addr+2);
   INC_ADDR(State.regs[OP[1]],4);
-  trace_output (OP_REG);
+  trace_output (OP_DREG);
 }
 
 /* ld2w */
 void
 OP_6200 ()
 {
-  trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
-  State.regs[OP[0]] = RW (State.regs[OP[1]]);
-  State.regs[OP[0]+1] = RW (State.regs[OP[1]]+2);
-  trace_output (OP_REG);
+  uint16 addr = State.regs[OP[1]];
+  trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
+  State.regs[OP[0]] = RW (addr);
+  State.regs[OP[0]+1] = RW (addr+2);
+  trace_output (OP_DREG);
 }
 
 /* ldb */
@@ -1107,8 +1254,7 @@ void
 OP_38000000 ()
 {
   trace_input ("ldb", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID);
-  State.regs[OP[0]] = RB (OP[1] + State.regs[OP[2]]);
-  SEXT8 (State.regs[OP[0]]);
+  State.regs[OP[0]] = SEXT8 (RB (OP[1] + State.regs[OP[2]]));
   trace_output (OP_REG);
 }
 
@@ -1117,8 +1263,7 @@ void
 OP_7000 ()
 {
   trace_input ("ldb", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
-  State.regs[OP[0]] = RB (State.regs[OP[1]]);
-  SEXT8 (State.regs[OP[0]]);
+  State.regs[OP[0]] = SEXT8 (RB (State.regs[OP[1]]));
   trace_output (OP_REG);
 }
 
@@ -1135,7 +1280,7 @@ OP_4001 ()
 void
 OP_20000000 ()
 {
-  trace_input ("ldi.s", OP_REG_OUTPUT, OP_CONSTANT16, OP_VOID);
+  trace_input ("ldi.l", OP_REG_OUTPUT, OP_CONSTANT16, OP_VOID);
   State.regs[OP[0]] = OP[1];
   trace_output (OP_REG);
 }
@@ -1207,13 +1352,17 @@ OP_1A00 ()
 void
 OP_3A00 ()
 {
-  int64 tmp;
+  uint64 tmp;
+  uint32 src1;
+  uint32 src2;
 
   trace_input ("macu", OP_ACCUM, OP_REG, OP_REG);
-  tmp = SEXT40 (State.regs[OP[1]] * State.regs[OP[2]]);
+  src1 = (uint16) State.regs[OP[1]];
+  src2 = (uint16) State.regs[OP[2]];
+  tmp = src1 * src2;
   if (State.FX)
-    tmp = SEXT40( (tmp << 1) & MASK40);
-  State.a[OP[0]] = (SEXT40 (State.a[OP[0]]) + tmp) & MASK40;
+    tmp = (tmp << 1);
+  State.a[OP[0]] = (State.a[OP[0]] + tmp) & MASK40;
   trace_output (OP_ACCUM);
 }
 
@@ -1369,14 +1518,18 @@ OP_1800 ()
 void
 OP_3800 ()
 {
-  int64 tmp;
+  uint64 tmp;
+  uint32 src1;
+  uint32 src2;
 
   trace_input ("msbu", OP_ACCUM, OP_REG, OP_REG);
-  tmp = SEXT40 (State.regs[OP[1]] * State.regs[OP[2]]);
+  src1 = (uint16) State.regs[OP[1]];
+  src2 = (uint16) State.regs[OP[2]];
+  tmp = src1 * src2;
   if (State.FX)
-    tmp = SEXT40( (tmp << 1) & MASK40);
+    tmp = (tmp << 1);
 
-  State.a[OP[0]] = (SEXT40 (State.a[OP[0]]) - tmp) & MASK40;
+  State.a[OP[0]] = (State.a[OP[0]] - tmp) & MASK40;
   trace_output (OP_ACCUM);
 }
 
@@ -1428,11 +1581,14 @@ OP_1C00 ()
 void
 OP_3C00 ()
 {
-  int64 tmp;
+  uint64 tmp;
+  uint32 src1;
+  uint32 src2;
 
   trace_input ("mulxu", OP_ACCUM_OUTPUT, OP_REG, OP_REG);
-  tmp = SEXT40 (State.regs[OP[1]] * State.regs[OP[2]]);
-
+  src1 = (uint16) State.regs[OP[1]];
+  src2 = (uint16) State.regs[OP[2]];
+  tmp = src1 * src2;
   if (State.FX)
     tmp <<= 1;
 
@@ -1473,9 +1629,9 @@ OP_3E00 ()
 void
 OP_3E01 ()
 {
-  trace_input ("mv2wtac", OP_ACCUM_OUTPUT, OP_DREG, OP_VOID);
+  trace_input ("mv2wtac", OP_DREG, OP_ACCUM_OUTPUT, OP_VOID);
   State.a[OP[1]] = (SEXT16 (State.regs[OP[0]]) << 16 | State.regs[OP[0]+1]) & MASK40;
-  trace_output (OP_ACCUM);
+  trace_output (OP_ACCUM_REVERSE);
 }
 
 /* mvac */
@@ -1555,6 +1711,7 @@ OP_5200 ()
       if (State.SM) PSW |= 0x8000;
       if (State.EA) PSW |= 0x2000;
       if (State.DB) PSW |= 0x1000;
+      if (State.DM) PSW |= 0x800;
       if (State.IE) PSW |= 0x400;
       if (State.RP) PSW |= 0x200;
       if (State.MD) PSW |= 0x100;
@@ -1611,6 +1768,7 @@ OP_5600 ()
       State.SM = (PSW & 0x8000) ? 1 : 0;
       State.EA = (PSW & 0x2000) ? 1 : 0;
       State.DB = (PSW & 0x1000) ? 1 : 0;
+      State.DM = (PSW & 0x800) ? 1 : 0;
       State.IE = (PSW & 0x400) ? 1 : 0;
       State.RP = (PSW & 0x200) ? 1 : 0;
       State.MD = (PSW & 0x100) ? 1 : 0;
@@ -1676,12 +1834,40 @@ void
 OP_5E00 ()
 {
   trace_input ("nop", OP_VOID, OP_VOID, OP_VOID);
-  trace_output (OP_VOID);
 
-  if (State.ins_type == INS_LEFT || State.ins_type == INS_LEFT_PARALLEL)
-    left_nops++;
-  else
-    right_nops++;
+  ins_type_counters[ (int)State.ins_type ]--;  /* don't count nops as normal instructions */
+  switch (State.ins_type)
+    {
+    default:
+      ins_type_counters[ (int)INS_UNKNOWN ]++;
+      break;
+
+    case INS_LEFT_PARALLEL:
+      /* Don't count a parallel op that includes a NOP as a true parallel op */
+      ins_type_counters[ (int)INS_RIGHT_PARALLEL ]--;
+      ins_type_counters[ (int)INS_RIGHT ]++;
+      ins_type_counters[ (int)INS_LEFT_NOPS ]++;
+      break;
+
+    case INS_LEFT:
+    case INS_LEFT_COND_EXE:
+      ins_type_counters[ (int)INS_LEFT_NOPS ]++;
+      break;
+
+    case INS_RIGHT_PARALLEL:
+      /* Don't count a parallel op that includes a NOP as a true parallel op */
+      ins_type_counters[ (int)INS_LEFT_PARALLEL ]--;
+      ins_type_counters[ (int)INS_LEFT ]++;
+      ins_type_counters[ (int)INS_RIGHT_NOPS ]++;
+      break;
+
+    case INS_RIGHT:
+    case INS_RIGHT_COND_EXE:
+      ins_type_counters[ (int)INS_RIGHT_NOPS ]++;
+      break;
+    }
+
+  trace_output (OP_VOID);
 }
 
 /* not */
@@ -1728,18 +1914,20 @@ OP_5201 ()
     }
 
   State.F1 = State.F0;
+  tmp = SEXT56 ((State.a[0] << 16) | (State.a[1] & 0xffff));
   if (shift >=0)
-    tmp = ((State.a[0] << 16) | (State.a[1] & 0xffff)) << shift;
+    tmp <<= shift;
   else
-    tmp = ((State.a[0] << 16) | (State.a[1] & 0xffff)) >> -shift;
-  tmp = ( SEXT60(tmp) + 0x8000 ) >> 16;
-  if (tmp > MAX32)
+    tmp >>= -shift;
+  tmp += 0x8000;
+  tmp >>= 16; /* look at bits 0:43 */
+  if (tmp > SEXT44 (SIGNED64 (0x0007fffffff)))
     {
       State.regs[OP[0]] = 0x7fff;
       State.regs[OP[0]+1] = 0xffff;
       State.F0 = 1;
     } 
-  else if (tmp < MIN32)
+  else if (tmp < SEXT44 (SIGNED64 (0xfff80000000)))
     {
       State.regs[OP[0]] = 0x8000;
       State.regs[OP[0]+1] = 0;
@@ -1758,23 +1946,23 @@ OP_5201 ()
 void
 OP_4201 ()
 {
-  int64 tmp;
+  signed64 tmp;
   int shift = SEXT3 (OP[2]);
 
   trace_input ("rachi", OP_REG_OUTPUT, OP_ACCUM, OP_CONSTANT3);
   State.F1 = State.F0;
   if (shift >=0)
-    tmp = SEXT44 (State.a[1]) << shift;
+    tmp = SEXT40 (State.a[OP[1]]) << shift;
   else
-    tmp = SEXT44 (State.a[1]) >> -shift;
+    tmp = SEXT40 (State.a[OP[1]]) >> -shift;
   tmp += 0x8000;
 
-  if (tmp > MAX32)
+  if (tmp > SEXT44 (SIGNED64 (0x0007fffffff)))
     {
       State.regs[OP[0]] = 0x7fff;
       State.F0 = 1;
     }
-  else if (tmp < 0xfff80000000LL)
+  else if (tmp < SEXT44 (SIGNED64 (0xfff80000000)))
     {
       State.regs[OP[0]] = 0x8000;
       State.F0 = 1;
@@ -1975,8 +2163,6 @@ OP_3201 ()
 void
 OP_460B ()
 {
-  uint16 tmp;
-
   trace_input ("slx", OP_REG, OP_FLAG, OP_VOID);
   State.regs[OP[0]] = (State.regs[OP[0]] << 1) | State.F0;
   trace_output (OP_REG);
@@ -1997,7 +2183,7 @@ OP_3400 ()
 {
   trace_input ("sra", OP_ACCUM, OP_REG, OP_VOID);
   if ((State.regs[OP[1]] & 31) <= 16)
-    State.a[OP[0]] >>= (State.regs[OP[1]] & 31);
+    State.a[OP[0]] = (SEXT40(State.a[OP[0]]) >> (State.regs[OP[1]] & 31)) & MASK40;
   else
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", State.regs[OP[1]] & 31);
@@ -2025,7 +2211,7 @@ OP_3401 ()
     OP[1] = 16;
 
   trace_input ("srai", OP_ACCUM, OP_CONSTANT16, OP_VOID);
-  State.a[OP[0]] >>= OP[1];
+  State.a[OP[0]] = (SEXT40(State.a[OP[0]]) >> OP[1]) & MASK40;
   trace_output (OP_ACCUM);
 }
 
@@ -2044,7 +2230,7 @@ OP_3000 ()
 {
   trace_input ("srl", OP_ACCUM, OP_REG, OP_VOID);
   if ((State.regs[OP[1]] & 31) <= 16)
-    State.a[OP[0]] >>= (State.regs[OP[1]] & 31);
+    State.a[OP[0]] = (uint64)((State.a[OP[0]] & MASK40) >> (State.regs[OP[1]] & 31));
   else
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", State.regs[OP[1]] & 31);
@@ -2072,7 +2258,7 @@ OP_3001 ()
     OP[1] = 16;
 
   trace_input ("srli", OP_ACCUM, OP_CONSTANT16, OP_VOID);
-  State.a[OP[0]] >>= OP[1];
+  State.a[OP[0]] = (uint64)(State.a[OP[0]] & MASK40) >> OP[1];
   trace_output (OP_ACCUM);
 }
 
@@ -2137,6 +2323,12 @@ void
 OP_6C01 ()
 {
   trace_input ("st", OP_REG, OP_POSTDEC, OP_VOID);
+  if ( OP[1] == 15 )
+    {
+      (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot post-decrement register r15 (SP).\n");
+      State.exception = SIGILL;
+      return;
+    }
   SW (State.regs[OP[1]], State.regs[OP[0]]);
   INC_ADDR (State.regs[OP[1]],-2);
   trace_output (OP_VOID);
@@ -2156,7 +2348,7 @@ OP_35000000 ()
 void
 OP_6A00 ()
 {
-  trace_input ("st2w", OP_REG, OP_MEMREF, OP_VOID);
+  trace_input ("st2w", OP_DREG, OP_MEMREF, OP_VOID);
   SW (State.regs[OP[1]],   State.regs[OP[0]]);
   SW (State.regs[OP[1]]+2, State.regs[OP[0]+1]);
   trace_output (OP_VOID);
@@ -2166,7 +2358,7 @@ OP_6A00 ()
 void
 OP_6E1F ()
 {
-  trace_input ("st2w", OP_REG, OP_PREDEC, OP_VOID);
+  trace_input ("st2w", OP_DREG, OP_PREDEC, OP_VOID);
   if ( OP[1] != 15 )
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot pre-decrement any registers but r15 (SP).\n");
@@ -2183,7 +2375,7 @@ OP_6E1F ()
 void
 OP_6A01 ()
 {
-  trace_input ("st2w", OP_REG, OP_POSTDEC, OP_VOID);
+  trace_input ("st2w", OP_DREG, OP_POSTINC, OP_VOID);
   SW (State.regs[OP[1]],   State.regs[OP[0]]);
   SW (State.regs[OP[1]]+2, State.regs[OP[0]+1]);
   INC_ADDR (State.regs[OP[1]],4);
@@ -2194,7 +2386,13 @@ OP_6A01 ()
 void
 OP_6E01 ()
 {
-  trace_input ("st2w", OP_REG, OP_POSTINC, OP_VOID);
+  trace_input ("st2w", OP_DREG, OP_POSTDEC, OP_VOID);
+  if ( OP[1] == 15 )
+    {
+      (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot post-decrement register r15 (SP).\n");
+      State.exception = SIGILL;
+      return;
+    }
   SW (State.regs[OP[1]],   State.regs[OP[0]]);
   SW (State.regs[OP[1]]+2, State.regs[OP[0]+1]);
   INC_ADDR (State.regs[OP[1]],-4);
@@ -2224,7 +2422,7 @@ void
 OP_5FE0 ()
 {
   trace_input ("stop", OP_VOID, OP_VOID, OP_VOID);
-  State.exception = SIGQUIT;
+  State.exception = SIG_D10V_STOP;
   trace_output (OP_VOID);
 }
 
@@ -2232,12 +2430,14 @@ OP_5FE0 ()
 void
 OP_0 ()
 {
-  int32 tmp;
+  uint16 tmp;
 
   trace_input ("sub", OP_REG, OP_REG, OP_VOID);
-  tmp = (int16)State.regs[OP[0]]- (int16)State.regs[OP[1]];
-  State.C = (tmp & 0xffff0000) ? 1 : 0;
-  State.regs[OP[0]] = tmp & 0xffff;
+  /* see ../common/sim-alu.h for a more extensive discussion on how to
+     compute the carry/overflow bits. */
+  tmp = State.regs[OP[0]] - State.regs[OP[1]];
+  State.C = ((uint16) State.regs[OP[0]] >= (uint16) State.regs[OP[1]]);
+  State.regs[OP[0]] = tmp;
   trace_output (OP_REG);
 }
 
@@ -2292,14 +2492,15 @@ OP_1003 ()
 void
 OP_1000 ()
 {
-  int64 tmp;
-  int32 a,b;
+  uint32 tmp,a,b;
 
   trace_input ("sub2w", OP_DREG, OP_DREG, OP_VOID);
-  a = (int32)((State.regs[OP[0]] << 16) | State.regs[OP[0]+1]);
-  b = (int32)((State.regs[OP[1]] << 16) | State.regs[OP[1]+1]);
-  tmp = a-b;
-  State.C = (tmp & 0xffffffff00000000LL) ? 1 : 0;  
+  a = (uint32)((State.regs[OP[0]] << 16) | State.regs[OP[0]+1]);
+  b = (uint32)((State.regs[OP[1]] << 16) | State.regs[OP[1]+1]);
+  /* see ../common/sim-alu.h for a more extensive discussion on how to
+     compute the carry/overflow bits */
+  tmp = a - b;
+  State.C = (a >= b);
   State.regs[OP[0]] = (tmp >> 16) & 0xffff;
   State.regs[OP[0]+1] = tmp & 0xffff;
   trace_output (OP_DREG);
@@ -2395,14 +2596,18 @@ OP_17001002 ()
 void
 OP_1 ()
 {
-  int32 tmp;
+  unsigned tmp;
   if (OP[1] == 0)
     OP[1] = 16;
 
   trace_input ("subi", OP_REG, OP_CONSTANT16, OP_VOID);
-  tmp = (int16)State.regs[OP[0]] - OP[1];
-  State.C = (tmp & 0xffff0000) ? 1 : 0;
-  State.regs[OP[0]] = tmp & 0xffff;  
+  /* see ../common/sim-alu.h for a more extensive discussion on how to
+     compute the carry/overflow bits. */
+  /* since OP[1] is never <= 0, -OP[1] == ~OP[1]+1 can never overflow */
+  tmp = ((unsigned)(unsigned16) State.regs[OP[0]]
+        + (unsigned)(unsigned16) ( - OP[1]));
+  State.C = (tmp >= (1 << 16));
+  State.regs[OP[0]] = tmp;
   trace_output (OP_REG);
 }
 
@@ -2410,57 +2615,230 @@ OP_1 ()
 void
 OP_5F00 ()
 {
-  trace_input ("trap", OP_CONSTANT16, OP_REG, OP_VOID);
+  trace_input ("trap", OP_CONSTANT4, OP_VOID, OP_VOID);
   trace_output (OP_VOID);
-  
+
   switch (OP[0])
     {
     default:
+#if 0
       (*d10v_callback->printf_filtered) (d10v_callback, "Unknown trap code %d\n", OP[0]);
       State.exception = SIGILL;
+#else
+      /* Use any other traps for batch debugging. */
+      {
+       int i;
+       static int first_time = 1;
+
+       if (first_time)
+         {
+           first_time = 0;
+           (*d10v_callback->printf_filtered) (d10v_callback, "Trap  #     PC ");
+           for (i = 0; i < 16; i++)
+             (*d10v_callback->printf_filtered) (d10v_callback, "  %sr%d", (i > 9) ? "" : " ", i);
+           (*d10v_callback->printf_filtered) (d10v_callback, "         a0         a1 f0 f1 c\n");
+         }
+
+       (*d10v_callback->printf_filtered) (d10v_callback, "Trap %2d 0x%.4x:", (int)OP[0], (int)PC);
+
+       for (i = 0; i < 16; i++)
+         (*d10v_callback->printf_filtered) (d10v_callback, " %.4x", (int) State.regs[i]);
+
+       for (i = 0; i < 2; i++)
+         (*d10v_callback->printf_filtered) (d10v_callback, " %.2x%.8lx",
+                                            ((int)(State.a[i] >> 32) & 0xff),
+                                            ((unsigned long)State.a[i]) & 0xffffffff);
+
+       (*d10v_callback->printf_filtered) (d10v_callback, "  %d  %d %d\n",
+                                          State.F0 != 0, State.F1 != 0, State.C != 0);
+       (*d10v_callback->flush_stdout) (d10v_callback);
+       break;
+      }
+#endif
 
-    case 0:
-      /* Trap 0 is used for simulating low-level I/O */
+    case 0:                    /* old system call trap, to be deleted */
+    case 15:                   /* new system call trap */
+      /* Trap 15 is used for simulating low-level I/O */
       {
-       int save_errno = errno; 
        errno = 0;
 
 /* Registers passed to trap 0 */
 
-#define FUNC   State.regs[2]   /* function number, return value */
-#define PARM1  State.regs[3]   /* optional parm 1 */
-#define PARM2  State.regs[4]   /* optional parm 2 */
-#define PARM3  State.regs[5]   /* optional parm 3 */
+#define FUNC   State.regs[6]   /* function number */
+#define PARM1  State.regs[2]   /* optional parm 1 */
+#define PARM2  State.regs[3]   /* optional parm 2 */
+#define PARM3  State.regs[4]   /* optional parm 3 */
+#define PARM4  State.regs[5]   /* optional parm 3 */
 
 /* Registers set by trap 0 */
 
-#define RETVAL State.regs[2]   /* return value */
-#define RETERR State.regs[3]   /* return error code */
+#define RETVAL State.regs[2]           /* return value */
+#define RETVAL_HIGH State.regs[2]      /* return value */
+#define RETVAL_LOW  State.regs[3]      /* return value */
+#define RETERR State.regs[4]           /* return error code */
 
 /* Turn a pointer in a register into a pointer into real memory. */
 
-#define MEMPTR(x) ((char *)((x) + State.imem))
+#define MEMPTR(x) ((char *)(dmem_addr(x)))
 
        switch (FUNC)
          {
 #if !defined(__GO32__) && !defined(_WIN32)
-#ifdef SYS_fork
          case SYS_fork:
            RETVAL = fork ();
+           trace_input ("<fork>", OP_VOID, OP_VOID, OP_VOID);
+           trace_output (OP_R2);
            break;
+
+         case SYS_getpid:
+           trace_input ("<getpid>", OP_VOID, OP_VOID, OP_VOID);
+           RETVAL = getpid ();
+           trace_output (OP_R2);
+           break;
+
+         case SYS_kill:
+           trace_input ("<kill>", OP_REG, OP_REG, OP_VOID);
+           if (PARM1 == getpid ())
+             {
+               trace_output (OP_VOID);
+               State.exception = PARM2;
+             }
+           else
+             {
+               int os_sig = -1;
+               switch (PARM2)
+                 {
+#ifdef SIGHUP
+                 case 1: os_sig = SIGHUP;      break;
+#endif
+#ifdef SIGINT
+                 case 2: os_sig = SIGINT;      break;
+#endif
+#ifdef SIGQUIT
+                 case 3: os_sig = SIGQUIT;     break;
+#endif
+#ifdef SIGILL
+                 case 4: os_sig = SIGILL;      break;
+#endif
+#ifdef SIGTRAP
+                 case 5: os_sig = SIGTRAP;     break;
+#endif
+#ifdef SIGABRT
+                 case 6: os_sig = SIGABRT;     break;
+#elif defined(SIGIOT)
+                 case 6: os_sig = SIGIOT;      break;
+#endif
+#ifdef SIGEMT
+                 case 7: os_sig = SIGEMT;      break;
+#endif
+#ifdef SIGFPE
+                 case 8: os_sig = SIGFPE;      break;
+#endif
+#ifdef SIGKILL
+                 case 9: os_sig = SIGKILL;     break;
+#endif
+#ifdef SIGBUS
+                 case 10: os_sig = SIGBUS;     break;
+#endif
+#ifdef SIGSEGV
+                 case 11: os_sig = SIGSEGV;    break;
+#endif
+#ifdef SIGSYS
+                 case 12: os_sig = SIGSYS;     break;
+#endif
+#ifdef SIGPIPE
+                 case 13: os_sig = SIGPIPE;    break;
+#endif
+#ifdef SIGALRM
+                 case 14: os_sig = SIGALRM;    break;
+#endif
+#ifdef SIGTERM
+                 case 15: os_sig = SIGTERM;    break;
+#endif
+#ifdef SIGURG
+                 case 16: os_sig = SIGURG;     break;
+#endif
+#ifdef SIGSTOP
+                 case 17: os_sig = SIGSTOP;    break;
+#endif
+#ifdef SIGTSTP
+                 case 18: os_sig = SIGTSTP;    break;
+#endif
+#ifdef SIGCONT
+                 case 19: os_sig = SIGCONT;    break;
+#endif
+#ifdef SIGCHLD
+                 case 20: os_sig = SIGCHLD;    break;
+#elif defined(SIGCLD)
+                 case 20: os_sig = SIGCLD;     break;
+#endif
+#ifdef SIGTTIN
+                 case 21: os_sig = SIGTTIN;    break;
+#endif
+#ifdef SIGTTOU
+                 case 22: os_sig = SIGTTOU;    break;
+#endif
+#ifdef SIGIO
+                 case 23: os_sig = SIGIO;      break;
+#elif defined (SIGPOLL)
+                 case 23: os_sig = SIGPOLL;    break;
 #endif
-#ifdef SYS_execve
+#ifdef SIGXCPU
+                 case 24: os_sig = SIGXCPU;    break;
+#endif
+#ifdef SIGXFSZ
+                 case 25: os_sig = SIGXFSZ;    break;
+#endif
+#ifdef SIGVTALRM
+                 case 26: os_sig = SIGVTALRM;  break;
+#endif
+#ifdef SIGPROF
+                 case 27: os_sig = SIGPROF;    break;
+#endif
+#ifdef SIGWINCH
+                 case 28: os_sig = SIGWINCH;   break;
+#endif
+#ifdef SIGLOST
+                 case 29: os_sig = SIGLOST;    break;
+#endif
+#ifdef SIGUSR1
+                 case 30: os_sig = SIGUSR1;    break;
+#endif
+#ifdef SIGUSR2
+                 case 31: os_sig = SIGUSR2;    break;
+#endif
+                 }
+
+               if (os_sig == -1)
+                 {
+                   trace_output (OP_VOID);
+                   (*d10v_callback->printf_filtered) (d10v_callback, "Unknown signal %d\n", PARM2);
+                   (*d10v_callback->flush_stdout) (d10v_callback);
+                   State.exception = SIGILL;
+                 }
+               else
+                 {
+                   RETVAL = kill (PARM1, PARM2);
+                   trace_output (OP_R2);
+                 }
+             }
+           break;
+
          case SYS_execve:
            RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2),
                             (char **)MEMPTR (PARM3));
+           trace_input ("<execve>", OP_R2, OP_R3, OP_R4);
+           trace_output (OP_R2);
            break;
-#endif
+
 #ifdef SYS_execv
          case SYS_execv:
            RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), NULL);
+           trace_input ("<execv>", OP_R2, OP_R3, OP_VOID);
+           trace_output (OP_R2);
            break;
 #endif
-#ifdef SYS_pipe
+
          case SYS_pipe:
            {
              reg_t buf;
@@ -2471,28 +2849,45 @@ OP_5F00 ()
              SW (buf, host_fd[0]);
              buf += sizeof(uint16);
              SW (buf, host_fd[1]);
+             trace_input ("<pipe>", OP_R2, OP_VOID, OP_VOID);
+             trace_output (OP_R2);
            }
          break;
-#endif
+
 #ifdef SYS_wait
          case SYS_wait:
            {
              int status;
 
              RETVAL = wait (&status);
-             SW (PARM1, status);
+             if (PARM1)
+               SW (PARM1, status);
+             trace_input ("<wait>", OP_R2, OP_VOID, OP_VOID);
+             trace_output (OP_R2);
            }
          break;
 #endif
+#else
+         case SYS_getpid:
+           trace_input ("<getpid>", OP_VOID, OP_VOID, OP_VOID);
+           RETVAL = 1;
+           trace_output (OP_R2);
+           break;
+
+         case SYS_kill:
+           trace_input ("<kill>", OP_REG, OP_REG, OP_VOID);
+           trace_output (OP_VOID);
+           State.exception = PARM2;
+           break;
 #endif
 
-#ifdef SYS_read
          case SYS_read:
            RETVAL = d10v_callback->read (d10v_callback, PARM1, MEMPTR (PARM2),
                                          PARM3);
+           trace_input ("<read>", OP_R2, OP_R3, OP_R4);
+           trace_output (OP_R2);
            break;
-#endif
-#ifdef SYS_write
+
          case SYS_write:
            if (PARM1 == 1)
              RETVAL = (int)d10v_callback->write_stdout (d10v_callback,
@@ -2500,32 +2895,42 @@ OP_5F00 ()
            else
              RETVAL = (int)d10v_callback->write (d10v_callback, PARM1,
                                                  MEMPTR (PARM2), PARM3);
+           trace_input ("<write>", OP_R2, OP_R3, OP_R4);
+           trace_output (OP_R2);
            break;
-#endif
-#ifdef SYS_lseek
+
          case SYS_lseek:
-           RETVAL = d10v_callback->lseek (d10v_callback, PARM1, PARM2, PARM3);
+           {
+             unsigned long ret = d10v_callback->lseek (d10v_callback, PARM1,
+                       (((unsigned long)PARM2) << 16) || (unsigned long)PARM3,
+                       PARM4);
+             RETVAL_HIGH = ret >> 16;
+             RETVAL_LOW  = ret & 0xffff;
+           }
+           trace_input ("<lseek>", OP_R2, OP_R3, OP_R4);
+           trace_output (OP_R2R3);
            break;
-#endif
-#ifdef SYS_close
+
          case SYS_close:
            RETVAL = d10v_callback->close (d10v_callback, PARM1);
+           trace_input ("<close>", OP_R2, OP_VOID, OP_VOID);
+           trace_output (OP_R2);
            break;
-#endif
-#ifdef SYS_open
+
          case SYS_open:
            RETVAL = d10v_callback->open (d10v_callback, MEMPTR (PARM1), PARM2);
+           trace_input ("<open>", OP_R2, OP_R3, OP_R4);
+           trace_output (OP_R2);
+           trace_input ("<open>", OP_R2, OP_R3, OP_R4);
+           trace_output (OP_R2);
            break;
-#endif
-#ifdef SYS_exit
+
          case SYS_exit:
-           /* EXIT - caller can look in PARM1 to work out the 
-              reason */
-           State.exception = SIGQUIT;
+           State.exception = SIG_D10V_EXIT;
+           trace_input ("<exit>", OP_R2, OP_VOID, OP_VOID);
+           trace_output (OP_VOID);
            break;
-#endif
 
-#ifdef SYS_stat
          case SYS_stat:
            /* stat system call */
            {
@@ -2551,57 +2956,50 @@ OP_5F00 ()
              SLW (buf+28, host_stat.st_mtime);
              SLW (buf+36, host_stat.st_ctime);
            }
+           trace_input ("<stat>", OP_R2, OP_R3, OP_VOID);
+           trace_output (OP_R2);
            break;
-#endif
 
-#ifdef SYS_chown
          case SYS_chown:
            RETVAL = chown (MEMPTR (PARM1), PARM2, PARM3);
+           trace_input ("<chown>", OP_R2, OP_R3, OP_R4);
+           trace_output (OP_R2);
            break;
-#endif
-#ifdef SYS_chmod
+
          case SYS_chmod:
            RETVAL = chmod (MEMPTR (PARM1), PARM2);
+           trace_input ("<chmod>", OP_R2, OP_R3, OP_R4);
+           trace_output (OP_R2);
            break;
-#endif
+
 #ifdef SYS_utime
          case SYS_utime:
            /* Cast the second argument to void *, to avoid type mismatch
               if a prototype is present.  */
            RETVAL = utime (MEMPTR (PARM1), (void *) MEMPTR (PARM2));
+           trace_input ("<utime>", OP_R2, OP_R3, OP_R4);
+           trace_output (OP_R2);
+           break;
+#endif
+
+#ifdef SYS_time
+         case SYS_time:
+           {
+             unsigned long ret = time (PARM1 ? MEMPTR (PARM1) : NULL);
+             RETVAL_HIGH = ret >> 16;
+             RETVAL_LOW  = ret & 0xffff;
+           }
+           trace_input ("<time>", OP_R2, OP_R3, OP_R4);
+           trace_output (OP_R2R3);
            break;
 #endif
+           
          default:
            abort ();
          }
-       RETERR = errno;
-       errno = save_errno;
-       break;
-      }
-
-    case 1:
-      /* Trap 1 prints a string */
-      {
-       char *fstr = State.regs[2] + State.imem;
-       fputs (fstr, stdout);
+       RETERR = (RETVAL == (uint16) -1) ? d10v_callback->get_errno(d10v_callback) : 0;
        break;
       }
-
-    case 2:
-      /* Trap 2 calls printf */
-      {
-       char *fstr = State.regs[2] + State.imem;
-       (*d10v_callback->printf_filtered) (d10v_callback, fstr,
-                                          (int16)State.regs[3],
-                                          (int16)State.regs[4],
-                                          (int16)State.regs[5]);
-       break;
-      }
-
-    case 3:
-      /* Trap 3 writes a character */
-      putchar (State.regs[2]);
-      break;
     }
 }