Add support for SIGILL (reserved-instruction-exception).
[deliverable/binutils-gdb.git] / sim / d10v / simops.c
index e0db5abc80238889d8a48a9a4f56379c5e1d32e6..cb0fa56c888fecfd709406cdcee7bc72e7d77797 100644 (file)
@@ -34,6 +34,7 @@ enum op_types {
   OP_CONSTANT4,
   OP_MEMREF,
   OP_MEMREF2,
+  OP_MEMREF3,
   OP_POSTDEC,
   OP_POSTINC,
   OP_PREDEC,
@@ -47,7 +48,6 @@ enum {
   PSW_MASK = (PSW_SM_BIT
              | PSW_EA_BIT
              | PSW_DB_BIT
-             | PSW_DM_BIT
              | PSW_IE_BIT
              | PSW_RP_BIT
              | PSW_MD_BIT
@@ -56,10 +56,13 @@ enum {
              | PSW_F0_BIT
              | PSW_F1_BIT
              | PSW_C_BIT),
+  /* The following bits in the PSW _can't_ be set by instructions such
+     as mvtc. */
+  PSW_HW_MASK = (PSW_MASK | PSW_DM_BIT)
 };
 
 reg_t
-move_to_cr (int cr, reg_t mask, reg_t val)
+move_to_cr (int cr, reg_t mask, reg_t val, int psw_hw_p)
 {
   /* A MASK bit is set when the corresponding bit in the CR should
      be left alone */
@@ -67,13 +70,18 @@ move_to_cr (int cr, reg_t mask, reg_t val)
   switch (cr)
     {
     case PSW_CR:
-      val &= PSW_MASK;
+      if (psw_hw_p)
+       val &= PSW_HW_MASK;
+      else
+       val &= PSW_MASK;
       if ((mask & PSW_SM_BIT) == 0)
        {
-         int new_sm = (val & PSW_SM_BIT) != 0;
-         SET_HELD_SP (PSW_SM, GPR (SP_IDX)); /* save old SP */
-         if (PSW_SM != new_sm)
-           SET_GPR (SP_IDX, HELD_SP (new_sm)); /* restore new SP */
+         int new_psw_sm = (val & PSW_SM_BIT) != 0;
+         /* save old SP */
+         SET_HELD_SP (PSW_SM, GPR (SP_IDX));
+         if (PSW_SM != new_psw_sm)
+           /* restore new SP */
+           SET_GPR (SP_IDX, HELD_SP (new_psw_sm));
        }
       if ((mask & (PSW_ST_BIT | PSW_FX_BIT)) == 0)
        {
@@ -91,7 +99,11 @@ move_to_cr (int cr, reg_t mask, reg_t val)
       break;
     case BPSW_CR:
     case DPSW_CR:
-      val &= PSW_MASK;
+      /* Just like PSW, mask things like DM out. */
+      if (psw_hw_p)
+       val &= PSW_HW_MASK;
+      else
+       val &= PSW_MASK;
       break;
     case MOD_S_CR:
     case MOD_E_CR:
@@ -307,6 +319,12 @@ trace_input_func (name, in1, in2, in3)
          comma = ",";
          break;
 
+       case OP_MEMREF3:
+         sprintf (p, "%s@%d", comma, OP[i]);
+         p += strlen (p);
+         comma = ",";
+         break;
+
        case OP_POSTINC:
          sprintf (p, "%s@r%d+", comma, OP[i]);
          p += strlen (p);
@@ -380,6 +398,10 @@ trace_input_func (name, in1, in2, in3)
                                                 (uint16) GPR (OP[i]));
              break;
 
+           case OP_MEMREF3:
+             (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", (uint16) OP[i]);
+             break;
+
            case OP_DREG:
              tmp = (long)((((uint32) GPR (OP[i])) << 16) | ((uint32) GPR (OP[i] + 1)));
              (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.8lx", SIZE_VALUES-10, "", tmp);
@@ -588,9 +610,9 @@ OP_5607 ()
       if (PSW_ST)
        {
          if (tmp > SEXT40(MAX32))
-           tmp = MAX32;
+           tmp = (MAX32);
          else if (tmp < SEXT40(MIN32))
-           tmp = MIN32;
+           tmp = (MIN32);
          else
            tmp = (tmp & MASK40);
        }
@@ -630,10 +652,10 @@ OP_1201 ()
   trace_input ("add", OP_ACCUM, OP_REG, OP_VOID);
   if (PSW_ST)
     {
-      if ( tmp > MAX32)
-       tmp = MAX32;
-      else if ( tmp < MIN32)
-       tmp = MIN32;
+      if (tmp > SEXT40(MAX32))
+       tmp = (MAX32);
+      else if (tmp < SEXT40(MIN32))
+       tmp = (MIN32);
       else
        tmp = (tmp & MASK40);
     }
@@ -653,10 +675,10 @@ OP_1203 ()
   trace_input ("add", OP_ACCUM, OP_ACCUM, OP_VOID);
   if (PSW_ST)
     {
-      if (tmp > MAX32)
-       tmp = MAX32;
-      else if ( tmp < MIN32)
-       tmp = MIN32;
+      if (tmp > SEXT40(MAX32))
+       tmp = (MAX32);
+      else if (tmp < SEXT40(MIN32))
+       tmp = (MIN32);
       else
        tmp = (tmp & MASK40);
     }
@@ -729,14 +751,14 @@ OP_17001200 ()
 
   trace_input ("addac3s", OP_DREG_OUTPUT, OP_DREG, OP_ACCUM);
   tmp = SEXT40 (ACC (OP[2])) + SEXT40 ((GPR (OP[1]) << 16) | GPR (OP[1] + 1));
-  if ( tmp > MAX32)
+  if (tmp > SEXT40(MAX32))
     {
-      tmp = 0x7fffffff;
+      tmp = (MAX32);
       SET_PSW_F0 (1);
     }      
-  else if (tmp < MIN32)
+  else if (tmp < SEXT40(MIN32))
     {
-      tmp = 0x80000000;
+      tmp = (MIN32);
       SET_PSW_F0 (1);
     }      
   else
@@ -757,14 +779,14 @@ OP_17001202 ()
 
   trace_input ("addac3s", OP_DREG_OUTPUT, OP_ACCUM, OP_ACCUM);
   tmp = SEXT40(ACC (OP[1])) + SEXT40(ACC (OP[2]));
-  if ( tmp > MAX32)
+  if (tmp > SEXT40(MAX32))
     {
-      tmp = 0x7fffffff;
+      tmp = (MAX32);
       SET_PSW_F0 (1);
     }      
-  else if (tmp < MIN32)
+  else if (tmp < SEXT40(MIN32))
     {
-      tmp = 0x80000000;
+      tmp = (MIN32);
       SET_PSW_F0 (1);
     }      
   else
@@ -1065,6 +1087,28 @@ OP_4E09 ()
   trace_output_flag ();
 }
 
+/* cpfg */
+void
+OP_4E0F ()
+{
+  uint8 val;
+  
+  trace_input ("cpfg", OP_FLAG_OUTPUT, OP_FLAG, OP_VOID);
+  
+  if (OP[1] == 0)
+    val = PSW_F0;
+  else if (OP[1] == 1)
+    val = PSW_F1;
+  else
+    val = PSW_C;
+  if (OP[0] == 0)
+    SET_PSW_F0 (val);
+  else
+    SET_PSW_F1 (val);
+
+  trace_output_flag ();
+}
+
 /* dbt */
 void
 OP_5F20 ()
@@ -1086,7 +1130,7 @@ OP_5F20 ()
       trace_input ("dbt", OP_VOID, OP_VOID, OP_VOID);
       SET_DPC (PC + 1);
       SET_DPSW (PSW);
-      SET_PSW (PSW_DM_BIT | (PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT)));
+      SET_HW_PSW (PSW_DM_BIT | (PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT)));
       JMP (DBT_VECTOR_START);
       trace_output_void ();
     }
@@ -1269,8 +1313,16 @@ void
 OP_30000000 ()
 {
   uint16 tmp;
+  uint16 addr = OP[1] + GPR (OP[2]);
   trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID);
-  tmp = RW (OP[1] + GPR (OP[2]));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  tmp = RW (addr);
   SET_GPR (OP[0], tmp);
   trace_output_16 (tmp);
 }
@@ -1280,8 +1332,16 @@ void
 OP_6401 ()
 {
   uint16 tmp;
+  uint16 addr = GPR (OP[1]);
   trace_input ("ld", OP_REG_OUTPUT, OP_POSTDEC, OP_VOID);
-  tmp = RW (GPR (OP[1]));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  tmp = RW (addr);
   SET_GPR (OP[0], tmp);
   if (OP[0] != OP[1])
     INC_ADDR (OP[1], -2);
@@ -1293,8 +1353,16 @@ void
 OP_6001 ()
 {
   uint16 tmp;
+  uint16 addr = GPR (OP[1]);
   trace_input ("ld", OP_REG_OUTPUT, OP_POSTINC, OP_VOID);
-  tmp = RW (GPR (OP[1]));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  tmp = RW (addr);
   SET_GPR (OP[0], tmp);
   if (OP[0] != OP[1])
     INC_ADDR (OP[1], 2);
@@ -1306,8 +1374,35 @@ void
 OP_6000 ()
 {
   uint16 tmp;
+  uint16 addr = GPR (OP[1]);
   trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
-  tmp = RW (GPR (OP[1]));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  tmp = RW (addr);
+  SET_GPR (OP[0], tmp);
+  trace_output_16 (tmp);
+}
+
+/* ld */
+void
+OP_32010000 ()
+{
+  uint16 tmp;
+  uint16 addr = OP[1];
+  trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF3, OP_VOID);
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  tmp = RW (addr);
   SET_GPR (OP[0], tmp);
   trace_output_16 (tmp);
 }
@@ -1317,9 +1412,16 @@ void
 OP_31000000 ()
 {
   int32 tmp;
-  uint16 addr = GPR (OP[2]);
+  uint16 addr = OP[1] + GPR (OP[2]);
   trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID);
-  tmp = RLW (OP[1] + addr);
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  tmp = RLW (addr);
   SET_GPR32 (OP[0], tmp);
   trace_output_32 (tmp);
 }
@@ -1331,9 +1433,17 @@ OP_6601 ()
   uint16 addr = GPR (OP[1]);
   int32 tmp;
   trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTDEC, OP_VOID);
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
   tmp = RLW (addr);
   SET_GPR32 (OP[0], tmp);
