From patchwork Wed May 10 14:18:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksandar Rikalo X-Patchwork-Id: 92154 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp3663307vqo; Wed, 10 May 2023 07:22:41 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5v+Vl2XjwuE1wivCbiqcy4nGWbtv7XzQnyb36iaDXjU6qCxEOb66c/IfcjkYX1U7MiYZjB X-Received: by 2002:a05:6402:514d:b0:4fa:4a27:adba with SMTP id n13-20020a056402514d00b004fa4a27adbamr13953062edd.22.1683728560869; Wed, 10 May 2023 07:22:40 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1683728560; cv=pass; d=google.com; s=arc-20160816; b=nnNQWrrOUmd/EnRMk/0fmpdRdjPbdPWa2fGnmQs/IY/qFqySXPEwyv0dnqNOCz/s9b +MkCDMJTEJ8PSPp2KTwIUCP00QQUHudmUuuUVU6hGoPW15D0nT8n8aBUIlKaheQks8Ea T6MXtGy0r0nxWXi6oCxwodRffWQMkDHYnTaSYJVc/gw+y1JI1UgvYpoCfhhJLepPXNK8 RjzRy+04I1T0wIGuQ77T5qx4dMJBFa2Ipvbr9io7xzSoq3CxUq5F93jSCAQsw1OnTbQc CJWMRL3T8a1lrGRpSfE1ymHay+apBlKIz98nf1HXTgQDiQRWKlqCseqzb/62yqFtQLFi FH6w== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:mime-version :content-transfer-encoding:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:dmarc-filter:delivered-to; bh=yT1p1eQ96rksM2FHZRmFBJyHbJsBfEJ0+dsxCkbvCe0=; b=jaHkKik7Dl62ZYcgZqCDoVRVSqqFCcYtNH5vfVpKh+cVafwGpXY3ks7/9ARflMSryv cK9tiJyq4p51vYrN7vnmxO3lEZ1XhhQmGogMHNTxT1hSX1FmEGkJAiML3Z/ymJAZfzIv xWtcezQx2VNmuCDR3wRvVIZhz9uQHHijv7Vx8CDlVojoLPUI1OOXw0AmPUkbSC+Dq8Fa FbkuXzEu7izy4EimOLgZSo3YOR+HAC9jBqZz7kg9TUoVp4SL38fscZNSKJVOX1ISvan8 rzzR1f430E4vT5jOtSZoQPFMOnziVijeP2ah3JH2qioI7jwJ+INpaBrwH1A8u4gNjhJr +uYw== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@syrmia.com header.s=selector1 header.b=m2qpeetH; arc=pass (i=1 spf=pass spfdomain=syrmia.com dkim=pass dkdomain=syrmia.com dmarc=pass fromdomain=syrmia.com); spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org" Received: from sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id c12-20020a056402120c00b0050bfc62e170si3087907edw.194.2023.05.10.07.22.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 May 2023 07:22:40 -0700 (PDT) Received-SPF: pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@syrmia.com header.s=selector1 header.b=m2qpeetH; arc=pass (i=1 spf=pass spfdomain=syrmia.com dkim=pass dkdomain=syrmia.com dmarc=pass fromdomain=syrmia.com); spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org" Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id F10573870D53 for ; Wed, 10 May 2023 14:20:47 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2101.outbound.protection.outlook.com [40.107.21.101]) by sourceware.org (Postfix) with ESMTPS id B3155385355E for ; Wed, 10 May 2023 14:19:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B3155385355E Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=syrmia.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=syrmia.com ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ah1FqML3Ume727EQC9A1PgO7LJrtO6VCCb7Wom3DWyogDbN5JCo2cNdULCr25UjzXNuG7f49L9fOeEJ2LMbjQI1s6MkQ721s9DCfSxyqoVH6ByGlnKApD2WhyQ40MUvr6K/f+Fq7IqJ5F+ZSNCqJvXEC8t2uVTJVanuMKFjlQgPRyL1VxCv48cFJDTMmM+glxt6pZtNL890jVFYQU+AgW4GxidBQxQckKZo4iQqlCeRmZEQsA9DKnyQpyhzvzDvIqVCZe4tBbdTeW+VCBJyJtbs7r2BiPOUJSZ+zuZICnNz3qbltFOe6MW7mNllQtSN5afXdJgPZDxfasJP2417nww== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=yT1p1eQ96rksM2FHZRmFBJyHbJsBfEJ0+dsxCkbvCe0=; b=lT+o7YpKYxi5cD2Ry1DtGy2xlNCFpUnNl3e4YoT7nzVVnJZ0ER1Z9i7FhF4RamCVoOqzpLOi6/6+hlZW1xexwUwgKCbLjujUpEkS6JHCcUSljneZ6r1SfWl6itqrWgmKr5iyb0dmAhZv7WvcC5nMBurZDXODF05RcvKaROo2ER/OnuOSSCbRHTEzVQxtHvXcdePWlEPm8FJkSleDT+fotfHeS7ZnVSKzbpNdxA9uuFZP86WlNdAu84mwpkbxPmNO+az/3b5J+fnZ4OBj9w3lNTFr8xSWEDqfZamJOPjWkGHzMqqLCwaG1dVAAP2jYBkNQgSGmiXRtjEwTdIdRvgRVw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=syrmia.com; dmarc=pass action=none header.from=syrmia.com; dkim=pass header.d=syrmia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=syrmia.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=yT1p1eQ96rksM2FHZRmFBJyHbJsBfEJ0+dsxCkbvCe0=; b=m2qpeetHYcWDQ8DL0DFxaaemnyKA8gs99EAWdgRA2+Koi9dwenzz3Q+rRsAHoai5uRJ15pop80KlbEaVRPjtAnj0KlE0fQTTBvfka9X9enPTR7C6DW92ADdz+IHjlaeA7msfjBJ7R8pTrnKotzdl6zKQ+WgSx3cX1/T+GGwNYHs= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=syrmia.com; Received: from VI1PR0302MB3486.eurprd03.prod.outlook.com (2603:10a6:803:1e::32) by DB9PR03MB9784.eurprd03.prod.outlook.com (2603:10a6:10:456::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6363.31; Wed, 10 May 2023 14:18:47 +0000 Received: from VI1PR0302MB3486.eurprd03.prod.outlook.com ([fe80::82b5:25de:e5b:9914]) by VI1PR0302MB3486.eurprd03.prod.outlook.com ([fe80::82b5:25de:e5b:9914%4]) with mapi id 15.20.6387.018; Wed, 10 May 2023 14:18:47 +0000 From: Aleksandar Rikalo To: binutils@sourceware.org Cc: nickc@redhat.com, macro@orcam.me.uk, dragan.mladjenovic@syrmia.com, lei.wang@oss.cipunited.com Subject: [PATCH v6 2/3] Opcodes changes for nanoMIPS support Date: Wed, 10 May 2023 16:18:28 +0200 Message-Id: <20230510141829.2748105-3-aleksandar.rikalo@syrmia.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230510141829.2748105-1-aleksandar.rikalo@syrmia.com> References: <20230510141829.2748105-1-aleksandar.rikalo@syrmia.com> X-ClientProxiedBy: VI1PR0501CA0030.eurprd05.prod.outlook.com (2603:10a6:800:60::16) To VI1PR0302MB3486.eurprd03.prod.outlook.com (2603:10a6:803:1e::32) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VI1PR0302MB3486:EE_|DB9PR03MB9784:EE_ X-MS-Office365-Filtering-Correlation-Id: 18b9fb10-f2a3-406b-3d4c-08db51617810 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 0XaBOqDrKU1FvmU9t53t7TpEyE4hNef0VH7EnobHysGn9pB1aHR4DuMk3ggdzbK/k/dId3iYH06vARU5qLAmnK33e9h9TQ4uA6KoC8dQqMG78KMjDW9y5iG/Wx3gCc0G+lcF3Iwd5OxhxxYvYpIwOeoPa4r5ePEwWfgj+Ye9o8hUZb9c8kK3vQtSkhwsIacobcu4op/yFI4L4ZHcH45o3Say/TQ6tsKRCx2NK1fxE05ciN7oygN/9RxakQzg0a7lqFCT8yaNjrdCWfPr12uevg7WESr4sBLAkeGMayErozOGePlKf3NgPoXOxlLNRARj3IgnCaxEAjI6drbcu9G7po7pSEz3XHjUHdnbrZI7JrfiuGcCwWPGIGXk0ewWT4nnKs1Gb09139sAiv9ExH0nydunOcmQh8ugzAD7kPNkgJlSiA5uIzqHn/CyV8eK4OKludwSZwFo+r4OBmhKDin+pFiCIw7dacw2k6aLBWcNHmkcmEXB5Yk8zwltxA8RdGjsKAFfQ7AkIRM7IIKlnsbgpMmIbynTnUoNy4kBmj5t1X5F2Xs1BhSPIpqcNCq+CxwfZPZdF/KCu9kmcgdyVu/qealAY1hbN751C1mOVkgslsx88qB82AuFRS93lxViZWlr X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI1PR0302MB3486.eurprd03.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230028)(39840400004)(396003)(366004)(346002)(376002)(136003)(451199021)(8676002)(36756003)(66556008)(83380400001)(38350700002)(44832011)(2906002)(38100700002)(30864003)(316002)(86362001)(66946007)(6916009)(66476007)(41300700001)(4326008)(5660300002)(8936002)(52116002)(6506007)(26005)(186003)(6512007)(1076003)(2616005)(6666004)(478600001)(6486002)(2004002)(579004)(559001); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: zhn+JzQoxZZImbwRdSS5ercxzNMVs8W3S6tEcLtUULFUImlyr4eW6liLT7d1/uvEkvOBhjaemX6qxRDj5g/VpNFuMdQMTkt1DalOThXiZBMObeNc4UZDxuTznIXLndNpsK1HzrYW7b2Kq27fRvV8Fn+F2G3gtsSjtbROpNnStC1V3dqGSEVuedRvwMAtFX5kG741isbfA57VzXSDvAuBUkNbT00IeFx6p7iGXihgzF6HbMwXgL8fyUGcJxQ1Z/ZjRrKSgSjEW+a2c/QZ7pfZ/6cNwqsZFtPMg+rK65VEXR3Y6x9eDCd21Wr6jXsMxIN6jEB37Ua8czZ++FTXR4edFTPA5+H8e4FDhW8efD5y0q1RgGcpakfnHulbKtY6RkMMpldrCpkc22PT38nMwzT+B2SGKUqCN5L4N51c1fu4pN6wgNWhJ97hjW+dLuqLyXUx8hREHZ2+wU4NqajTngum0Hr4oXVyY0+BQOUZpBokg9tqFUJ0OIv4vXOigDiWXooV2uiKjNWBVCs4SrDL1q/OiPC2DKI40v+d/1/Qioj5HirNo2KEYFgi1WY0EEUc7rvJ+HxEa7qe7o+GQt1IpReu2SUT/vbfaSsPlNzExQpGZT5SRUS2M4pVwrYrn5L6uP0VoPiSQV+9T63a++zPIFjJu5i0rlnLIYeo+81PvgH8e1TzWjlRsWbog1ufS6T2iyKiPBsHJMRoQpSkxiquX0GAyrZzUwUmHb7i+Gh9p4wy0gfgO0zLGV+mhAWWU1tqm3OM+gwzs71QMH9VslUWF62Kel3/jffrWVL3i+aUPWhPSNDATm6AeUmvXuRHBAfYFot3vUmL/jKWgJeXxRPF/XcegqFeuCAXHhAmD8IZTKLuDuTWS8v4q+Q+/pFyJGqc8j3sSGPkmxKCOYSsmZAsAlDLFlwOsvC796Kf4V6fXZqC3L6415kevJ6BKQkJo7UYllQxUSwkLKA/vdrosUwnzZ8UvaSEF/S3zHqyPl1WI71FQ/l8qHAYJBtWww+sOkuWH+7G8e8DMApUaQmLlvD6asB0s165vlKjjkFJTQeBfjDu3/6MDe/UE9Uq+kHzW3FGbc2QfFonX1Ex6BwXmQ/6chZemjGVBVCQzQlij4fqgQfowJDmfGVzXimVd/RvlZWwD4L3FnMQSObYLxDK3/MotIpdH1BNnvOqQhLZgvN054kbvEVbZLXIu8ZJ7uR5fBX0XvgNSqheE9WayMdMCPZ8AxbyJ26obl/13wCwvXkGYKDJZpDuoUumP0UGpIrMMNu255uRrCAOlomuMHJotnLK2U4UqBqP62fWSATYzzVun5Tr4dDDTItr1c30wwAn1mdQGDgIdGBfnnHGkcZOZCale1fmv/oPmcUfO1Gy1HPThJF3mVnUhEw2L0IblFA2h52z6jxeFSbdR+B/H5rv0PbUnvsZwilVzGtkFZ4drWitd3l8ap9oN9r5Zx7EkEo86mLZSWn4Qcs1P4Gt+APhChsz5St9cYpkjBV9koqbRgPuq5hfTAXW4g+r6zGi46NuSyut3NuIlrUyt++ZhypfYZix/b1NGY82zy7+DZN+bn9uYPgFG90iw3MRmTU2pevJ7QXkxH9SE5RgtjgILC0kWxuqpjHlDA== X-OriginatorOrg: syrmia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 18b9fb10-f2a3-406b-3d4c-08db51617810 X-MS-Exchange-CrossTenant-AuthSource: VI1PR0302MB3486.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 May 2023 14:18:47.3704 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 19214a73-c1ab-4e19-8f59-14bdcb09a66e X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 6BzjicOvXIHUVfJh1vFrG652159Z1I5hsqY4X/fG/yPzPiwOvP8JdYBVQAUtYIr3wAhkVs4lN3T4KVTWZr9xMQzaNDRnpVzWWaiwzUkNt6o= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR03MB9784 X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+ouuuleilei=gmail.com@sourceware.org Sender: "Binutils" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1765517359451812753?= X-GMAIL-MSGID: =?utf-8?q?1765517359451812753?= Add a subset of the functionality required for GDB. Co-Authored-By: Jaydeep Patil Co-Authored-By: Matthew Fortune Co-Authored-By: Maciej W. Rozycki Co-Authored-By: Stefan Markovic Co-Authored-By: Sara Graovac Co-Authored-By: Dragan Mladjenovic --- include/dis-asm.h | 11 + include/opcode/nanomips.h | 1453 +++++++++++++++++++++++++++++++++++ opcodes/Makefile.am | 2 + opcodes/Makefile.in | 10 + opcodes/configure | 1 + opcodes/configure.ac | 1 + opcodes/dis-buf.c | 9 + opcodes/dis-init.c | 1 + opcodes/disassemble.c | 13 + opcodes/nanomips-dis.c | 1466 ++++++++++++++++++++++++++++++++++++ opcodes/nanomips-formats.h | 265 +++++++ opcodes/nanomips-opc.c | 1073 ++++++++++++++++++++++++++ 12 files changed, 4305 insertions(+) create mode 100644 include/opcode/nanomips.h create mode 100644 opcodes/nanomips-dis.c create mode 100644 opcodes/nanomips-formats.h create mode 100644 opcodes/nanomips-opc.c diff --git a/include/dis-asm.h b/include/dis-asm.h index d356429f3c5..1baf43cf9ec 100644 --- a/include/dis-asm.h +++ b/include/dis-asm.h @@ -307,6 +307,11 @@ typedef struct disassemble_info /* Set to true if the disassembler applied styling to the output, otherwise, set to false. */ bool created_styled_output; + + /* Predict the size of an instruction. */ + int (* predict_insn_length) + (bfd_vma, int, struct disassemble_info *); + } disassemble_info; /* This struct is used to pass information about valid disassembler @@ -366,6 +371,7 @@ typedef int (*disassembler_ftype) (bfd_vma, disassemble_info *); extern int print_insn_m32c (bfd_vma, disassemble_info *); extern int print_insn_mep (bfd_vma, disassemble_info *); extern int print_insn_s12z (bfd_vma, disassemble_info *); +extern int print_insn_nanomips (bfd_vma, disassemble_info *); extern int print_insn_sh (bfd_vma, disassemble_info *); extern int print_insn_sparc (bfd_vma, disassemble_info *); extern int print_insn_rx (bfd_vma, disassemble_info *); @@ -380,6 +386,7 @@ extern disassembler_ftype cris_get_disassembler (bfd *); extern void print_aarch64_disassembler_options (FILE *); extern void print_i386_disassembler_options (FILE *); extern void print_mips_disassembler_options (FILE *); +extern void print_nanomips_disassembler_options (FILE *); extern void print_nfp_disassembler_options (FILE *); extern void print_ppc_disassembler_options (FILE *); extern void print_riscv_disassembler_options (FILE *); @@ -475,6 +482,10 @@ extern asymbol *generic_symbol_at_address extern bool generic_symbol_is_valid (asymbol *, struct disassemble_info *); +/* Generic insn length, returns 2nd argument. */ +extern int generic_predict_insn_length + (bfd_vma, int, struct disassemble_info *); + /* Method to initialize a disassemble_info struct. This should be called by all applications creating such a struct. */ extern void init_disassemble_info (struct disassemble_info *dinfo, void *stream, diff --git a/include/opcode/nanomips.h b/include/opcode/nanomips.h new file mode 100644 index 00000000000..d77120e244d --- /dev/null +++ b/include/opcode/nanomips.h @@ -0,0 +1,1453 @@ +/* nanomips.h. nanoMIPS opcode list for GDB, the GNU debugger. + Copyright (C) 2018-2022 Free Software Foundation, Inc. + + Written by Faraz Shahbazker + + This file is part of GDB, GAS, and the GNU binutils. + + GDB, GAS, and the GNU binutils are free software; you can redistribute + them and/or modify them under the terms of the GNU General Public + License as published by the Free Software Foundation; either version 3, + or (at your option) any later version. + + GDB, GAS, and the GNU binutils are distributed in the hope that they + will be useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this file; see the file COPYING3. If not, write to the Free + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#ifndef _NANOMIPS_H_ +#define _NANOMIPS_H_ + +#include "bfd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Enumerates the various types of nanoMIPS operand. */ +enum nanomips_operand_type { + /* Described by nanomips_int_operand. */ + OP_INT, + + /* Described by nanomips_mapped_int_operand. */ + OP_MAPPED_INT, + + /* Described by nanomips_msb_operand. */ + OP_MSB, + + /* Described by nanomips_reg_operand. */ + OP_REG, + + /* Like OP_REG, but can be omitted if the register is the same as the + previous operand. */ + OP_OPTIONAL_REG, + + /* Described by nanomips_reg_pair_operand. */ + OP_REG_PAIR, + + /* Described by nanomips_pcrel_operand. */ + OP_PCREL, + + /* The register list and frame size for a MIPS16 SAVE or RESTORE + instruction. */ + OP_SAVE_RESTORE_LIST, + + /* A register operand that must match the destination register. */ + OP_REPEAT_DEST_REG, + + /* A register operand that must match the previous register. */ + OP_REPEAT_PREV_REG, + + /* Described by nanomips_prev_operand. */ + OP_CHECK_PREV, + + /* A register operand that must not be zero. */ + OP_NON_ZERO_REG, + + /* The floating-point register list for a nanoMIPS SAVE or RESTORE + instruction. */ + OP_SAVE_RESTORE_FP_LIST, + + /* Fractured upper immediate PC-offset for nanoMIPS */ + OP_HI20_PCREL, + + /* Fractured upper immediate 20-bit signed integer for nanoMIPS */ + OP_HI20_INT, + + /* Fractured upper immediate 20-bit scaled integer for nanoMIPS */ + OP_HI20_SCALE, + + /* A non-zero PC-relative offset. */ + OP_NON_ZERO_PCREL_S1, + + /* To check a mapped register against a previous operand. */ + OP_MAPPED_CHECK_PREV, + + /* Unsigned word operand. */ + OP_UINT_WORD, + + /* Signed word operand. */ + OP_INT_WORD, + + /* Immediate PC-relative word operand. */ + OP_PC_WORD, + + /* Immediate GP-relative word operand. */ + OP_GPREL_WORD, + + /* Don't care bits. */ + OP_DONT_CARE, + + /* Immediate unsigned word operand, to be negated. */ + OP_NEG_INT, + + /* Immediate (non-relocatable) integer operand. */ + OP_IMM_INT, + + /* Immediate (non-relocatable) word operand. */ + OP_IMM_WORD, + + /* Base register for limited types of offsets. */ + OP_BASE_CHECK_OFFSET, + + /* Copy over bits from another part of instruction. */ + OP_COPY_BITS, + + /* Select bits for a COP0 register. */ + OP_CP0SEL, +}; + +/* Enumerates the types of nanoMIPS register. */ +enum nanomips_reg_operand_type { + /* General registers $0-$31. Software names like $at can also be used. */ + OP_REG_GP, + + /* Floating-point registers $f0-$f31. */ + OP_REG_FP, + + /* DSP accumulator registers $ac0-$ac3. */ + OP_REG_ACC, + + /* Coprocessor registers in numeric format, $0-$31. */ + OP_REG_COPRO, + + /* Hardware registers $0-$31. Mnemonic names like hwr_cpunum can + also be used in some contexts. */ + OP_REG_HW, + + /* MSA registers $w0-$w31. */ + OP_REG_MSA, + + /* MSA control registers $0-$31. */ + OP_REG_MSA_CTRL, + + /* Co-processor 0 named registers. */ + OP_REG_CP0, + + /* Co-processor 0 named registers with select. */ + OP_REG_CP0SEL, + + /* Co-processor 0 named registers with select. */ + OP_REG_HWRSEL +}; + +/* Base class for all operands. */ +struct nanomips_operand +{ + /* The type of the operand. */ + enum nanomips_operand_type type; + + /* The operand occupies SIZE bits of the instruction, starting at LSB. */ + unsigned short size; + unsigned short lsb; + + /* These are used to split a value across two different + parts of the instruction encoding. */ + unsigned int size_top; + unsigned int lsb_top; +}; + +/* Describes an integer operand with a regular encoding pattern. */ +struct nanomips_int_operand +{ + struct nanomips_operand root; + + /* The low ROOT.SIZE bits of MAX_VAL encodes (MAX_VAL + BIAS) << SHIFT. + The cyclically previous field value encodes 1 << SHIFT less than that, + and so on. E.g. + + - for { { T, 4, L }, 14, 0, 0 }, field values 0...14 encode themselves, + but 15 encodes -1. + + - { { T, 8, L }, 127, 0, 2 } is a normal signed 8-bit operand that is + shifted left two places. + + - { { T, 3, L }, 8, 0, 0 } is a normal unsigned 3-bit operand except + that 0 encodes 8. + + - { { ... }, 0, 1, 3 } means that N encodes (N + 1) << 3. */ + unsigned int max_val; + int bias; + unsigned int shift; + + /* True if the operand should be printed as hex rather than decimal. */ + bool print_hex; +}; + +/* Uses a lookup table to describe a small integer operand. */ +struct nanomips_mapped_int_operand +{ + struct nanomips_operand root; + + /* Maps each encoding value to the integer that it represents. */ + const int *int_map; + + /* True if the operand should be printed as hex rather than decimal. */ + bool print_hex; +}; + +/* An operand that encodes the most significant bit position of a bitfield. + Given a bitfield that spans bits [MSB, LSB], some operands of this type + encode MSB directly while others encode MSB - LSB. Each operand of this + type is preceded by an integer operand that specifies LSB. + + The assembly form varies between instructions. For some instructions, + such as EXT, the operand is written as the bitfield size. For others, + such as EXTS, it is written in raw MSB - LSB form. */ +struct nanomips_msb_operand +{ + struct nanomips_operand root; + + /* The assembly-level operand encoded by a field value of 0. */ + int bias; + + /* True if the operand encodes MSB directly, false if it encodes + MSB - LSB. */ + bool add_lsb; + + /* The maximum value of MSB + 1. */ + unsigned int opsize; +}; + +/* Describes a single register operand. */ +struct nanomips_reg_operand +{ + struct nanomips_operand root; + + /* The type of register. */ + enum nanomips_reg_operand_type reg_type; + + /* If nonnull, REG_MAP[N] gives the register associated with encoding N, + otherwise the encoding is the same as the register number. */ + const unsigned char *reg_map; +}; + +/* Describes an operand that which must match a condition based on the + previous operand. */ +struct nanomips_check_prev_operand +{ + struct nanomips_operand root; + + bool greater_than_ok; + bool less_than_ok; + bool equal_ok; + bool zero_ok; +}; + +/* Describes an operand that encodes a pair of registers. */ +struct nanomips_reg_pair_operand +{ + struct nanomips_operand root; + + /* The type of register. */ + enum nanomips_reg_operand_type reg_type; + + /* Encoding N represents REG1_MAP[N], REG2_MAP[N]. */ + unsigned char *reg1_map; + unsigned char *reg2_map; +}; + +/* Describes an operand that is calculated relative to a base PC. + The base PC is usually the address of the following instruction, + but the rules for MIPS16 instructions like ADDIUPC are more complicated. */ +struct nanomips_pcrel_operand +{ + /* Encodes the offset. */ + struct nanomips_int_operand root; + + /* The low ALIGN_LOG2 bits of the base PC are cleared to give PC', + which is then added to the offset encoded by ROOT. */ + unsigned int align_log2 : 8; + + /* If INCLUDE_ISA_BIT, the ISA bit of the original base PC is then + reinstated. This is true for jumps and branches and false for + PC-relative data instructions. */ + unsigned int include_isa_bit : 1; + + /* If FLIP_ISA_BIT, the ISA bit of the result is inverted. + This is true for JALX and false otherwise. */ + unsigned int flip_isa_bit : 1; +}; + +/* This structure holds information for a particular instruction. */ + +struct nanomips_opcode +{ + /* The name of the instruction. */ + const char *name; + /* An optional suffix. */ + const char *suffix; + /* A string describing the arguments for this instruction. */ + const char *args; + /* The basic opcode for the instruction. When assembling, this + opcode is modified by the arguments to produce the actual opcode + that is used. If pinfo is INSN_MACRO, then this is 0. */ + unsigned long match; + /* If pinfo is not INSN_MACRO, then this is a bit mask for the + relevant portions of the opcode when disassembling. If the + actual opcode anded with the match field equals the opcode field, + then we have found the correct instruction. If pinfo is + INSN_MACRO, then this field is the macro identifier. */ + unsigned long mask; + /* For a macro, this is INSN_MACRO. Otherwise, it is a collection + of bits describing the instruction, notably any relevant hazard + information. */ + unsigned long pinfo; + /* A collection of additional bits describing the instruction. */ + unsigned long pinfo2; + /* A collection of bits describing the instruction sets of which this + instruction or macro is a member. */ + unsigned long membership; + /* A collection of bits describing the ASE of which this instruction + or macro is a member. */ + unsigned long ase; +}; + +/* Return true if the assembly syntax allows OPERAND to be omitted. */ + +static inline bool +nanomips_optional_operand_p (const struct nanomips_operand *operand) +{ + return (operand->type == OP_OPTIONAL_REG + || operand->type == OP_REPEAT_PREV_REG + || (operand->type != OP_INT + && operand->size == 0 + && operand->lsb == 0)); +} + +/* Return a version of INSN in which the field specified by OPERAND + has value UVAL. */ + +static inline unsigned int +nanomips_insert_operand (const struct nanomips_operand *operand, + unsigned int insn, unsigned int uval) +{ + unsigned int mask; + unsigned int size_bottom = operand->size - operand->size_top; + + mask = (1 << size_bottom) - 1; + insn &= ~(mask << operand->lsb); + insn |= (uval & mask) << operand->lsb; + + mask = (1 << operand->size_top) - 1; + insn &= ~(mask << operand->lsb_top); + insn |= ((uval & (mask << size_bottom)) >> size_bottom) << operand->lsb_top; + return insn; +} + +/* Extract OPERAND from instruction INSN. */ + +static inline unsigned int +nanomips_extract_operand (const struct nanomips_operand *operand, + unsigned int insn) +{ + unsigned int uval; + unsigned int size_bottom = operand->size - operand->size_top; + + uval = (insn >> operand->lsb_top) & ((1 << operand->size_top) - 1); + uval <<= size_bottom; + uval |= (insn >> operand->lsb) & ((1 << size_bottom) - 1); + return uval; +} + +/* UVAL is the value encoded by OPERAND. Return it in signed form. */ + +static inline int +nanomips_signed_operand (const struct nanomips_operand *operand, + unsigned int uval) +{ + unsigned int sign_bit, mask; + + mask = (1 << operand->size) - 1; + sign_bit = 1 << (operand->size - 1); + return ((uval + sign_bit) & mask) - sign_bit; +} + +/* Return the integer that OPERAND encodes as UVAL. */ + +static inline int +nanomips_decode_int_operand (const struct nanomips_int_operand *operand, + unsigned int uval) +{ + uval |= (operand->max_val - uval) & -(1 << operand->root.size); + uval += operand->bias; + uval <<= operand->shift; + return uval; +} + +/* Return the maximum value that can be encoded by OPERAND. */ + +static inline int +nanomips_int_operand_max (const struct nanomips_int_operand *operand) +{ + return (operand->max_val + operand->bias) << operand->shift; +} + +/* Return the minimum value that can be encoded by OPERAND. */ + +static inline int +nanomips_int_operand_min (const struct nanomips_int_operand *operand) +{ + unsigned int mask; + + mask = (1 << operand->root.size) - 1; + return nanomips_int_operand_max (operand) - (mask << operand->shift); +} + +/* Return the register that OPERAND encodes as UVAL. */ + +static inline int +nanomips_decode_reg_operand (const struct nanomips_reg_operand *operand, + unsigned int uval) +{ + if (operand->reg_map) + uval = operand->reg_map[uval]; + return uval; +} + +/* PC-relative operand OPERAND has value UVAL and is relative to BASE_PC. + Return the address that it encodes. */ + +static inline bfd_vma +nanomips_decode_pcrel_operand (const struct nanomips_pcrel_operand *operand, + bfd_vma base_pc, unsigned int uval) +{ + bfd_vma addr; + + addr = base_pc & -(1 << operand->align_log2); + addr += nanomips_decode_int_operand (&operand->root, uval); + if (operand->include_isa_bit) + addr |= base_pc & 1; + if (operand->flip_isa_bit) + addr ^= 1; + return addr; +} + +/* Describes an operand that encapsulates a mapped register with + a check against the previous operand. */ +struct nanomips_mapped_check_prev_operand +{ + struct nanomips_operand root; + + enum nanomips_reg_operand_type reg_type; + const unsigned char *reg_map; + + bool greater_than_ok; + bool less_than_ok; + bool equal_ok; + bool zero_ok; +}; + +/* Describes an operand that encapsulates a base register with + a check against the type of offset. */ +struct nanomips_base_check_offset_operand +{ + struct nanomips_operand root; + + enum nanomips_reg_operand_type reg_type; + + bool const_ok; + bool expr_ok; +}; + +/* Return true if MO is an instruction that requires 32-bit encoding. */ + +static inline bool +nanomips_opcode_32bit_p (const struct nanomips_opcode *mo) +{ + return mo->mask >> 16 != 0; +} + +static inline int +nanomips_operand_mask (const struct nanomips_operand *operand) +{ + unsigned int mask; + + mask = ((1 << operand->size_top) - 1) << operand->lsb_top; + mask |= ((1 << (operand->size - operand->size_top)) - 1) << operand->lsb; + return mask; +} + +/* Return the UVAL encoding of REGNO as OPERAND. */ + +static inline unsigned int +nanomips_encode_reg_operand (const struct nanomips_operand *operand, + int regno) +{ + unsigned int uval; + const unsigned int num_vals = 1 << operand->size; + const struct nanomips_reg_operand *reg_op + = (const struct nanomips_reg_operand *) operand; + + for (uval = 0; uval < num_vals; uval++) + if (reg_op->reg_map[uval] == regno) + break; + return uval; +} + + +/* Re-organize HI20 bits of OPERAND encoded as UVAL. */ + +#define SIGNEX_VALUE(OP) {OP_INT, (unsigned short)(OP->size - 1), 0, 0, 0} + +static inline int +nanomips_decode_hi20_operand (const struct nanomips_operand *operand, + unsigned int uval) +{ + const struct nanomips_operand op_ext = SIGNEX_VALUE (operand); + const struct nanomips_operand op_shuffle = {OP_INT, 19, 10, 10, 0}; + unsigned int low19 = nanomips_extract_operand (&op_shuffle, uval); + return nanomips_insert_operand (&op_ext, uval, low19); +} + +/* Decode HI20 signed integer. */ + +#define SIGNED_VALUE(OP) {OP_INT, OP->size, 0, 0, 0} + +static inline int +nanomips_decode_hi20_int_operand (const struct nanomips_operand *operand, + unsigned int uval) +{ + const struct nanomips_operand op_enc = SIGNED_VALUE (operand); + uval = nanomips_decode_hi20_operand (operand, uval); + return (nanomips_signed_operand (&op_enc, uval)); +} + +/* Decode HI20 PCREL */ + +#define PCREL_VALUE(OP) { { { OP_PCREL, OP->size, 0, 0, 0}, \ + (unsigned int)((1 << (OP->size - 1)) - 1), 0, 0, false}, 12, 0, 0} + +static inline bfd_vma +nanomips_decode_hi20_pcrel_operand (const struct nanomips_operand *operand, + bfd_vma base_pc, unsigned int uval) +{ + const struct nanomips_pcrel_operand pcrel_op = PCREL_VALUE (operand); + uval = nanomips_decode_hi20_operand (operand, uval); + return nanomips_decode_pcrel_operand (&pcrel_op, base_pc, uval << 12); +} + + +/* Return true if MO is an instruction that requires 48-bit encoding. */ + +static inline bool +opcode_48bit_p (const struct nanomips_opcode *mo) +{ + return ((mo->mask >> 16 == 0) + && ((mo->match >> 10) == 0x18)); +} + +/* These are the bits which may be set in the pinfo field of an + instructions, if it is not equal to INSN_MACRO. */ + +/* Writes to operand number N. */ +#define INSN_WRITE_SHIFT 0 +#define INSN_WRITE_1 0x00000001 +#define INSN_WRITE_2 0x00000002 +#define INSN_WRITE_ALL 0x00000003 +/* Reads from operand number N. */ +#define INSN_READ_SHIFT 2 +#define INSN_READ_1 0x00000004 +#define INSN_READ_2 0x00000008 +#define INSN_READ_3 0x00000010 +#define INSN_READ_ALL 0x0000001c +/* Modifies general purpose register 31. */ +#define INSN_WRITE_GPR_31 0x00000020 +/* Reads coprocessor register other than floating point register. */ +#define INSN_COP 0x00000040 +/* Instruction loads value from memory. */ +#define INSN_LOAD_MEMORY 0x00000080 +/* Reads the accumulator register. */ +#define INSN_READ_ACC 0x00000100 +/* Modifies the HI register. */ +#define INSN_WRITE_ACC 0x00000200 +/* Instruction stores value into memory. */ +#define INSN_STORE_MEMORY 0x00000400 +/* Instruction uses single precision floating point. */ +#define INSN_FP_S 0x00000800 +/* Instruction uses double precision floating point. */ +#define INSN_FP_D 0x00001000 +/* A user-defined instruction. */ +#define INSN_UDI 0x00002000 +/* Instruction is actually a macro. It should be ignored by the + disassembler, and requires special treatment by the assembler. */ +#define INSN_MACRO 0xffffffff + +/* These are the bits which may be set in the pinfo2 field of an + instruction. */ + +/* Instruction is a simple alias (I.E. "move" for daddu/addu/or) */ +#define INSN2_ALIAS 0x00000001 +/* Macro uses single-precision floating-point instructions. This should + only be set for macros. For instructions, FP_S in pinfo carries the + same information. */ +#define INSN2_M_FP_S 0x00000002 +/* Macro uses double-precision floating-point instructions. This should + only be set for macros. For instructions, FP_D in pinfo carries the + same information. */ +#define INSN2_M_FP_D 0x00000004 +/* Is an unconditional branch insn. */ +#define INSN2_UNCOND_BRANCH 0x00000008 +/* Is a conditional branch insn. */ +#define INSN2_COND_BRANCH 0x00000010 +/* This indicates delayed branch converted to compact branch. */ +#define INSN2_CONVERTED_TO_COMPACT 0x00000020 +/* Marks the LI macro expansion as special, temporary. */ +#define INSN2_MACRO 0x00000040 +/* Marks the legacy/downgraded MTTGPR format, temporary. */ +#define INSN2_MTTGPR_RC1 0x00000080 + +/* Masks used to mark instructions to indicate which MIPS ISA level + they were introduced in. INSN_ISA_MASK masks an enumeration that + specifies the base ISA level(s). The remainder of a 32-bit + word constructed using these macros is a bitmask of the remaining + INSN_* values below. */ + +#define INSN_ISA_MASK 0x00000003ul + +/* We cannot start at zero due to ISA_UNKNOWN below. */ +#define INSN_ISAN32R6 1 +#define INSN_ISAN64R6 2 + +#define ISA_UNKNOWN 0 /* Gas internal use. */ + +#define ISA_NANOMIPS32R6 INSN_ISAN32R6 +#define ISA_NANOMIPS64R6 INSN_ISAN64R6 + +/* CPU defines, use instead of hardcoding processor number. Keep this + in sync with bfd/archures.c in order for machine selection to work. */ +#define CPU_UNKNOWN 0 /* Gas internal use. */ + +#define CPU_NANOMIPS32R6 32 +#define CPU_NANOMIPS64R6 64 + +#define ISAF(X) (1 << (INSN_ISA##X - 1)) + +/* The same information in table form: bit INSN_ISA - 1 of index + INSN_UPTO - 1 is set if ISA Y includes ISA X. */ +static const unsigned int nanomips_isa_table[] = { + ISAF(N32R6), + ISAF(N32R6) | ISAF(N64R6) +}; +#undef ISAF + +/* DSP ASE */ +#define ASE_DSP 0x00000001 +#define ASE_DSP64 0x00000002 +/* Enhanced VA Scheme */ +#define ASE_EVA 0x00000004 +/* MCU (MicroController) ASE */ +#define ASE_MCU 0x00000008 +/* MT ASE */ +#define ASE_MT 0x00000010 +/* Virtualization ASE */ +#define ASE_VIRT 0x00000020 +#define ASE_VIRT64 0x00000040 +/* MSA Extension */ +#define ASE_MSA 0x00000080 +#define ASE_MSA64 0x00000100 +/* Cyclic redundancy check (CRC) ASE */ +#define ASE_CRC 0x00000200 +#define ASE_CRC64 0x00000400 +/* Global INValidate Extension. */ +#define ASE_GINV 0x00000800 +/* The Virtualization ASE has Global INValidate extension instructions + which are only valid when both ASEs are enabled. */ +#define ASE_GINV_VIRT 0x00001000 +/* Excluded for low power instruction subset for nanoMIPS. */ +#define ASE_xNMS 0x00002000 +/* TLB control ASE. */ +#define ASE_TLB 0x00004000 + +static inline bool +nanomips_cpu_is_member (int cpu, unsigned int mask) +{ + switch (cpu) + { + case CPU_NANOMIPS32R6: + return (mask & INSN_ISA_MASK) == INSN_ISAN32R6; + + case CPU_NANOMIPS64R6: + return ((mask & INSN_ISA_MASK) == INSN_ISAN32R6) + || ((mask & INSN_ISA_MASK) == INSN_ISAN64R6); + + default: + return false; + } +} + +/* Test for membership in an ISA including chip specific ISAs. INSN + is pointer to an element of the opcode table; ISA is the specified + ISA/ASE bitmask to test against; and CPU is the CPU specific ISA to + test, or zero if no CPU specific ISA test is desired. Return true + if instruction INSN is available to the given ISA and CPU. */ +static inline bool +nanomips_opcode_is_member (const struct nanomips_opcode *insn, + int isa, int ase, int cpu) +{ + /* Test for ISA level compatibility. */ + if ((isa & INSN_ISA_MASK) != 0 + && (insn->membership & INSN_ISA_MASK) != 0 + && ((nanomips_isa_table[(isa & INSN_ISA_MASK) - 1] + >> ((insn->membership & INSN_ISA_MASK) - 1)) & 1) != 0) + return true; + + /* Test for ASE compatibility. */ + if (insn->ase != 0 && (ase & insn->ase) == insn->ase) + return true; + + /* Test for processor-specific extensions. */ + if (nanomips_cpu_is_member (cpu, insn->membership)) + return true; + + return false; +} + +/* This is a list of macro expanded instructions. + + _I appended means immediate + _A appended means target address of a jump + _AB appended means address with (possibly zero) base register + _AC appended means either symbolic address with no base register + or constant offset with base register. + _D appended means 64 bit floating point constant + _S appended means 32 bit floating point constant. */ + +enum +{ + M_ABS, + M_ACLR_AC, + M_ADD_I, + M_ADDU_I, + M_AND_I, + M_ASET_AC, + M_BEQ, + M_BEQ_I, + M_BGE, + M_BGE_I, + M_BGEU, + M_BGEU_I, + M_BGEZ, + M_BGT, + M_BGT_I, + M_BGTU, + M_BGTU_I, + M_BGTZ, + M_BLE, + M_BLE_I, + M_BLEU, + M_BLEU_I, + M_BLEZ, + M_BLT, + M_BLT_I, + M_BLTU, + M_BLTU_I, + M_BLTZ, + M_BNE, + M_BNE_I, + M_CACHE_AC, + M_CACHEE_AC, + M_DABS, + M_DADD_I, + M_DADDU_I, + M_DLA_AB, + M_DLI, + M_DMUL, + M_DMUL_I, + M_DSUB_I, + M_DSUBU_I, + M_J_A, + M_JAL_A, + M_JRADDIUSP, + M_LA_AB, + M_LB_AC, + M_LBE_AC, + M_LBU_AC, + M_LBUE_AC, + M_LBX_AB, + M_LBUX_AB, + M_LD_AC, + M_LDC1_AC, + M_LDC1X_AB, + M_LDC2_AC, + M_LDM_AC, + M_LDX_AB, + M_LH_AC, + M_LHE_AC, + M_LHU_AC, + M_LHUE_AC, + M_LHUX_AB, + M_LHX_AB, + M_LI, + M_LI_D, + M_LI_DD, + M_LI_S, + M_LI_SS, + M_LL_AC, + M_LLD_AC, + M_LLE_AC, + M_LLDP_AC, + M_LLWP_AC, + M_LW_AC, + M_LWC1_AC, + M_LWC1X_AB, + M_LWC2_AC, + M_LWE_AC, + M_LWM_AC, + M_LWU_AC, + M_LWUX_AB, + M_LWX_AB, + M_MUL, + M_MUL_I, + M_NOR_I, + M_OR_I, + M_PREF_AC, + M_PREFE_AC, + M_REM_3I, + M_DROL, + M_ROL, + M_DROL_I, + M_ROL_I, + M_ROR_I, + M_SC_AC, + M_SCD_AC, + M_SCE_AC, + M_SCDP_AC, + M_SCWP_AC, + M_SD_AC, + M_SDC1_AC, + M_SDC1X_AB, + M_SDC2_AC, + M_SDM_AC, + M_SDX_AB, + M_SEQ, + M_SEQ_I, + M_SGE, + M_SGE_I, + M_SGEU, + M_SGEU_I, + M_SGT, + M_SGT_I, + M_SGTU, + M_SGTU_I, + M_SLE, + M_SLE_I, + M_SLEU, + M_SLEU_I, + M_SLT_I, + M_SLTU_I, + M_SNE, + M_SNE_I, + M_SB_AC, + M_SBE_AC, + M_SBX_AB, + M_SH_AC, + M_SHE_AC, + M_SHX_AB, + M_SW_AC, + M_SWE_AC, + M_SWX_AB, + M_SWC1_AC, + M_SWC1X_AB, + M_SWC2_AC, + M_SWM_AC, + M_SUB_I, + M_SUBU_I, + M_TEQ_I, + M_TNE_I, + M_ULD_AC, + M_ULH_AC, + M_ULW_AC, + M_USH_AC, + M_USW_AC, + M_USD_AC, + M_XOR_I, + M_BGEZAL, + M_BLTZAL, + M_EXT, + M_INS, + M_MOD_I, + M_MODU_I, + M_DMOD_I, + M_DMODU_I, + M_DIV_I, + M_DIVU_I, + M_DDIV_I, + M_DDIVU_I, + M_NANOMIPS_NUM_MACROS +}; + +/* These are the bit masks and shift counts used for the different fields + in the nanoMIPS instruction formats. No masks are provided for the + fixed portions of an instruction, since they are not needed. */ + +#define NANOMIPSOP_MASK_RS 0x1f +#define NANOMIPSOP_SH_RS 16 +#define NANOMIPSOP_MASK_RT 0x1f +#define NANOMIPSOP_SH_RT 21 +#define NANOMIPSOP_MASK_RD 0x1f +#define NANOMIPSOP_SH_RD 11 +#define NANOMIPSOP_SH_ME 1 +#define NANOMIPSOP_SH_MC 4 +#define NANOMIPSOP_SH_MD 7 +#define NANOMIPSOP_SH_MP 5 +#define NANOMIPSOP_SH_MM 7 + +#define NANOMIPSOP_SH_CP0SEL 5 +#define NANOMIPSOP_MASK_CP0SEL 0x1f +#define NANOMIPSOP_SH_HWRSEL 5 +#define NANOMIPSOP_MASK_HWRSEL 0x1f + +/* Describes a COP0 named register with a fixed select. */ +struct nanomips_cp0_name +{ + const char *name; + unsigned int num; + unsigned int sel; +}; + +/* The reference list of COP0 named register with fixed selects. */ +static const struct nanomips_cp0_name nanomips_cp0_3264r6[] = { + {"$index", 0, 0}, + {"$mvpcontrol", 0, 1}, + {"$mvpconf0", 0, 2}, + {"$mvpconf1", 0, 3}, + {"$vpcontrol", 0, 4}, + {"$random", 1, 0}, + {"$vpecontrol", 1, 1}, + {"$vpeconf0", 1, 2}, + {"$vpeconf1", 1, 3}, + {"$yqmask", 1, 4}, + {"$vpeschedule", 1, 5}, + {"$vpeschefback", 1, 6}, + {"$vpeopt", 1, 7}, + {"$entrylo0", 2, 0}, + {"$tcstatus", 2, 1}, + {"$tcbind", 2, 2}, + {"$tcrestart", 2, 3}, + {"$tchalt", 2, 4}, + {"$tccontext", 2, 5}, + {"$tcschedule", 2, 6}, + {"$tcschefback", 2, 7}, + {"$entrylo1", 3, 0}, + {"$globalnumber", 3, 1}, + {"$tcopt", 3, 7}, + {"$context", 4, 0}, + {"$contextconfig", 4, 1}, + {"$userlocal", 4, 2}, + {"$xcontextconfig", 4, 3}, + {"$debugcontextid", 4, 4}, + {"$memorymapid", 4, 5}, + {"$pagemask", 5, 0}, + {"$pagegrain", 5, 1}, + {"$segctl0", 5, 2}, + {"$segctl1", 5, 3}, + {"$segctl2", 5, 4}, + {"$pwbase", 5, 5}, + {"$pwfield", 5, 6}, + {"$pwsize", 5, 7}, + {"$wired", 6, 0}, + {"$srsconf0", 6, 1}, + {"$srsconf1", 6, 2}, + {"$srsconf2", 6, 3}, + {"$srsconf3", 6, 4}, + {"$srsconf4", 6, 5}, + {"$pwctl", 6, 6}, + {"$hwrena", 7, 0}, + {"$badvaddr", 8, 0}, + {"$badinst", 8, 1}, + {"$badinstrp", 8, 2}, + {"$badinstrx", 8, 3}, + {"$count", 9, 0}, + {"$entryhi", 10, 0}, + {"$guestctl1", 10, 4}, + {"$guestctl2", 10, 5}, + {"$guestctl3", 10, 6}, + {"$compare", 11, 0}, + {"$guestctl0ext", 11, 4}, + {"$status", 12, 0}, + {"$intctl", 12, 1}, + {"$srsctl", 12, 2}, + {"$srsmap", 12, 3}, + {"$view_ipl", 12, 4}, + {"$srsmap2", 12, 5}, + {"$guestctl0", 12, 6}, + {"$gtoffset", 12, 7}, + {"$cause", 13, 0}, + {"$view_ripl", 13, 4}, + {"$nestedexc", 13, 5}, + {"$epc", 14, 0}, + {"$nestedepc", 14, 2}, + {"$prid", 15, 0}, + {"$ebase", 15, 1}, + {"$cdmmbase", 15, 2}, + {"$cmgcrbase", 15, 3}, + {"$bevva", 15, 4}, + {"$config", 16, 0}, + {"$config1", 16, 1}, + {"$config2", 16, 2}, + {"$config3", 16, 3}, + {"$config4", 16, 4}, + {"$config5", 16, 5}, + {"$lladdr", 17, 0}, + {"$maar", 17, 1}, + {"$maari", 17, 2}, + {"$watchlo0", 18, 0}, + {"$watchlo1", 18, 1}, + {"$watchlo2", 18, 2}, + {"$watchlo3", 18, 3}, + {"$watchlo4", 18, 4}, + {"$watchlo5", 18, 5}, + {"$watchlo6", 18, 6}, + {"$watchlo7", 18, 7}, + {"$watchlo8", 18, 8}, + {"$watchlo9", 18, 9}, + {"$watchlo10", 18, 10}, + {"$watchlo11", 18, 11}, + {"$watchlo12", 18, 12}, + {"$watchlo13", 18, 13}, + {"$watchlo14", 18, 14}, + {"$watchlo15", 18, 15}, + {"$watchhi0", 19, 0}, + {"$watchhi1", 19, 1}, + {"$watchhi2", 19, 2}, + {"$watchhi3", 19, 3}, + {"$watchhi4", 19, 4}, + {"$watchhi5", 19, 5}, + {"$watchhi6", 19, 6}, + {"$watchhi7", 19, 7}, + {"$watchhi8", 19, 8}, + {"$watchhi9", 19, 9}, + {"$watchhi10", 19, 10}, + {"$watchhi11", 19, 11}, + {"$watchhi12", 19, 12}, + {"$watchhi13", 19, 13}, + {"$watchhi14", 19, 14}, + {"$watchhi15", 19, 15}, + {"$xcontext", 20, 0}, + {"$debug", 23, 0}, + {"$tracecontrol", 23, 1}, + {"$tracecontrol2", 23, 2}, + {"$usertracedata1", 23, 3}, + {"$traceibpc", 23, 4}, + {"$tracedbpc", 23, 5}, + {"$debug2", 23, 6}, + {"$depc", 24, 0}, + {"$tracecontrol3", 24, 2}, + {"$usertracedata2", 24, 3}, + {"$perfctl0", 25, 0}, + {"$perfcnt0", 25, 1}, + {"$perfctl1", 25, 2}, + {"$perfcnt1", 25, 3}, + {"$perfctl2", 25, 4}, + {"$perfcnt2", 25, 5}, + {"$perfctl3", 25, 6}, + {"$perfcnt3", 25, 7}, + {"$perfctl4", 25, 8}, + {"$perfcnt4", 25, 9}, + {"$perfctl5", 25, 10}, + {"$perfcnt5", 25, 11}, + {"$perfctl6", 25, 12}, + {"$perfcnt6", 25, 13}, + {"$perfctl7", 25, 14}, + {"$perfcnt7", 25, 15}, + {"$errctl", 26, 0}, + {"$cacheerr", 27, 0}, + {"$itaglo", 28, 0}, + {"$idatalo", 28, 1}, + {"$dtaglo", 28, 2}, + {"$ddatalo", 28, 3}, + {"$itaghi", 29, 0}, + {"$idatahi", 29, 1}, + {"$dtaghi", 29, 2}, + {"$ddatahi", 29, 3}, + {"$errorepc", 30, 0}, + {"$desave", 31, 0}, + {"$kscratch1", 31, 2}, + {"$kscratch2", 31, 3}, + {"$kscratch3", 31, 4}, + {"$kscratch4", 31, 5}, + {"$kscratch5", 31, 6}, + {"$kscratch6", 31, 7}, + {NULL, 0, 0} +}; + +/* Describes a CP0 named register which permits various select values. */ + struct nanomips_cp0_select +{ + const char *name; + unsigned int num; + unsigned int selmask; +}; + +/* Currently recognized CP0 select patterns. */ + +#define NANOMIPS_CP0SEL_MASK_EVEN 0x55555555 +#define NANOMIPS_CP0SEL_MASK_ODD 0xaaaaaaaa +#define NANOMIPS_CP0SEL_MASK_ANY 0xffffffff +#define NANOMIPS_CP0SEL_MASK_EVEN16 0x5555 +#define NANOMIPS_CP0SEL_MASK_ODD16 0xaaaa +#define NANOMIPS_CP0SEL_MASK_ANY16 0xffff + +/* The reference list of CP0 named register with variable selects. */ +static const struct nanomips_cp0_select nanomips_cp0sel_3264r6[] = { + {"$watchlo", 18, NANOMIPS_CP0SEL_MASK_ANY16}, + {"$watchhi", 19, NANOMIPS_CP0SEL_MASK_ANY16}, + {"$perfctl", 25, NANOMIPS_CP0SEL_MASK_EVEN16}, + {"$perfcnt", 25, NANOMIPS_CP0SEL_MASK_ANY16}, + {"$taglo", 28, NANOMIPS_CP0SEL_MASK_EVEN}, + {"$datalo", 28, NANOMIPS_CP0SEL_MASK_ODD}, + {"$taghi", 29, NANOMIPS_CP0SEL_MASK_EVEN}, + {"$datahi", 29, NANOMIPS_CP0SEL_MASK_ODD}, + {NULL, 0, 0} +}; + + +/* Describes a HWR named register with a fixed select. If the HWR name + is remapped from an existing CP0 register name, its cp0_num and cp0_sel + fields will provide the mapping, else they will both be invalid. */ + +struct nanomips_hwr_name +{ + const char *name; + unsigned int num; + unsigned int sel; + unsigned int cp0_num; + unsigned int cp0_sel; +}; + +#define INV_RNUM 0xffffffff +#define INV_SEL 0xffffffff + + /* The reference list of named hardware register with fixed selects. */ +static const struct nanomips_hwr_name nanomips_hwr_names_3264r6[] = { + {"$cpunum", 0, 0, INV_RNUM, INV_SEL}, + {"$synci_step", 1, 0, INV_RNUM, INV_SEL}, + {"$cc", 2, 0, 9, 0}, + {"$count", 2, 0, 9, 0}, + {"$ccres", 3, 0, INV_RNUM, INV_SEL}, + {"$perfctl0", 4, 0, 25, 0}, + {"$perfcnt0", 4, 1, 25, 1}, + {"$perfctl1", 4, 2, 25, 2}, + {"$perfcnt1", 4, 3, 25, 3}, + {"$perfctl2", 4, 4, 25, 4}, + {"$perfcnt2", 4, 5, 25, 5}, + {"$perfctl3", 4, 6, 25, 6}, + {"$perfcnt3", 4, 7, 25, 7}, + {"$perfctl4", 4, 8, 25, 8}, + {"$perfcnt4", 4, 9, 25, 9}, + {"$perfctl5", 4, 10, 25, 10}, + {"$perfcnt5", 4, 11, 25, 11}, + {"$perfctl6", 4, 12, 25, 12}, + {"$perfcnt6", 4, 13, 25, 13}, + {"$perfctl7", 4, 14, 25, 14}, + {"$perfcnt7", 4, 15, 25, 15}, + {"$perfctl", 4, 0, 25, 0}, + {"$perfcnt", 4, 1, 25, 1}, + {"$xnp", 5, 0, INV_RNUM, INV_SEL}, + {"$userlocal", 29, 0, 4, 2}, + {NULL, 0, 0, INV_RNUM, INV_SEL} +}; + +#define NANOMIPS_CP0SEL_PERFCNT 25 +#define NANOMIPS_HWRSEL_PERFCNT 4 + +/* Don't care stubs in operand formats need special handling. */ +#define NANOMIPS_MIN_DONTCARE_FMT 'A' +#define NANOMIPS_MAX_DONTCARE_FMT 'Q' + +#define IS_NANOMIPS_DONTCARE_FMT(x) ((x)[0] == '-' \ + && (x)[1] >= NANOMIPS_MIN_DONTCARE_FMT \ + && (x)[1] <= NANOMIPS_MAX_DONTCARE_FMT) + +/* These are the characters which may appears in the args field of a nanoMIPS + instruction. They appear in the order in which the fields appear when the + instruction is used. Commas and parentheses in the args string are ignored + when assembling, and written into the output when disassembling. + + Operands for 16-bit nanoMIPS instructions. + + "ma" must be $28 + "mb" 5-bit non-zero GP register at bit 5 + "mc" 3-bit nanoMIPS registers 4-7, 16-19 bit 4 + The same register used as both source and target. + "md" 3-bit nanoMIPS registers 4-7, 16-19 at bit 7 + "me" 3-bit nanoMIPS registers 4-7, 16-19 at bit 1 + "mf" 3-bit nanoMIPS register 4-7, 16-19 at bit 7. + Must be larger than the last seen register. + "mg" 3-bit nanoMIPS register 4-7, 16-19 at bit 4. + Must be smaller than the last seen register. + "mh" 3-bit nanoMIPS register 4-7, 16-19 at bit 7. + Must be at least as large as the last seen register. + "mi" 3-bit nanoMIPS register 4-7, 16-19 at bit 4. + May be at most as large as the last seen register. + + "mj" 5-bit nanoMIPS registers at bit 0 + "mk" must be the same as the destination register + "ml" 3-bit nanoMIPS registers 4-7, 16-19 at bit 4 + "mm" 3-bit nanoMIPS registers 0, 4-7, 17-19 at bit 7 + "mn" 5-bit encoding of a save/restore register list + "mp" 5-bit nanoMIPS registers at bit 5 + "mq" 2-bit pair at bits [8,3] maps to ($a0,$a1), ($a1,$a2), ($a2,$a3) + or ($a3,$a4) + "mr" 2-bit pair at bits [8,3] maps to ($a1,$a0), ($a2,$a1), ($a3,$a2) + or ($a4,$a3) + "ms" must be $29 + "mt" must be the same as the previous register + "mu" 4-bit encoding of nanoMIPS destination register at bit 5 + "mv" 4-bit encoding of nanoMIPS destination register at bit 0 + "mw" 4-bit encoding of nanoMIPS source register at bit 5 + "mx" 4-bit encoding of nanoMIPS source register at bit 0 + "my" must be $31 + "mz" must be literal 0 + + "mA" 7-bit relocatable GP offset (0 .. 127) << 2 + "mB" 3-bit immediate at bit 0 (0, 4, 8, 12, 16, 20, 24, 28) + "mC" 4-bit immediate at bit 0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 65535, 14, 15) + "mD" 10-bit signed branch address, split & scaled at bit 0 [S9:1,S10] + "mE" 7-bit signed branch address, split & scaled at bit 0 [S6:1,S7] + "mF" 4-bit unsigned branch address, scaled at bit 0 [U4:U1] + "mG" 4-bit scaled immediate at bit 4, (0 .. 15) << 4 + "mH" 2-bit scaled immediate at bit 1, (0 .. 3) << 1 + "mI" 7-bit immediate at bit 0, (-1 .. 126) + "mJ" 4-bit scaled immediate at bit 0, (0 .. 15) << 2 + "mK" 3-bit BREAK/SDBBP code at bit 0 + "mL" 2-bit immediate at bit 0, (0 .. 3) + "mM" 3-bit immediate at bit 0, (1 .. 8) + "mN" 2-bit split scaled immediate at bits 8 & 3 (0 .. 3) << 2 + "mO" 7-bit immediate GP offset at bit 0, (0 .. 127) << 2 + "mP" 2-bit SYSCALL/HYPCALL code at bit 0 + "mQ" 4-bit immediate signed offset, (s3,s2:s0) + "mR" 5-bit immediate at bit 0, (0 .. 31) << 2 + "mS" 6-bit immediate at bit 0, (0 .. 63) << 2 + "mZ" must be zero + + Operands for 32-bit nanoMIPS instructions. + + "+1" 18-bit unsigned GP-relative offset, (u17:u0) + "+2" 18-bit scaled GP-relative offset, (u18:u2) << 2 + "+3" 21-bit scaled GP-relative offset, (u18:u1) << 1 + "+4" 18-bit GP-relative offset, (0 .. 2^18-1) << 3 + "+5" 4-bit encoding of nanoMIPS source register at bit 21 + "+6" 5-bit mask encoding, corresponding to (1 << X) - 1 + "+7" 1-bit register at bit 24, (0,1) => ($a0,$a1) + "+8" 23-bit un-spec'ed value at bit 3 for UDIs. + "+9" 7-bit immediate at bit 11, (0 .. 127) + + "+A" 5-bit INS/EXT/DINS/DEXT/DINSM/DEXTM position, which becomes + LSB. + "+B" 5-bit INS/DINS size, which becomes MSB + Requires that "+A" or "+E" occur first to set position. + Enforces: 0 < (pos+size) <= 32. + "+C" 5-bit EXT/DEXT size, which becomes MSBD. + Requires that "+A" or "+E" occur first to set position. + Enforces: 0 < (pos+size) <= 32. + "+D" 4-bit encoding of a floating point save/restore register list + "+E" 5-bit DINSU/DEXTU position, which becomes LSB-32. + "+F" 5-bit DINSM/DINSU size, which becomes MSB-32. + Requires that "+A" or "+E" occur first to set position. + Enforces: 32 < (pos+size) <= 64. + "+G" 5-bit DEXTM size, which becomes MSBD-32. + Requires that "+A" or "+E" occur first to set position. + Enforces: 32 < (pos+size) <= 64. + "+H" 5-bit DEXTU size, which becomes MSBD. + Requires that "+A" or "+E" occur first to set position. + Enforces: 32 < (pos+size) <= 64. + "+I" 5-bit EXTW/EXTD/PREPEND position, which becomes LSB. + "+J" 19-bit BREAK/SDBBP function code at bit 0 + "+K" Tri-part upper 20-bits of immediate value. + "+L" 10-bit WAIT code at bit 16 + "+M" 18-bit SYSCALL/HYPCALL code at bit 0 + "+N" 9-bit immediate at bit 3, (0 .. 511) << 3 + + "+i" 5-bit SYNC code type at bit 16, (0..31) + "+j" 9-bit signed offset (s7:s0,s8), (-256 .. 255) + "+k" 5-bit nanoMIPS registers at bit 3 + "+p" 9-bit scaled signed offset, (s7:s2) << 2 for LL/SC* + "+q" 9-bit scaled signed offset, (s7:s3) << 3 for LLD/SCD* + "+r" 21-bit PC-relative branch offset (s19:s1,s20) << 1 + "+s" 21-bit immediate offset for PC-relative operation ((s19:s1,s20) + 2) << 1 + "+t" 5-bit non-zero GP register at bit 21 + "+u" 25-bit PC-relative branch offset (s24:s1,s25) << 1 + "+v" 5-bit mapping of R6 ALIGN byte-wise shift to EXTW bit-wise shift. + "+w" 2-bit shift for scaled address calculation at bit 9, (0..3) + "+*" 4-bit ROTX shift at bit 7, (0 .. 15) << 1 + "+|" 1-bit ROTX stripe at bit 6, (0 .. 1) + + "." 21-bit scaled GP-relative offset, (u21:u2) << 2 + "<" 5-bit immediate shift value for bit operations, (0..31) + "|" 3-bit Element count for load/store multiple, (1..8) + "~" 11-bit branch offset, (s9:s1,s10) << 1 + "^" 5-bit trap code at bit 11, (0..31) + "b" 5-bit base register at bit 16 for label or symbolic offsets + "c" 5-bit base register at bit 16, either used with immediate offset + or skipped with symbolic offset. + "d" 5-bit destination register specifier at bit 11 + "g" 12-bit unsigned immediate at bit 0, (0..4095) + "h" 12-bit negative immediate at bit 0, (-4095..0) + "i" 12-bit unsigned immediate at bit 0, (0..4095) + "j" 16-bit unsigned immediate at bit 0, (0..65535) + "k" 5-bit cache operation code at bit 21, (0..31) + "n" 11-bit encoding of save/restore register list + "o" 12-bit offset at bit 0, (0..4095) + "p" 14-bit PC-relative branch offset (s13:s1,s14) << 1 + "r" 5-bit same register at bit 16, used as both source and target + "s" 5-bit source register specifier at bit 16 + "t" 5-bit target register specifier at bit 21 + "u" Tri-part upper 20 bits of address + "x" Tri-part upper 20 bits of address, scaled by 12 bits + "v" 5-bit same register used as both source and destination at bit 15 + "w" 5-bit same register used as both target and destination at bit 21 + "z" must be zero register + + Used in special matching contexts: + "-A" 5 don't care bits at bit 16 + "-B" 1 don't care bit at bit 10 + "-C" 12 don't care bits at bit 0 + "-D" 1 don't care bit at bit 17 + "-E" 3 don't care bits at bit 13 + "-F" 10 don't care bits at bit 16 + "-G" 8 split don't care bits, 3 at bit 9 and 5 at bit 7 + "-H" 9 don't care bits at bit 17 + "-I" 5 don't care bits at bit 21 + "-J" 3 don't care bits at bit 23 + "-K" 2 split don't care bits, 1 at bit 2 and 1 at bit 15 + "-L" 3 don't care bits at bit 6 + "-M" 3 don't care bits at bit 9 + "-N" 6 don't care bits at bit 10 + "-O" 1 don't care bit at bit 12 + "-P" 8 split don't care bits, 4 at bit 10 and 4 at bit 22 + "-Q" 1 don't care bit at bit 11 + + "-i" Ignored register operand, internally used for macro expansions. + "-m" Place-holder to copy 5 bits from bit 11 to bit 21 + "-n" Place-holder to copy 5 bits from bit 11 to bit 16 + + Exclusively for 48-bit nanoMIPS instructions: + + "+O" Signed GP-relative 32-bit offset in instruction byte order + "+P" Immediate signed 32-bit value in instruction byte order + "+Q" Unsigned 32-bit value or address in instruction byte order + "+R" Signed 32-bit value in instruction byte order + "+S" Signed PC-relative 32-bit offset in instruction byte order + + DSP instructions: + "0" 5-bit shift value for DSP accumulator at bit 16, (0..63) + "1" 5-bit position for DSP bit operations at bit 11 + "2" 5-bit size for DSP bit operations at bit 16 + "3" 3-bit byte vector shift at bit 13, (0..7) + "4" 4-bit hword vector shift at bit 12, (0..15) + "5" 8-bit unsigned immediate at bit 13, (0..255) + "7" 2-bit DSP accumulator register at bit 14, (0..3) + "8" 7-bit DSP control mask at bit 14, (0x3f) + "@" 10-bit signed immediate at bit 11, (0..1023) + + Coprocessor instructions: + "E" 5-bit target register + "G" 5-bit source register + "H" 5-bit sel field for (D)MTC* and (D)MFC* + "J" 5-bit select code at bit 11 for named COP1 registers, (0..31) + "K" 10-bit register+select encoding at bit 11 for named h/w register + "O" 10-bit register+select encoding at bit 11 for named COP1 register + "P" 5-bit named COP1 register at bit 16 + "Q" 5-bit select code at bit 11 + "U" 5-bit named HW register at bit 16 + + MT instructions: + "!" 1-bit u-mode for move to/from thread registers at bit 10, (0,1) + "$" 1-bit high-mode for move to/from thread registers at bit 3, (0,1) + "*" 2-bit accumulator register at bit 18, (0..3) + + GINV instructions + "+;" 2-bit global invalidate operation type at bit 21, (0..3) + + Floating point instructions: + "D" 5-bit destination register + "R" 5-bit fr destination register + "S" 5-bit fs source 1 register + "T" 5-bit ft source 2 register + "V" 5-bit same register used as floating source and destination or target + + Macro instructions: + "A" general 32 bit expression + "I" 32-bit immediate (value placed in imm_expr). + "F" 64-bit floating point constant in memory + "L" 64-bit floating point constant in memory + "f" 32-bit floating point constant in memory + "l" 32-bit floating point constant in memory + + CP2 instructions: + "C" 23-bit coprocessor function code at bit 3 + + MCU instructions: + "\" 3-bit position for atomic set/clear operations, (0..7) + + + Other: + "()" parens surrounding optional value + "," separates operands + "+" start of extension sequence + + Characters used so far, for quick reference when adding more: + "12345 78 0" + ".<\|~@^!$*" + "A CDEFGHIJKL OP RSTUV " + " bcde ghijk nop rstuvwx z" + + Extension character sequences used so far ("+" followed by the + following), for quick reference when adding more: + "123456789 + "*|;" + "ABCDEFGHIJKLMNOPQRS " + " ij pqrstuvw " + + Extension character sequences used so far ("m" followed by the + following), for quick reference when adding more: + "" + "" + "ABCDEFGHIJKLMNOPQRS Z" + "abcdefghijklmn pqrstuvwxyz" + + Extension character sequences used so far ("-" followed by the + following), for quick reference when adding more: + "" + "" + "ABCDEFGHIJKLMNOPQ " + " i mn " +*/ + +extern const struct nanomips_operand *decode_nanomips_operand (const char *); +extern const struct nanomips_opcode nanomips_opcodes[]; +extern const int bfd_nanomips_num_opcodes; + +#ifdef __cplusplus +} +#endif + +#endif /* _NANOMIPS_H_ */ diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am index 578fdc056c5..242fb95df04 100644 --- a/opcodes/Makefile.am +++ b/opcodes/Makefile.am @@ -214,6 +214,8 @@ TARGET32_LIBOPCODES_CFILES = \ mt-dis.c \ mt-ibld.c \ mt-opc.c \ + nanomips-dis.c \ + nanomips-opc.c \ nds32-asm.c \ nds32-dis.c \ nios2-dis.c \ diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in index 2db307e8d7c..3f60ed59ca4 100644 --- a/opcodes/Makefile.in +++ b/opcodes/Makefile.in @@ -597,6 +597,12 @@ TARGET32_LIBOPCODES_CFILES = \ mep-opc.c \ metag-dis.c \ microblaze-dis.c \ + micromips-opc.c \ + mips-dis.c \ + mips-opc.c \ + mips16-opc.c \ + mmix-dis.c \ + mmix-opc.c \ moxie-dis.c \ moxie-opc.c \ msp430-decode.c \ @@ -606,6 +612,8 @@ TARGET32_LIBOPCODES_CFILES = \ mt-dis.c \ mt-ibld.c \ mt-opc.c \ + nanomips-dis.c \ + nanomips-opc.c \ nds32-asm.c \ nds32-dis.c \ nios2-dis.c \ @@ -991,6 +999,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mt-dis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mt-ibld.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mt-opc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nanomips-dis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nanomips-opc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32-asm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nds32-dis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfp-dis.Plo@am__quote@ diff --git a/opcodes/configure b/opcodes/configure index 8717d99ca26..8c8bb61f63a 100755 --- a/opcodes/configure +++ b/opcodes/configure @@ -12558,6 +12558,7 @@ if test x${all_targets} = xfalse ; then bfd_mn10300_arch) ta="$ta m10300-dis.lo m10300-opc.lo" ;; bfd_mt_arch) ta="$ta mt-asm.lo mt-desc.lo mt-dis.lo mt-ibld.lo mt-opc.lo" using_cgen=yes ;; bfd_msp430_arch) ta="$ta msp430-dis.lo msp430-decode.lo" ;; + bfd_nanomips_arch) ta="$ta nanomips-dis.lo nanomips-opc.lo" ;; bfd_nds32_arch) ta="$ta nds32-asm.lo nds32-dis.lo" ;; bfd_nfp_arch) ta="$ta nfp-dis.lo" ;; bfd_nios2_arch) ta="$ta nios2-dis.lo nios2-opc.lo" ;; diff --git a/opcodes/configure.ac b/opcodes/configure.ac index 1beb72e87e0..2efb1338b36 100644 --- a/opcodes/configure.ac +++ b/opcodes/configure.ac @@ -306,6 +306,7 @@ if test x${all_targets} = xfalse ; then bfd_mn10300_arch) ta="$ta m10300-dis.lo m10300-opc.lo" ;; bfd_mt_arch) ta="$ta mt-asm.lo mt-desc.lo mt-dis.lo mt-ibld.lo mt-opc.lo" using_cgen=yes ;; bfd_msp430_arch) ta="$ta msp430-dis.lo msp430-decode.lo" ;; + bfd_nanomips_arch) ta="$ta nanomips-dis.lo nanomips-opc.lo" ;; bfd_nds32_arch) ta="$ta nds32-asm.lo nds32-dis.lo" ;; bfd_nfp_arch) ta="$ta nfp-dis.lo" ;; bfd_nios2_arch) ta="$ta nios2-dis.lo nios2-opc.lo" ;; diff --git a/opcodes/dis-buf.c b/opcodes/dis-buf.c index b3f7c981312..3edf4675932 100644 --- a/opcodes/dis-buf.c +++ b/opcodes/dis-buf.c @@ -99,3 +99,12 @@ generic_symbol_is_valid (asymbol * sym ATTRIBUTE_UNUSED, { return true; } + +/* Just return size of previous instruction. */ + +int +generic_predict_insn_length (bfd_vma addr ATTRIBUTE_UNUSED, int previous, + struct disassemble_info *info ATTRIBUTE_UNUSED) +{ + return previous; +} diff --git a/opcodes/dis-init.c b/opcodes/dis-init.c index f796aaa260b..f425933448e 100644 --- a/opcodes/dis-init.c +++ b/opcodes/dis-init.c @@ -43,6 +43,7 @@ init_disassemble_info (struct disassemble_info *info, void *stream, info->print_address_func = generic_print_address; info->symbol_at_address_func = generic_symbol_at_address; info->symbol_is_valid = generic_symbol_is_valid; + info->predict_insn_length = generic_predict_insn_length; info->display_endian = BFD_ENDIAN_UNKNOWN; info->created_styled_output = false; } diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c index 93052e75088..205795003a9 100644 --- a/opcodes/disassemble.c +++ b/opcodes/disassemble.c @@ -359,6 +359,11 @@ disassembler (enum bfd_architecture a, disassemble = print_insn_mn10300; break; #endif +#ifdef ARCH_nanomips + case bfd_arch_nanomips: + disassemble = print_insn_nanomips; + break; +#endif #ifdef ARCH_nios2 case bfd_arch_nios2: if (big) @@ -576,6 +581,9 @@ disassembler_usage (FILE *stream ATTRIBUTE_UNUSED) #ifdef ARCH_nfp print_nfp_disassembler_options (stream); #endif +#ifdef ARCH_nanomips + print_nanomips_disassembler_options (stream); +#endif #ifdef ARCH_powerpc print_ppc_disassembler_options (stream); #endif @@ -747,6 +755,11 @@ disassemble_init_for_target (struct disassemble_info * info) disassemble_init_nds32 (info); break; #endif +#ifdef ARCH_nanomips + case bfd_arch_nanomips: + info->disassembler_needs_relocs = true; + break; +#endif default: break; } diff --git a/opcodes/nanomips-dis.c b/opcodes/nanomips-dis.c new file mode 100644 index 00000000000..ef69d11c8bb --- /dev/null +++ b/opcodes/nanomips-dis.c @@ -0,0 +1,1466 @@ +/* Print nanoMIPS instructions for GDB, the GNU debugger, or for objdump. + Copyright (C) 2018-2022 Free Software Foundation, Inc. + + Written by Faraz Shahbazker + + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "dis-asm.h" +#include "libiberty.h" +#include "opcode/nanomips.h" +#include "opintl.h" + +#if !defined(EMBEDDED_ENV) +#include "elf-bfd.h" +#include "elf/nanomips.h" +#endif + +static const char * const nanomips_gpr_names_numeric[32] = { + "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", + "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", + "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", + "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31" +}; + +static const char * const nanomips_gpr_names_symbolic[32] = { + "zero", "at", "t4", "t5", "a0", "a1", "a2", "a3", + "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" +}; + +static const char * const nanomips_fpr_names_numeric[32] = { + "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", + "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", + "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", + "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31" +}; + +static const char * const nanomips_fpr_names_64[32] = { + "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3", + "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3", + "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11", + "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7" +}; + +static const char * const nanomips_cp1_names_numeric[32] = { + "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", + "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", + "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", + "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31" +}; + +static const char * const nanomips_cp1_names_3264r6[32] = { + "c1_fir", "c1_ufr", "$2", "$3", + "c1_unfr", "$5", "$6", "$7", + "$8", "$9", "$10", "$11", + "$12", "$13", "$14", "$15", + "$16", "$17", "$18", "$19", + "$20", "$21", "$22", "$23", + "$24", "c1_fccr", "c1_fexr", "$27", + "c1_fenr", "$29", "$30", "c1_fcsr" +}; + +static const char * const msa_control_names[32] = { + "msa_ir", "msa_csr", "msa_access", "msa_save", + "msa_modify", "msa_request", "msa_map", "msa_unmap", + "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", + "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", + "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31" +}; + +/* The empty-list of CP0 registers serves as an indicator to fall-back to + numeric register names. */ +static const struct nanomips_cp0_name nanomips_cp0_numeric[] = { + {NULL, 0, 0} +}; +static const struct nanomips_cp0_select nanomips_cp0sel_numeric[] = { + {NULL, 0, 0} +}; + +/* The empty-list of HWR registers serves as an indicator to fall-back to + numeric register names. */ +static const struct nanomips_hwr_name nanomips_hwr_names_numeric[] = { + {NULL, 0, 0, 0, 0} +}; + +struct nanomips_abi_choice +{ + const char *name; + const char *const *gpr_names; + const char *const *fpr_names; +}; + +struct nanomips_abi_choice nanomips_abi_choices[] = { + {"numeric", nanomips_gpr_names_numeric, nanomips_fpr_names_numeric}, + {"p32", nanomips_gpr_names_symbolic, nanomips_fpr_names_64}, + {"p64", nanomips_gpr_names_symbolic, nanomips_fpr_names_64}, +}; + +struct nanomips_arch_choice +{ + const char *name; + int bfd_mach_valid; + unsigned long bfd_mach; + int processor; + int isa; + int ase; + const struct nanomips_cp0_name *cp0_names; + const struct nanomips_cp0_select *cp0sel_names; + const char *const *cp1_names; + const struct nanomips_hwr_name *hwr_names; +}; + +const struct nanomips_arch_choice nanomips_arch_choices[] = { + {"numeric", 0, 0, 0, 0, 0, + nanomips_cp0_numeric, nanomips_cp0sel_numeric, nanomips_cp1_names_numeric, + nanomips_hwr_names_numeric}, + + {"32r6", 1, bfd_mach_nanomipsisa32r6, CPU_NANOMIPS32R6, ISA_NANOMIPS32R6, + (ASE_EVA | ASE_MSA | ASE_VIRT | ASE_MCU | ASE_MT | ASE_DSP | ASE_xNMS + | ASE_TLB | ASE_GINV | ASE_CRC), + nanomips_cp0_3264r6, nanomips_cp0sel_3264r6, nanomips_cp1_names_3264r6, + nanomips_hwr_names_3264r6}, + + {"32r6s", 1, bfd_mach_nanomipsisa32r6, CPU_NANOMIPS32R6, ISA_NANOMIPS32R6, + (ASE_EVA | ASE_MSA | ASE_VIRT | ASE_MCU | ASE_MT | ASE_DSP | ASE_TLB + | ASE_GINV | ASE_CRC), + nanomips_cp0_3264r6, nanomips_cp0sel_3264r6, nanomips_cp1_names_3264r6, + nanomips_hwr_names_3264r6}, + + {"64r6", 1, bfd_mach_nanomipsisa64r6, CPU_NANOMIPS64R6, ISA_NANOMIPS64R6, + (ASE_EVA | ASE_MSA | ASE_MSA64 | ASE_VIRT | ASE_MCU | ASE_MT | ASE_DSP + | ASE_DSP64 | ASE_xNMS | ASE_TLB | ASE_GINV | ASE_CRC | ASE_CRC64), + nanomips_cp0_3264r6, nanomips_cp0sel_3264r6, nanomips_cp1_names_3264r6, + nanomips_hwr_names_3264r6}, +}; + +/* ISA and processor type to disassemble for, and register names to use. + set_default_nanomips_dis_options and parse_nanomips_dis_options fill in + these values. */ + +static int nanomips_processor; +static int nanomips_ase; +static int nanomips_isa; +static const char *const *nanomips_gpr_names; +static const char *const *nanomips_fpr_names; +static const struct nanomips_cp0_name *nanomips_cp0_names; +static const struct nanomips_cp0_select *nanomips_cp0sel_names; +static const char *const *nanomips_cp1_names; +static const struct nanomips_hwr_name *nanomips_hwr_names; + +/* Other options */ +static int no_aliases; /* If set, disassemble as most general inst. */ +static bool show_arch_insn; /* Mnemonics with suffix. */ +static bool show_mttgpr_rc1 = false; /* RC1 style MTTGPR format. */ + + + +/* Map ABI name to nanomips_abi_choice descriptor. */ + +static const struct nanomips_abi_choice * +choose_abi_by_name (const char *name, unsigned int namelen) +{ + const struct nanomips_abi_choice *c; + unsigned int i; + + for (i = 0, c = NULL; i < ARRAY_SIZE (nanomips_abi_choices) && c == NULL; + i++) + if (strncmp (nanomips_abi_choices[i].name, name, namelen) == 0 + && strlen (nanomips_abi_choices[i].name) == namelen) + c = &nanomips_abi_choices[i]; + + return c; +} + +/* Map architecture name to nanomips_arch_choice descriptor. */ + +static const struct nanomips_arch_choice * +choose_arch_by_name (const char *name, unsigned int namelen) +{ + const struct nanomips_arch_choice *c = NULL; + unsigned int i; + + for (i = 0, c = NULL; i < ARRAY_SIZE (nanomips_arch_choices) && c == NULL; + i++) + if (strncmp (nanomips_arch_choices[i].name, name, namelen) == 0 + && strlen (nanomips_arch_choices[i].name) == namelen) + c = &nanomips_arch_choices[i]; + + return c; +} + +/* Map BFD architecture to nanomips_arch_choice descriptor. */ + +static const struct nanomips_arch_choice * +choose_arch_by_number (unsigned long mach) +{ + static unsigned long hint_bfd_mach; + static const struct nanomips_arch_choice *hint_arch_choice; + const struct nanomips_arch_choice *c; + unsigned int i; + + /* We optimize this because even if the user specifies no + flags, this will be done for every instruction! */ + if (hint_bfd_mach == mach + && hint_arch_choice != NULL + && hint_arch_choice->bfd_mach == hint_bfd_mach) + return hint_arch_choice; + + for (i = 0, c = NULL; i < ARRAY_SIZE (nanomips_arch_choices) && c == NULL; + i++) + { + if (nanomips_arch_choices[i].bfd_mach_valid + && nanomips_arch_choices[i].bfd_mach == mach) + { + c = &nanomips_arch_choices[i]; + hint_bfd_mach = mach; + hint_arch_choice = c; + } + } + return c; +} + +/* Select default descriptors and initial mode for the default + architecture. */ + +static void +set_default_nanomips_dis_options (struct disassemble_info *info) +{ + const struct nanomips_arch_choice *chosen_arch; + + nanomips_isa = ISA_NANOMIPS32R6; + nanomips_processor = CPU_NANOMIPS32R6; + nanomips_isa = true; + nanomips_ase = 0; + nanomips_fpr_names = nanomips_fpr_names_numeric; + nanomips_cp0_names = nanomips_cp0_numeric; + nanomips_cp0sel_names = nanomips_cp0sel_numeric; + nanomips_cp1_names = nanomips_cp1_names_numeric; + nanomips_hwr_names = nanomips_hwr_names_numeric; + no_aliases = 0; + show_arch_insn = false; + + nanomips_gpr_names = nanomips_gpr_names_symbolic; + + /* Set ISA, architecture, and cp0 register names as best we can. */ + chosen_arch = choose_arch_by_number (info->mach); + if (chosen_arch != NULL) + { + nanomips_processor = chosen_arch->processor; + nanomips_isa = chosen_arch->isa; + nanomips_ase = chosen_arch->ase; + nanomips_cp0_names = chosen_arch->cp0_names; + nanomips_cp0sel_names = chosen_arch->cp0sel_names; + nanomips_cp1_names = chosen_arch->cp1_names; + nanomips_hwr_names = chosen_arch->hwr_names; + } +} + +/* Parse and translate a command-line options to internal state. */ + +static void +parse_nanomips_dis_option (const char *option, unsigned int len) +{ + unsigned int i, optionlen, vallen; + const char *val; + const struct nanomips_abi_choice *chosen_abi; + const struct nanomips_arch_choice *chosen_arch; + + /* Try to match options that are simple flags */ + if (startswith (option, "show-arch-insn")) + { + show_arch_insn = true; + return; + } + + if (startswith (option, "no-aliases")) + { + no_aliases = 1; + return; + } + + if (startswith (option, "show-mttgpr-rc1")) + { + show_mttgpr_rc1 = true; + return; + } + + if (startswith (option, "msa")) + { + nanomips_ase |= ASE_MSA; + if ((nanomips_isa & INSN_ISA_MASK) == ISA_NANOMIPS64R6) + nanomips_ase |= ASE_MSA64; + return; + } + + if (startswith (option, "virt")) + { + nanomips_ase |= ASE_VIRT; + + if (nanomips_isa & ISA_NANOMIPS64R6) + nanomips_ase |= ASE_VIRT64; + + if (nanomips_ase & ASE_GINV) + nanomips_ase |= ASE_GINV_VIRT; + } + + if (startswith (option, "ginv")) + { + nanomips_ase |= ASE_GINV; + if (nanomips_ase & ASE_VIRT) + nanomips_ase |= ASE_GINV_VIRT; + return; + } + + /* Look for the = that delimits the end of the option name. */ + for (i = 0; i < len; i++) + if (option[i] == '=') + break; + + if (i == 0) /* Invalid option: no name before '='. */ + return; + if (i == len) /* Invalid option: no '='. */ + return; + if (i == (len - 1)) /* Invalid option: no value after '='. */ + return; + + optionlen = i; + val = option + (optionlen + 1); + vallen = len - (optionlen + 1); + + if (strncmp ("gpr-names", option, optionlen) == 0 + && strlen ("gpr-names") == optionlen) + { + chosen_abi = choose_abi_by_name (val, vallen); + if (chosen_abi != NULL) + nanomips_gpr_names = chosen_abi->gpr_names; + return; + } + + if (strncmp ("fpr-names", option, optionlen) == 0 + && strlen ("fpr-names") == optionlen) + { + chosen_abi = choose_abi_by_name (val, vallen); + if (chosen_abi != NULL) + nanomips_fpr_names = chosen_abi->fpr_names; + return; + } + + if (strncmp ("cp0-names", option, optionlen) == 0 + && strlen ("cp0-names") == optionlen) + { + chosen_arch = choose_arch_by_name (val, vallen); + if (chosen_arch != NULL) + { + nanomips_cp0_names = chosen_arch->cp0_names; + nanomips_cp0sel_names = chosen_arch->cp0sel_names; + } + return; + } + + if (strncmp ("cp1-names", option, optionlen) == 0 + && strlen ("cp1-names") == optionlen) + { + chosen_arch = choose_arch_by_name (val, vallen); + if (chosen_arch != NULL) + nanomips_cp1_names = chosen_arch->cp1_names; + return; + } + + if (strncmp ("hwr-names", option, optionlen) == 0 + && strlen ("hwr-names") == optionlen) + { + chosen_arch = choose_arch_by_name (val, vallen); + if (chosen_arch != NULL) + nanomips_hwr_names = chosen_arch->hwr_names; + return; + } + + if (strncmp ("reg-names", option, optionlen) == 0 + && strlen ("reg-names") == optionlen) + { + /* We check both ABI and ARCH here unconditionally, so + that "numeric" will do the desirable thing: select + numeric register names for all registers. Other than + that, a given name probably won't match both. */ + chosen_abi = choose_abi_by_name (val, vallen); + if (chosen_abi != NULL) + { + nanomips_gpr_names = chosen_abi->gpr_names; + nanomips_fpr_names = chosen_abi->fpr_names; + } + chosen_arch = choose_arch_by_name (val, vallen); + if (chosen_arch != NULL) + { + nanomips_cp0_names = chosen_arch->cp0_names; + nanomips_cp0sel_names = chosen_arch->cp0sel_names; + nanomips_cp1_names = chosen_arch->cp1_names; + nanomips_hwr_names = chosen_arch->hwr_names; + } + return; + } + + /* Invalid option. */ +} + +/* Loop to parse nanoMIPS-specific command-line options. */ + +static void +parse_nanomips_dis_options (const char *options) +{ + const char *option_end; + + if (options == NULL) + return; + + while (*options != '\0') + { + /* Skip empty options. */ + if (*options == ',') + { + options++; + continue; + } + + /* We know that *options is neither NUL or a comma. */ + option_end = options + 1; + while (*option_end != ',' && *option_end != '\0') + option_end++; + + parse_nanomips_dis_option (options, option_end - options); + + /* Go on to the next one. If option_end points to a comma, it + will be skipped above. */ + options = option_end; + } +} + +/* Look-up and print the symbolic name of a named CP0 register with + a fixed select value. Fall-back to numeric format if no match is + found. */ + +static void +print_cp0_reg (struct disassemble_info *info, int regno) +{ + int i; + unsigned int selnum = regno & NANOMIPSOP_MASK_CP0SEL; + unsigned int cp0_regno = regno >> NANOMIPSOP_SH_CP0SEL; + + if (nanomips_cp0_names != nanomips_cp0_numeric) + for (i = cp0_regno; nanomips_cp0_names[i].name; i++) + { + if (nanomips_cp0_names[i].num == cp0_regno + && nanomips_cp0_names[i].sel == selnum) + { + info->fprintf_func (info->stream, "%s", + nanomips_cp0_names[i].name + 1); + return; + } + } + + /* A select value of 0 is deemed optional. */ + if (selnum == 0) + info->fprintf_func (info->stream, "$%d", cp0_regno); + else + info->fprintf_func (info->stream, "$%d,%d", cp0_regno, selnum); +} + +/* Look-up and print the symbolic name of a named CP0 register with + a variable select value. Fall-back to numeric format if no match is + found. */ + +static void +print_cp0sel_reg (struct disassemble_info *info, unsigned int regno, + unsigned int selnum) +{ + int i; + + for (i = 0; nanomips_cp0sel_names[i].name; i++) + { + if (nanomips_cp0sel_names[i].num == regno + && ((1 << selnum) & nanomips_cp0sel_names[i].selmask) != 0) + { + info->fprintf_func (info->stream, "%s,%d", + nanomips_cp0sel_names[i].name + 1, selnum); + return; + } + } + + /* A select value of 0 is deemed optional. */ + if (selnum == 0) + info->fprintf_func (info->stream, "$%d", regno); + else + info->fprintf_func (info->stream, "$%d,%d", regno, selnum); +} + +/* Look-up and print the symbolic name of a named CP0 register with + a fixed select value. Fall-back to numeric format if no match is + found. */ + +static void +print_hwr_reg (struct disassemble_info *info, int regno) +{ + int i; + unsigned int selnum = regno & NANOMIPSOP_MASK_CP0SEL; + unsigned int hwr_regno = regno >> NANOMIPSOP_SH_HWRSEL; + + if (nanomips_hwr_names != nanomips_hwr_names_numeric) + for (i = 0; nanomips_hwr_names[i].name; i++) + { + if (nanomips_hwr_names[i].num == hwr_regno + && nanomips_hwr_names[i].sel == selnum) + { + info->fprintf_func (info->stream, "%s", + nanomips_hwr_names[i].name + 1); + return; + } + } + + /* A select value of 0 is deemed optional. */ + if (selnum == 0) + info->fprintf_func (info->stream, "$%d", hwr_regno); + else + info->fprintf_func (info->stream, "$%d,%d", hwr_regno, selnum); +} + +/* Print register REGNO, of type TYPE, for instruction OPCODE. */ + +static void +print_reg (struct disassemble_info *info, + const struct nanomips_opcode *opcode, + enum nanomips_reg_operand_type type, int regno) +{ + switch (type) + { + case OP_REG_GP: + info->fprintf_func (info->stream, "%s", nanomips_gpr_names[regno]); + break; + + case OP_REG_FP: + info->fprintf_func (info->stream, "%s", nanomips_fpr_names[regno]); + break; + + case OP_REG_ACC: + info->fprintf_func (info->stream, "$ac%d", regno); + break; + + case OP_REG_COPRO: + if (opcode->name[strlen (opcode->name) - 1] == '1') + info->fprintf_func (info->stream, "%s", nanomips_cp1_names[regno]); + else + info->fprintf_func (info->stream, "$%d", regno); + break; + + case OP_REG_HW: + case OP_REG_HWRSEL: + print_hwr_reg (info, regno); + break; + + case OP_REG_MSA: + info->fprintf_func (info->stream, "$w%d", regno); + break; + + case OP_REG_MSA_CTRL: + info->fprintf_func (info->stream, "%s", msa_control_names[regno]); + break; + + case OP_REG_CP0: + print_cp0_reg (info, regno); + break; + + case OP_REG_CP0SEL: + /* Need to check select bits againt mask, defer output to next operand. */ + break; + } +} + +/* Used to track the state carried over from previous operands in + an instruction. */ + +struct nanomips_print_arg_state +{ + /* The value of the last OP_INT seen. We only use this for OP_MSB, + where the value is known to be unsigned and small. */ + unsigned int last_int; + + /* The type and number of the last OP_REG seen. We only use this for + OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */ + enum nanomips_reg_operand_type last_reg_type; + unsigned int last_regno; + unsigned int dest_regno; + unsigned int seen_dest; +}; + +/* Initialize STATE for the start of an instruction. */ + +static inline void +init_print_arg_state (struct nanomips_print_arg_state *state) +{ + memset (state, 0, sizeof (*state)); +} + +/* Record information about a register operand. */ + +static void +nanomips_seen_register (struct nanomips_print_arg_state *state, + unsigned int regno, + enum nanomips_reg_operand_type reg_type) +{ + state->last_reg_type = reg_type; + state->last_regno = regno; + + if (!state->seen_dest) + { + state->seen_dest = 1; + state->dest_regno = regno; + } +} + +/* Pretty-print a save/restore register list. */ + +static void +nanomips_print_save_restore (struct disassemble_info *info, + unsigned int uval, bool mode16) +{ + const fprintf_ftype infprintf = info->fprintf_func; + void *is = info->stream; + char *comma = ","; + unsigned int pending = 0; + unsigned int freg, fp, gp, ra; + int count; + fp = gp = ra = 0; + + if (mode16) + { + freg = 30 | (uval >> 4); + count = uval & 0xf; + } + else + { + freg = (uval >> 6) & 0x1f; + count = (uval >> 1) & 0xf; + if (count > 0) + gp = uval & 1; + } + + if (freg == 30 && count > 0) + fp = 1; + if ((freg == 31 && count > 0) || (freg == 30 && count > 1)) + ra = 1; + + if (freg + count == 45) + gp = 1; + + count = count - gp; + if (fp && count > 0) + { + freg = (freg & 0x10) | ((freg + 1) % 32); + count--; + } + + if (ra && count > 0) + { + freg = (freg & 0x10) | ((freg + 1) % 32); + count--; + } + + if (fp) + { + infprintf (is, "%s", nanomips_gpr_names[30]); + pending = 1; + } + + if (ra) + { + infprintf (is, "%s%s", (pending ? comma : ""), nanomips_gpr_names[31]); + pending = 1; + } + + if (count > 0) + { + if (count > 1) + infprintf (is, "%s%s-%s", (pending ? comma : ""), + nanomips_gpr_names[freg], + nanomips_gpr_names[freg + count - 1]); + else + infprintf (is, "%s%s", (pending ? comma : ""), + nanomips_gpr_names[freg]); + pending = 1; + } + + if (gp) + infprintf (is, "%s%s", (pending ? comma : ""), nanomips_gpr_names[28]); +} + +/* Pretty-print save/restore floating-point register list. */ + +static void +nanomips_print_save_restore_fp (struct disassemble_info *info, + unsigned int count) +{ + const fprintf_ftype infprintf = info->fprintf_func; + void *is = info->stream; + + if (count == 1) + infprintf (is, "%s", nanomips_fpr_names[0]); + else + infprintf (is, "%s-%s", nanomips_fpr_names[0], + nanomips_fpr_names[count - 1]); +} + +/* Print operand OPERAND of OPCODE, using STATE to track inter-operand state. + UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is + the base address for OP_PCREL operands. */ + +static void +print_insn_arg (struct disassemble_info *info, + struct nanomips_print_arg_state *state, + const struct nanomips_opcode *opcode, + const struct nanomips_operand *operand, + bfd_vma base_pc, unsigned int uval) +{ + const fprintf_ftype infprintf = info->fprintf_func; + void *is = info->stream; + + switch (operand->type) + { + case OP_INT: + case OP_IMM_INT: + { + const struct nanomips_int_operand *int_op; + + int_op = (const struct nanomips_int_operand *) operand; + uval = nanomips_decode_int_operand (int_op, uval); + state->last_int = uval; + if (int_op->print_hex) + infprintf (is, "0x%x", uval); + else + infprintf (is, "%d", uval); + } + break; + + case OP_MAPPED_INT: + { + const struct nanomips_mapped_int_operand *mint_op; + + mint_op = (const struct nanomips_mapped_int_operand *) operand; + uval = mint_op->int_map[uval]; + state->last_int = uval; + if (mint_op->print_hex) + infprintf (is, "0x%x", uval); + else + infprintf (is, "%d", uval); + } + break; + + case OP_MSB: + { + const struct nanomips_msb_operand *msb_op; + + msb_op = (const struct nanomips_msb_operand *) operand; + uval += msb_op->bias; + if (msb_op->add_lsb) + uval -= state->last_int; + infprintf (is, "%d", uval); + } + break; + + case OP_REG: + case OP_OPTIONAL_REG: + case OP_MAPPED_CHECK_PREV: + case OP_BASE_CHECK_OFFSET: + { + const struct nanomips_reg_operand *reg_op; + + reg_op = (const struct nanomips_reg_operand *) operand; + uval = nanomips_decode_reg_operand (reg_op, uval); + print_reg (info, opcode, reg_op->reg_type, uval); + + nanomips_seen_register (state, uval, reg_op->reg_type); + } + break; + + case OP_REG_PAIR: + { + const struct nanomips_reg_pair_operand *pair_op; + + pair_op = (const struct nanomips_reg_pair_operand *) operand; + print_reg (info, opcode, pair_op->reg_type, pair_op->reg1_map[uval]); + infprintf (is, ","); + print_reg (info, opcode, pair_op->reg_type, pair_op->reg2_map[uval]); + } + break; + + case OP_PCREL: + { + const struct nanomips_pcrel_operand *pcrel_op; + + pcrel_op = (const struct nanomips_pcrel_operand *) operand; + info->target = nanomips_decode_pcrel_operand (pcrel_op, base_pc, uval); + + /* Preserve the ISA bit for the GDB disassembler, + otherwise clear it. */ + if (info->flavour != bfd_target_unknown_flavour) + info->target &= -2; + + (*info->print_address_func) (info->target, info); + } + break; + + case OP_NON_ZERO_PCREL_S1: + { + const struct nanomips_pcrel_operand pcrel_op = { + {{OP_PCREL, operand->size, operand->lsb, 0, 0}, + (1 << operand->size) - 1, 0, 1, true}, 0, 0, 0 + }; + + if ((info->flags & INSN_HAS_RELOC) == 0) + info->target = nanomips_decode_pcrel_operand (&pcrel_op, base_pc, + uval); + else + info->target = 0; + (*info->print_address_func) (info->target, info); + } + break; + + case OP_CHECK_PREV: + case OP_NON_ZERO_REG: + { + print_reg (info, opcode, OP_REG_GP, uval & 31); + nanomips_seen_register (state, uval, OP_REG_GP); + } + break; + + case OP_SAVE_RESTORE_LIST: + nanomips_print_save_restore (info, uval, opcode->mask >> 16 == 0); + break; + + case OP_SAVE_RESTORE_FP_LIST: + nanomips_print_save_restore_fp (info, uval + 1); + break; + + case OP_REPEAT_PREV_REG: + print_reg (info, opcode, state->last_reg_type, state->last_regno); + break; + + case OP_REPEAT_DEST_REG: + print_reg (info, opcode, state->last_reg_type, state->dest_regno); + break; + + case OP_HI20_PCREL: + { + if ((info->flags & INSN_HAS_RELOC) == 0) + { + uval = nanomips_decode_hi20_int_operand (operand, uval); + infprintf (is, "0x%x", uval & 0xfffff); + } + else + { + info->target = nanomips_decode_hi20_pcrel_operand (operand, base_pc, + uval); + infprintf (is, "%%pcrel_hi("); + (*info->print_address_func) (info->target, info); + infprintf (is, ")"); + } + } + break; + + case OP_HI20_SCALE: + { + uval = nanomips_decode_hi20_int_operand (operand, uval); + state->last_int = uval; + infprintf (is, "0x%x", uval & 0xfffff); + } + break; + + case OP_HI20_INT: + { + uval = nanomips_decode_hi20_int_operand (operand, uval); + state->last_int = uval; + if ((info->flags & INSN_HAS_RELOC) != 0 || uval == 0) + infprintf (is, "0x%x", uval & 0xfffff); + else + infprintf (is, "%%hi(0x%x)", (uval & 0xfffff) << 12); + } + break; + + case OP_IMM_WORD: + { + const struct nanomips_int_operand *int_op; + int_op = (const struct nanomips_int_operand *) operand; + state->last_int = ((uval >> 16) & 0xffff) | (uval << 16); + state->last_int += int_op->bias; + infprintf (is, "%d", state->last_int); + } + break; + + case OP_INT_WORD: + case OP_GPREL_WORD: + { + state->last_int = ((uval >> 16) & 0xffff) | (uval << 16); + infprintf (is, "%d", state->last_int); + } + break; + + case OP_UINT_WORD: + { + state->last_int = ((uval >> 16) & 0xffff) | (uval << 16); + infprintf (is, "0x%x", state->last_int); + } + break; + + case OP_PC_WORD: + { + info->target = base_pc + (((uval >> 16) & 0xffff) | (uval << 16)); + (*info->print_address_func) (info->target, info); + } + break; + + case OP_NEG_INT: + infprintf (is, "-%d", uval); + break; + + case OP_CP0SEL: + if (no_aliases) + infprintf (is, ",%d", uval); + else + print_cp0sel_reg (info, state->last_regno, uval); + break; + + case OP_DONT_CARE: + case OP_COPY_BITS: + default: + break; + } +} + +/* Check if register+select map to a valid CP0 select sequence. */ + +static bool +validate_cp0_reg_operand (unsigned int uval) +{ + int i; + unsigned int regno, selnum; + regno = uval >> NANOMIPSOP_SH_CP0SEL; + selnum = uval & NANOMIPSOP_MASK_CP0SEL; + + for (i = 0; nanomips_cp0_3264r6[i].name; i++) + if (regno == nanomips_cp0_3264r6[i].num + && selnum == nanomips_cp0_3264r6[i].sel) + break; + else if (regno < nanomips_cp0_3264r6[i].num) + return false; + + if (nanomips_cp0_3264r6[i].name == NULL) + return false; + + return true; +} + +/* Validate the arguments for INSN, which is described by OPCODE. + Use DECODE_OPERAND to get the encoding of each operand. */ + +static bool +validate_insn_args (const struct nanomips_opcode *opcode, + const struct nanomips_operand *(*decode_operand) (const char *), + unsigned int insn, struct disassemble_info *info) +{ + struct nanomips_print_arg_state state; + const struct nanomips_operand *operand; + const char *s; + unsigned int uval; + + init_print_arg_state (&state); + for (s = opcode->args; *s; ++s) + { + switch (*s) + { + case ',': + case '(': + case ')': + break; + + case '#': + ++s; + break; + + default: + operand = decode_operand (s); + + if (!operand) + continue; + + uval = nanomips_extract_operand (operand, insn); + switch (operand->type) + { + case OP_REG: + case OP_OPTIONAL_REG: + case OP_BASE_CHECK_OFFSET: + { + const struct nanomips_reg_operand *reg_op; + + reg_op = (const struct nanomips_reg_operand *) operand; + + if (operand->type == OP_REG + && reg_op->reg_type == OP_REG_CP0 + && !validate_cp0_reg_operand (uval)) + return false; + + uval = nanomips_decode_reg_operand (reg_op, uval); + nanomips_seen_register (&state, uval, reg_op->reg_type); + } + break; + + case OP_CHECK_PREV: + { + const struct nanomips_check_prev_operand *prev_op + = (const struct nanomips_check_prev_operand *) operand; + + if (!prev_op->zero_ok && uval == 0) + return false; + + if (((prev_op->less_than_ok && uval < state.last_regno) + || (prev_op->greater_than_ok && uval > state.last_regno) + || (prev_op->equal_ok && uval == state.last_regno))) + break; + + return false; + } + + case OP_MAPPED_CHECK_PREV: + { + const struct nanomips_mapped_check_prev_operand *prev_op = + (const struct nanomips_mapped_check_prev_operand *) operand; + unsigned int last_uval = + nanomips_encode_reg_operand (operand, state.last_regno); + + if (((prev_op->less_than_ok && uval < last_uval) + || (prev_op->greater_than_ok && uval > last_uval) + || (prev_op->equal_ok && uval == last_uval))) + break; + + return false; + } + + case OP_NON_ZERO_REG: + if (uval == 0) + return false; + break; + + case OP_NON_ZERO_PCREL_S1: + if (uval == 0 && (info->flags & INSN_HAS_RELOC) == 0) + return false; + break; + + case OP_SAVE_RESTORE_LIST: + { + /* The operand for SAVE/RESTORE is split into 3 pieces + rather than just 2 but we only support a 2-way split + decode the last bit of the instruction here. */ + if (opcode->mask >> 16 != 0 && ((insn >> 20) & 0x1) != 0) + return false; + } + break; + + case OP_IMM_INT: + case OP_IMM_WORD: + case OP_NEG_INT: + case OP_INT: + case OP_MAPPED_INT: + case OP_MSB: + case OP_REG_PAIR: + case OP_PCREL: + case OP_REPEAT_PREV_REG: + case OP_REPEAT_DEST_REG: + case OP_SAVE_RESTORE_FP_LIST: + case OP_HI20_INT: + case OP_HI20_PCREL: + case OP_INT_WORD: + case OP_UINT_WORD: + case OP_PC_WORD: + case OP_GPREL_WORD: + case OP_DONT_CARE: + case OP_HI20_SCALE: + case OP_COPY_BITS: + case OP_CP0SEL: + break; + } + + if (*s == 'm' || *s == '+' || *s == '-' || *s == '`') + ++s; + } + } + return true; +} + +/* Print the arguments for INSN, which is described by OPCODE. + Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC + as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL + operand is for a branch or jump. */ + +static void +print_insn_args (struct disassemble_info *info, + const struct nanomips_opcode *opcode, + const struct nanomips_operand *(*decode_operand) (const char *), + uint64_t insn, bfd_vma insn_pc, unsigned int length) +{ + const fprintf_ftype infprintf = info->fprintf_func; + void *is = info->stream; + struct nanomips_print_arg_state state; + const struct nanomips_operand *operand; + const char *s; + bool pending_sep = false; + bool pending_space = true; + + init_print_arg_state (&state); + for (s = opcode->args; *s; ++s) + { + switch (*s) + { + case ',': + pending_sep = true; + break; + case '(': + if (pending_sep) + { + infprintf (is, ","); + pending_sep = false; + } + /* fall-through */ + case ')': + infprintf (is, "%c", *s); + break; + + case '#': + ++s; + infprintf (is, "%c%c", *s, *s); + break; + + default: + operand = decode_operand (s); + if (!operand) + { + /* xgettext:c-format */ + infprintf (is, + _("# internal error, undefined operand in `%s %s'"), + opcode->name, opcode->args); + return; + } + + /* Defer printing the comma separator for CP0-select values since + the preceding register output is also defered. */ + if (operand->type != OP_DONT_CARE + && operand->type != OP_CP0SEL + && pending_sep) + { + infprintf (is, ","); + pending_sep = false; + } + + if (operand->type != OP_DONT_CARE && pending_space) + infprintf (is, "\t"); + pending_space = false; + + { + bfd_vma base_pc = 0; + bool have_reloc = ((info->flags & INSN_HAS_RELOC) != 0); + + if (!have_reloc) + base_pc = insn_pc; + + if ((operand->type == OP_PCREL + || operand->type == OP_HI20_PCREL + || operand->type == OP_NON_ZERO_PCREL_S1 + || operand->type == OP_PC_WORD) + && !have_reloc) + base_pc += length; + + if (operand->type == OP_INT_WORD + || operand->type == OP_UINT_WORD + || operand->type == OP_PC_WORD + || operand->type == OP_GPREL_WORD + || operand->type == OP_IMM_WORD) + print_insn_arg (info, &state, opcode, operand, base_pc, + insn >> 32); + else if (operand->type != OP_DONT_CARE) + print_insn_arg (info, &state, opcode, operand, base_pc, + nanomips_extract_operand (operand, insn)); + } + if (*s == 'm' || *s == '+' || *s == '-' || *s == '`') + ++s; + break; + } + } +} + +enum match_kind +{ + MATCH_NONE, + MATCH_FULL, + MATCH_SHORT +}; + +/* Disassemble nanoMIPS instructions. */ + +static int +_print_insn_nanomips (bfd_vma memaddr_base, struct disassemble_info *info) +{ + const fprintf_ftype infprintf = info->fprintf_func; + const struct nanomips_opcode *op, *opend; + void *is = info->stream; + bfd_byte buffer[2]; + uint64_t higher = 0; + unsigned int length; + int status; + uint64_t insn; + + bfd_vma memaddr = memaddr_base; + + info->bytes_per_chunk = 2; + info->display_endian = info->endian; + info->insn_info_valid = 1; + info->branch_delay_insns = 0; + info->data_size = 0; + info->insn_type = dis_nonbranch; + info->target = 0; + info->target2 = 0; + + status = (*info->read_memory_func) (memaddr, buffer, 2, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + + length = 2; + + if (info->endian == BFD_ENDIAN_BIG) + insn = bfd_getb16 (buffer); + else + insn = bfd_getl16 (buffer); + + if ((insn & 0xfc00) == 0x6000) + { + unsigned imm; + /* This is a 48-bit nanoMIPS instruction. */ + status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info); + if (status != 0) + { + infprintf (is, "0x%x (expected 48 bits, got only 16): ", + (unsigned) insn); + (*info->memory_error_func) (status, memaddr + 2, info); + return -1; + } + if (info->endian == BFD_ENDIAN_BIG) + imm = bfd_getb16 (buffer); + else + imm = bfd_getl16 (buffer); + higher = (imm << 16); + + status = (*info->read_memory_func) (memaddr + 4, buffer, 2, info); + if (status != 0) + { + infprintf (is, "0x%x (expected 48 bits, got only 32): ", + (unsigned) insn); + (*info->memory_error_func) (status, memaddr + 4, info); + return -1; + } + + if (info->endian == BFD_ENDIAN_BIG) + imm = bfd_getb16 (buffer); + else + imm = bfd_getl16 (buffer); + higher = higher | imm; + + length += 4; + } + else if ((insn & 0x1000) == 0x0) + { + /* This is a 32-bit nanoMIPS instruction. */ + higher = insn; + + status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info); + if (status != 0) + { + infprintf (is, "0x%x (expected 32 bits, got only 16): ", + (unsigned) higher); + (*info->memory_error_func) (status, memaddr + 2, info); + return -1; + } + + if (info->endian == BFD_ENDIAN_BIG) + insn = bfd_getb16 (buffer); + else + insn = bfd_getl16 (buffer); + + insn = insn | (higher << 16); + + length += 2; + } + + const struct nanomips_opcode *opcodes; + int num_opcodes; + struct nanomips_operand const *(*decode) (const char *); + + opcodes = nanomips_opcodes; + num_opcodes = bfd_nanomips_num_opcodes; + decode = decode_nanomips_operand; + + opend = opcodes + num_opcodes; + for (op = opcodes; op < opend; op++) + { + if (op->pinfo != INSN_MACRO + && !(no_aliases && (op->pinfo2 & INSN2_ALIAS)) + && (show_mttgpr_rc1 || (op->pinfo2 & INSN2_MTTGPR_RC1) == 0) + && (insn & op->mask) == op->match + && ((length == 2 && (op->mask & 0xffff0000) == 0) + || (length == 6 + && (op->mask & 0xffff0000) == 0) + || (length == 4 && (op->mask & 0xffff0000) != 0))) + { + if (!nanomips_opcode_is_member (op, nanomips_isa, nanomips_ase, + nanomips_processor) + || (op->pinfo2 & INSN2_CONVERTED_TO_COMPACT)) + continue; + + if (!validate_insn_args (op, decode, insn, info)) + continue; + + infprintf (is, "%s%s", op->name, + (show_arch_insn ? op->suffix : "")); + + if (length == 6) + insn |= (higher << 32); + + if (op->args[0]) + print_insn_args (info, op, decode, insn, memaddr, length); + + /* Figure out instruction type and branch delay information. */ + if ((op->pinfo2 & INSN2_UNCOND_BRANCH) != 0) + { + if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0) + info->insn_type = dis_jsr; + else + info->insn_type = dis_branch; + } + else if ((op->pinfo2 & INSN2_COND_BRANCH) != 0) + { + if ((op->pinfo & INSN_WRITE_GPR_31) != 0) + info->insn_type = dis_condjsr; + else + info->insn_type = dis_condbranch; + } + else if ((op->pinfo & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY)) != 0) + info->insn_type = dis_dref; + + return length; + } + } + + infprintf (is, "0x%x", (unsigned) insn); + info->insn_type = dis_noninsn; + + return length; +} + +/* Set up the options and disassemble. */ + +int +print_insn_nanomips (bfd_vma memaddr, struct disassemble_info *info) +{ + set_default_nanomips_dis_options (info); + parse_nanomips_dis_options (info->disassembler_options); + + return _print_insn_nanomips (memaddr, info); +} + +/* Print description of nanoMIPS-specific command-line options. */ + +void +print_nanomips_disassembler_options (FILE *stream) +{ + unsigned int i; + + fprintf (stream, _("\n\ +The following nanoMIPS specific disassembler options are supported for use\n\ +with the -M switch (multiple options should be separated by commas):\n")); + + fprintf (stream, _("\n\ + no-aliases Use canonical instruction forms.\n")); + + fprintf (stream, _("\n\ + show-arch-insn Print extended mnemonics in disassembly including\n\ + suffix as in the architecture reference manual.\n")); + + fprintf (stream, _("\n\ + show-mttgpr-rc1 Disassemble MTTGPR as RC1 style (deprecated) format.\n")); + + fprintf (stream, _("\n\ + msa Recognize MSA instructions.\n")); + + fprintf (stream, _("\n\ + virt Recognize the virtualization ASE instructions.\n")); + + fprintf (stream, _("\n\ + mxu Recognize the MXU ASE instructions.\n")); + + fprintf (stream, _("\n\ + gpr-names=ABI Print GPR names according to specified ABI.\n\ + Default: based on binary being disassembled.\n")); + + fprintf (stream, _("\n\ + fpr-names=ABI Print FPR names according to specified ABI.\n\ + Default: numeric.\n")); + + fprintf (stream, _("\n\ + cp0-names=ARCH Print CP0 register names according to\n\ + specified architecture.\n\ + Default: based on binary being disassembled.\n")); + + fprintf (stream, _("\n\ + hwr-names=ARCH Print HWR names according to specified \n\ + architecture.\n\ + Default: based on binary being disassembled.\n")); + + fprintf (stream, _("\n\ + reg-names=ABI Print GPR and FPR names according to\n\ + specified ABI.\n")); + + fprintf (stream, _("\n\ + reg-names=ARCH Print CP0 register and HWR names according to\n\ + specified architecture.\n")); + + fprintf (stream, _("\n\ + For the options above, the following values are supported for \"ABI\":\n\ + ")); + for (i = 0; i < ARRAY_SIZE (nanomips_abi_choices); i++) + fprintf (stream, " %s", nanomips_abi_choices[i].name); + fprintf (stream, _("\n")); + + fprintf (stream, _("\n\ + For the options above, The following values are supported for \"ARCH\":\n\ + ")); + for (i = 0; i < ARRAY_SIZE (nanomips_arch_choices); i++) + if (*nanomips_arch_choices[i].name != '\0') + fprintf (stream, " %s", nanomips_arch_choices[i].name); + fprintf (stream, _("\n")); + + fprintf (stream, _("\n")); +} diff --git a/opcodes/nanomips-formats.h b/opcodes/nanomips-formats.h new file mode 100644 index 00000000000..1144604abe6 --- /dev/null +++ b/opcodes/nanomips-formats.h @@ -0,0 +1,265 @@ +/* nanomips-formats.h + Copyright (C) 2018-2022 Free Software Foundation, Inc. + + Written by Faraz Shahbazker + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING3. If not, + see . */ + +#include "libiberty.h" + +#define INT_BIAS(SIZE, LSB, MAX_VAL, BIAS, SHIFT, PRINT_HEX) \ + { \ + static const struct nanomips_int_operand op = { \ + { OP_INT, SIZE, LSB, 0, 0 }, MAX_VAL, BIAS, SHIFT, PRINT_HEX \ + }; \ + return &op.root; \ + } + +#define INT_ADJ(SIZE, LSB, MAX_VAL, SHIFT, PRINT_HEX) \ + INT_BIAS(SIZE, LSB, MAX_VAL, 0, SHIFT, PRINT_HEX) + +#define UINT(SIZE, LSB) \ + INT_ADJ(SIZE, LSB, (1 << (SIZE)) - 1, 0, false) + +#define SINT(SIZE, LSB) \ + INT_ADJ(SIZE, LSB, (1 << ((SIZE) - 1)) - 1, 0, false) + +#define HINT(SIZE, LSB) \ + INT_ADJ(SIZE, LSB, (1 << (SIZE)) - 1, 0, true) + +#define BIT(SIZE, LSB, BIAS) \ + { \ + static const struct nanomips_int_operand op = { \ + { OP_INT, SIZE, LSB, 0, 0 }, (1 << (SIZE)) - 1, BIAS, 0, false \ + }; \ + return &op.root; \ + } + +#define MAPPED_INT(SIZE, LSB, MAP, PRINT_HEX) \ + { \ + typedef char ATTRIBUTE_UNUSED \ + static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \ + static const struct nanomips_mapped_int_operand op = { \ + { OP_MAPPED_INT, SIZE, LSB, 0, 0 }, MAP, PRINT_HEX \ + }; \ + return &op.root; \ + } + +#define MSB(SIZE, LSB, BIAS, ADD_LSB, OPSIZE) \ + { \ + static const struct nanomips_msb_operand op = { \ + { OP_MSB, SIZE, LSB, 0, 0 }, BIAS, ADD_LSB, OPSIZE \ + }; \ + return &op.root; \ + } + +#define REG(SIZE, LSB, BANK) \ + { \ + static const struct nanomips_reg_operand op = { \ + { OP_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, 0 \ + }; \ + return &op.root; \ + } + +#define OPTIONAL_REG(SIZE, LSB, BANK) \ + { \ + static const struct nanomips_reg_operand op = { \ + { OP_OPTIONAL_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, 0 \ + }; \ + return &op.root; \ + } + +#define MAPPED_REG(SIZE, LSB, BANK, MAP) \ + { \ + typedef char ATTRIBUTE_UNUSED \ + static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \ + static const struct nanomips_reg_operand op = { \ + { OP_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP \ + }; \ + return &op.root; \ + } + +#define SPLIT_MAPPED_REG(SIZE, LSB, SIZE_T, LSB_T, BANK, MAP) \ + { \ + typedef char ATTRIBUTE_UNUSED \ + static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \ + static const struct nanomips_reg_operand op = { \ + { OP_REG, SIZE, LSB, SIZE_T, LSB_T }, OP_REG_##BANK, MAP \ + }; \ + return &op.root; \ + } + +#define OPTIONAL_MAPPED_REG(SIZE, LSB, BANK, MAP) \ + { \ + typedef char ATTRIBUTE_UNUSED \ + static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \ + static const struct nanomips_reg_operand op = { \ + { OP_OPTIONAL_REG, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP \ + }; \ + return &op.root; \ + } + +#define REG_PAIR(SIZE, LSB, BANK, MAP) \ + { \ + typedef char ATTRIBUTE_UNUSED \ + static_assert1[(1 << (SIZE)) == ARRAY_SIZE (MAP##1)]; \ + typedef char ATTRIBUTE_UNUSED \ + static_assert2[(1 << (SIZE)) == ARRAY_SIZE (MAP##2)]; \ + static const struct nanomips_reg_pair_operand op = { \ + { OP_REG_PAIR, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP##1, MAP##2 \ + }; \ + return &op.root; \ + } + +#define PCREL(SIZE, LSB, IS_SIGNED, SHIFT, ALIGN_LOG2, INCLUDE_ISA_BIT, \ + FLIP_ISA_BIT) \ + { \ + static const struct nanomips_pcrel_operand op = { \ + { { OP_PCREL, SIZE, LSB, 0, 0 }, \ + (1 << ((SIZE) - (IS_SIGNED))) - 1, 0, SHIFT, true }, \ + ALIGN_LOG2, INCLUDE_ISA_BIT, FLIP_ISA_BIT \ + }; \ + return &op.root.root; \ + } + +#define JUMP(SIZE, LSB, SHIFT) \ + PCREL (SIZE, LSB, false, SHIFT, SIZE + SHIFT, true, false) + +#define JALX(SIZE, LSB, SHIFT) \ + PCREL (SIZE, LSB, false, SHIFT, SIZE + SHIFT, true, true) + +#define BRANCH(SIZE, LSB, SHIFT) \ + PCREL (SIZE, LSB, true, SHIFT, 0, true, false) + +#define SPECIAL(SIZE, LSB, TYPE) \ + { \ + static const struct nanomips_operand op = { OP_##TYPE, SIZE, LSB, 0, 0 }; \ + return &op; \ + } + +#define PREV_CHECK(SIZE, LSB, GT_OK, LT_OK, EQ_OK, ZERO_OK) \ + { \ + static const struct nanomips_check_prev_operand op = { \ + { OP_CHECK_PREV, SIZE, LSB, 0, 0 }, GT_OK, LT_OK, EQ_OK, ZERO_OK \ + }; \ + return &op.root; \ + } + +#define IMM_INT_BIAS(SIZE, LSB, MAX_VAL, BIAS, SHIFT, PRINT_HEX) \ + { \ + static const struct nanomips_int_operand op = { \ + { OP_IMM_INT, SIZE, LSB, 0, 0 }, MAX_VAL, BIAS, SHIFT, PRINT_HEX \ + }; \ + return &op.root; \ + } + +#define IMM_INT_ADJ(SIZE, LSB, MAX_VAL, SHIFT, PRINT_HEX) \ + IMM_INT_BIAS(SIZE, LSB, MAX_VAL, 0, SHIFT, PRINT_HEX) + +#define UINT_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP) \ + { \ + static const struct nanomips_int_operand op = { \ + { OP_INT, SIZE, LSB, SIZE_TOP, LSB_TOP }, \ + (1 << (SIZE)) - 1, 0, SHIFT, 0 \ + }; \ + return &op.root; \ + } + +#define SINT_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP, BIAS) \ + { \ + static const struct nanomips_int_operand op = { \ + { OP_INT, SIZE, LSB, SIZE_TOP, LSB_TOP }, \ + (1 << ((SIZE) -1)) - 1, BIAS, SHIFT, 0 \ + }; \ + return &op.root; \ + } + +#define IMM_SINT_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP, BIAS) \ + { \ + static const struct nanomips_int_operand op = { \ + { OP_IMM_INT, SIZE, LSB, SIZE_TOP, LSB_TOP }, \ + (1 << ((SIZE) -1)) - 1, BIAS, SHIFT, false \ + }; \ + return &op.root; \ + } + +#define HINT_SPLIT(SIZE, LSB, SIZE_T, LSB_T) \ + SINT_SPLIT(SIZE, LSB, 0, SIZE_T, LSB_T) + +#define SPLIT_MAPPED_REG_PAIR(SIZE, LSB, SIZE_T, LSB_T, BANK, MAP1, MAP2) \ + { \ + typedef char ATTRIBUTE_UNUSED \ + static_assert1[(1 << (SIZE)) == ARRAY_SIZE (MAP1)]; \ + typedef char ATTRIBUTE_UNUSED \ + static_assert2[(1 << (SIZE)) == ARRAY_SIZE (MAP2)]; \ + static const struct nanomips_reg_pair_operand op = { \ + { OP_REG_PAIR, SIZE, LSB, SIZE_T, LSB_T }, OP_REG_##BANK, \ + MAP1, MAP2 \ + }; \ + return &op.root; \ + } + +#define BRANCH_UNORD_SPLIT(SIZE, SHIFT) \ + { \ + static const struct nanomips_pcrel_operand op = { \ + { { OP_PCREL, SIZE, 1, 1, 0 }, \ + (1 << ((SIZE) - 1)) - 1, 0, SHIFT, true }, \ + 0, false, false \ + }; \ + return &op.root.root; \ + } + +#define BRANCH_SPLIT(SIZE, LSB, SHIFT, SIZE_TOP, LSB_TOP) \ + { \ + static const struct nanomips_pcrel_operand op = { \ + { { OP_PCREL, SIZE, 1, SIZE_TOP, LSB_TOP }, \ + (1 << ((SIZE) - 1)) - 1, LSB, SHIFT, true }, \ + 0, false, false \ + }; \ + return &op.root.root; \ + } + +#define SPECIAL_SPLIT(SIZE, LSB, SIZE_T, LSB_T, TYPE) \ + { \ + static const struct nanomips_operand op = { OP_##TYPE, SIZE, LSB, SIZE_T, LSB_T }; \ + return &op; \ + } + +#define SPECIAL_WORD(BIAS, TYPE) \ + { \ + static const struct nanomips_int_operand op = { { OP_##TYPE, 0, 0, 0, 0 }, \ + 0x7fffffff, BIAS, 0, false }; \ + return &op.root; \ + } + +#define MAPPED_PREV_CHECK(SIZE, LSB, BANK, MAP, GT_OK, LT_OK, EQ_OK, ZERO_OK) \ + { \ + typedef char ATTRIBUTE_UNUSED \ + static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \ + static const struct nanomips_mapped_check_prev_operand op = { \ + { OP_MAPPED_CHECK_PREV, SIZE, LSB, 0, 0 }, OP_REG_##BANK, MAP, \ + GT_OK, LT_OK, EQ_OK, ZERO_OK \ + }; \ + return &op.root; \ + } + +#define BASE_OFFSET_CHECK(SIZE, LSB, CONST_OK, EXPR_OK) \ + { \ + static const struct nanomips_base_check_offset_operand op = { \ + { OP_BASE_CHECK_OFFSET, SIZE, LSB, 0, 0 }, OP_REG_GP, \ + CONST_OK, EXPR_OK \ + }; \ + return &op.root; \ + } diff --git a/opcodes/nanomips-opc.c b/opcodes/nanomips-opc.c new file mode 100644 index 00000000000..aa82c5c021c --- /dev/null +++ b/opcodes/nanomips-opc.c @@ -0,0 +1,1073 @@ +/* nanomips-opc.c. nanoMIPS opcode table. + Copyright (C) 2018-2022 Free Software Foundation, Inc. + + Written by Faraz Shahbazker + + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this file; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "opcode/nanomips.h" +#include "nanomips-formats.h" + +static unsigned char reg_0_map[] = { 0 }; +static unsigned char reg_28_map[] = { 28 }; +static unsigned char reg_29_map[] = { 29 }; +static unsigned char reg_31_map[] = { 31 }; +static unsigned char reg_m16_map[] = { 16, 17, 18, 19, 4, 5, 6, 7 }; +static unsigned char reg_q_map[] = { 0, 17, 18, 19, 4, 5, 6, 7 }; + +static unsigned char reg_4to5_map[] = { + 8, 9, 10, 11, 4, 5, 6, 7, + 16, 17, 18, 19, 20, 21, 22, 23 +}; + +static unsigned char reg_4to5_srcmap[] = { + 8, 9, 10, 0, 4, 5, 6, 7, + 16, 17, 18, 19, 20, 21, 22, 23 +}; + +static unsigned char reg_4or5_map[] = { 4, 5 }; + +static unsigned char reg_gpr2d_map1[] = { 4, 5, 6, 7 }; +static unsigned char reg_gpr2d_map2[] = { 5, 6, 7, 8 }; + +static int int_b_map[] = { + 0, 4, 8, 12, 16, 20, 24, 28 +}; + +static int int_c_map[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 255, 65535, 14, 15 +}; + +static int word_byte_map[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0 +}; + +static int int_mask_map[] = { + 0x1, 0x3, 0x7, 0xf, + 0x1f, 0x3f, 0x7f, 0xff, + 0x1ff, 0x3ff, 0x7ff, 0xfff, + 0x1fff, 0x3fff, 0x7fff, 0xffff, + 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, + 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, + 0x1ffffff,0x3ffffff,0x7ffffff,0xfffffff, + 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff +}; + +/* Return the nanomips_operand structure for the operand at the + beginning of P. */ + +/* FIXME: Unused cases left commented in-place for quick reminder + of which character strings are unused. */ +const struct nanomips_operand * +decode_nanomips_operand (const char *p) +{ + switch (p[0]) + { + case 'm': + switch (p[1]) + { + case 'a': MAPPED_REG (0, 0, GP, reg_28_map); + case 'b': SPECIAL (5, 5, NON_ZERO_REG); + case 'c': OPTIONAL_MAPPED_REG (3, 4, GP, reg_m16_map); + case 'd': MAPPED_REG (3, 7, GP, reg_m16_map); + case 'e': MAPPED_REG (3, 1, GP, reg_m16_map); + case 'f': MAPPED_PREV_CHECK (3, 7, GP, reg_m16_map, true, false, false, false); + case 'g': MAPPED_PREV_CHECK (3, 4, GP, reg_m16_map, false, true, false, false); + case 'h': MAPPED_PREV_CHECK (3, 7, GP, reg_m16_map, false, true, true, false); + case 'i': MAPPED_PREV_CHECK (3, 4, GP, reg_m16_map, true, false, true, false); + case 'j': REG (5, 0, GP); + case 'k': SPECIAL (0, 0, REPEAT_DEST_REG); + case 'l': MAPPED_REG (3, 4, GP, reg_m16_map); + case 'm': MAPPED_REG (3, 7, GP, reg_q_map); + case 'n': SPECIAL_SPLIT (5, 0, 1, 9, SAVE_RESTORE_LIST); + case 'p': REG (5, 5, GP); + case 'q': SPLIT_MAPPED_REG_PAIR (2, 8, 1, 3, GP, reg_gpr2d_map1, + reg_gpr2d_map2); + case 'r': SPLIT_MAPPED_REG_PAIR (2, 8, 1, 3, GP, reg_gpr2d_map2, + reg_gpr2d_map1); + case 's': MAPPED_REG (0, 0, GP, reg_29_map); + case 't': SPECIAL (0, 0, REPEAT_PREV_REG); + case 'u': SPLIT_MAPPED_REG (4, 5, 1, 9, GP, reg_4to5_map); + case 'v': SPLIT_MAPPED_REG (4, 0, 1, 4, GP, reg_4to5_map); + case 'w': SPLIT_MAPPED_REG (4, 5, 1, 9, GP, reg_4to5_srcmap); + case 'x': SPLIT_MAPPED_REG (4, 0, 1, 4, GP, reg_4to5_srcmap); + case 'y': MAPPED_REG (0, 0, GP, reg_31_map); + case 'z': UINT (0, 0); /* Literal 0 */ + case 'A': INT_ADJ (7, 0, 127, 2, false); /* (0 .. 127) << 2 */ + case 'B': MAPPED_INT (3, 0, int_b_map, false); + case 'C': MAPPED_INT (4, 0, int_c_map, true); + case 'D': BRANCH_UNORD_SPLIT (10, 1); + case 'E': BRANCH_UNORD_SPLIT (7, 1); + case 'F': SPECIAL (4, 0, NON_ZERO_PCREL_S1); + case 'G': INT_ADJ (4, 4, 15, 4, false); + case 'H': INT_ADJ (2, 1, 3, 1, false); /* (0 .. 3) << 1 */ + case 'I': INT_ADJ (7, 0, 126, 0, false); /* (-1 .. 126) */ + case 'J': INT_ADJ (4, 0, 15, 2, false); /* (0 .. 15) << 2 */ + case 'K': HINT (3, 0); + case 'L': UINT (2, 0); /* (0 .. 3) */ + case 'M': INT_ADJ (3, 0, 8, 0, false); /* (1 .. 8) */ + case 'N': UINT_SPLIT (2, 8, 2, 1, 3); /* split encoded 2-bit offset << 2 */ + case 'O': IMM_INT_ADJ (7, 0, 127, 2, false); /* (0 .. 127) << 2 */ + case 'P': HINT (2, 0); + case 'Q': SINT_SPLIT (4, 0, 0, 1, 4, 0); + case 'R': INT_ADJ (5, 0, 31, 2, false); /* (0 .. 31) << 2 */ + case 'S': INT_ADJ (6, 0, 63, 2, false); /* (0 .. 63) << 2 */ + case 'Z': UINT (0, 0); /* 0 only */ + } + break; + + case '-': + switch (p[1]) + { + case 'i': REG (0, 0, GP); /* Ignored register operand. */ + case 'm': SPECIAL_SPLIT (5, 11, 5, 21, COPY_BITS); + case 'n': SPECIAL_SPLIT (5, 11, 5, 16, COPY_BITS); + case 'A': SPECIAL (5, 16, DONT_CARE); + case 'B': SPECIAL (1, 10, DONT_CARE); + case 'C': SPECIAL (12, 0, DONT_CARE); + case 'D': SPECIAL (1, 17, DONT_CARE); + case 'E': SPECIAL (3, 13, DONT_CARE); + case 'F': SPECIAL (10, 16, DONT_CARE); + case 'G': SPECIAL_SPLIT (8, 9, 5, 16, DONT_CARE); + case 'H': SPECIAL (9, 17, DONT_CARE); + case 'I': SPECIAL (5, 21, DONT_CARE); + case 'J': SPECIAL (3, 23, DONT_CARE); + case 'K': SPECIAL_SPLIT (2, 2, 1, 15, DONT_CARE); + case 'L': SPECIAL (3, 6, DONT_CARE); + case 'M': SPECIAL (3, 9, DONT_CARE); + case 'N': SPECIAL (6, 10, DONT_CARE); + case 'O': SPECIAL (1, 12, DONT_CARE); + case 'P': SPECIAL_SPLIT (8, 10, 4, 22, DONT_CARE); + case 'Q': SPECIAL (1, 11, DONT_CARE); + } + break; + + case '+': + switch (p[1]) + { + case 'A': BIT (5, 0, 0); /* (0 .. 31) */ + case 'B': MSB (5, 6, 1, true, 32); /* (1 .. 32), 32-bit op */ + case 'C': MSB (5, 6, 1, false, 32); /* (1 .. 32), 32-bit op */ + case 'D': SPECIAL (4, 16, SAVE_RESTORE_FP_LIST); + case 'E': BIT (5, 0, 32); /* (32 .. 63) */ + case 'F': MSB (5, 6, 33, true, 64); /* (33 .. 64), 64-bit op */ + case 'G': MSB (5, 6, 33, false, 64); /* (33 .. 64), 64-bit op */ + case 'H': MSB (5, 6, 1, false, 64); /* (1 .. 32), 64-bit op */ + case 'I': BIT (5, 6, 0); /* (0 .. 31) */ + case 'J': HINT (19, 0); + case 'K': SPECIAL_SPLIT (20, 2, 1, 0, HI20_PCREL); /* tri-part 20-bit */ + case 'L': HINT (10, 16); + case 'M': HINT (18, 0); + case 'N': INT_ADJ (9, 3, 511, 3, false); /* 9-bit << 3 */ + case 'O': SPECIAL_WORD (0, GPREL_WORD); + case 'P': SPECIAL_WORD (6, IMM_WORD); + case 'Q': SPECIAL_WORD (0, UINT_WORD); + case 'R': SPECIAL_WORD (0, INT_WORD); + case 'S': SPECIAL_WORD (0, PC_WORD); + + case 'i': HINT (5, 16); + case 'j': SINT_SPLIT (9, 0, 0, 1, 15, 0); + case 'p': SINT_SPLIT (7, 2, 2, 1, 15, 0); /* split 7-bit signed << 2 */ + case 'q': SINT_SPLIT (6, 3, 3, 1, 15, 0); /* split 6-bit signed << 3 */ + case 'r': BRANCH_UNORD_SPLIT (21, 1); /* split 21-bit signed << 1 */ + case 's': IMM_SINT_SPLIT (21, 1, 1, 1, 0, 2); /* split (21-bit signed + 2) << 1 */ + case 't': SPECIAL (5, 21, NON_ZERO_REG); + case 'u': BRANCH_UNORD_SPLIT (25, 1); + case 'v': MAPPED_INT (5, 6, word_byte_map, false); + case 'w': BIT (2, 9, 0); /* (0 .. 3) */ + + case '*': INT_ADJ (4, 7, 15, 1, false); /* (0 .. 15) << 1 */ + case '|': UINT (1, 6); /* 0/1 */ + case ';': UINT (2, 21); /* (0 .. 3) */ + case '1': UINT (18, 0); + case '2': INT_ADJ (16, 2, (1<<16) - 1, 2, false); + case '3': INT_ADJ (17, 1, (1<<17) - 1, 1, false); + case '4': INT_ADJ (18, 3, (1<<18)-1, 3, false); /* 18-bit << 3 */ + case '5': SPLIT_MAPPED_REG (4, 21, 1, 25, GP, reg_4to5_srcmap); + case '6': MAPPED_INT (5, 6, int_mask_map, true); + case '7': MAPPED_REG (1, 24, GP, reg_4or5_map); + case '8': HINT (23, 3); + case '9': UINT (7, 11); + } + break; + + case '.': INT_ADJ (19, 2, (1<<19) - 1, 2, false); + case '<': BIT (5, 0, 0); /* (0 .. 31) */ +/* case '>': BIT (5, 11, 32); /\* (32 .. 63) *\/ */ + case '\\': BIT (3, 21, 0); /* (0 .. 7) */ + case '|': INT_ADJ (3, 12, 8, 0, false); /* 1 .. 8 */ + case '~': BRANCH_UNORD_SPLIT (11, 1); /* split 11-bit signed << 1 */ + case '@': SINT (10, 11); + case '^': HINT (5, 11); + case '!': UINT (1, 10); + case '$': UINT (1, 3); + case '*': REG (2, 18, ACC); +/* case '&': REG (2, 23, ACC); */ + + case '0': SINT (6, 16); + case '1': BIT (5, 11, 0); /* (0 .. 31) */ + case '2': BIT (5, 16, 0); /* (0 .. 31) */ + case '3': BIT (3, 13, 0); + case '4': BIT (4, 12, 0); + case '5': HINT (8, 13); + case '7': REG (2, 14, ACC); + case '8': HINT (7, 14); + + case 'C': HINT (23, 3); + case 'D': REG (5, 11, FP); + case 'E': REG (5, 21, COPRO); + case 'G': REG (5, 16, COPRO); + case 'H': UINT (5, 11); + case 'J': SPECIAL (5, 11, CP0SEL); + case 'K': REG (10, 11, HW); +/* case 'M': REG (3, 13, CCC); */ +/* case 'N': REG (3, 18, CCC); */ + case 'O': REG (10, 11, CP0); + case 'P': REG (5, 16, CP0SEL); +/* case 'Q': UINT (5, 11); */ + case 'R': REG (5, 11, FP); + case 'S': REG (5, 16, FP); + case 'T': REG (5, 21, FP); + case 'U': REG (5, 16, HWRSEL); + case 'V': OPTIONAL_REG (5, 16, FP); + +/* case 'a': JUMP (26, 0, 1); */ + case 'b': REG (5, 16, GP); + case 'c': BASE_OFFSET_CHECK (5, 16, true, false); + case 'd': REG (5, 11, GP); + case 'e': REG (5, 3, GP); + case 'g': HINT (12, 0); + case 'h': SPECIAL (12, 0, NEG_INT); + case 'i': UINT (12, 0); + case 'j': UINT (16, 0); + case 'k': HINT (5, 21); + case 'n': SPECIAL_SPLIT (11, 2, 10, 16, SAVE_RESTORE_LIST); + case 'o': UINT (12, 0); + case 'p': BRANCH_UNORD_SPLIT (14, 1); +/* case 'q': BRANCH_UNORD_SPLIT (20, 1); - unused */ + case 'r': OPTIONAL_REG (5, 16, GP); + case 's': REG (5, 16, GP); + case 't': REG (5, 21, GP); + case 'u': SPECIAL_SPLIT (20, 2, 1, 0, HI20_INT); /* tri-part 20-bit */ + case 'v': OPTIONAL_REG (5, 16, GP); + case 'w': OPTIONAL_REG (5, 21, GP); + case 'x': SPECIAL_SPLIT (20, 2, 1, 0, HI20_SCALE); /* tri-part 20-bit */ + case 'z': MAPPED_REG (0, 0, GP, reg_0_map); + } + return 0; +} + +#define LM INSN_LOAD_MEMORY +#define SM INSN_STORE_MEMORY + +#define WR_1 INSN_WRITE_1 +#define WR_2 INSN_WRITE_2 +#define RD_1 INSN_READ_1 +#define RD_2 INSN_READ_2 +#define RD_3 INSN_READ_3 +#define MOD_1 (WR_1|RD_1) +#define MOD_2 (WR_2|RD_2) +#define FP_S INSN_FP_S +#define FP_D INSN_FP_D + + /* Write dsp accumulators */ +#define WR_a INSN_WRITE_ACC + /* Read dsp accumulators */ +#define RD_a INSN_READ_ACC + +/* Flags used in pinfo2. */ +#define CTC INSN2_CONVERTED_TO_COMPACT +#define UBR INSN2_UNCOND_BRANCH +#define CBR INSN2_COND_BRANCH +#define ALIAS INSN2_ALIAS + +/* For 32-bit nanoMIPS instructions. */ +#define WR_31 INSN_WRITE_GPR_31 + +/* nanoMIPS DSP ASE support. */ +#define D32 ASE_DSP + +/* nanoMIPS MT ASE support. */ +#define MT32 ASE_MT + +/* nanoMIPS MCU (MicroController) ASE support. */ +#define MC ASE_MCU + +/* nanoMIPS Enhanced VA Scheme. */ +#define EVA ASE_EVA + +/* MSA support. */ +#define MSA ASE_MSA +#define MSA64 ASE_MSA64 + +/* eXtended Physical Address (XPA) support. */ +#define XPA ASE_XPA + +/* Global INValidate extension. */ +#define GINV ASE_GINV + +/* Cyclic redundancy check instruction (CRC) support. */ +#define CRC ASE_CRC + +/* nanoMIPS instruction subset. */ +#define xNMS ASE_xNMS +/* TLB manipulations. */ +#define TLB ASE_TLB + +/* Base ISA for nanoMIPS. */ +#define I38 INSN_ISAN32R6 +#define I70 INSN_ISAN64R6 + +const struct nanomips_opcode nanomips_opcodes[] = { +/* These instructions appear first so that the disassembler will find + them first. The assemblers uses a hash table based on the + instruction name anyhow. */ +/* name, suffix, args, match, mask, pinfo pinfo2, membership, ase */ +/* Pure macros */ +{"la", "", "t,A(b)", 0, (int) M_LA_AB, INSN_MACRO, 0, I38, 0}, +{"dla", "", "t,A(b)", 0, (int) M_DLA_AB, INSN_MACRO, 0, I38, 0}, +/* Precedence=1 */ +{"aluipc", "", "t,+K", 0xe0000002, 0xfc000002, WR_1, 0, I38, 0}, /* ALUIPC */ +{"break", "[16]", "", 0x1010, 0xffff, 0, INSN2_ALIAS, I38, 0}, +{"break", "[16]", "mK", 0x1010, 0xfff8, 0, 0, I38, 0}, +{"break", "[32]", "", 0x00100000, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, +{"break", "[32]", "+J", 0x00100000, 0xfff80000, 0, 0, I38, 0}, +{"dvp", "", "-A", 0x20000390, 0xffe0ffff, 0, INSN2_ALIAS, I38, 0}, /* DVP */ +{"dvp", "", "t,-A", 0x20000390, 0xfc00ffff, WR_1, 0, I38, 0}, +{"nop", "[16]", "", 0x9008, 0xffff, 0, 0, I38, 0}, /* NOP[16] */ +{"nop", "[32]", "", 0x8000c000, 0xffffffff, 0, 0, I38, 0}, /* NOP */ +{"sdbbp", "[16]", "", 0x1018, 0xffff, 0, INSN2_ALIAS, I38, 0}, +{"sdbbp", "[16]", "mK", 0x1018, 0xfff8, 0, 0, I38, 0}, +{"sdbbp", "[32]", "", 0x00180000, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, +{"sdbbp", "[32]", "+J", 0x00180000, 0xfff80000, 0, 0, I38, 0}, +{"move", "", "mb,mj", 0x1000, 0xfc00, WR_1|RD_2, 0, I38, 0}, /* preceded by BREAK, SDBBP */ +{"move", "", "d,s", 0x20000290, 0xffe007ff, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* OR */ +{"move", "", "d,s", 0x20000150, 0xffe007ff, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* ADDU */ +{"sigrie", "", "+J", 0x00000000, 0xfff80000, 0, 0, I38, 0}, +{"synci", "[u12]", "o(b)", 0x87e03000, 0xffe0f000, RD_2, 0, I38, 0}, /* SYNCI[U12] */ +{"synci", "[s9]", "+j(b)", 0xa7e01800, 0xffe07f00, RD_2, 0, I38, 0}, /* SYNCI[S9] */ +{"syncie", "", "+j(b)", 0xa7e01a00, 0xffe07f00, RD_2, 0, 0, EVA}, +{"jrc", "[16]", "mp", 0xd800, 0xfc1f, RD_1, 0, I38, 0}, /* JRC[16] */ +{"jrc", "[32]", "s", 0x48000000, 0xffe0ffff, RD_1, INSN2_ALIAS, I38, 0}, /* JALRC */ +{"jalrc", "[16]", "mp", 0xd810, 0xfc1f, WR_31|RD_1, 0, I38, 0}, /* JALRC[16] */ +{"jalrc", "[16]", "my,mp", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS, I38, 0}, /* JALRC[16] */ +{"jalrc", "[32]", "s", 0x4be00000, 0xffe0ffff, RD_1, INSN2_ALIAS, I38, 0}, /* JALRC[32] */ +{"jalrc", "[32]", "t,s,-C", 0x48000000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, +{"jalrc", "", "mp,-i", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS, I38, 0}, /* JALRC[16] */ +{"jalrc", "", "s,-i", 0x4be00000, 0xffe0ffff, RD_1, INSN2_ALIAS, I38, 0}, /* JALRC[32] */ +{"jr", "", "mp", 0xd800, 0xfc1f, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JRC */ +{"jr", "", "s", 0x48000000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */ +{"jalr", "", "my,mp", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC[16] */ +{"jalr", "", "mp", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC[16] */ +{"jalr", "", "s", 0x4be00000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */ +{"jalr", "", "t,s", 0x48000000, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */ +{"lui", "", "t,u", 0xe0000000, 0xfc000002, WR_1, 0, I38, 0}, +{"li", "[16]", "md,mI", 0xd000, 0xfc00, WR_1, 0, I38, 0}, /* LI[16] */ +{"li", "", "mb,mZ", 0x1000, 0xfc1f, WR_1, INSN2_ALIAS, I38, 0}, /* MOVE[16] */ +{"li", "[32]", "+t,j", 0x00000000, 0xfc1f0000, WR_1, INSN2_ALIAS, I38, 0}, /* ADDIU[32] */ +{"li", "[neg]", "t,h", 0x80008000, 0xfc1ff000, WR_1, INSN2_ALIAS, I38, 0}, /* ADDIU[NEG] */ +{"li", "", "t,x", 0xe0000000, 0xfc000002, WR_1, INSN2_ALIAS, I38, 0}, /* LUI */ +{"li", "[48]", "mp,+Q", 0x6000, 0xfc1f, WR_1, 0, 0, xNMS}, /* LI[48] */ +{"li", "", "+t,A", 0, (int) M_LI, INSN_MACRO, INSN2_MACRO, I38, 0}, +{"ext", "", "t,r,+A,+C", 0x8000f000, 0xfc00f820, WR_1|RD_2, 0, 0, xNMS}, +{"ext", "", "t,r,+A,+C", 0, (int) M_EXT, INSN_MACRO, 0, I38, 0}, + +/* Precedence=0 */ +{"abs", "", "d,v", 0, (int) M_ABS, INSN_MACRO, 0, I38, 0}, +{"absq_s.ph", "", "t,s", 0x2000113f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"absq_s.qb", "", "t,s", 0x2000013f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"absq_s.w", "", "t,s", 0x2000213f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"add", "", "d,v,t,-B", 0x20000110, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, xNMS}, +{"add", "", "t,r,I", 0, (int) M_ADD_I, INSN_MACRO, 0, 0, xNMS}, +{"addi", "", "t,r,I", 0, (int) M_ADD_I, INSN_MACRO, 0, 0, xNMS}, +{"addiu", "[r1.sp]", "md,ms,mS", 0x7040, 0xfc40, WR_1|RD_2, 0, I38, 0}, /* ADDIU[R1.SP] */ +{"addiu", "[r2]", "md,mc,mB", 0x9000, 0xfc08, WR_1|RD_2, 0, I38, 0}, /* ADDIU[R2] */ +{"addiu", "[rs5]", "mp,mk,mQ", 0x9008, 0xfc08, MOD_1, INSN2_ALIAS, I38, 0}, /* ADDIU[RS5] */ +{"addiu", "[rs5]", "mp,mQ", 0x9008, 0xfc08, MOD_1, 0, I38, 0}, /* ADDIU[RS5], preceded by NOP[16] */ +{"addiu", "[gp.b]", "t,ma,+1", 0x440c0000, 0xfc1c0000, WR_1|RD_2, 0, I38, 0}, /* ADDIU[GP.B] */ +{"addiu", "[gp.w]", "t,ma,.", 0x40000000, 0xfc000003, WR_1|RD_2, 0, I38, 0}, /* ADDIU[GP.W] */ +{"addiu", "[32]", "+t,r,j", 0x00000000, 0xfc000000, WR_1|RD_2, 0, I38, 0}, /* preceded by SIGRIE */ +{"addiu", "[neg]", "t,r,h", 0x80008000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, /* ADDIU[NEG] */ +{"addiu", "[48]", "mp,mt,+R", 0x6001, 0xfc1f, MOD_1, 0, 0, xNMS}, /* ADDIU[48] */ +{"addiu", "[gp48]", "mp,ma,+O", 0x6002, 0xfc1f, WR_1|RD_2, 0, 0, xNMS}, /* ADDIU[GP48] */ +{"lapc", "[32]", "t,+r", 0x04000000, 0xfc000000, WR_1, INSN2_ALIAS, I38, 0}, /* ADDIUPC */ +{"lapc", "[48]", "mp,+S", 0x6003, 0xfc1f, WR_1, INSN2_ALIAS, 0, xNMS}, /* ADDIUPC[48] */ +{"lapc.h", "", "t,+r", 0x04000000, 0xfc000000, WR_1, INSN2_ALIAS, I38, 0}, /* ADDIUPC */ +{"lapc.b", "", "mp,+S", 0x6003, 0xfc1f, WR_1, INSN2_ALIAS, 0, xNMS}, /* ADDIUPC[48] */ +{"addiupc", "[32]", "t,+s", 0x04000000, 0xfc000000, WR_1, 0, I38, 0}, +{"addiupc", "[48]", "mp,+P", 0x6003, 0xfc1f, WR_1, 0, 0, xNMS}, /* ADDIUPC[48] */ +{"addiu.b", "", "t,ma,+1", 0x440c0000, 0xfc1c0000, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* ADDIU[GP.B] */ +{"addiu.w", "", "t,ma,.", 0x40000000, 0xfc000003, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* ADDIU[GP.W] */ +{"addiu.b32", "", "mp,ma,+O", 0x6002, 0xfc1f, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ADDIU[GP48] */ +{"addq.ph", "", "d,s,t", 0x2000000d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addqh.ph", "", "d,s,t", 0x2000004d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addqh.w", "", "d,s,t", 0x2000008d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addqh_r.ph", "", "d,s,t", 0x2000044d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addqh_r.w", "", "d,s,t", 0x2000048d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addq_s.ph", "", "d,s,t", 0x2000040d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addq_s.w", "", "d,s,t,-B", 0x20000305, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addsc", "", "d,s,t,-B", 0x20000385, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addu", "[16]", "me,mc,md", 0xb000, 0xfc01, WR_1|RD_2|RD_3, 0, I38, 0}, /* ADDU[16] */ +{"addu", "[4x4]", "mu,mt,mv", 0x3c00, 0xfd08, MOD_1|RD_3, 0, 0, xNMS}, /* ADDU[4X4] */ +{"addu", "[4x4]", "mu,mv,mk", 0x3c00, 0xfd08, MOD_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ADDU[4X4] */ +{"addu", "[32]", "d,v,t,-B", 0x20000150, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"addu", "", "t,r,I", 0, (int) M_ADDU_I, INSN_MACRO, 0, I38, 0}, +{"addu.ph", "", "d,s,t", 0x2000010d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addu.qb", "", "d,s,t", 0x200000cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"adduh.qb", "", "d,s,t", 0x2000014d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"adduh_r.qb", "", "d,s,t", 0x2000054d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addu_s.ph", "", "d,s,t", 0x2000050d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addu_s.qb", "", "d,s,t", 0x200004cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"addwc", "", "d,s,t,-B", 0x200003c5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"extw", "", "d,s,t,+I", 0x2000001f, 0xfc00003f, WR_1|RD_2|RD_3, 0, I38, 0}, +{"align", "", "mb,-i,mj,mz", 0x1000, 0xfc00, WR_1|RD_3, INSN2_ALIAS, I38, 0}, /* MOVE[16] */ +{"align", "", "d,-i,s,mz", 0x20000290, 0xffe007ff, WR_1|RD_3, INSN2_ALIAS, I38, 0}, /* MOVE[32] */ +{"align", "", "d,s,t,+v", 0x2000001f, 0xfc00003f, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* EXTW */ +{"and", "[16]", "md,mk,ml", 0x5008, 0xfc0f, MOD_1|RD_3, INSN2_ALIAS, I38, 0}, /* AND[16] */ +{"and", "[16]", "md,ml,mk", 0x5008, 0xfc0f, MOD_1|RD_2, INSN2_ALIAS, I38, 0}, /* AND[16] */ +{"and", "[16]", "md,ml", 0x5008, 0xfc0f, MOD_1|RD_2, 0, I38, 0}, /* AND[16] */ +{"and", "[32]", "d,v,t,-B", 0x20000250, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"and", "[32]", "t,r,I", 0, (int) M_AND_I, INSN_MACRO, 0, I38, 0}, +{"andi", "[16]", "md,mc,mC", 0xf000, 0xfc00, WR_1|RD_2, 0, I38, 0}, /* ANDI[16] */ +{"andi", "[32]", "t,r,g", 0x80002000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, +{"andi", "", "t,r,+6", 0x8000f000, 0xfc00f83f, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* EXT */ +{"append", "", "t,s,1", 0x20000215, 0xfc0007ff, WR_1|RD_2, 0, 0, D32}, +{"balc", "[16]", "mD", 0x3800, 0xfc00, WR_31, 0, I38, 0}, /* BALC[16] */ +{"balc", "[32]", "+u", 0x2a000000, 0xfe000000, WR_31, 0, I38, 0}, +{"bal", "", "mD", 0x3800, 0xfc00, WR_31, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BALC[16] */ +{"bal", "", "+u", 0x2a000000, 0xfe000000, WR_31, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BALC */ +{"balign", "", "d,-m,s,+v", 0x2000001f, 0xfc00003f, WR_1|RD_3, INSN2_ALIAS, 0, D32}, /* EXTW */ +{"balrsc", "", "+t,s,-C", 0x48008000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, +{"balrsc", "", "s", 0x4be08000, 0xffe0ffff, RD_1|WR_31, INSN2_ALIAS, I38, 0}, /* BALRSC */ +{"bbeqzc", "", "t,1,~,-D", 0xc8040000, 0xfc1d0000, RD_1, 0, 0, xNMS}, +{"bbnezc", "", "t,1,~,-D", 0xc8140000, 0xfc1d0000, RD_1, 0, 0, xNMS}, +{"bc", "[16]", "mD", 0x1800, 0xfc00, 0, 0, I38, 0}, /* BC[16] */ +{"bc", "[32]", "+u", 0x28000000, 0xfe000000, 0, 0, I38, 0}, +{"b", "", "mD", 0x1800, 0xfc00, 0, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BC[16] */ +{"b", "", "+u", 0x28000000, 0xfe000000, 0, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BC */ +{"beqzc", "[16]", "md,mE", 0x9800, 0xfc00, RD_1, 0, I38, 0}, /* BEQZC[16] */ +{"beqzc", "[32]", "t,p", 0x88000000, 0xfc1fc000, RD_1, INSN2_ALIAS, I38, 0}, /* BEQC */ +{"beqzc", "[32]", "s,p", 0x88000000, 0xffe0c000, RD_1, INSN2_ALIAS, I38, 0}, /* BEQC */ +{"beqz", "", "md,mE", 0x9800, 0xfc00, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BEQZC[16] */ +{"beqz", "", "t,p", 0x88000000, 0xfc1fc000, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BEQC */ +{"beqz", "", "s,p", 0x88000000, 0xffe0c000, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BEQC */ +{"beqc", "[16]", "md,z,mE", 0x9800, 0xfc00, RD_1, INSN2_ALIAS, I38, 0}, /* BEQZC[16] */ +{"beqc", "[16]", "z,md,mE", 0x9800, 0xfc00, RD_1, INSN2_ALIAS, I38, 0}, /* BEQZC[16] */ +{"beqc", "[16]", "ml,mf,mF", 0xd800, 0xfc00, RD_1|RD_2, 0, 0, xNMS}, /* BEQC[16], with rs3=rt3 && u[4:1]!=0 */ +{"bnec", "[16]", "md,mi,mF", 0xd800, 0xfc00, RD_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* BNEC[16], with operands commutated */ +{"bnec", "[32]", "s,t,p", 0xa8000000, 0xfc00c000, RD_1|RD_2, 0, I38, 0}, +{"bne", "", "md,z,mE", 0xb800, 0xfc00, RD_1, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BNEZC[16] */ +{"bne", "", "z,md,mE", 0xb800, 0xfc00, RD_2, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BNEZC[16] */ +{"bne", "", "ml,mh,mF", 0xd800, 0xfc00, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, 0, xNMS}, /* BNEC[16], with rs3>=rt3 && u[4:1]!=0 */ +{"bne", "", "md,mi,mF", 0xd800, 0xfc00, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, 0, xNMS}, /* BNEC[16], with operands commutated */ +{"bne", "", "s,t,p", 0xa8000000, 0xfc00c000, RD_1|RD_2, INSN2_ALIAS|CBR|CTC, I38, 0}, /* BNEC */ +{"bne", "", "s,I,p", 0, (int) M_BNE_I, INSN_MACRO, 0, I38, 0}, +{"bneic", "", "t,+9,~", 0xc8100000, 0xfc1c0000, RD_1, 0, I38, 0}, +{"bposge32c", "", "p,-I", 0x88044000, 0xfc1fc000, 0, 0, 0, D32}, +{"bposge32", "", "p", 0x88044000, 0xffffc000, 0, INSN2_ALIAS|CBR|CTC, 0, D32}, /* BPOSGE32C */ +{"brsc", "", "s,-C", 0x48008000, 0xffe0f000, RD_1, 0, I38, 0}, +{"byterevh", "", "t,r", 0x8000d608, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ROTX t,s,8,24 */ +{"byterevw", "", "t,r", 0x8000d218, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ROTX t,s,24,8 */ +{"cache", "", "k,+j(b)", 0xa4003900, 0xfc007f00, RD_3, 0, I38, 0}, +{"cache", "", "k,A(c)", 0, (int) M_CACHE_AC, INSN_MACRO, 0, I38, 0}, +{"cachee", "", "k,+j(b)", 0xa4003a00, 0xfc007f00, RD_3, 0, 0, EVA}, +{"cachee", "", "k,A(c)", 0, (int) M_CACHEE_AC, INSN_MACRO, 0, 0, EVA}, +{"cfc1", "", "t,G", 0xa000103b, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, I38, 0}, +{"cfc1", "", "t,S", 0xa000103b, 0xfc00ffff, WR_1|RD_2, 0, I38, 0}, +{"cftc1", "", "t,G", 0x20001e30, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"cftc1", "", "t,S", 0x20001e30, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"cftc2", "", "t,G", 0x20002e30, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"clo", "", "t,s", 0x20004b3f, 0xfc00ffff, WR_1|RD_2, 0, 0, xNMS}, +{"clz", "", "t,s", 0x20005b3f, 0xfc00ffff, WR_1|RD_2, 0, 0, xNMS}, +{"cmp.eq.ph", "", "s,t,-N", 0x20000005, 0xfc0003ff, WR_1|RD_2, 0, 0, D32}, +{"cmp.le.ph", "", "s,t,-N", 0x20000085, 0xfc0003ff, WR_1|RD_2, 0, 0, D32}, +{"cmp.lt.ph", "", "s,t,-N", 0x20000045, 0xfc0003ff, WR_1|RD_2, 0, 0, D32}, +{"cmpgdu.eq.qb", "", "d,s,t,-B", 0x20000185, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"cmpgdu.le.qb", "", "d,s,t,-B", 0x20000205, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"cmpgdu.lt.qb", "", "d,s,t,-B", 0x200001c5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"cmpgu.eq.qb", "", "d,s,t,-B", 0x200000c5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"cmpgu.le.qb", "", "d,s,t,-B", 0x20000145, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"cmpgu.lt.qb", "", "d,s,t,-B", 0x20000105, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"cmpu.eq.qb", "", "s,t,-N", 0x20000245, 0xfc0003ff, WR_1|RD_2, 0, 0, D32}, +{"cmpu.le.qb", "", "s,t,-N", 0x200002c5, 0xfc0003ff, WR_1|RD_2, 0, 0, D32}, +{"cmpu.lt.qb", "", "s,t,-N", 0x20000285, 0xfc0003ff, WR_1|RD_2, 0, 0, D32}, +{"cop2_1", "", "C", 0x20000002, 0xfc000007, 0, 0, I38, 0}, +{"crc32b", "", "t,r,-E", 0x200003e8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC}, +{"crc32h", "", "t,r,-E", 0x200007e8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC}, +{"crc32w", "", "t,r,-E", 0x20000be8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC}, +{"crc32cb", "", "t,r,-E", 0x200013e8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC}, +{"crc32ch", "", "t,r,-E", 0x200017e8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC}, +{"crc32cw", "", "t,r,-E", 0x20001be8, 0xfc001fff, WR_1|RD_2, 0, 0, CRC}, +{"ctc1", "", "t,G", 0xa000183b, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS, I38, 0}, +{"ctc1", "", "t,S", 0xa000183b, 0xfc00ffff, RD_1|WR_2, 0, I38, 0}, +{"cttc1", "", "t,G", 0x20001e70, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"cttc1", "", "t,S", 0x20001e70, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"cttc2", "", "t,G", 0x20002e70, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"dabs", "", "d,v", 0, (int) M_DABS, INSN_MACRO, 0, I38, 0}, +{"daddiu", "[neg]", "t,r,h", 0x80008000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, /* DADDIU[NEG] */ +{"deret", "", "-F", 0x2000e37f, 0xfc00ffff, 0, 0, I38, 0}, +{"di", "", "", 0x2000477f, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, +{"di", "", "w,-A", 0x2000477f, 0xfc00ffff, WR_1, 0, I38, 0}, +{"div", "", "d,v,t,-B", 0x20000118, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"div", "", "d,v,I", 0, (int) M_DIV_I, INSN_MACRO, 0, I38, 0}, +{"divu", "", "d,v,t,-B", 0x20000198, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"divu", "", "d,v,I", 0, (int) M_DIVU_I, INSN_MACRO, 0, I38, 0}, +{"dmt", "", "", 0x20010ab0, 0xffffffff, 0, INSN2_ALIAS, 0, MT32}, +{"dmt", "", "t", 0x20010ab0, 0xfc1fffff, WR_1, 0, 0, MT32}, +{"dpa.w.ph", "", "7,s,t", 0x200000bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpaqx_s.w.ph", "", "7,s,t", 0x200022bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpaqx_sa.w.ph","", "7,s,t", 0x200032bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpaq_s.w.ph", "", "7,s,t", 0x200002bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpaq_sa.l.w", "", "7,s,t", 0x200012bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpau.h.qbl", "", "7,s,t", 0x200020bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpau.h.qbr", "", "7,s,t", 0x200030bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpax.w.ph", "", "7,s,t", 0x200010bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dps.w.ph", "", "7,s,t", 0x200004bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpsqx_s.w.ph", "", "7,s,t", 0x200026bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpsqx_sa.w.ph", "", "7,s,t", 0x200036bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpsq_s.w.ph", "", "7,s,t", 0x200006bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpsq_sa.l.w", "", "7,s,t", 0x200016bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpsu.h.qbl", "", "7,s,t", 0x200024bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpsu.h.qbr", "", "7,s,t", 0x200034bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dpsx.w.ph", "", "7,s,t", 0x200014bf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"dvpe", "", "", 0x20000ab0, 0xffffffff, 0, INSN2_ALIAS, 0, MT32}, /* DVPE */ +{"dvpe", "", "t", 0x20000ab0, 0xfc1fffff, WR_1, 0, 0, MT32}, +{"ehb", "", "-G", 0x8000c003, 0xffe0f1ff, 0, 0, I38, 0}, +{"ei", "", "", 0x2000577f, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, +{"ei", "", "t,-A", 0x2000577f, 0xfc00ffff, WR_1, 0, I38, 0}, +{"emt", "", "", 0x20010eb0, 0xffffffff, 0, INSN2_ALIAS, 0, MT32}, +{"emt", "", "t", 0x20010eb0, 0xfc1fffff, WR_1, 0, 0, MT32}, +{"eret", "", "-H", 0x2000f37f, 0xfc01ffff, 0, 0, I38, 0}, +{"eretnc", "", "-H", 0x2001f37f, 0xfc01ffff, 0, 0, I38, 0}, +{"evpe", "", "", 0x20000eb0, 0xffffffff, 0, INSN2_ALIAS, 0, MT32}, /* EVPE */ +{"evpe", "", "t", 0x20000eb0, 0xfc1fffff, WR_1, 0, 0, MT32}, +{"evp", "", "-A", 0x20000790, 0xffe0ffff, 0, INSN2_ALIAS, I38, 0}, /* EVP */ +{"evp", "", "t,-A", 0x20000790, 0xfc00ffff, WR_1, 0, I38, 0}, +{"extp", "", "t,7,2", 0x2000267f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, +{"extpdp", "", "t,7,2", 0x2000367f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, +{"extpdpv", "", "t,7,s", 0x200038bf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"extpv", "", "t,7,s", 0x200028bf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"extr.w", "", "t,7,2", 0x20000e7f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, +{"extrv.w", "", "t,7,s", 0x20000ebf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"extrv_r.w", "", "t,7,s", 0x20001ebf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"extrv_rs.w", "", "t,7,s", 0x20002ebf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"extrv_s.h", "", "t,7,s", 0x20003ebf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"extr_r.w", "", "t,7,2", 0x20001e7f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, +{"extr_rs.w", "", "t,7,2", 0x20002e7f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, +{"extr_s.h", "", "t,7,2", 0x20003e7f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, +{"fork", "", "d,s,t,-B", 0x20000228, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, MT32}, +{"ginvi", "", "s,-I", 0x20001f7f, 0xfc00ffff, RD_1, 0, 0, GINV}, +{"ginvt", "", "s,+;,-J", 0x20000f7f, 0xfc00ffff, RD_1, 0, 0, GINV}, +{"ins", "", "t,r,+A,+B", 0x8000e000, 0xfc00f820, WR_1|RD_2, 0, 0, xNMS}, +{"ins", "", "t,r,+A,+B", 0, (int) M_INS, INSN_MACRO, 0, I38, 0}, +{"insv", "", "t,s", 0x2000413f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"j", "", "mp", 0xd800, 0xfc1f, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, +{"j", "", "+u", 0x28000000, 0xfe000000, 0, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BC */ +{"j", "", "s", 0x48000000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */ +{"jrc.hb", "", "s", 0x48001000, 0xffe0ffff, RD_1, INSN2_ALIAS, I38, 0}, /* JALRC.HB */ +{"jr.hb", "", "s", 0x48001000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC.HB */ +{"jalrc.hb", "", "s", 0x4be01000, 0xffe0ffff, RD_1, INSN2_ALIAS, I38, 0}, /* JALRC.HB */ +{"jalrc.hb", "", "t,s,-C", 0x48001000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, +{"jalr.hb", "", "s", 0x4be01000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC.HB */ +{"jalr.hb", "", "t,s", 0x48001000, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC.HB */ +/* SVR4 PIC code requires special handling for jal, so it must be a macro. */ +{"jal", "", "my,mp", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC[16] */ +{"jal", "", "mp", 0xd810, 0xfc1f, WR_31|RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC[16] */ +{"jal", "", "s", 0x4be00000, 0xffe0ffff, RD_1, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */ +{"jal", "", "t,s", 0x48000000, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS|UBR|CTC, I38, 0}, /* JALRC */ +{"jal", "", "A", 0, (int) M_JAL_A, INSN_MACRO, 0, I38, 0}, +{"jal", "", "+u", 0x2a000000, 0xfe000000, WR_31, INSN2_ALIAS|UBR|CTC, I38, 0}, /* BALC */ +{"lb", "[16]", "md,mL(ml)", 0x5c00, 0xfc0c, WR_1|RD_3, 0, I38, 0}, /* LB[16] */ +{"lb", "[gp]", "t,+1(ma)", 0x44000000, 0xfc1c0000, WR_1|RD_3, 0, I38, 0}, /* LB[GP] */ +{"lb", "[u12]", "t,o(b)", 0x84000000, 0xfc00f000, WR_1|RD_3, 0, I38, 0}, /* LB[U12] */ +{"lb", "[s9]", "t,+j(b)", 0xa4000000, 0xfc007f00, WR_1|RD_3, 0, I38, 0}, /* LB[S9] */ +{"lb", "", "t,A(c)", 0, (int) M_LB_AC, INSN_MACRO, 0, I38, 0}, +{"lb", "", "t,A(b)", 0, (int) M_LBX_AB, INSN_MACRO, 0, I38, 0}, +{"lbe", "", "t,+j(b)", 0xa4000200, 0xfc007f00, WR_1|RD_3, 0, 0, EVA}, +{"lbe", "", "t,A(c)", 0, (int) M_LBE_AC, INSN_MACRO, 0, 0, EVA}, +{"lbu", "[16]", "md,mL(ml)", 0x5c08, 0xfc0c, WR_1|RD_3, 0, I38, 0}, /* LBU[16] */ +{"lbu", "[gp]", "t,+1(ma)", 0x44080000, 0xfc1c0000, WR_1|RD_3, 0, I38, 0}, /* LBU[GP] */ +{"lbu", "[u12]", "t,o(b)", 0x84002000, 0xfc00f000, WR_1|RD_3, 0, I38, 0}, /* LBU[U12] */ +{"lbu", "[s9]", "t,+j(b)", 0xa4001000, 0xfc007f00, WR_1|RD_3, 0, I38, 0}, /* LBU[S9] */ +{"lbu", "", "t,A(c)", 0, (int) M_LBU_AC, INSN_MACRO, 0, I38, 0}, +{"lbu", "", "t,A(b)", 0, (int) M_LBUX_AB, INSN_MACRO, 0, I38, 0}, +{"lbue", "", "t,+j(b)", 0xa4001200, 0xfc007f00, WR_1|RD_3, 0, 0, EVA}, +{"lbue", "", "t,A(c)", 0, (int) M_LBUE_AC, INSN_MACRO, 0, 0, EVA}, +{"lbux", "", "d,s(t)", 0x20000107, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"lbx", "", "d,s(t)", 0x20000007, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"ld", "", "t,A(c)", 0, (int) M_LD_AC, INSN_MACRO, 0, I38, 0}, +{"ld", "", "t,A(b)", 0, (int) M_LDX_AB, INSN_MACRO, 0, I38, 0}, +{"lh", "[16]", "md,mH(ml)", 0x7c00, 0xfc09, WR_1|RD_3, 0, I38, 0}, /* LH[16] */ +{"lh", "[gp]", "t,+3(ma)", 0x44100000, 0xfc1c0001, WR_1|RD_3, 0, I38, 0}, /* LH[GP] */ +{"lh", "[u12]", "t,o(b)", 0x84004000, 0xfc00f000, WR_1|RD_3, 0, I38, 0}, /* LH[U12] */ +{"lh", "[s9]", "t,+j(b)", 0xa4002000, 0xfc007f00, WR_1|RD_3, 0, I38, 0}, /* LH[S9] */ +{"lh", "", "t,A(c)", 0, (int) M_LH_AC, INSN_MACRO, 0, I38, 0}, +{"lh", "", "t,A(b)", 0, (int) M_LHX_AB, INSN_MACRO, 0, I38, 0}, +{"lhe", "", "t,+j(b)", 0xa4002200, 0xfc007f00, WR_1|RD_3, 0, 0, EVA}, +{"lhe", "", "t,A(c)", 0, (int) M_LHE_AC, INSN_MACRO, 0, 0, EVA}, +{"lhu", "[16]", "md,mH(ml)", 0x7c08, 0xfc09, WR_1|RD_3, 0, I38, 0}, /* LHU[16] */ +{"lhu", "[gp]", "t,+3(ma)", 0x44100001, 0xfc1c0001, WR_1|RD_3, 0, I38, 0}, /* LHU[GP] */ +{"lhu", "[u12]", "t,o(b)", 0x84006000, 0xfc00f000, WR_1|RD_3, 0, I38, 0}, /* LHU[U12] */ +{"lhu", "[s9]", "t,+j(b)", 0xa4003000, 0xfc007f00, WR_1|RD_3, 0, I38, 0}, /* LHU[S9] */ +{"lhu", "", "t,A(c)", 0, (int) M_LHU_AC, INSN_MACRO, 0, I38, 0}, +{"lhu", "", "t,A(b)", 0, (int) M_LHUX_AB, INSN_MACRO, 0, I38, 0}, +{"lhue", "", "t,+j(b)", 0xa4003200, 0xfc007f00, WR_1|RD_3, 0, 0, EVA}, +{"lhue", "", "t,A(c)", 0, (int) M_LHUE_AC, INSN_MACRO, 0, 0, EVA}, +{"lhux", "", "d,s(t)", 0x20000307, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"lhuxs", "", "d,s(t)", 0x20000347, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"lhx", "", "d,s(t)", 0x20000207, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"lhxs", "", "d,s(t)", 0x20000247, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"li.d", "", "t,F", 0, (int) M_LI_D, INSN_MACRO, 0, I38, 0}, +{"li.s", "", "t,f", 0, (int) M_LI_S, INSN_MACRO, 0, I38, 0}, +{"ll", "", "t,+p(b)", 0xa4005100, 0xfc007f03, WR_1|RD_3, 0, I38, 0}, +{"ll", "", "t,A(c)", 0, (int) M_LL_AC, INSN_MACRO, 0, I38, 0}, +{"lle", "", "t,+p(b)", 0xa4005200, 0xfc007f03, WR_1|RD_3, 0, 0, EVA}, +{"lle", "", "t,A(c)", 0, (int) M_LLE_AC, INSN_MACRO, 0, 0, EVA}, +{"llwp", "", "t,e,(b),-K", 0xa4005101, 0xfc007f03, WR_1|WR_2|RD_3, 0, 0, xNMS}, +{"llwp", "", "t,e,A(c)", 0, (int) M_LLWP_AC, INSN_MACRO, 0, 0, xNMS}, +{"llwpe", "", "t,e,(b),-K", 0xa4005201, 0xfc007f03, WR_1|WR_2|RD_3, 0, 0, EVA}, +{"llwpe", "", "t,e,A(c)", 0, (int) M_LLWP_AC, INSN_MACRO, 0, 0, EVA}, +{"lsa", "", "d,v,t,+w,-L", 0x2000000f, 0xfc00003f, WR_1|RD_2|RD_3, 0, I38, 0}, +{"lw", "[16]", "md,mJ(ml)", 0x1400, 0xfc00, WR_1|RD_3, 0, I38, 0}, /* LW[16] */ +{"lw", "[4x4]", "mu,mN(mv)", 0x7400, 0xfc00, WR_1|RD_3, 0, 0, xNMS}, /* LW[4X4] */ +{"lw", "[sp]", "mp,mR(ms)", 0x3400, 0xfc00, WR_1|RD_3, 0, I38, 0}, /* LW[SP] */ +{"lw", "[gp16]", "md,mO(ma)", 0x5400, 0xfc00, WR_1|RD_3, 0, I38, 0}, /* LW[GP16] */ +{"lw", "[gp]", "t,.(ma)", 0x40000002, 0xfc000003, WR_1|RD_3, 0, I38, 0}, /* LW[GP] */ +{"lw", "[gp16]", "md,mA(ma)", 0x5400, 0xfc00, WR_1|RD_3, 0, I38, 0}, /* LW[GP16] */ +{"lw", "[u12]", "t,o(b)", 0x84008000, 0xfc00f000, WR_1|RD_3, 0, I38, 0}, /* LW[U12] */ +{"lw", "[s9]", "t,+j(b)", 0xa4004000, 0xfc007f00, WR_1|RD_3, 0, I38, 0}, /* LW[S9] */ +{"lw", "", "t,A(c)", 0, (int) M_LW_AC, INSN_MACRO, 0, I38, 0}, +{"lw", "", "t,A(b)", 0, (int) M_LWX_AB, INSN_MACRO, 0, I38, 0}, +{"lwe", "", "t,+j(b)", 0xa4004200, 0xfc007f00, WR_1|RD_3, 0, 0, EVA}, +{"lwe", "", "t,A(c)", 0, (int) M_LWE_AC, INSN_MACRO, 0, 0, EVA}, +{"lwm", "", "t,+j(b),|", 0xa4000400, 0xfc000f00, WR_1|RD_3, 0, 0, xNMS}, /* LWM */ +{"lwpc", "[48]", "mp,+S", 0x600b, 0xfc1f, WR_1, 0, 0, xNMS}, /* LWPC[48] */ +{"lwx", "", "d,s(t)", 0x20000407, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"lwxs", "[16]", "me,ml(md)", 0x5001, 0xfc01, WR_1|RD_2|RD_3, 0, I38, 0}, /* LWXS[16] */ +{"lwxs", "[32]", "d,s(t)", 0x20000447, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"madd", "[dsp]", "7,s,t", 0x20000abf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, /* MADD[DSP] */ +{"maddu", "[dsp]", "7,s,t", 0x20001abf, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, /* MADDU[DSP] */ +{"maq_s.w.phl", "", "7,s,t", 0x20001a7f, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"maq_s.w.phr", "", "7,s,t", 0x20000a7f, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"maq_sa.w.phl", "", "7,s,t", 0x20003a7f, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"maq_sa.w.phr", "", "7,s,t", 0x20002a7f, 0xfc003fff, MOD_1|RD_2|RD_3, 0, 0, D32}, +{"mfc0", "", "t,O", 0x20000030, 0xfc0007ff, WR_1, INSN2_ALIAS, I38, 0}, /* MFC0 with named register */ +{"mfc0", "", "t,P,J", 0x20000030, 0xfc0007ff, WR_1, INSN2_ALIAS, I38, 0}, /* MFC0 with named register & select */ +{"mfc0", "", "t,G,J,-B", 0x20000030, 0xfc0003ff, WR_1, 0, I38, 0}, +{"mfhc0", "", "t,O", 0x20000038, 0xfc0007ff, WR_1, INSN2_ALIAS, I38, 0}, /* MFHC0 with named register */ +{"mfhc0", "", "t,P,J", 0x20000038, 0xfc0007ff, WR_1, INSN2_ALIAS, I38, 0}, /* MFHC0 with named register & select*/ +{"mfhc0", "", "t,G,J,-B", 0x20000038, 0xfc0003ff, WR_1, 0, I38, 0}, +{"mfhi", "[dsp]", "t,7,-A", 0x2000007f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, /* MFHI[DSP] */ +{"mflo", "[dsp]", "t,7,-A", 0x2000107f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, /* MFLO[DSP] */ +{"mftc0", "", "t,O", 0x20000230, 0xfc0007ff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR with named register */ +{"mftc0", "", "t,P,J", 0x20000230, 0xfc0007ff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR with named register & select */ +{"mfthc0", "", "t,O", 0x20000238, 0xfc0007ff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR with named register */ +{"mfthc0", "", "t,P,J", 0x20000238, 0xfc0007ff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR with named register & select*/ +{"mftc1", "", "t,S", 0x20001630, 0xfc00ffff, WR_1|RD_2|FP_S, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mftc1", "", "t,G", 0x20001630, 0xfc00ffff, WR_1|RD_2|FP_S, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mftc2", "", "t,G", 0x20002630, 0xfc00ffff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mftdsp", "", "t", 0x20100e30, 0xfc1fffff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mftgpr", "", "t,s", 0x20000630, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mfthc1", "", "t,S", 0x20001638, 0xfc00ffff, WR_1|RD_2|FP_D, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mfthc1", "", "t,G", 0x20001638, 0xfc00ffff, WR_1|RD_2|FP_D, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mfthc2", "", "t,G", 0x20002638, 0xfc00ffff, WR_1, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mfthi", "", "t", 0x20010e30, 0xfc1fffff, WR_1|RD_a, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mfthi", "", "t,*", 0x20010e30, 0xfc13ffff, WR_1|RD_a, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mftlo", "", "t", 0x20000e30, 0xfc1fffff, WR_1|RD_a, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mftlo", "", "t,*", 0x20000e30, 0xfc13ffff, WR_1|RD_a, INSN2_ALIAS, 0, MT32}, /* MFTR */ +{"mftr", "", "t,s,!,H,$", 0x20000230, 0xfc0003f7, WR_1, 0, 0, MT32}, +{"mod", "", "d,v,t,-B", 0x20000158, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"mod", "", "d,v,I", 0, (int) M_MOD_I, INSN_MACRO, 0, I38, 0}, +{"modsub", "", "d,s,t,-B", 0x20000295, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"modu", "", "d,v,t,-B", 0x200001d8, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"modu", "", "d,v,I", 0, (int) M_MODU_I, INSN_MACRO, 0, I38, 0}, +{"move.balc", "", "+7,+5,+r", 0x08000000, 0xfc000000, WR_1|RD_2, 0, 0, xNMS}, +{"move.bal", "", "+7,+5,+r", 0x08000000, 0xfc000000, WR_1|RD_2, INSN2_ALIAS|UBR|CTC, 0, xNMS}, /* MOVE.BALC */ +{"movep", "", "mq,mx,mw", 0xbc00, 0xfc00, WR_1|RD_2|RD_3, 0, 0, xNMS}, /* MOVEP */ +{"movep", "", "mr,mw,mx", 0xbc00, 0xfc00, WR_1|RD_2|RD_3, INSN2_ALIAS, 0, xNMS}, /* MOVEP */ +{"movep", "[rev]", "mv,mu,mq", 0xfc00, 0xfc00, WR_1|WR_2|RD_3, 0, 0, xNMS}, /* MOVEP[REV] */ +{"movep", "[rev]", "mu,mv,mr", 0xfc00, 0xfc00, WR_1|WR_2|RD_3, INSN2_ALIAS, 0, xNMS}, /* MOVEP[REV] */ +{"movn", "", "d,v,t", 0x20000610, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"movz", "", "d,v,t", 0x20000210, 0xfc0007ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"msub", "[dsp]", "7,s,t", 0x20002abf, 0xfc003fff,MOD_1|RD_2|RD_3, 0, 0, D32}, /* MSUB[DSP] */ +{"msubu", "[dsp]", "7,s,t", 0x20003abf, 0xfc003fff,MOD_1|RD_2|RD_3, 0, 0, D32}, /* MSUBU[DSP] */ +{"mtc0", "", "t,O", 0x20000070, 0xfc0007ff, RD_1, INSN2_ALIAS, I38, 0}, /* MTC0 with named register */ +{"mtc0", "", "t,P,J", 0x20000070, 0xfc0007ff, RD_1, INSN2_ALIAS, I38, 0}, /* MTCO with named register & select */ +{"mtc0", "", "t,G,J,-B", 0x20000070, 0xfc0003ff, RD_1, 0, I38, 0}, +{"mthc0", "", "t,O", 0x20000078, 0xfc0007ff, RD_1, INSN2_ALIAS, I38, 0}, /* MTHC0 with named register */ +{"mthc0", "", "t,P,J", 0x20000078, 0xfc0007ff, RD_1, INSN2_ALIAS, I38, 0}, /* MTHC0 with named register & select */ +{"mthc0", "", "t,G,J,-B", 0x20000078, 0xfc0003ff, RD_1, 0, I38, 0}, +{"mthi", "[dsp]", "s,7,-I", 0x2000207f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, /* MTHI[DSP] */ +{"mthlip", "", "s,7,-I", 0x2000027f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, +{"mtlo", "[dsp]", "s,7,-I", 0x2000307f, 0xfc003fff, WR_1|RD_2, 0, 0, D32}, /* MTLO[DSP] */ +{"mttc0", "", "t,O", 0x20000270, 0xfc0007ff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR with named register */ +{"mttc0", "", "t,P,J", 0x20000270, 0xfc0007ff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR with named register & select */ +{"mtthc0", "", "t,O", 0x20000278, 0xfc0007ff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR with named register*/ +{"mtthc0", "", "t,P,J", 0x20000278, 0xfc0007ff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR with named register & select */ +{"mttc1", "", "t,S", 0x20001670, 0xfc00ffff, RD_1|WR_2|FP_S, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mttc1", "", "t,G", 0x20001670, 0xfc00ffff, RD_1|WR_2|FP_S, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mttc2", "", "t,G", 0x20002670, 0xfc00ffff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mttgpr", "", "s,t", 0x20000670, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS|INSN2_MTTGPR_RC1, 0, MT32}, /* MTTR */ +{"mttgpr", "", "t,s", 0x20000670, 0xfc00ffff, RD_1|WR_2, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mtthc1", "", "t,S", 0x20001678, 0xfc00ffff, RD_1|WR_2|FP_D, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mtthc1", "", "t,G", 0x20001678, 0xfc00ffff, RD_1|WR_2|FP_D, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mtthc2", "", "t,G", 0x20002678, 0xfc00ffff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mtthi", "", "t", 0x20010e70, 0xfc1fffff, RD_1|WR_a, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mtthi", "", "t,*", 0x20010e70, 0xfc13ffff, RD_1|WR_a, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mttlo", "", "t", 0x20000e70, 0xfc1fffff, RD_1|WR_a, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mttlo", "", "t,*", 0x20000e70, 0xfc13ffff, RD_1|WR_a, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mttdsp", "", "t", 0x20100e70, 0xfc1fffff, RD_1, INSN2_ALIAS, 0, MT32}, /* MTTR */ +{"mttr", "", "t,s,!,H,$", 0x20000270, 0xfc0003f7, RD_1, 0, 0, MT32}, +{"muh", "", "d,v,t,-B", 0x20000058, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"muhu", "", "d,v,t,-B", 0x200000d8, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"mul", "[4x4]", "mu,mt,mv", 0x3c08, 0xfd08, MOD_1|RD_3, 0, 0, xNMS}, /* MUL[4X4] */ +{"mul", "[4x4]", "mu,mv,mk", 0x3c08, 0xfd08, MOD_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* MUL[4X4] */ +{"mul", "[32]", "d,v,t,-B", 0x20000018, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"mul", "", "d,v,I", 0, (int) M_MUL_I, INSN_MACRO, 0, I38, 0}, +{"mul.ph", "", "d,s,t", 0x2000002d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"muleq_s.w.phl", "", "d,s,t,-B", 0x20000025, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"muleq_s.w.phr", "", "d,s,t,-B", 0x20000065, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"muleu_s.ph.qbl", "", "d,s,t,-B", 0x20000095, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"muleu_s.ph.qbr", "", "d,s,t,-B", 0x200000d5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"mulq_rs.ph", "", "d,s,t,-B", 0x20000115, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"mulq_rs.w", "", "d,s,t,-B", 0x20000195, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"mulq_s.ph", "", "d,s,t,-B", 0x20000155, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"mulq_s.w", "", "d,s,t,-B", 0x200001d5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"mulsa.w.ph", "", "7,s,t", 0x20002cbf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"mulsaq_s.w.ph", "", "7,s,t", 0x20003cbf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"mult", "[dsp]", "7,s,t", 0x20000cbf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, /* MULT[DSP] */ +{"multu", "[dsp]", "7,s,t", 0x20001cbf, 0xfc003fff, WR_1|RD_2|RD_3, 0, 0, D32}, /* MULTU[DSP] */ +{"mulu", "", "d,v,t,-B", 0x20000098, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"mul_s.ph", "", "d,s,t", 0x2000042d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"neg", "", "d,w", 0x20000190, 0xfc1f07ff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* SUB */ +{"negu", "", "d,w", 0x200001d0, 0xfc1f07ff, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* SUBU */ +{"not", "[16]", "md,ml", 0x5000, 0xfc0f, WR_1|RD_2, 0, I38, 0}, /* NOT[16] */ +{"not", "[32]", "d,v", 0x200002d0, 0xffe007ff, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* NOR */ +{"nor", "", "d,v,t,-B", 0x200002d0, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"nor", "", "t,r,I", 0, (int) M_NOR_I, INSN_MACRO, 0, I38, 0}, +{"or", "[16]", "md,mk,ml", 0x500c, 0xfc0f, WR_1|RD_3, INSN2_ALIAS, I38, 0}, /* OR[16] */ +{"or", "[16]", "md,ml,mk", 0x500c, 0xfc0f, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* OR[16] */ +{"or", "[16]", "md,ml", 0x500c, 0xfc0f, WR_1|RD_2, 0, I38, 0}, /* OR[16] */ +{"or", "[32]", "d,v,t,-B", 0x20000290, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"or", "", "t,r,I", 0, (int) M_OR_I, INSN_MACRO, 0, I38, 0}, +{"ori", "", "t,r,g", 0x80000000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, +{"pause", "", "-M", 0x8000c005, 0xfffff1ff, 0, 0, I38, 0}, +{"packrl.ph", "", "d,s,t,-B", 0x200001ad, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"pick.ph", "", "d,s,t,-B", 0x2000022d, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"pick.qb", "", "d,s,t,-B", 0x200001ed, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"preceq.w.phl", "", "t,s", 0x2000513f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"preceq.w.phr", "", "t,s", 0x2000613f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"precequ.ph.qbl", "", "t,s", 0x2000713f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"precequ.ph.qbla", "", "t,s", 0x2000733f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"precequ.ph.qbr", "", "t,s", 0x2000913f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"precequ.ph.qbra", "", "t,s", 0x2000933f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"preceu.ph.qbl", "", "t,s", 0x2000b13f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"preceu.ph.qbla", "", "t,s", 0x2000b33f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"preceu.ph.qbr", "", "t,s", 0x2000d13f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"preceu.ph.qbra", "", "t,s", 0x2000d33f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"precr.qb.ph", "", "d,s,t,-B", 0x2000006d, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"precrq.ph.w", "", "d,s,t,-B", 0x200000ed, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"precrq.qb.ph", "", "d,s,t,-B", 0x200000ad, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"precrqu_s.qb.ph", "", "d,s,t,-B", 0x2000016d, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"precrq_rs.ph.w", "", "d,s,t,-B", 0x2000012d, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"precr_sra.ph.w", "", "t,s,1", 0x200003cd, 0xfc0007ff, WR_1|RD_2, 0, 0, D32}, +{"precr_sra_r.ph.w", "", "t,s,1", 0x200007cd, 0xfc0007ff, WR_1|RD_2, 0, 0, D32}, +{"pref", "[u12]", "k,o(b)", 0x84003000, 0xfc00f000, RD_3, 0, I38, 0}, /* PREF[U12] */ +{"pref", "[s9]", "k,+j(b)", 0xa4001800, 0xfc007f00, RD_3, 0, I38, 0}, /* PREF[S9], preceded by SYNCI[S9] */ +{"pref", "", "k,A(c)", 0, (int) M_PREF_AC, INSN_MACRO, 0, I38, 0}, +{"prefe", "", "k,+j(b)", 0xa4001a00, 0xfc007f00, RD_3, 0, 0, EVA}, /* preceded by SYNCIE */ +{"prefe", "", "k,A(c)", 0, (int) M_PREFE_AC, INSN_MACRO, 0, 0, EVA}, +{"prepend", "", "d,-n,t,+I", 0x2000001f, 0xfc00003f, WR_1|RD_3, INSN2_ALIAS, 0, D32}, /* EXTW */ +{"raddu.w.qb", "", "t,s", 0x2000f13f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"rddsp", "", "t", 0x201fc67f, 0xfc1fffff, WR_1, INSN2_ALIAS, 0, D32}, +{"rddsp", "", "t,8", 0x2000067f, 0xfc003fff, WR_1, 0, 0, D32}, +{"rdhwr", "", "t,K", 0x200001c0, 0xfc0007ff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* RDHWR with sel=0 */ +{"rdhwr", "", "t,U,J", 0x200001c0, 0xfc0007ff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, +{"rdhwr", "", "t,G,H,-B", 0x200001c0, 0xfc0003ff, WR_1|RD_2, 0, 0, xNMS}, /* RDWHR */ +{"rdpgpr", "", "t,s", 0x2000e17f, 0xfc00ffff, WR_1|RD_2, 0, I38, 0}, +{"rem", "", "d,v,t", 0x20000158, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* MOD */ +{"rem", "", "d,v,I", 0, (int) M_REM_3I, INSN_MACRO, 0, I38, 0}, +{"remu", "", "d,v,t", 0x200001d8, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* MODU */ +{"repl.ph", "", "t,@,-B", 0x2000003d, 0xfc0003ff, WR_1, 0, 0, D32}, +{"repl.qb", "", "t,5,-O", 0x200005ff, 0xfc000fff, WR_1, 0, 0, D32}, +{"replv.ph", "", "t,s", 0x2000033f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"replv.qb", "", "t,s", 0x2000133f, 0xfc00ffff, WR_1|RD_2, 0, 0, D32}, +{"restore", "[32]", "+N,n", 0x80003002, 0xfc00f003, 0, 0, I38, 0}, +{"restore.jrc", "[16]", "mG", 0x1d00, 0xff0f, 0, 0, I38, 0}, /* RESTORE.JRC[16] */ +{"restore.jrc", "[16]", "mG,mn", 0x1d00, 0xfd00, 0, 0, I38, 0}, /* RESTORE.JRC[16], preceded by RESTORE[16] */ +{"restore.jrc", "[32]", "+N", 0x80003003, 0xfffff007, 0, 0, I38, 0}, /* RESTORE.JRC[32] */ +{"restore.jrc", "[32]", "+N,n", 0x80003003, 0xfc00f003, 0, 0, I38, 0}, +{"jraddiusp", "", "mG", 0x1d00, 0xff0f, 0, INSN2_ALIAS, I38, 0}, /* RESTORE.JRC[16] */ +{"jraddiusp", "", "+N", 0x80003003, 0xfffff007, 0, INSN2_ALIAS, I38, 0}, /* RESTORE.JRC[32] */ +{"jraddiusp", "", "I", 0, (int) M_JRADDIUSP, INSN_MACRO, 0, I38, 0}, +{"rol", "", "d,v,t", 0, (int) M_ROL, INSN_MACRO, 0, I38, 0}, +{"rol", "", "d,v,I", 0, (int) M_ROL_I, INSN_MACRO, 0, I38, 0}, +{"rotrv", "", "d,s,t,-B", 0x200000d0, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"rotr", "", "t,r,<,-M", 0x8000c0c0, 0xfc00f1e0, WR_1|RD_2, 0, I38, 0}, +{"rotr", "", "d,v,t", 0x200000d0, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* ROTRV */ +{"ror", "", "t,r,<", 0x8000c0c0, 0xfc00ffe0, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* ROTR */ +{"ror", "", "d,v,t", 0x200000d0, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* ROTRV */ +{"ror", "", "d,v,I", 0, (int) M_ROR_I, INSN_MACRO, 0, I38, 0}, +{"rorv", "", "t,r,<", 0x8000c0c0, 0xfc00ffe0, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* ROTR */ +{"rorv", "", "d,v,t", 0x200000d0, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* ROTRV */ +{"rotl", "", "d,v,t", 0, (int) M_ROL, INSN_MACRO, 0, I38, 0}, +{"rotl", "", "d,v,I", 0, (int) M_ROL_I, INSN_MACRO, 0, I38, 0}, +{"wsbh", "", "t,r", 0x8000d608, 0xfc00ffff, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* ROTX t,s,8,24*/ +{"rotx", "", "t,r,<,+*", 0x8000d000, 0xfc00f860, WR_1|RD_2, INSN2_ALIAS, 0, xNMS}, +{"rotx", "", "t,r,<,+*,+|", 0x8000d000, 0xfc00f820, WR_1|RD_2, 0, 0, xNMS}, +{"save", "[16]", "mG", 0x1c00, 0xff0f, 0, 0, I38, 0}, /* SAVE[16] */ +{"save", "[16]", "mG,mn", 0x1c00, 0xfd00, 0, 0, I38, 0}, /* SAVE[16] */ +{"save", "[32]", "+N,n", 0x80003000, 0xfc00f003, 0, 0, I38, 0}, +{"sb", "[16]", "mm,mL(ml)", 0x5c04, 0xfc0c, RD_1|RD_3, 0, I38, 0}, /* SB[16] */ +{"sb", "[gp]", "t,+1(ma)", 0x44040000, 0xfc1c0000, RD_1|RD_3, 0, I38, 0}, /* SB[GP] */ +{"sb", "[u12]", "t,o(b)", 0x84001000, 0xfc00f000, RD_1|RD_3, 0, I38, 0}, /* SB[U12] */ +{"sb", "[s9]", "t,+j(b)", 0xa4000800, 0xfc007f00, RD_1|RD_3, 0, I38, 0}, /* SB[S9] */ +{"sb", "", "t,A(c)", 0, (int) M_SB_AC, INSN_MACRO, 0, I38, 0}, +{"sb", "", "t,A(b)", 0, (int) M_SBX_AB, INSN_MACRO, 0, 0, xNMS}, +{"sbe", "", "t,+j(b)", 0xa4000a00, 0xfc007f00, RD_1|RD_3, 0, 0, EVA}, +{"sbe", "", "t,A(c)", 0, (int) M_SBE_AC, INSN_MACRO, 0, 0, EVA}, +{"sbx", "", "d,s(t)", 0x20000087, 0xfc0007ff, RD_1|RD_2|RD_3, 0, 0, xNMS}, +{"sc", "", "t,+p(b)", 0xa4005900, 0xfc007f03, MOD_1|RD_3, 0, I38, 0}, +{"sc", "", "t,A(c)", 0, (int) M_SC_AC, INSN_MACRO, 0, I38, 0}, +{"sce", "", "t,+p(b)", 0xa4005a00, 0xfc007f03, MOD_1|RD_3, 0, 0, EVA}, +{"sce", "", "t,A(c)", 0, (int) M_SCE_AC, INSN_MACRO, 0, 0, EVA}, +{"scwp", "", "t,e,(b),-K", 0xa4005901, 0xfc007f03, MOD_1|WR_2|RD_3, 0, 0, xNMS}, +{"scwp", "", "t,e,A(c)", 0, (int) M_SCWP_AC, INSN_MACRO, 0, 0, xNMS}, +{"scwpe", "", "t,e,(b),-K", 0xa4005a01, 0xfc007f03, MOD_1|WR_2|RD_3, 0, 0, EVA}, +{"scwpe", "", "t,e,A(c)", 0, (int) M_SCWP_AC, INSN_MACRO, 0, 0, EVA}, +{"sd", "", "t,A(c)", 0, (int) M_SD_AC, INSN_MACRO, 0, I38, 0}, +{"sd", "", "t,A(b)", 0, (int) M_SDX_AB, INSN_MACRO, 0, I38, 0}, +{"seb", "", "t,r,-N", 0x20000008, 0xfc0003ff, WR_1|RD_2, 0, 0, xNMS}, +{"seh", "", "t,r,-N", 0x20000048, 0xfc0003ff, WR_1|RD_2, 0, I38, 0}, +{"seqi", "", "t,r,i", 0x80006000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, +{"seq", "", "d,v,t", 0, (int) M_SEQ, INSN_MACRO, 0, I38, 0}, +{"seq", "", "d,v,I", 0, (int) M_SEQ_I, INSN_MACRO, 0, I38, 0}, +{"sge", "", "d,v,t", 0, (int) M_SGE, INSN_MACRO, 0, I38, 0}, +{"sge", "", "d,v,I", 0, (int) M_SGE_I, INSN_MACRO, 0, I38, 0}, +{"sgeu", "", "d,v,t", 0, (int) M_SGEU, INSN_MACRO, 0, I38, 0}, +{"sgeu", "", "d,v,I", 0, (int) M_SGEU_I, INSN_MACRO, 0, I38, 0}, +{"sgt", "", "d,v,t", 0, (int) M_SGT, INSN_MACRO, 0, I38, 0}, +{"sgt", "", "d,v,I", 0, (int) M_SGT_I, INSN_MACRO, 0, I38, 0}, +{"sgtu", "", "d,v,t", 0, (int) M_SGTU, INSN_MACRO, 0, I38, 0}, +{"sgtu", "", "d,v,I", 0, (int) M_SGTU_I, INSN_MACRO, 0, I38, 0}, +{"sh", "[16]", "mm,mH(ml)", 0x7c01, 0xfc09, RD_1|RD_3, 0, I38, 0}, /* SH[16] */ +{"sh", "[gp]", "t,+3(ma)", 0x44140000, 0xfc1c0001, RD_1|RD_3, 0, I38, 0}, /* SH[GP] */ +{"sh", "[u12]", "t,o(b)", 0x84005000, 0xfc00f000, RD_1|RD_3, 0, I38, 0}, /* SH[U12] */ +{"sh", "[s9]", "t,+j(b)", 0xa4002800, 0xfc007f00, RD_1|RD_3, 0, I38, 0}, /* SH[S9] */ +{"sh", "", "t,A(c)", 0, (int) M_SH_AC, INSN_MACRO, 0, I38, 0}, +{"sh", "", "t,A(b)", 0, (int) M_SHX_AB, INSN_MACRO, 0, 0, xNMS}, /* SHX */ +{"she", "", "t,+j(b)", 0xa4002a00, 0xfc007f00, RD_1|RD_3, 0, 0, EVA}, +{"she", "", "t,A(c)", 0, (int) M_SHE_AC, INSN_MACRO, 0, 0, EVA}, +{"shilo", "", "7,0,-P", 0x2000001d, 0xfc0003ff, MOD_1, 0, 0, D32}, +{"shilov", "", "7,s,-I", 0x2000127f, 0xfc003fff, MOD_1|RD_2, 0, 0, D32}, +{"shll.ph", "", "t,s,4", 0x200003b5, 0xfc000fff, WR_1|RD_2, 0, 0, D32}, +{"shll.qb", "", "t,s,3", 0x2000087f, 0xfc001fff, WR_1|RD_2, 0, 0, D32}, +{"shllv.ph", "", "d,t,s", 0x2000038d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"shllv.qb", "", "d,t,s,-B", 0x20000395, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"shllv_s.ph", "", "d,t,s", 0x2000078d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"shllv_s.w", "", "d,t,s,-B", 0x200003d5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"shll_s.ph", "", "t,s,4", 0x20000bb5, 0xfc000fff, WR_1|RD_2, 0, 0, D32}, +{"shll_s.w", "", "t,s,1,-B", 0x200003f5, 0xfc0003ff, WR_1|RD_2, 0, 0, D32}, +{"shra.ph", "", "t,s,4", 0x20000335, 0xfc000fff, WR_1|RD_2, 0, 0, D32}, +{"shra.qb", "", "t,s,3", 0x200001ff, 0xfc001fff, WR_1|RD_2, 0, 0, D32}, +{"shrav.ph", "", "d,t,s", 0x2000018d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"shrav.qb", "", "d,t,s", 0x200001cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"shrav_r.ph", "", "d,t,s", 0x2000058d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"shrav_r.qb", "", "d,t,s", 0x200005cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"shrav_r.w", "", "d,t,s,-B", 0x200002d5, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"shra_r.ph", "", "t,s,4,-Q", 0x20000735, 0xfc0007ff, WR_1|RD_2, 0, 0, D32}, +{"shra_r.qb", "", "t,s,3", 0x200011ff, 0xfc001fff, WR_1|RD_2, 0, 0, D32}, +{"shra_r.w", "", "t,s,1,-B", 0x200002f5, 0xfc0003ff, WR_1|RD_2, 0, 0, D32}, +{"shrl.ph", "", "t,s,4", 0x200003ff, 0xfc000fff, WR_1|RD_2, 0, 0, D32}, +{"shrl.qb", "", "t,s,3", 0x2000187f, 0xfc001fff, WR_1|RD_2, 0, 0, D32}, +{"shrlv.ph", "", "d,t,s,-B", 0x20000315, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"shrlv.qb", "", "d,t,s,-B", 0x20000355, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"shx", "", "d,s(t)", 0x20000287, 0xfc0007ff, RD_1|RD_2|RD_3, 0, 0, xNMS}, +{"shxs", "", "d,s(t)", 0x200002c7, 0xfc0007ff, RD_1|RD_2|RD_3, 0, 0, xNMS}, +{"sync_wmb", "", "", 0x8004c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */ +{"sync_mb", "", "", 0x8010c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */ +{"sync_acquire", "", "", 0x8011c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */ +{"sync_release", "", "", 0x8012c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */ +{"sync_rmb", "", "", 0x8013c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */ +{"sync_ginv", "", "", 0x8014c006, 0xffffffff, 0, INSN2_ALIAS, 0, GINV}, /* SYNC */ +{"sync", "", "", 0x8000c006, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, /* SYNC */ +{"sync", "", "+i,-M", 0x8000c006, 0xffe0f1ff, 0, 0, I38, 0}, +{"sle", "", "d,v,t", 0, (int) M_SLE, INSN_MACRO, 0, I38, 0}, +{"sle", "", "d,v,I", 0, (int) M_SLE_I, INSN_MACRO, 0, I38, 0}, +{"sleu", "", "d,v,t", 0, (int) M_SLEU, INSN_MACRO, 0, I38, 0}, +{"sleu", "", "d,v,I", 0, (int) M_SLEU_I, INSN_MACRO, 0, I38, 0}, +{"sllv", "", "d,s,t,-B", 0x20000010, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"sll", "[16]", "md,mc,mM", 0x3000, 0xfc08, WR_1|RD_2, 0, I38, 0}, /* SLL[16] */ +{"sll", "[32]", "t,r,<,-M", 0x8000c000, 0xfc00f1e0, WR_1|RD_2, 0, I38, 0}, /* preceded by EHB, PAUSE, SYNC */ +{"sll", "[32]", "d,v,t", 0x20000010, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* SLLV */ +{"slt", "", "d,v,t,-B", 0x20000350, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"slt", "", "d,v,I", 0, (int) M_SLT_I, INSN_MACRO, 0, I38, 0}, +{"slti", "", "t,r,i", 0x80004000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, +{"sltiu", "", "t,r,i", 0x80005000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, +{"sltu", "", "d,v,t,-B", 0x20000390, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, /* preceded by DVP */ +{"sltu", "", "d,v,I", 0, (int) M_SLTU_I, INSN_MACRO, 0, I38, 0}, +{"sne", "", "d,v,t", 0, (int) M_SNE, INSN_MACRO, 0, I38, 0}, +{"sne", "", "d,v,I", 0, (int) M_SNE_I, INSN_MACRO, 0, I38, 0}, +{"sov", "", "d,v,t,-B", 0x200003d0, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"srav", "", "d,s,t,-B", 0x20000090, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"sra", "", "t,r,<,-M", 0x8000c080, 0xfc00f1e0, WR_1|RD_2, 0, I38, 0}, +{"sra", "", "d,v,t", 0x20000090, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* SRAV */ +{"srlv", "", "d,s,t,-B", 0x20000050, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"srl", "[16]", "md,mc,mM", 0x3008, 0xfc08, WR_1|RD_2, 0, I38, 0}, /* SRL[16] */ +{"srl", "[32]", "t,r,<,-M", 0x8000c040, 0xfc00f1e0, WR_1|RD_2, 0, I38, 0}, +{"srl", "[32]", "d,v,t", 0x20000050, 0xfc0007ff, WR_1|RD_2|RD_3, INSN2_ALIAS, I38, 0}, /* SRLV */ +{"sub", "", "d,v,t,-B", 0x20000190, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, xNMS}, +{"sub", "", "t,r,I", 0, (int) M_SUB_I, INSN_MACRO, 0, 0, xNMS}, +{"subq.ph", "", "d,s,t", 0x2000020d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subqh.ph", "", "d,s,t", 0x2000024d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subqh.w", "", "d,s,t", 0x2000028d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subqh_r.ph", "", "d,s,t", 0x2000064d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subqh_r.w", "", "d,s,t", 0x2000068d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subq_s.ph", "", "d,s,t", 0x2000060d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subq_s.w", "", "d,s,t,-B", 0x20000345, 0xfc0003ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subu", "[16]", "me,mc,md", 0xb001, 0xfc01, WR_1|RD_2|RD_3, 0, I38, 0}, /* SUBU[16] */ +{"subu", "[32]", "d,v,t,-B", 0x200001d0, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"subu", "", "d,v,I", 0, (int) M_SUBU_I, INSN_MACRO, 0, I38, 0}, +{"subu.ph", "", "d,s,t", 0x2000030d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subu.qb", "", "d,s,t", 0x200002cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subuh.qb", "", "d,s,t", 0x2000034d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subuh_r.qb", "", "d,s,t", 0x2000074d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subu_s.ph", "", "d,s,t", 0x2000070d, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"subu_s.qb", "", "d,s,t", 0x200006cd, 0xfc0007ff, WR_1|RD_2|RD_3, 0, 0, D32}, +{"sw", "[16]", "mm,mJ(ml)", 0x9400, 0xfc00, RD_1|RD_3, 0, I38, 0}, /* SW[16] */ +{"sw", "[sp]", "mp,mR(ms)", 0xb400, 0xfc00, RD_1|RD_3, 0, I38, 0}, /* SW[SP] */ +{"sw", "[4x4]", "mw,mN(mv)", 0xf400, 0xfc00, RD_1|RD_3, 0, 0, xNMS}, /* SW[4X4] */ +{"sw", "[gp16]", "mm,mO(ma)", 0xd400, 0xfc00, RD_1|RD_3, 0, I38, 0}, /* SW[GP16] */ +{"sw", "[gp]", "t,.(ma)", 0x40000003, 0xfc000003, RD_1|RD_3, 0, I38, 0}, /* SW[GP] */ +{"sw", "[gp16]", "mm,mA(ma)", 0xd400, 0xfc00, RD_1|RD_3, 0, I38, 0}, /* SW[GP16] */ +{"sw", "[u12]", "t,o(b)", 0x84009000, 0xfc00f000, RD_1|RD_3, 0, I38, 0}, /* SW[U12] */ +{"sw", "[s9]", "t,+j(b)", 0xa4004800, 0xfc007f00, RD_1|RD_3, 0, I38, 0}, /* SW[S9] */ +{"sw", "", "t,A(c)", 0, (int) M_SW_AC, INSN_MACRO, 0, I38, 0}, +{"sw", "", "t,A(b)", 0, (int) M_SWX_AB, INSN_MACRO, 0, 0, xNMS}, /* SWX */ +{"swe", "", "t,+j(b)", 0xa4004a00, 0xfc007f00, RD_1|RD_3, 0, 0, EVA}, +{"swe", "", "t,A(c)", 0, (int) M_SWE_AC, INSN_MACRO, 0, 0, EVA}, +{"swm", "", "t,+j(b),|", 0xa4000c00, 0xfc000f00, RD_1|RD_3, 0, 0, xNMS}, /* SWM */ +{"swpc", "[48]", "mp,+S", 0x600f, 0xfc1f, WR_1, 0, 0, xNMS}, /* SWPC[48] */ +{"swx", "", "d,s(t)", 0x20000487, 0xfc0007ff, RD_1|RD_2|RD_3, 0, 0, xNMS}, +{"swxs", "", "d,s(t)", 0x200004c7, 0xfc0007ff, RD_1|RD_2|RD_3, 0, 0, xNMS}, +{"syscall", "[16]", "", 0x1008, 0xffff, 0, INSN2_ALIAS, I38, 0}, /* SYSCALL[16] */ +{"syscall", "[16]", "mP", 0x1008, 0xfffc, 0, 0, I38, 0}, /* SYSCALL[16] */ +{"syscall", "[32]", "", 0x00080000, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, +{"syscall", "[32]", "+M", 0x00080000, 0xfffc0000, 0, 0, I38, 0}, +{"teq", "", "s,t", 0x20000000, 0xfc00ffff, RD_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* TEQ */ +{"teq", "", "s,t,^", 0x20000000, 0xfc0007ff, RD_1|RD_2, 0, 0, xNMS}, /* TEQ */ +{"teq", "", "s,I", 0, (int) M_TEQ_I, INSN_MACRO, 0, 0, xNMS}, +{"tne", "", "s,t", 0x20000400, 0xfc00ffff, RD_1|RD_2, INSN2_ALIAS, 0, xNMS}, /* TNE */ +{"tne", "", "s,t,^", 0x20000400, 0xfc0007ff, RD_1|RD_2, 0, 0, xNMS}, /* TNE */ +{"tne", "", "s,I", 0, (int) M_TNE_I, INSN_MACRO, 0, 0, xNMS}, +{"tlbinv", "", "-F", 0x2000077f, 0xfc00ffff, 0, 0, 0, TLB}, +{"tlbinvf", "", "-F", 0x2000177f, 0xfc00ffff, 0, 0, 0, TLB}, +{"tlbp", "", "-F", 0x2000037f, 0xfc00ffff, 0, 0, 0, TLB}, +{"tlbr", "", "-F", 0x2000137f, 0xfc00ffff, 0, 0, 0, TLB}, +{"tlbwi", "", "-F", 0x2000237f, 0xfc00ffff, 0, 0, 0, TLB}, +{"tlbwr", "", "-F", 0x2000337f, 0xfc00ffff, 0, 0, 0, TLB}, +{"ualh", "", "t,+j(b)", 0xa4002100, 0xfc007f00, WR_1|RD_3, 0, 0, xNMS}, +{"ualw", "", "t,+j(b)", 0xa4001500, 0xfc007f00, WR_1|RD_3, INSN2_ALIAS, 0, xNMS}, /* UALWM */ +{"ualwm", "", "t,+j(b),|", 0xa4000500, 0xfc000f00, WR_1|RD_3, 0, 0, xNMS}, /* UALWM */ +{"uash", "", "t,+j(b)", 0xa4002900, 0xfc007f00, RD_1|RD_3, 0, 0, xNMS}, +{"uasw", "", "t,+j(b)", 0xa4001d00, 0xfc007f00, RD_1|RD_3, INSN2_ALIAS, 0, xNMS}, /* UASWM */ +{"uaswm", "", "t,+j(b),|", 0xa4000d00, 0xfc000f00, RD_1|RD_3, 0, 0, xNMS}, /* UASWM */ +{"uld", "", "t,A(c)", 0, (int) M_ULD_AC, INSN_MACRO, 0, 0, xNMS}, +{"ulh", "", "t,A(c)", 0, (int) M_ULH_AC, INSN_MACRO, 0, 0, xNMS}, +{"ulw", "", "t,A(c)", 0, (int) M_ULW_AC, INSN_MACRO, 0, 0, xNMS}, +{"usd", "", "t,A(c)", 0, (int) M_USD_AC, INSN_MACRO, 0, 0, xNMS}, +{"ush", "", "t,A(c)", 0, (int) M_USH_AC, INSN_MACRO, 0, 0, xNMS}, +{"usw", "", "t,A(c)", 0, (int) M_USW_AC, INSN_MACRO, 0, 0, xNMS}, +{"wait", "", "", 0x2000c37f, 0xffffffff, 0, INSN2_ALIAS, I38, 0}, +{"wait", "", "+L", 0x2000c37f, 0xfc00ffff, 0, 0, I38, 0}, +{"wrdsp", "", "t", 0x201fd67f, 0xfc1fffff, RD_1, INSN2_ALIAS, 0, D32}, +{"wrdsp", "", "t,8", 0x2000167f, 0xfc003fff, RD_1, 0, 0, D32}, +{"wrpgpr", "", "t,r", 0x2000f17f, 0xfc00ffff, WR_1|RD_2, 0, I38, 0}, +{"xor", "[16]", "md,mk,ml", 0x5004, 0xfc0f, WR_1|RD_3, INSN2_ALIAS, I38, 0}, /* XOR[16] */ +{"xor", "[16]", "md,ml,mk", 0x5004, 0xfc0f, WR_1|RD_2, INSN2_ALIAS, I38, 0}, /* XOR[16] */ +{"xor", "[16]", "md,ml", 0x5004, 0xfc0f, WR_1|RD_2, 0, I38, 0}, /* XOR[16] */ +{"xor", "[32]", "d,v,t,-B", 0x20000310, 0xfc0003ff, WR_1|RD_2|RD_3, 0, I38, 0}, +{"xor", "", "t,r,I", 0, (int) M_XOR_I, INSN_MACRO, 0, I38, 0}, +{"xori", "", "t,r,g", 0x80001000, 0xfc00f000, WR_1|RD_2, 0, I38, 0}, +{"yield", "", "s", 0x20000268, 0xffe0ffff, RD_1, INSN2_ALIAS, 0, MT32}, +{"yield", "", "t,s,-N", 0x20000268, 0xfc0003ff, WR_1|RD_2, 0, 0, MT32}, +}; + +const int bfd_nanomips_num_opcodes = + ((sizeof nanomips_opcodes) / (sizeof (nanomips_opcodes[0])));