* [Qemu-devel] [PATCH] Add special MIPS multiply instructions
@ 2006-04-21 18:30 Dirk Behme
0 siblings, 0 replies; 2+ messages in thread
From: Dirk Behme @ 2006-04-21 18:30 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 757 bytes --]
Hi,
while playing with different -march options of MIPS GCC, I
found that GCC generates some special R5400 three register
multiply assembly commands if used with -march=vr5400 (MULS,
MULHI, MACC etc.). These commands use 11 bit extended
opcodes where the lowest 6 bits are the same as for the
standard MULT/MULTU instructions (0x18 & 0x19). See for
example chapter 17.4 of
www.necelam.com/docs/files/1375_V2.pdf
Unfortunately, because QEMU uses mask 0x3F to extract
opcode, it doesn't detect these special opcodes and instead
executes the (wrong) standard ones. No exception or
warning is given. Calculation is simply wrong and program
misbehaves while working with wrong values.
Patch below adds support for these special MIPS opcodes.
Regards
Dirk
[-- Attachment #2: qemu-mips-r54xx-multiply-patch.txt --]
[-- Type: text/plain, Size: 10478 bytes --]
--- ./target-mips/op_helper.c_orig 2006-04-21 19:47:43.000000000 +0200
+++ ./target-mips/op_helper.c 2006-04-21 20:18:38.000000000 +0200
@@ -129,6 +129,132 @@ void do_msubu (void)
tmp = ((uint64_t)T0 * (uint64_t)T1);
set_HILO(get_HILO() - tmp);
}
+
+void do_muls (void)
+{
+ int64_t tmp;
+
+ tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_mulsu (void)
+{
+ uint64_t tmp;
+
+ tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_macc (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_macchi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_maccu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_macchiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_msac (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_msachi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_msacu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_msachiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_mulhi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_mulhiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_mulshi (void)
+{
+ int64_t tmp;
+
+ tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_mulshiu (void)
+{
+ uint64_t tmp;
+
+ tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
#endif
#if defined(CONFIG_USER_ONLY)
--- ./target-mips/op.c_orig 2006-04-21 19:47:43.000000000 +0200
+++ ./target-mips/op.c 2006-04-21 20:06:58.000000000 +0200
@@ -409,6 +409,146 @@ void op_msubu (void)
set_HILO(get_HILO() - tmp);
RETURN();
}
+
+void op_muls (void)
+{
+ int64_t tmp;
+
+ tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_mulsu (void)
+{
+ uint64_t tmp;
+
+ tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_macc (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_macchi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_maccu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_macchiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_msac (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_msachi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_msacu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_msachiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulhi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulhiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulshi (void)
+{
+ int64_t tmp;
+
+ tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulshiu (void)
+{
+ uint64_t tmp;
+
+ tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
#else
void op_mult (void)
{
@@ -445,6 +585,89 @@ void op_msubu (void)
CALL_FROM_TB0(do_msubu);
RETURN();
}
+
+void op_muls (void)
+{
+ CALL_FROM_TB0(do_muls);
+ RETURN();
+}
+
+void op_mulsu (void)
+{
+ CALL_FROM_TB0(do_mulsu);
+ RETURN();
+}
+
+void op_macc (void)
+{
+ CALL_FROM_TB0(do_macc);
+ RETURN();
+}
+
+void op_macchi (void)
+{
+ CALL_FROM_TB0(do_macchi);
+ RETURN();
+}
+
+void op_maccu (void)
+{
+ CALL_FROM_TB0(do_maccu);
+ RETURN();
+}
+void op_macchiu (void)
+{
+ CALL_FROM_TB0(do_macchiu);
+ RETURN();
+}
+
+void op_msac (void)
+{
+ CALL_FROM_TB0(do_msac);
+ RETURN();
+}
+
+void op_msachi (void)
+{
+ CALL_FROM_TB0(do_msachi);
+ RETURN();
+}
+
+void op_msacu (void)
+{
+ CALL_FROM_TB0(do_msacu);
+ RETURN();
+}
+
+void op_msachiu (void)
+{
+ CALL_FROM_TB0(do_msachiu);
+ RETURN();
+}
+
+void op_mulhi (void)
+{
+ CALL_FROM_TB0(do_mulhi);
+ RETURN();
+}
+
+void op_mulhiu (void)
+{
+ CALL_FROM_TB0(do_mulhiu);
+ RETURN();
+}
+
+void op_mulshi (void)
+{
+ CALL_FROM_TB0(do_mulshi);
+ RETURN();
+}
+
+void op_mulshiu (void)
+{
+ CALL_FROM_TB0(do_mulshiu);
+ RETURN();
+}
#endif
/* Conditional moves */
--- ./target-mips/translate.c_orig 2006-04-21 19:47:43.000000000 +0200
+++ ./target-mips/translate.c 2006-04-21 20:12:15.000000000 +0200
@@ -186,6 +186,24 @@ enum {
OPC_SDBBP = 0x3F | EXT_SPECIAL2,
};
+enum {
+ /* Extended three operand multiply operations with 11 bit opcode */
+ OPC_MULS = 0x0D8,
+ OPC_MULSU = 0x0D9,
+ OPC_MACC = 0x158,
+ OPC_MACCU = 0x159,
+ OPC_MSAC = 0x1D8,
+ OPC_MSACU = 0x1D9,
+ OPC_MULHI = 0x258,
+ OPC_MULHIU = 0x259,
+ OPC_MULSHI = 0x2D8,
+ OPC_MULSHIU = 0x2D9,
+ OPC_MACCHI = 0x358,
+ OPC_MACCHIU = 0x359,
+ OPC_MSACHI = 0x3D8,
+ OPC_MSACHIU = 0x3D9,
+};
+
/* Branch REGIMM */
enum {
OPC_BLTZ = 0x00 | EXT_REGIMM,
@@ -810,6 +828,79 @@ static void gen_muldiv (DisasContext *ct
MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
}
+static void gen_muldiv_ext (DisasContext *ctx, uint16_t opc,
+ int rd, int rs, int rt)
+{
+ const unsigned char *opn = "unk";
+
+ GEN_LOAD_REG_TN(T0, rs);
+ GEN_LOAD_REG_TN(T1, rt);
+ switch (opc) {
+ case OPC_MULS:
+ gen_op_muls();
+ opn = "muls";
+ break;
+ case OPC_MULSU:
+ gen_op_mulsu();
+ opn = "mulsu";
+ break;
+ case OPC_MACC:
+ gen_op_macc();
+ opn = "macc";
+ break;
+ case OPC_MACCU:
+ gen_op_maccu();
+ opn = "maccu";
+ break;
+ case OPC_MSAC:
+ gen_op_msac();
+ opn = "msac";
+ break;
+ case OPC_MSACU:
+ gen_op_msacu();
+ opn = "msacu";
+ break;
+ case OPC_MULHI:
+ gen_op_mulhi();
+ opn = "mulhi";
+ break;
+ case OPC_MULHIU:
+ gen_op_mulhiu();
+ opn = "mulhiu";
+ break;
+ case OPC_MULSHI:
+ gen_op_mulshi();
+ opn = "mulshi";
+ break;
+ case OPC_MULSHIU:
+ gen_op_mulshiu();
+ opn = "mulshiu";
+ break;
+ case OPC_MACCHI:
+ gen_op_macchi();
+ opn = "macchi";
+ break;
+ case OPC_MACCHIU:
+ gen_op_macchiu();
+ opn = "macchiu";
+ break;
+ case OPC_MSACHI:
+ gen_op_msachi();
+ opn = "msachi";
+ break;
+ case OPC_MSACHIU:
+ gen_op_msachiu();
+ opn = "msachiu";
+ break;
+ default:
+ MIPS_INVAL("mul/div ext");
+ generate_exception(ctx, EXCP_RI);
+ return;
+ }
+ GEN_STORE_TN_REG(rd, T0);
+ MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
+}
+
static void gen_cl (DisasContext *ctx, uint16_t opc,
int rd, int rs)
{
@@ -1347,7 +1438,12 @@ static void decode_opc (DisasContext *ct
gen_arith(ctx, op1 | EXT_SPECIAL, rd, rs, rt);
break;
case 0x18 ... 0x1B: /* MULT / DIV */
- gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt);
+ if(!sa) {
+ gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt);
+ } else {
+ op1 = ctx->opcode & 0x7FF;
+ gen_muldiv_ext(ctx, op1, rd, rs, rt);
+ }
break;
case 0x08 ... 0x09: /* Jumps */
gen_compute_branch(ctx, op1 | EXT_SPECIAL, rs, rd, sa);
--- ./target-mips/exec.h_orig 2006-04-21 20:03:32.000000000 +0200
+++ ./target-mips/exec.h 2006-04-21 20:06:44.000000000 +0200
@@ -58,6 +58,20 @@ void do_madd (void);
void do_maddu (void);
void do_msub (void);
void do_msubu (void);
+void do_muls (void);
+void do_mulsu (void);
+void do_macc (void);
+void do_macchi (void);
+void do_maccu (void);
+void do_macchiu (void);
+void do_msac (void);
+void do_msachi (void);
+void do_msacu (void);
+void do_msachiu (void);
+void do_mulhi (void);
+void do_mulhiu (void);
+void do_mulshi (void);
+void do_mulshiu (void);
#endif
void do_mfc0(int reg, int sel);
void do_mtc0(int reg, int sel);
^ permalink raw reply [flat|nested] 2+ messages in thread
* [Qemu-devel] [PATCH] Add special MIPS multiply instructions
@ 2006-07-22 6:04 Dirk Behme
0 siblings, 0 replies; 2+ messages in thread
From: Dirk Behme @ 2006-07-22 6:04 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 349 bytes --]
This is an update of MIPS NEC VR5400 special instruction
patch [1]. It is necessary because of MIPS instruction set
configuration patch. Therefore this patch has to be applied
on top of
http://lists.gnu.org/archive/html/qemu-devel/2006-07/msg00158.html
Best regards
Dirk
[1]
http://lists.gnu.org/archive/html/qemu-devel/2006-04/msg00375.html
[-- Attachment #2: qemu-mips-r5400-patch.txt --]
[-- Type: text/plain, Size: 12033 bytes --]
--- ./target-mips/op_helper.c_orig 2006-07-22 07:32:51.000000000 +0200
+++ ./target-mips/op_helper.c 2006-07-22 08:01:16.000000000 +0200
@@ -128,6 +128,134 @@ void do_msubu (void)
tmp = ((uint64_t)T0 * (uint64_t)T1);
set_HILO(get_HILO() - tmp);
}
+
+#ifdef MIPS_USES_NEC_VR5400
+void do_muls (void)
+{
+ int64_t tmp;
+
+ tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_mulsu (void)
+{
+ uint64_t tmp;
+
+ tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_macc (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_macchi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_maccu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_macchiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_msac (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_msachi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_msacu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_msachiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_mulhi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_mulhiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_mulshi (void)
+{
+ int64_t tmp;
+
+ tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+
+void do_mulshiu (void)
+{
+ uint64_t tmp;
+
+ tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+}
+#endif /* MIPS_USES_NEC_VR5400 */
#endif
#if defined(CONFIG_USER_ONLY)
@@ -159,6 +287,149 @@ void do_tlbr (void)
{
cpu_abort(env, "tlbr\n");
}
+
+#ifdef MIPS_USES_NEC_VR5400
+void op_muls (void)
+{
+ int64_t tmp;
+
+ tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_mulsu (void)
+{
+ uint64_t tmp;
+
+ tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_macc (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_macchi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_maccu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_macchiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_msac (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_msachi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_msacu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_msachiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulhi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulhiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulshi (void)
+{
+ int64_t tmp;
+
+ tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulshiu (void)
+{
+ uint64_t tmp;
+
+ tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+#endif /* MIPS_USES_NEC_VR5400 */
+
#else
/* CP0 helpers */
--- ./target-mips/op.c_orig 2006-07-22 07:32:51.000000000 +0200
+++ ./target-mips/op.c 2006-07-22 08:00:37.000000000 +0200
@@ -549,6 +549,148 @@ void op_msubu (void)
set_HILO(get_HILO() - tmp);
RETURN();
}
+
+#ifdef MIPS_USES_NEC_VR5400
+void op_muls (void)
+{
+ int64_t tmp;
+
+ tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_mulsu (void)
+{
+ uint64_t tmp;
+
+ tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_macc (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_macchi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_maccu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_macchiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_msac (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_msachi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_msacu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp & 0xFFFFFFFF;
+ RETURN();
+}
+
+void op_msachiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulhi (void)
+{
+ int64_t tmp;
+
+ tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulhiu (void)
+{
+ uint64_t tmp;
+
+ tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulshi (void)
+{
+ int64_t tmp;
+
+ tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+
+void op_mulshiu (void)
+{
+ uint64_t tmp;
+
+ tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+ set_HILO(tmp);
+ T0 = tmp >> 32;
+ RETURN();
+}
+#endif /* MIPS_USES_NEC_VR5400 */
#else
void op_mult (void)
{
@@ -585,6 +727,91 @@ void op_msubu (void)
CALL_FROM_TB0(do_msubu);
RETURN();
}
+
+#ifdef MIPS_USES_NEC_VR5400
+void op_muls (void)
+{
+ CALL_FROM_TB0(do_muls);
+ RETURN();
+}
+
+void op_mulsu (void)
+{
+ CALL_FROM_TB0(do_mulsu);
+ RETURN();
+}
+
+void op_macc (void)
+{
+ CALL_FROM_TB0(do_macc);
+ RETURN();
+}
+
+void op_macchi (void)
+{
+ CALL_FROM_TB0(do_macchi);
+ RETURN();
+}
+
+void op_maccu (void)
+{
+ CALL_FROM_TB0(do_maccu);
+ RETURN();
+}
+void op_macchiu (void)
+{
+ CALL_FROM_TB0(do_macchiu);
+ RETURN();
+}
+
+void op_msac (void)
+{
+ CALL_FROM_TB0(do_msac);
+ RETURN();
+}
+
+void op_msachi (void)
+{
+ CALL_FROM_TB0(do_msachi);
+ RETURN();
+}
+
+void op_msacu (void)
+{
+ CALL_FROM_TB0(do_msacu);
+ RETURN();
+}
+
+void op_msachiu (void)
+{
+ CALL_FROM_TB0(do_msachiu);
+ RETURN();
+}
+
+void op_mulhi (void)
+{
+ CALL_FROM_TB0(do_mulhi);
+ RETURN();
+}
+
+void op_mulhiu (void)
+{
+ CALL_FROM_TB0(do_mulhiu);
+ RETURN();
+}
+
+void op_mulshi (void)
+{
+ CALL_FROM_TB0(do_mulshi);
+ RETURN();
+}
+
+void op_mulshiu (void)
+{
+ CALL_FROM_TB0(do_mulshiu);
+ RETURN();
+}
+#endif /* MIPS_USES_NEC_VR5400 */
#endif
/* Conditional moves */
--- ./target-mips/translate.c_orig 2006-07-22 07:32:51.000000000 +0200
+++ ./target-mips/translate.c 2006-07-22 08:01:44.000000000 +0200
@@ -984,6 +984,81 @@ static void gen_muldiv (DisasContext *ct
MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
}
+#ifdef MIPS_USES_NEC_VR5400
+static void gen_muldiv_ext (DisasContext *ctx, uint16_t opc,
+ int rd, int rs, int rt)
+{
+ const unsigned char *opn = "unk";
+
+ GEN_LOAD_REG_TN(T0, rs);
+ GEN_LOAD_REG_TN(T1, rt);
+ switch (opc) {
+ case 0x0d8:
+ gen_op_muls();
+ opn = "muls";
+ break;
+ case 0x0d9:
+ gen_op_mulsu();
+ opn = "mulsu";
+ break;
+ case 0x158:
+ gen_op_macc();
+ opn = "macc";
+ break;
+ case 0x159:
+ gen_op_maccu();
+ opn = "maccu";
+ break;
+ case 0x1d8:
+ gen_op_msac();
+ opn = "msac";
+ break;
+ case 0x1d9:
+ gen_op_msacu();
+ opn = "msacu";
+ break;
+ case 0x258:
+ gen_op_mulhi();
+ opn = "mulhi";
+ break;
+ case 0x259:
+ gen_op_mulhiu();
+ opn = "mulhiu";
+ break;
+ case 0x2d8:
+ gen_op_mulshi();
+ opn = "mulshi";
+ break;
+ case 0x2d9:
+ gen_op_mulshiu();
+ opn = "mulshiu";
+ break;
+ case 0x358:
+ gen_op_macchi();
+ opn = "macchi";
+ break;
+ case 0x359:
+ gen_op_macchiu();
+ opn = "macchiu";
+ break;
+ case 0x3d8:
+ gen_op_msachi();
+ opn = "msachi";
+ break;
+ case 0x3d9:
+ gen_op_msachiu();
+ opn = "msachiu";
+ break;
+ default:
+ MIPS_INVAL("mul/div ext");
+ generate_exception(ctx, EXCP_RI);
+ return;
+ }
+ GEN_STORE_TN_REG(rd, T0);
+ MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
+}
+#endif /* MIPS_USES_NEC_VR5400 */
+
static void gen_cl (DisasContext *ctx, uint16_t opc,
int rd, int rs)
{
@@ -1932,7 +2007,7 @@ static void decode_opc (CPUState *env, D
} else {
if(mips_uses_nec_vr5400()) {
op1 = ctx->opcode & 0x7FF;
- /* tbd: call handler for special NEC instructions */
+ gen_muldiv_ext(ctx, op1, rd, rs, rt);
} else {
MIPS_INVAL("NEC extension");
generate_exception(ctx, EXCP_RI);
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-07-22 6:04 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-21 18:30 [Qemu-devel] [PATCH] Add special MIPS multiply instructions Dirk Behme
-- strict thread matches above, loose matches on Subject: below --
2006-07-22 6:04 Dirk Behme
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).