-  INC_ADDR (OP[1], -4);
+  if (OP[0] != OP[1] && ((OP[0] + 1) != OP[1]))
+    INC_ADDR (OP[1], -4);
   trace_output_32 (tmp);
 }
 
@@ -1344,9 +1454,17 @@ OP_6201 ()
   int32 tmp;
   uint16 addr = GPR (OP[1]);
   trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTINC, OP_VOID);
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
   tmp = RLW (addr);
   SET_GPR32 (OP[0], tmp);
-  INC_ADDR (OP[1], 4);
+  if (OP[0] != OP[1] && ((OP[0] + 1) != OP[1]))
+    INC_ADDR (OP[1], 4);
   trace_output_32 (tmp);
 }
 
@@ -1357,7 +1475,33 @@ OP_6200 ()
   uint16 addr = GPR (OP[1]);
   int32 tmp;
   trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
-  tmp = RLW (addr + 0);
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  tmp = RLW (addr);
+  SET_GPR32 (OP[0], tmp);
+  trace_output_32 (tmp);
+}
+
+/* ld2w */
+void
+OP_33010000 ()
+{
+  int32 tmp;
+  uint16 addr = OP[1];
+  trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF3, OP_VOID);
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  tmp = RLW (addr);
   SET_GPR32 (OP[0], tmp);
   trace_output_32 (tmp);
 }
