+op movsxy_tab[] =
+{
+/* If this is disabled, the simulator speeds up by about 12% on a
+ 450 MHz PIII - 9% with ACE_FAST.
+ Maybe we should have separate simulator loops? */
+#if 1
+ { "n", "n", "movs.w @-<REG_N>,<DSP_REG_M>", "111101NNMMMM0000",
+ "MA (1);",
+ "R[n] -= 2;",
+ "DSP_R (m) = RSWAT (R[n]) << 16;",
+ "DSP_GRD (m) = SIGN32 (DSP_R (m));",
+ },
+ { "", "n", "movs.w @<REG_N>,<DSP_REG_M>", "111101NNMMMM0100",
+ "MA (1);",
+ "DSP_R (m) = RSWAT (R[n]) << 16;",
+ "DSP_GRD (m) = SIGN32 (DSP_R (m));",
+ },
+ { "n", "n", "movs.w @<REG_N>+,<DSP_REG_M>", "111101NNMMMM1000",
+ "MA (1);",
+ "DSP_R (m) = RSWAT (R[n]) << 16;",
+ "DSP_GRD (m) = SIGN32 (DSP_R (m));",
+ "R[n] += 2;",
+ },
+ { "n", "n8","movs.w @<REG_N>+REG_8,<DSP_REG_M>", "111101NNMMMM1100",
+ "MA (1);",
+ "DSP_R (m) = RSWAT (R[n]) << 16;",
+ "DSP_GRD (m) = SIGN32 (DSP_R (m));",
+ "R[n] += R[8];",
+ },
+ { "n", "n", "movs.w @-<REG_N>,<DSP_GRD_M>", "111101NNGGGG0000",
+ "MA (1);",
+ "R[n] -= 2;",
+ "DSP_R (m) = RSWAT (R[n]);",
+ },
+ { "", "n", "movs.w @<REG_N>,<DSP_GRD_M>", "111101NNGGGG0100",
+ "MA (1);",
+ "DSP_R (m) = RSWAT (R[n]);",
+ },
+ { "n", "n", "movs.w @<REG_N>+,<DSP_GRD_M>", "111101NNGGGG1000",
+ "MA (1);",
+ "DSP_R (m) = RSWAT (R[n]);",
+ "R[n] += 2;",
+ },
+ { "n", "n8","movs.w @<REG_N>+REG_8,<DSP_GRD_M>", "111101NNGGGG1100",
+ "MA (1);",
+ "DSP_R (m) = RSWAT (R[n]);",
+ "R[n] += R[8];",
+ },
+ { "n", "n", "movs.w <DSP_REG_M>,@-<REG_N>", "111101NNMMMM0001",
+ "MA (1);",
+ "R[n] -= 2;",
+ "WWAT (R[n], DSP_R (m) >> 16);",
+ },
+ { "", "n", "movs.w <DSP_REG_M>,@<REG_N>", "111101NNMMMM0101",
+ "MA (1);",
+ "WWAT (R[n], DSP_R (m) >> 16);",
+ },
+ { "n", "n", "movs.w <DSP_REG_M>,@<REG_N>+", "111101NNMMMM1001",
+ "MA (1);",
+ "WWAT (R[n], DSP_R (m) >> 16);",
+ "R[n] += 2;",
+ },
+ { "n", "n8","movs.w <DSP_REG_M>,@<REG_N>+REG_8", "111101NNMMMM1101",
+ "MA (1);",
+ "WWAT (R[n], DSP_R (m) >> 16);",
+ "R[n] += R[8];",
+ },
+ { "n", "n", "movs.w <DSP_GRD_M>,@-<REG_N>", "111101NNGGGG0001",
+ "MA (1);",
+ "R[n] -= 2;",
+ "WWAT (R[n], SEXT (DSP_R (m)));",
+ },
+ { "", "n", "movs.w <DSP_GRD_M>,@<REG_N>", "111101NNGGGG0101",
+ "MA (1);",
+ "WWAT (R[n], SEXT (DSP_R (m)));",
+ },
+ { "n", "n", "movs.w <DSP_GRD_M>,@<REG_N>+", "111101NNGGGG1001",
+ "MA (1);",
+ "WWAT (R[n], SEXT (DSP_R (m)));",
+ "R[n] += 2;",
+ },
+ { "n", "n8","movs.w <DSP_GRD_M>,@<REG_N>+REG_8", "111101NNGGGG1101",
+ "MA (1);",
+ "WWAT (R[n], SEXT (DSP_R (m)));",
+ "R[n] += R[8];",
+ },
+ { "n", "n", "movs.l @-<REG_N>,<DSP_REG_M>", "111101NNMMMM0010",
+ "MA (1);",
+ "R[n] -= 4;",
+ "DSP_R (m) = RLAT (R[n]);",
+ "DSP_GRD (m) = SIGN32 (DSP_R (m));",
+ },
+ { "", "n", "movs.l @<REG_N>,<DSP_REG_M>", "111101NNMMMM0110",
+ "MA (1);",
+ "DSP_R (m) = RLAT (R[n]);",
+ "DSP_GRD (m) = SIGN32 (DSP_R (m));",
+ },
+ { "n", "n", "movs.l @<REG_N>+,<DSP_REG_M>", "111101NNMMMM1010",
+ "MA (1);",
+ "DSP_R (m) = RLAT (R[n]);",
+ "DSP_GRD (m) = SIGN32 (DSP_R (m));",
+ "R[n] += 4;",
+ },
+ { "n", "n8","movs.l @<REG_N>+REG_8,<DSP_REG_M>", "111101NNMMMM1110",
+ "MA (1);",
+ "DSP_R (m) = RLAT (R[n]);",
+ "DSP_GRD (m) = SIGN32 (DSP_R (m));",
+ "R[n] += R[8];",
+ },
+ { "n", "n", "movs.l <DSP_REG_M>,@-<REG_N>", "111101NNMMMM0011",
+ "MA (1);",
+ "R[n] -= 4;",
+ "WLAT (R[n], DSP_R (m));",
+ },
+ { "", "n", "movs.l <DSP_REG_M>,@<REG_N>", "111101NNMMMM0111",
+ "MA (1);",
+ "WLAT (R[n], DSP_R (m));",
+ },
+ { "n", "n", "movs.l <DSP_REG_M>,@<REG_N>+", "111101NNMMMM1011",
+ "MA (1);",
+ "WLAT (R[n], DSP_R (m));",
+ "R[n] += 4;",
+ },
+ { "n", "n8","movs.l <DSP_REG_M>,@<REG_N>+REG_8", "111101NNMMMM1111",
+ "MA (1);",
+ "WLAT (R[n], DSP_R (m));",
+ "R[n] += R[8];",
+ },
+ { "n", "n", "movs.l <DSP_GRD_M>,@-<REG_N>", "111101NNGGGG0011",
+ "MA (1);",
+ "R[n] -= 4;",
+ "WLAT (R[n], SEXT (DSP_R (m)));",
+ },
+ { "", "n", "movs.l <DSP_GRD_M>,@<REG_N>", "111101NNGGGG0111",
+ "MA (1);",
+ "WLAT (R[n], SEXT (DSP_R (m)));",
+ },
+ { "n", "n", "movs.l <DSP_GRD_M>,@<REG_N>+", "111101NNGGGG1011",
+ "MA (1);",
+ "WLAT (R[n], SEXT (DSP_R (m)));",
+ "R[n] += 4;",
+ },
+ { "n", "n8","movs.l <DSP_GRD_M>,@<REG_N>+REG_8", "111101NNGGGG1111",
+ "MA (1);",
+ "WLAT (R[n], SEXT (DSP_R (m)));",
+ "R[n] += R[8];",
+ },
+ { "", "n", "movx.w @<REG_xy>,<DSP_XY>", "111100xyXY0001??",
+ "DSP_R (m) = RSWAT (R[n]) << 16;",
+ "if (iword & 3)",
+ " {",
+ " iword &= 0xfd53; goto top;",
+ " }",
+ },
+ { "", "n", "movx.l @<REG_xy>,<DSP_XY>", "111100xyXY010100",
+ "DSP_R (m) = RLAT (R[n]);",
+ },
+ { "n", "n", "movx.w @<REG_xy>+,<DSP_XY>", "111100xyXY0010??",
+ "DSP_R (m) = RSWAT (R[n]) << 16;",
+ "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;",
+ "if (iword & 3)",
+ " {",
+ " iword &= 0xfd53; goto top;",
+ " }",
+ },
+ { "n", "n", "movx.l @<REG_xy>+,<DSP_XY>", "111100xyXY011000",
+ "DSP_R (m) = RLAT (R[n]);",
+ "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 4;",
+ },
+ { "n", "n8","movx.w @<REG_xy>+REG_8,<DSP_XY>", "111100xyXY0011??",
+ "DSP_R (m) = RSWAT (R[n]) << 16;",
+ "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
+ "if (iword & 3)",
+ " {",
+ " iword &= 0xfd53; goto top;",
+ " }",
+ },
+ { "n", "n8","movx.l @<REG_xy>+REG_8,<DSP_XY>", "111100xyXY011100",
+ "DSP_R (m) = RLAT (R[n]);",
+ "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
+ },
+ { "", "n", "movx.w <DSP_Ax>,@<REG_xy>", "111100xyax1001??",
+ "WWAT (R[n], DSP_R (m) >> 16);",
+ "if (iword & 3)",
+ " {",
+ " iword &= 0xfd53; goto top;",
+ " }",
+ },
+ { "", "n", "movx.l <DSP_Ax>,@<REG_xy>", "111100xyax110100",
+ "WLAT (R[n], DSP_R (m));",
+ },
+ { "n", "n", "movx.w <DSP_Ax>,@<REG_xy>+", "111100xyax1010??",
+ "WWAT (R[n], DSP_R (m) >> 16);",
+ "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;",
+ "if (iword & 3)",
+ " {",
+ " iword &= 0xfd53; goto top;",
+ " }",
+ },
+ { "n", "n", "movx.l <DSP_Ax>,@<REG_xy>+", "111100xyax111000",
+ "WLAT (R[n], DSP_R (m));",
+ "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 4;",
+ },
+ { "n", "n8","movx.w <DSP_Ax>,@<REG_xy>+REG_8","111100xyax1011??",
+ "WWAT (R[n], DSP_R (m) >> 16);",
+ "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
+ "if (iword & 3)",
+ " {",
+ " iword &= 0xfd53; goto top;",
+ " }",
+ },
+ { "n", "n8","movx.l <DSP_Ax>,@<REG_xy>+REG_8","111100xyax111100",
+ "WLAT (R[n], DSP_R (m));",
+ "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
+ },
+ { "", "n", "movy.w @<REG_yx>,<DSP_YX>", "111100yxYX000001",
+ "DSP_R (m) = RSWAT (R[n]) << 16;",
+ },
+ { "n", "n", "movy.w @<REG_yx>+,<DSP_YX>", "111100yxYX000010",
+ "DSP_R (m) = RSWAT (R[n]) << 16;",
+ "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;",
+ },
+ { "n", "n9","movy.w @<REG_yx>+REG_9,<DSP_YX>", "111100yxYX000011",
+ "DSP_R (m) = RSWAT (R[n]) << 16;",
+ "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
+ },
+ { "", "n", "movy.w <DSP_Ay>,@<REG_yx>", "111100yxAY010001",
+ "WWAT (R[n], DSP_R (m) >> 16);",
+ },
+ { "n", "n", "movy.w <DSP_Ay>,@<REG_yx>+", "111100yxAY010010",
+ "WWAT (R[n], DSP_R (m) >> 16);",
+ "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;",
+ },
+ { "n", "n9", "movy.w <DSP_Ay>,@<REG_yx>+REG_9", "111100yxAY010011",
+ "WWAT (R[n], DSP_R (m) >> 16);",
+ "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
+ },
+ { "", "n", "movy.l @<REG_yx>,<DSP_YX>", "111100yxYX100001",
+ "DSP_R (m) = RLAT (R[n]);",
+ },
+ { "n", "n", "movy.l @<REG_yx>+,<DSP_YX>", "111100yxYX100010",
+ "DSP_R (m) = RLAT (R[n]);",
+ "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 4;",
+ },
+ { "n", "n9","movy.l @<REG_yx>+REG_9,<DSP_YX>", "111100yxYX100011",
+ "DSP_R (m) = RLAT (R[n]);",
+ "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
+ },
+ { "", "n", "movy.l <DSP_Ay>,@<REG_yx>", "111100yxAY110001",
+ "WLAT (R[n], DSP_R (m));",
+ },
+ { "n", "n", "movy.l <DSP_Ay>,@<REG_yx>+", "111100yxAY110010",
+ "WLAT (R[n], DSP_R (m));",
+ "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 4;",
+ },
+ { "n", "n9", "movy.l <DSP_Ay>,@<REG_yx>+REG_9", "111100yxAY110011",
+ "WLAT (R[n], DSP_R (m));",
+ "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
+ },
+ { "", "", "nopx nopy", "1111000000000000",
+ "/* nop */",
+ },
+ { "", "", "ppi", "1111100000000000",
+ "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();",
+ "ppi_insn (RIAT (nip));",
+ "SET_NIP (nip + 2);",
+ "iword &= 0xf7ff; goto top;",
+ },
+#endif
+ {0, 0}};
+
+op ppi_tab[] =
+{
+ { "","", "pshl #<imm>,dz", "00000iiim16.zzzz",
+ "int Sz = DSP_R (z) & 0xffff0000;",
+ "",
+ "if (i <= 16)",
+ " res = Sz << i;",
+ "else if (i >= 128 - 16)",
+ " res = (unsigned) Sz >> 128 - i; /* no sign extension */",
+ "else",
+ " {",
+ " RAISE_EXCEPTION (SIGILL);",
+ " return;",
+ " }",
+ "res &= 0xffff0000;",
+ "res_grd = 0;",
+ "goto logical;",
+ },
+ { "","", "psha #<imm>,dz", "00010iiim32.zzzz",
+ "int Sz = DSP_R (z);",
+ "int Sz_grd = GET_DSP_GRD (z);",
+ "",
+ "if (i <= 32)",
+ " {",
+ " if (i == 32)",
+ " {",
+ " res = 0;",
+ " res_grd = Sz;",
+ " }",
+ " else",
+ " {",
+ " res = Sz << i;",
+ " res_grd = Sz_grd << i | (unsigned) Sz >> 32 - i;",
+ " }",
+ " res_grd = SEXT (res_grd);",
+ " carry = res_grd & 1;",
+ " }",
+ "else if (i >= 96)",
+ " {",
+ " i = 128 - i;",
+ " if (i == 32)",
+ " {",
+ " res_grd = SIGN32 (Sz_grd);",
+ " res = Sz_grd;",
+ " }",
+ " else",
+ " {",
+ " res = Sz >> i | Sz_grd << 32 - i;",
+ " res_grd = Sz_grd >> i;",
+ " }",
+ " carry = Sz >> (i - 1) & 1;",
+ " }",
+ "else",
+ " {",
+ " RAISE_EXCEPTION (SIGILL);",
+ " return;",
+ " }",
+ "COMPUTE_OVERFLOW;",
+ "greater_equal = 0;",
+ },
+ { "","", "pmuls Se,Sf,Dg", "0100eeffxxyygguu",
+ "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;",
+ "if (res == 0x80000000)",
+ " res = 0x7fffffff;",
+ "DSP_R (g) = res;",
+ "DSP_GRD (g) = SIGN32 (res);",
+ "return;",
+ },
+ { "","", "psub Sx,Sy,Du pmuls Se,Sf,Dg", "0110eeffxxyygguu",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;",
+ "if (res == 0x80000000)",
+ " res = 0x7fffffff;",
+ "DSP_R (g) = res;",
+ "DSP_GRD (g) = SIGN32 (res);",
+ "",
+ "z = u;",
+ "res = Sx - Sy;",
+ "carry = (unsigned) res > (unsigned) Sx;",
+ "res_grd = Sx_grd - Sy_grd - carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "padd Sx,Sy,Du pmuls Se,Sf,Dg", "0111eeffxxyygguu",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;",
+ "if (res == 0x80000000)",
+ " res = 0x7fffffff;",
+ "DSP_R (g) = res;",
+ "DSP_GRD (g) = SIGN32 (res);",
+ "",
+ "z = u;",
+ "res = Sx + Sy;",
+ "carry = (unsigned) res < (unsigned) Sx;",
+ "res_grd = Sx_grd + Sy_grd + carry;",
+ "COMPUTE_OVERFLOW;",
+ },
+ { "","", "psubc Sx,Sy,Dz", "10100000xxyyzzzz",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = Sx - Sy - (DSR & 1);",
+ "carry = (unsigned) res > (unsigned) Sx || (res == Sx && Sy);",
+ "res_grd = Sx_grd + Sy_grd + carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ "DSR &= ~0xf1;\n",
+ "if (res || res_grd)\n",
+ " DSR |= greater_equal | res_grd >> 2 & DSR_MASK_N | overflow;\n",
+ "else\n",
+ " DSR |= DSR_MASK_Z | overflow;\n",
+ "DSR |= carry;\n",
+ "goto assign_z;\n",
+ },
+ { "","", "paddc Sx,Sy,Dz", "10110000xxyyzzzz",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = Sx + Sy + (DSR & 1);",
+ "carry = (unsigned) res < (unsigned) Sx || (res == Sx && Sy);",
+ "res_grd = Sx_grd + Sy_grd + carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ "DSR &= ~0xf1;\n",
+ "if (res || res_grd)\n",
+ " DSR |= greater_equal | res_grd >> 2 & DSR_MASK_N | overflow;\n",
+ "else\n",
+ " DSR |= DSR_MASK_Z | overflow;\n",
+ "DSR |= carry;\n",
+ "goto assign_z;\n",
+ },
+ { "","", "pcmp Sx,Sy", "10000100xxyyzzzz",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "z = 17; /* Ignore result. */",
+ "res = Sx - Sy;",
+ "carry = (unsigned) res > (unsigned) Sx;",
+ "res_grd = Sx_grd - Sy_grd - carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "pwsb Sx,Sy,Dz", "10100100xxyyzzzz",
+ },
+ { "","", "pwad Sx,Sy,Dz", "10110100xxyyzzzz",
+ },
+ { "","", "(if cc) pabs Sx,Dz", "100010ccxx01zzzz",
+ "/* FIXME: duplicate code pabs. */",
+ "res = DSP_R (x);",
+ "res_grd = GET_DSP_GRD (x);",
+ "if (res >= 0)",
+ " carry = 0;",
+ "else",
+ " {",
+ " res = -res;",
+ " carry = (res != 0); /* The manual has a bug here. */",
+ " res_grd = -res_grd - carry;",
+ " }",
+ "COMPUTE_OVERFLOW;",
+ "/* ??? The re-computing of overflow after",
+ " saturation processing is specific to pabs. */",
+ "overflow = res_grd != SIGN32 (res) ? DSR_MASK_V : 0;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "pabs Sx,Dz", "10001000xx..zzzz",
+ "res = DSP_R (x);",
+ "res_grd = GET_DSP_GRD (x);",
+ "if (res >= 0)",
+ " carry = 0;",
+ "else",
+ " {",
+ " res = -res;",
+ " carry = (res != 0); /* The manual has a bug here. */",
+ " res_grd = -res_grd - carry;",
+ " }",
+ "COMPUTE_OVERFLOW;",
+ "/* ??? The re-computing of overflow after",
+ " saturation processing is specific to pabs. */",
+ "overflow = res_grd != SIGN32 (res) ? DSR_MASK_V : 0;",
+ "ADD_SUB_GE;",
+ },
+
+ { "","", "(if cc) prnd Sx,Dz", "100110ccxx01zzzz",
+ "/* FIXME: duplicate code prnd. */",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "",
+ "res = (Sx + 0x8000) & 0xffff0000;",
+ "carry = (unsigned) res < (unsigned) Sx;",
+ "res_grd = Sx_grd + carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "prnd Sx,Dz", "10011000xx..zzzz",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "",
+ "res = (Sx + 0x8000) & 0xffff0000;",
+ "carry = (unsigned) res < (unsigned) Sx;",
+ "res_grd = Sx_grd + carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+
+ { "","", "(if cc) pabs Sy,Dz", "101010cc01yyzzzz",
+ "/* FIXME: duplicate code pabs. */",
+ "res = DSP_R (y);",
+ "res_grd = 0;",
+ "overflow = 0;",
+ "greater_equal = DSR_MASK_G;",
+ "if (res >= 0)",
+ " carry = 0;",
+ "else",
+ " {",
+ " res = -res;",
+ " carry = 1;",
+ " if (res < 0)",
+ " {",
+ " if (S)",
+ " res = 0x7fffffff;",
+ " else",
+ " {",
+ " overflow = DSR_MASK_V;",
+ " greater_equal = 0;",
+ " }",
+ " }",
+ " }",
+ },
+ { "","", "pabs Sy,Dz", "10101000..yyzzzz",
+ "res = DSP_R (y);",
+ "res_grd = 0;",
+ "overflow = 0;",
+ "greater_equal = DSR_MASK_G;",
+ "if (res >= 0)",
+ " carry = 0;",
+ "else",
+ " {",
+ " res = -res;",
+ " carry = 1;",
+ " if (res < 0)",
+ " {",
+ " if (S)",
+ " res = 0x7fffffff;",
+ " else",
+ " {",
+ " overflow = DSR_MASK_V;",
+ " greater_equal = 0;",
+ " }",
+ " }",
+ " }",
+ },
+ { "","", "(if cc) prnd Sy,Dz", "101110cc01yyzzzz",
+ "/* FIXME: duplicate code prnd. */",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = (Sy + 0x8000) & 0xffff0000;",
+ "carry = (unsigned) res < (unsigned) Sy;",
+ "res_grd = Sy_grd + carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "prnd Sy,Dz", "10111000..yyzzzz",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = (Sy + 0x8000) & 0xffff0000;",
+ "carry = (unsigned) res < (unsigned) Sy;",
+ "res_grd = Sy_grd + carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "(if cc) pshl Sx,Sy,Dz", "100000ccxxyyzzzz",
+ "int Sx = DSP_R (x) & 0xffff0000;",
+ "int Sy = DSP_R (y) >> 16 & 0x7f;",
+ "",
+ "if (Sy <= 16)",
+ " res = Sx << Sy;",
+ "else if (Sy >= 128 - 16)",
+ " res = (unsigned) Sx >> 128 - Sy; /* no sign extension */",
+ "else",
+ " {",
+ " RAISE_EXCEPTION (SIGILL);",
+ " return;",
+ " }",
+ "goto cond_logical;",
+ },
+ { "","", "(if cc) psha Sx,Sy,Dz", "100100ccxxyyzzzz",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "int Sy = DSP_R (y) >> 16 & 0x7f;",
+ "",
+ "if (Sy <= 32)",
+ " {",
+ " if (Sy == 32)",
+ " {",
+ " res = 0;",
+ " res_grd = Sx;",
+ " }",
+ " else",
+ " {",
+ " res = Sx << Sy;",
+ " res_grd = Sx_grd << Sy | (unsigned) Sx >> 32 - Sy;",
+ " }",
+ " res_grd = SEXT (res_grd);",
+ " carry = res_grd & 1;",
+ " }",
+ "else if (Sy >= 96)",
+ " {",
+ " Sy = 128 - Sy;",
+ " if (Sy == 32)",
+ " {",
+ " res_grd = SIGN32 (Sx_grd);",
+ " res = Sx_grd;",
+ " }",
+ " else",
+ " {",
+ " res = Sx >> Sy | Sx_grd << 32 - Sy;",
+ " res_grd = Sx_grd >> Sy;",
+ " }",
+ " carry = Sx >> (Sy - 1) & 1;",
+ " }",
+ "else",
+ " {",
+ " RAISE_EXCEPTION (SIGILL);",
+ " return;",
+ " }",
+ "COMPUTE_OVERFLOW;",
+ "greater_equal = 0;",
+ },
+ { "","", "(if cc) psub Sx,Sy,Dz", "101000ccxxyyzzzz",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = Sx - Sy;",
+ "carry = (unsigned) res > (unsigned) Sx;",
+ "res_grd = Sx_grd - Sy_grd - carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "(if cc) psub Sy,Sx,Dz", "100001ccxxyyzzzz",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = Sy - Sx;",
+ "carry = (unsigned) res > (unsigned) Sy;",
+ "res_grd = Sy_grd - Sx_grd - carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "(if cc) padd Sx,Sy,Dz", "101100ccxxyyzzzz",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = Sx + Sy;",
+ "carry = (unsigned) res < (unsigned) Sx;",
+ "res_grd = Sx_grd + Sy_grd + carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "(if cc) pand Sx,Sy,Dz", "100101ccxxyyzzzz",
+ "res = DSP_R (x) & DSP_R (y);",
+ "cond_logical:",
+ "res &= 0xffff0000;",
+ "res_grd = 0;",
+ "if (iword & 0x200)\n",
+ " goto assign_z;\n",
+ "logical:",
+ "carry = 0;",
+ "overflow = 0;",
+ "greater_equal = 0;",
+ "DSR &= ~0xf1;\n",
+ "if (res)\n",
+ " DSR |= res >> 26 & DSR_MASK_N;\n",
+ "else\n",
+ " DSR |= DSR_MASK_Z;\n",
+ "goto assign_dc;\n",
+ },
+ { "","", "(if cc) pxor Sx,Sy,Dz", "101001ccxxyyzzzz",
+ "res = DSP_R (x) ^ DSP_R (y);",
+ "goto cond_logical;",
+ },
+ { "","", "(if cc) por Sx,Sy,Dz", "101101ccxxyyzzzz",
+ "res = DSP_R (x) | DSP_R (y);",
+ "goto cond_logical;",
+ },
+ { "","", "(if cc) pdec Sx,Dz", "100010ccxx..zzzz",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "",
+ "res = Sx - 0x10000;",
+ "carry = res > Sx;",
+ "res_grd = Sx_grd - carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ "res &= 0xffff0000;",
+ },
+ { "","", "(if cc) pinc Sx,Dz", "100110ccxx..zzzz",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "",
+ "res = Sx + 0x10000;",
+ "carry = res < Sx;",
+ "res_grd = Sx_grd + carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ "res &= 0xffff0000;",
+ },
+ { "","", "(if cc) pdec Sy,Dz", "101010cc..yyzzzz",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = Sy - 0x10000;",
+ "carry = res > Sy;",
+ "res_grd = Sy_grd - carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ "res &= 0xffff0000;",
+ },
+ { "","", "(if cc) pinc Sy,Dz", "101110cc..yyzzzz",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = Sy + 0x10000;",
+ "carry = res < Sy;",
+ "res_grd = Sy_grd + carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ "res &= 0xffff0000;",
+ },
+ { "","", "(if cc) pclr Dz", "100011cc....zzzz",
+ "res = 0;",
+ "res_grd = 0;",
+ "carry = 0;",
+ "overflow = 0;",
+ "greater_equal = 1;",
+ },
+ { "","", "pclr Du pmuls Se,Sf,Dg", "0100eeff0001gguu",
+ "/* Do multiply. */",
+ "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;",
+ "if (res == 0x80000000)",
+ " res = 0x7fffffff;",
+ "DSP_R (g) = res;",
+ "DSP_GRD (g) = SIGN32 (res);",
+ "/* FIXME: update DSR based on results of multiply! */",
+ "",
+ "/* Do clr. */",
+ "z = u;",
+ "res = 0;",
+ "res_grd = 0;",
+ "goto assign_z;",
+ },
+ { "","", "(if cc) pdmsb Sx,Dz", "100111ccxx..zzzz",
+ "unsigned Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "int i = 16;",
+ "",
+ "if (Sx_grd < 0)",
+ " {",
+ " Sx_grd = ~Sx_grd;",
+ " Sx = ~Sx;",
+ " }",
+ "if (Sx_grd)",
+ " {",
+ " Sx = Sx_grd;",
+ " res = -2;",
+ " }",
+ "else if (Sx)",
+ " res = 30;",
+ "else",
+ " res = 31;",
+ "do",
+ " {",
+ " if (Sx & ~0 << i)",
+ " {",
+ " res -= i;",
+ " Sx >>= i;",
+ " }",
+ " }",
+ "while (i >>= 1);",
+ "res <<= 16;",
+ "res_grd = SIGN32 (res);",
+ "carry = 0;",
+ "overflow = 0;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "(if cc) pdmsb Sy,Dz", "101111cc..yyzzzz",
+ "unsigned Sy = DSP_R (y);",
+ "int i;",
+ "",
+ "if (Sy < 0)",
+ " Sy = ~Sy;",
+ "Sy <<= 1;",
+ "res = 31;",
+ "do",
+ " {",
+ " if (Sy & ~0 << i)",
+ " {",
+ " res -= i;",
+ " Sy >>= i;",
+ " }",
+ " }",
+ "while (i >>= 1);",
+ "res <<= 16;",
+ "res_grd = SIGN32 (res);",
+ "carry = 0;",
+ "overflow = 0;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "(if cc) pneg Sx,Dz", "110010ccxx..zzzz",
+ "int Sx = DSP_R (x);",
+ "int Sx_grd = GET_DSP_GRD (x);",
+ "",
+ "res = 0 - Sx;",
+ "carry = res != 0;",
+ "res_grd = 0 - Sx_grd - carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "(if cc) pcopy Sx,Dz", "110110ccxx..zzzz",
+ "res = DSP_R (x);",
+ "res_grd = GET_DSP_GRD (x);",
+ "carry = 0;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "(if cc) pneg Sy,Dz", "111010cc..yyzzzz",
+ "int Sy = DSP_R (y);",
+ "int Sy_grd = SIGN32 (Sy);",
+ "",
+ "res = 0 - Sy;",
+ "carry = res != 0;",
+ "res_grd = 0 - Sy_grd - carry;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "(if cc) pcopy Sy,Dz", "111110cc..yyzzzz",
+ "res = DSP_R (y);",
+ "res_grd = SIGN32 (res);",
+ "carry = 0;",
+ "COMPUTE_OVERFLOW;",
+ "ADD_SUB_GE;",
+ },
+ { "","", "(if cc) psts MACH,Dz", "110011cc....zzzz",
+ "res = MACH;",
+ "res_grd = SIGN32 (res);",
+ "goto assign_z;",
+ },
+ { "","", "(if cc) psts MACL,Dz", "110111cc....zzzz",
+ "res = MACL;",
+ "res_grd = SIGN32 (res);",
+ "goto assign_z;",
+ },
+ { "","", "(if cc) plds Dz,MACH", "111011cc....zzzz",
+ "if (0xa05f >> z & 1)",
+ " RAISE_EXCEPTION (SIGILL);",
+ "else",
+ " MACH = DSP_R (z);",
+ "return;",
+ },
+ { "","", "(if cc) plds Dz,MACL", "111111cc....zzzz",
+ "if (0xa05f >> z & 1)",
+ " RAISE_EXCEPTION (SIGILL);",
+ "else",
+ " MACL = DSP_R (z) = res;",
+ "return;",
+ },
+ /* sh4a */
+ { "","", "(if cc) pswap Sx,Dz", "100111ccxx01zzzz",
+ "int Sx = DSP_R (x);",
+ "",
+ "res = ((Sx & 0xffff) * 65536) + ((Sx >> 16) & 0xffff);",
+ "res_grd = GET_DSP_GRD (x);",
+ "carry = 0;",
+ "overflow = 0;",
+ "greater_equal = res & 0x80000000 ? 0 : DSR_MASK_G;",
+ },
+ /* sh4a */
+ { "","", "(if cc) pswap Sy,Dz", "101111cc01yyzzzz",
+ "int Sy = DSP_R (y);",
+ "",
+ "res = ((Sy & 0xffff) * 65536) + ((Sy >> 16) & 0xffff);",
+ "res_grd = SIGN32 (Sy);",
+ "carry = 0;",
+ "overflow = 0;",
+ "greater_equal = res & 0x80000000 ? 0 : DSR_MASK_G;",
+ },
+
+ {0, 0}
+};
+