From patchwork Fri May 5 09:23:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Aleksandar Rikalo X-Patchwork-Id: 90380 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp262470vqo; Fri, 5 May 2023 02:23:54 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7qkTBQbdCgu4aeH1Pc8Mgf+bp661PQ92VvNxWw4Y3lnYSGVjF8B/0k9A/9Yo7Il/KqOVau X-Received: by 2002:a17:907:9805:b0:965:a08e:3674 with SMTP id ji5-20020a170907980500b00965a08e3674mr626863ejc.14.1683278634254; Fri, 05 May 2023 02:23:54 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1683278634; cv=pass; d=google.com; s=arc-20160816; b=uPH1qskbzFtTVnMOq0Dx8gSe3zDTo3oK/7J7enxMBBESQSQRR+nQPpO20G4izlYc3Y m+sq58taDOebN31rfHoCkEQuIsKUuT/o6mJHXRcw9bcbQeOT293ddK1f8BQoKnSeaGFA bQC0pcBTXnmx6FYiXz2RYtNS66YvmR4UPcUHYktKh1yryMyeRTprXlMF2GXwKgBCfwOg 7T+u8h+M2hZUlVVx1AfxhnGp+9glNepUgG7IPn/oPoFQwEAhL7/xg9XRNkGV/JOgfucN GAVVKdEgIXuEzOgONwxMKm647KnNxGzpjz2q3GKQ2uReaQ+SV6uUvwkUE2LSbIEapM/i Du/g== 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:message-id:date:subject:cc:to:from :dkim-signature:dmarc-filter:delivered-to; bh=yxITzuV3jnyXc+zwRa2W1rZihA1f2duJQ/EwGvehYyo=; b=nX+aDQVvLkcuD2+A6bknZ2pZ9pDF/tnrRxXd7LjGJGGcrSqcQxhIjvcvIAFLX5paL2 9D3ANuWrbzDQlitrzYOXyUXaRobGj7hNm5NfxjAQrusb/ea00QJp6W+b75q6IYviimhU DqYqlqWYrNHfBVJi0/qVPa93mGy9waAbQ7uA0xXMerpXXOF5l/VOk8VPJCNoU42P2hzF iG367TuL/OTgJsxbUd1LqDJAPI/ymCHAb4aYeU0aY1+zF6wtmT2CEaD+UPPDd0fpyjr+ 8CuWLVQn6J624Wv5VJ2B9neMbZIgvUwCJnvJciSd6YDDWELzaQSlcKQlHY5UW+533AuC gKYw== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@syrmia.com header.s=selector1 header.b=y6yZbVVF; 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 (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id bw18-20020a170906c1d200b0094f67fc03d4si1078135ejb.991.2023.05.05.02.23.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 May 2023 02:23:54 -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=y6yZbVVF; 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 ABE853857735 for ; Fri, 5 May 2023 09:23:52 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on2129.outbound.protection.outlook.com [40.107.22.129]) by sourceware.org (Postfix) with ESMTPS id B56743858D20 for ; Fri, 5 May 2023 09:23:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B56743858D20 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=auatrK6U5bp4c78CmACdgy8nXARQp759c41LHb3OcesEeN5O9FD8wJqTh2XJ6E+ygIDevpqRTYdfw0ElrrYF0UCsOEhosUJu0+8UzMZC4BNlA0OzgQNiOibFUZU6GTEytgY9BQxzorjZMt10zRy8lj+0HqZrzUNvPlvil9/g+Cn/+g916XZp7UnizJKApYjKPKR0QZbQxMZ8p2M/ckk3cn6NZpsxQQlXGosh0HkgJlbmX0bLnh+/4PwLuj9dpXHzhxktbsnOIjKD02bmwTkTNHUPHCjPAv5h+j/zf7/DLYG6tID82MC2Ch4lBcujCm4T77UvW2vFJv2WMY6VSyST6A== 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=yxITzuV3jnyXc+zwRa2W1rZihA1f2duJQ/EwGvehYyo=; b=k8eNGPfBqNUC8Jg2FqzJDcsgUFvlXXgokKEM7nfO3n7WG5K1sCuRS7AJwtJanvAlXMzHf5DFk62XDHqxCyoJhrcyOEJIY8+GKoVRD5QMT/2uMxxWy6/dNOoHGHT5qYM1YjeugYCd9jiMeoDioJXjjjiCl61de+vcBV9I8Fe09N62RAaP3cp2QhSbz1vE3w0ziLGyB2iarDC0kaQbz3N/uJG2/W1TJfZ0LUdY/NOwmAkeUGQu5XAcMI/kayywdpnO2EMPLQxbxydF74KPwPCOqmJO9zH4Ot25WMqhFovbaUi1bKbKYVYVTsi/RtJbYuwBN4VHmJW9FZC30guLe8oEyg== 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=yxITzuV3jnyXc+zwRa2W1rZihA1f2duJQ/EwGvehYyo=; b=y6yZbVVF533Q6rEwEnqnPVvY54x8Pt9I9xL74n08VbP9McVzNu+H8o303IfP0rOUkx2Rkjw+jKBdTUG3ZSMnTw+nNAjNqFQydkACra3/KL5wVEUWYCGTNR/qbxqo5llvme70KzK8z49p6xjlOl629dca2JD8O6nQ8B+vz89Zrws= 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 DU0PR03MB9151.eurprd03.prod.outlook.com (2603:10a6:10:467::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6363.22; Fri, 5 May 2023 09:23:23 +0000 Received: from VI1PR0302MB3486.eurprd03.prod.outlook.com ([fe80::c6c9:5454:b566:b509]) by VI1PR0302MB3486.eurprd03.prod.outlook.com ([fe80::c6c9:5454:b566:b509%7]) with mapi id 15.20.6363.022; Fri, 5 May 2023 09:23:23 +0000 From: Aleksandar Rikalo To: binutils@sourceware.org Cc: nickc@redhat.com, macro@orcam.me.uk, dragan.mladjenovic@syrmia.com Subject: [PATCH v5] Add support for nanoMIPS architecture Date: Fri, 5 May 2023 11:23:16 +0200 Message-Id: <20230505092316.1046472-1-aleksandar.rikalo@syrmia.com> X-Mailer: git-send-email 2.25.1 X-ClientProxiedBy: VI1PR07CA0218.eurprd07.prod.outlook.com (2603:10a6:802:58::21) To VI1PR0302MB3486.eurprd03.prod.outlook.com (2603:10a6:803:1e::32) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VI1PR0302MB3486:EE_|DU0PR03MB9151:EE_ X-MS-Office365-Filtering-Correlation-Id: cef8ec14-347c-46a6-f640-08db4d4a5fa1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: DshvDBFQa9NfPt96o9iuPIyQyc8IeDe4DTpfGewyMmjNU+6LlEkcAK8bPPTaOwHx/ODsWcRT1bhosBd74t+j4mFkmLefcz78QZETlW1IqGRhYngtdgH454QB0DimHzUBwGDJ8aP9ZxZLdEGgBPkPVRl8Hzz69zV+BlWYJlkgpvfaGh2Zi3gkIV0k2hRJwJ0VA9KpC1Ghe8PEp4YTGRHtrvlzT9m/pWUegMGjblzrUmsR/6jalP4/V9E+Yh9Ia09xwBNbqJnchLh4QTZ7PUlyWPZgH6+bOYvHJsIPAKyygxAbpx8dIQsRxrRUHM/7GleE8/4WVLMgYDDo/IeE3dxZLZVFlcmrjzAmjleG9xVAWHSbkqLDAxTN7UVDn4ldY3FyITRnC3SURT8pJg8ELInrINO2w7TijtQrCnG2MxKR667z9ni2MmxH2fGTyYaQtSm9Ut7x9lsrJupx7ovfhGVZB86xcq3T5lJHx/jampPkmGWcWInOby526Vzvk24gMn4QCTpe+QJ8drQPaz0nUYWRp2E3EtdD22Srj+1YdPLJXdhxRjHeCLcrS+WvF8GK3uDXRTqY2Z/FX7vxW+T+JIZAicSMPjlfFEowuJyXG88ViaAibbZH0QVRYrv0RYK7dyLEff6iTYRNb5MM15b223uYVA== 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)(136003)(366004)(376002)(346002)(396003)(39840400004)(451199021)(2906002)(30864003)(44832011)(6486002)(8936002)(8676002)(478600001)(5660300002)(66476007)(66946007)(107886003)(66556008)(52116002)(19627235002)(4326008)(6666004)(86362001)(41300700001)(36756003)(316002)(6916009)(38350700002)(26005)(186003)(38100700002)(83380400001)(2616005)(1076003)(6506007)(6512007)(21314003)(2004002)(559001)(579004); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?q?0lG33AAToJrzzHVBs/mjiXsPIeLV?= =?utf-8?q?T6kPy1X/Vxqyt5xWCrsM4AQiKoQjJOh8zI1NBm6XNAkHQ2Qz8JPBgHK8w2AM/FSok?= =?utf-8?q?O1M4E6G30ss7225HPg4t3Ta5J0t0i3uEU4U1WA6nbzS+VKN8cMdGwNGEwwnd+vYAJ?= =?utf-8?q?+CsqVzsolISsLMsluO+1XjTUaDP9rGSGVdDVz2XT4lJHOlZNHlb8Hjmhpgcbpye+N?= =?utf-8?q?zUKvlcaOAMcsAS9Dk1gCCmzAhHNeynvLPmac2/Jcex1qzqaOZ8OsjnO70EHanltfY?= =?utf-8?q?1dJFiA2XlUbMVnAMi1qofXVzRfF6X6P2WfPD6tIz+7+1gG6oXnYLPPQPYtOI2c78a?= =?utf-8?q?0CKjlJSaanyhGa080q1E4Hjv/eSNLZjtvQ4+CkaAvqhXHdn1t9JY9CHR4U5CATfQ/?= =?utf-8?q?bUvJoRoc/+kWYHvBGUAyvQfJEmXAb11CBH4NiVtjuHG5Jg2J/DHxz9h6yo+VNxjWR?= =?utf-8?q?6i54naY7j6wbzrNidO00GopJNKIvHuocyQ54JNsScTiz9ewzZhCw8LzHw+DTDKAo2?= =?utf-8?q?5CkdhyPUk1KbOP8++6jKbIkBaMR/fOOTv38XbpO6y5faI2nyYEHizp8Iudbqq332K?= =?utf-8?q?Np2jJXeyoZpz+lib2RkKOt3cdEdVIH6jUZtpioCjCIq6PcXchZctuAaY8h13TtOH5?= =?utf-8?q?GYaDJc1f2nf7rzqRB7i3ZroKIyFAj1ygsaZp58Oe9+zAIZrVy7kbZUdS6JQx1XJo8?= =?utf-8?q?MWx40kJcJlSYjiR/2wp99n3gOUBkMqWWUcH5uYyLqJHkjeoJFywRvOwhjv6HZboQN?= =?utf-8?q?shDkV/wPkESyiaNaF526zkxJH87Eod68FyAbUK/M6fmayxaG8/5/NvR/RtiXXLQ2K?= =?utf-8?q?4HTflXyhWn0n52S2YGBPBCwFHwMRmffk3uy2Yds2yX3BRKupBHZzNuo8+0R2v0spw?= =?utf-8?q?in4Q8/E7RRBTJnVstOIlCTp+6NMi9kWr6rkFm9whhBbGdxsFVBJqtIK0UAOA2XSmh?= =?utf-8?q?B3JDZMmVhSJv4wkAkQS/Zr0SkN2fCHr60ako4O9bfF/aBpGtML0Tu8BNBBDlZ9W9Y?= =?utf-8?q?V9VwMu++lsic+4JODCxPZa+GGIjSoPuaox+oHBeVVml6h+0iUJeHPpaimGeAajSY1?= =?utf-8?q?HHqJsWRsevXjoRvYXlTCCHbHroplyGXXjNo0CF7ycUwt+GrL50SaqlqZO8uW5rkxp?= =?utf-8?q?+D7BUjZZ/IWNKIKlrPb3UBlYlFhb7uMhwtayUz0CPrrO3GQ30KDrrk8cLwMjBRYt3?= =?utf-8?q?3nnzDZrxff79WjyhD1hL67E6GX2fR7/gacF5soM1e5BDhdyDRzHe2ookxl9b4crTx?= =?utf-8?q?stXeP9WSIB4QkbGE63x6HEkOUTsOA4/tTAWXnZ54FMM+3erjSavqeOIqq5pJQQo9b?= =?utf-8?q?4TC98OCCIsZx8DyWoEap9LG5/p/18WXtL31t4sbwQUH1tRvf8L4ENc2Hfzr26wnM7?= =?utf-8?q?6VW5rgXeDLe0kRqoyxVdPqfZOCmzZf07MZdUaaEBecBrgRrCU+mhjvO61xSXSRUpT?= =?utf-8?q?sXM2UmhbnEuw86rY8nGupPRc4MK2H0NH0J/qcBilSoc6pYsyNpr4bec8toOVlzRtE?= =?utf-8?q?+2uhR/sJQjCgzQF37QFAZ86yN9w3r4TA4A=3D=3D?= X-OriginatorOrg: syrmia.com X-MS-Exchange-CrossTenant-Network-Message-Id: cef8ec14-347c-46a6-f640-08db4d4a5fa1 X-MS-Exchange-CrossTenant-AuthSource: VI1PR0302MB3486.eurprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 May 2023 09:23:23.4680 (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: FrIj2lPeL82dalsg2xCaSx9SJIDg6yO5nRa3j+zxOSMR/eMth/t+WaGXjOdzikgIuhJ8xFkLDP/jkPT/3PsvqioYnBlpbbdO//EwOSppgZk= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DU0PR03MB9151 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?1765045577138811737?= X-GMAIL-MSGID: =?utf-8?q?1765045577138811737?= 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 --- bfd/Makefile.am | 19 + bfd/Makefile.in | 22 + bfd/archures.c | 5 + bfd/bfd-in2.h | 74 ++ bfd/config.bfd | 6 + bfd/configure | 4 + bfd/configure.ac | 4 + bfd/cpu-nanomips.c | 61 ++ bfd/elf-bfd.h | 1 + bfd/elfnn-nanomips.c | 1423 ++++++++++++++++++++++++++++++++++ bfd/elfxx-mips.h | 5 + bfd/elfxx-nanomips.c | 794 +++++++++++++++++++ bfd/elfxx-nanomips.h | 54 ++ bfd/libbfd.h | 69 ++ bfd/reloc.c | 140 ++++ bfd/targets.c | 11 + binutils/readelf.c | 502 +++++++++++- include/dis-asm.h | 11 + include/elf/common.h | 2 +- include/elf/mips-common.h | 41 + include/elf/nanomips.h | 260 +++++++ 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 | 1470 ++++++++++++++++++++++++++++++++++++ opcodes/nanomips-formats.h | 265 +++++++ opcodes/nanomips-opc.c | 1073 ++++++++++++++++++++++++++ 32 files changed, 7804 insertions(+), 2 deletions(-) create mode 100644 bfd/cpu-nanomips.c create mode 100644 bfd/elfnn-nanomips.c create mode 100644 bfd/elfxx-nanomips.c create mode 100644 bfd/elfxx-nanomips.h create mode 100644 include/elf/mips-common.h create mode 100644 include/elf/nanomips.h 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/bfd/Makefile.am b/bfd/Makefile.am index 5c5fdefd3b8..8f452f856f7 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -142,6 +142,7 @@ ALL_MACHINES = \ cpu-moxie.lo \ cpu-msp430.lo \ cpu-mt.lo \ + cpu-nanomips.lo \ cpu-nds32.lo \ cpu-nfp.lo \ cpu-nios2.lo \ @@ -547,6 +548,7 @@ BFD64_BACKENDS = \ coff64-rs6000.lo \ elf32-ia64.lo \ elf32-mips.lo \ + elf32-nanomips.lo \ elf32-score.lo \ elf32-score7.lo \ elf64-alpha.lo \ @@ -564,6 +566,8 @@ BFD64_BACKENDS = \ elfxx-mips.lo \ elf64-mmix.lo \ elf64-nfp.lo \ + elf64-nanomips.lo \ + elfxx-nanomips.lo \ elf64-ppc.lo \ elf32-riscv.lo \ elf64-riscv.lo \ @@ -607,6 +611,7 @@ BFD64_BACKENDS_CFILES = \ elf64-mips.c \ elf64-mmix.c \ elf64-nfp.c \ + elf64-nanomips.c \ elf64-ppc.c \ elf64-s390.c \ elf64-sparc.c \ @@ -620,6 +625,7 @@ BFD64_BACKENDS_CFILES = \ elfxx-ia64.c \ elfxx-loongarch.c \ elfxx-mips.c \ + elfxx-nanomips.c \ elfxx-riscv.c \ mach-o-aarch64.c \ mach-o-x86-64.c \ @@ -684,6 +690,7 @@ BUILD_CFILES = \ elf32-ia64.c elf64-ia64.c \ elf32-loongarch.c elf64-loongarch.c \ elf32-riscv.c elf64-riscv.c \ + elf32-nanomips.c elf64-nanomips.c \ peigen.c pepigen.c pex64igen.c pe-aarch64igen.c pe-loongarch64igen.c CFILES = $(SOURCE_CFILES) $(BUILD_CFILES) @@ -886,6 +893,18 @@ pe-loongarch64igen.c: peXXigen.c $(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@ $(AM_V_GEN)$(SED) -e s/XX/peLoongArch64/g < $< >> $@ +elf32-nanomips.c : elfnn-nanomips.c + rm -f elf32-nanomips.c + echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf32-nanomips.new + sed -e s/NN/32/g < $(srcdir)/elfnn-nanomips.c >> elf32-nanomips.new + mv -f elf32-nanomips.new elf32-nanomips.c + +elf64-nanomips.c : elfnn-nanomips.c + rm -f elf64-nanomips.c + echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf64-nanomips.new + sed -e s/NN/64/g < $(srcdir)/elfnn-nanomips.c >> elf64-nanomips.new + mv -f elf64-nanomips.new elf64-nanomips.c + host-aout.lo: Makefile # The following program can be used to generate a simple config file diff --git a/bfd/Makefile.in b/bfd/Makefile.in index 4edfedee924..64ff01733fd 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -597,6 +597,7 @@ ALL_MACHINES = \ cpu-moxie.lo \ cpu-msp430.lo \ cpu-mt.lo \ + cpu-nanomips.lo \ cpu-nds32.lo \ cpu-nfp.lo \ cpu-nios2.lo \ @@ -1004,6 +1005,7 @@ BFD64_BACKENDS = \ coff64-rs6000.lo \ elf32-ia64.lo \ elf32-mips.lo \ + elf32-nanomips.lo \ elf32-score.lo \ elf32-score7.lo \ elf64-alpha.lo \ @@ -1021,6 +1023,8 @@ BFD64_BACKENDS = \ elfxx-mips.lo \ elf64-mmix.lo \ elf64-nfp.lo \ + elf64-nanomips.lo \ + elfxx-nanomips.lo \ elf64-ppc.lo \ elf32-riscv.lo \ elf64-riscv.lo \ @@ -1064,6 +1068,7 @@ BFD64_BACKENDS_CFILES = \ elf64-mips.c \ elf64-mmix.c \ elf64-nfp.c \ + elf64-nanomips.c \ elf64-ppc.c \ elf64-s390.c \ elf64-sparc.c \ @@ -1077,6 +1082,7 @@ BFD64_BACKENDS_CFILES = \ elfxx-ia64.c \ elfxx-loongarch.c \ elfxx-mips.c \ + elfxx-nanomips.c \ elfxx-riscv.c \ mach-o-aarch64.c \ mach-o-x86-64.c \ @@ -1140,6 +1146,7 @@ BUILD_CFILES = \ elf32-ia64.c elf64-ia64.c \ elf32-loongarch.c elf64-loongarch.c \ elf32-riscv.c elf64-riscv.c \ + elf32-nanomips.c elf64-nanomips.c \ peigen.c pepigen.c pex64igen.c pe-aarch64igen.c pe-loongarch64igen.c CFILES = $(SOURCE_CFILES) $(BUILD_CFILES) @@ -1593,6 +1600,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-moxie.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-msp430.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-mt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-nanomips.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-nds32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-nios2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-or1k.Plo@am__quote@ @@ -1633,6 +1641,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mips.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mmix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-nfp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-nanomips.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ppc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-riscv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-s390.Plo@am__quote@ @@ -1646,6 +1655,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-ia64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-loongarch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-mips.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-nanomips.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-riscv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-sparc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-tilegx.Plo@am__quote@ @@ -2384,6 +2394,18 @@ pe-loongarch64igen.c: peXXigen.c $(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@ $(AM_V_GEN)$(SED) -e s/XX/peLoongArch64/g < $< >> $@ +elf32-nanomips.c : elfnn-nanomips.c + rm -f elf32-nanomips.c + echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf32-nanomips.new + sed -e s/NN/32/g < $(srcdir)/elfnn-nanomips.c >> elf32-nanomips.new + mv -f elf32-nanomips.new elf32-nanomips.c + +elf64-nanomips.c : elfnn-nanomips.c + rm -f elf64-nanomips.c + echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf64-nanomips.new + sed -e s/NN/64/g < $(srcdir)/elfnn-nanomips.c >> elf64-nanomips.new + mv -f elf64-nanomips.new elf64-nanomips.c + host-aout.lo: Makefile # The following program can be used to generate a simple config file diff --git a/bfd/archures.c b/bfd/archures.c index 6fe8701b412..5e5fd28e71d 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -563,6 +563,9 @@ DESCRIPTION .#define bfd_mach_amdgcn_gfx1030 0x036 .#define bfd_mach_amdgcn_gfx1031 0x037 .#define bfd_mach_amdgcn_gfx1032 0x038 +. bfd_arch_nanomips, {* nanoMIPS. *} +.#define bfd_mach_nanomipsisa32r6 32 +.#define bfd_mach_nanomipsisa64r6 64 . bfd_arch_last . }; */ @@ -663,6 +666,7 @@ extern const bfd_arch_info_type bfd_moxie_arch; extern const bfd_arch_info_type bfd_ft32_arch; extern const bfd_arch_info_type bfd_msp430_arch; extern const bfd_arch_info_type bfd_mt_arch; +extern const bfd_arch_info_type bfd_nanomips_arch; extern const bfd_arch_info_type bfd_nds32_arch; extern const bfd_arch_info_type bfd_nfp_arch; extern const bfd_arch_info_type bfd_nios2_arch; @@ -751,6 +755,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] = &bfd_ft32_arch, &bfd_msp430_arch, &bfd_mt_arch, + &bfd_nanomips_arch, &bfd_nds32_arch, &bfd_nfp_arch, &bfd_nios2_arch, diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 7be18db20a8..98fd0bf2d8f 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1816,6 +1816,9 @@ enum bfd_architecture #define bfd_mach_amdgcn_gfx1030 0x036 #define bfd_mach_amdgcn_gfx1031 0x037 #define bfd_mach_amdgcn_gfx1032 0x038 + bfd_arch_nanomips, /* nanoMIPS. */ +#define bfd_mach_nanomipsisa32r6 32 +#define bfd_mach_nanomipsisa64r6 64 bfd_arch_last }; @@ -3663,6 +3666,77 @@ to compensate for the borrow when the low bits are added. */ BFD_RELOC_MIPS_JUMP_SLOT, +/* nanoMIPS relocations */ + BFD_RELOC_NANOMIPS_HI20, + BFD_RELOC_NANOMIPS_LO12, + BFD_RELOC_NANOMIPS_LO4_S2, + BFD_RELOC_NANOMIPS_IMM16, + BFD_RELOC_NANOMIPS_NEG12, + BFD_RELOC_NANOMIPS_GPREL7_S2, + BFD_RELOC_NANOMIPS_GPREL18, + BFD_RELOC_NANOMIPS_GPREL19_S2, + BFD_RELOC_NANOMIPS_GPREL16_S2, + BFD_RELOC_NANOMIPS_GPREL18_S3, + BFD_RELOC_NANOMIPS_4_PCREL_S1, + BFD_RELOC_NANOMIPS_7_PCREL_S1, + BFD_RELOC_NANOMIPS_10_PCREL_S1, + BFD_RELOC_NANOMIPS_11_PCREL_S1, + BFD_RELOC_NANOMIPS_14_PCREL_S1, + BFD_RELOC_NANOMIPS_21_PCREL_S1, + BFD_RELOC_NANOMIPS_25_PCREL_S1, + BFD_RELOC_NANOMIPS_PCREL_HI20, + BFD_RELOC_NANOMIPS_GOT_CALL, + BFD_RELOC_NANOMIPS_GOTPC_HI20, + BFD_RELOC_NANOMIPS_GOTPC_I32, + BFD_RELOC_NANOMIPS_GOT_LO12, + BFD_RELOC_NANOMIPS_GOT_DISP, + BFD_RELOC_NANOMIPS_GOT_PAGE, + BFD_RELOC_NANOMIPS_GOT_OFST, + BFD_RELOC_NANOMIPS_I32, + BFD_RELOC_NANOMIPS_GPREL_HI20, + BFD_RELOC_NANOMIPS_GPREL_LO12, + BFD_RELOC_NANOMIPS_TLS_GD, + BFD_RELOC_NANOMIPS_TLS_GD_I32, + BFD_RELOC_NANOMIPS_TLS_LD, + BFD_RELOC_NANOMIPS_TLS_LD_I32, + BFD_RELOC_NANOMIPS_TLS_DTPREL12, + BFD_RELOC_NANOMIPS_TLS_DTPREL16, + BFD_RELOC_NANOMIPS_TLS_DTPREL_I32, + BFD_RELOC_NANOMIPS_TLS_GOTTPREL, + BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32, + BFD_RELOC_NANOMIPS_TLS_TPREL12, + BFD_RELOC_NANOMIPS_TLS_TPREL16, + BFD_RELOC_NANOMIPS_TLS_TPREL_I32, + BFD_RELOC_NANOMIPS_TLS_DTPMOD, + BFD_RELOC_NANOMIPS_TLS_DTPREL, + BFD_RELOC_NANOMIPS_TLS_TPREL, + BFD_RELOC_NANOMIPS_PC_I32, + BFD_RELOC_NANOMIPS_GPREL_I32, + BFD_RELOC_NANOMIPS_GPREL17_S1, + BFD_RELOC_NANOMIPS_NEG, + BFD_RELOC_NANOMIPS_ASHIFTR_1, + BFD_RELOC_NANOMIPS_UNSIGNED_8, + BFD_RELOC_NANOMIPS_UNSIGNED_16, + BFD_RELOC_NANOMIPS_SIGNED_8, + BFD_RELOC_NANOMIPS_SIGNED_16, + BFD_RELOC_NANOMIPS_EH, + BFD_RELOC_NANOMIPS_JUMP_SLOT, + BFD_RELOC_NANOMIPS_ALIGN, + BFD_RELOC_NANOMIPS_FILL, + BFD_RELOC_NANOMIPS_MAX, + BFD_RELOC_NANOMIPS_INSN32, + BFD_RELOC_NANOMIPS_INSN16, + BFD_RELOC_NANOMIPS_FIXED, + BFD_RELOC_NANOMIPS_RELAX, + BFD_RELOC_NANOMIPS_NORELAX, + BFD_RELOC_NANOMIPS_SAVERESTORE, + BFD_RELOC_NANOMIPS_JALR16, + BFD_RELOC_NANOMIPS_JALR32, + BFD_RELOC_NANOMIPS_COPY, + BFD_RELOC_NANOMIPS_SIGNED_9, + BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD, + + /* Moxie ELF relocations. */ BFD_RELOC_MOXIE_10_PCREL, diff --git a/bfd/config.bfd b/bfd/config.bfd index 954837033c8..6f9324f89a8 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -202,6 +202,7 @@ m6812*|m68hc12*) targ_archs="bfd_m68hc12_arch bfd_m68hc11_arch bfd_m9s12x_arch b m68*) targ_archs=bfd_m68k_arch ;; microblaze*) targ_archs=bfd_microblaze_arch ;; mips*) targ_archs=bfd_mips_arch ;; +nanomips*) targ_archs=bfd_nanomips_arch ;; nds32*) targ_archs=bfd_nds32_arch ;; nios2*) targ_archs=bfd_nios2_arch ;; or1k*|or1knd*) targ_archs=bfd_or1k_arch ;; @@ -1020,6 +1021,11 @@ case "${targ}" in targ_selvecs=msp430_elf32_ti_vec ;; + nanomips*-*-elf*) + targ_defvec=nanomips_elf32_le_vec + targ_selvecs="nanomips_elf32_be_vec nanomips_elf64_be_vec nanomips_elf64_le_vec" + ;; + nds32*le-*-linux*) targ_defvec=nds32_elf32_linux_le_vec targ_selvecs=nds32_elf32_linux_be_vec diff --git a/bfd/configure b/bfd/configure index 41d280ef461..81cb3cfec49 100755 --- a/bfd/configure +++ b/bfd/configure @@ -13988,6 +13988,10 @@ do msp430_elf32_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;; msp430_elf32_ti_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;; mt_elf32_vec) tb="$tb elf32-mt.lo elf32.lo $elf" ;; + nanomips_elf32_be_vec) tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;; + nanomips_elf32_le_vec) tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;; + nanomips_elf64_be_vec) tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + nanomips_elf64_le_vec) tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; nds32_elf32_be_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;; nds32_elf32_le_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;; nds32_elf32_linux_be_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;; diff --git a/bfd/configure.ac b/bfd/configure.ac index f044616f4d9..b2c54704d48 100644 --- a/bfd/configure.ac +++ b/bfd/configure.ac @@ -555,6 +555,10 @@ do msp430_elf32_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;; msp430_elf32_ti_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;; mt_elf32_vec) tb="$tb elf32-mt.lo elf32.lo $elf" ;; + nanomips_elf32_be_vec) tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;; + nanomips_elf32_le_vec) tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;; + nanomips_elf64_be_vec) tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; + nanomips_elf64_le_vec) tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; nds32_elf32_be_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;; nds32_elf32_le_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;; nds32_elf32_linux_be_vec) tb="$tb elf32-nds32.lo elf32.lo $elf" ;; diff --git a/bfd/cpu-nanomips.c b/bfd/cpu-nanomips.c new file mode 100644 index 00000000000..2cd66786cfe --- /dev/null +++ b/bfd/cpu-nanomips.c @@ -0,0 +1,61 @@ +/* bfd back-end for nanomips support + Copyright (C) 2018-2022 Free Software Foundation, Inc. + + Written by Faraz Shahbazker + + This file is part of BFD, the Binary File Descriptor library. + + This program 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 of the License, or + (at your option) any later version. + + This program 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 "bfd.h" +#include "libbfd.h" + +#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \ + { \ + BITS_WORD, /* bits in a word */ \ + BITS_ADDR, /* bits in an address */ \ + 8, /* 8 bits in a byte */ \ + bfd_arch_nanomips, \ + NUMBER, \ + "nanomips", \ + PRINT, \ + 3, \ + DEFAULT, \ + bfd_default_compatible, \ + bfd_default_scan, \ + bfd_arch_default_fill, \ + NEXT, \ + 0 /* Maximum offset of a reloc from the start of an insn. */ \ + } + +enum +{ + I_nanomipsisa32r6, + I_nanomipsisa64r6, +}; + +#define NN(index) (&arch_info_struct[(index) + 1]) + +static const bfd_arch_info_type arch_info_struct[] = { + N (32, 32, bfd_mach_nanomipsisa32r6, "nanomips:isa32r6", false, + NN (I_nanomipsisa32r6)), + N (64, 64, bfd_mach_nanomipsisa64r6, "nanomips:isa64r6", false, + 0), +}; + +const bfd_arch_info_type bfd_nanomips_arch = +N (32, 32, 0, "nanomips", true, &arch_info_struct[0]); diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 2a64a1e6a03..cbdc0d61758 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -554,6 +554,7 @@ enum elf_target_id MICROBLAZE_ELF_DATA, MIPS_ELF_DATA, MN10300_ELF_DATA, + NANOMIPS_ELF_DATA, NDS32_ELF_DATA, NIOS2_ELF_DATA, OR1K_ELF_DATA, diff --git a/bfd/elfnn-nanomips.c b/bfd/elfnn-nanomips.c new file mode 100644 index 00000000000..e134a51c5ee --- /dev/null +++ b/bfd/elfnn-nanomips.c @@ -0,0 +1,1423 @@ +/* nanoMIPS-specific support for 32-bit ELF + Copyright (C) 2018-2022 Free Software Foundation, Inc. + + Written by Faraz Shahbazker + + This file is part of BFD, the Binary File Descriptor library. + + This program 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 of the License, or + (at your option) any later version. + + This program 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. */ + + +/* This file handles nanoMIPS ELF targets. */ + +#include "sysdep.h" +#include "bfd.h" +#include "libbfd.h" +#include "elf-bfd.h" +#include "elfxx-nanomips.h" +#include "elf/nanomips.h" + +#define ARCH_SIZE NN + +#if ARCH_SIZE == 32 +/* Nonzero if ABFD is using the P32 ABI. */ +#define ABI_P32_P(abfd) \ + ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) != E_NANOMIPS_ABI_P64) +#else /* ARCH_SIZE != 32 */ +/* Nonzero if ABFD is using the P64 ABI. */ +#define ABI_P64_P(abfd) \ + ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) != E_NANOMIPS_ABI_P32) +#endif /* ARCH_SIZE == 32 */ + +/* In case we're on a 32-bit machine, construct a 64-bit "-1" value + from smaller values. Start with zero, widen, *then* decrement. */ +#define MINUS_ONE (((bfd_vma)0) - 1) + +/* The relocation table used for SHT_RELA sections. */ + +static reloc_howto_type elfNN_nanomips_howto_table_rela[] = { + /* No relocation. */ + HOWTO (R_NANOMIPS_NONE, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_NONE", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* 32 bit relocation. */ + HOWTO (R_NANOMIPS_32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* 64 bit relocation. */ + HOWTO (R_NANOMIPS_64, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_64", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + MINUS_ONE, /* dst_mask */ + false), /* pcrel_offset */ + + /* Symbol address negation, can be composed for label differences. */ + HOWTO (R_NANOMIPS_NEG, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_negative_reloc, /* special_function */ + "R_NANOMIPS_NEG", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* A 5 bit shift field. */ + HOWTO (R_NANOMIPS_ASHIFTR_1, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_ASHIFTR_1", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_UNSIGNED_8, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_UNSIGNED_8", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_SIGNED_8, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_SIGNED_8", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_UNSIGNED_16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_UNSIGNED_16", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_SIGNED_16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_SIGNED_16", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + false), /* pcrel_offset */ + + EMPTY_HOWTO (R_NANOMIPS_RELATIVE), + EMPTY_HOWTO (R_NANOMIPS_GLOBAL), + + /* Lazy resolver jump slot. */ + HOWTO (R_NANOMIPS_JUMP_SLOT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_JUMP_SLOT", /* name */ + false, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Reserved for IFUNC support. */ + EMPTY_HOWTO (R_NANOMIPS_IRELATIVE), + + HOWTO (R_NANOMIPS_PC25_S1, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 25, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_PC25_S1", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x01ffffff, /* dst_mask */ + true), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_PC21_S1, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 21, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_PC21_S1", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x0001ffff, /* dst_mask */ + true), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_PC14_S1, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 14, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_PC14_S1", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x00003fff, /* dst_mask */ + true), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_PC11_S1, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 11, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_PC11_S1", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x000007ff, /* dst_mask */ + true), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_PC10_S1, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_PC10_S1", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x000003ff, /* dst_mask */ + true), /* pcrel_offset */ + + /* This is for nanoMIPS branches. */ + HOWTO (R_NANOMIPS_PC7_S1, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 7, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_PC7_S1", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x0000007f, /* dst_mask */ + true), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_PC4_S1, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_PC4_S1", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x0000000f, /* dst_mask */ + true), /* pcrel_offset */ + + /* GP relative reference. */ + HOWTO (R_NANOMIPS_GPREL19_S2, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + false, /* pc_relative */ + 2, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GPREL19_S2", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x001ffffc, /* dst_mask */ + false), /* pcrel_offset */ + + /* GP relative reference. */ + HOWTO (R_NANOMIPS_GPREL18_S3, /* type */ + 3, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 18, /* bitsize */ + false, /* pc_relative */ + 3, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GPREL18_S3", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x001ffff8, /* dst_mask */ + false), /* pcrel_offset */ + + /* GP relative reference. */ + HOWTO (R_NANOMIPS_GPREL18, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 18, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GPREL18", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x0003ffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* GP relative reference. */ + HOWTO (R_NANOMIPS_GPREL17_S1, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 17, /* bitsize */ + false, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GPREL17_S1", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x0001fffe, /* dst_mask */ + false), /* pcrel_offset */ + + /* GP relative reference. */ + HOWTO (R_NANOMIPS_GPREL16_S2, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 2, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GPREL16_S2", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x0003fffc, /* dst_mask */ + false), /* pcrel_offset */ + + /* GP- and PC-relative relocations. */ + HOWTO (R_NANOMIPS_GPREL7_S2, /* type */ + 2, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 7, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GPREL7_S2", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x0000007f, /* dst_mask */ + false), /* pcrel_offset */ + + /* High 20 bits of GP relative reference. */ + HOWTO (R_NANOMIPS_GPREL_HI20, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GPREL_HI20", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x001ffffd, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_PCHI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_PCHI20", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x001ffffd, /* dst_mask */ + true), /* pcrel_offset */ + + /* High 20 bits of symbol value. */ + HOWTO (R_NANOMIPS_HI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_HI20", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x001ffffd, /* dst_mask */ + false), /* pcrel_offset */ + + /* Low 12 bits of symbol value. */ + HOWTO (R_NANOMIPS_LO12, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_LO12", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x00000fff, /* dst_mask */ + false), /* pcrel_offset */ + + /* High 32 bits of 64-bit address. */ + HOWTO (R_NANOMIPS_GPREL_I32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GPREL_I32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* High 32 bits of 64-bit address. */ + HOWTO (R_NANOMIPS_PC_I32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_PC_I32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* Refers to low 32-bits of 48-bit instruction. The 32-bit value + is encoded as nanoMIPS instruction stream - so it will be + half-word swapped on little endian targets. */ + HOWTO (R_NANOMIPS_I32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_I32", /* name */ + false, /* partial_inplace */ + 0x0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* Displacement in the global offset table. */ + HOWTO (R_NANOMIPS_GOT_DISP, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + false, /* pc_relative */ + 2, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GOT_DISP", /* name */ + false, /* partial_inplace */ + 0x0, /* src_mask */ + 0x001ffffc, /* dst_mask */ + false), /* pcrel_offset */ + /* High 32 bits of 64-bit address. */ + HOWTO (R_NANOMIPS_GOTPC_I32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GOTPC_I32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* High 20 bits of PC-relative GOT offset. */ + HOWTO (R_NANOMIPS_GOTPC_HI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GOTPC_HI20", /* name */ + false, /* partial_inplace */ + 0x0, /* src_mask */ + 0x001ffffd, /* dst_mask */ + true), /* pcrel_offset */ + + /* Low 12 bits of displacement in global offset table. */ + HOWTO (R_NANOMIPS_GOT_LO12, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + false, /* pc_relative */ + 2, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GOT_LO12", /* name */ + false, /* partial_inplace */ + 0x0, /* src_mask */ + 0x00000fff, /* dst_mask */ + true), /* pcrel_offset */ + + /* 19 bit call through global offset table. */ + HOWTO (R_NANOMIPS_GOT_CALL, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GOT_CALL", /* name */ + false, /* partial_inplace */ + 0x0, /* src_mask */ + 0x001ffffc, /* dst_mask */ + false), /* pcrel_offset */ + + /* Displacement to page pointer in the global offset table. */ + HOWTO (R_NANOMIPS_GOT_PAGE, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GOT_PAGE", /* name */ + false, /* partial_inplace */ + 0x0, /* src_mask */ + 0x001ffffc, /* dst_mask */ + false), /* pcrel_offset */ + + /* Offset from page pointer in the global offset table. */ + HOWTO (R_NANOMIPS_GOT_OFST, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GOT_OFST", /* name */ + false, /* partial_inplace */ + 0x0, /* src_mask */ + 0x00000fff, /* dst_mask */ + false), /* pcrel_offset */ + + /* Low 4 bits of symbol value. */ + HOWTO (R_NANOMIPS_LO4_S2, /* type */ + 2, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_LO4_S2", /* name */ + false, /* partial_inplace */ + 0x0000000f, /* src_mask */ + 0x0000000f, /* dst_mask */ + false), /* pcrel_offset */ + + /* Reserved for 64-bit ABI, HI32 relocation. */ + EMPTY_HOWTO (R_NANOMIPS_RESERVED1), + + /* Low 12 bits of GP-relative displacement. */ + HOWTO (R_NANOMIPS_GPREL_LO12, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_GPREL_LO12", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x00000fff, /* dst_mask */ + false), /* pcrel_offset */ + + /* Section displacement. */ + HOWTO (R_NANOMIPS_SCN_DISP, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_SCN_DISP", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* Copy relocation. */ + HOWTO (R_NANOMIPS_COPY, /* type */ + 0, /* rightshift */ + 0, /* this one is variable size */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_COPY", /* name */ + false, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ + false), /* pcrel_offset */ + + EMPTY_HOWTO (45), + EMPTY_HOWTO (46), + EMPTY_HOWTO (47), + EMPTY_HOWTO (48), + EMPTY_HOWTO (49), + EMPTY_HOWTO (50), + EMPTY_HOWTO (51), + EMPTY_HOWTO (52), + EMPTY_HOWTO (53), + EMPTY_HOWTO (54), + EMPTY_HOWTO (55), + EMPTY_HOWTO (56), + EMPTY_HOWTO (57), + EMPTY_HOWTO (58), + EMPTY_HOWTO (59), + EMPTY_HOWTO (60), + EMPTY_HOWTO (61), + EMPTY_HOWTO (62), + EMPTY_HOWTO (63), + + /* Place-holder for code alignment. */ + HOWTO (R_NANOMIPS_ALIGN, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler. */ + "R_NANOMIPS_ALIGN", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Fill value for code alignment. */ + HOWTO (R_NANOMIPS_FILL, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler. */ + "R_NANOMIPS_FILL", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Maximum padding bytes for code alignment. */ + HOWTO (R_NANOMIPS_MAX, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler. */ + "R_NANOMIPS_MAX", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Place-holder to enforce 32-bit instruction encoding. */ + HOWTO (R_NANOMIPS_INSN32, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler. */ + "R_NANOMIPS_INSN32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Place-holder to inhibit relaxation on one instruction. */ + HOWTO (R_NANOMIPS_FIXED, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler. */ + "R_NANOMIPS_FIXED", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Marker to inhibit linker relaxation. */ + HOWTO (R_NANOMIPS_NORELAX, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler. */ + "R_NANOMIPS_NORELAX", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Marker to enable linker relaxation. */ + HOWTO (R_NANOMIPS_RELAX, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler. */ + "R_NANOMIPS_RELAX", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Place-holder for relaxation of save/restore instructions. */ + HOWTO (R_NANOMIPS_SAVERESTORE, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler. */ + "R_NANOMIPS_SAVERESTORE", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Place-holder to enforce 16-bit instruction encoding. */ + HOWTO (R_NANOMIPS_INSN16, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler. */ + "R_NANOMIPS_INSN16", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Place-holder to enforce 32-bit JALR encoding. */ + HOWTO (R_NANOMIPS_JALR32, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler. */ + "R_NANOMIPS_JALR32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Place-holder to enforce 16-bit JALR encoding. */ + HOWTO (R_NANOMIPS_JALR16, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler. */ + "R_NANOMIPS_JALR16", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Place-holder for compressed jump-table load instructions. */ + HOWTO (R_NANOMIPS_JUMPTABLE_LOAD, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler */ + "R_NANOMIPS_JUMPTABLE_LOAD", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + /* Place-holder for relaxing frame-register information. */ + HOWTO (R_NANOMIPS_FRAME_REG, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special handler */ + "R_NANOMIPS_FRAME_REG", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + + EMPTY_HOWTO (77), + EMPTY_HOWTO (78), + EMPTY_HOWTO (79), + + /* TLS GD/LD dynamic relocations. */ + HOWTO (R_NANOMIPS_TLS_DTPMOD, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_DTPMOD", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_TLS_DTPREL, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_DTPREL", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* TLS IE dynamic relocations. */ + HOWTO (R_NANOMIPS_TLS_TPREL, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_TPREL", /* name */ + false, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* TLS general dynamic variable reference. */ + HOWTO (R_NANOMIPS_TLS_GD, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + false, /* pc_relative */ + 2, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_GD", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x001ffffc, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_TLS_GD_I32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_GD_I32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* TLS local dynamic variable reference. */ + HOWTO (R_NANOMIPS_TLS_LD, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + false, /* pc_relative */ + 2, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_LD", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x001ffffc, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_NANOMIPS_TLS_LD_I32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_LD_I32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* TLS local dynamic 12-bit offset. */ + HOWTO (R_NANOMIPS_TLS_DTPREL12, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_DTPREL12", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x00000fff, /* dst_mask */ + false), /* pcrel_offset */ + + /* TLS local dynamic 16-bit offset. */ + HOWTO (R_NANOMIPS_TLS_DTPREL16, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_DTPREL16", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x0000ffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* TLS local dynamic 32-bit offset. */ + HOWTO (R_NANOMIPS_TLS_DTPREL_I32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_DTPREL_I32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* TLS thread pointer 21-bit GOT offset. */ + HOWTO (R_NANOMIPS_TLS_GOTTPREL, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + false, /* pc_relative */ + 2, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_GOTTPREL", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x001ffffc, /* dst_mask */ + false), /* pcrel_offset */ + + /* TLS thread pointer 32-bit GOT offset. */ + HOWTO (R_NANOMIPS_TLS_GOTTPREL_PC_I32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_GOTTPREL_PC_I32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + true), /* pcrel_offset */ + + /* TLS thread pointer 12-bit offset. */ + HOWTO (R_NANOMIPS_TLS_TPREL12, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_TPREL12", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x00000fff, /* dst_mask */ + false), /* pcrel_offset */ + + /* TLS thread pointer 16-bit offset. */ + HOWTO (R_NANOMIPS_TLS_TPREL16, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_TPREL16", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0x0000ffff, /* dst_mask */ + false), /* pcrel_offset */ + + /* TLS thread pointer 32-bit offset. */ + HOWTO (R_NANOMIPS_TLS_TPREL_I32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_TLS_TPREL_I32", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ +}; + +/* GNU extension to record C++ vtable hierarchy */ +static reloc_howto_type elf_nanomips_gnu_vtinherit_howto = + HOWTO (R_NANOMIPS_GNU_VTINHERIT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + NULL, /* special_function */ + "R_NANOMIPS_GNU_VTINHERIT", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false); /* pcrel_offset */ + +/* GNU extension to record C++ vtable member usage */ +static reloc_howto_type elf_nanomips_gnu_vtentry_howto = + HOWTO (R_NANOMIPS_GNU_VTENTRY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_elf_rel_vtable_reloc_fn, /* special_function */ + "R_NANOMIPS_GNU_VTENTRY", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false); /* pcrel_offset */ + +/* 32 bit pc-relative. */ +static reloc_howto_type elf_nanomips_gnu_pcrel32 = + HOWTO (R_NANOMIPS_PC32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_PC32", /* name */ + true, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + true); /* pcrel_offset */ + +/* Used in EH tables. */ +static reloc_howto_type elf_nanomips_eh_howto = + HOWTO (R_NANOMIPS_EH, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_nanomips_elf_generic_reloc, /* special_function */ + "R_NANOMIPS_EH", /* name */ + true, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + false); /* pcrel_offset */ + +/* A mapping from BFD reloc types to nanoMIPS ELF reloc types. */ + +struct elf_reloc_map +{ + bfd_reloc_code_real_type bfd_val; + enum elf_nanomips_reloc_type elf_val; +}; + +static const struct elf_reloc_map nanomips_reloc_map[] = { + { BFD_RELOC_NONE, R_NANOMIPS_NONE }, + { BFD_RELOC_32, R_NANOMIPS_32 }, + { BFD_RELOC_64, R_NANOMIPS_64 }, + { BFD_RELOC_NANOMIPS_NEG, R_NANOMIPS_NEG }, + { BFD_RELOC_NANOMIPS_ASHIFTR_1, R_NANOMIPS_ASHIFTR_1 }, + { BFD_RELOC_NANOMIPS_UNSIGNED_8, R_NANOMIPS_UNSIGNED_8 }, + { BFD_RELOC_NANOMIPS_SIGNED_8, R_NANOMIPS_SIGNED_8 }, + { BFD_RELOC_NANOMIPS_UNSIGNED_16, R_NANOMIPS_UNSIGNED_16 }, + { BFD_RELOC_16, R_NANOMIPS_UNSIGNED_16 }, + { BFD_RELOC_NANOMIPS_SIGNED_16, R_NANOMIPS_SIGNED_16 }, + { BFD_RELOC_NANOMIPS_HI20, R_NANOMIPS_HI20 }, + { BFD_RELOC_NANOMIPS_LO12, R_NANOMIPS_LO12 }, + { BFD_RELOC_NANOMIPS_IMM16, R_NANOMIPS_LO12 }, + { BFD_RELOC_NANOMIPS_25_PCREL_S1, R_NANOMIPS_PC25_S1 }, + { BFD_RELOC_NANOMIPS_21_PCREL_S1, R_NANOMIPS_PC21_S1 }, + { BFD_RELOC_NANOMIPS_14_PCREL_S1, R_NANOMIPS_PC14_S1 }, + { BFD_RELOC_NANOMIPS_11_PCREL_S1, R_NANOMIPS_PC11_S1 }, + { BFD_RELOC_NANOMIPS_10_PCREL_S1, R_NANOMIPS_PC10_S1 }, + { BFD_RELOC_NANOMIPS_7_PCREL_S1, R_NANOMIPS_PC7_S1 }, + { BFD_RELOC_NANOMIPS_GPREL7_S2, R_NANOMIPS_GPREL7_S2 }, + { BFD_RELOC_NANOMIPS_GPREL18, R_NANOMIPS_GPREL18 }, + { BFD_RELOC_NANOMIPS_GPREL19_S2, R_NANOMIPS_GPREL19_S2 }, + { BFD_RELOC_NANOMIPS_4_PCREL_S1,R_NANOMIPS_PC4_S1 }, + { BFD_RELOC_NANOMIPS_PCREL_HI20, R_NANOMIPS_PCHI20 }, + { BFD_RELOC_NANOMIPS_GPREL16_S2, R_NANOMIPS_GPREL16_S2 }, + { BFD_RELOC_NANOMIPS_GPREL18_S3, R_NANOMIPS_GPREL18_S3 }, + { BFD_RELOC_NANOMIPS_GOT_CALL, R_NANOMIPS_GOT_CALL }, + { BFD_RELOC_NANOMIPS_GOT_DISP, R_NANOMIPS_GOT_DISP }, + { BFD_RELOC_NANOMIPS_GOT_PAGE, R_NANOMIPS_GOT_PAGE }, + { BFD_RELOC_NANOMIPS_GOT_OFST, R_NANOMIPS_GOT_OFST }, + { BFD_RELOC_NANOMIPS_GOTPC_HI20, R_NANOMIPS_GOTPC_HI20 }, + { BFD_RELOC_NANOMIPS_GOT_LO12, R_NANOMIPS_GOT_LO12 }, + { BFD_RELOC_NANOMIPS_GOTPC_I32, R_NANOMIPS_GOTPC_I32 }, + { BFD_RELOC_NANOMIPS_I32, R_NANOMIPS_I32 }, + { BFD_RELOC_NANOMIPS_GPREL_HI20, R_NANOMIPS_GPREL_HI20 }, + { BFD_RELOC_NANOMIPS_PC_I32, R_NANOMIPS_PC_I32 }, + { BFD_RELOC_NANOMIPS_GPREL_I32, R_NANOMIPS_GPREL_I32 }, + { BFD_RELOC_NANOMIPS_GPREL17_S1, R_NANOMIPS_GPREL17_S1 }, + { BFD_RELOC_NANOMIPS_GPREL_LO12, R_NANOMIPS_GPREL_LO12 }, + { BFD_RELOC_NANOMIPS_LO4_S2, R_NANOMIPS_LO4_S2 }, + { BFD_RELOC_NANOMIPS_COPY, R_NANOMIPS_COPY }, + + { BFD_RELOC_NANOMIPS_ALIGN, R_NANOMIPS_ALIGN }, + { BFD_RELOC_NANOMIPS_FILL, R_NANOMIPS_FILL }, + { BFD_RELOC_NANOMIPS_MAX, R_NANOMIPS_MAX }, + { BFD_RELOC_NANOMIPS_INSN32, R_NANOMIPS_INSN32 }, + { BFD_RELOC_NANOMIPS_INSN16, R_NANOMIPS_INSN16 }, + { BFD_RELOC_NANOMIPS_FIXED, R_NANOMIPS_FIXED }, + { BFD_RELOC_NANOMIPS_RELAX, R_NANOMIPS_RELAX }, + { BFD_RELOC_NANOMIPS_NORELAX, R_NANOMIPS_NORELAX }, + { BFD_RELOC_NANOMIPS_SAVERESTORE, R_NANOMIPS_SAVERESTORE }, + { BFD_RELOC_NANOMIPS_JALR32, R_NANOMIPS_JALR32 }, + { BFD_RELOC_NANOMIPS_JALR16, R_NANOMIPS_JALR16 }, + { BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD, R_NANOMIPS_JUMPTABLE_LOAD }, + + { BFD_RELOC_NANOMIPS_TLS_GD, R_NANOMIPS_TLS_GD }, + { BFD_RELOC_NANOMIPS_TLS_GD_I32, R_NANOMIPS_TLS_GD_I32 }, + { BFD_RELOC_NANOMIPS_TLS_LD, R_NANOMIPS_TLS_LD }, + { BFD_RELOC_NANOMIPS_TLS_LD_I32, R_NANOMIPS_TLS_LD_I32 }, + { BFD_RELOC_NANOMIPS_TLS_DTPREL12, R_NANOMIPS_TLS_DTPREL12 }, + { BFD_RELOC_NANOMIPS_TLS_DTPREL16, R_NANOMIPS_TLS_DTPREL16 }, + { BFD_RELOC_NANOMIPS_TLS_DTPREL_I32, R_NANOMIPS_TLS_DTPREL_I32 }, + { BFD_RELOC_NANOMIPS_TLS_GOTTPREL, R_NANOMIPS_TLS_GOTTPREL }, + { BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32, R_NANOMIPS_TLS_GOTTPREL_PC_I32 }, + { BFD_RELOC_NANOMIPS_TLS_TPREL12, R_NANOMIPS_TLS_TPREL12 }, + { BFD_RELOC_NANOMIPS_TLS_TPREL16, R_NANOMIPS_TLS_TPREL16 }, + { BFD_RELOC_NANOMIPS_TLS_TPREL_I32, R_NANOMIPS_TLS_TPREL_I32 }, + { BFD_RELOC_NANOMIPS_TLS_DTPMOD, R_NANOMIPS_TLS_DTPMOD }, + { BFD_RELOC_NANOMIPS_TLS_DTPREL, R_NANOMIPS_TLS_DTPREL }, + { BFD_RELOC_NANOMIPS_TLS_TPREL, R_NANOMIPS_TLS_TPREL }, +}; + +/* Given a BFD reloc type, return a howto structure. */ + +static reloc_howto_type * +bfd_elfNN_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) +{ + unsigned int i; + reloc_howto_type *howto_nanomips_table; + + howto_nanomips_table = elfNN_nanomips_howto_table_rela; + + for (i = 0; i < sizeof (nanomips_reloc_map) / sizeof (struct elf_reloc_map); + i++) + { + if (nanomips_reloc_map[i].bfd_val == code) + return &howto_nanomips_table[(int) nanomips_reloc_map[i].elf_val]; + } + + switch (code) + { + default: + bfd_set_error (bfd_error_bad_value); + return NULL; + + case BFD_RELOC_CTOR: + return &howto_nanomips_table[(int) R_NANOMIPS_32]; + + case BFD_RELOC_VTABLE_INHERIT: + return &elf_nanomips_gnu_vtinherit_howto; + case BFD_RELOC_VTABLE_ENTRY: + return &elf_nanomips_gnu_vtentry_howto; + case BFD_RELOC_NANOMIPS_EH: + return &elf_nanomips_eh_howto; + case BFD_RELOC_32_PCREL: + return &elf_nanomips_gnu_pcrel32; + } +} + +/* Map a BFD relocation to its display name. */ + +static reloc_howto_type * +bfd_elfNN_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < (sizeof (elfNN_nanomips_howto_table_rela) + / sizeof (elfNN_nanomips_howto_table_rela[0])); i++) + if (elfNN_nanomips_howto_table_rela[i].name != NULL + && strcasecmp (elfNN_nanomips_howto_table_rela[i].name, r_name) == 0) + return &elfNN_nanomips_howto_table_rela[i]; + + if (strcasecmp (elf_nanomips_gnu_vtinherit_howto.name, r_name) == 0) + return &elf_nanomips_gnu_vtinherit_howto; + if (strcasecmp (elf_nanomips_gnu_vtentry_howto.name, r_name) == 0) + return &elf_nanomips_gnu_vtentry_howto; + if (strcasecmp (elf_nanomips_eh_howto.name, r_name) == 0) + return &elf_nanomips_eh_howto; + + return NULL; +} + +/* Given a nanoMIPS Elf_Internal_Rel, fill in an arelent structure. */ + +static reloc_howto_type * +nanomips_elfNN_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED, + unsigned int r_type, + bool rela_p ATTRIBUTE_UNUSED) +{ + switch (r_type) + { + case R_NANOMIPS_GNU_VTINHERIT: + return &elf_nanomips_gnu_vtinherit_howto; + case R_NANOMIPS_GNU_VTENTRY: + return &elf_nanomips_gnu_vtentry_howto; + case R_NANOMIPS_EH: + return &elf_nanomips_eh_howto; + case R_NANOMIPS_PC32: + return &elf_nanomips_gnu_pcrel32; + default: + return &elfNN_nanomips_howto_table_rela[r_type]; + } +} + +/* Given a nanoMIPS Elf_Internal_Rela, fill in an arelent structure. */ + +static bool +nanomips_info_to_howto_rela (bfd *abfd, arelent *cache_ptr, + Elf_Internal_Rela *dst) +{ + const struct elf_backend_data *bed; + unsigned int r_type; + + r_type = ELFNN_R_TYPE (dst->r_info); + bed = get_elf_backend_data (abfd); + cache_ptr->howto = bed->elf_backend_mips_rtype_to_howto (abfd, r_type, true); + cache_ptr->addend = dst->r_addend; + return true; +} + +/* nanoMIPS ELF local labels start with '$'. */ + +static bool +nanomips_elf_is_local_label_name (bfd *abfd, const char *name) +{ + if (name[0] == '$') + return true; + + /* Fall back to the generic ELF local label syntax. */ + return _bfd_elf_is_local_label_name (abfd, name); +} + +/* Set the right machine number for a nanoMIPS ELF file. */ + +static bool +nanomips_elfNN_object_p (bfd *abfd) +{ + unsigned long mach; + + if (!ABI_PNN_P (abfd)) + return false; + + mach = _bfd_elf_nanomips_mach (elf_elfheader (abfd)->e_flags); + bfd_default_set_arch_mach (abfd, bfd_arch_nanomips, mach); + return true; +} + +#define ELF_ARCH bfd_arch_nanomips +#define ELF_TARGET_ID NANOMIPS_ELF_DATA +#define ELF_MACHINE_CODE EM_NANOMIPS + +#define elf_backend_collect true +#define elf_backend_type_change_ok true +#define elf_info_to_howto nanomips_info_to_howto_rela +#define elf_backend_object_p nanomips_elfNN_object_p +#define elf_backend_section_processing _bfd_nanomips_elf_section_processing +#define elf_backend_section_from_shdr _bfd_nanomips_elf_section_from_shdr +#define elf_backend_fake_sections _bfd_nanomips_elf_fake_sections +#define elf_backend_final_write_processing \ + _bfd_nanomips_elf_final_write_processing + +#define elf_backend_may_use_rela_p 1 +#define elf_backend_default_use_rela_p 1 +#define elf_backend_sign_extend_vma true +#define elf_backend_plt_readonly 1 + +#define bfd_elfNN_bfd_get_relocated_section_contents \ + _bfd_elf_nanomips_get_relocated_section_contents +#define elf_backend_mips_rtype_to_howto nanomips_elfNN_rtype_to_howto +#define bfd_elfNN_bfd_print_private_bfd_data \ + _bfd_nanomips_elf_print_private_bfd_data +#define bfd_elfNN_mkobject _bfd_nanomips_elf_mkobject +#define bfd_elfNN_bfd_is_local_label_name \ + nanomips_elf_is_local_label_name + +#define ELF_MAXPAGESIZE 0x1000 +#define ELF_COMMONPAGESIZE 0x1000 + +/* Support for nanomipsNN target. */ + +#define TARGET_LITTLE_SYM nanomips_elfNN_le_vec +#define TARGET_LITTLE_NAME "elfNN-littlenanomips" +#define TARGET_BIG_SYM nanomips_elfNN_be_vec +#define TARGET_BIG_NAME "elfNN-bignanomips" + +#define elfNN_bed elfNN_nanomips_bed + +/* Include the target file for this target. */ +#include "elfNN-target.h" diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h index 2c790ed5ed6..a24c30f5d55 100644 --- a/bfd/elfxx-mips.h +++ b/bfd/elfxx-mips.h @@ -65,6 +65,8 @@ extern bool _bfd_mips_elf_create_dynamic_sections (bfd *, struct bfd_link_info *); extern bool _bfd_mips_elf_check_relocs (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *); +extern bool _bfd_mips_relax_section + (bfd *, asection *, struct bfd_link_info *, bool *again); extern bool _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *, struct elf_link_hash_entry *); extern bool _bfd_mips_elf_always_size_sections @@ -133,6 +135,8 @@ extern const char * _bfd_mips_fp_abi_string (int); extern bool _bfd_mips_elf_print_private_bfd_data (bfd *, void *); +extern bool _bfd_nanomips_elf_print_private_bfd_data + (bfd *, void *); extern bool _bfd_mips_elf_discard_info (bfd *, struct elf_reloc_cookie *, struct bfd_link_info *); extern bool _bfd_mips_elf_write_section @@ -165,6 +169,7 @@ extern bfd_vma _bfd_mips_elf_sign_extend extern void _bfd_mips_elf_merge_symbol_attribute (struct elf_link_hash_entry *, unsigned int, bool, bool); extern char *_bfd_mips_elf_get_target_dtag (bfd_vma); +extern char *_bfd_nanomips_elf_get_target_dtag (bfd_vma); extern bool _bfd_mips_elf_ignore_undef_symbol (struct elf_link_hash_entry *); extern void _bfd_mips_elf_use_plts_and_copy_relocs diff --git a/bfd/elfxx-nanomips.c b/bfd/elfxx-nanomips.c new file mode 100644 index 00000000000..8405fe09c34 --- /dev/null +++ b/bfd/elfxx-nanomips.c @@ -0,0 +1,794 @@ +/* nanoMIPS-specific support for ELF + Copyright (C) 2018-2022 Free Software Foundation, Inc. + + Written by Faraz Shahbazker + + This file is part of BFD, the Binary File Descriptor library. + + This program 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 of the License, or + (at your option) any later version. + + This program 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. */ + + +/* This file handles functionality common to nanoMIPS ABIs. */ + +#include "sysdep.h" +#include "bfd.h" +#include "libbfd.h" +#include "elf-bfd.h" +#include "elfxx-nanomips.h" +#include "elf/nanomips.h" + +/* nanoMIPS ELF private object data. */ + +struct nanomips_elf_obj_tdata +{ + /* Generic ELF private object data. */ + struct elf_obj_tdata root; + + /* Input BFD providing Tag_GNU_NANOMIPS_ABI_FP attribute for output. */ + bfd *abi_fp_bfd; + + /* Input BFD providing Tag_GNU_NANOMIPS_ABI_MSA attribute for output. */ + bfd *abi_msa_bfd; + + /* The abiflags for this object. */ + Elf_Internal_ABIFlags_v0 abiflags; + bool abiflags_valid; + + bfd_signed_vma sdata_section[1000]; +}; + +/* Get nanoMIPS ELF private object data from BFD's tdata. */ + +#define nanomips_elf_tdata(bfd) \ + ((struct nanomips_elf_obj_tdata *) (bfd)->tdata.any) + +/* True if NAME is the recognized name of any SHT_NANOMIPS_ABIFLAGS section. */ + +#define NANOMIPS_ELF_ABIFLAGS_SECTION_NAME_P(NAME) \ + (strcmp (NAME, ".nanoMIPS.abiflags") == 0) + +/* Allocate nanoMIPS ELF private object data. */ + +bool +_bfd_nanomips_elf_mkobject (bfd *abfd) +{ + return bfd_elf_allocate_object (abfd, + sizeof (struct nanomips_elf_obj_tdata), + NANOMIPS_ELF_DATA); +} + +/* A generic howto special_function. This calculates and installs the + relocation itself, thus avoiding the oft-discussed problems in + bfd_perform_relocation and bfd_install_relocation. */ + +bfd_reloc_status_type +_bfd_nanomips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, asymbol *symbol, + void *data ATTRIBUTE_UNUSED, + asection *input_section, bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) +{ + bfd_signed_vma val; + bfd_reloc_status_type status; + bool relocatable; + + relocatable = (output_bfd != NULL); + + if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + return bfd_reloc_outofrange; + + /* Build up the field adjustment in VAL. */ + val = 0; + if (!relocatable || (symbol->flags & BSF_SECTION_SYM) != 0) + { + /* Either we're calculating the final field value or we have a + relocation against a section symbol. Add in the section's + offset or address. */ + val += symbol->section->output_section->vma; + val += symbol->section->output_offset; + } + + if (!relocatable) + { + /* We're calculating the final field value. Add in the symbol's value + and, if pc-relative, subtract the address of the field itself. */ + val += symbol->value; + if (reloc_entry->howto->pc_relative) + { + val -= input_section->output_section->vma; + val -= input_section->output_offset; + val -= reloc_entry->address; + } + } + + /* VAL is now the final adjustment. If we're keeping this relocation + in the output file, and if the relocation uses a separate addend, + we just need to add VAL to that addend. Otherwise we need to add + VAL to the relocation field itself. */ + if (relocatable && !reloc_entry->howto->partial_inplace) + reloc_entry->addend += val; + else + { + bfd_byte *location = (bfd_byte *) data + reloc_entry->address; + + /* Add in the separate addend, if any. */ + val += reloc_entry->addend; + + /* Add VAL to the relocation field. */ + status = _bfd_relocate_contents (reloc_entry->howto, abfd, val, + location); + if (status != bfd_reloc_ok) + return status; + } + + if (relocatable) + reloc_entry->address += input_section->output_offset; + + return bfd_reloc_ok; +} + +/* A negation howto special_function. */ + +bfd_reloc_status_type +_bfd_nanomips_elf_negative_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, asymbol *symbol, + void *data ATTRIBUTE_UNUSED, + asection *input_section, bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) +{ + bfd_signed_vma val; + bool relocatable; + + relocatable = (output_bfd != NULL); + + if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + return bfd_reloc_outofrange; + + /* Calculate the value of the symbol S. */ + val = symbol->section->output_section->vma; + val += symbol->section->output_offset; + val += symbol->value; + + /* Add negated value to addend: (-S + A). */ + if (! relocatable ) + reloc_entry->addend = -val + reloc_entry->addend; + + if (relocatable) + reloc_entry->address += input_section->output_offset; + + return bfd_reloc_ok; +} + +/* Swap in an abiflags structure. */ + +void +bfd_nanomips_elf_swap_abiflags_v0_in (bfd *abfd, + const Elf_External_ABIFlags_v0 *ex, + Elf_Internal_ABIFlags_v0 *in) +{ + in->version = H_GET_16 (abfd, ex->version); + in->isa_level = H_GET_8 (abfd, ex->isa_level); + in->isa_rev = H_GET_8 (abfd, ex->isa_rev); + in->gpr_size = H_GET_8 (abfd, ex->gpr_size); + in->cpr1_size = H_GET_8 (abfd, ex->cpr1_size); + in->cpr2_size = H_GET_8 (abfd, ex->cpr2_size); + in->fp_abi = H_GET_8 (abfd, ex->fp_abi); + in->isa_ext = H_GET_32 (abfd, ex->isa_ext); + in->ases = H_GET_32 (abfd, ex->ases); + in->flags1 = H_GET_32 (abfd, ex->flags1); + in->flags2 = H_GET_32 (abfd, ex->flags2); +} + +/* Swap out an abiflags structure. */ + +void +bfd_nanomips_elf_swap_abiflags_v0_out (bfd *abfd, + const Elf_Internal_ABIFlags_v0 *in, + Elf_External_ABIFlags_v0 *ex) +{ + H_PUT_16 (abfd, in->version, ex->version); + H_PUT_8 (abfd, in->isa_level, ex->isa_level); + H_PUT_8 (abfd, in->isa_rev, ex->isa_rev); + H_PUT_8 (abfd, in->gpr_size, ex->gpr_size); + H_PUT_8 (abfd, in->cpr1_size, ex->cpr1_size); + H_PUT_8 (abfd, in->cpr2_size, ex->cpr2_size); + H_PUT_8 (abfd, in->fp_abi, ex->fp_abi); + H_PUT_32 (abfd, in->isa_ext, ex->isa_ext); + H_PUT_32 (abfd, in->ases, ex->ases); + H_PUT_32 (abfd, in->flags1, ex->flags1); + H_PUT_32 (abfd, in->flags2, ex->flags2); +} + +/* Map flag bits to BFD architecture. */ + +unsigned long +_bfd_elf_nanomips_mach (flagword flags) +{ + switch (flags & EF_NANOMIPS_ARCH) + { + default: + case E_NANOMIPS_ARCH_32R6: + return bfd_mach_nanomipsisa32r6; + + case E_NANOMIPS_ARCH_64R6: + return bfd_mach_nanomipsisa64r6; + } + + return 0; +} + +/* Work over a section just before writing it out. This routine is + used by both the 32-bit and the 64-bit ABI. */ + +bool +_bfd_nanomips_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, + Elf_Internal_Shdr *hdr) +{ + if (hdr->bfd_section != NULL) + { + const char *name = bfd_section_name (hdr->bfd_section); + + /* .sbss is not handled specially here because the GNU/Linux + prelinker can convert .sbss from NOBITS to PROGBITS and + changing it back to NOBITS breaks the binary. The entry in + _bfd_nanomips_elf_special_sections will ensure the correct flags + are set on .sbss if BFD creates it without reading it from an + input file, and without special handling here the flags set + on it in an input file will be followed. */ + if (strcmp (name, ".sdata") == 0 + || strcmp (name, ".lit8") == 0 + || strcmp (name, ".lit4") == 0 + || strncmp (name, ".sdata_", 7) == 0) + { + hdr->sh_flags |= SHF_ALLOC | SHF_WRITE; + hdr->sh_type = SHT_PROGBITS; + } + else if (strcmp (name, ".srdata") == 0) + { + hdr->sh_flags |= SHF_ALLOC; + hdr->sh_type = SHT_PROGBITS; + } + else if (strcmp (name, ".compact_rel") == 0) + { + hdr->sh_flags = 0; + hdr->sh_type = SHT_PROGBITS; + } + else if (strcmp (name, ".rtproc") == 0) + { + if (hdr->sh_addralign != 0 && hdr->sh_entsize == 0) + { + unsigned int adjust; + + adjust = hdr->sh_size % hdr->sh_addralign; + if (adjust != 0) + hdr->sh_size += hdr->sh_addralign - adjust; + } + } + } + + return true; +} + +/* Handle a nanoMIPS specific section when reading an object file. + This is called when elfcode.h finds a section with an unknown type. + This routine supports both the 32-bit and 64-bit ELF ABI. */ + +bool +_bfd_nanomips_elf_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, + const char *name, int shindex) +{ + flagword flags = 0; + + /* There ought to be a place to keep ELF backend specific flags, but + at the moment there isn't one. We just keep track of the + sections by their name, instead. */ + switch (hdr->sh_type) + { + case SHT_NANOMIPS_ABIFLAGS: + if (!NANOMIPS_ELF_ABIFLAGS_SECTION_NAME_P (name)) + return false; + flags = (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_SIZE); + break; + default: + break; + } + + if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) + return false; + + if (flags) + { + if (!bfd_set_section_flags (hdr->bfd_section, + (bfd_section_flags (hdr->bfd_section) + | flags))) + return false; + } + + if (hdr->sh_type == SHT_NANOMIPS_ABIFLAGS) + { + Elf_External_ABIFlags_v0 ext; + + if (! bfd_get_section_contents (abfd, hdr->bfd_section, &ext, + 0, sizeof ext)) + return false; + bfd_nanomips_elf_swap_abiflags_v0_in + (abfd, &ext, &nanomips_elf_tdata (abfd)->abiflags); + if (nanomips_elf_tdata (abfd)->abiflags.version != 0) + return false; + nanomips_elf_tdata (abfd)->abiflags_valid = true; + } + + return true; +} + +/* Set the correct type for a nanoMIPS ELF section. We do this by the + section name, which is a hack, but ought to work. This routine is + used by both the 32-bit and the 64-bit ABI. */ + +bool +_bfd_nanomips_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, + Elf_Internal_Shdr *hdr, + asection *sec) +{ + const char *name = bfd_section_name (sec); + + if (startswith (name, ".nanoMIPS.abiflags")) + { + hdr->sh_type = SHT_NANOMIPS_ABIFLAGS; + hdr->sh_entsize = sizeof (Elf_External_ABIFlags_v0); + } + + /* The generic elf_fake_sections will set up REL_HDR using the default + kind of relocations. */ + return true; +} + +/* Functions for the dynamic linker. */ + +/* Set ABFD's EF_NANOMIPS_ARCH and EF_NANOMIPS_MACH flags. */ + +static void +nanomips_set_isa_flags (bfd *abfd) +{ + flagword val = 0; + + switch (bfd_get_mach (abfd)) + { + case bfd_mach_nanomipsisa32r6: + val = E_NANOMIPS_ARCH_32R6; + break; + + case bfd_mach_nanomipsisa64r6: + val = E_NANOMIPS_ARCH_64R6; + break; + default: + break; + } + + elf_elfheader (abfd)->e_flags &= ~(EF_NANOMIPS_ARCH | EF_NANOMIPS_MACH); + elf_elfheader (abfd)->e_flags |= val; +} + +/* The final processing done just before writing out a nanoMIPS ELF + object file. This gets the nanoMIPS architecture right based on the + machine number. This is used by both the 32-bit and the 64-bit ABI. */ + +bool +_bfd_nanomips_elf_final_write_processing (bfd *abfd) +{ + nanomips_set_isa_flags (abfd); + return _bfd_elf_final_write_processing (abfd); +} + +/* Return the meaning of Tag_GNU_NANOMIPS_ABI_FP value FP, or null if + not known. */ + +const char * +_bfd_nanomips_fp_abi_string (int fp) +{ + switch (fp) + { + /* These strings aren't translated because they're simply + option lists. */ + case Val_GNU_NANOMIPS_ABI_FP_DOUBLE: + return "-mdouble-float"; + + case Val_GNU_NANOMIPS_ABI_FP_SINGLE: + return "-msingle-float"; + + case Val_GNU_NANOMIPS_ABI_FP_SOFT: + return "-msoft-float"; + + default: + return 0; + } +} + +/* Print the name of an ASE. */ + +static void +print_nanomips_ases (FILE *file, unsigned int mask) +{ + if (mask & NANOMIPS_ASE_DSPR3) + fputs ("\n\tDSP R3 ASE", file); + if (mask & NANOMIPS_ASE_EVA) + fputs ("\n\tEnhanced VA Scheme", file); + if (mask & NANOMIPS_ASE_MCU) + fputs ("\n\tMCU (MicroController) ASE", file); + if (mask & NANOMIPS_ASE_MT) + fputs ("\n\tMT ASE", file); + if (mask & NANOMIPS_ASE_VIRT) + fputs ("\n\tVZ ASE", file); + if (mask & NANOMIPS_ASE_MSA) + fputs ("\n\tMSA ASE", file); + if (mask & NANOMIPS_ASE_TLB) + fputs ("\n\tTLB ASE", file); + if (mask & NANOMIPS_ASE_CRC) + fputs ("\n\tCRC ASE", file); + if ((mask & NANOMIPS_ASE_xNMS) == 0) + fputs ("\n\tnanoMIPS subset", file); + else if (mask == 0) + fprintf (file, "\n\t%s", _("None")); + else if ((mask & ~NANOMIPS_ASE_MASK) != 0) + fprintf (stdout, "\n\t%s (%x)", _("Unknown"), mask & ~NANOMIPS_ASE_MASK); +} + +/* Print the name of an ISA extension. None yet for nanoMIPS. */ + +static void +print_nanomips_isa_ext (FILE *file, unsigned int isa_ext) +{ + switch (isa_ext) + { + case 0: + fputs (_("None"), file); + break; + default: + fprintf (file, "%s (%d)", _("Unknown"), isa_ext); + break; + } +} + +/* Decode and print the FP ABI mode. */ + +static void +print_nanomips_fp_abi_value (FILE *file, int val) +{ + switch (val) + { + case Val_GNU_NANOMIPS_ABI_FP_ANY: + fprintf (file, _("Hard or soft float\n")); + break; + case Val_GNU_NANOMIPS_ABI_FP_DOUBLE: + fprintf (file, _("Hard float (double precision)\n")); + break; + case Val_GNU_NANOMIPS_ABI_FP_SINGLE: + fprintf (file, _("Hard float (single precision)\n")); + break; + case Val_GNU_NANOMIPS_ABI_FP_SOFT: + fprintf (file, _("Soft float\n")); + break; + default: + fprintf (file, "??? (%d)\n", val); + break; + } +} + +/* Map register type to size. */ + +static int +get_nanomips_reg_size (int reg_size) +{ + return ((reg_size == AFL_REG_NONE) ? 0 + : (reg_size == AFL_REG_32) ? 32 + : (reg_size == AFL_REG_64) ? 64 + : (reg_size == AFL_REG_128) ? 128 + : -1); +} + +/* Print nanoMIPS-specific ELF data. */ + +bool +_bfd_nanomips_elf_print_private_bfd_data (bfd *abfd, void *ptr) +{ + FILE *file = ptr; + + BFD_ASSERT (abfd != NULL && ptr != NULL); + + /* Print normal ELF private data. */ + _bfd_elf_print_private_bfd_data (abfd, ptr); + + /* xgettext:c-format */ + fprintf (file, _("private flags = %08lx:"), elf_elfheader (abfd)->e_flags); + + if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) == E_NANOMIPS_ABI_P32) + fprintf (file, _(" [abi=P32]")); + else if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) == + E_NANOMIPS_ABI_P64) + fprintf (file, _(" [abi=P64]")); + else + fprintf (file, _(" [no abi set]")); + + if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ARCH) + == E_NANOMIPS_ARCH_32R6) + fprintf (file, " [nanomips32r6]"); + else if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ARCH) + == E_NANOMIPS_ARCH_64R6) + fprintf (file, " [nanomips64r6]"); + else + fprintf (file, _(" [unknown ISA]")); + + if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_32BITMODE) + fprintf (file, " [32bitmode]"); + else + fprintf (file, _(" [not 32bitmode]")); + + if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_LINKRELAX) + fprintf (file, " [RELAXABLE]"); + + if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_PIC) + fprintf (file, " [PIC]"); + + if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_PID) + fprintf (file, " [PID]"); + + if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_PCREL) + fprintf (file, " [PCREL]"); + + fputc ('\n', file); + + if (nanomips_elf_tdata (abfd)->abiflags_valid) + { + Elf_Internal_ABIFlags_v0 *abiflags = + &nanomips_elf_tdata (abfd)->abiflags; + fprintf (file, "\nnanoMIPS ABI Flags Version: %d\n", abiflags->version); + fprintf (file, "\nISA: nanoMIPS%d", abiflags->isa_level); + if (abiflags->isa_rev > 1) + fprintf (file, "r%d", abiflags->isa_rev); + fprintf (file, "\nGPR size: %d", + get_nanomips_reg_size (abiflags->gpr_size)); + fprintf (file, "\nCPR1 size: %d", + get_nanomips_reg_size (abiflags->cpr1_size)); + fprintf (file, "\nCPR2 size: %d", + get_nanomips_reg_size (abiflags->cpr2_size)); + fputs ("\nFP ABI: ", file); + print_nanomips_fp_abi_value (file, abiflags->fp_abi); + fputs ("ISA Extension: ", file); + print_nanomips_isa_ext (file, abiflags->isa_ext); + fputs ("\nASEs:", file); + print_nanomips_ases (file, abiflags->ases); + fprintf (file, "\nFLAGS 1: %8.8lx", abiflags->flags1); + fprintf (file, "\nFLAGS 2: %8.8lx", abiflags->flags2); + fputc ('\n', file); + } + + return true; +} + +const struct bfd_elf_special_section _bfd_nanomips_elf_special_sections[] = { + { STRING_COMMA_LEN (".lit4"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE}, + { STRING_COMMA_LEN (".lit8"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE}, + { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE}, + { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE}, + { NULL, 0, 0, 0, 0 } +}; + +/* Merge non visibility st_other attributes. Ensure that the + STO_OPTIONAL flag is copied into h->other, even if this is not a + definiton of the symbol. */ + +void +_bfd_nanomips_elf_merge_symbol_attribute (struct elf_link_hash_entry *h, + unsigned int st_other, + bool definition, + bool dynamic + ATTRIBUTE_UNUSED) +{ + if ((st_other & ~ELF_ST_VISIBILITY (-1)) != 0) + { + unsigned char other; + + other = (definition ? st_other : h->other); + other &= ~ELF_ST_VISIBILITY (-1); + h->other = other | ELF_ST_VISIBILITY (h->other); + } +} + +/* Get ABI flags for a nanoMIPS BFD arch. */ + +Elf_Internal_ABIFlags_v0 * +bfd_nanomips_elf_get_abiflags (bfd *abfd) +{ + struct nanomips_elf_obj_tdata *tdata = nanomips_elf_tdata (abfd); + + return tdata->abiflags_valid ? &tdata->abiflags : NULL; +} + +/* Relocate a section. Tools like readelf/binutils needed to perform a static + relocation on objects to make sense debug information that contains label + difference relocations. The only difference between this and the generic + ELF version is that correct handling of composite relocations according to + gABI spec. */ + +bfd_byte * +_bfd_elf_nanomips_get_relocated_section_contents (bfd *abfd, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, + bfd_byte *data, + bool relocatable, + asymbol **symbols) +{ + bfd *input_bfd = link_order->u.indirect.section->owner; + asection *input_section = link_order->u.indirect.section; + long reloc_size; + arelent **reloc_vector; + long reloc_count; + + reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); + if (reloc_size < 0) + return NULL; + + /* Read in the section. */ + if (!bfd_get_full_section_contents (input_bfd, input_section, &data)) + return NULL; + + if (data == NULL) + return NULL; + + if (reloc_size == 0) + return data; + + reloc_vector = (arelent **) bfd_malloc (reloc_size); + if (reloc_vector == NULL) + return NULL; + + reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, + reloc_vector, symbols); + + if (reloc_count < 0) + goto error_return; + + if (reloc_count > 0) + { + arelent **parent; + /* offset in section of previous relocation */ + bfd_size_type last_address = 0; + /* saved result of previous relocation. */ + bfd_vma saved_addend = 0; + + for (parent = reloc_vector; *parent != NULL; parent++) + { + char *error_message = NULL; + asymbol *symbol; + bfd_reloc_status_type r; + + symbol = *(*parent)->sym_ptr_ptr; + /* PR ld/19628: A specially crafted input file + can result in a NULL symbol pointer here. */ + if (symbol == NULL) + { + link_info->callbacks->einfo + /* xgettext:c-format */ + (_("%X%P: %B(%A): error: relocation for offset %V has no value\n"), + abfd, input_section, (* parent)->address); + goto error_return; + } + + if (symbol->section && discarded_section (symbol->section)) + { + bfd_vma off; + static reloc_howto_type none_howto + = HOWTO (0, 0, 0, 0, false, 0, complain_overflow_dont, NULL, + "unused", false, 0, 0, false); + + off = (*parent)->address * bfd_octets_per_byte (input_bfd, input_section); + _bfd_clear_contents ((*parent)->howto, input_bfd, input_section, + data, off); + (*parent)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + (*parent)->addend = 0; + (*parent)->howto = &none_howto; + r = bfd_reloc_ok; + } + else + { + if (last_address != 0 && (*parent)->address == last_address) + (*parent)->addend = saved_addend; + else + saved_addend = 0; + + r = bfd_perform_relocation (input_bfd, + *parent, + data, + input_section, + relocatable ? abfd : NULL, + &error_message); + saved_addend = (*parent)->addend; + } + + if (relocatable) + { + asection *os = input_section->output_section; + + /* A partial link, so keep the relocs. */ + os->orelocation[os->reloc_count] = *parent; + os->reloc_count++; + } + + if (r != bfd_reloc_ok) + { + switch (r) + { + case bfd_reloc_undefined: + (*link_info->callbacks->undefined_symbol) + (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), + input_bfd, input_section, (*parent)->address, true); + break; + case bfd_reloc_dangerous: + BFD_ASSERT (error_message != NULL); + (*link_info->callbacks->reloc_dangerous) + (link_info, error_message, + input_bfd, input_section, (*parent)->address); + break; + case bfd_reloc_overflow: + (*link_info->callbacks->reloc_overflow) + (link_info, NULL, + bfd_asymbol_name (*(*parent)->sym_ptr_ptr), + (*parent)->howto->name, (*parent)->addend, + input_bfd, input_section, (*parent)->address); + break; + case bfd_reloc_outofrange: + /* PR ld/13730: + This error can result when processing some partially + complete binaries. Do not abort, but issue an error + message instead. */ + link_info->callbacks->einfo + /* xgettext:c-format */ + (_("%X%P: %B(%A): relocation \"%R\" goes out of range\n"), + abfd, input_section, *parent); + goto error_return; + + case bfd_reloc_notsupported: + /* PR ld/17512 + This error can result when processing a corrupt binary. + Do not abort. Issue an error message instead. */ + link_info->callbacks->einfo + /* xgettext:c-format */ + (_("%X%P: %B(%A): relocation \"%R\" is not supported\n"), + abfd, input_section, *parent); + goto error_return; + + default: + /* PR 17512; file: 90c2a92e. + Report unexpected results, without aborting. */ + link_info->callbacks->einfo + /* xgettext:c-format */ + (_("%X%P: %B(%A): relocation \"%R\" returns an unrecognized value %x\n"), + abfd, input_section, *parent, r); + break; + } + + } + last_address = (*parent)->address; + } + } + + free (reloc_vector); + return data; + +error_return: + free (reloc_vector); + return NULL; +} diff --git a/bfd/elfxx-nanomips.h b/bfd/elfxx-nanomips.h new file mode 100644 index 00000000000..6566db550cb --- /dev/null +++ b/bfd/elfxx-nanomips.h @@ -0,0 +1,54 @@ +/* nanoMIPS ELF specific backend routines. + Copyright (C) 2018-2022 Free Software Foundation, Inc. + + Written by Faraz Shahbazker + + This file is part of BFD, the Binary File Descriptor library. + + This program 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 of the License, or + (at your option) any later version. + + This program 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 "elf/nanomips.h" + +extern bool _bfd_nanomips_elf_mkobject (bfd *); +extern bool _bfd_nanomips_elf_section_processing + (bfd *, Elf_Internal_Shdr *); +extern bool _bfd_nanomips_elf_section_from_shdr + (bfd *, Elf_Internal_Shdr *, const char *, int); +extern bool _bfd_nanomips_elf_fake_sections + (bfd *, Elf_Internal_Shdr *, asection *); +extern bool _bfd_nanomips_elf_final_write_processing (bfd *); +extern const char *_bfd_nanomips_fp_abi_string (int); +extern bool _bfd_nanomips_elf_print_private_bfd_data (bfd *, void *); + +extern bfd_reloc_status_type _bfd_nanomips_elf_generic_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); +extern bfd_reloc_status_type _bfd_nanomips_elf_negative_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); + +extern unsigned long _bfd_elf_nanomips_mach (flagword); +extern void _bfd_nanomips_elf_merge_symbol_attribute + (struct elf_link_hash_entry *, unsigned int, bool, bool); + +extern const struct bfd_elf_special_section + _bfd_nanomips_elf_special_sections[]; + +extern bfd_byte *_bfd_elf_nanomips_get_relocated_section_contents + (bfd *, struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *, bool, asymbol **); + +#define elf_backend_special_sections _bfd_nanomips_elf_special_sections +#define elf_backend_merge_symbol_attribute \ + _bfd_nanomips_elf_merge_symbol_attribute diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 05508c986ad..c48f85ea582 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1330,6 +1330,75 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_MIPS_COPY", "BFD_RELOC_MIPS_JUMP_SLOT", + "BFD_RELOC_NANOMIPS_HI20", + "BFD_RELOC_NANOMIPS_LO12", + "BFD_RELOC_NANOMIPS_LO4_S2", + "BFD_RELOC_NANOMIPS_IMM16", + "BFD_RELOC_NANOMIPS_NEG12", + "BFD_RELOC_NANOMIPS_GPREL7_S2", + "BFD_RELOC_NANOMIPS_GPREL18", + "BFD_RELOC_NANOMIPS_GPREL19_S2", + "BFD_RELOC_NANOMIPS_GPREL16_S2", + "BFD_RELOC_NANOMIPS_GPREL18_S3", + "BFD_RELOC_NANOMIPS_4_PCREL_S1", + "BFD_RELOC_NANOMIPS_7_PCREL_S1", + "BFD_RELOC_NANOMIPS_10_PCREL_S1", + "BFD_RELOC_NANOMIPS_11_PCREL_S1", + "BFD_RELOC_NANOMIPS_14_PCREL_S1", + "BFD_RELOC_NANOMIPS_21_PCREL_S1", + "BFD_RELOC_NANOMIPS_25_PCREL_S1", + "BFD_RELOC_NANOMIPS_PCREL_HI20", + "BFD_RELOC_NANOMIPS_GOT_CALL", + "BFD_RELOC_NANOMIPS_GOTPC_HI20", + "BFD_RELOC_NANOMIPS_GOTPC_I32", + "BFD_RELOC_NANOMIPS_GOT_LO12", + "BFD_RELOC_NANOMIPS_GOT_DISP", + "BFD_RELOC_NANOMIPS_GOT_PAGE", + "BFD_RELOC_NANOMIPS_GOT_OFST", + "BFD_RELOC_NANOMIPS_I32", + "BFD_RELOC_NANOMIPS_GPREL_HI20", + "BFD_RELOC_NANOMIPS_GPREL_LO12", + "BFD_RELOC_NANOMIPS_TLS_GD", + "BFD_RELOC_NANOMIPS_TLS_GD_I32", + "BFD_RELOC_NANOMIPS_TLS_LD", + "BFD_RELOC_NANOMIPS_TLS_LD_I32", + "BFD_RELOC_NANOMIPS_TLS_DTPREL12", + "BFD_RELOC_NANOMIPS_TLS_DTPREL16", + "BFD_RELOC_NANOMIPS_TLS_DTPREL_I32", + "BFD_RELOC_NANOMIPS_TLS_GOTTPREL", + "BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32", + "BFD_RELOC_NANOMIPS_TLS_TPREL12", + "BFD_RELOC_NANOMIPS_TLS_TPREL16", + "BFD_RELOC_NANOMIPS_TLS_TPREL_I32", + "BFD_RELOC_NANOMIPS_TLS_DTPMOD", + "BFD_RELOC_NANOMIPS_TLS_DTPREL", + "BFD_RELOC_NANOMIPS_TLS_TPREL", + "BFD_RELOC_NANOMIPS_PC_I32", + "BFD_RELOC_NANOMIPS_GPREL_I32", + "BFD_RELOC_NANOMIPS_GPREL17_S1", + "BFD_RELOC_NANOMIPS_NEG", + "BFD_RELOC_NANOMIPS_ASHIFTR_1", + "BFD_RELOC_NANOMIPS_UNSIGNED_8", + "BFD_RELOC_NANOMIPS_UNSIGNED_16", + "BFD_RELOC_NANOMIPS_SIGNED_8", + "BFD_RELOC_NANOMIPS_SIGNED_16", + "BFD_RELOC_NANOMIPS_EH", + "BFD_RELOC_NANOMIPS_JUMP_SLOT", + "BFD_RELOC_NANOMIPS_ALIGN", + "BFD_RELOC_NANOMIPS_FILL", + "BFD_RELOC_NANOMIPS_MAX", + "BFD_RELOC_NANOMIPS_INSN32", + "BFD_RELOC_NANOMIPS_INSN16", + "BFD_RELOC_NANOMIPS_FIXED", + "BFD_RELOC_NANOMIPS_RELAX", + "BFD_RELOC_NANOMIPS_NORELAX", + "BFD_RELOC_NANOMIPS_SAVERESTORE", + "BFD_RELOC_NANOMIPS_JALR16", + "BFD_RELOC_NANOMIPS_JALR32", + "BFD_RELOC_NANOMIPS_COPY", + "BFD_RELOC_NANOMIPS_SIGNED_9", + "BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD", + "BFD_RELOC_MOXIE_10_PCREL", "BFD_RELOC_FT32_10", diff --git a/bfd/reloc.c b/bfd/reloc.c index aab5d49bdb3..bc422fef840 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2177,6 +2177,146 @@ ENUMDOC MIPS ELF relocations (VxWorks and PLT extensions). COMMENT +ENUM + BFD_RELOC_NANOMIPS_HI20 +ENUMX + BFD_RELOC_NANOMIPS_LO12 +ENUMX + BFD_RELOC_NANOMIPS_LO4_S2 +ENUMX + BFD_RELOC_NANOMIPS_IMM16 +ENUMX + BFD_RELOC_NANOMIPS_NEG12 +ENUMX + BFD_RELOC_NANOMIPS_GPREL7_S2 +ENUMX + BFD_RELOC_NANOMIPS_GPREL18 +ENUMX + BFD_RELOC_NANOMIPS_GPREL19_S2 +ENUMX + BFD_RELOC_NANOMIPS_GPREL16_S2 +ENUMX + BFD_RELOC_NANOMIPS_GPREL18_S3 +ENUMX + BFD_RELOC_NANOMIPS_4_PCREL_S1 +ENUMX + BFD_RELOC_NANOMIPS_7_PCREL_S1 +ENUMX + BFD_RELOC_NANOMIPS_10_PCREL_S1 +ENUMX + BFD_RELOC_NANOMIPS_11_PCREL_S1 +ENUMX + BFD_RELOC_NANOMIPS_14_PCREL_S1 +ENUMX + BFD_RELOC_NANOMIPS_21_PCREL_S1 +ENUMX + BFD_RELOC_NANOMIPS_25_PCREL_S1 +ENUMX + BFD_RELOC_NANOMIPS_PCREL_HI20 +ENUMX + BFD_RELOC_NANOMIPS_GOT_CALL +ENUMX + BFD_RELOC_NANOMIPS_GOTPC_HI20 +ENUMX + BFD_RELOC_NANOMIPS_GOTPC_I32 +ENUMX + BFD_RELOC_NANOMIPS_GOT_LO12 +ENUMX + BFD_RELOC_NANOMIPS_GOT_DISP +ENUMX + BFD_RELOC_NANOMIPS_GOT_PAGE +ENUMX + BFD_RELOC_NANOMIPS_GOT_OFST +ENUMX + BFD_RELOC_NANOMIPS_I32 +ENUMX + BFD_RELOC_NANOMIPS_GPREL_HI20 +ENUMX + BFD_RELOC_NANOMIPS_GPREL_LO12 +ENUMX + BFD_RELOC_NANOMIPS_TLS_GD +ENUMX + BFD_RELOC_NANOMIPS_TLS_GD_I32 +ENUMX + BFD_RELOC_NANOMIPS_TLS_LD +ENUMX + BFD_RELOC_NANOMIPS_TLS_LD_I32 +ENUMX + BFD_RELOC_NANOMIPS_TLS_DTPREL12 +ENUMX + BFD_RELOC_NANOMIPS_TLS_DTPREL16 +ENUMX + BFD_RELOC_NANOMIPS_TLS_DTPREL_I32 +ENUMX + BFD_RELOC_NANOMIPS_TLS_GOTTPREL +ENUMX + BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32 +ENUMX + BFD_RELOC_NANOMIPS_TLS_TPREL12 +ENUMX + BFD_RELOC_NANOMIPS_TLS_TPREL16 +ENUMX + BFD_RELOC_NANOMIPS_TLS_TPREL_I32 +ENUMX + BFD_RELOC_NANOMIPS_TLS_DTPMOD +ENUMX + BFD_RELOC_NANOMIPS_TLS_DTPREL +ENUMX + BFD_RELOC_NANOMIPS_TLS_TPREL +ENUMX + BFD_RELOC_NANOMIPS_PC_I32 +ENUMX + BFD_RELOC_NANOMIPS_GPREL_I32 +ENUMX + BFD_RELOC_NANOMIPS_GPREL17_S1 +ENUMX + BFD_RELOC_NANOMIPS_NEG +ENUMX + BFD_RELOC_NANOMIPS_ASHIFTR_1 +ENUMX + BFD_RELOC_NANOMIPS_UNSIGNED_8 +ENUMX + BFD_RELOC_NANOMIPS_UNSIGNED_16 +ENUMX + BFD_RELOC_NANOMIPS_SIGNED_8 +ENUMX + BFD_RELOC_NANOMIPS_SIGNED_16 +ENUMX + BFD_RELOC_NANOMIPS_EH +ENUMX + BFD_RELOC_NANOMIPS_JUMP_SLOT +ENUMX + BFD_RELOC_NANOMIPS_ALIGN +ENUMX + BFD_RELOC_NANOMIPS_FILL +ENUMX + BFD_RELOC_NANOMIPS_MAX +ENUMX + BFD_RELOC_NANOMIPS_INSN32 +ENUMX + BFD_RELOC_NANOMIPS_INSN16 +ENUMX + BFD_RELOC_NANOMIPS_FIXED +ENUMX + BFD_RELOC_NANOMIPS_RELAX +ENUMX + BFD_RELOC_NANOMIPS_NORELAX +ENUMX + BFD_RELOC_NANOMIPS_SAVERESTORE +ENUMX + BFD_RELOC_NANOMIPS_JALR16 +ENUMX + BFD_RELOC_NANOMIPS_JALR32 +ENUMX + BFD_RELOC_NANOMIPS_COPY +ENUMX + BFD_RELOC_NANOMIPS_SIGNED_9 +ENUMX + BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD +ENUMDOC + nanoMIPS relocations +COMMENT + ENUM BFD_RELOC_MOXIE_10_PCREL ENUMDOC diff --git a/bfd/targets.c b/bfd/targets.c index 3dbcd088966..264933a83eb 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -829,6 +829,10 @@ extern const bfd_target moxie_elf32_le_vec; extern const bfd_target msp430_elf32_vec; extern const bfd_target msp430_elf32_ti_vec; extern const bfd_target mt_elf32_vec; +extern const bfd_target nanomips_elf32_be_vec; +extern const bfd_target nanomips_elf32_le_vec; +extern const bfd_target nanomips_elf64_le_vec; +extern const bfd_target nanomips_elf64_be_vec; extern const bfd_target nds32_elf32_be_vec; extern const bfd_target nds32_elf32_le_vec; extern const bfd_target nds32_elf32_linux_be_vec; @@ -1203,6 +1207,13 @@ static const bfd_target * const _bfd_target_vector[] = &mt_elf32_vec, + &nanomips_elf32_be_vec, + &nanomips_elf32_le_vec, +#ifdef BFD64 + &nanomips_elf64_be_vec, + &nanomips_elf64_le_vec, +#endif + &nds32_elf32_be_vec, &nds32_elf32_le_vec, &nds32_elf32_linux_be_vec, diff --git a/binutils/readelf.c b/binutils/readelf.c index b872876a8b6..b31a61dc568 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -139,6 +139,7 @@ #include "elf/moxie.h" #include "elf/mt.h" #include "elf/msp430.h" +#include "elf/nanomips.h" #include "elf/nds32.h" #include "elf/nfp.h" #include "elf/nios2.h" @@ -1097,6 +1098,7 @@ guess_is_rela (unsigned int e_machine) case EM_MSP430: case EM_MSP430_OLD: case EM_MT: + case EM_NANOMIPS: case EM_NDS32: case EM_NIOS32: case EM_OR1K: @@ -1894,6 +1896,10 @@ dump_relocations (Filedata *filedata, rtype = elf_nios2_reloc_type (type); break; + case EM_NANOMIPS: + rtype = elf_nanomips_reloc_type (type); + break; + case EM_TI_PRU: rtype = elf_pru_reloc_type (type); break; @@ -2205,6 +2211,16 @@ get_mips_dynamic_type (unsigned long type) } } +static const char * +get_nanomips_dynamic_type (unsigned long type) +{ + switch (type) + { + default: + return NULL; + } +} + static const char * get_sparc64_dynamic_type (unsigned long type) { @@ -2571,6 +2587,9 @@ get_dynamic_type (Filedata * filedata, unsigned long type) case EM_RISCV: result = get_riscv_dynamic_type (type); break; + case EM_NANOMIPS: + result = get_nanomips_dynamic_type (type); + break; default: if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) result = get_solaris_dynamic_type (type); @@ -2963,7 +2982,7 @@ get_machine_name (unsigned e_machine) case EM_CEVA_X2: return "CEVA X2 Processor Family"; case EM_BPF: return "Linux BPF"; case EM_GRAPHCORE_IPU: return "Graphcore Intelligent Processing Unit"; - case EM_IMG1: return "Imagination Technologies"; + case EM_NANOMIPS: return "Imagination Technologies"; /* 250 */ case EM_NFP: return "Netronome Flow Processor"; case EM_VE: return "NEC Vector Engine"; @@ -4393,6 +4412,38 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine) strcat (buf, ", OBJ-v1"); break; + case EM_NANOMIPS: + if (e_flags & EF_NANOMIPS_PIC) + strcat (buf, ", pic"); + + if (e_flags & EF_NANOMIPS_32BITMODE) + strcat (buf, ", 32bitmode"); + + switch ((e_flags & EF_NANOMIPS_MACH)) + { + default: strcat (buf, _(", unknown CPU")); break; + } + + switch ((e_flags & EF_NANOMIPS_ABI)) + { + case E_NANOMIPS_ABI_P32: strcat (buf, ", p32"); break; + case E_NANOMIPS_ABI_P64: strcat (buf, ", p64"); break; + case 0: + /* We simply ignore the field in this case to avoid confusion: + MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension. + This means it is likely to be an o32 file, but not for + sure. */ + break; + default: strcat (buf, _(", unknown ABI")); break; + } + + switch ((e_flags & EF_NANOMIPS_ARCH)) + { + case E_NANOMIPS_ARCH_32R6: strcat (buf, ", nanomips32r6"); break; + case E_NANOMIPS_ARCH_64R6: strcat (buf, ", nanomips64r6"); break; + default: strcat (buf, _(", unknown ISA")); break; + } + break; } } @@ -4521,6 +4572,20 @@ get_mips_segment_type (unsigned long type) } } +static const char * +get_nanomips_segment_type (unsigned long type) +{ + switch (type) + { + case PT_NANOMIPS_ABIFLAGS: + return "ABIFLAGS"; + default: + break; + } + + return NULL; +} + static const char * get_parisc_segment_type (unsigned long type) { @@ -4675,6 +4740,9 @@ get_segment_type (Filedata * filedata, unsigned long p_type) case EM_S390_OLD: result = get_s390_segment_type (p_type); break; + case EM_NANOMIPS: + result = get_nanomips_segment_type (p_type); + break; case EM_RISCV: result = get_riscv_segment_type (p_type); break; @@ -10725,6 +10793,17 @@ dynamic_section_mips_val (Filedata * filedata, Elf_Internal_Dyn * entry) putchar ('\n'); } +static void +dynamic_section_nanomips_val (Elf_Internal_Dyn * entry) +{ + switch (entry->d_tag) + { + default: + print_vma (entry->d_un.d_ptr, PREFIX_HEX); + } + putchar ('\n'); +} + static void dynamic_section_parisc_val (Elf_Internal_Dyn * entry) { @@ -12065,6 +12144,9 @@ the .dynstr section doesn't match the DT_STRTAB and DT_STRSZ tags\n")); case EM_IA_64: dynamic_section_ia64_val (entry); break; + case EM_NANOMIPS: + dynamic_section_nanomips_val (entry); + break; default: print_vma (entry->d_un.d_val, PREFIX_HEX); putchar ('\n'); @@ -14357,6 +14439,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) return reloc_type == 1; /* R_MSP430_32 or R_MSP320_ABS32. */ case EM_MT: return reloc_type == 2; /* R_MT_32. */ + case EM_NANOMIPS: + return reloc_type == 1; /* R_NANOMIPS_32. */ case EM_NDS32: return reloc_type == 20; /* R_NDS32_32_RELA. */ case EM_ALTERA_NIOS2: @@ -14561,6 +14645,8 @@ is_64bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) return reloc_type == 1; /* R_TILEGX_64. */ case EM_MIPS: return reloc_type == 18; /* R_MIPS_64. */ + case EM_NANOMIPS: + return reloc_type == 2; /* R_NANOMIPS_64. */ default: return false; } @@ -14668,6 +14754,8 @@ is_16bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) /* Fall through. */ case EM_MSP430_OLD: return reloc_type == 5; /* R_MSP430_16_BYTE. */ + case EM_NANOMIPS: + return reloc_type == 7; /* R_NANOMIPS_UNSIGNED_16 */ case EM_NDS32: return reloc_type == 19; /* R_NDS32_16_RELA. */ case EM_ALTERA_NIOS2: @@ -14896,6 +14984,7 @@ is_none_reloc (Filedata * filedata, unsigned int reloc_type) case EM_MOXIE: /* R_MOXIE_NONE. */ case EM_NIOS32: /* R_NIOS_NONE. */ case EM_OR1K: /* R_OR1K_NONE. */ + case EM_NANOMIPS: /* R_NANOMIPS_NONE. */ case EM_PARISC: /* R_PARISC_NONE. */ case EM_PPC64: /* R_PPC64_NONE. */ case EM_PPC: /* R_PPC_NONE. */ @@ -17480,6 +17569,71 @@ display_mips_gnu_attribute (unsigned char * p, return display_tag_value (tag & 1, p, end); } +static void +print_nanomips_fp_abi_value (int val) +{ + switch (val) + { + case Val_GNU_NANOMIPS_ABI_FP_ANY: + printf (_("Hard or soft float\n")); + break; + case Val_GNU_NANOMIPS_ABI_FP_DOUBLE: + printf (_("Hard float (double precision)\n")); + break; + case Val_GNU_NANOMIPS_ABI_FP_SINGLE: + printf (_("Hard float (single precision)\n")); + break; + case Val_GNU_NANOMIPS_ABI_FP_SOFT: + printf (_("Soft float\n")); + break; + default: + printf ("??? (%d)\n", val); + break; + } +} + +static unsigned char * +display_nanomips_gnu_attribute (unsigned char * p, + unsigned int tag, + const unsigned char * const end) +{ + if (tag == Tag_GNU_NANOMIPS_ABI_FP) + { + uint64_t val; + + READ_ULEB (val, p, end); + printf (" Tag_GNU_NANOMIPS_ABI_FP: "); + + print_nanomips_fp_abi_value (val); + + return p; + } + + if (tag == Tag_GNU_NANOMIPS_ABI_MSA) + { + uint64_t val; + + READ_ULEB (val, p, end); + printf (" Tag_GNU_NANOMIPS_ABI_MSA: "); + + switch (val) + { + case Val_GNU_NANOMIPS_ABI_MSA_ANY: + printf (_("Any MSA or not\n")); + break; + case Val_GNU_NANOMIPS_ABI_MSA_128: + printf (_("128-bit MSA\n")); + break; + default: + printf ("??? (%lu)\n", val); + break; + } + return p; + } + + return display_tag_value (tag & 1, p, end); +} + static unsigned char * display_tic6x_attribute (unsigned char * p, const unsigned char * const end) @@ -19317,6 +19471,350 @@ process_mips_specific (Filedata * filedata) return res; } +static void +print_nanomips_ases (unsigned int mask) +{ + if (mask & NANOMIPS_ASE_DSPR3) + fputs ("\n\tDSP R3 ASE", stdout); + if (mask & NANOMIPS_ASE_EVA) + fputs ("\n\tEnhanced VA Scheme", stdout); + if (mask & NANOMIPS_ASE_MCU) + fputs ("\n\tMCU (MicroController) ASE", stdout); + if (mask & NANOMIPS_ASE_MT) + fputs ("\n\tMT ASE", stdout); + if (mask & NANOMIPS_ASE_VIRT) + fputs ("\n\tVZ ASE", stdout); + if (mask & NANOMIPS_ASE_MSA) + fputs ("\n\tMSA ASE", stdout); + if (mask & NANOMIPS_ASE_TLB) + fputs ("\n\tTLB ASE", stdout); + if (mask & NANOMIPS_ASE_GINV) + fputs ("\n\tGINV ASE", stdout); + if ((mask & NANOMIPS_ASE_xNMS) == 0) + fputs ("\n\tnanoMIPS subset", stdout); + else if (mask == 0) + fprintf (stdout, "\n\t%s", _("None")); + else if ((mask & ~NANOMIPS_ASE_MASK) != 0) + fprintf (stdout, "\n\t%s (%x)", _("Unknown"), mask & ~NANOMIPS_ASE_MASK); +} + +static void +print_nanomips_isa_ext (unsigned int isa_ext) +{ + switch (isa_ext) + { + case 0: + fputs (_("None"), stdout); + break; + default: + fprintf (stdout, "%s (%d)", _("Unknown"), isa_ext); + } +} + +static int +get_nanomips_reg_size (int reg_size) +{ + return (get_mips_reg_size (reg_size)); +} + +static bool +process_nanomips_specific (Filedata * filedata) +{ + Elf_Internal_Dyn * entry; + Elf_Internal_Shdr *sect = NULL; + size_t options_offset = 0; + bfd_vma pltgot = 0; + bfd_vma gotsym = 0; + bfd_vma symtabno = 0; + + process_attributes (filedata, NULL, SHT_GNU_ATTRIBUTES, NULL, + display_nanomips_gnu_attribute); + + sect = find_section (filedata, ".nanoMIPS.abiflags"); + + if (sect != NULL) + { + Elf_External_ABIFlags_v0 *abiflags_ext; + Elf_Internal_ABIFlags_v0 abiflags_in; + + if (sizeof (Elf_External_ABIFlags_v0) != sect->sh_size) + fputs ("\nCorrupt ABI Flags section.\n", stdout); + else + { + abiflags_ext = get_data (NULL, filedata, sect->sh_offset, 1, + sect->sh_size, _("nanoMIPS ABI Flags section")); + if (abiflags_ext) + { + abiflags_in.version = BYTE_GET (abiflags_ext->version); + abiflags_in.isa_level = BYTE_GET (abiflags_ext->isa_level); + abiflags_in.isa_rev = BYTE_GET (abiflags_ext->isa_rev); + abiflags_in.gpr_size = BYTE_GET (abiflags_ext->gpr_size); + abiflags_in.cpr1_size = BYTE_GET (abiflags_ext->cpr1_size); + abiflags_in.cpr2_size = BYTE_GET (abiflags_ext->cpr2_size); + abiflags_in.fp_abi = BYTE_GET (abiflags_ext->fp_abi); + abiflags_in.isa_ext = BYTE_GET (abiflags_ext->isa_ext); + abiflags_in.ases = BYTE_GET (abiflags_ext->ases); + abiflags_in.flags1 = BYTE_GET (abiflags_ext->flags1); + abiflags_in.flags2 = BYTE_GET (abiflags_ext->flags2); + + printf ("\nnanoMIPS ABI Flags Version: %d\n", abiflags_in.version); + printf ("\nISA: nanoMIPS%d", abiflags_in.isa_level); + if (abiflags_in.isa_rev > 1) + printf ("r%d", abiflags_in.isa_rev); + printf ("\nGPR size: %d", + get_nanomips_reg_size (abiflags_in.gpr_size)); + printf ("\nCPR1 size: %d", + get_nanomips_reg_size (abiflags_in.cpr1_size)); + printf ("\nCPR2 size: %d", + get_nanomips_reg_size (abiflags_in.cpr2_size)); + fputs ("\nFP ABI: ", stdout); + print_nanomips_fp_abi_value (abiflags_in.fp_abi); + fputs ("ISA Extension: ", stdout); + print_nanomips_isa_ext (abiflags_in.isa_ext); + fputs ("\nASEs:", stdout); + print_nanomips_ases (abiflags_in.ases); + printf ("\nFLAGS 1: %8.8lx", abiflags_in.flags1); + printf ("\nFLAGS 2: %8.8lx", abiflags_in.flags2); + fputc ('\n', stdout); + free (abiflags_ext); + } + } + } + + if (!get_dynamic_section (filedata)) + return false; + + for (entry = filedata->dynamic_section; + entry < filedata->dynamic_section + filedata->dynamic_nent && entry->d_tag != DT_NULL; + ++entry) + switch (entry->d_tag) + { + case DT_PLTGOT: + pltgot = entry->d_un.d_ptr; + break; + default: + break; + } + + if (options_offset != 0) + { + Elf_External_Options * eopt; + Elf_Internal_Options * iopt; + Elf_Internal_Options * option; + size_t offset; + int cnt; + sect = filedata->section_headers; + + /* Find the section header so that we get the size. */ + sect = find_section_by_type (filedata, SHT_MIPS_OPTIONS); + if (sect == NULL) + { + error (_("No MIPS_OPTIONS header found\n")); + return 0; + } + + eopt = (Elf_External_Options *) get_data (NULL, filedata, options_offset, 1, + sect->sh_size, _("options")); + if (eopt) + { + iopt = (Elf_Internal_Options *) + cmalloc ((sect->sh_size / sizeof (eopt)), sizeof (* iopt)); + if (iopt == NULL) + { + error (_("Out of memory allocatinf space for MIPS options\n")); + return 0; + } + + offset = cnt = 0; + option = iopt; + + while (offset < sect->sh_size) + { + Elf_External_Options * eoption; + eoption = (Elf_External_Options *) ((char *) eopt + offset); + + option->kind = BYTE_GET (eoption->kind); + option->size = BYTE_GET (eoption->size); + option->section = BYTE_GET (eoption->section); + option->info = BYTE_GET (eoption->info); + + offset += option->size; + + ++option; + ++cnt; + } + + printf (_("\nSection '%s' contains %d entries:\n"), + printable_section_name (filedata, sect), cnt); + + option = iopt; + + while (cnt-- > 0) + { + size_t len; + + switch (option->kind) + { + case ODK_NULL: + /* This shouldn't happen. */ + printf (" NULL %d %x", option->section, option->info); + break; + case ODK_EXCEPTIONS: + fputs (" EXCEPTIONS fpe_min(", stdout); + process_mips_fpe_exception (option->info & OEX_FPU_MIN); + fputs (") fpe_max(", stdout); + process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8); + fputs (")", stdout); + + if (option->info & OEX_PAGE0) + fputs (" PAGE0", stdout); + if (option->info & OEX_SMM) + fputs (" SMM", stdout); + if (option->info & OEX_FPDBUG) + fputs (" FPDBUG", stdout); + if (option->info & OEX_DISMISS) + fputs (" DISMISS", stdout); + break; + case ODK_PAD: + fputs (" PAD ", stdout); + if (option->info & OPAD_PREFIX) + fputs (" PREFIX", stdout); + if (option->info & OPAD_POSTFIX) + fputs (" POSTFIX", stdout); + if (option->info & OPAD_SYMBOL) + fputs (" SYMBOL", stdout); + break; + case ODK_HWPATCH: + fputs (" HWPATCH ", stdout); + if (option->info & OHW_R4KEOP) + fputs (" R4KEOP", stdout); + if (option->info & OHW_R8KPFETCH) + fputs (" R8KPFETCH", stdout); + if (option->info & OHW_R5KEOP) + fputs (" R5KEOP", stdout); + if (option->info & OHW_R5KCVTL) + fputs (" R5KCVTL", stdout); + break; + case ODK_FILL: + fputs (" FILL ", stdout); + /* XXX Print content of info word? */ + break; + case ODK_TAGS: + fputs (" TAGS ", stdout); + /* XXX Print content of info word? */ + break; + case ODK_HWAND: + fputs (" HWAND ", stdout); + if (option->info & OHWA0_R4KEOP_CHECKED) + fputs (" R4KEOP_CHECKED", stdout); + if (option->info & OHWA0_R4KEOP_CLEAN) + fputs (" R4KEOP_CLEAN", stdout); + break; + case ODK_HWOR: + fputs (" HWOR ", stdout); + if (option->info & OHWA0_R4KEOP_CHECKED) + fputs (" R4KEOP_CHECKED", stdout); + if (option->info & OHWA0_R4KEOP_CLEAN) + fputs (" R4KEOP_CLEAN", stdout); + break; + case ODK_GP_GROUP: + printf (" GP_GROUP %#06x self-contained %#06x", + option->info & OGP_GROUP, + (option->info & OGP_SELF) >> 16); + break; + case ODK_IDENT: + printf (" IDENT %#06x self-contained %#06x", + option->info & OGP_GROUP, + (option->info & OGP_SELF) >> 16); + break; + default: + /* This shouldn't happen. */ + printf (" %3d ??? %d %x", + option->kind, option->section, option->info); + break; + } + len = sizeof (* eopt); + while (len < option->size) + if (((char *) option)[len] >= ' ' + && ((char *) option)[len] < 0x7f) + printf ("%c", ((char *) option)[len++]); + else + printf ("\\%03o", ((char *) option)[len++]); + + fputs ("\n", stdout); + ++option; + } + free (eopt); + } + } + + if (pltgot != 0) + { + bfd_vma ent, end; + size_t i, offset; + unsigned char * data; + int addr_size; + + ent = pltgot; + addr_size = (is_32bit_elf ? 4 : 8); + + if (symtabno < gotsym) + { + error (_("The GOT symbol offset (%lu) is greater than the symbol table size (%lu)\n"), + (long) gotsym, (long) symtabno); + return 0; + } + + end = pltgot + (symtabno - gotsym) * addr_size; + offset = offset_from_vma (filedata, pltgot, end - pltgot); + data = (unsigned char *) get_data (NULL, filedata, offset, + end - pltgot, 1, + _("Global Offset Table data")); + if (data == NULL) + return 0; + + printf (_(" Canonical gp value: ")); + print_vma (pltgot + 0x7ff0, LONG_HEX); + printf ("\n\n"); + + printf (_(" Reserved entries:\n")); + printf (_(" %*s %10s %*s Purpose\n"), + addr_size * 2, _("Address"), _("Access"), + addr_size * 2, _("Initial")); + ent = print_mips_got_entry (data, pltgot, ent, data + (end - pltgot)); + printf (_(" Lazy resolver\n")); + if (data + && (byte_get (data + ent - pltgot, addr_size) + >> (addr_size * 8 - 1)) != 0) + { + ent = print_mips_got_entry (data, pltgot, ent, data + (end - pltgot)); + printf (_(" Module pointer (GNU extension)\n")); + } + printf ("\n\n"); + printf (_(" Entries:\n")); + printf (" %*s %10s %*s %*s %-7s %3s %s\n", + addr_size * 2, _("Address"), + _("Access"), + addr_size * 2, _("Initial"), + addr_size * 2, _("Sym.Val."), + _("Type"), + /* Note for translators: "Ndx" = abbreviated form of "Index". */ + _("Ndx"), _("Name")); + + for (i = gotsym; i < symtabno; i++) + { + ent = print_mips_got_entry (data, pltgot, ent, data + (end - pltgot)); + printf (" "); + printf ("\n"); + } + + if (data) + free (data); + } + + return 1; +} + static bool process_nds32_specific (Filedata * filedata) { @@ -22264,6 +22762,8 @@ process_arch_specific (Filedata * filedata) return process_attributes (filedata, "c6xabi", SHT_C6000_ATTRIBUTES, display_tic6x_attribute, display_generic_attribute); + case EM_NANOMIPS: + return process_nanomips_specific (filedata); case EM_CSKY: return process_attributes (filedata, "csky", SHT_CSKY_ATTRIBUTES, 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/elf/common.h b/include/elf/common.h index 6f64f05890c..253200fa652 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -346,7 +346,7 @@ #define EM_CEVA_X2 246 /* CEVA X2 Processor Family */ #define EM_BPF 247 /* Linux BPF – in-kernel virtual machine. */ #define EM_GRAPHCORE_IPU 248 /* Graphcore Intelligent Processing Unit */ -#define EM_IMG1 249 /* Imagination Technologies */ +#define EM_NANOMIPS 249 /* nanoMIPS */ #define EM_NFP 250 /* Netronome Flow Processor. */ #define EM_VE 251 /* NEC Vector Engine */ #define EM_CSKY 252 /* C-SKY processor family. */ diff --git a/include/elf/mips-common.h b/include/elf/mips-common.h new file mode 100644 index 00000000000..1d941fa9f2d --- /dev/null +++ b/include/elf/mips-common.h @@ -0,0 +1,41 @@ +/* MIPS ELF support for BFD. + Copyright (C) 2018-2022 Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program 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 of the License, or + (at your option) any later version. + + This program 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. */ + +/* This file holds definitions common to the MIPS and nanoMIPS ELF ABIs. */ + +#ifndef _ELF_MIPS_COMMON_H +#define _ELF_MIPS_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Values for the xxx_size bytes of an ABI flags structure. */ + +#define AFL_REG_NONE 0x00 /* No registers. */ +#define AFL_REG_32 0x01 /* 32-bit registers. */ +#define AFL_REG_64 0x02 /* 64-bit registers. */ +#define AFL_REG_128 0x03 /* 128-bit registers. */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ELF_MIPS_COMMON_H */ diff --git a/include/elf/nanomips.h b/include/elf/nanomips.h new file mode 100644 index 00000000000..82d081c04f8 --- /dev/null +++ b/include/elf/nanomips.h @@ -0,0 +1,260 @@ +/* nanoMIPS ELF support for BFD. + Copyright (C) 2018-2022 Free Software Foundation, Inc. + + Written by Faraz Shahbazker + + This file is part of BFD, the Binary File Descriptor library. + + This program 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 of the License, or + (at your option) any later version. + + This program 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. */ + +/* This file holds definitions specific to the nanoMIPS ELF ABI. */ + +#ifndef _ELF_NANOMIPS_H +#define _ELF_NANOMIPS_H + +#include "elf/reloc-macros.h" +#include "elf/mips.h" +#include "elf/mips-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +START_RELOC_NUMBERS (elf_nanomips_reloc_type) + RELOC_NUMBER (R_NANOMIPS_NONE, 0) + RELOC_NUMBER (R_NANOMIPS_32, 1) + RELOC_NUMBER (R_NANOMIPS_64, 2) + RELOC_NUMBER (R_NANOMIPS_NEG, 3) + RELOC_NUMBER (R_NANOMIPS_ASHIFTR_1, 4) + RELOC_NUMBER (R_NANOMIPS_UNSIGNED_8, 5) + RELOC_NUMBER (R_NANOMIPS_SIGNED_8, 6) + RELOC_NUMBER (R_NANOMIPS_UNSIGNED_16, 7) + RELOC_NUMBER (R_NANOMIPS_SIGNED_16, 8) + RELOC_NUMBER (R_NANOMIPS_RELATIVE, 9) + RELOC_NUMBER (R_NANOMIPS_GLOBAL, 10) + RELOC_NUMBER (R_NANOMIPS_JUMP_SLOT, 11) + RELOC_NUMBER (R_NANOMIPS_IRELATIVE, 12) + + RELOC_NUMBER (R_NANOMIPS_PC25_S1, 13) + RELOC_NUMBER (R_NANOMIPS_PC21_S1, 14) + RELOC_NUMBER (R_NANOMIPS_PC14_S1, 15) + RELOC_NUMBER (R_NANOMIPS_PC11_S1, 16) + RELOC_NUMBER (R_NANOMIPS_PC10_S1, 17) + RELOC_NUMBER (R_NANOMIPS_PC7_S1, 18) + RELOC_NUMBER (R_NANOMIPS_PC4_S1, 19) + + RELOC_NUMBER (R_NANOMIPS_GPREL19_S2, 20) + RELOC_NUMBER (R_NANOMIPS_GPREL18_S3, 21) + RELOC_NUMBER (R_NANOMIPS_GPREL18, 22) + RELOC_NUMBER (R_NANOMIPS_GPREL17_S1, 23) + RELOC_NUMBER (R_NANOMIPS_GPREL16_S2, 24) + RELOC_NUMBER (R_NANOMIPS_GPREL7_S2, 25) + RELOC_NUMBER (R_NANOMIPS_GPREL_HI20, 26) + RELOC_NUMBER (R_NANOMIPS_PCHI20, 27) + + RELOC_NUMBER (R_NANOMIPS_HI20, 28) + RELOC_NUMBER (R_NANOMIPS_LO12, 29) + RELOC_NUMBER (R_NANOMIPS_GPREL_I32, 30) + RELOC_NUMBER (R_NANOMIPS_PC_I32, 31) + RELOC_NUMBER (R_NANOMIPS_I32, 32) + RELOC_NUMBER (R_NANOMIPS_GOT_DISP, 33) + RELOC_NUMBER (R_NANOMIPS_GOTPC_I32, 34) + RELOC_NUMBER (R_NANOMIPS_GOTPC_HI20, 35) + RELOC_NUMBER (R_NANOMIPS_GOT_LO12, 36) + RELOC_NUMBER (R_NANOMIPS_GOT_CALL, 37) + RELOC_NUMBER (R_NANOMIPS_GOT_PAGE, 38) + RELOC_NUMBER (R_NANOMIPS_GOT_OFST, 39) + RELOC_NUMBER (R_NANOMIPS_LO4_S2, 40) + /* Reserved for 64-bit ABI. */ + RELOC_NUMBER (R_NANOMIPS_RESERVED1, 41) + RELOC_NUMBER (R_NANOMIPS_GPREL_LO12, 42) + RELOC_NUMBER (R_NANOMIPS_SCN_DISP, 43) + RELOC_NUMBER (R_NANOMIPS_COPY, 44) + + RELOC_NUMBER (R_NANOMIPS_ALIGN, 64) + RELOC_NUMBER (R_NANOMIPS_FILL, 65) + RELOC_NUMBER (R_NANOMIPS_MAX, 66) + RELOC_NUMBER (R_NANOMIPS_INSN32, 67) + RELOC_NUMBER (R_NANOMIPS_FIXED, 68) + RELOC_NUMBER (R_NANOMIPS_NORELAX, 69) + RELOC_NUMBER (R_NANOMIPS_RELAX, 70) + RELOC_NUMBER (R_NANOMIPS_SAVERESTORE, 71) + RELOC_NUMBER (R_NANOMIPS_INSN16, 72) + RELOC_NUMBER (R_NANOMIPS_JALR32, 73) + RELOC_NUMBER (R_NANOMIPS_JALR16, 74) + RELOC_NUMBER (R_NANOMIPS_JUMPTABLE_LOAD, 75) + RELOC_NUMBER (R_NANOMIPS_FRAME_REG, 76) + + /* TLS relocations. */ + RELOC_NUMBER (R_NANOMIPS_TLS_DTPMOD, 80) + RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL, 81) + RELOC_NUMBER (R_NANOMIPS_TLS_TPREL, 82) + RELOC_NUMBER (R_NANOMIPS_TLS_GD, 83) + RELOC_NUMBER (R_NANOMIPS_TLS_GD_I32, 84) + RELOC_NUMBER (R_NANOMIPS_TLS_LD, 85) + RELOC_NUMBER (R_NANOMIPS_TLS_LD_I32, 86) + RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL12, 87) + RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL16, 88) + RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL_I32, 89) + RELOC_NUMBER (R_NANOMIPS_TLS_GOTTPREL, 90) + RELOC_NUMBER (R_NANOMIPS_TLS_GOTTPREL_PC_I32, 91) + RELOC_NUMBER (R_NANOMIPS_TLS_TPREL12, 92) + RELOC_NUMBER (R_NANOMIPS_TLS_TPREL16, 93) + RELOC_NUMBER (R_NANOMIPS_TLS_TPREL_I32, 94) + + FAKE_RELOC (R_NANOMIPS_max, 94) + /* May be used for compact unwind tables in the future. */ + RELOC_NUMBER (R_NANOMIPS_PC32, 248) + RELOC_NUMBER (R_NANOMIPS_EH, 249) + /* These are GNU extensions to enable C++ vtable garbage collection. */ + RELOC_NUMBER (R_NANOMIPS_GNU_VTINHERIT, 253) + RELOC_NUMBER (R_NANOMIPS_GNU_VTENTRY, 254) +END_RELOC_NUMBERS (R_NANOMIPS_maxext) + +/* Processor specific flags for the ELF header e_flags field. */ + +/* File may be relaxed by the linker. */ +#define EF_NANOMIPS_LINKRELAX 0x00000001 + +/* File contains position independent code. */ +#define EF_NANOMIPS_PIC 0x00000002 + +/* Indicates code compiled for a 64-bit machine in 32-bit mode + (regs are 32-bits wide). */ +#define EF_NANOMIPS_32BITMODE 0x00000004 + +/* File contains position independent code. */ +#define EF_NANOMIPS_PID 0x00000008 + +/* File contains pure PC-relative code. */ +#define EF_NANOMIPS_PCREL 0x00000010 + +/* Four bit nanoMIPS architecture field. */ +#define EF_NANOMIPS_ARCH 0xf0000000 + +/* -march=32r6[s] code. */ +#define E_NANOMIPS_ARCH_32R6 0x00000000 + +/* -march=64r6 code. */ +#define E_NANOMIPS_ARCH_64R6 0x10000000 + +/* The ABI of the file. */ +#define EF_NANOMIPS_ABI 0x0000F000 + +/* nanoMIPS ABI in 32 bit mode. */ +#define E_NANOMIPS_ABI_P32 0x00001000 + +/* nanoMIPS ABI in 64 bit mode. */ +#define E_NANOMIPS_ABI_P64 0x00002000 + +/* Machine variant if we know it. This field was invented at Cygnus + for MIPS. It may be used similarly for nanoMIPS. */ + +#define EF_NANOMIPS_MACH 0x00FF0000 + + +/* Processor specific section types. */ + +/* ABI related flags section. */ +#define SHT_NANOMIPS_ABIFLAGS 0x70000000 + + +/* Processor specific program header types. */ + +/* Records ABI related flags. */ +#define PT_NANOMIPS_ABIFLAGS 0x70000000 + + + +/* Object attribute tags. */ +enum +{ + /* 0-3 are generic. */ + + /* Floating-point ABI used by this object file. */ + Tag_GNU_NANOMIPS_ABI_FP = 4, + + /* MSA ABI used by this object file. */ + Tag_GNU_NANOMIPS_ABI_MSA = 8, +}; + +/* Object attribute values. */ +enum +{ + /* Values defined for Tag_GNU_NANOMIPS_ABI_FP. */ + + /* Not tagged or not using any ABIs affected by the differences. */ + Val_GNU_NANOMIPS_ABI_FP_ANY = 0, + + /* Using hard-float -mdouble-float. */ + Val_GNU_NANOMIPS_ABI_FP_DOUBLE = 1, + + /* Using hard-float -msingle-float. */ + Val_GNU_NANOMIPS_ABI_FP_SINGLE = 2, + + /* Using soft-float. */ + Val_GNU_NANOMIPS_ABI_FP_SOFT = 3, + + /* Not tagged or not using any ABIs affected by the differences. */ + Val_GNU_NANOMIPS_ABI_MSA_ANY = 0, + + /* Using 128-bit MSA. */ + Val_GNU_NANOMIPS_ABI_MSA_128 = 1, +}; + +/* Masks for the ases word of an ABI flags structure. + + Unfortunate decisions in early development transitioning from MIPS + to nanoMIPS, left this horifically fragmented. Bits marked as + UNUSED may be cannibalized for future ASEs; bits marked as RESERVED + are intended to remain blocked. If MIPS history is anything to go + by, nanoMIPS will eventually spawn enough ASEs to fill up the gaps! +*/ + +#define NANOMIPS_ASE_TLB 0x00000001 /* TLB control ASE. */ +#define NANOMIPS_ASE_UNUSED1 0x00000002 /* was DSP R2 ASE. */ +#define NANOMIPS_ASE_EVA 0x00000004 /* Enhanced VA Scheme. */ +#define NANOMIPS_ASE_MCU 0x00000008 /* MCU (MicroController) ASE. */ +#define NANOMIPS_ASE_UNUSED2 0x00000010 /* was MDMX ASE. */ +#define NANOMIPS_ASE_UNUSED3 0x00000020 /* was MIPS-3D ASE. */ +#define NANOMIPS_ASE_MT 0x00000040 /* MT ASE. */ +#define NANOMIPS_ASE_UNUSED4 0x00000080 /* was SmartMIPS ASE. */ +#define NANOMIPS_ASE_VIRT 0x00000100 /* VZ ASE. */ +#define NANOMIPS_ASE_MSA 0x00000200 /* MSA ASE. */ +#define NANOMIPS_ASE_RESERVED1 0x00000400 /* was MIPS16 ASE. */ +#define NANOMIPS_ASE_RESERVED2 0x00000800 /* was MICROMIPS ASE. */ +#define NANOMIPS_ASE_UNUSED6 0x00001000 /* was XPA. */ +#define NANOMIPS_ASE_DSPR3 0x00002000 /* DSP R3 ASE. */ +#define NANOMIPS_ASE_UNUSED5 0x00004000 /* was MIPS16 E2 Extension. */ +#define NANOMIPS_ASE_CRC 0x00008000 /* CRC extension. */ +#define NANOMIPS_ASE_CRYPTO 0x00010000 /* Cryptography extension. */ +#define NANOMIPS_ASE_GINV 0x00020000 /* GINV ASE. */ +#define NANOMIPS_ASE_xNMS 0x00040000 /* not nanoMIPS Subset. */ +#define NANOMIPS_ASE_MASK 0x0007af4d /* All valid ASEs. */ + +/* nanoMIPS ELF flags routines. */ +extern Elf_Internal_ABIFlags_v0 * bfd_nanomips_elf_get_abiflags (bfd *); + +extern void bfd_nanomips_elf_swap_abiflags_v0_in + (bfd *, const Elf_External_ABIFlags_v0 *, Elf_Internal_ABIFlags_v0 *); +extern void bfd_nanomips_elf_swap_abiflags_v0_out + (bfd *, const Elf_Internal_ABIFlags_v0 *, Elf_External_ABIFlags_v0 *); + +#ifdef __cplusplus +} +#endif + +#endif /* _ELF_NANOMIPS_H */ 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..7f206199c96 --- /dev/null +++ b/opcodes/nanomips-dis.c @@ -0,0 +1,1470 @@ +/* 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 + + +/* FIXME: These should be shared with gdb somehow. */ + +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; + } + + /* FIXME: Should probably use a hash table on the major opcode here. */ + 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])));