@@ -1441,15 +1585,15 @@ OP_2A00 ()
     tmp = SEXT40( (tmp << 1) & MASK40);
 
   if (PSW_ST && tmp > SEXT40(MAX32))
-    tmp = MAX32;
+    tmp = (MAX32);
 
   tmp += SEXT40 (ACC (OP[0]));
   if (PSW_ST)
     {
       if (tmp > SEXT40(MAX32))
-       tmp = MAX32;
+       tmp = (MAX32);
       else if (tmp < SEXT40(MIN32))
-       tmp = MIN32;
+       tmp = (MIN32);
       else
        tmp = (tmp & MASK40);
     }
@@ -1637,15 +1781,15 @@ OP_2800 ()
     tmp = SEXT40 ((tmp << 1) & MASK40);
 
   if (PSW_ST && tmp > SEXT40(MAX32))
-    tmp = MAX32;
+    tmp = (MAX32);
 
   tmp = SEXT40(ACC (OP[0])) - tmp;
   if (PSW_ST)
     {
       if (tmp > SEXT40(MAX32))
-       tmp = MAX32;
+       tmp = (MAX32);
       else if (tmp < SEXT40(MIN32))
-       tmp = MIN32;
+       tmp = (MIN32);
       else
        tmp = (tmp & MASK40);
     }
