jit: make gdb_symtab::blocks an std::forward_list
[deliverable/binutils-gdb.git] / sim / mips / vr.igen
index 863bb556229cb72203f21bcd451c552e9055fc93..9266ae6dc613865427e17cfa2060242fb26fed62 100644 (file)
 // NEC specific instructions
 //
 
-// Integer Instructions
-// --------------------
-//
-// MulAcc is the Multiply Accumulator.
-//     This register is mapped on the the HI and LO registers.
-//     Upper 32 bits of MulAcc is mapped on to lower 32 bits of HI register.
-//     Lower 32 bits of MulAcc is mapped on to lower 32 bits of LO register.
+:%s::::MFHI:int hi
+{
+  return hi ? "hi" : "";
+}
 
+:%s::::SAT:int s
+{
+  return s ? "s" : "";
+}
 
-:function:::unsigned64:MulAcc:
-*vr4100:
+:%s::::UNS:int u
 {
-  unsigned64 result = U8_4 (HI, LO);
-  return result;
+  return u ? "u" : "";
 }
 
-:function:::void:SET_MulAcc:unsigned64 value
-*vr4100:
+// Simulate the various kinds of multiply and multiply-accumulate instructions.
+// Perform an operation of the form:
+//
+//     LHS (+/-) GPR[RS] * GPR[RT]
+//
+// and store it in the 64-bit accumulator.  Optionally copy either LO or
+// HI into a general purpose register.
+//
+// - RD is the destination register of the LO or HI move
+// - RS are RT are the multiplication source registers
+// - ACCUMULATE_P is true if LHS should be the value of the 64-bit accumulator,
+//     false if it should be 0.
+// - STORE_HI_P is true if HI should be stored in RD, false if LO should be.
+// - UNSIGNED_P is true if the operation should be unsigned.
+// - SATURATE_P is true if the result should be saturated to a 32-bit value.
+// - SUBTRACT_P is true if the right hand side should be subtraced from LHS,
+//     false if it should be added.
+// - SHORT_P is true if RS and RT must be 16-bit numbers.
+// - DOUBLE_P is true if the 64-bit accumulator is in LO, false it is a
+//     concatenation of the low 32 bits of HI and LO.
+:function:::void:do_vr_mul_op:int rd, int rs, int rt, int accumulate_p, int store_hi_p, int unsigned_p, int saturate_p, int subtract_p, int short_p, int double_p
 {
-  /* 64 bit specific */
-  *AL4_8 (&HI) = VH4_8 (value);
-  *AL4_8 (&LO) = VL4_8 (value);
+  unsigned64 lhs, x, y, xcut, ycut, product, result;
+
+  check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+
+  lhs = (!accumulate_p ? 0 : double_p ? LO : U8_4 (HI, LO));
+  x = GPR[rs];
+  y = GPR[rt];
+
+  /* Work out the canonical form of X and Y from their significant bits.  */
+  if (!short_p)
+    {
+      /* Normal sign-extension rule for 32-bit operands.  */
+      xcut = EXTEND32 (x);
+      ycut = EXTEND32 (y);
+    }
+  else if (unsigned_p)
+    {
+      /* Operands must be zero-extended 16-bit numbers.  */
+      xcut = x & 0xffff;
+      ycut = y & 0xffff;
+    }
+  else
+    {
+      /* Likewise but sign-extended.  */
+      xcut = EXTEND16 (x);
+      ycut = EXTEND16 (y);
+    }
+  if (x != xcut || y != ycut)
+    sim_engine_abort (SD, CPU, CIA,
+                     "invalid multiplication operand at 0x%08lx\n",
+                     (long) CIA);
+
+  TRACE_ALU_INPUT2 (x, y);
+  product = (unsigned_p
+            ? V8_4 (x, 1) * V8_4 (y, 1)
+            : EXTEND32 (x) * EXTEND32 (y));
+  result = (subtract_p ? lhs - product : lhs + product);
+  if (saturate_p)
+    {
+      /* Saturate the result to 32 bits.  An unsigned, unsaturated
+        result is zero-extended to 64 bits, but unsigned overflow
+        causes all 64 bits to be set.  */
+      if (!unsigned_p && (unsigned64) EXTEND32 (result) != result)
+       result = ((signed64) result < 0 ? -0x7fffffff - 1 : 0x7fffffff);
+      else if (unsigned_p && (result >> 32) != 0)
+       result = (unsigned64) 0 - 1;
+    }
+  TRACE_ALU_RESULT (result);
+
+  if (double_p)
+    LO = result;
+  else
+    {
+      LO = EXTEND32 (result);
+      HI = EXTEND32 (VH4_8 (result));
+    }
+  if (rd != 0)
+    GPR[rd] = store_hi_p ? HI : LO;
 }
 
-:function:::signed64:SignedMultiply:signed32 l, signed32 r
+// VR4100 instructions.
+
+000000,5.RS,5.RT,00000,00000,101000::32::MADD16
+"madd16 r<RS>, r<RT>"
 *vr4100:
 {
-  signed64 result = (signed64) l * (signed64) r;
-  return result;
+  do_vr_mul_op (SD_, 0, RS, RT,
+               1 /* accumulate */,
+               0 /* store in LO */,
+               0 /* signed arithmetic */,
+               0 /* don't saturate */,
+               0 /* don't subtract */,
+               1 /* short */,
+               0 /* single */);
 }
 
