From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR03-DBA-obe.outbound.protection.outlook.com (mail-dbaeur03on2083.outbound.protection.outlook.com [40.107.104.83]) by sourceware.org (Postfix) with ESMTPS id 297593850871 for ; Fri, 10 Mar 2023 10:21:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 297593850871 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.com ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=WgVgiiSnWPLYIOOs5VR3OZJUjA0xfnntKV112g68CsQPfXuT6aurmmsiCrxb8okj+FeCjoTpoqw9C0aPH0eWukqy1o2G/cDh5fzs0Tu8P9eEHj1DXruT6S2CGF1S22ATayMCXjAmoKgomD86mSVPAAclwDeqxjbchYZPvya0QRvPhgKN5KGzfmP9ZLLSo0Lc1b67gD/dk5ES7qdGiZC3Be/r1MdH0ZDBB0dAU/VrDocpzVUg+5Kq//DmhKODozCHEd1b6AZqnO06ZMVg/qQXEST6XBZqKOJcuEMXtHw10FYEDUzgNLv07ev/9Zcor4YAso8T+phHQedtobXwgDLncQ== 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=u1nFIsGTKMsR80NROZ9e3I7Ny5JmIHy+otziwPd6ERw=; b=eeG2bZTbPT+QeNcVmlhb83xVqbM8QNZxL6v6S3y+hgWjJdIDMO4rPr8XIjF8yBEMK4l+OrXhIavwTjo+8vvnGs+Defhsh/GbDzbNoC5vyG36ayovJ8d+7RQVjnupARrJQACYc441MSxJ04ZsjZJ5g+VnVH4VcUxWpme/vVhTcUrzxHUpqfOJBJ7eP4LFp+BEyTarlyotX92BOF5NNeRqvCdqi6u+xKQ8orCQbBobXkTHNvbX/NWkGv51MdBM940KDDA2MjSznjqqAOnI40oihBZFEwO8DPl9CIP+NbVXmhrgGoV3uS4CpmdfcbkPrjtoBIojRRYqN6K0idbVJ6E2MQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=suse.com; dmarc=pass action=none header.from=suse.com; dkim=pass header.d=suse.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=u1nFIsGTKMsR80NROZ9e3I7Ny5JmIHy+otziwPd6ERw=; b=Cd/ENPCyxnVHvZsiM6wURCfB1kp1XhhPMzHy0AbrhY1mBMEoGz4VwDSiC16nok41qD9SwveN8VxN55XFayYUG62OVDLq3meCb+7r/lkVJzKP7kXfiVj7YW9PupRjthXDCa/6RMLMBRtRoSCZygVRsrRXC+PPFde8gewd8Ek74lNoK/hIQUFFKOqeOynYcKZl32iShVKSDyCn3VGLzGyUgwO0jZtZlRMVfmmGHG8Al3A/oRBEDEbUhy9Lm6lxp/C1lvzskxQ+QsKUMQ9n7YeUTNakcF8SJsEl33LvJRkwgJqvJFN80xZndZzA0XijceYPmhu0m5weBTMUQOUsI+YAZg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=suse.com; Received: from VE1PR04MB6560.eurprd04.prod.outlook.com (2603:10a6:803:122::25) by AM9PR04MB8339.eurprd04.prod.outlook.com (2603:10a6:20b:3e6::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6178.19; Fri, 10 Mar 2023 10:21:14 +0000 Received: from VE1PR04MB6560.eurprd04.prod.outlook.com ([fe80::154e:166d:ec25:531b]) by VE1PR04MB6560.eurprd04.prod.outlook.com ([fe80::154e:166d:ec25:531b%5]) with mapi id 15.20.6178.019; Fri, 10 Mar 2023 10:21:14 +0000 Message-ID: Date: Fri, 10 Mar 2023 11:21:11 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.8.0 Subject: [PATCH v2 04/14] x86: re-work build_modrm_byte()'s register assignment Content-Language: en-US To: Binutils Cc: "H.J. Lu" , "Jiang, Haochen" References: From: Jan Beulich In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-ClientProxiedBy: FR3P281CA0126.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:94::16) To VE1PR04MB6560.eurprd04.prod.outlook.com (2603:10a6:803:122::25) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VE1PR04MB6560:EE_|AM9PR04MB8339:EE_ X-MS-Office365-Filtering-Correlation-Id: b14dde7a-70aa-4d59-8f5e-08db21512d57 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: PAvst0OJx1nYlMvInlbZZOtZWL9z+BPsoS0CddSJynQc1o0b7pDcFeOxjKvZJ0CJzgKyyC5b8xp7x9QZvBqQj3NVD1wW3uh0fbKK0WKAAmiBu+prQuL06Qcnfvk/CQCHy2BF3+Np7R0v303NkIus+FWYuVgKPN6obEisXDaGJEzqQS2InkjJN+7qsUi3GsQy3e12KJV2Jh43F851ogVlZMi5U/j+Hz98wcLwDEKFbplPAdJNqsIUVe/R9raq86YqqueOqm2RaDju52ErbtB/SFt+7wzzEASxblyP1Dck5tb9C9UMT/zYghSXAWVkYIj/qnBD00ZWMe6BADRC2fwQqQtj2PTgXK57NPBO7wvkkE/GEtHrEDgf9uEEFD1agQZy649OkxFh+m2WUrCmF2tU+xUFRBM2FkT9o6cE8b5RLf17CAwW1z35mO9GfztVXQbboW/k1bP/2DPdUTHgVWda26xE03eBLacfbTR4f1a06y9BgVPE2guFkO0jIvREBNl4kPCleCGRMQxxwYhuIGdMetdXG0Sd201dUsyaLLQAGiWGf0PI6ocfJP8PbhfcxksdqT2OkdJr6IQ8XjJ5mFtyOzue38hIf7lGI0ki1MO6UMmclUGbu0ZCh6hatOmLgKc40Wq1FwsCeyaCXBu6VDwe5re/vUf7975a1OaJv+pZmFvhED+TSAZHePydpWqNXnmzG9DyYFapdZZKjJIoNMUWYeyKPV3CarvI+X1D5lIUl2U= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VE1PR04MB6560.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230025)(39860400002)(396003)(136003)(346002)(366004)(376002)(451199018)(38100700002)(36756003)(54906003)(6916009)(478600001)(6486002)(316002)(5660300002)(66556008)(8936002)(2906002)(30864003)(66476007)(8676002)(41300700001)(66946007)(4326008)(26005)(83380400001)(31696002)(86362001)(6666004)(6506007)(186003)(2616005)(6512007)(31686004)(43740500002)(45980500001);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?VWsxV1NBMnp1dHNJZ21FSHk2ajg4L0NLNER5S1kzcVFQMVMrM1JXWlNPVDFC?= =?utf-8?B?UmVONysrUU5NYTJUd3JlcGFnYTdXQ1pYSnBHK20xUjFPdXhzTTNVbVpid04z?= =?utf-8?B?UEVueDBCQWdvU2RTL0hwVW9CQ2hTbXFRRzFOeElsR2Nia1NKaFNrTUhNc1JC?= =?utf-8?B?RXlzNFlNWko3cG9SbE5jaXRVdzlFWHpOY3U0VXpod2hqMkZCeXU4U29uL0ll?= =?utf-8?B?WmwwOUZyK1Zrd1JlZzJOVkEvek40YzlQRkRjYWlKblFFMnQ2U0ppT0VrZGJu?= =?utf-8?B?c1Q1NitpK2hQT0RvTjVLK1NBNEtzYWk2Vmk3WktoaDJUelc2cW9MRjVwdE1r?= =?utf-8?B?N1lReFBOWUNpTk9DUlovelVUdm55anJXRXk4amN5bXJDT01iS25sRzRSb3ZW?= =?utf-8?B?YjJoNEU0UVZCcVJnWWNqb3lnOWw0bSt3UTduT002T1RXT3RhZnFsKzFXSktQ?= =?utf-8?B?YkxUUTVzdDRpM21zeGJwRnJkam5GLzZmNk4rdWFrMjc0YWgrTjc0cjg5SURh?= =?utf-8?B?VnZzT0VFN2VPQ0NNdEFkcVNGMC9wVUpEaW85VmpwYmxQclF6elpWZmxVTS9H?= =?utf-8?B?WDVOR2hxb0dBS2l4NytQNStiY2dzUW5CbUdmd3I5ZmNWRHQycjIyVGN3V1I5?= =?utf-8?B?czBRWC8vbnIyR3MyTlNMSnozaDRQRmpVcU9XRjJqWUpDc3hiNStHMkVNM2JH?= =?utf-8?B?VjAwdkNSNzRVWndXYUlkYTZHWG0vTlQwY2EvcFROdmpsaDFESDhMaHh0MmtR?= =?utf-8?B?ajJvWEw0R1htK2Z3SW5sc2NCUHluVVZreXczZnNDelVvYlNxRXc1WkkrWFJw?= =?utf-8?B?TFdEMGdOZ3d0MzBoaEwreStLd2hqT2hVQzU1YlNlVUhUbHd3c3l3dTZaYXRw?= =?utf-8?B?ZkhyVVF2ZTFFS25WekxjejRaN2Q1a1NGZ3lCekd2QW1YOWI5VVowamxZNmhl?= =?utf-8?B?VEFyQjVVS1JsUE9JV1NQR1J6cWtjMGNaVG56cW1XWnBTS1AvQWkyWVlpM2xv?= =?utf-8?B?WmdTNWRJR1MvaDR1MVRKYzdSMGswQ25ObFR4NmZRVDROL1VFZk9ydWErVlNK?= =?utf-8?B?Um8rN3Z4VWpxaS83eTB3OTlnQ1crNyswTnpKejhNTVoyUGFCem81TXJYNWJ5?= =?utf-8?B?YnVNZTZkMXFPRWNuT1J4UzJMakV6ZzZ3VnJoMEszc2FCOTJmQi9ubVJ5ZE5s?= =?utf-8?B?ZWxiWmIrUVF5emsyb1FpVGFDTmkxUkJ0NnhzUUZHd3I2dG9zSzBuWllWSy8y?= =?utf-8?B?QTlSbDAvZHllVzJEZ0VuVWF6cWtyNFFoT1g5Rmk4bU5rMXdDbDJpM2RhY0xu?= =?utf-8?B?ZXJzTG1KbVAyZXM2SXlJaC9LNXFCRk1pZlJmelpuVHp5WHB0Z0RkcDhrZFpG?= =?utf-8?B?SERncjBnQVoxTzd2cTNTWCttbHU2WWhKUzlRWXhwYThSU1JJQm1xdHhVK1Fv?= =?utf-8?B?QmZxTmdGUnZhaUV2SGhHdFc4bmtYQlc3Z2FjNW1iUGpDS1hCWkU3bHNGdllr?= =?utf-8?B?dmxrOUxRRkZ3RnNQclhLaDFHZVgvckxiOWhXWFFRNU9kYzUzNjd1RkhkbzBB?= =?utf-8?B?Z0xuN1BwUmU1SXE5OWJTTDJWZVNwRjlNNXh4UW54NXRjTkdZbGlLQmxOWUV1?= =?utf-8?B?TkpoZjdyUDRBM0pzbHA4UnEzZHp0b1JBbTRCS1pGejk3MVl0NERZdHdjQmVk?= =?utf-8?B?TzJzS3I0TGJOVUxZOVR0cFhwRHNJWGppOWRWK29ENmJpOXJ3akp3TjkxRFlp?= =?utf-8?B?dFdZU3hYazB3anB2S2Q5cnFZR3NRTWdNdnlEbGhReS9ZQzN6TnNTZk9WMTZy?= =?utf-8?B?L0ZNc1lBM1hJQTBIVEN5QjBtckNOZCtUeXE1SXNKUG5EcW1XQ0MxeVNNYnBD?= =?utf-8?B?aVRiZ1ZwRWE2KzB5enpZT0gvWTlZdlpCMGdCWGxpOTZabUpNN2tmeUhwaFlC?= =?utf-8?B?Nk9zTFNWa3o3Qmhxb1NOVGgwZzNhUTRpRUkxWDY2SWo3bWJCWEN4QmVHWlNq?= =?utf-8?B?UkptaGk3SlkwSFYyWGRCSFNIM0tXMkdJSmtFN0U4S1FjcG11UjVHSmpxQjJ4?= =?utf-8?B?WWhreTlUU1V4K0RHSjVscXJwZytPeTZOYkQ2K2dkVzZCdFRzbElvL1E1SVJm?= =?utf-8?Q?zOvfmO+GlOZOD8svt2JbPbU/T?= X-OriginatorOrg: suse.com X-MS-Exchange-CrossTenant-Network-Message-Id: b14dde7a-70aa-4d59-8f5e-08db21512d57 X-MS-Exchange-CrossTenant-AuthSource: VE1PR04MB6560.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 Mar 2023 10:21:14.1243 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: f7a17af6-1c5c-4a36-aa8b-f5be247aa4ba X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: +pbQZtonA15SaD05Uh9MIR06RLA7hoD3d5hgCyCJMl0VaNsGDYN3WazlZdCYzXuQaNclqvxx0vSJc7qRcXDUnA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM9PR04MB8339 X-Spam-Status: No, score=-3028.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: The function has accumulated a number of special cases for no real reason. Some were necessary because insn attributes (SwapSources in particular) weren't suitably utilized instead. Note that the addition of SwapSources actually increases consistency among the templates: Like others which already have the attribute, these are all insns where the VEX.VVVV-encoded register comes first (or last when looking at the SDM). Note that the vexvvvv attribute now has merely boolean meaning anymore, in line with the SDM long having dropped the NDS/NDD/DDS concept of identifying encoding variants. The fallout will be taken care of subsequently, though, to not further clutter the change here. As to the TILEZERO special case: If more instructions like this appeared, a new attribute would likely be the way to go. But as long as it's only a single insn, going from the mnemonic is cheaper. --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -8056,6 +8056,22 @@ process_operands (void) else if (i.tm.opcode_modifier.immext) process_immext (); + /* TILEZERO is unusual in that it has a single operand encoded in ModR/M.reg, + not ModR/M.rm. To avoid special casing this in build_modrm_byte(), fake a + new destination operand here, while converting the source one to register + number 0. */ + if (i.tm.mnem_off == MN_tilezero) + { + i.op[1].regs = i.op[0].regs; + i.op[0].regs -= i.op[0].regs->reg_num; + i.types[1] = i.types[0]; + i.tm.operand_types[1] = i.tm.operand_types[0]; + i.flags[1] = i.flags[0]; + i.operands++; + i.reg_operands++; + i.tm.operands++; + } + if (i.tm.opcode_modifier.sse2avx && i.tm.opcode_modifier.vexvvvv) { static const i386_operand_type regxmm = { @@ -8287,17 +8303,27 @@ static const reg_entry * build_modrm_byte (void) { const reg_entry *default_seg = NULL; - unsigned int source, dest; - bool vex_3_sources = (i.reg_operands + i.mem_operands == 4); + unsigned int source = i.imm_operands - i.tm.opcode_modifier.immext + /* Compensate for kludge in md_assemble(). */ + + i.tm.operand_types[0].bitfield.imm1; + unsigned int dest = i.operands - 1 - i.tm.opcode_modifier.immext; + unsigned int v, op, reg_slot = ~0; + + /* Accumulator (in particular %st), shift count (%cl), and alike need + to be skipped just like immediate operands do. */ + if (i.tm.operand_types[source].bitfield.instance) + ++source; + while (i.tm.operand_types[dest].bitfield.instance) + --dest; + + for (op = source; op < i.operands; ++op) + if (i.tm.operand_types[op].bitfield.baseindex) + break; - if (vex_3_sources) + if (i.reg_operands + i.mem_operands + (i.tm.extension_opcode != None) == 4) { - unsigned int nds, reg_slot; expressionS *exp; - dest = i.operands - 1; - nds = dest - 1; - /* There are 2 kinds of instructions: 1. 5 operands: 4 register operands or 3 register operands plus 1 memory operand plus one Imm4 operand, VexXDS, and @@ -8309,18 +8335,12 @@ build_modrm_byte (void) && i.tm.opcode_modifier.vexw && i.tm.operand_types[dest].bitfield.class == RegSIMD); - /* If VexW1 is set, the first non-immediate operand is the source and - the second non-immediate one is encoded in the immediate operand. */ - if (i.tm.opcode_modifier.vexw == VEXW1) - { - source = i.imm_operands; - reg_slot = i.imm_operands + 1; - } + /* Of the first two non-immediate operands the one with the template + not allowing for a memory one is encoded in the immediate operand. */ + if (source == op) + reg_slot = source + 1; else - { - source = i.imm_operands + 1; - reg_slot = i.imm_operands; - } + reg_slot = source++; if (i.imm_operands == 0) { @@ -8350,159 +8370,42 @@ build_modrm_byte (void) |= register_number (i.op[reg_slot].regs) << 4; gas_assert ((i.op[reg_slot].regs->reg_flags & RegVRex) == 0); } - - gas_assert (i.tm.operand_types[nds].bitfield.class == RegSIMD); - i.vex.register_specifier = i.op[nds].regs; } - else - source = dest = 0; - - /* i.reg_operands MUST be the number of real register operands; - implicit registers do not count. If there are 3 register - operands, it must be a instruction with VexNDS. For a - instruction with VexNDD, the destination register is encoded - in VEX prefix. If there are 4 register operands, it must be - a instruction with VEX prefix and 3 sources. */ - if (i.mem_operands == 0 - && ((i.reg_operands == 2 - && i.tm.opcode_modifier.vexvvvv <= VEXXDS) - || (i.reg_operands == 3 - && i.tm.opcode_modifier.vexvvvv == VEXXDS) - || (i.reg_operands == 4 && vex_3_sources))) - { - switch (i.operands) - { - case 2: - source = 0; - break; - case 3: - /* When there are 3 operands, one of them may be immediate, - which may be the first or the last operand. Otherwise, - the first operand must be shift count register (cl) or it - is an instruction with VexNDS. */ - gas_assert (i.imm_operands == 1 - || (i.imm_operands == 0 - && (i.tm.opcode_modifier.vexvvvv == VEXXDS - || (i.types[0].bitfield.instance == RegC - && i.types[0].bitfield.byte)))); - if (operand_type_check (i.types[0], imm) - || (i.types[0].bitfield.instance == RegC - && i.types[0].bitfield.byte)) - source = 1; - else - source = 0; - break; - case 4: - /* When there are 4 operands, the first two must be 8bit - immediate operands. The source operand will be the 3rd - one. - - For instructions with VexNDS, if the first operand - an imm8, the source operand is the 2nd one. If the last - operand is imm8, the source operand is the first one. */ - gas_assert ((i.imm_operands == 2 - && i.types[0].bitfield.imm8 - && i.types[1].bitfield.imm8) - || (i.tm.opcode_modifier.vexvvvv == VEXXDS - && i.imm_operands == 1 - && (i.types[0].bitfield.imm8 - || i.types[0].bitfield.imm8s - || i.types[i.operands - 1].bitfield.imm8))); - if (i.imm_operands == 2) - source = 2; - else - { - if (i.types[0].bitfield.imm8) - source = 1; - else - source = 0; - } - break; - case 5: - gas_assert (!is_evex_encoding (&i.tm)); - gas_assert (i.imm_operands == 1 && vex_3_sources); - break; - default: - abort (); - } - - if (!vex_3_sources) - { - dest = source + 1; - - if (i.tm.opcode_modifier.vexvvvv == VEXXDS) - { - /* For instructions with VexNDS, the register-only source - operand must be a 32/64bit integer, XMM, YMM, ZMM, or mask - register. It is encoded in VEX prefix. */ - i386_operand_type op; - unsigned int vvvv; - - /* Swap two source operands if needed. */ - if (i.tm.opcode_modifier.operandconstraint == SWAP_SOURCES) - { - vvvv = source; - source = dest; - } - else - vvvv = dest; + for (v = source + 1; v < dest; ++v) + if (v != reg_slot) + break; + if (v >= dest) + v = ~0; + if (i.tm.extension_opcode != None) + { + if (dest != source) + v = dest; + dest = ~0; + } + gas_assert (source < dest); + if (i.tm.opcode_modifier.operandconstraint == SWAP_SOURCES + && source != op) + { + unsigned int tmp = source; - op = i.tm.operand_types[vvvv]; - if ((dest + 1) >= i.operands - || ((op.bitfield.class != Reg - || (!op.bitfield.dword && !op.bitfield.qword)) - && op.bitfield.class != RegSIMD - && op.bitfield.class != RegMask)) - abort (); - i.vex.register_specifier = i.op[vvvv].regs; - dest++; - } - } + source = v; + v = tmp; + } - i.rm.mode = 3; - /* One of the register operands will be encoded in the i.rm.reg - field, the other in the combined i.rm.mode and i.rm.regmem - fields. If no form of this instruction supports a memory - destination operand, then we assume the source operand may - sometimes be a memory operand and so we need to store the - destination in the i.rm.reg field. */ - if (!i.tm.opcode_modifier.regmem - && operand_type_check (i.tm.operand_types[dest], anymem) == 0) - { - i.rm.reg = i.op[dest].regs->reg_num; - i.rm.regmem = i.op[source].regs->reg_num; - set_rex_vrex (i.op[dest].regs, REX_R, i.tm.opcode_modifier.sse2avx); - set_rex_vrex (i.op[source].regs, REX_B, false); - } - else - { - i.rm.reg = i.op[source].regs->reg_num; - i.rm.regmem = i.op[dest].regs->reg_num; - set_rex_vrex (i.op[dest].regs, REX_B, i.tm.opcode_modifier.sse2avx); - set_rex_vrex (i.op[source].regs, REX_R, false); - } - if (flag_code != CODE_64BIT && (i.rex & REX_R)) - { - if (i.types[!i.tm.opcode_modifier.regmem].bitfield.class != RegCR) - abort (); - i.rex &= ~REX_R; - add_prefix (LOCK_PREFIX_OPCODE); - } + if (v < MAX_OPERANDS) + { + gas_assert (i.tm.opcode_modifier.vexvvvv); + i.vex.register_specifier = i.op[v].regs; } - else - { /* If it's not 2 reg operands... */ - unsigned int mem; + if (op < i.operands) + { if (i.mem_operands) { unsigned int fake_zero_displacement = 0; - unsigned int op; - for (op = 0; op < i.operands; op++) - if (i.flags[op] & Operand_Mem) - break; - gas_assert (op < i.operands); + gas_assert (i.flags[op] & Operand_Mem); if (i.tm.opcode_modifier.sib) { @@ -8732,140 +8635,62 @@ build_modrm_byte (void) exp->X_add_symbol = (symbolS *) 0; exp->X_op_symbol = (symbolS *) 0; } + } + else + { + i.rm.mode = 3; + i.rm.regmem = i.op[op].regs->reg_num; + set_rex_vrex (i.op[op].regs, REX_B, false); + } - mem = op; + if (op == dest) + dest = ~0; + if (op == source) + source = ~0; + } + else + { + i.rm.mode = 3; + if (!i.tm.opcode_modifier.regmem) + { + gas_assert (source < MAX_OPERANDS); + i.rm.regmem = i.op[source].regs->reg_num; + set_rex_vrex (i.op[source].regs, REX_B, + dest >= MAX_OPERANDS && i.tm.opcode_modifier.sse2avx); + source = ~0; } else - mem = ~0; - - if (i.tm.opcode_modifier.vexvvvv == VEXLWP) { - i.vex.register_specifier = i.op[2].regs; - if (!i.mem_operands) - { - i.rm.mode = 3; - i.rm.regmem = i.op[1].regs->reg_num; - if ((i.op[1].regs->reg_flags & RegRex) != 0) - i.rex |= REX_B; - } + gas_assert (dest < MAX_OPERANDS); + i.rm.regmem = i.op[dest].regs->reg_num; + set_rex_vrex (i.op[dest].regs, REX_B, i.tm.opcode_modifier.sse2avx); + dest = ~0; } - /* Fill in i.rm.reg or i.rm.regmem field with register operand - (if any) based on i.tm.extension_opcode. Again, we must be - careful to make sure that segment/control/debug/test/MMX - registers are coded into the i.rm.reg field. */ - else if (i.reg_operands) - { - unsigned int op; - unsigned int vex_reg = ~0; - - for (op = 0; op < i.operands; op++) - if (i.types[op].bitfield.class == Reg - || i.types[op].bitfield.class == RegBND - || i.types[op].bitfield.class == RegMask - || i.types[op].bitfield.class == SReg - || i.types[op].bitfield.class == RegCR - || i.types[op].bitfield.class == RegDR - || i.types[op].bitfield.class == RegTR - || i.types[op].bitfield.class == RegSIMD - || i.types[op].bitfield.class == RegMMX) - break; - - if (vex_3_sources) - op = dest; - else if (i.tm.opcode_modifier.vexvvvv == VEXXDS) - { - /* For instructions with VexNDS, the register-only - source operand is encoded in VEX prefix. */ - gas_assert (mem != (unsigned int) ~0); - - if (op > mem || i.tm.cpu_flags.bitfield.cpucmpccxadd) - { - vex_reg = op++; - gas_assert (op < i.operands); - } - else - { - /* Check register-only source operand when two source - operands are swapped. */ - if (!i.tm.operand_types[op].bitfield.baseindex - && i.tm.operand_types[op + 1].bitfield.baseindex) - { - vex_reg = op; - op += 2; - gas_assert (mem == (vex_reg + 1) - && op < i.operands); - } - else - { - vex_reg = op + 1; - gas_assert (vex_reg < i.operands); - } - } - } - else if (i.tm.opcode_modifier.vexvvvv == VEXNDD) - { - /* For instructions with VexNDD, the register destination - is encoded in VEX prefix. */ - if (i.mem_operands == 0) - { - /* There is no memory operand. */ - gas_assert ((op + 2) == i.operands); - vex_reg = op + 1; - } - else - { - /* There are only 2 non-immediate operands. */ - gas_assert (op < i.imm_operands + 2 - && i.operands == i.imm_operands + 2); - vex_reg = i.imm_operands + 1; - } - } - else - gas_assert (op < i.operands); - - if (vex_reg != (unsigned int) ~0) - { - i386_operand_type *type = &i.tm.operand_types[vex_reg]; - - if ((type->bitfield.class != Reg - || (!type->bitfield.dword && !type->bitfield.qword)) - && type->bitfield.class != RegSIMD - && type->bitfield.class != RegMask) - abort (); - - i.vex.register_specifier = i.op[vex_reg].regs; - } - - /* Don't set OP operand twice. */ - if (vex_reg != op) - { - /* If there is an extension opcode to put here, the - register number must be put into the regmem field. */ - if (i.tm.extension_opcode != None) - { - i.rm.regmem = i.op[op].regs->reg_num; - set_rex_vrex (i.op[op].regs, REX_B, - i.tm.opcode_modifier.sse2avx); - } - else - { - i.rm.reg = i.op[op].regs->reg_num; - set_rex_vrex (i.op[op].regs, REX_R, - i.tm.opcode_modifier.sse2avx); - } - } + } - /* Now, if no memory operand has set i.rm.mode = 0, 1, 2 we - must set it to 3 to indicate this is a register operand - in the regmem field. */ - if (!i.mem_operands) - i.rm.mode = 3; - } + /* Fill in i.rm.reg field with extension opcode (if any) or the + appropriate register. */ + if (i.tm.extension_opcode != None) + i.rm.reg = i.tm.extension_opcode; + else if (!i.tm.opcode_modifier.regmem && dest < MAX_OPERANDS) + { + i.rm.reg = i.op[dest].regs->reg_num; + set_rex_vrex (i.op[dest].regs, REX_R, i.tm.opcode_modifier.sse2avx); + } + else + { + gas_assert (source < MAX_OPERANDS); + i.rm.reg = i.op[source].regs->reg_num; + set_rex_vrex (i.op[source].regs, REX_R, false); + } - /* Fill in i.rm.reg field with extension opcode (if any). */ - if (i.tm.extension_opcode != None) - i.rm.reg = i.tm.extension_opcode; + if (flag_code != CODE_64BIT && (i.rex & REX_R)) + { + gas_assert (i.types[!i.tm.opcode_modifier.regmem].bitfield.class == RegCR); + i.rex &= ~REX_R; + add_prefix (LOCK_PREFIX_OPCODE); } + return default_seg; } --- a/opcodes/i386-opc.tbl +++ b/opcodes/i386-opc.tbl @@ -1749,18 +1749,18 @@ vpsravd, 0x6646, AVX2, Modrm|Vex|Space0F vpsrlv, 0x6645, AVX2, Modrm|Vex|Space0F38|VexVVVV||CheckOperandSize|NoSuf, { Unspecified|BaseIndex|RegXMM|RegYMM, RegXMM|RegYMM, RegXMM|RegYMM } // AVX gather instructions -vgatherdpd, 0x6692, AVX2, Modrm|Vex|Space0F38|VexVVVV|VexW1|CheckOperandSize|NoSuf|VecSIB128, { RegXMM|RegYMM, Qword|Unspecified|BaseIndex, RegXMM|RegYMM } -vgatherdps, 0x6692, AVX2, Modrm|Vex|Space0F38|VexVVVV|VexW0|NoSuf|VecSIB128, { RegXMM, Dword|Unspecified|BaseIndex, RegXMM } -vgatherdps, 0x6692, AVX2, Modrm|Vex=2|Space0F38|VexVVVV|VexW0|NoSuf|VecSIB256, { RegYMM, Dword|Unspecified|BaseIndex, RegYMM } -vgatherqp, 0x6693, AVX2, Modrm|Vex|Space0F38|VexVVVV||NoSuf|VecSIB128, { RegXMM, |Unspecified|BaseIndex, RegXMM } -vgatherqpd, 0x6693, AVX2, Modrm|Vex=2|Space0F38|VexVVVV|VexW1|NoSuf|VecSIB256, { RegYMM, Qword|Unspecified|BaseIndex, RegYMM } -vgatherqps, 0x6693, AVX2, Modrm|Vex=2|Space0F38|VexVVVV|VexW0|NoSuf|VecSIB256, { RegXMM, Dword|Unspecified|BaseIndex, RegXMM } -vpgatherdd, 0x6690, AVX2, Modrm|Vex|Space0F38|VexVVVV|VexW0|NoSuf|VecSIB128, { RegXMM, Dword|Unspecified|BaseIndex, RegXMM } -vpgatherdd, 0x6690, AVX2, Modrm|Vex=2|Space0F38|VexVVVV|VexW0|NoSuf|VecSIB256, { RegYMM, Dword|Unspecified|BaseIndex, RegYMM } -vpgatherdq, 0x6690, AVX2, Modrm|Vex|Space0F38|VexVVVV|VexW1|CheckOperandSize|NoSuf|VecSIB128, { RegXMM|RegYMM, Qword|Unspecified|BaseIndex, RegXMM|RegYMM } -vpgatherq, 0x6691, AVX2, Modrm|Vex|Space0F38|VexVVVV||NoSuf|VecSIB128, { RegXMM, |Unspecified|BaseIndex, RegXMM } -vpgatherqd, 0x6691, AVX2, Modrm|Vex=2|Space0F38|VexVVVV|VexW0|NoSuf|VecSIB256, { RegXMM, Dword|Unspecified|BaseIndex, RegXMM } -vpgatherqq, 0x6691, AVX2, Modrm|Vex=2|Space0F38|VexVVVV|VexW1|NoSuf|VecSIB256, { RegYMM, Qword|Unspecified|BaseIndex, RegYMM } +vgatherdpd, 0x6692, AVX2, Modrm|Vex|Space0F38|VexVVVV|VexW1|SwapSources|CheckOperandSize|NoSuf|VecSIB128, { RegXMM|RegYMM, Qword|Unspecified|BaseIndex, RegXMM|RegYMM } +vgatherdps, 0x6692, AVX2, Modrm|Vex128|Space0F38|VexVVVV|VexW0|SwapSources|NoSuf|VecSIB128, { RegXMM, Dword|Unspecified|BaseIndex, RegXMM } +vgatherdps, 0x6692, AVX2, Modrm|Vex256|Space0F38|VexVVVV|VexW0|SwapSources|NoSuf|VecSIB256, { RegYMM, Dword|Unspecified|BaseIndex, RegYMM } +vgatherqp, 0x6693, AVX2, Modrm|Vex|Space0F38|VexVVVV||SwapSources|NoSuf|VecSIB128, { RegXMM, |Unspecified|BaseIndex, RegXMM } +vgatherqpd, 0x6693, AVX2, Modrm|Vex256|Space0F38|VexVVVV|VexW1|SwapSources|NoSuf|VecSIB256, { RegYMM, Qword|Unspecified|BaseIndex, RegYMM } +vgatherqps, 0x6693, AVX2, Modrm|Vex256|Space0F38|VexVVVV|VexW0|SwapSources|NoSuf|VecSIB256, { RegXMM, Dword|Unspecified|BaseIndex, RegXMM } +vpgatherdd, 0x6690, AVX2, Modrm|Vex128|Space0F38|VexVVVV|VexW0|SwapSources|NoSuf|VecSIB128, { RegXMM, Dword|Unspecified|BaseIndex, RegXMM } +vpgatherdd, 0x6690, AVX2, Modrm|Vex256|Space0F38|VexVVVV|VexW0|SwapSources|NoSuf|VecSIB256, { RegYMM, Dword|Unspecified|BaseIndex, RegYMM } +vpgatherdq, 0x6690, AVX2, Modrm|Vex|Space0F38|VexVVVV|VexW1|SwapSources|CheckOperandSize|NoSuf|VecSIB128, { RegXMM|RegYMM, Qword|Unspecified|BaseIndex, RegXMM|RegYMM } +vpgatherq, 0x6691, AVX2, Modrm|Vex128|Space0F38|VexVVVV||SwapSources|NoSuf|VecSIB128, { RegXMM, |Unspecified|BaseIndex, RegXMM } +vpgatherqd, 0x6691, AVX2, Modrm|Vex256|Space0F38|VexVVVV|VexW0|SwapSources|NoSuf|VecSIB256, { RegXMM, Dword|Unspecified|BaseIndex, RegXMM } +vpgatherqq, 0x6691, AVX2, Modrm|Vex256|Space0F38|VexVVVV|VexW1|SwapSources|NoSuf|VecSIB256, { RegYMM, Qword|Unspecified|BaseIndex, RegYMM } // AES + AVX @@ -3321,7 +3321,7 @@ prefetchit1, 0xf18/6, PREFETCHI|x64, Mod // CMPCCXADD instructions. -cmpxadd, 0x66e, CMPCCXADD|x64, Modrm|Vex|Space0F38|VexVVVV|CheckOperandSize|NoSuf, { Reg32|Reg64, Reg32|Reg64, Dword|Qword|Unspecified|BaseIndex } +cmpxadd, 0x66e, CMPCCXADD|x64, Modrm|Vex|Space0F38|VexVVVV|SwapSources|CheckOperandSize|NoSuf, { Reg32|Reg64, Reg32|Reg64, Dword|Qword|Unspecified|BaseIndex } // CMPCCXADD instructions end.