@@ -1714,8 +1858,8 @@ OP_2C00 ()
   if (PSW_FX)
     tmp = SEXT40 ((tmp << 1) & MASK40);
 
-  if (PSW_ST && tmp > MAX32)
-    tmp = MAX32;
+  if (PSW_ST && tmp > SEXT40(MAX32))
+    tmp = (MAX32);
   else
     tmp = (tmp & MASK40);
   SET_ACC (OP[0], tmp);
@@ -2205,6 +2349,71 @@ OP_5F40 ()
   trace_output_void ();
 }
 
+/* sac */
+void OP_5209 ()
+{
+  int64 tmp;
+
+  trace_input ("sac", OP_REG_OUTPUT, OP_ACCUM, OP_VOID);
+
+  tmp = SEXT40(ACC (OP[1]));
+
+  SET_PSW_F1 (PSW_F0);
+
+  if (tmp > SEXT40(MAX32))
+    {
+      tmp = (MAX32);
+      SET_PSW_F0 (1);
+    }
+  else if (tmp < SEXT40(MIN32))
+    {
+      tmp = 0x80000000;
+      SET_PSW_F0 (1);
+    }
+  else
+    {
+      tmp = (tmp & MASK32);
+      SET_PSW_F0 (0);
+    }
+
+  SET_GPR32 (OP[0], tmp);
+
+  trace_output_40 (tmp);
+}
+
+/* sachi */
+void
+OP_4209 ()
+{
+  int64 tmp;
+
+  trace_input ("sachi", OP_REG_OUTPUT, OP_ACCUM, OP_VOID);
+
+  tmp = SEXT40(ACC (OP[1]));
+
+  SET_PSW_F1 (PSW_F0);
+
+  if (tmp > SEXT40(MAX32))
+    {
+      tmp = 0x7fff;
+      SET_PSW_F0 (1);
+    }
+  else if (tmp < SEXT40(MIN32))
+    {
+      tmp = 0x8000;
+      SET_PSW_F0 (1);
+    }
+  else
+    {
+      tmp >>= 16;
+      SET_PSW_F0 (0);
+    }
+
+  SET_GPR (OP[0], tmp);
+
+  trace_output_16 (OP[0]);
+}
+
 /* sadd */
 void
 OP_1223 ()
@@ -2250,6 +2459,58 @@ OP_4613 ()
   trace_output_16 (tmp);
 }
 