-:function:::unsigned64:UnsignedMultiply:unsigned32 l, unsigned32 r
+000000,5.RS,5.RT,00000,00000,101001::64::DMADD16
+"dmadd16 r<RS>, r<RT>"
 *vr4100:
 {
-  unsigned64 result = (unsigned64) l * (unsigned64) r;
-  return result;
+  do_vr_mul_op (SD_, 0, RS, RT,
+               1 /* accumulate */,
+               0 /* store in LO */,
+               0 /* signed arithmetic */,
+               0 /* don't saturate */,
+               0 /* don't subtract */,
+               1 /* short */,
+               1 /* double */);
 }
 
-:function:::unsigned64:Low32Bits:unsigned64 value
-*vr4100:
+
+
+// VR4120 and VR4130 instructions.
+
+000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101001::64::DMACC
+"dmacc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
+*vr4120:
 {
-  unsigned64 result = (signed64) (signed32) VL4_8 (value);
-  return result;
+  do_vr_mul_op (SD_, RD, RS, RT,
+               1 /* accumulate */,
+               MFHI, UNS, SAT,
+               0 /* don't subtract */,
+               SAT /* short */,
+               1 /* double */);
 }
 
-:function:::unsigned64:High32Bits:unsigned64 value
-*vr4100:
+000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101000::32::MACC_4120
+"macc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
+*vr4120:
 {
-  unsigned64 result = (signed64) (signed32) VH4_8 (value);
-  return result;
+  do_vr_mul_op (SD_, RD, RS, RT,
+               1 /* accumulate */,
+               MFHI, UNS, SAT,
+               0 /* don't subtract */,
+               SAT /* short */,
+               0 /* single */);
 }
 
 
+// VR5400 and VR5500 instructions.
 
-// Multiply, Accumulate
-000000,5.RS,5.RT,00000,00000,101000::64::MAC
-"mac r<RS>, r<RT>"
-*vr4100:
+000000,5.RS,5.RT,5.RD,0,1.MFHI,001,01100,1.UNS::32::MUL
+"mul%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
+*vr5400:
+*vr5500:
 {
-  SET_MulAcc (SD_, MulAcc (SD_) + SignedMultiply (SD_, GPR[RS], GPR[RT]));
+  do_vr_mul_op (SD_, RD, RS, RT,
+               0 /* don't accumulate */,
+               MFHI, UNS,
+               0 /* don't saturate */,
+               0 /* don't subtract */,
+               0 /* not short */,
+               0 /* single */);
 }
 
+000000,5.RS,5.RT,5.RD,0,1.MFHI,011,01100,1.UNS::32::MULS
+"muls%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
+*vr5400:
+*vr5500:
+{
+  do_vr_mul_op (SD_, RD, RS, RT,
+               0 /* don't accumulate */,
+               MFHI, UNS,
+               0 /* don't saturate */,
+               1 /* subtract */,
+               0 /* not short */,
+               0 /* single */);
+}
 
-// D-Multiply, Accumulate
-000000,5.RS,5.RT,00000,00000,101001::64::DMAC
-"dmac r<RS>, r<RT>"
-*vr4100:
+000000,5.RS,5.RT,5.RD,0,1.MFHI,101,01100,1.UNS::32::MACC_5xxx
+"macc%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
+*vr5400:
+*vr5500:
+{
+  do_vr_mul_op (SD_, RD, RS, RT,
+               1 /* accumulate */,
+               MFHI, UNS,
+               0 /* don't saturate */,
+               0 /* don't subtract */,
+               0 /* not short */,
+               0 /* single */);
+}
+
+000000,5.RS,5.RT,5.RD,0,1.MFHI,111,01100,1.UNS::32::MSAC
+"msac%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
+*vr5400:
+*vr5500:
+{
+  do_vr_mul_op (SD_, RD, RS, RT,
+               1 /* accumulate */,
+               MFHI, UNS,
+               0 /* don't saturate */,
+               1 /* subtract */,
+               0 /* not short */,
+               0 /* single */);
+}
+
+
+010011,5.BASE,5.INDEX,5.0,5.FD,000101:COP1X:64::LUXC1
+"luxc1 f<FD>, r<INDEX>(r<BASE>)"
+*vr5500:
 {
-  LO = LO + SignedMultiply (SD_, GPR[RS], GPR[RT]);
+  check_fpu (SD_);
+  COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD,
+                         (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0));
 }
 
+010011,5.BASE,5.INDEX,5.FS,00000,001101:COP1X:64::SUXC1
+"suxc1 f<FS>, r<INDEX>(r<BASE>)"
+*vr5500:
+{
+  check_fpu (SD_);
+  do_store (SD_, AccessLength_DOUBLEWORD,
+           (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0,
+           COP_SD (1, FS));
+}
+
+010000,1,19.*,100000:COP0:32::WAIT
+"wait"
+*vr5500:
+
+011100,00000,5.RT,5.DR,00000,111101:SPECIAL:64::MFDR
+"mfdr r<RT>, r<DR>"
+*vr5400:
+*vr5500:
 
+011100,00100,5.RT,5.DR,00000,111101:SPECIAL:64::MTDR
+"mtdr r<RT>, r<DR>"
+*vr5400:
+*vr5500:
 
+011100,00000,00000,00000,00000,111110:SPECIAL:64::DRET
+"dret"
+*vr5400:
+*vr5500:
This page took 0.026944 seconds and 4 git commands to generate.