From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:60775) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Scmd6-0007W7-MQ for qemu-devel@nongnu.org; Thu, 07 Jun 2012 20:00:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Scmd3-0001mo-T7 for qemu-devel@nongnu.org; Thu, 07 Jun 2012 20:00:40 -0400 Received: from mail-lpp01m010-f45.google.com ([209.85.215.45]:62117) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Scmd3-0001mb-DU for qemu-devel@nongnu.org; Thu, 07 Jun 2012 20:00:37 -0400 Received: by lahc1 with SMTP id c1so952595lah.4 for ; Thu, 07 Jun 2012 17:00:34 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: References: <1338985632-29597-1-git-send-email-proljc@gmail.com> <1338985632-29597-9-git-send-email-proljc@gmail.com> Date: Fri, 8 Jun 2012 08:00:34 +0800 Message-ID: From: Jia Liu Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v3 08/16] target-or32: Add translation routines List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Max Filippov Cc: qemu-devel@nongnu.org Hi Max, Thank you for your unaided eye look :-) I've fixed them, and, I think, it will be good if you check them before I make V4 pacthes. So, please, use your unaided eye again. On Thu, Jun 7, 2012 at 12:40 AM, Max Filippov wrote: > Hi Jia, > > more comments on remaining issues visible with unaided eye. > > On Wed, Jun 6, 2012 at 4:27 PM, Jia Liu wrote: >> Add OpenRISC translation routines. >> >> Signed-off-by: Jia Liu >> --- > > [...] > >> + =A0 =A0case 0x0009: >> + =A0 =A0 =A0 =A0switch (op1) { >> + =A0 =A0 =A0 =A0case 0x03: =A0 /*l.div*/ >> + =A0 =A0 =A0 =A0 =A0 =A0LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb); >> + =A0 =A0 =A0 =A0 =A0 =A0{ >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0TCGv_i32 sr_ove; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int lab =3D gen_new_label(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0sr_ove =3D tcg_temp_new(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE)= ; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (rb =3D=3D 0) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_brcondi_tl(TCG_COND_NE,= sr_ove, SR_OVE, lab); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_exception(dc, EXCP_RANGE); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_set_label(lab); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ra =3D=3D 0xffffffff && rb = =3D=3D 0x80000000) { > > Cannot do that: ra and rb are register numbers, not the values > contained in these registers. > Hence you need to generate code that will check these combinations of > register values. > case 0x03: /*l.div*/ LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb); { int lab0 =3D gen_new_label(); int lab1 =3D gen_new_label(); int lab2 =3D gen_new_label(); TCGv_i32 sr_ove =3D tcg_temp_new_i32(); tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); if (rb =3D=3D 0) { tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV); tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY); tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0); gen_exception(dc, EXCP_RANGE); gen_set_label(lab0); } else { tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[rb], 0x00000000, lab1); tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[ra], 0xffffffff, lab2); tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], 0x80000000, lab2); gen_set_label(lab1); tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV); tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY); tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab2); gen_exception(dc, EXCP_RANGE); gen_set_label(lab2); tcg_gen_div_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); } tcg_temp_free_i32(sr_ove); } break; is this right? >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_brcondi_tl(TCG_= COND_NE, sr_ove, SR_OVE, lab); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_exception(dc, EXCP_= RANGE); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_set_label(lab); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_div_tl(cpu_R[rd= ], cpu_R[ra], cpu_R[rb]); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(sr_ove); >> + =A0 =A0 =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0 =A0 =A0break; >> + >> + =A0 =A0 =A0 =A0default: >> + =A0 =A0 =A0 =A0 =A0 =A0gen_illegal_exception(dc); >> + =A0 =A0 =A0 =A0 =A0 =A0break; >> + =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0break; >> + >> + =A0 =A0case 0x000a: >> + =A0 =A0 =A0 =A0switch (op1) { >> + =A0 =A0 =A0 =A0case 0x03: =A0 /*l.divu*/ >> + =A0 =A0 =A0 =A0 =A0 =A0LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb); >> + =A0 =A0 =A0 =A0 =A0 =A0if (rb =3D=3D 0) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0TCGv_i32 sr_ove; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int lab =3D gen_new_label(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0sr_ove =3D tcg_temp_new(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE)= ; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove,= SR_OVE, lab); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_exception(dc, EXCP_RANGE); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_set_label(lab); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(sr_ove); >> + =A0 =A0 =A0 =A0 =A0 =A0} else if (rb !=3D 0) { > > 'if (rb !=3D 0)' and the following 'else' block are redundant here. > > I feel that I repeatedly fail to explain what's wrong with these div/divu > implementations; could you please add testcases for l.div and l.divu > that divide by the register other than r0 that contains 0 value? > and case 0x03: /*l.divu*/ LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb); { int lab0 =3D gen_new_label(); int lab1 =3D gen_new_label(); TCGv_i32 sr_ove =3D tcg_temp_new(); tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); if (rb =3D=3D 0) { tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV); tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY); tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab0); gen_exception(dc, EXCP_RANGE); gen_set_label(lab0); } else { tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[rb], 0x00000000, lab1); tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV); tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY); tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab1); gen_exception(dc, EXCP_RANGE); gen_set_label(lab1); tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); } tcg_temp_free_i32(sr_ove); } break; is this OK? >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_divu_tl(cpu_R[rd], cpu_R[ra], c= pu_R[rb]); >> + =A0 =A0 =A0 =A0 =A0 =A0} else { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break; >> + =A0 =A0 =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0 =A0 =A0break; >> + >> + =A0 =A0 =A0 =A0default: >> + =A0 =A0 =A0 =A0 =A0 =A0gen_illegal_exception(dc); >> + =A0 =A0 =A0 =A0 =A0 =A0break; >> + =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0break; >> + >> + =A0 =A0case 0x000b: >> + =A0 =A0 =A0 =A0switch (op1) { >> + =A0 =A0 =A0 =A0case 0x03: =A0 /*l.mulu*/ >> + =A0 =A0 =A0 =A0 =A0 =A0LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb); >> + =A0 =A0 =A0 =A0 =A0 =A0if (rb !=3D 0 && ra !=3D 0) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0TCGv result =3D tcg_temp_new(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0TCGv high =3D tcg_temp_new(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0TCGv tra =3D tcg_temp_new(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0TCGv trb =3D tcg_temp_new(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0TCGv_i32 sr_ove =3D tcg_temp_new(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int lab =3D gen_new_label(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int lab2 =3D gen_new_label(); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_extu_i32_i64(tra, cpu_R[ra]); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_extu_i32_i64(trb, cpu_R[rb]); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_mul_tl(result, cpu_R[ra], cpu_R= [rb]); > > You've calculated tra and trb but haven't uses them here. > >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_shri_tl(high, result, (sizeof(t= arget_ulong) * 8)); > > You probably meant result and high to be _i64. > >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_brcondi_tl(TCG_COND_EQ, high, 0= x0, lab); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE)= ; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove,= SR_OVE, lab2); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_exception(dc, EXCP_RANGE); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_set_label(lab); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_set_label(lab2); > > No need to set two labels at one point. > case 0x03: /*l.mulu*/ LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb); if (rb !=3D 0 && ra !=3D 0) { TCGv_i64 result =3D tcg_temp_new_i64(); TCGv_i64 tra =3D tcg_temp_new_i64(); TCGv_i64 trb =3D tcg_temp_new_i64(); TCGv high =3D tcg_temp_new(); TCGv_i32 sr_ove =3D tcg_temp_new(); int lab =3D gen_new_label(); tcg_gen_extu_i32_i64(tra, cpu_R[ra]); tcg_gen_extu_i32_i64(trb, cpu_R[rb]); tcg_gen_mul_i64(result, tra, trb); tcg_temp_free(tra); tcg_temp_free(trb); tcg_gen_shri_i64(high, result, (sizeof(target_ulong) * 8)); tcg_gen_brcondi_tl(TCG_COND_EQ, high, 0x00000000, lab); tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_CY); tcg_gen_ori_tl(cpu_sr, cpu_sr, SR_OV); tcg_gen_andi_tl(sr_ove, cpu_sr, SR_OVE); tcg_gen_brcondi_tl(TCG_COND_NE, sr_ove, SR_OVE, lab); gen_exception(dc, EXCP_RANGE); gen_set_label(lab); tcg_temp_free(high); tcg_gen_trunc_i64_tl(cpu_R[rd], result); tcg_temp_free(result); tcg_temp_free(sr_ove); } else { tcg_gen_movi_tl(cpu_R[rd], 0); } break; is it right this time? >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_trunc_i64_tl(cpu_R[rd], result)= ; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(result); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(high); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(sr_ove); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(tra); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(trb); >> + =A0 =A0 =A0 =A0 =A0 =A0} else { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_movi_tl(cpu_R[rd], 0); >> + =A0 =A0 =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0 =A0 =A0break; >> + >> + =A0 =A0 =A0 =A0default: >> + =A0 =A0 =A0 =A0 =A0 =A0gen_illegal_exception(dc); >> + =A0 =A0 =A0 =A0 =A0 =A0break; >> + =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0break; >> + > > [...] > >> + =A0 =A0case 0x13: =A0 =A0/*l.maci*/ >> + =A0 =A0 =A0 =A0LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11); >> + =A0 =A0 =A0 =A0{ >> + =A0 =A0 =A0 =A0 =A0 =A0TCGv t1 =3D tcg_temp_new(); >> + =A0 =A0 =A0 =A0 =A0 =A0TCGv t2 =3D tcg_temp_new(); >> + =A0 =A0 =A0 =A0 =A0 =A0TCGv ttmp =3D tcg_temp_new(); =A0 /* =A0store m= achi maclo*/ >> + =A0 =A0 =A0 =A0 =A0 =A0ttmp =3D tcg_const_tl(tmp); > > Leaked previous ttmp temporary. > >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_mul_tl(t0, cpu_R[ra], ttmp); > > What t0? > >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_ext_i32_i64(t1, t0); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_concat_i32_i64(t2, maclo, machi); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_add_i64(t2, t2, t1); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_trunc_i64_i32(maclo, t2); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_shri_i64(t2, t2, 32); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_trunc_i64_i32(machi, t2); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(t0); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(t1); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(t2); > > Leaked ttmp temporary. case 0x13: /*l.maci*/ LOG_DIS("l.maci %d, r%d, %d\n", I5, ra, I11); { TCGv t1 =3D tcg_temp_new(); TCGv t2 =3D tcg_temp_new(); TCGv ttmp =3D tcg_const_tl(tmp); /* store machi maclo*/ tcg_gen_mul_tl(ttmp, cpu_R[ra], ttmp); tcg_gen_ext_i32_i64(t1, ttmp); tcg_gen_concat_i32_i64(t2, maclo, machi); tcg_gen_add_i64(t2, t2, t1); tcg_gen_trunc_i64_i32(maclo, t2); tcg_gen_shri_i64(t2, t2, 32); tcg_gen_trunc_i64_i32(machi, t2); tcg_temp_free(ttmp); tcg_temp_free(t1); tcg_temp_free(t2); } break; > >> + =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0break; > > [...] > >> + =A0 =A0case 0x20: =A0 /*l.ld*/ >> + =A0 =A0 =A0 =A0LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16); >> + =A0 =A0 =A0 =A0tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16)); >> + =A0 =A0 =A0 =A0tcg_gen_qemu_ld64(cpu_R[rd], t0, dc->mem_idx); > > Cannot ld64 into _tl register. > case 0x20: /*l.ld*/ LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16); { check_ob64s(dc); TCGv_i64 t0 =3D tcg_temp_new_i64(); tcg_gen_addi_i64(t0, cpu_R[ra], sign_extend(I16, 16)); tcg_gen_qemu_ld64(cpu_R[rd], t0, dc->mem_idx); tcg_temp_free_i64(t0); } break; > [...] > >> + =A0 =A0case 0x34: =A0 /*l.sd*/ >> + =A0 =A0 =A0 =A0LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11); >> + =A0 =A0 =A0 =A0tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16)); >> + =A0 =A0 =A0 =A0tcg_gen_qemu_st64(cpu_R[rb], t0, dc->mem_idx); > > Ditto. > > [...] > >> +static void dec_mac(DisasContext *dc, CPUOpenRISCState *env, uint32_t i= nsn) >> +{ >> + =A0 =A0uint32_t op0; >> + =A0 =A0uint32_t ra, rb; >> + =A0 =A0op0 =3D field(insn, 0, 4); >> + =A0 =A0ra =3D field(insn, 16, 5); >> + =A0 =A0rb =3D field(insn, 11, 5); >> + =A0 =A0TCGv_i64 t0 =3D tcg_temp_new(); >> + =A0 =A0TCGv_i64 t1 =3D tcg_temp_new(); >> + =A0 =A0TCGv_i64 t2 =3D tcg_temp_new(); >> + =A0 =A0switch (op0) { >> + =A0 =A0case 0x0001: =A0 /*l.mac*/ >> + =A0 =A0 =A0 =A0LOG_DIS("l.mac r%d, r%d\n", ra, rb); >> + =A0 =A0 =A0 =A0{ >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_ext_i32_i64(t1, t0); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_concat_i32_i64(t2, maclo, machi); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_add_i64(t2, t2, t1); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_trunc_i64_i32(maclo, t2); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_shri_i64(t2, t2, 32); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_trunc_i64_i32(machi, t2); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(t0); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(t1); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(t2); > > Instead of freeing temporaries repeatedly in some cases (and > leaking them in others) you could free them once after the switch. > case 0x0001: /*l.mac*/ LOG_DIS("l.mac r%d, r%d\n", ra, rb); { TCGv_i64 t0 =3D tcg_temp_new(); TCGv_i64 t1 =3D tcg_temp_new(); TCGv_i64 t2 =3D tcg_temp_new(); tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]); tcg_gen_ext_i32_i64(t1, t0); tcg_gen_concat_i32_i64(t2, maclo, machi); tcg_gen_add_i64(t2, t2, t1); tcg_gen_trunc_i64_i32(maclo, t2); tcg_gen_shri_i64(t2, t2, 32); tcg_gen_trunc_i64_i32(machi, t2); tcg_temp_free(t0); tcg_temp_free(t1); tcg_temp_free(t2); } break; I think define use and free them separately make code more clear :-) >> + =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0break; >> + >> + =A0 =A0case 0x0002: =A0 /*l.msb*/ >> + =A0 =A0 =A0 =A0LOG_DIS("l.msb r%d, r%d\n", ra, rb); >> + =A0 =A0 =A0 =A0{ >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_ext_i32_i64(t1, t0); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_concat_i32_i64(t2, maclo, machi); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_sub_i64(t2, t2, t1); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_trunc_i64_i32(maclo, t2); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_shri_i64(t2, t2, 32); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_trunc_i64_i32(machi, t2); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(t0); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(t1); >> + =A0 =A0 =A0 =A0 =A0 =A0tcg_temp_free(t2); >> + =A0 =A0 =A0 =A0} >> + =A0 =A0 =A0 =A0break; >> + >> + =A0 =A0default: >> + =A0 =A0 =A0 =A0gen_illegal_exception(dc); >> + =A0 =A0 =A0 =A0break; >> + =A0 } >> +} > > -- > Thanks. > -- Max Thank you very much, nice man. Jia.