+/* slae */
+void
+OP_3220 ()
+{
+  int64 tmp;
+  int16 reg;
+
+  trace_input ("slae", OP_ACCUM, OP_REG, OP_VOID);
+
+  reg = SEXT16 (GPR (OP[1]));
+
+  if (reg >= 17 || reg <= -17)
+    {
+      (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", reg);
+      State.exception = SIGILL;
+      return;
+    }
+
+  tmp = SEXT40 (ACC (OP[0]));
+
+  if (PSW_ST && (tmp < SEXT40 (MIN32) || tmp > SEXT40 (MAX32)))
+    {
+      (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: accumulator value 0x%.2x%.8lx out of range\n", ((int)(tmp >> 32) & 0xff), ((unsigned long) tmp) & 0xffffffff);
+      State.exception = SIGILL;
+      return;
+    }
+
+  if (reg >= 0 && reg <= 16)
+    {
+      tmp = SEXT56 ((SEXT56 (tmp)) << (GPR (OP[1])));
+      if (PSW_ST)
+       {
+         if (tmp > SEXT40(MAX32))
+           tmp = (MAX32);
+         else if (tmp < SEXT40(MIN32))
+           tmp = (MIN32);
+         else
+           tmp = (tmp & MASK40);
+       }
+      else
+       tmp = (tmp & MASK40);
+    }
+  else
+    {
+      tmp = (SEXT40 (ACC (OP[0]))) >> (-GPR (OP[1]));
+    }
+
+  SET_ACC(OP[0], tmp);
+
+  trace_output_40(tmp);
+}
+
 /* sleep */
 void
 OP_5FC0 ()
@@ -2287,9 +2548,9 @@ OP_3200 ()
 
   if (PSW_ST)
     {
-      if (tmp > MAX32)
+      if (tmp > SEXT40(MAX32))
        tmp = (MAX32);
-      else if (tmp < 0xffffff80000000LL)
+      else if (tmp < SEXT40(MIN32))
        tmp = (MIN32);
       else
        tmp = (tmp & MASK40);
@@ -2325,9 +2586,9 @@ OP_3201 ()
 
   if (PSW_ST)
     {
-      if (tmp > MAX32)
+      if (tmp > SEXT40(MAX32))
        tmp = (MAX32);
-      else if (tmp < 0xffffff80000000LL)
+      else if (tmp < SEXT40(MIN32))
        tmp = (MIN32);
       else
        tmp = (tmp & MASK40);
@@ -2476,8 +2737,16 @@ OP_4609 ()
 void
 OP_34000000 ()
 {
+  uint16 addr = OP[1] + GPR (OP[2]);
   trace_input ("st", OP_REG, OP_MEMREF2, OP_VOID);
-  SW (OP[1] + GPR (OP[2]), GPR (OP[0]));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  SW (addr, GPR (OP[0]));
   trace_output_void ();
 }
 
@@ -2485,12 +2754,21 @@ OP_34000000 ()
 void
 OP_6800 ()
 {
+  uint16 addr = GPR (OP[1]);
   trace_input ("st", OP_REG, OP_MEMREF, OP_VOID);
-  SW (GPR (OP[1]), GPR (OP[0]));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  SW (addr, GPR (OP[0]));
   trace_output_void ();
 }
 
 /* st */
+/* st Rsrc1,@-SP */
 void
 OP_6C1F ()
 {
@@ -2502,6 +2780,13 @@ OP_6C1F ()
       State.exception = SIGILL;
       return;
     }
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
   SW (addr, GPR (OP[0]));
   SET_GPR (OP[1], addr);
   trace_output_void ();
@@ -2511,8 +2796,16 @@ OP_6C1F ()
 void
 OP_6801 ()
 {
+  uint16 addr = GPR (OP[1]);
   trace_input ("st", OP_REG, OP_POSTINC, OP_VOID);
-  SW (GPR (OP[1]), GPR (OP[0]));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  SW (addr, GPR (OP[0]));
   INC_ADDR (OP[1], 2);
   trace_output_void ();
 }
@@ -2521,6 +2814,7 @@ OP_6801 ()
 void
 OP_6C01 ()
 {
+  uint16 addr = GPR (OP[1]);
   trace_input ("st", OP_REG, OP_POSTDEC, OP_VOID);
   if ( OP[1] == 15 )
     {
@@ -2528,18 +2822,50 @@ OP_6C01 ()
       State.exception = SIGILL;
       return;
     }
-  SW (GPR (OP[1]), GPR (OP[0]));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  SW (addr, GPR (OP[0]));
   INC_ADDR (OP[1], -2);
   trace_output_void ();
 }
 
+/* st */
+void
+OP_36010000 ()
+{
+  uint16 addr = OP[1];
+  trace_input ("st", OP_REG, OP_MEMREF3, OP_VOID);
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  SW (addr, GPR (OP[0]));
+  trace_output_void ();
+}
+
 /* st2w */
 void
 OP_35000000 ()
 {
+  uint16 addr = GPR (OP[2])+ OP[1];
   trace_input ("st2w", OP_DREG, OP_MEMREF2, OP_VOID);
-  SW (GPR (OP[2])+ OP[1] + 0, GPR (OP[0] + 0));
-  SW (GPR (OP[2])+ OP[1] + 2, GPR (OP[0] + 1));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  SW (addr + 0, GPR (OP[0] + 0));
+  SW (addr + 2, GPR (OP[0] + 1));
   trace_output_void ();
 }
 
@@ -2547,9 +2873,17 @@ OP_35000000 ()
 void
 OP_6A00 ()
 {
+  uint16 addr = GPR (OP[1]);
   trace_input ("st2w", OP_DREG, OP_MEMREF, OP_VOID);
-  SW (GPR (OP[1]) + 0, GPR (OP[0] + 0));
-  SW (GPR (OP[1]) + 2, GPR (OP[0] + 1));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  SW (addr + 0, GPR (OP[0] + 0));
+  SW (addr + 2, GPR (OP[0] + 1));
   trace_output_void ();
 }
 
@@ -2565,6 +2899,13 @@ OP_6E1F ()
       State.exception = SIGILL;
       return;
     }
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
   SW (addr + 0, GPR (OP[0] + 0));
   SW (addr + 2, GPR (OP[0] + 1));
   SET_GPR (OP[1], addr);
@@ -2575,9 +2916,17 @@ OP_6E1F ()
 void
 OP_6A01 ()
 {
+  uint16 addr = GPR (OP[1]);
   trace_input ("st2w", OP_DREG, OP_POSTINC, OP_VOID);
-  SW (GPR (OP[1]) + 0, GPR (OP[0] + 0));
-  SW (GPR (OP[1]) + 2, GPR (OP[0] + 1));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  SW (addr + 0, GPR (OP[0] + 0));
+  SW (addr + 2, GPR (OP[0] + 1));
   INC_ADDR (OP[1], 4);
   trace_output_void ();
 }
@@ -2586,6 +2935,7 @@ OP_6A01 ()
 void
 OP_6E01 ()
 {
+  uint16 addr = GPR (OP[1]);
   trace_input ("st2w", OP_DREG, OP_POSTDEC, OP_VOID);
   if ( OP[1] == 15 )
     {
@@ -2593,12 +2943,37 @@ OP_6E01 ()
       State.exception = SIGILL;
       return;
     }
-  SW (GPR (OP[1]) + 0, GPR (OP[0] + 0));
-  SW (GPR (OP[1]) + 2, GPR (OP[0] + 1));
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  SW (addr + 0, GPR (OP[0] + 0));
+  SW (addr + 2, GPR (OP[0] + 1));
   INC_ADDR (OP[1], -4);
   trace_output_void ();
 }
 
+/* st2w */
+void
+OP_37010000 ()
+{
+  uint16 addr = OP[1];
+  trace_input ("st2w", OP_DREG, OP_MEMREF3, OP_VOID);
+  if ((addr & 1))
+    {
+      State.exception = SIG_D10V_BUS;
+      State.pc_changed = 1; /* Don't increment the PC. */
+      trace_output_void ();
+      return;
+    }
+  SW (addr + 0, GPR (OP[0] + 0));
+  SW (addr + 2, GPR (OP[0] + 1));
+  trace_output_void ();
+}
+
 /* stb */
 void
 OP_3C000000 ()
@@ -2651,9 +3026,9 @@ OP_1001 ()
   tmp = SEXT40(ACC (OP[0])) - (SEXT16 (GPR (OP[1])) << 16 | GPR (OP[1] + 1));
   if (PSW_ST)
     {
-      if ( tmp > MAX32)
+      if (tmp > SEXT40(MAX32))
        tmp = (MAX32);
-      else if ( tmp < MIN32)
+      else if (tmp < SEXT40(MIN32))
        tmp = (MIN32);
       else
        tmp = (tmp & MASK40);
@@ -2676,9 +3051,9 @@ OP_1003 ()
   tmp = SEXT40(ACC (OP[0])) - SEXT40(ACC (OP[1]));
   if (PSW_ST)
     {
-      if (tmp > MAX32)
+      if (tmp > SEXT40(MAX32))
        tmp = (MAX32);
-      else if ( tmp < MIN32)
+      else if (tmp < SEXT40(MIN32))
        tmp = (MIN32);
       else
        tmp = (tmp & MASK40);
@@ -2740,14 +3115,14 @@ OP_17001000 ()
   trace_input ("subac3s", OP_DREG_OUTPUT, OP_DREG, OP_ACCUM);
   SET_PSW_F1 (PSW_F0);
   tmp = SEXT40 ((GPR (OP[1]) << 16) | GPR (OP[1] + 1)) - SEXT40(ACC (OP[2]));
-  if ( tmp > MAX32)
+  if (tmp > SEXT40(MAX32))
     {
-      tmp = 0x7fffffff;
+      tmp = (MAX32);
       SET_PSW_F0 (1);
     }      
-  else if (tmp < MIN32)
+  else if (tmp < SEXT40(MIN32))
     {
-      tmp = 0x80000000;
+      tmp = (MIN32);
       SET_PSW_F0 (1);
     }      
   else
@@ -2767,14 +3142,14 @@ OP_17001002 ()
   trace_input ("subac3s", OP_DREG_OUTPUT, OP_ACCUM, OP_ACCUM);
   SET_PSW_F1 (PSW_F0);
   tmp = SEXT40(ACC (OP[1])) - SEXT40(ACC (OP[2]));
-  if ( tmp > MAX32)
+  if (tmp > SEXT40(MAX32))
     {
-      tmp = 0x7fffffff;
+      tmp = (MAX32);
       SET_PSW_F0 (1);
     }      
-  else if (tmp < MIN32)
+  else if (tmp < SEXT40(MIN32))
     {
-      tmp = 0x80000000;
+      tmp = (MIN32);
       SET_PSW_F0 (1);
     }      
   else
@@ -3124,6 +3499,7 @@ OP_5F00 ()
            trace_output_void ();
            break;
 
+#ifdef TARGET_SYS_stat
          case TARGET_SYS_stat:
            trace_input ("<stat>", OP_R0, OP_R1, OP_VOID);
            /* stat system call */
@@ -3152,6 +3528,7 @@ OP_5F00 ()
            }
            trace_output_16 (result);
            break;
+#endif
 
          case TARGET_SYS_chown:
            trace_input ("<chown>", OP_R0, OP_R1, OP_R2);
@@ -3249,4 +3626,3 @@ OP_5000000 ()
   SET_GPR (OP[0], tmp);
   trace_output_16 (tmp);
 }
-
This page took 0.049021 seconds and 4 git commands to generate.