blob: d08748e473fc14beffa48880e8be7f8ccb025541 [file] [log] [blame]
/*---------------------------------------------------------------*/
/*--- begin host_arm64_defs.c ---*/
/*---------------------------------------------------------------*/
/*
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (C) 2013-2013 OpenWorks
info@open-works.net
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 2 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.
The GNU General Public License is contained in the file COPYING.
*/
#include "libvex_basictypes.h"
#include "libvex.h"
#include "libvex_trc_values.h"
#include "main_util.h"
#include "host_generic_regs.h"
#include "host_arm64_defs.h"
//ZZ UInt arm_hwcaps = 0;
/* --------- Registers. --------- */
/* The usual HReg abstraction. We use the following classes only:
X regs (64 bit int)
D regs (64 bit float, also used for 32 bit float)
Q regs (128 bit vector)
*/
void ppHRegARM64 ( HReg reg ) {
Int r;
/* Be generic for all virtual regs. */
if (hregIsVirtual(reg)) {
ppHReg(reg);
return;
}
/* But specific for real regs. */
switch (hregClass(reg)) {
case HRcInt64:
r = hregNumber(reg);
vassert(r >= 0 && r < 31);
vex_printf("x%d", r);
return;
case HRcFlt64:
r = hregNumber(reg);
vassert(r >= 0 && r < 32);
vex_printf("d%d", r);
return;
case HRcVec128:
r = hregNumber(reg);
vassert(r >= 0 && r < 32);
vex_printf("q%d", r);
return;
default:
vpanic("ppHRegARM64");
}
}
static void ppHRegARM64asSreg ( HReg reg ) {
ppHRegARM64(reg);
vex_printf("(S-reg)");
}
HReg hregARM64_X0 ( void ) { return mkHReg(0, HRcInt64, False); }
HReg hregARM64_X1 ( void ) { return mkHReg(1, HRcInt64, False); }
HReg hregARM64_X2 ( void ) { return mkHReg(2, HRcInt64, False); }
HReg hregARM64_X3 ( void ) { return mkHReg(3, HRcInt64, False); }
HReg hregARM64_X4 ( void ) { return mkHReg(4, HRcInt64, False); }
HReg hregARM64_X5 ( void ) { return mkHReg(5, HRcInt64, False); }
HReg hregARM64_X6 ( void ) { return mkHReg(6, HRcInt64, False); }
HReg hregARM64_X7 ( void ) { return mkHReg(7, HRcInt64, False); }
HReg hregARM64_X8 ( void ) { return mkHReg(8, HRcInt64, False); }
HReg hregARM64_X9 ( void ) { return mkHReg(9, HRcInt64, False); }
HReg hregARM64_X10 ( void ) { return mkHReg(10, HRcInt64, False); }
HReg hregARM64_X11 ( void ) { return mkHReg(11, HRcInt64, False); }
HReg hregARM64_X12 ( void ) { return mkHReg(12, HRcInt64, False); }
HReg hregARM64_X13 ( void ) { return mkHReg(13, HRcInt64, False); }
HReg hregARM64_X14 ( void ) { return mkHReg(14, HRcInt64, False); }
HReg hregARM64_X15 ( void ) { return mkHReg(15, HRcInt64, False); }
HReg hregARM64_X21 ( void ) { return mkHReg(21, HRcInt64, False); }
HReg hregARM64_X22 ( void ) { return mkHReg(22, HRcInt64, False); }
HReg hregARM64_X23 ( void ) { return mkHReg(23, HRcInt64, False); }
HReg hregARM64_X24 ( void ) { return mkHReg(24, HRcInt64, False); }
HReg hregARM64_X25 ( void ) { return mkHReg(25, HRcInt64, False); }
HReg hregARM64_X26 ( void ) { return mkHReg(26, HRcInt64, False); }
HReg hregARM64_X27 ( void ) { return mkHReg(27, HRcInt64, False); }
HReg hregARM64_X28 ( void ) { return mkHReg(28, HRcInt64, False); }
// Should really use D8 .. D15 for class F64, since they are callee
// save
HReg hregARM64_D8 ( void ) { return mkHReg(8, HRcFlt64, False); }
HReg hregARM64_D9 ( void ) { return mkHReg(9, HRcFlt64, False); }
HReg hregARM64_D10 ( void ) { return mkHReg(10, HRcFlt64, False); }
HReg hregARM64_D11 ( void ) { return mkHReg(11, HRcFlt64, False); }
HReg hregARM64_D12 ( void ) { return mkHReg(12, HRcFlt64, False); }
HReg hregARM64_D13 ( void ) { return mkHReg(13, HRcFlt64, False); }
HReg hregARM64_Q16 ( void ) { return mkHReg(16, HRcVec128, False); }
HReg hregARM64_Q17 ( void ) { return mkHReg(17, HRcVec128, False); }
HReg hregARM64_Q18 ( void ) { return mkHReg(18, HRcVec128, False); }
HReg hregARM64_Q19 ( void ) { return mkHReg(19, HRcVec128, False); }
HReg hregARM64_Q20 ( void ) { return mkHReg(20, HRcVec128, False); }
void getAllocableRegs_ARM64 ( Int* nregs, HReg** arr )
{
Int i = 0;
*nregs = 26;
*arr = LibVEX_Alloc(*nregs * sizeof(HReg));
// callee saves ones (22 to 28) are listed first, since we prefer
// them if they're available
(*arr)[i++] = hregARM64_X22();
(*arr)[i++] = hregARM64_X23();
(*arr)[i++] = hregARM64_X24();
(*arr)[i++] = hregARM64_X25();
(*arr)[i++] = hregARM64_X26();
(*arr)[i++] = hregARM64_X27();
(*arr)[i++] = hregARM64_X28();
(*arr)[i++] = hregARM64_X0();
(*arr)[i++] = hregARM64_X1();
(*arr)[i++] = hregARM64_X2();
(*arr)[i++] = hregARM64_X3();
(*arr)[i++] = hregARM64_X4();
(*arr)[i++] = hregARM64_X5();
(*arr)[i++] = hregARM64_X6();
(*arr)[i++] = hregARM64_X7();
// X8 is used as a ProfInc temporary, not available to regalloc.
// X9 is a chaining/spill temporary, not available to regalloc.
// Do we really need all these?
//(*arr)[i++] = hregARM64_X10();
//(*arr)[i++] = hregARM64_X11();
//(*arr)[i++] = hregARM64_X12();
//(*arr)[i++] = hregARM64_X13();
//(*arr)[i++] = hregARM64_X14();
//(*arr)[i++] = hregARM64_X15();
// X21 is the guest state pointer, not available to regalloc.
// vector regs. Unfortunately not callee-saved.
(*arr)[i++] = hregARM64_Q16();
(*arr)[i++] = hregARM64_Q17();
(*arr)[i++] = hregARM64_Q18();
(*arr)[i++] = hregARM64_Q19();
(*arr)[i++] = hregARM64_Q20();
// F64 regs, all of which are callee-saved
(*arr)[i++] = hregARM64_D8();
(*arr)[i++] = hregARM64_D9();
(*arr)[i++] = hregARM64_D10();
(*arr)[i++] = hregARM64_D11();
(*arr)[i++] = hregARM64_D12();
(*arr)[i++] = hregARM64_D13();
// unavail: x21 as GSP
// x8 is used as a ProfInc temporary
// x9 is used as a spill/reload/chaining/call temporary
// x30 as LR
// x31 because dealing with the SP-vs-ZR overloading is too
// confusing, and we don't need to do so, so let's just avoid
// the problem
//
// Currently, we have 15 allocatable integer registers:
// 0 1 2 3 4 5 6 7 22 23 24 25 26 27 28
//
// Hence for the allocatable integer registers we have:
//
// callee-saved: 22 23 24 25 26 27 28
// caller-saved: 0 1 2 3 4 5 6 7
//
// If the set of available registers changes or if the e/r status
// changes, be sure to re-check/sync the definition of
// getRegUsage for ARM64Instr_Call too.
vassert(i == *nregs);
}
/* --------- Condition codes, ARM64 encoding. --------- */
static const HChar* showARM64CondCode ( ARM64CondCode cond ) {
switch (cond) {
case ARM64cc_EQ: return "eq";
case ARM64cc_NE: return "ne";
case ARM64cc_CS: return "cs";
case ARM64cc_CC: return "cc";
case ARM64cc_MI: return "mi";
case ARM64cc_PL: return "pl";
case ARM64cc_VS: return "vs";
case ARM64cc_VC: return "vc";
case ARM64cc_HI: return "hi";
case ARM64cc_LS: return "ls";
case ARM64cc_GE: return "ge";
case ARM64cc_LT: return "lt";
case ARM64cc_GT: return "gt";
case ARM64cc_LE: return "le";
case ARM64cc_AL: return "al"; // default
case ARM64cc_NV: return "nv";
default: vpanic("showARM64CondCode");
}
}
/* --------- Memory address expressions (amodes). --------- */
ARM64AMode* ARM64AMode_RI9 ( HReg reg, Int simm9 ) {
ARM64AMode* am = LibVEX_Alloc(sizeof(ARM64AMode));
am->tag = ARM64am_RI9;
am->ARM64am.RI9.reg = reg;
am->ARM64am.RI9.simm9 = simm9;
vassert(-256 <= simm9 && simm9 <= 255);
return am;
}
ARM64AMode* ARM64AMode_RI12 ( HReg reg, Int uimm12, UChar szB ) {
ARM64AMode* am = LibVEX_Alloc(sizeof(ARM64AMode));
am->tag = ARM64am_RI12;
am->ARM64am.RI12.reg = reg;
am->ARM64am.RI12.uimm12 = uimm12;
am->ARM64am.RI12.szB = szB;
vassert(uimm12 >= 0 && uimm12 <= 4095);
switch (szB) {
case 1: case 2: case 4: case 8: break;
default: vassert(0);
}
return am;
}
ARM64AMode* ARM64AMode_RR ( HReg base, HReg index ) {
ARM64AMode* am = LibVEX_Alloc(sizeof(ARM64AMode));
am->tag = ARM64am_RR;
am->ARM64am.RR.base = base;
am->ARM64am.RR.index = index;
return am;
}
static void ppARM64AMode ( ARM64AMode* am ) {
switch (am->tag) {
case ARM64am_RI9:
vex_printf("%d(", am->ARM64am.RI9.simm9);
ppHRegARM64(am->ARM64am.RI9.reg);
vex_printf(")");
break;
case ARM64am_RI12:
vex_printf("%u(", (UInt)am->ARM64am.RI12.szB
* (UInt)am->ARM64am.RI12.uimm12);
ppHRegARM64(am->ARM64am.RI12.reg);
vex_printf(")");
break;
case ARM64am_RR:
vex_printf("(");
ppHRegARM64(am->ARM64am.RR.base);
vex_printf(",");
ppHRegARM64(am->ARM64am.RR.index);
vex_printf(")");
break;
default:
vassert(0);
}
}
static void addRegUsage_ARM64AMode ( HRegUsage* u, ARM64AMode* am ) {
switch (am->tag) {
case ARM64am_RI9:
addHRegUse(u, HRmRead, am->ARM64am.RI9.reg);
return;
case ARM64am_RI12:
addHRegUse(u, HRmRead, am->ARM64am.RI12.reg);
return;
case ARM64am_RR:
addHRegUse(u, HRmRead, am->ARM64am.RR.base);
addHRegUse(u, HRmRead, am->ARM64am.RR.index);
return;
default:
vpanic("addRegUsage_ARM64Amode");
}
}
static void mapRegs_ARM64AMode ( HRegRemap* m, ARM64AMode* am ) {
switch (am->tag) {
case ARM64am_RI9:
am->ARM64am.RI9.reg = lookupHRegRemap(m, am->ARM64am.RI9.reg);
return;
case ARM64am_RI12:
am->ARM64am.RI12.reg = lookupHRegRemap(m, am->ARM64am.RI12.reg);
return;
case ARM64am_RR:
am->ARM64am.RR.base = lookupHRegRemap(m, am->ARM64am.RR.base);
am->ARM64am.RR.index = lookupHRegRemap(m, am->ARM64am.RR.index);
return;
default:
vpanic("mapRegs_ARM64Amode");
}
}
/* --------- Reg or uimm12<<{0,12} operands --------- */
ARM64RIA* ARM64RIA_I12 ( UShort imm12, UChar shift ) {
ARM64RIA* riA = LibVEX_Alloc(sizeof(ARM64RIA));
riA->tag = ARM64riA_I12;
riA->ARM64riA.I12.imm12 = imm12;
riA->ARM64riA.I12.shift = shift;
vassert(imm12 < 4096);
vassert(shift == 0 || shift == 12);
return riA;
}
ARM64RIA* ARM64RIA_R ( HReg reg ) {
ARM64RIA* riA = LibVEX_Alloc(sizeof(ARM64RIA));
riA->tag = ARM64riA_R;
riA->ARM64riA.R.reg = reg;
return riA;
}
static void ppARM64RIA ( ARM64RIA* riA ) {
switch (riA->tag) {
case ARM64riA_I12:
vex_printf("#%u",(UInt)(riA->ARM64riA.I12.imm12
<< riA->ARM64riA.I12.shift));
break;
case ARM64riA_R:
ppHRegARM64(riA->ARM64riA.R.reg);
break;
default:
vassert(0);
}
}
static void addRegUsage_ARM64RIA ( HRegUsage* u, ARM64RIA* riA ) {
switch (riA->tag) {
case ARM64riA_I12:
return;
case ARM64riA_R:
addHRegUse(u, HRmRead, riA->ARM64riA.R.reg);
return;
default:
vpanic("addRegUsage_ARM64RIA");
}
}
static void mapRegs_ARM64RIA ( HRegRemap* m, ARM64RIA* riA ) {
switch (riA->tag) {
case ARM64riA_I12:
return;
case ARM64riA_R:
riA->ARM64riA.R.reg = lookupHRegRemap(m, riA->ARM64riA.R.reg);
return;
default:
vpanic("mapRegs_ARM64RIA");
}
}
/* --------- Reg or "bitfield" (logic immediate) operands --------- */
ARM64RIL* ARM64RIL_I13 ( UChar bitN, UChar immR, UChar immS ) {
ARM64RIL* riL = LibVEX_Alloc(sizeof(ARM64RIL));
riL->tag = ARM64riL_I13;
riL->ARM64riL.I13.bitN = bitN;
riL->ARM64riL.I13.immR = immR;
riL->ARM64riL.I13.immS = immS;
vassert(bitN < 2);
vassert(immR < 64);
vassert(immS < 64);
return riL;
}
ARM64RIL* ARM64RIL_R ( HReg reg ) {
ARM64RIL* riL = LibVEX_Alloc(sizeof(ARM64RIL));
riL->tag = ARM64riL_R;
riL->ARM64riL.R.reg = reg;
return riL;
}
static void ppARM64RIL ( ARM64RIL* riL ) {
switch (riL->tag) {
case ARM64riL_I13:
vex_printf("#nrs(%u,%u,%u)",
(UInt)riL->ARM64riL.I13.bitN,
(UInt)riL->ARM64riL.I13.immR,
(UInt)riL->ARM64riL.I13.immS);
break;
case ARM64riL_R:
ppHRegARM64(riL->ARM64riL.R.reg);
break;
default:
vassert(0);
}
}
static void addRegUsage_ARM64RIL ( HRegUsage* u, ARM64RIL* riL ) {
switch (riL->tag) {
case ARM64riL_I13:
return;
case ARM64riL_R:
addHRegUse(u, HRmRead, riL->ARM64riL.R.reg);
return;
default:
vpanic("addRegUsage_ARM64RIL");
}
}
static void mapRegs_ARM64RIL ( HRegRemap* m, ARM64RIL* riL ) {
switch (riL->tag) {
case ARM64riL_I13:
return;
case ARM64riL_R:
riL->ARM64riL.R.reg = lookupHRegRemap(m, riL->ARM64riL.R.reg);
return;
default:
vpanic("mapRegs_ARM64RIL");
}
}
/* --------------- Reg or uimm6 operands --------------- */
ARM64RI6* ARM64RI6_I6 ( UInt imm6 ) {
ARM64RI6* ri6 = LibVEX_Alloc(sizeof(ARM64RI6));
ri6->tag = ARM64ri6_I6;
ri6->ARM64ri6.I6.imm6 = imm6;
vassert(imm6 > 0 && imm6 < 64);
return ri6;
}
ARM64RI6* ARM64RI6_R ( HReg reg ) {
ARM64RI6* ri6 = LibVEX_Alloc(sizeof(ARM64RI6));
ri6->tag = ARM64ri6_R;
ri6->ARM64ri6.R.reg = reg;
return ri6;
}
static void ppARM64RI6 ( ARM64RI6* ri6 ) {
switch (ri6->tag) {
case ARM64ri6_I6:
vex_printf("#%u", ri6->ARM64ri6.I6.imm6);
break;
case ARM64ri6_R:
ppHRegARM64(ri6->ARM64ri6.R.reg);
break;
default:
vassert(0);
}
}
static void addRegUsage_ARM64RI6 ( HRegUsage* u, ARM64RI6* ri6 ) {
switch (ri6->tag) {
case ARM64ri6_I6:
return;
case ARM64ri6_R:
addHRegUse(u, HRmRead, ri6->ARM64ri6.R.reg);
return;
default:
vpanic("addRegUsage_ARM64RI6");
}
}
static void mapRegs_ARM64RI6 ( HRegRemap* m, ARM64RI6* ri6 ) {
switch (ri6->tag) {
case ARM64ri6_I6:
return;
case ARM64ri6_R:
ri6->ARM64ri6.R.reg = lookupHRegRemap(m, ri6->ARM64ri6.R.reg);
return;
default:
vpanic("mapRegs_ARM64RI6");
}
}
/* --------- Instructions. --------- */
static const HChar* showARM64LogicOp ( ARM64LogicOp op ) {
switch (op) {
case ARM64lo_AND: return "and";
case ARM64lo_OR: return "orr";
case ARM64lo_XOR: return "eor";
default: vpanic("showARM64LogicOp");
}
}
static const HChar* showARM64ShiftOp ( ARM64ShiftOp op ) {
switch (op) {
case ARM64sh_SHL: return "lsl";
case ARM64sh_SHR: return "lsr";
case ARM64sh_SAR: return "asr";
default: vpanic("showARM64ShiftOp");
}
}
static const HChar* showARM64UnaryOp ( ARM64UnaryOp op ) {
switch (op) {
case ARM64un_NEG: return "neg";
case ARM64un_NOT: return "not";
case ARM64un_CLZ: return "clz";
default: vpanic("showARM64UnaryOp");
}
}
static const HChar* showARM64MulOp ( ARM64MulOp op ) {
switch (op) {
case ARM64mul_PLAIN: return "mul ";
case ARM64mul_ZX: return "umulh";
case ARM64mul_SX: return "smulh";
default: vpanic("showARM64MulOp");
}
}
static void characteriseARM64CvtOp ( /*OUT*/HChar* syn,
/*OUT*/UInt* fszB, /*OUT*/UInt* iszB,
ARM64CvtOp op ) {
switch (op) {
case ARM64cvt_F32_I32S:
*syn = 's'; *fszB = 4; *iszB = 4; break;
case ARM64cvt_F64_I32S:
*syn = 's'; *fszB = 8; *iszB = 4; break;
case ARM64cvt_F32_I64S:
*syn = 's'; *fszB = 4; *iszB = 8; break;
case ARM64cvt_F64_I64S:
*syn = 's'; *fszB = 8; *iszB = 8; break;
case ARM64cvt_F32_I32U:
*syn = 'u'; *fszB = 4; *iszB = 4; break;
case ARM64cvt_F64_I32U:
*syn = 'u'; *fszB = 8; *iszB = 4; break;
case ARM64cvt_F32_I64U:
*syn = 'u'; *fszB = 4; *iszB = 8; break;
case ARM64cvt_F64_I64U:
*syn = 'u'; *fszB = 8; *iszB = 8; break;
default:
vpanic("characteriseARM64CvtOp");
}
}
static const HChar* showARM64FpBinOp ( ARM64FpBinOp op ) {
switch (op) {
case ARM64fpb_ADD: return "add";
case ARM64fpb_SUB: return "sub";
case ARM64fpb_MUL: return "mul";
case ARM64fpb_DIV: return "div";
default: vpanic("showARM64FpBinOp");
}
}
static const HChar* showARM64FpUnaryOp ( ARM64FpUnaryOp op ) {
switch (op) {
case ARM64fpu_NEG: return "neg ";
case ARM64fpu_ABS: return "abs ";
case ARM64fpu_SQRT: return "sqrt ";
case ARM64fpu_RINT: return "rinti";
default: vpanic("showARM64FpUnaryOp");
}
}
static void showARM64VecBinOp(/*OUT*/const HChar** nm,
/*OUT*/const HChar** ar, ARM64VecBinOp op ) {
switch (op) {
case ARM64vecb_ADD64x2: *nm = "add "; *ar = "2d"; return;
case ARM64vecb_ADD32x4: *nm = "add "; *ar = "4s"; return;
case ARM64vecb_ADD16x8: *nm = "add "; *ar = "8h"; return;
case ARM64vecb_ADD8x16: *nm = "add "; *ar = "16b"; return;
case ARM64vecb_SUB64x2: *nm = "sub "; *ar = "2d"; return;
case ARM64vecb_SUB32x4: *nm = "sub "; *ar = "4s"; return;
case ARM64vecb_SUB16x8: *nm = "sub "; *ar = "8h"; return;
case ARM64vecb_SUB8x16: *nm = "sub "; *ar = "16b"; return;
case ARM64vecb_MUL32x4: *nm = "mul "; *ar = "4s"; return;
case ARM64vecb_MUL16x8: *nm = "mul "; *ar = "8h"; return;
case ARM64vecb_MUL8x16: *nm = "mul "; *ar = "16b"; return;
case ARM64vecb_FADD64x2: *nm = "fadd "; *ar = "2d"; return;
case ARM64vecb_FSUB64x2: *nm = "fsub "; *ar = "2d"; return;
case ARM64vecb_FMUL64x2: *nm = "fmul "; *ar = "2d"; return;
case ARM64vecb_FDIV64x2: *nm = "fdiv "; *ar = "2d"; return;
case ARM64vecb_FADD32x4: *nm = "fadd "; *ar = "4s"; return;
case ARM64vecb_FSUB32x4: *nm = "fsub "; *ar = "4s"; return;
case ARM64vecb_FMUL32x4: *nm = "fmul "; *ar = "4s"; return;
case ARM64vecb_FDIV32x4: *nm = "fdiv "; *ar = "4s"; return;
case ARM64vecb_UMAX32x4: *nm = "umax "; *ar = "4s"; return;
case ARM64vecb_UMAX16x8: *nm = "umax "; *ar = "8h"; return;
case ARM64vecb_UMAX8x16: *nm = "umax "; *ar = "16b"; return;
case ARM64vecb_UMIN32x4: *nm = "umin "; *ar = "4s"; return;
case ARM64vecb_UMIN16x8: *nm = "umin "; *ar = "8h"; return;
case ARM64vecb_UMIN8x16: *nm = "umin "; *ar = "16b"; return;
case ARM64vecb_SMAX32x4: *nm = "smax "; *ar = "4s"; return;
case ARM64vecb_SMAX16x8: *nm = "smax "; *ar = "8h"; return;
case ARM64vecb_SMAX8x16: *nm = "smax "; *ar = "16b"; return;
case ARM64vecb_SMIN32x4: *nm = "smin "; *ar = "4s"; return;
case ARM64vecb_SMIN16x8: *nm = "smin "; *ar = "8h"; return;
case ARM64vecb_SMIN8x16: *nm = "smin "; *ar = "16b"; return;
case ARM64vecb_AND: *nm = "and "; *ar = "16b"; return;
case ARM64vecb_ORR: *nm = "orr "; *ar = "16b"; return;
case ARM64vecb_XOR: *nm = "eor "; *ar = "16b"; return;
case ARM64vecb_CMEQ64x2: *nm = "cmeq "; *ar = "2d"; return;
case ARM64vecb_CMEQ32x4: *nm = "cmeq "; *ar = "4s"; return;
case ARM64vecb_CMEQ16x8: *nm = "cmeq "; *ar = "8h"; return;
case ARM64vecb_CMEQ8x16: *nm = "cmeq "; *ar = "16b"; return;
case ARM64vecb_CMHI64x2: *nm = "cmhi "; *ar = "2d"; return;
case ARM64vecb_CMHI32x4: *nm = "cmhi "; *ar = "4s"; return;
case ARM64vecb_CMHI16x8: *nm = "cmhi "; *ar = "8h"; return;
case ARM64vecb_CMHI8x16: *nm = "cmhi "; *ar = "16b"; return;
case ARM64vecb_CMGT64x2: *nm = "cmgt "; *ar = "2d"; return;
case ARM64vecb_CMGT32x4: *nm = "cmgt "; *ar = "4s"; return;
case ARM64vecb_CMGT16x8: *nm = "cmgt "; *ar = "8h"; return;
case ARM64vecb_CMGT8x16: *nm = "cmgt "; *ar = "16b"; return;
case ARM64vecb_FCMEQ64x2: *nm = "fcmeq "; *ar = "2d"; return;
case ARM64vecb_FCMEQ32x4: *nm = "fcmeq "; *ar = "4s"; return;
case ARM64vecb_FCMGE64x2: *nm = "fcmge "; *ar = "2d"; return;
case ARM64vecb_FCMGE32x4: *nm = "fcmge "; *ar = "4s"; return;
case ARM64vecb_FCMGT64x2: *nm = "fcmgt "; *ar = "2d"; return;
case ARM64vecb_FCMGT32x4: *nm = "fcmgt "; *ar = "4s"; return;
case ARM64vecb_TBL1: *nm = "tbl "; *ar = "16b"; return;
case ARM64vecb_UZP164x2: *nm = "uzp1 "; *ar = "2d"; return;
case ARM64vecb_UZP132x4: *nm = "uzp1 "; *ar = "4s"; return;
case ARM64vecb_UZP116x8: *nm = "uzp1 "; *ar = "8h"; return;
case ARM64vecb_UZP18x16: *nm = "uzp1 "; *ar = "16b"; return;
case ARM64vecb_UZP264x2: *nm = "uzp2 "; *ar = "2d"; return;
case ARM64vecb_UZP232x4: *nm = "uzp2 "; *ar = "4s"; return;
case ARM64vecb_UZP216x8: *nm = "uzp2 "; *ar = "8h"; return;
case ARM64vecb_UZP28x16: *nm = "uzp2 "; *ar = "16b"; return;
case ARM64vecb_ZIP132x4: *nm = "zip1 "; *ar = "4s"; return;
case ARM64vecb_ZIP116x8: *nm = "zip1 "; *ar = "8h"; return;
case ARM64vecb_ZIP18x16: *nm = "zip1 "; *ar = "16b"; return;
case ARM64vecb_ZIP232x4: *nm = "zip2 "; *ar = "4s"; return;
case ARM64vecb_ZIP216x8: *nm = "zip2 "; *ar = "8h"; return;
case ARM64vecb_ZIP28x16: *nm = "zip2 "; *ar = "16b"; return;
case ARM64vecb_PMUL8x16: *nm = "pmul "; *ar = "16b"; return;
case ARM64vecb_PMULL8x8: *nm = "pmull "; *ar = "8hbb"; return;
case ARM64vecb_UMULL2DSS: *nm = "umull "; *ar = "2dss"; return;
case ARM64vecb_UMULL4SHH: *nm = "umull "; *ar = "4shh"; return;
case ARM64vecb_UMULL8HBB: *nm = "umull "; *ar = "8hbb"; return;
case ARM64vecb_SMULL2DSS: *nm = "smull "; *ar = "2dss"; return;
case ARM64vecb_SMULL4SHH: *nm = "smull "; *ar = "4shh"; return;
case ARM64vecb_SMULL8HBB: *nm = "smull "; *ar = "8hbb"; return;
case ARM64vecb_SQADD64x2: *nm = "sqadd "; *ar = "2d"; return;
case ARM64vecb_SQADD32x4: *nm = "sqadd "; *ar = "4s"; return;
case ARM64vecb_SQADD16x8: *nm = "sqadd "; *ar = "8h"; return;
case ARM64vecb_SQADD8x16: *nm = "sqadd "; *ar = "16b"; return;
case ARM64vecb_UQADD64x2: *nm = "uqadd "; *ar = "2d"; return;
case ARM64vecb_UQADD32x4: *nm = "uqadd "; *ar = "4s"; return;
case ARM64vecb_UQADD16x8: *nm = "uqadd "; *ar = "8h"; return;
case ARM64vecb_UQADD8x16: *nm = "uqadd "; *ar = "16b"; return;
case ARM64vecb_SQSUB64x2: *nm = "sqsub "; *ar = "2d"; return;
case ARM64vecb_SQSUB32x4: *nm = "sqsub "; *ar = "4s"; return;
case ARM64vecb_SQSUB16x8: *nm = "sqsub "; *ar = "8h"; return;
case ARM64vecb_SQSUB8x16: *nm = "sqsub "; *ar = "16b"; return;
case ARM64vecb_UQSUB64x2: *nm = "uqsub "; *ar = "2d"; return;
case ARM64vecb_UQSUB32x4: *nm = "uqsub "; *ar = "4s"; return;
case ARM64vecb_UQSUB16x8: *nm = "uqsub "; *ar = "8h"; return;
case ARM64vecb_UQSUB8x16: *nm = "uqsub "; *ar = "16b"; return;
case ARM64vecb_SQDMULL2DSS: *nm = "sqdmull"; *ar = "2dss"; return;
case ARM64vecb_SQDMULL4SHH: *nm = "sqdmull"; *ar = "4shh"; return;
case ARM64vecb_SQDMULH32x4: *nm = "sqdmulh"; *ar = "4s"; return;
case ARM64vecb_SQDMULH16x8: *nm = "sqdmulh"; *ar = "8h"; return;
case ARM64vecb_SQRDMULH32x4: *nm = "sqrdmulh"; *ar = "4s"; return;
case ARM64vecb_SQRDMULH16x8: *nm = "sqrdmulh"; *ar = "8h"; return;
case ARM64vecb_SQSHL64x2: *nm = "sqshl "; *ar = "2d"; return;
case ARM64vecb_SQSHL32x4: *nm = "sqshl "; *ar = "4s"; return;
case ARM64vecb_SQSHL16x8: *nm = "sqshl "; *ar = "8h"; return;
case ARM64vecb_SQSHL8x16: *nm = "sqshl "; *ar = "16b"; return;
case ARM64vecb_UQSHL64x2: *nm = "uqshl "; *ar = "2d"; return;
case ARM64vecb_UQSHL32x4: *nm = "uqshl "; *ar = "4s"; return;
case ARM64vecb_UQSHL16x8: *nm = "uqshl "; *ar = "8h"; return;
case ARM64vecb_UQSHL8x16: *nm = "uqshl "; *ar = "16b"; return;
case ARM64vecb_SQRSHL64x2: *nm = "sqrshl"; *ar = "2d"; return;
case ARM64vecb_SQRSHL32x4: *nm = "sqrshl"; *ar = "4s"; return;
case ARM64vecb_SQRSHL16x8: *nm = "sqrshl"; *ar = "8h"; return;
case ARM64vecb_SQRSHL8x16: *nm = "sqrshl"; *ar = "16b"; return;
case ARM64vecb_UQRSHL64x2: *nm = "uqrshl"; *ar = "2d"; return;
case ARM64vecb_UQRSHL32x4: *nm = "uqrshl"; *ar = "4s"; return;
case ARM64vecb_UQRSHL16x8: *nm = "uqrshl"; *ar = "8h"; return;
case ARM64vecb_UQRSHL8x16: *nm = "uqrshl"; *ar = "16b"; return;
case ARM64vecb_SSHL64x2: *nm = "sshl"; *ar = "2d"; return;
case ARM64vecb_SSHL32x4: *nm = "sshl"; *ar = "4s"; return;
case ARM64vecb_SSHL16x8: *nm = "sshl"; *ar = "8h"; return;
case ARM64vecb_SSHL8x16: *nm = "sshl"; *ar = "16b"; return;
case ARM64vecb_USHL64x2: *nm = "ushl"; *ar = "2d"; return;
case ARM64vecb_USHL32x4: *nm = "ushl"; *ar = "4s"; return;
case ARM64vecb_USHL16x8: *nm = "ushl"; *ar = "8h"; return;
case ARM64vecb_USHL8x16: *nm = "ushl"; *ar = "16b"; return;
case ARM64vecb_SRSHL64x2: *nm = "srshl"; *ar = "2d"; return;
case ARM64vecb_SRSHL32x4: *nm = "srshl"; *ar = "4s"; return;
case ARM64vecb_SRSHL16x8: *nm = "srshl"; *ar = "8h"; return;
case ARM64vecb_SRSHL8x16: *nm = "srshl"; *ar = "16b"; return;
case ARM64vecb_URSHL64x2: *nm = "urshl"; *ar = "2d"; return;
case ARM64vecb_URSHL32x4: *nm = "urshl"; *ar = "4s"; return;
case ARM64vecb_URSHL16x8: *nm = "urshl"; *ar = "8h"; return;
case ARM64vecb_URSHL8x16: *nm = "urshl"; *ar = "16b"; return;
default: vpanic("showARM64VecBinOp");
}
}
static void showARM64VecModifyOp(/*OUT*/const HChar** nm,
/*OUT*/const HChar** ar,
ARM64VecModifyOp op ) {
switch (op) {
case ARM64vecmo_SUQADD64x2: *nm = "suqadd"; *ar = "2d"; return;
case ARM64vecmo_SUQADD32x4: *nm = "suqadd"; *ar = "4s"; return;
case ARM64vecmo_SUQADD16x8: *nm = "suqadd"; *ar = "8h"; return;
case ARM64vecmo_SUQADD8x16: *nm = "suqadd"; *ar = "16b"; return;
case ARM64vecmo_USQADD64x2: *nm = "usqadd"; *ar = "2d"; return;
case ARM64vecmo_USQADD32x4: *nm = "usqadd"; *ar = "4s"; return;
case ARM64vecmo_USQADD16x8: *nm = "usqadd"; *ar = "8h"; return;
case ARM64vecmo_USQADD8x16: *nm = "usqadd"; *ar = "16b"; return;
default: vpanic("showARM64VecModifyOp");
}
}
static void showARM64VecUnaryOp(/*OUT*/const HChar** nm,
/*OUT*/const HChar** ar, ARM64VecUnaryOp op )
{
switch (op) {
case ARM64vecu_FNEG64x2: *nm = "fneg "; *ar = "2d"; return;
case ARM64vecu_FNEG32x4: *nm = "fneg "; *ar = "4s"; return;
case ARM64vecu_FABS64x2: *nm = "fabs "; *ar = "2d"; return;
case ARM64vecu_FABS32x4: *nm = "fabs "; *ar = "4s"; return;
case ARM64vecu_NOT: *nm = "not "; *ar = "all"; return;
case ARM64vecu_ABS64x2: *nm = "abs "; *ar = "2d"; return;
case ARM64vecu_ABS32x4: *nm = "abs "; *ar = "4s"; return;
case ARM64vecu_ABS16x8: *nm = "abs "; *ar = "8h"; return;
case ARM64vecu_ABS8x16: *nm = "abs "; *ar = "16b"; return;
case ARM64vecu_CLS32x4: *nm = "cls "; *ar = "4s"; return;
case ARM64vecu_CLS16x8: *nm = "cls "; *ar = "8h"; return;
case ARM64vecu_CLS8x16: *nm = "cls "; *ar = "16b"; return;
case ARM64vecu_CLZ32x4: *nm = "clz "; *ar = "4s"; return;
case ARM64vecu_CLZ16x8: *nm = "clz "; *ar = "8h"; return;
case ARM64vecu_CLZ8x16: *nm = "clz "; *ar = "16b"; return;
case ARM64vecu_CNT8x16: *nm = "cnt "; *ar = "16b"; return;
case ARM64vecu_RBIT: *nm = "rbit "; *ar = "16b"; return;
case ARM64vecu_REV1616B: *nm = "rev16"; *ar = "16b"; return;
case ARM64vecu_REV3216B: *nm = "rev32"; *ar = "16b"; return;
case ARM64vecu_REV328H: *nm = "rev32"; *ar = "8h"; return;
case ARM64vecu_REV6416B: *nm = "rev64"; *ar = "16b"; return;
case ARM64vecu_REV648H: *nm = "rev64"; *ar = "8h"; return;
case ARM64vecu_REV644S: *nm = "rev64"; *ar = "4s"; return;
case ARM64vecu_URECPE32x4: *nm = "urecpe"; *ar = "4s"; return;
case ARM64vecu_URSQRTE32x4: *nm = "ursqrte"; *ar = "4s"; return;
default: vpanic("showARM64VecUnaryOp");
}
}
static void showARM64VecShiftImmOp(/*OUT*/const HChar** nm,
/*OUT*/const HChar** ar,
ARM64VecShiftImmOp op )
{
switch (op) {
case ARM64vecshi_USHR64x2: *nm = "ushr "; *ar = "2d"; return;
case ARM64vecshi_USHR32x4: *nm = "ushr "; *ar = "4s"; return;
case ARM64vecshi_USHR16x8: *nm = "ushr "; *ar = "8h"; return;
case ARM64vecshi_USHR8x16: *nm = "ushr "; *ar = "16b"; return;
case ARM64vecshi_SSHR64x2: *nm = "sshr "; *ar = "2d"; return;
case ARM64vecshi_SSHR32x4: *nm = "sshr "; *ar = "4s"; return;
case ARM64vecshi_SSHR16x8: *nm = "sshr "; *ar = "8h"; return;
case ARM64vecshi_SSHR8x16: *nm = "sshr "; *ar = "16b"; return;
case ARM64vecshi_SHL64x2: *nm = "shl "; *ar = "2d"; return;
case ARM64vecshi_SHL32x4: *nm = "shl "; *ar = "4s"; return;
case ARM64vecshi_SHL16x8: *nm = "shl "; *ar = "8h"; return;
case ARM64vecshi_SHL8x16: *nm = "shl "; *ar = "16b"; return;
case ARM64vecshi_SQSHRN2SD: *nm = "sqshrn"; *ar = "2sd"; return;
case ARM64vecshi_SQSHRN4HS: *nm = "sqshrn"; *ar = "4hs"; return;
case ARM64vecshi_SQSHRN8BH: *nm = "sqshrn"; *ar = "8bh"; return;
case ARM64vecshi_UQSHRN2SD: *nm = "uqshrn"; *ar = "2sd"; return;
case ARM64vecshi_UQSHRN4HS: *nm = "uqshrn"; *ar = "4hs"; return;
case ARM64vecshi_UQSHRN8BH: *nm = "uqshrn"; *ar = "8bh"; return;
case ARM64vecshi_SQSHRUN2SD: *nm = "sqshrun"; *ar = "2sd"; return;
case ARM64vecshi_SQSHRUN4HS: *nm = "sqshrun"; *ar = "4hs"; return;
case ARM64vecshi_SQSHRUN8BH: *nm = "sqshrun"; *ar = "8bh"; return;
case ARM64vecshi_SQRSHRN2SD: *nm = "sqrshrn"; *ar = "2sd"; return;
case ARM64vecshi_SQRSHRN4HS: *nm = "sqrshrn"; *ar = "4hs"; return;
case ARM64vecshi_SQRSHRN8BH: *nm = "sqrshrn"; *ar = "8bh"; return;
case ARM64vecshi_UQRSHRN2SD: *nm = "uqrshrn"; *ar = "2sd"; return;
case ARM64vecshi_UQRSHRN4HS: *nm = "uqrshrn"; *ar = "4hs"; return;
case ARM64vecshi_UQRSHRN8BH: *nm = "uqrshrn"; *ar = "8bh"; return;
case ARM64vecshi_SQRSHRUN2SD: *nm = "sqrshrun"; *ar = "2sd"; return;
case ARM64vecshi_SQRSHRUN4HS: *nm = "sqrshrun"; *ar = "4hs"; return;
case ARM64vecshi_SQRSHRUN8BH: *nm = "sqrshrun"; *ar = "8bh"; return;
case ARM64vecshi_UQSHL64x2: *nm = "uqshl "; *ar = "2d"; return;
case ARM64vecshi_UQSHL32x4: *nm = "uqshl "; *ar = "4s"; return;
case ARM64vecshi_UQSHL16x8: *nm = "uqshl "; *ar = "8h"; return;
case ARM64vecshi_UQSHL8x16: *nm = "uqshl "; *ar = "16b"; return;
case ARM64vecshi_SQSHL64x2: *nm = "sqshl "; *ar = "2d"; return;
case ARM64vecshi_SQSHL32x4: *nm = "sqshl "; *ar = "4s"; return;
case ARM64vecshi_SQSHL16x8: *nm = "sqshl "; *ar = "8h"; return;
case ARM64vecshi_SQSHL8x16: *nm = "sqshl "; *ar = "16b"; return;
case ARM64vecshi_SQSHLU64x2: *nm = "sqshlu"; *ar = "2d"; return;
case ARM64vecshi_SQSHLU32x4: *nm = "sqshlu"; *ar = "4s"; return;
case ARM64vecshi_SQSHLU16x8: *nm = "sqshlu"; *ar = "8h"; return;
case ARM64vecshi_SQSHLU8x16: *nm = "sqshlu"; *ar = "16b"; return;
default: vpanic("showARM64VecShiftImmOp");
}
}
static const HChar* showARM64VecNarrowOp(ARM64VecNarrowOp op) {
switch (op) {
case ARM64vecna_XTN: return "xtn ";
case ARM64vecna_SQXTN: return "sqxtn ";
case ARM64vecna_UQXTN: return "uqxtn ";
case ARM64vecna_SQXTUN: return "sqxtun";
default: vpanic("showARM64VecNarrowOp");
}
}
ARM64Instr* ARM64Instr_Arith ( HReg dst,
HReg argL, ARM64RIA* argR, Bool isAdd ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_Arith;
i->ARM64in.Arith.dst = dst;
i->ARM64in.Arith.argL = argL;
i->ARM64in.Arith.argR = argR;
i->ARM64in.Arith.isAdd = isAdd;
return i;
}
ARM64Instr* ARM64Instr_Cmp ( HReg argL, ARM64RIA* argR, Bool is64 ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_Cmp;
i->ARM64in.Cmp.argL = argL;
i->ARM64in.Cmp.argR = argR;
i->ARM64in.Cmp.is64 = is64;
return i;
}
ARM64Instr* ARM64Instr_Logic ( HReg dst,
HReg argL, ARM64RIL* argR, ARM64LogicOp op ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_Logic;
i->ARM64in.Logic.dst = dst;
i->ARM64in.Logic.argL = argL;
i->ARM64in.Logic.argR = argR;
i->ARM64in.Logic.op = op;
return i;
}
ARM64Instr* ARM64Instr_Test ( HReg argL, ARM64RIL* argR ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_Test;
i->ARM64in.Test.argL = argL;
i->ARM64in.Test.argR = argR;
return i;
}
ARM64Instr* ARM64Instr_Shift ( HReg dst,
HReg argL, ARM64RI6* argR, ARM64ShiftOp op ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_Shift;
i->ARM64in.Shift.dst = dst;
i->ARM64in.Shift.argL = argL;
i->ARM64in.Shift.argR = argR;
i->ARM64in.Shift.op = op;
return i;
}
ARM64Instr* ARM64Instr_Unary ( HReg dst, HReg src, ARM64UnaryOp op ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_Unary;
i->ARM64in.Unary.dst = dst;
i->ARM64in.Unary.src = src;
i->ARM64in.Unary.op = op;
return i;
}
ARM64Instr* ARM64Instr_MovI ( HReg dst, HReg src ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_MovI;
i->ARM64in.MovI.dst = dst;
i->ARM64in.MovI.src = src;
vassert(hregClass(src) == HRcInt64);
vassert(hregClass(dst) == HRcInt64);
return i;
}
ARM64Instr* ARM64Instr_Imm64 ( HReg dst, ULong imm64 ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_Imm64;
i->ARM64in.Imm64.dst = dst;
i->ARM64in.Imm64.imm64 = imm64;
return i;
}
ARM64Instr* ARM64Instr_LdSt64 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_LdSt64;
i->ARM64in.LdSt64.isLoad = isLoad;
i->ARM64in.LdSt64.rD = rD;
i->ARM64in.LdSt64.amode = amode;
return i;
}
ARM64Instr* ARM64Instr_LdSt32 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_LdSt32;
i->ARM64in.LdSt32.isLoad = isLoad;
i->ARM64in.LdSt32.rD = rD;
i->ARM64in.LdSt32.amode = amode;
return i;
}
ARM64Instr* ARM64Instr_LdSt16 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_LdSt16;
i->ARM64in.LdSt16.isLoad = isLoad;
i->ARM64in.LdSt16.rD = rD;
i->ARM64in.LdSt16.amode = amode;
return i;
}
ARM64Instr* ARM64Instr_LdSt8 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_LdSt8;
i->ARM64in.LdSt8.isLoad = isLoad;
i->ARM64in.LdSt8.rD = rD;
i->ARM64in.LdSt8.amode = amode;
return i;
}
ARM64Instr* ARM64Instr_XDirect ( Addr64 dstGA, ARM64AMode* amPC,
ARM64CondCode cond, Bool toFastEP ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_XDirect;
i->ARM64in.XDirect.dstGA = dstGA;
i->ARM64in.XDirect.amPC = amPC;
i->ARM64in.XDirect.cond = cond;
i->ARM64in.XDirect.toFastEP = toFastEP;
return i;
}
ARM64Instr* ARM64Instr_XIndir ( HReg dstGA, ARM64AMode* amPC,
ARM64CondCode cond ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_XIndir;
i->ARM64in.XIndir.dstGA = dstGA;
i->ARM64in.XIndir.amPC = amPC;
i->ARM64in.XIndir.cond = cond;
return i;
}
ARM64Instr* ARM64Instr_XAssisted ( HReg dstGA, ARM64AMode* amPC,
ARM64CondCode cond, IRJumpKind jk ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_XAssisted;
i->ARM64in.XAssisted.dstGA = dstGA;
i->ARM64in.XAssisted.amPC = amPC;
i->ARM64in.XAssisted.cond = cond;
i->ARM64in.XAssisted.jk = jk;
return i;
}
ARM64Instr* ARM64Instr_CSel ( HReg dst, HReg argL, HReg argR,
ARM64CondCode cond ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_CSel;
i->ARM64in.CSel.dst = dst;
i->ARM64in.CSel.argL = argL;
i->ARM64in.CSel.argR = argR;
i->ARM64in.CSel.cond = cond;
return i;
}
ARM64Instr* ARM64Instr_Call ( ARM64CondCode cond, HWord target, Int nArgRegs,
RetLoc rloc ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_Call;
i->ARM64in.Call.cond = cond;
i->ARM64in.Call.target = target;
i->ARM64in.Call.nArgRegs = nArgRegs;
i->ARM64in.Call.rloc = rloc;
vassert(is_sane_RetLoc(rloc));
return i;
}
extern ARM64Instr* ARM64Instr_AddToSP ( Int simm ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_AddToSP;
i->ARM64in.AddToSP.simm = simm;
vassert(-4096 < simm && simm < 4096);
vassert(0 == (simm & 0xF));
return i;
}
extern ARM64Instr* ARM64Instr_FromSP ( HReg dst ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_FromSP;
i->ARM64in.FromSP.dst = dst;
return i;
}
ARM64Instr* ARM64Instr_Mul ( HReg dst, HReg argL, HReg argR,
ARM64MulOp op ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_Mul;
i->ARM64in.Mul.dst = dst;
i->ARM64in.Mul.argL = argL;
i->ARM64in.Mul.argR = argR;
i->ARM64in.Mul.op = op;
return i;
}
ARM64Instr* ARM64Instr_LdrEX ( Int szB ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_LdrEX;
i->ARM64in.LdrEX.szB = szB;
vassert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
return i;
}
ARM64Instr* ARM64Instr_StrEX ( Int szB ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_StrEX;
i->ARM64in.StrEX.szB = szB;
vassert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
return i;
}
ARM64Instr* ARM64Instr_MFence ( void ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_MFence;
return i;
}
ARM64Instr* ARM64Instr_VLdStS ( Bool isLoad, HReg sD, HReg rN, UInt uimm12 ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VLdStS;
i->ARM64in.VLdStS.isLoad = isLoad;
i->ARM64in.VLdStS.sD = sD;
i->ARM64in.VLdStS.rN = rN;
i->ARM64in.VLdStS.uimm12 = uimm12;
vassert(uimm12 < 16384 && 0 == (uimm12 & 3));
return i;
}
ARM64Instr* ARM64Instr_VLdStD ( Bool isLoad, HReg dD, HReg rN, UInt uimm12 ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VLdStD;
i->ARM64in.VLdStD.isLoad = isLoad;
i->ARM64in.VLdStD.dD = dD;
i->ARM64in.VLdStD.rN = rN;
i->ARM64in.VLdStD.uimm12 = uimm12;
vassert(uimm12 < 32768 && 0 == (uimm12 & 7));
return i;
}
ARM64Instr* ARM64Instr_VLdStQ ( Bool isLoad, HReg rQ, HReg rN ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VLdStQ;
i->ARM64in.VLdStQ.isLoad = isLoad;
i->ARM64in.VLdStQ.rQ = rQ;
i->ARM64in.VLdStQ.rN = rN;
return i;
}
ARM64Instr* ARM64Instr_VCvtI2F ( ARM64CvtOp how, HReg rD, HReg rS ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VCvtI2F;
i->ARM64in.VCvtI2F.how = how;
i->ARM64in.VCvtI2F.rD = rD;
i->ARM64in.VCvtI2F.rS = rS;
return i;
}
ARM64Instr* ARM64Instr_VCvtF2I ( ARM64CvtOp how, HReg rD, HReg rS,
UChar armRM ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VCvtF2I;
i->ARM64in.VCvtF2I.how = how;
i->ARM64in.VCvtF2I.rD = rD;
i->ARM64in.VCvtF2I.rS = rS;
i->ARM64in.VCvtF2I.armRM = armRM;
vassert(armRM <= 3);
return i;
}
ARM64Instr* ARM64Instr_VCvtSD ( Bool sToD, HReg dst, HReg src ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VCvtSD;
i->ARM64in.VCvtSD.sToD = sToD;
i->ARM64in.VCvtSD.dst = dst;
i->ARM64in.VCvtSD.src = src;
return i;
}
ARM64Instr* ARM64Instr_VUnaryD ( ARM64FpUnaryOp op, HReg dst, HReg src ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VUnaryD;
i->ARM64in.VUnaryD.op = op;
i->ARM64in.VUnaryD.dst = dst;
i->ARM64in.VUnaryD.src = src;
return i;
}
ARM64Instr* ARM64Instr_VUnaryS ( ARM64FpUnaryOp op, HReg dst, HReg src ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VUnaryS;
i->ARM64in.VUnaryS.op = op;
i->ARM64in.VUnaryS.dst = dst;
i->ARM64in.VUnaryS.src = src;
return i;
}
ARM64Instr* ARM64Instr_VBinD ( ARM64FpBinOp op,
HReg dst, HReg argL, HReg argR ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VBinD;
i->ARM64in.VBinD.op = op;
i->ARM64in.VBinD.dst = dst;
i->ARM64in.VBinD.argL = argL;
i->ARM64in.VBinD.argR = argR;
return i;
}
ARM64Instr* ARM64Instr_VBinS ( ARM64FpBinOp op,
HReg dst, HReg argL, HReg argR ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VBinS;
i->ARM64in.VBinS.op = op;
i->ARM64in.VBinS.dst = dst;
i->ARM64in.VBinS.argL = argL;
i->ARM64in.VBinS.argR = argR;
return i;
}
ARM64Instr* ARM64Instr_VCmpD ( HReg argL, HReg argR ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VCmpD;
i->ARM64in.VCmpD.argL = argL;
i->ARM64in.VCmpD.argR = argR;
return i;
}
ARM64Instr* ARM64Instr_VCmpS ( HReg argL, HReg argR ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VCmpS;
i->ARM64in.VCmpS.argL = argL;
i->ARM64in.VCmpS.argR = argR;
return i;
}
ARM64Instr* ARM64Instr_FPCR ( Bool toFPCR, HReg iReg ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_FPCR;
i->ARM64in.FPCR.toFPCR = toFPCR;
i->ARM64in.FPCR.iReg = iReg;
return i;
}
ARM64Instr* ARM64Instr_FPSR ( Bool toFPSR, HReg iReg ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_FPSR;
i->ARM64in.FPSR.toFPSR = toFPSR;
i->ARM64in.FPSR.iReg = iReg;
return i;
}
ARM64Instr* ARM64Instr_VBinV ( ARM64VecBinOp op,
HReg dst, HReg argL, HReg argR ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VBinV;
i->ARM64in.VBinV.op = op;
i->ARM64in.VBinV.dst = dst;
i->ARM64in.VBinV.argL = argL;
i->ARM64in.VBinV.argR = argR;
return i;
}
ARM64Instr* ARM64Instr_VModifyV ( ARM64VecModifyOp op, HReg mod, HReg arg ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VModifyV;
i->ARM64in.VModifyV.op = op;
i->ARM64in.VModifyV.mod = mod;
i->ARM64in.VModifyV.arg = arg;
return i;
}
ARM64Instr* ARM64Instr_VUnaryV ( ARM64VecUnaryOp op, HReg dst, HReg arg ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VUnaryV;
i->ARM64in.VUnaryV.op = op;
i->ARM64in.VUnaryV.dst = dst;
i->ARM64in.VUnaryV.arg = arg;
return i;
}
ARM64Instr* ARM64Instr_VNarrowV ( ARM64VecNarrowOp op,
UInt dszBlg2, HReg dst, HReg src ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VNarrowV;
i->ARM64in.VNarrowV.op = op;
i->ARM64in.VNarrowV.dszBlg2 = dszBlg2;
i->ARM64in.VNarrowV.dst = dst;
i->ARM64in.VNarrowV.src = src;
vassert(dszBlg2 == 0 || dszBlg2 == 1 || dszBlg2 == 2);
return i;
}
ARM64Instr* ARM64Instr_VShiftImmV ( ARM64VecShiftImmOp op,
HReg dst, HReg src, UInt amt ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VShiftImmV;
i->ARM64in.VShiftImmV.op = op;
i->ARM64in.VShiftImmV.dst = dst;
i->ARM64in.VShiftImmV.src = src;
i->ARM64in.VShiftImmV.amt = amt;
UInt minSh = 0;
UInt maxSh = 0;
switch (op) {
/* For right shifts, the allowed shift amounts are 1 .. lane_size.
For left shifts, the allowed shift amounts are 0 .. lane_size-1.
*/
case ARM64vecshi_USHR64x2: case ARM64vecshi_SSHR64x2:
case ARM64vecshi_UQSHRN2SD: case ARM64vecshi_SQSHRN2SD:
case ARM64vecshi_SQSHRUN2SD:
case ARM64vecshi_UQRSHRN2SD: case ARM64vecshi_SQRSHRN2SD:
case ARM64vecshi_SQRSHRUN2SD:
minSh = 1; maxSh = 64; break;
case ARM64vecshi_SHL64x2:
case ARM64vecshi_UQSHL64x2: case ARM64vecshi_SQSHL64x2:
case ARM64vecshi_SQSHLU64x2:
minSh = 0; maxSh = 63; break;
case ARM64vecshi_USHR32x4: case ARM64vecshi_SSHR32x4:
case ARM64vecshi_UQSHRN4HS: case ARM64vecshi_SQSHRN4HS:
case ARM64vecshi_SQSHRUN4HS:
case ARM64vecshi_UQRSHRN4HS: case ARM64vecshi_SQRSHRN4HS:
case ARM64vecshi_SQRSHRUN4HS:
minSh = 1; maxSh = 32; break;
case ARM64vecshi_SHL32x4:
case ARM64vecshi_UQSHL32x4: case ARM64vecshi_SQSHL32x4:
case ARM64vecshi_SQSHLU32x4:
minSh = 0; maxSh = 31; break;
case ARM64vecshi_USHR16x8: case ARM64vecshi_SSHR16x8:
case ARM64vecshi_UQSHRN8BH: case ARM64vecshi_SQSHRN8BH:
case ARM64vecshi_SQSHRUN8BH:
case ARM64vecshi_UQRSHRN8BH: case ARM64vecshi_SQRSHRN8BH:
case ARM64vecshi_SQRSHRUN8BH:
minSh = 1; maxSh = 16; break;
case ARM64vecshi_SHL16x8:
case ARM64vecshi_UQSHL16x8: case ARM64vecshi_SQSHL16x8:
case ARM64vecshi_SQSHLU16x8:
minSh = 0; maxSh = 15; break;
case ARM64vecshi_USHR8x16: case ARM64vecshi_SSHR8x16:
minSh = 1; maxSh = 8; break;
case ARM64vecshi_SHL8x16:
case ARM64vecshi_UQSHL8x16: case ARM64vecshi_SQSHL8x16:
case ARM64vecshi_SQSHLU8x16:
minSh = 0; maxSh = 7; break;
default:
vassert(0);
}
vassert(maxSh > 0);
vassert(amt >= minSh && amt <= maxSh);
return i;
}
ARM64Instr* ARM64Instr_VExtV ( HReg dst, HReg srcLo, HReg srcHi, UInt amtB ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VExtV;
i->ARM64in.VExtV.dst = dst;
i->ARM64in.VExtV.srcLo = srcLo;
i->ARM64in.VExtV.srcHi = srcHi;
i->ARM64in.VExtV.amtB = amtB;
vassert(amtB >= 1 && amtB <= 15);
return i;
}
ARM64Instr* ARM64Instr_VImmQ (HReg rQ, UShort imm) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VImmQ;
i->ARM64in.VImmQ.rQ = rQ;
i->ARM64in.VImmQ.imm = imm;
return i;
}
ARM64Instr* ARM64Instr_VDfromX ( HReg rD, HReg rX ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VDfromX;
i->ARM64in.VDfromX.rD = rD;
i->ARM64in.VDfromX.rX = rX;
return i;
}
ARM64Instr* ARM64Instr_VQfromX ( HReg rQ, HReg rXlo ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VQfromX;
i->ARM64in.VQfromX.rQ = rQ;
i->ARM64in.VQfromX.rXlo = rXlo;
return i;
}
ARM64Instr* ARM64Instr_VQfromXX ( HReg rQ, HReg rXhi, HReg rXlo ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VQfromXX;
i->ARM64in.VQfromXX.rQ = rQ;
i->ARM64in.VQfromXX.rXhi = rXhi;
i->ARM64in.VQfromXX.rXlo = rXlo;
return i;
}
ARM64Instr* ARM64Instr_VXfromQ ( HReg rX, HReg rQ, UInt laneNo ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VXfromQ;
i->ARM64in.VXfromQ.rX = rX;
i->ARM64in.VXfromQ.rQ = rQ;
i->ARM64in.VXfromQ.laneNo = laneNo;
vassert(laneNo <= 1);
return i;
}
ARM64Instr* ARM64Instr_VXfromDorS ( HReg rX, HReg rDorS, Bool fromD ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VXfromDorS;
i->ARM64in.VXfromDorS.rX = rX;
i->ARM64in.VXfromDorS.rDorS = rDorS;
i->ARM64in.VXfromDorS.fromD = fromD;
return i;
}
ARM64Instr* ARM64Instr_VMov ( UInt szB, HReg dst, HReg src ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_VMov;
i->ARM64in.VMov.szB = szB;
i->ARM64in.VMov.dst = dst;
i->ARM64in.VMov.src = src;
switch (szB) {
case 16:
vassert(hregClass(src) == HRcVec128);
vassert(hregClass(dst) == HRcVec128);
break;
case 8:
vassert(hregClass(src) == HRcFlt64);
vassert(hregClass(dst) == HRcFlt64);
break;
default:
vpanic("ARM64Instr_VMov");
}
return i;
}
ARM64Instr* ARM64Instr_EvCheck ( ARM64AMode* amCounter,
ARM64AMode* amFailAddr ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_EvCheck;
i->ARM64in.EvCheck.amCounter = amCounter;
i->ARM64in.EvCheck.amFailAddr = amFailAddr;
return i;
}
ARM64Instr* ARM64Instr_ProfInc ( void ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_ProfInc;
return i;
}
/* ... */
void ppARM64Instr ( ARM64Instr* i ) {
switch (i->tag) {
case ARM64in_Arith:
vex_printf("%s ", i->ARM64in.Arith.isAdd ? "add" : "sub");
ppHRegARM64(i->ARM64in.Arith.dst);
vex_printf(", ");
ppHRegARM64(i->ARM64in.Arith.argL);
vex_printf(", ");
ppARM64RIA(i->ARM64in.Arith.argR);
return;
case ARM64in_Cmp:
vex_printf("cmp%s ", i->ARM64in.Cmp.is64 ? " " : "(w)" );
ppHRegARM64(i->ARM64in.Cmp.argL);
vex_printf(", ");
ppARM64RIA(i->ARM64in.Cmp.argR);
return;
case ARM64in_Logic:
vex_printf("%s ", showARM64LogicOp(i->ARM64in.Logic.op));
ppHRegARM64(i->ARM64in.Logic.dst);
vex_printf(", ");
ppHRegARM64(i->ARM64in.Logic.argL);
vex_printf(", ");
ppARM64RIL(i->ARM64in.Logic.argR);
return;
case ARM64in_Test:
vex_printf("tst ");
ppHRegARM64(i->ARM64in.Test.argL);
vex_printf(", ");
ppARM64RIL(i->ARM64in.Test.argR);
return;
case ARM64in_Shift:
vex_printf("%s ", showARM64ShiftOp(i->ARM64in.Shift.op));
ppHRegARM64(i->ARM64in.Shift.dst);
vex_printf(", ");
ppHRegARM64(i->ARM64in.Shift.argL);
vex_printf(", ");
ppARM64RI6(i->ARM64in.Shift.argR);
return;
case ARM64in_Unary:
vex_printf("%s ", showARM64UnaryOp(i->ARM64in.Unary.op));
ppHRegARM64(i->ARM64in.Unary.dst);
vex_printf(", ");
ppHRegARM64(i->ARM64in.Unary.src);
return;
case ARM64in_MovI:
vex_printf("mov ");
ppHRegARM64(i->ARM64in.MovI.dst);
vex_printf(", ");
ppHRegARM64(i->ARM64in.MovI.src);
return;
case ARM64in_Imm64:
vex_printf("imm64 ");
ppHRegARM64(i->ARM64in.Imm64.dst);
vex_printf(", 0x%llx", i->ARM64in.Imm64.imm64);
return;
case ARM64in_LdSt64:
if (i->ARM64in.LdSt64.isLoad) {
vex_printf("ldr ");
ppHRegARM64(i->ARM64in.LdSt64.rD);
vex_printf(", ");
ppARM64AMode(i->ARM64in.LdSt64.amode);
} else {
vex_printf("str ");
ppARM64AMode(i->ARM64in.LdSt64.amode);
vex_printf(", ");
ppHRegARM64(i->ARM64in.LdSt64.rD);
}
return;
case ARM64in_LdSt32:
if (i->ARM64in.LdSt32.isLoad) {
vex_printf("ldruw ");
ppHRegARM64(i->ARM64in.LdSt32.rD);
vex_printf(", ");
ppARM64AMode(i->ARM64in.LdSt32.amode);
} else {
vex_printf("strw ");
ppARM64AMode(i->ARM64in.LdSt32.amode);
vex_printf(", ");
ppHRegARM64(i->ARM64in.LdSt32.rD);
}
return;
case ARM64in_LdSt16:
if (i->ARM64in.LdSt16.isLoad) {
vex_printf("ldruh ");
ppHRegARM64(i->ARM64in.LdSt16.rD);
vex_printf(", ");
ppARM64AMode(i->ARM64in.LdSt16.amode);
} else {
vex_printf("strh ");
ppARM64AMode(i->ARM64in.LdSt16.amode);
vex_printf(", ");
ppHRegARM64(i->ARM64in.LdSt16.rD);
}
return;
case ARM64in_LdSt8:
if (i->ARM64in.LdSt8.isLoad) {
vex_printf("ldrub ");
ppHRegARM64(i->ARM64in.LdSt8.rD);
vex_printf(", ");
ppARM64AMode(i->ARM64in.LdSt8.amode);
} else {
vex_printf("strb ");
ppARM64AMode(i->ARM64in.LdSt8.amode);
vex_printf(", ");
ppHRegARM64(i->ARM64in.LdSt8.rD);
}
return;
case ARM64in_XDirect:
vex_printf("(xDirect) ");
vex_printf("if (%%pstate.%s) { ",
showARM64CondCode(i->ARM64in.XDirect.cond));
vex_printf("imm64 x9,0x%llx; ", i->ARM64in.XDirect.dstGA);
vex_printf("str x9,");
ppARM64AMode(i->ARM64in.XDirect.amPC);
vex_printf("; imm64-exactly4 x9,$disp_cp_chain_me_to_%sEP; ",
i->ARM64in.XDirect.toFastEP ? "fast" : "slow");
vex_printf("blr x9 }");
return;
case ARM64in_XIndir:
vex_printf("(xIndir) ");
vex_printf("if (%%pstate.%s) { ",
showARM64CondCode(i->ARM64in.XIndir.cond));
vex_printf("str ");
ppHRegARM64(i->ARM64in.XIndir.dstGA);
vex_printf(",");
ppARM64AMode(i->ARM64in.XIndir.amPC);
vex_printf("; imm64 x9,$disp_cp_xindir; ");
vex_printf("br x9 }");
return;
case ARM64in_XAssisted:
vex_printf("(xAssisted) ");
vex_printf("if (%%pstate.%s) { ",
showARM64CondCode(i->ARM64in.XAssisted.cond));
vex_printf("str ");
ppHRegARM64(i->ARM64in.XAssisted.dstGA);
vex_printf(",");
ppARM64AMode(i->ARM64in.XAssisted.amPC);
vex_printf("; movw x21,$IRJumpKind_to_TRCVAL(%d); ",
(Int)i->ARM64in.XAssisted.jk);
vex_printf("imm64 x9,$disp_cp_xassisted; ");
vex_printf("br x9 }");
return;
case ARM64in_CSel:
vex_printf("csel ");
ppHRegARM64(i->ARM64in.CSel.dst);
vex_printf(", ");
ppHRegARM64(i->ARM64in.CSel.argL);
vex_printf(", ");
ppHRegARM64(i->ARM64in.CSel.argR);
vex_printf(", %s", showARM64CondCode(i->ARM64in.CSel.cond));
return;
case ARM64in_Call:
vex_printf("call%s ",
i->ARM64in.Call.cond==ARM64cc_AL
? " " : showARM64CondCode(i->ARM64in.Call.cond));
vex_printf("0x%lx [nArgRegs=%d, ",
i->ARM64in.Call.target, i->ARM64in.Call.nArgRegs);
ppRetLoc(i->ARM64in.Call.rloc);
vex_printf("]");
return;
case ARM64in_AddToSP: {
Int simm = i->ARM64in.AddToSP.simm;
vex_printf("%s xsp, xsp, #%d", simm < 0 ? "sub" : "add",
simm < 0 ? -simm : simm);
return;
}
case ARM64in_FromSP:
vex_printf("mov ");
ppHRegARM64(i->ARM64in.FromSP.dst);
vex_printf(", xsp");
return;
case ARM64in_Mul:
vex_printf("%s ", showARM64MulOp(i->ARM64in.Mul.op));
ppHRegARM64(i->ARM64in.Mul.dst);
vex_printf(", ");
ppHRegARM64(i->ARM64in.Mul.argL);
vex_printf(", ");
ppHRegARM64(i->ARM64in.Mul.argR);
return;
case ARM64in_LdrEX: {
const HChar* sz = " ";
switch (i->ARM64in.LdrEX.szB) {
case 1: sz = "b"; break;
case 2: sz = "h"; break;
case 4: case 8: break;
default: vassert(0);
}
vex_printf("ldxr%s %c2, [x4]",
sz, i->ARM64in.LdrEX.szB == 8 ? 'x' : 'w');
return;
}
case ARM64in_StrEX: {
const HChar* sz = " ";
switch (i->ARM64in.StrEX.szB) {
case 1: sz = "b"; break;
case 2: sz = "h"; break;
case 4: case 8: break;
default: vassert(0);
}
vex_printf("stxr%s w0, %c2, [x4]",
sz, i->ARM64in.StrEX.szB == 8 ? 'x' : 'w');
return;
}
case ARM64in_MFence:
vex_printf("(mfence) dsb sy; dmb sy; isb");
return;
case ARM64in_VLdStS:
if (i->ARM64in.VLdStS.isLoad) {
vex_printf("ldr ");
ppHRegARM64asSreg(i->ARM64in.VLdStS.sD);
vex_printf(", %u(", i->ARM64in.VLdStS.uimm12);
ppHRegARM64(i->ARM64in.VLdStS.rN);
vex_printf(")");
} else {
vex_printf("str ");
vex_printf("%u(", i->ARM64in.VLdStS.uimm12);
ppHRegARM64(i->ARM64in.VLdStS.rN);
vex_printf("), ");
ppHRegARM64asSreg(i->ARM64in.VLdStS.sD);
}
return;
case ARM64in_VLdStD:
if (i->ARM64in.VLdStD.isLoad) {
vex_printf("ldr ");
ppHRegARM64(i->ARM64in.VLdStD.dD);
vex_printf(", %u(", i->ARM64in.VLdStD.uimm12);
ppHRegARM64(i->ARM64in.VLdStD.rN);
vex_printf(")");
} else {
vex_printf("str ");
vex_printf("%u(", i->ARM64in.VLdStD.uimm12);
ppHRegARM64(i->ARM64in.VLdStD.rN);
vex_printf("), ");
ppHRegARM64(i->ARM64in.VLdStD.dD);
}
return;
case ARM64in_VLdStQ:
if (i->ARM64in.VLdStQ.isLoad)
vex_printf("ld1.2d {");
else
vex_printf("st1.2d {");
ppHRegARM64(i->ARM64in.VLdStQ.rQ);
vex_printf("}, [");
ppHRegARM64(i->ARM64in.VLdStQ.rN);
vex_printf("]");
return;
case ARM64in_VCvtI2F: {
HChar syn = '?';
UInt fszB = 0;
UInt iszB = 0;
characteriseARM64CvtOp(&syn, &fszB, &iszB, i->ARM64in.VCvtI2F.how);
vex_printf("%ccvtf ", syn);
ppHRegARM64(i->ARM64in.VCvtI2F.rD);
vex_printf("(%c-reg), ", fszB == 4 ? 'S' : 'D');
ppHRegARM64(i->ARM64in.VCvtI2F.rS);
vex_printf("(%c-reg)", iszB == 4 ? 'W' : 'X');
return;
}
case ARM64in_VCvtF2I: {
HChar syn = '?';
UInt fszB = 0;
UInt iszB = 0;
HChar rmo = '?';
characteriseARM64CvtOp(&syn, &fszB, &iszB, i->ARM64in.VCvtF2I.how);
UChar armRM = i->ARM64in.VCvtF2I.armRM;
if (armRM < 4) rmo = "npmz"[armRM];
vex_printf("fcvt%c%c ", rmo, syn);
ppHRegARM64(i->ARM64in.VCvtF2I.rD);
vex_printf("(%c-reg), ", iszB == 4 ? 'W' : 'X');
ppHRegARM64(i->ARM64in.VCvtF2I.rS);
vex_printf("(%c-reg)", fszB == 4 ? 'S' : 'D');
return;
}
case ARM64in_VCvtSD:
vex_printf("fcvt%s ", i->ARM64in.VCvtSD.sToD ? "s2d" : "d2s");
if (i->ARM64in.VCvtSD.sToD) {
ppHRegARM64(i->ARM64in.VCvtSD.dst);
vex_printf(", ");
ppHRegARM64asSreg(i->ARM64in.VCvtSD.src);
} else {
ppHRegARM64asSreg(i->ARM64in.VCvtSD.dst);
vex_printf(", ");
ppHRegARM64(i->ARM64in.VCvtSD.src);
}
return;
case ARM64in_VUnaryD:
vex_printf("f%s ", showARM64FpUnaryOp(i->ARM64in.VUnaryD.op));
ppHRegARM64(i->ARM64in.VUnaryD.dst);
vex_printf(", ");
ppHRegARM64(i->ARM64in.VUnaryD.src);
return;
case ARM64in_VUnaryS:
vex_printf("f%s ", showARM64FpUnaryOp(i->ARM64in.VUnaryS.op));
ppHRegARM64asSreg(i->ARM64in.VUnaryS.dst);
vex_printf(", ");
ppHRegARM64asSreg(i->ARM64in.VUnaryS.src);
return;
case ARM64in_VBinD:
vex_printf("f%s ", showARM64FpBinOp(i->ARM64in.VBinD.op));
ppHRegARM64(i->ARM64in.VBinD.dst);
vex_printf(", ");
ppHRegARM64(i->ARM64in.VBinD.argL);
vex_printf(", ");
ppHRegARM64(i->ARM64in.VBinD.argR);
return;
case ARM64in_VBinS:
vex_printf("f%s ", showARM64FpBinOp(i->ARM64in.VBinS.op));
ppHRegARM64asSreg(i->ARM64in.VBinS.dst);
vex_printf(", ");
ppHRegARM64asSreg(i->ARM64in.VBinS.argL);
vex_printf(", ");
ppHRegARM64asSreg(i->ARM64in.VBinS.argR);
return;
case ARM64in_VCmpD:
vex_printf("fcmp ");
ppHRegARM64(i->ARM64in.VCmpD.argL);
vex_printf(", ");
ppHRegARM64(i->ARM64in.VCmpD.argR);
return;
case ARM64in_VCmpS:
vex_printf("fcmp ");
ppHRegARM64asSreg(i->ARM64in.VCmpS.argL);
vex_printf(", ");
ppHRegARM64asSreg(i->ARM64in.VCmpS.argR);
return;
case ARM64in_FPCR:
if (i->ARM64in.FPCR.toFPCR) {
vex_printf("msr fpcr, ");
ppHRegARM64(i->ARM64in.FPCR.iReg);
} else {
vex_printf("mrs ");
ppHRegARM64(i->ARM64in.FPCR.iReg);
vex_printf(", fpcr");
}
return;
case ARM64in_FPSR:
if (i->ARM64in.FPSR.toFPSR) {
vex_printf("msr fpsr, ");
ppHRegARM64(i->ARM64in.FPSR.iReg);
} else {
vex_printf("mrs ");
ppHRegARM64(i->ARM64in.FPSR.iReg);
vex_printf(", fpsr");
}
return;
case ARM64in_VBinV: {
const HChar* nm = "??";
const HChar* ar = "??";
showARM64VecBinOp(&nm, &ar, i->ARM64in.VBinV.op);
vex_printf("%s ", nm);
ppHRegARM64(i->ARM64in.VBinV.dst);
vex_printf(".%s, ", ar);
ppHRegARM64(i->ARM64in.VBinV.argL);
vex_printf(".%s, ", ar);
ppHRegARM64(i->ARM64in.VBinV.argR);
vex_printf(".%s", ar);
return;
}
case ARM64in_VModifyV: {
const HChar* nm = "??";
const HChar* ar = "??";
showARM64VecModifyOp(&nm, &ar, i->ARM64in.VModifyV.op);
vex_printf("%s ", nm);
ppHRegARM64(i->ARM64in.VModifyV.mod);
vex_printf(".%s, ", ar);
ppHRegARM64(i->ARM64in.VModifyV.arg);
vex_printf(".%s", ar);
return;
}
case ARM64in_VUnaryV: {
const HChar* nm = "??";
const HChar* ar = "??";
showARM64VecUnaryOp(&nm, &ar, i->ARM64in.VUnaryV.op);
vex_printf("%s ", nm);
ppHRegARM64(i->ARM64in.VUnaryV.dst);
vex_printf(".%s, ", ar);
ppHRegARM64(i->ARM64in.VUnaryV.arg);
vex_printf(".%s", ar);
return;
}
case ARM64in_VNarrowV: {
UInt dszBlg2 = i->ARM64in.VNarrowV.dszBlg2;
const HChar* darr[3] = { "8b", "4h", "2s" };
const HChar* sarr[3] = { "8h", "4s", "2d" };
const HChar* nm = showARM64VecNarrowOp(i->ARM64in.VNarrowV.op);
vex_printf("%s ", nm);
ppHRegARM64(i->ARM64in.VNarrowV.dst);
vex_printf(".%s, ", dszBlg2 < 3 ? darr[dszBlg2] : "??");
ppHRegARM64(i->ARM64in.VNarrowV.src);
vex_printf(".%s", dszBlg2 < 3 ? sarr[dszBlg2] : "??");
return;
}
case ARM64in_VShiftImmV: {
const HChar* nm = "??";
const HChar* ar = "??";
showARM64VecShiftImmOp(&nm, &ar, i->ARM64in.VShiftImmV.op);
vex_printf("%s ", nm);
ppHRegARM64(i->ARM64in.VShiftImmV.dst);
vex_printf(".%s, ", ar);
ppHRegARM64(i->ARM64in.VShiftImmV.src);
vex_printf(".%s, #%u", ar, i->ARM64in.VShiftImmV.amt);
return;
}
case ARM64in_VExtV: {
vex_printf("ext ");
ppHRegARM64(i->ARM64in.VExtV.dst);
vex_printf(".16b, ");
ppHRegARM64(i->ARM64in.VExtV.srcLo);
vex_printf(".16b, ");
ppHRegARM64(i->ARM64in.VExtV.srcHi);
vex_printf(".16b, #%u", i->ARM64in.VExtV.amtB);
return;
}
case ARM64in_VImmQ:
vex_printf("qimm ");
ppHRegARM64(i->ARM64in.VImmQ.rQ);
vex_printf(", Bits16toBytes16(0x%x)", (UInt)i->ARM64in.VImmQ.imm);
return;
case ARM64in_VDfromX:
vex_printf("fmov ");
ppHRegARM64(i->ARM64in.VDfromX.rD);
vex_printf(", ");
ppHRegARM64(i->ARM64in.VDfromX.rX);
return;
case ARM64in_VQfromX:
vex_printf("fmov ");
ppHRegARM64(i->ARM64in.VQfromX.rQ);
vex_printf(".d[0], ");
ppHRegARM64(i->ARM64in.VQfromX.rXlo);
return;
case ARM64in_VQfromXX:
vex_printf("qFromXX ");
ppHRegARM64(i->ARM64in.VQfromXX.rQ);
vex_printf(", ");
ppHRegARM64(i->ARM64in.VQfromXX.rXhi);
vex_printf(", ");
ppHRegARM64(i->ARM64in.VQfromXX.rXlo);
return;
case ARM64in_VXfromQ:
vex_printf("fmov ");
ppHRegARM64(i->ARM64in.VXfromQ.rX);
vex_printf(", ");
ppHRegARM64(i->ARM64in.VXfromQ.rQ);
vex_printf(".d[%u]", i->ARM64in.VXfromQ.laneNo);
return;
case ARM64in_VXfromDorS:
vex_printf("fmov ");
ppHRegARM64(i->ARM64in.VXfromDorS.rX);
vex_printf("(%c-reg), ", i->ARM64in.VXfromDorS.fromD ? 'X':'W');
ppHRegARM64(i->ARM64in.VXfromDorS.rDorS);
vex_printf("(%c-reg)", i->ARM64in.VXfromDorS.fromD ? 'D' : 'S');
return;
case ARM64in_VMov: {
UChar aux = '?';
switch (i->ARM64in.VMov.szB) {
case 16: aux = 'q'; break;
case 8: aux = 'd'; break;
case 4: aux = 's'; break;
default: break;
}
vex_printf("mov(%c) ", aux);
ppHRegARM64(i->ARM64in.VMov.dst);
vex_printf(", ");
ppHRegARM64(i->ARM64in.VMov.src);
return;
}
case ARM64in_EvCheck:
vex_printf("(evCheck) ldr w9,");
ppARM64AMode(i->ARM64in.EvCheck.amCounter);
vex_printf("; subs w9,w9,$1; str w9,");
ppARM64AMode(i->ARM64in.EvCheck.amCounter);
vex_printf("; bpl nofail; ldr x9,");
ppARM64AMode(i->ARM64in.EvCheck.amFailAddr);
vex_printf("; br x9; nofail:");
return;
case ARM64in_ProfInc:
vex_printf("(profInc) imm64-fixed4 x9,$NotKnownYet; "
"ldr x8,[x9]; add x8,x8,#1, str x8,[x9]");
return;
default:
vex_printf("ppARM64Instr: unhandled case (tag %d)", (Int)i->tag);
vpanic("ppARM64Instr(1)");
return;
}
}
/* --------- Helpers for register allocation. --------- */
void getRegUsage_ARM64Instr ( HRegUsage* u, ARM64Instr* i, Bool mode64 )
{
vassert(mode64 == True);
initHRegUsage(u);
switch (i->tag) {
case ARM64in_Arith:
addHRegUse(u, HRmWrite, i->ARM64in.Arith.dst);
addHRegUse(u, HRmRead, i->ARM64in.Arith.argL);
addRegUsage_ARM64RIA(u, i->ARM64in.Arith.argR);
return;
case ARM64in_Cmp:
addHRegUse(u, HRmRead, i->ARM64in.Cmp.argL);
addRegUsage_ARM64RIA(u, i->ARM64in.Cmp.argR);
return;
case ARM64in_Logic:
addHRegUse(u, HRmWrite, i->ARM64in.Logic.dst);
addHRegUse(u, HRmRead, i->ARM64in.Logic.argL);
addRegUsage_ARM64RIL(u, i->ARM64in.Logic.argR);
return;
case ARM64in_Test:
addHRegUse(u, HRmRead, i->ARM64in.Test.argL);
addRegUsage_ARM64RIL(u, i->ARM64in.Test.argR);
return;
case ARM64in_Shift:
addHRegUse(u, HRmWrite, i->ARM64in.Shift.dst);
addHRegUse(u, HRmRead, i->ARM64in.Shift.argL);
addRegUsage_ARM64RI6(u, i->ARM64in.Shift.argR);
return;
case ARM64in_Unary:
addHRegUse(u, HRmWrite, i->ARM64in.Unary.dst);
addHRegUse(u, HRmRead, i->ARM64in.Unary.src);
return;
case ARM64in_MovI:
addHRegUse(u, HRmWrite, i->ARM64in.MovI.dst);
addHRegUse(u, HRmRead, i->ARM64in.MovI.src);
return;
case ARM64in_Imm64:
addHRegUse(u, HRmWrite, i->ARM64in.Imm64.dst);
return;
case ARM64in_LdSt64:
addRegUsage_ARM64AMode(u, i->ARM64in.LdSt64.amode);
if (i->ARM64in.LdSt64.isLoad) {
addHRegUse(u, HRmWrite, i->ARM64in.LdSt64.rD);
} else {
addHRegUse(u, HRmRead, i->ARM64in.LdSt64.rD);
}
return;
case ARM64in_LdSt32:
addRegUsage_ARM64AMode(u, i->ARM64in.LdSt32.amode);
if (i->ARM64in.LdSt32.isLoad) {
addHRegUse(u, HRmWrite, i->ARM64in.LdSt32.rD);
} else {
addHRegUse(u, HRmRead, i->ARM64in.LdSt32.rD);
}
return;
case ARM64in_LdSt16:
addRegUsage_ARM64AMode(u, i->ARM64in.LdSt16.amode);
if (i->ARM64in.LdSt16.isLoad) {
addHRegUse(u, HRmWrite, i->ARM64in.LdSt16.rD);
} else {
addHRegUse(u, HRmRead, i->ARM64in.LdSt16.rD);
}
return;
case ARM64in_LdSt8:
addRegUsage_ARM64AMode(u, i->ARM64in.LdSt8.amode);
if (i->ARM64in.LdSt8.isLoad) {
addHRegUse(u, HRmWrite, i->ARM64in.LdSt8.rD);
} else {
addHRegUse(u, HRmRead, i->ARM64in.LdSt8.rD);
}
return;
/* XDirect/XIndir/XAssisted are also a bit subtle. They
conditionally exit the block. Hence we only need to list (1)
the registers that they read, and (2) the registers that they
write in the case where the block is not exited. (2) is
empty, hence only (1) is relevant here. */
case ARM64in_XDirect:
addRegUsage_ARM64AMode(u, i->ARM64in.XDirect.amPC);
return;
case ARM64in_XIndir:
addHRegUse(u, HRmRead, i->ARM64in.XIndir.dstGA);
addRegUsage_ARM64AMode(u, i->ARM64in.XIndir.amPC);
return;
case ARM64in_XAssisted:
addHRegUse(u, HRmRead, i->ARM64in.XAssisted.dstGA);
addRegUsage_ARM64AMode(u, i->ARM64in.XAssisted.amPC);
return;
case ARM64in_CSel:
addHRegUse(u, HRmWrite, i->ARM64in.CSel.dst);
addHRegUse(u, HRmRead, i->ARM64in.CSel.argL);
addHRegUse(u, HRmRead, i->ARM64in.CSel.argR);
return;
case ARM64in_Call:
/* logic and comments copied/modified from x86 back end */
/* This is a bit subtle. */
/* First off, claim it trashes all the caller-saved regs
which fall within the register allocator's jurisdiction.
These I believe to be x0 to x7 and the 128-bit vector
registers in use, q16 .. q20. */
addHRegUse(u, HRmWrite, hregARM64_X0());
addHRegUse(u, HRmWrite, hregARM64_X1());
addHRegUse(u, HRmWrite, hregARM64_X2());
addHRegUse(u, HRmWrite, hregARM64_X3());
addHRegUse(u, HRmWrite, hregARM64_X4());
addHRegUse(u, HRmWrite, hregARM64_X5());
addHRegUse(u, HRmWrite, hregARM64_X6());
addHRegUse(u, HRmWrite, hregARM64_X7());
addHRegUse(u, HRmWrite, hregARM64_Q16());
addHRegUse(u, HRmWrite, hregARM64_Q17());
addHRegUse(u, HRmWrite, hregARM64_Q18());
addHRegUse(u, HRmWrite, hregARM64_Q19());
addHRegUse(u, HRmWrite, hregARM64_Q20());
/* Now we have to state any parameter-carrying registers
which might be read. This depends on nArgRegs. */
switch (i->ARM64in.Call.nArgRegs) {
case 8: addHRegUse(u, HRmRead, hregARM64_X7()); /*fallthru*/
case 7: addHRegUse(u, HRmRead, hregARM64_X6()); /*fallthru*/
case 6: addHRegUse(u, HRmRead, hregARM64_X5()); /*fallthru*/
case 5: addHRegUse(u, HRmRead, hregARM64_X4()); /*fallthru*/
case 4: addHRegUse(u, HRmRead, hregARM64_X3()); /*fallthru*/
case 3: addHRegUse(u, HRmRead, hregARM64_X2()); /*fallthru*/
case 2: addHRegUse(u, HRmRead, hregARM64_X1()); /*fallthru*/
case 1: addHRegUse(u, HRmRead, hregARM64_X0()); break;
case 0: break;
default: vpanic("getRegUsage_ARM64:Call:regparms");
}
/* Finally, there is the issue that the insn trashes a
register because the literal target address has to be
loaded into a register. However, we reserve x9 for that
purpose so there's no further complexity here. Stating x9
as trashed is pointless since it's not under the control
of the allocator, but what the hell. */
addHRegUse(u, HRmWrite, hregARM64_X9());
return;
case ARM64in_AddToSP:
/* Only changes SP, but regalloc doesn't control that, hence
we don't care. */
return;
case ARM64in_FromSP:
addHRegUse(u, HRmWrite, i->ARM64in.FromSP.dst);
return;
case ARM64in_Mul:
addHRegUse(u, HRmWrite, i->ARM64in.Mul.dst);
addHRegUse(u, HRmRead, i->ARM64in.Mul.argL);
addHRegUse(u, HRmRead, i->ARM64in.Mul.argR);
return;
case ARM64in_LdrEX:
addHRegUse(u, HRmRead, hregARM64_X4());
addHRegUse(u, HRmWrite, hregARM64_X2());
return;
case ARM64in_StrEX:
addHRegUse(u, HRmRead, hregARM64_X4());
addHRegUse(u, HRmWrite, hregARM64_X0());
addHRegUse(u, HRmRead, hregARM64_X2());
return;
case ARM64in_MFence:
return;
case ARM64in_VLdStS:
addHRegUse(u, HRmRead, i->ARM64in.VLdStS.rN);
if (i->ARM64in.VLdStS.isLoad) {
addHRegUse(u, HRmWrite, i->ARM64in.VLdStS.sD);
} else {
addHRegUse(u, HRmRead, i->ARM64in.VLdStS.sD);
}
return;
case ARM64in_VLdStD:
addHRegUse(u, HRmRead, i->ARM64in.VLdStD.rN);
if (i->ARM64in.VLdStD.isLoad) {
addHRegUse(u, HRmWrite, i->ARM64in.VLdStD.dD);
} else {
addHRegUse(u, HRmRead, i->ARM64in.VLdStD.dD);
}
return;
case ARM64in_VLdStQ:
addHRegUse(u, HRmRead, i->ARM64in.VLdStQ.rN);
if (i->ARM64in.VLdStQ.isLoad)
addHRegUse(u, HRmWrite, i->ARM64in.VLdStQ.rQ);
else
addHRegUse(u, HRmRead, i->ARM64in.VLdStQ.rQ);
return;
case ARM64in_VCvtI2F:
addHRegUse(u, HRmRead, i->ARM64in.VCvtI2F.rS);
addHRegUse(u, HRmWrite, i->ARM64in.VCvtI2F.rD);
return;
case ARM64in_VCvtF2I:
addHRegUse(u, HRmRead, i->ARM64in.VCvtF2I.rS);
addHRegUse(u, HRmWrite, i->ARM64in.VCvtF2I.rD);
return;
case ARM64in_VCvtSD:
addHRegUse(u, HRmWrite, i->ARM64in.VCvtSD.dst);
addHRegUse(u, HRmRead, i->ARM64in.VCvtSD.src);
return;
case ARM64in_VUnaryD:
addHRegUse(u, HRmWrite, i->ARM64in.VUnaryD.dst);
addHRegUse(u, HRmRead, i->ARM64in.VUnaryD.src);
return;
case ARM64in_VUnaryS:
addHRegUse(u, HRmWrite, i->ARM64in.VUnaryS.dst);
addHRegUse(u, HRmRead, i->ARM64in.VUnaryS.src);
return;
case ARM64in_VBinD:
addHRegUse(u, HRmWrite, i->ARM64in.VBinD.dst);
addHRegUse(u, HRmRead, i->ARM64in.VBinD.argL);
addHRegUse(u, HRmRead, i->ARM64in.VBinD.argR);
return;
case ARM64in_VBinS:
addHRegUse(u, HRmWrite, i->ARM64in.VBinS.dst);
addHRegUse(u, HRmRead, i->ARM64in.VBinS.argL);
addHRegUse(u, HRmRead, i->ARM64in.VBinS.argR);
return;
case ARM64in_VCmpD:
addHRegUse(u, HRmRead, i->ARM64in.VCmpD.argL);
addHRegUse(u, HRmRead, i->ARM64in.VCmpD.argR);
return;
case ARM64in_VCmpS:
addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argL);
addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argR);
return;
case ARM64in_FPCR:
if (i->ARM64in.FPCR.toFPCR)
addHRegUse(u, HRmRead, i->ARM64in.FPCR.iReg);
else
addHRegUse(u, HRmWrite, i->ARM64in.FPCR.iReg);
return;
case ARM64in_FPSR:
if (i->ARM64in.FPSR.toFPSR)
addHRegUse(u, HRmRead, i->ARM64in.FPSR.iReg);
else
addHRegUse(u, HRmWrite, i->ARM64in.FPSR.iReg);
return;
case ARM64in_VBinV:
addHRegUse(u, HRmWrite, i->ARM64in.VBinV.dst);
addHRegUse(u, HRmRead, i->ARM64in.VBinV.argL);
addHRegUse(u, HRmRead, i->ARM64in.VBinV.argR);
return;
case ARM64in_VModifyV:
addHRegUse(u, HRmWrite, i->ARM64in.VModifyV.mod);
addHRegUse(u, HRmRead, i->ARM64in.VModifyV.mod);
addHRegUse(u, HRmRead, i->ARM64in.VModifyV.arg);
return;
case ARM64in_VUnaryV:
addHRegUse(u, HRmWrite, i->ARM64in.VUnaryV.dst);
addHRegUse(u, HRmRead, i->ARM64in.VUnaryV.arg);
return;
case ARM64in_VNarrowV:
addHRegUse(u, HRmWrite, i->ARM64in.VNarrowV.dst);
addHRegUse(u, HRmRead, i->ARM64in.VNarrowV.src);
return;
case ARM64in_VShiftImmV:
addHRegUse(u, HRmWrite, i->ARM64in.VShiftImmV.dst);
addHRegUse(u, HRmRead, i->ARM64in.VShiftImmV.src);
return;
case ARM64in_VExtV:
addHRegUse(u, HRmWrite, i->ARM64in.VExtV.dst);
addHRegUse(u, HRmRead, i->ARM64in.VExtV.srcLo);
addHRegUse(u, HRmRead, i->ARM64in.VExtV.srcHi);
return;
case ARM64in_VImmQ:
addHRegUse(u, HRmWrite, i->ARM64in.VImmQ.rQ);
return;
case ARM64in_VDfromX:
addHRegUse(u, HRmWrite, i->ARM64in.VDfromX.rD);
addHRegUse(u, HRmRead, i->ARM64in.VDfromX.rX);
return;
case ARM64in_VQfromX:
addHRegUse(u, HRmWrite, i->ARM64in.VQfromX.rQ);
addHRegUse(u, HRmRead, i->ARM64in.VQfromX.rXlo);
return;
case ARM64in_VQfromXX:
addHRegUse(u, HRmWrite, i->ARM64in.VQfromXX.rQ);
addHRegUse(u, HRmRead, i->ARM64in.VQfromXX.rXhi);
addHRegUse(u, HRmRead, i->ARM64in.VQfromXX.rXlo);
return;
case ARM64in_VXfromQ:
addHRegUse(u, HRmWrite, i->ARM64in.VXfromQ.rX);
addHRegUse(u, HRmRead, i->ARM64in.VXfromQ.rQ);
return;
case ARM64in_VXfromDorS:
addHRegUse(u, HRmWrite, i->ARM64in.VXfromDorS.rX);
addHRegUse(u, HRmRead, i->ARM64in.VXfromDorS.rDorS);
return;
case ARM64in_VMov:
addHRegUse(u, HRmWrite, i->ARM64in.VMov.dst);
addHRegUse(u, HRmRead, i->ARM64in.VMov.src);
return;
case ARM64in_EvCheck:
/* We expect both amodes only to mention x21, so this is in
fact pointless, since x21 isn't allocatable, but
anyway.. */
addRegUsage_ARM64AMode(u, i->ARM64in.EvCheck.amCounter);
addRegUsage_ARM64AMode(u, i->ARM64in.EvCheck.amFailAddr);
addHRegUse(u, HRmWrite, hregARM64_X9()); /* also unavail to RA */
return;
case ARM64in_ProfInc:
/* Again, pointless to actually state these since neither
is available to RA. */
addHRegUse(u, HRmWrite, hregARM64_X9()); /* unavail to RA */
addHRegUse(u, HRmWrite, hregARM64_X8()); /* unavail to RA */
return;
default:
ppARM64Instr(i);
vpanic("getRegUsage_ARM64Instr");
}
}
void mapRegs_ARM64Instr ( HRegRemap* m, ARM64Instr* i, Bool mode64 )
{
vassert(mode64 == True);
switch (i->tag) {
case ARM64in_Arith:
i->ARM64in.Arith.dst = lookupHRegRemap(m, i->ARM64in.Arith.dst);
i->ARM64in.Arith.argL = lookupHRegRemap(m, i->ARM64in.Arith.argL);
mapRegs_ARM64RIA(m, i->ARM64in.Arith.argR);
return;
case ARM64in_Cmp:
i->ARM64in.Cmp.argL = lookupHRegRemap(m, i->ARM64in.Cmp.argL);
mapRegs_ARM64RIA(m, i->ARM64in.Cmp.argR);
return;
case ARM64in_Logic:
i->ARM64in.Logic.dst = lookupHRegRemap(m, i->ARM64in.Logic.dst);
i->ARM64in.Logic.argL = lookupHRegRemap(m, i->ARM64in.Logic.argL);
mapRegs_ARM64RIL(m, i->ARM64in.Logic.argR);
return;
case ARM64in_Test:
i->ARM64in.Test.argL = lookupHRegRemap(m, i->ARM64in.Test.argL);
mapRegs_ARM64RIL(m, i->ARM64in.Logic.argR);
return;
case ARM64in_Shift:
i->ARM64in.Shift.dst = lookupHRegRemap(m, i->ARM64in.Shift.dst);
i->ARM64in.Shift.argL = lookupHRegRemap(m, i->ARM64in.Shift.argL);
mapRegs_ARM64RI6(m, i->ARM64in.Shift.argR);
return;
case ARM64in_Unary:
i->ARM64in.Unary.dst = lookupHRegRemap(m, i->ARM64in.Unary.dst);