From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1G4AbH-0000Mt-HP for qemu-devel@nongnu.org; Sat, 22 Jul 2006 02:04:31 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1G4AbG-0000Mh-I8 for qemu-devel@nongnu.org; Sat, 22 Jul 2006 02:04:31 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1G4AbF-0000MZ-Sk for qemu-devel@nongnu.org; Sat, 22 Jul 2006 02:04:29 -0400 Received: from [64.233.182.191] (helo=nf-out-0910.google.com) by monty-python.gnu.org with esmtp (Exim 4.52) id 1G4Abp-0007vL-2s for qemu-devel@nongnu.org; Sat, 22 Jul 2006 02:05:05 -0400 Received: by nf-out-0910.google.com with SMTP id m19so997312nfc for ; Fri, 21 Jul 2006 23:04:28 -0700 (PDT) Message-ID: <44C1BFFE.70800@gmail.com> Date: Sat, 22 Jul 2006 08:04:46 +0200 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------090409010707020909040401" From: Dirk Behme Subject: [Qemu-devel] [PATCH] Add special MIPS multiply instructions Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------090409010707020909040401 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 --------------090409010707020909040401 Content-Type: text/plain; name="qemu-mips-r5400-patch.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="qemu-mips-r5400-patch.txt" --- ./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); --------------090409010707020909040401--