From nobody Fri May 3 04:33:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.221.53 as permitted sender) client-ip=209.85.221.53; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-f53.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.53 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1623952155; cv=none; d=zohomail.com; s=zohoarc; b=GQmUpBY7lqXCPC+hwjWDi30ewrIzcio9nYmyR8V4FB8VTN8t7m7lM0qEMdecZXe3wayN1io3pekJWITutkPGRNE1AWYQr1S7e2iLmMu9V5cFYrcbHHu0EkUul/RQ5RJZgO0mVdXGVddzK95URIU/cLKbZqgdAikUjIeNkenSRIQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1623952155; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=9xW3U7g7xe/I6XaUOpOGPcO2/ZapWcqv9gLbJJFxqrU=; b=RgWMiPeL7BDcs4B+gWHubhSRjOYLfebu1/lATqh2gbOB3lA/hfRgFXM5qttrT95P3RUZJpzn9TT5t8zYqnQQfp5gTPDrtgSi3FMIUMsir2grx2GyKU9AqF1OOOkgbJ+D5zgaQ+33A5q7zhsJBG2LLkOWwo5SnVrKT/d17DGBW7c= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.53 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) by mx.zohomail.com with SMTPS id 162395215577346.19320886495177; Thu, 17 Jun 2021 10:49:15 -0700 (PDT) Received: by mail-wr1-f53.google.com with SMTP id c9so7733039wrt.5 for ; Thu, 17 Jun 2021 10:49:15 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.. (93.red-83-35-24.dynamicip.rima-tde.net. [83.35.24.93]) by smtp.gmail.com with ESMTPSA id z6sm3266944wrl.15.2021.06.17.10.49.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Jun 2021 10:49:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9xW3U7g7xe/I6XaUOpOGPcO2/ZapWcqv9gLbJJFxqrU=; b=ZVBndOVawyGC+BkA/yY/W7i2azPgbz+0DtIsDu0cPjqpjX2tG3jePVamSjioIEzd+U cNi/a4jEoLk0RKbuRO+VUNo36Xz88HUAp92rNHqHalBDLX2PLmWgNuuVsuyQhnH8jYz9 cVdtq7A9dKDXj+6X2z3TVd9rk8YwEY2QOR0O8/ZZMA2tikTz4jRDfhULLF2m6x6uUdnW 50rNnFWPRLJRjMAzpBM8rmyuaJ+VcoxxMfShDWYCcfJTO/UOAw3zU2SPzvB/unVBmFdC QG/vwNW2PGITS0GJOjg7ptNeV5Is/tihpUjxj62wtanZeqcS26RzeFe9kaAvoswCe+da l0ZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=9xW3U7g7xe/I6XaUOpOGPcO2/ZapWcqv9gLbJJFxqrU=; b=gYWEo9h5KLhKU27qD8IpCMX+FoQXtSzfwYw9T3O2tKicqYTCl4aMj2/QS4mnI2L3Um xdSaOPYKwvy5n7WLeC7LUZ3z0dStI7D4nxeFG3PsmkTYPLACbMQ+rbltKE+vAUrYvQm4 37ejk/JO2sNalxQSHd3gpVAP1iLW/NkRylmhZ2HTt8nD5MoULbtqvIx+2XBHgd7XXF9M e8wLg+yDEBDwsWAeNzL3Kuyxs6E5+86aeJGUCHzG0O2HYTFuIXGwu9/ZCffI+Hcs8t5R n+ur+PLIHPY3b+3dJbn2585lC1fjYc7wl4HkCqRIFK7r5MbujI5t5pMNd0u5dkPFXv9h SxVQ== X-Gm-Message-State: AOAM530NXRkehDdcIKldFK8AGQIhdR52XFx/7rn1bd5EjwIKbFbqlw2D MPPf98SJvLIGu8gXH0D4sbA= X-Google-Smtp-Source: ABdhPJyk4cNILlcD3//gDjTsuwlTQT7K+u3v0B6bkOwmUoVG5gFALdfzF84l1P40rmem6Ezq3qAGzQ== X-Received: by 2002:adf:c3d4:: with SMTP id d20mr7216605wrg.183.1623952153988; Thu, 17 Jun 2021 10:49:13 -0700 (PDT) Sender: =?UTF-8?Q?Philippe_Mathieu=2DDaud=C3=A9?= From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Aurelien Jarno , Aleksandar Rikalo , Richard Henderson , Jiaxun Yang Subject: [PATCH 1/4] target/mips: Add declarations for generic TCG helpers Date: Thu, 17 Jun 2021 19:49:04 +0200 Message-Id: <20210617174907.2904067-2-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210617174907.2904067-1-f4bug@amsat.org> References: <20210617174907.2904067-1-f4bug@amsat.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @gmail.com) To be able to extract the microMIPS ISA and Code Compaction ASE translation routines to different source files, declare few TCG helpers which are also used by translate.c in "translate.h". Signed-off-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Richard Henderson --- target/mips/tcg/translate.h | 5 +++++ target/mips/tcg/translate.c | 9 ++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h index 61442590340..c25fad597d5 100644 --- a/target/mips/tcg/translate.h +++ b/target/mips/tcg/translate.h @@ -146,6 +146,11 @@ void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, in= t reg); void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg); int get_fp_bit(int cc); =20 +void gen_ldxs(DisasContext *ctx, int base, int index, int rd); +void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int = bp); +void gen_addiupc(DisasContext *ctx, int rx, int imm, + int is_64_bit, int extended); + /* * Address Computation and Large Constant Instructions */ diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 255f97fe9c1..c0ae180969e 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -5630,8 +5630,7 @@ static void gen_align_bits(DisasContext *ctx, int wor= dsz, int rd, int rs, tcg_temp_free(t0); } =20 -static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int r= t, - int bp) +void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int = bp) { gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8); } @@ -12779,8 +12778,8 @@ static void gen_mips16_restore(DisasContext *ctx, tcg_temp_free(t2); } =20 -static void gen_addiupc(DisasContext *ctx, int rx, int imm, - int is_64_bit, int extended) +void gen_addiupc(DisasContext *ctx, int rx, int imm, + int is_64_bit, int extended) { TCGv t0; =20 @@ -14511,7 +14510,7 @@ static void gen_pool16c_r6_insn(DisasContext *ctx) } } =20 -static void gen_ldxs(DisasContext *ctx, int base, int index, int rd) +void gen_ldxs(DisasContext *ctx, int base, int index, int rd) { TCGv t0 =3D tcg_temp_new(); TCGv t1 =3D tcg_temp_new(); --=20 2.31.1 From nobody Fri May 3 04:33:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.221.51 as permitted sender) client-ip=209.85.221.51; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-f51.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.51 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1623952161; cv=none; d=zohomail.com; s=zohoarc; b=L73cDXSfkqsHVngQv3OazjxNCRA90ZfqBLpCuvVfLi0kajFmmfh/mrdZ2UBZeotsjM4+rkz8M0rM4tNZcYTAjdjYRsu/vphjl/+B5GN9yCOZP9tNnKHzDeIB+pIFedRmgZ2/MR3110xD04ugDZx0jpqxBsBWF9vR4fotSAy1Yjw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1623952161; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=SdZmiDP8AujpV4PF0iU9y/FjXomWE/8B5JNSWzy2QHw=; b=LgednBVb2uyQcn+Dh8aUG+Gz2JX4HFdlP3uPj9Pcj569yJZ3lizd625hIWYnlD0iKn8yAF/KjOPQJcqigxDBDHoBYfM/Q6yYQqplpReST/0X3+cAO/PoxA6cF4BQUwLTv6dfHEiOrx5NgEKJzZgMUiyMRGB1VtpUsDP6dd/SCeI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.51 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) by mx.zohomail.com with SMTPS id 1623952161133328.8077810195151; Thu, 17 Jun 2021 10:49:21 -0700 (PDT) Received: by mail-wr1-f51.google.com with SMTP id f2so7696891wri.11 for ; Thu, 17 Jun 2021 10:49:20 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.. (93.red-83-35-24.dynamicip.rima-tde.net. [83.35.24.93]) by smtp.gmail.com with ESMTPSA id f13sm8054817wmg.7.2021.06.17.10.49.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Jun 2021 10:49:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=SdZmiDP8AujpV4PF0iU9y/FjXomWE/8B5JNSWzy2QHw=; b=ByI/HZJPdb/b8eTXtcnSSqcP0gLJcpXXudFVTENzX42jQmFV4EJLZu3CEwvhKgWnVJ cgbTEVtQFo0VVqSdHumtjhfuoSCj4LY5AgLUKI/XB6KWD2T8Ql9ue6FkM2eZsKjtBJej oXZR6JpWsR3fubYleylaMckffQELcLoV0H/wcrcsx74z8V6JdL4MEI+pUyhJE8MrbtZY ubkzZhLLxg5q7TPMcp2emv0VLWhYZMk1atucSBC92Q0wYACeWIcOMK8Ih1BwqDGHgCpm d6d0dp+Ihdi3qeCa+VA+2jKhOPFtheK7sr7PPmN3qPI7Q4arI3WC5mGH0oQi9Tm3gmfX yJBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=SdZmiDP8AujpV4PF0iU9y/FjXomWE/8B5JNSWzy2QHw=; b=lS4inFcccy9HexfbnbAS5EGlJmeuLsMKuFkQS4CsznfP5nFuyNJonDLDMPx1IYvsP7 RCrDBytkewye0WfuN6NX4CqMPG2uAvOr1epFROrkzZ/LoBEh0Jdv9s33DYcWQBb/eE6m p5UdUqevS3w8pO+5+hZy4UACIoH6l0J4Bd0vTQ6BQK5B4l/5U7TzQkeLgEyZgsDoWJk+ ifGZqfPgCXbS8VzrV0Oo63PM64IvCPj/IB2ATXPXRI0DnGtqULDnZpUnD3CPtRNiyIfp jjXeOdTnTCo6MHX+o46+tWQIt/bh/STnbqwjvkfJwCdf80DSL3aczcLRYyuFM+R0r9hj aJ/Q== X-Gm-Message-State: AOAM532RBGP/sP9Ck+UmGZfWA38lpoadalvjxEyIz1gjuA1viVTBt7Pl C2EBqDe8c2Wo4IfC91ypI+I= X-Google-Smtp-Source: ABdhPJxx+4YIO64zPxD/QGnwdSaK/jxNtRGdhm4ryO8n4i0SPM/P3sFz/HDUBhJu2A65nW4b3Umv+Q== X-Received: by 2002:a5d:4e4d:: with SMTP id r13mr7377789wrt.218.1623952158870; Thu, 17 Jun 2021 10:49:18 -0700 (PDT) Sender: =?UTF-8?Q?Philippe_Mathieu=2DDaud=C3=A9?= From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Aurelien Jarno , Aleksandar Rikalo , Richard Henderson , Jiaxun Yang Subject: [PATCH 2/4] target/mips: Extract Code Compaction ASE translation routines Date: Thu, 17 Jun 2021 19:49:05 +0200 Message-Id: <20210617174907.2904067-3-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210617174907.2904067-1-f4bug@amsat.org> References: <20210617174907.2904067-1-f4bug@amsat.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @gmail.com) Extract 1100+ lines from the huge translate.c to a new file, 'mips16e_translate.c.inc'. As there are too many inter- dependencies we don't compile it as another object, but keep including it in the big translate.o. We gain in code maintainability. Signed-off-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-10-f4bug@amsat.org> --- target/mips/tcg/translate.c | 1123 +---------------------- target/mips/tcg/mips16e_translate.c.inc | 1123 +++++++++++++++++++++++ 2 files changed, 1129 insertions(+), 1117 deletions(-) create mode 100644 target/mips/tcg/mips16e_translate.c.inc diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index c0ae180969e..c939ba09f2b 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -12393,391 +12393,6 @@ out: tcg_temp_free(t1); } =20 -/* ISA extensions (ASEs) */ -/* MIPS16 extension to MIPS32 */ - -/* MIPS16 major opcodes */ -enum { - M16_OPC_ADDIUSP =3D 0x00, - M16_OPC_ADDIUPC =3D 0x01, - M16_OPC_B =3D 0x02, - M16_OPC_JAL =3D 0x03, - M16_OPC_BEQZ =3D 0x04, - M16_OPC_BNEQZ =3D 0x05, - M16_OPC_SHIFT =3D 0x06, - M16_OPC_LD =3D 0x07, - M16_OPC_RRIA =3D 0x08, - M16_OPC_ADDIU8 =3D 0x09, - M16_OPC_SLTI =3D 0x0a, - M16_OPC_SLTIU =3D 0x0b, - M16_OPC_I8 =3D 0x0c, - M16_OPC_LI =3D 0x0d, - M16_OPC_CMPI =3D 0x0e, - M16_OPC_SD =3D 0x0f, - M16_OPC_LB =3D 0x10, - M16_OPC_LH =3D 0x11, - M16_OPC_LWSP =3D 0x12, - M16_OPC_LW =3D 0x13, - M16_OPC_LBU =3D 0x14, - M16_OPC_LHU =3D 0x15, - M16_OPC_LWPC =3D 0x16, - M16_OPC_LWU =3D 0x17, - M16_OPC_SB =3D 0x18, - M16_OPC_SH =3D 0x19, - M16_OPC_SWSP =3D 0x1a, - M16_OPC_SW =3D 0x1b, - M16_OPC_RRR =3D 0x1c, - M16_OPC_RR =3D 0x1d, - M16_OPC_EXTEND =3D 0x1e, - M16_OPC_I64 =3D 0x1f -}; - -/* I8 funct field */ -enum { - I8_BTEQZ =3D 0x0, - I8_BTNEZ =3D 0x1, - I8_SWRASP =3D 0x2, - I8_ADJSP =3D 0x3, - I8_SVRS =3D 0x4, - I8_MOV32R =3D 0x5, - I8_MOVR32 =3D 0x7 -}; - -/* RRR f field */ -enum { - RRR_DADDU =3D 0x0, - RRR_ADDU =3D 0x1, - RRR_DSUBU =3D 0x2, - RRR_SUBU =3D 0x3 -}; - -/* RR funct field */ -enum { - RR_JR =3D 0x00, - RR_SDBBP =3D 0x01, - RR_SLT =3D 0x02, - RR_SLTU =3D 0x03, - RR_SLLV =3D 0x04, - RR_BREAK =3D 0x05, - RR_SRLV =3D 0x06, - RR_SRAV =3D 0x07, - RR_DSRL =3D 0x08, - RR_CMP =3D 0x0a, - RR_NEG =3D 0x0b, - RR_AND =3D 0x0c, - RR_OR =3D 0x0d, - RR_XOR =3D 0x0e, - RR_NOT =3D 0x0f, - RR_MFHI =3D 0x10, - RR_CNVT =3D 0x11, - RR_MFLO =3D 0x12, - RR_DSRA =3D 0x13, - RR_DSLLV =3D 0x14, - RR_DSRLV =3D 0x16, - RR_DSRAV =3D 0x17, - RR_MULT =3D 0x18, - RR_MULTU =3D 0x19, - RR_DIV =3D 0x1a, - RR_DIVU =3D 0x1b, - RR_DMULT =3D 0x1c, - RR_DMULTU =3D 0x1d, - RR_DDIV =3D 0x1e, - RR_DDIVU =3D 0x1f -}; - -/* I64 funct field */ -enum { - I64_LDSP =3D 0x0, - I64_SDSP =3D 0x1, - I64_SDRASP =3D 0x2, - I64_DADJSP =3D 0x3, - I64_LDPC =3D 0x4, - I64_DADDIU5 =3D 0x5, - I64_DADDIUPC =3D 0x6, - I64_DADDIUSP =3D 0x7 -}; - -/* RR ry field for CNVT */ -enum { - RR_RY_CNVT_ZEB =3D 0x0, - RR_RY_CNVT_ZEH =3D 0x1, - RR_RY_CNVT_ZEW =3D 0x2, - RR_RY_CNVT_SEB =3D 0x4, - RR_RY_CNVT_SEH =3D 0x5, - RR_RY_CNVT_SEW =3D 0x6, -}; - -static int xlat(int r) -{ - static int map[] =3D { 16, 17, 2, 3, 4, 5, 6, 7 }; - - return map[r]; -} - -static void gen_mips16_save(DisasContext *ctx, - int xsregs, int aregs, - int do_ra, int do_s0, int do_s1, - int framesize) -{ - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - TCGv t2 =3D tcg_temp_new(); - int args, astatic; - - switch (aregs) { - case 0: - case 1: - case 2: - case 3: - case 11: - args =3D 0; - break; - case 4: - case 5: - case 6: - case 7: - args =3D 1; - break; - case 8: - case 9: - case 10: - args =3D 2; - break; - case 12: - case 13: - args =3D 3; - break; - case 14: - args =3D 4; - break; - default: - gen_reserved_instruction(ctx); - return; - } - - switch (args) { - case 4: - gen_base_offset_addr(ctx, t0, 29, 12); - gen_load_gpr(t1, 7); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - /* Fall through */ - case 3: - gen_base_offset_addr(ctx, t0, 29, 8); - gen_load_gpr(t1, 6); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - /* Fall through */ - case 2: - gen_base_offset_addr(ctx, t0, 29, 4); - gen_load_gpr(t1, 5); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - /* Fall through */ - case 1: - gen_base_offset_addr(ctx, t0, 29, 0); - gen_load_gpr(t1, 4); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - } - - gen_load_gpr(t0, 29); - -#define DECR_AND_STORE(reg) do { \ - tcg_gen_movi_tl(t2, -4); \ - gen_op_addr_add(ctx, t0, t0, t2); \ - gen_load_gpr(t1, reg); \ - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \ - } while (0) - - if (do_ra) { - DECR_AND_STORE(31); - } - - switch (xsregs) { - case 7: - DECR_AND_STORE(30); - /* Fall through */ - case 6: - DECR_AND_STORE(23); - /* Fall through */ - case 5: - DECR_AND_STORE(22); - /* Fall through */ - case 4: - DECR_AND_STORE(21); - /* Fall through */ - case 3: - DECR_AND_STORE(20); - /* Fall through */ - case 2: - DECR_AND_STORE(19); - /* Fall through */ - case 1: - DECR_AND_STORE(18); - } - - if (do_s1) { - DECR_AND_STORE(17); - } - if (do_s0) { - DECR_AND_STORE(16); - } - - switch (aregs) { - case 0: - case 4: - case 8: - case 12: - case 14: - astatic =3D 0; - break; - case 1: - case 5: - case 9: - case 13: - astatic =3D 1; - break; - case 2: - case 6: - case 10: - astatic =3D 2; - break; - case 3: - case 7: - astatic =3D 3; - break; - case 11: - astatic =3D 4; - break; - default: - gen_reserved_instruction(ctx); - return; - } - - if (astatic > 0) { - DECR_AND_STORE(7); - if (astatic > 1) { - DECR_AND_STORE(6); - if (astatic > 2) { - DECR_AND_STORE(5); - if (astatic > 3) { - DECR_AND_STORE(4); - } - } - } - } -#undef DECR_AND_STORE - - tcg_gen_movi_tl(t2, -framesize); - gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2); - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); -} - -static void gen_mips16_restore(DisasContext *ctx, - int xsregs, int aregs, - int do_ra, int do_s0, int do_s1, - int framesize) -{ - int astatic; - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - TCGv t2 =3D tcg_temp_new(); - - tcg_gen_movi_tl(t2, framesize); - gen_op_addr_add(ctx, t0, cpu_gpr[29], t2); - -#define DECR_AND_LOAD(reg) do { \ - tcg_gen_movi_tl(t2, -4); \ - gen_op_addr_add(ctx, t0, t0, t2); \ - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \ - gen_store_gpr(t1, reg); \ - } while (0) - - if (do_ra) { - DECR_AND_LOAD(31); - } - - switch (xsregs) { - case 7: - DECR_AND_LOAD(30); - /* Fall through */ - case 6: - DECR_AND_LOAD(23); - /* Fall through */ - case 5: - DECR_AND_LOAD(22); - /* Fall through */ - case 4: - DECR_AND_LOAD(21); - /* Fall through */ - case 3: - DECR_AND_LOAD(20); - /* Fall through */ - case 2: - DECR_AND_LOAD(19); - /* Fall through */ - case 1: - DECR_AND_LOAD(18); - } - - if (do_s1) { - DECR_AND_LOAD(17); - } - if (do_s0) { - DECR_AND_LOAD(16); - } - - switch (aregs) { - case 0: - case 4: - case 8: - case 12: - case 14: - astatic =3D 0; - break; - case 1: - case 5: - case 9: - case 13: - astatic =3D 1; - break; - case 2: - case 6: - case 10: - astatic =3D 2; - break; - case 3: - case 7: - astatic =3D 3; - break; - case 11: - astatic =3D 4; - break; - default: - gen_reserved_instruction(ctx); - return; - } - - if (astatic > 0) { - DECR_AND_LOAD(7); - if (astatic > 1) { - DECR_AND_LOAD(6); - if (astatic > 2) { - DECR_AND_LOAD(5); - if (astatic > 3) { - DECR_AND_LOAD(4); - } - } - } - } -#undef DECR_AND_LOAD - - tcg_gen_movi_tl(t2, framesize); - gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2); - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); -} - void gen_addiupc(DisasContext *ctx, int rx, int imm, int is_64_bit, int extended) { @@ -12810,267 +12425,6 @@ static void gen_cache_operation(DisasContext *ctx= , uint32_t op, int base, tcg_temp_free_i32(t0); } =20 -#if defined(TARGET_MIPS64) -static void decode_i64_mips16(DisasContext *ctx, - int ry, int funct, int16_t offset, - int extended) -{ - switch (funct) { - case I64_LDSP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset =3D extended ? offset : offset << 3; - gen_ld(ctx, OPC_LD, ry, 29, offset); - break; - case I64_SDSP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset =3D extended ? offset : offset << 3; - gen_st(ctx, OPC_SD, ry, 29, offset); - break; - case I64_SDRASP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset =3D extended ? offset : (ctx->opcode & 0xff) << 3; - gen_st(ctx, OPC_SD, 31, 29, offset); - break; - case I64_DADJSP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset =3D extended ? offset : ((int8_t)ctx->opcode) << 3; - gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset); - break; - case I64_LDPC: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) { - gen_reserved_instruction(ctx); - } else { - offset =3D extended ? offset : offset << 3; - gen_ld(ctx, OPC_LDPC, ry, 0, offset); - } - break; - case I64_DADDIU5: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset =3D extended ? offset : ((int8_t)(offset << 3)) >> 3; - gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset); - break; - case I64_DADDIUPC: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset =3D extended ? offset : offset << 2; - gen_addiupc(ctx, ry, offset, 1, extended); - break; - case I64_DADDIUSP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - offset =3D extended ? offset : offset << 2; - gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset); - break; - } -} -#endif - -static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx) -{ - int extend =3D translator_lduw(env, ctx->base.pc_next + 2); - int op, rx, ry, funct, sa; - int16_t imm, offset; - - ctx->opcode =3D (ctx->opcode << 16) | extend; - op =3D (ctx->opcode >> 11) & 0x1f; - sa =3D (ctx->opcode >> 22) & 0x1f; - funct =3D (ctx->opcode >> 8) & 0x7; - rx =3D xlat((ctx->opcode >> 8) & 0x7); - ry =3D xlat((ctx->opcode >> 5) & 0x7); - offset =3D imm =3D (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11 - | ((ctx->opcode >> 21) & 0x3f) << 5 - | (ctx->opcode & 0x1f)); - - /* - * The extended opcodes cleverly reuse the opcodes from their 16-bit - * counterparts. - */ - switch (op) { - case M16_OPC_ADDIUSP: - gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm); - break; - case M16_OPC_ADDIUPC: - gen_addiupc(ctx, rx, imm, 0, 1); - break; - case M16_OPC_B: - gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_BEQZ: - gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_BNEQZ: - gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_SHIFT: - switch (ctx->opcode & 0x3) { - case 0x0: - gen_shift_imm(ctx, OPC_SLL, rx, ry, sa); - break; - case 0x1: -#if defined(TARGET_MIPS64) - check_mips_64(ctx); - gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa); -#else - gen_reserved_instruction(ctx); -#endif - break; - case 0x2: - gen_shift_imm(ctx, OPC_SRL, rx, ry, sa); - break; - case 0x3: - gen_shift_imm(ctx, OPC_SRA, rx, ry, sa); - break; - } - break; -#if defined(TARGET_MIPS64) - case M16_OPC_LD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_ld(ctx, OPC_LD, ry, rx, offset); - break; -#endif - case M16_OPC_RRIA: - imm =3D ctx->opcode & 0xf; - imm =3D imm | ((ctx->opcode >> 20) & 0x7f) << 4; - imm =3D imm | ((ctx->opcode >> 16) & 0xf) << 11; - imm =3D (int16_t) (imm << 1) >> 1; - if ((ctx->opcode >> 4) & 0x1) { -#if defined(TARGET_MIPS64) - check_mips_64(ctx); - gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm); -#else - gen_reserved_instruction(ctx); -#endif - } else { - gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm); - } - break; - case M16_OPC_ADDIU8: - gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm); - break; - case M16_OPC_SLTI: - gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm); - break; - case M16_OPC_SLTIU: - gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm); - break; - case M16_OPC_I8: - switch (funct) { - case I8_BTEQZ: - gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0); - break; - case I8_BTNEZ: - gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0); - break; - case I8_SWRASP: - gen_st(ctx, OPC_SW, 31, 29, imm); - break; - case I8_ADJSP: - gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm); - break; - case I8_SVRS: - check_insn(ctx, ISA_MIPS_R1); - { - int xsregs =3D (ctx->opcode >> 24) & 0x7; - int aregs =3D (ctx->opcode >> 16) & 0xf; - int do_ra =3D (ctx->opcode >> 6) & 0x1; - int do_s0 =3D (ctx->opcode >> 5) & 0x1; - int do_s1 =3D (ctx->opcode >> 4) & 0x1; - int framesize =3D (((ctx->opcode >> 20) & 0xf) << 4 - | (ctx->opcode & 0xf)) << 3; - - if (ctx->opcode & (1 << 7)) { - gen_mips16_save(ctx, xsregs, aregs, - do_ra, do_s0, do_s1, - framesize); - } else { - gen_mips16_restore(ctx, xsregs, aregs, - do_ra, do_s0, do_s1, - framesize); - } - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case M16_OPC_LI: - tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm); - break; - case M16_OPC_CMPI: - tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm); - break; -#if defined(TARGET_MIPS64) - case M16_OPC_SD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_st(ctx, OPC_SD, ry, rx, offset); - break; -#endif - case M16_OPC_LB: - gen_ld(ctx, OPC_LB, ry, rx, offset); - break; - case M16_OPC_LH: - gen_ld(ctx, OPC_LH, ry, rx, offset); - break; - case M16_OPC_LWSP: - gen_ld(ctx, OPC_LW, rx, 29, offset); - break; - case M16_OPC_LW: - gen_ld(ctx, OPC_LW, ry, rx, offset); - break; - case M16_OPC_LBU: - gen_ld(ctx, OPC_LBU, ry, rx, offset); - break; - case M16_OPC_LHU: - gen_ld(ctx, OPC_LHU, ry, rx, offset); - break; - case M16_OPC_LWPC: - gen_ld(ctx, OPC_LWPC, rx, 0, offset); - break; -#if defined(TARGET_MIPS64) - case M16_OPC_LWU: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_ld(ctx, OPC_LWU, ry, rx, offset); - break; -#endif - case M16_OPC_SB: - gen_st(ctx, OPC_SB, ry, rx, offset); - break; - case M16_OPC_SH: - gen_st(ctx, OPC_SH, ry, rx, offset); - break; - case M16_OPC_SWSP: - gen_st(ctx, OPC_SW, rx, 29, offset); - break; - case M16_OPC_SW: - gen_st(ctx, OPC_SW, ry, rx, offset); - break; -#if defined(TARGET_MIPS64) - case M16_OPC_I64: - decode_i64_mips16(ctx, ry, funct, offset, 1); - break; -#endif - default: - gen_reserved_instruction(ctx); - break; - } - - return 4; -} - static inline bool is_uhi(int sdbbp_code) { #ifdef CONFIG_USER_ONLY @@ -13088,476 +12442,6 @@ static inline void gen_helper_do_semihosting(void= *env) } #endif =20 -static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx) -{ - int rx, ry; - int sa; - int op, cnvt_op, op1, offset; - int funct; - int n_bytes; - - op =3D (ctx->opcode >> 11) & 0x1f; - sa =3D (ctx->opcode >> 2) & 0x7; - sa =3D sa =3D=3D 0 ? 8 : sa; - rx =3D xlat((ctx->opcode >> 8) & 0x7); - cnvt_op =3D (ctx->opcode >> 5) & 0x7; - ry =3D xlat((ctx->opcode >> 5) & 0x7); - op1 =3D offset =3D ctx->opcode & 0x1f; - - n_bytes =3D 2; - - switch (op) { - case M16_OPC_ADDIUSP: - { - int16_t imm =3D ((uint8_t) ctx->opcode) << 2; - - gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm); - } - break; - case M16_OPC_ADDIUPC: - gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0); - break; - case M16_OPC_B: - offset =3D (ctx->opcode & 0x7ff) << 1; - offset =3D (int16_t)(offset << 4) >> 4; - gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_JAL: - offset =3D translator_lduw(env, ctx->base.pc_next + 2); - offset =3D (((ctx->opcode & 0x1f) << 21) - | ((ctx->opcode >> 5) & 0x1f) << 16 - | offset) << 2; - op =3D ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL; - gen_compute_branch(ctx, op, 4, rx, ry, offset, 2); - n_bytes =3D 4; - break; - case M16_OPC_BEQZ: - gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, - ((int8_t)ctx->opcode) << 1, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_BNEQZ: - gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, - ((int8_t)ctx->opcode) << 1, 0); - /* No delay slot, so just process as a normal instruction */ - break; - case M16_OPC_SHIFT: - switch (ctx->opcode & 0x3) { - case 0x0: - gen_shift_imm(ctx, OPC_SLL, rx, ry, sa); - break; - case 0x1: -#if defined(TARGET_MIPS64) - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa); -#else - gen_reserved_instruction(ctx); -#endif - break; - case 0x2: - gen_shift_imm(ctx, OPC_SRL, rx, ry, sa); - break; - case 0x3: - gen_shift_imm(ctx, OPC_SRA, rx, ry, sa); - break; - } - break; -#if defined(TARGET_MIPS64) - case M16_OPC_LD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_ld(ctx, OPC_LD, ry, rx, offset << 3); - break; -#endif - case M16_OPC_RRIA: - { - int16_t imm =3D (int8_t)((ctx->opcode & 0xf) << 4) >> 4; - - if ((ctx->opcode >> 4) & 1) { -#if defined(TARGET_MIPS64) - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm); -#else - gen_reserved_instruction(ctx); -#endif - } else { - gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm); - } - } - break; - case M16_OPC_ADDIU8: - { - int16_t imm =3D (int8_t) ctx->opcode; - - gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm); - } - break; - case M16_OPC_SLTI: - { - int16_t imm =3D (uint8_t) ctx->opcode; - gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm); - } - break; - case M16_OPC_SLTIU: - { - int16_t imm =3D (uint8_t) ctx->opcode; - gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm); - } - break; - case M16_OPC_I8: - { - int reg32; - - funct =3D (ctx->opcode >> 8) & 0x7; - switch (funct) { - case I8_BTEQZ: - gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0, - ((int8_t)ctx->opcode) << 1, 0); - break; - case I8_BTNEZ: - gen_compute_branch(ctx, OPC_BNE, 2, 24, 0, - ((int8_t)ctx->opcode) << 1, 0); - break; - case I8_SWRASP: - gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2); - break; - case I8_ADJSP: - gen_arith_imm(ctx, OPC_ADDIU, 29, 29, - ((int8_t)ctx->opcode) << 3); - break; - case I8_SVRS: - check_insn(ctx, ISA_MIPS_R1); - { - int do_ra =3D ctx->opcode & (1 << 6); - int do_s0 =3D ctx->opcode & (1 << 5); - int do_s1 =3D ctx->opcode & (1 << 4); - int framesize =3D ctx->opcode & 0xf; - - if (framesize =3D=3D 0) { - framesize =3D 128; - } else { - framesize =3D framesize << 3; - } - - if (ctx->opcode & (1 << 7)) { - gen_mips16_save(ctx, 0, 0, - do_ra, do_s0, do_s1, framesize); - } else { - gen_mips16_restore(ctx, 0, 0, - do_ra, do_s0, do_s1, framesize); - } - } - break; - case I8_MOV32R: - { - int rz =3D xlat(ctx->opcode & 0x7); - - reg32 =3D (((ctx->opcode >> 3) & 0x3) << 3) | - ((ctx->opcode >> 5) & 0x7); - gen_arith(ctx, OPC_ADDU, reg32, rz, 0); - } - break; - case I8_MOVR32: - reg32 =3D ctx->opcode & 0x1f; - gen_arith(ctx, OPC_ADDU, ry, reg32, 0); - break; - default: - gen_reserved_instruction(ctx); - break; - } - } - break; - case M16_OPC_LI: - { - int16_t imm =3D (uint8_t) ctx->opcode; - - gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm); - } - break; - case M16_OPC_CMPI: - { - int16_t imm =3D (uint8_t) ctx->opcode; - gen_logic_imm(ctx, OPC_XORI, 24, rx, imm); - } - break; -#if defined(TARGET_MIPS64) - case M16_OPC_SD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_st(ctx, OPC_SD, ry, rx, offset << 3); - break; -#endif - case M16_OPC_LB: - gen_ld(ctx, OPC_LB, ry, rx, offset); - break; - case M16_OPC_LH: - gen_ld(ctx, OPC_LH, ry, rx, offset << 1); - break; - case M16_OPC_LWSP: - gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2); - break; - case M16_OPC_LW: - gen_ld(ctx, OPC_LW, ry, rx, offset << 2); - break; - case M16_OPC_LBU: - gen_ld(ctx, OPC_LBU, ry, rx, offset); - break; - case M16_OPC_LHU: - gen_ld(ctx, OPC_LHU, ry, rx, offset << 1); - break; - case M16_OPC_LWPC: - gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2); - break; -#if defined(TARGET_MIPS64) - case M16_OPC_LWU: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_ld(ctx, OPC_LWU, ry, rx, offset << 2); - break; -#endif - case M16_OPC_SB: - gen_st(ctx, OPC_SB, ry, rx, offset); - break; - case M16_OPC_SH: - gen_st(ctx, OPC_SH, ry, rx, offset << 1); - break; - case M16_OPC_SWSP: - gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2); - break; - case M16_OPC_SW: - gen_st(ctx, OPC_SW, ry, rx, offset << 2); - break; - case M16_OPC_RRR: - { - int rz =3D xlat((ctx->opcode >> 2) & 0x7); - int mips32_op; - - switch (ctx->opcode & 0x3) { - case RRR_ADDU: - mips32_op =3D OPC_ADDU; - break; - case RRR_SUBU: - mips32_op =3D OPC_SUBU; - break; -#if defined(TARGET_MIPS64) - case RRR_DADDU: - mips32_op =3D OPC_DADDU; - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - break; - case RRR_DSUBU: - mips32_op =3D OPC_DSUBU; - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - break; -#endif - default: - gen_reserved_instruction(ctx); - goto done; - } - - gen_arith(ctx, mips32_op, rz, rx, ry); - done: - ; - } - break; - case M16_OPC_RR: - switch (op1) { - case RR_JR: - { - int nd =3D (ctx->opcode >> 7) & 0x1; - int link =3D (ctx->opcode >> 6) & 0x1; - int ra =3D (ctx->opcode >> 5) & 0x1; - - if (nd) { - check_insn(ctx, ISA_MIPS_R1); - } - - if (link) { - op =3D OPC_JALR; - } else { - op =3D OPC_JR; - } - - gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0, - (nd ? 0 : 2)); - } - break; - case RR_SDBBP: - if (is_uhi(extract32(ctx->opcode, 5, 6))) { - gen_helper_do_semihosting(cpu_env); - } else { - /* - * XXX: not clear which exception should be raised - * when in debug mode... - */ - check_insn(ctx, ISA_MIPS_R1); - generate_exception_end(ctx, EXCP_DBp); - } - break; - case RR_SLT: - gen_slt(ctx, OPC_SLT, 24, rx, ry); - break; - case RR_SLTU: - gen_slt(ctx, OPC_SLTU, 24, rx, ry); - break; - case RR_BREAK: - generate_exception_end(ctx, EXCP_BREAK); - break; - case RR_SLLV: - gen_shift(ctx, OPC_SLLV, ry, rx, ry); - break; - case RR_SRLV: - gen_shift(ctx, OPC_SRLV, ry, rx, ry); - break; - case RR_SRAV: - gen_shift(ctx, OPC_SRAV, ry, rx, ry); - break; -#if defined(TARGET_MIPS64) - case RR_DSRL: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa); - break; -#endif - case RR_CMP: - gen_logic(ctx, OPC_XOR, 24, rx, ry); - break; - case RR_NEG: - gen_arith(ctx, OPC_SUBU, rx, 0, ry); - break; - case RR_AND: - gen_logic(ctx, OPC_AND, rx, rx, ry); - break; - case RR_OR: - gen_logic(ctx, OPC_OR, rx, rx, ry); - break; - case RR_XOR: - gen_logic(ctx, OPC_XOR, rx, rx, ry); - break; - case RR_NOT: - gen_logic(ctx, OPC_NOR, rx, ry, 0); - break; - case RR_MFHI: - gen_HILO(ctx, OPC_MFHI, 0, rx); - break; - case RR_CNVT: - check_insn(ctx, ISA_MIPS_R1); - switch (cnvt_op) { - case RR_RY_CNVT_ZEB: - tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; - case RR_RY_CNVT_ZEH: - tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; - case RR_RY_CNVT_SEB: - tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; - case RR_RY_CNVT_SEH: - tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; -#if defined(TARGET_MIPS64) - case RR_RY_CNVT_ZEW: - check_insn(ctx, ISA_MIPS_R1); - check_mips_64(ctx); - tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; - case RR_RY_CNVT_SEW: - check_insn(ctx, ISA_MIPS_R1); - check_mips_64(ctx); - tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]); - break; -#endif - default: - gen_reserved_instruction(ctx); - break; - } - break; - case RR_MFLO: - gen_HILO(ctx, OPC_MFLO, 0, rx); - break; -#if defined(TARGET_MIPS64) - case RR_DSRA: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa); - break; - case RR_DSLLV: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift(ctx, OPC_DSLLV, ry, rx, ry); - break; - case RR_DSRLV: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift(ctx, OPC_DSRLV, ry, rx, ry); - break; - case RR_DSRAV: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_shift(ctx, OPC_DSRAV, ry, rx, ry); - break; -#endif - case RR_MULT: - gen_muldiv(ctx, OPC_MULT, 0, rx, ry); - break; - case RR_MULTU: - gen_muldiv(ctx, OPC_MULTU, 0, rx, ry); - break; - case RR_DIV: - gen_muldiv(ctx, OPC_DIV, 0, rx, ry); - break; - case RR_DIVU: - gen_muldiv(ctx, OPC_DIVU, 0, rx, ry); - break; -#if defined(TARGET_MIPS64) - case RR_DMULT: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_muldiv(ctx, OPC_DMULT, 0, rx, ry); - break; - case RR_DMULTU: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry); - break; - case RR_DDIV: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_muldiv(ctx, OPC_DDIV, 0, rx, ry); - break; - case RR_DDIVU: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry); - break; -#endif - default: - gen_reserved_instruction(ctx); - break; - } - break; - case M16_OPC_EXTEND: - decode_extended_mips16_opc(env, ctx); - n_bytes =3D 4; - break; -#if defined(TARGET_MIPS64) - case M16_OPC_I64: - funct =3D (ctx->opcode >> 8) & 0x7; - decode_i64_mips16(ctx, ry, funct, offset, 0); - break; -#endif - default: - gen_reserved_instruction(ctx); - break; - } - - return n_bytes; -} - /* microMIPS extension to MIPS32/MIPS64 */ =20 /* @@ -16850,6 +15734,11 @@ static int decode_micromips_opc(CPUMIPSState *env,= DisasContext *ctx) return 2; } =20 +/* ISA extensions (ASEs) */ + +/* MIPS16 extension to MIPS32 */ +#include "mips16e_translate.c.inc" + /* * * nanoMIPS opcodes @@ -25492,7 +24381,7 @@ static void mips_tr_translate_insn(DisasContextBase= *dcbase, CPUState *cs) insn_bytes =3D decode_micromips_opc(env, ctx); } else if (ctx->insn_flags & ASE_MIPS16) { ctx->opcode =3D translator_lduw(env, ctx->base.pc_next); - insn_bytes =3D decode_mips16_opc(env, ctx); + insn_bytes =3D decode_ase_mips16e(env, ctx); } else { gen_reserved_instruction(ctx); g_assert(ctx->base.is_jmp =3D=3D DISAS_NORETURN); diff --git a/target/mips/tcg/mips16e_translate.c.inc b/target/mips/tcg/mips= 16e_translate.c.inc new file mode 100644 index 00000000000..54071813f12 --- /dev/null +++ b/target/mips/tcg/mips16e_translate.c.inc @@ -0,0 +1,1123 @@ +/* + * MIPS16 extension (Code Compaction) ASE translation routines + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +/* MIPS16 major opcodes */ +enum { + M16_OPC_ADDIUSP =3D 0x00, + M16_OPC_ADDIUPC =3D 0x01, + M16_OPC_B =3D 0x02, + M16_OPC_JAL =3D 0x03, + M16_OPC_BEQZ =3D 0x04, + M16_OPC_BNEQZ =3D 0x05, + M16_OPC_SHIFT =3D 0x06, + M16_OPC_LD =3D 0x07, + M16_OPC_RRIA =3D 0x08, + M16_OPC_ADDIU8 =3D 0x09, + M16_OPC_SLTI =3D 0x0a, + M16_OPC_SLTIU =3D 0x0b, + M16_OPC_I8 =3D 0x0c, + M16_OPC_LI =3D 0x0d, + M16_OPC_CMPI =3D 0x0e, + M16_OPC_SD =3D 0x0f, + M16_OPC_LB =3D 0x10, + M16_OPC_LH =3D 0x11, + M16_OPC_LWSP =3D 0x12, + M16_OPC_LW =3D 0x13, + M16_OPC_LBU =3D 0x14, + M16_OPC_LHU =3D 0x15, + M16_OPC_LWPC =3D 0x16, + M16_OPC_LWU =3D 0x17, + M16_OPC_SB =3D 0x18, + M16_OPC_SH =3D 0x19, + M16_OPC_SWSP =3D 0x1a, + M16_OPC_SW =3D 0x1b, + M16_OPC_RRR =3D 0x1c, + M16_OPC_RR =3D 0x1d, + M16_OPC_EXTEND =3D 0x1e, + M16_OPC_I64 =3D 0x1f +}; + +/* I8 funct field */ +enum { + I8_BTEQZ =3D 0x0, + I8_BTNEZ =3D 0x1, + I8_SWRASP =3D 0x2, + I8_ADJSP =3D 0x3, + I8_SVRS =3D 0x4, + I8_MOV32R =3D 0x5, + I8_MOVR32 =3D 0x7 +}; + +/* RRR f field */ +enum { + RRR_DADDU =3D 0x0, + RRR_ADDU =3D 0x1, + RRR_DSUBU =3D 0x2, + RRR_SUBU =3D 0x3 +}; + +/* RR funct field */ +enum { + RR_JR =3D 0x00, + RR_SDBBP =3D 0x01, + RR_SLT =3D 0x02, + RR_SLTU =3D 0x03, + RR_SLLV =3D 0x04, + RR_BREAK =3D 0x05, + RR_SRLV =3D 0x06, + RR_SRAV =3D 0x07, + RR_DSRL =3D 0x08, + RR_CMP =3D 0x0a, + RR_NEG =3D 0x0b, + RR_AND =3D 0x0c, + RR_OR =3D 0x0d, + RR_XOR =3D 0x0e, + RR_NOT =3D 0x0f, + RR_MFHI =3D 0x10, + RR_CNVT =3D 0x11, + RR_MFLO =3D 0x12, + RR_DSRA =3D 0x13, + RR_DSLLV =3D 0x14, + RR_DSRLV =3D 0x16, + RR_DSRAV =3D 0x17, + RR_MULT =3D 0x18, + RR_MULTU =3D 0x19, + RR_DIV =3D 0x1a, + RR_DIVU =3D 0x1b, + RR_DMULT =3D 0x1c, + RR_DMULTU =3D 0x1d, + RR_DDIV =3D 0x1e, + RR_DDIVU =3D 0x1f +}; + +/* I64 funct field */ +enum { + I64_LDSP =3D 0x0, + I64_SDSP =3D 0x1, + I64_SDRASP =3D 0x2, + I64_DADJSP =3D 0x3, + I64_LDPC =3D 0x4, + I64_DADDIU5 =3D 0x5, + I64_DADDIUPC =3D 0x6, + I64_DADDIUSP =3D 0x7 +}; + +/* RR ry field for CNVT */ +enum { + RR_RY_CNVT_ZEB =3D 0x0, + RR_RY_CNVT_ZEH =3D 0x1, + RR_RY_CNVT_ZEW =3D 0x2, + RR_RY_CNVT_SEB =3D 0x4, + RR_RY_CNVT_SEH =3D 0x5, + RR_RY_CNVT_SEW =3D 0x6, +}; + +static int xlat(int r) +{ + static int map[] =3D { 16, 17, 2, 3, 4, 5, 6, 7 }; + + return map[r]; +} + +static void gen_mips16_save(DisasContext *ctx, + int xsregs, int aregs, + int do_ra, int do_s0, int do_s1, + int framesize) +{ + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + TCGv t2 =3D tcg_temp_new(); + int args, astatic; + + switch (aregs) { + case 0: + case 1: + case 2: + case 3: + case 11: + args =3D 0; + break; + case 4: + case 5: + case 6: + case 7: + args =3D 1; + break; + case 8: + case 9: + case 10: + args =3D 2; + break; + case 12: + case 13: + args =3D 3; + break; + case 14: + args =3D 4; + break; + default: + gen_reserved_instruction(ctx); + return; + } + + switch (args) { + case 4: + gen_base_offset_addr(ctx, t0, 29, 12); + gen_load_gpr(t1, 7); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + /* Fall through */ + case 3: + gen_base_offset_addr(ctx, t0, 29, 8); + gen_load_gpr(t1, 6); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + /* Fall through */ + case 2: + gen_base_offset_addr(ctx, t0, 29, 4); + gen_load_gpr(t1, 5); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + /* Fall through */ + case 1: + gen_base_offset_addr(ctx, t0, 29, 0); + gen_load_gpr(t1, 4); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + } + + gen_load_gpr(t0, 29); + +#define DECR_AND_STORE(reg) do { \ + tcg_gen_movi_tl(t2, -4); \ + gen_op_addr_add(ctx, t0, t0, t2); \ + gen_load_gpr(t1, reg); \ + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \ + } while (0) + + if (do_ra) { + DECR_AND_STORE(31); + } + + switch (xsregs) { + case 7: + DECR_AND_STORE(30); + /* Fall through */ + case 6: + DECR_AND_STORE(23); + /* Fall through */ + case 5: + DECR_AND_STORE(22); + /* Fall through */ + case 4: + DECR_AND_STORE(21); + /* Fall through */ + case 3: + DECR_AND_STORE(20); + /* Fall through */ + case 2: + DECR_AND_STORE(19); + /* Fall through */ + case 1: + DECR_AND_STORE(18); + } + + if (do_s1) { + DECR_AND_STORE(17); + } + if (do_s0) { + DECR_AND_STORE(16); + } + + switch (aregs) { + case 0: + case 4: + case 8: + case 12: + case 14: + astatic =3D 0; + break; + case 1: + case 5: + case 9: + case 13: + astatic =3D 1; + break; + case 2: + case 6: + case 10: + astatic =3D 2; + break; + case 3: + case 7: + astatic =3D 3; + break; + case 11: + astatic =3D 4; + break; + default: + gen_reserved_instruction(ctx); + return; + } + + if (astatic > 0) { + DECR_AND_STORE(7); + if (astatic > 1) { + DECR_AND_STORE(6); + if (astatic > 2) { + DECR_AND_STORE(5); + if (astatic > 3) { + DECR_AND_STORE(4); + } + } + } + } +#undef DECR_AND_STORE + + tcg_gen_movi_tl(t2, -framesize); + gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2); + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); +} + +static void gen_mips16_restore(DisasContext *ctx, + int xsregs, int aregs, + int do_ra, int do_s0, int do_s1, + int framesize) +{ + int astatic; + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + TCGv t2 =3D tcg_temp_new(); + + tcg_gen_movi_tl(t2, framesize); + gen_op_addr_add(ctx, t0, cpu_gpr[29], t2); + +#define DECR_AND_LOAD(reg) do { \ + tcg_gen_movi_tl(t2, -4); \ + gen_op_addr_add(ctx, t0, t0, t2); \ + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \ + gen_store_gpr(t1, reg); \ + } while (0) + + if (do_ra) { + DECR_AND_LOAD(31); + } + + switch (xsregs) { + case 7: + DECR_AND_LOAD(30); + /* Fall through */ + case 6: + DECR_AND_LOAD(23); + /* Fall through */ + case 5: + DECR_AND_LOAD(22); + /* Fall through */ + case 4: + DECR_AND_LOAD(21); + /* Fall through */ + case 3: + DECR_AND_LOAD(20); + /* Fall through */ + case 2: + DECR_AND_LOAD(19); + /* Fall through */ + case 1: + DECR_AND_LOAD(18); + } + + if (do_s1) { + DECR_AND_LOAD(17); + } + if (do_s0) { + DECR_AND_LOAD(16); + } + + switch (aregs) { + case 0: + case 4: + case 8: + case 12: + case 14: + astatic =3D 0; + break; + case 1: + case 5: + case 9: + case 13: + astatic =3D 1; + break; + case 2: + case 6: + case 10: + astatic =3D 2; + break; + case 3: + case 7: + astatic =3D 3; + break; + case 11: + astatic =3D 4; + break; + default: + gen_reserved_instruction(ctx); + return; + } + + if (astatic > 0) { + DECR_AND_LOAD(7); + if (astatic > 1) { + DECR_AND_LOAD(6); + if (astatic > 2) { + DECR_AND_LOAD(5); + if (astatic > 3) { + DECR_AND_LOAD(4); + } + } + } + } +#undef DECR_AND_LOAD + + tcg_gen_movi_tl(t2, framesize); + gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2); + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); +} + +#if defined(TARGET_MIPS64) +static void decode_i64_mips16(DisasContext *ctx, + int ry, int funct, int16_t offset, + int extended) +{ + switch (funct) { + case I64_LDSP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset =3D extended ? offset : offset << 3; + gen_ld(ctx, OPC_LD, ry, 29, offset); + break; + case I64_SDSP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset =3D extended ? offset : offset << 3; + gen_st(ctx, OPC_SD, ry, 29, offset); + break; + case I64_SDRASP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset =3D extended ? offset : (ctx->opcode & 0xff) << 3; + gen_st(ctx, OPC_SD, 31, 29, offset); + break; + case I64_DADJSP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset =3D extended ? offset : ((int8_t)ctx->opcode) << 3; + gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset); + break; + case I64_LDPC: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) { + gen_reserved_instruction(ctx); + } else { + offset =3D extended ? offset : offset << 3; + gen_ld(ctx, OPC_LDPC, ry, 0, offset); + } + break; + case I64_DADDIU5: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset =3D extended ? offset : ((int8_t)(offset << 3)) >> 3; + gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset); + break; + case I64_DADDIUPC: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset =3D extended ? offset : offset << 2; + gen_addiupc(ctx, ry, offset, 1, extended); + break; + case I64_DADDIUSP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + offset =3D extended ? offset : offset << 2; + gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset); + break; + } +} +#endif + +static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx) +{ + int extend =3D translator_lduw(env, ctx->base.pc_next + 2); + int op, rx, ry, funct, sa; + int16_t imm, offset; + + ctx->opcode =3D (ctx->opcode << 16) | extend; + op =3D (ctx->opcode >> 11) & 0x1f; + sa =3D (ctx->opcode >> 22) & 0x1f; + funct =3D (ctx->opcode >> 8) & 0x7; + rx =3D xlat((ctx->opcode >> 8) & 0x7); + ry =3D xlat((ctx->opcode >> 5) & 0x7); + offset =3D imm =3D (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11 + | ((ctx->opcode >> 21) & 0x3f) << 5 + | (ctx->opcode & 0x1f)); + + /* + * The extended opcodes cleverly reuse the opcodes from their 16-bit + * counterparts. + */ + switch (op) { + case M16_OPC_ADDIUSP: + gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm); + break; + case M16_OPC_ADDIUPC: + gen_addiupc(ctx, rx, imm, 0, 1); + break; + case M16_OPC_B: + gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_BEQZ: + gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_BNEQZ: + gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_SHIFT: + switch (ctx->opcode & 0x3) { + case 0x0: + gen_shift_imm(ctx, OPC_SLL, rx, ry, sa); + break; + case 0x1: +#if defined(TARGET_MIPS64) + check_mips_64(ctx); + gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa); +#else + gen_reserved_instruction(ctx); +#endif + break; + case 0x2: + gen_shift_imm(ctx, OPC_SRL, rx, ry, sa); + break; + case 0x3: + gen_shift_imm(ctx, OPC_SRA, rx, ry, sa); + break; + } + break; +#if defined(TARGET_MIPS64) + case M16_OPC_LD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_ld(ctx, OPC_LD, ry, rx, offset); + break; +#endif + case M16_OPC_RRIA: + imm =3D ctx->opcode & 0xf; + imm =3D imm | ((ctx->opcode >> 20) & 0x7f) << 4; + imm =3D imm | ((ctx->opcode >> 16) & 0xf) << 11; + imm =3D (int16_t) (imm << 1) >> 1; + if ((ctx->opcode >> 4) & 0x1) { +#if defined(TARGET_MIPS64) + check_mips_64(ctx); + gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm); +#else + gen_reserved_instruction(ctx); +#endif + } else { + gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm); + } + break; + case M16_OPC_ADDIU8: + gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm); + break; + case M16_OPC_SLTI: + gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm); + break; + case M16_OPC_SLTIU: + gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm); + break; + case M16_OPC_I8: + switch (funct) { + case I8_BTEQZ: + gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0); + break; + case I8_BTNEZ: + gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0); + break; + case I8_SWRASP: + gen_st(ctx, OPC_SW, 31, 29, imm); + break; + case I8_ADJSP: + gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm); + break; + case I8_SVRS: + check_insn(ctx, ISA_MIPS_R1); + { + int xsregs =3D (ctx->opcode >> 24) & 0x7; + int aregs =3D (ctx->opcode >> 16) & 0xf; + int do_ra =3D (ctx->opcode >> 6) & 0x1; + int do_s0 =3D (ctx->opcode >> 5) & 0x1; + int do_s1 =3D (ctx->opcode >> 4) & 0x1; + int framesize =3D (((ctx->opcode >> 20) & 0xf) << 4 + | (ctx->opcode & 0xf)) << 3; + + if (ctx->opcode & (1 << 7)) { + gen_mips16_save(ctx, xsregs, aregs, + do_ra, do_s0, do_s1, + framesize); + } else { + gen_mips16_restore(ctx, xsregs, aregs, + do_ra, do_s0, do_s1, + framesize); + } + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case M16_OPC_LI: + tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm); + break; + case M16_OPC_CMPI: + tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm); + break; +#if defined(TARGET_MIPS64) + case M16_OPC_SD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_st(ctx, OPC_SD, ry, rx, offset); + break; +#endif + case M16_OPC_LB: + gen_ld(ctx, OPC_LB, ry, rx, offset); + break; + case M16_OPC_LH: + gen_ld(ctx, OPC_LH, ry, rx, offset); + break; + case M16_OPC_LWSP: + gen_ld(ctx, OPC_LW, rx, 29, offset); + break; + case M16_OPC_LW: + gen_ld(ctx, OPC_LW, ry, rx, offset); + break; + case M16_OPC_LBU: + gen_ld(ctx, OPC_LBU, ry, rx, offset); + break; + case M16_OPC_LHU: + gen_ld(ctx, OPC_LHU, ry, rx, offset); + break; + case M16_OPC_LWPC: + gen_ld(ctx, OPC_LWPC, rx, 0, offset); + break; +#if defined(TARGET_MIPS64) + case M16_OPC_LWU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_ld(ctx, OPC_LWU, ry, rx, offset); + break; +#endif + case M16_OPC_SB: + gen_st(ctx, OPC_SB, ry, rx, offset); + break; + case M16_OPC_SH: + gen_st(ctx, OPC_SH, ry, rx, offset); + break; + case M16_OPC_SWSP: + gen_st(ctx, OPC_SW, rx, 29, offset); + break; + case M16_OPC_SW: + gen_st(ctx, OPC_SW, ry, rx, offset); + break; +#if defined(TARGET_MIPS64) + case M16_OPC_I64: + decode_i64_mips16(ctx, ry, funct, offset, 1); + break; +#endif + default: + gen_reserved_instruction(ctx); + break; + } + + return 4; +} + +static int decode_ase_mips16e(CPUMIPSState *env, DisasContext *ctx) +{ + int rx, ry; + int sa; + int op, cnvt_op, op1, offset; + int funct; + int n_bytes; + + op =3D (ctx->opcode >> 11) & 0x1f; + sa =3D (ctx->opcode >> 2) & 0x7; + sa =3D sa =3D=3D 0 ? 8 : sa; + rx =3D xlat((ctx->opcode >> 8) & 0x7); + cnvt_op =3D (ctx->opcode >> 5) & 0x7; + ry =3D xlat((ctx->opcode >> 5) & 0x7); + op1 =3D offset =3D ctx->opcode & 0x1f; + + n_bytes =3D 2; + + switch (op) { + case M16_OPC_ADDIUSP: + { + int16_t imm =3D ((uint8_t) ctx->opcode) << 2; + + gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm); + } + break; + case M16_OPC_ADDIUPC: + gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0); + break; + case M16_OPC_B: + offset =3D (ctx->opcode & 0x7ff) << 1; + offset =3D (int16_t)(offset << 4) >> 4; + gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_JAL: + offset =3D translator_lduw(env, ctx->base.pc_next + 2); + offset =3D (((ctx->opcode & 0x1f) << 21) + | ((ctx->opcode >> 5) & 0x1f) << 16 + | offset) << 2; + op =3D ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL; + gen_compute_branch(ctx, op, 4, rx, ry, offset, 2); + n_bytes =3D 4; + break; + case M16_OPC_BEQZ: + gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, + ((int8_t)ctx->opcode) << 1, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_BNEQZ: + gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, + ((int8_t)ctx->opcode) << 1, 0); + /* No delay slot, so just process as a normal instruction */ + break; + case M16_OPC_SHIFT: + switch (ctx->opcode & 0x3) { + case 0x0: + gen_shift_imm(ctx, OPC_SLL, rx, ry, sa); + break; + case 0x1: +#if defined(TARGET_MIPS64) + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa); +#else + gen_reserved_instruction(ctx); +#endif + break; + case 0x2: + gen_shift_imm(ctx, OPC_SRL, rx, ry, sa); + break; + case 0x3: + gen_shift_imm(ctx, OPC_SRA, rx, ry, sa); + break; + } + break; +#if defined(TARGET_MIPS64) + case M16_OPC_LD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_ld(ctx, OPC_LD, ry, rx, offset << 3); + break; +#endif + case M16_OPC_RRIA: + { + int16_t imm =3D (int8_t)((ctx->opcode & 0xf) << 4) >> 4; + + if ((ctx->opcode >> 4) & 1) { +#if defined(TARGET_MIPS64) + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm); +#else + gen_reserved_instruction(ctx); +#endif + } else { + gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm); + } + } + break; + case M16_OPC_ADDIU8: + { + int16_t imm =3D (int8_t) ctx->opcode; + + gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm); + } + break; + case M16_OPC_SLTI: + { + int16_t imm =3D (uint8_t) ctx->opcode; + gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm); + } + break; + case M16_OPC_SLTIU: + { + int16_t imm =3D (uint8_t) ctx->opcode; + gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm); + } + break; + case M16_OPC_I8: + { + int reg32; + + funct =3D (ctx->opcode >> 8) & 0x7; + switch (funct) { + case I8_BTEQZ: + gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0, + ((int8_t)ctx->opcode) << 1, 0); + break; + case I8_BTNEZ: + gen_compute_branch(ctx, OPC_BNE, 2, 24, 0, + ((int8_t)ctx->opcode) << 1, 0); + break; + case I8_SWRASP: + gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2); + break; + case I8_ADJSP: + gen_arith_imm(ctx, OPC_ADDIU, 29, 29, + ((int8_t)ctx->opcode) << 3); + break; + case I8_SVRS: + check_insn(ctx, ISA_MIPS_R1); + { + int do_ra =3D ctx->opcode & (1 << 6); + int do_s0 =3D ctx->opcode & (1 << 5); + int do_s1 =3D ctx->opcode & (1 << 4); + int framesize =3D ctx->opcode & 0xf; + + if (framesize =3D=3D 0) { + framesize =3D 128; + } else { + framesize =3D framesize << 3; + } + + if (ctx->opcode & (1 << 7)) { + gen_mips16_save(ctx, 0, 0, + do_ra, do_s0, do_s1, framesize); + } else { + gen_mips16_restore(ctx, 0, 0, + do_ra, do_s0, do_s1, framesize); + } + } + break; + case I8_MOV32R: + { + int rz =3D xlat(ctx->opcode & 0x7); + + reg32 =3D (((ctx->opcode >> 3) & 0x3) << 3) | + ((ctx->opcode >> 5) & 0x7); + gen_arith(ctx, OPC_ADDU, reg32, rz, 0); + } + break; + case I8_MOVR32: + reg32 =3D ctx->opcode & 0x1f; + gen_arith(ctx, OPC_ADDU, ry, reg32, 0); + break; + default: + gen_reserved_instruction(ctx); + break; + } + } + break; + case M16_OPC_LI: + { + int16_t imm =3D (uint8_t) ctx->opcode; + + gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm); + } + break; + case M16_OPC_CMPI: + { + int16_t imm =3D (uint8_t) ctx->opcode; + gen_logic_imm(ctx, OPC_XORI, 24, rx, imm); + } + break; +#if defined(TARGET_MIPS64) + case M16_OPC_SD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_st(ctx, OPC_SD, ry, rx, offset << 3); + break; +#endif + case M16_OPC_LB: + gen_ld(ctx, OPC_LB, ry, rx, offset); + break; + case M16_OPC_LH: + gen_ld(ctx, OPC_LH, ry, rx, offset << 1); + break; + case M16_OPC_LWSP: + gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2); + break; + case M16_OPC_LW: + gen_ld(ctx, OPC_LW, ry, rx, offset << 2); + break; + case M16_OPC_LBU: + gen_ld(ctx, OPC_LBU, ry, rx, offset); + break; + case M16_OPC_LHU: + gen_ld(ctx, OPC_LHU, ry, rx, offset << 1); + break; + case M16_OPC_LWPC: + gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2); + break; +#if defined(TARGET_MIPS64) + case M16_OPC_LWU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_ld(ctx, OPC_LWU, ry, rx, offset << 2); + break; +#endif + case M16_OPC_SB: + gen_st(ctx, OPC_SB, ry, rx, offset); + break; + case M16_OPC_SH: + gen_st(ctx, OPC_SH, ry, rx, offset << 1); + break; + case M16_OPC_SWSP: + gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2); + break; + case M16_OPC_SW: + gen_st(ctx, OPC_SW, ry, rx, offset << 2); + break; + case M16_OPC_RRR: + { + int rz =3D xlat((ctx->opcode >> 2) & 0x7); + int mips32_op; + + switch (ctx->opcode & 0x3) { + case RRR_ADDU: + mips32_op =3D OPC_ADDU; + break; + case RRR_SUBU: + mips32_op =3D OPC_SUBU; + break; +#if defined(TARGET_MIPS64) + case RRR_DADDU: + mips32_op =3D OPC_DADDU; + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + break; + case RRR_DSUBU: + mips32_op =3D OPC_DSUBU; + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + break; +#endif + default: + gen_reserved_instruction(ctx); + goto done; + } + + gen_arith(ctx, mips32_op, rz, rx, ry); + done: + ; + } + break; + case M16_OPC_RR: + switch (op1) { + case RR_JR: + { + int nd =3D (ctx->opcode >> 7) & 0x1; + int link =3D (ctx->opcode >> 6) & 0x1; + int ra =3D (ctx->opcode >> 5) & 0x1; + + if (nd) { + check_insn(ctx, ISA_MIPS_R1); + } + + if (link) { + op =3D OPC_JALR; + } else { + op =3D OPC_JR; + } + + gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0, + (nd ? 0 : 2)); + } + break; + case RR_SDBBP: + if (is_uhi(extract32(ctx->opcode, 5, 6))) { + gen_helper_do_semihosting(cpu_env); + } else { + /* + * XXX: not clear which exception should be raised + * when in debug mode... + */ + check_insn(ctx, ISA_MIPS_R1); + generate_exception_end(ctx, EXCP_DBp); + } + break; + case RR_SLT: + gen_slt(ctx, OPC_SLT, 24, rx, ry); + break; + case RR_SLTU: + gen_slt(ctx, OPC_SLTU, 24, rx, ry); + break; + case RR_BREAK: + generate_exception_end(ctx, EXCP_BREAK); + break; + case RR_SLLV: + gen_shift(ctx, OPC_SLLV, ry, rx, ry); + break; + case RR_SRLV: + gen_shift(ctx, OPC_SRLV, ry, rx, ry); + break; + case RR_SRAV: + gen_shift(ctx, OPC_SRAV, ry, rx, ry); + break; +#if defined(TARGET_MIPS64) + case RR_DSRL: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa); + break; +#endif + case RR_CMP: + gen_logic(ctx, OPC_XOR, 24, rx, ry); + break; + case RR_NEG: + gen_arith(ctx, OPC_SUBU, rx, 0, ry); + break; + case RR_AND: + gen_logic(ctx, OPC_AND, rx, rx, ry); + break; + case RR_OR: + gen_logic(ctx, OPC_OR, rx, rx, ry); + break; + case RR_XOR: + gen_logic(ctx, OPC_XOR, rx, rx, ry); + break; + case RR_NOT: + gen_logic(ctx, OPC_NOR, rx, ry, 0); + break; + case RR_MFHI: + gen_HILO(ctx, OPC_MFHI, 0, rx); + break; + case RR_CNVT: + check_insn(ctx, ISA_MIPS_R1); + switch (cnvt_op) { + case RR_RY_CNVT_ZEB: + tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_ZEH: + tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_SEB: + tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_SEH: + tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; +#if defined(TARGET_MIPS64) + case RR_RY_CNVT_ZEW: + check_insn(ctx, ISA_MIPS_R1); + check_mips_64(ctx); + tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; + case RR_RY_CNVT_SEW: + check_insn(ctx, ISA_MIPS_R1); + check_mips_64(ctx); + tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]); + break; +#endif + default: + gen_reserved_instruction(ctx); + break; + } + break; + case RR_MFLO: + gen_HILO(ctx, OPC_MFLO, 0, rx); + break; +#if defined(TARGET_MIPS64) + case RR_DSRA: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa); + break; + case RR_DSLLV: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift(ctx, OPC_DSLLV, ry, rx, ry); + break; + case RR_DSRLV: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift(ctx, OPC_DSRLV, ry, rx, ry); + break; + case RR_DSRAV: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_shift(ctx, OPC_DSRAV, ry, rx, ry); + break; +#endif + case RR_MULT: + gen_muldiv(ctx, OPC_MULT, 0, rx, ry); + break; + case RR_MULTU: + gen_muldiv(ctx, OPC_MULTU, 0, rx, ry); + break; + case RR_DIV: + gen_muldiv(ctx, OPC_DIV, 0, rx, ry); + break; + case RR_DIVU: + gen_muldiv(ctx, OPC_DIVU, 0, rx, ry); + break; +#if defined(TARGET_MIPS64) + case RR_DMULT: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_muldiv(ctx, OPC_DMULT, 0, rx, ry); + break; + case RR_DMULTU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry); + break; + case RR_DDIV: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_muldiv(ctx, OPC_DDIV, 0, rx, ry); + break; + case RR_DDIVU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry); + break; +#endif + default: + gen_reserved_instruction(ctx); + break; + } + break; + case M16_OPC_EXTEND: + decode_extended_mips16_opc(env, ctx); + n_bytes =3D 4; + break; +#if defined(TARGET_MIPS64) + case M16_OPC_I64: + funct =3D (ctx->opcode >> 8) & 0x7; + decode_i64_mips16(ctx, ry, funct, offset, 0); + break; +#endif + default: + gen_reserved_instruction(ctx); + break; + } + + return n_bytes; +} --=20 2.31.1 From nobody Fri May 3 04:33:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.221.45 as permitted sender) client-ip=209.85.221.45; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-f45.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.45 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1623952167; cv=none; d=zohomail.com; s=zohoarc; b=P76r03XFQHGVV1wFhrn04O7AJAYX1Jgqs0PawFvGOc2Nn6TEqgz8EAYFDT5TFRcdUI0i4YXYUlzvFYi2l1Uo72mjlBZnunxMcBklbCMZyQK1L3YLhf+aeK2Bk5O5xjklTij5TeM+Szgytpb5nuDiToNSmQrdwSuL8d16wOyNJJg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1623952167; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ouJW6Tu1Wi2ugnpSAzhcCZMWHmSzJZ21PGf32aTzlN8=; b=DlXmQ8DC0LoWSDUPy5oO++XPY9LVTthDgDvM/h8D6rMZJ/q4oCchkbOGkIwOVc6n/DTFe2bXvn76va0P/o/RxUw21WDps5OWeJmHVCP2rNnm/nmh8ftrd0RAP5D3VlGZWG3e1CfxNERQxibRnZpU2I7gCl3wZFwyV6C2ml6bBPI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.45 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wr1-f45.google.com (mail-wr1-f45.google.com [209.85.221.45]) by mx.zohomail.com with SMTPS id 1623952166686873.4184875525061; Thu, 17 Jun 2021 10:49:26 -0700 (PDT) Received: by mail-wr1-f45.google.com with SMTP id y7so7687752wrh.7 for ; Thu, 17 Jun 2021 10:49:25 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.. (93.red-83-35-24.dynamicip.rima-tde.net. [83.35.24.93]) by smtp.gmail.com with ESMTPSA id i16sm5899465wmm.9.2021.06.17.10.49.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Jun 2021 10:49:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ouJW6Tu1Wi2ugnpSAzhcCZMWHmSzJZ21PGf32aTzlN8=; b=ehdwTXi6pK+nUsSJiMCAVu7rD67R4Zbj/qpcKHL5FgVaAjY6NGDWwDFx5O+R9Jtife B8DUR8oLp40hUSZ8qbk8JrsrUod++3Jisx3NTZ+sv0HOiXPWFpb+hnLGnVm84C3GhpSP DDM6YpZ7ZJJ+Kr00iWqfww/SXZj5xaGhnlsSoyNHEVFoaYWILSf2MpDX1I2LI24PD4Wu vPIjcNXNzy94oWGFmyiUzKPdlw+nwJq6+R/0PGPw9c97mvSt9Jjez0WoByqcpHgOnXDG JBau69bgs2TnLtWxPF3Y6KhvFRChCNvY4FvtyKL7KMBgo/WzkbOPr28bOTJ1a26bfe17 5Xjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=ouJW6Tu1Wi2ugnpSAzhcCZMWHmSzJZ21PGf32aTzlN8=; b=KJ+qGsSIXheAu6cPaS2QB78vHJ/4zWV+xdDj5QV6KOMy3IcA4cCeOV067Bj1en23aH JMmIFjPedFAiFWzdp1yAGr3RWpeA00aF3eSqJMAUHKiZzG2qdCwAfN33Q3jsKzA5Gl7x q1PwzTu4Z2KYdhlidMeJQs+l7o8IppxNwYMVcghDDso407c3XVtUvEMB/M553PcuKhMM JQ9Zqb43thmyxFzU3eu4eVo13wIOJYOlCxn4QuKtqwHYYyvnBosC/30Doa4ayEuLW70A V2/H72UKJF2mko+NkrgzO8cApsJDzjvVUbtOWikbAgg/IKnshIgcbGiT7ijrENZaw39R mW1Q== X-Gm-Message-State: AOAM5333iH6KpqkmXtbeLbCeWDKe52pBbfzXFRVEELjLvgOh4Kmb517o Ia1B27HEa7yyl6zwYBIT/CM= X-Google-Smtp-Source: ABdhPJwyEh9fgI03dRyo5tSGbZ4O/0sE6wRrv402Mze3Uo/cHZ7GEBBjDsn5mn4pAOolRB0NIgXnNg== X-Received: by 2002:adf:f98a:: with SMTP id f10mr7291089wrr.143.1623952163821; Thu, 17 Jun 2021 10:49:23 -0700 (PDT) Sender: =?UTF-8?Q?Philippe_Mathieu=2DDaud=C3=A9?= From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Aurelien Jarno , Aleksandar Rikalo , Richard Henderson , Jiaxun Yang Subject: [PATCH 3/4] target/mips: Extract the microMIPS ISA translation routines Date: Thu, 17 Jun 2021 19:49:06 +0200 Message-Id: <20210617174907.2904067-4-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210617174907.2904067-1-f4bug@amsat.org> References: <20210617174907.2904067-1-f4bug@amsat.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @gmail.com) Extract 3200+ lines from the huge translate.c to a new file, 'micromips_translate.c.inc'. As there are too many inter- dependencies we don't compile it as another object, but keep including it in the big translate.o. We gain in code maintainability. Signed-off-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Richard Henderson Message-Id: <20201120210844.2625602-12-f4bug@amsat.org> --- target/mips/tcg/translate.c | 3231 +-------------------- target/mips/tcg/micromips_translate.c.inc | 3231 +++++++++++++++++++++ 2 files changed, 3237 insertions(+), 3225 deletions(-) create mode 100644 target/mips/tcg/micromips_translate.c.inc diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index c939ba09f2b..7b173e2bd2f 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -12442,958 +12442,6 @@ static inline void gen_helper_do_semihosting(void= *env) } #endif =20 -/* microMIPS extension to MIPS32/MIPS64 */ - -/* - * microMIPS32/microMIPS64 major opcodes - * - * 1. MIPS Architecture for Programmers Volume II-B: - * The microMIPS32 Instruction Set (Revision 3.05) - * - * Table 6.2 microMIPS32 Encoding of Major Opcode Field - * - * 2. MIPS Architecture For Programmers Volume II-A: - * The MIPS64 Instruction Set (Revision 3.51) - */ - -enum { - POOL32A =3D 0x00, - POOL16A =3D 0x01, - LBU16 =3D 0x02, - MOVE16 =3D 0x03, - ADDI32 =3D 0x04, - R6_LUI =3D 0x04, - AUI =3D 0x04, - LBU32 =3D 0x05, - SB32 =3D 0x06, - LB32 =3D 0x07, - - POOL32B =3D 0x08, - POOL16B =3D 0x09, - LHU16 =3D 0x0a, - ANDI16 =3D 0x0b, - ADDIU32 =3D 0x0c, - LHU32 =3D 0x0d, - SH32 =3D 0x0e, - LH32 =3D 0x0f, - - POOL32I =3D 0x10, - POOL16C =3D 0x11, - LWSP16 =3D 0x12, - POOL16D =3D 0x13, - ORI32 =3D 0x14, - POOL32F =3D 0x15, - POOL32S =3D 0x16, /* MIPS64 */ - DADDIU32 =3D 0x17, /* MIPS64 */ - - POOL32C =3D 0x18, - LWGP16 =3D 0x19, - LW16 =3D 0x1a, - POOL16E =3D 0x1b, - XORI32 =3D 0x1c, - JALS32 =3D 0x1d, - BOVC =3D 0x1d, - BEQC =3D 0x1d, - BEQZALC =3D 0x1d, - ADDIUPC =3D 0x1e, - PCREL =3D 0x1e, - BNVC =3D 0x1f, - BNEC =3D 0x1f, - BNEZALC =3D 0x1f, - - R6_BEQZC =3D 0x20, - JIC =3D 0x20, - POOL16F =3D 0x21, - SB16 =3D 0x22, - BEQZ16 =3D 0x23, - BEQZC16 =3D 0x23, - SLTI32 =3D 0x24, - BEQ32 =3D 0x25, - BC =3D 0x25, - SWC132 =3D 0x26, - LWC132 =3D 0x27, - - /* 0x29 is reserved */ - RES_29 =3D 0x29, - R6_BNEZC =3D 0x28, - JIALC =3D 0x28, - SH16 =3D 0x2a, - BNEZ16 =3D 0x2b, - BNEZC16 =3D 0x2b, - SLTIU32 =3D 0x2c, - BNE32 =3D 0x2d, - BALC =3D 0x2d, - SDC132 =3D 0x2e, - LDC132 =3D 0x2f, - - /* 0x31 is reserved */ - RES_31 =3D 0x31, - BLEZALC =3D 0x30, - BGEZALC =3D 0x30, - BGEUC =3D 0x30, - SWSP16 =3D 0x32, - B16 =3D 0x33, - BC16 =3D 0x33, - ANDI32 =3D 0x34, - J32 =3D 0x35, - BGTZC =3D 0x35, - BLTZC =3D 0x35, - BLTC =3D 0x35, - SD32 =3D 0x36, /* MIPS64 */ - LD32 =3D 0x37, /* MIPS64 */ - - /* 0x39 is reserved */ - RES_39 =3D 0x39, - BGTZALC =3D 0x38, - BLTZALC =3D 0x38, - BLTUC =3D 0x38, - SW16 =3D 0x3a, - LI16 =3D 0x3b, - JALX32 =3D 0x3c, - JAL32 =3D 0x3d, - BLEZC =3D 0x3d, - BGEZC =3D 0x3d, - BGEC =3D 0x3d, - SW32 =3D 0x3e, - LW32 =3D 0x3f -}; - -/* PCREL Instructions perform PC-Relative address calculation. bits 20..16= */ -enum { - ADDIUPC_00 =3D 0x00, - ADDIUPC_01 =3D 0x01, - ADDIUPC_02 =3D 0x02, - ADDIUPC_03 =3D 0x03, - ADDIUPC_04 =3D 0x04, - ADDIUPC_05 =3D 0x05, - ADDIUPC_06 =3D 0x06, - ADDIUPC_07 =3D 0x07, - AUIPC =3D 0x1e, - ALUIPC =3D 0x1f, - LWPC_08 =3D 0x08, - LWPC_09 =3D 0x09, - LWPC_0A =3D 0x0A, - LWPC_0B =3D 0x0B, - LWPC_0C =3D 0x0C, - LWPC_0D =3D 0x0D, - LWPC_0E =3D 0x0E, - LWPC_0F =3D 0x0F, -}; - -/* POOL32A encoding of minor opcode field */ - -enum { - /* - * These opcodes are distinguished only by bits 9..6; those bits are - * what are recorded below. - */ - SLL32 =3D 0x0, - SRL32 =3D 0x1, - SRA =3D 0x2, - ROTR =3D 0x3, - SELEQZ =3D 0x5, - SELNEZ =3D 0x6, - R6_RDHWR =3D 0x7, - - SLLV =3D 0x0, - SRLV =3D 0x1, - SRAV =3D 0x2, - ROTRV =3D 0x3, - ADD =3D 0x4, - ADDU32 =3D 0x5, - SUB =3D 0x6, - SUBU32 =3D 0x7, - MUL =3D 0x8, - AND =3D 0x9, - OR32 =3D 0xa, - NOR =3D 0xb, - XOR32 =3D 0xc, - SLT =3D 0xd, - SLTU =3D 0xe, - - MOVN =3D 0x0, - R6_MUL =3D 0x0, - MOVZ =3D 0x1, - MUH =3D 0x1, - MULU =3D 0x2, - MUHU =3D 0x3, - LWXS =3D 0x4, - R6_DIV =3D 0x4, - MOD =3D 0x5, - R6_DIVU =3D 0x6, - MODU =3D 0x7, - - /* The following can be distinguished by their lower 6 bits. */ - BREAK32 =3D 0x07, - INS =3D 0x0c, - LSA =3D 0x0f, - ALIGN =3D 0x1f, - EXT =3D 0x2c, - POOL32AXF =3D 0x3c, - SIGRIE =3D 0x3f -}; - -/* POOL32AXF encoding of minor opcode field extension */ - -/* - * 1. MIPS Architecture for Programmers Volume II-B: - * The microMIPS32 Instruction Set (Revision 3.05) - * - * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field - * - * 2. MIPS Architecture for Programmers VolumeIV-e: - * The MIPS DSP Application-Specific Extension - * to the microMIPS32 Architecture (Revision 2.34) - * - * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field - */ - -enum { - /* bits 11..6 */ - TEQ =3D 0x00, - TGE =3D 0x08, - TGEU =3D 0x10, - TLT =3D 0x20, - TLTU =3D 0x28, - TNE =3D 0x30, - - MFC0 =3D 0x03, - MTC0 =3D 0x0b, - - /* begin of microMIPS32 DSP */ - - /* bits 13..12 for 0x01 */ - MFHI_ACC =3D 0x0, - MFLO_ACC =3D 0x1, - MTHI_ACC =3D 0x2, - MTLO_ACC =3D 0x3, - - /* bits 13..12 for 0x2a */ - MADD_ACC =3D 0x0, - MADDU_ACC =3D 0x1, - MSUB_ACC =3D 0x2, - MSUBU_ACC =3D 0x3, - - /* bits 13..12 for 0x32 */ - MULT_ACC =3D 0x0, - MULTU_ACC =3D 0x1, - - /* end of microMIPS32 DSP */ - - /* bits 15..12 for 0x2c */ - BITSWAP =3D 0x0, - SEB =3D 0x2, - SEH =3D 0x3, - CLO =3D 0x4, - CLZ =3D 0x5, - RDHWR =3D 0x6, - WSBH =3D 0x7, - MULT =3D 0x8, - MULTU =3D 0x9, - DIV =3D 0xa, - DIVU =3D 0xb, - MADD =3D 0xc, - MADDU =3D 0xd, - MSUB =3D 0xe, - MSUBU =3D 0xf, - - /* bits 15..12 for 0x34 */ - MFC2 =3D 0x4, - MTC2 =3D 0x5, - MFHC2 =3D 0x8, - MTHC2 =3D 0x9, - CFC2 =3D 0xc, - CTC2 =3D 0xd, - - /* bits 15..12 for 0x3c */ - JALR =3D 0x0, - JR =3D 0x0, /* alias */ - JALRC =3D 0x0, - JRC =3D 0x0, - JALR_HB =3D 0x1, - JALRC_HB =3D 0x1, - JALRS =3D 0x4, - JALRS_HB =3D 0x5, - - /* bits 15..12 for 0x05 */ - RDPGPR =3D 0xe, - WRPGPR =3D 0xf, - - /* bits 15..12 for 0x0d */ - TLBP =3D 0x0, - TLBR =3D 0x1, - TLBWI =3D 0x2, - TLBWR =3D 0x3, - TLBINV =3D 0x4, - TLBINVF =3D 0x5, - WAIT =3D 0x9, - IRET =3D 0xd, - DERET =3D 0xe, - ERET =3D 0xf, - - /* bits 15..12 for 0x15 */ - DMT =3D 0x0, - DVPE =3D 0x1, - EMT =3D 0x2, - EVPE =3D 0x3, - - /* bits 15..12 for 0x1d */ - DI =3D 0x4, - EI =3D 0x5, - - /* bits 15..12 for 0x2d */ - SYNC =3D 0x6, - SYSCALL =3D 0x8, - SDBBP =3D 0xd, - - /* bits 15..12 for 0x35 */ - MFHI32 =3D 0x0, - MFLO32 =3D 0x1, - MTHI32 =3D 0x2, - MTLO32 =3D 0x3, -}; - -/* POOL32B encoding of minor opcode field (bits 15..12) */ - -enum { - LWC2 =3D 0x0, - LWP =3D 0x1, - LDP =3D 0x4, - LWM32 =3D 0x5, - CACHE =3D 0x6, - LDM =3D 0x7, - SWC2 =3D 0x8, - SWP =3D 0x9, - SDP =3D 0xc, - SWM32 =3D 0xd, - SDM =3D 0xf -}; - -/* POOL32C encoding of minor opcode field (bits 15..12) */ - -enum { - LWL =3D 0x0, - SWL =3D 0x8, - LWR =3D 0x1, - SWR =3D 0x9, - PREF =3D 0x2, - ST_EVA =3D 0xa, - LL =3D 0x3, - SC =3D 0xb, - LDL =3D 0x4, - SDL =3D 0xc, - LDR =3D 0x5, - SDR =3D 0xd, - LD_EVA =3D 0x6, - LWU =3D 0xe, - LLD =3D 0x7, - SCD =3D 0xf -}; - -/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */ - -enum { - LBUE =3D 0x0, - LHUE =3D 0x1, - LWLE =3D 0x2, - LWRE =3D 0x3, - LBE =3D 0x4, - LHE =3D 0x5, - LLE =3D 0x6, - LWE =3D 0x7, -}; - -/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */ - -enum { - SWLE =3D 0x0, - SWRE =3D 0x1, - PREFE =3D 0x2, - CACHEE =3D 0x3, - SBE =3D 0x4, - SHE =3D 0x5, - SCE =3D 0x6, - SWE =3D 0x7, -}; - -/* POOL32F encoding of minor opcode field (bits 5..0) */ - -enum { - /* These are the bit 7..6 values */ - ADD_FMT =3D 0x0, - - SUB_FMT =3D 0x1, - - MUL_FMT =3D 0x2, - - DIV_FMT =3D 0x3, - - /* These are the bit 8..6 values */ - MOVN_FMT =3D 0x0, - RSQRT2_FMT =3D 0x0, - MOVF_FMT =3D 0x0, - RINT_FMT =3D 0x0, - SELNEZ_FMT =3D 0x0, - - MOVZ_FMT =3D 0x1, - LWXC1 =3D 0x1, - MOVT_FMT =3D 0x1, - CLASS_FMT =3D 0x1, - SELEQZ_FMT =3D 0x1, - - PLL_PS =3D 0x2, - SWXC1 =3D 0x2, - SEL_FMT =3D 0x2, - - PLU_PS =3D 0x3, - LDXC1 =3D 0x3, - - MOVN_FMT_04 =3D 0x4, - PUL_PS =3D 0x4, - SDXC1 =3D 0x4, - RECIP2_FMT =3D 0x4, - - MOVZ_FMT_05 =3D 0x05, - PUU_PS =3D 0x5, - LUXC1 =3D 0x5, - - CVT_PS_S =3D 0x6, - SUXC1 =3D 0x6, - ADDR_PS =3D 0x6, - PREFX =3D 0x6, - MADDF_FMT =3D 0x6, - - MULR_PS =3D 0x7, - MSUBF_FMT =3D 0x7, - - MADD_S =3D 0x01, - MADD_D =3D 0x09, - MADD_PS =3D 0x11, - ALNV_PS =3D 0x19, - MSUB_S =3D 0x21, - MSUB_D =3D 0x29, - MSUB_PS =3D 0x31, - - NMADD_S =3D 0x02, - NMADD_D =3D 0x0a, - NMADD_PS =3D 0x12, - NMSUB_S =3D 0x22, - NMSUB_D =3D 0x2a, - NMSUB_PS =3D 0x32, - - MIN_FMT =3D 0x3, - MAX_FMT =3D 0xb, - MINA_FMT =3D 0x23, - MAXA_FMT =3D 0x2b, - POOL32FXF =3D 0x3b, - - CABS_COND_FMT =3D 0x1c, /* MIPS3D */ - C_COND_FMT =3D 0x3c, - - CMP_CONDN_S =3D 0x5, - CMP_CONDN_D =3D 0x15 -}; - -/* POOL32Fxf encoding of minor opcode extension field */ - -enum { - CVT_L =3D 0x04, - RSQRT_FMT =3D 0x08, - FLOOR_L =3D 0x0c, - CVT_PW_PS =3D 0x1c, - CVT_W =3D 0x24, - SQRT_FMT =3D 0x28, - FLOOR_W =3D 0x2c, - CVT_PS_PW =3D 0x3c, - CFC1 =3D 0x40, - RECIP_FMT =3D 0x48, - CEIL_L =3D 0x4c, - CTC1 =3D 0x60, - CEIL_W =3D 0x6c, - MFC1 =3D 0x80, - CVT_S_PL =3D 0x84, - TRUNC_L =3D 0x8c, - MTC1 =3D 0xa0, - CVT_S_PU =3D 0xa4, - TRUNC_W =3D 0xac, - MFHC1 =3D 0xc0, - ROUND_L =3D 0xcc, - MTHC1 =3D 0xe0, - ROUND_W =3D 0xec, - - MOV_FMT =3D 0x01, - MOVF =3D 0x05, - ABS_FMT =3D 0x0d, - RSQRT1_FMT =3D 0x1d, - MOVT =3D 0x25, - NEG_FMT =3D 0x2d, - CVT_D =3D 0x4d, - RECIP1_FMT =3D 0x5d, - CVT_S =3D 0x6d -}; - -/* POOL32I encoding of minor opcode field (bits 25..21) */ - -enum { - BLTZ =3D 0x00, - BLTZAL =3D 0x01, - BGEZ =3D 0x02, - BGEZAL =3D 0x03, - BLEZ =3D 0x04, - BNEZC =3D 0x05, - BGTZ =3D 0x06, - BEQZC =3D 0x07, - TLTI =3D 0x08, - BC1EQZC =3D 0x08, - TGEI =3D 0x09, - BC1NEZC =3D 0x09, - TLTIU =3D 0x0a, - BC2EQZC =3D 0x0a, - TGEIU =3D 0x0b, - BC2NEZC =3D 0x0a, - TNEI =3D 0x0c, - R6_SYNCI =3D 0x0c, - LUI =3D 0x0d, - TEQI =3D 0x0e, - SYNCI =3D 0x10, - BLTZALS =3D 0x11, - BGEZALS =3D 0x13, - BC2F =3D 0x14, - BC2T =3D 0x15, - /* These overlap and are distinguished by bit16 of the instruction */ - BC1F =3D 0x1c, - BC1T =3D 0x1d, - BC1ANY2F =3D 0x1c, - BC1ANY2T =3D 0x1d, - BC1ANY4F =3D 0x1e, - BC1ANY4T =3D 0x1f -}; - -/* POOL16A encoding of minor opcode field */ - -enum { - ADDU16 =3D 0x0, - SUBU16 =3D 0x1 -}; - -/* POOL16B encoding of minor opcode field */ - -enum { - SLL16 =3D 0x0, - SRL16 =3D 0x1 -}; - -/* POOL16C encoding of minor opcode field */ - -enum { - NOT16 =3D 0x00, - XOR16 =3D 0x04, - AND16 =3D 0x08, - OR16 =3D 0x0c, - LWM16 =3D 0x10, - SWM16 =3D 0x14, - JR16 =3D 0x18, - JRC16 =3D 0x1a, - JALR16 =3D 0x1c, - JALR16S =3D 0x1e, - MFHI16 =3D 0x20, - MFLO16 =3D 0x24, - BREAK16 =3D 0x28, - SDBBP16 =3D 0x2c, - JRADDIUSP =3D 0x30 -}; - -/* R6 POOL16C encoding of minor opcode field (bits 0..5) */ - -enum { - R6_NOT16 =3D 0x00, - R6_AND16 =3D 0x01, - R6_LWM16 =3D 0x02, - R6_JRC16 =3D 0x03, - MOVEP =3D 0x04, - MOVEP_05 =3D 0x05, - MOVEP_06 =3D 0x06, - MOVEP_07 =3D 0x07, - R6_XOR16 =3D 0x08, - R6_OR16 =3D 0x09, - R6_SWM16 =3D 0x0a, - JALRC16 =3D 0x0b, - MOVEP_0C =3D 0x0c, - MOVEP_0D =3D 0x0d, - MOVEP_0E =3D 0x0e, - MOVEP_0F =3D 0x0f, - JRCADDIUSP =3D 0x13, - R6_BREAK16 =3D 0x1b, - R6_SDBBP16 =3D 0x3b -}; - -/* POOL16D encoding of minor opcode field */ - -enum { - ADDIUS5 =3D 0x0, - ADDIUSP =3D 0x1 -}; - -/* POOL16E encoding of minor opcode field */ - -enum { - ADDIUR2 =3D 0x0, - ADDIUR1SP =3D 0x1 -}; - -static int mmreg(int r) -{ - static const int map[] =3D { 16, 17, 2, 3, 4, 5, 6, 7 }; - - return map[r]; -} - -/* Used for 16-bit store instructions. */ -static int mmreg2(int r) -{ - static const int map[] =3D { 0, 17, 2, 3, 4, 5, 6, 7 }; - - return map[r]; -} - -#define uMIPS_RD(op) ((op >> 7) & 0x7) -#define uMIPS_RS(op) ((op >> 4) & 0x7) -#define uMIPS_RS2(op) uMIPS_RS(op) -#define uMIPS_RS1(op) ((op >> 1) & 0x7) -#define uMIPS_RD5(op) ((op >> 5) & 0x1f) -#define uMIPS_RS5(op) (op & 0x1f) - -/* Signed immediate */ -#define SIMM(op, start, width) \ - ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \ - << (32 - width)) \ - >> (32 - width)) -/* Zero-extended immediate */ -#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width))) - -static void gen_addiur1sp(DisasContext *ctx) -{ - int rd =3D mmreg(uMIPS_RD(ctx->opcode)); - - gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2= ); -} - -static void gen_addiur2(DisasContext *ctx) -{ - static const int decoded_imm[] =3D { 1, 4, 8, 12, 16, 20, 24, -1 }; - int rd =3D mmreg(uMIPS_RD(ctx->opcode)); - int rs =3D mmreg(uMIPS_RS(ctx->opcode)); - - gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1,= 3)]); -} - -static void gen_addiusp(DisasContext *ctx) -{ - int encoded =3D ZIMM(ctx->opcode, 1, 9); - int decoded; - - if (encoded <=3D 1) { - decoded =3D 256 + encoded; - } else if (encoded <=3D 255) { - decoded =3D encoded; - } else if (encoded <=3D 509) { - decoded =3D encoded - 512; - } else { - decoded =3D encoded - 768; - } - - gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2); -} - -static void gen_addius5(DisasContext *ctx) -{ - int imm =3D SIMM(ctx->opcode, 1, 4); - int rd =3D (ctx->opcode >> 5) & 0x1f; - - gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm); -} - -static void gen_andi16(DisasContext *ctx) -{ - static const int decoded_imm[] =3D { 128, 1, 2, 3, 4, 7, 8, 15, 16, - 31, 32, 63, 64, 255, 32768, 65535 }; - int rd =3D mmreg(uMIPS_RD(ctx->opcode)); - int rs =3D mmreg(uMIPS_RS(ctx->opcode)); - int encoded =3D ZIMM(ctx->opcode, 0, 4); - - gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]); -} - -static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist, - int base, int16_t offset) -{ - TCGv t0, t1; - TCGv_i32 t2; - - if (ctx->hflags & MIPS_HFLAG_BMASK) { - gen_reserved_instruction(ctx); - return; - } - - t0 =3D tcg_temp_new(); - - gen_base_offset_addr(ctx, t0, base, offset); - - t1 =3D tcg_const_tl(reglist); - t2 =3D tcg_const_i32(ctx->mem_idx); - - save_cpu_state(ctx, 1); - switch (opc) { - case LWM32: - gen_helper_lwm(cpu_env, t0, t1, t2); - break; - case SWM32: - gen_helper_swm(cpu_env, t0, t1, t2); - break; -#ifdef TARGET_MIPS64 - case LDM: - gen_helper_ldm(cpu_env, t0, t1, t2); - break; - case SDM: - gen_helper_sdm(cpu_env, t0, t1, t2); - break; -#endif - } - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free_i32(t2); -} - - -static void gen_pool16c_insn(DisasContext *ctx) -{ - int rd =3D mmreg((ctx->opcode >> 3) & 0x7); - int rs =3D mmreg(ctx->opcode & 0x7); - - switch (((ctx->opcode) >> 4) & 0x3f) { - case NOT16 + 0: - case NOT16 + 1: - case NOT16 + 2: - case NOT16 + 3: - gen_logic(ctx, OPC_NOR, rd, rs, 0); - break; - case XOR16 + 0: - case XOR16 + 1: - case XOR16 + 2: - case XOR16 + 3: - gen_logic(ctx, OPC_XOR, rd, rd, rs); - break; - case AND16 + 0: - case AND16 + 1: - case AND16 + 2: - case AND16 + 3: - gen_logic(ctx, OPC_AND, rd, rd, rs); - break; - case OR16 + 0: - case OR16 + 1: - case OR16 + 2: - case OR16 + 3: - gen_logic(ctx, OPC_OR, rd, rd, rs); - break; - case LWM16 + 0: - case LWM16 + 1: - case LWM16 + 2: - case LWM16 + 3: - { - static const int lwm_convert[] =3D { 0x11, 0x12, 0x13, 0x14 }; - int offset =3D ZIMM(ctx->opcode, 0, 4); - - gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) &= 0x3], - 29, offset << 2); - } - break; - case SWM16 + 0: - case SWM16 + 1: - case SWM16 + 2: - case SWM16 + 3: - { - static const int swm_convert[] =3D { 0x11, 0x12, 0x13, 0x14 }; - int offset =3D ZIMM(ctx->opcode, 0, 4); - - gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) &= 0x3], - 29, offset << 2); - } - break; - case JR16 + 0: - case JR16 + 1: - { - int reg =3D ctx->opcode & 0x1f; - - gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4); - } - break; - case JRC16 + 0: - case JRC16 + 1: - { - int reg =3D ctx->opcode & 0x1f; - gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0); - /* - * Let normal delay slot handling in our caller take us - * to the branch target. - */ - } - break; - case JALR16 + 0: - case JALR16 + 1: - gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4); - ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; - break; - case JALR16S + 0: - case JALR16S + 1: - gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2); - ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; - break; - case MFHI16 + 0: - case MFHI16 + 1: - gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode)); - break; - case MFLO16 + 0: - case MFLO16 + 1: - gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode)); - break; - case BREAK16: - generate_exception_end(ctx, EXCP_BREAK); - break; - case SDBBP16: - if (is_uhi(extract32(ctx->opcode, 0, 4))) { - gen_helper_do_semihosting(cpu_env); - } else { - /* - * XXX: not clear which exception should be raised - * when in debug mode... - */ - check_insn(ctx, ISA_MIPS_R1); - generate_exception_end(ctx, EXCP_DBp); - } - break; - case JRADDIUSP + 0: - case JRADDIUSP + 1: - { - int imm =3D ZIMM(ctx->opcode, 0, 5); - gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0); - gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2); - /* - * Let normal delay slot handling in our caller take us - * to the branch target. - */ - } - break; - default: - gen_reserved_instruction(ctx); - break; - } -} - -static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt, - int enc_rs) -{ - int rd, re; - static const int rd_enc[] =3D { 5, 5, 6, 4, 4, 4, 4, 4 }; - static const int re_enc[] =3D { 6, 7, 7, 21, 22, 5, 6, 7 }; - static const int rs_rt_enc[] =3D { 0, 17, 2, 3, 16, 18, 19, 20 }; - - rd =3D rd_enc[enc_dest]; - re =3D re_enc[enc_dest]; - gen_load_gpr(cpu_gpr[rd], rs_rt_enc[enc_rs]); - gen_load_gpr(cpu_gpr[re], rs_rt_enc[enc_rt]); -} - -static void gen_pool16c_r6_insn(DisasContext *ctx) -{ - int rt =3D mmreg((ctx->opcode >> 7) & 0x7); - int rs =3D mmreg((ctx->opcode >> 4) & 0x7); - - switch (ctx->opcode & 0xf) { - case R6_NOT16: - gen_logic(ctx, OPC_NOR, rt, rs, 0); - break; - case R6_AND16: - gen_logic(ctx, OPC_AND, rt, rt, rs); - break; - case R6_LWM16: - { - int lwm_converted =3D 0x11 + extract32(ctx->opcode, 8, 2); - int offset =3D extract32(ctx->opcode, 4, 4); - gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2); - } - break; - case R6_JRC16: /* JRCADDIUSP */ - if ((ctx->opcode >> 4) & 1) { - /* JRCADDIUSP */ - int imm =3D extract32(ctx->opcode, 5, 5); - gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0); - gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2); - } else { - /* JRC16 */ - rs =3D extract32(ctx->opcode, 5, 5); - gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0); - } - break; - case MOVEP: - case MOVEP_05: - case MOVEP_06: - case MOVEP_07: - case MOVEP_0C: - case MOVEP_0D: - case MOVEP_0E: - case MOVEP_0F: - { - int enc_dest =3D uMIPS_RD(ctx->opcode); - int enc_rt =3D uMIPS_RS2(ctx->opcode); - int enc_rs =3D (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4); - gen_movep(ctx, enc_dest, enc_rt, enc_rs); - } - break; - case R6_XOR16: - gen_logic(ctx, OPC_XOR, rt, rt, rs); - break; - case R6_OR16: - gen_logic(ctx, OPC_OR, rt, rt, rs); - break; - case R6_SWM16: - { - int swm_converted =3D 0x11 + extract32(ctx->opcode, 8, 2); - int offset =3D extract32(ctx->opcode, 4, 4); - gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2); - } - break; - case JALRC16: /* BREAK16, SDBBP16 */ - switch (ctx->opcode & 0x3f) { - case JALRC16: - case JALRC16 + 0x20: - /* JALRC16 */ - gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f, - 31, 0, 0); - break; - case R6_BREAK16: - /* BREAK16 */ - generate_exception(ctx, EXCP_BREAK); - break; - case R6_SDBBP16: - /* SDBBP16 */ - if (is_uhi(extract32(ctx->opcode, 6, 4))) { - gen_helper_do_semihosting(cpu_env); - } else { - if (ctx->hflags & MIPS_HFLAG_SBRI) { - generate_exception(ctx, EXCP_RI); - } else { - generate_exception(ctx, EXCP_DBp); - } - } - break; - } - break; - default: - generate_exception(ctx, EXCP_RI); - break; - } -} - void gen_ldxs(DisasContext *ctx, int base, int index, int rd) { TCGv t0 =3D tcg_temp_new(); @@ -13414,69 +12462,6 @@ void gen_ldxs(DisasContext *ctx, int base, int ind= ex, int rd) tcg_temp_free(t1); } =20 -static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd, - int base, int16_t offset) -{ - TCGv t0, t1; - - if (ctx->hflags & MIPS_HFLAG_BMASK || rd =3D=3D 31) { - gen_reserved_instruction(ctx); - return; - } - - t0 =3D tcg_temp_new(); - t1 =3D tcg_temp_new(); - - gen_base_offset_addr(ctx, t0, base, offset); - - switch (opc) { - case LWP: - if (rd =3D=3D base) { - gen_reserved_instruction(ctx); - return; - } - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); - gen_store_gpr(t1, rd); - tcg_gen_movi_tl(t1, 4); - gen_op_addr_add(ctx, t0, t0, t1); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); - gen_store_gpr(t1, rd + 1); - break; - case SWP: - gen_load_gpr(t1, rd); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - tcg_gen_movi_tl(t1, 4); - gen_op_addr_add(ctx, t0, t0, t1); - gen_load_gpr(t1, rd + 1); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - break; -#ifdef TARGET_MIPS64 - case LDP: - if (rd =3D=3D base) { - gen_reserved_instruction(ctx); - return; - } - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); - gen_store_gpr(t1, rd); - tcg_gen_movi_tl(t1, 8); - gen_op_addr_add(ctx, t0, t0, t1); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); - gen_store_gpr(t1, rd + 1); - break; - case SDP: - gen_load_gpr(t1, rd); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ); - tcg_gen_movi_tl(t1, 8); - gen_op_addr_add(ctx, t0, t0, t1); - gen_load_gpr(t1, rd + 1); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ); - break; -#endif - } - tcg_temp_free(t0); - tcg_temp_free(t1); -} - static void gen_sync(int stype) { TCGBar tcg_mo =3D TCG_BAR_SC; @@ -13505,353 +12490,12 @@ static void gen_sync(int stype) tcg_gen_mb(tcg_mo); } =20 -static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, in= t rs) -{ - int extension =3D (ctx->opcode >> 6) & 0x3f; - int minor =3D (ctx->opcode >> 12) & 0xf; - uint32_t mips32_op; +/* ISA extensions (ASEs) */ =20 - switch (extension) { - case TEQ: - mips32_op =3D OPC_TEQ; - goto do_trap; - case TGE: - mips32_op =3D OPC_TGE; - goto do_trap; - case TGEU: - mips32_op =3D OPC_TGEU; - goto do_trap; - case TLT: - mips32_op =3D OPC_TLT; - goto do_trap; - case TLTU: - mips32_op =3D OPC_TLTU; - goto do_trap; - case TNE: - mips32_op =3D OPC_TNE; - do_trap: - gen_trap(ctx, mips32_op, rs, rt, -1); - break; -#ifndef CONFIG_USER_ONLY - case MFC0: - case MFC0 + 32: - check_cp0_enabled(ctx); - if (rt =3D=3D 0) { - /* Treat as NOP. */ - break; - } - gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7); - break; - case MTC0: - case MTC0 + 32: - check_cp0_enabled(ctx); - { - TCGv t0 =3D tcg_temp_new(); +/* MIPS16 extension to MIPS32 */ +#include "mips16e_translate.c.inc" =20 - gen_load_gpr(t0, rt); - gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7); - tcg_temp_free(t0); - } - break; -#endif - case 0x2a: - switch (minor & 3) { - case MADD_ACC: - gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt); - break; - case MADDU_ACC: - gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt); - break; - case MSUB_ACC: - gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt); - break; - case MSUBU_ACC: - gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x32: - switch (minor & 3) { - case MULT_ACC: - gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt); - break; - case MULTU_ACC: - gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x2c: - switch (minor) { - case BITSWAP: - check_insn(ctx, ISA_MIPS_R6); - gen_bitswap(ctx, OPC_BITSWAP, rs, rt); - break; - case SEB: - gen_bshfl(ctx, OPC_SEB, rs, rt); - break; - case SEH: - gen_bshfl(ctx, OPC_SEH, rs, rt); - break; - case CLO: - mips32_op =3D OPC_CLO; - goto do_cl; - case CLZ: - mips32_op =3D OPC_CLZ; - do_cl: - check_insn(ctx, ISA_MIPS_R1); - gen_cl(ctx, mips32_op, rt, rs); - break; - case RDHWR: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_rdhwr(ctx, rt, rs, 0); - break; - case WSBH: - gen_bshfl(ctx, OPC_WSBH, rs, rt); - break; - case MULT: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MULT; - goto do_mul; - case MULTU: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MULTU; - goto do_mul; - case DIV: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_DIV; - goto do_div; - case DIVU: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_DIVU; - goto do_div; - do_div: - check_insn(ctx, ISA_MIPS_R1); - gen_muldiv(ctx, mips32_op, 0, rs, rt); - break; - case MADD: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MADD; - goto do_mul; - case MADDU: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MADDU; - goto do_mul; - case MSUB: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MSUB; - goto do_mul; - case MSUBU: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MSUBU; - do_mul: - check_insn(ctx, ISA_MIPS_R1); - gen_muldiv(ctx, mips32_op, 0, rs, rt); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x34: - switch (minor) { - case MFC2: - case MTC2: - case MFHC2: - case MTHC2: - case CFC2: - case CTC2: - generate_exception_err(ctx, EXCP_CpU, 2); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x3c: - switch (minor) { - case JALR: /* JALRC */ - case JALR_HB: /* JALRC_HB */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* JALRC, JALRC_HB */ - gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0); - } else { - /* JALR, JALR_HB */ - gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4); - ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; - } - break; - case JALRS: - case JALRS_HB: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2); - ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; - break; - default: - goto pool32axf_invalid; - } - break; - case 0x05: - switch (minor) { - case RDPGPR: - check_cp0_enabled(ctx); - check_insn(ctx, ISA_MIPS_R2); - gen_load_srsgpr(rs, rt); - break; - case WRPGPR: - check_cp0_enabled(ctx); - check_insn(ctx, ISA_MIPS_R2); - gen_store_srsgpr(rs, rt); - break; - default: - goto pool32axf_invalid; - } - break; -#ifndef CONFIG_USER_ONLY - case 0x0d: - switch (minor) { - case TLBP: - mips32_op =3D OPC_TLBP; - goto do_cp0; - case TLBR: - mips32_op =3D OPC_TLBR; - goto do_cp0; - case TLBWI: - mips32_op =3D OPC_TLBWI; - goto do_cp0; - case TLBWR: - mips32_op =3D OPC_TLBWR; - goto do_cp0; - case TLBINV: - mips32_op =3D OPC_TLBINV; - goto do_cp0; - case TLBINVF: - mips32_op =3D OPC_TLBINVF; - goto do_cp0; - case WAIT: - mips32_op =3D OPC_WAIT; - goto do_cp0; - case DERET: - mips32_op =3D OPC_DERET; - goto do_cp0; - case ERET: - mips32_op =3D OPC_ERET; - do_cp0: - gen_cp0(env, ctx, mips32_op, rt, rs); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x1d: - switch (minor) { - case DI: - check_cp0_enabled(ctx); - { - TCGv t0 =3D tcg_temp_new(); - - save_cpu_state(ctx, 1); - gen_helper_di(t0, cpu_env); - gen_store_gpr(t0, rs); - /* - * Stop translation as we may have switched the execution - * mode. - */ - ctx->base.is_jmp =3D DISAS_STOP; - tcg_temp_free(t0); - } - break; - case EI: - check_cp0_enabled(ctx); - { - TCGv t0 =3D tcg_temp_new(); - - save_cpu_state(ctx, 1); - gen_helper_ei(t0, cpu_env); - gen_store_gpr(t0, rs); - /* - * DISAS_STOP isn't sufficient, we need to ensure we break= out - * of translated code to check for pending interrupts. - */ - gen_save_pc(ctx->base.pc_next + 4); - ctx->base.is_jmp =3D DISAS_EXIT; - tcg_temp_free(t0); - } - break; - default: - goto pool32axf_invalid; - } - break; -#endif - case 0x2d: - switch (minor) { - case SYNC: - gen_sync(extract32(ctx->opcode, 16, 5)); - break; - case SYSCALL: - generate_exception_end(ctx, EXCP_SYSCALL); - break; - case SDBBP: - if (is_uhi(extract32(ctx->opcode, 16, 10))) { - gen_helper_do_semihosting(cpu_env); - } else { - check_insn(ctx, ISA_MIPS_R1); - if (ctx->hflags & MIPS_HFLAG_SBRI) { - gen_reserved_instruction(ctx); - } else { - generate_exception_end(ctx, EXCP_DBp); - } - } - break; - default: - goto pool32axf_invalid; - } - break; - case 0x01: - switch (minor & 3) { - case MFHI_ACC: - gen_HILO(ctx, OPC_MFHI, minor >> 2, rs); - break; - case MFLO_ACC: - gen_HILO(ctx, OPC_MFLO, minor >> 2, rs); - break; - case MTHI_ACC: - gen_HILO(ctx, OPC_MTHI, minor >> 2, rs); - break; - case MTLO_ACC: - gen_HILO(ctx, OPC_MTLO, minor >> 2, rs); - break; - default: - goto pool32axf_invalid; - } - break; - case 0x35: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - switch (minor) { - case MFHI32: - gen_HILO(ctx, OPC_MFHI, 0, rs); - break; - case MFLO32: - gen_HILO(ctx, OPC_MFLO, 0, rs); - break; - case MTHI32: - gen_HILO(ctx, OPC_MTHI, 0, rs); - break; - case MTLO32: - gen_HILO(ctx, OPC_MTLO, 0, rs); - break; - default: - goto pool32axf_invalid; - } - break; - default: - pool32axf_invalid: - MIPS_INVAL("pool32axf"); - gen_reserved_instruction(ctx); - break; - } -} +/* microMIPS extension to MIPS32/MIPS64 */ =20 /* * Values for microMIPS fmt field. Variable-width, depending on which @@ -13874,1870 +12518,7 @@ enum { FMT_DWL_L =3D 2 }; =20 -static void gen_pool32fxf(DisasContext *ctx, int rt, int rs) -{ - int extension =3D (ctx->opcode >> 6) & 0x3ff; - uint32_t mips32_op; - -#define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc) -#define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc) -#define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc) - - switch (extension) { - case FLOAT_1BIT_FMT(CFC1, 0): - mips32_op =3D OPC_CFC1; - goto do_cp1; - case FLOAT_1BIT_FMT(CTC1, 0): - mips32_op =3D OPC_CTC1; - goto do_cp1; - case FLOAT_1BIT_FMT(MFC1, 0): - mips32_op =3D OPC_MFC1; - goto do_cp1; - case FLOAT_1BIT_FMT(MTC1, 0): - mips32_op =3D OPC_MTC1; - goto do_cp1; - case FLOAT_1BIT_FMT(MFHC1, 0): - mips32_op =3D OPC_MFHC1; - goto do_cp1; - case FLOAT_1BIT_FMT(MTHC1, 0): - mips32_op =3D OPC_MTHC1; - do_cp1: - gen_cp1(ctx, mips32_op, rt, rs); - break; - - /* Reciprocal square root */ - case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S): - mips32_op =3D OPC_RSQRT_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D): - mips32_op =3D OPC_RSQRT_D; - goto do_unaryfp; - - /* Square root */ - case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S): - mips32_op =3D OPC_SQRT_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D): - mips32_op =3D OPC_SQRT_D; - goto do_unaryfp; - - /* Reciprocal */ - case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S): - mips32_op =3D OPC_RECIP_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D): - mips32_op =3D OPC_RECIP_D; - goto do_unaryfp; - - /* Floor */ - case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S): - mips32_op =3D OPC_FLOOR_L_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D): - mips32_op =3D OPC_FLOOR_L_D; - goto do_unaryfp; - case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S): - mips32_op =3D OPC_FLOOR_W_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D): - mips32_op =3D OPC_FLOOR_W_D; - goto do_unaryfp; - - /* Ceiling */ - case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S): - mips32_op =3D OPC_CEIL_L_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D): - mips32_op =3D OPC_CEIL_L_D; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S): - mips32_op =3D OPC_CEIL_W_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D): - mips32_op =3D OPC_CEIL_W_D; - goto do_unaryfp; - - /* Truncation */ - case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S): - mips32_op =3D OPC_TRUNC_L_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D): - mips32_op =3D OPC_TRUNC_L_D; - goto do_unaryfp; - case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S): - mips32_op =3D OPC_TRUNC_W_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D): - mips32_op =3D OPC_TRUNC_W_D; - goto do_unaryfp; - - /* Round */ - case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S): - mips32_op =3D OPC_ROUND_L_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D): - mips32_op =3D OPC_ROUND_L_D; - goto do_unaryfp; - case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S): - mips32_op =3D OPC_ROUND_W_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D): - mips32_op =3D OPC_ROUND_W_D; - goto do_unaryfp; - - /* Integer to floating-point conversion */ - case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S): - mips32_op =3D OPC_CVT_L_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D): - mips32_op =3D OPC_CVT_L_D; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S): - mips32_op =3D OPC_CVT_W_S; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D): - mips32_op =3D OPC_CVT_W_D; - goto do_unaryfp; - - /* Paired-foo conversions */ - case FLOAT_1BIT_FMT(CVT_S_PL, 0): - mips32_op =3D OPC_CVT_S_PL; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_S_PU, 0): - mips32_op =3D OPC_CVT_S_PU; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_PW_PS, 0): - mips32_op =3D OPC_CVT_PW_PS; - goto do_unaryfp; - case FLOAT_1BIT_FMT(CVT_PS_PW, 0): - mips32_op =3D OPC_CVT_PS_PW; - goto do_unaryfp; - - /* Floating-point moves */ - case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S): - mips32_op =3D OPC_MOV_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D): - mips32_op =3D OPC_MOV_D; - goto do_unaryfp; - case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS): - mips32_op =3D OPC_MOV_PS; - goto do_unaryfp; - - /* Absolute value */ - case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S): - mips32_op =3D OPC_ABS_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D): - mips32_op =3D OPC_ABS_D; - goto do_unaryfp; - case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS): - mips32_op =3D OPC_ABS_PS; - goto do_unaryfp; - - /* Negation */ - case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S): - mips32_op =3D OPC_NEG_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D): - mips32_op =3D OPC_NEG_D; - goto do_unaryfp; - case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS): - mips32_op =3D OPC_NEG_PS; - goto do_unaryfp; - - /* Reciprocal square root step */ - case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S): - mips32_op =3D OPC_RSQRT1_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D): - mips32_op =3D OPC_RSQRT1_D; - goto do_unaryfp; - case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS): - mips32_op =3D OPC_RSQRT1_PS; - goto do_unaryfp; - - /* Reciprocal step */ - case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S): - mips32_op =3D OPC_RECIP1_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D): - mips32_op =3D OPC_RECIP1_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS): - mips32_op =3D OPC_RECIP1_PS; - goto do_unaryfp; - - /* Conversions from double */ - case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S): - mips32_op =3D OPC_CVT_D_S; - goto do_unaryfp; - case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W): - mips32_op =3D OPC_CVT_D_W; - goto do_unaryfp; - case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L): - mips32_op =3D OPC_CVT_D_L; - goto do_unaryfp; - - /* Conversions from single */ - case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D): - mips32_op =3D OPC_CVT_S_D; - goto do_unaryfp; - case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W): - mips32_op =3D OPC_CVT_S_W; - goto do_unaryfp; - case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L): - mips32_op =3D OPC_CVT_S_L; - do_unaryfp: - gen_farith(ctx, mips32_op, -1, rs, rt, 0); - break; - - /* Conditional moves on floating-point codes */ - case COND_FLOAT_MOV(MOVT, 0): - case COND_FLOAT_MOV(MOVT, 1): - case COND_FLOAT_MOV(MOVT, 2): - case COND_FLOAT_MOV(MOVT, 3): - case COND_FLOAT_MOV(MOVT, 4): - case COND_FLOAT_MOV(MOVT, 5): - case COND_FLOAT_MOV(MOVT, 6): - case COND_FLOAT_MOV(MOVT, 7): - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1); - break; - case COND_FLOAT_MOV(MOVF, 0): - case COND_FLOAT_MOV(MOVF, 1): - case COND_FLOAT_MOV(MOVF, 2): - case COND_FLOAT_MOV(MOVF, 3): - case COND_FLOAT_MOV(MOVF, 4): - case COND_FLOAT_MOV(MOVF, 5): - case COND_FLOAT_MOV(MOVF, 6): - case COND_FLOAT_MOV(MOVF, 7): - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0); - break; - default: - MIPS_INVAL("pool32fxf"); - gen_reserved_instruction(ctx); - break; - } -} - -static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) -{ - int32_t offset; - uint16_t insn; - int rt, rs, rd, rr; - int16_t imm; - uint32_t op, minor, minor2, mips32_op; - uint32_t cond, fmt, cc; - - insn =3D translator_lduw(env, ctx->base.pc_next + 2); - ctx->opcode =3D (ctx->opcode << 16) | insn; - - rt =3D (ctx->opcode >> 21) & 0x1f; - rs =3D (ctx->opcode >> 16) & 0x1f; - rd =3D (ctx->opcode >> 11) & 0x1f; - rr =3D (ctx->opcode >> 6) & 0x1f; - imm =3D (int16_t) ctx->opcode; - - op =3D (ctx->opcode >> 26) & 0x3f; - switch (op) { - case POOL32A: - minor =3D ctx->opcode & 0x3f; - switch (minor) { - case 0x00: - minor =3D (ctx->opcode >> 6) & 0xf; - switch (minor) { - case SLL32: - mips32_op =3D OPC_SLL; - goto do_shifti; - case SRA: - mips32_op =3D OPC_SRA; - goto do_shifti; - case SRL32: - mips32_op =3D OPC_SRL; - goto do_shifti; - case ROTR: - mips32_op =3D OPC_ROTR; - do_shifti: - gen_shift_imm(ctx, mips32_op, rt, rs, rd); - break; - case SELEQZ: - check_insn(ctx, ISA_MIPS_R6); - gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt); - break; - case SELNEZ: - check_insn(ctx, ISA_MIPS_R6); - gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt); - break; - case R6_RDHWR: - check_insn(ctx, ISA_MIPS_R6); - gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); - break; - default: - goto pool32a_invalid; - } - break; - case 0x10: - minor =3D (ctx->opcode >> 6) & 0xf; - switch (minor) { - /* Arithmetic */ - case ADD: - mips32_op =3D OPC_ADD; - goto do_arith; - case ADDU32: - mips32_op =3D OPC_ADDU; - goto do_arith; - case SUB: - mips32_op =3D OPC_SUB; - goto do_arith; - case SUBU32: - mips32_op =3D OPC_SUBU; - goto do_arith; - case MUL: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MUL; - do_arith: - gen_arith(ctx, mips32_op, rd, rs, rt); - break; - /* Shifts */ - case SLLV: - mips32_op =3D OPC_SLLV; - goto do_shift; - case SRLV: - mips32_op =3D OPC_SRLV; - goto do_shift; - case SRAV: - mips32_op =3D OPC_SRAV; - goto do_shift; - case ROTRV: - mips32_op =3D OPC_ROTRV; - do_shift: - gen_shift(ctx, mips32_op, rd, rs, rt); - break; - /* Logical operations */ - case AND: - mips32_op =3D OPC_AND; - goto do_logic; - case OR32: - mips32_op =3D OPC_OR; - goto do_logic; - case NOR: - mips32_op =3D OPC_NOR; - goto do_logic; - case XOR32: - mips32_op =3D OPC_XOR; - do_logic: - gen_logic(ctx, mips32_op, rd, rs, rt); - break; - /* Set less than */ - case SLT: - mips32_op =3D OPC_SLT; - goto do_slt; - case SLTU: - mips32_op =3D OPC_SLTU; - do_slt: - gen_slt(ctx, mips32_op, rd, rs, rt); - break; - default: - goto pool32a_invalid; - } - break; - case 0x18: - minor =3D (ctx->opcode >> 6) & 0xf; - switch (minor) { - /* Conditional moves */ - case MOVN: /* MUL */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* MUL */ - gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt); - } else { - /* MOVN */ - gen_cond_move(ctx, OPC_MOVN, rd, rs, rt); - } - break; - case MOVZ: /* MUH */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* MUH */ - gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt); - } else { - /* MOVZ */ - gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt); - } - break; - case MULU: - check_insn(ctx, ISA_MIPS_R6); - gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt); - break; - case MUHU: - check_insn(ctx, ISA_MIPS_R6); - gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt); - break; - case LWXS: /* DIV */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* DIV */ - gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt); - } else { - /* LWXS */ - gen_ldxs(ctx, rs, rt, rd); - } - break; - case MOD: - check_insn(ctx, ISA_MIPS_R6); - gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt); - break; - case R6_DIVU: - check_insn(ctx, ISA_MIPS_R6); - gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt); - break; - case MODU: - check_insn(ctx, ISA_MIPS_R6); - gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt); - break; - default: - goto pool32a_invalid; - } - break; - case INS: - gen_bitops(ctx, OPC_INS, rt, rs, rr, rd); - return; - case LSA: - check_insn(ctx, ISA_MIPS_R6); - gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2)); - break; - case ALIGN: - check_insn(ctx, ISA_MIPS_R6); - gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2)); - break; - case EXT: - gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd); - return; - case POOL32AXF: - gen_pool32axf(env, ctx, rt, rs); - break; - case BREAK32: - generate_exception_end(ctx, EXCP_BREAK); - break; - case SIGRIE: - check_insn(ctx, ISA_MIPS_R6); - gen_reserved_instruction(ctx); - break; - default: - pool32a_invalid: - MIPS_INVAL("pool32a"); - gen_reserved_instruction(ctx); - break; - } - break; - case POOL32B: - minor =3D (ctx->opcode >> 12) & 0xf; - switch (minor) { - case CACHE: - check_cp0_enabled(ctx); - if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { - gen_cache_operation(ctx, rt, rs, imm); - } - break; - case LWC2: - case SWC2: - /* COP2: Not implemented. */ - generate_exception_err(ctx, EXCP_CpU, 2); - break; -#ifdef TARGET_MIPS64 - case LDP: - case SDP: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); -#endif - /* fall through */ - case LWP: - case SWP: - gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12)); - break; -#ifdef TARGET_MIPS64 - case LDM: - case SDM: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); -#endif - /* fall through */ - case LWM32: - case SWM32: - gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12)= ); - break; - default: - MIPS_INVAL("pool32b"); - gen_reserved_instruction(ctx); - break; - } - break; - case POOL32F: - if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { - minor =3D ctx->opcode & 0x3f; - check_cp1_enabled(ctx); - switch (minor) { - case ALNV_PS: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_ALNV_PS; - goto do_madd; - case MADD_S: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MADD_S; - goto do_madd; - case MADD_D: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MADD_D; - goto do_madd; - case MADD_PS: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MADD_PS; - goto do_madd; - case MSUB_S: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MSUB_S; - goto do_madd; - case MSUB_D: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MSUB_D; - goto do_madd; - case MSUB_PS: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_MSUB_PS; - goto do_madd; - case NMADD_S: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_NMADD_S; - goto do_madd; - case NMADD_D: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_NMADD_D; - goto do_madd; - case NMADD_PS: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_NMADD_PS; - goto do_madd; - case NMSUB_S: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_NMSUB_S; - goto do_madd; - case NMSUB_D: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_NMSUB_D; - goto do_madd; - case NMSUB_PS: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_NMSUB_PS; - do_madd: - gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt); - break; - case CABS_COND_FMT: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - cond =3D (ctx->opcode >> 6) & 0xf; - cc =3D (ctx->opcode >> 13) & 0x7; - fmt =3D (ctx->opcode >> 10) & 0x3; - switch (fmt) { - case 0x0: - gen_cmpabs_s(ctx, cond, rt, rs, cc); - break; - case 0x1: - gen_cmpabs_d(ctx, cond, rt, rs, cc); - break; - case 0x2: - gen_cmpabs_ps(ctx, cond, rt, rs, cc); - break; - default: - goto pool32f_invalid; - } - break; - case C_COND_FMT: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - cond =3D (ctx->opcode >> 6) & 0xf; - cc =3D (ctx->opcode >> 13) & 0x7; - fmt =3D (ctx->opcode >> 10) & 0x3; - switch (fmt) { - case 0x0: - gen_cmp_s(ctx, cond, rt, rs, cc); - break; - case 0x1: - gen_cmp_d(ctx, cond, rt, rs, cc); - break; - case 0x2: - gen_cmp_ps(ctx, cond, rt, rs, cc); - break; - default: - goto pool32f_invalid; - } - break; - case CMP_CONDN_S: - check_insn(ctx, ISA_MIPS_R6); - gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd); - break; - case CMP_CONDN_D: - check_insn(ctx, ISA_MIPS_R6); - gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd); - break; - case POOL32FXF: - gen_pool32fxf(ctx, rt, rs); - break; - case 0x00: - /* PLL foo */ - switch ((ctx->opcode >> 6) & 0x7) { - case PLL_PS: - mips32_op =3D OPC_PLL_PS; - goto do_ps; - case PLU_PS: - mips32_op =3D OPC_PLU_PS; - goto do_ps; - case PUL_PS: - mips32_op =3D OPC_PUL_PS; - goto do_ps; - case PUU_PS: - mips32_op =3D OPC_PUU_PS; - goto do_ps; - case CVT_PS_S: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_CVT_PS_S; - do_ps: - gen_farith(ctx, mips32_op, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case MIN_FMT: - check_insn(ctx, ISA_MIPS_R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case 0x08: - /* [LS][WDU]XC1 */ - switch ((ctx->opcode >> 6) & 0x7) { - case LWXC1: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_LWXC1; - goto do_ldst_cp1; - case SWXC1: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_SWXC1; - goto do_ldst_cp1; - case LDXC1: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_LDXC1; - goto do_ldst_cp1; - case SDXC1: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_SDXC1; - goto do_ldst_cp1; - case LUXC1: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_LUXC1; - goto do_ldst_cp1; - case SUXC1: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_SUXC1; - do_ldst_cp1: - gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs); - break; - default: - goto pool32f_invalid; - } - break; - case MAX_FMT: - check_insn(ctx, ISA_MIPS_R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case 0x18: - /* 3D insns */ - check_insn_opc_removed(ctx, ISA_MIPS_R6); - fmt =3D (ctx->opcode >> 9) & 0x3; - switch ((ctx->opcode >> 6) & 0x7) { - case RSQRT2_FMT: - switch (fmt) { - case FMT_SDPS_S: - mips32_op =3D OPC_RSQRT2_S; - goto do_3d; - case FMT_SDPS_D: - mips32_op =3D OPC_RSQRT2_D; - goto do_3d; - case FMT_SDPS_PS: - mips32_op =3D OPC_RSQRT2_PS; - goto do_3d; - default: - goto pool32f_invalid; - } - break; - case RECIP2_FMT: - switch (fmt) { - case FMT_SDPS_S: - mips32_op =3D OPC_RECIP2_S; - goto do_3d; - case FMT_SDPS_D: - mips32_op =3D OPC_RECIP2_D; - goto do_3d; - case FMT_SDPS_PS: - mips32_op =3D OPC_RECIP2_PS; - goto do_3d; - default: - goto pool32f_invalid; - } - break; - case ADDR_PS: - mips32_op =3D OPC_ADDR_PS; - goto do_3d; - case MULR_PS: - mips32_op =3D OPC_MULR_PS; - do_3d: - gen_farith(ctx, mips32_op, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case 0x20: - /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/ - cc =3D (ctx->opcode >> 13) & 0x7; - fmt =3D (ctx->opcode >> 9) & 0x3; - switch ((ctx->opcode >> 6) & 0x7) { - case MOVF_FMT: /* RINT_FMT */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* RINT_FMT */ - switch (fmt) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0); - break; - default: - goto pool32f_invalid; - } - } else { - /* MOVF_FMT */ - switch (fmt) { - case FMT_SDPS_S: - gen_movcf_s(ctx, rs, rt, cc, 0); - break; - case FMT_SDPS_D: - gen_movcf_d(ctx, rs, rt, cc, 0); - break; - case FMT_SDPS_PS: - check_ps(ctx); - gen_movcf_ps(ctx, rs, rt, cc, 0); - break; - default: - goto pool32f_invalid; - } - } - break; - case MOVT_FMT: /* CLASS_FMT */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* CLASS_FMT */ - switch (fmt) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0); - break; - default: - goto pool32f_invalid; - } - } else { - /* MOVT_FMT */ - switch (fmt) { - case FMT_SDPS_S: - gen_movcf_s(ctx, rs, rt, cc, 1); - break; - case FMT_SDPS_D: - gen_movcf_d(ctx, rs, rt, cc, 1); - break; - case FMT_SDPS_PS: - check_ps(ctx); - gen_movcf_ps(ctx, rs, rt, cc, 1); - break; - default: - goto pool32f_invalid; - } - } - break; - case PREFX: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - break; - default: - goto pool32f_invalid; - } - break; -#define FINSN_3ARG_SDPS(prfx) \ - switch ((ctx->opcode >> 8) & 0x3) { \ - case FMT_SDPS_S: \ - mips32_op =3D OPC_##prfx##_S; \ - goto do_fpop; \ - case FMT_SDPS_D: \ - mips32_op =3D OPC_##prfx##_D; \ - goto do_fpop; \ - case FMT_SDPS_PS: \ - check_ps(ctx); \ - mips32_op =3D OPC_##prfx##_PS; \ - goto do_fpop; \ - default: \ - goto pool32f_invalid; \ - } - case MINA_FMT: - check_insn(ctx, ISA_MIPS_R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case MAXA_FMT: - check_insn(ctx, ISA_MIPS_R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0); - break; - case FMT_SDPS_D: - gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0); - break; - default: - goto pool32f_invalid; - } - break; - case 0x30: - /* regular FP ops */ - switch ((ctx->opcode >> 6) & 0x3) { - case ADD_FMT: - FINSN_3ARG_SDPS(ADD); - break; - case SUB_FMT: - FINSN_3ARG_SDPS(SUB); - break; - case MUL_FMT: - FINSN_3ARG_SDPS(MUL); - break; - case DIV_FMT: - fmt =3D (ctx->opcode >> 8) & 0x3; - if (fmt =3D=3D 1) { - mips32_op =3D OPC_DIV_D; - } else if (fmt =3D=3D 0) { - mips32_op =3D OPC_DIV_S; - } else { - goto pool32f_invalid; - } - goto do_fpop; - default: - goto pool32f_invalid; - } - break; - case 0x38: - /* cmovs */ - switch ((ctx->opcode >> 6) & 0x7) { - case MOVN_FMT: /* SELEQZ_FMT */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* SELEQZ_FMT */ - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs); - break; - case FMT_SDPS_D: - gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs); - break; - default: - goto pool32f_invalid; - } - } else { - /* MOVN_FMT */ - FINSN_3ARG_SDPS(MOVN); - } - break; - case MOVN_FMT_04: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - FINSN_3ARG_SDPS(MOVN); - break; - case MOVZ_FMT: /* SELNEZ_FMT */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* SELNEZ_FMT */ - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs); - break; - case FMT_SDPS_D: - gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs); - break; - default: - goto pool32f_invalid; - } - } else { - /* MOVZ_FMT */ - FINSN_3ARG_SDPS(MOVZ); - } - break; - case MOVZ_FMT_05: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - FINSN_3ARG_SDPS(MOVZ); - break; - case SEL_FMT: - check_insn(ctx, ISA_MIPS_R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs); - break; - case FMT_SDPS_D: - gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs); - break; - default: - goto pool32f_invalid; - } - break; - case MADDF_FMT: - check_insn(ctx, ISA_MIPS_R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - mips32_op =3D OPC_MADDF_S; - goto do_fpop; - case FMT_SDPS_D: - mips32_op =3D OPC_MADDF_D; - goto do_fpop; - default: - goto pool32f_invalid; - } - break; - case MSUBF_FMT: - check_insn(ctx, ISA_MIPS_R6); - switch ((ctx->opcode >> 9) & 0x3) { - case FMT_SDPS_S: - mips32_op =3D OPC_MSUBF_S; - goto do_fpop; - case FMT_SDPS_D: - mips32_op =3D OPC_MSUBF_D; - goto do_fpop; - default: - goto pool32f_invalid; - } - break; - default: - goto pool32f_invalid; - } - break; - do_fpop: - gen_farith(ctx, mips32_op, rt, rs, rd, 0); - break; - default: - pool32f_invalid: - MIPS_INVAL("pool32f"); - gen_reserved_instruction(ctx); - break; - } - } else { - generate_exception_err(ctx, EXCP_CpU, 1); - } - break; - case POOL32I: - minor =3D (ctx->opcode >> 21) & 0x1f; - switch (minor) { - case BLTZ: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4); - break; - case BLTZAL: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4); - ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; - break; - case BLTZALS: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2); - ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; - break; - case BGEZ: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4); - break; - case BGEZAL: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4); - ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; - break; - case BGEZALS: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2); - ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; - break; - case BLEZ: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4); - break; - case BGTZ: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4); - break; - - /* Traps */ - case TLTI: /* BC1EQZC */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* BC1EQZC */ - check_cp1_enabled(ctx); - gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0); - } else { - /* TLTI */ - mips32_op =3D OPC_TLTI; - goto do_trapi; - } - break; - case TGEI: /* BC1NEZC */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* BC1NEZC */ - check_cp1_enabled(ctx); - gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0); - } else { - /* TGEI */ - mips32_op =3D OPC_TGEI; - goto do_trapi; - } - break; - case TLTIU: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_TLTIU; - goto do_trapi; - case TGEIU: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_TGEIU; - goto do_trapi; - case TNEI: /* SYNCI */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* SYNCI */ - /* - * Break the TB to be able to sync copied instructions - * immediately. - */ - ctx->base.is_jmp =3D DISAS_STOP; - } else { - /* TNEI */ - mips32_op =3D OPC_TNEI; - goto do_trapi; - } - break; - case TEQI: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_TEQI; - do_trapi: - gen_trap(ctx, mips32_op, rs, -1, imm); - break; - - case BNEZC: - case BEQZC: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_compute_branch(ctx, minor =3D=3D BNEZC ? OPC_BNE : OPC_BEQ, - 4, rs, 0, imm << 1, 0); - /* - * Compact branches don't have a delay slot, so just let - * the normal delay slot handling take us to the branch - * target. - */ - break; - case LUI: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_logic_imm(ctx, OPC_LUI, rs, 0, imm); - break; - case SYNCI: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - /* - * Break the TB to be able to sync copied instructions - * immediately. - */ - ctx->base.is_jmp =3D DISAS_STOP; - break; - case BC2F: - case BC2T: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - /* COP2: Not implemented. */ - generate_exception_err(ctx, EXCP_CpU, 2); - break; - case BC1F: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_B= C1F; - goto do_cp1branch; - case BC1T: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_B= C1T; - goto do_cp1branch; - case BC1ANY4F: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_BC1FANY4; - goto do_cp1mips3d; - case BC1ANY4T: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_BC1TANY4; - do_cp1mips3d: - check_cop1x(ctx); - check_insn(ctx, ASE_MIPS3D); - /* Fall through */ - do_cp1branch: - if (env->CP0_Config1 & (1 << CP0C1_FP)) { - check_cp1_enabled(ctx); - gen_compute_branch1(ctx, mips32_op, - (ctx->opcode >> 18) & 0x7, imm << 1); - } else { - generate_exception_err(ctx, EXCP_CpU, 1); - } - break; - default: - MIPS_INVAL("pool32i"); - gen_reserved_instruction(ctx); - break; - } - break; - case POOL32C: - minor =3D (ctx->opcode >> 12) & 0xf; - offset =3D sextract32(ctx->opcode, 0, - (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12); - switch (minor) { - case LWL: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_LWL; - goto do_ld_lr; - case SWL: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_SWL; - goto do_st_lr; - case LWR: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_LWR; - goto do_ld_lr; - case SWR: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_SWR; - goto do_st_lr; -#if defined(TARGET_MIPS64) - case LDL: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_LDL; - goto do_ld_lr; - case SDL: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_SDL; - goto do_st_lr; - case LDR: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_LDR; - goto do_ld_lr; - case SDR: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_SDR; - goto do_st_lr; - case LWU: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - mips32_op =3D OPC_LWU; - goto do_ld_lr; - case LLD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - mips32_op =3D OPC_LLD; - goto do_ld_lr; -#endif - case LL: - mips32_op =3D OPC_LL; - goto do_ld_lr; - do_ld_lr: - gen_ld(ctx, mips32_op, rt, rs, offset); - break; - do_st_lr: - gen_st(ctx, mips32_op, rt, rs, offset); - break; - case SC: - gen_st_cond(ctx, rt, rs, offset, MO_TESL, false); - break; -#if defined(TARGET_MIPS64) - case SCD: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false); - break; -#endif - case LD_EVA: - if (!ctx->eva) { - MIPS_INVAL("pool32c ld-eva"); - gen_reserved_instruction(ctx); - break; - } - check_cp0_enabled(ctx); - - minor2 =3D (ctx->opcode >> 9) & 0x7; - offset =3D sextract32(ctx->opcode, 0, 9); - switch (minor2) { - case LBUE: - mips32_op =3D OPC_LBUE; - goto do_ld_lr; - case LHUE: - mips32_op =3D OPC_LHUE; - goto do_ld_lr; - case LWLE: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_LWLE; - goto do_ld_lr; - case LWRE: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_LWRE; - goto do_ld_lr; - case LBE: - mips32_op =3D OPC_LBE; - goto do_ld_lr; - case LHE: - mips32_op =3D OPC_LHE; - goto do_ld_lr; - case LLE: - mips32_op =3D OPC_LLE; - goto do_ld_lr; - case LWE: - mips32_op =3D OPC_LWE; - goto do_ld_lr; - }; - break; - case ST_EVA: - if (!ctx->eva) { - MIPS_INVAL("pool32c st-eva"); - gen_reserved_instruction(ctx); - break; - } - check_cp0_enabled(ctx); - - minor2 =3D (ctx->opcode >> 9) & 0x7; - offset =3D sextract32(ctx->opcode, 0, 9); - switch (minor2) { - case SWLE: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_SWLE; - goto do_st_lr; - case SWRE: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - mips32_op =3D OPC_SWRE; - goto do_st_lr; - case PREFE: - /* Treat as no-op */ - if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >=3D 24)) { - /* hint codes 24-31 are reserved and signal RI */ - generate_exception(ctx, EXCP_RI); - } - break; - case CACHEE: - /* Treat as no-op */ - if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { - gen_cache_operation(ctx, rt, rs, offset); - } - break; - case SBE: - mips32_op =3D OPC_SBE; - goto do_st_lr; - case SHE: - mips32_op =3D OPC_SHE; - goto do_st_lr; - case SCE: - gen_st_cond(ctx, rt, rs, offset, MO_TESL, true); - break; - case SWE: - mips32_op =3D OPC_SWE; - goto do_st_lr; - }; - break; - case PREF: - /* Treat as no-op */ - if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >=3D 24)) { - /* hint codes 24-31 are reserved and signal RI */ - generate_exception(ctx, EXCP_RI); - } - break; - default: - MIPS_INVAL("pool32c"); - gen_reserved_instruction(ctx); - break; - } - break; - case ADDI32: /* AUI, LUI */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* AUI, LUI */ - gen_logic_imm(ctx, OPC_LUI, rt, rs, imm); - } else { - /* ADDI32 */ - mips32_op =3D OPC_ADDI; - goto do_addi; - } - break; - case ADDIU32: - mips32_op =3D OPC_ADDIU; - do_addi: - gen_arith_imm(ctx, mips32_op, rt, rs, imm); - break; - - /* Logical operations */ - case ORI32: - mips32_op =3D OPC_ORI; - goto do_logici; - case XORI32: - mips32_op =3D OPC_XORI; - goto do_logici; - case ANDI32: - mips32_op =3D OPC_ANDI; - do_logici: - gen_logic_imm(ctx, mips32_op, rt, rs, imm); - break; - - /* Set less than immediate */ - case SLTI32: - mips32_op =3D OPC_SLTI; - goto do_slti; - case SLTIU32: - mips32_op =3D OPC_SLTIU; - do_slti: - gen_slt_imm(ctx, mips32_op, rt, rs, imm); - break; - case JALX32: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - offset =3D (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; - gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4); - ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; - break; - case JALS32: /* BOVC, BEQC, BEQZALC */ - if (ctx->insn_flags & ISA_MIPS_R6) { - if (rs >=3D rt) { - /* BOVC */ - mips32_op =3D OPC_BOVC; - } else if (rs < rt && rs =3D=3D 0) { - /* BEQZALC */ - mips32_op =3D OPC_BEQZALC; - } else { - /* BEQC */ - mips32_op =3D OPC_BEQC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - } else { - /* JALS32 */ - offset =3D (int32_t)(ctx->opcode & 0x3FFFFFF) << 1; - gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2); - ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; - } - break; - case BEQ32: /* BC */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* BC */ - gen_compute_compact_branch(ctx, OPC_BC, 0, 0, - sextract32(ctx->opcode << 1, 0, 27)= ); - } else { - /* BEQ32 */ - gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4); - } - break; - case BNE32: /* BALC */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* BALC */ - gen_compute_compact_branch(ctx, OPC_BALC, 0, 0, - sextract32(ctx->opcode << 1, 0, 27)= ); - } else { - /* BNE32 */ - gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4); - } - break; - case J32: /* BGTZC, BLTZC, BLTC */ - if (ctx->insn_flags & ISA_MIPS_R6) { - if (rs =3D=3D 0 && rt !=3D 0) { - /* BGTZC */ - mips32_op =3D OPC_BGTZC; - } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { - /* BLTZC */ - mips32_op =3D OPC_BLTZC; - } else { - /* BLTC */ - mips32_op =3D OPC_BLTC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - } else { - /* J32 */ - gen_compute_branch(ctx, OPC_J, 4, rt, rs, - (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); - } - break; - case JAL32: /* BLEZC, BGEZC, BGEC */ - if (ctx->insn_flags & ISA_MIPS_R6) { - if (rs =3D=3D 0 && rt !=3D 0) { - /* BLEZC */ - mips32_op =3D OPC_BLEZC; - } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { - /* BGEZC */ - mips32_op =3D OPC_BGEZC; - } else { - /* BGEC */ - mips32_op =3D OPC_BGEC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - } else { - /* JAL32 */ - gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, - (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); - ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; - } - break; - /* Floating point (COP1) */ - case LWC132: - mips32_op =3D OPC_LWC1; - goto do_cop1; - case LDC132: - mips32_op =3D OPC_LDC1; - goto do_cop1; - case SWC132: - mips32_op =3D OPC_SWC1; - goto do_cop1; - case SDC132: - mips32_op =3D OPC_SDC1; - do_cop1: - gen_cop1_ldst(ctx, mips32_op, rt, rs, imm); - break; - case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */ - if (ctx->insn_flags & ISA_MIPS_R6) { - /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */ - switch ((ctx->opcode >> 16) & 0x1f) { - case ADDIUPC_00: - case ADDIUPC_01: - case ADDIUPC_02: - case ADDIUPC_03: - case ADDIUPC_04: - case ADDIUPC_05: - case ADDIUPC_06: - case ADDIUPC_07: - gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt); - break; - case AUIPC: - gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt); - break; - case ALUIPC: - gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt); - break; - case LWPC_08: - case LWPC_09: - case LWPC_0A: - case LWPC_0B: - case LWPC_0C: - case LWPC_0D: - case LWPC_0E: - case LWPC_0F: - gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt); - break; - default: - generate_exception(ctx, EXCP_RI); - break; - } - } else { - /* ADDIUPC */ - int reg =3D mmreg(ZIMM(ctx->opcode, 23, 3)); - offset =3D SIMM(ctx->opcode, 0, 23) << 2; - - gen_addiupc(ctx, reg, offset, 0, 0); - } - break; - case BNVC: /* BNEC, BNEZALC */ - check_insn(ctx, ISA_MIPS_R6); - if (rs >=3D rt) { - /* BNVC */ - mips32_op =3D OPC_BNVC; - } else if (rs < rt && rs =3D=3D 0) { - /* BNEZALC */ - mips32_op =3D OPC_BNEZALC; - } else { - /* BNEC */ - mips32_op =3D OPC_BNEC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - break; - case R6_BNEZC: /* JIALC */ - check_insn(ctx, ISA_MIPS_R6); - if (rt !=3D 0) { - /* BNEZC */ - gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0, - sextract32(ctx->opcode << 1, 0, 22)= ); - } else { - /* JIALC */ - gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm); - } - break; - case R6_BEQZC: /* JIC */ - check_insn(ctx, ISA_MIPS_R6); - if (rt !=3D 0) { - /* BEQZC */ - gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0, - sextract32(ctx->opcode << 1, 0, 22)= ); - } else { - /* JIC */ - gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm); - } - break; - case BLEZALC: /* BGEZALC, BGEUC */ - check_insn(ctx, ISA_MIPS_R6); - if (rs =3D=3D 0 && rt !=3D 0) { - /* BLEZALC */ - mips32_op =3D OPC_BLEZALC; - } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { - /* BGEZALC */ - mips32_op =3D OPC_BGEZALC; - } else { - /* BGEUC */ - mips32_op =3D OPC_BGEUC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - break; - case BGTZALC: /* BLTZALC, BLTUC */ - check_insn(ctx, ISA_MIPS_R6); - if (rs =3D=3D 0 && rt !=3D 0) { - /* BGTZALC */ - mips32_op =3D OPC_BGTZALC; - } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { - /* BLTZALC */ - mips32_op =3D OPC_BLTZALC; - } else { - /* BLTUC */ - mips32_op =3D OPC_BLTUC; - } - gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); - break; - /* Loads and stores */ - case LB32: - mips32_op =3D OPC_LB; - goto do_ld; - case LBU32: - mips32_op =3D OPC_LBU; - goto do_ld; - case LH32: - mips32_op =3D OPC_LH; - goto do_ld; - case LHU32: - mips32_op =3D OPC_LHU; - goto do_ld; - case LW32: - mips32_op =3D OPC_LW; - goto do_ld; -#ifdef TARGET_MIPS64 - case LD32: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - mips32_op =3D OPC_LD; - goto do_ld; - case SD32: - check_insn(ctx, ISA_MIPS3); - check_mips_64(ctx); - mips32_op =3D OPC_SD; - goto do_st; -#endif - case SB32: - mips32_op =3D OPC_SB; - goto do_st; - case SH32: - mips32_op =3D OPC_SH; - goto do_st; - case SW32: - mips32_op =3D OPC_SW; - goto do_st; - do_ld: - gen_ld(ctx, mips32_op, rt, rs, imm); - break; - do_st: - gen_st(ctx, mips32_op, rt, rs, imm); - break; - default: - gen_reserved_instruction(ctx); - break; - } -} - -static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t op; - - /* make sure instructions are on a halfword boundary */ - if (ctx->base.pc_next & 0x1) { - env->CP0_BadVAddr =3D ctx->base.pc_next; - generate_exception_end(ctx, EXCP_AdEL); - return 2; - } - - op =3D (ctx->opcode >> 10) & 0x3f; - /* Enforce properly-sized instructions in a delay slot */ - if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) { - switch (op & 0x7) { /* MSB-3..MSB-5 */ - case 0: - /* POOL32A, POOL32B, POOL32I, POOL32C */ - case 4: - /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32= */ - case 5: - /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */ - case 6: - /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */ - case 7: - /* LB32, LH32, LWC132, LDC132, LW32 */ - if (ctx->hflags & MIPS_HFLAG_BDS16) { - gen_reserved_instruction(ctx); - return 2; - } - break; - case 1: - /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */ - case 2: - /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */ - case 3: - /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */ - if (ctx->hflags & MIPS_HFLAG_BDS32) { - gen_reserved_instruction(ctx); - return 2; - } - break; - } - } - - switch (op) { - case POOL16A: - { - int rd =3D mmreg(uMIPS_RD(ctx->opcode)); - int rs1 =3D mmreg(uMIPS_RS1(ctx->opcode)); - int rs2 =3D mmreg(uMIPS_RS2(ctx->opcode)); - uint32_t opc =3D 0; - - switch (ctx->opcode & 0x1) { - case ADDU16: - opc =3D OPC_ADDU; - break; - case SUBU16: - opc =3D OPC_SUBU; - break; - } - if (ctx->insn_flags & ISA_MIPS_R6) { - /* - * In the Release 6, the register number location in - * the instruction encoding has changed. - */ - gen_arith(ctx, opc, rs1, rd, rs2); - } else { - gen_arith(ctx, opc, rd, rs1, rs2); - } - } - break; - case POOL16B: - { - int rd =3D mmreg(uMIPS_RD(ctx->opcode)); - int rs =3D mmreg(uMIPS_RS(ctx->opcode)); - int amount =3D (ctx->opcode >> 1) & 0x7; - uint32_t opc =3D 0; - amount =3D amount =3D=3D 0 ? 8 : amount; - - switch (ctx->opcode & 0x1) { - case SLL16: - opc =3D OPC_SLL; - break; - case SRL16: - opc =3D OPC_SRL; - break; - } - - gen_shift_imm(ctx, opc, rd, rs, amount); - } - break; - case POOL16C: - if (ctx->insn_flags & ISA_MIPS_R6) { - gen_pool16c_r6_insn(ctx); - } else { - gen_pool16c_insn(ctx); - } - break; - case LWGP16: - { - int rd =3D mmreg(uMIPS_RD(ctx->opcode)); - int rb =3D 28; /* GP */ - int16_t offset =3D SIMM(ctx->opcode, 0, 7) << 2; - - gen_ld(ctx, OPC_LW, rd, rb, offset); - } - break; - case POOL16F: - check_insn_opc_removed(ctx, ISA_MIPS_R6); - if (ctx->opcode & 1) { - gen_reserved_instruction(ctx); - } else { - /* MOVEP */ - int enc_dest =3D uMIPS_RD(ctx->opcode); - int enc_rt =3D uMIPS_RS2(ctx->opcode); - int enc_rs =3D uMIPS_RS1(ctx->opcode); - gen_movep(ctx, enc_dest, enc_rt, enc_rs); - } - break; - case LBU16: - { - int rd =3D mmreg(uMIPS_RD(ctx->opcode)); - int rb =3D mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset =3D ZIMM(ctx->opcode, 0, 4); - offset =3D (offset =3D=3D 0xf ? -1 : offset); - - gen_ld(ctx, OPC_LBU, rd, rb, offset); - } - break; - case LHU16: - { - int rd =3D mmreg(uMIPS_RD(ctx->opcode)); - int rb =3D mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset =3D ZIMM(ctx->opcode, 0, 4) << 1; - - gen_ld(ctx, OPC_LHU, rd, rb, offset); - } - break; - case LWSP16: - { - int rd =3D (ctx->opcode >> 5) & 0x1f; - int rb =3D 29; /* SP */ - int16_t offset =3D ZIMM(ctx->opcode, 0, 5) << 2; - - gen_ld(ctx, OPC_LW, rd, rb, offset); - } - break; - case LW16: - { - int rd =3D mmreg(uMIPS_RD(ctx->opcode)); - int rb =3D mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset =3D ZIMM(ctx->opcode, 0, 4) << 2; - - gen_ld(ctx, OPC_LW, rd, rb, offset); - } - break; - case SB16: - { - int rd =3D mmreg2(uMIPS_RD(ctx->opcode)); - int rb =3D mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset =3D ZIMM(ctx->opcode, 0, 4); - - gen_st(ctx, OPC_SB, rd, rb, offset); - } - break; - case SH16: - { - int rd =3D mmreg2(uMIPS_RD(ctx->opcode)); - int rb =3D mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset =3D ZIMM(ctx->opcode, 0, 4) << 1; - - gen_st(ctx, OPC_SH, rd, rb, offset); - } - break; - case SWSP16: - { - int rd =3D (ctx->opcode >> 5) & 0x1f; - int rb =3D 29; /* SP */ - int16_t offset =3D ZIMM(ctx->opcode, 0, 5) << 2; - - gen_st(ctx, OPC_SW, rd, rb, offset); - } - break; - case SW16: - { - int rd =3D mmreg2(uMIPS_RD(ctx->opcode)); - int rb =3D mmreg(uMIPS_RS(ctx->opcode)); - int16_t offset =3D ZIMM(ctx->opcode, 0, 4) << 2; - - gen_st(ctx, OPC_SW, rd, rb, offset); - } - break; - case MOVE16: - { - int rd =3D uMIPS_RD5(ctx->opcode); - int rs =3D uMIPS_RS5(ctx->opcode); - - gen_arith(ctx, OPC_ADDU, rd, rs, 0); - } - break; - case ANDI16: - gen_andi16(ctx); - break; - case POOL16D: - switch (ctx->opcode & 0x1) { - case ADDIUS5: - gen_addius5(ctx); - break; - case ADDIUSP: - gen_addiusp(ctx); - break; - } - break; - case POOL16E: - switch (ctx->opcode & 0x1) { - case ADDIUR2: - gen_addiur2(ctx); - break; - case ADDIUR1SP: - gen_addiur1sp(ctx); - break; - } - break; - case B16: /* BC16 */ - gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, - sextract32(ctx->opcode, 0, 10) << 1, - (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4); - break; - case BNEZ16: /* BNEZC16 */ - case BEQZ16: /* BEQZC16 */ - gen_compute_branch(ctx, op =3D=3D BNEZ16 ? OPC_BNE : OPC_BEQ, 2, - mmreg(uMIPS_RD(ctx->opcode)), - 0, sextract32(ctx->opcode, 0, 7) << 1, - (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4); - - break; - case LI16: - { - int reg =3D mmreg(uMIPS_RD(ctx->opcode)); - int imm =3D ZIMM(ctx->opcode, 0, 7); - - imm =3D (imm =3D=3D 0x7f ? -1 : imm); - tcg_gen_movi_tl(cpu_gpr[reg], imm); - } - break; - case RES_29: - case RES_31: - case RES_39: - gen_reserved_instruction(ctx); - break; - default: - decode_micromips32_opc(env, ctx); - return 4; - } - - return 2; -} - -/* ISA extensions (ASEs) */ - -/* MIPS16 extension to MIPS32 */ -#include "mips16e_translate.c.inc" +#include "micromips_translate.c.inc" =20 /* * @@ -24378,7 +21159,7 @@ static void mips_tr_translate_insn(DisasContextBase= *dcbase, CPUState *cs) decode_opc(env, ctx); } else if (ctx->insn_flags & ASE_MICROMIPS) { ctx->opcode =3D translator_lduw(env, ctx->base.pc_next); - insn_bytes =3D decode_micromips_opc(env, ctx); + insn_bytes =3D decode_isa_micromips(env, ctx); } else if (ctx->insn_flags & ASE_MIPS16) { ctx->opcode =3D translator_lduw(env, ctx->base.pc_next); insn_bytes =3D decode_ase_mips16e(env, ctx); diff --git a/target/mips/tcg/micromips_translate.c.inc b/target/mips/tcg/mi= cromips_translate.c.inc new file mode 100644 index 00000000000..5e95f478546 --- /dev/null +++ b/target/mips/tcg/micromips_translate.c.inc @@ -0,0 +1,3231 @@ +/* + * microMIPS translation routines + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +/* + * microMIPS32/microMIPS64 major opcodes + * + * 1. MIPS Architecture for Programmers Volume II-B: + * The microMIPS32 Instruction Set (Revision 3.05) + * + * Table 6.2 microMIPS32 Encoding of Major Opcode Field + * + * 2. MIPS Architecture For Programmers Volume II-A: + * The MIPS64 Instruction Set (Revision 3.51) + */ + +enum { + POOL32A =3D 0x00, + POOL16A =3D 0x01, + LBU16 =3D 0x02, + MOVE16 =3D 0x03, + ADDI32 =3D 0x04, + R6_LUI =3D 0x04, + AUI =3D 0x04, + LBU32 =3D 0x05, + SB32 =3D 0x06, + LB32 =3D 0x07, + + POOL32B =3D 0x08, + POOL16B =3D 0x09, + LHU16 =3D 0x0a, + ANDI16 =3D 0x0b, + ADDIU32 =3D 0x0c, + LHU32 =3D 0x0d, + SH32 =3D 0x0e, + LH32 =3D 0x0f, + + POOL32I =3D 0x10, + POOL16C =3D 0x11, + LWSP16 =3D 0x12, + POOL16D =3D 0x13, + ORI32 =3D 0x14, + POOL32F =3D 0x15, + POOL32S =3D 0x16, /* MIPS64 */ + DADDIU32 =3D 0x17, /* MIPS64 */ + + POOL32C =3D 0x18, + LWGP16 =3D 0x19, + LW16 =3D 0x1a, + POOL16E =3D 0x1b, + XORI32 =3D 0x1c, + JALS32 =3D 0x1d, + BOVC =3D 0x1d, + BEQC =3D 0x1d, + BEQZALC =3D 0x1d, + ADDIUPC =3D 0x1e, + PCREL =3D 0x1e, + BNVC =3D 0x1f, + BNEC =3D 0x1f, + BNEZALC =3D 0x1f, + + R6_BEQZC =3D 0x20, + JIC =3D 0x20, + POOL16F =3D 0x21, + SB16 =3D 0x22, + BEQZ16 =3D 0x23, + BEQZC16 =3D 0x23, + SLTI32 =3D 0x24, + BEQ32 =3D 0x25, + BC =3D 0x25, + SWC132 =3D 0x26, + LWC132 =3D 0x27, + + /* 0x29 is reserved */ + RES_29 =3D 0x29, + R6_BNEZC =3D 0x28, + JIALC =3D 0x28, + SH16 =3D 0x2a, + BNEZ16 =3D 0x2b, + BNEZC16 =3D 0x2b, + SLTIU32 =3D 0x2c, + BNE32 =3D 0x2d, + BALC =3D 0x2d, + SDC132 =3D 0x2e, + LDC132 =3D 0x2f, + + /* 0x31 is reserved */ + RES_31 =3D 0x31, + BLEZALC =3D 0x30, + BGEZALC =3D 0x30, + BGEUC =3D 0x30, + SWSP16 =3D 0x32, + B16 =3D 0x33, + BC16 =3D 0x33, + ANDI32 =3D 0x34, + J32 =3D 0x35, + BGTZC =3D 0x35, + BLTZC =3D 0x35, + BLTC =3D 0x35, + SD32 =3D 0x36, /* MIPS64 */ + LD32 =3D 0x37, /* MIPS64 */ + + /* 0x39 is reserved */ + RES_39 =3D 0x39, + BGTZALC =3D 0x38, + BLTZALC =3D 0x38, + BLTUC =3D 0x38, + SW16 =3D 0x3a, + LI16 =3D 0x3b, + JALX32 =3D 0x3c, + JAL32 =3D 0x3d, + BLEZC =3D 0x3d, + BGEZC =3D 0x3d, + BGEC =3D 0x3d, + SW32 =3D 0x3e, + LW32 =3D 0x3f +}; + +/* PCREL Instructions perform PC-Relative address calculation. bits 20..16= */ +enum { + ADDIUPC_00 =3D 0x00, + ADDIUPC_01 =3D 0x01, + ADDIUPC_02 =3D 0x02, + ADDIUPC_03 =3D 0x03, + ADDIUPC_04 =3D 0x04, + ADDIUPC_05 =3D 0x05, + ADDIUPC_06 =3D 0x06, + ADDIUPC_07 =3D 0x07, + AUIPC =3D 0x1e, + ALUIPC =3D 0x1f, + LWPC_08 =3D 0x08, + LWPC_09 =3D 0x09, + LWPC_0A =3D 0x0A, + LWPC_0B =3D 0x0B, + LWPC_0C =3D 0x0C, + LWPC_0D =3D 0x0D, + LWPC_0E =3D 0x0E, + LWPC_0F =3D 0x0F, +}; + +/* POOL32A encoding of minor opcode field */ + +enum { + /* + * These opcodes are distinguished only by bits 9..6; those bits are + * what are recorded below. + */ + SLL32 =3D 0x0, + SRL32 =3D 0x1, + SRA =3D 0x2, + ROTR =3D 0x3, + SELEQZ =3D 0x5, + SELNEZ =3D 0x6, + R6_RDHWR =3D 0x7, + + SLLV =3D 0x0, + SRLV =3D 0x1, + SRAV =3D 0x2, + ROTRV =3D 0x3, + ADD =3D 0x4, + ADDU32 =3D 0x5, + SUB =3D 0x6, + SUBU32 =3D 0x7, + MUL =3D 0x8, + AND =3D 0x9, + OR32 =3D 0xa, + NOR =3D 0xb, + XOR32 =3D 0xc, + SLT =3D 0xd, + SLTU =3D 0xe, + + MOVN =3D 0x0, + R6_MUL =3D 0x0, + MOVZ =3D 0x1, + MUH =3D 0x1, + MULU =3D 0x2, + MUHU =3D 0x3, + LWXS =3D 0x4, + R6_DIV =3D 0x4, + MOD =3D 0x5, + R6_DIVU =3D 0x6, + MODU =3D 0x7, + + /* The following can be distinguished by their lower 6 bits. */ + BREAK32 =3D 0x07, + INS =3D 0x0c, + LSA =3D 0x0f, + ALIGN =3D 0x1f, + EXT =3D 0x2c, + POOL32AXF =3D 0x3c, + SIGRIE =3D 0x3f +}; + +/* POOL32AXF encoding of minor opcode field extension */ + +/* + * 1. MIPS Architecture for Programmers Volume II-B: + * The microMIPS32 Instruction Set (Revision 3.05) + * + * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field + * + * 2. MIPS Architecture for Programmers VolumeIV-e: + * The MIPS DSP Application-Specific Extension + * to the microMIPS32 Architecture (Revision 2.34) + * + * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field + */ + +enum { + /* bits 11..6 */ + TEQ =3D 0x00, + TGE =3D 0x08, + TGEU =3D 0x10, + TLT =3D 0x20, + TLTU =3D 0x28, + TNE =3D 0x30, + + MFC0 =3D 0x03, + MTC0 =3D 0x0b, + + /* begin of microMIPS32 DSP */ + + /* bits 13..12 for 0x01 */ + MFHI_ACC =3D 0x0, + MFLO_ACC =3D 0x1, + MTHI_ACC =3D 0x2, + MTLO_ACC =3D 0x3, + + /* bits 13..12 for 0x2a */ + MADD_ACC =3D 0x0, + MADDU_ACC =3D 0x1, + MSUB_ACC =3D 0x2, + MSUBU_ACC =3D 0x3, + + /* bits 13..12 for 0x32 */ + MULT_ACC =3D 0x0, + MULTU_ACC =3D 0x1, + + /* end of microMIPS32 DSP */ + + /* bits 15..12 for 0x2c */ + BITSWAP =3D 0x0, + SEB =3D 0x2, + SEH =3D 0x3, + CLO =3D 0x4, + CLZ =3D 0x5, + RDHWR =3D 0x6, + WSBH =3D 0x7, + MULT =3D 0x8, + MULTU =3D 0x9, + DIV =3D 0xa, + DIVU =3D 0xb, + MADD =3D 0xc, + MADDU =3D 0xd, + MSUB =3D 0xe, + MSUBU =3D 0xf, + + /* bits 15..12 for 0x34 */ + MFC2 =3D 0x4, + MTC2 =3D 0x5, + MFHC2 =3D 0x8, + MTHC2 =3D 0x9, + CFC2 =3D 0xc, + CTC2 =3D 0xd, + + /* bits 15..12 for 0x3c */ + JALR =3D 0x0, + JR =3D 0x0, /* alias */ + JALRC =3D 0x0, + JRC =3D 0x0, + JALR_HB =3D 0x1, + JALRC_HB =3D 0x1, + JALRS =3D 0x4, + JALRS_HB =3D 0x5, + + /* bits 15..12 for 0x05 */ + RDPGPR =3D 0xe, + WRPGPR =3D 0xf, + + /* bits 15..12 for 0x0d */ + TLBP =3D 0x0, + TLBR =3D 0x1, + TLBWI =3D 0x2, + TLBWR =3D 0x3, + TLBINV =3D 0x4, + TLBINVF =3D 0x5, + WAIT =3D 0x9, + IRET =3D 0xd, + DERET =3D 0xe, + ERET =3D 0xf, + + /* bits 15..12 for 0x15 */ + DMT =3D 0x0, + DVPE =3D 0x1, + EMT =3D 0x2, + EVPE =3D 0x3, + + /* bits 15..12 for 0x1d */ + DI =3D 0x4, + EI =3D 0x5, + + /* bits 15..12 for 0x2d */ + SYNC =3D 0x6, + SYSCALL =3D 0x8, + SDBBP =3D 0xd, + + /* bits 15..12 for 0x35 */ + MFHI32 =3D 0x0, + MFLO32 =3D 0x1, + MTHI32 =3D 0x2, + MTLO32 =3D 0x3, +}; + +/* POOL32B encoding of minor opcode field (bits 15..12) */ + +enum { + LWC2 =3D 0x0, + LWP =3D 0x1, + LDP =3D 0x4, + LWM32 =3D 0x5, + CACHE =3D 0x6, + LDM =3D 0x7, + SWC2 =3D 0x8, + SWP =3D 0x9, + SDP =3D 0xc, + SWM32 =3D 0xd, + SDM =3D 0xf +}; + +/* POOL32C encoding of minor opcode field (bits 15..12) */ + +enum { + LWL =3D 0x0, + SWL =3D 0x8, + LWR =3D 0x1, + SWR =3D 0x9, + PREF =3D 0x2, + ST_EVA =3D 0xa, + LL =3D 0x3, + SC =3D 0xb, + LDL =3D 0x4, + SDL =3D 0xc, + LDR =3D 0x5, + SDR =3D 0xd, + LD_EVA =3D 0x6, + LWU =3D 0xe, + LLD =3D 0x7, + SCD =3D 0xf +}; + +/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */ + +enum { + LBUE =3D 0x0, + LHUE =3D 0x1, + LWLE =3D 0x2, + LWRE =3D 0x3, + LBE =3D 0x4, + LHE =3D 0x5, + LLE =3D 0x6, + LWE =3D 0x7, +}; + +/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */ + +enum { + SWLE =3D 0x0, + SWRE =3D 0x1, + PREFE =3D 0x2, + CACHEE =3D 0x3, + SBE =3D 0x4, + SHE =3D 0x5, + SCE =3D 0x6, + SWE =3D 0x7, +}; + +/* POOL32F encoding of minor opcode field (bits 5..0) */ + +enum { + /* These are the bit 7..6 values */ + ADD_FMT =3D 0x0, + + SUB_FMT =3D 0x1, + + MUL_FMT =3D 0x2, + + DIV_FMT =3D 0x3, + + /* These are the bit 8..6 values */ + MOVN_FMT =3D 0x0, + RSQRT2_FMT =3D 0x0, + MOVF_FMT =3D 0x0, + RINT_FMT =3D 0x0, + SELNEZ_FMT =3D 0x0, + + MOVZ_FMT =3D 0x1, + LWXC1 =3D 0x1, + MOVT_FMT =3D 0x1, + CLASS_FMT =3D 0x1, + SELEQZ_FMT =3D 0x1, + + PLL_PS =3D 0x2, + SWXC1 =3D 0x2, + SEL_FMT =3D 0x2, + + PLU_PS =3D 0x3, + LDXC1 =3D 0x3, + + MOVN_FMT_04 =3D 0x4, + PUL_PS =3D 0x4, + SDXC1 =3D 0x4, + RECIP2_FMT =3D 0x4, + + MOVZ_FMT_05 =3D 0x05, + PUU_PS =3D 0x5, + LUXC1 =3D 0x5, + + CVT_PS_S =3D 0x6, + SUXC1 =3D 0x6, + ADDR_PS =3D 0x6, + PREFX =3D 0x6, + MADDF_FMT =3D 0x6, + + MULR_PS =3D 0x7, + MSUBF_FMT =3D 0x7, + + MADD_S =3D 0x01, + MADD_D =3D 0x09, + MADD_PS =3D 0x11, + ALNV_PS =3D 0x19, + MSUB_S =3D 0x21, + MSUB_D =3D 0x29, + MSUB_PS =3D 0x31, + + NMADD_S =3D 0x02, + NMADD_D =3D 0x0a, + NMADD_PS =3D 0x12, + NMSUB_S =3D 0x22, + NMSUB_D =3D 0x2a, + NMSUB_PS =3D 0x32, + + MIN_FMT =3D 0x3, + MAX_FMT =3D 0xb, + MINA_FMT =3D 0x23, + MAXA_FMT =3D 0x2b, + POOL32FXF =3D 0x3b, + + CABS_COND_FMT =3D 0x1c, /* MIPS3D */ + C_COND_FMT =3D 0x3c, + + CMP_CONDN_S =3D 0x5, + CMP_CONDN_D =3D 0x15 +}; + +/* POOL32Fxf encoding of minor opcode extension field */ + +enum { + CVT_L =3D 0x04, + RSQRT_FMT =3D 0x08, + FLOOR_L =3D 0x0c, + CVT_PW_PS =3D 0x1c, + CVT_W =3D 0x24, + SQRT_FMT =3D 0x28, + FLOOR_W =3D 0x2c, + CVT_PS_PW =3D 0x3c, + CFC1 =3D 0x40, + RECIP_FMT =3D 0x48, + CEIL_L =3D 0x4c, + CTC1 =3D 0x60, + CEIL_W =3D 0x6c, + MFC1 =3D 0x80, + CVT_S_PL =3D 0x84, + TRUNC_L =3D 0x8c, + MTC1 =3D 0xa0, + CVT_S_PU =3D 0xa4, + TRUNC_W =3D 0xac, + MFHC1 =3D 0xc0, + ROUND_L =3D 0xcc, + MTHC1 =3D 0xe0, + ROUND_W =3D 0xec, + + MOV_FMT =3D 0x01, + MOVF =3D 0x05, + ABS_FMT =3D 0x0d, + RSQRT1_FMT =3D 0x1d, + MOVT =3D 0x25, + NEG_FMT =3D 0x2d, + CVT_D =3D 0x4d, + RECIP1_FMT =3D 0x5d, + CVT_S =3D 0x6d +}; + +/* POOL32I encoding of minor opcode field (bits 25..21) */ + +enum { + BLTZ =3D 0x00, + BLTZAL =3D 0x01, + BGEZ =3D 0x02, + BGEZAL =3D 0x03, + BLEZ =3D 0x04, + BNEZC =3D 0x05, + BGTZ =3D 0x06, + BEQZC =3D 0x07, + TLTI =3D 0x08, + BC1EQZC =3D 0x08, + TGEI =3D 0x09, + BC1NEZC =3D 0x09, + TLTIU =3D 0x0a, + BC2EQZC =3D 0x0a, + TGEIU =3D 0x0b, + BC2NEZC =3D 0x0a, + TNEI =3D 0x0c, + R6_SYNCI =3D 0x0c, + LUI =3D 0x0d, + TEQI =3D 0x0e, + SYNCI =3D 0x10, + BLTZALS =3D 0x11, + BGEZALS =3D 0x13, + BC2F =3D 0x14, + BC2T =3D 0x15, + /* These overlap and are distinguished by bit16 of the instruction */ + BC1F =3D 0x1c, + BC1T =3D 0x1d, + BC1ANY2F =3D 0x1c, + BC1ANY2T =3D 0x1d, + BC1ANY4F =3D 0x1e, + BC1ANY4T =3D 0x1f +}; + +/* POOL16A encoding of minor opcode field */ + +enum { + ADDU16 =3D 0x0, + SUBU16 =3D 0x1 +}; + +/* POOL16B encoding of minor opcode field */ + +enum { + SLL16 =3D 0x0, + SRL16 =3D 0x1 +}; + +/* POOL16C encoding of minor opcode field */ + +enum { + NOT16 =3D 0x00, + XOR16 =3D 0x04, + AND16 =3D 0x08, + OR16 =3D 0x0c, + LWM16 =3D 0x10, + SWM16 =3D 0x14, + JR16 =3D 0x18, + JRC16 =3D 0x1a, + JALR16 =3D 0x1c, + JALR16S =3D 0x1e, + MFHI16 =3D 0x20, + MFLO16 =3D 0x24, + BREAK16 =3D 0x28, + SDBBP16 =3D 0x2c, + JRADDIUSP =3D 0x30 +}; + +/* R6 POOL16C encoding of minor opcode field (bits 0..5) */ + +enum { + R6_NOT16 =3D 0x00, + R6_AND16 =3D 0x01, + R6_LWM16 =3D 0x02, + R6_JRC16 =3D 0x03, + MOVEP =3D 0x04, + MOVEP_05 =3D 0x05, + MOVEP_06 =3D 0x06, + MOVEP_07 =3D 0x07, + R6_XOR16 =3D 0x08, + R6_OR16 =3D 0x09, + R6_SWM16 =3D 0x0a, + JALRC16 =3D 0x0b, + MOVEP_0C =3D 0x0c, + MOVEP_0D =3D 0x0d, + MOVEP_0E =3D 0x0e, + MOVEP_0F =3D 0x0f, + JRCADDIUSP =3D 0x13, + R6_BREAK16 =3D 0x1b, + R6_SDBBP16 =3D 0x3b +}; + +/* POOL16D encoding of minor opcode field */ + +enum { + ADDIUS5 =3D 0x0, + ADDIUSP =3D 0x1 +}; + +/* POOL16E encoding of minor opcode field */ + +enum { + ADDIUR2 =3D 0x0, + ADDIUR1SP =3D 0x1 +}; + +static int mmreg(int r) +{ + static const int map[] =3D { 16, 17, 2, 3, 4, 5, 6, 7 }; + + return map[r]; +} + +/* Used for 16-bit store instructions. */ +static int mmreg2(int r) +{ + static const int map[] =3D { 0, 17, 2, 3, 4, 5, 6, 7 }; + + return map[r]; +} + +#define uMIPS_RD(op) ((op >> 7) & 0x7) +#define uMIPS_RS(op) ((op >> 4) & 0x7) +#define uMIPS_RS2(op) uMIPS_RS(op) +#define uMIPS_RS1(op) ((op >> 1) & 0x7) +#define uMIPS_RD5(op) ((op >> 5) & 0x1f) +#define uMIPS_RS5(op) (op & 0x1f) + +/* Signed immediate */ +#define SIMM(op, start, width) \ + ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \ + << (32 - width)) \ + >> (32 - width)) +/* Zero-extended immediate */ +#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width))) + +static void gen_addiur1sp(DisasContext *ctx) +{ + int rd =3D mmreg(uMIPS_RD(ctx->opcode)); + + gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2= ); +} + +static void gen_addiur2(DisasContext *ctx) +{ + static const int decoded_imm[] =3D { 1, 4, 8, 12, 16, 20, 24, -1 }; + int rd =3D mmreg(uMIPS_RD(ctx->opcode)); + int rs =3D mmreg(uMIPS_RS(ctx->opcode)); + + gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1,= 3)]); +} + +static void gen_addiusp(DisasContext *ctx) +{ + int encoded =3D ZIMM(ctx->opcode, 1, 9); + int decoded; + + if (encoded <=3D 1) { + decoded =3D 256 + encoded; + } else if (encoded <=3D 255) { + decoded =3D encoded; + } else if (encoded <=3D 509) { + decoded =3D encoded - 512; + } else { + decoded =3D encoded - 768; + } + + gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2); +} + +static void gen_addius5(DisasContext *ctx) +{ + int imm =3D SIMM(ctx->opcode, 1, 4); + int rd =3D (ctx->opcode >> 5) & 0x1f; + + gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm); +} + +static void gen_andi16(DisasContext *ctx) +{ + static const int decoded_imm[] =3D { 128, 1, 2, 3, 4, 7, 8, 15, 16, + 31, 32, 63, 64, 255, 32768, 65535 }; + int rd =3D mmreg(uMIPS_RD(ctx->opcode)); + int rs =3D mmreg(uMIPS_RS(ctx->opcode)); + int encoded =3D ZIMM(ctx->opcode, 0, 4); + + gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]); +} + +static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist, + int base, int16_t offset) +{ + TCGv t0, t1; + TCGv_i32 t2; + + if (ctx->hflags & MIPS_HFLAG_BMASK) { + gen_reserved_instruction(ctx); + return; + } + + t0 =3D tcg_temp_new(); + + gen_base_offset_addr(ctx, t0, base, offset); + + t1 =3D tcg_const_tl(reglist); + t2 =3D tcg_const_i32(ctx->mem_idx); + + save_cpu_state(ctx, 1); + switch (opc) { + case LWM32: + gen_helper_lwm(cpu_env, t0, t1, t2); + break; + case SWM32: + gen_helper_swm(cpu_env, t0, t1, t2); + break; +#ifdef TARGET_MIPS64 + case LDM: + gen_helper_ldm(cpu_env, t0, t1, t2); + break; + case SDM: + gen_helper_sdm(cpu_env, t0, t1, t2); + break; +#endif + } + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free_i32(t2); +} + + +static void gen_pool16c_insn(DisasContext *ctx) +{ + int rd =3D mmreg((ctx->opcode >> 3) & 0x7); + int rs =3D mmreg(ctx->opcode & 0x7); + + switch (((ctx->opcode) >> 4) & 0x3f) { + case NOT16 + 0: + case NOT16 + 1: + case NOT16 + 2: + case NOT16 + 3: + gen_logic(ctx, OPC_NOR, rd, rs, 0); + break; + case XOR16 + 0: + case XOR16 + 1: + case XOR16 + 2: + case XOR16 + 3: + gen_logic(ctx, OPC_XOR, rd, rd, rs); + break; + case AND16 + 0: + case AND16 + 1: + case AND16 + 2: + case AND16 + 3: + gen_logic(ctx, OPC_AND, rd, rd, rs); + break; + case OR16 + 0: + case OR16 + 1: + case OR16 + 2: + case OR16 + 3: + gen_logic(ctx, OPC_OR, rd, rd, rs); + break; + case LWM16 + 0: + case LWM16 + 1: + case LWM16 + 2: + case LWM16 + 3: + { + static const int lwm_convert[] =3D { 0x11, 0x12, 0x13, 0x14 }; + int offset =3D ZIMM(ctx->opcode, 0, 4); + + gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) &= 0x3], + 29, offset << 2); + } + break; + case SWM16 + 0: + case SWM16 + 1: + case SWM16 + 2: + case SWM16 + 3: + { + static const int swm_convert[] =3D { 0x11, 0x12, 0x13, 0x14 }; + int offset =3D ZIMM(ctx->opcode, 0, 4); + + gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) &= 0x3], + 29, offset << 2); + } + break; + case JR16 + 0: + case JR16 + 1: + { + int reg =3D ctx->opcode & 0x1f; + + gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4); + } + break; + case JRC16 + 0: + case JRC16 + 1: + { + int reg =3D ctx->opcode & 0x1f; + gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0); + /* + * Let normal delay slot handling in our caller take us + * to the branch target. + */ + } + break; + case JALR16 + 0: + case JALR16 + 1: + gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4); + ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; + break; + case JALR16S + 0: + case JALR16S + 1: + gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2); + ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; + break; + case MFHI16 + 0: + case MFHI16 + 1: + gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode)); + break; + case MFLO16 + 0: + case MFLO16 + 1: + gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode)); + break; + case BREAK16: + generate_exception_end(ctx, EXCP_BREAK); + break; + case SDBBP16: + if (is_uhi(extract32(ctx->opcode, 0, 4))) { + gen_helper_do_semihosting(cpu_env); + } else { + /* + * XXX: not clear which exception should be raised + * when in debug mode... + */ + check_insn(ctx, ISA_MIPS_R1); + generate_exception_end(ctx, EXCP_DBp); + } + break; + case JRADDIUSP + 0: + case JRADDIUSP + 1: + { + int imm =3D ZIMM(ctx->opcode, 0, 5); + gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0); + gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2); + /* + * Let normal delay slot handling in our caller take us + * to the branch target. + */ + } + break; + default: + gen_reserved_instruction(ctx); + break; + } +} + +static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt, + int enc_rs) +{ + int rd, re; + static const int rd_enc[] =3D { 5, 5, 6, 4, 4, 4, 4, 4 }; + static const int re_enc[] =3D { 6, 7, 7, 21, 22, 5, 6, 7 }; + static const int rs_rt_enc[] =3D { 0, 17, 2, 3, 16, 18, 19, 20 }; + + rd =3D rd_enc[enc_dest]; + re =3D re_enc[enc_dest]; + gen_load_gpr(cpu_gpr[rd], rs_rt_enc[enc_rs]); + gen_load_gpr(cpu_gpr[re], rs_rt_enc[enc_rt]); +} + +static void gen_pool16c_r6_insn(DisasContext *ctx) +{ + int rt =3D mmreg((ctx->opcode >> 7) & 0x7); + int rs =3D mmreg((ctx->opcode >> 4) & 0x7); + + switch (ctx->opcode & 0xf) { + case R6_NOT16: + gen_logic(ctx, OPC_NOR, rt, rs, 0); + break; + case R6_AND16: + gen_logic(ctx, OPC_AND, rt, rt, rs); + break; + case R6_LWM16: + { + int lwm_converted =3D 0x11 + extract32(ctx->opcode, 8, 2); + int offset =3D extract32(ctx->opcode, 4, 4); + gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2); + } + break; + case R6_JRC16: /* JRCADDIUSP */ + if ((ctx->opcode >> 4) & 1) { + /* JRCADDIUSP */ + int imm =3D extract32(ctx->opcode, 5, 5); + gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0); + gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2); + } else { + /* JRC16 */ + rs =3D extract32(ctx->opcode, 5, 5); + gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0); + } + break; + case MOVEP: + case MOVEP_05: + case MOVEP_06: + case MOVEP_07: + case MOVEP_0C: + case MOVEP_0D: + case MOVEP_0E: + case MOVEP_0F: + { + int enc_dest =3D uMIPS_RD(ctx->opcode); + int enc_rt =3D uMIPS_RS2(ctx->opcode); + int enc_rs =3D (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4); + gen_movep(ctx, enc_dest, enc_rt, enc_rs); + } + break; + case R6_XOR16: + gen_logic(ctx, OPC_XOR, rt, rt, rs); + break; + case R6_OR16: + gen_logic(ctx, OPC_OR, rt, rt, rs); + break; + case R6_SWM16: + { + int swm_converted =3D 0x11 + extract32(ctx->opcode, 8, 2); + int offset =3D extract32(ctx->opcode, 4, 4); + gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2); + } + break; + case JALRC16: /* BREAK16, SDBBP16 */ + switch (ctx->opcode & 0x3f) { + case JALRC16: + case JALRC16 + 0x20: + /* JALRC16 */ + gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f, + 31, 0, 0); + break; + case R6_BREAK16: + /* BREAK16 */ + generate_exception(ctx, EXCP_BREAK); + break; + case R6_SDBBP16: + /* SDBBP16 */ + if (is_uhi(extract32(ctx->opcode, 6, 4))) { + gen_helper_do_semihosting(cpu_env); + } else { + if (ctx->hflags & MIPS_HFLAG_SBRI) { + generate_exception(ctx, EXCP_RI); + } else { + generate_exception(ctx, EXCP_DBp); + } + } + break; + } + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } +} + +static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd, + int base, int16_t offset) +{ + TCGv t0, t1; + + if (ctx->hflags & MIPS_HFLAG_BMASK || rd =3D=3D 31) { + gen_reserved_instruction(ctx); + return; + } + + t0 =3D tcg_temp_new(); + t1 =3D tcg_temp_new(); + + gen_base_offset_addr(ctx, t0, base, offset); + + switch (opc) { + case LWP: + if (rd =3D=3D base) { + gen_reserved_instruction(ctx); + return; + } + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); + gen_store_gpr(t1, rd); + tcg_gen_movi_tl(t1, 4); + gen_op_addr_add(ctx, t0, t0, t1); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); + gen_store_gpr(t1, rd + 1); + break; + case SWP: + gen_load_gpr(t1, rd); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + tcg_gen_movi_tl(t1, 4); + gen_op_addr_add(ctx, t0, t0, t1); + gen_load_gpr(t1, rd + 1); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + break; +#ifdef TARGET_MIPS64 + case LDP: + if (rd =3D=3D base) { + gen_reserved_instruction(ctx); + return; + } + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); + gen_store_gpr(t1, rd); + tcg_gen_movi_tl(t1, 8); + gen_op_addr_add(ctx, t0, t0, t1); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); + gen_store_gpr(t1, rd + 1); + break; + case SDP: + gen_load_gpr(t1, rd); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_movi_tl(t1, 8); + gen_op_addr_add(ctx, t0, t0, t1); + gen_load_gpr(t1, rd + 1); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ); + break; +#endif + } + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, in= t rs) +{ + int extension =3D (ctx->opcode >> 6) & 0x3f; + int minor =3D (ctx->opcode >> 12) & 0xf; + uint32_t mips32_op; + + switch (extension) { + case TEQ: + mips32_op =3D OPC_TEQ; + goto do_trap; + case TGE: + mips32_op =3D OPC_TGE; + goto do_trap; + case TGEU: + mips32_op =3D OPC_TGEU; + goto do_trap; + case TLT: + mips32_op =3D OPC_TLT; + goto do_trap; + case TLTU: + mips32_op =3D OPC_TLTU; + goto do_trap; + case TNE: + mips32_op =3D OPC_TNE; + do_trap: + gen_trap(ctx, mips32_op, rs, rt, -1); + break; +#ifndef CONFIG_USER_ONLY + case MFC0: + case MFC0 + 32: + check_cp0_enabled(ctx); + if (rt =3D=3D 0) { + /* Treat as NOP. */ + break; + } + gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7); + break; + case MTC0: + case MTC0 + 32: + check_cp0_enabled(ctx); + { + TCGv t0 =3D tcg_temp_new(); + + gen_load_gpr(t0, rt); + gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7); + tcg_temp_free(t0); + } + break; +#endif + case 0x2a: + switch (minor & 3) { + case MADD_ACC: + gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt); + break; + case MADDU_ACC: + gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt); + break; + case MSUB_ACC: + gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt); + break; + case MSUBU_ACC: + gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x32: + switch (minor & 3) { + case MULT_ACC: + gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt); + break; + case MULTU_ACC: + gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x2c: + switch (minor) { + case BITSWAP: + check_insn(ctx, ISA_MIPS_R6); + gen_bitswap(ctx, OPC_BITSWAP, rs, rt); + break; + case SEB: + gen_bshfl(ctx, OPC_SEB, rs, rt); + break; + case SEH: + gen_bshfl(ctx, OPC_SEH, rs, rt); + break; + case CLO: + mips32_op =3D OPC_CLO; + goto do_cl; + case CLZ: + mips32_op =3D OPC_CLZ; + do_cl: + check_insn(ctx, ISA_MIPS_R1); + gen_cl(ctx, mips32_op, rt, rs); + break; + case RDHWR: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_rdhwr(ctx, rt, rs, 0); + break; + case WSBH: + gen_bshfl(ctx, OPC_WSBH, rs, rt); + break; + case MULT: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MULT; + goto do_mul; + case MULTU: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MULTU; + goto do_mul; + case DIV: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_DIV; + goto do_div; + case DIVU: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_DIVU; + goto do_div; + do_div: + check_insn(ctx, ISA_MIPS_R1); + gen_muldiv(ctx, mips32_op, 0, rs, rt); + break; + case MADD: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MADD; + goto do_mul; + case MADDU: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MADDU; + goto do_mul; + case MSUB: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MSUB; + goto do_mul; + case MSUBU: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MSUBU; + do_mul: + check_insn(ctx, ISA_MIPS_R1); + gen_muldiv(ctx, mips32_op, 0, rs, rt); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x34: + switch (minor) { + case MFC2: + case MTC2: + case MFHC2: + case MTHC2: + case CFC2: + case CTC2: + generate_exception_err(ctx, EXCP_CpU, 2); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x3c: + switch (minor) { + case JALR: /* JALRC */ + case JALR_HB: /* JALRC_HB */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* JALRC, JALRC_HB */ + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0); + } else { + /* JALR, JALR_HB */ + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4); + ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; + } + break; + case JALRS: + case JALRS_HB: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2); + ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; + break; + default: + goto pool32axf_invalid; + } + break; + case 0x05: + switch (minor) { + case RDPGPR: + check_cp0_enabled(ctx); + check_insn(ctx, ISA_MIPS_R2); + gen_load_srsgpr(rs, rt); + break; + case WRPGPR: + check_cp0_enabled(ctx); + check_insn(ctx, ISA_MIPS_R2); + gen_store_srsgpr(rs, rt); + break; + default: + goto pool32axf_invalid; + } + break; +#ifndef CONFIG_USER_ONLY + case 0x0d: + switch (minor) { + case TLBP: + mips32_op =3D OPC_TLBP; + goto do_cp0; + case TLBR: + mips32_op =3D OPC_TLBR; + goto do_cp0; + case TLBWI: + mips32_op =3D OPC_TLBWI; + goto do_cp0; + case TLBWR: + mips32_op =3D OPC_TLBWR; + goto do_cp0; + case TLBINV: + mips32_op =3D OPC_TLBINV; + goto do_cp0; + case TLBINVF: + mips32_op =3D OPC_TLBINVF; + goto do_cp0; + case WAIT: + mips32_op =3D OPC_WAIT; + goto do_cp0; + case DERET: + mips32_op =3D OPC_DERET; + goto do_cp0; + case ERET: + mips32_op =3D OPC_ERET; + do_cp0: + gen_cp0(env, ctx, mips32_op, rt, rs); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x1d: + switch (minor) { + case DI: + check_cp0_enabled(ctx); + { + TCGv t0 =3D tcg_temp_new(); + + save_cpu_state(ctx, 1); + gen_helper_di(t0, cpu_env); + gen_store_gpr(t0, rs); + /* + * Stop translation as we may have switched the execution + * mode. + */ + ctx->base.is_jmp =3D DISAS_STOP; + tcg_temp_free(t0); + } + break; + case EI: + check_cp0_enabled(ctx); + { + TCGv t0 =3D tcg_temp_new(); + + save_cpu_state(ctx, 1); + gen_helper_ei(t0, cpu_env); + gen_store_gpr(t0, rs); + /* + * DISAS_STOP isn't sufficient, we need to ensure we break= out + * of translated code to check for pending interrupts. + */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp =3D DISAS_EXIT; + tcg_temp_free(t0); + } + break; + default: + goto pool32axf_invalid; + } + break; +#endif + case 0x2d: + switch (minor) { + case SYNC: + gen_sync(extract32(ctx->opcode, 16, 5)); + break; + case SYSCALL: + generate_exception_end(ctx, EXCP_SYSCALL); + break; + case SDBBP: + if (is_uhi(extract32(ctx->opcode, 16, 10))) { + gen_helper_do_semihosting(cpu_env); + } else { + check_insn(ctx, ISA_MIPS_R1); + if (ctx->hflags & MIPS_HFLAG_SBRI) { + gen_reserved_instruction(ctx); + } else { + generate_exception_end(ctx, EXCP_DBp); + } + } + break; + default: + goto pool32axf_invalid; + } + break; + case 0x01: + switch (minor & 3) { + case MFHI_ACC: + gen_HILO(ctx, OPC_MFHI, minor >> 2, rs); + break; + case MFLO_ACC: + gen_HILO(ctx, OPC_MFLO, minor >> 2, rs); + break; + case MTHI_ACC: + gen_HILO(ctx, OPC_MTHI, minor >> 2, rs); + break; + case MTLO_ACC: + gen_HILO(ctx, OPC_MTLO, minor >> 2, rs); + break; + default: + goto pool32axf_invalid; + } + break; + case 0x35: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + switch (minor) { + case MFHI32: + gen_HILO(ctx, OPC_MFHI, 0, rs); + break; + case MFLO32: + gen_HILO(ctx, OPC_MFLO, 0, rs); + break; + case MTHI32: + gen_HILO(ctx, OPC_MTHI, 0, rs); + break; + case MTLO32: + gen_HILO(ctx, OPC_MTLO, 0, rs); + break; + default: + goto pool32axf_invalid; + } + break; + default: + pool32axf_invalid: + MIPS_INVAL("pool32axf"); + gen_reserved_instruction(ctx); + break; + } +} + +static void gen_pool32fxf(DisasContext *ctx, int rt, int rs) +{ + int extension =3D (ctx->opcode >> 6) & 0x3ff; + uint32_t mips32_op; + +#define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc) +#define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc) +#define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc) + + switch (extension) { + case FLOAT_1BIT_FMT(CFC1, 0): + mips32_op =3D OPC_CFC1; + goto do_cp1; + case FLOAT_1BIT_FMT(CTC1, 0): + mips32_op =3D OPC_CTC1; + goto do_cp1; + case FLOAT_1BIT_FMT(MFC1, 0): + mips32_op =3D OPC_MFC1; + goto do_cp1; + case FLOAT_1BIT_FMT(MTC1, 0): + mips32_op =3D OPC_MTC1; + goto do_cp1; + case FLOAT_1BIT_FMT(MFHC1, 0): + mips32_op =3D OPC_MFHC1; + goto do_cp1; + case FLOAT_1BIT_FMT(MTHC1, 0): + mips32_op =3D OPC_MTHC1; + do_cp1: + gen_cp1(ctx, mips32_op, rt, rs); + break; + + /* Reciprocal square root */ + case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S): + mips32_op =3D OPC_RSQRT_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D): + mips32_op =3D OPC_RSQRT_D; + goto do_unaryfp; + + /* Square root */ + case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S): + mips32_op =3D OPC_SQRT_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D): + mips32_op =3D OPC_SQRT_D; + goto do_unaryfp; + + /* Reciprocal */ + case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S): + mips32_op =3D OPC_RECIP_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D): + mips32_op =3D OPC_RECIP_D; + goto do_unaryfp; + + /* Floor */ + case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S): + mips32_op =3D OPC_FLOOR_L_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D): + mips32_op =3D OPC_FLOOR_L_D; + goto do_unaryfp; + case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S): + mips32_op =3D OPC_FLOOR_W_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D): + mips32_op =3D OPC_FLOOR_W_D; + goto do_unaryfp; + + /* Ceiling */ + case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S): + mips32_op =3D OPC_CEIL_L_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D): + mips32_op =3D OPC_CEIL_L_D; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S): + mips32_op =3D OPC_CEIL_W_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D): + mips32_op =3D OPC_CEIL_W_D; + goto do_unaryfp; + + /* Truncation */ + case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S): + mips32_op =3D OPC_TRUNC_L_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D): + mips32_op =3D OPC_TRUNC_L_D; + goto do_unaryfp; + case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S): + mips32_op =3D OPC_TRUNC_W_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D): + mips32_op =3D OPC_TRUNC_W_D; + goto do_unaryfp; + + /* Round */ + case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S): + mips32_op =3D OPC_ROUND_L_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D): + mips32_op =3D OPC_ROUND_L_D; + goto do_unaryfp; + case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S): + mips32_op =3D OPC_ROUND_W_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D): + mips32_op =3D OPC_ROUND_W_D; + goto do_unaryfp; + + /* Integer to floating-point conversion */ + case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S): + mips32_op =3D OPC_CVT_L_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D): + mips32_op =3D OPC_CVT_L_D; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S): + mips32_op =3D OPC_CVT_W_S; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D): + mips32_op =3D OPC_CVT_W_D; + goto do_unaryfp; + + /* Paired-foo conversions */ + case FLOAT_1BIT_FMT(CVT_S_PL, 0): + mips32_op =3D OPC_CVT_S_PL; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_S_PU, 0): + mips32_op =3D OPC_CVT_S_PU; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_PW_PS, 0): + mips32_op =3D OPC_CVT_PW_PS; + goto do_unaryfp; + case FLOAT_1BIT_FMT(CVT_PS_PW, 0): + mips32_op =3D OPC_CVT_PS_PW; + goto do_unaryfp; + + /* Floating-point moves */ + case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S): + mips32_op =3D OPC_MOV_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D): + mips32_op =3D OPC_MOV_D; + goto do_unaryfp; + case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS): + mips32_op =3D OPC_MOV_PS; + goto do_unaryfp; + + /* Absolute value */ + case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S): + mips32_op =3D OPC_ABS_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D): + mips32_op =3D OPC_ABS_D; + goto do_unaryfp; + case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS): + mips32_op =3D OPC_ABS_PS; + goto do_unaryfp; + + /* Negation */ + case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S): + mips32_op =3D OPC_NEG_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D): + mips32_op =3D OPC_NEG_D; + goto do_unaryfp; + case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS): + mips32_op =3D OPC_NEG_PS; + goto do_unaryfp; + + /* Reciprocal square root step */ + case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S): + mips32_op =3D OPC_RSQRT1_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D): + mips32_op =3D OPC_RSQRT1_D; + goto do_unaryfp; + case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS): + mips32_op =3D OPC_RSQRT1_PS; + goto do_unaryfp; + + /* Reciprocal step */ + case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S): + mips32_op =3D OPC_RECIP1_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D): + mips32_op =3D OPC_RECIP1_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS): + mips32_op =3D OPC_RECIP1_PS; + goto do_unaryfp; + + /* Conversions from double */ + case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S): + mips32_op =3D OPC_CVT_D_S; + goto do_unaryfp; + case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W): + mips32_op =3D OPC_CVT_D_W; + goto do_unaryfp; + case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L): + mips32_op =3D OPC_CVT_D_L; + goto do_unaryfp; + + /* Conversions from single */ + case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D): + mips32_op =3D OPC_CVT_S_D; + goto do_unaryfp; + case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W): + mips32_op =3D OPC_CVT_S_W; + goto do_unaryfp; + case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L): + mips32_op =3D OPC_CVT_S_L; + do_unaryfp: + gen_farith(ctx, mips32_op, -1, rs, rt, 0); + break; + + /* Conditional moves on floating-point codes */ + case COND_FLOAT_MOV(MOVT, 0): + case COND_FLOAT_MOV(MOVT, 1): + case COND_FLOAT_MOV(MOVT, 2): + case COND_FLOAT_MOV(MOVT, 3): + case COND_FLOAT_MOV(MOVT, 4): + case COND_FLOAT_MOV(MOVT, 5): + case COND_FLOAT_MOV(MOVT, 6): + case COND_FLOAT_MOV(MOVT, 7): + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1); + break; + case COND_FLOAT_MOV(MOVF, 0): + case COND_FLOAT_MOV(MOVF, 1): + case COND_FLOAT_MOV(MOVF, 2): + case COND_FLOAT_MOV(MOVF, 3): + case COND_FLOAT_MOV(MOVF, 4): + case COND_FLOAT_MOV(MOVF, 5): + case COND_FLOAT_MOV(MOVF, 6): + case COND_FLOAT_MOV(MOVF, 7): + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0); + break; + default: + MIPS_INVAL("pool32fxf"); + gen_reserved_instruction(ctx); + break; + } +} + +static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) +{ + int32_t offset; + uint16_t insn; + int rt, rs, rd, rr; + int16_t imm; + uint32_t op, minor, minor2, mips32_op; + uint32_t cond, fmt, cc; + + insn =3D translator_lduw(env, ctx->base.pc_next + 2); + ctx->opcode =3D (ctx->opcode << 16) | insn; + + rt =3D (ctx->opcode >> 21) & 0x1f; + rs =3D (ctx->opcode >> 16) & 0x1f; + rd =3D (ctx->opcode >> 11) & 0x1f; + rr =3D (ctx->opcode >> 6) & 0x1f; + imm =3D (int16_t) ctx->opcode; + + op =3D (ctx->opcode >> 26) & 0x3f; + switch (op) { + case POOL32A: + minor =3D ctx->opcode & 0x3f; + switch (minor) { + case 0x00: + minor =3D (ctx->opcode >> 6) & 0xf; + switch (minor) { + case SLL32: + mips32_op =3D OPC_SLL; + goto do_shifti; + case SRA: + mips32_op =3D OPC_SRA; + goto do_shifti; + case SRL32: + mips32_op =3D OPC_SRL; + goto do_shifti; + case ROTR: + mips32_op =3D OPC_ROTR; + do_shifti: + gen_shift_imm(ctx, mips32_op, rt, rs, rd); + break; + case SELEQZ: + check_insn(ctx, ISA_MIPS_R6); + gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt); + break; + case SELNEZ: + check_insn(ctx, ISA_MIPS_R6); + gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt); + break; + case R6_RDHWR: + check_insn(ctx, ISA_MIPS_R6); + gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); + break; + default: + goto pool32a_invalid; + } + break; + case 0x10: + minor =3D (ctx->opcode >> 6) & 0xf; + switch (minor) { + /* Arithmetic */ + case ADD: + mips32_op =3D OPC_ADD; + goto do_arith; + case ADDU32: + mips32_op =3D OPC_ADDU; + goto do_arith; + case SUB: + mips32_op =3D OPC_SUB; + goto do_arith; + case SUBU32: + mips32_op =3D OPC_SUBU; + goto do_arith; + case MUL: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MUL; + do_arith: + gen_arith(ctx, mips32_op, rd, rs, rt); + break; + /* Shifts */ + case SLLV: + mips32_op =3D OPC_SLLV; + goto do_shift; + case SRLV: + mips32_op =3D OPC_SRLV; + goto do_shift; + case SRAV: + mips32_op =3D OPC_SRAV; + goto do_shift; + case ROTRV: + mips32_op =3D OPC_ROTRV; + do_shift: + gen_shift(ctx, mips32_op, rd, rs, rt); + break; + /* Logical operations */ + case AND: + mips32_op =3D OPC_AND; + goto do_logic; + case OR32: + mips32_op =3D OPC_OR; + goto do_logic; + case NOR: + mips32_op =3D OPC_NOR; + goto do_logic; + case XOR32: + mips32_op =3D OPC_XOR; + do_logic: + gen_logic(ctx, mips32_op, rd, rs, rt); + break; + /* Set less than */ + case SLT: + mips32_op =3D OPC_SLT; + goto do_slt; + case SLTU: + mips32_op =3D OPC_SLTU; + do_slt: + gen_slt(ctx, mips32_op, rd, rs, rt); + break; + default: + goto pool32a_invalid; + } + break; + case 0x18: + minor =3D (ctx->opcode >> 6) & 0xf; + switch (minor) { + /* Conditional moves */ + case MOVN: /* MUL */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* MUL */ + gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt); + } else { + /* MOVN */ + gen_cond_move(ctx, OPC_MOVN, rd, rs, rt); + } + break; + case MOVZ: /* MUH */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* MUH */ + gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt); + } else { + /* MOVZ */ + gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt); + } + break; + case MULU: + check_insn(ctx, ISA_MIPS_R6); + gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt); + break; + case MUHU: + check_insn(ctx, ISA_MIPS_R6); + gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt); + break; + case LWXS: /* DIV */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* DIV */ + gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt); + } else { + /* LWXS */ + gen_ldxs(ctx, rs, rt, rd); + } + break; + case MOD: + check_insn(ctx, ISA_MIPS_R6); + gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt); + break; + case R6_DIVU: + check_insn(ctx, ISA_MIPS_R6); + gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt); + break; + case MODU: + check_insn(ctx, ISA_MIPS_R6); + gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt); + break; + default: + goto pool32a_invalid; + } + break; + case INS: + gen_bitops(ctx, OPC_INS, rt, rs, rr, rd); + return; + case LSA: + check_insn(ctx, ISA_MIPS_R6); + gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2)); + break; + case ALIGN: + check_insn(ctx, ISA_MIPS_R6); + gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2)); + break; + case EXT: + gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd); + return; + case POOL32AXF: + gen_pool32axf(env, ctx, rt, rs); + break; + case BREAK32: + generate_exception_end(ctx, EXCP_BREAK); + break; + case SIGRIE: + check_insn(ctx, ISA_MIPS_R6); + gen_reserved_instruction(ctx); + break; + default: + pool32a_invalid: + MIPS_INVAL("pool32a"); + gen_reserved_instruction(ctx); + break; + } + break; + case POOL32B: + minor =3D (ctx->opcode >> 12) & 0xf; + switch (minor) { + case CACHE: + check_cp0_enabled(ctx); + if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { + gen_cache_operation(ctx, rt, rs, imm); + } + break; + case LWC2: + case SWC2: + /* COP2: Not implemented. */ + generate_exception_err(ctx, EXCP_CpU, 2); + break; +#ifdef TARGET_MIPS64 + case LDP: + case SDP: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); +#endif + /* fall through */ + case LWP: + case SWP: + gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12)); + break; +#ifdef TARGET_MIPS64 + case LDM: + case SDM: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); +#endif + /* fall through */ + case LWM32: + case SWM32: + gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12)= ); + break; + default: + MIPS_INVAL("pool32b"); + gen_reserved_instruction(ctx); + break; + } + break; + case POOL32F: + if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { + minor =3D ctx->opcode & 0x3f; + check_cp1_enabled(ctx); + switch (minor) { + case ALNV_PS: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_ALNV_PS; + goto do_madd; + case MADD_S: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MADD_S; + goto do_madd; + case MADD_D: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MADD_D; + goto do_madd; + case MADD_PS: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MADD_PS; + goto do_madd; + case MSUB_S: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MSUB_S; + goto do_madd; + case MSUB_D: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MSUB_D; + goto do_madd; + case MSUB_PS: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_MSUB_PS; + goto do_madd; + case NMADD_S: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_NMADD_S; + goto do_madd; + case NMADD_D: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_NMADD_D; + goto do_madd; + case NMADD_PS: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_NMADD_PS; + goto do_madd; + case NMSUB_S: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_NMSUB_S; + goto do_madd; + case NMSUB_D: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_NMSUB_D; + goto do_madd; + case NMSUB_PS: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_NMSUB_PS; + do_madd: + gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt); + break; + case CABS_COND_FMT: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + cond =3D (ctx->opcode >> 6) & 0xf; + cc =3D (ctx->opcode >> 13) & 0x7; + fmt =3D (ctx->opcode >> 10) & 0x3; + switch (fmt) { + case 0x0: + gen_cmpabs_s(ctx, cond, rt, rs, cc); + break; + case 0x1: + gen_cmpabs_d(ctx, cond, rt, rs, cc); + break; + case 0x2: + gen_cmpabs_ps(ctx, cond, rt, rs, cc); + break; + default: + goto pool32f_invalid; + } + break; + case C_COND_FMT: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + cond =3D (ctx->opcode >> 6) & 0xf; + cc =3D (ctx->opcode >> 13) & 0x7; + fmt =3D (ctx->opcode >> 10) & 0x3; + switch (fmt) { + case 0x0: + gen_cmp_s(ctx, cond, rt, rs, cc); + break; + case 0x1: + gen_cmp_d(ctx, cond, rt, rs, cc); + break; + case 0x2: + gen_cmp_ps(ctx, cond, rt, rs, cc); + break; + default: + goto pool32f_invalid; + } + break; + case CMP_CONDN_S: + check_insn(ctx, ISA_MIPS_R6); + gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd); + break; + case CMP_CONDN_D: + check_insn(ctx, ISA_MIPS_R6); + gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd); + break; + case POOL32FXF: + gen_pool32fxf(ctx, rt, rs); + break; + case 0x00: + /* PLL foo */ + switch ((ctx->opcode >> 6) & 0x7) { + case PLL_PS: + mips32_op =3D OPC_PLL_PS; + goto do_ps; + case PLU_PS: + mips32_op =3D OPC_PLU_PS; + goto do_ps; + case PUL_PS: + mips32_op =3D OPC_PUL_PS; + goto do_ps; + case PUU_PS: + mips32_op =3D OPC_PUU_PS; + goto do_ps; + case CVT_PS_S: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_CVT_PS_S; + do_ps: + gen_farith(ctx, mips32_op, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case MIN_FMT: + check_insn(ctx, ISA_MIPS_R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case 0x08: + /* [LS][WDU]XC1 */ + switch ((ctx->opcode >> 6) & 0x7) { + case LWXC1: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_LWXC1; + goto do_ldst_cp1; + case SWXC1: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_SWXC1; + goto do_ldst_cp1; + case LDXC1: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_LDXC1; + goto do_ldst_cp1; + case SDXC1: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_SDXC1; + goto do_ldst_cp1; + case LUXC1: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_LUXC1; + goto do_ldst_cp1; + case SUXC1: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_SUXC1; + do_ldst_cp1: + gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs); + break; + default: + goto pool32f_invalid; + } + break; + case MAX_FMT: + check_insn(ctx, ISA_MIPS_R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case 0x18: + /* 3D insns */ + check_insn_opc_removed(ctx, ISA_MIPS_R6); + fmt =3D (ctx->opcode >> 9) & 0x3; + switch ((ctx->opcode >> 6) & 0x7) { + case RSQRT2_FMT: + switch (fmt) { + case FMT_SDPS_S: + mips32_op =3D OPC_RSQRT2_S; + goto do_3d; + case FMT_SDPS_D: + mips32_op =3D OPC_RSQRT2_D; + goto do_3d; + case FMT_SDPS_PS: + mips32_op =3D OPC_RSQRT2_PS; + goto do_3d; + default: + goto pool32f_invalid; + } + break; + case RECIP2_FMT: + switch (fmt) { + case FMT_SDPS_S: + mips32_op =3D OPC_RECIP2_S; + goto do_3d; + case FMT_SDPS_D: + mips32_op =3D OPC_RECIP2_D; + goto do_3d; + case FMT_SDPS_PS: + mips32_op =3D OPC_RECIP2_PS; + goto do_3d; + default: + goto pool32f_invalid; + } + break; + case ADDR_PS: + mips32_op =3D OPC_ADDR_PS; + goto do_3d; + case MULR_PS: + mips32_op =3D OPC_MULR_PS; + do_3d: + gen_farith(ctx, mips32_op, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case 0x20: + /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/ + cc =3D (ctx->opcode >> 13) & 0x7; + fmt =3D (ctx->opcode >> 9) & 0x3; + switch ((ctx->opcode >> 6) & 0x7) { + case MOVF_FMT: /* RINT_FMT */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* RINT_FMT */ + switch (fmt) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0); + break; + default: + goto pool32f_invalid; + } + } else { + /* MOVF_FMT */ + switch (fmt) { + case FMT_SDPS_S: + gen_movcf_s(ctx, rs, rt, cc, 0); + break; + case FMT_SDPS_D: + gen_movcf_d(ctx, rs, rt, cc, 0); + break; + case FMT_SDPS_PS: + check_ps(ctx); + gen_movcf_ps(ctx, rs, rt, cc, 0); + break; + default: + goto pool32f_invalid; + } + } + break; + case MOVT_FMT: /* CLASS_FMT */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* CLASS_FMT */ + switch (fmt) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0); + break; + default: + goto pool32f_invalid; + } + } else { + /* MOVT_FMT */ + switch (fmt) { + case FMT_SDPS_S: + gen_movcf_s(ctx, rs, rt, cc, 1); + break; + case FMT_SDPS_D: + gen_movcf_d(ctx, rs, rt, cc, 1); + break; + case FMT_SDPS_PS: + check_ps(ctx); + gen_movcf_ps(ctx, rs, rt, cc, 1); + break; + default: + goto pool32f_invalid; + } + } + break; + case PREFX: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + break; + default: + goto pool32f_invalid; + } + break; +#define FINSN_3ARG_SDPS(prfx) \ + switch ((ctx->opcode >> 8) & 0x3) { \ + case FMT_SDPS_S: \ + mips32_op =3D OPC_##prfx##_S; \ + goto do_fpop; \ + case FMT_SDPS_D: \ + mips32_op =3D OPC_##prfx##_D; \ + goto do_fpop; \ + case FMT_SDPS_PS: \ + check_ps(ctx); \ + mips32_op =3D OPC_##prfx##_PS; \ + goto do_fpop; \ + default: \ + goto pool32f_invalid; \ + } + case MINA_FMT: + check_insn(ctx, ISA_MIPS_R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case MAXA_FMT: + check_insn(ctx, ISA_MIPS_R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0); + break; + case FMT_SDPS_D: + gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0); + break; + default: + goto pool32f_invalid; + } + break; + case 0x30: + /* regular FP ops */ + switch ((ctx->opcode >> 6) & 0x3) { + case ADD_FMT: + FINSN_3ARG_SDPS(ADD); + break; + case SUB_FMT: + FINSN_3ARG_SDPS(SUB); + break; + case MUL_FMT: + FINSN_3ARG_SDPS(MUL); + break; + case DIV_FMT: + fmt =3D (ctx->opcode >> 8) & 0x3; + if (fmt =3D=3D 1) { + mips32_op =3D OPC_DIV_D; + } else if (fmt =3D=3D 0) { + mips32_op =3D OPC_DIV_S; + } else { + goto pool32f_invalid; + } + goto do_fpop; + default: + goto pool32f_invalid; + } + break; + case 0x38: + /* cmovs */ + switch ((ctx->opcode >> 6) & 0x7) { + case MOVN_FMT: /* SELEQZ_FMT */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* SELEQZ_FMT */ + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs); + break; + case FMT_SDPS_D: + gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs); + break; + default: + goto pool32f_invalid; + } + } else { + /* MOVN_FMT */ + FINSN_3ARG_SDPS(MOVN); + } + break; + case MOVN_FMT_04: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + FINSN_3ARG_SDPS(MOVN); + break; + case MOVZ_FMT: /* SELNEZ_FMT */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* SELNEZ_FMT */ + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs); + break; + case FMT_SDPS_D: + gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs); + break; + default: + goto pool32f_invalid; + } + } else { + /* MOVZ_FMT */ + FINSN_3ARG_SDPS(MOVZ); + } + break; + case MOVZ_FMT_05: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + FINSN_3ARG_SDPS(MOVZ); + break; + case SEL_FMT: + check_insn(ctx, ISA_MIPS_R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs); + break; + case FMT_SDPS_D: + gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs); + break; + default: + goto pool32f_invalid; + } + break; + case MADDF_FMT: + check_insn(ctx, ISA_MIPS_R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + mips32_op =3D OPC_MADDF_S; + goto do_fpop; + case FMT_SDPS_D: + mips32_op =3D OPC_MADDF_D; + goto do_fpop; + default: + goto pool32f_invalid; + } + break; + case MSUBF_FMT: + check_insn(ctx, ISA_MIPS_R6); + switch ((ctx->opcode >> 9) & 0x3) { + case FMT_SDPS_S: + mips32_op =3D OPC_MSUBF_S; + goto do_fpop; + case FMT_SDPS_D: + mips32_op =3D OPC_MSUBF_D; + goto do_fpop; + default: + goto pool32f_invalid; + } + break; + default: + goto pool32f_invalid; + } + break; + do_fpop: + gen_farith(ctx, mips32_op, rt, rs, rd, 0); + break; + default: + pool32f_invalid: + MIPS_INVAL("pool32f"); + gen_reserved_instruction(ctx); + break; + } + } else { + generate_exception_err(ctx, EXCP_CpU, 1); + } + break; + case POOL32I: + minor =3D (ctx->opcode >> 21) & 0x1f; + switch (minor) { + case BLTZ: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4); + break; + case BLTZAL: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4); + ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; + break; + case BLTZALS: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2); + ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; + break; + case BGEZ: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4); + break; + case BGEZAL: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4); + ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; + break; + case BGEZALS: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2); + ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; + break; + case BLEZ: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4); + break; + case BGTZ: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4); + break; + + /* Traps */ + case TLTI: /* BC1EQZC */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* BC1EQZC */ + check_cp1_enabled(ctx); + gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0); + } else { + /* TLTI */ + mips32_op =3D OPC_TLTI; + goto do_trapi; + } + break; + case TGEI: /* BC1NEZC */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* BC1NEZC */ + check_cp1_enabled(ctx); + gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0); + } else { + /* TGEI */ + mips32_op =3D OPC_TGEI; + goto do_trapi; + } + break; + case TLTIU: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_TLTIU; + goto do_trapi; + case TGEIU: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_TGEIU; + goto do_trapi; + case TNEI: /* SYNCI */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* SYNCI */ + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ + ctx->base.is_jmp =3D DISAS_STOP; + } else { + /* TNEI */ + mips32_op =3D OPC_TNEI; + goto do_trapi; + } + break; + case TEQI: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_TEQI; + do_trapi: + gen_trap(ctx, mips32_op, rs, -1, imm); + break; + + case BNEZC: + case BEQZC: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_compute_branch(ctx, minor =3D=3D BNEZC ? OPC_BNE : OPC_BEQ, + 4, rs, 0, imm << 1, 0); + /* + * Compact branches don't have a delay slot, so just let + * the normal delay slot handling take us to the branch + * target. + */ + break; + case LUI: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + gen_logic_imm(ctx, OPC_LUI, rs, 0, imm); + break; + case SYNCI: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ + ctx->base.is_jmp =3D DISAS_STOP; + break; + case BC2F: + case BC2T: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + /* COP2: Not implemented. */ + generate_exception_err(ctx, EXCP_CpU, 2); + break; + case BC1F: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_B= C1F; + goto do_cp1branch; + case BC1T: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_B= C1T; + goto do_cp1branch; + case BC1ANY4F: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_BC1FANY4; + goto do_cp1mips3d; + case BC1ANY4T: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_BC1TANY4; + do_cp1mips3d: + check_cop1x(ctx); + check_insn(ctx, ASE_MIPS3D); + /* Fall through */ + do_cp1branch: + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + check_cp1_enabled(ctx); + gen_compute_branch1(ctx, mips32_op, + (ctx->opcode >> 18) & 0x7, imm << 1); + } else { + generate_exception_err(ctx, EXCP_CpU, 1); + } + break; + default: + MIPS_INVAL("pool32i"); + gen_reserved_instruction(ctx); + break; + } + break; + case POOL32C: + minor =3D (ctx->opcode >> 12) & 0xf; + offset =3D sextract32(ctx->opcode, 0, + (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12); + switch (minor) { + case LWL: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_LWL; + goto do_ld_lr; + case SWL: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_SWL; + goto do_st_lr; + case LWR: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_LWR; + goto do_ld_lr; + case SWR: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_SWR; + goto do_st_lr; +#if defined(TARGET_MIPS64) + case LDL: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_LDL; + goto do_ld_lr; + case SDL: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_SDL; + goto do_st_lr; + case LDR: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_LDR; + goto do_ld_lr; + case SDR: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_SDR; + goto do_st_lr; + case LWU: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + mips32_op =3D OPC_LWU; + goto do_ld_lr; + case LLD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + mips32_op =3D OPC_LLD; + goto do_ld_lr; +#endif + case LL: + mips32_op =3D OPC_LL; + goto do_ld_lr; + do_ld_lr: + gen_ld(ctx, mips32_op, rt, rs, offset); + break; + do_st_lr: + gen_st(ctx, mips32_op, rt, rs, offset); + break; + case SC: + gen_st_cond(ctx, rt, rs, offset, MO_TESL, false); + break; +#if defined(TARGET_MIPS64) + case SCD: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false); + break; +#endif + case LD_EVA: + if (!ctx->eva) { + MIPS_INVAL("pool32c ld-eva"); + gen_reserved_instruction(ctx); + break; + } + check_cp0_enabled(ctx); + + minor2 =3D (ctx->opcode >> 9) & 0x7; + offset =3D sextract32(ctx->opcode, 0, 9); + switch (minor2) { + case LBUE: + mips32_op =3D OPC_LBUE; + goto do_ld_lr; + case LHUE: + mips32_op =3D OPC_LHUE; + goto do_ld_lr; + case LWLE: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_LWLE; + goto do_ld_lr; + case LWRE: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_LWRE; + goto do_ld_lr; + case LBE: + mips32_op =3D OPC_LBE; + goto do_ld_lr; + case LHE: + mips32_op =3D OPC_LHE; + goto do_ld_lr; + case LLE: + mips32_op =3D OPC_LLE; + goto do_ld_lr; + case LWE: + mips32_op =3D OPC_LWE; + goto do_ld_lr; + }; + break; + case ST_EVA: + if (!ctx->eva) { + MIPS_INVAL("pool32c st-eva"); + gen_reserved_instruction(ctx); + break; + } + check_cp0_enabled(ctx); + + minor2 =3D (ctx->opcode >> 9) & 0x7; + offset =3D sextract32(ctx->opcode, 0, 9); + switch (minor2) { + case SWLE: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_SWLE; + goto do_st_lr; + case SWRE: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + mips32_op =3D OPC_SWRE; + goto do_st_lr; + case PREFE: + /* Treat as no-op */ + if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >=3D 24)) { + /* hint codes 24-31 are reserved and signal RI */ + generate_exception(ctx, EXCP_RI); + } + break; + case CACHEE: + /* Treat as no-op */ + if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { + gen_cache_operation(ctx, rt, rs, offset); + } + break; + case SBE: + mips32_op =3D OPC_SBE; + goto do_st_lr; + case SHE: + mips32_op =3D OPC_SHE; + goto do_st_lr; + case SCE: + gen_st_cond(ctx, rt, rs, offset, MO_TESL, true); + break; + case SWE: + mips32_op =3D OPC_SWE; + goto do_st_lr; + }; + break; + case PREF: + /* Treat as no-op */ + if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >=3D 24)) { + /* hint codes 24-31 are reserved and signal RI */ + generate_exception(ctx, EXCP_RI); + } + break; + default: + MIPS_INVAL("pool32c"); + gen_reserved_instruction(ctx); + break; + } + break; + case ADDI32: /* AUI, LUI */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* AUI, LUI */ + gen_logic_imm(ctx, OPC_LUI, rt, rs, imm); + } else { + /* ADDI32 */ + mips32_op =3D OPC_ADDI; + goto do_addi; + } + break; + case ADDIU32: + mips32_op =3D OPC_ADDIU; + do_addi: + gen_arith_imm(ctx, mips32_op, rt, rs, imm); + break; + + /* Logical operations */ + case ORI32: + mips32_op =3D OPC_ORI; + goto do_logici; + case XORI32: + mips32_op =3D OPC_XORI; + goto do_logici; + case ANDI32: + mips32_op =3D OPC_ANDI; + do_logici: + gen_logic_imm(ctx, mips32_op, rt, rs, imm); + break; + + /* Set less than immediate */ + case SLTI32: + mips32_op =3D OPC_SLTI; + goto do_slti; + case SLTIU32: + mips32_op =3D OPC_SLTIU; + do_slti: + gen_slt_imm(ctx, mips32_op, rt, rs, imm); + break; + case JALX32: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + offset =3D (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; + gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4); + ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; + break; + case JALS32: /* BOVC, BEQC, BEQZALC */ + if (ctx->insn_flags & ISA_MIPS_R6) { + if (rs >=3D rt) { + /* BOVC */ + mips32_op =3D OPC_BOVC; + } else if (rs < rt && rs =3D=3D 0) { + /* BEQZALC */ + mips32_op =3D OPC_BEQZALC; + } else { + /* BEQC */ + mips32_op =3D OPC_BEQC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + } else { + /* JALS32 */ + offset =3D (int32_t)(ctx->opcode & 0x3FFFFFF) << 1; + gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2); + ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; + } + break; + case BEQ32: /* BC */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* BC */ + gen_compute_compact_branch(ctx, OPC_BC, 0, 0, + sextract32(ctx->opcode << 1, 0, 27)= ); + } else { + /* BEQ32 */ + gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4); + } + break; + case BNE32: /* BALC */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* BALC */ + gen_compute_compact_branch(ctx, OPC_BALC, 0, 0, + sextract32(ctx->opcode << 1, 0, 27)= ); + } else { + /* BNE32 */ + gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4); + } + break; + case J32: /* BGTZC, BLTZC, BLTC */ + if (ctx->insn_flags & ISA_MIPS_R6) { + if (rs =3D=3D 0 && rt !=3D 0) { + /* BGTZC */ + mips32_op =3D OPC_BGTZC; + } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { + /* BLTZC */ + mips32_op =3D OPC_BLTZC; + } else { + /* BLTC */ + mips32_op =3D OPC_BLTC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + } else { + /* J32 */ + gen_compute_branch(ctx, OPC_J, 4, rt, rs, + (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); + } + break; + case JAL32: /* BLEZC, BGEZC, BGEC */ + if (ctx->insn_flags & ISA_MIPS_R6) { + if (rs =3D=3D 0 && rt !=3D 0) { + /* BLEZC */ + mips32_op =3D OPC_BLEZC; + } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { + /* BGEZC */ + mips32_op =3D OPC_BGEZC; + } else { + /* BGEC */ + mips32_op =3D OPC_BGEC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + } else { + /* JAL32 */ + gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, + (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); + ctx->hflags |=3D MIPS_HFLAG_BDS_STRICT; + } + break; + /* Floating point (COP1) */ + case LWC132: + mips32_op =3D OPC_LWC1; + goto do_cop1; + case LDC132: + mips32_op =3D OPC_LDC1; + goto do_cop1; + case SWC132: + mips32_op =3D OPC_SWC1; + goto do_cop1; + case SDC132: + mips32_op =3D OPC_SDC1; + do_cop1: + gen_cop1_ldst(ctx, mips32_op, rt, rs, imm); + break; + case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */ + if (ctx->insn_flags & ISA_MIPS_R6) { + /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */ + switch ((ctx->opcode >> 16) & 0x1f) { + case ADDIUPC_00: + case ADDIUPC_01: + case ADDIUPC_02: + case ADDIUPC_03: + case ADDIUPC_04: + case ADDIUPC_05: + case ADDIUPC_06: + case ADDIUPC_07: + gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt); + break; + case AUIPC: + gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt); + break; + case ALUIPC: + gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt); + break; + case LWPC_08: + case LWPC_09: + case LWPC_0A: + case LWPC_0B: + case LWPC_0C: + case LWPC_0D: + case LWPC_0E: + case LWPC_0F: + gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt); + break; + default: + generate_exception(ctx, EXCP_RI); + break; + } + } else { + /* ADDIUPC */ + int reg =3D mmreg(ZIMM(ctx->opcode, 23, 3)); + offset =3D SIMM(ctx->opcode, 0, 23) << 2; + + gen_addiupc(ctx, reg, offset, 0, 0); + } + break; + case BNVC: /* BNEC, BNEZALC */ + check_insn(ctx, ISA_MIPS_R6); + if (rs >=3D rt) { + /* BNVC */ + mips32_op =3D OPC_BNVC; + } else if (rs < rt && rs =3D=3D 0) { + /* BNEZALC */ + mips32_op =3D OPC_BNEZALC; + } else { + /* BNEC */ + mips32_op =3D OPC_BNEC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + break; + case R6_BNEZC: /* JIALC */ + check_insn(ctx, ISA_MIPS_R6); + if (rt !=3D 0) { + /* BNEZC */ + gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0, + sextract32(ctx->opcode << 1, 0, 22)= ); + } else { + /* JIALC */ + gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm); + } + break; + case R6_BEQZC: /* JIC */ + check_insn(ctx, ISA_MIPS_R6); + if (rt !=3D 0) { + /* BEQZC */ + gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0, + sextract32(ctx->opcode << 1, 0, 22)= ); + } else { + /* JIC */ + gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm); + } + break; + case BLEZALC: /* BGEZALC, BGEUC */ + check_insn(ctx, ISA_MIPS_R6); + if (rs =3D=3D 0 && rt !=3D 0) { + /* BLEZALC */ + mips32_op =3D OPC_BLEZALC; + } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { + /* BGEZALC */ + mips32_op =3D OPC_BGEZALC; + } else { + /* BGEUC */ + mips32_op =3D OPC_BGEUC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + break; + case BGTZALC: /* BLTZALC, BLTUC */ + check_insn(ctx, ISA_MIPS_R6); + if (rs =3D=3D 0 && rt !=3D 0) { + /* BGTZALC */ + mips32_op =3D OPC_BGTZALC; + } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { + /* BLTZALC */ + mips32_op =3D OPC_BLTZALC; + } else { + /* BLTUC */ + mips32_op =3D OPC_BLTUC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + break; + /* Loads and stores */ + case LB32: + mips32_op =3D OPC_LB; + goto do_ld; + case LBU32: + mips32_op =3D OPC_LBU; + goto do_ld; + case LH32: + mips32_op =3D OPC_LH; + goto do_ld; + case LHU32: + mips32_op =3D OPC_LHU; + goto do_ld; + case LW32: + mips32_op =3D OPC_LW; + goto do_ld; +#ifdef TARGET_MIPS64 + case LD32: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + mips32_op =3D OPC_LD; + goto do_ld; + case SD32: + check_insn(ctx, ISA_MIPS3); + check_mips_64(ctx); + mips32_op =3D OPC_SD; + goto do_st; +#endif + case SB32: + mips32_op =3D OPC_SB; + goto do_st; + case SH32: + mips32_op =3D OPC_SH; + goto do_st; + case SW32: + mips32_op =3D OPC_SW; + goto do_st; + do_ld: + gen_ld(ctx, mips32_op, rt, rs, imm); + break; + do_st: + gen_st(ctx, mips32_op, rt, rs, imm); + break; + default: + gen_reserved_instruction(ctx); + break; + } +} + +static int decode_isa_micromips(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t op; + + /* make sure instructions are on a halfword boundary */ + if (ctx->base.pc_next & 0x1) { + env->CP0_BadVAddr =3D ctx->base.pc_next; + generate_exception_end(ctx, EXCP_AdEL); + return 2; + } + + op =3D (ctx->opcode >> 10) & 0x3f; + /* Enforce properly-sized instructions in a delay slot */ + if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) { + switch (op & 0x7) { /* MSB-3..MSB-5 */ + case 0: + /* POOL32A, POOL32B, POOL32I, POOL32C */ + case 4: + /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32= */ + case 5: + /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */ + case 6: + /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */ + case 7: + /* LB32, LH32, LWC132, LDC132, LW32 */ + if (ctx->hflags & MIPS_HFLAG_BDS16) { + gen_reserved_instruction(ctx); + return 2; + } + break; + case 1: + /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */ + case 2: + /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */ + case 3: + /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */ + if (ctx->hflags & MIPS_HFLAG_BDS32) { + gen_reserved_instruction(ctx); + return 2; + } + break; + } + } + + switch (op) { + case POOL16A: + { + int rd =3D mmreg(uMIPS_RD(ctx->opcode)); + int rs1 =3D mmreg(uMIPS_RS1(ctx->opcode)); + int rs2 =3D mmreg(uMIPS_RS2(ctx->opcode)); + uint32_t opc =3D 0; + + switch (ctx->opcode & 0x1) { + case ADDU16: + opc =3D OPC_ADDU; + break; + case SUBU16: + opc =3D OPC_SUBU; + break; + } + if (ctx->insn_flags & ISA_MIPS_R6) { + /* + * In the Release 6, the register number location in + * the instruction encoding has changed. + */ + gen_arith(ctx, opc, rs1, rd, rs2); + } else { + gen_arith(ctx, opc, rd, rs1, rs2); + } + } + break; + case POOL16B: + { + int rd =3D mmreg(uMIPS_RD(ctx->opcode)); + int rs =3D mmreg(uMIPS_RS(ctx->opcode)); + int amount =3D (ctx->opcode >> 1) & 0x7; + uint32_t opc =3D 0; + amount =3D amount =3D=3D 0 ? 8 : amount; + + switch (ctx->opcode & 0x1) { + case SLL16: + opc =3D OPC_SLL; + break; + case SRL16: + opc =3D OPC_SRL; + break; + } + + gen_shift_imm(ctx, opc, rd, rs, amount); + } + break; + case POOL16C: + if (ctx->insn_flags & ISA_MIPS_R6) { + gen_pool16c_r6_insn(ctx); + } else { + gen_pool16c_insn(ctx); + } + break; + case LWGP16: + { + int rd =3D mmreg(uMIPS_RD(ctx->opcode)); + int rb =3D 28; /* GP */ + int16_t offset =3D SIMM(ctx->opcode, 0, 7) << 2; + + gen_ld(ctx, OPC_LW, rd, rb, offset); + } + break; + case POOL16F: + check_insn_opc_removed(ctx, ISA_MIPS_R6); + if (ctx->opcode & 1) { + gen_reserved_instruction(ctx); + } else { + /* MOVEP */ + int enc_dest =3D uMIPS_RD(ctx->opcode); + int enc_rt =3D uMIPS_RS2(ctx->opcode); + int enc_rs =3D uMIPS_RS1(ctx->opcode); + gen_movep(ctx, enc_dest, enc_rt, enc_rs); + } + break; + case LBU16: + { + int rd =3D mmreg(uMIPS_RD(ctx->opcode)); + int rb =3D mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset =3D ZIMM(ctx->opcode, 0, 4); + offset =3D (offset =3D=3D 0xf ? -1 : offset); + + gen_ld(ctx, OPC_LBU, rd, rb, offset); + } + break; + case LHU16: + { + int rd =3D mmreg(uMIPS_RD(ctx->opcode)); + int rb =3D mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset =3D ZIMM(ctx->opcode, 0, 4) << 1; + + gen_ld(ctx, OPC_LHU, rd, rb, offset); + } + break; + case LWSP16: + { + int rd =3D (ctx->opcode >> 5) & 0x1f; + int rb =3D 29; /* SP */ + int16_t offset =3D ZIMM(ctx->opcode, 0, 5) << 2; + + gen_ld(ctx, OPC_LW, rd, rb, offset); + } + break; + case LW16: + { + int rd =3D mmreg(uMIPS_RD(ctx->opcode)); + int rb =3D mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset =3D ZIMM(ctx->opcode, 0, 4) << 2; + + gen_ld(ctx, OPC_LW, rd, rb, offset); + } + break; + case SB16: + { + int rd =3D mmreg2(uMIPS_RD(ctx->opcode)); + int rb =3D mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset =3D ZIMM(ctx->opcode, 0, 4); + + gen_st(ctx, OPC_SB, rd, rb, offset); + } + break; + case SH16: + { + int rd =3D mmreg2(uMIPS_RD(ctx->opcode)); + int rb =3D mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset =3D ZIMM(ctx->opcode, 0, 4) << 1; + + gen_st(ctx, OPC_SH, rd, rb, offset); + } + break; + case SWSP16: + { + int rd =3D (ctx->opcode >> 5) & 0x1f; + int rb =3D 29; /* SP */ + int16_t offset =3D ZIMM(ctx->opcode, 0, 5) << 2; + + gen_st(ctx, OPC_SW, rd, rb, offset); + } + break; + case SW16: + { + int rd =3D mmreg2(uMIPS_RD(ctx->opcode)); + int rb =3D mmreg(uMIPS_RS(ctx->opcode)); + int16_t offset =3D ZIMM(ctx->opcode, 0, 4) << 2; + + gen_st(ctx, OPC_SW, rd, rb, offset); + } + break; + case MOVE16: + { + int rd =3D uMIPS_RD5(ctx->opcode); + int rs =3D uMIPS_RS5(ctx->opcode); + + gen_arith(ctx, OPC_ADDU, rd, rs, 0); + } + break; + case ANDI16: + gen_andi16(ctx); + break; + case POOL16D: + switch (ctx->opcode & 0x1) { + case ADDIUS5: + gen_addius5(ctx); + break; + case ADDIUSP: + gen_addiusp(ctx); + break; + } + break; + case POOL16E: + switch (ctx->opcode & 0x1) { + case ADDIUR2: + gen_addiur2(ctx); + break; + case ADDIUR1SP: + gen_addiur1sp(ctx); + break; + } + break; + case B16: /* BC16 */ + gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, + sextract32(ctx->opcode, 0, 10) << 1, + (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4); + break; + case BNEZ16: /* BNEZC16 */ + case BEQZ16: /* BEQZC16 */ + gen_compute_branch(ctx, op =3D=3D BNEZ16 ? OPC_BNE : OPC_BEQ, 2, + mmreg(uMIPS_RD(ctx->opcode)), + 0, sextract32(ctx->opcode, 0, 7) << 1, + (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4); + + break; + case LI16: + { + int reg =3D mmreg(uMIPS_RD(ctx->opcode)); + int imm =3D ZIMM(ctx->opcode, 0, 7); + + imm =3D (imm =3D=3D 0x7f ? -1 : imm); + tcg_gen_movi_tl(cpu_gpr[reg], imm); + } + break; + case RES_29: + case RES_31: + case RES_39: + gen_reserved_instruction(ctx); + break; + default: + decode_micromips32_opc(env, ctx); + return 4; + } + + return 2; +} --=20 2.31.1 From nobody Fri May 3 04:33:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.221.48 as permitted sender) client-ip=209.85.221.48; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-f48.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.48 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1623952170; cv=none; d=zohomail.com; s=zohoarc; b=gOVVh6CvqDWDumJbI+w65YLl1s8tYKUOF/RfTfdv8Rw5l3EF9zYr1ssxCqYIH+bw3CY9tnZDS/0N/gZ7sLLldMixPVPTIfBg5yBa2JiM1jKKX6LRYbSXhIa2Z1ANq29sV+TddMznYDMiKO9Ar+7bMyChuD6gJ4HAVJVilOHXyKI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1623952170; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=3cJHVP7PCPcnG9dBbz0rAw/mtV+g+hts+a+OLq73puU=; b=ADyPL5h4GXz1dpMFEg8MH63L6dk5wyg6VjqSbqTK+2zBQvAZ0f0d8EhqeswX7OAI68yjdt7Ss0FkS/Pp9dvJ1eG4j0iiBJtcHlUIYFUy3afyYsP24fDr4+wPN25+SH1I4/V0PpAz5pVLSWR3OIbcIImeBSxP2jfQmlxH0TR3alM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.48 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com [209.85.221.48]) by mx.zohomail.com with SMTPS id 1623952170119572.6340091111119; Thu, 17 Jun 2021 10:49:30 -0700 (PDT) Received: by mail-wr1-f48.google.com with SMTP id n7so7743857wri.3 for ; Thu, 17 Jun 2021 10:49:29 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.. (93.red-83-35-24.dynamicip.rima-tde.net. [83.35.24.93]) by smtp.gmail.com with ESMTPSA id e17sm6947404wre.79.2021.06.17.10.49.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Jun 2021 10:49:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3cJHVP7PCPcnG9dBbz0rAw/mtV+g+hts+a+OLq73puU=; b=MNGqGwHoW/vP+zUZlny2AdixPoU5jkX2uqj7dg2S8MbGCPLjhwB1oGl4/r+t7nmGz4 2R2B4ekeBliFsDBNGhCsl7PpciPvCbT7+VyyzPtu0NEkRLS3Xxih2XjdR+ph5fRBLJS9 1j1xVbz61G7ZXe3Rwc6NfyXvmRgCCuyeGY8S/vdfw0tYmOn7a0pyw/9fvwCopK8QbNMJ XOjPNfJqimxhfhkUpuptJcuMTj96br67D9+7gEWuRY3PB1RNr1iC5lOvgFSsoHUajuQs G8dJtgTIBEw4K2f+RHCz2WWyKPVk3gCbV3pA+fRXwvzFWz165k/54QRktXiaqEweropI ZbZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=3cJHVP7PCPcnG9dBbz0rAw/mtV+g+hts+a+OLq73puU=; b=mEVTAqz3ELTBSi7Vp4zzhz6xyTeVeWXB0O+uwIILWejHIEBqUhWOszk85bZI1Y7hsT +O7fM/ZMINBL3Zlf7F95ZWQYcP02OuGU7NIZNR3LOXAxC6vgwqdyGendLiTxvJhcpadA RfRlC3c5PzZdkvFRag68lWxnztN8ahP748mRqBXCpMH5mp5172M5vAbRS5GEVTAcgbut D1+v88veD2PXBQ16p7/Zd6PKuLyNc81Zw6JPkfBCY1Ch74vhYTYPAYWSnV0rFmvQ+sga omBxsJbg2ouX7NA/gGcEtzFYhYNytj9UnMeNN0wsTVKOkb14uElRyUQM2FuRD4qtP4dn ByyA== X-Gm-Message-State: AOAM530c/nRCF9b4/i5Grm+wakC68O7YrlHsu2uMr+9tJfQ8gZxcJtIu QVEXqM9iZyN8x1+7YA5X0N8= X-Google-Smtp-Source: ABdhPJzWelY9HMhfn643SsMvxAX4n9qDHz2Mbx7qkmJty595B5lkPhsXEnnXRIVku4YDaSLaIYhtng== X-Received: by 2002:a5d:6882:: with SMTP id h2mr6080999wru.243.1623952168323; Thu, 17 Jun 2021 10:49:28 -0700 (PDT) Sender: =?UTF-8?Q?Philippe_Mathieu=2DDaud=C3=A9?= From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Aurelien Jarno , Aleksandar Rikalo , Richard Henderson , Jiaxun Yang Subject: [PATCH 4/4] target/mips: Add declarations for generic DSP TCG helpers Date: Thu, 17 Jun 2021 19:49:07 +0200 Message-Id: <20210617174907.2904067-5-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210617174907.2904067-1-f4bug@amsat.org> References: <20210617174907.2904067-1-f4bug@amsat.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @gmail.com) To be able to extract the DSP ASE translation routines to different source file, declare few TCG helpers, MASK_SPECIAL3 and a DSP register in "translate.h". Signed-off-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Richard Henderson --- target/mips/tcg/translate.h | 7 +++++++ target/mips/tcg/translate.c | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h index c25fad597d5..c6f57de7e0d 100644 --- a/target/mips/tcg/translate.h +++ b/target/mips/tcg/translate.h @@ -52,6 +52,8 @@ typedef struct DisasContext { /* MIPS major opcodes */ #define MASK_OP_MAJOR(op) (op & (0x3F << 26)) =20 +#define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F)) + #define OPC_CP1 (0x11 << 26) =20 /* Coprocessor 1 (rs field) */ @@ -131,6 +133,10 @@ void check_cp1_64bitmode(DisasContext *ctx); void check_cp1_registers(DisasContext *ctx, int regs); void check_cop1x(DisasContext *ctx); =20 +void check_dsp(DisasContext *ctx); +void check_dsp_r2(DisasContext *ctx); +void check_dsp_r3(DisasContext *ctx); + void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offs= et); void gen_move_low32(TCGv ret, TCGv_i64 arg); void gen_move_high32(TCGv ret, TCGv_i64 arg); @@ -168,6 +174,7 @@ extern TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; extern TCGv_i32 fpu_fcr0, fpu_fcr31; extern TCGv_i64 fpu_f64[32]; extern TCGv bcond; +extern TCGv cpu_dspctrl; =20 #define LOG_DISAS(...) = \ do { = \ diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 7b173e2bd2f..97ef816e95f 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -374,7 +374,6 @@ enum { }; =20 /* Special3 opcodes */ -#define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F)) =20 enum { OPC_EXT =3D 0x00 | OPC_SPECIAL3, @@ -1227,8 +1226,9 @@ TCGv cpu_gpr[32], cpu_PC; */ TCGv_i64 cpu_gpr_hi[32]; TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; -static TCGv cpu_dspctrl, btarget; +static TCGv btarget; TCGv bcond; +TCGv cpu_dspctrl; static TCGv cpu_lladdr, cpu_llval; static TCGv_i32 hflags; TCGv_i32 fpu_fcr0, fpu_fcr31; @@ -1633,7 +1633,7 @@ void check_cp1_registers(DisasContext *ctx, int regs) * Verify that the processor is running with DSP instructions enabled. * This is enabled by CP0 Status register MX(24) bit. */ -static inline void check_dsp(DisasContext *ctx) +void check_dsp(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) { if (ctx->insn_flags & ASE_DSP) { @@ -1644,7 +1644,7 @@ static inline void check_dsp(DisasContext *ctx) } } =20 -static inline void check_dsp_r2(DisasContext *ctx) +void check_dsp_r2(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) { if (ctx->insn_flags & ASE_DSP) { @@ -1655,7 +1655,7 @@ static inline void check_dsp_r2(DisasContext *ctx) } } =20 -static inline void check_dsp_r3(DisasContext *ctx) +void check_dsp_r3(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) { if (ctx->insn_flags & ASE_DSP) { --=20 2.31.1