From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.128.41 as permitted sender) client-ip=209.85.128.41; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-f41.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.41 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625232966; cv=none; d=zohomail.com; s=zohoarc; b=ED+i8GJy5S+Lwd0gLxP4vGL+VIptFiNL4It35sqbdM+ifd4zhcn5RwQs1WLL9oDN4+Y9LKqtJuj8mE5FsKXrYFN4GxUY5HrQdgHsgJF2Pn7MNW9pwyKKqe1sWaeAGPUfZdJ4lKGnwNgZAWEm7JKftplRFva3BohizeziQq6xRRc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625232966; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=3L5gBpbgmqBBugkJukw22D8IeaKPnzHPS3VsGEJn7Vs=; b=dLZ9NkEkzFLwWWLe9fMxJK2em0UzxnQ0IeQ95afOqXb0RJ1eI9dxv0Z61Xgb6y2vgymqX1q/0iujc/s9h9BTYVYMhd2V9sSQiVbqPm+cDuxHNgPZ0zJjEJ1q99fxtgjme6qeKicvqtbK8dCGFjIdQOkZmUlZUm6zAWrROTWWkZI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.41 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) by mx.zohomail.com with SMTPS id 1625232966275288.33027230607036; Fri, 2 Jul 2021 06:36:06 -0700 (PDT) Received: by mail-wm1-f41.google.com with SMTP id m41-20020a05600c3b29b02901dcd3733f24so9115809wms.1 for ; Fri, 02 Jul 2021 06:36:05 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id i11sm13450671wmg.18.2021.07.02.06.36.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:36:04 -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=3L5gBpbgmqBBugkJukw22D8IeaKPnzHPS3VsGEJn7Vs=; b=CphryjQtJ6re9YMlgTWuqtGBZ5ScCrt/5jdQ6snyb9ED6aHMhYVDOnR4K+MMEBInWi tUfTpEwIFU6XR80b6b6NXssZWbfQF+vD4mmmYovJI5khIaf9yKttd0orCuP1Zs8wkWSb t+X39hmsCBitES/5V3ZymrUGwNqEXzP1/oG6tDjOBPS2wn4/tTOkCnFdAKV9nOJmWrQn y5P2H8d9N5HQmUiudpAtjrQKNBafln3P63hj5XAVKEnOhdbi+zOeqRYuMNl8EWd5PkUk R7w85PgrO5BlSyFC+HHHlBYDUvUJxoZQ19wLHA3/opCPPvRYcibEfomOAkcBPduY89cB fKXg== 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=3L5gBpbgmqBBugkJukw22D8IeaKPnzHPS3VsGEJn7Vs=; b=f6zM3LlEoI0waCsj10rb0Qs0/FHpV4hakZdacrvvJ4lSAJxM0JmgG7SPpV9pziUOgm Tvbnnmzn6WNT+p4oAX7Yu98qJusGz1A4PnN2xWrXORKoHAjBZKw6MGehhTn2YSkGkkDf c13SjX9/hzoRLmaDFffmSOxI2X9FY+oJcM19M0tP8Vh7WYZUctXcsQ4KcipH0VULRuqn Cr3r5IM67yqPJPI+orDzvPgghGtIm7J+pu9b6kufRbcWhus/70IdXrBKAV64ykghSz2K 5xbPSaxwTqmnsBOs0z5IS0GUXGyCiWlqz2Vh5grS2TsLEoD9QoPi1vfZjrSw7Om95jdy kmYQ== X-Gm-Message-State: AOAM533aVBzxVny2bC8P+olIIklDM8WMd/5tz9EVGpYgRoT3mPM8Cn3q 2d4N1jXuvcn3u+YgyZNv4Nw= X-Google-Smtp-Source: ABdhPJyL5vBEMRfxcu054vvpV7PpjHL1ki2WUWAgOImGqqJ2klrVGVs2clWNne4byi1Mo2k+vNkGAg== X-Received: by 2002:a7b:c0d0:: with SMTP id s16mr16256697wmh.81.1625232964631; Fri, 02 Jul 2021 06:36:04 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson Subject: [PULL 01/18] target/mips: Add declarations for generic TCG helpers Date: Fri, 2 Jul 2021 15:35:40 +0200 Message-Id: <20210702133557.60317-2-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625232967023100001 We want to extract the microMIPS ISA and Code Compaction ASE to new compilation units. We will first extract this code as included source files (.c.inc), then make them new compilation units afterward. The following methods are going to be used externally: micromips_translate.c.inc:1778: gen_ldxs(ctx, rs, rt, rd); micromips_translate.c.inc:1806: gen_align(ctx, 32, rd, rs, ... micromips_translate.c.inc:2859: gen_addiupc(ctx, reg, offset, ... mips16e_translate.c.inc:444: gen_addiupc(ctx, ry, offset, ... To avoid too much code churn, it is simpler to declare these prototypes in "translate.h" now. Signed-off-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Richard Henderson Message-Id: <20210617174907.2904067-2-f4bug@amsat.org> --- 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 b4a454ec09b..3e9945540fc 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -5629,8 +5629,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); } @@ -12778,8 +12777,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 @@ -14510,7 +14509,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 Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.128.48 as permitted sender) client-ip=209.85.128.48; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-f48.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.48 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625232973; cv=none; d=zohomail.com; s=zohoarc; b=XMMvS6raECDhle5ZdU5Au+eqXPRUnS5Cqt9DkY/AJMe09y6LV72PZLDxCHKJEn462tNM/iHXXIVlfGsXzbVpbel8dJ3Ez+7s2D0+foL21CKOZ8fBIFHmUcjPm2pI/XyDwjmVdVArp5Vsfyjaw6Lk3pBJMHlZpKm8Yp9BGZOrmus= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625232973; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=DvVQ7fjUSpNJwtLTixLExXwdnvmo5vRNOUR78BWhF4U=; b=FV0tokXdUOSCxKan75oFGM7QSpBbIrErf1HGtZiZ3wVY+cL72B3+B6gVOEmYHQJjVLXSDW6pamFEkgnxiC/LiNidm9BZNi0+pF0ge9G+WJyXOQveHt0PMLhThK9NcXP5Z6bW727gKP3+lzaveSde4E+yfDMMtB5oVPfxivUg/nk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.48 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) by mx.zohomail.com with SMTPS id 1625232973198560.5454119153669; Fri, 2 Jul 2021 06:36:13 -0700 (PDT) Received: by mail-wm1-f48.google.com with SMTP id a5-20020a7bc1c50000b02901e3bbe0939bso6433186wmj.0 for ; Fri, 02 Jul 2021 06:36:12 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id d12sm3385624wri.77.2021.07.02.06.36.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:36:09 -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=DvVQ7fjUSpNJwtLTixLExXwdnvmo5vRNOUR78BWhF4U=; b=GKOCWFNY4Rw3bqy6sn6Ymu0EEYLykUOmlSPly08pb22hegfYB3QxKXOu74INUbiLQ7 Day5wwECCSkojFddvzPrRDTkW0kl3C8fg5vruYDzpnu3UG6XyvF2b0OltoaFOmBrK7mw wFJZ2Ru46nHgNLGAyrbjLHt3X6Bc0IKjvPyqrx5jiBxUFh6BERLwjluLGJ4iM/qsTK9P 45bjsPK4IKKdVxsQzggxOBCiZS8BqtQPpvBsteFFR424Hx3uZbwt3cdZGdAjqbrMS5yl F3CRh8Q4UlDzOaw/RewTG+hG3urgLy3arUkI2zl9by82mv1jeZMyc4sCMft8GuMyteUQ h/qg== 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=DvVQ7fjUSpNJwtLTixLExXwdnvmo5vRNOUR78BWhF4U=; b=AIwW1dBfRYk35GJBcJ/PG3DVTe3o05PmiahCiKRrNiHH3KX7PO/EUClCPFlK35nKkr nCo/5JwL+vzec9usCmpFztLKNvPFmwy1v6FLYpTRIlzmmQCoMvXqKtlZ8HK2mxnH0rZL Jb3MAwm2va0R1VbNbznSucGY20rC9CS6LOy6++TWviIY9Gf05RTagfTiHvAkesshwDaZ 9XQwj2LmkwvI9TNXzsOr7xiF0Q38kTOsHmALOKUJsP/o/7jSlaquHqhIG2K0DJ9++m37 t6NWU9CywzJrlmlXHP19lPk4PEtOAKcSAZft8ovmzw56WxYlfQcbFo3pbm0wQTvChOYr HSwg== X-Gm-Message-State: AOAM530jY2ObLc/V5aK1G43IQphTLVUAf/bJnJhPR7R/JAJRcATeRjTr G1ykDUmAuTE74wYf9mEnuH8= X-Google-Smtp-Source: ABdhPJxLjLLvJSYyj1fJFOxXvCk9csABGkEI6RxF91MZhNsM1FeM/GMgbXxkZJJg9sVGiOnoXhbBYA== X-Received: by 2002:a1c:9d0b:: with SMTP id g11mr5717807wme.132.1625232970771; Fri, 02 Jul 2021 06:36:10 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson Subject: [PULL 02/18] target/mips: Extract Code Compaction ASE translation routines Date: Fri, 2 Jul 2021 15:35:41 +0200 Message-Id: <20210702133557.60317-3-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625232974001100001 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 3e9945540fc..6690e50670d 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -12392,391 +12392,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) { @@ -12809,267 +12424,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 @@ -13087,476 +12441,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 /* @@ -16849,6 +15733,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 @@ -25491,7 +24380,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 Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.221.49 as permitted sender) client-ip=209.85.221.49; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-f49.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.49 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625232979; cv=none; d=zohomail.com; s=zohoarc; b=hM7OSLd6/3oW96Y2bMuc3e6VVFsLzmoycxyNLfVKJsPrb2xkLeC6Z5DZmPzIKu+7jGH1H2tfVUbhZub+0G3PbLB6ulfMjxEDEBqjODLcQ7+Z9mWADINh9Jj3f3N+hs+Cuh6+xw1V/t4ncmYQClWp00UgZOacJ590k0Gsu/htjn0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625232979; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=v3qAW4d0sxbq/ealuv40MDyvJXRCMcBuMcn2caT5aaU=; b=mMYf7LSUGLBQTfJbnyAsnbRC72XHr2ee72vgpEgoOVg0Fv3vwFFYi9MEegR4gBI2nhCM/UIJaOZx6wNzGXnXvEuzssNiPZ1jykeEPFs/STzA06FqOvBdEdWrD9xsNwEPHYQ1Lf5az0hAWgEYafpZldp+HsXVFwgqXBckxZlVWy4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.49 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) by mx.zohomail.com with SMTPS id 1625232979546980.4469511857034; Fri, 2 Jul 2021 06:36:19 -0700 (PDT) Received: by mail-wr1-f49.google.com with SMTP id p8so12530005wrr.1 for ; Fri, 02 Jul 2021 06:36:18 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id l9sm3295764wrp.14.2021.07.02.06.36.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:36:15 -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=v3qAW4d0sxbq/ealuv40MDyvJXRCMcBuMcn2caT5aaU=; b=s1qRfS09+UNXgYlx3gWmFsEYlZKuDgaKPyESxJC1eOf+P4A6nm19Euj08b2mCo+CnN HfXsOljo/y3b33Xo3VpeS4FEWB8ROdrddNMvEfTs5jmKPq5ZjlVqxMGr8malHF0bYGNc pzCRnXZsuEV7C39kYgUet6Fi5QkRXDFFYBs5TvQgOtWVunqOviwyJ9quH2YPEyvtWXxg yhY+8gpSsrb/gYwFZCoVZF3VcKWSUgscKoOMs+leo3PgH8G5+vwdie+MHxxzdcItOkgb 2NXxOWslyBmfHCIX3Cmql1BoQnla2NbcFb2n3nyLmLVwk1Wd1hD3B7/9Yc+pO8uL0Qrd OMzg== 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=v3qAW4d0sxbq/ealuv40MDyvJXRCMcBuMcn2caT5aaU=; b=iVOow+L67VbcD43FlkgtgkO+36xwN72BNNWJjUf6LTW7e0qvIwu0cU9BTREwKuOnIu j9F7OshH9DPJMAhZ+P/o8OPKbwj/vo7t6MiDOm1WufCWph6adz7GOogMwnZOnzldTven siZe1djt1U0cyta37E8nKGYVKwtfq0wnbMlqPjVBzVugwnT8UDOjgivv2dGxQW+h6F8K E5mV4RuYqGZEY5GZGRoQOmrxSEFgfdGuVPTes+ph6cnntrlSnYu+Lvhrv4AqtWaAuPBh ZViIKEIcccfdq4X1P5FgmrAsPvkfl4HsSuGYZmMJ5l0SvmYZFnjpJBeSybWaTZpAsDhl FqjA== X-Gm-Message-State: AOAM533YwVl8416Hn72Yn5xttSn8YdxCLSCXyTlbm+d1JtjcPLvBu+Yj tEGANX5oDmuE3CGxuCkJR+U= X-Google-Smtp-Source: ABdhPJwwIcmXmGjjAPUxedeKx3MT/pY89RFBjtC2hrFAo6oUST/WNI0w4b4l/Y8oW1VzDiLwcAtDYA== X-Received: by 2002:a5d:6904:: with SMTP id t4mr5021302wru.20.1625232976541; Fri, 02 Jul 2021 06:36:16 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson Subject: [PULL 03/18] target/mips: Extract the microMIPS ISA translation routines Date: Fri, 2 Jul 2021 15:35:42 +0200 Message-Id: <20210702133557.60317-4-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625232980934100001 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 6690e50670d..f4f47f0c552 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -12441,958 +12441,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(); @@ -13413,69 +12461,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; @@ -13504,353 +12489,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 @@ -13873,1870 +12517,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 /* * @@ -24377,7 +21158,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 Mon Feb 9 16:21:58 2026 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=1625232989; cv=none; d=zohomail.com; s=zohoarc; b=cZGM37pAy7i/XNGdkDjLznZKmH2WNKnigIfpklbEppLCm/4q6rmJr0wzVsWmDzKE4/G8BQHwF04G6ABFyyqVfZFPyrue3USLOmAAIA2IxjAv0oLou0fVHj0QaI1oNBo4LO6FWOMYlxlQ8Us1UmSTXfNCKeMDNNalYoPNSu4N6Tk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625232989; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=LK8W1h0h6hZ8IdN6/C+YfViySrR406VCFcagdNIlHQc=; b=KdAygiZsdqt7f2G3ytsZ/TAXQ2Wbtgzx1ZnhutZjqjMZ2az+8Uq2tUua+2RYBqmvens8vj8hdkAHeWhknu76ajvVgfssFK3Kqa9uOaXJUVQVHYrcn0ENGTlDFcKbmqF3Pp86oKT6hiaOT8NGoE3kI2LtOF8PFI8m/AwbeoKAOpU= 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 1625232989322759.003465190974; Fri, 2 Jul 2021 06:36:29 -0700 (PDT) Received: by mail-wr1-f51.google.com with SMTP id t15so9145880wry.11 for ; Fri, 02 Jul 2021 06:36:28 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id m18sm3099408wmq.45.2021.07.02.06.36.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:36:25 -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=LK8W1h0h6hZ8IdN6/C+YfViySrR406VCFcagdNIlHQc=; b=F+ZgXVtvOCbz6Qlzw8/ROq7NZ4GSYd3ic21fcPiJDijetXc055OLXjsZ7nu/6EcfhX EyujHMWBbXzZ1Zi00Wi8o7pgauF96FA1h3zov+zc6LmIBeJ7rI9TYftYc5HfM0fWQUT6 TtVVdDFARmnkBfzxvC+9Zbz4dogRSr75kjH0MjAlLizCF8PaUZaTv7816c6usi3XBcqG bbFWPzbdpQsjrd2Z7DWtkYHDMURjAUAZ4Xc2T68egHHHGeo4nKZrLghMvETWGoU2zWlU OT7WUA6WevhcupFWhOfdME7KVxZr7LuvNuKA8aBccZwYgLDPE2KcwUHHKH2PaElbk3qP NxvA== 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=LK8W1h0h6hZ8IdN6/C+YfViySrR406VCFcagdNIlHQc=; b=IOG+vlsGpRcEWMFIo+Mj5BpbddpQYAE/Ckv9MXOFVNaTa/6KegxC7+kW5gauqHO75A UhY9xhuZ0fvKzl2a5LIItEHZboCcOJjjI5Dkq0YuAIKaJTI+jz01FQ//+uL10dg5qyGs AAXSxyZMxhUniZt1mVOGE1jKP/f/xMjyZef6tSBQxX2T8+b8eYZqERZV0JtfmEglNLz0 eeVqPs5mXvz9mo6IHBNzLRaWOiyuzbxo/VPCXVINALLjTr9ahXA/Hs1eh/PuwJvyce+I JtTQbngj0X8X3vpXjwWNBrFUMu6L0ynx1S+tr9ACQAlRMYy4mmx3dQ+y8DZzlXl3uRsz wOkQ== X-Gm-Message-State: AOAM533ogKWzHh6qP13O/lEGBe3L8X0b6K6P5phZSnTKGbfx0oD6Lwcd Thggcbr1XsHK56t+4Jr7pmqbNvXzx1W5CFBv X-Google-Smtp-Source: ABdhPJyb3524NO5tSDok01HOU2zDUGkk+xP6PwCG7Yjn8blvAvyzOPrMIxxSJ9gzqllM/GWCYCBc9A== X-Received: by 2002:a5d:64c3:: with SMTP id f3mr6025894wri.10.1625232986202; Fri, 02 Jul 2021 06:36:26 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson Subject: [PULL 04/18] target/mips: Extract nanoMIPS ISA translation routines Date: Fri, 2 Jul 2021 15:35:43 +0200 Message-Id: <20210702133557.60317-5-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625232990308100001 Extract 4900 lines from the huge translate.c to a new file, 'nanomips_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-13-f4bug@amsat.org> --- target/mips/tcg/translate.c | 4924 +--------------------- target/mips/tcg/nanomips_translate.c.inc | 4922 +++++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 4925 insertions(+), 4922 deletions(-) create mode 100644 target/mips/tcg/nanomips_translate.c.inc diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index f4f47f0c552..ae33c75f088 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -2278,31 +2278,6 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, tcg_temp_free(t0); } =20 -static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset, - uint32_t reg1, uint32_t reg2) -{ - TCGv taddr =3D tcg_temp_new(); - TCGv_i64 tval =3D tcg_temp_new_i64(); - TCGv tmp1 =3D tcg_temp_new(); - TCGv tmp2 =3D tcg_temp_new(); - - gen_base_offset_addr(ctx, taddr, base, offset); - tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx); -#ifdef TARGET_WORDS_BIGENDIAN - tcg_gen_extr_i64_tl(tmp2, tmp1, tval); -#else - tcg_gen_extr_i64_tl(tmp1, tmp2, tval); -#endif - gen_store_gpr(tmp1, reg1); - tcg_temp_free(tmp1); - gen_store_gpr(tmp2, reg2); - tcg_temp_free(tmp2); - tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp)); - tcg_temp_free_i64(tval); - tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr)); - tcg_temp_free(taddr); -} - /* Store */ static void gen_st(DisasContext *ctx, uint32_t opc, int rt, int base, int offset) @@ -2396,52 +2371,6 @@ static void gen_st_cond(DisasContext *ctx, int rt, i= nt base, int offset, tcg_temp_free(t0); } =20 - -static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset, - uint32_t reg1, uint32_t reg2, bool eva) -{ - TCGv taddr =3D tcg_temp_local_new(); - TCGv lladdr =3D tcg_temp_local_new(); - TCGv_i64 tval =3D tcg_temp_new_i64(); - TCGv_i64 llval =3D tcg_temp_new_i64(); - TCGv_i64 val =3D tcg_temp_new_i64(); - TCGv tmp1 =3D tcg_temp_new(); - TCGv tmp2 =3D tcg_temp_new(); - TCGLabel *lab_fail =3D gen_new_label(); - TCGLabel *lab_done =3D gen_new_label(); - - gen_base_offset_addr(ctx, taddr, base, offset); - - tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr)); - tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail); - - gen_load_gpr(tmp1, reg1); - gen_load_gpr(tmp2, reg2); - -#ifdef TARGET_WORDS_BIGENDIAN - tcg_gen_concat_tl_i64(tval, tmp2, tmp1); -#else - tcg_gen_concat_tl_i64(tval, tmp1, tmp2); -#endif - - tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp)); - tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval, - eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64); - if (reg1 !=3D 0) { - tcg_gen_movi_tl(cpu_gpr[reg1], 1); - } - tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done); - - gen_set_label(lab_fail); - - if (reg1 !=3D 0) { - tcg_gen_movi_tl(cpu_gpr[reg1], 0); - } - gen_set_label(lab_done); - tcg_gen_movi_tl(lladdr, -1); - tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr)); -} - /* Load and store */ static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft, TCGv t0) @@ -5304,129 +5233,6 @@ static void gen_compute_branch(DisasContext *ctx, u= int32_t opc, } =20 =20 -/* nanoMIPS Branches */ -static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc, - int insn_bytes, - int rs, int rt, int32_t offset) -{ - target_ulong btgt =3D -1; - int bcond_compute =3D 0; - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - - /* Load needed operands */ - switch (opc) { - case OPC_BEQ: - case OPC_BNE: - /* Compare two registers */ - if (rs !=3D rt) { - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - bcond_compute =3D 1; - } - btgt =3D ctx->base.pc_next + insn_bytes + offset; - break; - case OPC_BGEZAL: - /* Compare to zero */ - if (rs !=3D 0) { - gen_load_gpr(t0, rs); - bcond_compute =3D 1; - } - btgt =3D ctx->base.pc_next + insn_bytes + offset; - break; - case OPC_BPOSGE32: - tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F); - bcond_compute =3D 1; - btgt =3D ctx->base.pc_next + insn_bytes + offset; - break; - case OPC_JR: - case OPC_JALR: - /* Jump to register */ - if (offset !=3D 0 && offset !=3D 16) { - /* - * Hint =3D 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the - * others are reserved. - */ - MIPS_INVAL("jump hint"); - gen_reserved_instruction(ctx); - goto out; - } - gen_load_gpr(btarget, rs); - break; - default: - MIPS_INVAL("branch/jump"); - gen_reserved_instruction(ctx); - goto out; - } - if (bcond_compute =3D=3D 0) { - /* No condition to be computed */ - switch (opc) { - case OPC_BEQ: /* rx =3D=3D rx */ - /* Always take */ - ctx->hflags |=3D MIPS_HFLAG_B; - break; - case OPC_BGEZAL: /* 0 >=3D 0 */ - /* Always take and link */ - tcg_gen_movi_tl(cpu_gpr[31], - ctx->base.pc_next + insn_bytes); - ctx->hflags |=3D MIPS_HFLAG_B; - break; - case OPC_BNE: /* rx !=3D rx */ - tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8); - /* Skip the instruction in the delay slot */ - ctx->base.pc_next +=3D 4; - goto out; - case OPC_JR: - ctx->hflags |=3D MIPS_HFLAG_BR; - break; - case OPC_JALR: - if (rt > 0) { - tcg_gen_movi_tl(cpu_gpr[rt], - ctx->base.pc_next + insn_bytes); - } - ctx->hflags |=3D MIPS_HFLAG_BR; - break; - default: - MIPS_INVAL("branch/jump"); - gen_reserved_instruction(ctx); - goto out; - } - } else { - switch (opc) { - case OPC_BEQ: - tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); - goto not_likely; - case OPC_BNE: - tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); - goto not_likely; - case OPC_BGEZAL: - tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); - tcg_gen_movi_tl(cpu_gpr[31], - ctx->base.pc_next + insn_bytes); - goto not_likely; - case OPC_BPOSGE32: - tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32); - not_likely: - ctx->hflags |=3D MIPS_HFLAG_BC; - break; - default: - MIPS_INVAL("conditional branch/jump"); - gen_reserved_instruction(ctx); - goto out; - } - } - - ctx->btarget =3D btgt; - - out: - if (insn_bytes =3D=3D 2) { - ctx->hflags |=3D MIPS_HFLAG_B16; - } - tcg_temp_free(t0); - tcg_temp_free(t1); -} - - /* special3 bitfield operations */ static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt, int rs, int lsb, int msb) @@ -5634,12 +5440,6 @@ 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); } =20 -static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt, - int shift) -{ - gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift); -} - static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt) { TCGv t0; @@ -12519,4727 +12319,7 @@ enum { =20 #include "micromips_translate.c.inc" =20 -/* - * - * nanoMIPS opcodes - * - */ - -/* MAJOR, P16, and P32 pools opcodes */ -enum { - NM_P_ADDIU =3D 0x00, - NM_ADDIUPC =3D 0x01, - NM_MOVE_BALC =3D 0x02, - NM_P16_MV =3D 0x04, - NM_LW16 =3D 0x05, - NM_BC16 =3D 0x06, - NM_P16_SR =3D 0x07, - - NM_POOL32A =3D 0x08, - NM_P_BAL =3D 0x0a, - NM_P16_SHIFT =3D 0x0c, - NM_LWSP16 =3D 0x0d, - NM_BALC16 =3D 0x0e, - NM_P16_4X4 =3D 0x0f, - - NM_P_GP_W =3D 0x10, - NM_P_GP_BH =3D 0x11, - NM_P_J =3D 0x12, - NM_P16C =3D 0x14, - NM_LWGP16 =3D 0x15, - NM_P16_LB =3D 0x17, - - NM_P48I =3D 0x18, - NM_P16_A1 =3D 0x1c, - NM_LW4X4 =3D 0x1d, - NM_P16_LH =3D 0x1f, - - NM_P_U12 =3D 0x20, - NM_P_LS_U12 =3D 0x21, - NM_P_BR1 =3D 0x22, - NM_P16_A2 =3D 0x24, - NM_SW16 =3D 0x25, - NM_BEQZC16 =3D 0x26, - - NM_POOL32F =3D 0x28, - NM_P_LS_S9 =3D 0x29, - NM_P_BR2 =3D 0x2a, - - NM_P16_ADDU =3D 0x2c, - NM_SWSP16 =3D 0x2d, - NM_BNEZC16 =3D 0x2e, - NM_MOVEP =3D 0x2f, - - NM_POOL32S =3D 0x30, - NM_P_BRI =3D 0x32, - NM_LI16 =3D 0x34, - NM_SWGP16 =3D 0x35, - NM_P16_BR =3D 0x36, - - NM_P_LUI =3D 0x38, - NM_ANDI16 =3D 0x3c, - NM_SW4X4 =3D 0x3d, - NM_MOVEPREV =3D 0x3f, -}; - -/* POOL32A instruction pool */ -enum { - NM_POOL32A0 =3D 0x00, - NM_SPECIAL2 =3D 0x01, - NM_COP2_1 =3D 0x02, - NM_UDI =3D 0x03, - NM_POOL32A5 =3D 0x05, - NM_POOL32A7 =3D 0x07, -}; - -/* P.GP.W instruction pool */ -enum { - NM_ADDIUGP_W =3D 0x00, - NM_LWGP =3D 0x02, - NM_SWGP =3D 0x03, -}; - -/* P48I instruction pool */ -enum { - NM_LI48 =3D 0x00, - NM_ADDIU48 =3D 0x01, - NM_ADDIUGP48 =3D 0x02, - NM_ADDIUPC48 =3D 0x03, - NM_LWPC48 =3D 0x0b, - NM_SWPC48 =3D 0x0f, -}; - -/* P.U12 instruction pool */ -enum { - NM_ORI =3D 0x00, - NM_XORI =3D 0x01, - NM_ANDI =3D 0x02, - NM_P_SR =3D 0x03, - NM_SLTI =3D 0x04, - NM_SLTIU =3D 0x05, - NM_SEQI =3D 0x06, - NM_ADDIUNEG =3D 0x08, - NM_P_SHIFT =3D 0x0c, - NM_P_ROTX =3D 0x0d, - NM_P_INS =3D 0x0e, - NM_P_EXT =3D 0x0f, -}; - -/* POOL32F instruction pool */ -enum { - NM_POOL32F_0 =3D 0x00, - NM_POOL32F_3 =3D 0x03, - NM_POOL32F_5 =3D 0x05, -}; - -/* POOL32S instruction pool */ -enum { - NM_POOL32S_0 =3D 0x00, - NM_POOL32S_4 =3D 0x04, -}; - -/* P.LUI instruction pool */ -enum { - NM_LUI =3D 0x00, - NM_ALUIPC =3D 0x01, -}; - -/* P.GP.BH instruction pool */ -enum { - NM_LBGP =3D 0x00, - NM_SBGP =3D 0x01, - NM_LBUGP =3D 0x02, - NM_ADDIUGP_B =3D 0x03, - NM_P_GP_LH =3D 0x04, - NM_P_GP_SH =3D 0x05, - NM_P_GP_CP1 =3D 0x06, -}; - -/* P.LS.U12 instruction pool */ -enum { - NM_LB =3D 0x00, - NM_SB =3D 0x01, - NM_LBU =3D 0x02, - NM_P_PREFU12 =3D 0x03, - NM_LH =3D 0x04, - NM_SH =3D 0x05, - NM_LHU =3D 0x06, - NM_LWU =3D 0x07, - NM_LW =3D 0x08, - NM_SW =3D 0x09, - NM_LWC1 =3D 0x0a, - NM_SWC1 =3D 0x0b, - NM_LDC1 =3D 0x0e, - NM_SDC1 =3D 0x0f, -}; - -/* P.LS.S9 instruction pool */ -enum { - NM_P_LS_S0 =3D 0x00, - NM_P_LS_S1 =3D 0x01, - NM_P_LS_E0 =3D 0x02, - NM_P_LS_WM =3D 0x04, - NM_P_LS_UAWM =3D 0x05, -}; - -/* P.BAL instruction pool */ -enum { - NM_BC =3D 0x00, - NM_BALC =3D 0x01, -}; - -/* P.J instruction pool */ -enum { - NM_JALRC =3D 0x00, - NM_JALRC_HB =3D 0x01, - NM_P_BALRSC =3D 0x08, -}; - -/* P.BR1 instruction pool */ -enum { - NM_BEQC =3D 0x00, - NM_P_BR3A =3D 0x01, - NM_BGEC =3D 0x02, - NM_BGEUC =3D 0x03, -}; - -/* P.BR2 instruction pool */ -enum { - NM_BNEC =3D 0x00, - NM_BLTC =3D 0x02, - NM_BLTUC =3D 0x03, -}; - -/* P.BRI instruction pool */ -enum { - NM_BEQIC =3D 0x00, - NM_BBEQZC =3D 0x01, - NM_BGEIC =3D 0x02, - NM_BGEIUC =3D 0x03, - NM_BNEIC =3D 0x04, - NM_BBNEZC =3D 0x05, - NM_BLTIC =3D 0x06, - NM_BLTIUC =3D 0x07, -}; - -/* P16.SHIFT instruction pool */ -enum { - NM_SLL16 =3D 0x00, - NM_SRL16 =3D 0x01, -}; - -/* POOL16C instruction pool */ -enum { - NM_POOL16C_0 =3D 0x00, - NM_LWXS16 =3D 0x01, -}; - -/* P16.A1 instruction pool */ -enum { - NM_ADDIUR1SP =3D 0x01, -}; - -/* P16.A2 instruction pool */ -enum { - NM_ADDIUR2 =3D 0x00, - NM_P_ADDIURS5 =3D 0x01, -}; - -/* P16.ADDU instruction pool */ -enum { - NM_ADDU16 =3D 0x00, - NM_SUBU16 =3D 0x01, -}; - -/* P16.SR instruction pool */ -enum { - NM_SAVE16 =3D 0x00, - NM_RESTORE_JRC16 =3D 0x01, -}; - -/* P16.4X4 instruction pool */ -enum { - NM_ADDU4X4 =3D 0x00, - NM_MUL4X4 =3D 0x01, -}; - -/* P16.LB instruction pool */ -enum { - NM_LB16 =3D 0x00, - NM_SB16 =3D 0x01, - NM_LBU16 =3D 0x02, -}; - -/* P16.LH instruction pool */ -enum { - NM_LH16 =3D 0x00, - NM_SH16 =3D 0x01, - NM_LHU16 =3D 0x02, -}; - -/* P.RI instruction pool */ -enum { - NM_SIGRIE =3D 0x00, - NM_P_SYSCALL =3D 0x01, - NM_BREAK =3D 0x02, - NM_SDBBP =3D 0x03, -}; - -/* POOL32A0 instruction pool */ -enum { - NM_P_TRAP =3D 0x00, - NM_SEB =3D 0x01, - NM_SLLV =3D 0x02, - NM_MUL =3D 0x03, - NM_MFC0 =3D 0x06, - NM_MFHC0 =3D 0x07, - NM_SEH =3D 0x09, - NM_SRLV =3D 0x0a, - NM_MUH =3D 0x0b, - NM_MTC0 =3D 0x0e, - NM_MTHC0 =3D 0x0f, - NM_SRAV =3D 0x12, - NM_MULU =3D 0x13, - NM_ROTRV =3D 0x1a, - NM_MUHU =3D 0x1b, - NM_ADD =3D 0x22, - NM_DIV =3D 0x23, - NM_ADDU =3D 0x2a, - NM_MOD =3D 0x2b, - NM_SUB =3D 0x32, - NM_DIVU =3D 0x33, - NM_RDHWR =3D 0x38, - NM_SUBU =3D 0x3a, - NM_MODU =3D 0x3b, - NM_P_CMOVE =3D 0x42, - NM_FORK =3D 0x45, - NM_MFTR =3D 0x46, - NM_MFHTR =3D 0x47, - NM_AND =3D 0x4a, - NM_YIELD =3D 0x4d, - NM_MTTR =3D 0x4e, - NM_MTHTR =3D 0x4f, - NM_OR =3D 0x52, - NM_D_E_MT_VPE =3D 0x56, - NM_NOR =3D 0x5a, - NM_XOR =3D 0x62, - NM_SLT =3D 0x6a, - NM_P_SLTU =3D 0x72, - NM_SOV =3D 0x7a, -}; - -/* CRC32 instruction pool */ -enum { - NM_CRC32B =3D 0x00, - NM_CRC32H =3D 0x01, - NM_CRC32W =3D 0x02, - NM_CRC32CB =3D 0x04, - NM_CRC32CH =3D 0x05, - NM_CRC32CW =3D 0x06, -}; - -/* POOL32A5 instruction pool */ -enum { - NM_CMP_EQ_PH =3D 0x00, - NM_CMP_LT_PH =3D 0x08, - NM_CMP_LE_PH =3D 0x10, - NM_CMPGU_EQ_QB =3D 0x18, - NM_CMPGU_LT_QB =3D 0x20, - NM_CMPGU_LE_QB =3D 0x28, - NM_CMPGDU_EQ_QB =3D 0x30, - NM_CMPGDU_LT_QB =3D 0x38, - NM_CMPGDU_LE_QB =3D 0x40, - NM_CMPU_EQ_QB =3D 0x48, - NM_CMPU_LT_QB =3D 0x50, - NM_CMPU_LE_QB =3D 0x58, - NM_ADDQ_S_W =3D 0x60, - NM_SUBQ_S_W =3D 0x68, - NM_ADDSC =3D 0x70, - NM_ADDWC =3D 0x78, - - NM_ADDQ_S_PH =3D 0x01, - NM_ADDQH_R_PH =3D 0x09, - NM_ADDQH_R_W =3D 0x11, - NM_ADDU_S_QB =3D 0x19, - NM_ADDU_S_PH =3D 0x21, - NM_ADDUH_R_QB =3D 0x29, - NM_SHRAV_R_PH =3D 0x31, - NM_SHRAV_R_QB =3D 0x39, - NM_SUBQ_S_PH =3D 0x41, - NM_SUBQH_R_PH =3D 0x49, - NM_SUBQH_R_W =3D 0x51, - NM_SUBU_S_QB =3D 0x59, - NM_SUBU_S_PH =3D 0x61, - NM_SUBUH_R_QB =3D 0x69, - NM_SHLLV_S_PH =3D 0x71, - NM_PRECR_SRA_R_PH_W =3D 0x79, - - NM_MULEU_S_PH_QBL =3D 0x12, - NM_MULEU_S_PH_QBR =3D 0x1a, - NM_MULQ_RS_PH =3D 0x22, - NM_MULQ_S_PH =3D 0x2a, - NM_MULQ_RS_W =3D 0x32, - NM_MULQ_S_W =3D 0x3a, - NM_APPEND =3D 0x42, - NM_MODSUB =3D 0x52, - NM_SHRAV_R_W =3D 0x5a, - NM_SHRLV_PH =3D 0x62, - NM_SHRLV_QB =3D 0x6a, - NM_SHLLV_QB =3D 0x72, - NM_SHLLV_S_W =3D 0x7a, - - NM_SHILO =3D 0x03, - - NM_MULEQ_S_W_PHL =3D 0x04, - NM_MULEQ_S_W_PHR =3D 0x0c, - - NM_MUL_S_PH =3D 0x05, - NM_PRECR_QB_PH =3D 0x0d, - NM_PRECRQ_QB_PH =3D 0x15, - NM_PRECRQ_PH_W =3D 0x1d, - NM_PRECRQ_RS_PH_W =3D 0x25, - NM_PRECRQU_S_QB_PH =3D 0x2d, - NM_PACKRL_PH =3D 0x35, - NM_PICK_QB =3D 0x3d, - NM_PICK_PH =3D 0x45, - - NM_SHRA_R_W =3D 0x5e, - NM_SHRA_R_PH =3D 0x66, - NM_SHLL_S_PH =3D 0x76, - NM_SHLL_S_W =3D 0x7e, - - NM_REPL_PH =3D 0x07 -}; - -/* POOL32A7 instruction pool */ -enum { - NM_P_LSX =3D 0x00, - NM_LSA =3D 0x01, - NM_EXTW =3D 0x03, - NM_POOL32AXF =3D 0x07, -}; - -/* P.SR instruction pool */ -enum { - NM_PP_SR =3D 0x00, - NM_P_SR_F =3D 0x01, -}; - -/* P.SHIFT instruction pool */ -enum { - NM_P_SLL =3D 0x00, - NM_SRL =3D 0x02, - NM_SRA =3D 0x04, - NM_ROTR =3D 0x06, -}; - -/* P.ROTX instruction pool */ -enum { - NM_ROTX =3D 0x00, -}; - -/* P.INS instruction pool */ -enum { - NM_INS =3D 0x00, -}; - -/* P.EXT instruction pool */ -enum { - NM_EXT =3D 0x00, -}; - -/* POOL32F_0 (fmt) instruction pool */ -enum { - NM_RINT_S =3D 0x04, - NM_RINT_D =3D 0x44, - NM_ADD_S =3D 0x06, - NM_SELEQZ_S =3D 0x07, - NM_SELEQZ_D =3D 0x47, - NM_CLASS_S =3D 0x0c, - NM_CLASS_D =3D 0x4c, - NM_SUB_S =3D 0x0e, - NM_SELNEZ_S =3D 0x0f, - NM_SELNEZ_D =3D 0x4f, - NM_MUL_S =3D 0x16, - NM_SEL_S =3D 0x17, - NM_SEL_D =3D 0x57, - NM_DIV_S =3D 0x1e, - NM_ADD_D =3D 0x26, - NM_SUB_D =3D 0x2e, - NM_MUL_D =3D 0x36, - NM_MADDF_S =3D 0x37, - NM_MADDF_D =3D 0x77, - NM_DIV_D =3D 0x3e, - NM_MSUBF_S =3D 0x3f, - NM_MSUBF_D =3D 0x7f, -}; - -/* POOL32F_3 instruction pool */ -enum { - NM_MIN_FMT =3D 0x00, - NM_MAX_FMT =3D 0x01, - NM_MINA_FMT =3D 0x04, - NM_MAXA_FMT =3D 0x05, - NM_POOL32FXF =3D 0x07, -}; - -/* POOL32F_5 instruction pool */ -enum { - NM_CMP_CONDN_S =3D 0x00, - NM_CMP_CONDN_D =3D 0x02, -}; - -/* P.GP.LH instruction pool */ -enum { - NM_LHGP =3D 0x00, - NM_LHUGP =3D 0x01, -}; - -/* P.GP.SH instruction pool */ -enum { - NM_SHGP =3D 0x00, -}; - -/* P.GP.CP1 instruction pool */ -enum { - NM_LWC1GP =3D 0x00, - NM_SWC1GP =3D 0x01, - NM_LDC1GP =3D 0x02, - NM_SDC1GP =3D 0x03, -}; - -/* P.LS.S0 instruction pool */ -enum { - NM_LBS9 =3D 0x00, - NM_LHS9 =3D 0x04, - NM_LWS9 =3D 0x08, - NM_LDS9 =3D 0x0c, - - NM_SBS9 =3D 0x01, - NM_SHS9 =3D 0x05, - NM_SWS9 =3D 0x09, - NM_SDS9 =3D 0x0d, - - NM_LBUS9 =3D 0x02, - NM_LHUS9 =3D 0x06, - NM_LWC1S9 =3D 0x0a, - NM_LDC1S9 =3D 0x0e, - - NM_P_PREFS9 =3D 0x03, - NM_LWUS9 =3D 0x07, - NM_SWC1S9 =3D 0x0b, - NM_SDC1S9 =3D 0x0f, -}; - -/* P.LS.S1 instruction pool */ -enum { - NM_ASET_ACLR =3D 0x02, - NM_UALH =3D 0x04, - NM_UASH =3D 0x05, - NM_CACHE =3D 0x07, - NM_P_LL =3D 0x0a, - NM_P_SC =3D 0x0b, -}; - -/* P.LS.E0 instruction pool */ -enum { - NM_LBE =3D 0x00, - NM_SBE =3D 0x01, - NM_LBUE =3D 0x02, - NM_P_PREFE =3D 0x03, - NM_LHE =3D 0x04, - NM_SHE =3D 0x05, - NM_LHUE =3D 0x06, - NM_CACHEE =3D 0x07, - NM_LWE =3D 0x08, - NM_SWE =3D 0x09, - NM_P_LLE =3D 0x0a, - NM_P_SCE =3D 0x0b, -}; - -/* P.PREFE instruction pool */ -enum { - NM_SYNCIE =3D 0x00, - NM_PREFE =3D 0x01, -}; - -/* P.LLE instruction pool */ -enum { - NM_LLE =3D 0x00, - NM_LLWPE =3D 0x01, -}; - -/* P.SCE instruction pool */ -enum { - NM_SCE =3D 0x00, - NM_SCWPE =3D 0x01, -}; - -/* P.LS.WM instruction pool */ -enum { - NM_LWM =3D 0x00, - NM_SWM =3D 0x01, -}; - -/* P.LS.UAWM instruction pool */ -enum { - NM_UALWM =3D 0x00, - NM_UASWM =3D 0x01, -}; - -/* P.BR3A instruction pool */ -enum { - NM_BC1EQZC =3D 0x00, - NM_BC1NEZC =3D 0x01, - NM_BC2EQZC =3D 0x02, - NM_BC2NEZC =3D 0x03, - NM_BPOSGE32C =3D 0x04, -}; - -/* P16.RI instruction pool */ -enum { - NM_P16_SYSCALL =3D 0x01, - NM_BREAK16 =3D 0x02, - NM_SDBBP16 =3D 0x03, -}; - -/* POOL16C_0 instruction pool */ -enum { - NM_POOL16C_00 =3D 0x00, -}; - -/* P16.JRC instruction pool */ -enum { - NM_JRC =3D 0x00, - NM_JALRC16 =3D 0x01, -}; - -/* P.SYSCALL instruction pool */ -enum { - NM_SYSCALL =3D 0x00, - NM_HYPCALL =3D 0x01, -}; - -/* P.TRAP instruction pool */ -enum { - NM_TEQ =3D 0x00, - NM_TNE =3D 0x01, -}; - -/* P.CMOVE instruction pool */ -enum { - NM_MOVZ =3D 0x00, - NM_MOVN =3D 0x01, -}; - -/* POOL32Axf instruction pool */ -enum { - NM_POOL32AXF_1 =3D 0x01, - NM_POOL32AXF_2 =3D 0x02, - NM_POOL32AXF_4 =3D 0x04, - NM_POOL32AXF_5 =3D 0x05, - NM_POOL32AXF_7 =3D 0x07, -}; - -/* POOL32Axf_1 instruction pool */ -enum { - NM_POOL32AXF_1_0 =3D 0x00, - NM_POOL32AXF_1_1 =3D 0x01, - NM_POOL32AXF_1_3 =3D 0x03, - NM_POOL32AXF_1_4 =3D 0x04, - NM_POOL32AXF_1_5 =3D 0x05, - NM_POOL32AXF_1_7 =3D 0x07, -}; - -/* POOL32Axf_2 instruction pool */ -enum { - NM_POOL32AXF_2_0_7 =3D 0x00, - NM_POOL32AXF_2_8_15 =3D 0x01, - NM_POOL32AXF_2_16_23 =3D 0x02, - NM_POOL32AXF_2_24_31 =3D 0x03, -}; - -/* POOL32Axf_7 instruction pool */ -enum { - NM_SHRA_R_QB =3D 0x0, - NM_SHRL_PH =3D 0x1, - NM_REPL_QB =3D 0x2, -}; - -/* POOL32Axf_1_0 instruction pool */ -enum { - NM_MFHI =3D 0x0, - NM_MFLO =3D 0x1, - NM_MTHI =3D 0x2, - NM_MTLO =3D 0x3, -}; - -/* POOL32Axf_1_1 instruction pool */ -enum { - NM_MTHLIP =3D 0x0, - NM_SHILOV =3D 0x1, -}; - -/* POOL32Axf_1_3 instruction pool */ -enum { - NM_RDDSP =3D 0x0, - NM_WRDSP =3D 0x1, - NM_EXTP =3D 0x2, - NM_EXTPDP =3D 0x3, -}; - -/* POOL32Axf_1_4 instruction pool */ -enum { - NM_SHLL_QB =3D 0x0, - NM_SHRL_QB =3D 0x1, -}; - -/* POOL32Axf_1_5 instruction pool */ -enum { - NM_MAQ_S_W_PHR =3D 0x0, - NM_MAQ_S_W_PHL =3D 0x1, - NM_MAQ_SA_W_PHR =3D 0x2, - NM_MAQ_SA_W_PHL =3D 0x3, -}; - -/* POOL32Axf_1_7 instruction pool */ -enum { - NM_EXTR_W =3D 0x0, - NM_EXTR_R_W =3D 0x1, - NM_EXTR_RS_W =3D 0x2, - NM_EXTR_S_H =3D 0x3, -}; - -/* POOL32Axf_2_0_7 instruction pool */ -enum { - NM_DPA_W_PH =3D 0x0, - NM_DPAQ_S_W_PH =3D 0x1, - NM_DPS_W_PH =3D 0x2, - NM_DPSQ_S_W_PH =3D 0x3, - NM_BALIGN =3D 0x4, - NM_MADD =3D 0x5, - NM_MULT =3D 0x6, - NM_EXTRV_W =3D 0x7, -}; - -/* POOL32Axf_2_8_15 instruction pool */ -enum { - NM_DPAX_W_PH =3D 0x0, - NM_DPAQ_SA_L_W =3D 0x1, - NM_DPSX_W_PH =3D 0x2, - NM_DPSQ_SA_L_W =3D 0x3, - NM_MADDU =3D 0x5, - NM_MULTU =3D 0x6, - NM_EXTRV_R_W =3D 0x7, -}; - -/* POOL32Axf_2_16_23 instruction pool */ -enum { - NM_DPAU_H_QBL =3D 0x0, - NM_DPAQX_S_W_PH =3D 0x1, - NM_DPSU_H_QBL =3D 0x2, - NM_DPSQX_S_W_PH =3D 0x3, - NM_EXTPV =3D 0x4, - NM_MSUB =3D 0x5, - NM_MULSA_W_PH =3D 0x6, - NM_EXTRV_RS_W =3D 0x7, -}; - -/* POOL32Axf_2_24_31 instruction pool */ -enum { - NM_DPAU_H_QBR =3D 0x0, - NM_DPAQX_SA_W_PH =3D 0x1, - NM_DPSU_H_QBR =3D 0x2, - NM_DPSQX_SA_W_PH =3D 0x3, - NM_EXTPDPV =3D 0x4, - NM_MSUBU =3D 0x5, - NM_MULSAQ_S_W_PH =3D 0x6, - NM_EXTRV_S_H =3D 0x7, -}; - -/* POOL32Axf_{4, 5} instruction pool */ -enum { - NM_CLO =3D 0x25, - NM_CLZ =3D 0x2d, - - NM_TLBP =3D 0x01, - NM_TLBR =3D 0x09, - NM_TLBWI =3D 0x11, - NM_TLBWR =3D 0x19, - NM_TLBINV =3D 0x03, - NM_TLBINVF =3D 0x0b, - NM_DI =3D 0x23, - NM_EI =3D 0x2b, - NM_RDPGPR =3D 0x70, - NM_WRPGPR =3D 0x78, - NM_WAIT =3D 0x61, - NM_DERET =3D 0x71, - NM_ERETX =3D 0x79, - - /* nanoMIPS DSP instructions */ - NM_ABSQ_S_QB =3D 0x00, - NM_ABSQ_S_PH =3D 0x08, - NM_ABSQ_S_W =3D 0x10, - NM_PRECEQ_W_PHL =3D 0x28, - NM_PRECEQ_W_PHR =3D 0x30, - NM_PRECEQU_PH_QBL =3D 0x38, - NM_PRECEQU_PH_QBR =3D 0x48, - NM_PRECEU_PH_QBL =3D 0x58, - NM_PRECEU_PH_QBR =3D 0x68, - NM_PRECEQU_PH_QBLA =3D 0x39, - NM_PRECEQU_PH_QBRA =3D 0x49, - NM_PRECEU_PH_QBLA =3D 0x59, - NM_PRECEU_PH_QBRA =3D 0x69, - NM_REPLV_PH =3D 0x01, - NM_REPLV_QB =3D 0x09, - NM_BITREV =3D 0x18, - NM_INSV =3D 0x20, - NM_RADDU_W_QB =3D 0x78, - - NM_BITSWAP =3D 0x05, - NM_WSBH =3D 0x3d, -}; - -/* PP.SR instruction pool */ -enum { - NM_SAVE =3D 0x00, - NM_RESTORE =3D 0x02, - NM_RESTORE_JRC =3D 0x03, -}; - -/* P.SR.F instruction pool */ -enum { - NM_SAVEF =3D 0x00, - NM_RESTOREF =3D 0x01, -}; - -/* P16.SYSCALL instruction pool */ -enum { - NM_SYSCALL16 =3D 0x00, - NM_HYPCALL16 =3D 0x01, -}; - -/* POOL16C_00 instruction pool */ -enum { - NM_NOT16 =3D 0x00, - NM_XOR16 =3D 0x01, - NM_AND16 =3D 0x02, - NM_OR16 =3D 0x03, -}; - -/* PP.LSX and PP.LSXS instruction pool */ -enum { - NM_LBX =3D 0x00, - NM_LHX =3D 0x04, - NM_LWX =3D 0x08, - NM_LDX =3D 0x0c, - - NM_SBX =3D 0x01, - NM_SHX =3D 0x05, - NM_SWX =3D 0x09, - NM_SDX =3D 0x0d, - - NM_LBUX =3D 0x02, - NM_LHUX =3D 0x06, - NM_LWC1X =3D 0x0a, - NM_LDC1X =3D 0x0e, - - NM_LWUX =3D 0x07, - NM_SWC1X =3D 0x0b, - NM_SDC1X =3D 0x0f, - - NM_LHXS =3D 0x04, - NM_LWXS =3D 0x08, - NM_LDXS =3D 0x0c, - - NM_SHXS =3D 0x05, - NM_SWXS =3D 0x09, - NM_SDXS =3D 0x0d, - - NM_LHUXS =3D 0x06, - NM_LWC1XS =3D 0x0a, - NM_LDC1XS =3D 0x0e, - - NM_LWUXS =3D 0x07, - NM_SWC1XS =3D 0x0b, - NM_SDC1XS =3D 0x0f, -}; - -/* ERETx instruction pool */ -enum { - NM_ERET =3D 0x00, - NM_ERETNC =3D 0x01, -}; - -/* POOL32FxF_{0, 1} insturction pool */ -enum { - NM_CFC1 =3D 0x40, - NM_CTC1 =3D 0x60, - NM_MFC1 =3D 0x80, - NM_MTC1 =3D 0xa0, - NM_MFHC1 =3D 0xc0, - NM_MTHC1 =3D 0xe0, - - NM_CVT_S_PL =3D 0x84, - NM_CVT_S_PU =3D 0xa4, - - NM_CVT_L_S =3D 0x004, - NM_CVT_L_D =3D 0x104, - NM_CVT_W_S =3D 0x024, - NM_CVT_W_D =3D 0x124, - - NM_RSQRT_S =3D 0x008, - NM_RSQRT_D =3D 0x108, - - NM_SQRT_S =3D 0x028, - NM_SQRT_D =3D 0x128, - - NM_RECIP_S =3D 0x048, - NM_RECIP_D =3D 0x148, - - NM_FLOOR_L_S =3D 0x00c, - NM_FLOOR_L_D =3D 0x10c, - - NM_FLOOR_W_S =3D 0x02c, - NM_FLOOR_W_D =3D 0x12c, - - NM_CEIL_L_S =3D 0x04c, - NM_CEIL_L_D =3D 0x14c, - NM_CEIL_W_S =3D 0x06c, - NM_CEIL_W_D =3D 0x16c, - NM_TRUNC_L_S =3D 0x08c, - NM_TRUNC_L_D =3D 0x18c, - NM_TRUNC_W_S =3D 0x0ac, - NM_TRUNC_W_D =3D 0x1ac, - NM_ROUND_L_S =3D 0x0cc, - NM_ROUND_L_D =3D 0x1cc, - NM_ROUND_W_S =3D 0x0ec, - NM_ROUND_W_D =3D 0x1ec, - - NM_MOV_S =3D 0x01, - NM_MOV_D =3D 0x81, - NM_ABS_S =3D 0x0d, - NM_ABS_D =3D 0x8d, - NM_NEG_S =3D 0x2d, - NM_NEG_D =3D 0xad, - NM_CVT_D_S =3D 0x04d, - NM_CVT_D_W =3D 0x0cd, - NM_CVT_D_L =3D 0x14d, - NM_CVT_S_D =3D 0x06d, - NM_CVT_S_W =3D 0x0ed, - NM_CVT_S_L =3D 0x16d, -}; - -/* P.LL instruction pool */ -enum { - NM_LL =3D 0x00, - NM_LLWP =3D 0x01, -}; - -/* P.SC instruction pool */ -enum { - NM_SC =3D 0x00, - NM_SCWP =3D 0x01, -}; - -/* P.DVP instruction pool */ -enum { - NM_DVP =3D 0x00, - NM_EVP =3D 0x01, -}; - - -/* - * - * nanoMIPS decoding engine - * - */ - - -/* extraction utilities */ - -#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7) -#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7) -#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7) -#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f) -#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f) - -/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */ -static inline int decode_gpr_gpr3(int r) -{ - static const int map[] =3D { 16, 17, 18, 19, 4, 5, 6, 7 }; - - return map[r & 0x7]; -} - -/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store')= . */ -static inline int decode_gpr_gpr3_src_store(int r) -{ - static const int map[] =3D { 0, 17, 18, 19, 4, 5, 6, 7 }; - - return map[r & 0x7]; -} - -/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */ -static inline int decode_gpr_gpr4(int r) -{ - static const int map[] =3D { 8, 9, 10, 11, 4, 5, 6, 7, - 16, 17, 18, 19, 20, 21, 22, 23 }; - - return map[r & 0xf]; -} - -/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */ -static inline int decode_gpr_gpr4_zero(int r) -{ - static const int map[] =3D { 8, 9, 10, 0, 4, 5, 6, 7, - 16, 17, 18, 19, 20, 21, 22, 23 }; - - return map[r & 0xf]; -} - - -static void gen_adjust_sp(DisasContext *ctx, int u) -{ - gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u); -} - -static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count, - uint8_t gp, uint16_t u) -{ - int counter =3D 0; - TCGv va =3D tcg_temp_new(); - TCGv t0 =3D tcg_temp_new(); - - while (counter !=3D count) { - bool use_gp =3D gp && (counter =3D=3D count - 1); - int this_rt =3D use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f= ); - int this_offset =3D -((counter + 1) << 2); - gen_base_offset_addr(ctx, va, 29, this_offset); - gen_load_gpr(t0, this_rt); - tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx, - (MO_TEUL | ctx->default_tcg_memop_mask)); - counter++; - } - - /* adjust stack pointer */ - gen_adjust_sp(ctx, -u); - - tcg_temp_free(t0); - tcg_temp_free(va); -} - -static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count, - uint8_t gp, uint16_t u) -{ - int counter =3D 0; - TCGv va =3D tcg_temp_new(); - TCGv t0 =3D tcg_temp_new(); - - while (counter !=3D count) { - bool use_gp =3D gp && (counter =3D=3D count - 1); - int this_rt =3D use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f= ); - int this_offset =3D u - ((counter + 1) << 2); - gen_base_offset_addr(ctx, va, 29, this_offset); - tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL | - ctx->default_tcg_memop_mask); - tcg_gen_ext32s_tl(t0, t0); - gen_store_gpr(t0, this_rt); - counter++; - } - - /* adjust stack pointer */ - gen_adjust_sp(ctx, u); - - tcg_temp_free(t0); - tcg_temp_free(va); -} - -static void gen_pool16c_nanomips_insn(DisasContext *ctx) -{ - int rt =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode)); - int rs =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); - - switch (extract32(ctx->opcode, 2, 2)) { - case NM_NOT16: - gen_logic(ctx, OPC_NOR, rt, rs, 0); - break; - case NM_AND16: - gen_logic(ctx, OPC_AND, rt, rt, rs); - break; - case NM_XOR16: - gen_logic(ctx, OPC_XOR, rt, rt, rs); - break; - case NM_OR16: - gen_logic(ctx, OPC_OR, rt, rt, rs); - break; - } -} - -static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ct= x) -{ - int rt =3D extract32(ctx->opcode, 21, 5); - int rs =3D extract32(ctx->opcode, 16, 5); - int rd =3D extract32(ctx->opcode, 11, 5); - - switch (extract32(ctx->opcode, 3, 7)) { - case NM_P_TRAP: - switch (extract32(ctx->opcode, 10, 1)) { - case NM_TEQ: - check_nms(ctx); - gen_trap(ctx, OPC_TEQ, rs, rt, -1); - break; - case NM_TNE: - check_nms(ctx); - gen_trap(ctx, OPC_TNE, rs, rt, -1); - break; - } - break; - case NM_RDHWR: - check_nms(ctx); - gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); - break; - case NM_SEB: - check_nms(ctx); - gen_bshfl(ctx, OPC_SEB, rs, rt); - break; - case NM_SEH: - gen_bshfl(ctx, OPC_SEH, rs, rt); - break; - case NM_SLLV: - gen_shift(ctx, OPC_SLLV, rd, rt, rs); - break; - case NM_SRLV: - gen_shift(ctx, OPC_SRLV, rd, rt, rs); - break; - case NM_SRAV: - gen_shift(ctx, OPC_SRAV, rd, rt, rs); - break; - case NM_ROTRV: - gen_shift(ctx, OPC_ROTRV, rd, rt, rs); - break; - case NM_ADD: - gen_arith(ctx, OPC_ADD, rd, rs, rt); - break; - case NM_ADDU: - gen_arith(ctx, OPC_ADDU, rd, rs, rt); - break; - case NM_SUB: - check_nms(ctx); - gen_arith(ctx, OPC_SUB, rd, rs, rt); - break; - case NM_SUBU: - gen_arith(ctx, OPC_SUBU, rd, rs, rt); - break; - case NM_P_CMOVE: - switch (extract32(ctx->opcode, 10, 1)) { - case NM_MOVZ: - gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt); - break; - case NM_MOVN: - gen_cond_move(ctx, OPC_MOVN, rd, rs, rt); - break; - } - break; - case NM_AND: - gen_logic(ctx, OPC_AND, rd, rs, rt); - break; - case NM_OR: - gen_logic(ctx, OPC_OR, rd, rs, rt); - break; - case NM_NOR: - gen_logic(ctx, OPC_NOR, rd, rs, rt); - break; - case NM_XOR: - gen_logic(ctx, OPC_XOR, rd, rs, rt); - break; - case NM_SLT: - gen_slt(ctx, OPC_SLT, rd, rs, rt); - break; - case NM_P_SLTU: - if (rd =3D=3D 0) { - /* P_DVP */ -#ifndef CONFIG_USER_ONLY - TCGv t0 =3D tcg_temp_new(); - switch (extract32(ctx->opcode, 10, 1)) { - case NM_DVP: - if (ctx->vp) { - check_cp0_enabled(ctx); - gen_helper_dvp(t0, cpu_env); - gen_store_gpr(t0, rt); - } - break; - case NM_EVP: - if (ctx->vp) { - check_cp0_enabled(ctx); - gen_helper_evp(t0, cpu_env); - gen_store_gpr(t0, rt); - } - break; - } - tcg_temp_free(t0); -#endif - } else { - gen_slt(ctx, OPC_SLTU, rd, rs, rt); - } - break; - case NM_SOV: - { - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - TCGv t2 =3D tcg_temp_new(); - - gen_load_gpr(t1, rs); - gen_load_gpr(t2, rt); - tcg_gen_add_tl(t0, t1, t2); - tcg_gen_ext32s_tl(t0, t0); - tcg_gen_xor_tl(t1, t1, t2); - tcg_gen_xor_tl(t2, t0, t2); - tcg_gen_andc_tl(t1, t2, t1); - - /* operands of same sign, result different sign */ - tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0); - gen_store_gpr(t0, rd); - - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(t2); - } - break; - case NM_MUL: - gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt); - break; - case NM_MUH: - gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt); - break; - case NM_MULU: - gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt); - break; - case NM_MUHU: - gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt); - break; - case NM_DIV: - gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt); - break; - case NM_MOD: - gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt); - break; - case NM_DIVU: - gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt); - break; - case NM_MODU: - gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt); - break; -#ifndef CONFIG_USER_ONLY - case NM_MFC0: - check_cp0_enabled(ctx); - if (rt =3D=3D 0) { - /* Treat as NOP. */ - break; - } - gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3)); - break; - case NM_MTC0: - check_cp0_enabled(ctx); - { - TCGv t0 =3D tcg_temp_new(); - - gen_load_gpr(t0, rt); - gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3)); - tcg_temp_free(t0); - } - break; - case NM_D_E_MT_VPE: - { - uint8_t sc =3D extract32(ctx->opcode, 10, 1); - TCGv t0 =3D tcg_temp_new(); - - switch (sc) { - case 0: - if (rs =3D=3D 1) { - /* DMT */ - check_cp0_mt(ctx); - gen_helper_dmt(t0); - gen_store_gpr(t0, rt); - } else if (rs =3D=3D 0) { - /* DVPE */ - check_cp0_mt(ctx); - gen_helper_dvpe(t0, cpu_env); - gen_store_gpr(t0, rt); - } else { - gen_reserved_instruction(ctx); - } - break; - case 1: - if (rs =3D=3D 1) { - /* EMT */ - check_cp0_mt(ctx); - gen_helper_emt(t0); - gen_store_gpr(t0, rt); - } else if (rs =3D=3D 0) { - /* EVPE */ - check_cp0_mt(ctx); - gen_helper_evpe(t0, cpu_env); - gen_store_gpr(t0, rt); - } else { - gen_reserved_instruction(ctx); - } - break; - } - - tcg_temp_free(t0); - } - break; - case NM_FORK: - check_mt(ctx); - { - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - - gen_load_gpr(t0, rt); - gen_load_gpr(t1, rs); - gen_helper_fork(t0, t1); - tcg_temp_free(t0); - tcg_temp_free(t1); - } - break; - case NM_MFTR: - case NM_MFHTR: - check_cp0_enabled(ctx); - if (rd =3D=3D 0) { - /* Treat as NOP. */ - return; - } - gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1), - extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, = 1)); - break; - case NM_MTTR: - case NM_MTHTR: - check_cp0_enabled(ctx); - gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1), - extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, = 1)); - break; - case NM_YIELD: - check_mt(ctx); - { - TCGv t0 =3D tcg_temp_new(); - - gen_load_gpr(t0, rs); - gen_helper_yield(t0, cpu_env, t0); - gen_store_gpr(t0, rt); - tcg_temp_free(t0); - } - break; -#endif - default: - gen_reserved_instruction(ctx); - break; - } -} - -/* dsp */ -static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t op= c, - int ret, int v1, int v2) -{ - TCGv_i32 t0; - TCGv v0_t; - TCGv v1_t; - - t0 =3D tcg_temp_new_i32(); - - v0_t =3D tcg_temp_new(); - v1_t =3D tcg_temp_new(); - - tcg_gen_movi_i32(t0, v2 >> 3); - - gen_load_gpr(v0_t, ret); - gen_load_gpr(v1_t, v1); - - switch (opc) { - case NM_MAQ_S_W_PHR: - check_dsp(ctx); - gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env); - break; - case NM_MAQ_S_W_PHL: - check_dsp(ctx); - gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env); - break; - case NM_MAQ_SA_W_PHR: - check_dsp(ctx); - gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env); - break; - case NM_MAQ_SA_W_PHL: - check_dsp(ctx); - gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env); - break; - default: - gen_reserved_instruction(ctx); - break; - } - - tcg_temp_free_i32(t0); - - tcg_temp_free(v0_t); - tcg_temp_free(v1_t); -} - - -static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc, - int ret, int v1, int v2) -{ - int16_t imm; - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - TCGv v0_t =3D tcg_temp_new(); - - gen_load_gpr(v0_t, v1); - - switch (opc) { - case NM_POOL32AXF_1_0: - check_dsp(ctx); - switch (extract32(ctx->opcode, 12, 2)) { - case NM_MFHI: - gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret); - break; - case NM_MFLO: - gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret); - break; - case NM_MTHI: - gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1); - break; - case NM_MTLO: - gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1); - break; - } - break; - case NM_POOL32AXF_1_1: - check_dsp(ctx); - switch (extract32(ctx->opcode, 12, 2)) { - case NM_MTHLIP: - tcg_gen_movi_tl(t0, v2); - gen_helper_mthlip(t0, v0_t, cpu_env); - break; - case NM_SHILOV: - tcg_gen_movi_tl(t0, v2 >> 3); - gen_helper_shilo(t0, v0_t, cpu_env); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_POOL32AXF_1_3: - check_dsp(ctx); - imm =3D extract32(ctx->opcode, 14, 7); - switch (extract32(ctx->opcode, 12, 2)) { - case NM_RDDSP: - tcg_gen_movi_tl(t0, imm); - gen_helper_rddsp(t0, t0, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_WRDSP: - gen_load_gpr(t0, ret); - tcg_gen_movi_tl(t1, imm); - gen_helper_wrdsp(t0, t1, cpu_env); - break; - case NM_EXTP: - tcg_gen_movi_tl(t0, v2 >> 3); - tcg_gen_movi_tl(t1, v1); - gen_helper_extp(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_EXTPDP: - tcg_gen_movi_tl(t0, v2 >> 3); - tcg_gen_movi_tl(t1, v1); - gen_helper_extpdp(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - } - break; - case NM_POOL32AXF_1_4: - check_dsp(ctx); - tcg_gen_movi_tl(t0, v2 >> 2); - switch (extract32(ctx->opcode, 12, 1)) { - case NM_SHLL_QB: - gen_helper_shll_qb(t0, t0, v0_t, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_SHRL_QB: - gen_helper_shrl_qb(t0, t0, v0_t); - gen_store_gpr(t0, ret); - break; - } - break; - case NM_POOL32AXF_1_5: - opc =3D extract32(ctx->opcode, 12, 2); - gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2); - break; - case NM_POOL32AXF_1_7: - check_dsp(ctx); - tcg_gen_movi_tl(t0, v2 >> 3); - tcg_gen_movi_tl(t1, v1); - switch (extract32(ctx->opcode, 12, 2)) { - case NM_EXTR_W: - gen_helper_extr_w(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_EXTR_R_W: - gen_helper_extr_r_w(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_EXTR_RS_W: - gen_helper_extr_rs_w(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_EXTR_S_H: - gen_helper_extr_s_h(t0, t0, t1, cpu_env); - gen_store_gpr(t0, ret); - break; - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_temp_free(v0_t); -} - -static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc, - TCGv v0, TCGv v1, int rd) -{ - TCGv_i32 t0; - - t0 =3D tcg_temp_new_i32(); - - tcg_gen_movi_i32(t0, rd >> 3); - - switch (opc) { - case NM_POOL32AXF_2_0_7: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPA_W_PH: - check_dsp_r2(ctx); - gen_helper_dpa_w_ph(t0, v1, v0, cpu_env); - break; - case NM_DPAQ_S_W_PH: - check_dsp(ctx); - gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env); - break; - case NM_DPS_W_PH: - check_dsp_r2(ctx); - gen_helper_dps_w_ph(t0, v1, v0, cpu_env); - break; - case NM_DPSQ_S_W_PH: - check_dsp(ctx); - gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_POOL32AXF_2_8_15: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAX_W_PH: - check_dsp_r2(ctx); - gen_helper_dpax_w_ph(t0, v0, v1, cpu_env); - break; - case NM_DPAQ_SA_L_W: - check_dsp(ctx); - gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env); - break; - case NM_DPSX_W_PH: - check_dsp_r2(ctx); - gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env); - break; - case NM_DPSQ_SA_L_W: - check_dsp(ctx); - gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_POOL32AXF_2_16_23: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAU_H_QBL: - check_dsp(ctx); - gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env); - break; - case NM_DPAQX_S_W_PH: - check_dsp_r2(ctx); - gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env); - break; - case NM_DPSU_H_QBL: - check_dsp(ctx); - gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env); - break; - case NM_DPSQX_S_W_PH: - check_dsp_r2(ctx); - gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env); - break; - case NM_MULSA_W_PH: - check_dsp_r2(ctx); - gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_POOL32AXF_2_24_31: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAU_H_QBR: - check_dsp(ctx); - gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env); - break; - case NM_DPAQX_SA_W_PH: - check_dsp_r2(ctx); - gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env); - break; - case NM_DPSU_H_QBR: - check_dsp(ctx); - gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env); - break; - case NM_DPSQX_SA_W_PH: - check_dsp_r2(ctx); - gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env); - break; - case NM_MULSAQ_S_W_PH: - check_dsp(ctx); - gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - - tcg_temp_free_i32(t0); -} - -static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc, - int rt, int rs, int rd) -{ - int ret =3D rt; - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - TCGv v0_t =3D tcg_temp_new(); - TCGv v1_t =3D tcg_temp_new(); - - gen_load_gpr(v0_t, rt); - gen_load_gpr(v1_t, rs); - - switch (opc) { - case NM_POOL32AXF_2_0_7: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPA_W_PH: - case NM_DPAQ_S_W_PH: - case NM_DPS_W_PH: - case NM_DPSQ_S_W_PH: - gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); - break; - case NM_BALIGN: - check_dsp_r2(ctx); - if (rt !=3D 0) { - gen_load_gpr(t0, rs); - rd &=3D 3; - if (rd !=3D 0 && rd !=3D 2) { - tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd); - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_shri_tl(t0, t0, 8 * (4 - rd)); - tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); - } - tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); - } - break; - case NM_MADD: - check_dsp(ctx); - { - int acc =3D extract32(ctx->opcode, 14, 2); - TCGv_i64 t2 =3D tcg_temp_new_i64(); - TCGv_i64 t3 =3D tcg_temp_new_i64(); - - gen_load_gpr(t0, rt); - gen_load_gpr(t1, rs); - tcg_gen_ext_tl_i64(t2, t0); - tcg_gen_ext_tl_i64(t3, t1); - tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); - tcg_gen_add_i64(t2, t2, t3); - tcg_temp_free_i64(t3); - gen_move_low32(cpu_LO[acc], t2); - gen_move_high32(cpu_HI[acc], t2); - tcg_temp_free_i64(t2); - } - break; - case NM_MULT: - check_dsp(ctx); - { - int acc =3D extract32(ctx->opcode, 14, 2); - TCGv_i32 t2 =3D tcg_temp_new_i32(); - TCGv_i32 t3 =3D tcg_temp_new_i32(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_trunc_tl_i32(t2, t0); - tcg_gen_trunc_tl_i32(t3, t1); - tcg_gen_muls2_i32(t2, t3, t2, t3); - tcg_gen_ext_i32_tl(cpu_LO[acc], t2); - tcg_gen_ext_i32_tl(cpu_HI[acc], t3); - tcg_temp_free_i32(t2); - tcg_temp_free_i32(t3); - } - break; - case NM_EXTRV_W: - check_dsp(ctx); - gen_load_gpr(v1_t, rs); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extr_w(t0, t0, v1_t, cpu_env); - gen_store_gpr(t0, ret); - break; - } - break; - case NM_POOL32AXF_2_8_15: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAX_W_PH: - case NM_DPAQ_SA_L_W: - case NM_DPSX_W_PH: - case NM_DPSQ_SA_L_W: - gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); - break; - case NM_MADDU: - check_dsp(ctx); - { - int acc =3D extract32(ctx->opcode, 14, 2); - TCGv_i64 t2 =3D tcg_temp_new_i64(); - TCGv_i64 t3 =3D tcg_temp_new_i64(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_extu_tl_i64(t2, t0); - tcg_gen_extu_tl_i64(t3, t1); - tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); - tcg_gen_add_i64(t2, t2, t3); - tcg_temp_free_i64(t3); - gen_move_low32(cpu_LO[acc], t2); - gen_move_high32(cpu_HI[acc], t2); - tcg_temp_free_i64(t2); - } - break; - case NM_MULTU: - check_dsp(ctx); - { - int acc =3D extract32(ctx->opcode, 14, 2); - TCGv_i32 t2 =3D tcg_temp_new_i32(); - TCGv_i32 t3 =3D tcg_temp_new_i32(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_trunc_tl_i32(t2, t0); - tcg_gen_trunc_tl_i32(t3, t1); - tcg_gen_mulu2_i32(t2, t3, t2, t3); - tcg_gen_ext_i32_tl(cpu_LO[acc], t2); - tcg_gen_ext_i32_tl(cpu_HI[acc], t3); - tcg_temp_free_i32(t2); - tcg_temp_free_i32(t3); - } - break; - case NM_EXTRV_R_W: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extr_r_w(t0, t0, v1_t, cpu_env); - gen_store_gpr(t0, ret); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_POOL32AXF_2_16_23: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAU_H_QBL: - case NM_DPAQX_S_W_PH: - case NM_DPSU_H_QBL: - case NM_DPSQX_S_W_PH: - case NM_MULSA_W_PH: - gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); - break; - case NM_EXTPV: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extp(t0, t0, v1_t, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_MSUB: - check_dsp(ctx); - { - int acc =3D extract32(ctx->opcode, 14, 2); - TCGv_i64 t2 =3D tcg_temp_new_i64(); - TCGv_i64 t3 =3D tcg_temp_new_i64(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_ext_tl_i64(t2, t0); - tcg_gen_ext_tl_i64(t3, t1); - tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); - tcg_gen_sub_i64(t2, t3, t2); - tcg_temp_free_i64(t3); - gen_move_low32(cpu_LO[acc], t2); - gen_move_high32(cpu_HI[acc], t2); - tcg_temp_free_i64(t2); - } - break; - case NM_EXTRV_RS_W: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env); - gen_store_gpr(t0, ret); - break; - } - break; - case NM_POOL32AXF_2_24_31: - switch (extract32(ctx->opcode, 9, 3)) { - case NM_DPAU_H_QBR: - case NM_DPAQX_SA_W_PH: - case NM_DPSU_H_QBR: - case NM_DPSQX_SA_W_PH: - case NM_MULSAQ_S_W_PH: - gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); - break; - case NM_EXTPDPV: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extpdp(t0, t0, v1_t, cpu_env); - gen_store_gpr(t0, ret); - break; - case NM_MSUBU: - check_dsp(ctx); - { - int acc =3D extract32(ctx->opcode, 14, 2); - TCGv_i64 t2 =3D tcg_temp_new_i64(); - TCGv_i64 t3 =3D tcg_temp_new_i64(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_ext32u_tl(t0, t0); - tcg_gen_ext32u_tl(t1, t1); - tcg_gen_extu_tl_i64(t2, t0); - tcg_gen_extu_tl_i64(t3, t1); - tcg_gen_mul_i64(t2, t2, t3); - tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); - tcg_gen_sub_i64(t2, t3, t2); - tcg_temp_free_i64(t3); - gen_move_low32(cpu_LO[acc], t2); - gen_move_high32(cpu_HI[acc], t2); - tcg_temp_free_i64(t2); - } - break; - case NM_EXTRV_S_H: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extr_s_h(t0, t0, v0_t, cpu_env); - gen_store_gpr(t0, ret); - break; - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - - tcg_temp_free(t0); - tcg_temp_free(t1); - - tcg_temp_free(v0_t); - tcg_temp_free(v1_t); -} - -static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc, - int rt, int rs) -{ - int ret =3D rt; - TCGv t0 =3D tcg_temp_new(); - TCGv v0_t =3D tcg_temp_new(); - - gen_load_gpr(v0_t, rs); - - switch (opc) { - case NM_ABSQ_S_QB: - check_dsp_r2(ctx); - gen_helper_absq_s_qb(v0_t, v0_t, cpu_env); - gen_store_gpr(v0_t, ret); - break; - case NM_ABSQ_S_PH: - check_dsp(ctx); - gen_helper_absq_s_ph(v0_t, v0_t, cpu_env); - gen_store_gpr(v0_t, ret); - break; - case NM_ABSQ_S_W: - check_dsp(ctx); - gen_helper_absq_s_w(v0_t, v0_t, cpu_env); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQ_W_PHL: - check_dsp(ctx); - tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000); - tcg_gen_ext32s_tl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQ_W_PHR: - check_dsp(ctx); - tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF); - tcg_gen_shli_tl(v0_t, v0_t, 16); - tcg_gen_ext32s_tl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQU_PH_QBL: - check_dsp(ctx); - gen_helper_precequ_ph_qbl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQU_PH_QBR: - check_dsp(ctx); - gen_helper_precequ_ph_qbr(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQU_PH_QBLA: - check_dsp(ctx); - gen_helper_precequ_ph_qbla(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEQU_PH_QBRA: - check_dsp(ctx); - gen_helper_precequ_ph_qbra(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEU_PH_QBL: - check_dsp(ctx); - gen_helper_preceu_ph_qbl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEU_PH_QBR: - check_dsp(ctx); - gen_helper_preceu_ph_qbr(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEU_PH_QBLA: - check_dsp(ctx); - gen_helper_preceu_ph_qbla(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_PRECEU_PH_QBRA: - check_dsp(ctx); - gen_helper_preceu_ph_qbra(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_REPLV_PH: - check_dsp(ctx); - tcg_gen_ext16u_tl(v0_t, v0_t); - tcg_gen_shli_tl(t0, v0_t, 16); - tcg_gen_or_tl(v0_t, v0_t, t0); - tcg_gen_ext32s_tl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_REPLV_QB: - check_dsp(ctx); - tcg_gen_ext8u_tl(v0_t, v0_t); - tcg_gen_shli_tl(t0, v0_t, 8); - tcg_gen_or_tl(v0_t, v0_t, t0); - tcg_gen_shli_tl(t0, v0_t, 16); - tcg_gen_or_tl(v0_t, v0_t, t0); - tcg_gen_ext32s_tl(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_BITREV: - check_dsp(ctx); - gen_helper_bitrev(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_INSV: - check_dsp(ctx); - { - TCGv tv0 =3D tcg_temp_new(); - - gen_load_gpr(tv0, rt); - gen_helper_insv(v0_t, cpu_env, v0_t, tv0); - gen_store_gpr(v0_t, ret); - tcg_temp_free(tv0); - } - break; - case NM_RADDU_W_QB: - check_dsp(ctx); - gen_helper_raddu_w_qb(v0_t, v0_t); - gen_store_gpr(v0_t, ret); - break; - case NM_BITSWAP: - gen_bitswap(ctx, OPC_BITSWAP, ret, rs); - break; - case NM_CLO: - check_nms(ctx); - gen_cl(ctx, OPC_CLO, ret, rs); - break; - case NM_CLZ: - check_nms(ctx); - gen_cl(ctx, OPC_CLZ, ret, rs); - break; - case NM_WSBH: - gen_bshfl(ctx, OPC_WSBH, ret, rs); - break; - default: - gen_reserved_instruction(ctx); - break; - } - - tcg_temp_free(v0_t); - tcg_temp_free(t0); -} - -static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc, - int rt, int rs, int rd) -{ - TCGv t0 =3D tcg_temp_new(); - TCGv rs_t =3D tcg_temp_new(); - - gen_load_gpr(rs_t, rs); - - switch (opc) { - case NM_SHRA_R_QB: - check_dsp_r2(ctx); - tcg_gen_movi_tl(t0, rd >> 2); - switch (extract32(ctx->opcode, 12, 1)) { - case 0: - /* NM_SHRA_QB */ - gen_helper_shra_qb(t0, t0, rs_t); - gen_store_gpr(t0, rt); - break; - case 1: - /* NM_SHRA_R_QB */ - gen_helper_shra_r_qb(t0, t0, rs_t); - gen_store_gpr(t0, rt); - break; - } - break; - case NM_SHRL_PH: - check_dsp_r2(ctx); - tcg_gen_movi_tl(t0, rd >> 1); - gen_helper_shrl_ph(t0, t0, rs_t); - gen_store_gpr(t0, rt); - break; - case NM_REPL_QB: - check_dsp(ctx); - { - int16_t imm; - target_long result; - imm =3D extract32(ctx->opcode, 13, 8); - result =3D (uint32_t)imm << 24 | - (uint32_t)imm << 16 | - (uint32_t)imm << 8 | - (uint32_t)imm; - result =3D (int32_t)result; - tcg_gen_movi_tl(t0, result); - gen_store_gpr(t0, rt); - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - tcg_temp_free(t0); - tcg_temp_free(rs_t); -} - - -static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *c= tx) -{ - int rt =3D extract32(ctx->opcode, 21, 5); - int rs =3D extract32(ctx->opcode, 16, 5); - int rd =3D extract32(ctx->opcode, 11, 5); - - switch (extract32(ctx->opcode, 6, 3)) { - case NM_POOL32AXF_1: - { - int32_t op1 =3D extract32(ctx->opcode, 9, 3); - gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd); - } - break; - case NM_POOL32AXF_2: - { - int32_t op1 =3D extract32(ctx->opcode, 12, 2); - gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd); - } - break; - case NM_POOL32AXF_4: - { - int32_t op1 =3D extract32(ctx->opcode, 9, 7); - gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs); - } - break; - case NM_POOL32AXF_5: - switch (extract32(ctx->opcode, 9, 7)) { -#ifndef CONFIG_USER_ONLY - case NM_TLBP: - gen_cp0(env, ctx, OPC_TLBP, 0, 0); - break; - case NM_TLBR: - gen_cp0(env, ctx, OPC_TLBR, 0, 0); - break; - case NM_TLBWI: - gen_cp0(env, ctx, OPC_TLBWI, 0, 0); - break; - case NM_TLBWR: - gen_cp0(env, ctx, OPC_TLBWR, 0, 0); - break; - case NM_TLBINV: - gen_cp0(env, ctx, OPC_TLBINV, 0, 0); - break; - case NM_TLBINVF: - gen_cp0(env, ctx, OPC_TLBINVF, 0, 0); - break; - case NM_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, rt); - /* Stop translation as we may have switched the execution mode= */ - ctx->base.is_jmp =3D DISAS_STOP; - tcg_temp_free(t0); - } - break; - case NM_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, rt); - /* Stop translation as we may have switched the execution mode= */ - ctx->base.is_jmp =3D DISAS_STOP; - tcg_temp_free(t0); - } - break; - case NM_RDPGPR: - check_cp0_enabled(ctx); - gen_load_srsgpr(rs, rt); - break; - case NM_WRPGPR: - check_cp0_enabled(ctx); - gen_store_srsgpr(rs, rt); - break; - case NM_WAIT: - gen_cp0(env, ctx, OPC_WAIT, 0, 0); - break; - case NM_DERET: - gen_cp0(env, ctx, OPC_DERET, 0, 0); - break; - case NM_ERETX: - gen_cp0(env, ctx, OPC_ERET, 0, 0); - break; -#endif - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_POOL32AXF_7: - { - int32_t op1 =3D extract32(ctx->opcode, 9, 3); - gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd); - } - break; - default: - gen_reserved_instruction(ctx); - break; - } -} - -/* Immediate Value Compact Branches */ -static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, - int rt, int32_t imm, int32_t offset) -{ - TCGCond cond =3D TCG_COND_ALWAYS; - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - - gen_load_gpr(t0, rt); - tcg_gen_movi_tl(t1, imm); - ctx->btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); - - /* Load needed operands and calculate btarget */ - switch (opc) { - case NM_BEQIC: - if (rt =3D=3D 0 && imm =3D=3D 0) { - /* Unconditional branch */ - } else if (rt =3D=3D 0 && imm !=3D 0) { - /* Treat as NOP */ - goto out; - } else { - cond =3D TCG_COND_EQ; - } - break; - case NM_BBEQZC: - case NM_BBNEZC: - check_nms(ctx); - if (imm >=3D 32 && !(ctx->hflags & MIPS_HFLAG_64)) { - gen_reserved_instruction(ctx); - goto out; - } else if (rt =3D=3D 0 && opc =3D=3D NM_BBEQZC) { - /* Unconditional branch */ - } else if (rt =3D=3D 0 && opc =3D=3D NM_BBNEZC) { - /* Treat as NOP */ - goto out; - } else { - tcg_gen_shri_tl(t0, t0, imm); - tcg_gen_andi_tl(t0, t0, 1); - tcg_gen_movi_tl(t1, 0); - if (opc =3D=3D NM_BBEQZC) { - cond =3D TCG_COND_EQ; - } else { - cond =3D TCG_COND_NE; - } - } - break; - case NM_BNEIC: - if (rt =3D=3D 0 && imm =3D=3D 0) { - /* Treat as NOP */ - goto out; - } else if (rt =3D=3D 0 && imm !=3D 0) { - /* Unconditional branch */ - } else { - cond =3D TCG_COND_NE; - } - break; - case NM_BGEIC: - if (rt =3D=3D 0 && imm =3D=3D 0) { - /* Unconditional branch */ - } else { - cond =3D TCG_COND_GE; - } - break; - case NM_BLTIC: - cond =3D TCG_COND_LT; - break; - case NM_BGEIUC: - if (rt =3D=3D 0 && imm =3D=3D 0) { - /* Unconditional branch */ - } else { - cond =3D TCG_COND_GEU; - } - break; - case NM_BLTIUC: - cond =3D TCG_COND_LTU; - break; - default: - MIPS_INVAL("Immediate Value Compact branch"); - gen_reserved_instruction(ctx); - goto out; - } - - /* branch completion */ - clear_branch_hflags(ctx); - ctx->base.is_jmp =3D DISAS_NORETURN; - - if (cond =3D=3D TCG_COND_ALWAYS) { - /* Unconditional compact branch */ - gen_goto_tb(ctx, 0, ctx->btarget); - } else { - /* Conditional compact branch */ - TCGLabel *fs =3D gen_new_label(); - - tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs); - - gen_goto_tb(ctx, 1, ctx->btarget); - gen_set_label(fs); - - gen_goto_tb(ctx, 0, ctx->base.pc_next + 4); - } - -out: - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */ -static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs, - int rt) -{ - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - - /* load rs */ - gen_load_gpr(t0, rs); - - /* link */ - if (rt !=3D 0) { - tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4); - } - - /* calculate btarget */ - tcg_gen_shli_tl(t0, t0, 1); - tcg_gen_movi_tl(t1, ctx->base.pc_next + 4); - gen_op_addr_add(ctx, btarget, t1, t0); - - /* branch completion */ - clear_branch_hflags(ctx); - ctx->base.is_jmp =3D DISAS_NORETURN; - - /* unconditional branch to register */ - tcg_gen_mov_tl(cpu_PC, btarget); - tcg_gen_lookup_and_goto_ptr(); - - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -/* nanoMIPS Branches */ -static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc, - int rs, int rt, int32_t offset) -{ - int bcond_compute =3D 0; - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - - /* Load needed operands and calculate btarget */ - switch (opc) { - /* compact branch */ - case OPC_BGEC: - case OPC_BLTC: - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - bcond_compute =3D 1; - ctx->btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); - break; - case OPC_BGEUC: - case OPC_BLTUC: - if (rs =3D=3D 0 || rs =3D=3D rt) { - /* OPC_BLEZALC, OPC_BGEZALC */ - /* OPC_BGTZALC, OPC_BLTZALC */ - tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4); - } - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - bcond_compute =3D 1; - ctx->btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); - break; - case OPC_BC: - ctx->btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); - break; - case OPC_BEQZC: - if (rs !=3D 0) { - /* OPC_BEQZC, OPC_BNEZC */ - gen_load_gpr(t0, rs); - bcond_compute =3D 1; - ctx->btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); - } else { - /* OPC_JIC, OPC_JIALC */ - TCGv tbase =3D tcg_temp_new(); - TCGv toffset =3D tcg_temp_new(); - - gen_load_gpr(tbase, rt); - tcg_gen_movi_tl(toffset, offset); - gen_op_addr_add(ctx, btarget, tbase, toffset); - tcg_temp_free(tbase); - tcg_temp_free(toffset); - } - break; - default: - MIPS_INVAL("Compact branch/jump"); - gen_reserved_instruction(ctx); - goto out; - } - - if (bcond_compute =3D=3D 0) { - /* Unconditional compact branch */ - switch (opc) { - case OPC_BC: - gen_goto_tb(ctx, 0, ctx->btarget); - break; - default: - MIPS_INVAL("Compact branch/jump"); - gen_reserved_instruction(ctx); - goto out; - } - } else { - /* Conditional compact branch */ - TCGLabel *fs =3D gen_new_label(); - - switch (opc) { - case OPC_BGEUC: - if (rs =3D=3D 0 && rt !=3D 0) { - /* OPC_BLEZALC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs= ); - } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { - /* OPC_BGEZALC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs= ); - } else { - /* OPC_BGEUC */ - tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, f= s); - } - break; - case OPC_BLTUC: - if (rs =3D=3D 0 && rt !=3D 0) { - /* OPC_BGTZALC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs= ); - } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { - /* OPC_BLTZALC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs= ); - } else { - /* OPC_BLTUC */ - tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, f= s); - } - break; - case OPC_BGEC: - if (rs =3D=3D 0 && rt !=3D 0) { - /* OPC_BLEZC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs= ); - } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { - /* OPC_BGEZC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs= ); - } else { - /* OPC_BGEC */ - tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs= ); - } - break; - case OPC_BLTC: - if (rs =3D=3D 0 && rt !=3D 0) { - /* OPC_BGTZC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs= ); - } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { - /* OPC_BLTZC */ - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs= ); - } else { - /* OPC_BLTC */ - tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs= ); - } - break; - case OPC_BEQZC: - tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs); - break; - default: - MIPS_INVAL("Compact conditional branch/jump"); - gen_reserved_instruction(ctx); - goto out; - } - - /* branch completion */ - clear_branch_hflags(ctx); - ctx->base.is_jmp =3D DISAS_NORETURN; - - /* Generating branch here as compact branches don't have delay slo= t */ - gen_goto_tb(ctx, 1, ctx->btarget); - gen_set_label(fs); - - gen_goto_tb(ctx, 0, ctx->base.pc_next + 4); - } - -out: - tcg_temp_free(t0); - tcg_temp_free(t1); -} - - -/* nanoMIPS CP1 Branches */ -static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op, - int32_t ft, int32_t offset) -{ - target_ulong btarget; - TCGv_i64 t0 =3D tcg_temp_new_i64(); - - gen_load_fpr64(ctx, t0, ft); - tcg_gen_andi_i64(t0, t0, 1); - - btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); - - switch (op) { - case NM_BC1EQZC: - tcg_gen_xori_i64(t0, t0, 1); - ctx->hflags |=3D MIPS_HFLAG_BC; - break; - case NM_BC1NEZC: - /* t0 already set */ - ctx->hflags |=3D MIPS_HFLAG_BC; - break; - default: - MIPS_INVAL("cp1 cond branch"); - gen_reserved_instruction(ctx); - goto out; - } - - tcg_gen_trunc_i64_tl(bcond, t0); - - ctx->btarget =3D btarget; - -out: - tcg_temp_free_i64(t0); -} - - -static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt) -{ - TCGv t0, t1; - t0 =3D tcg_temp_new(); - t1 =3D tcg_temp_new(); - - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - - if ((extract32(ctx->opcode, 6, 1)) =3D=3D 1) { - /* PP.LSXS instructions require shifting */ - switch (extract32(ctx->opcode, 7, 4)) { - case NM_SHXS: - check_nms(ctx); - /* fall through */ - case NM_LHXS: - case NM_LHUXS: - tcg_gen_shli_tl(t0, t0, 1); - break; - case NM_SWXS: - check_nms(ctx); - /* fall through */ - case NM_LWXS: - case NM_LWC1XS: - case NM_SWC1XS: - tcg_gen_shli_tl(t0, t0, 2); - break; - case NM_LDC1XS: - case NM_SDC1XS: - tcg_gen_shli_tl(t0, t0, 3); - break; - } - } - gen_op_addr_add(ctx, t0, t0, t1); - - switch (extract32(ctx->opcode, 7, 4)) { - case NM_LBX: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, - MO_SB); - gen_store_gpr(t0, rd); - break; - case NM_LHX: - /*case NM_LHXS:*/ - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, - MO_TESW); - gen_store_gpr(t0, rd); - break; - case NM_LWX: - /*case NM_LWXS:*/ - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, - MO_TESL); - gen_store_gpr(t0, rd); - break; - case NM_LBUX: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, - MO_UB); - gen_store_gpr(t0, rd); - break; - case NM_LHUX: - /*case NM_LHUXS:*/ - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, - MO_TEUW); - gen_store_gpr(t0, rd); - break; - case NM_SBX: - check_nms(ctx); - gen_load_gpr(t1, rd); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, - MO_8); - break; - case NM_SHX: - /*case NM_SHXS:*/ - check_nms(ctx); - gen_load_gpr(t1, rd); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, - MO_TEUW); - break; - case NM_SWX: - /*case NM_SWXS:*/ - check_nms(ctx); - gen_load_gpr(t1, rd); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, - MO_TEUL); - break; - case NM_LWC1X: - /*case NM_LWC1XS:*/ - case NM_LDC1X: - /*case NM_LDC1XS:*/ - case NM_SWC1X: - /*case NM_SWC1XS:*/ - case NM_SDC1X: - /*case NM_SDC1XS:*/ - if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { - check_cp1_enabled(ctx); - switch (extract32(ctx->opcode, 7, 4)) { - case NM_LWC1X: - /*case NM_LWC1XS:*/ - gen_flt_ldst(ctx, OPC_LWC1, rd, t0); - break; - case NM_LDC1X: - /*case NM_LDC1XS:*/ - gen_flt_ldst(ctx, OPC_LDC1, rd, t0); - break; - case NM_SWC1X: - /*case NM_SWC1XS:*/ - gen_flt_ldst(ctx, OPC_SWC1, rd, t0); - break; - case NM_SDC1X: - /*case NM_SDC1XS:*/ - gen_flt_ldst(ctx, OPC_SDC1, rd, t0); - break; - } - } else { - generate_exception_err(ctx, EXCP_CpU, 1); - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - - tcg_temp_free(t0); - tcg_temp_free(t1); -} - -static void gen_pool32f_nanomips_insn(DisasContext *ctx) -{ - int rt, rs, rd; - - rt =3D extract32(ctx->opcode, 21, 5); - rs =3D extract32(ctx->opcode, 16, 5); - rd =3D extract32(ctx->opcode, 11, 5); - - if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) { - gen_reserved_instruction(ctx); - return; - } - check_cp1_enabled(ctx); - switch (extract32(ctx->opcode, 0, 3)) { - case NM_POOL32F_0: - switch (extract32(ctx->opcode, 3, 7)) { - case NM_RINT_S: - gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0); - break; - case NM_RINT_D: - gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0); - break; - case NM_CLASS_S: - gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0); - break; - case NM_CLASS_D: - gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0); - break; - case NM_ADD_S: - gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0); - break; - case NM_ADD_D: - gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0); - break; - case NM_SUB_S: - gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0); - break; - case NM_SUB_D: - gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0); - break; - case NM_MUL_S: - gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0); - break; - case NM_MUL_D: - gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0); - break; - case NM_DIV_S: - gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0); - break; - case NM_DIV_D: - gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0); - break; - case NM_SELEQZ_S: - gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs); - break; - case NM_SELEQZ_D: - gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs); - break; - case NM_SELNEZ_S: - gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs); - break; - case NM_SELNEZ_D: - gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs); - break; - case NM_SEL_S: - gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs); - break; - case NM_SEL_D: - gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs); - break; - case NM_MADDF_S: - gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0); - break; - case NM_MADDF_D: - gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0); - break; - case NM_MSUBF_S: - gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0); - break; - case NM_MSUBF_D: - gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_POOL32F_3: - switch (extract32(ctx->opcode, 3, 3)) { - case NM_MIN_FMT: - switch (extract32(ctx->opcode, 9, 1)) { - 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; - } - break; - case NM_MAX_FMT: - switch (extract32(ctx->opcode, 9, 1)) { - 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; - } - break; - case NM_MINA_FMT: - switch (extract32(ctx->opcode, 9, 1)) { - 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; - } - break; - case NM_MAXA_FMT: - switch (extract32(ctx->opcode, 9, 1)) { - 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; - } - break; - case NM_POOL32FXF: - switch (extract32(ctx->opcode, 6, 8)) { - case NM_CFC1: - gen_cp1(ctx, OPC_CFC1, rt, rs); - break; - case NM_CTC1: - gen_cp1(ctx, OPC_CTC1, rt, rs); - break; - case NM_MFC1: - gen_cp1(ctx, OPC_MFC1, rt, rs); - break; - case NM_MTC1: - gen_cp1(ctx, OPC_MTC1, rt, rs); - break; - case NM_MFHC1: - gen_cp1(ctx, OPC_MFHC1, rt, rs); - break; - case NM_MTHC1: - gen_cp1(ctx, OPC_MTHC1, rt, rs); - break; - case NM_CVT_S_PL: - gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0); - break; - case NM_CVT_S_PU: - gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0); - break; - default: - switch (extract32(ctx->opcode, 6, 9)) { - case NM_CVT_L_S: - gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0); - break; - case NM_CVT_L_D: - gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0); - break; - case NM_CVT_W_S: - gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0); - break; - case NM_CVT_W_D: - gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0); - break; - case NM_RSQRT_S: - gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0); - break; - case NM_RSQRT_D: - gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0); - break; - case NM_SQRT_S: - gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0); - break; - case NM_SQRT_D: - gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0); - break; - case NM_RECIP_S: - gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0); - break; - case NM_RECIP_D: - gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0); - break; - case NM_FLOOR_L_S: - gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0); - break; - case NM_FLOOR_L_D: - gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0); - break; - case NM_FLOOR_W_S: - gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0); - break; - case NM_FLOOR_W_D: - gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0); - break; - case NM_CEIL_L_S: - gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0); - break; - case NM_CEIL_L_D: - gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0); - break; - case NM_CEIL_W_S: - gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0); - break; - case NM_CEIL_W_D: - gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0); - break; - case NM_TRUNC_L_S: - gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0); - break; - case NM_TRUNC_L_D: - gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0); - break; - case NM_TRUNC_W_S: - gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0); - break; - case NM_TRUNC_W_D: - gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0); - break; - case NM_ROUND_L_S: - gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0); - break; - case NM_ROUND_L_D: - gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0); - break; - case NM_ROUND_W_S: - gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0); - break; - case NM_ROUND_W_D: - gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0); - break; - case NM_MOV_S: - gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0); - break; - case NM_MOV_D: - gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0); - break; - case NM_ABS_S: - gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0); - break; - case NM_ABS_D: - gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0); - break; - case NM_NEG_S: - gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0); - break; - case NM_NEG_D: - gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0); - break; - case NM_CVT_D_S: - gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0); - break; - case NM_CVT_D_W: - gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0); - break; - case NM_CVT_D_L: - gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0); - break; - case NM_CVT_S_D: - gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0); - break; - case NM_CVT_S_W: - gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0); - break; - case NM_CVT_S_L: - gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - } - break; - } - break; - case NM_POOL32F_5: - switch (extract32(ctx->opcode, 3, 3)) { - case NM_CMP_CONDN_S: - gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd); - break; - case NM_CMP_CONDN_D: - gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - default: - gen_reserved_instruction(ctx); - break; - } -} - -static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc, - int rd, int rs, int rt) -{ - int ret =3D rd; - TCGv t0 =3D tcg_temp_new(); - TCGv v1_t =3D tcg_temp_new(); - TCGv v2_t =3D tcg_temp_new(); - - gen_load_gpr(v1_t, rs); - gen_load_gpr(v2_t, rt); - - switch (opc) { - case NM_CMP_EQ_PH: - check_dsp(ctx); - gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env); - break; - case NM_CMP_LT_PH: - check_dsp(ctx); - gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env); - break; - case NM_CMP_LE_PH: - check_dsp(ctx); - gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env); - break; - case NM_CMPU_EQ_QB: - check_dsp(ctx); - gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env); - break; - case NM_CMPU_LT_QB: - check_dsp(ctx); - gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env); - break; - case NM_CMPU_LE_QB: - check_dsp(ctx); - gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env); - break; - case NM_CMPGU_EQ_QB: - check_dsp(ctx); - gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_CMPGU_LT_QB: - check_dsp(ctx); - gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_CMPGU_LE_QB: - check_dsp(ctx); - gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_CMPGDU_EQ_QB: - check_dsp_r2(ctx); - gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t); - tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); - gen_store_gpr(v1_t, ret); - break; - case NM_CMPGDU_LT_QB: - check_dsp_r2(ctx); - gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t); - tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); - gen_store_gpr(v1_t, ret); - break; - case NM_CMPGDU_LE_QB: - check_dsp_r2(ctx); - gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t); - tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); - gen_store_gpr(v1_t, ret); - break; - case NM_PACKRL_PH: - check_dsp(ctx); - gen_helper_packrl_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_PICK_QB: - check_dsp(ctx); - gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_PICK_PH: - check_dsp(ctx); - gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_ADDQ_S_W: - check_dsp(ctx); - gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_SUBQ_S_W: - check_dsp(ctx); - gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_ADDSC: - check_dsp(ctx); - gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_ADDWC: - check_dsp(ctx); - gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_ADDQ_S_PH: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDQ_PH */ - gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDQ_S_PH */ - gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_ADDQH_R_PH: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDQH_PH */ - gen_helper_addqh_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDQH_R_PH */ - gen_helper_addqh_r_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_ADDQH_R_W: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDQH_W */ - gen_helper_addqh_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDQH_R_W */ - gen_helper_addqh_r_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_ADDU_S_QB: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDU_QB */ - gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDU_S_QB */ - gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_ADDU_S_PH: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDU_PH */ - gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDU_S_PH */ - gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_ADDUH_R_QB: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* ADDUH_QB */ - gen_helper_adduh_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* ADDUH_R_QB */ - gen_helper_adduh_r_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SHRAV_R_PH: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SHRAV_PH */ - gen_helper_shra_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SHRAV_R_PH */ - gen_helper_shra_r_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SHRAV_R_QB: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SHRAV_QB */ - gen_helper_shra_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SHRAV_R_QB */ - gen_helper_shra_r_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBQ_S_PH: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBQ_PH */ - gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBQ_S_PH */ - gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBQH_R_PH: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBQH_PH */ - gen_helper_subqh_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBQH_R_PH */ - gen_helper_subqh_r_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBQH_R_W: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBQH_W */ - gen_helper_subqh_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBQH_R_W */ - gen_helper_subqh_r_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBU_S_QB: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBU_QB */ - gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBU_S_QB */ - gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBU_S_PH: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBU_PH */ - gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBU_S_PH */ - gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SUBUH_R_QB: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SUBUH_QB */ - gen_helper_subuh_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SUBUH_R_QB */ - gen_helper_subuh_r_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_SHLLV_S_PH: - check_dsp(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SHLLV_PH */ - gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* SHLLV_S_PH */ - gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_PRECR_SRA_R_PH_W: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* PRECR_SRA_PH_W */ - { - TCGv_i32 sa_t =3D tcg_const_i32(rd); - gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t, - cpu_gpr[rt]); - gen_store_gpr(v1_t, rt); - tcg_temp_free_i32(sa_t); - } - break; - case 1: - /* PRECR_SRA_R_PH_W */ - { - TCGv_i32 sa_t =3D tcg_const_i32(rd); - gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t, - cpu_gpr[rt]); - gen_store_gpr(v1_t, rt); - tcg_temp_free_i32(sa_t); - } - break; - } - break; - case NM_MULEU_S_PH_QBL: - check_dsp(ctx); - gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULEU_S_PH_QBR: - check_dsp(ctx); - gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULQ_RS_PH: - check_dsp(ctx); - gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULQ_S_PH: - check_dsp_r2(ctx); - gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULQ_RS_W: - check_dsp_r2(ctx); - gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULQ_S_W: - check_dsp_r2(ctx); - gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_APPEND: - check_dsp_r2(ctx); - gen_load_gpr(t0, rs); - if (rd !=3D 0) { - tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd); - } - tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); - break; - case NM_MODSUB: - check_dsp(ctx); - gen_helper_modsub(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_SHRAV_R_W: - check_dsp(ctx); - gen_helper_shra_r_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_SHRLV_PH: - check_dsp_r2(ctx); - gen_helper_shrl_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_SHRLV_QB: - check_dsp(ctx); - gen_helper_shrl_qb(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_SHLLV_QB: - check_dsp(ctx); - gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_SHLLV_S_W: - check_dsp(ctx); - gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_SHILO: - check_dsp(ctx); - { - TCGv tv0 =3D tcg_temp_new(); - TCGv tv1 =3D tcg_temp_new(); - int16_t imm =3D extract32(ctx->opcode, 16, 7); - - tcg_gen_movi_tl(tv0, rd >> 3); - tcg_gen_movi_tl(tv1, imm); - gen_helper_shilo(tv0, tv1, cpu_env); - tcg_temp_free(tv1); - tcg_temp_free(tv0); - } - break; - case NM_MULEQ_S_W_PHL: - check_dsp(ctx); - gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MULEQ_S_W_PHR: - check_dsp(ctx); - gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_MUL_S_PH: - check_dsp_r2(ctx); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* MUL_PH */ - gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case 1: - /* MUL_S_PH */ - gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - } - break; - case NM_PRECR_QB_PH: - check_dsp_r2(ctx); - gen_helper_precr_qb_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_PRECRQ_QB_PH: - check_dsp(ctx); - gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_PRECRQ_PH_W: - check_dsp(ctx); - gen_helper_precrq_ph_w(v1_t, v1_t, v2_t); - gen_store_gpr(v1_t, ret); - break; - case NM_PRECRQ_RS_PH_W: - check_dsp(ctx); - gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_PRECRQU_S_QB_PH: - check_dsp(ctx); - gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env); - gen_store_gpr(v1_t, ret); - break; - case NM_SHRA_R_W: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd); - gen_helper_shra_r_w(v1_t, t0, v1_t); - gen_store_gpr(v1_t, rt); - break; - case NM_SHRA_R_PH: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 1); - switch (extract32(ctx->opcode, 10, 1)) { - case 0: - /* SHRA_PH */ - gen_helper_shra_ph(v1_t, t0, v1_t); - gen_store_gpr(v1_t, rt); - break; - case 1: - /* SHRA_R_PH */ - gen_helper_shra_r_ph(v1_t, t0, v1_t); - gen_store_gpr(v1_t, rt); - break; - } - break; - case NM_SHLL_S_PH: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd >> 1); - switch (extract32(ctx->opcode, 10, 2)) { - case 0: - /* SHLL_PH */ - gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env); - gen_store_gpr(v1_t, rt); - break; - case 2: - /* SHLL_S_PH */ - gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env); - gen_store_gpr(v1_t, rt); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_SHLL_S_W: - check_dsp(ctx); - tcg_gen_movi_tl(t0, rd); - gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env); - gen_store_gpr(v1_t, rt); - break; - case NM_REPL_PH: - check_dsp(ctx); - { - int16_t imm; - imm =3D sextract32(ctx->opcode, 11, 11); - imm =3D (int16_t)(imm << 6) >> 6; - if (rt !=3D 0) { - tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm)); - } - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - - tcg_temp_free(v2_t); - tcg_temp_free(v1_t); - tcg_temp_free(t0); -} - -static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) -{ - uint16_t insn; - uint32_t op; - int rt, rs, rd; - int offset; - int imm; - - insn =3D translator_lduw(env, ctx->base.pc_next + 2); - ctx->opcode =3D (ctx->opcode << 16) | insn; - - rt =3D extract32(ctx->opcode, 21, 5); - rs =3D extract32(ctx->opcode, 16, 5); - rd =3D extract32(ctx->opcode, 11, 5); - - op =3D extract32(ctx->opcode, 26, 6); - switch (op) { - case NM_P_ADDIU: - if (rt =3D=3D 0) { - /* P.RI */ - switch (extract32(ctx->opcode, 19, 2)) { - case NM_SIGRIE: - default: - gen_reserved_instruction(ctx); - break; - case NM_P_SYSCALL: - if ((extract32(ctx->opcode, 18, 1)) =3D=3D NM_SYSCALL) { - generate_exception_end(ctx, EXCP_SYSCALL); - } else { - gen_reserved_instruction(ctx); - } - break; - case NM_BREAK: - generate_exception_end(ctx, EXCP_BREAK); - break; - case NM_SDBBP: - if (is_uhi(extract32(ctx->opcode, 0, 19))) { - gen_helper_do_semihosting(cpu_env); - } else { - if (ctx->hflags & MIPS_HFLAG_SBRI) { - gen_reserved_instruction(ctx); - } else { - generate_exception_end(ctx, EXCP_DBp); - } - } - break; - } - } else { - /* NM_ADDIU */ - imm =3D extract32(ctx->opcode, 0, 16); - if (rs !=3D 0) { - tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm); - } else { - tcg_gen_movi_tl(cpu_gpr[rt], imm); - } - tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); - } - break; - case NM_ADDIUPC: - if (rt !=3D 0) { - offset =3D sextract32(ctx->opcode, 0, 1) << 21 | - extract32(ctx->opcode, 1, 20) << 1; - target_long addr =3D addr_add(ctx, ctx->base.pc_next + 4, offs= et); - tcg_gen_movi_tl(cpu_gpr[rt], addr); - } - break; - case NM_POOL32A: - switch (ctx->opcode & 0x07) { - case NM_POOL32A0: - gen_pool32a0_nanomips_insn(env, ctx); - break; - case NM_POOL32A5: - { - int32_t op1 =3D extract32(ctx->opcode, 3, 7); - gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt); - } - break; - case NM_POOL32A7: - switch (extract32(ctx->opcode, 3, 3)) { - case NM_P_LSX: - gen_p_lsx(ctx, rd, rs, rt); - break; - case NM_LSA: - /* - * In nanoMIPS, the shift field directly encodes the shift - * amount, meaning that the supported shift values are in - * the range 0 to 3 (instead of 1 to 4 in MIPSR6). - */ - gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1); - break; - case NM_EXTW: - gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5)); - break; - case NM_POOL32AXF: - gen_pool32axf_nanomips_insn(env, ctx); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_P_GP_W: - switch (ctx->opcode & 0x03) { - case NM_ADDIUGP_W: - if (rt !=3D 0) { - offset =3D extract32(ctx->opcode, 0, 21); - gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset); - } - break; - case NM_LWGP: - gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2= ); - break; - case NM_SWGP: - gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2= ); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_P48I: - { - insn =3D translator_lduw(env, ctx->base.pc_next + 4); - target_long addr_off =3D extract32(ctx->opcode, 0, 16) | insn = << 16; - switch (extract32(ctx->opcode, 16, 5)) { - case NM_LI48: - check_nms(ctx); - if (rt !=3D 0) { - tcg_gen_movi_tl(cpu_gpr[rt], addr_off); - } - break; - case NM_ADDIU48: - check_nms(ctx); - if (rt !=3D 0) { - tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off); - tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); - } - break; - case NM_ADDIUGP48: - check_nms(ctx); - if (rt !=3D 0) { - gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_o= ff); - } - break; - case NM_ADDIUPC48: - check_nms(ctx); - if (rt !=3D 0) { - target_long addr =3D addr_add(ctx, ctx->base.pc_next += 6, - addr_off); - - tcg_gen_movi_tl(cpu_gpr[rt], addr); - } - break; - case NM_LWPC48: - check_nms(ctx); - if (rt !=3D 0) { - TCGv t0; - t0 =3D tcg_temp_new(); - - target_long addr =3D addr_add(ctx, ctx->base.pc_next += 6, - addr_off); - - tcg_gen_movi_tl(t0, addr); - tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_T= ESL); - tcg_temp_free(t0); - } - break; - case NM_SWPC48: - check_nms(ctx); - { - TCGv t0, t1; - t0 =3D tcg_temp_new(); - t1 =3D tcg_temp_new(); - - target_long addr =3D addr_add(ctx, ctx->base.pc_next += 6, - addr_off); - - tcg_gen_movi_tl(t0, addr); - gen_load_gpr(t1, rt); - - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); - - tcg_temp_free(t0); - tcg_temp_free(t1); - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - return 6; - } - case NM_P_U12: - switch (extract32(ctx->opcode, 12, 4)) { - case NM_ORI: - gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, = 12)); - break; - case NM_XORI: - gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0,= 12)); - break; - case NM_ANDI: - gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0,= 12)); - break; - case NM_P_SR: - switch (extract32(ctx->opcode, 20, 1)) { - case NM_PP_SR: - switch (ctx->opcode & 3) { - case NM_SAVE: - gen_save(ctx, rt, extract32(ctx->opcode, 16, 4), - extract32(ctx->opcode, 2, 1), - extract32(ctx->opcode, 3, 9) << 3); - break; - case NM_RESTORE: - case NM_RESTORE_JRC: - gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4), - extract32(ctx->opcode, 2, 1), - extract32(ctx->opcode, 3, 9) << 3); - if ((ctx->opcode & 3) =3D=3D NM_RESTORE_JRC) { - gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0); - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_P_SR_F: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_SLTI: - gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 1= 2)); - break; - case NM_SLTIU: - gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, = 12)); - break; - case NM_SEQI: - { - TCGv t0 =3D tcg_temp_new(); - - imm =3D extract32(ctx->opcode, 0, 12); - gen_load_gpr(t0, rs); - tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm); - gen_store_gpr(t0, rt); - - tcg_temp_free(t0); - } - break; - case NM_ADDIUNEG: - imm =3D (int16_t) extract32(ctx->opcode, 0, 12); - gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm); - break; - case NM_P_SHIFT: - { - int shift =3D extract32(ctx->opcode, 0, 5); - switch (extract32(ctx->opcode, 5, 4)) { - case NM_P_SLL: - if (rt =3D=3D 0 && shift =3D=3D 0) { - /* NOP */ - } else if (rt =3D=3D 0 && shift =3D=3D 3) { - /* EHB - treat as NOP */ - } else if (rt =3D=3D 0 && shift =3D=3D 5) { - /* PAUSE - treat as NOP */ - } else if (rt =3D=3D 0 && shift =3D=3D 6) { - /* SYNC */ - gen_sync(extract32(ctx->opcode, 16, 5)); - } else { - /* SLL */ - gen_shift_imm(ctx, OPC_SLL, rt, rs, - extract32(ctx->opcode, 0, 5)); - } - break; - case NM_SRL: - gen_shift_imm(ctx, OPC_SRL, rt, rs, - extract32(ctx->opcode, 0, 5)); - break; - case NM_SRA: - gen_shift_imm(ctx, OPC_SRA, rt, rs, - extract32(ctx->opcode, 0, 5)); - break; - case NM_ROTR: - gen_shift_imm(ctx, OPC_ROTR, rt, rs, - extract32(ctx->opcode, 0, 5)); - break; - } - } - break; - case NM_P_ROTX: - check_nms(ctx); - if (rt !=3D 0) { - TCGv t0 =3D tcg_temp_new(); - TCGv_i32 shift =3D tcg_const_i32(extract32(ctx->opcode, 0,= 5)); - TCGv_i32 shiftx =3D tcg_const_i32(extract32(ctx->opcode, 7= , 4) - << 1); - TCGv_i32 stripe =3D tcg_const_i32(extract32(ctx->opcode, 6= , 1)); - - gen_load_gpr(t0, rs); - gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe); - tcg_temp_free(t0); - - tcg_temp_free_i32(shift); - tcg_temp_free_i32(shiftx); - tcg_temp_free_i32(stripe); - } - break; - case NM_P_INS: - switch (((ctx->opcode >> 10) & 2) | - (extract32(ctx->opcode, 5, 1))) { - case NM_INS: - check_nms(ctx); - gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0,= 5), - extract32(ctx->opcode, 6, 5)); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_P_EXT: - switch (((ctx->opcode >> 10) & 2) | - (extract32(ctx->opcode, 5, 1))) { - case NM_EXT: - check_nms(ctx); - gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0,= 5), - extract32(ctx->opcode, 6, 5)); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_POOL32F: - gen_pool32f_nanomips_insn(ctx); - break; - case NM_POOL32S: - break; - case NM_P_LUI: - switch (extract32(ctx->opcode, 1, 1)) { - case NM_LUI: - if (rt !=3D 0) { - tcg_gen_movi_tl(cpu_gpr[rt], - sextract32(ctx->opcode, 0, 1) << 31 | - extract32(ctx->opcode, 2, 10) << 21 | - extract32(ctx->opcode, 12, 9) << 12); - } - break; - case NM_ALUIPC: - if (rt !=3D 0) { - offset =3D sextract32(ctx->opcode, 0, 1) << 31 | - extract32(ctx->opcode, 2, 10) << 21 | - extract32(ctx->opcode, 12, 9) << 12; - target_long addr; - addr =3D ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, off= set); - tcg_gen_movi_tl(cpu_gpr[rt], addr); - } - break; - } - break; - case NM_P_GP_BH: - { - uint32_t u =3D extract32(ctx->opcode, 0, 18); - - switch (extract32(ctx->opcode, 18, 3)) { - case NM_LBGP: - gen_ld(ctx, OPC_LB, rt, 28, u); - break; - case NM_SBGP: - gen_st(ctx, OPC_SB, rt, 28, u); - break; - case NM_LBUGP: - gen_ld(ctx, OPC_LBU, rt, 28, u); - break; - case NM_ADDIUGP_B: - if (rt !=3D 0) { - gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u); - } - break; - case NM_P_GP_LH: - u &=3D ~1; - switch (ctx->opcode & 1) { - case NM_LHGP: - gen_ld(ctx, OPC_LH, rt, 28, u); - break; - case NM_LHUGP: - gen_ld(ctx, OPC_LHU, rt, 28, u); - break; - } - break; - case NM_P_GP_SH: - u &=3D ~1; - switch (ctx->opcode & 1) { - case NM_SHGP: - gen_st(ctx, OPC_SH, rt, 28, u); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_P_GP_CP1: - u &=3D ~0x3; - switch (ctx->opcode & 0x3) { - case NM_LWC1GP: - gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u); - break; - case NM_LDC1GP: - gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u); - break; - case NM_SWC1GP: - gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u); - break; - case NM_SDC1GP: - gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u); - break; - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - } - break; - case NM_P_LS_U12: - { - uint32_t u =3D extract32(ctx->opcode, 0, 12); - - switch (extract32(ctx->opcode, 12, 4)) { - case NM_P_PREFU12: - if (rt =3D=3D 31) { - /* SYNCI */ - /* - * Break the TB to be able to sync copied instructions - * immediately. - */ - ctx->base.is_jmp =3D DISAS_STOP; - } else { - /* PREF */ - /* Treat as NOP. */ - } - break; - case NM_LB: - gen_ld(ctx, OPC_LB, rt, rs, u); - break; - case NM_LH: - gen_ld(ctx, OPC_LH, rt, rs, u); - break; - case NM_LW: - gen_ld(ctx, OPC_LW, rt, rs, u); - break; - case NM_LBU: - gen_ld(ctx, OPC_LBU, rt, rs, u); - break; - case NM_LHU: - gen_ld(ctx, OPC_LHU, rt, rs, u); - break; - case NM_SB: - gen_st(ctx, OPC_SB, rt, rs, u); - break; - case NM_SH: - gen_st(ctx, OPC_SH, rt, rs, u); - break; - case NM_SW: - gen_st(ctx, OPC_SW, rt, rs, u); - break; - case NM_LWC1: - gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u); - break; - case NM_LDC1: - gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u); - break; - case NM_SWC1: - gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u); - break; - case NM_SDC1: - gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u); - break; - default: - gen_reserved_instruction(ctx); - break; - } - } - break; - case NM_P_LS_S9: - { - int32_t s =3D (sextract32(ctx->opcode, 15, 1) << 8) | - extract32(ctx->opcode, 0, 8); - - switch (extract32(ctx->opcode, 8, 3)) { - case NM_P_LS_S0: - switch (extract32(ctx->opcode, 11, 4)) { - case NM_LBS9: - gen_ld(ctx, OPC_LB, rt, rs, s); - break; - case NM_LHS9: - gen_ld(ctx, OPC_LH, rt, rs, s); - break; - case NM_LWS9: - gen_ld(ctx, OPC_LW, rt, rs, s); - break; - case NM_LBUS9: - gen_ld(ctx, OPC_LBU, rt, rs, s); - break; - case NM_LHUS9: - gen_ld(ctx, OPC_LHU, rt, rs, s); - break; - case NM_SBS9: - gen_st(ctx, OPC_SB, rt, rs, s); - break; - case NM_SHS9: - gen_st(ctx, OPC_SH, rt, rs, s); - break; - case NM_SWS9: - gen_st(ctx, OPC_SW, rt, rs, s); - break; - case NM_LWC1S9: - gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s); - break; - case NM_LDC1S9: - gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s); - break; - case NM_SWC1S9: - gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s); - break; - case NM_SDC1S9: - gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s); - break; - case NM_P_PREFS9: - if (rt =3D=3D 31) { - /* SYNCI */ - /* - * Break the TB to be able to sync copied instruct= ions - * immediately. - */ - ctx->base.is_jmp =3D DISAS_STOP; - } else { - /* PREF */ - /* Treat as NOP. */ - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_P_LS_S1: - switch (extract32(ctx->opcode, 11, 4)) { - case NM_UALH: - case NM_UASH: - check_nms(ctx); - { - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - - gen_base_offset_addr(ctx, t0, rs, s); - - switch (extract32(ctx->opcode, 11, 4)) { - case NM_UALH: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TE= SW | - MO_UNALN); - gen_store_gpr(t0, rt); - break; - case NM_UASH: - gen_load_gpr(t1, rt); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TE= UW | - MO_UNALN); - break; - } - tcg_temp_free(t0); - tcg_temp_free(t1); - } - break; - case NM_P_LL: - switch (ctx->opcode & 0x03) { - case NM_LL: - gen_ld(ctx, OPC_LL, rt, rs, s); - break; - case NM_LLWP: - check_xnp(ctx); - gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3,= 5)); - break; - } - break; - case NM_P_SC: - switch (ctx->opcode & 0x03) { - case NM_SC: - gen_st_cond(ctx, rt, rs, s, MO_TESL, false); - break; - case NM_SCWP: - check_xnp(ctx); - gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3,= 5), - false); - break; - } - break; - case NM_CACHE: - check_cp0_enabled(ctx); - if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { - gen_cache_operation(ctx, rt, rs, s); - } - break; - } - break; - case NM_P_LS_E0: - switch (extract32(ctx->opcode, 11, 4)) { - case NM_LBE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LBE, rt, rs, s); - break; - case NM_SBE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_st(ctx, OPC_SBE, rt, rs, s); - break; - case NM_LBUE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LBUE, rt, rs, s); - break; - case NM_P_PREFE: - if (rt =3D=3D 31) { - /* case NM_SYNCIE */ - check_eva(ctx); - check_cp0_enabled(ctx); - /* - * Break the TB to be able to sync copied instruct= ions - * immediately. - */ - ctx->base.is_jmp =3D DISAS_STOP; - } else { - /* case NM_PREFE */ - check_eva(ctx); - check_cp0_enabled(ctx); - /* Treat as NOP. */ - } - break; - case NM_LHE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LHE, rt, rs, s); - break; - case NM_SHE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_st(ctx, OPC_SHE, rt, rs, s); - break; - case NM_LHUE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LHUE, rt, rs, s); - break; - case NM_CACHEE: - check_eva(ctx); - check_cp0_enabled(ctx); - check_nms_dl_il_sl_tl_l2c(ctx); - gen_cache_operation(ctx, rt, rs, s); - break; - case NM_LWE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LWE, rt, rs, s); - break; - case NM_SWE: - check_eva(ctx); - check_cp0_enabled(ctx); - gen_st(ctx, OPC_SWE, rt, rs, s); - break; - case NM_P_LLE: - switch (extract32(ctx->opcode, 2, 2)) { - case NM_LLE: - check_xnp(ctx); - check_eva(ctx); - check_cp0_enabled(ctx); - gen_ld(ctx, OPC_LLE, rt, rs, s); - break; - case NM_LLWPE: - check_xnp(ctx); - check_eva(ctx); - check_cp0_enabled(ctx); - gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3,= 5)); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_P_SCE: - switch (extract32(ctx->opcode, 2, 2)) { - case NM_SCE: - check_xnp(ctx); - check_eva(ctx); - check_cp0_enabled(ctx); - gen_st_cond(ctx, rt, rs, s, MO_TESL, true); - break; - case NM_SCWPE: - check_xnp(ctx); - check_eva(ctx); - check_cp0_enabled(ctx); - gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3,= 5), - true); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - } - break; - case NM_P_LS_WM: - case NM_P_LS_UAWM: - check_nms(ctx); - { - int count =3D extract32(ctx->opcode, 12, 3); - int counter =3D 0; - - offset =3D sextract32(ctx->opcode, 15, 1) << 8 | - extract32(ctx->opcode, 0, 8); - TCGv va =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - MemOp memop =3D (extract32(ctx->opcode, 8, 3)) =3D=3D - NM_P_LS_UAWM ? MO_UNALN : 0; - - count =3D (count =3D=3D 0) ? 8 : count; - while (counter !=3D count) { - int this_rt =3D ((rt + counter) & 0x1f) | (rt & 0x= 10); - int this_offset =3D offset + (counter << 2); - - gen_base_offset_addr(ctx, va, rs, this_offset); - - switch (extract32(ctx->opcode, 11, 1)) { - case NM_LWM: - tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx, - memop | MO_TESL); - gen_store_gpr(t1, this_rt); - if ((this_rt =3D=3D rs) && - (counter !=3D (count - 1))) { - /* UNPREDICTABLE */ - } - break; - case NM_SWM: - this_rt =3D (rt =3D=3D 0) ? 0 : this_rt; - gen_load_gpr(t1, this_rt); - tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx, - memop | MO_TEUL); - break; - } - counter++; - } - tcg_temp_free(va); - tcg_temp_free(t1); - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - } - break; - case NM_MOVE_BALC: - check_nms(ctx); - { - TCGv t0 =3D tcg_temp_new(); - int32_t s =3D sextract32(ctx->opcode, 0, 1) << 21 | - extract32(ctx->opcode, 1, 20) << 1; - rd =3D (extract32(ctx->opcode, 24, 1)) =3D=3D 0 ? 4 : 5; - rt =3D decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3= | - extract32(ctx->opcode, 21, 3)); - gen_load_gpr(t0, rt); - tcg_gen_mov_tl(cpu_gpr[rd], t0); - gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s); - tcg_temp_free(t0); - } - break; - case NM_P_BAL: - { - int32_t s =3D sextract32(ctx->opcode, 0, 1) << 25 | - extract32(ctx->opcode, 1, 24) << 1; - - if ((extract32(ctx->opcode, 25, 1)) =3D=3D 0) { - /* BC */ - gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s); - } else { - /* BALC */ - gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s); - } - } - break; - case NM_P_J: - switch (extract32(ctx->opcode, 12, 4)) { - case NM_JALRC: - case NM_JALRC_HB: - gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0); - break; - case NM_P_BALRSC: - gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_P_BR1: - { - int32_t s =3D sextract32(ctx->opcode, 0, 1) << 14 | - extract32(ctx->opcode, 1, 13) << 1; - switch (extract32(ctx->opcode, 14, 2)) { - case NM_BEQC: - check_nms(ctx); - gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s); - break; - case NM_P_BR3A: - s =3D sextract32(ctx->opcode, 0, 1) << 14 | - extract32(ctx->opcode, 1, 13) << 1; - check_cp1_enabled(ctx); - switch (extract32(ctx->opcode, 16, 5)) { - case NM_BC1EQZC: - gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s); - break; - case NM_BC1NEZC: - gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s); - break; - case NM_BPOSGE32C: - check_dsp_r3(ctx); - { - int32_t imm =3D extract32(ctx->opcode, 1, 13) | - extract32(ctx->opcode, 0, 1) << 13; - - gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2, - imm << 1); - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_BGEC: - if (rs =3D=3D rt) { - gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s); - } else { - gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s= ); - } - break; - case NM_BGEUC: - if (rs =3D=3D rt || rt =3D=3D 0) { - gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s); - } else if (rs =3D=3D 0) { - gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s= ); - } else { - gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, = s); - } - break; - } - } - break; - case NM_P_BR2: - { - int32_t s =3D sextract32(ctx->opcode, 0, 1) << 14 | - extract32(ctx->opcode, 1, 13) << 1; - switch (extract32(ctx->opcode, 14, 2)) { - case NM_BNEC: - check_nms(ctx); - gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s); - break; - case NM_BLTC: - if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { - /* NOP */ - ctx->hflags |=3D MIPS_HFLAG_FBNSLOT; - } else { - gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s= ); - } - break; - case NM_BLTUC: - if (rs =3D=3D 0 || rs =3D=3D rt) { - /* NOP */ - ctx->hflags |=3D MIPS_HFLAG_FBNSLOT; - } else { - gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, = s); - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - } - break; - case NM_P_BRI: - { - int32_t s =3D sextract32(ctx->opcode, 0, 1) << 11 | - extract32(ctx->opcode, 1, 10) << 1; - uint32_t u =3D extract32(ctx->opcode, 11, 7); - - gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3), - rt, u, s); - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - return 4; -} - -static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx) -{ - uint32_t op; - int rt =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode)); - int rs =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); - int rd =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode)); - int offset; - int imm; - - /* make sure instructions are on a halfword boundary */ - if (ctx->base.pc_next & 0x1) { - TCGv tmp =3D tcg_const_tl(ctx->base.pc_next); - tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); - tcg_temp_free(tmp); - generate_exception_end(ctx, EXCP_AdEL); - return 2; - } - - op =3D extract32(ctx->opcode, 10, 6); - switch (op) { - case NM_P16_MV: - rt =3D NANOMIPS_EXTRACT_RD5(ctx->opcode); - if (rt !=3D 0) { - /* MOVE */ - rs =3D NANOMIPS_EXTRACT_RS5(ctx->opcode); - gen_arith(ctx, OPC_ADDU, rt, rs, 0); - } else { - /* P16.RI */ - switch (extract32(ctx->opcode, 3, 2)) { - case NM_P16_SYSCALL: - if (extract32(ctx->opcode, 2, 1) =3D=3D 0) { - generate_exception_end(ctx, EXCP_SYSCALL); - } else { - gen_reserved_instruction(ctx); - } - break; - case NM_BREAK16: - generate_exception_end(ctx, EXCP_BREAK); - break; - case NM_SDBBP16: - if (is_uhi(extract32(ctx->opcode, 0, 3))) { - gen_helper_do_semihosting(cpu_env); - } else { - if (ctx->hflags & MIPS_HFLAG_SBRI) { - gen_reserved_instruction(ctx); - } else { - generate_exception_end(ctx, EXCP_DBp); - } - } - break; - default: - gen_reserved_instruction(ctx); - break; - } - } - break; - case NM_P16_SHIFT: - { - int shift =3D extract32(ctx->opcode, 0, 3); - uint32_t opc =3D 0; - shift =3D (shift =3D=3D 0) ? 8 : shift; - - switch (extract32(ctx->opcode, 3, 1)) { - case NM_SLL16: - opc =3D OPC_SLL; - break; - case NM_SRL16: - opc =3D OPC_SRL; - break; - } - gen_shift_imm(ctx, opc, rt, rs, shift); - } - break; - case NM_P16C: - switch (ctx->opcode & 1) { - case NM_POOL16C_0: - gen_pool16c_nanomips_insn(ctx); - break; - case NM_LWXS16: - gen_ldxs(ctx, rt, rs, rd); - break; - } - break; - case NM_P16_A1: - switch (extract32(ctx->opcode, 6, 1)) { - case NM_ADDIUR1SP: - imm =3D extract32(ctx->opcode, 0, 6) << 2; - gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_P16_A2: - switch (extract32(ctx->opcode, 3, 1)) { - case NM_ADDIUR2: - imm =3D extract32(ctx->opcode, 0, 3) << 2; - gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm); - break; - case NM_P_ADDIURS5: - rt =3D extract32(ctx->opcode, 5, 5); - if (rt !=3D 0) { - /* imm =3D sign_extend(s[3] . s[2:0] , from_nbits =3D 4) */ - imm =3D (sextract32(ctx->opcode, 4, 1) << 3) | - (extract32(ctx->opcode, 0, 3)); - gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm); - } - break; - } - break; - case NM_P16_ADDU: - switch (ctx->opcode & 0x1) { - case NM_ADDU16: - gen_arith(ctx, OPC_ADDU, rd, rs, rt); - break; - case NM_SUBU16: - gen_arith(ctx, OPC_SUBU, rd, rs, rt); - break; - } - break; - case NM_P16_4X4: - rt =3D (extract32(ctx->opcode, 9, 1) << 3) | - extract32(ctx->opcode, 5, 3); - rs =3D (extract32(ctx->opcode, 4, 1) << 3) | - extract32(ctx->opcode, 0, 3); - rt =3D decode_gpr_gpr4(rt); - rs =3D decode_gpr_gpr4(rs); - switch ((extract32(ctx->opcode, 7, 2) & 0x2) | - (extract32(ctx->opcode, 3, 1))) { - case NM_ADDU4X4: - check_nms(ctx); - gen_arith(ctx, OPC_ADDU, rt, rs, rt); - break; - case NM_MUL4X4: - check_nms(ctx); - gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_LI16: - { - int imm =3D extract32(ctx->opcode, 0, 7); - imm =3D (imm =3D=3D 0x7f ? -1 : imm); - if (rt !=3D 0) { - tcg_gen_movi_tl(cpu_gpr[rt], imm); - } - } - break; - case NM_ANDI16: - { - uint32_t u =3D extract32(ctx->opcode, 0, 4); - u =3D (u =3D=3D 12) ? 0xff : - (u =3D=3D 13) ? 0xffff : u; - gen_logic_imm(ctx, OPC_ANDI, rt, rs, u); - } - break; - case NM_P16_LB: - offset =3D extract32(ctx->opcode, 0, 2); - switch (extract32(ctx->opcode, 2, 2)) { - case NM_LB16: - gen_ld(ctx, OPC_LB, rt, rs, offset); - break; - case NM_SB16: - rt =3D decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RT3(ctx->opcode)); - gen_st(ctx, OPC_SB, rt, rs, offset); - break; - case NM_LBU16: - gen_ld(ctx, OPC_LBU, rt, rs, offset); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_P16_LH: - offset =3D extract32(ctx->opcode, 1, 2) << 1; - switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) { - case NM_LH16: - gen_ld(ctx, OPC_LH, rt, rs, offset); - break; - case NM_SH16: - rt =3D decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RT3(ctx->opcode)); - gen_st(ctx, OPC_SH, rt, rs, offset); - break; - case NM_LHU16: - gen_ld(ctx, OPC_LHU, rt, rs, offset); - break; - default: - gen_reserved_instruction(ctx); - break; - } - break; - case NM_LW16: - offset =3D extract32(ctx->opcode, 0, 4) << 2; - gen_ld(ctx, OPC_LW, rt, rs, offset); - break; - case NM_LWSP16: - rt =3D NANOMIPS_EXTRACT_RD5(ctx->opcode); - offset =3D extract32(ctx->opcode, 0, 5) << 2; - gen_ld(ctx, OPC_LW, rt, 29, offset); - break; - case NM_LW4X4: - check_nms(ctx); - rt =3D (extract32(ctx->opcode, 9, 1) << 3) | - extract32(ctx->opcode, 5, 3); - rs =3D (extract32(ctx->opcode, 4, 1) << 3) | - extract32(ctx->opcode, 0, 3); - offset =3D (extract32(ctx->opcode, 3, 1) << 3) | - (extract32(ctx->opcode, 8, 1) << 2); - rt =3D decode_gpr_gpr4(rt); - rs =3D decode_gpr_gpr4(rs); - gen_ld(ctx, OPC_LW, rt, rs, offset); - break; - case NM_SW4X4: - check_nms(ctx); - rt =3D (extract32(ctx->opcode, 9, 1) << 3) | - extract32(ctx->opcode, 5, 3); - rs =3D (extract32(ctx->opcode, 4, 1) << 3) | - extract32(ctx->opcode, 0, 3); - offset =3D (extract32(ctx->opcode, 3, 1) << 3) | - (extract32(ctx->opcode, 8, 1) << 2); - rt =3D decode_gpr_gpr4_zero(rt); - rs =3D decode_gpr_gpr4(rs); - gen_st(ctx, OPC_SW, rt, rs, offset); - break; - case NM_LWGP16: - offset =3D extract32(ctx->opcode, 0, 7) << 2; - gen_ld(ctx, OPC_LW, rt, 28, offset); - break; - case NM_SWSP16: - rt =3D NANOMIPS_EXTRACT_RD5(ctx->opcode); - offset =3D extract32(ctx->opcode, 0, 5) << 2; - gen_st(ctx, OPC_SW, rt, 29, offset); - break; - case NM_SW16: - rt =3D decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RT3(ctx->opcode)); - rs =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); - offset =3D extract32(ctx->opcode, 0, 4) << 2; - gen_st(ctx, OPC_SW, rt, rs, offset); - break; - case NM_SWGP16: - rt =3D decode_gpr_gpr3_src_store( - NANOMIPS_EXTRACT_RT3(ctx->opcode)); - offset =3D extract32(ctx->opcode, 0, 7) << 2; - gen_st(ctx, OPC_SW, rt, 28, offset); - break; - case NM_BC16: - gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0, - (sextract32(ctx->opcode, 0, 1) << 10) | - (extract32(ctx->opcode, 1, 9) << 1)); - break; - case NM_BALC16: - gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0, - (sextract32(ctx->opcode, 0, 1) << 10) | - (extract32(ctx->opcode, 1, 9) << 1)); - break; - case NM_BEQZC16: - gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0, - (sextract32(ctx->opcode, 0, 1) << 7) | - (extract32(ctx->opcode, 1, 6) << 1)); - break; - case NM_BNEZC16: - gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0, - (sextract32(ctx->opcode, 0, 1) << 7) | - (extract32(ctx->opcode, 1, 6) << 1)); - break; - case NM_P16_BR: - switch (ctx->opcode & 0xf) { - case 0: - /* P16.JRC */ - switch (extract32(ctx->opcode, 4, 1)) { - case NM_JRC: - gen_compute_branch_nm(ctx, OPC_JR, 2, - extract32(ctx->opcode, 5, 5), 0, 0); - break; - case NM_JALRC16: - gen_compute_branch_nm(ctx, OPC_JALR, 2, - extract32(ctx->opcode, 5, 5), 31, 0); - break; - } - break; - default: - { - /* P16.BRI */ - uint32_t opc =3D extract32(ctx->opcode, 4, 3) < - extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OP= C_BNE; - gen_compute_branch_nm(ctx, opc, 2, rs, rt, - extract32(ctx->opcode, 0, 4) << 1); - } - break; - } - break; - case NM_P16_SR: - { - int count =3D extract32(ctx->opcode, 0, 4); - int u =3D extract32(ctx->opcode, 4, 4) << 4; - - rt =3D 30 + extract32(ctx->opcode, 9, 1); - switch (extract32(ctx->opcode, 8, 1)) { - case NM_SAVE16: - gen_save(ctx, rt, count, 0, u); - break; - case NM_RESTORE_JRC16: - gen_restore(ctx, rt, count, 0, u); - gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0); - break; - } - } - break; - case NM_MOVEP: - case NM_MOVEPREV: - check_nms(ctx); - { - static const int gpr2reg1[] =3D {4, 5, 6, 7}; - static const int gpr2reg2[] =3D {5, 6, 7, 8}; - int re; - int rd2 =3D extract32(ctx->opcode, 3, 1) << 1 | - extract32(ctx->opcode, 8, 1); - int r1 =3D gpr2reg1[rd2]; - int r2 =3D gpr2reg2[rd2]; - int r3 =3D extract32(ctx->opcode, 4, 1) << 3 | - extract32(ctx->opcode, 0, 3); - int r4 =3D extract32(ctx->opcode, 9, 1) << 3 | - extract32(ctx->opcode, 5, 3); - TCGv t0 =3D tcg_temp_new(); - TCGv t1 =3D tcg_temp_new(); - if (op =3D=3D NM_MOVEP) { - rd =3D r1; - re =3D r2; - rs =3D decode_gpr_gpr4_zero(r3); - rt =3D decode_gpr_gpr4_zero(r4); - } else { - rd =3D decode_gpr_gpr4(r3); - re =3D decode_gpr_gpr4(r4); - rs =3D r1; - rt =3D r2; - } - gen_load_gpr(t0, rs); - gen_load_gpr(t1, rt); - tcg_gen_mov_tl(cpu_gpr[rd], t0); - tcg_gen_mov_tl(cpu_gpr[re], t1); - tcg_temp_free(t0); - tcg_temp_free(t1); - } - break; - default: - return decode_nanomips_32_48_opc(env, ctx); - } - - return 2; -} - +#include "nanomips_translate.c.inc" =20 /* MIPSDSP functions. */ static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc, @@ -21151,7 +16231,7 @@ static void mips_tr_translate_insn(DisasContextBase= *dcbase, CPUState *cs) is_slot =3D ctx->hflags & MIPS_HFLAG_BMASK; if (ctx->insn_flags & ISA_NANOMIPS32) { ctx->opcode =3D translator_lduw(env, ctx->base.pc_next); - insn_bytes =3D decode_nanomips_opc(env, ctx); + insn_bytes =3D decode_isa_nanomips(env, ctx); } else if (!(ctx->hflags & MIPS_HFLAG_M16)) { ctx->opcode =3D translator_ldl(env, ctx->base.pc_next); insn_bytes =3D 4; diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nan= omips_translate.c.inc new file mode 100644 index 00000000000..09e64a69480 --- /dev/null +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -0,0 +1,4922 @@ +/* + * MIPS emulation for QEMU - nanoMIPS 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) + * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +/* MAJOR, P16, and P32 pools opcodes */ +enum { + NM_P_ADDIU =3D 0x00, + NM_ADDIUPC =3D 0x01, + NM_MOVE_BALC =3D 0x02, + NM_P16_MV =3D 0x04, + NM_LW16 =3D 0x05, + NM_BC16 =3D 0x06, + NM_P16_SR =3D 0x07, + + NM_POOL32A =3D 0x08, + NM_P_BAL =3D 0x0a, + NM_P16_SHIFT =3D 0x0c, + NM_LWSP16 =3D 0x0d, + NM_BALC16 =3D 0x0e, + NM_P16_4X4 =3D 0x0f, + + NM_P_GP_W =3D 0x10, + NM_P_GP_BH =3D 0x11, + NM_P_J =3D 0x12, + NM_P16C =3D 0x14, + NM_LWGP16 =3D 0x15, + NM_P16_LB =3D 0x17, + + NM_P48I =3D 0x18, + NM_P16_A1 =3D 0x1c, + NM_LW4X4 =3D 0x1d, + NM_P16_LH =3D 0x1f, + + NM_P_U12 =3D 0x20, + NM_P_LS_U12 =3D 0x21, + NM_P_BR1 =3D 0x22, + NM_P16_A2 =3D 0x24, + NM_SW16 =3D 0x25, + NM_BEQZC16 =3D 0x26, + + NM_POOL32F =3D 0x28, + NM_P_LS_S9 =3D 0x29, + NM_P_BR2 =3D 0x2a, + + NM_P16_ADDU =3D 0x2c, + NM_SWSP16 =3D 0x2d, + NM_BNEZC16 =3D 0x2e, + NM_MOVEP =3D 0x2f, + + NM_POOL32S =3D 0x30, + NM_P_BRI =3D 0x32, + NM_LI16 =3D 0x34, + NM_SWGP16 =3D 0x35, + NM_P16_BR =3D 0x36, + + NM_P_LUI =3D 0x38, + NM_ANDI16 =3D 0x3c, + NM_SW4X4 =3D 0x3d, + NM_MOVEPREV =3D 0x3f, +}; + +/* POOL32A instruction pool */ +enum { + NM_POOL32A0 =3D 0x00, + NM_SPECIAL2 =3D 0x01, + NM_COP2_1 =3D 0x02, + NM_UDI =3D 0x03, + NM_POOL32A5 =3D 0x05, + NM_POOL32A7 =3D 0x07, +}; + +/* P.GP.W instruction pool */ +enum { + NM_ADDIUGP_W =3D 0x00, + NM_LWGP =3D 0x02, + NM_SWGP =3D 0x03, +}; + +/* P48I instruction pool */ +enum { + NM_LI48 =3D 0x00, + NM_ADDIU48 =3D 0x01, + NM_ADDIUGP48 =3D 0x02, + NM_ADDIUPC48 =3D 0x03, + NM_LWPC48 =3D 0x0b, + NM_SWPC48 =3D 0x0f, +}; + +/* P.U12 instruction pool */ +enum { + NM_ORI =3D 0x00, + NM_XORI =3D 0x01, + NM_ANDI =3D 0x02, + NM_P_SR =3D 0x03, + NM_SLTI =3D 0x04, + NM_SLTIU =3D 0x05, + NM_SEQI =3D 0x06, + NM_ADDIUNEG =3D 0x08, + NM_P_SHIFT =3D 0x0c, + NM_P_ROTX =3D 0x0d, + NM_P_INS =3D 0x0e, + NM_P_EXT =3D 0x0f, +}; + +/* POOL32F instruction pool */ +enum { + NM_POOL32F_0 =3D 0x00, + NM_POOL32F_3 =3D 0x03, + NM_POOL32F_5 =3D 0x05, +}; + +/* POOL32S instruction pool */ +enum { + NM_POOL32S_0 =3D 0x00, + NM_POOL32S_4 =3D 0x04, +}; + +/* P.LUI instruction pool */ +enum { + NM_LUI =3D 0x00, + NM_ALUIPC =3D 0x01, +}; + +/* P.GP.BH instruction pool */ +enum { + NM_LBGP =3D 0x00, + NM_SBGP =3D 0x01, + NM_LBUGP =3D 0x02, + NM_ADDIUGP_B =3D 0x03, + NM_P_GP_LH =3D 0x04, + NM_P_GP_SH =3D 0x05, + NM_P_GP_CP1 =3D 0x06, +}; + +/* P.LS.U12 instruction pool */ +enum { + NM_LB =3D 0x00, + NM_SB =3D 0x01, + NM_LBU =3D 0x02, + NM_P_PREFU12 =3D 0x03, + NM_LH =3D 0x04, + NM_SH =3D 0x05, + NM_LHU =3D 0x06, + NM_LWU =3D 0x07, + NM_LW =3D 0x08, + NM_SW =3D 0x09, + NM_LWC1 =3D 0x0a, + NM_SWC1 =3D 0x0b, + NM_LDC1 =3D 0x0e, + NM_SDC1 =3D 0x0f, +}; + +/* P.LS.S9 instruction pool */ +enum { + NM_P_LS_S0 =3D 0x00, + NM_P_LS_S1 =3D 0x01, + NM_P_LS_E0 =3D 0x02, + NM_P_LS_WM =3D 0x04, + NM_P_LS_UAWM =3D 0x05, +}; + +/* P.BAL instruction pool */ +enum { + NM_BC =3D 0x00, + NM_BALC =3D 0x01, +}; + +/* P.J instruction pool */ +enum { + NM_JALRC =3D 0x00, + NM_JALRC_HB =3D 0x01, + NM_P_BALRSC =3D 0x08, +}; + +/* P.BR1 instruction pool */ +enum { + NM_BEQC =3D 0x00, + NM_P_BR3A =3D 0x01, + NM_BGEC =3D 0x02, + NM_BGEUC =3D 0x03, +}; + +/* P.BR2 instruction pool */ +enum { + NM_BNEC =3D 0x00, + NM_BLTC =3D 0x02, + NM_BLTUC =3D 0x03, +}; + +/* P.BRI instruction pool */ +enum { + NM_BEQIC =3D 0x00, + NM_BBEQZC =3D 0x01, + NM_BGEIC =3D 0x02, + NM_BGEIUC =3D 0x03, + NM_BNEIC =3D 0x04, + NM_BBNEZC =3D 0x05, + NM_BLTIC =3D 0x06, + NM_BLTIUC =3D 0x07, +}; + +/* P16.SHIFT instruction pool */ +enum { + NM_SLL16 =3D 0x00, + NM_SRL16 =3D 0x01, +}; + +/* POOL16C instruction pool */ +enum { + NM_POOL16C_0 =3D 0x00, + NM_LWXS16 =3D 0x01, +}; + +/* P16.A1 instruction pool */ +enum { + NM_ADDIUR1SP =3D 0x01, +}; + +/* P16.A2 instruction pool */ +enum { + NM_ADDIUR2 =3D 0x00, + NM_P_ADDIURS5 =3D 0x01, +}; + +/* P16.ADDU instruction pool */ +enum { + NM_ADDU16 =3D 0x00, + NM_SUBU16 =3D 0x01, +}; + +/* P16.SR instruction pool */ +enum { + NM_SAVE16 =3D 0x00, + NM_RESTORE_JRC16 =3D 0x01, +}; + +/* P16.4X4 instruction pool */ +enum { + NM_ADDU4X4 =3D 0x00, + NM_MUL4X4 =3D 0x01, +}; + +/* P16.LB instruction pool */ +enum { + NM_LB16 =3D 0x00, + NM_SB16 =3D 0x01, + NM_LBU16 =3D 0x02, +}; + +/* P16.LH instruction pool */ +enum { + NM_LH16 =3D 0x00, + NM_SH16 =3D 0x01, + NM_LHU16 =3D 0x02, +}; + +/* P.RI instruction pool */ +enum { + NM_SIGRIE =3D 0x00, + NM_P_SYSCALL =3D 0x01, + NM_BREAK =3D 0x02, + NM_SDBBP =3D 0x03, +}; + +/* POOL32A0 instruction pool */ +enum { + NM_P_TRAP =3D 0x00, + NM_SEB =3D 0x01, + NM_SLLV =3D 0x02, + NM_MUL =3D 0x03, + NM_MFC0 =3D 0x06, + NM_MFHC0 =3D 0x07, + NM_SEH =3D 0x09, + NM_SRLV =3D 0x0a, + NM_MUH =3D 0x0b, + NM_MTC0 =3D 0x0e, + NM_MTHC0 =3D 0x0f, + NM_SRAV =3D 0x12, + NM_MULU =3D 0x13, + NM_ROTRV =3D 0x1a, + NM_MUHU =3D 0x1b, + NM_ADD =3D 0x22, + NM_DIV =3D 0x23, + NM_ADDU =3D 0x2a, + NM_MOD =3D 0x2b, + NM_SUB =3D 0x32, + NM_DIVU =3D 0x33, + NM_RDHWR =3D 0x38, + NM_SUBU =3D 0x3a, + NM_MODU =3D 0x3b, + NM_P_CMOVE =3D 0x42, + NM_FORK =3D 0x45, + NM_MFTR =3D 0x46, + NM_MFHTR =3D 0x47, + NM_AND =3D 0x4a, + NM_YIELD =3D 0x4d, + NM_MTTR =3D 0x4e, + NM_MTHTR =3D 0x4f, + NM_OR =3D 0x52, + NM_D_E_MT_VPE =3D 0x56, + NM_NOR =3D 0x5a, + NM_XOR =3D 0x62, + NM_SLT =3D 0x6a, + NM_P_SLTU =3D 0x72, + NM_SOV =3D 0x7a, +}; + +/* CRC32 instruction pool */ +enum { + NM_CRC32B =3D 0x00, + NM_CRC32H =3D 0x01, + NM_CRC32W =3D 0x02, + NM_CRC32CB =3D 0x04, + NM_CRC32CH =3D 0x05, + NM_CRC32CW =3D 0x06, +}; + +/* POOL32A5 instruction pool */ +enum { + NM_CMP_EQ_PH =3D 0x00, + NM_CMP_LT_PH =3D 0x08, + NM_CMP_LE_PH =3D 0x10, + NM_CMPGU_EQ_QB =3D 0x18, + NM_CMPGU_LT_QB =3D 0x20, + NM_CMPGU_LE_QB =3D 0x28, + NM_CMPGDU_EQ_QB =3D 0x30, + NM_CMPGDU_LT_QB =3D 0x38, + NM_CMPGDU_LE_QB =3D 0x40, + NM_CMPU_EQ_QB =3D 0x48, + NM_CMPU_LT_QB =3D 0x50, + NM_CMPU_LE_QB =3D 0x58, + NM_ADDQ_S_W =3D 0x60, + NM_SUBQ_S_W =3D 0x68, + NM_ADDSC =3D 0x70, + NM_ADDWC =3D 0x78, + + NM_ADDQ_S_PH =3D 0x01, + NM_ADDQH_R_PH =3D 0x09, + NM_ADDQH_R_W =3D 0x11, + NM_ADDU_S_QB =3D 0x19, + NM_ADDU_S_PH =3D 0x21, + NM_ADDUH_R_QB =3D 0x29, + NM_SHRAV_R_PH =3D 0x31, + NM_SHRAV_R_QB =3D 0x39, + NM_SUBQ_S_PH =3D 0x41, + NM_SUBQH_R_PH =3D 0x49, + NM_SUBQH_R_W =3D 0x51, + NM_SUBU_S_QB =3D 0x59, + NM_SUBU_S_PH =3D 0x61, + NM_SUBUH_R_QB =3D 0x69, + NM_SHLLV_S_PH =3D 0x71, + NM_PRECR_SRA_R_PH_W =3D 0x79, + + NM_MULEU_S_PH_QBL =3D 0x12, + NM_MULEU_S_PH_QBR =3D 0x1a, + NM_MULQ_RS_PH =3D 0x22, + NM_MULQ_S_PH =3D 0x2a, + NM_MULQ_RS_W =3D 0x32, + NM_MULQ_S_W =3D 0x3a, + NM_APPEND =3D 0x42, + NM_MODSUB =3D 0x52, + NM_SHRAV_R_W =3D 0x5a, + NM_SHRLV_PH =3D 0x62, + NM_SHRLV_QB =3D 0x6a, + NM_SHLLV_QB =3D 0x72, + NM_SHLLV_S_W =3D 0x7a, + + NM_SHILO =3D 0x03, + + NM_MULEQ_S_W_PHL =3D 0x04, + NM_MULEQ_S_W_PHR =3D 0x0c, + + NM_MUL_S_PH =3D 0x05, + NM_PRECR_QB_PH =3D 0x0d, + NM_PRECRQ_QB_PH =3D 0x15, + NM_PRECRQ_PH_W =3D 0x1d, + NM_PRECRQ_RS_PH_W =3D 0x25, + NM_PRECRQU_S_QB_PH =3D 0x2d, + NM_PACKRL_PH =3D 0x35, + NM_PICK_QB =3D 0x3d, + NM_PICK_PH =3D 0x45, + + NM_SHRA_R_W =3D 0x5e, + NM_SHRA_R_PH =3D 0x66, + NM_SHLL_S_PH =3D 0x76, + NM_SHLL_S_W =3D 0x7e, + + NM_REPL_PH =3D 0x07 +}; + +/* POOL32A7 instruction pool */ +enum { + NM_P_LSX =3D 0x00, + NM_LSA =3D 0x01, + NM_EXTW =3D 0x03, + NM_POOL32AXF =3D 0x07, +}; + +/* P.SR instruction pool */ +enum { + NM_PP_SR =3D 0x00, + NM_P_SR_F =3D 0x01, +}; + +/* P.SHIFT instruction pool */ +enum { + NM_P_SLL =3D 0x00, + NM_SRL =3D 0x02, + NM_SRA =3D 0x04, + NM_ROTR =3D 0x06, +}; + +/* P.ROTX instruction pool */ +enum { + NM_ROTX =3D 0x00, +}; + +/* P.INS instruction pool */ +enum { + NM_INS =3D 0x00, +}; + +/* P.EXT instruction pool */ +enum { + NM_EXT =3D 0x00, +}; + +/* POOL32F_0 (fmt) instruction pool */ +enum { + NM_RINT_S =3D 0x04, + NM_RINT_D =3D 0x44, + NM_ADD_S =3D 0x06, + NM_SELEQZ_S =3D 0x07, + NM_SELEQZ_D =3D 0x47, + NM_CLASS_S =3D 0x0c, + NM_CLASS_D =3D 0x4c, + NM_SUB_S =3D 0x0e, + NM_SELNEZ_S =3D 0x0f, + NM_SELNEZ_D =3D 0x4f, + NM_MUL_S =3D 0x16, + NM_SEL_S =3D 0x17, + NM_SEL_D =3D 0x57, + NM_DIV_S =3D 0x1e, + NM_ADD_D =3D 0x26, + NM_SUB_D =3D 0x2e, + NM_MUL_D =3D 0x36, + NM_MADDF_S =3D 0x37, + NM_MADDF_D =3D 0x77, + NM_DIV_D =3D 0x3e, + NM_MSUBF_S =3D 0x3f, + NM_MSUBF_D =3D 0x7f, +}; + +/* POOL32F_3 instruction pool */ +enum { + NM_MIN_FMT =3D 0x00, + NM_MAX_FMT =3D 0x01, + NM_MINA_FMT =3D 0x04, + NM_MAXA_FMT =3D 0x05, + NM_POOL32FXF =3D 0x07, +}; + +/* POOL32F_5 instruction pool */ +enum { + NM_CMP_CONDN_S =3D 0x00, + NM_CMP_CONDN_D =3D 0x02, +}; + +/* P.GP.LH instruction pool */ +enum { + NM_LHGP =3D 0x00, + NM_LHUGP =3D 0x01, +}; + +/* P.GP.SH instruction pool */ +enum { + NM_SHGP =3D 0x00, +}; + +/* P.GP.CP1 instruction pool */ +enum { + NM_LWC1GP =3D 0x00, + NM_SWC1GP =3D 0x01, + NM_LDC1GP =3D 0x02, + NM_SDC1GP =3D 0x03, +}; + +/* P.LS.S0 instruction pool */ +enum { + NM_LBS9 =3D 0x00, + NM_LHS9 =3D 0x04, + NM_LWS9 =3D 0x08, + NM_LDS9 =3D 0x0c, + + NM_SBS9 =3D 0x01, + NM_SHS9 =3D 0x05, + NM_SWS9 =3D 0x09, + NM_SDS9 =3D 0x0d, + + NM_LBUS9 =3D 0x02, + NM_LHUS9 =3D 0x06, + NM_LWC1S9 =3D 0x0a, + NM_LDC1S9 =3D 0x0e, + + NM_P_PREFS9 =3D 0x03, + NM_LWUS9 =3D 0x07, + NM_SWC1S9 =3D 0x0b, + NM_SDC1S9 =3D 0x0f, +}; + +/* P.LS.S1 instruction pool */ +enum { + NM_ASET_ACLR =3D 0x02, + NM_UALH =3D 0x04, + NM_UASH =3D 0x05, + NM_CACHE =3D 0x07, + NM_P_LL =3D 0x0a, + NM_P_SC =3D 0x0b, +}; + +/* P.LS.E0 instruction pool */ +enum { + NM_LBE =3D 0x00, + NM_SBE =3D 0x01, + NM_LBUE =3D 0x02, + NM_P_PREFE =3D 0x03, + NM_LHE =3D 0x04, + NM_SHE =3D 0x05, + NM_LHUE =3D 0x06, + NM_CACHEE =3D 0x07, + NM_LWE =3D 0x08, + NM_SWE =3D 0x09, + NM_P_LLE =3D 0x0a, + NM_P_SCE =3D 0x0b, +}; + +/* P.PREFE instruction pool */ +enum { + NM_SYNCIE =3D 0x00, + NM_PREFE =3D 0x01, +}; + +/* P.LLE instruction pool */ +enum { + NM_LLE =3D 0x00, + NM_LLWPE =3D 0x01, +}; + +/* P.SCE instruction pool */ +enum { + NM_SCE =3D 0x00, + NM_SCWPE =3D 0x01, +}; + +/* P.LS.WM instruction pool */ +enum { + NM_LWM =3D 0x00, + NM_SWM =3D 0x01, +}; + +/* P.LS.UAWM instruction pool */ +enum { + NM_UALWM =3D 0x00, + NM_UASWM =3D 0x01, +}; + +/* P.BR3A instruction pool */ +enum { + NM_BC1EQZC =3D 0x00, + NM_BC1NEZC =3D 0x01, + NM_BC2EQZC =3D 0x02, + NM_BC2NEZC =3D 0x03, + NM_BPOSGE32C =3D 0x04, +}; + +/* P16.RI instruction pool */ +enum { + NM_P16_SYSCALL =3D 0x01, + NM_BREAK16 =3D 0x02, + NM_SDBBP16 =3D 0x03, +}; + +/* POOL16C_0 instruction pool */ +enum { + NM_POOL16C_00 =3D 0x00, +}; + +/* P16.JRC instruction pool */ +enum { + NM_JRC =3D 0x00, + NM_JALRC16 =3D 0x01, +}; + +/* P.SYSCALL instruction pool */ +enum { + NM_SYSCALL =3D 0x00, + NM_HYPCALL =3D 0x01, +}; + +/* P.TRAP instruction pool */ +enum { + NM_TEQ =3D 0x00, + NM_TNE =3D 0x01, +}; + +/* P.CMOVE instruction pool */ +enum { + NM_MOVZ =3D 0x00, + NM_MOVN =3D 0x01, +}; + +/* POOL32Axf instruction pool */ +enum { + NM_POOL32AXF_1 =3D 0x01, + NM_POOL32AXF_2 =3D 0x02, + NM_POOL32AXF_4 =3D 0x04, + NM_POOL32AXF_5 =3D 0x05, + NM_POOL32AXF_7 =3D 0x07, +}; + +/* POOL32Axf_1 instruction pool */ +enum { + NM_POOL32AXF_1_0 =3D 0x00, + NM_POOL32AXF_1_1 =3D 0x01, + NM_POOL32AXF_1_3 =3D 0x03, + NM_POOL32AXF_1_4 =3D 0x04, + NM_POOL32AXF_1_5 =3D 0x05, + NM_POOL32AXF_1_7 =3D 0x07, +}; + +/* POOL32Axf_2 instruction pool */ +enum { + NM_POOL32AXF_2_0_7 =3D 0x00, + NM_POOL32AXF_2_8_15 =3D 0x01, + NM_POOL32AXF_2_16_23 =3D 0x02, + NM_POOL32AXF_2_24_31 =3D 0x03, +}; + +/* POOL32Axf_7 instruction pool */ +enum { + NM_SHRA_R_QB =3D 0x0, + NM_SHRL_PH =3D 0x1, + NM_REPL_QB =3D 0x2, +}; + +/* POOL32Axf_1_0 instruction pool */ +enum { + NM_MFHI =3D 0x0, + NM_MFLO =3D 0x1, + NM_MTHI =3D 0x2, + NM_MTLO =3D 0x3, +}; + +/* POOL32Axf_1_1 instruction pool */ +enum { + NM_MTHLIP =3D 0x0, + NM_SHILOV =3D 0x1, +}; + +/* POOL32Axf_1_3 instruction pool */ +enum { + NM_RDDSP =3D 0x0, + NM_WRDSP =3D 0x1, + NM_EXTP =3D 0x2, + NM_EXTPDP =3D 0x3, +}; + +/* POOL32Axf_1_4 instruction pool */ +enum { + NM_SHLL_QB =3D 0x0, + NM_SHRL_QB =3D 0x1, +}; + +/* POOL32Axf_1_5 instruction pool */ +enum { + NM_MAQ_S_W_PHR =3D 0x0, + NM_MAQ_S_W_PHL =3D 0x1, + NM_MAQ_SA_W_PHR =3D 0x2, + NM_MAQ_SA_W_PHL =3D 0x3, +}; + +/* POOL32Axf_1_7 instruction pool */ +enum { + NM_EXTR_W =3D 0x0, + NM_EXTR_R_W =3D 0x1, + NM_EXTR_RS_W =3D 0x2, + NM_EXTR_S_H =3D 0x3, +}; + +/* POOL32Axf_2_0_7 instruction pool */ +enum { + NM_DPA_W_PH =3D 0x0, + NM_DPAQ_S_W_PH =3D 0x1, + NM_DPS_W_PH =3D 0x2, + NM_DPSQ_S_W_PH =3D 0x3, + NM_BALIGN =3D 0x4, + NM_MADD =3D 0x5, + NM_MULT =3D 0x6, + NM_EXTRV_W =3D 0x7, +}; + +/* POOL32Axf_2_8_15 instruction pool */ +enum { + NM_DPAX_W_PH =3D 0x0, + NM_DPAQ_SA_L_W =3D 0x1, + NM_DPSX_W_PH =3D 0x2, + NM_DPSQ_SA_L_W =3D 0x3, + NM_MADDU =3D 0x5, + NM_MULTU =3D 0x6, + NM_EXTRV_R_W =3D 0x7, +}; + +/* POOL32Axf_2_16_23 instruction pool */ +enum { + NM_DPAU_H_QBL =3D 0x0, + NM_DPAQX_S_W_PH =3D 0x1, + NM_DPSU_H_QBL =3D 0x2, + NM_DPSQX_S_W_PH =3D 0x3, + NM_EXTPV =3D 0x4, + NM_MSUB =3D 0x5, + NM_MULSA_W_PH =3D 0x6, + NM_EXTRV_RS_W =3D 0x7, +}; + +/* POOL32Axf_2_24_31 instruction pool */ +enum { + NM_DPAU_H_QBR =3D 0x0, + NM_DPAQX_SA_W_PH =3D 0x1, + NM_DPSU_H_QBR =3D 0x2, + NM_DPSQX_SA_W_PH =3D 0x3, + NM_EXTPDPV =3D 0x4, + NM_MSUBU =3D 0x5, + NM_MULSAQ_S_W_PH =3D 0x6, + NM_EXTRV_S_H =3D 0x7, +}; + +/* POOL32Axf_{4, 5} instruction pool */ +enum { + NM_CLO =3D 0x25, + NM_CLZ =3D 0x2d, + + NM_TLBP =3D 0x01, + NM_TLBR =3D 0x09, + NM_TLBWI =3D 0x11, + NM_TLBWR =3D 0x19, + NM_TLBINV =3D 0x03, + NM_TLBINVF =3D 0x0b, + NM_DI =3D 0x23, + NM_EI =3D 0x2b, + NM_RDPGPR =3D 0x70, + NM_WRPGPR =3D 0x78, + NM_WAIT =3D 0x61, + NM_DERET =3D 0x71, + NM_ERETX =3D 0x79, + + /* nanoMIPS DSP instructions */ + NM_ABSQ_S_QB =3D 0x00, + NM_ABSQ_S_PH =3D 0x08, + NM_ABSQ_S_W =3D 0x10, + NM_PRECEQ_W_PHL =3D 0x28, + NM_PRECEQ_W_PHR =3D 0x30, + NM_PRECEQU_PH_QBL =3D 0x38, + NM_PRECEQU_PH_QBR =3D 0x48, + NM_PRECEU_PH_QBL =3D 0x58, + NM_PRECEU_PH_QBR =3D 0x68, + NM_PRECEQU_PH_QBLA =3D 0x39, + NM_PRECEQU_PH_QBRA =3D 0x49, + NM_PRECEU_PH_QBLA =3D 0x59, + NM_PRECEU_PH_QBRA =3D 0x69, + NM_REPLV_PH =3D 0x01, + NM_REPLV_QB =3D 0x09, + NM_BITREV =3D 0x18, + NM_INSV =3D 0x20, + NM_RADDU_W_QB =3D 0x78, + + NM_BITSWAP =3D 0x05, + NM_WSBH =3D 0x3d, +}; + +/* PP.SR instruction pool */ +enum { + NM_SAVE =3D 0x00, + NM_RESTORE =3D 0x02, + NM_RESTORE_JRC =3D 0x03, +}; + +/* P.SR.F instruction pool */ +enum { + NM_SAVEF =3D 0x00, + NM_RESTOREF =3D 0x01, +}; + +/* P16.SYSCALL instruction pool */ +enum { + NM_SYSCALL16 =3D 0x00, + NM_HYPCALL16 =3D 0x01, +}; + +/* POOL16C_00 instruction pool */ +enum { + NM_NOT16 =3D 0x00, + NM_XOR16 =3D 0x01, + NM_AND16 =3D 0x02, + NM_OR16 =3D 0x03, +}; + +/* PP.LSX and PP.LSXS instruction pool */ +enum { + NM_LBX =3D 0x00, + NM_LHX =3D 0x04, + NM_LWX =3D 0x08, + NM_LDX =3D 0x0c, + + NM_SBX =3D 0x01, + NM_SHX =3D 0x05, + NM_SWX =3D 0x09, + NM_SDX =3D 0x0d, + + NM_LBUX =3D 0x02, + NM_LHUX =3D 0x06, + NM_LWC1X =3D 0x0a, + NM_LDC1X =3D 0x0e, + + NM_LWUX =3D 0x07, + NM_SWC1X =3D 0x0b, + NM_SDC1X =3D 0x0f, + + NM_LHXS =3D 0x04, + NM_LWXS =3D 0x08, + NM_LDXS =3D 0x0c, + + NM_SHXS =3D 0x05, + NM_SWXS =3D 0x09, + NM_SDXS =3D 0x0d, + + NM_LHUXS =3D 0x06, + NM_LWC1XS =3D 0x0a, + NM_LDC1XS =3D 0x0e, + + NM_LWUXS =3D 0x07, + NM_SWC1XS =3D 0x0b, + NM_SDC1XS =3D 0x0f, +}; + +/* ERETx instruction pool */ +enum { + NM_ERET =3D 0x00, + NM_ERETNC =3D 0x01, +}; + +/* POOL32FxF_{0, 1} insturction pool */ +enum { + NM_CFC1 =3D 0x40, + NM_CTC1 =3D 0x60, + NM_MFC1 =3D 0x80, + NM_MTC1 =3D 0xa0, + NM_MFHC1 =3D 0xc0, + NM_MTHC1 =3D 0xe0, + + NM_CVT_S_PL =3D 0x84, + NM_CVT_S_PU =3D 0xa4, + + NM_CVT_L_S =3D 0x004, + NM_CVT_L_D =3D 0x104, + NM_CVT_W_S =3D 0x024, + NM_CVT_W_D =3D 0x124, + + NM_RSQRT_S =3D 0x008, + NM_RSQRT_D =3D 0x108, + + NM_SQRT_S =3D 0x028, + NM_SQRT_D =3D 0x128, + + NM_RECIP_S =3D 0x048, + NM_RECIP_D =3D 0x148, + + NM_FLOOR_L_S =3D 0x00c, + NM_FLOOR_L_D =3D 0x10c, + + NM_FLOOR_W_S =3D 0x02c, + NM_FLOOR_W_D =3D 0x12c, + + NM_CEIL_L_S =3D 0x04c, + NM_CEIL_L_D =3D 0x14c, + NM_CEIL_W_S =3D 0x06c, + NM_CEIL_W_D =3D 0x16c, + NM_TRUNC_L_S =3D 0x08c, + NM_TRUNC_L_D =3D 0x18c, + NM_TRUNC_W_S =3D 0x0ac, + NM_TRUNC_W_D =3D 0x1ac, + NM_ROUND_L_S =3D 0x0cc, + NM_ROUND_L_D =3D 0x1cc, + NM_ROUND_W_S =3D 0x0ec, + NM_ROUND_W_D =3D 0x1ec, + + NM_MOV_S =3D 0x01, + NM_MOV_D =3D 0x81, + NM_ABS_S =3D 0x0d, + NM_ABS_D =3D 0x8d, + NM_NEG_S =3D 0x2d, + NM_NEG_D =3D 0xad, + NM_CVT_D_S =3D 0x04d, + NM_CVT_D_W =3D 0x0cd, + NM_CVT_D_L =3D 0x14d, + NM_CVT_S_D =3D 0x06d, + NM_CVT_S_W =3D 0x0ed, + NM_CVT_S_L =3D 0x16d, +}; + +/* P.LL instruction pool */ +enum { + NM_LL =3D 0x00, + NM_LLWP =3D 0x01, +}; + +/* P.SC instruction pool */ +enum { + NM_SC =3D 0x00, + NM_SCWP =3D 0x01, +}; + +/* P.DVP instruction pool */ +enum { + NM_DVP =3D 0x00, + NM_EVP =3D 0x01, +}; + + +/* + * + * nanoMIPS decoding engine + * + */ + + +/* extraction utilities */ + +#define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7) +#define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7) +#define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7) +#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f) +#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f) + +/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */ +static inline int decode_gpr_gpr3(int r) +{ + static const int map[] =3D { 16, 17, 18, 19, 4, 5, 6, 7 }; + + return map[r & 0x7]; +} + +/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store')= . */ +static inline int decode_gpr_gpr3_src_store(int r) +{ + static const int map[] =3D { 0, 17, 18, 19, 4, 5, 6, 7 }; + + return map[r & 0x7]; +} + +/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */ +static inline int decode_gpr_gpr4(int r) +{ + static const int map[] =3D { 8, 9, 10, 11, 4, 5, 6, 7, + 16, 17, 18, 19, 20, 21, 22, 23 }; + + return map[r & 0xf]; +} + +/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */ +static inline int decode_gpr_gpr4_zero(int r) +{ + static const int map[] =3D { 8, 9, 10, 0, 4, 5, 6, 7, + 16, 17, 18, 19, 20, 21, 22, 23 }; + + return map[r & 0xf]; +} + +static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt, + int shift) +{ + gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift); +} + +static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset, + uint32_t reg1, uint32_t reg2) +{ + TCGv taddr =3D tcg_temp_new(); + TCGv_i64 tval =3D tcg_temp_new_i64(); + TCGv tmp1 =3D tcg_temp_new(); + TCGv tmp2 =3D tcg_temp_new(); + + gen_base_offset_addr(ctx, taddr, base, offset); + tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx); +#ifdef TARGET_WORDS_BIGENDIAN + tcg_gen_extr_i64_tl(tmp2, tmp1, tval); +#else + tcg_gen_extr_i64_tl(tmp1, tmp2, tval); +#endif + gen_store_gpr(tmp1, reg1); + tcg_temp_free(tmp1); + gen_store_gpr(tmp2, reg2); + tcg_temp_free(tmp2); + tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp)); + tcg_temp_free_i64(tval); + tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr)); + tcg_temp_free(taddr); +} + +static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset, + uint32_t reg1, uint32_t reg2, bool eva) +{ + TCGv taddr =3D tcg_temp_local_new(); + TCGv lladdr =3D tcg_temp_local_new(); + TCGv_i64 tval =3D tcg_temp_new_i64(); + TCGv_i64 llval =3D tcg_temp_new_i64(); + TCGv_i64 val =3D tcg_temp_new_i64(); + TCGv tmp1 =3D tcg_temp_new(); + TCGv tmp2 =3D tcg_temp_new(); + TCGLabel *lab_fail =3D gen_new_label(); + TCGLabel *lab_done =3D gen_new_label(); + + gen_base_offset_addr(ctx, taddr, base, offset); + + tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr)); + tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail); + + gen_load_gpr(tmp1, reg1); + gen_load_gpr(tmp2, reg2); + +#ifdef TARGET_WORDS_BIGENDIAN + tcg_gen_concat_tl_i64(tval, tmp2, tmp1); +#else + tcg_gen_concat_tl_i64(tval, tmp1, tmp2); +#endif + + tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp)); + tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval, + eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64); + if (reg1 !=3D 0) { + tcg_gen_movi_tl(cpu_gpr[reg1], 1); + } + tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done); + + gen_set_label(lab_fail); + + if (reg1 !=3D 0) { + tcg_gen_movi_tl(cpu_gpr[reg1], 0); + } + gen_set_label(lab_done); + tcg_gen_movi_tl(lladdr, -1); + tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr)); +} + +static void gen_adjust_sp(DisasContext *ctx, int u) +{ + gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u); +} + +static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count, + uint8_t gp, uint16_t u) +{ + int counter =3D 0; + TCGv va =3D tcg_temp_new(); + TCGv t0 =3D tcg_temp_new(); + + while (counter !=3D count) { + bool use_gp =3D gp && (counter =3D=3D count - 1); + int this_rt =3D use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f= ); + int this_offset =3D -((counter + 1) << 2); + gen_base_offset_addr(ctx, va, 29, this_offset); + gen_load_gpr(t0, this_rt); + tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx, + (MO_TEUL | ctx->default_tcg_memop_mask)); + counter++; + } + + /* adjust stack pointer */ + gen_adjust_sp(ctx, -u); + + tcg_temp_free(t0); + tcg_temp_free(va); +} + +static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count, + uint8_t gp, uint16_t u) +{ + int counter =3D 0; + TCGv va =3D tcg_temp_new(); + TCGv t0 =3D tcg_temp_new(); + + while (counter !=3D count) { + bool use_gp =3D gp && (counter =3D=3D count - 1); + int this_rt =3D use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f= ); + int this_offset =3D u - ((counter + 1) << 2); + gen_base_offset_addr(ctx, va, 29, this_offset); + tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL | + ctx->default_tcg_memop_mask); + tcg_gen_ext32s_tl(t0, t0); + gen_store_gpr(t0, this_rt); + counter++; + } + + /* adjust stack pointer */ + gen_adjust_sp(ctx, u); + + tcg_temp_free(t0); + tcg_temp_free(va); +} + +static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc, + int insn_bytes, + int rs, int rt, int32_t offset) +{ + target_ulong btgt =3D -1; + int bcond_compute =3D 0; + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + + /* Load needed operands */ + switch (opc) { + case OPC_BEQ: + case OPC_BNE: + /* Compare two registers */ + if (rs !=3D rt) { + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + bcond_compute =3D 1; + } + btgt =3D ctx->base.pc_next + insn_bytes + offset; + break; + case OPC_BGEZAL: + /* Compare to zero */ + if (rs !=3D 0) { + gen_load_gpr(t0, rs); + bcond_compute =3D 1; + } + btgt =3D ctx->base.pc_next + insn_bytes + offset; + break; + case OPC_BPOSGE32: + tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F); + bcond_compute =3D 1; + btgt =3D ctx->base.pc_next + insn_bytes + offset; + break; + case OPC_JR: + case OPC_JALR: + /* Jump to register */ + if (offset !=3D 0 && offset !=3D 16) { + /* + * Hint =3D 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the + * others are reserved. + */ + MIPS_INVAL("jump hint"); + gen_reserved_instruction(ctx); + goto out; + } + gen_load_gpr(btarget, rs); + break; + default: + MIPS_INVAL("branch/jump"); + gen_reserved_instruction(ctx); + goto out; + } + if (bcond_compute =3D=3D 0) { + /* No condition to be computed */ + switch (opc) { + case OPC_BEQ: /* rx =3D=3D rx */ + /* Always take */ + ctx->hflags |=3D MIPS_HFLAG_B; + break; + case OPC_BGEZAL: /* 0 >=3D 0 */ + /* Always take and link */ + tcg_gen_movi_tl(cpu_gpr[31], + ctx->base.pc_next + insn_bytes); + ctx->hflags |=3D MIPS_HFLAG_B; + break; + case OPC_BNE: /* rx !=3D rx */ + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8); + /* Skip the instruction in the delay slot */ + ctx->base.pc_next +=3D 4; + goto out; + case OPC_JR: + ctx->hflags |=3D MIPS_HFLAG_BR; + break; + case OPC_JALR: + if (rt > 0) { + tcg_gen_movi_tl(cpu_gpr[rt], + ctx->base.pc_next + insn_bytes); + } + ctx->hflags |=3D MIPS_HFLAG_BR; + break; + default: + MIPS_INVAL("branch/jump"); + gen_reserved_instruction(ctx); + goto out; + } + } else { + switch (opc) { + case OPC_BEQ: + tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); + goto not_likely; + case OPC_BNE: + tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); + goto not_likely; + case OPC_BGEZAL: + tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); + tcg_gen_movi_tl(cpu_gpr[31], + ctx->base.pc_next + insn_bytes); + goto not_likely; + case OPC_BPOSGE32: + tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32); + not_likely: + ctx->hflags |=3D MIPS_HFLAG_BC; + break; + default: + MIPS_INVAL("conditional branch/jump"); + gen_reserved_instruction(ctx); + goto out; + } + } + + ctx->btarget =3D btgt; + + out: + if (insn_bytes =3D=3D 2) { + ctx->hflags |=3D MIPS_HFLAG_B16; + } + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_pool16c_nanomips_insn(DisasContext *ctx) +{ + int rt =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode)); + int rs =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); + + switch (extract32(ctx->opcode, 2, 2)) { + case NM_NOT16: + gen_logic(ctx, OPC_NOR, rt, rs, 0); + break; + case NM_AND16: + gen_logic(ctx, OPC_AND, rt, rt, rs); + break; + case NM_XOR16: + gen_logic(ctx, OPC_XOR, rt, rt, rs); + break; + case NM_OR16: + gen_logic(ctx, OPC_OR, rt, rt, rs); + break; + } +} + +static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ct= x) +{ + int rt =3D extract32(ctx->opcode, 21, 5); + int rs =3D extract32(ctx->opcode, 16, 5); + int rd =3D extract32(ctx->opcode, 11, 5); + + switch (extract32(ctx->opcode, 3, 7)) { + case NM_P_TRAP: + switch (extract32(ctx->opcode, 10, 1)) { + case NM_TEQ: + check_nms(ctx); + gen_trap(ctx, OPC_TEQ, rs, rt, -1); + break; + case NM_TNE: + check_nms(ctx); + gen_trap(ctx, OPC_TNE, rs, rt, -1); + break; + } + break; + case NM_RDHWR: + check_nms(ctx); + gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); + break; + case NM_SEB: + check_nms(ctx); + gen_bshfl(ctx, OPC_SEB, rs, rt); + break; + case NM_SEH: + gen_bshfl(ctx, OPC_SEH, rs, rt); + break; + case NM_SLLV: + gen_shift(ctx, OPC_SLLV, rd, rt, rs); + break; + case NM_SRLV: + gen_shift(ctx, OPC_SRLV, rd, rt, rs); + break; + case NM_SRAV: + gen_shift(ctx, OPC_SRAV, rd, rt, rs); + break; + case NM_ROTRV: + gen_shift(ctx, OPC_ROTRV, rd, rt, rs); + break; + case NM_ADD: + gen_arith(ctx, OPC_ADD, rd, rs, rt); + break; + case NM_ADDU: + gen_arith(ctx, OPC_ADDU, rd, rs, rt); + break; + case NM_SUB: + check_nms(ctx); + gen_arith(ctx, OPC_SUB, rd, rs, rt); + break; + case NM_SUBU: + gen_arith(ctx, OPC_SUBU, rd, rs, rt); + break; + case NM_P_CMOVE: + switch (extract32(ctx->opcode, 10, 1)) { + case NM_MOVZ: + gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt); + break; + case NM_MOVN: + gen_cond_move(ctx, OPC_MOVN, rd, rs, rt); + break; + } + break; + case NM_AND: + gen_logic(ctx, OPC_AND, rd, rs, rt); + break; + case NM_OR: + gen_logic(ctx, OPC_OR, rd, rs, rt); + break; + case NM_NOR: + gen_logic(ctx, OPC_NOR, rd, rs, rt); + break; + case NM_XOR: + gen_logic(ctx, OPC_XOR, rd, rs, rt); + break; + case NM_SLT: + gen_slt(ctx, OPC_SLT, rd, rs, rt); + break; + case NM_P_SLTU: + if (rd =3D=3D 0) { + /* P_DVP */ +#ifndef CONFIG_USER_ONLY + TCGv t0 =3D tcg_temp_new(); + switch (extract32(ctx->opcode, 10, 1)) { + case NM_DVP: + if (ctx->vp) { + check_cp0_enabled(ctx); + gen_helper_dvp(t0, cpu_env); + gen_store_gpr(t0, rt); + } + break; + case NM_EVP: + if (ctx->vp) { + check_cp0_enabled(ctx); + gen_helper_evp(t0, cpu_env); + gen_store_gpr(t0, rt); + } + break; + } + tcg_temp_free(t0); +#endif + } else { + gen_slt(ctx, OPC_SLTU, rd, rs, rt); + } + break; + case NM_SOV: + { + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + TCGv t2 =3D tcg_temp_new(); + + gen_load_gpr(t1, rs); + gen_load_gpr(t2, rt); + tcg_gen_add_tl(t0, t1, t2); + tcg_gen_ext32s_tl(t0, t0); + tcg_gen_xor_tl(t1, t1, t2); + tcg_gen_xor_tl(t2, t0, t2); + tcg_gen_andc_tl(t1, t2, t1); + + /* operands of same sign, result different sign */ + tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0); + gen_store_gpr(t0, rd); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + } + break; + case NM_MUL: + gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt); + break; + case NM_MUH: + gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt); + break; + case NM_MULU: + gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt); + break; + case NM_MUHU: + gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt); + break; + case NM_DIV: + gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt); + break; + case NM_MOD: + gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt); + break; + case NM_DIVU: + gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt); + break; + case NM_MODU: + gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt); + break; +#ifndef CONFIG_USER_ONLY + case NM_MFC0: + check_cp0_enabled(ctx); + if (rt =3D=3D 0) { + /* Treat as NOP. */ + break; + } + gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3)); + break; + case NM_MTC0: + check_cp0_enabled(ctx); + { + TCGv t0 =3D tcg_temp_new(); + + gen_load_gpr(t0, rt); + gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3)); + tcg_temp_free(t0); + } + break; + case NM_D_E_MT_VPE: + { + uint8_t sc =3D extract32(ctx->opcode, 10, 1); + TCGv t0 =3D tcg_temp_new(); + + switch (sc) { + case 0: + if (rs =3D=3D 1) { + /* DMT */ + check_cp0_mt(ctx); + gen_helper_dmt(t0); + gen_store_gpr(t0, rt); + } else if (rs =3D=3D 0) { + /* DVPE */ + check_cp0_mt(ctx); + gen_helper_dvpe(t0, cpu_env); + gen_store_gpr(t0, rt); + } else { + gen_reserved_instruction(ctx); + } + break; + case 1: + if (rs =3D=3D 1) { + /* EMT */ + check_cp0_mt(ctx); + gen_helper_emt(t0); + gen_store_gpr(t0, rt); + } else if (rs =3D=3D 0) { + /* EVPE */ + check_cp0_mt(ctx); + gen_helper_evpe(t0, cpu_env); + gen_store_gpr(t0, rt); + } else { + gen_reserved_instruction(ctx); + } + break; + } + + tcg_temp_free(t0); + } + break; + case NM_FORK: + check_mt(ctx); + { + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); + gen_helper_fork(t0, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); + } + break; + case NM_MFTR: + case NM_MFHTR: + check_cp0_enabled(ctx); + if (rd =3D=3D 0) { + /* Treat as NOP. */ + return; + } + gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1), + extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, = 1)); + break; + case NM_MTTR: + case NM_MTHTR: + check_cp0_enabled(ctx); + gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1), + extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, = 1)); + break; + case NM_YIELD: + check_mt(ctx); + { + TCGv t0 =3D tcg_temp_new(); + + gen_load_gpr(t0, rs); + gen_helper_yield(t0, cpu_env, t0); + gen_store_gpr(t0, rt); + tcg_temp_free(t0); + } + break; +#endif + default: + gen_reserved_instruction(ctx); + break; + } +} + +/* dsp */ +static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t op= c, + int ret, int v1, int v2) +{ + TCGv_i32 t0; + TCGv v0_t; + TCGv v1_t; + + t0 =3D tcg_temp_new_i32(); + + v0_t =3D tcg_temp_new(); + v1_t =3D tcg_temp_new(); + + tcg_gen_movi_i32(t0, v2 >> 3); + + gen_load_gpr(v0_t, ret); + gen_load_gpr(v1_t, v1); + + switch (opc) { + case NM_MAQ_S_W_PHR: + check_dsp(ctx); + gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env); + break; + case NM_MAQ_S_W_PHL: + check_dsp(ctx); + gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env); + break; + case NM_MAQ_SA_W_PHR: + check_dsp(ctx); + gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env); + break; + case NM_MAQ_SA_W_PHL: + check_dsp(ctx); + gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env); + break; + default: + gen_reserved_instruction(ctx); + break; + } + + tcg_temp_free_i32(t0); + + tcg_temp_free(v0_t); + tcg_temp_free(v1_t); +} + + +static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc, + int ret, int v1, int v2) +{ + int16_t imm; + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + TCGv v0_t =3D tcg_temp_new(); + + gen_load_gpr(v0_t, v1); + + switch (opc) { + case NM_POOL32AXF_1_0: + check_dsp(ctx); + switch (extract32(ctx->opcode, 12, 2)) { + case NM_MFHI: + gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret); + break; + case NM_MFLO: + gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret); + break; + case NM_MTHI: + gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1); + break; + case NM_MTLO: + gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1); + break; + } + break; + case NM_POOL32AXF_1_1: + check_dsp(ctx); + switch (extract32(ctx->opcode, 12, 2)) { + case NM_MTHLIP: + tcg_gen_movi_tl(t0, v2); + gen_helper_mthlip(t0, v0_t, cpu_env); + break; + case NM_SHILOV: + tcg_gen_movi_tl(t0, v2 >> 3); + gen_helper_shilo(t0, v0_t, cpu_env); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_POOL32AXF_1_3: + check_dsp(ctx); + imm =3D extract32(ctx->opcode, 14, 7); + switch (extract32(ctx->opcode, 12, 2)) { + case NM_RDDSP: + tcg_gen_movi_tl(t0, imm); + gen_helper_rddsp(t0, t0, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_WRDSP: + gen_load_gpr(t0, ret); + tcg_gen_movi_tl(t1, imm); + gen_helper_wrdsp(t0, t1, cpu_env); + break; + case NM_EXTP: + tcg_gen_movi_tl(t0, v2 >> 3); + tcg_gen_movi_tl(t1, v1); + gen_helper_extp(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_EXTPDP: + tcg_gen_movi_tl(t0, v2 >> 3); + tcg_gen_movi_tl(t1, v1); + gen_helper_extpdp(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + } + break; + case NM_POOL32AXF_1_4: + check_dsp(ctx); + tcg_gen_movi_tl(t0, v2 >> 2); + switch (extract32(ctx->opcode, 12, 1)) { + case NM_SHLL_QB: + gen_helper_shll_qb(t0, t0, v0_t, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_SHRL_QB: + gen_helper_shrl_qb(t0, t0, v0_t); + gen_store_gpr(t0, ret); + break; + } + break; + case NM_POOL32AXF_1_5: + opc =3D extract32(ctx->opcode, 12, 2); + gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2); + break; + case NM_POOL32AXF_1_7: + check_dsp(ctx); + tcg_gen_movi_tl(t0, v2 >> 3); + tcg_gen_movi_tl(t1, v1); + switch (extract32(ctx->opcode, 12, 2)) { + case NM_EXTR_W: + gen_helper_extr_w(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_EXTR_R_W: + gen_helper_extr_r_w(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_EXTR_RS_W: + gen_helper_extr_rs_w(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_EXTR_S_H: + gen_helper_extr_s_h(t0, t0, t1, cpu_env); + gen_store_gpr(t0, ret); + break; + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(v0_t); +} + +static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc, + TCGv v0, TCGv v1, int rd) +{ + TCGv_i32 t0; + + t0 =3D tcg_temp_new_i32(); + + tcg_gen_movi_i32(t0, rd >> 3); + + switch (opc) { + case NM_POOL32AXF_2_0_7: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPA_W_PH: + check_dsp_r2(ctx); + gen_helper_dpa_w_ph(t0, v1, v0, cpu_env); + break; + case NM_DPAQ_S_W_PH: + check_dsp(ctx); + gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env); + break; + case NM_DPS_W_PH: + check_dsp_r2(ctx); + gen_helper_dps_w_ph(t0, v1, v0, cpu_env); + break; + case NM_DPSQ_S_W_PH: + check_dsp(ctx); + gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_POOL32AXF_2_8_15: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAX_W_PH: + check_dsp_r2(ctx); + gen_helper_dpax_w_ph(t0, v0, v1, cpu_env); + break; + case NM_DPAQ_SA_L_W: + check_dsp(ctx); + gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env); + break; + case NM_DPSX_W_PH: + check_dsp_r2(ctx); + gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env); + break; + case NM_DPSQ_SA_L_W: + check_dsp(ctx); + gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_POOL32AXF_2_16_23: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAU_H_QBL: + check_dsp(ctx); + gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env); + break; + case NM_DPAQX_S_W_PH: + check_dsp_r2(ctx); + gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env); + break; + case NM_DPSU_H_QBL: + check_dsp(ctx); + gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env); + break; + case NM_DPSQX_S_W_PH: + check_dsp_r2(ctx); + gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env); + break; + case NM_MULSA_W_PH: + check_dsp_r2(ctx); + gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_POOL32AXF_2_24_31: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAU_H_QBR: + check_dsp(ctx); + gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env); + break; + case NM_DPAQX_SA_W_PH: + check_dsp_r2(ctx); + gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env); + break; + case NM_DPSU_H_QBR: + check_dsp(ctx); + gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env); + break; + case NM_DPSQX_SA_W_PH: + check_dsp_r2(ctx); + gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env); + break; + case NM_MULSAQ_S_W_PH: + check_dsp(ctx); + gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + + tcg_temp_free_i32(t0); +} + +static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc, + int rt, int rs, int rd) +{ + int ret =3D rt; + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + TCGv v0_t =3D tcg_temp_new(); + TCGv v1_t =3D tcg_temp_new(); + + gen_load_gpr(v0_t, rt); + gen_load_gpr(v1_t, rs); + + switch (opc) { + case NM_POOL32AXF_2_0_7: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPA_W_PH: + case NM_DPAQ_S_W_PH: + case NM_DPS_W_PH: + case NM_DPSQ_S_W_PH: + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); + break; + case NM_BALIGN: + check_dsp_r2(ctx); + if (rt !=3D 0) { + gen_load_gpr(t0, rs); + rd &=3D 3; + if (rd !=3D 0 && rd !=3D 2) { + tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_shri_tl(t0, t0, 8 * (4 - rd)); + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); + } + tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); + } + break; + case NM_MADD: + check_dsp(ctx); + { + int acc =3D extract32(ctx->opcode, 14, 2); + TCGv_i64 t2 =3D tcg_temp_new_i64(); + TCGv_i64 t3 =3D tcg_temp_new_i64(); + + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); + tcg_gen_ext_tl_i64(t2, t0); + tcg_gen_ext_tl_i64(t3, t1); + tcg_gen_mul_i64(t2, t2, t3); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); + tcg_gen_add_i64(t2, t2, t3); + tcg_temp_free_i64(t3); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); + tcg_temp_free_i64(t2); + } + break; + case NM_MULT: + check_dsp(ctx); + { + int acc =3D extract32(ctx->opcode, 14, 2); + TCGv_i32 t2 =3D tcg_temp_new_i32(); + TCGv_i32 t3 =3D tcg_temp_new_i32(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_muls2_i32(t2, t3, t2, t3); + tcg_gen_ext_i32_tl(cpu_LO[acc], t2); + tcg_gen_ext_i32_tl(cpu_HI[acc], t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + break; + case NM_EXTRV_W: + check_dsp(ctx); + gen_load_gpr(v1_t, rs); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extr_w(t0, t0, v1_t, cpu_env); + gen_store_gpr(t0, ret); + break; + } + break; + case NM_POOL32AXF_2_8_15: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAX_W_PH: + case NM_DPAQ_SA_L_W: + case NM_DPSX_W_PH: + case NM_DPSQ_SA_L_W: + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); + break; + case NM_MADDU: + check_dsp(ctx); + { + int acc =3D extract32(ctx->opcode, 14, 2); + TCGv_i64 t2 =3D tcg_temp_new_i64(); + TCGv_i64 t3 =3D tcg_temp_new_i64(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_extu_tl_i64(t2, t0); + tcg_gen_extu_tl_i64(t3, t1); + tcg_gen_mul_i64(t2, t2, t3); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); + tcg_gen_add_i64(t2, t2, t3); + tcg_temp_free_i64(t3); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); + tcg_temp_free_i64(t2); + } + break; + case NM_MULTU: + check_dsp(ctx); + { + int acc =3D extract32(ctx->opcode, 14, 2); + TCGv_i32 t2 =3D tcg_temp_new_i32(); + TCGv_i32 t3 =3D tcg_temp_new_i32(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_mulu2_i32(t2, t3, t2, t3); + tcg_gen_ext_i32_tl(cpu_LO[acc], t2); + tcg_gen_ext_i32_tl(cpu_HI[acc], t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + break; + case NM_EXTRV_R_W: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extr_r_w(t0, t0, v1_t, cpu_env); + gen_store_gpr(t0, ret); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_POOL32AXF_2_16_23: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAU_H_QBL: + case NM_DPAQX_S_W_PH: + case NM_DPSU_H_QBL: + case NM_DPSQX_S_W_PH: + case NM_MULSA_W_PH: + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); + break; + case NM_EXTPV: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extp(t0, t0, v1_t, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_MSUB: + check_dsp(ctx); + { + int acc =3D extract32(ctx->opcode, 14, 2); + TCGv_i64 t2 =3D tcg_temp_new_i64(); + TCGv_i64 t3 =3D tcg_temp_new_i64(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_ext_tl_i64(t2, t0); + tcg_gen_ext_tl_i64(t3, t1); + tcg_gen_mul_i64(t2, t2, t3); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); + tcg_gen_sub_i64(t2, t3, t2); + tcg_temp_free_i64(t3); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); + tcg_temp_free_i64(t2); + } + break; + case NM_EXTRV_RS_W: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env); + gen_store_gpr(t0, ret); + break; + } + break; + case NM_POOL32AXF_2_24_31: + switch (extract32(ctx->opcode, 9, 3)) { + case NM_DPAU_H_QBR: + case NM_DPAQX_SA_W_PH: + case NM_DPSU_H_QBR: + case NM_DPSQX_SA_W_PH: + case NM_MULSAQ_S_W_PH: + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); + break; + case NM_EXTPDPV: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extpdp(t0, t0, v1_t, cpu_env); + gen_store_gpr(t0, ret); + break; + case NM_MSUBU: + check_dsp(ctx); + { + int acc =3D extract32(ctx->opcode, 14, 2); + TCGv_i64 t2 =3D tcg_temp_new_i64(); + TCGv_i64 t3 =3D tcg_temp_new_i64(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_extu_tl_i64(t2, t0); + tcg_gen_extu_tl_i64(t3, t1); + tcg_gen_mul_i64(t2, t2, t3); + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); + tcg_gen_sub_i64(t2, t3, t2); + tcg_temp_free_i64(t3); + gen_move_low32(cpu_LO[acc], t2); + gen_move_high32(cpu_HI[acc], t2); + tcg_temp_free_i64(t2); + } + break; + case NM_EXTRV_S_H: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 3); + gen_helper_extr_s_h(t0, t0, v0_t, cpu_env); + gen_store_gpr(t0, ret); + break; + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + + tcg_temp_free(t0); + tcg_temp_free(t1); + + tcg_temp_free(v0_t); + tcg_temp_free(v1_t); +} + +static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc, + int rt, int rs) +{ + int ret =3D rt; + TCGv t0 =3D tcg_temp_new(); + TCGv v0_t =3D tcg_temp_new(); + + gen_load_gpr(v0_t, rs); + + switch (opc) { + case NM_ABSQ_S_QB: + check_dsp_r2(ctx); + gen_helper_absq_s_qb(v0_t, v0_t, cpu_env); + gen_store_gpr(v0_t, ret); + break; + case NM_ABSQ_S_PH: + check_dsp(ctx); + gen_helper_absq_s_ph(v0_t, v0_t, cpu_env); + gen_store_gpr(v0_t, ret); + break; + case NM_ABSQ_S_W: + check_dsp(ctx); + gen_helper_absq_s_w(v0_t, v0_t, cpu_env); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQ_W_PHL: + check_dsp(ctx); + tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000); + tcg_gen_ext32s_tl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQ_W_PHR: + check_dsp(ctx); + tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF); + tcg_gen_shli_tl(v0_t, v0_t, 16); + tcg_gen_ext32s_tl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQU_PH_QBL: + check_dsp(ctx); + gen_helper_precequ_ph_qbl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQU_PH_QBR: + check_dsp(ctx); + gen_helper_precequ_ph_qbr(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQU_PH_QBLA: + check_dsp(ctx); + gen_helper_precequ_ph_qbla(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEQU_PH_QBRA: + check_dsp(ctx); + gen_helper_precequ_ph_qbra(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEU_PH_QBL: + check_dsp(ctx); + gen_helper_preceu_ph_qbl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEU_PH_QBR: + check_dsp(ctx); + gen_helper_preceu_ph_qbr(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEU_PH_QBLA: + check_dsp(ctx); + gen_helper_preceu_ph_qbla(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_PRECEU_PH_QBRA: + check_dsp(ctx); + gen_helper_preceu_ph_qbra(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_REPLV_PH: + check_dsp(ctx); + tcg_gen_ext16u_tl(v0_t, v0_t); + tcg_gen_shli_tl(t0, v0_t, 16); + tcg_gen_or_tl(v0_t, v0_t, t0); + tcg_gen_ext32s_tl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_REPLV_QB: + check_dsp(ctx); + tcg_gen_ext8u_tl(v0_t, v0_t); + tcg_gen_shli_tl(t0, v0_t, 8); + tcg_gen_or_tl(v0_t, v0_t, t0); + tcg_gen_shli_tl(t0, v0_t, 16); + tcg_gen_or_tl(v0_t, v0_t, t0); + tcg_gen_ext32s_tl(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_BITREV: + check_dsp(ctx); + gen_helper_bitrev(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_INSV: + check_dsp(ctx); + { + TCGv tv0 =3D tcg_temp_new(); + + gen_load_gpr(tv0, rt); + gen_helper_insv(v0_t, cpu_env, v0_t, tv0); + gen_store_gpr(v0_t, ret); + tcg_temp_free(tv0); + } + break; + case NM_RADDU_W_QB: + check_dsp(ctx); + gen_helper_raddu_w_qb(v0_t, v0_t); + gen_store_gpr(v0_t, ret); + break; + case NM_BITSWAP: + gen_bitswap(ctx, OPC_BITSWAP, ret, rs); + break; + case NM_CLO: + check_nms(ctx); + gen_cl(ctx, OPC_CLO, ret, rs); + break; + case NM_CLZ: + check_nms(ctx); + gen_cl(ctx, OPC_CLZ, ret, rs); + break; + case NM_WSBH: + gen_bshfl(ctx, OPC_WSBH, ret, rs); + break; + default: + gen_reserved_instruction(ctx); + break; + } + + tcg_temp_free(v0_t); + tcg_temp_free(t0); +} + +static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc, + int rt, int rs, int rd) +{ + TCGv t0 =3D tcg_temp_new(); + TCGv rs_t =3D tcg_temp_new(); + + gen_load_gpr(rs_t, rs); + + switch (opc) { + case NM_SHRA_R_QB: + check_dsp_r2(ctx); + tcg_gen_movi_tl(t0, rd >> 2); + switch (extract32(ctx->opcode, 12, 1)) { + case 0: + /* NM_SHRA_QB */ + gen_helper_shra_qb(t0, t0, rs_t); + gen_store_gpr(t0, rt); + break; + case 1: + /* NM_SHRA_R_QB */ + gen_helper_shra_r_qb(t0, t0, rs_t); + gen_store_gpr(t0, rt); + break; + } + break; + case NM_SHRL_PH: + check_dsp_r2(ctx); + tcg_gen_movi_tl(t0, rd >> 1); + gen_helper_shrl_ph(t0, t0, rs_t); + gen_store_gpr(t0, rt); + break; + case NM_REPL_QB: + check_dsp(ctx); + { + int16_t imm; + target_long result; + imm =3D extract32(ctx->opcode, 13, 8); + result =3D (uint32_t)imm << 24 | + (uint32_t)imm << 16 | + (uint32_t)imm << 8 | + (uint32_t)imm; + result =3D (int32_t)result; + tcg_gen_movi_tl(t0, result); + gen_store_gpr(t0, rt); + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + tcg_temp_free(t0); + tcg_temp_free(rs_t); +} + + +static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *c= tx) +{ + int rt =3D extract32(ctx->opcode, 21, 5); + int rs =3D extract32(ctx->opcode, 16, 5); + int rd =3D extract32(ctx->opcode, 11, 5); + + switch (extract32(ctx->opcode, 6, 3)) { + case NM_POOL32AXF_1: + { + int32_t op1 =3D extract32(ctx->opcode, 9, 3); + gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd); + } + break; + case NM_POOL32AXF_2: + { + int32_t op1 =3D extract32(ctx->opcode, 12, 2); + gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd); + } + break; + case NM_POOL32AXF_4: + { + int32_t op1 =3D extract32(ctx->opcode, 9, 7); + gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs); + } + break; + case NM_POOL32AXF_5: + switch (extract32(ctx->opcode, 9, 7)) { +#ifndef CONFIG_USER_ONLY + case NM_TLBP: + gen_cp0(env, ctx, OPC_TLBP, 0, 0); + break; + case NM_TLBR: + gen_cp0(env, ctx, OPC_TLBR, 0, 0); + break; + case NM_TLBWI: + gen_cp0(env, ctx, OPC_TLBWI, 0, 0); + break; + case NM_TLBWR: + gen_cp0(env, ctx, OPC_TLBWR, 0, 0); + break; + case NM_TLBINV: + gen_cp0(env, ctx, OPC_TLBINV, 0, 0); + break; + case NM_TLBINVF: + gen_cp0(env, ctx, OPC_TLBINVF, 0, 0); + break; + case NM_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, rt); + /* Stop translation as we may have switched the execution mode= */ + ctx->base.is_jmp =3D DISAS_STOP; + tcg_temp_free(t0); + } + break; + case NM_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, rt); + /* Stop translation as we may have switched the execution mode= */ + ctx->base.is_jmp =3D DISAS_STOP; + tcg_temp_free(t0); + } + break; + case NM_RDPGPR: + check_cp0_enabled(ctx); + gen_load_srsgpr(rs, rt); + break; + case NM_WRPGPR: + check_cp0_enabled(ctx); + gen_store_srsgpr(rs, rt); + break; + case NM_WAIT: + gen_cp0(env, ctx, OPC_WAIT, 0, 0); + break; + case NM_DERET: + gen_cp0(env, ctx, OPC_DERET, 0, 0); + break; + case NM_ERETX: + gen_cp0(env, ctx, OPC_ERET, 0, 0); + break; +#endif + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_POOL32AXF_7: + { + int32_t op1 =3D extract32(ctx->opcode, 9, 3); + gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd); + } + break; + default: + gen_reserved_instruction(ctx); + break; + } +} + +/* Immediate Value Compact Branches */ +static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, + int rt, int32_t imm, int32_t offset) +{ + TCGCond cond =3D TCG_COND_ALWAYS; + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + + gen_load_gpr(t0, rt); + tcg_gen_movi_tl(t1, imm); + ctx->btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); + + /* Load needed operands and calculate btarget */ + switch (opc) { + case NM_BEQIC: + if (rt =3D=3D 0 && imm =3D=3D 0) { + /* Unconditional branch */ + } else if (rt =3D=3D 0 && imm !=3D 0) { + /* Treat as NOP */ + goto out; + } else { + cond =3D TCG_COND_EQ; + } + break; + case NM_BBEQZC: + case NM_BBNEZC: + check_nms(ctx); + if (imm >=3D 32 && !(ctx->hflags & MIPS_HFLAG_64)) { + gen_reserved_instruction(ctx); + goto out; + } else if (rt =3D=3D 0 && opc =3D=3D NM_BBEQZC) { + /* Unconditional branch */ + } else if (rt =3D=3D 0 && opc =3D=3D NM_BBNEZC) { + /* Treat as NOP */ + goto out; + } else { + tcg_gen_shri_tl(t0, t0, imm); + tcg_gen_andi_tl(t0, t0, 1); + tcg_gen_movi_tl(t1, 0); + if (opc =3D=3D NM_BBEQZC) { + cond =3D TCG_COND_EQ; + } else { + cond =3D TCG_COND_NE; + } + } + break; + case NM_BNEIC: + if (rt =3D=3D 0 && imm =3D=3D 0) { + /* Treat as NOP */ + goto out; + } else if (rt =3D=3D 0 && imm !=3D 0) { + /* Unconditional branch */ + } else { + cond =3D TCG_COND_NE; + } + break; + case NM_BGEIC: + if (rt =3D=3D 0 && imm =3D=3D 0) { + /* Unconditional branch */ + } else { + cond =3D TCG_COND_GE; + } + break; + case NM_BLTIC: + cond =3D TCG_COND_LT; + break; + case NM_BGEIUC: + if (rt =3D=3D 0 && imm =3D=3D 0) { + /* Unconditional branch */ + } else { + cond =3D TCG_COND_GEU; + } + break; + case NM_BLTIUC: + cond =3D TCG_COND_LTU; + break; + default: + MIPS_INVAL("Immediate Value Compact branch"); + gen_reserved_instruction(ctx); + goto out; + } + + /* branch completion */ + clear_branch_hflags(ctx); + ctx->base.is_jmp =3D DISAS_NORETURN; + + if (cond =3D=3D TCG_COND_ALWAYS) { + /* Uncoditional compact branch */ + gen_goto_tb(ctx, 0, ctx->btarget); + } else { + /* Conditional compact branch */ + TCGLabel *fs =3D gen_new_label(); + + tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs); + + gen_goto_tb(ctx, 1, ctx->btarget); + gen_set_label(fs); + + gen_goto_tb(ctx, 0, ctx->base.pc_next + 4); + } + +out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */ +static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs, + int rt) +{ + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + + /* load rs */ + gen_load_gpr(t0, rs); + + /* link */ + if (rt !=3D 0) { + tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4); + } + + /* calculate btarget */ + tcg_gen_shli_tl(t0, t0, 1); + tcg_gen_movi_tl(t1, ctx->base.pc_next + 4); + gen_op_addr_add(ctx, btarget, t1, t0); + + /* branch completion */ + clear_branch_hflags(ctx); + ctx->base.is_jmp =3D DISAS_NORETURN; + + /* unconditional branch to register */ + tcg_gen_mov_tl(cpu_PC, btarget); + tcg_gen_lookup_and_goto_ptr(); + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +/* nanoMIPS Branches */ +static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc, + int rs, int rt, int32_t offset) +{ + int bcond_compute =3D 0; + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + + /* Load needed operands and calculate btarget */ + switch (opc) { + /* compact branch */ + case OPC_BGEC: + case OPC_BLTC: + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + bcond_compute =3D 1; + ctx->btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); + break; + case OPC_BGEUC: + case OPC_BLTUC: + if (rs =3D=3D 0 || rs =3D=3D rt) { + /* OPC_BLEZALC, OPC_BGEZALC */ + /* OPC_BGTZALC, OPC_BLTZALC */ + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4); + } + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + bcond_compute =3D 1; + ctx->btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); + break; + case OPC_BC: + ctx->btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); + break; + case OPC_BEQZC: + if (rs !=3D 0) { + /* OPC_BEQZC, OPC_BNEZC */ + gen_load_gpr(t0, rs); + bcond_compute =3D 1; + ctx->btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); + } else { + /* OPC_JIC, OPC_JIALC */ + TCGv tbase =3D tcg_temp_new(); + TCGv toffset =3D tcg_temp_new(); + + gen_load_gpr(tbase, rt); + tcg_gen_movi_tl(toffset, offset); + gen_op_addr_add(ctx, btarget, tbase, toffset); + tcg_temp_free(tbase); + tcg_temp_free(toffset); + } + break; + default: + MIPS_INVAL("Compact branch/jump"); + gen_reserved_instruction(ctx); + goto out; + } + + if (bcond_compute =3D=3D 0) { + /* Uncoditional compact branch */ + switch (opc) { + case OPC_BC: + gen_goto_tb(ctx, 0, ctx->btarget); + break; + default: + MIPS_INVAL("Compact branch/jump"); + gen_reserved_instruction(ctx); + goto out; + } + } else { + /* Conditional compact branch */ + TCGLabel *fs =3D gen_new_label(); + + switch (opc) { + case OPC_BGEUC: + if (rs =3D=3D 0 && rt !=3D 0) { + /* OPC_BLEZALC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs= ); + } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { + /* OPC_BGEZALC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs= ); + } else { + /* OPC_BGEUC */ + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, f= s); + } + break; + case OPC_BLTUC: + if (rs =3D=3D 0 && rt !=3D 0) { + /* OPC_BGTZALC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs= ); + } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { + /* OPC_BLTZALC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs= ); + } else { + /* OPC_BLTUC */ + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, f= s); + } + break; + case OPC_BGEC: + if (rs =3D=3D 0 && rt !=3D 0) { + /* OPC_BLEZC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs= ); + } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { + /* OPC_BGEZC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs= ); + } else { + /* OPC_BGEC */ + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs= ); + } + break; + case OPC_BLTC: + if (rs =3D=3D 0 && rt !=3D 0) { + /* OPC_BGTZC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs= ); + } else if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { + /* OPC_BLTZC */ + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs= ); + } else { + /* OPC_BLTC */ + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs= ); + } + break; + case OPC_BEQZC: + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs); + break; + default: + MIPS_INVAL("Compact conditional branch/jump"); + gen_reserved_instruction(ctx); + goto out; + } + + /* branch completion */ + clear_branch_hflags(ctx); + ctx->base.is_jmp =3D DISAS_NORETURN; + + /* Generating branch here as compact branches don't have delay slo= t */ + gen_goto_tb(ctx, 1, ctx->btarget); + gen_set_label(fs); + + gen_goto_tb(ctx, 0, ctx->base.pc_next + 4); + } + +out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} + + +/* nanoMIPS CP1 Branches */ +static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op, + int32_t ft, int32_t offset) +{ + target_ulong btarget; + TCGv_i64 t0 =3D tcg_temp_new_i64(); + + gen_load_fpr64(ctx, t0, ft); + tcg_gen_andi_i64(t0, t0, 1); + + btarget =3D addr_add(ctx, ctx->base.pc_next + 4, offset); + + switch (op) { + case NM_BC1EQZC: + tcg_gen_xori_i64(t0, t0, 1); + ctx->hflags |=3D MIPS_HFLAG_BC; + break; + case NM_BC1NEZC: + /* t0 already set */ + ctx->hflags |=3D MIPS_HFLAG_BC; + break; + default: + MIPS_INVAL("cp1 cond branch"); + gen_reserved_instruction(ctx); + goto out; + } + + tcg_gen_trunc_i64_tl(bcond, t0); + + ctx->btarget =3D btarget; + +out: + tcg_temp_free_i64(t0); +} + + +static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt) +{ + TCGv t0, t1; + t0 =3D tcg_temp_new(); + t1 =3D tcg_temp_new(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + + if ((extract32(ctx->opcode, 6, 1)) =3D=3D 1) { + /* PP.LSXS instructions require shifting */ + switch (extract32(ctx->opcode, 7, 4)) { + case NM_SHXS: + check_nms(ctx); + /* fall through */ + case NM_LHXS: + case NM_LHUXS: + tcg_gen_shli_tl(t0, t0, 1); + break; + case NM_SWXS: + check_nms(ctx); + /* fall through */ + case NM_LWXS: + case NM_LWC1XS: + case NM_SWC1XS: + tcg_gen_shli_tl(t0, t0, 2); + break; + case NM_LDC1XS: + case NM_SDC1XS: + tcg_gen_shli_tl(t0, t0, 3); + break; + } + } + gen_op_addr_add(ctx, t0, t0, t1); + + switch (extract32(ctx->opcode, 7, 4)) { + case NM_LBX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, + MO_SB); + gen_store_gpr(t0, rd); + break; + case NM_LHX: + /*case NM_LHXS:*/ + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, + MO_TESW); + gen_store_gpr(t0, rd); + break; + case NM_LWX: + /*case NM_LWXS:*/ + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, + MO_TESL); + gen_store_gpr(t0, rd); + break; + case NM_LBUX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, + MO_UB); + gen_store_gpr(t0, rd); + break; + case NM_LHUX: + /*case NM_LHUXS:*/ + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, + MO_TEUW); + gen_store_gpr(t0, rd); + break; + case NM_SBX: + check_nms(ctx); + gen_load_gpr(t1, rd); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, + MO_8); + break; + case NM_SHX: + /*case NM_SHXS:*/ + check_nms(ctx); + gen_load_gpr(t1, rd); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, + MO_TEUW); + break; + case NM_SWX: + /*case NM_SWXS:*/ + check_nms(ctx); + gen_load_gpr(t1, rd); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, + MO_TEUL); + break; + case NM_LWC1X: + /*case NM_LWC1XS:*/ + case NM_LDC1X: + /*case NM_LDC1XS:*/ + case NM_SWC1X: + /*case NM_SWC1XS:*/ + case NM_SDC1X: + /*case NM_SDC1XS:*/ + if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { + check_cp1_enabled(ctx); + switch (extract32(ctx->opcode, 7, 4)) { + case NM_LWC1X: + /*case NM_LWC1XS:*/ + gen_flt_ldst(ctx, OPC_LWC1, rd, t0); + break; + case NM_LDC1X: + /*case NM_LDC1XS:*/ + gen_flt_ldst(ctx, OPC_LDC1, rd, t0); + break; + case NM_SWC1X: + /*case NM_SWC1XS:*/ + gen_flt_ldst(ctx, OPC_SWC1, rd, t0); + break; + case NM_SDC1X: + /*case NM_SDC1XS:*/ + gen_flt_ldst(ctx, OPC_SDC1, rd, t0); + break; + } + } else { + generate_exception_err(ctx, EXCP_CpU, 1); + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_pool32f_nanomips_insn(DisasContext *ctx) +{ + int rt, rs, rd; + + rt =3D extract32(ctx->opcode, 21, 5); + rs =3D extract32(ctx->opcode, 16, 5); + rd =3D extract32(ctx->opcode, 11, 5); + + if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) { + gen_reserved_instruction(ctx); + return; + } + check_cp1_enabled(ctx); + switch (extract32(ctx->opcode, 0, 3)) { + case NM_POOL32F_0: + switch (extract32(ctx->opcode, 3, 7)) { + case NM_RINT_S: + gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0); + break; + case NM_RINT_D: + gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0); + break; + case NM_CLASS_S: + gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0); + break; + case NM_CLASS_D: + gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0); + break; + case NM_ADD_S: + gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0); + break; + case NM_ADD_D: + gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0); + break; + case NM_SUB_S: + gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0); + break; + case NM_SUB_D: + gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0); + break; + case NM_MUL_S: + gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0); + break; + case NM_MUL_D: + gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0); + break; + case NM_DIV_S: + gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0); + break; + case NM_DIV_D: + gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0); + break; + case NM_SELEQZ_S: + gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs); + break; + case NM_SELEQZ_D: + gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs); + break; + case NM_SELNEZ_S: + gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs); + break; + case NM_SELNEZ_D: + gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs); + break; + case NM_SEL_S: + gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs); + break; + case NM_SEL_D: + gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs); + break; + case NM_MADDF_S: + gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0); + break; + case NM_MADDF_D: + gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0); + break; + case NM_MSUBF_S: + gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0); + break; + case NM_MSUBF_D: + gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_POOL32F_3: + switch (extract32(ctx->opcode, 3, 3)) { + case NM_MIN_FMT: + switch (extract32(ctx->opcode, 9, 1)) { + 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; + } + break; + case NM_MAX_FMT: + switch (extract32(ctx->opcode, 9, 1)) { + 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; + } + break; + case NM_MINA_FMT: + switch (extract32(ctx->opcode, 9, 1)) { + 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; + } + break; + case NM_MAXA_FMT: + switch (extract32(ctx->opcode, 9, 1)) { + 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; + } + break; + case NM_POOL32FXF: + switch (extract32(ctx->opcode, 6, 8)) { + case NM_CFC1: + gen_cp1(ctx, OPC_CFC1, rt, rs); + break; + case NM_CTC1: + gen_cp1(ctx, OPC_CTC1, rt, rs); + break; + case NM_MFC1: + gen_cp1(ctx, OPC_MFC1, rt, rs); + break; + case NM_MTC1: + gen_cp1(ctx, OPC_MTC1, rt, rs); + break; + case NM_MFHC1: + gen_cp1(ctx, OPC_MFHC1, rt, rs); + break; + case NM_MTHC1: + gen_cp1(ctx, OPC_MTHC1, rt, rs); + break; + case NM_CVT_S_PL: + gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0); + break; + case NM_CVT_S_PU: + gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0); + break; + default: + switch (extract32(ctx->opcode, 6, 9)) { + case NM_CVT_L_S: + gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0); + break; + case NM_CVT_L_D: + gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0); + break; + case NM_CVT_W_S: + gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0); + break; + case NM_CVT_W_D: + gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0); + break; + case NM_RSQRT_S: + gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0); + break; + case NM_RSQRT_D: + gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0); + break; + case NM_SQRT_S: + gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0); + break; + case NM_SQRT_D: + gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0); + break; + case NM_RECIP_S: + gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0); + break; + case NM_RECIP_D: + gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0); + break; + case NM_FLOOR_L_S: + gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0); + break; + case NM_FLOOR_L_D: + gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0); + break; + case NM_FLOOR_W_S: + gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0); + break; + case NM_FLOOR_W_D: + gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0); + break; + case NM_CEIL_L_S: + gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0); + break; + case NM_CEIL_L_D: + gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0); + break; + case NM_CEIL_W_S: + gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0); + break; + case NM_CEIL_W_D: + gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0); + break; + case NM_TRUNC_L_S: + gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0); + break; + case NM_TRUNC_L_D: + gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0); + break; + case NM_TRUNC_W_S: + gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0); + break; + case NM_TRUNC_W_D: + gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0); + break; + case NM_ROUND_L_S: + gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0); + break; + case NM_ROUND_L_D: + gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0); + break; + case NM_ROUND_W_S: + gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0); + break; + case NM_ROUND_W_D: + gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0); + break; + case NM_MOV_S: + gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0); + break; + case NM_MOV_D: + gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0); + break; + case NM_ABS_S: + gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0); + break; + case NM_ABS_D: + gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0); + break; + case NM_NEG_S: + gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0); + break; + case NM_NEG_D: + gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0); + break; + case NM_CVT_D_S: + gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0); + break; + case NM_CVT_D_W: + gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0); + break; + case NM_CVT_D_L: + gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0); + break; + case NM_CVT_S_D: + gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0); + break; + case NM_CVT_S_W: + gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0); + break; + case NM_CVT_S_L: + gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + } + break; + } + break; + case NM_POOL32F_5: + switch (extract32(ctx->opcode, 3, 3)) { + case NM_CMP_CONDN_S: + gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd); + break; + case NM_CMP_CONDN_D: + gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + default: + gen_reserved_instruction(ctx); + break; + } +} + +static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc, + int rd, int rs, int rt) +{ + int ret =3D rd; + TCGv t0 =3D tcg_temp_new(); + TCGv v1_t =3D tcg_temp_new(); + TCGv v2_t =3D tcg_temp_new(); + + gen_load_gpr(v1_t, rs); + gen_load_gpr(v2_t, rt); + + switch (opc) { + case NM_CMP_EQ_PH: + check_dsp(ctx); + gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env); + break; + case NM_CMP_LT_PH: + check_dsp(ctx); + gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env); + break; + case NM_CMP_LE_PH: + check_dsp(ctx); + gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env); + break; + case NM_CMPU_EQ_QB: + check_dsp(ctx); + gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env); + break; + case NM_CMPU_LT_QB: + check_dsp(ctx); + gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env); + break; + case NM_CMPU_LE_QB: + check_dsp(ctx); + gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env); + break; + case NM_CMPGU_EQ_QB: + check_dsp(ctx); + gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_CMPGU_LT_QB: + check_dsp(ctx); + gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_CMPGU_LE_QB: + check_dsp(ctx); + gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_CMPGDU_EQ_QB: + check_dsp_r2(ctx); + gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t); + tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); + gen_store_gpr(v1_t, ret); + break; + case NM_CMPGDU_LT_QB: + check_dsp_r2(ctx); + gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t); + tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); + gen_store_gpr(v1_t, ret); + break; + case NM_CMPGDU_LE_QB: + check_dsp_r2(ctx); + gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t); + tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); + gen_store_gpr(v1_t, ret); + break; + case NM_PACKRL_PH: + check_dsp(ctx); + gen_helper_packrl_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_PICK_QB: + check_dsp(ctx); + gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_PICK_PH: + check_dsp(ctx); + gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_ADDQ_S_W: + check_dsp(ctx); + gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_SUBQ_S_W: + check_dsp(ctx); + gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_ADDSC: + check_dsp(ctx); + gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_ADDWC: + check_dsp(ctx); + gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_ADDQ_S_PH: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDQ_PH */ + gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDQ_S_PH */ + gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_ADDQH_R_PH: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDQH_PH */ + gen_helper_addqh_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDQH_R_PH */ + gen_helper_addqh_r_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_ADDQH_R_W: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDQH_W */ + gen_helper_addqh_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDQH_R_W */ + gen_helper_addqh_r_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_ADDU_S_QB: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDU_QB */ + gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDU_S_QB */ + gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_ADDU_S_PH: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDU_PH */ + gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDU_S_PH */ + gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_ADDUH_R_QB: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* ADDUH_QB */ + gen_helper_adduh_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* ADDUH_R_QB */ + gen_helper_adduh_r_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SHRAV_R_PH: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SHRAV_PH */ + gen_helper_shra_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SHRAV_R_PH */ + gen_helper_shra_r_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SHRAV_R_QB: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SHRAV_QB */ + gen_helper_shra_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SHRAV_R_QB */ + gen_helper_shra_r_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBQ_S_PH: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBQ_PH */ + gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBQ_S_PH */ + gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBQH_R_PH: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBQH_PH */ + gen_helper_subqh_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBQH_R_PH */ + gen_helper_subqh_r_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBQH_R_W: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBQH_W */ + gen_helper_subqh_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBQH_R_W */ + gen_helper_subqh_r_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBU_S_QB: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBU_QB */ + gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBU_S_QB */ + gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBU_S_PH: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBU_PH */ + gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBU_S_PH */ + gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SUBUH_R_QB: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SUBUH_QB */ + gen_helper_subuh_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SUBUH_R_QB */ + gen_helper_subuh_r_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_SHLLV_S_PH: + check_dsp(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SHLLV_PH */ + gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* SHLLV_S_PH */ + gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_PRECR_SRA_R_PH_W: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* PRECR_SRA_PH_W */ + { + TCGv_i32 sa_t =3D tcg_const_i32(rd); + gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t, + cpu_gpr[rt]); + gen_store_gpr(v1_t, rt); + tcg_temp_free_i32(sa_t); + } + break; + case 1: + /* PRECR_SRA_R_PH_W */ + { + TCGv_i32 sa_t =3D tcg_const_i32(rd); + gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t, + cpu_gpr[rt]); + gen_store_gpr(v1_t, rt); + tcg_temp_free_i32(sa_t); + } + break; + } + break; + case NM_MULEU_S_PH_QBL: + check_dsp(ctx); + gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULEU_S_PH_QBR: + check_dsp(ctx); + gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULQ_RS_PH: + check_dsp(ctx); + gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULQ_S_PH: + check_dsp_r2(ctx); + gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULQ_RS_W: + check_dsp_r2(ctx); + gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULQ_S_W: + check_dsp_r2(ctx); + gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_APPEND: + check_dsp_r2(ctx); + gen_load_gpr(t0, rs); + if (rd !=3D 0) { + tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd); + } + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); + break; + case NM_MODSUB: + check_dsp(ctx); + gen_helper_modsub(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_SHRAV_R_W: + check_dsp(ctx); + gen_helper_shra_r_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_SHRLV_PH: + check_dsp_r2(ctx); + gen_helper_shrl_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_SHRLV_QB: + check_dsp(ctx); + gen_helper_shrl_qb(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_SHLLV_QB: + check_dsp(ctx); + gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_SHLLV_S_W: + check_dsp(ctx); + gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_SHILO: + check_dsp(ctx); + { + TCGv tv0 =3D tcg_temp_new(); + TCGv tv1 =3D tcg_temp_new(); + int16_t imm =3D extract32(ctx->opcode, 16, 7); + + tcg_gen_movi_tl(tv0, rd >> 3); + tcg_gen_movi_tl(tv1, imm); + gen_helper_shilo(tv0, tv1, cpu_env); + tcg_temp_free(tv1); + tcg_temp_free(tv0); + } + break; + case NM_MULEQ_S_W_PHL: + check_dsp(ctx); + gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MULEQ_S_W_PHR: + check_dsp(ctx); + gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_MUL_S_PH: + check_dsp_r2(ctx); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* MUL_PH */ + gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case 1: + /* MUL_S_PH */ + gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + } + break; + case NM_PRECR_QB_PH: + check_dsp_r2(ctx); + gen_helper_precr_qb_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_PRECRQ_QB_PH: + check_dsp(ctx); + gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_PRECRQ_PH_W: + check_dsp(ctx); + gen_helper_precrq_ph_w(v1_t, v1_t, v2_t); + gen_store_gpr(v1_t, ret); + break; + case NM_PRECRQ_RS_PH_W: + check_dsp(ctx); + gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_PRECRQU_S_QB_PH: + check_dsp(ctx); + gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env); + gen_store_gpr(v1_t, ret); + break; + case NM_SHRA_R_W: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd); + gen_helper_shra_r_w(v1_t, t0, v1_t); + gen_store_gpr(v1_t, rt); + break; + case NM_SHRA_R_PH: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 1); + switch (extract32(ctx->opcode, 10, 1)) { + case 0: + /* SHRA_PH */ + gen_helper_shra_ph(v1_t, t0, v1_t); + gen_store_gpr(v1_t, rt); + break; + case 1: + /* SHRA_R_PH */ + gen_helper_shra_r_ph(v1_t, t0, v1_t); + gen_store_gpr(v1_t, rt); + break; + } + break; + case NM_SHLL_S_PH: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd >> 1); + switch (extract32(ctx->opcode, 10, 2)) { + case 0: + /* SHLL_PH */ + gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env); + gen_store_gpr(v1_t, rt); + break; + case 2: + /* SHLL_S_PH */ + gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env); + gen_store_gpr(v1_t, rt); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_SHLL_S_W: + check_dsp(ctx); + tcg_gen_movi_tl(t0, rd); + gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env); + gen_store_gpr(v1_t, rt); + break; + case NM_REPL_PH: + check_dsp(ctx); + { + int16_t imm; + imm =3D sextract32(ctx->opcode, 11, 11); + imm =3D (int16_t)(imm << 6) >> 6; + if (rt !=3D 0) { + tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm)); + } + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + + tcg_temp_free(v2_t); + tcg_temp_free(v1_t); + tcg_temp_free(t0); +} + +static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) +{ + uint16_t insn; + uint32_t op; + int rt, rs, rd; + int offset; + int imm; + + insn =3D translator_lduw(env, ctx->base.pc_next + 2); + ctx->opcode =3D (ctx->opcode << 16) | insn; + + rt =3D extract32(ctx->opcode, 21, 5); + rs =3D extract32(ctx->opcode, 16, 5); + rd =3D extract32(ctx->opcode, 11, 5); + + op =3D extract32(ctx->opcode, 26, 6); + switch (op) { + case NM_P_ADDIU: + if (rt =3D=3D 0) { + /* P.RI */ + switch (extract32(ctx->opcode, 19, 2)) { + case NM_SIGRIE: + default: + gen_reserved_instruction(ctx); + break; + case NM_P_SYSCALL: + if ((extract32(ctx->opcode, 18, 1)) =3D=3D NM_SYSCALL) { + generate_exception_end(ctx, EXCP_SYSCALL); + } else { + gen_reserved_instruction(ctx); + } + break; + case NM_BREAK: + generate_exception_end(ctx, EXCP_BREAK); + break; + case NM_SDBBP: + if (is_uhi(extract32(ctx->opcode, 0, 19))) { + gen_helper_do_semihosting(cpu_env); + } else { + if (ctx->hflags & MIPS_HFLAG_SBRI) { + gen_reserved_instruction(ctx); + } else { + generate_exception_end(ctx, EXCP_DBp); + } + } + break; + } + } else { + /* NM_ADDIU */ + imm =3D extract32(ctx->opcode, 0, 16); + if (rs !=3D 0) { + tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm); + } else { + tcg_gen_movi_tl(cpu_gpr[rt], imm); + } + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); + } + break; + case NM_ADDIUPC: + if (rt !=3D 0) { + offset =3D sextract32(ctx->opcode, 0, 1) << 21 | + extract32(ctx->opcode, 1, 20) << 1; + target_long addr =3D addr_add(ctx, ctx->base.pc_next + 4, offs= et); + tcg_gen_movi_tl(cpu_gpr[rt], addr); + } + break; + case NM_POOL32A: + switch (ctx->opcode & 0x07) { + case NM_POOL32A0: + gen_pool32a0_nanomips_insn(env, ctx); + break; + case NM_POOL32A5: + { + int32_t op1 =3D extract32(ctx->opcode, 3, 7); + gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt); + } + break; + case NM_POOL32A7: + switch (extract32(ctx->opcode, 3, 3)) { + case NM_P_LSX: + gen_p_lsx(ctx, rd, rs, rt); + break; + case NM_LSA: + /* + * In nanoMIPS, the shift field directly encodes the shift + * amount, meaning that the supported shift values are in + * the range 0 to 3 (instead of 1 to 4 in MIPSR6). + */ + gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1); + break; + case NM_EXTW: + gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5)); + break; + case NM_POOL32AXF: + gen_pool32axf_nanomips_insn(env, ctx); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_P_GP_W: + switch (ctx->opcode & 0x03) { + case NM_ADDIUGP_W: + if (rt !=3D 0) { + offset =3D extract32(ctx->opcode, 0, 21); + gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset); + } + break; + case NM_LWGP: + gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2= ); + break; + case NM_SWGP: + gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2= ); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_P48I: + { + insn =3D translator_lduw(env, ctx->base.pc_next + 4); + target_long addr_off =3D extract32(ctx->opcode, 0, 16) | insn = << 16; + switch (extract32(ctx->opcode, 16, 5)) { + case NM_LI48: + check_nms(ctx); + if (rt !=3D 0) { + tcg_gen_movi_tl(cpu_gpr[rt], addr_off); + } + break; + case NM_ADDIU48: + check_nms(ctx); + if (rt !=3D 0) { + tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off); + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); + } + break; + case NM_ADDIUGP48: + check_nms(ctx); + if (rt !=3D 0) { + gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_o= ff); + } + break; + case NM_ADDIUPC48: + check_nms(ctx); + if (rt !=3D 0) { + target_long addr =3D addr_add(ctx, ctx->base.pc_next += 6, + addr_off); + + tcg_gen_movi_tl(cpu_gpr[rt], addr); + } + break; + case NM_LWPC48: + check_nms(ctx); + if (rt !=3D 0) { + TCGv t0; + t0 =3D tcg_temp_new(); + + target_long addr =3D addr_add(ctx, ctx->base.pc_next += 6, + addr_off); + + tcg_gen_movi_tl(t0, addr); + tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_T= ESL); + tcg_temp_free(t0); + } + break; + case NM_SWPC48: + check_nms(ctx); + { + TCGv t0, t1; + t0 =3D tcg_temp_new(); + t1 =3D tcg_temp_new(); + + target_long addr =3D addr_add(ctx, ctx->base.pc_next += 6, + addr_off); + + tcg_gen_movi_tl(t0, addr); + gen_load_gpr(t1, rt); + + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); + + tcg_temp_free(t0); + tcg_temp_free(t1); + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + return 6; + } + case NM_P_U12: + switch (extract32(ctx->opcode, 12, 4)) { + case NM_ORI: + gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, = 12)); + break; + case NM_XORI: + gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0,= 12)); + break; + case NM_ANDI: + gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0,= 12)); + break; + case NM_P_SR: + switch (extract32(ctx->opcode, 20, 1)) { + case NM_PP_SR: + switch (ctx->opcode & 3) { + case NM_SAVE: + gen_save(ctx, rt, extract32(ctx->opcode, 16, 4), + extract32(ctx->opcode, 2, 1), + extract32(ctx->opcode, 3, 9) << 3); + break; + case NM_RESTORE: + case NM_RESTORE_JRC: + gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4), + extract32(ctx->opcode, 2, 1), + extract32(ctx->opcode, 3, 9) << 3); + if ((ctx->opcode & 3) =3D=3D NM_RESTORE_JRC) { + gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0); + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_P_SR_F: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_SLTI: + gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 1= 2)); + break; + case NM_SLTIU: + gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, = 12)); + break; + case NM_SEQI: + { + TCGv t0 =3D tcg_temp_new(); + + imm =3D extract32(ctx->opcode, 0, 12); + gen_load_gpr(t0, rs); + tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm); + gen_store_gpr(t0, rt); + + tcg_temp_free(t0); + } + break; + case NM_ADDIUNEG: + imm =3D (int16_t) extract32(ctx->opcode, 0, 12); + gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm); + break; + case NM_P_SHIFT: + { + int shift =3D extract32(ctx->opcode, 0, 5); + switch (extract32(ctx->opcode, 5, 4)) { + case NM_P_SLL: + if (rt =3D=3D 0 && shift =3D=3D 0) { + /* NOP */ + } else if (rt =3D=3D 0 && shift =3D=3D 3) { + /* EHB - treat as NOP */ + } else if (rt =3D=3D 0 && shift =3D=3D 5) { + /* PAUSE - treat as NOP */ + } else if (rt =3D=3D 0 && shift =3D=3D 6) { + /* SYNC */ + gen_sync(extract32(ctx->opcode, 16, 5)); + } else { + /* SLL */ + gen_shift_imm(ctx, OPC_SLL, rt, rs, + extract32(ctx->opcode, 0, 5)); + } + break; + case NM_SRL: + gen_shift_imm(ctx, OPC_SRL, rt, rs, + extract32(ctx->opcode, 0, 5)); + break; + case NM_SRA: + gen_shift_imm(ctx, OPC_SRA, rt, rs, + extract32(ctx->opcode, 0, 5)); + break; + case NM_ROTR: + gen_shift_imm(ctx, OPC_ROTR, rt, rs, + extract32(ctx->opcode, 0, 5)); + break; + } + } + break; + case NM_P_ROTX: + check_nms(ctx); + if (rt !=3D 0) { + TCGv t0 =3D tcg_temp_new(); + TCGv_i32 shift =3D tcg_const_i32(extract32(ctx->opcode, 0,= 5)); + TCGv_i32 shiftx =3D tcg_const_i32(extract32(ctx->opcode, 7= , 4) + << 1); + TCGv_i32 stripe =3D tcg_const_i32(extract32(ctx->opcode, 6= , 1)); + + gen_load_gpr(t0, rs); + gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe); + tcg_temp_free(t0); + + tcg_temp_free_i32(shift); + tcg_temp_free_i32(shiftx); + tcg_temp_free_i32(stripe); + } + break; + case NM_P_INS: + switch (((ctx->opcode >> 10) & 2) | + (extract32(ctx->opcode, 5, 1))) { + case NM_INS: + check_nms(ctx); + gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0,= 5), + extract32(ctx->opcode, 6, 5)); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_P_EXT: + switch (((ctx->opcode >> 10) & 2) | + (extract32(ctx->opcode, 5, 1))) { + case NM_EXT: + check_nms(ctx); + gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0,= 5), + extract32(ctx->opcode, 6, 5)); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_POOL32F: + gen_pool32f_nanomips_insn(ctx); + break; + case NM_POOL32S: + break; + case NM_P_LUI: + switch (extract32(ctx->opcode, 1, 1)) { + case NM_LUI: + if (rt !=3D 0) { + tcg_gen_movi_tl(cpu_gpr[rt], + sextract32(ctx->opcode, 0, 1) << 31 | + extract32(ctx->opcode, 2, 10) << 21 | + extract32(ctx->opcode, 12, 9) << 12); + } + break; + case NM_ALUIPC: + if (rt !=3D 0) { + offset =3D sextract32(ctx->opcode, 0, 1) << 31 | + extract32(ctx->opcode, 2, 10) << 21 | + extract32(ctx->opcode, 12, 9) << 12; + target_long addr; + addr =3D ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, off= set); + tcg_gen_movi_tl(cpu_gpr[rt], addr); + } + break; + } + break; + case NM_P_GP_BH: + { + uint32_t u =3D extract32(ctx->opcode, 0, 18); + + switch (extract32(ctx->opcode, 18, 3)) { + case NM_LBGP: + gen_ld(ctx, OPC_LB, rt, 28, u); + break; + case NM_SBGP: + gen_st(ctx, OPC_SB, rt, 28, u); + break; + case NM_LBUGP: + gen_ld(ctx, OPC_LBU, rt, 28, u); + break; + case NM_ADDIUGP_B: + if (rt !=3D 0) { + gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u); + } + break; + case NM_P_GP_LH: + u &=3D ~1; + switch (ctx->opcode & 1) { + case NM_LHGP: + gen_ld(ctx, OPC_LH, rt, 28, u); + break; + case NM_LHUGP: + gen_ld(ctx, OPC_LHU, rt, 28, u); + break; + } + break; + case NM_P_GP_SH: + u &=3D ~1; + switch (ctx->opcode & 1) { + case NM_SHGP: + gen_st(ctx, OPC_SH, rt, 28, u); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_P_GP_CP1: + u &=3D ~0x3; + switch (ctx->opcode & 0x3) { + case NM_LWC1GP: + gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u); + break; + case NM_LDC1GP: + gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u); + break; + case NM_SWC1GP: + gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u); + break; + case NM_SDC1GP: + gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u); + break; + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + } + break; + case NM_P_LS_U12: + { + uint32_t u =3D extract32(ctx->opcode, 0, 12); + + switch (extract32(ctx->opcode, 12, 4)) { + case NM_P_PREFU12: + if (rt =3D=3D 31) { + /* SYNCI */ + /* + * Break the TB to be able to sync copied instructions + * immediately. + */ + ctx->base.is_jmp =3D DISAS_STOP; + } else { + /* PREF */ + /* Treat as NOP. */ + } + break; + case NM_LB: + gen_ld(ctx, OPC_LB, rt, rs, u); + break; + case NM_LH: + gen_ld(ctx, OPC_LH, rt, rs, u); + break; + case NM_LW: + gen_ld(ctx, OPC_LW, rt, rs, u); + break; + case NM_LBU: + gen_ld(ctx, OPC_LBU, rt, rs, u); + break; + case NM_LHU: + gen_ld(ctx, OPC_LHU, rt, rs, u); + break; + case NM_SB: + gen_st(ctx, OPC_SB, rt, rs, u); + break; + case NM_SH: + gen_st(ctx, OPC_SH, rt, rs, u); + break; + case NM_SW: + gen_st(ctx, OPC_SW, rt, rs, u); + break; + case NM_LWC1: + gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u); + break; + case NM_LDC1: + gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u); + break; + case NM_SWC1: + gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u); + break; + case NM_SDC1: + gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u); + break; + default: + gen_reserved_instruction(ctx); + break; + } + } + break; + case NM_P_LS_S9: + { + int32_t s =3D (sextract32(ctx->opcode, 15, 1) << 8) | + extract32(ctx->opcode, 0, 8); + + switch (extract32(ctx->opcode, 8, 3)) { + case NM_P_LS_S0: + switch (extract32(ctx->opcode, 11, 4)) { + case NM_LBS9: + gen_ld(ctx, OPC_LB, rt, rs, s); + break; + case NM_LHS9: + gen_ld(ctx, OPC_LH, rt, rs, s); + break; + case NM_LWS9: + gen_ld(ctx, OPC_LW, rt, rs, s); + break; + case NM_LBUS9: + gen_ld(ctx, OPC_LBU, rt, rs, s); + break; + case NM_LHUS9: + gen_ld(ctx, OPC_LHU, rt, rs, s); + break; + case NM_SBS9: + gen_st(ctx, OPC_SB, rt, rs, s); + break; + case NM_SHS9: + gen_st(ctx, OPC_SH, rt, rs, s); + break; + case NM_SWS9: + gen_st(ctx, OPC_SW, rt, rs, s); + break; + case NM_LWC1S9: + gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s); + break; + case NM_LDC1S9: + gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s); + break; + case NM_SWC1S9: + gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s); + break; + case NM_SDC1S9: + gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s); + break; + case NM_P_PREFS9: + if (rt =3D=3D 31) { + /* SYNCI */ + /* + * Break the TB to be able to sync copied instruct= ions + * immediately. + */ + ctx->base.is_jmp =3D DISAS_STOP; + } else { + /* PREF */ + /* Treat as NOP. */ + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_P_LS_S1: + switch (extract32(ctx->opcode, 11, 4)) { + case NM_UALH: + case NM_UASH: + check_nms(ctx); + { + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + + gen_base_offset_addr(ctx, t0, rs, s); + + switch (extract32(ctx->opcode, 11, 4)) { + case NM_UALH: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TE= SW | + MO_UNALN); + gen_store_gpr(t0, rt); + break; + case NM_UASH: + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TE= UW | + MO_UNALN); + break; + } + tcg_temp_free(t0); + tcg_temp_free(t1); + } + break; + case NM_P_LL: + switch (ctx->opcode & 0x03) { + case NM_LL: + gen_ld(ctx, OPC_LL, rt, rs, s); + break; + case NM_LLWP: + check_xnp(ctx); + gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3,= 5)); + break; + } + break; + case NM_P_SC: + switch (ctx->opcode & 0x03) { + case NM_SC: + gen_st_cond(ctx, rt, rs, s, MO_TESL, false); + break; + case NM_SCWP: + check_xnp(ctx); + gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3,= 5), + false); + break; + } + break; + case NM_CACHE: + check_cp0_enabled(ctx); + if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { + gen_cache_operation(ctx, rt, rs, s); + } + break; + } + break; + case NM_P_LS_E0: + switch (extract32(ctx->opcode, 11, 4)) { + case NM_LBE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LBE, rt, rs, s); + break; + case NM_SBE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_st(ctx, OPC_SBE, rt, rs, s); + break; + case NM_LBUE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LBUE, rt, rs, s); + break; + case NM_P_PREFE: + if (rt =3D=3D 31) { + /* case NM_SYNCIE */ + check_eva(ctx); + check_cp0_enabled(ctx); + /* + * Break the TB to be able to sync copied instruct= ions + * immediately. + */ + ctx->base.is_jmp =3D DISAS_STOP; + } else { + /* case NM_PREFE */ + check_eva(ctx); + check_cp0_enabled(ctx); + /* Treat as NOP. */ + } + break; + case NM_LHE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LHE, rt, rs, s); + break; + case NM_SHE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_st(ctx, OPC_SHE, rt, rs, s); + break; + case NM_LHUE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LHUE, rt, rs, s); + break; + case NM_CACHEE: + check_eva(ctx); + check_cp0_enabled(ctx); + check_nms_dl_il_sl_tl_l2c(ctx); + gen_cache_operation(ctx, rt, rs, s); + break; + case NM_LWE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LWE, rt, rs, s); + break; + case NM_SWE: + check_eva(ctx); + check_cp0_enabled(ctx); + gen_st(ctx, OPC_SWE, rt, rs, s); + break; + case NM_P_LLE: + switch (extract32(ctx->opcode, 2, 2)) { + case NM_LLE: + check_xnp(ctx); + check_eva(ctx); + check_cp0_enabled(ctx); + gen_ld(ctx, OPC_LLE, rt, rs, s); + break; + case NM_LLWPE: + check_xnp(ctx); + check_eva(ctx); + check_cp0_enabled(ctx); + gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3,= 5)); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_P_SCE: + switch (extract32(ctx->opcode, 2, 2)) { + case NM_SCE: + check_xnp(ctx); + check_eva(ctx); + check_cp0_enabled(ctx); + gen_st_cond(ctx, rt, rs, s, MO_TESL, true); + break; + case NM_SCWPE: + check_xnp(ctx); + check_eva(ctx); + check_cp0_enabled(ctx); + gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3,= 5), + true); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + } + break; + case NM_P_LS_WM: + case NM_P_LS_UAWM: + check_nms(ctx); + { + int count =3D extract32(ctx->opcode, 12, 3); + int counter =3D 0; + + offset =3D sextract32(ctx->opcode, 15, 1) << 8 | + extract32(ctx->opcode, 0, 8); + TCGv va =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + MemOp memop =3D (extract32(ctx->opcode, 8, 3)) =3D=3D + NM_P_LS_UAWM ? MO_UNALN : 0; + + count =3D (count =3D=3D 0) ? 8 : count; + while (counter !=3D count) { + int this_rt =3D ((rt + counter) & 0x1f) | (rt & 0x= 10); + int this_offset =3D offset + (counter << 2); + + gen_base_offset_addr(ctx, va, rs, this_offset); + + switch (extract32(ctx->opcode, 11, 1)) { + case NM_LWM: + tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx, + memop | MO_TESL); + gen_store_gpr(t1, this_rt); + if ((this_rt =3D=3D rs) && + (counter !=3D (count - 1))) { + /* UNPREDICTABLE */ + } + break; + case NM_SWM: + this_rt =3D (rt =3D=3D 0) ? 0 : this_rt; + gen_load_gpr(t1, this_rt); + tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx, + memop | MO_TEUL); + break; + } + counter++; + } + tcg_temp_free(va); + tcg_temp_free(t1); + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + } + break; + case NM_MOVE_BALC: + check_nms(ctx); + { + TCGv t0 =3D tcg_temp_new(); + int32_t s =3D sextract32(ctx->opcode, 0, 1) << 21 | + extract32(ctx->opcode, 1, 20) << 1; + rd =3D (extract32(ctx->opcode, 24, 1)) =3D=3D 0 ? 4 : 5; + rt =3D decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3= | + extract32(ctx->opcode, 21, 3)); + gen_load_gpr(t0, rt); + tcg_gen_mov_tl(cpu_gpr[rd], t0); + gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s); + tcg_temp_free(t0); + } + break; + case NM_P_BAL: + { + int32_t s =3D sextract32(ctx->opcode, 0, 1) << 25 | + extract32(ctx->opcode, 1, 24) << 1; + + if ((extract32(ctx->opcode, 25, 1)) =3D=3D 0) { + /* BC */ + gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s); + } else { + /* BALC */ + gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s); + } + } + break; + case NM_P_J: + switch (extract32(ctx->opcode, 12, 4)) { + case NM_JALRC: + case NM_JALRC_HB: + gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0); + break; + case NM_P_BALRSC: + gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_P_BR1: + { + int32_t s =3D sextract32(ctx->opcode, 0, 1) << 14 | + extract32(ctx->opcode, 1, 13) << 1; + switch (extract32(ctx->opcode, 14, 2)) { + case NM_BEQC: + check_nms(ctx); + gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s); + break; + case NM_P_BR3A: + s =3D sextract32(ctx->opcode, 0, 1) << 14 | + extract32(ctx->opcode, 1, 13) << 1; + check_cp1_enabled(ctx); + switch (extract32(ctx->opcode, 16, 5)) { + case NM_BC1EQZC: + gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s); + break; + case NM_BC1NEZC: + gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s); + break; + case NM_BPOSGE32C: + check_dsp_r3(ctx); + { + int32_t imm =3D extract32(ctx->opcode, 1, 13) | + extract32(ctx->opcode, 0, 1) << 13; + + gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2, + imm << 1); + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_BGEC: + if (rs =3D=3D rt) { + gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s); + } else { + gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s= ); + } + break; + case NM_BGEUC: + if (rs =3D=3D rt || rt =3D=3D 0) { + gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s); + } else if (rs =3D=3D 0) { + gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s= ); + } else { + gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, = s); + } + break; + } + } + break; + case NM_P_BR2: + { + int32_t s =3D sextract32(ctx->opcode, 0, 1) << 14 | + extract32(ctx->opcode, 1, 13) << 1; + switch (extract32(ctx->opcode, 14, 2)) { + case NM_BNEC: + check_nms(ctx); + gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s); + break; + case NM_BLTC: + if (rs !=3D 0 && rt !=3D 0 && rs =3D=3D rt) { + /* NOP */ + ctx->hflags |=3D MIPS_HFLAG_FBNSLOT; + } else { + gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s= ); + } + break; + case NM_BLTUC: + if (rs =3D=3D 0 || rs =3D=3D rt) { + /* NOP */ + ctx->hflags |=3D MIPS_HFLAG_FBNSLOT; + } else { + gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, = s); + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + } + break; + case NM_P_BRI: + { + int32_t s =3D sextract32(ctx->opcode, 0, 1) << 11 | + extract32(ctx->opcode, 1, 10) << 1; + uint32_t u =3D extract32(ctx->opcode, 11, 7); + + gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3), + rt, u, s); + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + return 4; +} + +static int decode_isa_nanomips(CPUMIPSState *env, DisasContext *ctx) +{ + uint32_t op; + int rt =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode)); + int rs =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); + int rd =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode)); + int offset; + int imm; + + /* make sure instructions are on a halfword boundary */ + if (ctx->base.pc_next & 0x1) { + TCGv tmp =3D tcg_const_tl(ctx->base.pc_next); + tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); + tcg_temp_free(tmp); + generate_exception_end(ctx, EXCP_AdEL); + return 2; + } + + op =3D extract32(ctx->opcode, 10, 6); + switch (op) { + case NM_P16_MV: + rt =3D NANOMIPS_EXTRACT_RD5(ctx->opcode); + if (rt !=3D 0) { + /* MOVE */ + rs =3D NANOMIPS_EXTRACT_RS5(ctx->opcode); + gen_arith(ctx, OPC_ADDU, rt, rs, 0); + } else { + /* P16.RI */ + switch (extract32(ctx->opcode, 3, 2)) { + case NM_P16_SYSCALL: + if (extract32(ctx->opcode, 2, 1) =3D=3D 0) { + generate_exception_end(ctx, EXCP_SYSCALL); + } else { + gen_reserved_instruction(ctx); + } + break; + case NM_BREAK16: + generate_exception_end(ctx, EXCP_BREAK); + break; + case NM_SDBBP16: + if (is_uhi(extract32(ctx->opcode, 0, 3))) { + gen_helper_do_semihosting(cpu_env); + } else { + if (ctx->hflags & MIPS_HFLAG_SBRI) { + gen_reserved_instruction(ctx); + } else { + generate_exception_end(ctx, EXCP_DBp); + } + } + break; + default: + gen_reserved_instruction(ctx); + break; + } + } + break; + case NM_P16_SHIFT: + { + int shift =3D extract32(ctx->opcode, 0, 3); + uint32_t opc =3D 0; + shift =3D (shift =3D=3D 0) ? 8 : shift; + + switch (extract32(ctx->opcode, 3, 1)) { + case NM_SLL16: + opc =3D OPC_SLL; + break; + case NM_SRL16: + opc =3D OPC_SRL; + break; + } + gen_shift_imm(ctx, opc, rt, rs, shift); + } + break; + case NM_P16C: + switch (ctx->opcode & 1) { + case NM_POOL16C_0: + gen_pool16c_nanomips_insn(ctx); + break; + case NM_LWXS16: + gen_ldxs(ctx, rt, rs, rd); + break; + } + break; + case NM_P16_A1: + switch (extract32(ctx->opcode, 6, 1)) { + case NM_ADDIUR1SP: + imm =3D extract32(ctx->opcode, 0, 6) << 2; + gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_P16_A2: + switch (extract32(ctx->opcode, 3, 1)) { + case NM_ADDIUR2: + imm =3D extract32(ctx->opcode, 0, 3) << 2; + gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm); + break; + case NM_P_ADDIURS5: + rt =3D extract32(ctx->opcode, 5, 5); + if (rt !=3D 0) { + /* imm =3D sign_extend(s[3] . s[2:0] , from_nbits =3D 4) */ + imm =3D (sextract32(ctx->opcode, 4, 1) << 3) | + (extract32(ctx->opcode, 0, 3)); + gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm); + } + break; + } + break; + case NM_P16_ADDU: + switch (ctx->opcode & 0x1) { + case NM_ADDU16: + gen_arith(ctx, OPC_ADDU, rd, rs, rt); + break; + case NM_SUBU16: + gen_arith(ctx, OPC_SUBU, rd, rs, rt); + break; + } + break; + case NM_P16_4X4: + rt =3D (extract32(ctx->opcode, 9, 1) << 3) | + extract32(ctx->opcode, 5, 3); + rs =3D (extract32(ctx->opcode, 4, 1) << 3) | + extract32(ctx->opcode, 0, 3); + rt =3D decode_gpr_gpr4(rt); + rs =3D decode_gpr_gpr4(rs); + switch ((extract32(ctx->opcode, 7, 2) & 0x2) | + (extract32(ctx->opcode, 3, 1))) { + case NM_ADDU4X4: + check_nms(ctx); + gen_arith(ctx, OPC_ADDU, rt, rs, rt); + break; + case NM_MUL4X4: + check_nms(ctx); + gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_LI16: + { + int imm =3D extract32(ctx->opcode, 0, 7); + imm =3D (imm =3D=3D 0x7f ? -1 : imm); + if (rt !=3D 0) { + tcg_gen_movi_tl(cpu_gpr[rt], imm); + } + } + break; + case NM_ANDI16: + { + uint32_t u =3D extract32(ctx->opcode, 0, 4); + u =3D (u =3D=3D 12) ? 0xff : + (u =3D=3D 13) ? 0xffff : u; + gen_logic_imm(ctx, OPC_ANDI, rt, rs, u); + } + break; + case NM_P16_LB: + offset =3D extract32(ctx->opcode, 0, 2); + switch (extract32(ctx->opcode, 2, 2)) { + case NM_LB16: + gen_ld(ctx, OPC_LB, rt, rs, offset); + break; + case NM_SB16: + rt =3D decode_gpr_gpr3_src_store( + NANOMIPS_EXTRACT_RT3(ctx->opcode)); + gen_st(ctx, OPC_SB, rt, rs, offset); + break; + case NM_LBU16: + gen_ld(ctx, OPC_LBU, rt, rs, offset); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_P16_LH: + offset =3D extract32(ctx->opcode, 1, 2) << 1; + switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) { + case NM_LH16: + gen_ld(ctx, OPC_LH, rt, rs, offset); + break; + case NM_SH16: + rt =3D decode_gpr_gpr3_src_store( + NANOMIPS_EXTRACT_RT3(ctx->opcode)); + gen_st(ctx, OPC_SH, rt, rs, offset); + break; + case NM_LHU16: + gen_ld(ctx, OPC_LHU, rt, rs, offset); + break; + default: + gen_reserved_instruction(ctx); + break; + } + break; + case NM_LW16: + offset =3D extract32(ctx->opcode, 0, 4) << 2; + gen_ld(ctx, OPC_LW, rt, rs, offset); + break; + case NM_LWSP16: + rt =3D NANOMIPS_EXTRACT_RD5(ctx->opcode); + offset =3D extract32(ctx->opcode, 0, 5) << 2; + gen_ld(ctx, OPC_LW, rt, 29, offset); + break; + case NM_LW4X4: + check_nms(ctx); + rt =3D (extract32(ctx->opcode, 9, 1) << 3) | + extract32(ctx->opcode, 5, 3); + rs =3D (extract32(ctx->opcode, 4, 1) << 3) | + extract32(ctx->opcode, 0, 3); + offset =3D (extract32(ctx->opcode, 3, 1) << 3) | + (extract32(ctx->opcode, 8, 1) << 2); + rt =3D decode_gpr_gpr4(rt); + rs =3D decode_gpr_gpr4(rs); + gen_ld(ctx, OPC_LW, rt, rs, offset); + break; + case NM_SW4X4: + check_nms(ctx); + rt =3D (extract32(ctx->opcode, 9, 1) << 3) | + extract32(ctx->opcode, 5, 3); + rs =3D (extract32(ctx->opcode, 4, 1) << 3) | + extract32(ctx->opcode, 0, 3); + offset =3D (extract32(ctx->opcode, 3, 1) << 3) | + (extract32(ctx->opcode, 8, 1) << 2); + rt =3D decode_gpr_gpr4_zero(rt); + rs =3D decode_gpr_gpr4(rs); + gen_st(ctx, OPC_SW, rt, rs, offset); + break; + case NM_LWGP16: + offset =3D extract32(ctx->opcode, 0, 7) << 2; + gen_ld(ctx, OPC_LW, rt, 28, offset); + break; + case NM_SWSP16: + rt =3D NANOMIPS_EXTRACT_RD5(ctx->opcode); + offset =3D extract32(ctx->opcode, 0, 5) << 2; + gen_st(ctx, OPC_SW, rt, 29, offset); + break; + case NM_SW16: + rt =3D decode_gpr_gpr3_src_store( + NANOMIPS_EXTRACT_RT3(ctx->opcode)); + rs =3D decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode)); + offset =3D extract32(ctx->opcode, 0, 4) << 2; + gen_st(ctx, OPC_SW, rt, rs, offset); + break; + case NM_SWGP16: + rt =3D decode_gpr_gpr3_src_store( + NANOMIPS_EXTRACT_RT3(ctx->opcode)); + offset =3D extract32(ctx->opcode, 0, 7) << 2; + gen_st(ctx, OPC_SW, rt, 28, offset); + break; + case NM_BC16: + gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0, + (sextract32(ctx->opcode, 0, 1) << 10) | + (extract32(ctx->opcode, 1, 9) << 1)); + break; + case NM_BALC16: + gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0, + (sextract32(ctx->opcode, 0, 1) << 10) | + (extract32(ctx->opcode, 1, 9) << 1)); + break; + case NM_BEQZC16: + gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0, + (sextract32(ctx->opcode, 0, 1) << 7) | + (extract32(ctx->opcode, 1, 6) << 1)); + break; + case NM_BNEZC16: + gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0, + (sextract32(ctx->opcode, 0, 1) << 7) | + (extract32(ctx->opcode, 1, 6) << 1)); + break; + case NM_P16_BR: + switch (ctx->opcode & 0xf) { + case 0: + /* P16.JRC */ + switch (extract32(ctx->opcode, 4, 1)) { + case NM_JRC: + gen_compute_branch_nm(ctx, OPC_JR, 2, + extract32(ctx->opcode, 5, 5), 0, 0); + break; + case NM_JALRC16: + gen_compute_branch_nm(ctx, OPC_JALR, 2, + extract32(ctx->opcode, 5, 5), 31, 0); + break; + } + break; + default: + { + /* P16.BRI */ + uint32_t opc =3D extract32(ctx->opcode, 4, 3) < + extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OP= C_BNE; + gen_compute_branch_nm(ctx, opc, 2, rs, rt, + extract32(ctx->opcode, 0, 4) << 1); + } + break; + } + break; + case NM_P16_SR: + { + int count =3D extract32(ctx->opcode, 0, 4); + int u =3D extract32(ctx->opcode, 4, 4) << 4; + + rt =3D 30 + extract32(ctx->opcode, 9, 1); + switch (extract32(ctx->opcode, 8, 1)) { + case NM_SAVE16: + gen_save(ctx, rt, count, 0, u); + break; + case NM_RESTORE_JRC16: + gen_restore(ctx, rt, count, 0, u); + gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0); + break; + } + } + break; + case NM_MOVEP: + case NM_MOVEPREV: + check_nms(ctx); + { + static const int gpr2reg1[] =3D {4, 5, 6, 7}; + static const int gpr2reg2[] =3D {5, 6, 7, 8}; + int re; + int rd2 =3D extract32(ctx->opcode, 3, 1) << 1 | + extract32(ctx->opcode, 8, 1); + int r1 =3D gpr2reg1[rd2]; + int r2 =3D gpr2reg2[rd2]; + int r3 =3D extract32(ctx->opcode, 4, 1) << 3 | + extract32(ctx->opcode, 0, 3); + int r4 =3D extract32(ctx->opcode, 9, 1) << 3 | + extract32(ctx->opcode, 5, 3); + TCGv t0 =3D tcg_temp_new(); + TCGv t1 =3D tcg_temp_new(); + if (op =3D=3D NM_MOVEP) { + rd =3D r1; + re =3D r2; + rs =3D decode_gpr_gpr4_zero(r3); + rt =3D decode_gpr_gpr4_zero(r4); + } else { + rd =3D decode_gpr_gpr4(r3); + re =3D decode_gpr_gpr4(r4); + rs =3D r1; + rt =3D r2; + } + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_mov_tl(cpu_gpr[rd], t0); + tcg_gen_mov_tl(cpu_gpr[re], t1); + tcg_temp_free(t0); + tcg_temp_free(t1); + } + break; + default: + return decode_nanomips_32_48_opc(env, ctx); + } + + return 2; +} diff --git a/MAINTAINERS b/MAINTAINERS index cfbf7ef79bc..c663dfe4d76 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -246,6 +246,7 @@ K: ^Subject:.*(?i)mips MIPS TCG CPUs (nanoMIPS ISA) S: Orphan F: disas/nanomips.* +F: target/mips/tcg/*nanomips* =20 NiosII TCG CPUs M: Chris Wulff --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.221.41 as permitted sender) client-ip=209.85.221.41; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-f41.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.41 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625232993; cv=none; d=zohomail.com; s=zohoarc; b=Q5OeCOR/QGW63tfrY2udIxqngLipaEToaMoamJeWgQI1sfDc2Nk6Z6k+2I/zNyfJwlzKKUY0N730Gxpjd0PyX0cYrL6bn6bcWGscdzqew0lWbQSY7U3iNPsj8CGp4mQRsZ+E3wd82ZgPorWuEYYKGhAIfVjQvLQZdy1kqbwKjRc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625232993; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=7A/j/FYlYSZh3luNW3Um8CEXczwC9yclCtiX6mQrEkk=; b=AuPOZweD0GwnP36RapOjQe6Hnq3X3XMss3gxPgcpLZysmwkmiBBa8gHzX2EGyV73+NRZqRVOI29998+rYYnjlrQIJ5jLs2K9Ag0+FtfjidMbX/xAkbygFLGMS0F8J57Ly+8Hk93xvJSfmbfUU2MlFjw4gBBUUdVhuI1qpR5j0hI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.41 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) by mx.zohomail.com with SMTPS id 1625232993867540.8778638703869; Fri, 2 Jul 2021 06:36:33 -0700 (PDT) Received: by mail-wr1-f41.google.com with SMTP id f14so12143097wrs.6 for ; Fri, 02 Jul 2021 06:36:33 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id t11sm3398734wrz.7.2021.07.02.06.36.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:36:31 -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=7A/j/FYlYSZh3luNW3Um8CEXczwC9yclCtiX6mQrEkk=; b=gJI0detEXXLTl/G77/lBfTmHYiZ/XWAZ42aKTylylRnSLpOQUxkbRB856WuF/GxkIs vmtb+sOg5N2RnfUIsOypf2qG1VFs/fN+xAjwnnclgNUmWCnKDdmMlW+mWPaqTfkAhwSx IVoXqwzC0io8DkwqGyM4J/nFPTMMt24f5yC/qsUizrhLBHTLMArdRQY2d2fe1N0KL7vr qa6BtZpGubKqS/KS4dknOZy6S5RumlfTLuPwOh7s/kHFKmxvbMOqcz0Hn0sBRgtIlKUS ciLCAkucBLXmdZoEb9Pn23Lt6c9t51qN098XqdGJjU/c0/q/8aZLDFE6XhHN+vGhqcr9 O03Q== 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=7A/j/FYlYSZh3luNW3Um8CEXczwC9yclCtiX6mQrEkk=; b=g0mJs/77mS+UArK9CDLXwgbtwgj9UdXVascpvfCDGbTc5IDYST5Id0YHe19VL0E6rB LsJ5iz+QZdT1V8Y0RbcSjHeA4IjVijtw3AcVhaWbExR6mD1oYLL2joE/6LApMgwUM5Qc JoyoBlXsHG3mNma98PpXYKMs65nQpZ/+pIzhTOqgCqjznsVtWz873xJ8R63mAi93QWLP 73wobue/aN76c7YTCIaUpjToCwxiqzTZnJd9HWhv4CQr2EdvPug1v9KaV7fRoTCBBS2x ihtIwMieILG/2hybuOhIcVz8JJLnEW435HYY6Z7AT+HR2VWqkL4p0qhMjr576aRyRQaI At2g== X-Gm-Message-State: AOAM530aaihCIpoVw/OEd+gA6tUTpIaihpc+4UrOxVX3PWf3Jepbuodn XRtdK4oAyW/bj89F39+TCM8= X-Google-Smtp-Source: ABdhPJwS8nEeA1Ovh/xQ9nm1AetIMf/pLFXH7rZQfY6uwbpsF/gsoBepbpNuxQmiF1lh/APxyDOcFg== X-Received: by 2002:adf:fb51:: with SMTP id c17mr6191200wrs.106.1625232991992; Fri, 02 Jul 2021 06:36:31 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PULL 05/18] hw/pci-host/bonito: Trace PCI config accesses smaller than 32-bit Date: Fri, 2 Jul 2021 15:35:44 +0200 Message-Id: <20210702133557.60317-6-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625232994227100001 Per the datasheet section "5.7.5. Accessing PCI configuration space" the address must be 32-bit aligned. Trace eventual accesses not aligned to 32-bit. Signed-off-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20210624202747.1433023-3-f4bug@amsat.org> --- hw/pci-host/bonito.c | 8 ++++++++ hw/pci-host/trace-events | 3 +++ 2 files changed, 11 insertions(+) diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index afb3d1f81d5..751fdcec689 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -52,6 +52,7 @@ #include "hw/misc/unimp.h" #include "hw/registerfields.h" #include "qom/object.h" +#include "trace.h" =20 /* #define DEBUG_BONITO */ =20 @@ -185,6 +186,7 @@ FIELD(BONGENCFG, PCIQUEUE, 12, 1) #define BONITO_PCICONF_IDSEL_OFFSET 11 #define BONITO_PCICONF_FUN_MASK 0x700 /* [10:8] */ #define BONITO_PCICONF_FUN_OFFSET 8 +#define BONITO_PCICONF_REG_MASK_DS (~3) /* Per datasheet */ #define BONITO_PCICONF_REG_MASK 0xFC #define BONITO_PCICONF_REG_OFFSET 0 =20 @@ -495,6 +497,9 @@ static void bonito_spciconf_write(void *opaque, hwaddr = addr, uint64_t val, if (pciaddr =3D=3D 0xffffffff) { return; } + if (addr & ~BONITO_PCICONF_REG_MASK_DS) { + trace_bonito_spciconf_small_access(addr, size); + } =20 /* set the pci address in s->config_reg */ phb->config_reg =3D (pciaddr) | (1u << 31); @@ -521,6 +526,9 @@ static uint64_t bonito_spciconf_read(void *opaque, hwad= dr addr, unsigned size) if (pciaddr =3D=3D 0xffffffff) { return MAKE_64BIT_MASK(0, size * 8); } + if (addr & ~BONITO_PCICONF_REG_MASK_DS) { + trace_bonito_spciconf_small_access(addr, size); + } =20 /* set the pci address in s->config_reg */ phb->config_reg =3D (pciaddr) | (1u << 31); diff --git a/hw/pci-host/trace-events b/hw/pci-host/trace-events index f4b3a50cb0b..630e9fcc5e7 100644 --- a/hw/pci-host/trace-events +++ b/hw/pci-host/trace-events @@ -1,5 +1,8 @@ # See docs/devel/tracing.rst for syntax documentation. =20 +# bonito.c +bonito_spciconf_small_access(uint64_t addr, unsigned size) "PCI config add= ress is smaller then 32-bit, addr: 0x%"PRIx64", size: %u" + # grackle.c grackle_set_irq(int irq_num, int level) "set_irq num %d level %d" =20 --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.221.41 as permitted sender) client-ip=209.85.221.41; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-f41.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.41 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625232999; cv=none; d=zohomail.com; s=zohoarc; b=PliNc22JI9L0DlMmnc7tUqpSXmSDoZ8pWfRO5SKYlln7xLEKQ53y2e45sYqIrFqB6VgcLksrHCqaCxNTEGS5+ANk0vKflPfThOR0+GDfBgCh4dnWyVPVWkiCQESyWHM0Ywn+IS7N8UkJW6zCn6CPY6KbUjJB+7h/+znK92GIgW8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625232999; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=6SjNTNzzmhwEPVZj6BseAgSSsGle0gDtK79Bw/VO9BM=; b=g2b+VvlXvLxZOhY3bd9eFYJdb5N0uhy2WVLGDdbZ8hzp2+1o4YMJjyIHJrB5JLMrtRaziso91lTWbzpXXCmy/jnW7ktnEw2h9ZkD3VXLJwN5zqTIxQleq2OnL64OtLo1r2Gm5O6rZR/Ib7cIZ3Qjmqf4vMUCWN476ruGnA8Be5Q= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.41 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) by mx.zohomail.com with SMTPS id 1625232999618789.748135229081; Fri, 2 Jul 2021 06:36:39 -0700 (PDT) Received: by mail-wr1-f41.google.com with SMTP id i8so12584335wrc.0 for ; Fri, 02 Jul 2021 06:36:39 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id 12sm13818781wme.28.2021.07.02.06.36.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:36:37 -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=6SjNTNzzmhwEPVZj6BseAgSSsGle0gDtK79Bw/VO9BM=; b=qLcaIT6ez1LLeRUhcFFHNmBAGy3IgyPTHV5AHk/0THkgLGh5tMP8+1ao0gLAX/eXFN /J6WvTwnAuUILnQdS2OZXZQFsKKDaFPyuel7NGsJOosphFgD+r5pfhLeb6tPiV4Z3dnB j/d8ljvI451K0BNeWMjO9xNilLVcUxmPdYAF7vvxxaWckwfSLZbqXpowiudJUUookw1J gIjkuNvstpZrPa1GjlEr0zZMt45Jdr1TgL/G6MpveGNLbMggRE6CMFCm7fEWOTdl1Dst 7I6d55UZBeAufXY1cnA5VgHgo6kIhoRlN/cDN9HitP7P3BQeR+7u2uO4YrF4g2OEnnN9 2BxA== 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=6SjNTNzzmhwEPVZj6BseAgSSsGle0gDtK79Bw/VO9BM=; b=fI0apWHfeZo7T+UbduUu86acRWnO1/ZznbUEYvt1BB4kP5u/cxuLpR1XE7DinfP3FI TWFQrB1vEeVxFy0ZwNJ+1KIza0rUSn7mfj5im8SVSkSXi9sNdz0ThByk0wlCLsirbg6I 4U9lBADtIEbngxdYERjhKMAF/83Q7qrhJy169NsaW/2ZWmv+4Slqy88401QY1xIVxarL arGYemm/ZTLwYICQlugjDjJmAh5mUeK5+aI2LtgUkn13bEXHuL+oUIn8w7Jw138fD5p4 wSOOiXcF66XKEMJgO+4D4Ub/q38PF4tV54UoHsknVPsWT4Wdy485qfxY/+vZmqpeW1Mh INTA== X-Gm-Message-State: AOAM531qRE1CwzvksrJLQ0lD0XpGaylUSHXYB1HUAC8pxm1v2iNrWBhI PhbynOCeeP9FJpkCz918Hvk= X-Google-Smtp-Source: ABdhPJw6d8jE9xJfuhvSOPUKaDYl1J0qM8JABqzy0N4k6eRpKKcvrK09h5dtF+tA60i5ORokrv+cDA== X-Received: by 2002:a5d:4f05:: with SMTP id c5mr5927418wru.362.1625232997916; Fri, 02 Jul 2021 06:36:37 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , BALATON Zoltan , Jiaxun Yang Subject: [PULL 06/18] hw/pci-host/bonito: Allow PCI config accesses smaller than 32-bit Date: Fri, 2 Jul 2021 15:35:45 +0200 Message-Id: <20210702133557.60317-7-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233000864100001 When running the official PMON firmware for the Fuloong 2E, we see 8-bit and 16-bit accesses to PCI config space: $ qemu-system-mips64el -M fuloong2e -bios pmon_2e.bin \ -trace -trace bonito\* -trace pci_cfg\* pci_cfg_write vt82c686b-pm 05:4 @0x90 <- 0xeee1 bonito_spciconf_small_access PCI config address is smaller then 32-bit, a= ddr: 0x4d2, size: 2 pci_cfg_write vt82c686b-pm 05:4 @0xd2 <- 0x1 pci_cfg_write vt82c686b-pm 05:4 @0x4 <- 0x1 pci_cfg_write vt82c686b-isa 05:0 @0x4 <- 0x7 bonito_spciconf_small_access PCI config address is smaller then 32-bit, a= ddr: 0x81, size: 1 pci_cfg_read vt82c686b-isa 05:0 @0x81 -> 0x0 bonito_spciconf_small_access PCI config address is smaller then 32-bit, a= ddr: 0x81, size: 1 pci_cfg_write vt82c686b-isa 05:0 @0x81 <- 0x80 bonito_spciconf_small_access PCI config address is smaller then 32-bit, a= ddr: 0x83, size: 1 pci_cfg_write vt82c686b-isa 05:0 @0x83 <- 0x89 bonito_spciconf_small_access PCI config address is smaller then 32-bit, a= ddr: 0x85, size: 1 pci_cfg_write vt82c686b-isa 05:0 @0x85 <- 0x3 bonito_spciconf_small_access PCI config address is smaller then 32-bit, a= ddr: 0x5a, size: 1 pci_cfg_write vt82c686b-isa 05:0 @0x5a <- 0x7 bonito_spciconf_small_access PCI config address is smaller then 32-bit, a= ddr: 0x85, size: 1 pci_cfg_write vt82c686b-isa 05:0 @0x85 <- 0x1 Also this is what the Linux kernel does since it supports the Bonito north bridge: https://elixir.bootlin.com/linux/v2.6.15/source/arch/mips/pci/ops-bonito64.= c#L85 So it seems safe to assume the datasheet is incomplete or outdated regarding the address constraints. This problem was exposed by commit 911629e6d3773a8adeab48b ("vt82c686: Fix SMBus IO base and configuration registers"). Reported-by: BALATON Zoltan Suggested-by: Jiaxun Yang Signed-off-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20210624202747.1433023-4-f4bug@amsat.org> Tested-by: BALATON Zoltan --- hw/pci-host/bonito.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index 751fdcec689..a57e81e3a97 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -187,7 +187,7 @@ FIELD(BONGENCFG, PCIQUEUE, 12, 1) #define BONITO_PCICONF_FUN_MASK 0x700 /* [10:8] */ #define BONITO_PCICONF_FUN_OFFSET 8 #define BONITO_PCICONF_REG_MASK_DS (~3) /* Per datasheet */ -#define BONITO_PCICONF_REG_MASK 0xFC +#define BONITO_PCICONF_REG_MASK_HW 0xff /* As seen running PMO= N */ #define BONITO_PCICONF_REG_OFFSET 0 =20 =20 @@ -466,7 +466,7 @@ static uint32_t bonito_sbridge_pciaddr(void *opaque, hw= addr addr) BONITO_PCICONF_IDSEL_OFFSET; devno =3D ctz32(idsel); funno =3D (cfgaddr & BONITO_PCICONF_FUN_MASK) >> BONITO_PCICONF_FUN_OF= FSET; - regno =3D (cfgaddr & BONITO_PCICONF_REG_MASK) >> BONITO_PCICONF_REG_OF= FSET; + regno =3D (cfgaddr & BONITO_PCICONF_REG_MASK_HW) >> BONITO_PCICONF_REG= _OFFSET; =20 if (idsel =3D=3D 0) { error_report("error in bonito pci config address 0x" TARGET_FMT_plx --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 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=1625233004; cv=none; d=zohomail.com; s=zohoarc; b=LMjzfp+XH4Wri6vXUsZgwBoKMG3YhkKO6J4Vtp9O+PigOxI4nsHtu9CTxyVHocYa2fJnkwDStjwFY+02BZss0fBgjy+a+BdxvN9StQFlWGIxszmf6Wp9oWpijQKOZeJ2t7Pu07KLguP0SUOoiut3Ba7fA0zBGEm9aI8rqEmisoY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233004; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=BdMlioqEm9E1wpS8AcjxouwS36MURC9LLrc7wkl7cFg=; b=g8d/DY+hA0yhCCPSkK5OWGKI66esUu2d5zuqoI8XFhURqtJ00x8qSzjK2/yKnpqow0Kqpyc7/opfgybv8HXbU6Tx0n+09bA5d4XRSOr2yH7JEVBqSGUIS14CD1bo6IlmDPTj6VeJq+sVfl8Sgg3+4UTMJWA0SoltMlJx0xY27KU= 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 162523300459123.336594122268934; Fri, 2 Jul 2021 06:36:44 -0700 (PDT) Received: by mail-wr1-f51.google.com with SMTP id i94so12522344wri.4 for ; Fri, 02 Jul 2021 06:36:44 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id y20sm12436214wmi.31.2021.07.02.06.36.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:36:42 -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=BdMlioqEm9E1wpS8AcjxouwS36MURC9LLrc7wkl7cFg=; b=Hn5bncr1Yy/a6wC3znuBznBdEnu5+Zw/DHeB0EvgfWv9hMSdx//p1wZyVZn83eEb7H Lt6y9gme/wmxqyS8Iraekg1LqjkZrRBhBLWJQr6TzNDdXK7uz29sM4WvWVDwIW7jOvAJ hjnqBOpnl8XTlfAi8ItPRVZWoU1iITjgCCmtpcSLVpEwaFS7yKumDVkw6KbTunXvIM3F EaCgaMax1FL1WtH0eZsvqIDe/s+rGfaByHYb2n8nIh9zSyu98dcWklFMpJaE1KRM51Xi UT8kUH47lXttYjzwLga2EtVCwzE4ovLQWbIRGk5KtMq4XmcBPtT2no4bKoZikeTcWTXI Jq1Q== 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=BdMlioqEm9E1wpS8AcjxouwS36MURC9LLrc7wkl7cFg=; b=p3Zco+yZuBUovs1IsEaOgK3l9sXgNW5TSdc+7X8JXjp0wdfSevfQSslZCe5kecHI+i lNxhKwKOd+zSdnwxYcOoxPoUyjrhVP5Xt0aY44LMoak3eyryBD2AcBc7lvqcL1YV9IWO Mxl+qfBzzM1As+ZrWsiEcwMmuVGP/CxVaIf+CwvmlyV0WvciQD80oPz7/YlmDVofAcuH gFP0HGJyMYIq+OD1b21aSB1mknhRombrNeEbkiHxXstl31WO3XtowD6BcskdkwmvCeyx jRB5Ao9xPkZUfRVcxeycQbJyWo5nx78EsBlCBdBJl/vsnvUrIPfohPm804WvBp9FVbg6 yGuA== X-Gm-Message-State: AOAM533EK8pTB2Y4ixCcZRjkBeyUGfVCTjVAAZ+BF6xgF0PoR4Awf0G9 vCrwfVrkNcU6PpPjR2XoZRk= X-Google-Smtp-Source: ABdhPJyIOu/wp4EKqCmpmGJGt+SudUyihsDI2H+sfWnF3Cm4Fn6SAebiKHnda5UW+Dc57i/VJKTv+g== X-Received: by 2002:a5d:6846:: with SMTP id o6mr5825427wrw.89.1625233002810; Fri, 02 Jul 2021 06:36:42 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Wainer dos Santos Moschetta Subject: [PULL 07/18] tests/acceptance: Test Linux on the Fuloong 2E machine Date: Fri, 2 Jul 2021 15:35:46 +0200 Message-Id: <20210702133557.60317-8-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233005309100001 Test the kernel from Lemote rescue image: http://dev.lemote.com/files/resource/download/rescue/rescue-yl Once downloaded, set the RESCUE_YL_PATH environment variable to point to the downloaded image and test as: $ RESCUE_YL_PATH=3D~/images/fuloong2e/rescue-yl \ AVOCADO_ALLOW_UNTRUSTED_CODE=3D1 \ avocado --show=3Dapp,console run tests/acceptance/machine_mips_fuloong2= e.py Fetching asset from tests/acceptance/machine_mips_fuloong2e.py:MipsFuloon= g2e.test_linux_kernel_isa_serial (1/1) tests/acceptance/machine_mips_fuloong2e.py:MipsFuloong2e.test_linu= x_kernel_isa_serial: console: Linux version 2.6.27.7lemote (root@debian) (gcc version 4.1.3 20= 080623 (prerelease) (Debian 4.1.2-23)) #6 Fri Dec 12 00:11:25 CST 2008 console: busclock=3D33000000, cpuclock=3D-2145008360,memsize=3D256,highme= msize=3D0 console: console [early0] enabled console: CPU revision is: 00006302 (ICT Loongson-2) PASS (0.16 s) JOB TIME : 0.51 s Signed-off-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Wainer dos Santos Moschetta Message-Id: <20210624202747.1433023-5-f4bug@amsat.org> --- MAINTAINERS | 1 + tests/acceptance/machine_mips_fuloong2e.py | 42 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/acceptance/machine_mips_fuloong2e.py diff --git a/MAINTAINERS b/MAINTAINERS index c663dfe4d76..cb8f3ea2c2e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1178,6 +1178,7 @@ F: hw/isa/vt82c686.c F: hw/pci-host/bonito.c F: hw/usb/vt82c686-uhci-pci.c F: include/hw/isa/vt82c686.h +F: tests/acceptance/machine_mips_fuloong2e.py =20 Loongson-3 virtual platforms M: Huacai Chen diff --git a/tests/acceptance/machine_mips_fuloong2e.py b/tests/acceptance/= machine_mips_fuloong2e.py new file mode 100644 index 00000000000..0ac285e2af1 --- /dev/null +++ b/tests/acceptance/machine_mips_fuloong2e.py @@ -0,0 +1,42 @@ +# Functional tests for the Lemote Fuloong-2E machine. +# +# Copyright (c) 2019 Philippe Mathieu-Daud=C3=A9 +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from avocado import skipUnless +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern + +class MipsFuloong2e(Test): + + timeout =3D 60 + + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code= ') + @skipUnless(os.getenv('RESCUE_YL_PATH'), 'RESCUE_YL_PATH not available= ') + def test_linux_kernel_isa_serial(self): + """ + :avocado: tags=3Darch:mips64el + :avocado: tags=3Dmachine:fuloong2e + :avocado: tags=3Dendian:little + :avocado: tags=3Ddevice:bonito64 + :avocado: tags=3Ddevice:via686b + """ + # Recovery system for the Yeeloong laptop + # (enough to test the fuloong2e southbridge, accessing its ISA bus) + # http://dev.lemote.com/files/resource/download/rescue/rescue-yl + kernel_hash =3D 'ec4d1bd89a8439c41033ca63db60160cc6d6f09a' + kernel_path =3D self.fetch_asset('file://' + os.getenv('RESCUE_YL_= PATH'), + asset_hash=3Dkernel_hash) + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path) + self.vm.launch() + wait_for_console_pattern(self, 'Linux version 2.6.27.7lemote') + cpu_revision =3D 'CPU revision is: 00006302 (ICT Loongson-2)' + wait_for_console_pattern(self, cpu_revision) --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.128.54 as permitted sender) client-ip=209.85.128.54; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-f54.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.54 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625233009; cv=none; d=zohomail.com; s=zohoarc; b=C4qoIk1797bWq8WTcqxcnBnIH4c0voJxh4zV04FnKIYst2mnvcLC9OOTfCH46W4FLzNSg72N4MSeW45yVTdXgJjkp39T1YqeKUkHdtVt2Jn9Uvs3Sh7gKjN1ux1AYppIeJ5gU4Ryi0W5dfjy/0YA2pqN9wHTG7rlNNBAYB+Zq+Q= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233009; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=UOJ2AWq2wxlaeERjjMTMns7W7OqhadIfD9DbevBL6vY=; b=KwCKk8CUViudxBoWSsNOMdiroFef2ThzlcK9g9MWQQEhHjchvXfHMTL/tHiP24hHzaAxvh2XnWafC6gB8zLmSeoi5+yWybxaPEZQ/R3AYFOAdrJ5ejwbtgc1AN2nfKkDd9hTYMveypgmQ9oKn0GQSSTtJxiPn2iD2vNjoVm7nYk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.54 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) by mx.zohomail.com with SMTPS id 1625233009504979.6683624292854; Fri, 2 Jul 2021 06:36:49 -0700 (PDT) Received: by mail-wm1-f54.google.com with SMTP id q18-20020a1ce9120000b02901f259f3a250so6409294wmc.2 for ; Fri, 02 Jul 2021 06:36:48 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id z6sm3203990wrh.67.2021.07.02.06.36.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:36:47 -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=UOJ2AWq2wxlaeERjjMTMns7W7OqhadIfD9DbevBL6vY=; b=ZwNVl21NM8+vaDgEv9+dcEyK16tS/Xa80+qWTAVIDYTzaEQDGoQLLRYHUvMlTAo4PR X0coVEGw5niRrBhhf/VY+qfTODurMqUyMi2vd6il7NjlMA+DPJuhbbCYakPX2ZcvPaU0 JcOdoI7jK+42ilZ20gr17hHe2zfvpp7a5jx5vryAolNvy23awje5IPRJOo6vP1q9K4an BxX+Mu6iKk0uC42Q7tz9+GRiE5pGt3TPf8S3EN53eHdzwmoKbXs2VZnmcSo5zqfUuBGh lud1x7VRExQm7tCGrxvd6n3JIRK3Wvx+1A8XDnVSDN5vys/ddBBGkSB1TynI8dNKnuAo OPPQ== 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=UOJ2AWq2wxlaeERjjMTMns7W7OqhadIfD9DbevBL6vY=; b=FZKVpR4zZHprcPBDQhDDQAHxFaFah5VSK8EQfiBgqy1G23mDJgpaZgQKuIDQ6iYn0V GetwutzUasANkRsQ8GqEtqGXgINkLsXpFnR268ebtJ2wGvL6rOtTqMwz/t7BCdu2cKWQ 9briEjk/wehgQeNqKDVXTGuAfEFE0JWipG+5FvUoCWUJgQt9fIqqhLgE1JS2Bpclpl06 NpRJjIgKQw5yD9P5hUNOlU8Nt+kTOgCtsVZ/ZWUqbOSAZ9VXhN1kU9DFwr9H/LnA2cFW venQQBPFrdlGO2NjhHqbjNFepzKnL/IC8bB+9XH39+/jhuTanon+GeuJi6sLvh82EheS RAaA== X-Gm-Message-State: AOAM532q9bY3XwfaBKS+ToFX59N9tfE6lkR33hC28IMwWN6VciTOIguy 6QwBSmvyhoh6pLmKp8kBdrk= X-Google-Smtp-Source: ABdhPJyrkJpQrH5Ie0670mbo2ZKPOlJkrIOcEGS8vU0jF1v86O0336FBlmEmR4ov98MWw7xtib5Zzg== X-Received: by 2002:a1c:7515:: with SMTP id o21mr16840389wmc.65.1625233007796; Fri, 02 Jul 2021 06:36:47 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PULL 08/18] g364fb: use RAM memory region for framebuffer Date: Fri, 2 Jul 2021 15:35:47 +0200 Message-Id: <20210702133557.60317-9-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233011754100001 From: Mark Cave-Ayland Since the migration stream is already broken, we can use this opportunity to change the framebuffer so that it is migrated as a RAM memory region rather than as an array of bytes. In particular this helps the output of the analyze-migration.py tool which no longer contains a huge array representing the framebuffer contents. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20210625163554.14879-2-mark.cave-ayland@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- hw/display/g364fb.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index 8f1725432cd..87effbf2b0f 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -22,6 +22,7 @@ #include "hw/hw.h" #include "hw/irq.h" #include "hw/qdev-properties.h" +#include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/module.h" #include "ui/console.h" @@ -33,7 +34,6 @@ =20 typedef struct G364State { /* hardware */ - uint8_t *vram; uint32_t vram_size; qemu_irq irq; MemoryRegion mem_vram; @@ -125,7 +125,7 @@ static void g364fb_draw_graphic8(G364State *s) xcursor =3D ycursor =3D -65; } =20 - vram =3D s->vram + s->top_of_screen; + vram =3D memory_region_get_ram_ptr(&s->mem_vram) + s->top_of_screen; /* XXX: out of range in vram? */ data_display =3D dd =3D surface_data(surface); snap =3D memory_region_snapshot_and_clear_dirty(&s->mem_vram, 0, s->vr= am_size, @@ -274,6 +274,8 @@ static inline void g364fb_invalidate_display(void *opaq= ue) =20 static void g364fb_reset(G364State *s) { + uint8_t *vram =3D memory_region_get_ram_ptr(&s->mem_vram); + qemu_irq_lower(s->irq); =20 memset(s->color_palette, 0, sizeof(s->color_palette)); @@ -283,7 +285,7 @@ static void g364fb_reset(G364State *s) s->ctla =3D 0; s->top_of_screen =3D 0; s->width =3D s->height =3D 0; - memset(s->vram, 0, s->vram_size); + memset(vram, 0, s->vram_size); g364fb_invalidate_display(s); } =20 @@ -450,11 +452,10 @@ static int g364fb_post_load(void *opaque, int version= _id) =20 static const VMStateDescription vmstate_g364fb =3D { .name =3D "g364fb", - .version_id =3D 1, - .minimum_version_id =3D 1, + .version_id =3D 2, + .minimum_version_id =3D 2, .post_load =3D g364fb_post_load, .fields =3D (VMStateField[]) { - VMSTATE_VBUFFER_UINT32(vram, G364State, 1, NULL, vram_size), VMSTATE_BUFFER_UNSAFE(color_palette, G364State, 0, 256 * 3), VMSTATE_BUFFER_UNSAFE(cursor_palette, G364State, 0, 9), VMSTATE_UINT16_ARRAY(cursor, G364State, 512), @@ -474,15 +475,12 @@ static const GraphicHwOps g364fb_ops =3D { =20 static void g364fb_init(DeviceState *dev, G364State *s) { - s->vram =3D g_malloc0(s->vram_size); - s->con =3D graphic_console_init(dev, 0, &g364fb_ops, s); =20 memory_region_init_io(&s->mem_ctrl, OBJECT(dev), &g364fb_ctrl_ops, s, "ctrl", 0x180000); - memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram", - s->vram_size, s->vram); - vmstate_register_ram(&s->mem_vram, dev); + memory_region_init_ram(&s->mem_vram, NULL, "g364fb.vram", s->vram_size, + &error_fatal); memory_region_set_log(&s->mem_vram, true, DIRTY_MEMORY_VGA); } =20 --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.128.50 as permitted sender) client-ip=209.85.128.50; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-f50.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.50 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625233014; cv=none; d=zohomail.com; s=zohoarc; b=U0faeivk9qgJJUzQj/6oQIi4cHYGW15WeFatRJJfU+dp6jMBhFKxIf3Ssm8MrkjBsd08laXISm0yowOcc+ureGxaUuk24bLc4bNVrDLIDzg9Ze6H3z+DPV3fs/tsEuQDI/4cMLi3PLO/LqJ3V8fH3ehUBITLKoz3NUz5FIgneHU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233014; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=XwdyHylrd/DY/3JN/AT1x4i76a7V8lVv7L0SE4yhb+8=; b=X3d+NnKCsC8ZappKFqIq6rwADH4LD6ypXytIHRe4PEZO6eYnO7WiW/NdDs6mOxpUt1QZGl9gE/ZM8Fj33Gey++YM2VLBGvSS85Casw1y0rDUypcvO4mt1FFnMrS13DaC3uyZnKBc4bvUKAtupdXzzdotH5Rge9MZvF7H5H4uQAM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.50 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) by mx.zohomail.com with SMTPS id 1625233014255710.9650027158951; Fri, 2 Jul 2021 06:36:54 -0700 (PDT) Received: by mail-wm1-f50.google.com with SMTP id a5-20020a7bc1c50000b02901e3bbe0939bso6434723wmj.0 for ; Fri, 02 Jul 2021 06:36:53 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id r16sm3912571wrx.63.2021.07.02.06.36.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:36:52 -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=XwdyHylrd/DY/3JN/AT1x4i76a7V8lVv7L0SE4yhb+8=; b=jl0o0fTbk8q3CAt3kGKAB9Lj9peuWAf3NZwq1Me7vOqkOqCOiStrBKAf2O9c4J3TMT NNfpHuFlzE7SPxFdLRxl+3wwnELXmabRM5k4tFmmSyS+i+mdrWuaoaI3e+/6mFyziqHL N6eX3VAKaFId3QNBjMEShvPART/ckOO9W1n4hpGGqeUN23wqAYtj61ppiR6cbhVqUcFh K8NZcBCLmXMsYaBTV5MTcnpkF3XEgW6alWfgeztUEGTcdKdu+gUPIhMnL8yTLdyievNG 8feJsb+it9KO0aZnOBCEnFSYfqBJ4lVUFNOFcuaZeBdXxYxCDhgKHBkAyK9gaUIz/mVr 0v2w== 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=XwdyHylrd/DY/3JN/AT1x4i76a7V8lVv7L0SE4yhb+8=; b=iX1PJmQK+qTkQ+nSlOu3qWH8GOaXkg+b+7BjL+UYVGCHkO20mcRbI2fg+JXjOB/d8a lV2Pe3/krVskMzeV1riQBkSKMpPdkkEgoqiQ/tbKnL8tje6PLMUFNBdLPSgNM6s8zd9Z aIvhOTgG3f5Az8I3hB5I1gk+OrD6daq2x8xAtmyPyWmu/pCjK93CJWlyXKOn2ZhRCL39 oGaet6Tp/0S7YcvVqSRisapwDznRLZ0wdFobw27jobFqrc7lLHgEuXQUioZ2IMY7WRcn s9Xmd8ha9GY+0CzA5pgGNh8iReJlYYgcHW+1o0dJzUb0IKBmGKaYQZ2uiqOG10hN7PzT CK0w== X-Gm-Message-State: AOAM5328t4jyBQ4Fv/nDGJZpp622M1FRa09f2n1cr9UNqHbNI2sua77M M/vAaUywN1Hst3hKmoQmElo= X-Google-Smtp-Source: ABdhPJysDHPTWOwBXvPfMpqRnbPOiI97Z8Vbsvf3BMYDzA402TkjIFW8qN12ZPf5RgjZOshZhSISmQ== X-Received: by 2002:a05:600c:c4:: with SMTP id u4mr5641411wmm.10.1625233012619; Fri, 02 Jul 2021 06:36:52 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PULL 09/18] g364fb: add VMStateDescription for G364SysBusState Date: Fri, 2 Jul 2021 15:35:48 +0200 Message-Id: <20210702133557.60317-10-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233016264100001 From: Mark Cave-Ayland Currently when QEMU attempts to migrate the MIPS magnum machine it crashes = due to a mistake in the g364fb VMStateDescription configuration which expects a G364SysBusState and not a G364State. Resolve the issue by adding a new VMStateDescription for G364SysBusState and embedding the existing vmstate_g364fb VMStateDescription inside it using VMSTATE_STRUCT. Signed-off-by: Mark Cave-Ayland Fixes: 97a3f6ffbba ("g364fb: convert to qdev") Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20210625163554.14879-3-mark.cave-ayland@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- hw/display/g364fb.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index 87effbf2b0f..caca86d7738 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -517,6 +517,16 @@ static Property g364fb_sysbus_properties[] =3D { DEFINE_PROP_END_OF_LIST(), }; =20 +static const VMStateDescription vmstate_g364fb_sysbus =3D { + .name =3D "g364fb-sysbus", + .version_id =3D 2, + .minimum_version_id =3D 2, + .fields =3D (VMStateField[]) { + VMSTATE_STRUCT(g364, G364SysBusState, 2, vmstate_g364fb, G364State= ), + VMSTATE_END_OF_LIST() + } +}; + static void g364fb_sysbus_class_init(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); @@ -525,7 +535,7 @@ static void g364fb_sysbus_class_init(ObjectClass *klass= , void *data) set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); dc->desc =3D "G364 framebuffer"; dc->reset =3D g364fb_sysbus_reset; - dc->vmsd =3D &vmstate_g364fb; + dc->vmsd =3D &vmstate_g364fb_sysbus; device_class_set_props(dc, g364fb_sysbus_properties); } =20 --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.221.43 as permitted sender) client-ip=209.85.221.43; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-f43.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.43 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625233019; cv=none; d=zohomail.com; s=zohoarc; b=MIKA09fiAu8QYOrSXHh13XSB95A3GObQXNjUUpsyQlw2tcZ4RmXE7JD1/mBbCgtjluFO9B9scV+vxZr1WKu3nTS5LTxrHEqjeX653sU2Ft573uqOoB/f1YBhEyor4lfj5Hn0E2SU1h+LgVmR0EyXam9nl/to5WaEllKSuV7DeeM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233019; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=G063yAbshkplc+JBOrHG+Ax7yPLtkUG8hisGeshfJgs=; b=ENauO7lULUDcftw8/RLoQTYZD31PKCs7WW5PXF3ngpsJv4/N3EvARas+caPQVqb4ifF32aDP+QLkuR1/zvdulRIu3l8AlCR+9f0qULquOmY0RoY+pc5qbJuLeTyyIDpqmJUX40rWdWtcaPt1cm1qGrMDtDQAFs1Dj8VvL3IjGTg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.43 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) by mx.zohomail.com with SMTPS id 1625233019269673.5783541793074; Fri, 2 Jul 2021 06:36:59 -0700 (PDT) Received: by mail-wr1-f43.google.com with SMTP id u8so12488485wrq.8 for ; Fri, 02 Jul 2021 06:36:58 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id d12sm3387976wri.77.2021.07.02.06.36.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:36:57 -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=G063yAbshkplc+JBOrHG+Ax7yPLtkUG8hisGeshfJgs=; b=rVYnxLJvj+CRV+aLRw2XbY13b2IHV76ePZzyEsxpP1KAQVNr3Z58Is3Vi+eeSCIDiX CAX+9RaX3S7Jxfe0QMx3pJxV4L5rbueiGUCAcs7H+YCdqUE+MYKCwtO0W5CGILWG86e4 O+fQtvpkMrRaJ1kePxipnOaEWaGYOWGj5OUNlREBgmDYon/dyHCdhNuIRD2PMReuFjol SZZwYYTa2zKnDh7XsQyoXh2agXED2ZJ3iG+J87bXqwtJNFf5DxQSsEpF6M0HdRwTk0Z7 6MF+N7ylTy56gyklWVJypJtDIQqNY6+oAK5ZcMpTw7ZAuXj+d9rM3bVy/jk7nuE237dh zJkA== 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=G063yAbshkplc+JBOrHG+Ax7yPLtkUG8hisGeshfJgs=; b=YPcedTsXEiE6LNLneAm3Xhs69W14VZIuDXlS+VVpi4UaZZlTH4Eo4sXmcwaZ2TNdVv zouJEJlvzeJbj2ePgO8olOSsbqm/h4QgWZfSNKb0AEv28puk2d4zJhpN5tRFYjsc0+01 +1bp0ASg7PsVdMGYFLsvwUxjmM5DSKA0+0YCKOknK5ZpwkwtFsSnno5YQKX12Kxc1sWE YN7InQOuPiQi8Yhi5lb9qhjmucTS9jsUbVgq7lfTu82fZtSezzXz72pGe1OYjhW3IFPI CDMhYxuBzczYW95pb5lgyZ2d/67cUTHRAxoBS53HKhqEsgLu24EHWvwi6VAOd0laBSNX Bnaw== X-Gm-Message-State: AOAM5331u0yTeI/NQMIHCJtnbtRz9NH3DI8ouHySkJk4wiYvHCU5i4Fo 0Y7hWnmufNu3cb7kTTybtNo= X-Google-Smtp-Source: ABdhPJzPwFqXMJjKM0+/eaADA4cqC+lT+inZOiK7mxeQgViv88zx/sVHOXgNMys0UYCGe/t38PQwXQ== X-Received: by 2002:adf:f68f:: with SMTP id v15mr5998955wrp.291.1625233017494; Fri, 02 Jul 2021 06:36:57 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Finn Thain Subject: [PULL 10/18] dp8393x: checkpatch fixes Date: Fri, 2 Jul 2021 15:35:49 +0200 Message-Id: <20210702133557.60317-11-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233021361100001 From: Mark Cave-Ayland Also fix a simple comment typo of "constrainst" to "constraints". Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daud=C3=A9 Tested-by: Finn Thain Message-Id: <20210625065401.30170-2-mark.cave-ayland@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- hw/net/dp8393x.c | 231 +++++++++++++++++++++++++---------------------- 1 file changed, 122 insertions(+), 109 deletions(-) diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index 533a8304d0b..56af08f0fe5 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -29,14 +29,14 @@ #include #include "qom/object.h" =20 -//#define DEBUG_SONIC +/* #define DEBUG_SONIC */ =20 #define SONIC_PROM_SIZE 0x1000 =20 #ifdef DEBUG_SONIC #define DPRINTF(fmt, ...) \ do { printf("sonic: " fmt , ## __VA_ARGS__); } while (0) -static const char* reg_names[] =3D { +static const char *reg_names[] =3D { "CR", "DCR", "RCR", "TCR", "IMR", "ISR", "UTDA", "CTDA", "TPS", "TFC", "TSA0", "TSA1", "TFS", "URDA", "CRDA", "CRBA0", "CRBA1", "RBWC0", "RBWC1", "EOBC", "URRA", "RSA", "REA", "RRP", @@ -185,7 +185,8 @@ struct dp8393xState { AddressSpace as; }; =20 -/* Accessor functions for values which are formed by +/* + * Accessor functions for values which are formed by * concatenating two 16 bit device registers. By putting these * in their own functions with a uint32_t return type we avoid the * pitfall of implicit sign extension where ((x << 16) | y) is a @@ -350,8 +351,7 @@ static void dp8393x_do_read_rra(dp8393xState *s) } =20 /* Warn the host if CRBA now has the last available resource */ - if (s->regs[SONIC_RRP] =3D=3D s->regs[SONIC_RWP]) - { + if (s->regs[SONIC_RRP] =3D=3D s->regs[SONIC_RWP]) { s->regs[SONIC_ISR] |=3D SONIC_ISR_RBE; dp8393x_update_irq(s); } @@ -364,7 +364,8 @@ static void dp8393x_do_software_reset(dp8393xState *s) { timer_del(s->watchdog); =20 - s->regs[SONIC_CR] &=3D ~(SONIC_CR_LCAM | SONIC_CR_RRRA | SONIC_CR_TXP = | SONIC_CR_HTX); + s->regs[SONIC_CR] &=3D ~(SONIC_CR_LCAM | SONIC_CR_RRRA | SONIC_CR_TXP | + SONIC_CR_HTX); s->regs[SONIC_CR] |=3D SONIC_CR_RST | SONIC_CR_RXDIS; } =20 @@ -490,8 +491,10 @@ static void dp8393x_do_transmit_packets(dp8393xState *= s) =20 /* Handle Ethernet checksum */ if (!(s->regs[SONIC_TCR] & SONIC_TCR_CRCI)) { - /* Don't append FCS there, to look like slirp packets - * which don't have one */ + /* + * Don't append FCS there, to look like slirp packets + * which don't have one + */ } else { /* Remove existing FCS */ tx_len -=3D 4; @@ -558,26 +561,34 @@ static void dp8393x_do_command(dp8393xState *s, uint1= 6_t command) =20 s->regs[SONIC_CR] |=3D (command & SONIC_CR_MASK); =20 - if (command & SONIC_CR_HTX) + if (command & SONIC_CR_HTX) { dp8393x_do_halt_transmission(s); - if (command & SONIC_CR_TXP) + } + if (command & SONIC_CR_TXP) { dp8393x_do_transmit_packets(s); - if (command & SONIC_CR_RXDIS) + } + if (command & SONIC_CR_RXDIS) { dp8393x_do_receiver_disable(s); - if (command & SONIC_CR_RXEN) + } + if (command & SONIC_CR_RXEN) { dp8393x_do_receiver_enable(s); - if (command & SONIC_CR_STP) + } + if (command & SONIC_CR_STP) { dp8393x_do_stop_timer(s); - if (command & SONIC_CR_ST) + } + if (command & SONIC_CR_ST) { dp8393x_do_start_timer(s); - if (command & SONIC_CR_RST) + } + if (command & SONIC_CR_RST) { dp8393x_do_software_reset(s); + } if (command & SONIC_CR_RRRA) { dp8393x_do_read_rra(s); s->regs[SONIC_CR] &=3D ~SONIC_CR_RRRA; } - if (command & SONIC_CR_LCAM) + if (command & SONIC_CR_LCAM) { dp8393x_do_load_cam(s); + } } =20 static uint64_t dp8393x_read(void *opaque, hwaddr addr, unsigned int size) @@ -587,24 +598,24 @@ static uint64_t dp8393x_read(void *opaque, hwaddr add= r, unsigned int size) uint16_t val =3D 0; =20 switch (reg) { - /* Update data before reading it */ - case SONIC_WT0: - case SONIC_WT1: - dp8393x_update_wt_regs(s); - val =3D s->regs[reg]; - break; - /* Accept read to some registers only when in reset mode */ - case SONIC_CAP2: - case SONIC_CAP1: - case SONIC_CAP0: - if (s->regs[SONIC_CR] & SONIC_CR_RST) { - val =3D s->cam[s->regs[SONIC_CEP] & 0xf][2* (SONIC_CAP0 - = reg) + 1] << 8; - val |=3D s->cam[s->regs[SONIC_CEP] & 0xf][2* (SONIC_CAP0 -= reg)]; - } - break; - /* All other registers have no special contrainst */ - default: - val =3D s->regs[reg]; + /* Update data before reading it */ + case SONIC_WT0: + case SONIC_WT1: + dp8393x_update_wt_regs(s); + val =3D s->regs[reg]; + break; + /* Accept read to some registers only when in reset mode */ + case SONIC_CAP2: + case SONIC_CAP1: + case SONIC_CAP0: + if (s->regs[SONIC_CR] & SONIC_CR_RST) { + val =3D s->cam[s->regs[SONIC_CEP] & 0xf][2 * (SONIC_CAP0 - reg= ) + 1] << 8; + val |=3D s->cam[s->regs[SONIC_CEP] & 0xf][2 * (SONIC_CAP0 - re= g)]; + } + break; + /* All other registers have no special contraints */ + default: + val =3D s->regs[reg]; } =20 DPRINTF("read 0x%04x from reg %s\n", val, reg_names[reg]); @@ -622,75 +633,75 @@ static void dp8393x_write(void *opaque, hwaddr addr, = uint64_t data, DPRINTF("write 0x%04x to reg %s\n", (uint16_t)val, reg_names[reg]); =20 switch (reg) { - /* Command register */ - case SONIC_CR: - dp8393x_do_command(s, val); - break; - /* Prevent write to read-only registers */ - case SONIC_CAP2: - case SONIC_CAP1: - case SONIC_CAP0: - case SONIC_SR: - case SONIC_MDT: - DPRINTF("writing to reg %d invalid\n", reg); - break; - /* Accept write to some registers only when in reset mode */ - case SONIC_DCR: - if (s->regs[SONIC_CR] & SONIC_CR_RST) { - s->regs[reg] =3D val & 0xbfff; - } else { - DPRINTF("writing to DCR invalid\n"); - } - break; - case SONIC_DCR2: - if (s->regs[SONIC_CR] & SONIC_CR_RST) { - s->regs[reg] =3D val & 0xf017; - } else { - DPRINTF("writing to DCR2 invalid\n"); - } - break; - /* 12 lower bytes are Read Only */ - case SONIC_TCR: - s->regs[reg] =3D val & 0xf000; - break; - /* 9 lower bytes are Read Only */ - case SONIC_RCR: - s->regs[reg] =3D val & 0xffe0; - break; - /* Ignore most significant bit */ - case SONIC_IMR: - s->regs[reg] =3D val & 0x7fff; - dp8393x_update_irq(s); - break; - /* Clear bits by writing 1 to them */ - case SONIC_ISR: - val &=3D s->regs[reg]; - s->regs[reg] &=3D ~val; - if (val & SONIC_ISR_RBE) { - dp8393x_do_read_rra(s); - } - dp8393x_update_irq(s); - break; - /* The guest is required to store aligned pointers here */ - case SONIC_RSA: - case SONIC_REA: - case SONIC_RRP: - case SONIC_RWP: - if (s->regs[SONIC_DCR] & SONIC_DCR_DW) { - s->regs[reg] =3D val & 0xfffc; - } else { - s->regs[reg] =3D val & 0xfffe; - } - break; - /* Invert written value for some registers */ - case SONIC_CRCT: - case SONIC_FAET: - case SONIC_MPT: - s->regs[reg] =3D val ^ 0xffff; - break; - /* All other registers have no special contrainst */ - default: - s->regs[reg] =3D val; + /* Command register */ + case SONIC_CR: + dp8393x_do_command(s, val); + break; + /* Prevent write to read-only registers */ + case SONIC_CAP2: + case SONIC_CAP1: + case SONIC_CAP0: + case SONIC_SR: + case SONIC_MDT: + DPRINTF("writing to reg %d invalid\n", reg); + break; + /* Accept write to some registers only when in reset mode */ + case SONIC_DCR: + if (s->regs[SONIC_CR] & SONIC_CR_RST) { + s->regs[reg] =3D val & 0xbfff; + } else { + DPRINTF("writing to DCR invalid\n"); + } + break; + case SONIC_DCR2: + if (s->regs[SONIC_CR] & SONIC_CR_RST) { + s->regs[reg] =3D val & 0xf017; + } else { + DPRINTF("writing to DCR2 invalid\n"); + } + break; + /* 12 lower bytes are Read Only */ + case SONIC_TCR: + s->regs[reg] =3D val & 0xf000; + break; + /* 9 lower bytes are Read Only */ + case SONIC_RCR: + s->regs[reg] =3D val & 0xffe0; + break; + /* Ignore most significant bit */ + case SONIC_IMR: + s->regs[reg] =3D val & 0x7fff; + dp8393x_update_irq(s); + break; + /* Clear bits by writing 1 to them */ + case SONIC_ISR: + val &=3D s->regs[reg]; + s->regs[reg] &=3D ~val; + if (val & SONIC_ISR_RBE) { + dp8393x_do_read_rra(s); + } + dp8393x_update_irq(s); + break; + /* The guest is required to store aligned pointers here */ + case SONIC_RSA: + case SONIC_REA: + case SONIC_RRP: + case SONIC_RWP: + if (s->regs[SONIC_DCR] & SONIC_DCR_DW) { + s->regs[reg] =3D val & 0xfffc; + } else { + s->regs[reg] =3D val & 0xfffe; + } + break; + /* Invert written value for some registers */ + case SONIC_CRCT: + case SONIC_FAET: + case SONIC_MPT: + s->regs[reg] =3D val ^ 0xffff; + break; + /* All other registers have no special contrainst */ + default: + s->regs[reg] =3D val; } =20 if (reg =3D=3D SONIC_WT0 || reg =3D=3D SONIC_WT1) { @@ -747,17 +758,18 @@ static int dp8393x_receive_filter(dp8393xState *s, co= nst uint8_t * buf, } =20 /* Check broadcast */ - if ((s->regs[SONIC_RCR] & SONIC_RCR_BRD) && !memcmp(buf, bcast, sizeof= (bcast))) { + if ((s->regs[SONIC_RCR] & SONIC_RCR_BRD) && + !memcmp(buf, bcast, sizeof(bcast))) { return SONIC_RCR_BC; } =20 /* Check CAM */ for (i =3D 0; i < 16; i++) { if (s->regs[SONIC_CE] & (1 << i)) { - /* Entry enabled */ - if (!memcmp(buf, s->cam[i], sizeof(s->cam[i]))) { - return 0; - } + /* Entry enabled */ + if (!memcmp(buf, s->cam[i], sizeof(s->cam[i]))) { + return 0; + } } } =20 @@ -938,7 +950,8 @@ static void dp8393x_reset(DeviceState *dev) s->regs[SONIC_SR] =3D 0x0004; /* only revision recognized by Linux/mip= s */ s->regs[SONIC_CR] =3D SONIC_CR_RST | SONIC_CR_STP | SONIC_CR_RXDIS; s->regs[SONIC_DCR] &=3D ~(SONIC_DCR_EXBUS | SONIC_DCR_LBR); - s->regs[SONIC_RCR] &=3D ~(SONIC_RCR_LB0 | SONIC_RCR_LB1 | SONIC_RCR_BR= D | SONIC_RCR_RNT); + s->regs[SONIC_RCR] &=3D ~(SONIC_RCR_LB0 | SONIC_RCR_LB1 | SONIC_RCR_BR= D | + SONIC_RCR_RNT); s->regs[SONIC_TCR] |=3D SONIC_TCR_NCRS | SONIC_TCR_PTX; s->regs[SONIC_TCR] &=3D ~SONIC_TCR_BCM; s->regs[SONIC_IMR] =3D 0; --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.221.54 as permitted sender) client-ip=209.85.221.54; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-f54.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.54 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625233024; cv=none; d=zohomail.com; s=zohoarc; b=R6+Q/siiDHsAo9lTtPb0PQTkWUr/PFW+qOPWid6yunhpJr4yw40o9GjEf+Tnx7wgNNYo2Da6SaZwhpuwjJYThQxVb0xqvxy5k1qxGwbA+wQftJKaqpypJPgRHlqt6ot4++1d5TB16spljJHtvk9r2TUwkToxH6PeaYNZIRf/9Qo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233024; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=FiQP2Kda3TCgkNjkAt/LnGohajmVGYrbWL9QRpFB8YM=; b=djDifv0n9gwVKP8YKWd53jaoNZExtMTRpouLEY7Glh9NMFEgJVFvCaf5BMZ3zRZu/a7kf/inRVyrN9+QJ0jb6AkjMvXrpA3HoIB5GCTJMtHqbVQmV+/N8BO2bfH1cFkiSfOPp8v6UOA7X8nZlWwxrkhBlY6m5RzgGtNmIHo/Qhw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.54 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.54]) by mx.zohomail.com with SMTPS id 1625233024357164.71762792406446; Fri, 2 Jul 2021 06:37:04 -0700 (PDT) Received: by mail-wr1-f54.google.com with SMTP id i8so12585798wrc.0 for ; Fri, 02 Jul 2021 06:37:03 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id f2sm3335952wrq.69.2021.07.02.06.37.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:37:01 -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=FiQP2Kda3TCgkNjkAt/LnGohajmVGYrbWL9QRpFB8YM=; b=o955vt+5XKqJ7yUAL6VO0AjVyNnq3PA0QyohtmWSWRYNiB3CVERSuHyjGuwxlhn7mA Yfdw4EkDHKfJknN9l4FW8W+3Nhca5aNhZihieAB2GLdUjMda2zQ34q70bXO5rjhi7E1M /zbVvRGthkSfoSw9pCA4kGLYu9aHXEk4l9oZ8d4pR/V4gQ90vxeNqgBKdYPnq9mh9ACO ACRn0x1mlutlLHjZ43mkfb3HGpXWnEFOvyC75nqWsMbqzSZVXEPaCOd4+z+I69UcQPSf Yml/zHwzynzPPFmtSkcZlIALUasHNSl1G1SgQz5m0lzEg4udE4SGMwfuOA3Xz1ZeNH49 7fuA== 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=FiQP2Kda3TCgkNjkAt/LnGohajmVGYrbWL9QRpFB8YM=; b=BwOaV+qJh1AGNogK3WKAM0nRcylstyAcf12JqnJwH8wJ8NTWWhXjmr2/Vxx6VRxl4n ecIF/PHGGyZBHcuxJZuhz4/Q4MFxtNl3TN4nJ2FedMBswHFs9YFnT6Jp6v44q0ijFN1Q 6uD8GzLLf8TNbWHF/BiiPdMyD/quFHbd5grRmkYa9aByHS8XcX2gHFh87CAB9ODR1Rr5 M4aD2JSGe3Y2PILQjA2tkqiQX8yns4L6ypWc+RC3MDYkBsbZyVQw87CJ85op0mddkt7p 5vl4Q+gOm+WAYcupR2B6AxLluOtqPZQ0es8KuvjAS0lI07H38zM7gO00v2FjW0PNaAoM QnQw== X-Gm-Message-State: AOAM533hveL9f3iwEVZhFpYa2ZGIECV5EaUW3wRLlB64UjiMso69gNdF pl5ayWDCqSYwPKwBMz3SIzw= X-Google-Smtp-Source: ABdhPJwrJ2/QhYeF11Vcdi88+iSfNAsc1v1yn2FAmAcpaUjhcYKBoAU38Z1s/8Z10Lui+Mtk79u1pA== X-Received: by 2002:a5d:58f3:: with SMTP id f19mr5842718wrd.15.1625233022477; Fri, 02 Jul 2021 06:37:02 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Finn Thain Subject: [PULL 11/18] dp8393x: convert to trace-events Date: Fri, 2 Jul 2021 15:35:50 +0200 Message-Id: <20210702133557.60317-12-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233025800100001 From: Mark Cave-Ayland Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daud=C3=A9 Tested-by: Finn Thain Message-Id: <20210625065401.30170-3-mark.cave-ayland@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- hw/net/dp8393x.c | 55 +++++++++++++++++---------------------------- hw/net/trace-events | 17 ++++++++++++++ 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index 56af08f0fe5..ea5b22f6802 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -28,14 +28,10 @@ #include "qemu/timer.h" #include #include "qom/object.h" - -/* #define DEBUG_SONIC */ +#include "trace.h" =20 #define SONIC_PROM_SIZE 0x1000 =20 -#ifdef DEBUG_SONIC -#define DPRINTF(fmt, ...) \ -do { printf("sonic: " fmt , ## __VA_ARGS__); } while (0) static const char *reg_names[] =3D { "CR", "DCR", "RCR", "TCR", "IMR", "ISR", "UTDA", "CTDA", "TPS", "TFC", "TSA0", "TSA1", "TFS", "URDA", "CRDA", "CRBA0", @@ -45,12 +41,6 @@ static const char *reg_names[] =3D { "SR", "WT0", "WT1", "RSC", "CRCT", "FAET", "MPT", "MDT", "0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37", "0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "DCR2" }; -#else -#define DPRINTF(fmt, ...) do {} while (0) -#endif - -#define SONIC_ERROR(fmt, ...) \ -do { printf("sonic ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (= 0) =20 #define SONIC_CR 0x00 #define SONIC_DCR 0x01 @@ -161,9 +151,7 @@ struct dp8393xState { bool big_endian; bool last_rba_is_full; qemu_irq irq; -#ifdef DEBUG_SONIC int irq_level; -#endif QEMUTimer *watchdog; int64_t wt_last_update; NICConf conf; @@ -270,16 +258,14 @@ static void dp8393x_update_irq(dp8393xState *s) { int level =3D (s->regs[SONIC_IMR] & s->regs[SONIC_ISR]) ? 1 : 0; =20 -#ifdef DEBUG_SONIC if (level !=3D s->irq_level) { s->irq_level =3D level; if (level) { - DPRINTF("raise irq, isr is 0x%04x\n", s->regs[SONIC_ISR]); + trace_dp8393x_raise_irq(s->regs[SONIC_ISR]); } else { - DPRINTF("lower irq\n"); + trace_dp8393x_lower_irq(); } } -#endif =20 qemu_set_irq(s->irq, level); } @@ -302,9 +288,9 @@ static void dp8393x_do_load_cam(dp8393xState *s) s->cam[index][3] =3D dp8393x_get(s, width, 2) >> 8; s->cam[index][4] =3D dp8393x_get(s, width, 3) & 0xff; s->cam[index][5] =3D dp8393x_get(s, width, 3) >> 8; - DPRINTF("load cam[%d] with %02x%02x%02x%02x%02x%02x\n", index, - s->cam[index][0], s->cam[index][1], s->cam[index][2], - s->cam[index][3], s->cam[index][4], s->cam[index][5]); + trace_dp8393x_load_cam(index, s->cam[index][0], s->cam[index][1], + s->cam[index][2], s->cam[index][3], + s->cam[index][4], s->cam[index][5]); /* Move to next entry */ s->regs[SONIC_CDC]--; s->regs[SONIC_CDP] +=3D size; @@ -315,7 +301,7 @@ static void dp8393x_do_load_cam(dp8393xState *s) address_space_read(&s->as, dp8393x_cdp(s), MEMTXATTRS_UNSPECIFIED, s->data, size); s->regs[SONIC_CE] =3D dp8393x_get(s, width, 0); - DPRINTF("load cam done. cam enable mask 0x%04x\n", s->regs[SONIC_CE]); + trace_dp8393x_load_cam_done(s->regs[SONIC_CE]); =20 /* Done */ s->regs[SONIC_CR] &=3D ~SONIC_CR_LCAM; @@ -338,9 +324,8 @@ static void dp8393x_do_read_rra(dp8393xState *s) s->regs[SONIC_CRBA1] =3D dp8393x_get(s, width, 1); s->regs[SONIC_RBWC0] =3D dp8393x_get(s, width, 2); s->regs[SONIC_RBWC1] =3D dp8393x_get(s, width, 3); - DPRINTF("CRBA0/1: 0x%04x/0x%04x, RBWC0/1: 0x%04x/0x%04x\n", - s->regs[SONIC_CRBA0], s->regs[SONIC_CRBA1], - s->regs[SONIC_RBWC0], s->regs[SONIC_RBWC1]); + trace_dp8393x_read_rra_regs(s->regs[SONIC_CRBA0], s->regs[SONIC_CRBA1], + s->regs[SONIC_RBWC0], s->regs[SONIC_RBWC1]= ); =20 /* Go to next entry */ s->regs[SONIC_RRP] +=3D size; @@ -444,7 +429,7 @@ static void dp8393x_do_transmit_packets(dp8393xState *s) /* Read memory */ size =3D sizeof(uint16_t) * 6 * width; s->regs[SONIC_TTDA] =3D s->regs[SONIC_CTDA]; - DPRINTF("Transmit packet at %08x\n", dp8393x_ttda(s)); + trace_dp8393x_transmit_packet(dp8393x_ttda(s)); address_space_read(&s->as, dp8393x_ttda(s) + sizeof(uint16_t) * wi= dth, MEMTXATTRS_UNSPECIFIED, s->data, size); tx_len =3D 0; @@ -499,7 +484,7 @@ static void dp8393x_do_transmit_packets(dp8393xState *s) /* Remove existing FCS */ tx_len -=3D 4; if (tx_len < 0) { - SONIC_ERROR("tx_len is %d\n", tx_len); + trace_dp8393x_transmit_txlen_error(tx_len); break; } } @@ -618,7 +603,7 @@ static uint64_t dp8393x_read(void *opaque, hwaddr addr,= unsigned int size) val =3D s->regs[reg]; } =20 - DPRINTF("read 0x%04x from reg %s\n", val, reg_names[reg]); + trace_dp8393x_read(reg, reg_names[reg], val, size); =20 return s->big_endian ? val << 16 : val; } @@ -630,7 +615,7 @@ static void dp8393x_write(void *opaque, hwaddr addr, ui= nt64_t data, int reg =3D addr >> s->it_shift; uint32_t val =3D s->big_endian ? data >> 16 : data; =20 - DPRINTF("write 0x%04x to reg %s\n", (uint16_t)val, reg_names[reg]); + trace_dp8393x_write(reg, reg_names[reg], val, size); =20 switch (reg) { /* Command register */ @@ -643,21 +628,21 @@ static void dp8393x_write(void *opaque, hwaddr addr, = uint64_t data, case SONIC_CAP0: case SONIC_SR: case SONIC_MDT: - DPRINTF("writing to reg %d invalid\n", reg); + trace_dp8393x_write_invalid(reg); break; /* Accept write to some registers only when in reset mode */ case SONIC_DCR: if (s->regs[SONIC_CR] & SONIC_CR_RST) { s->regs[reg] =3D val & 0xbfff; } else { - DPRINTF("writing to DCR invalid\n"); + trace_dp8393x_write_invalid_dcr("DCR"); } break; case SONIC_DCR2: if (s->regs[SONIC_CR] & SONIC_CR_RST) { s->regs[reg] =3D val & 0xf017; } else { - DPRINTF("writing to DCR2 invalid\n"); + trace_dp8393x_write_invalid_dcr("DCR2"); } break; /* 12 lower bytes are Read Only */ @@ -803,7 +788,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, cons= t uint8_t * buf, } =20 if (padded_len > dp8393x_rbwc(s) * 2) { - DPRINTF("oversize packet, pkt_size is %d\n", pkt_size); + trace_dp8393x_receive_oversize(pkt_size); s->regs[SONIC_ISR] |=3D SONIC_ISR_RBAE; dp8393x_update_irq(s); s->regs[SONIC_RCR] |=3D SONIC_RCR_LPKT; @@ -812,7 +797,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, cons= t uint8_t * buf, =20 packet_type =3D dp8393x_receive_filter(s, buf, pkt_size); if (packet_type < 0) { - DPRINTF("packet not for netcard\n"); + trace_dp8393x_receive_not_netcard(); return -1; } =20 @@ -850,7 +835,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, cons= t uint8_t * buf, checksum =3D cpu_to_le32(crc32(0, buf, pkt_size)); =20 /* Put packet into RBA */ - DPRINTF("Receive packet at %08x\n", dp8393x_crba(s)); + trace_dp8393x_receive_packet(dp8393x_crba(s)); address =3D dp8393x_crba(s); address_space_write(&s->as, address, MEMTXATTRS_UNSPECIFIED, buf, pkt_size); @@ -888,7 +873,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, cons= t uint8_t * buf, } =20 /* Write status to memory */ - DPRINTF("Write status at %08x\n", dp8393x_crda(s)); + trace_dp8393x_receive_write_status(dp8393x_crda(s)); dp8393x_put(s, width, 0, s->regs[SONIC_RCR]); /* status */ dp8393x_put(s, width, 1, rx_len); /* byte count */ dp8393x_put(s, width, 2, s->regs[SONIC_TRBA0]); /* pkt_ptr0 */ diff --git a/hw/net/trace-events b/hw/net/trace-events index c28b91ee1aa..643338f6109 100644 --- a/hw/net/trace-events +++ b/hw/net/trace-events @@ -436,3 +436,20 @@ npcm7xx_emc_received_packet(uint32_t len) "Received %u= byte packet" npcm7xx_emc_rx_done(uint32_t crxdsa) "RX done, CRXDSA=3D0x%x" npcm7xx_emc_reg_read(int emc_num, uint32_t result, const char *name, int r= egno) "emc%d: 0x%x =3D reg[%s/%d]" npcm7xx_emc_reg_write(int emc_num, const char *name, int regno, uint32_t v= alue) "emc%d: reg[%s/%d] =3D 0x%x" + +# dp8398x.c +dp8393x_raise_irq(int isr) "raise irq, isr is 0x%04x" +dp8393x_lower_irq(void) "lower irq" +dp8393x_load_cam(int idx, int cam0, int cam1, int cam2, int cam3, int cam4= , int cam5) "load cam[%d] with 0x%02x0x%02x0x%02x0x%02x0x%02x0x%02x" +dp8393x_load_cam_done(int cen) "load cam done. cam enable mask 0x%04x" +dp8393x_read_rra_regs(int crba0, int crba1, int rbwc0, int rbwc1) "CRBA0/1= : 0x%04x/0x%04x, RBWC0/1: 0x%04x/0x%04x" +dp8393x_transmit_packet(int ttda) "Transmit packet at 0x%"PRIx32 +dp8393x_transmit_txlen_error(int len) "tx_len is %d" +dp8393x_read(int reg, const char *name, int val, int size) "reg=3D0x%x [%s= ] val=3D0x%04x size=3D%d" +dp8393x_write(int reg, const char *name, int val, int size) "reg=3D0x%x [%= s] val=3D0x%04x size=3D%d" +dp8393x_write_invalid(int reg) "writing to reg %d invalid" +dp8393x_write_invalid_dcr(const char *name) "writing to %s invalid" +dp8393x_receive_oversize(int size) "oversize packet, pkt_size is %d" +dp8393x_receive_not_netcard(void) "packet not for netcard" +dp8393x_receive_packet(int crba) "Receive packet at 0x%"PRIx32 +dp8393x_receive_write_status(int crba) "Write status at 0x%"PRIx32 --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.128.45 as permitted sender) client-ip=209.85.128.45; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-f45.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.45 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625233031; cv=none; d=zohomail.com; s=zohoarc; b=lo7ZKgy5S6DsBODTmV1F/Ht9wBYK6Yjrj71NqI6zl/t7gvyquGkhbpQBjOgUCM2p06a4a7xaAsXUleNaMR1rP1dGdfcumGHs8+bFIkt0zjfCpqo97YVtDlCpdsk3Zqk1xiqBfc4QtbQpPL1ruwHmhW49gT2RA7+q0QBFjOSlfqw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233031; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=mP6GfEEKKXaBd1tf8TIMMHcK8n5QD1fCIHiJmE/WS14=; b=Ene7IaybfjAoSM1S9s8nBSBO9QZDnxX4GkncJzkzXiDDO7KUFMo0xGfsn8m0aNVbltYtyGe33knSlTUnhFdr6PwEGIWEk3IaCDnqODN0EtBtq4weydEn/limv3obGEd3dXaKaOQYcTV7VfGeqqgEjlWWs43u7vxpKz6oP5efdew= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.45 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) by mx.zohomail.com with SMTPS id 1625233031446855.8003937643872; Fri, 2 Jul 2021 06:37:11 -0700 (PDT) Received: by mail-wm1-f45.google.com with SMTP id b14-20020a1c1b0e0000b02901fc3a62af78so2543019wmb.3 for ; Fri, 02 Jul 2021 06:37:10 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id 204sm3353242wma.30.2021.07.02.06.37.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:37:06 -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=mP6GfEEKKXaBd1tf8TIMMHcK8n5QD1fCIHiJmE/WS14=; b=ViY3nhI6gmCOFWVmlnuH+/UzDULmVfCuImnZd7Q14XbdTPiAEPvvkg1nnobBh1qA6n hYaHwWC5Ez97331EPIHwSqL/ZhtiCUEM1X3YECy48Mga/auki5S97ZR4Tn6litaynEL2 8TH0TXzSmK0cRbbogO0rPANb6jan1wTiUf414/pKg7M6dt94Iod13CH2sR7UXHblkpaG uesewqFMgUCgxr8eXE+8wgx6UPLgaJWQ8ep6qBCmZqugCpfNM4XPmxDKjUl486t0dPTO iTBcpG1piaNIoEjcZ991q7JQDEXdfStB8mjTxe1CCq2TNOAYG2xJYpykMxk7knbuImJt jUNw== 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=mP6GfEEKKXaBd1tf8TIMMHcK8n5QD1fCIHiJmE/WS14=; b=rMhtp+LtIhIdmBqicmw9p8CJeb/7TeZqyHjyX2NVlYnAgjbo3ioycafm+iFS/VA+hd N5RlTgh3IoDu8RrvRHENcNBDOs48NXnF9CSB2WmNMsJ/J++kpE8RrjCmFSX9PblTTg/z SdmJX3hLG0pQcSH0qjJ8gi68fVqdhx2Wn61/+zyA9aVPAlVfSp01+ouMiuSBQbaYgPQx AiMy0J4TLcKIG08qyCdCwC07S/y3T8SfymFbrn+Rl4/tny59bGSvkwzK2Yx61I2VNiAQ 991MZhf+rpS6H/C/QMlGf1+UlVA73m7xBIeMs8MB5a7ElibQWa11cv9XqiYdu0pvDUZo zjFg== X-Gm-Message-State: AOAM533EHciqlCWFDPvFhOpEVhOaDujqeqpIoWZdnLK7OXiBt/uZNg+j Cp8sYWNiVnh/F8wVMp2+yH8= X-Google-Smtp-Source: ABdhPJzbv1kB3Yq7JKnSuetxw1I8iMndxrSmXsnsj4Tim8X3eOIe9C5gzqq0FTHXrnc1Q0zOWUDWjQ== X-Received: by 2002:a05:600c:14c6:: with SMTP id i6mr4491759wmh.169.1625233029634; Fri, 02 Jul 2021 06:37:09 -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: Mark Cave-Ayland , Finn Thain , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PULL 12/18] hw/mips/jazz: move PROM and checksum calculation from dp8393x device to board Date: Fri, 2 Jul 2021 15:35:51 +0200 Message-Id: <20210702133557.60317-13-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233032390100001 From: Mark Cave-Ayland This is in preparation for each board to have its own separate bit storage format and checksum for storing the MAC address. Signed-off-by: Mark Cave-Ayland Tested-by: Finn Thain Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20210625065401.30170-4-mark.cave-ayland@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- hw/mips/jazz.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index 1e1cf8154e7..89ca8bb9107 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -119,6 +119,8 @@ static const MemoryRegionOps dma_dummy_ops =3D { #define MAGNUM_BIOS_SIZE = \ (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_M= AX) =20 +#define SONIC_PROM_SIZE 0x1000 + static void mips_jazz_init(MachineState *machine, enum jazz_model_e jazz_model) { @@ -137,6 +139,7 @@ static void mips_jazz_init(MachineState *machine, MemoryRegion *rtc =3D g_new(MemoryRegion, 1); MemoryRegion *i8042 =3D g_new(MemoryRegion, 1); MemoryRegion *dma_dummy =3D g_new(MemoryRegion, 1); + MemoryRegion *dp8393x_prom =3D g_new(MemoryRegion, 1); NICInfo *nd; DeviceState *dev, *rc4030; SysBusDevice *sysbus; @@ -228,6 +231,10 @@ static void mips_jazz_init(MachineState *machine, NULL, "dummy_dma", 0x1000); memory_region_add_subregion(address_space, 0x8000d000, dma_dummy); =20 + memory_region_init_rom(dp8393x_prom, NULL, "dp8393x-jazz.prom", + SONIC_PROM_SIZE, &error_fatal); + memory_region_add_subregion(address_space, 0x8000b000, dp8393x_prom); + /* ISA bus: IO space at 0x90000000, mem space at 0x91000000 */ memory_region_init(isa_io, NULL, "isa-io", 0x00010000); memory_region_init(isa_mem, NULL, "isa-mem", 0x01000000); @@ -275,6 +282,9 @@ static void mips_jazz_init(MachineState *machine, nd->model =3D g_strdup("dp83932"); } if (strcmp(nd->model, "dp83932") =3D=3D 0) { + int checksum, i; + uint8_t *prom; + qemu_check_nic_model(nd, "dp83932"); =20 dev =3D qdev_new("dp8393x"); @@ -285,8 +295,19 @@ static void mips_jazz_init(MachineState *machine, sysbus =3D SYS_BUS_DEVICE(dev); sysbus_realize_and_unref(sysbus, &error_fatal); sysbus_mmio_map(sysbus, 0, 0x80001000); - sysbus_mmio_map(sysbus, 1, 0x8000b000); sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 4)); + + /* Add MAC address with valid checksum to PROM */ + prom =3D memory_region_get_ram_ptr(dp8393x_prom); + checksum =3D 0; + for (i =3D 0; i < 6; i++) { + prom[i] =3D nd->macaddr.a[i]; + checksum +=3D prom[i]; + if (checksum > 0xff) { + checksum =3D (checksum + 1) & 0xff; + } + } + prom[7] =3D 0xff - checksum; break; } else if (is_help_option(nd->model)) { error_report("Supported NICs: dp83932"); --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.128.46 as permitted sender) client-ip=209.85.128.46; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-f46.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.46 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625233037; cv=none; d=zohomail.com; s=zohoarc; b=cSY6vAe28Tn2TRq+JJEiJ9Sj/qy6iA+XkfM1qTr9ZJfcHMPIW4BXUpNtzqYaEZZeqtHw6YWQbxxZluDAU43R1wcTStLQhKqGk6EpQ2urGThqrNUGIgMOZLiu5a0nGscljFBlPsjfCFDAqHsOjsQcfDGX9YA9BDyuDy+ViRY6Oas= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233037; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=hM5jFlzSYXmgSnw6kDffxFRxISxlO+HVFgqFqsltpDQ=; b=l6JbFmbpyIhv0r/lZRex7Ubv7DToOwWGc6OZtIhC7ZpDxXQGiBFo0fzbqYrzbjdAI+ZqMifMVZz/n2giEBA7W04FIwm8fveZHmu5B7YbEY49LBNRSaiOTySVzZUsF0wh3YYG61lvkfjDC1oGLeK1tzI1oeAh9PK6BNfP42Q6dOQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.46 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) by mx.zohomail.com with SMTPS id 1625233037980968.702869480237; Fri, 2 Jul 2021 06:37:17 -0700 (PDT) Received: by mail-wm1-f46.google.com with SMTP id b14-20020a1c1b0e0000b02901fc3a62af78so2543257wmb.3 for ; Fri, 02 Jul 2021 06:37:17 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id z8sm3757939wrw.18.2021.07.02.06.37.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:37:15 -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=hM5jFlzSYXmgSnw6kDffxFRxISxlO+HVFgqFqsltpDQ=; b=cSSDa3oV+PY0+J8L2l2wGPTpdpORwDur2Xp9tzxHg4DoMgOnZNQAazXFibMwxEhGu2 Y8BQNDgnDsOwsczO0b2gUlsNU/FuGODTg1hCmVX4VUsZRyQjTnpxlCjZKhd1sov20G3h WM7qPMa/6pMA3dM/vrfT4biQBOZIzj/G0/fDjyVxR3IeM+FRnUjeYvmYN9Y//U3ULnAv 3shLyFeO2hmFwkSREQS/BbLCLwNrOVA4yQABNbaKDBtA7zkU/tOExx6oF5GTTeN0Gwgu k/cnr/hBIjFj820LZwjfG6ydruLyQc8aRlm9M6ESd6Xe5r9nAv+4MoHoR4g8rDdgPxpE bHbg== 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=hM5jFlzSYXmgSnw6kDffxFRxISxlO+HVFgqFqsltpDQ=; b=Tp863s72h2kOPbwT3723M6xATyLlsnrrWB+vEXyOmidrDdEif1tMewkH4rZsXNiLd5 FvtMjx9/2Yp6dWQJHNtA1ACgI9rIFkawuIuHD8803XD8sQEXy+sixS6dZ7dcw9zeum1w 7AH2J15QdOZ9FJ10lZ7K+yc8JLCw8seQ0ukViLdzkeyjdVjp7sYKvoliej3/8Sd+Pe8Z rZyp7byXfBJ86PrDlAnKljjCQcxzbrUhrICoBxhIk2xxtV00M6s3ejgAm0OyWn60ACOD QBgXWN7ZU+Nmy7KWULIntnUX1KkRr6SDV/EBiF3u8j6E9EBLRT+pfqe/H7QdjGpIDSTX N30A== X-Gm-Message-State: AOAM533zCb50ERWjRZlYiNuFXUw0c8dxV1vRrQ88wA00prHv5WZ6PYhb 37UdAcm7EZub6GBVSJntLcs= X-Google-Smtp-Source: ABdhPJxEh0epQX1hiViElOcLV+9aiVzEKSyFo71kY8PhdieWv6izyPh1J+wFZmfxndg5hVy4nyJo8g== X-Received: by 2002:a05:600c:4f8a:: with SMTP id n10mr16285008wmq.11.1625233036229; Fri, 02 Jul 2021 06:37:16 -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: Mark Cave-Ayland , Finn Thain , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PULL 13/18] hw/m68k/q800: move PROM and checksum calculation from dp8393x device to board Date: Fri, 2 Jul 2021 15:35:52 +0200 Message-Id: <20210702133557.60317-14-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233038927100001 From: Mark Cave-Ayland This is in preparation for each board to have its own separate bit storage format and checksum for storing the MAC address. Signed-off-by: Mark Cave-Ayland Tested-by: Finn Thain Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20210625065401.30170-5-mark.cave-ayland@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- hw/m68k/q800.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index 11376daa858..491f283a17a 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -70,6 +70,8 @@ #define NUBUS_SUPER_SLOT_BASE 0x60000000 #define NUBUS_SLOT_BASE 0xf0000000 =20 +#define SONIC_PROM_SIZE 0x1000 + /* * the video base, whereas it a Nubus address, * is needed by the kernel to have early display and @@ -211,8 +213,10 @@ static void q800_init(MachineState *machine) int32_t initrd_size; MemoryRegion *rom; MemoryRegion *io; + MemoryRegion *dp8393x_prom =3D g_new(MemoryRegion, 1); + uint8_t *prom; const int io_slice_nb =3D (IO_SIZE / IO_SLICE) - 1; - int i; + int i, checksum; ram_addr_t ram_size =3D machine->ram_size; const char *kernel_filename =3D machine->kernel_filename; const char *initrd_filename =3D machine->initrd_filename; @@ -319,9 +323,25 @@ static void q800_init(MachineState *machine) sysbus =3D SYS_BUS_DEVICE(dev); sysbus_realize_and_unref(sysbus, &error_fatal); sysbus_mmio_map(sysbus, 0, SONIC_BASE); - sysbus_mmio_map(sysbus, 1, SONIC_PROM_BASE); sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(glue, 2)); =20 + memory_region_init_rom(dp8393x_prom, NULL, "dp8393x-q800.prom", + SONIC_PROM_SIZE, &error_fatal); + memory_region_add_subregion(get_system_memory(), SONIC_PROM_BASE, + dp8393x_prom); + + /* Add MAC address with valid checksum to PROM */ + prom =3D memory_region_get_ram_ptr(dp8393x_prom); + checksum =3D 0; + for (i =3D 0; i < 6; i++) { + prom[i] =3D nd_table[0].macaddr.a[i]; + checksum +=3D prom[i]; + if (checksum > 0xff) { + checksum =3D (checksum + 1) & 0xff; + } + } + prom[7] =3D 0xff - checksum; + /* SCC */ =20 dev =3D qdev_new(TYPE_ESCC); --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.221.41 as permitted sender) client-ip=209.85.221.41; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-f41.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.41 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625233043; cv=none; d=zohomail.com; s=zohoarc; b=ZNUS7lLnKq1ptMYeZcv+21tGVaoGuh6q3kKlpls5h334rfsRPhmd7D5r6SRJRNCSdIs4xVr8K+H9A0yqQkDJ3AEufVrmECvY4OZMucY4+wWsHYKiTn+7zp4W24tOkx9Uj/rikmulvY3r47k2R2nn8nZw2X6GcEAQ1634/8eUru8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233043; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=CpqtyrEBgGp2q4wqDOzQhvyghW20BSPg8kexiW49YjQ=; b=DRQd1ZVktsGihcBnBAwVZE4rYAiY5BCDpRyagIusl2woA8wAjfJrFRvzxW7t33KtJGNv9JDazUzcA8lhDXVLyXr6QMGvO3jOXlQGPzhe/mAFgbAqd+gbzCHaImQKbUdV/u6KgSIIj/VzlARlFK183O/LV3pt4gfjGSLc7+zM8Lo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.41 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) by mx.zohomail.com with SMTPS id 1625233043846413.8555159383766; Fri, 2 Jul 2021 06:37:23 -0700 (PDT) Received: by mail-wr1-f41.google.com with SMTP id a13so12483265wrf.10 for ; Fri, 02 Jul 2021 06:37:23 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id n12sm3782890wmq.5.2021.07.02.06.37.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:37:21 -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=CpqtyrEBgGp2q4wqDOzQhvyghW20BSPg8kexiW49YjQ=; b=brjstrgbDbMKkqR75WF8H/ykYRSyX1VZzBTJts8CHFOvXwcT/6rFHYDuIOYSY7R3Xj 7qEqCpzfVgwhoNaIXldQstroytDz9yvh2QK55FLaeMSUN820QaxAeX0D5q79QlC3enP9 H0PIthmmRCgyA3lF18ZcFaQJIdia0jzTOz9ZuRuRpef+opIaA4k4pELjAl8k4YzHKaBw kJhHQQ/Nx/7eqUeerxchAx9wYS+kZ5psU583ar6N/gLRnRbprzJK9jnK9+RwucgWHNkI A7dCvxt7V5e34LGYM9m7/WWDaltSkvANfmlVjcq7DITZ2wbokG5h9WjkD6VuQ44ehtDq T2gQ== 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=CpqtyrEBgGp2q4wqDOzQhvyghW20BSPg8kexiW49YjQ=; b=VWEjvqgkeN2aRHouRR8yhW2jpMiZT1dIltK2ol34I425zpUtV3aHx/Ffy3ijayXivW 9biDcLkwDRsS4EDmTeHvhryhvzemPN9CU2HzIvI4spNC9TGhOd+Dg8xJhibqizfmnJ8k 0KphibUMsEMy3xNyebvhHLdyqf21DnD1Kx56WqUEEM9lOTpOvl3QDcjop9rPoT65eHuz UtUI1NwqgtW/3rRNujvP07w+0auO1fPhiPSEE4bR1fnu2e3GE9uHOT3uYg7tTrGKpk8C WyrU8XOB5mIBkOXOow4YQdEzSNsHwgkfgSClhClmzugFNdextvDIy8SmbvvI8V4D0pmQ 77ZQ== X-Gm-Message-State: AOAM532mjUG1gfdwN5FLjmkBQ4Y7Wqo7i+yDgkU/CNgOTaAlcuFaQxQR hywK1dQR3vANiNNc3Zb/U9Zr2g3C9tC1cXnC X-Google-Smtp-Source: ABdhPJzAzFLDTf+pnaaSJqPc0qK4DsyEbvN2Gnlfr8IiI4ef5N6FeOjz0JPZJMT1cyjUTyi+M624TQ== X-Received: by 2002:a5d:524e:: with SMTP id k14mr6091871wrc.390.1625233042168; Fri, 02 Jul 2021 06:37:22 -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: Mark Cave-Ayland , Finn Thain , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PULL 14/18] dp8393x: remove onboard PROM containing MAC address and checksum Date: Fri, 2 Jul 2021 15:35:53 +0200 Message-Id: <20210702133557.60317-15-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233045715100001 From: Mark Cave-Ayland According to the datasheet the dp8393x chipset does not contain any NVRAM c= apable of storing a MAC address or checksum. Now that both the MIPS jazz and m68k = q800 boards generate the PROM region and checksum themselves, remove the generat= ed PROM from the dp8393x device itself. Signed-off-by: Mark Cave-Ayland Tested-by: Finn Thain Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20210625065401.30170-6-mark.cave-ayland@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- hw/net/dp8393x.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index ea5b22f6802..252c0a26641 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -30,8 +30,6 @@ #include "qom/object.h" #include "trace.h" =20 -#define SONIC_PROM_SIZE 0x1000 - static const char *reg_names[] =3D { "CR", "DCR", "RCR", "TCR", "IMR", "ISR", "UTDA", "CTDA", "TPS", "TFC", "TSA0", "TSA1", "TFS", "URDA", "CRDA", "CRBA0", @@ -157,7 +155,6 @@ struct dp8393xState { NICConf conf; NICState *nic; MemoryRegion mmio; - MemoryRegion prom; =20 /* Registers */ uint8_t cam[16][6]; @@ -966,16 +963,12 @@ static void dp8393x_instance_init(Object *obj) dp8393xState *s =3D DP8393X(obj); =20 sysbus_init_mmio(sbd, &s->mmio); - sysbus_init_mmio(sbd, &s->prom); sysbus_init_irq(sbd, &s->irq); } =20 static void dp8393x_realize(DeviceState *dev, Error **errp) { dp8393xState *s =3D DP8393X(dev); - int i, checksum; - uint8_t *prom; - Error *local_err =3D NULL; =20 address_space_init(&s->as, s->dma_mr, "dp8393x"); memory_region_init_io(&s->mmio, OBJECT(dev), &dp8393x_ops, s, @@ -986,23 +979,6 @@ static void dp8393x_realize(DeviceState *dev, Error **= errp) qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); =20 s->watchdog =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s); - - memory_region_init_rom(&s->prom, OBJECT(dev), "dp8393x-prom", - SONIC_PROM_SIZE, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - prom =3D memory_region_get_ram_ptr(&s->prom); - checksum =3D 0; - for (i =3D 0; i < 6; i++) { - prom[i] =3D s->conf.macaddr.a[i]; - checksum +=3D prom[i]; - if (checksum > 0xff) { - checksum =3D (checksum + 1) & 0xff; - } - } - prom[7] =3D 0xff - checksum; } =20 static const VMStateDescription vmstate_dp8393x =3D { --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.128.53 as permitted sender) client-ip=209.85.128.53; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-f53.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.53 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625233050; cv=none; d=zohomail.com; s=zohoarc; b=BepBs5h0Xk5smhmWFr7WgvBTcQYSBUyNmePI9EkW554c7l9xbb/jI7nAzAS7WfA+ALs+hh0qTEVJq8egZJog0plhdow1Prx6eQsOECXxNFANvRkT96AdQ1r9ySalEecHdQXdFkK/3wqXKKBOT3iHcVky5uNkDYXFW23aHOQgtmg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233050; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=erflfoQZg1zmJhaY5+bBLo3ktzzY4R/YAAD7gOAMH4Y=; b=WO0z/AZY0ZqpDVq/1y6pfjYw60nDouF3xDV1AHqsqzfawm2xT/Z0ZRYOilcNILnedEgHeDqbbm/Hq6GDiFgpB/OmDRpnCnAL3CRL+CMQtfNuow481Gl40sXStURwpmXmoMcfB2rVZ5euNHQsKskFQ0o6mScYTe0aleAvu9bTlTM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.53 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) by mx.zohomail.com with SMTPS id 1625233050307990.7824480506389; Fri, 2 Jul 2021 06:37:30 -0700 (PDT) Received: by mail-wm1-f53.google.com with SMTP id r9-20020a7bc0890000b02901f347b31d55so6236869wmh.2 for ; Fri, 02 Jul 2021 06:37:29 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id y8sm3035642wrr.76.2021.07.02.06.37.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:37:28 -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=erflfoQZg1zmJhaY5+bBLo3ktzzY4R/YAAD7gOAMH4Y=; b=ehIuFKNCoZxrPpqeDb3mouNygSzBqn0qXPpThpiERIHsd3HKnhfo2znWjZGM6E3luU WFoDUmy5nrIPhGVxouOvx56q19qO863LtpqilrqTLMKHol0aADd2fpb00jGW7VD8TEll xzsXzQVwgFleibqtQSSHQBj9Ysivc4esZ30BNB4XaZG6vK6fvsTlOQ/t6fsfnY1MZWCr 47U6V9Ve5RJvoUJQg5b73iUB7yud3RYeNr/95XIw969SYA0c5flwbOaIq5aYQukAXRMR puFLj7pEuFd3wesqnQfDssfctbe9DhYbIA8f9SgzJQvGjFtSViD8urJ0/9qpkVg+zW6Y RSWA== 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=erflfoQZg1zmJhaY5+bBLo3ktzzY4R/YAAD7gOAMH4Y=; b=KZslWVvvtXWJjuGzMfES8JdM8K2ka5UipSi2Vh7lKT4xvHHz++l/6qKXud2KJ/9XR1 1smXn8eXNXpw9/180clU52Ob7w2D46d4eA0rK9PpaRPlUx15uzRiTrkSHKn/Sf+dmaQK FeCG7eMpsG5nXn2VyBoQQO88V6NQmzQFN2qQ04YQumfO4dbswJfRsHi4l/XNyof2oAXB uj+LgNqmEcAI13XUDEEa6J0i9S5sj5gwv0jbuiod8woTPTUCQTGK6CW1J8EvcxrRiqNu 5yF1+5bDriJRsZfXSRb8y8TKO+B5niLWi3266Fyl6R+G0HgzhPuGihTffoUdXeSF5V4G C8Hw== X-Gm-Message-State: AOAM532iofiy8x7gMlMzjx9zTZHjq3MOmjspjbW0mtzFX35zxF9dM+8J tohr8158WbjwKNiDKPgjmBQ= X-Google-Smtp-Source: ABdhPJywG/3yi7DbCLL+EsFEAtNWK1rU6OXUhDsCWML3RrkCqKBosySxzOxGB6MTJObLMk8DABRdIA== X-Received: by 2002:a1c:f206:: with SMTP id s6mr5471046wmc.102.1625233048549; Fri, 02 Jul 2021 06:37: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: Mark Cave-Ayland , Finn Thain , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PULL 15/18] qemu/bitops.h: add bitrev8 implementation Date: Fri, 2 Jul 2021 15:35:54 +0200 Message-Id: <20210702133557.60317-16-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233052490100001 From: Mark Cave-Ayland This will be required for an upcoming checksum calculation. Signed-off-by: Mark Cave-Ayland Tested-by: Finn Thain Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20210625065401.30170-7-mark.cave-ayland@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- include/qemu/bitops.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h index 03213ce952c..110c56e0993 100644 --- a/include/qemu/bitops.h +++ b/include/qemu/bitops.h @@ -618,4 +618,26 @@ static inline uint64_t half_unshuffle64(uint64_t x) return x; } =20 +/** + * bitrev8: + * @x: 8-bit value to be reversed + * + * Given an input value with bits:: + * + * ABCDEFGH + * + * return the value with its bits reversed from left to right:: + * + * HGFEDCBA + * + * Returns: the bit-reversed value. + */ +static inline uint8_t bitrev8(uint8_t x) +{ + x =3D ((x >> 1) & 0x55) | ((x << 1) & 0xaa); + x =3D ((x >> 2) & 0x33) | ((x << 2) & 0xcc); + x =3D (x >> 4) | (x << 4) ; + return x; +} + #endif --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.128.52 as permitted sender) client-ip=209.85.128.52; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-f52.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.52 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625233055; cv=none; d=zohomail.com; s=zohoarc; b=Tk+gscMR9DXjBP5B3uqW0NJLHzr2E4kGeYFr0ffao/zRmcZzyUbxwq6zzZ18vsm2KCDwfFn0XgiHV7m4Zj4SOR6bTxvFzlphwlS/6aUyrX91jIXUmFVjaNR+NxY/M79ENXoOgNZvoVRkWF1/JiX4Rbx3mAdbEMhaCe9AiNsIGhM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233055; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Tzi8eTHim8Z+u+XnqhLJG2X/L8m9qzdiOwJHksilmKc=; b=gvYbOLtBMJa70GUmcuCZKQpeUp1wms9C9h1+vN5c/ocB6pxCFTWtoeBiVgF197IcR0X1W68lLukkrTvlNUU1PJvrjiysnaw2d+v32eT6b46f9f4ymIid4l9QCdtOksyunKqtGxAiewHm7c9ecLgmtwDlPnegGjiDfxMt8lFlx90= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.52 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) by mx.zohomail.com with SMTPS id 1625233055355671.0238484405825; Fri, 2 Jul 2021 06:37:35 -0700 (PDT) Received: by mail-wm1-f52.google.com with SMTP id g8-20020a1c9d080000b02901f13dd1672aso5907322wme.0 for ; Fri, 02 Jul 2021 06:37:34 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id u18sm3103763wmj.15.2021.07.02.06.37.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:37:33 -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=Tzi8eTHim8Z+u+XnqhLJG2X/L8m9qzdiOwJHksilmKc=; b=WxEQ9XyBEZInFqZQQ1lfiKdjeGdMQGb5CUOJPQm2L45JtkP5PwxzbeAkNzt76fvY3c Mgth7lollzCrjl648Va+SkJYErKtF2AWDs8FVKvCO+nOuLkGHy+eo3XHvKY/513HFVT+ znOHrnexxpZgunTvsMy2pynt15MNTAYIBQ6pQKoG3pdql0wZ81yFxFxV8IdQ4QDR6KcN h+2ovJFbbJ3g7Y+GmUgUGsQhJm5rWfk0Vg1QcXmAi54frgLwx7rUL3YpMRoT7rJqNrzy bVoXW44MXa4V7pukptukNjt+hFN3flp7ak1GaSwsXBY3frKLX+wujeQCiMLfd6Uv/tl2 dzWQ== 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=Tzi8eTHim8Z+u+XnqhLJG2X/L8m9qzdiOwJHksilmKc=; b=hp6d/ansrhqYNxVlLafb+za74ij7CRLBrVXhD6hYId5TPvLxWcPyh9hAekDhawHokY Mkik9w3CMkyyTeBx3pgdpJAwPUN0g1qLWhXWGgpyEmFpC55GwrrtrJtWsdVOcfVe47Q6 e4p/euiDNLKEj0bU3B4lUfudV6xcfJsnDEf1MkE7Aum6NKPHw69fH/UkcwJ6z5UQhJm0 ASTVeoLwl83oOTevNGeZScuvkrYkbV9ixVZlO+FzMCU1RRep+FIxOZruNJLlAIWlfriq mHBi+05sz5ieybT9lsXt6L86i+EX0PcUTP8j+CTA6jZfgAgRIHPJ9ZoGUNfQlkNd+DUV dowA== X-Gm-Message-State: AOAM532bjLQRpfDBBqPMxvMWIFQNi47IhQny5q7+Rgv3OP+nVm7skO/N vAGr8Kf5Gx1HCCjlfI3lflg= X-Google-Smtp-Source: ABdhPJwzV9+YncrImddv7b0oK2Itiouto2WSxbbuZIViPeRHt8OBAGrXh3erixtrrknRjyXDER3sPQ== X-Received: by 2002:a1c:7915:: with SMTP id l21mr13936387wme.62.1625233053645; Fri, 02 Jul 2021 06:37:33 -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: Mark Cave-Ayland , Finn Thain , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PULL 16/18] hw/m68k/q800: fix PROM checksum and MAC address storage Date: Fri, 2 Jul 2021 15:35:55 +0200 Message-Id: <20210702133557.60317-17-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233057042100001 From: Mark Cave-Ayland The checksum used by MacOS to validate the PROM content is an exclusive-OR rather than a sum over the corresponding bytes. In addition the MAC address must be stored in bit-reversed format as indicated in comments in Linux's macsonic.c. With the PROM contents fixed MacOS starts to probe the device registers when AppleTalk is enabled in the Control Panel. Signed-off-by: Mark Cave-Ayland Tested-by: Finn Thain Message-Id: <20210625065401.30170-8-mark.cave-ayland@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- hw/m68k/q800.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index 491f283a17a..6817c8b5d1a 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -334,11 +334,8 @@ static void q800_init(MachineState *machine) prom =3D memory_region_get_ram_ptr(dp8393x_prom); checksum =3D 0; for (i =3D 0; i < 6; i++) { - prom[i] =3D nd_table[0].macaddr.a[i]; - checksum +=3D prom[i]; - if (checksum > 0xff) { - checksum =3D (checksum + 1) & 0xff; - } + prom[i] =3D bitrev8(nd_table[0].macaddr.a[i]); + checksum ^=3D prom[i]; } prom[7] =3D 0xff - checksum; =20 --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.221.46 as permitted sender) client-ip=209.85.221.46; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wr1-f46.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.46 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625233060; cv=none; d=zohomail.com; s=zohoarc; b=XAMLcrdU+hO1ckLt3q8xlUamfzK5cg+55KXz/wywr8g9FZwRzjO1BzKmeYGHt1yGL5cytPb9vyIgV2c7bU0y2fU78dBqTFqBgpt2movya8ZjCVdA0kQbzT9iS2CWcnMl0U5Afm6am7c/tNgLXVwKKaNnCpRNmSRQ+QxkexP1fdE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233060; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=RXzcBY1Xz+NzYhjk5HmcS/3KibwDarkLazlUMdNcDYk=; b=OAEGME3gLz12mSl8Gi6hagxBp4DV6zRm+6q/VODTNYviv75n4k570TenRMgUsb/+6qJ1pR5Av2yh8e1DNstbfi9bZK+j15oEui7TFbC+i8toE1dvVWA1lcp99N04NdpsuQJ3UyDvVffatNDoC6F7MmSXu1Sxc8GpeX2z3wbi3co= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.221.46 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) by mx.zohomail.com with SMTPS id 1625233060244424.6420301419996; Fri, 2 Jul 2021 06:37:40 -0700 (PDT) Received: by mail-wr1-f46.google.com with SMTP id i8so12588003wrc.0 for ; Fri, 02 Jul 2021 06:37:39 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id h10sm13644502wmq.0.2021.07.02.06.37.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:37:38 -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=RXzcBY1Xz+NzYhjk5HmcS/3KibwDarkLazlUMdNcDYk=; b=VQxDiu3oXmp8q+ULhpUe/Law/dvmY9ty3gGvPQWK7tJddH7G5XXwOGKhGpwRSZlaEr O9w/zdVsHVsPRMOMvWGKixCeZ6lm9+vaq1Xn8FW1ThWanjeT+0Y13B67j8stVY5vOJlH +XmkKiV6DhIsLtwT5hey0YpRp0evIuuXa1mUpefvk0J3xExKHs1ovovvz5J7tB/0gJuo L7yICrchrS2uscyqwPJbilf2HRoz7P6oA/np9TbHZ26g33ZVzPGErz0R7+s+XNGQqhbN oRn2mQ+v1CT1PTg025R2fcqcJf96uyapi+FJpV2IpTsPt3ivSe0j3GdIPKhsK2FQ5Wh3 NnTQ== 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=RXzcBY1Xz+NzYhjk5HmcS/3KibwDarkLazlUMdNcDYk=; b=m4FVGsUoTWp9i0o0vIKSPFm17loDz5AvtfWUHAgiUWNK4d6KXmqHgX7WLagl4ZLM4z lbaFwcWMvD/tTWKugCqtLwE2hevTFa0FSCadWekm/lDIKoMJBUkKCN3mf0IC9yck42GU 1SbfT7aHixE3y9BoJqf9d8vYH/JHhIFmzPSzKEHfgprkJGzFXR4xwjAffzSPYzHV2QeN W9vnoOZ6BWPFEAGEOStOpvHckkmkgfxw2A0BZ6FNCYpCFxnw2jIzU29BMRfAf1GotmnU Yc6pzccVG6pJxeJHnb7M3nojO9Vr7IiSac9YI+ZfmjMchPuD4rLC9gtYN+mE4fiGd9Db M3bQ== X-Gm-Message-State: AOAM5335Z7LNBPADjSewFR2KHQ/cs5INJTSzFP8H//bM5YYt0HCWPlsp aNFw/fV6avJUgi3PuiQORZg= X-Google-Smtp-Source: ABdhPJxctLpMrvv3XuqntkdS50fc3IMCTk6IkkoYGuhQgzLVmLNst08JkrW8OHBsPrXCoyEibZ4t2Q== X-Received: by 2002:a05:6000:1c9:: with SMTP id t9mr5998774wrx.330.1625233058535; Fri, 02 Jul 2021 06:37:38 -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: Mark Cave-Ayland , Finn Thain , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PULL 17/18] hw/mips/jazz: specify correct endian for dp8393x device Date: Fri, 2 Jul 2021 15:35:56 +0200 Message-Id: <20210702133557.60317-18-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233061484100003 From: Mark Cave-Ayland The MIPS magnum machines are available in both big endian (mips64) and litt= le endian (mips64el) configurations. Ensure that the dp893x big_endian property is set accordingly using logic similar to that used for the MIPS malta machines. Signed-off-by: Mark Cave-Ayland Tested-by: Finn Thain Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20210625065401.30170-11-mark.cave-ayland@ilande.co.uk> Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- hw/mips/jazz.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index 89ca8bb9107..ee1789183eb 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -126,7 +126,7 @@ static void mips_jazz_init(MachineState *machine, { MemoryRegion *address_space =3D get_system_memory(); char *filename; - int bios_size, n; + int bios_size, n, big_endian; Clock *cpuclk; MIPSCPU *cpu; MIPSCPUClass *mcc; @@ -158,6 +158,12 @@ static void mips_jazz_init(MachineState *machine, [JAZZ_PICA61] =3D {33333333, 4}, }; =20 +#ifdef TARGET_WORDS_BIGENDIAN + big_endian =3D 1; +#else + big_endian =3D 0; +#endif + if (machine->ram_size > 256 * MiB) { error_report("RAM size more than 256Mb is not supported"); exit(EXIT_FAILURE); @@ -290,6 +296,7 @@ static void mips_jazz_init(MachineState *machine, dev =3D qdev_new("dp8393x"); qdev_set_nic_properties(dev, nd); qdev_prop_set_uint8(dev, "it_shift", 2); + qdev_prop_set_bit(dev, "big_endian", big_endian > 0); object_property_set_link(OBJECT(dev), "dma_mr", OBJECT(rc4030_dma_mr), &error_abort); sysbus =3D SYS_BUS_DEVICE(dev); --=20 2.31.1 From nobody Mon Feb 9 16:21:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of _spf.google.com designates 209.85.128.54 as permitted sender) client-ip=209.85.128.54; envelope-from=philippe.mathieu.daude@gmail.com; helo=mail-wm1-f54.google.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.54 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1625233065; cv=none; d=zohomail.com; s=zohoarc; b=NPHNY+N370MK0g6BhCmtDfcZLB/iRjqP9H/Od4MnMVB/Dx9k9aTv03NEg5kasNsy0oqGtcBENh3yF0KOeZWCV4OyIhGiL7a9ww7bTw1X7l4oiIkzjsSGkl2i7zLEKT+/eY4Qd6I1G9DDZeRCANb27+uwl/SehxiRrd+UUC29z9k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1625233065; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Sender:Subject:To; bh=klbhgHqkEpwdq3x6lzv467uqizGi7EOdKnPiTzMYnoA=; b=e9EyJaUrksmf1G0baoSzl2W7UyplHRDha1S7qRFhAExpo838UrwXNMvbP70k/883gY68w8XLanibMRZcSOTQI745AZiss6eNO6URzwGp/9kA9r1LaXmwl1uYS+cYskcoSjgGKyZuPOxw1P2/S4KcebO841xaWJUtYVG6hU37jEI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of _spf.google.com designates 209.85.128.54 as permitted sender) smtp.mailfrom=philippe.mathieu.daude@gmail.com Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) by mx.zohomail.com with SMTPS id 1625233065720712.3773590378673; Fri, 2 Jul 2021 06:37:45 -0700 (PDT) Received: by mail-wm1-f54.google.com with SMTP id g10so857899wmh.2 for ; Fri, 02 Jul 2021 06:37:45 -0700 (PDT) Return-Path: Return-Path: Received: from x1w.Ascou-CH1 (pop.92-184-108-23.mobile.abo.orange.fr. [92.184.108.23]) by smtp.gmail.com with ESMTPSA id l20sm3256961wmq.3.2021.07.02.06.37.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 06:37:43 -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=klbhgHqkEpwdq3x6lzv467uqizGi7EOdKnPiTzMYnoA=; b=fKW8Btz5Jm2yAjNqi2d5bA9i0htbw1BJU17Q9h9u4cIP9/xxUJ532mxPFA8XwV/mcF o7uneAmOs5EMt/S55N+Lt78ICod/wggEmXnY32fMsw/2yW+hNbbBpY8+WDunazRXw258 7Ux3Z8h2YJkO9YOvQDXvmCdaeoPcsKEPCOEwga96jiWMOYSqn5czjx2c0oNzt+QZtAUt 9SCUmR+OWUyy1R4iDTBhxZcixaqP5MSrs/Tohh/L8K4OVgGeSuYAbdAfty+MRO9ORo3C xy1eIKPdss7Tm6nKY8Y5pVk/ODWqe+nfBL6dKjJFNsIUL6DfZo9Dl5ChPEfs71trEepf 89qg== 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=klbhgHqkEpwdq3x6lzv467uqizGi7EOdKnPiTzMYnoA=; b=ZoO2iPry2978kiU5inGcj4egaZv1fPwDHEUJUymxpWZ88dDq62qnUdMZYiE9vCdtSL UYE1KUdTUt/DVk2VMfEPB28u7+QMPCrprwnQcKFc9Riq8Bu9gQwpvXK9/0o71WYqq+PU 3GF2F5LAD1+uAH6n58qEs9N7vwnDkLX1EXanuvSBUD2x/aXAfthcBsdyCOtZpZvBgBuu iOa9Yffms/prFYOFwYVuthT4zC0DdXosa15uQ5NlbpWa0VT4DgITlDa/n2gVWi7lNK2D 2A7G2TKNeaBUh49bEkLOAXuG/I3TBfkE1IdK2xlkcV+xQAY/mIInk2AyAom+mMFX1Kzo hr3g== X-Gm-Message-State: AOAM530budWNVPEOz5ByOBeHbZv6iYnWFO+kT+/hGHhB9Tnp8NHf4i6x bUYWhKD7F+M0OCq6Jcl7IGc= X-Google-Smtp-Source: ABdhPJwZjJ++YQ1VTLOz+3qdKA9Qa2FADOBmGKy7C2PXwTwLuV5Nf4L92b7p2/mfTj1aogQshl7F/g== X-Received: by 2002:a7b:c248:: with SMTP id b8mr17310372wmj.115.1625233063983; Fri, 02 Jul 2021 06:37:43 -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: Mark Cave-Ayland , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Peter Maydell Subject: [PULL 18/18] hw/mips/jazz: Map the UART devices unconditionally Date: Fri, 2 Jul 2021 15:35:57 +0200 Message-Id: <20210702133557.60317-19-f4bug@amsat.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210702133557.60317-1-f4bug@amsat.org> References: <20210702133557.60317-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) X-ZM-MESSAGEID: 1625233066221100001 When using the Magnum ARC firmware we can see accesses to the UART1 being rejected, because the device is not mapped: $ qemu-system-mips64el -M magnum -d guest_errors,unimp -bios NTPROM.RAW Invalid access at addr 0x80007004, size 1, region '(null)', reason: rejec= ted Invalid access at addr 0x80007001, size 1, region '(null)', reason: rejec= ted Invalid access at addr 0x80007002, size 1, region '(null)', reason: rejec= ted Invalid access at addr 0x80007003, size 1, region '(null)', reason: rejec= ted Invalid access at addr 0x80007004, size 1, region '(null)', reason: rejec= ted Since both UARTs are present (soldered on the board) regardless of whether there are character devices connected, map them unconditionally. (This code pre-dated commit 12051d82f004 which made it safe to pass NULL in as a chardev to serial devices.) Signed-off-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Peter Maydell Message-Id: <20210629053704.2584504-1-f4bug@amsat.org> --- hw/mips/jazz.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index ee1789183eb..d6183e18821 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -361,16 +361,12 @@ static void mips_jazz_init(MachineState *machine, memory_region_add_subregion(address_space, 0x80005000, i8042); =20 /* Serial ports */ - if (serial_hd(0)) { - serial_mm_init(address_space, 0x80006000, 0, - qdev_get_gpio_in(rc4030, 8), 8000000 / 16, - serial_hd(0), DEVICE_NATIVE_ENDIAN); - } - if (serial_hd(1)) { - serial_mm_init(address_space, 0x80007000, 0, - qdev_get_gpio_in(rc4030, 9), 8000000 / 16, - serial_hd(1), DEVICE_NATIVE_ENDIAN); - } + serial_mm_init(address_space, 0x80006000, 0, + qdev_get_gpio_in(rc4030, 8), 8000000 / 16, + serial_hd(0), DEVICE_NATIVE_ENDIAN); + serial_mm_init(address_space, 0x80007000, 0, + qdev_get_gpio_in(rc4030, 9), 8000000 / 16, + serial_hd(1), DEVICE_NATIVE_ENDIAN); =20 /* Parallel port */ if (parallel_hds[0]) --=20 2.31.1