1139c1837SPaolo Bonzini/* 2139c1837SPaolo Bonzini * Initial TCG Implementation for aarch64 3139c1837SPaolo Bonzini * 4139c1837SPaolo Bonzini * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH 5139c1837SPaolo Bonzini * Written by Claudio Fontana 6139c1837SPaolo Bonzini * 7139c1837SPaolo Bonzini * This work is licensed under the terms of the GNU GPL, version 2 or 8139c1837SPaolo Bonzini * (at your option) any later version. 9139c1837SPaolo Bonzini * 10139c1837SPaolo Bonzini * See the COPYING file in the top-level directory for details. 11139c1837SPaolo Bonzini */ 12139c1837SPaolo Bonzini 13f85ab3d2SRichard Henderson#include "../tcg-ldst.c.inc" 14139c1837SPaolo Bonzini#include "../tcg-pool.c.inc" 15139c1837SPaolo Bonzini#include "qemu/bitops.h" 16139c1837SPaolo Bonzini 17139c1837SPaolo Bonzini/* We're going to re-use TCGType in setting of the SF bit, which controls 18139c1837SPaolo Bonzini the size of the operation performed. If we know the values match, it 19139c1837SPaolo Bonzini makes things much cleaner. */ 20139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(TCG_TYPE_I32 != 0 || TCG_TYPE_I64 != 1); 21139c1837SPaolo Bonzini 22139c1837SPaolo Bonzini#ifdef CONFIG_DEBUG_TCG 23139c1837SPaolo Bonzinistatic const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { 24139c1837SPaolo Bonzini "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 25139c1837SPaolo Bonzini "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 26139c1837SPaolo Bonzini "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 27139c1837SPaolo Bonzini "x24", "x25", "x26", "x27", "x28", "fp", "x30", "sp", 28139c1837SPaolo Bonzini 29139c1837SPaolo Bonzini "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", 30139c1837SPaolo Bonzini "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", 31139c1837SPaolo Bonzini "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", 32139c1837SPaolo Bonzini "v24", "v25", "v26", "v27", "v28", "fp", "v30", "v31", 33139c1837SPaolo Bonzini}; 34139c1837SPaolo Bonzini#endif /* CONFIG_DEBUG_TCG */ 35139c1837SPaolo Bonzini 36139c1837SPaolo Bonzinistatic const int tcg_target_reg_alloc_order[] = { 37139c1837SPaolo Bonzini TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23, 38139c1837SPaolo Bonzini TCG_REG_X24, TCG_REG_X25, TCG_REG_X26, TCG_REG_X27, 39139c1837SPaolo Bonzini TCG_REG_X28, /* we will reserve this for guest_base if configured */ 40139c1837SPaolo Bonzini 41139c1837SPaolo Bonzini TCG_REG_X8, TCG_REG_X9, TCG_REG_X10, TCG_REG_X11, 42139c1837SPaolo Bonzini TCG_REG_X12, TCG_REG_X13, TCG_REG_X14, TCG_REG_X15, 43139c1837SPaolo Bonzini 44139c1837SPaolo Bonzini TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3, 45139c1837SPaolo Bonzini TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7, 46139c1837SPaolo Bonzini 47da4d0d95SRichard Henderson /* X16 reserved as temporary */ 48da4d0d95SRichard Henderson /* X17 reserved as temporary */ 49139c1837SPaolo Bonzini /* X18 reserved by system */ 50139c1837SPaolo Bonzini /* X19 reserved for AREG0 */ 51139c1837SPaolo Bonzini /* X29 reserved as fp */ 52139c1837SPaolo Bonzini /* X30 reserved as temporary */ 53139c1837SPaolo Bonzini 54139c1837SPaolo Bonzini TCG_REG_V0, TCG_REG_V1, TCG_REG_V2, TCG_REG_V3, 55139c1837SPaolo Bonzini TCG_REG_V4, TCG_REG_V5, TCG_REG_V6, TCG_REG_V7, 56139c1837SPaolo Bonzini /* V8 - V15 are call-saved, and skipped. */ 57139c1837SPaolo Bonzini TCG_REG_V16, TCG_REG_V17, TCG_REG_V18, TCG_REG_V19, 58139c1837SPaolo Bonzini TCG_REG_V20, TCG_REG_V21, TCG_REG_V22, TCG_REG_V23, 59139c1837SPaolo Bonzini TCG_REG_V24, TCG_REG_V25, TCG_REG_V26, TCG_REG_V27, 60139c1837SPaolo Bonzini TCG_REG_V28, TCG_REG_V29, TCG_REG_V30, TCG_REG_V31, 61139c1837SPaolo Bonzini}; 62139c1837SPaolo Bonzini 63139c1837SPaolo Bonzinistatic const int tcg_target_call_iarg_regs[8] = { 64139c1837SPaolo Bonzini TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3, 65139c1837SPaolo Bonzini TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7 66139c1837SPaolo Bonzini}; 675e3d0c19SRichard Henderson 685e3d0c19SRichard Hendersonstatic TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot) 695e3d0c19SRichard Henderson{ 705e3d0c19SRichard Henderson tcg_debug_assert(kind == TCG_CALL_RET_NORMAL); 715e3d0c19SRichard Henderson tcg_debug_assert(slot >= 0 && slot <= 1); 725e3d0c19SRichard Henderson return TCG_REG_X0 + slot; 735e3d0c19SRichard Henderson} 74139c1837SPaolo Bonzini 75da4d0d95SRichard Henderson#define TCG_REG_TMP0 TCG_REG_X16 76da4d0d95SRichard Henderson#define TCG_REG_TMP1 TCG_REG_X17 77da4d0d95SRichard Henderson#define TCG_REG_TMP2 TCG_REG_X30 78d67bcbddSRichard Henderson#define TCG_VEC_TMP0 TCG_REG_V31 79139c1837SPaolo Bonzini 80139c1837SPaolo Bonzini#define TCG_REG_GUEST_BASE TCG_REG_X28 81139c1837SPaolo Bonzini 82ffba3eb3SRichard Hendersonstatic bool reloc_pc26(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 83139c1837SPaolo Bonzini{ 84ffba3eb3SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 85ffba3eb3SRichard Henderson ptrdiff_t offset = target - src_rx; 86ffba3eb3SRichard Henderson 87139c1837SPaolo Bonzini if (offset == sextract64(offset, 0, 26)) { 88139c1837SPaolo Bonzini /* read instruction, mask away previous PC_REL26 parameter contents, 89139c1837SPaolo Bonzini set the proper offset, then write back the instruction. */ 90ffba3eb3SRichard Henderson *src_rw = deposit32(*src_rw, 0, 26, offset); 91139c1837SPaolo Bonzini return true; 92139c1837SPaolo Bonzini } 93139c1837SPaolo Bonzini return false; 94139c1837SPaolo Bonzini} 95139c1837SPaolo Bonzini 96ffba3eb3SRichard Hendersonstatic bool reloc_pc19(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 97139c1837SPaolo Bonzini{ 98ffba3eb3SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 99ffba3eb3SRichard Henderson ptrdiff_t offset = target - src_rx; 100ffba3eb3SRichard Henderson 101139c1837SPaolo Bonzini if (offset == sextract64(offset, 0, 19)) { 102ffba3eb3SRichard Henderson *src_rw = deposit32(*src_rw, 5, 19, offset); 103139c1837SPaolo Bonzini return true; 104139c1837SPaolo Bonzini } 105139c1837SPaolo Bonzini return false; 106139c1837SPaolo Bonzini} 107139c1837SPaolo Bonzini 10892a11b93SRichard Hendersonstatic bool reloc_pc14(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 10992a11b93SRichard Henderson{ 11092a11b93SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 11192a11b93SRichard Henderson ptrdiff_t offset = target - src_rx; 11292a11b93SRichard Henderson 11392a11b93SRichard Henderson if (offset == sextract64(offset, 0, 14)) { 11492a11b93SRichard Henderson *src_rw = deposit32(*src_rw, 5, 14, offset); 11592a11b93SRichard Henderson return true; 11692a11b93SRichard Henderson } 11792a11b93SRichard Henderson return false; 11892a11b93SRichard Henderson} 11992a11b93SRichard Henderson 120ffba3eb3SRichard Hendersonstatic bool patch_reloc(tcg_insn_unit *code_ptr, int type, 121139c1837SPaolo Bonzini intptr_t value, intptr_t addend) 122139c1837SPaolo Bonzini{ 123139c1837SPaolo Bonzini tcg_debug_assert(addend == 0); 124139c1837SPaolo Bonzini switch (type) { 125139c1837SPaolo Bonzini case R_AARCH64_JUMP26: 126139c1837SPaolo Bonzini case R_AARCH64_CALL26: 127ffba3eb3SRichard Henderson return reloc_pc26(code_ptr, (const tcg_insn_unit *)value); 128139c1837SPaolo Bonzini case R_AARCH64_CONDBR19: 129ffba3eb3SRichard Henderson return reloc_pc19(code_ptr, (const tcg_insn_unit *)value); 13092a11b93SRichard Henderson case R_AARCH64_TSTBR14: 13192a11b93SRichard Henderson return reloc_pc14(code_ptr, (const tcg_insn_unit *)value); 132139c1837SPaolo Bonzini default: 133139c1837SPaolo Bonzini g_assert_not_reached(); 134139c1837SPaolo Bonzini } 135139c1837SPaolo Bonzini} 136139c1837SPaolo Bonzini 137139c1837SPaolo Bonzini#define TCG_CT_CONST_AIMM 0x100 138139c1837SPaolo Bonzini#define TCG_CT_CONST_LIMM 0x200 139139c1837SPaolo Bonzini#define TCG_CT_CONST_ZERO 0x400 140139c1837SPaolo Bonzini#define TCG_CT_CONST_MONE 0x800 141139c1837SPaolo Bonzini#define TCG_CT_CONST_ORRI 0x1000 142139c1837SPaolo Bonzini#define TCG_CT_CONST_ANDI 0x2000 143339adf2fSRichard Henderson#define TCG_CT_CONST_CMP 0x4000 144139c1837SPaolo Bonzini 145abc730e1SRichard Henderson#define ALL_GENERAL_REGS 0xffffffffu 146abc730e1SRichard Henderson#define ALL_VECTOR_REGS 0xffffffff00000000ull 147abc730e1SRichard Henderson 148139c1837SPaolo Bonzini/* Match a constant valid for addition (12-bit, optionally shifted). */ 149139c1837SPaolo Bonzinistatic inline bool is_aimm(uint64_t val) 150139c1837SPaolo Bonzini{ 151139c1837SPaolo Bonzini return (val & ~0xfff) == 0 || (val & ~0xfff000) == 0; 152139c1837SPaolo Bonzini} 153139c1837SPaolo Bonzini 154139c1837SPaolo Bonzini/* Match a constant valid for logical operations. */ 155139c1837SPaolo Bonzinistatic inline bool is_limm(uint64_t val) 156139c1837SPaolo Bonzini{ 157139c1837SPaolo Bonzini /* Taking a simplified view of the logical immediates for now, ignoring 158139c1837SPaolo Bonzini the replication that can happen across the field. Match bit patterns 159139c1837SPaolo Bonzini of the forms 160139c1837SPaolo Bonzini 0....01....1 161139c1837SPaolo Bonzini 0..01..10..0 162139c1837SPaolo Bonzini and their inverses. */ 163139c1837SPaolo Bonzini 164139c1837SPaolo Bonzini /* Make things easier below, by testing the form with msb clear. */ 165139c1837SPaolo Bonzini if ((int64_t)val < 0) { 166139c1837SPaolo Bonzini val = ~val; 167139c1837SPaolo Bonzini } 168139c1837SPaolo Bonzini if (val == 0) { 169139c1837SPaolo Bonzini return false; 170139c1837SPaolo Bonzini } 171139c1837SPaolo Bonzini val += val & -val; 172139c1837SPaolo Bonzini return (val & (val - 1)) == 0; 173139c1837SPaolo Bonzini} 174139c1837SPaolo Bonzini 175139c1837SPaolo Bonzini/* Return true if v16 is a valid 16-bit shifted immediate. */ 176139c1837SPaolo Bonzinistatic bool is_shimm16(uint16_t v16, int *cmode, int *imm8) 177139c1837SPaolo Bonzini{ 178139c1837SPaolo Bonzini if (v16 == (v16 & 0xff)) { 179139c1837SPaolo Bonzini *cmode = 0x8; 180139c1837SPaolo Bonzini *imm8 = v16 & 0xff; 181139c1837SPaolo Bonzini return true; 182139c1837SPaolo Bonzini } else if (v16 == (v16 & 0xff00)) { 183139c1837SPaolo Bonzini *cmode = 0xa; 184139c1837SPaolo Bonzini *imm8 = v16 >> 8; 185139c1837SPaolo Bonzini return true; 186139c1837SPaolo Bonzini } 187139c1837SPaolo Bonzini return false; 188139c1837SPaolo Bonzini} 189139c1837SPaolo Bonzini 190139c1837SPaolo Bonzini/* Return true if v32 is a valid 32-bit shifted immediate. */ 191139c1837SPaolo Bonzinistatic bool is_shimm32(uint32_t v32, int *cmode, int *imm8) 192139c1837SPaolo Bonzini{ 193139c1837SPaolo Bonzini if (v32 == (v32 & 0xff)) { 194139c1837SPaolo Bonzini *cmode = 0x0; 195139c1837SPaolo Bonzini *imm8 = v32 & 0xff; 196139c1837SPaolo Bonzini return true; 197139c1837SPaolo Bonzini } else if (v32 == (v32 & 0xff00)) { 198139c1837SPaolo Bonzini *cmode = 0x2; 199139c1837SPaolo Bonzini *imm8 = (v32 >> 8) & 0xff; 200139c1837SPaolo Bonzini return true; 201139c1837SPaolo Bonzini } else if (v32 == (v32 & 0xff0000)) { 202139c1837SPaolo Bonzini *cmode = 0x4; 203139c1837SPaolo Bonzini *imm8 = (v32 >> 16) & 0xff; 204139c1837SPaolo Bonzini return true; 205139c1837SPaolo Bonzini } else if (v32 == (v32 & 0xff000000)) { 206139c1837SPaolo Bonzini *cmode = 0x6; 207139c1837SPaolo Bonzini *imm8 = v32 >> 24; 208139c1837SPaolo Bonzini return true; 209139c1837SPaolo Bonzini } 210139c1837SPaolo Bonzini return false; 211139c1837SPaolo Bonzini} 212139c1837SPaolo Bonzini 213139c1837SPaolo Bonzini/* Return true if v32 is a valid 32-bit shifting ones immediate. */ 214139c1837SPaolo Bonzinistatic bool is_soimm32(uint32_t v32, int *cmode, int *imm8) 215139c1837SPaolo Bonzini{ 216139c1837SPaolo Bonzini if ((v32 & 0xffff00ff) == 0xff) { 217139c1837SPaolo Bonzini *cmode = 0xc; 218139c1837SPaolo Bonzini *imm8 = (v32 >> 8) & 0xff; 219139c1837SPaolo Bonzini return true; 220139c1837SPaolo Bonzini } else if ((v32 & 0xff00ffff) == 0xffff) { 221139c1837SPaolo Bonzini *cmode = 0xd; 222139c1837SPaolo Bonzini *imm8 = (v32 >> 16) & 0xff; 223139c1837SPaolo Bonzini return true; 224139c1837SPaolo Bonzini } 225139c1837SPaolo Bonzini return false; 226139c1837SPaolo Bonzini} 227139c1837SPaolo Bonzini 228139c1837SPaolo Bonzini/* Return true if v32 is a valid float32 immediate. */ 229139c1837SPaolo Bonzinistatic bool is_fimm32(uint32_t v32, int *cmode, int *imm8) 230139c1837SPaolo Bonzini{ 231139c1837SPaolo Bonzini if (extract32(v32, 0, 19) == 0 232139c1837SPaolo Bonzini && (extract32(v32, 25, 6) == 0x20 233139c1837SPaolo Bonzini || extract32(v32, 25, 6) == 0x1f)) { 234139c1837SPaolo Bonzini *cmode = 0xf; 235139c1837SPaolo Bonzini *imm8 = (extract32(v32, 31, 1) << 7) 236139c1837SPaolo Bonzini | (extract32(v32, 25, 1) << 6) 237139c1837SPaolo Bonzini | extract32(v32, 19, 6); 238139c1837SPaolo Bonzini return true; 239139c1837SPaolo Bonzini } 240139c1837SPaolo Bonzini return false; 241139c1837SPaolo Bonzini} 242139c1837SPaolo Bonzini 243139c1837SPaolo Bonzini/* Return true if v64 is a valid float64 immediate. */ 244139c1837SPaolo Bonzinistatic bool is_fimm64(uint64_t v64, int *cmode, int *imm8) 245139c1837SPaolo Bonzini{ 246139c1837SPaolo Bonzini if (extract64(v64, 0, 48) == 0 247139c1837SPaolo Bonzini && (extract64(v64, 54, 9) == 0x100 248139c1837SPaolo Bonzini || extract64(v64, 54, 9) == 0x0ff)) { 249139c1837SPaolo Bonzini *cmode = 0xf; 250139c1837SPaolo Bonzini *imm8 = (extract64(v64, 63, 1) << 7) 251139c1837SPaolo Bonzini | (extract64(v64, 54, 1) << 6) 252139c1837SPaolo Bonzini | extract64(v64, 48, 6); 253139c1837SPaolo Bonzini return true; 254139c1837SPaolo Bonzini } 255139c1837SPaolo Bonzini return false; 256139c1837SPaolo Bonzini} 257139c1837SPaolo Bonzini 258139c1837SPaolo Bonzini/* 259139c1837SPaolo Bonzini * Return non-zero if v32 can be formed by MOVI+ORR. 260139c1837SPaolo Bonzini * Place the parameters for MOVI in (cmode, imm8). 261139c1837SPaolo Bonzini * Return the cmode for ORR; the imm8 can be had via extraction from v32. 262139c1837SPaolo Bonzini */ 263139c1837SPaolo Bonzinistatic int is_shimm32_pair(uint32_t v32, int *cmode, int *imm8) 264139c1837SPaolo Bonzini{ 265139c1837SPaolo Bonzini int i; 266139c1837SPaolo Bonzini 267139c1837SPaolo Bonzini for (i = 6; i > 0; i -= 2) { 268139c1837SPaolo Bonzini /* Mask out one byte we can add with ORR. */ 269139c1837SPaolo Bonzini uint32_t tmp = v32 & ~(0xffu << (i * 4)); 270139c1837SPaolo Bonzini if (is_shimm32(tmp, cmode, imm8) || 271139c1837SPaolo Bonzini is_soimm32(tmp, cmode, imm8)) { 272139c1837SPaolo Bonzini break; 273139c1837SPaolo Bonzini } 274139c1837SPaolo Bonzini } 275139c1837SPaolo Bonzini return i; 276139c1837SPaolo Bonzini} 277139c1837SPaolo Bonzini 278139c1837SPaolo Bonzini/* Return true if V is a valid 16-bit or 32-bit shifted immediate. */ 279139c1837SPaolo Bonzinistatic bool is_shimm1632(uint32_t v32, int *cmode, int *imm8) 280139c1837SPaolo Bonzini{ 281139c1837SPaolo Bonzini if (v32 == deposit32(v32, 16, 16, v32)) { 282139c1837SPaolo Bonzini return is_shimm16(v32, cmode, imm8); 283139c1837SPaolo Bonzini } else { 284139c1837SPaolo Bonzini return is_shimm32(v32, cmode, imm8); 285139c1837SPaolo Bonzini } 286139c1837SPaolo Bonzini} 287139c1837SPaolo Bonzini 28821e9a8aeSRichard Hendersonstatic bool tcg_target_const_match(int64_t val, int ct, 28921e9a8aeSRichard Henderson TCGType type, TCGCond cond, int vece) 290139c1837SPaolo Bonzini{ 291139c1837SPaolo Bonzini if (ct & TCG_CT_CONST) { 292139c1837SPaolo Bonzini return 1; 293139c1837SPaolo Bonzini } 294139c1837SPaolo Bonzini if (type == TCG_TYPE_I32) { 295139c1837SPaolo Bonzini val = (int32_t)val; 296139c1837SPaolo Bonzini } 297339adf2fSRichard Henderson 298339adf2fSRichard Henderson if (ct & TCG_CT_CONST_CMP) { 299339adf2fSRichard Henderson if (is_tst_cond(cond)) { 300339adf2fSRichard Henderson ct |= TCG_CT_CONST_LIMM; 301339adf2fSRichard Henderson } else { 302339adf2fSRichard Henderson ct |= TCG_CT_CONST_AIMM; 303339adf2fSRichard Henderson } 304339adf2fSRichard Henderson } 305339adf2fSRichard Henderson 306139c1837SPaolo Bonzini if ((ct & TCG_CT_CONST_AIMM) && (is_aimm(val) || is_aimm(-val))) { 307139c1837SPaolo Bonzini return 1; 308139c1837SPaolo Bonzini } 309139c1837SPaolo Bonzini if ((ct & TCG_CT_CONST_LIMM) && is_limm(val)) { 310139c1837SPaolo Bonzini return 1; 311139c1837SPaolo Bonzini } 312139c1837SPaolo Bonzini if ((ct & TCG_CT_CONST_ZERO) && val == 0) { 313139c1837SPaolo Bonzini return 1; 314139c1837SPaolo Bonzini } 315139c1837SPaolo Bonzini if ((ct & TCG_CT_CONST_MONE) && val == -1) { 316139c1837SPaolo Bonzini return 1; 317139c1837SPaolo Bonzini } 318139c1837SPaolo Bonzini 319139c1837SPaolo Bonzini switch (ct & (TCG_CT_CONST_ORRI | TCG_CT_CONST_ANDI)) { 320139c1837SPaolo Bonzini case 0: 321139c1837SPaolo Bonzini break; 322139c1837SPaolo Bonzini case TCG_CT_CONST_ANDI: 323139c1837SPaolo Bonzini val = ~val; 324139c1837SPaolo Bonzini /* fallthru */ 325139c1837SPaolo Bonzini case TCG_CT_CONST_ORRI: 326139c1837SPaolo Bonzini if (val == deposit64(val, 32, 32, val)) { 327139c1837SPaolo Bonzini int cmode, imm8; 328139c1837SPaolo Bonzini return is_shimm1632(val, &cmode, &imm8); 329139c1837SPaolo Bonzini } 330139c1837SPaolo Bonzini break; 331139c1837SPaolo Bonzini default: 332139c1837SPaolo Bonzini /* Both bits should not be set for the same insn. */ 333139c1837SPaolo Bonzini g_assert_not_reached(); 334139c1837SPaolo Bonzini } 335139c1837SPaolo Bonzini 336139c1837SPaolo Bonzini return 0; 337139c1837SPaolo Bonzini} 338139c1837SPaolo Bonzini 339139c1837SPaolo Bonzinienum aarch64_cond_code { 340139c1837SPaolo Bonzini COND_EQ = 0x0, 341139c1837SPaolo Bonzini COND_NE = 0x1, 342139c1837SPaolo Bonzini COND_CS = 0x2, /* Unsigned greater or equal */ 343139c1837SPaolo Bonzini COND_HS = COND_CS, /* ALIAS greater or equal */ 344139c1837SPaolo Bonzini COND_CC = 0x3, /* Unsigned less than */ 345139c1837SPaolo Bonzini COND_LO = COND_CC, /* ALIAS Lower */ 346139c1837SPaolo Bonzini COND_MI = 0x4, /* Negative */ 347139c1837SPaolo Bonzini COND_PL = 0x5, /* Zero or greater */ 348139c1837SPaolo Bonzini COND_VS = 0x6, /* Overflow */ 349139c1837SPaolo Bonzini COND_VC = 0x7, /* No overflow */ 350139c1837SPaolo Bonzini COND_HI = 0x8, /* Unsigned greater than */ 351139c1837SPaolo Bonzini COND_LS = 0x9, /* Unsigned less or equal */ 352139c1837SPaolo Bonzini COND_GE = 0xa, 353139c1837SPaolo Bonzini COND_LT = 0xb, 354139c1837SPaolo Bonzini COND_GT = 0xc, 355139c1837SPaolo Bonzini COND_LE = 0xd, 356139c1837SPaolo Bonzini COND_AL = 0xe, 357139c1837SPaolo Bonzini COND_NV = 0xf, /* behaves like COND_AL here */ 358139c1837SPaolo Bonzini}; 359139c1837SPaolo Bonzini 360139c1837SPaolo Bonzinistatic const enum aarch64_cond_code tcg_cond_to_aarch64[] = { 361139c1837SPaolo Bonzini [TCG_COND_EQ] = COND_EQ, 362139c1837SPaolo Bonzini [TCG_COND_NE] = COND_NE, 363139c1837SPaolo Bonzini [TCG_COND_LT] = COND_LT, 364139c1837SPaolo Bonzini [TCG_COND_GE] = COND_GE, 365139c1837SPaolo Bonzini [TCG_COND_LE] = COND_LE, 366139c1837SPaolo Bonzini [TCG_COND_GT] = COND_GT, 367139c1837SPaolo Bonzini /* unsigned */ 368139c1837SPaolo Bonzini [TCG_COND_LTU] = COND_LO, 369139c1837SPaolo Bonzini [TCG_COND_GTU] = COND_HI, 370139c1837SPaolo Bonzini [TCG_COND_GEU] = COND_HS, 371139c1837SPaolo Bonzini [TCG_COND_LEU] = COND_LS, 372339adf2fSRichard Henderson /* bit test */ 373339adf2fSRichard Henderson [TCG_COND_TSTEQ] = COND_EQ, 374339adf2fSRichard Henderson [TCG_COND_TSTNE] = COND_NE, 375139c1837SPaolo Bonzini}; 376139c1837SPaolo Bonzini 377139c1837SPaolo Bonzinitypedef enum { 378139c1837SPaolo Bonzini LDST_ST = 0, /* store */ 379139c1837SPaolo Bonzini LDST_LD = 1, /* load */ 380139c1837SPaolo Bonzini LDST_LD_S_X = 2, /* load and sign-extend into Xt */ 381139c1837SPaolo Bonzini LDST_LD_S_W = 3, /* load and sign-extend into Wt */ 382139c1837SPaolo Bonzini} AArch64LdstType; 383139c1837SPaolo Bonzini 384139c1837SPaolo Bonzini/* We encode the format of the insn into the beginning of the name, so that 385139c1837SPaolo Bonzini we can have the preprocessor help "typecheck" the insn vs the output 386139c1837SPaolo Bonzini function. Arm didn't provide us with nice names for the formats, so we 387139c1837SPaolo Bonzini use the section number of the architecture reference manual in which the 388139c1837SPaolo Bonzini instruction group is described. */ 389139c1837SPaolo Bonzinitypedef enum { 390139c1837SPaolo Bonzini /* Compare and branch (immediate). */ 391139c1837SPaolo Bonzini I3201_CBZ = 0x34000000, 392139c1837SPaolo Bonzini I3201_CBNZ = 0x35000000, 393139c1837SPaolo Bonzini 394139c1837SPaolo Bonzini /* Conditional branch (immediate). */ 395139c1837SPaolo Bonzini I3202_B_C = 0x54000000, 396139c1837SPaolo Bonzini 39792a11b93SRichard Henderson /* Test and branch (immediate). */ 39892a11b93SRichard Henderson I3205_TBZ = 0x36000000, 39992a11b93SRichard Henderson I3205_TBNZ = 0x37000000, 40092a11b93SRichard Henderson 401139c1837SPaolo Bonzini /* Unconditional branch (immediate). */ 402139c1837SPaolo Bonzini I3206_B = 0x14000000, 403139c1837SPaolo Bonzini I3206_BL = 0x94000000, 404139c1837SPaolo Bonzini 405139c1837SPaolo Bonzini /* Unconditional branch (register). */ 406139c1837SPaolo Bonzini I3207_BR = 0xd61f0000, 407139c1837SPaolo Bonzini I3207_BLR = 0xd63f0000, 408139c1837SPaolo Bonzini I3207_RET = 0xd65f0000, 409139c1837SPaolo Bonzini 410139c1837SPaolo Bonzini /* AdvSIMD load/store single structure. */ 411139c1837SPaolo Bonzini I3303_LD1R = 0x0d40c000, 412139c1837SPaolo Bonzini 413139c1837SPaolo Bonzini /* Load literal for loading the address at pc-relative offset */ 414139c1837SPaolo Bonzini I3305_LDR = 0x58000000, 415139c1837SPaolo Bonzini I3305_LDR_v64 = 0x5c000000, 416139c1837SPaolo Bonzini I3305_LDR_v128 = 0x9c000000, 417139c1837SPaolo Bonzini 418929124ecSRichard Henderson /* Load/store exclusive. */ 419929124ecSRichard Henderson I3306_LDXP = 0xc8600000, 420929124ecSRichard Henderson I3306_STXP = 0xc8200000, 421929124ecSRichard Henderson 422139c1837SPaolo Bonzini /* Load/store register. Described here as 3.3.12, but the helper 423139c1837SPaolo Bonzini that emits them can transform to 3.3.10 or 3.3.13. */ 424139c1837SPaolo Bonzini I3312_STRB = 0x38000000 | LDST_ST << 22 | MO_8 << 30, 425139c1837SPaolo Bonzini I3312_STRH = 0x38000000 | LDST_ST << 22 | MO_16 << 30, 426139c1837SPaolo Bonzini I3312_STRW = 0x38000000 | LDST_ST << 22 | MO_32 << 30, 427139c1837SPaolo Bonzini I3312_STRX = 0x38000000 | LDST_ST << 22 | MO_64 << 30, 428139c1837SPaolo Bonzini 429139c1837SPaolo Bonzini I3312_LDRB = 0x38000000 | LDST_LD << 22 | MO_8 << 30, 430139c1837SPaolo Bonzini I3312_LDRH = 0x38000000 | LDST_LD << 22 | MO_16 << 30, 431139c1837SPaolo Bonzini I3312_LDRW = 0x38000000 | LDST_LD << 22 | MO_32 << 30, 432139c1837SPaolo Bonzini I3312_LDRX = 0x38000000 | LDST_LD << 22 | MO_64 << 30, 433139c1837SPaolo Bonzini 434139c1837SPaolo Bonzini I3312_LDRSBW = 0x38000000 | LDST_LD_S_W << 22 | MO_8 << 30, 435139c1837SPaolo Bonzini I3312_LDRSHW = 0x38000000 | LDST_LD_S_W << 22 | MO_16 << 30, 436139c1837SPaolo Bonzini 437139c1837SPaolo Bonzini I3312_LDRSBX = 0x38000000 | LDST_LD_S_X << 22 | MO_8 << 30, 438139c1837SPaolo Bonzini I3312_LDRSHX = 0x38000000 | LDST_LD_S_X << 22 | MO_16 << 30, 439139c1837SPaolo Bonzini I3312_LDRSWX = 0x38000000 | LDST_LD_S_X << 22 | MO_32 << 30, 440139c1837SPaolo Bonzini 441139c1837SPaolo Bonzini I3312_LDRVS = 0x3c000000 | LDST_LD << 22 | MO_32 << 30, 442139c1837SPaolo Bonzini I3312_STRVS = 0x3c000000 | LDST_ST << 22 | MO_32 << 30, 443139c1837SPaolo Bonzini 444139c1837SPaolo Bonzini I3312_LDRVD = 0x3c000000 | LDST_LD << 22 | MO_64 << 30, 445139c1837SPaolo Bonzini I3312_STRVD = 0x3c000000 | LDST_ST << 22 | MO_64 << 30, 446139c1837SPaolo Bonzini 447139c1837SPaolo Bonzini I3312_LDRVQ = 0x3c000000 | 3 << 22 | 0 << 30, 448139c1837SPaolo Bonzini I3312_STRVQ = 0x3c000000 | 2 << 22 | 0 << 30, 449139c1837SPaolo Bonzini 450139c1837SPaolo Bonzini I3312_TO_I3310 = 0x00200800, 451139c1837SPaolo Bonzini I3312_TO_I3313 = 0x01000000, 452139c1837SPaolo Bonzini 453139c1837SPaolo Bonzini /* Load/store register pair instructions. */ 454139c1837SPaolo Bonzini I3314_LDP = 0x28400000, 455139c1837SPaolo Bonzini I3314_STP = 0x28000000, 456139c1837SPaolo Bonzini 457139c1837SPaolo Bonzini /* Add/subtract immediate instructions. */ 458139c1837SPaolo Bonzini I3401_ADDI = 0x11000000, 459139c1837SPaolo Bonzini I3401_ADDSI = 0x31000000, 460139c1837SPaolo Bonzini I3401_SUBI = 0x51000000, 461139c1837SPaolo Bonzini I3401_SUBSI = 0x71000000, 462139c1837SPaolo Bonzini 463139c1837SPaolo Bonzini /* Bitfield instructions. */ 464139c1837SPaolo Bonzini I3402_BFM = 0x33000000, 465139c1837SPaolo Bonzini I3402_SBFM = 0x13000000, 466139c1837SPaolo Bonzini I3402_UBFM = 0x53000000, 467139c1837SPaolo Bonzini 468139c1837SPaolo Bonzini /* Extract instruction. */ 469139c1837SPaolo Bonzini I3403_EXTR = 0x13800000, 470139c1837SPaolo Bonzini 471139c1837SPaolo Bonzini /* Logical immediate instructions. */ 472139c1837SPaolo Bonzini I3404_ANDI = 0x12000000, 473139c1837SPaolo Bonzini I3404_ORRI = 0x32000000, 474139c1837SPaolo Bonzini I3404_EORI = 0x52000000, 475f85ab3d2SRichard Henderson I3404_ANDSI = 0x72000000, 476139c1837SPaolo Bonzini 477139c1837SPaolo Bonzini /* Move wide immediate instructions. */ 478139c1837SPaolo Bonzini I3405_MOVN = 0x12800000, 479139c1837SPaolo Bonzini I3405_MOVZ = 0x52800000, 480139c1837SPaolo Bonzini I3405_MOVK = 0x72800000, 481139c1837SPaolo Bonzini 482139c1837SPaolo Bonzini /* PC relative addressing instructions. */ 483139c1837SPaolo Bonzini I3406_ADR = 0x10000000, 484139c1837SPaolo Bonzini I3406_ADRP = 0x90000000, 485139c1837SPaolo Bonzini 486929124ecSRichard Henderson /* Add/subtract extended register instructions. */ 487929124ecSRichard Henderson I3501_ADD = 0x0b200000, 488929124ecSRichard Henderson 489139c1837SPaolo Bonzini /* Add/subtract shifted register instructions (without a shift). */ 490139c1837SPaolo Bonzini I3502_ADD = 0x0b000000, 491139c1837SPaolo Bonzini I3502_ADDS = 0x2b000000, 492139c1837SPaolo Bonzini I3502_SUB = 0x4b000000, 493139c1837SPaolo Bonzini I3502_SUBS = 0x6b000000, 494139c1837SPaolo Bonzini 495139c1837SPaolo Bonzini /* Add/subtract shifted register instructions (with a shift). */ 496139c1837SPaolo Bonzini I3502S_ADD_LSL = I3502_ADD, 497139c1837SPaolo Bonzini 498139c1837SPaolo Bonzini /* Add/subtract with carry instructions. */ 499139c1837SPaolo Bonzini I3503_ADC = 0x1a000000, 500139c1837SPaolo Bonzini I3503_SBC = 0x5a000000, 501139c1837SPaolo Bonzini 502139c1837SPaolo Bonzini /* Conditional select instructions. */ 503139c1837SPaolo Bonzini I3506_CSEL = 0x1a800000, 504139c1837SPaolo Bonzini I3506_CSINC = 0x1a800400, 505139c1837SPaolo Bonzini I3506_CSINV = 0x5a800000, 506139c1837SPaolo Bonzini I3506_CSNEG = 0x5a800400, 507139c1837SPaolo Bonzini 508139c1837SPaolo Bonzini /* Data-processing (1 source) instructions. */ 509139c1837SPaolo Bonzini I3507_CLZ = 0x5ac01000, 510139c1837SPaolo Bonzini I3507_RBIT = 0x5ac00000, 511dfa24dfaSRichard Henderson I3507_REV = 0x5ac00000, /* + size << 10 */ 512139c1837SPaolo Bonzini 513139c1837SPaolo Bonzini /* Data-processing (2 source) instructions. */ 514139c1837SPaolo Bonzini I3508_LSLV = 0x1ac02000, 515139c1837SPaolo Bonzini I3508_LSRV = 0x1ac02400, 516139c1837SPaolo Bonzini I3508_ASRV = 0x1ac02800, 517139c1837SPaolo Bonzini I3508_RORV = 0x1ac02c00, 518139c1837SPaolo Bonzini I3508_SMULH = 0x9b407c00, 519139c1837SPaolo Bonzini I3508_UMULH = 0x9bc07c00, 520139c1837SPaolo Bonzini I3508_UDIV = 0x1ac00800, 521139c1837SPaolo Bonzini I3508_SDIV = 0x1ac00c00, 522139c1837SPaolo Bonzini 523139c1837SPaolo Bonzini /* Data-processing (3 source) instructions. */ 524139c1837SPaolo Bonzini I3509_MADD = 0x1b000000, 525139c1837SPaolo Bonzini I3509_MSUB = 0x1b008000, 526139c1837SPaolo Bonzini 527139c1837SPaolo Bonzini /* Logical shifted register instructions (without a shift). */ 528139c1837SPaolo Bonzini I3510_AND = 0x0a000000, 529139c1837SPaolo Bonzini I3510_BIC = 0x0a200000, 530139c1837SPaolo Bonzini I3510_ORR = 0x2a000000, 531139c1837SPaolo Bonzini I3510_ORN = 0x2a200000, 532139c1837SPaolo Bonzini I3510_EOR = 0x4a000000, 533139c1837SPaolo Bonzini I3510_EON = 0x4a200000, 534139c1837SPaolo Bonzini I3510_ANDS = 0x6a000000, 535139c1837SPaolo Bonzini 536139c1837SPaolo Bonzini /* Logical shifted register instructions (with a shift). */ 537139c1837SPaolo Bonzini I3502S_AND_LSR = I3510_AND | (1 << 22), 538139c1837SPaolo Bonzini 539139c1837SPaolo Bonzini /* AdvSIMD copy */ 540139c1837SPaolo Bonzini I3605_DUP = 0x0e000400, 541139c1837SPaolo Bonzini I3605_INS = 0x4e001c00, 542139c1837SPaolo Bonzini I3605_UMOV = 0x0e003c00, 543139c1837SPaolo Bonzini 544139c1837SPaolo Bonzini /* AdvSIMD modified immediate */ 545139c1837SPaolo Bonzini I3606_MOVI = 0x0f000400, 546139c1837SPaolo Bonzini I3606_MVNI = 0x2f000400, 547139c1837SPaolo Bonzini I3606_BIC = 0x2f001400, 548139c1837SPaolo Bonzini I3606_ORR = 0x0f001400, 549139c1837SPaolo Bonzini 550d81bad24SRichard Henderson /* AdvSIMD scalar shift by immediate */ 551d81bad24SRichard Henderson I3609_SSHR = 0x5f000400, 552d81bad24SRichard Henderson I3609_SSRA = 0x5f001400, 553d81bad24SRichard Henderson I3609_SHL = 0x5f005400, 554d81bad24SRichard Henderson I3609_USHR = 0x7f000400, 555d81bad24SRichard Henderson I3609_USRA = 0x7f001400, 556d81bad24SRichard Henderson I3609_SLI = 0x7f005400, 557d81bad24SRichard Henderson 558d81bad24SRichard Henderson /* AdvSIMD scalar three same */ 559d81bad24SRichard Henderson I3611_SQADD = 0x5e200c00, 560d81bad24SRichard Henderson I3611_SQSUB = 0x5e202c00, 561d81bad24SRichard Henderson I3611_CMGT = 0x5e203400, 562d81bad24SRichard Henderson I3611_CMGE = 0x5e203c00, 563d81bad24SRichard Henderson I3611_SSHL = 0x5e204400, 564d81bad24SRichard Henderson I3611_ADD = 0x5e208400, 565d81bad24SRichard Henderson I3611_CMTST = 0x5e208c00, 566d81bad24SRichard Henderson I3611_UQADD = 0x7e200c00, 567d81bad24SRichard Henderson I3611_UQSUB = 0x7e202c00, 568d81bad24SRichard Henderson I3611_CMHI = 0x7e203400, 569d81bad24SRichard Henderson I3611_CMHS = 0x7e203c00, 570d81bad24SRichard Henderson I3611_USHL = 0x7e204400, 571d81bad24SRichard Henderson I3611_SUB = 0x7e208400, 572d81bad24SRichard Henderson I3611_CMEQ = 0x7e208c00, 573d81bad24SRichard Henderson 574d81bad24SRichard Henderson /* AdvSIMD scalar two-reg misc */ 575d81bad24SRichard Henderson I3612_CMGT0 = 0x5e208800, 576d81bad24SRichard Henderson I3612_CMEQ0 = 0x5e209800, 577d81bad24SRichard Henderson I3612_CMLT0 = 0x5e20a800, 578d81bad24SRichard Henderson I3612_ABS = 0x5e20b800, 579d81bad24SRichard Henderson I3612_CMGE0 = 0x7e208800, 580d81bad24SRichard Henderson I3612_CMLE0 = 0x7e209800, 581d81bad24SRichard Henderson I3612_NEG = 0x7e20b800, 582d81bad24SRichard Henderson 583139c1837SPaolo Bonzini /* AdvSIMD shift by immediate */ 584139c1837SPaolo Bonzini I3614_SSHR = 0x0f000400, 585139c1837SPaolo Bonzini I3614_SSRA = 0x0f001400, 586139c1837SPaolo Bonzini I3614_SHL = 0x0f005400, 587139c1837SPaolo Bonzini I3614_SLI = 0x2f005400, 588139c1837SPaolo Bonzini I3614_USHR = 0x2f000400, 589139c1837SPaolo Bonzini I3614_USRA = 0x2f001400, 590139c1837SPaolo Bonzini 591139c1837SPaolo Bonzini /* AdvSIMD three same. */ 592139c1837SPaolo Bonzini I3616_ADD = 0x0e208400, 593139c1837SPaolo Bonzini I3616_AND = 0x0e201c00, 594139c1837SPaolo Bonzini I3616_BIC = 0x0e601c00, 595139c1837SPaolo Bonzini I3616_BIF = 0x2ee01c00, 596139c1837SPaolo Bonzini I3616_BIT = 0x2ea01c00, 597139c1837SPaolo Bonzini I3616_BSL = 0x2e601c00, 598139c1837SPaolo Bonzini I3616_EOR = 0x2e201c00, 599139c1837SPaolo Bonzini I3616_MUL = 0x0e209c00, 600139c1837SPaolo Bonzini I3616_ORR = 0x0ea01c00, 601139c1837SPaolo Bonzini I3616_ORN = 0x0ee01c00, 602139c1837SPaolo Bonzini I3616_SUB = 0x2e208400, 603139c1837SPaolo Bonzini I3616_CMGT = 0x0e203400, 604139c1837SPaolo Bonzini I3616_CMGE = 0x0e203c00, 605139c1837SPaolo Bonzini I3616_CMTST = 0x0e208c00, 606139c1837SPaolo Bonzini I3616_CMHI = 0x2e203400, 607139c1837SPaolo Bonzini I3616_CMHS = 0x2e203c00, 608139c1837SPaolo Bonzini I3616_CMEQ = 0x2e208c00, 609139c1837SPaolo Bonzini I3616_SMAX = 0x0e206400, 610139c1837SPaolo Bonzini I3616_SMIN = 0x0e206c00, 611139c1837SPaolo Bonzini I3616_SSHL = 0x0e204400, 612139c1837SPaolo Bonzini I3616_SQADD = 0x0e200c00, 613139c1837SPaolo Bonzini I3616_SQSUB = 0x0e202c00, 614139c1837SPaolo Bonzini I3616_UMAX = 0x2e206400, 615139c1837SPaolo Bonzini I3616_UMIN = 0x2e206c00, 616139c1837SPaolo Bonzini I3616_UQADD = 0x2e200c00, 617139c1837SPaolo Bonzini I3616_UQSUB = 0x2e202c00, 618139c1837SPaolo Bonzini I3616_USHL = 0x2e204400, 619139c1837SPaolo Bonzini 620139c1837SPaolo Bonzini /* AdvSIMD two-reg misc. */ 621139c1837SPaolo Bonzini I3617_CMGT0 = 0x0e208800, 622139c1837SPaolo Bonzini I3617_CMEQ0 = 0x0e209800, 623139c1837SPaolo Bonzini I3617_CMLT0 = 0x0e20a800, 624139c1837SPaolo Bonzini I3617_CMGE0 = 0x2e208800, 6256c2c7772SRichard Henderson I3617_CMLE0 = 0x2e209800, 626139c1837SPaolo Bonzini I3617_NOT = 0x2e205800, 627139c1837SPaolo Bonzini I3617_ABS = 0x0e20b800, 628139c1837SPaolo Bonzini I3617_NEG = 0x2e20b800, 629139c1837SPaolo Bonzini 630139c1837SPaolo Bonzini /* System instructions. */ 631139c1837SPaolo Bonzini NOP = 0xd503201f, 632139c1837SPaolo Bonzini DMB_ISH = 0xd50338bf, 633139c1837SPaolo Bonzini DMB_LD = 0x00000100, 634139c1837SPaolo Bonzini DMB_ST = 0x00000200, 6355826a0dbSRichard Henderson 6365826a0dbSRichard Henderson BTI_C = 0xd503245f, 6375826a0dbSRichard Henderson BTI_J = 0xd503249f, 6385826a0dbSRichard Henderson BTI_JC = 0xd50324df, 639139c1837SPaolo Bonzini} AArch64Insn; 640139c1837SPaolo Bonzini 641139c1837SPaolo Bonzinistatic inline uint32_t tcg_in32(TCGContext *s) 642139c1837SPaolo Bonzini{ 643139c1837SPaolo Bonzini uint32_t v = *(uint32_t *)s->code_ptr; 644139c1837SPaolo Bonzini return v; 645139c1837SPaolo Bonzini} 646139c1837SPaolo Bonzini 647139c1837SPaolo Bonzini/* Emit an opcode with "type-checking" of the format. */ 648139c1837SPaolo Bonzini#define tcg_out_insn(S, FMT, OP, ...) \ 649139c1837SPaolo Bonzini glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__) 650139c1837SPaolo Bonzini 651139c1837SPaolo Bonzinistatic void tcg_out_insn_3303(TCGContext *s, AArch64Insn insn, bool q, 652139c1837SPaolo Bonzini TCGReg rt, TCGReg rn, unsigned size) 653139c1837SPaolo Bonzini{ 654139c1837SPaolo Bonzini tcg_out32(s, insn | (rt & 0x1f) | (rn << 5) | (size << 10) | (q << 30)); 655139c1837SPaolo Bonzini} 656139c1837SPaolo Bonzini 657139c1837SPaolo Bonzinistatic void tcg_out_insn_3305(TCGContext *s, AArch64Insn insn, 658139c1837SPaolo Bonzini int imm19, TCGReg rt) 659139c1837SPaolo Bonzini{ 660139c1837SPaolo Bonzini tcg_out32(s, insn | (imm19 & 0x7ffff) << 5 | rt); 661139c1837SPaolo Bonzini} 662139c1837SPaolo Bonzini 663929124ecSRichard Hendersonstatic void tcg_out_insn_3306(TCGContext *s, AArch64Insn insn, TCGReg rs, 664929124ecSRichard Henderson TCGReg rt, TCGReg rt2, TCGReg rn) 665929124ecSRichard Henderson{ 666929124ecSRichard Henderson tcg_out32(s, insn | rs << 16 | rt2 << 10 | rn << 5 | rt); 667929124ecSRichard Henderson} 668929124ecSRichard Henderson 669139c1837SPaolo Bonzinistatic void tcg_out_insn_3201(TCGContext *s, AArch64Insn insn, TCGType ext, 670139c1837SPaolo Bonzini TCGReg rt, int imm19) 671139c1837SPaolo Bonzini{ 672139c1837SPaolo Bonzini tcg_out32(s, insn | ext << 31 | (imm19 & 0x7ffff) << 5 | rt); 673139c1837SPaolo Bonzini} 674139c1837SPaolo Bonzini 675139c1837SPaolo Bonzinistatic void tcg_out_insn_3202(TCGContext *s, AArch64Insn insn, 676139c1837SPaolo Bonzini TCGCond c, int imm19) 677139c1837SPaolo Bonzini{ 678139c1837SPaolo Bonzini tcg_out32(s, insn | tcg_cond_to_aarch64[c] | (imm19 & 0x7ffff) << 5); 679139c1837SPaolo Bonzini} 680139c1837SPaolo Bonzini 68192a11b93SRichard Hendersonstatic void tcg_out_insn_3205(TCGContext *s, AArch64Insn insn, 68292a11b93SRichard Henderson TCGReg rt, int imm6, int imm14) 68392a11b93SRichard Henderson{ 68492a11b93SRichard Henderson insn |= (imm6 & 0x20) << (31 - 5); 68592a11b93SRichard Henderson insn |= (imm6 & 0x1f) << 19; 68692a11b93SRichard Henderson tcg_out32(s, insn | (imm14 & 0x3fff) << 5 | rt); 68792a11b93SRichard Henderson} 68892a11b93SRichard Henderson 689139c1837SPaolo Bonzinistatic void tcg_out_insn_3206(TCGContext *s, AArch64Insn insn, int imm26) 690139c1837SPaolo Bonzini{ 691139c1837SPaolo Bonzini tcg_out32(s, insn | (imm26 & 0x03ffffff)); 692139c1837SPaolo Bonzini} 693139c1837SPaolo Bonzini 694139c1837SPaolo Bonzinistatic void tcg_out_insn_3207(TCGContext *s, AArch64Insn insn, TCGReg rn) 695139c1837SPaolo Bonzini{ 696139c1837SPaolo Bonzini tcg_out32(s, insn | rn << 5); 697139c1837SPaolo Bonzini} 698139c1837SPaolo Bonzini 699139c1837SPaolo Bonzinistatic void tcg_out_insn_3314(TCGContext *s, AArch64Insn insn, 700139c1837SPaolo Bonzini TCGReg r1, TCGReg r2, TCGReg rn, 701139c1837SPaolo Bonzini tcg_target_long ofs, bool pre, bool w) 702139c1837SPaolo Bonzini{ 703139c1837SPaolo Bonzini insn |= 1u << 31; /* ext */ 704139c1837SPaolo Bonzini insn |= pre << 24; 705139c1837SPaolo Bonzini insn |= w << 23; 706139c1837SPaolo Bonzini 707139c1837SPaolo Bonzini tcg_debug_assert(ofs >= -0x200 && ofs < 0x200 && (ofs & 7) == 0); 708139c1837SPaolo Bonzini insn |= (ofs & (0x7f << 3)) << (15 - 3); 709139c1837SPaolo Bonzini 710139c1837SPaolo Bonzini tcg_out32(s, insn | r2 << 10 | rn << 5 | r1); 711139c1837SPaolo Bonzini} 712139c1837SPaolo Bonzini 713139c1837SPaolo Bonzinistatic void tcg_out_insn_3401(TCGContext *s, AArch64Insn insn, TCGType ext, 714139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, uint64_t aimm) 715139c1837SPaolo Bonzini{ 716139c1837SPaolo Bonzini if (aimm > 0xfff) { 717139c1837SPaolo Bonzini tcg_debug_assert((aimm & 0xfff) == 0); 718139c1837SPaolo Bonzini aimm >>= 12; 719139c1837SPaolo Bonzini tcg_debug_assert(aimm <= 0xfff); 720139c1837SPaolo Bonzini aimm |= 1 << 12; /* apply LSL 12 */ 721139c1837SPaolo Bonzini } 722139c1837SPaolo Bonzini tcg_out32(s, insn | ext << 31 | aimm << 10 | rn << 5 | rd); 723139c1837SPaolo Bonzini} 724139c1837SPaolo Bonzini 725139c1837SPaolo Bonzini/* This function can be used for both 3.4.2 (Bitfield) and 3.4.4 726139c1837SPaolo Bonzini (Logical immediate). Both insn groups have N, IMMR and IMMS fields 727139c1837SPaolo Bonzini that feed the DecodeBitMasks pseudo function. */ 728139c1837SPaolo Bonzinistatic void tcg_out_insn_3402(TCGContext *s, AArch64Insn insn, TCGType ext, 729139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, int n, int immr, int imms) 730139c1837SPaolo Bonzini{ 731139c1837SPaolo Bonzini tcg_out32(s, insn | ext << 31 | n << 22 | immr << 16 | imms << 10 732139c1837SPaolo Bonzini | rn << 5 | rd); 733139c1837SPaolo Bonzini} 734139c1837SPaolo Bonzini 735139c1837SPaolo Bonzini#define tcg_out_insn_3404 tcg_out_insn_3402 736139c1837SPaolo Bonzini 737139c1837SPaolo Bonzinistatic void tcg_out_insn_3403(TCGContext *s, AArch64Insn insn, TCGType ext, 738139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, TCGReg rm, int imms) 739139c1837SPaolo Bonzini{ 740139c1837SPaolo Bonzini tcg_out32(s, insn | ext << 31 | ext << 22 | rm << 16 | imms << 10 741139c1837SPaolo Bonzini | rn << 5 | rd); 742139c1837SPaolo Bonzini} 743139c1837SPaolo Bonzini 744139c1837SPaolo Bonzini/* This function is used for the Move (wide immediate) instruction group. 745139c1837SPaolo Bonzini Note that SHIFT is a full shift count, not the 2 bit HW field. */ 746139c1837SPaolo Bonzinistatic void tcg_out_insn_3405(TCGContext *s, AArch64Insn insn, TCGType ext, 747139c1837SPaolo Bonzini TCGReg rd, uint16_t half, unsigned shift) 748139c1837SPaolo Bonzini{ 749139c1837SPaolo Bonzini tcg_debug_assert((shift & ~0x30) == 0); 750139c1837SPaolo Bonzini tcg_out32(s, insn | ext << 31 | shift << (21 - 4) | half << 5 | rd); 751139c1837SPaolo Bonzini} 752139c1837SPaolo Bonzini 753139c1837SPaolo Bonzinistatic void tcg_out_insn_3406(TCGContext *s, AArch64Insn insn, 754139c1837SPaolo Bonzini TCGReg rd, int64_t disp) 755139c1837SPaolo Bonzini{ 756139c1837SPaolo Bonzini tcg_out32(s, insn | (disp & 3) << 29 | (disp & 0x1ffffc) << (5 - 2) | rd); 757139c1837SPaolo Bonzini} 758139c1837SPaolo Bonzini 759929124ecSRichard Hendersonstatic inline void tcg_out_insn_3501(TCGContext *s, AArch64Insn insn, 760929124ecSRichard Henderson TCGType sf, TCGReg rd, TCGReg rn, 761929124ecSRichard Henderson TCGReg rm, int opt, int imm3) 762929124ecSRichard Henderson{ 763929124ecSRichard Henderson tcg_out32(s, insn | sf << 31 | rm << 16 | opt << 13 | 764929124ecSRichard Henderson imm3 << 10 | rn << 5 | rd); 765929124ecSRichard Henderson} 766929124ecSRichard Henderson 767139c1837SPaolo Bonzini/* This function is for both 3.5.2 (Add/Subtract shifted register), for 768139c1837SPaolo Bonzini the rare occasion when we actually want to supply a shift amount. */ 769139c1837SPaolo Bonzinistatic inline void tcg_out_insn_3502S(TCGContext *s, AArch64Insn insn, 770139c1837SPaolo Bonzini TCGType ext, TCGReg rd, TCGReg rn, 771139c1837SPaolo Bonzini TCGReg rm, int imm6) 772139c1837SPaolo Bonzini{ 773139c1837SPaolo Bonzini tcg_out32(s, insn | ext << 31 | rm << 16 | imm6 << 10 | rn << 5 | rd); 774139c1837SPaolo Bonzini} 775139c1837SPaolo Bonzini 776139c1837SPaolo Bonzini/* This function is for 3.5.2 (Add/subtract shifted register), 777139c1837SPaolo Bonzini and 3.5.10 (Logical shifted register), for the vast majorty of cases 778139c1837SPaolo Bonzini when we don't want to apply a shift. Thus it can also be used for 779139c1837SPaolo Bonzini 3.5.3 (Add/subtract with carry) and 3.5.8 (Data processing 2 source). */ 780139c1837SPaolo Bonzinistatic void tcg_out_insn_3502(TCGContext *s, AArch64Insn insn, TCGType ext, 781139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, TCGReg rm) 782139c1837SPaolo Bonzini{ 783139c1837SPaolo Bonzini tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd); 784139c1837SPaolo Bonzini} 785139c1837SPaolo Bonzini 786139c1837SPaolo Bonzini#define tcg_out_insn_3503 tcg_out_insn_3502 787139c1837SPaolo Bonzini#define tcg_out_insn_3508 tcg_out_insn_3502 788139c1837SPaolo Bonzini#define tcg_out_insn_3510 tcg_out_insn_3502 789139c1837SPaolo Bonzini 790139c1837SPaolo Bonzinistatic void tcg_out_insn_3506(TCGContext *s, AArch64Insn insn, TCGType ext, 791139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, TCGReg rm, TCGCond c) 792139c1837SPaolo Bonzini{ 793139c1837SPaolo Bonzini tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd 794139c1837SPaolo Bonzini | tcg_cond_to_aarch64[c] << 12); 795139c1837SPaolo Bonzini} 796139c1837SPaolo Bonzini 797139c1837SPaolo Bonzinistatic void tcg_out_insn_3507(TCGContext *s, AArch64Insn insn, TCGType ext, 798139c1837SPaolo Bonzini TCGReg rd, TCGReg rn) 799139c1837SPaolo Bonzini{ 800139c1837SPaolo Bonzini tcg_out32(s, insn | ext << 31 | rn << 5 | rd); 801139c1837SPaolo Bonzini} 802139c1837SPaolo Bonzini 803139c1837SPaolo Bonzinistatic void tcg_out_insn_3509(TCGContext *s, AArch64Insn insn, TCGType ext, 804139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, TCGReg rm, TCGReg ra) 805139c1837SPaolo Bonzini{ 806139c1837SPaolo Bonzini tcg_out32(s, insn | ext << 31 | rm << 16 | ra << 10 | rn << 5 | rd); 807139c1837SPaolo Bonzini} 808139c1837SPaolo Bonzini 809139c1837SPaolo Bonzinistatic void tcg_out_insn_3605(TCGContext *s, AArch64Insn insn, bool q, 810139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, int dst_idx, int src_idx) 811139c1837SPaolo Bonzini{ 812139c1837SPaolo Bonzini /* Note that bit 11 set means general register input. Therefore 813139c1837SPaolo Bonzini we can handle both register sets with one function. */ 814139c1837SPaolo Bonzini tcg_out32(s, insn | q << 30 | (dst_idx << 16) | (src_idx << 11) 815139c1837SPaolo Bonzini | (rd & 0x1f) | (~rn & 0x20) << 6 | (rn & 0x1f) << 5); 816139c1837SPaolo Bonzini} 817139c1837SPaolo Bonzini 818139c1837SPaolo Bonzinistatic void tcg_out_insn_3606(TCGContext *s, AArch64Insn insn, bool q, 819139c1837SPaolo Bonzini TCGReg rd, bool op, int cmode, uint8_t imm8) 820139c1837SPaolo Bonzini{ 821139c1837SPaolo Bonzini tcg_out32(s, insn | q << 30 | op << 29 | cmode << 12 | (rd & 0x1f) 822139c1837SPaolo Bonzini | (imm8 & 0xe0) << (16 - 5) | (imm8 & 0x1f) << 5); 823139c1837SPaolo Bonzini} 824139c1837SPaolo Bonzini 825d81bad24SRichard Hendersonstatic void tcg_out_insn_3609(TCGContext *s, AArch64Insn insn, 826d81bad24SRichard Henderson TCGReg rd, TCGReg rn, unsigned immhb) 827d81bad24SRichard Henderson{ 828d81bad24SRichard Henderson tcg_out32(s, insn | immhb << 16 | (rn & 0x1f) << 5 | (rd & 0x1f)); 829d81bad24SRichard Henderson} 830d81bad24SRichard Henderson 831d81bad24SRichard Hendersonstatic void tcg_out_insn_3611(TCGContext *s, AArch64Insn insn, 832d81bad24SRichard Henderson unsigned size, TCGReg rd, TCGReg rn, TCGReg rm) 833d81bad24SRichard Henderson{ 834d81bad24SRichard Henderson tcg_out32(s, insn | (size << 22) | (rm & 0x1f) << 16 835d81bad24SRichard Henderson | (rn & 0x1f) << 5 | (rd & 0x1f)); 836d81bad24SRichard Henderson} 837d81bad24SRichard Henderson 838d81bad24SRichard Hendersonstatic void tcg_out_insn_3612(TCGContext *s, AArch64Insn insn, 839d81bad24SRichard Henderson unsigned size, TCGReg rd, TCGReg rn) 840d81bad24SRichard Henderson{ 841d81bad24SRichard Henderson tcg_out32(s, insn | (size << 22) | (rn & 0x1f) << 5 | (rd & 0x1f)); 842d81bad24SRichard Henderson} 843d81bad24SRichard Henderson 844139c1837SPaolo Bonzinistatic void tcg_out_insn_3614(TCGContext *s, AArch64Insn insn, bool q, 845139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, unsigned immhb) 846139c1837SPaolo Bonzini{ 847139c1837SPaolo Bonzini tcg_out32(s, insn | q << 30 | immhb << 16 848139c1837SPaolo Bonzini | (rn & 0x1f) << 5 | (rd & 0x1f)); 849139c1837SPaolo Bonzini} 850139c1837SPaolo Bonzini 851139c1837SPaolo Bonzinistatic void tcg_out_insn_3616(TCGContext *s, AArch64Insn insn, bool q, 852139c1837SPaolo Bonzini unsigned size, TCGReg rd, TCGReg rn, TCGReg rm) 853139c1837SPaolo Bonzini{ 854139c1837SPaolo Bonzini tcg_out32(s, insn | q << 30 | (size << 22) | (rm & 0x1f) << 16 855139c1837SPaolo Bonzini | (rn & 0x1f) << 5 | (rd & 0x1f)); 856139c1837SPaolo Bonzini} 857139c1837SPaolo Bonzini 858139c1837SPaolo Bonzinistatic void tcg_out_insn_3617(TCGContext *s, AArch64Insn insn, bool q, 859139c1837SPaolo Bonzini unsigned size, TCGReg rd, TCGReg rn) 860139c1837SPaolo Bonzini{ 861139c1837SPaolo Bonzini tcg_out32(s, insn | q << 30 | (size << 22) 862139c1837SPaolo Bonzini | (rn & 0x1f) << 5 | (rd & 0x1f)); 863139c1837SPaolo Bonzini} 864139c1837SPaolo Bonzini 865139c1837SPaolo Bonzinistatic void tcg_out_insn_3310(TCGContext *s, AArch64Insn insn, 866139c1837SPaolo Bonzini TCGReg rd, TCGReg base, TCGType ext, 867139c1837SPaolo Bonzini TCGReg regoff) 868139c1837SPaolo Bonzini{ 869139c1837SPaolo Bonzini /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */ 870139c1837SPaolo Bonzini tcg_out32(s, insn | I3312_TO_I3310 | regoff << 16 | 871139c1837SPaolo Bonzini 0x4000 | ext << 13 | base << 5 | (rd & 0x1f)); 872139c1837SPaolo Bonzini} 873139c1837SPaolo Bonzini 874139c1837SPaolo Bonzinistatic void tcg_out_insn_3312(TCGContext *s, AArch64Insn insn, 875139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, intptr_t offset) 876139c1837SPaolo Bonzini{ 877139c1837SPaolo Bonzini tcg_out32(s, insn | (offset & 0x1ff) << 12 | rn << 5 | (rd & 0x1f)); 878139c1837SPaolo Bonzini} 879139c1837SPaolo Bonzini 880139c1837SPaolo Bonzinistatic void tcg_out_insn_3313(TCGContext *s, AArch64Insn insn, 881139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, uintptr_t scaled_uimm) 882139c1837SPaolo Bonzini{ 883139c1837SPaolo Bonzini /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */ 884139c1837SPaolo Bonzini tcg_out32(s, insn | I3312_TO_I3313 | scaled_uimm << 10 885139c1837SPaolo Bonzini | rn << 5 | (rd & 0x1f)); 886139c1837SPaolo Bonzini} 887139c1837SPaolo Bonzini 8885826a0dbSRichard Hendersonstatic void tcg_out_bti(TCGContext *s, AArch64Insn insn) 8895826a0dbSRichard Henderson{ 8905826a0dbSRichard Henderson /* 8915826a0dbSRichard Henderson * While BTI insns are nops on hosts without FEAT_BTI, 8925826a0dbSRichard Henderson * there is no point in emitting them in that case either. 8935826a0dbSRichard Henderson */ 8945826a0dbSRichard Henderson if (cpuinfo & CPUINFO_BTI) { 8955826a0dbSRichard Henderson tcg_out32(s, insn); 8965826a0dbSRichard Henderson } 8975826a0dbSRichard Henderson} 8985826a0dbSRichard Henderson 899139c1837SPaolo Bonzini/* Register to register move using ORR (shifted register with no shift). */ 900139c1837SPaolo Bonzinistatic void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rm) 901139c1837SPaolo Bonzini{ 902139c1837SPaolo Bonzini tcg_out_insn(s, 3510, ORR, ext, rd, TCG_REG_XZR, rm); 903139c1837SPaolo Bonzini} 904139c1837SPaolo Bonzini 905139c1837SPaolo Bonzini/* Register to register move using ADDI (move to/from SP). */ 906139c1837SPaolo Bonzinistatic void tcg_out_movr_sp(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn) 907139c1837SPaolo Bonzini{ 908139c1837SPaolo Bonzini tcg_out_insn(s, 3401, ADDI, ext, rd, rn, 0); 909139c1837SPaolo Bonzini} 910139c1837SPaolo Bonzini 911139c1837SPaolo Bonzini/* This function is used for the Logical (immediate) instruction group. 912139c1837SPaolo Bonzini The value of LIMM must satisfy IS_LIMM. See the comment above about 913139c1837SPaolo Bonzini only supporting simplified logical immediates. */ 914139c1837SPaolo Bonzinistatic void tcg_out_logicali(TCGContext *s, AArch64Insn insn, TCGType ext, 915139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, uint64_t limm) 916139c1837SPaolo Bonzini{ 917139c1837SPaolo Bonzini unsigned h, l, r, c; 918139c1837SPaolo Bonzini 919139c1837SPaolo Bonzini tcg_debug_assert(is_limm(limm)); 920139c1837SPaolo Bonzini 921139c1837SPaolo Bonzini h = clz64(limm); 922139c1837SPaolo Bonzini l = ctz64(limm); 923139c1837SPaolo Bonzini if (l == 0) { 924139c1837SPaolo Bonzini r = 0; /* form 0....01....1 */ 925139c1837SPaolo Bonzini c = ctz64(~limm) - 1; 926139c1837SPaolo Bonzini if (h == 0) { 927139c1837SPaolo Bonzini r = clz64(~limm); /* form 1..10..01..1 */ 928139c1837SPaolo Bonzini c += r; 929139c1837SPaolo Bonzini } 930139c1837SPaolo Bonzini } else { 931139c1837SPaolo Bonzini r = 64 - l; /* form 1....10....0 or 0..01..10..0 */ 932139c1837SPaolo Bonzini c = r - h - 1; 933139c1837SPaolo Bonzini } 934139c1837SPaolo Bonzini if (ext == TCG_TYPE_I32) { 935139c1837SPaolo Bonzini r &= 31; 936139c1837SPaolo Bonzini c &= 31; 937139c1837SPaolo Bonzini } 938139c1837SPaolo Bonzini 939139c1837SPaolo Bonzini tcg_out_insn_3404(s, insn, ext, rd, rn, ext, r, c); 940139c1837SPaolo Bonzini} 941139c1837SPaolo Bonzini 9424e186175SRichard Hendersonstatic void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece, 9434e186175SRichard Henderson TCGReg rd, int64_t v64) 944139c1837SPaolo Bonzini{ 945139c1837SPaolo Bonzini bool q = type == TCG_TYPE_V128; 946139c1837SPaolo Bonzini int cmode, imm8, i; 947139c1837SPaolo Bonzini 948139c1837SPaolo Bonzini /* Test all bytes equal first. */ 9494e186175SRichard Henderson if (vece == MO_8) { 950139c1837SPaolo Bonzini imm8 = (uint8_t)v64; 951139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MOVI, q, rd, 0, 0xe, imm8); 952139c1837SPaolo Bonzini return; 953139c1837SPaolo Bonzini } 954139c1837SPaolo Bonzini 955139c1837SPaolo Bonzini /* 956139c1837SPaolo Bonzini * Test all bytes 0x00 or 0xff second. This can match cases that 957139c1837SPaolo Bonzini * might otherwise take 2 or 3 insns for MO_16 or MO_32 below. 958139c1837SPaolo Bonzini */ 959139c1837SPaolo Bonzini for (i = imm8 = 0; i < 8; i++) { 960139c1837SPaolo Bonzini uint8_t byte = v64 >> (i * 8); 961139c1837SPaolo Bonzini if (byte == 0xff) { 962139c1837SPaolo Bonzini imm8 |= 1 << i; 963139c1837SPaolo Bonzini } else if (byte != 0) { 964139c1837SPaolo Bonzini goto fail_bytes; 965139c1837SPaolo Bonzini } 966139c1837SPaolo Bonzini } 967139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MOVI, q, rd, 1, 0xe, imm8); 968139c1837SPaolo Bonzini return; 969139c1837SPaolo Bonzini fail_bytes: 970139c1837SPaolo Bonzini 971139c1837SPaolo Bonzini /* 972139c1837SPaolo Bonzini * Tests for various replications. For each element width, if we 973139c1837SPaolo Bonzini * cannot find an expansion there's no point checking a larger 974139c1837SPaolo Bonzini * width because we already know by replication it cannot match. 975139c1837SPaolo Bonzini */ 9764e186175SRichard Henderson if (vece == MO_16) { 977139c1837SPaolo Bonzini uint16_t v16 = v64; 978139c1837SPaolo Bonzini 979139c1837SPaolo Bonzini if (is_shimm16(v16, &cmode, &imm8)) { 980139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MOVI, q, rd, 0, cmode, imm8); 981139c1837SPaolo Bonzini return; 982139c1837SPaolo Bonzini } 983139c1837SPaolo Bonzini if (is_shimm16(~v16, &cmode, &imm8)) { 984139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MVNI, q, rd, 0, cmode, imm8); 985139c1837SPaolo Bonzini return; 986139c1837SPaolo Bonzini } 987139c1837SPaolo Bonzini 988139c1837SPaolo Bonzini /* 989139c1837SPaolo Bonzini * Otherwise, all remaining constants can be loaded in two insns: 990139c1837SPaolo Bonzini * rd = v16 & 0xff, rd |= v16 & 0xff00. 991139c1837SPaolo Bonzini */ 992139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MOVI, q, rd, 0, 0x8, v16 & 0xff); 993139c1837SPaolo Bonzini tcg_out_insn(s, 3606, ORR, q, rd, 0, 0xa, v16 >> 8); 994139c1837SPaolo Bonzini return; 9954e186175SRichard Henderson } else if (vece == MO_32) { 996139c1837SPaolo Bonzini uint32_t v32 = v64; 997139c1837SPaolo Bonzini uint32_t n32 = ~v32; 998139c1837SPaolo Bonzini 999139c1837SPaolo Bonzini if (is_shimm32(v32, &cmode, &imm8) || 1000139c1837SPaolo Bonzini is_soimm32(v32, &cmode, &imm8) || 1001139c1837SPaolo Bonzini is_fimm32(v32, &cmode, &imm8)) { 1002139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MOVI, q, rd, 0, cmode, imm8); 1003139c1837SPaolo Bonzini return; 1004139c1837SPaolo Bonzini } 1005139c1837SPaolo Bonzini if (is_shimm32(n32, &cmode, &imm8) || 1006139c1837SPaolo Bonzini is_soimm32(n32, &cmode, &imm8)) { 1007139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MVNI, q, rd, 0, cmode, imm8); 1008139c1837SPaolo Bonzini return; 1009139c1837SPaolo Bonzini } 1010139c1837SPaolo Bonzini 1011139c1837SPaolo Bonzini /* 1012139c1837SPaolo Bonzini * Restrict the set of constants to those we can load with 1013139c1837SPaolo Bonzini * two instructions. Others we load from the pool. 1014139c1837SPaolo Bonzini */ 1015139c1837SPaolo Bonzini i = is_shimm32_pair(v32, &cmode, &imm8); 1016139c1837SPaolo Bonzini if (i) { 1017139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MOVI, q, rd, 0, cmode, imm8); 1018139c1837SPaolo Bonzini tcg_out_insn(s, 3606, ORR, q, rd, 0, i, extract32(v32, i * 4, 8)); 1019139c1837SPaolo Bonzini return; 1020139c1837SPaolo Bonzini } 1021139c1837SPaolo Bonzini i = is_shimm32_pair(n32, &cmode, &imm8); 1022139c1837SPaolo Bonzini if (i) { 1023139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MVNI, q, rd, 0, cmode, imm8); 1024139c1837SPaolo Bonzini tcg_out_insn(s, 3606, BIC, q, rd, 0, i, extract32(n32, i * 4, 8)); 1025139c1837SPaolo Bonzini return; 1026139c1837SPaolo Bonzini } 1027139c1837SPaolo Bonzini } else if (is_fimm64(v64, &cmode, &imm8)) { 1028139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MOVI, q, rd, 1, cmode, imm8); 1029139c1837SPaolo Bonzini return; 1030139c1837SPaolo Bonzini } 1031139c1837SPaolo Bonzini 1032139c1837SPaolo Bonzini /* 1033139c1837SPaolo Bonzini * As a last resort, load from the constant pool. Sadly there 1034139c1837SPaolo Bonzini * is no LD1R (literal), so store the full 16-byte vector. 1035139c1837SPaolo Bonzini */ 1036139c1837SPaolo Bonzini if (type == TCG_TYPE_V128) { 1037139c1837SPaolo Bonzini new_pool_l2(s, R_AARCH64_CONDBR19, s->code_ptr, 0, v64, v64); 1038139c1837SPaolo Bonzini tcg_out_insn(s, 3305, LDR_v128, 0, rd); 1039139c1837SPaolo Bonzini } else { 1040139c1837SPaolo Bonzini new_pool_label(s, v64, R_AARCH64_CONDBR19, s->code_ptr, 0); 1041139c1837SPaolo Bonzini tcg_out_insn(s, 3305, LDR_v64, 0, rd); 1042139c1837SPaolo Bonzini } 1043139c1837SPaolo Bonzini} 1044139c1837SPaolo Bonzini 1045139c1837SPaolo Bonzinistatic bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece, 1046139c1837SPaolo Bonzini TCGReg rd, TCGReg rs) 1047139c1837SPaolo Bonzini{ 1048139c1837SPaolo Bonzini int is_q = type - TCG_TYPE_V64; 1049139c1837SPaolo Bonzini tcg_out_insn(s, 3605, DUP, is_q, rd, rs, 1 << vece, 0); 1050139c1837SPaolo Bonzini return true; 1051139c1837SPaolo Bonzini} 1052139c1837SPaolo Bonzini 1053139c1837SPaolo Bonzinistatic bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece, 1054139c1837SPaolo Bonzini TCGReg r, TCGReg base, intptr_t offset) 1055139c1837SPaolo Bonzini{ 1056d67bcbddSRichard Henderson TCGReg temp = TCG_REG_TMP0; 1057139c1837SPaolo Bonzini 1058139c1837SPaolo Bonzini if (offset < -0xffffff || offset > 0xffffff) { 1059139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_PTR, temp, offset); 1060139c1837SPaolo Bonzini tcg_out_insn(s, 3502, ADD, 1, temp, temp, base); 1061139c1837SPaolo Bonzini base = temp; 1062139c1837SPaolo Bonzini } else { 1063139c1837SPaolo Bonzini AArch64Insn add_insn = I3401_ADDI; 1064139c1837SPaolo Bonzini 1065139c1837SPaolo Bonzini if (offset < 0) { 1066139c1837SPaolo Bonzini add_insn = I3401_SUBI; 1067139c1837SPaolo Bonzini offset = -offset; 1068139c1837SPaolo Bonzini } 1069139c1837SPaolo Bonzini if (offset & 0xfff000) { 1070139c1837SPaolo Bonzini tcg_out_insn_3401(s, add_insn, 1, temp, base, offset & 0xfff000); 1071139c1837SPaolo Bonzini base = temp; 1072139c1837SPaolo Bonzini } 1073139c1837SPaolo Bonzini if (offset & 0xfff) { 1074139c1837SPaolo Bonzini tcg_out_insn_3401(s, add_insn, 1, temp, base, offset & 0xfff); 1075139c1837SPaolo Bonzini base = temp; 1076139c1837SPaolo Bonzini } 1077139c1837SPaolo Bonzini } 1078139c1837SPaolo Bonzini tcg_out_insn(s, 3303, LD1R, type == TCG_TYPE_V128, r, base, vece); 1079139c1837SPaolo Bonzini return true; 1080139c1837SPaolo Bonzini} 1081139c1837SPaolo Bonzini 1082139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, 1083139c1837SPaolo Bonzini tcg_target_long value) 1084139c1837SPaolo Bonzini{ 1085139c1837SPaolo Bonzini tcg_target_long svalue = value; 1086139c1837SPaolo Bonzini tcg_target_long ivalue = ~value; 1087139c1837SPaolo Bonzini tcg_target_long t0, t1, t2; 1088139c1837SPaolo Bonzini int s0, s1; 1089139c1837SPaolo Bonzini AArch64Insn opc; 1090139c1837SPaolo Bonzini 1091139c1837SPaolo Bonzini switch (type) { 1092139c1837SPaolo Bonzini case TCG_TYPE_I32: 1093139c1837SPaolo Bonzini case TCG_TYPE_I64: 1094139c1837SPaolo Bonzini tcg_debug_assert(rd < 32); 1095139c1837SPaolo Bonzini break; 1096139c1837SPaolo Bonzini default: 1097139c1837SPaolo Bonzini g_assert_not_reached(); 1098139c1837SPaolo Bonzini } 1099139c1837SPaolo Bonzini 1100139c1837SPaolo Bonzini /* For 32-bit values, discard potential garbage in value. For 64-bit 1101139c1837SPaolo Bonzini values within [2**31, 2**32-1], we can create smaller sequences by 1102139c1837SPaolo Bonzini interpreting this as a negative 32-bit number, while ensuring that 1103139c1837SPaolo Bonzini the high 32 bits are cleared by setting SF=0. */ 1104139c1837SPaolo Bonzini if (type == TCG_TYPE_I32 || (value & ~0xffffffffull) == 0) { 1105139c1837SPaolo Bonzini svalue = (int32_t)value; 1106139c1837SPaolo Bonzini value = (uint32_t)value; 1107139c1837SPaolo Bonzini ivalue = (uint32_t)ivalue; 1108139c1837SPaolo Bonzini type = TCG_TYPE_I32; 1109139c1837SPaolo Bonzini } 1110139c1837SPaolo Bonzini 1111139c1837SPaolo Bonzini /* Speed things up by handling the common case of small positive 1112139c1837SPaolo Bonzini and negative values specially. */ 1113139c1837SPaolo Bonzini if ((value & ~0xffffull) == 0) { 1114139c1837SPaolo Bonzini tcg_out_insn(s, 3405, MOVZ, type, rd, value, 0); 1115139c1837SPaolo Bonzini return; 1116139c1837SPaolo Bonzini } else if ((ivalue & ~0xffffull) == 0) { 1117139c1837SPaolo Bonzini tcg_out_insn(s, 3405, MOVN, type, rd, ivalue, 0); 1118139c1837SPaolo Bonzini return; 1119139c1837SPaolo Bonzini } 1120139c1837SPaolo Bonzini 1121139c1837SPaolo Bonzini /* Check for bitfield immediates. For the benefit of 32-bit quantities, 1122139c1837SPaolo Bonzini use the sign-extended value. That lets us match rotated values such 1123139c1837SPaolo Bonzini as 0xff0000ff with the same 64-bit logic matching 0xffffffffff0000ff. */ 1124139c1837SPaolo Bonzini if (is_limm(svalue)) { 1125139c1837SPaolo Bonzini tcg_out_logicali(s, I3404_ORRI, type, rd, TCG_REG_XZR, svalue); 1126139c1837SPaolo Bonzini return; 1127139c1837SPaolo Bonzini } 1128139c1837SPaolo Bonzini 1129139c1837SPaolo Bonzini /* Look for host pointer values within 4G of the PC. This happens 1130139c1837SPaolo Bonzini often when loading pointers to QEMU's own data structures. */ 1131139c1837SPaolo Bonzini if (type == TCG_TYPE_I64) { 1132ffba3eb3SRichard Henderson intptr_t src_rx = (intptr_t)tcg_splitwx_to_rx(s->code_ptr); 1133ffba3eb3SRichard Henderson tcg_target_long disp = value - src_rx; 1134139c1837SPaolo Bonzini if (disp == sextract64(disp, 0, 21)) { 1135139c1837SPaolo Bonzini tcg_out_insn(s, 3406, ADR, rd, disp); 1136139c1837SPaolo Bonzini return; 1137139c1837SPaolo Bonzini } 1138ffba3eb3SRichard Henderson disp = (value >> 12) - (src_rx >> 12); 1139139c1837SPaolo Bonzini if (disp == sextract64(disp, 0, 21)) { 1140139c1837SPaolo Bonzini tcg_out_insn(s, 3406, ADRP, rd, disp); 1141139c1837SPaolo Bonzini if (value & 0xfff) { 1142139c1837SPaolo Bonzini tcg_out_insn(s, 3401, ADDI, type, rd, rd, value & 0xfff); 1143139c1837SPaolo Bonzini } 1144139c1837SPaolo Bonzini return; 1145139c1837SPaolo Bonzini } 1146139c1837SPaolo Bonzini } 1147139c1837SPaolo Bonzini 1148139c1837SPaolo Bonzini /* Would it take fewer insns to begin with MOVN? */ 1149139c1837SPaolo Bonzini if (ctpop64(value) >= 32) { 1150139c1837SPaolo Bonzini t0 = ivalue; 1151139c1837SPaolo Bonzini opc = I3405_MOVN; 1152139c1837SPaolo Bonzini } else { 1153139c1837SPaolo Bonzini t0 = value; 1154139c1837SPaolo Bonzini opc = I3405_MOVZ; 1155139c1837SPaolo Bonzini } 1156139c1837SPaolo Bonzini s0 = ctz64(t0) & (63 & -16); 11577ceee3a1SRichard Henderson t1 = t0 & ~(0xffffull << s0); 1158139c1837SPaolo Bonzini s1 = ctz64(t1) & (63 & -16); 11597ceee3a1SRichard Henderson t2 = t1 & ~(0xffffull << s1); 1160139c1837SPaolo Bonzini if (t2 == 0) { 1161139c1837SPaolo Bonzini tcg_out_insn_3405(s, opc, type, rd, t0 >> s0, s0); 1162139c1837SPaolo Bonzini if (t1 != 0) { 1163139c1837SPaolo Bonzini tcg_out_insn(s, 3405, MOVK, type, rd, value >> s1, s1); 1164139c1837SPaolo Bonzini } 1165139c1837SPaolo Bonzini return; 1166139c1837SPaolo Bonzini } 1167139c1837SPaolo Bonzini 1168139c1837SPaolo Bonzini /* For more than 2 insns, dump it into the constant pool. */ 1169139c1837SPaolo Bonzini new_pool_label(s, value, R_AARCH64_CONDBR19, s->code_ptr, 0); 1170139c1837SPaolo Bonzini tcg_out_insn(s, 3305, LDR, 0, rd); 1171139c1837SPaolo Bonzini} 1172139c1837SPaolo Bonzini 1173767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2) 1174767c2503SRichard Henderson{ 1175767c2503SRichard Henderson return false; 1176767c2503SRichard Henderson} 1177767c2503SRichard Henderson 11786a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs, 11796a6d772eSRichard Henderson tcg_target_long imm) 11806a6d772eSRichard Henderson{ 11816a6d772eSRichard Henderson /* This function is only used for passing structs by reference. */ 11826a6d772eSRichard Henderson g_assert_not_reached(); 11836a6d772eSRichard Henderson} 11846a6d772eSRichard Henderson 1185139c1837SPaolo Bonzini/* Define something more legible for general use. */ 1186139c1837SPaolo Bonzini#define tcg_out_ldst_r tcg_out_insn_3310 1187139c1837SPaolo Bonzini 1188139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, AArch64Insn insn, TCGReg rd, 1189139c1837SPaolo Bonzini TCGReg rn, intptr_t offset, int lgsize) 1190139c1837SPaolo Bonzini{ 1191139c1837SPaolo Bonzini /* If the offset is naturally aligned and in range, then we can 1192139c1837SPaolo Bonzini use the scaled uimm12 encoding */ 1193139c1837SPaolo Bonzini if (offset >= 0 && !(offset & ((1 << lgsize) - 1))) { 1194139c1837SPaolo Bonzini uintptr_t scaled_uimm = offset >> lgsize; 1195139c1837SPaolo Bonzini if (scaled_uimm <= 0xfff) { 1196139c1837SPaolo Bonzini tcg_out_insn_3313(s, insn, rd, rn, scaled_uimm); 1197139c1837SPaolo Bonzini return; 1198139c1837SPaolo Bonzini } 1199139c1837SPaolo Bonzini } 1200139c1837SPaolo Bonzini 1201139c1837SPaolo Bonzini /* Small signed offsets can use the unscaled encoding. */ 1202139c1837SPaolo Bonzini if (offset >= -256 && offset < 256) { 1203139c1837SPaolo Bonzini tcg_out_insn_3312(s, insn, rd, rn, offset); 1204139c1837SPaolo Bonzini return; 1205139c1837SPaolo Bonzini } 1206139c1837SPaolo Bonzini 1207139c1837SPaolo Bonzini /* Worst-case scenario, move offset to temp register, use reg offset. */ 1208d67bcbddSRichard Henderson tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, offset); 1209d67bcbddSRichard Henderson tcg_out_ldst_r(s, insn, rd, rn, TCG_TYPE_I64, TCG_REG_TMP0); 1210139c1837SPaolo Bonzini} 1211139c1837SPaolo Bonzini 1212139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 1213139c1837SPaolo Bonzini{ 1214139c1837SPaolo Bonzini if (ret == arg) { 1215139c1837SPaolo Bonzini return true; 1216139c1837SPaolo Bonzini } 1217139c1837SPaolo Bonzini switch (type) { 1218139c1837SPaolo Bonzini case TCG_TYPE_I32: 1219139c1837SPaolo Bonzini case TCG_TYPE_I64: 1220139c1837SPaolo Bonzini if (ret < 32 && arg < 32) { 1221139c1837SPaolo Bonzini tcg_out_movr(s, type, ret, arg); 1222139c1837SPaolo Bonzini break; 1223139c1837SPaolo Bonzini } else if (ret < 32) { 1224139c1837SPaolo Bonzini tcg_out_insn(s, 3605, UMOV, type, ret, arg, 0, 0); 1225139c1837SPaolo Bonzini break; 1226139c1837SPaolo Bonzini } else if (arg < 32) { 1227139c1837SPaolo Bonzini tcg_out_insn(s, 3605, INS, 0, ret, arg, 4 << type, 0); 1228139c1837SPaolo Bonzini break; 1229139c1837SPaolo Bonzini } 1230139c1837SPaolo Bonzini /* FALLTHRU */ 1231139c1837SPaolo Bonzini 1232139c1837SPaolo Bonzini case TCG_TYPE_V64: 1233139c1837SPaolo Bonzini tcg_debug_assert(ret >= 32 && arg >= 32); 1234139c1837SPaolo Bonzini tcg_out_insn(s, 3616, ORR, 0, 0, ret, arg, arg); 1235139c1837SPaolo Bonzini break; 1236139c1837SPaolo Bonzini case TCG_TYPE_V128: 1237139c1837SPaolo Bonzini tcg_debug_assert(ret >= 32 && arg >= 32); 1238139c1837SPaolo Bonzini tcg_out_insn(s, 3616, ORR, 1, 0, ret, arg, arg); 1239139c1837SPaolo Bonzini break; 1240139c1837SPaolo Bonzini 1241139c1837SPaolo Bonzini default: 1242139c1837SPaolo Bonzini g_assert_not_reached(); 1243139c1837SPaolo Bonzini } 1244139c1837SPaolo Bonzini return true; 1245139c1837SPaolo Bonzini} 1246139c1837SPaolo Bonzini 1247139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, 1248139c1837SPaolo Bonzini TCGReg base, intptr_t ofs) 1249139c1837SPaolo Bonzini{ 1250139c1837SPaolo Bonzini AArch64Insn insn; 1251139c1837SPaolo Bonzini int lgsz; 1252139c1837SPaolo Bonzini 1253139c1837SPaolo Bonzini switch (type) { 1254139c1837SPaolo Bonzini case TCG_TYPE_I32: 1255139c1837SPaolo Bonzini insn = (ret < 32 ? I3312_LDRW : I3312_LDRVS); 1256139c1837SPaolo Bonzini lgsz = 2; 1257139c1837SPaolo Bonzini break; 1258139c1837SPaolo Bonzini case TCG_TYPE_I64: 1259139c1837SPaolo Bonzini insn = (ret < 32 ? I3312_LDRX : I3312_LDRVD); 1260139c1837SPaolo Bonzini lgsz = 3; 1261139c1837SPaolo Bonzini break; 1262139c1837SPaolo Bonzini case TCG_TYPE_V64: 1263139c1837SPaolo Bonzini insn = I3312_LDRVD; 1264139c1837SPaolo Bonzini lgsz = 3; 1265139c1837SPaolo Bonzini break; 1266139c1837SPaolo Bonzini case TCG_TYPE_V128: 1267139c1837SPaolo Bonzini insn = I3312_LDRVQ; 1268139c1837SPaolo Bonzini lgsz = 4; 1269139c1837SPaolo Bonzini break; 1270139c1837SPaolo Bonzini default: 1271139c1837SPaolo Bonzini g_assert_not_reached(); 1272139c1837SPaolo Bonzini } 1273139c1837SPaolo Bonzini tcg_out_ldst(s, insn, ret, base, ofs, lgsz); 1274139c1837SPaolo Bonzini} 1275139c1837SPaolo Bonzini 1276139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg src, 1277139c1837SPaolo Bonzini TCGReg base, intptr_t ofs) 1278139c1837SPaolo Bonzini{ 1279139c1837SPaolo Bonzini AArch64Insn insn; 1280139c1837SPaolo Bonzini int lgsz; 1281139c1837SPaolo Bonzini 1282139c1837SPaolo Bonzini switch (type) { 1283139c1837SPaolo Bonzini case TCG_TYPE_I32: 1284139c1837SPaolo Bonzini insn = (src < 32 ? I3312_STRW : I3312_STRVS); 1285139c1837SPaolo Bonzini lgsz = 2; 1286139c1837SPaolo Bonzini break; 1287139c1837SPaolo Bonzini case TCG_TYPE_I64: 1288139c1837SPaolo Bonzini insn = (src < 32 ? I3312_STRX : I3312_STRVD); 1289139c1837SPaolo Bonzini lgsz = 3; 1290139c1837SPaolo Bonzini break; 1291139c1837SPaolo Bonzini case TCG_TYPE_V64: 1292139c1837SPaolo Bonzini insn = I3312_STRVD; 1293139c1837SPaolo Bonzini lgsz = 3; 1294139c1837SPaolo Bonzini break; 1295139c1837SPaolo Bonzini case TCG_TYPE_V128: 1296139c1837SPaolo Bonzini insn = I3312_STRVQ; 1297139c1837SPaolo Bonzini lgsz = 4; 1298139c1837SPaolo Bonzini break; 1299139c1837SPaolo Bonzini default: 1300139c1837SPaolo Bonzini g_assert_not_reached(); 1301139c1837SPaolo Bonzini } 1302139c1837SPaolo Bonzini tcg_out_ldst(s, insn, src, base, ofs, lgsz); 1303139c1837SPaolo Bonzini} 1304139c1837SPaolo Bonzini 1305139c1837SPaolo Bonzinistatic inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, 1306139c1837SPaolo Bonzini TCGReg base, intptr_t ofs) 1307139c1837SPaolo Bonzini{ 1308139c1837SPaolo Bonzini if (type <= TCG_TYPE_I64 && val == 0) { 1309139c1837SPaolo Bonzini tcg_out_st(s, type, TCG_REG_XZR, base, ofs); 1310139c1837SPaolo Bonzini return true; 1311139c1837SPaolo Bonzini } 1312139c1837SPaolo Bonzini return false; 1313139c1837SPaolo Bonzini} 1314139c1837SPaolo Bonzini 1315139c1837SPaolo Bonzinistatic inline void tcg_out_bfm(TCGContext *s, TCGType ext, TCGReg rd, 1316139c1837SPaolo Bonzini TCGReg rn, unsigned int a, unsigned int b) 1317139c1837SPaolo Bonzini{ 1318139c1837SPaolo Bonzini tcg_out_insn(s, 3402, BFM, ext, rd, rn, ext, a, b); 1319139c1837SPaolo Bonzini} 1320139c1837SPaolo Bonzini 1321139c1837SPaolo Bonzinistatic inline void tcg_out_ubfm(TCGContext *s, TCGType ext, TCGReg rd, 1322139c1837SPaolo Bonzini TCGReg rn, unsigned int a, unsigned int b) 1323139c1837SPaolo Bonzini{ 1324139c1837SPaolo Bonzini tcg_out_insn(s, 3402, UBFM, ext, rd, rn, ext, a, b); 1325139c1837SPaolo Bonzini} 1326139c1837SPaolo Bonzini 1327139c1837SPaolo Bonzinistatic inline void tcg_out_sbfm(TCGContext *s, TCGType ext, TCGReg rd, 1328139c1837SPaolo Bonzini TCGReg rn, unsigned int a, unsigned int b) 1329139c1837SPaolo Bonzini{ 1330139c1837SPaolo Bonzini tcg_out_insn(s, 3402, SBFM, ext, rd, rn, ext, a, b); 1331139c1837SPaolo Bonzini} 1332139c1837SPaolo Bonzini 1333139c1837SPaolo Bonzinistatic inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd, 1334139c1837SPaolo Bonzini TCGReg rn, TCGReg rm, unsigned int a) 1335139c1837SPaolo Bonzini{ 1336139c1837SPaolo Bonzini tcg_out_insn(s, 3403, EXTR, ext, rd, rn, rm, a); 1337139c1837SPaolo Bonzini} 1338139c1837SPaolo Bonzini 1339139c1837SPaolo Bonzinistatic inline void tcg_out_shl(TCGContext *s, TCGType ext, 1340139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, unsigned int m) 1341139c1837SPaolo Bonzini{ 1342139c1837SPaolo Bonzini int bits = ext ? 64 : 32; 1343139c1837SPaolo Bonzini int max = bits - 1; 134494bcc91bSRichard Henderson tcg_out_ubfm(s, ext, rd, rn, (bits - m) & max, (max - m) & max); 1345139c1837SPaolo Bonzini} 1346139c1837SPaolo Bonzini 1347139c1837SPaolo Bonzinistatic inline void tcg_out_shr(TCGContext *s, TCGType ext, 1348139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, unsigned int m) 1349139c1837SPaolo Bonzini{ 1350139c1837SPaolo Bonzini int max = ext ? 63 : 31; 1351139c1837SPaolo Bonzini tcg_out_ubfm(s, ext, rd, rn, m & max, max); 1352139c1837SPaolo Bonzini} 1353139c1837SPaolo Bonzini 1354139c1837SPaolo Bonzinistatic inline void tcg_out_sar(TCGContext *s, TCGType ext, 1355139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, unsigned int m) 1356139c1837SPaolo Bonzini{ 1357139c1837SPaolo Bonzini int max = ext ? 63 : 31; 1358139c1837SPaolo Bonzini tcg_out_sbfm(s, ext, rd, rn, m & max, max); 1359139c1837SPaolo Bonzini} 1360139c1837SPaolo Bonzini 1361139c1837SPaolo Bonzinistatic inline void tcg_out_rotr(TCGContext *s, TCGType ext, 1362139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, unsigned int m) 1363139c1837SPaolo Bonzini{ 1364139c1837SPaolo Bonzini int max = ext ? 63 : 31; 1365139c1837SPaolo Bonzini tcg_out_extr(s, ext, rd, rn, rn, m & max); 1366139c1837SPaolo Bonzini} 1367139c1837SPaolo Bonzini 1368139c1837SPaolo Bonzinistatic inline void tcg_out_rotl(TCGContext *s, TCGType ext, 1369139c1837SPaolo Bonzini TCGReg rd, TCGReg rn, unsigned int m) 1370139c1837SPaolo Bonzini{ 137126b1248fSYasuo Kuwahara int max = ext ? 63 : 31; 137226b1248fSYasuo Kuwahara tcg_out_extr(s, ext, rd, rn, rn, -m & max); 1373139c1837SPaolo Bonzini} 1374139c1837SPaolo Bonzini 1375139c1837SPaolo Bonzinistatic inline void tcg_out_dep(TCGContext *s, TCGType ext, TCGReg rd, 1376139c1837SPaolo Bonzini TCGReg rn, unsigned lsb, unsigned width) 1377139c1837SPaolo Bonzini{ 1378139c1837SPaolo Bonzini unsigned size = ext ? 64 : 32; 1379139c1837SPaolo Bonzini unsigned a = (size - lsb) & (size - 1); 1380139c1837SPaolo Bonzini unsigned b = width - 1; 1381139c1837SPaolo Bonzini tcg_out_bfm(s, ext, rd, rn, a, b); 1382139c1837SPaolo Bonzini} 1383139c1837SPaolo Bonzini 1384339adf2fSRichard Hendersonstatic void tcg_out_cmp(TCGContext *s, TCGType ext, TCGCond cond, TCGReg a, 1385139c1837SPaolo Bonzini tcg_target_long b, bool const_b) 1386139c1837SPaolo Bonzini{ 1387339adf2fSRichard Henderson if (is_tst_cond(cond)) { 1388339adf2fSRichard Henderson if (!const_b) { 1389339adf2fSRichard Henderson tcg_out_insn(s, 3510, ANDS, ext, TCG_REG_XZR, a, b); 1390139c1837SPaolo Bonzini } else { 13911d24c36bSRichard Henderson tcg_out_logicali(s, I3404_ANDSI, ext, TCG_REG_XZR, a, b); 1392139c1837SPaolo Bonzini } 1393139c1837SPaolo Bonzini } else { 1394339adf2fSRichard Henderson if (!const_b) { 1395139c1837SPaolo Bonzini tcg_out_insn(s, 3502, SUBS, ext, TCG_REG_XZR, a, b); 1396339adf2fSRichard Henderson } else if (b >= 0) { 1397339adf2fSRichard Henderson tcg_debug_assert(is_aimm(b)); 1398339adf2fSRichard Henderson tcg_out_insn(s, 3401, SUBSI, ext, TCG_REG_XZR, a, b); 1399339adf2fSRichard Henderson } else { 1400339adf2fSRichard Henderson tcg_debug_assert(is_aimm(-b)); 1401339adf2fSRichard Henderson tcg_out_insn(s, 3401, ADDSI, ext, TCG_REG_XZR, a, -b); 1402339adf2fSRichard Henderson } 1403139c1837SPaolo Bonzini } 1404139c1837SPaolo Bonzini} 1405139c1837SPaolo Bonzini 1406ffd0e507SRichard Hendersonstatic void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target) 1407139c1837SPaolo Bonzini{ 1408ffba3eb3SRichard Henderson ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2; 1409139c1837SPaolo Bonzini tcg_debug_assert(offset == sextract64(offset, 0, 26)); 1410139c1837SPaolo Bonzini tcg_out_insn(s, 3206, B, offset); 1411139c1837SPaolo Bonzini} 1412139c1837SPaolo Bonzini 1413cee44b03SRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *target) 1414139c1837SPaolo Bonzini{ 1415ffba3eb3SRichard Henderson ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2; 1416139c1837SPaolo Bonzini if (offset == sextract64(offset, 0, 26)) { 1417139c1837SPaolo Bonzini tcg_out_insn(s, 3206, BL, offset); 1418139c1837SPaolo Bonzini } else { 1419d67bcbddSRichard Henderson tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, (intptr_t)target); 1420d67bcbddSRichard Henderson tcg_out_insn(s, 3207, BLR, TCG_REG_TMP0); 1421139c1837SPaolo Bonzini } 1422139c1837SPaolo Bonzini} 1423139c1837SPaolo Bonzini 1424cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *target, 1425cee44b03SRichard Henderson const TCGHelperInfo *info) 1426cee44b03SRichard Henderson{ 1427cee44b03SRichard Henderson tcg_out_call_int(s, target); 1428cee44b03SRichard Henderson} 1429cee44b03SRichard Henderson 1430139c1837SPaolo Bonzinistatic inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l) 1431139c1837SPaolo Bonzini{ 1432139c1837SPaolo Bonzini if (!l->has_value) { 1433139c1837SPaolo Bonzini tcg_out_reloc(s, s->code_ptr, R_AARCH64_JUMP26, l, 0); 1434139c1837SPaolo Bonzini tcg_out_insn(s, 3206, B, 0); 1435139c1837SPaolo Bonzini } else { 1436139c1837SPaolo Bonzini tcg_out_goto(s, l->u.value_ptr); 1437139c1837SPaolo Bonzini } 1438139c1837SPaolo Bonzini} 1439139c1837SPaolo Bonzini 1440139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGType ext, TCGCond c, TCGArg a, 1441139c1837SPaolo Bonzini TCGArg b, bool b_const, TCGLabel *l) 1442139c1837SPaolo Bonzini{ 144392a11b93SRichard Henderson int tbit = -1; 1444a0f5b3fcSPhilippe Mathieu-Daudé bool need_cmp = true; 1445139c1837SPaolo Bonzini 1446a0f5b3fcSPhilippe Mathieu-Daudé switch (c) { 1447a0f5b3fcSPhilippe Mathieu-Daudé case TCG_COND_EQ: 1448a0f5b3fcSPhilippe Mathieu-Daudé case TCG_COND_NE: 144992a11b93SRichard Henderson /* cmp xN,0; b.ne L -> cbnz xN,L */ 1450a0f5b3fcSPhilippe Mathieu-Daudé if (b_const && b == 0) { 1451139c1837SPaolo Bonzini need_cmp = false; 1452a0f5b3fcSPhilippe Mathieu-Daudé } 1453a0f5b3fcSPhilippe Mathieu-Daudé break; 145492a11b93SRichard Henderson case TCG_COND_LT: 145592a11b93SRichard Henderson case TCG_COND_GE: 145692a11b93SRichard Henderson /* cmp xN,0; b.mi L -> tbnz xN,63,L */ 145792a11b93SRichard Henderson if (b_const && b == 0) { 145892a11b93SRichard Henderson c = (c == TCG_COND_LT ? TCG_COND_TSTNE : TCG_COND_TSTEQ); 145992a11b93SRichard Henderson tbit = ext ? 63 : 31; 146092a11b93SRichard Henderson need_cmp = false; 146192a11b93SRichard Henderson } 146292a11b93SRichard Henderson break; 146392a11b93SRichard Henderson case TCG_COND_TSTEQ: 146492a11b93SRichard Henderson case TCG_COND_TSTNE: 146534aff3c2SRichard Henderson /* tst xN,0xffffffff; b.ne L -> cbnz wN,L */ 146634aff3c2SRichard Henderson if (b_const && b == UINT32_MAX) { 14674fe19bbbSRichard Henderson c = tcg_tst_eqne_cond(c); 146834aff3c2SRichard Henderson ext = TCG_TYPE_I32; 146934aff3c2SRichard Henderson need_cmp = false; 147034aff3c2SRichard Henderson break; 147134aff3c2SRichard Henderson } 147292a11b93SRichard Henderson /* tst xN,1<<B; b.ne L -> tbnz xN,B,L */ 147392a11b93SRichard Henderson if (b_const && is_power_of_2(b)) { 147492a11b93SRichard Henderson tbit = ctz64(b); 147592a11b93SRichard Henderson need_cmp = false; 147692a11b93SRichard Henderson } 147792a11b93SRichard Henderson break; 1478a0f5b3fcSPhilippe Mathieu-Daudé default: 1479a0f5b3fcSPhilippe Mathieu-Daudé break; 1480a0f5b3fcSPhilippe Mathieu-Daudé } 1481a0f5b3fcSPhilippe Mathieu-Daudé 1482a0f5b3fcSPhilippe Mathieu-Daudé if (need_cmp) { 1483339adf2fSRichard Henderson tcg_out_cmp(s, ext, c, a, b, b_const); 1484139c1837SPaolo Bonzini tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, l, 0); 148592a11b93SRichard Henderson tcg_out_insn(s, 3202, B_C, c, 0); 148692a11b93SRichard Henderson return; 1487139c1837SPaolo Bonzini } 1488139c1837SPaolo Bonzini 148992a11b93SRichard Henderson if (tbit >= 0) { 149092a11b93SRichard Henderson tcg_out_reloc(s, s->code_ptr, R_AARCH64_TSTBR14, l, 0); 149192a11b93SRichard Henderson switch (c) { 149292a11b93SRichard Henderson case TCG_COND_TSTEQ: 149392a11b93SRichard Henderson tcg_out_insn(s, 3205, TBZ, a, tbit, 0); 149492a11b93SRichard Henderson break; 149592a11b93SRichard Henderson case TCG_COND_TSTNE: 149692a11b93SRichard Henderson tcg_out_insn(s, 3205, TBNZ, a, tbit, 0); 149792a11b93SRichard Henderson break; 149892a11b93SRichard Henderson default: 149992a11b93SRichard Henderson g_assert_not_reached(); 150092a11b93SRichard Henderson } 1501139c1837SPaolo Bonzini } else { 150292a11b93SRichard Henderson tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, l, 0); 1503a0f5b3fcSPhilippe Mathieu-Daudé switch (c) { 1504a0f5b3fcSPhilippe Mathieu-Daudé case TCG_COND_EQ: 150592a11b93SRichard Henderson tcg_out_insn(s, 3201, CBZ, ext, a, 0); 1506a0f5b3fcSPhilippe Mathieu-Daudé break; 1507a0f5b3fcSPhilippe Mathieu-Daudé case TCG_COND_NE: 150892a11b93SRichard Henderson tcg_out_insn(s, 3201, CBNZ, ext, a, 0); 1509a0f5b3fcSPhilippe Mathieu-Daudé break; 1510a0f5b3fcSPhilippe Mathieu-Daudé default: 1511a0f5b3fcSPhilippe Mathieu-Daudé g_assert_not_reached(); 1512a0f5b3fcSPhilippe Mathieu-Daudé } 1513139c1837SPaolo Bonzini } 1514139c1837SPaolo Bonzini} 1515139c1837SPaolo Bonzini 1516dfa24dfaSRichard Hendersonstatic inline void tcg_out_rev(TCGContext *s, int ext, MemOp s_bits, 1517dfa24dfaSRichard Henderson TCGReg rd, TCGReg rn) 1518139c1837SPaolo Bonzini{ 1519dfa24dfaSRichard Henderson /* REV, REV16, REV32 */ 1520dfa24dfaSRichard Henderson tcg_out_insn_3507(s, I3507_REV | (s_bits << 10), ext, rd, rn); 1521139c1837SPaolo Bonzini} 1522139c1837SPaolo Bonzini 1523139c1837SPaolo Bonzinistatic inline void tcg_out_sxt(TCGContext *s, TCGType ext, MemOp s_bits, 1524139c1837SPaolo Bonzini TCGReg rd, TCGReg rn) 1525139c1837SPaolo Bonzini{ 1526139c1837SPaolo Bonzini /* Using ALIASes SXTB, SXTH, SXTW, of SBFM Xd, Xn, #0, #7|15|31 */ 1527139c1837SPaolo Bonzini int bits = (8 << s_bits) - 1; 1528139c1837SPaolo Bonzini tcg_out_sbfm(s, ext, rd, rn, 0, bits); 1529139c1837SPaolo Bonzini} 1530139c1837SPaolo Bonzini 1531678155b2SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn) 1532678155b2SRichard Henderson{ 1533678155b2SRichard Henderson tcg_out_sxt(s, type, MO_8, rd, rn); 1534678155b2SRichard Henderson} 1535678155b2SRichard Henderson 1536753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn) 1537753e42eaSRichard Henderson{ 1538753e42eaSRichard Henderson tcg_out_sxt(s, type, MO_16, rd, rn); 1539753e42eaSRichard Henderson} 1540753e42eaSRichard Henderson 154152bf3398SRichard Hendersonstatic void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rn) 154252bf3398SRichard Henderson{ 154352bf3398SRichard Henderson tcg_out_sxt(s, TCG_TYPE_I64, MO_32, rd, rn); 154452bf3398SRichard Henderson} 154552bf3398SRichard Henderson 15469c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rn) 15479c6aa274SRichard Henderson{ 15489c6aa274SRichard Henderson tcg_out_ext32s(s, rd, rn); 15499c6aa274SRichard Henderson} 15509c6aa274SRichard Henderson 1551139c1837SPaolo Bonzinistatic inline void tcg_out_uxt(TCGContext *s, MemOp s_bits, 1552139c1837SPaolo Bonzini TCGReg rd, TCGReg rn) 1553139c1837SPaolo Bonzini{ 1554139c1837SPaolo Bonzini /* Using ALIASes UXTB, UXTH of UBFM Wd, Wn, #0, #7|15 */ 1555139c1837SPaolo Bonzini int bits = (8 << s_bits) - 1; 1556139c1837SPaolo Bonzini tcg_out_ubfm(s, 0, rd, rn, 0, bits); 1557139c1837SPaolo Bonzini} 1558139c1837SPaolo Bonzini 1559d0e66c89SRichard Hendersonstatic void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rn) 1560d0e66c89SRichard Henderson{ 1561d0e66c89SRichard Henderson tcg_out_uxt(s, MO_8, rd, rn); 1562d0e66c89SRichard Henderson} 1563d0e66c89SRichard Henderson 1564379afdffSRichard Hendersonstatic void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rn) 1565379afdffSRichard Henderson{ 1566379afdffSRichard Henderson tcg_out_uxt(s, MO_16, rd, rn); 1567379afdffSRichard Henderson} 1568379afdffSRichard Henderson 15699ecf5f61SRichard Hendersonstatic void tcg_out_ext32u(TCGContext *s, TCGReg rd, TCGReg rn) 15709ecf5f61SRichard Henderson{ 15719ecf5f61SRichard Henderson tcg_out_movr(s, TCG_TYPE_I32, rd, rn); 15729ecf5f61SRichard Henderson} 15739ecf5f61SRichard Henderson 1574b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rn) 1575b9bfe000SRichard Henderson{ 1576b9bfe000SRichard Henderson tcg_out_ext32u(s, rd, rn); 1577b9bfe000SRichard Henderson} 1578b9bfe000SRichard Henderson 1579b8b94ac6SRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rn) 1580b8b94ac6SRichard Henderson{ 1581b8b94ac6SRichard Henderson tcg_out_mov(s, TCG_TYPE_I32, rd, rn); 1582b8b94ac6SRichard Henderson} 1583b8b94ac6SRichard Henderson 1584139c1837SPaolo Bonzinistatic void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd, 1585139c1837SPaolo Bonzini TCGReg rn, int64_t aimm) 1586139c1837SPaolo Bonzini{ 1587139c1837SPaolo Bonzini if (aimm >= 0) { 1588139c1837SPaolo Bonzini tcg_out_insn(s, 3401, ADDI, ext, rd, rn, aimm); 1589139c1837SPaolo Bonzini } else { 1590139c1837SPaolo Bonzini tcg_out_insn(s, 3401, SUBI, ext, rd, rn, -aimm); 1591139c1837SPaolo Bonzini } 1592139c1837SPaolo Bonzini} 1593139c1837SPaolo Bonzini 1594707b45a2SRichard Hendersonstatic void tcg_out_addsub2(TCGContext *s, TCGType ext, TCGReg rl, 1595139c1837SPaolo Bonzini TCGReg rh, TCGReg al, TCGReg ah, 1596139c1837SPaolo Bonzini tcg_target_long bl, tcg_target_long bh, 1597139c1837SPaolo Bonzini bool const_bl, bool const_bh, bool sub) 1598139c1837SPaolo Bonzini{ 1599139c1837SPaolo Bonzini TCGReg orig_rl = rl; 1600139c1837SPaolo Bonzini AArch64Insn insn; 1601139c1837SPaolo Bonzini 1602139c1837SPaolo Bonzini if (rl == ah || (!const_bh && rl == bh)) { 1603d67bcbddSRichard Henderson rl = TCG_REG_TMP0; 1604139c1837SPaolo Bonzini } 1605139c1837SPaolo Bonzini 1606139c1837SPaolo Bonzini if (const_bl) { 1607707b45a2SRichard Henderson if (bl < 0) { 1608139c1837SPaolo Bonzini bl = -bl; 1609707b45a2SRichard Henderson insn = sub ? I3401_ADDSI : I3401_SUBSI; 1610707b45a2SRichard Henderson } else { 1611707b45a2SRichard Henderson insn = sub ? I3401_SUBSI : I3401_ADDSI; 1612139c1837SPaolo Bonzini } 1613707b45a2SRichard Henderson 1614139c1837SPaolo Bonzini if (unlikely(al == TCG_REG_XZR)) { 1615139c1837SPaolo Bonzini /* ??? We want to allow al to be zero for the benefit of 1616139c1837SPaolo Bonzini negation via subtraction. However, that leaves open the 1617139c1837SPaolo Bonzini possibility of adding 0+const in the low part, and the 1618139c1837SPaolo Bonzini immediate add instructions encode XSP not XZR. Don't try 1619139c1837SPaolo Bonzini anything more elaborate here than loading another zero. */ 1620d67bcbddSRichard Henderson al = TCG_REG_TMP0; 1621139c1837SPaolo Bonzini tcg_out_movi(s, ext, al, 0); 1622139c1837SPaolo Bonzini } 1623139c1837SPaolo Bonzini tcg_out_insn_3401(s, insn, ext, rl, al, bl); 1624139c1837SPaolo Bonzini } else { 1625139c1837SPaolo Bonzini tcg_out_insn_3502(s, sub ? I3502_SUBS : I3502_ADDS, ext, rl, al, bl); 1626139c1837SPaolo Bonzini } 1627139c1837SPaolo Bonzini 1628139c1837SPaolo Bonzini insn = I3503_ADC; 1629139c1837SPaolo Bonzini if (const_bh) { 1630139c1837SPaolo Bonzini /* Note that the only two constants we support are 0 and -1, and 1631139c1837SPaolo Bonzini that SBC = rn + ~rm + c, so adc -1 is sbc 0, and vice-versa. */ 1632139c1837SPaolo Bonzini if ((bh != 0) ^ sub) { 1633139c1837SPaolo Bonzini insn = I3503_SBC; 1634139c1837SPaolo Bonzini } 1635139c1837SPaolo Bonzini bh = TCG_REG_XZR; 1636139c1837SPaolo Bonzini } else if (sub) { 1637139c1837SPaolo Bonzini insn = I3503_SBC; 1638139c1837SPaolo Bonzini } 1639139c1837SPaolo Bonzini tcg_out_insn_3503(s, insn, ext, rh, ah, bh); 1640139c1837SPaolo Bonzini 1641139c1837SPaolo Bonzini tcg_out_mov(s, ext, orig_rl, rl); 1642139c1837SPaolo Bonzini} 1643139c1837SPaolo Bonzini 1644139c1837SPaolo Bonzinistatic inline void tcg_out_mb(TCGContext *s, TCGArg a0) 1645139c1837SPaolo Bonzini{ 1646139c1837SPaolo Bonzini static const uint32_t sync[] = { 1647139c1837SPaolo Bonzini [0 ... TCG_MO_ALL] = DMB_ISH | DMB_LD | DMB_ST, 1648139c1837SPaolo Bonzini [TCG_MO_ST_ST] = DMB_ISH | DMB_ST, 1649139c1837SPaolo Bonzini [TCG_MO_LD_LD] = DMB_ISH | DMB_LD, 1650139c1837SPaolo Bonzini [TCG_MO_LD_ST] = DMB_ISH | DMB_LD, 1651139c1837SPaolo Bonzini [TCG_MO_LD_ST | TCG_MO_LD_LD] = DMB_ISH | DMB_LD, 1652139c1837SPaolo Bonzini }; 1653139c1837SPaolo Bonzini tcg_out32(s, sync[a0 & TCG_MO_ALL]); 1654139c1837SPaolo Bonzini} 1655139c1837SPaolo Bonzini 1656139c1837SPaolo Bonzinistatic void tcg_out_cltz(TCGContext *s, TCGType ext, TCGReg d, 1657139c1837SPaolo Bonzini TCGReg a0, TCGArg b, bool const_b, bool is_ctz) 1658139c1837SPaolo Bonzini{ 1659139c1837SPaolo Bonzini TCGReg a1 = a0; 1660139c1837SPaolo Bonzini if (is_ctz) { 1661d67bcbddSRichard Henderson a1 = TCG_REG_TMP0; 1662139c1837SPaolo Bonzini tcg_out_insn(s, 3507, RBIT, ext, a1, a0); 1663139c1837SPaolo Bonzini } 1664139c1837SPaolo Bonzini if (const_b && b == (ext ? 64 : 32)) { 1665139c1837SPaolo Bonzini tcg_out_insn(s, 3507, CLZ, ext, d, a1); 1666139c1837SPaolo Bonzini } else { 1667139c1837SPaolo Bonzini AArch64Insn sel = I3506_CSEL; 1668139c1837SPaolo Bonzini 1669339adf2fSRichard Henderson tcg_out_cmp(s, ext, TCG_COND_NE, a0, 0, 1); 1670d67bcbddSRichard Henderson tcg_out_insn(s, 3507, CLZ, ext, TCG_REG_TMP0, a1); 1671139c1837SPaolo Bonzini 1672139c1837SPaolo Bonzini if (const_b) { 1673139c1837SPaolo Bonzini if (b == -1) { 1674139c1837SPaolo Bonzini b = TCG_REG_XZR; 1675139c1837SPaolo Bonzini sel = I3506_CSINV; 1676139c1837SPaolo Bonzini } else if (b == 0) { 1677139c1837SPaolo Bonzini b = TCG_REG_XZR; 1678139c1837SPaolo Bonzini } else { 1679139c1837SPaolo Bonzini tcg_out_movi(s, ext, d, b); 1680139c1837SPaolo Bonzini b = d; 1681139c1837SPaolo Bonzini } 1682139c1837SPaolo Bonzini } 1683d67bcbddSRichard Henderson tcg_out_insn_3506(s, sel, ext, d, TCG_REG_TMP0, b, TCG_COND_NE); 1684139c1837SPaolo Bonzini } 1685139c1837SPaolo Bonzini} 1686139c1837SPaolo Bonzini 16877f65be51SRichard Hendersontypedef struct { 16887f65be51SRichard Henderson TCGReg base; 16897f65be51SRichard Henderson TCGReg index; 16907f65be51SRichard Henderson TCGType index_ext; 169164741d99SRichard Henderson TCGAtomAlign aa; 16927f65be51SRichard Henderson} HostAddress; 16937f65be51SRichard Henderson 16947b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop) 16957b880107SRichard Henderson{ 16967b880107SRichard Henderson return false; 16977b880107SRichard Henderson} 16987b880107SRichard Henderson 16996e96422bSRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = { 1700d67bcbddSRichard Henderson .ntmp = 1, .tmp = { TCG_REG_TMP0 } 17016e96422bSRichard Henderson}; 17026e96422bSRichard Henderson 1703139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1704139c1837SPaolo Bonzini{ 17056e96422bSRichard Henderson MemOp opc = get_memop(lb->oi); 1706139c1837SPaolo Bonzini 1707ffba3eb3SRichard Henderson if (!reloc_pc19(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { 1708139c1837SPaolo Bonzini return false; 1709139c1837SPaolo Bonzini } 1710139c1837SPaolo Bonzini 17116e96422bSRichard Henderson tcg_out_ld_helper_args(s, lb, &ldst_helper_param); 1712cee44b03SRichard Henderson tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SIZE]); 17136e96422bSRichard Henderson tcg_out_ld_helper_ret(s, lb, false, &ldst_helper_param); 1714139c1837SPaolo Bonzini tcg_out_goto(s, lb->raddr); 1715139c1837SPaolo Bonzini return true; 1716139c1837SPaolo Bonzini} 1717139c1837SPaolo Bonzini 1718139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 1719139c1837SPaolo Bonzini{ 17206e96422bSRichard Henderson MemOp opc = get_memop(lb->oi); 1721139c1837SPaolo Bonzini 1722ffba3eb3SRichard Henderson if (!reloc_pc19(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { 1723139c1837SPaolo Bonzini return false; 1724139c1837SPaolo Bonzini } 1725139c1837SPaolo Bonzini 17266e96422bSRichard Henderson tcg_out_st_helper_args(s, lb, &ldst_helper_param); 1727cee44b03SRichard Henderson tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE]); 1728139c1837SPaolo Bonzini tcg_out_goto(s, lb->raddr); 1729139c1837SPaolo Bonzini return true; 1730139c1837SPaolo Bonzini} 1731139c1837SPaolo Bonzini 1732d0a9bb5eSRichard Henderson/* We expect to use a 7-bit scaled negative offset from ENV. */ 1733d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS -512 1734d0a9bb5eSRichard Henderson 17351e612dd6SRichard Henderson/* 17367893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare. 17377893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests. 17381e612dd6SRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path 17391e612dd6SRichard Henderson * is required and fill in @h with the host address for the fast path. 17401e612dd6SRichard Henderson */ 17411e612dd6SRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h, 17421e612dd6SRichard Henderson TCGReg addr_reg, MemOpIdx oi, 17431e612dd6SRichard Henderson bool is_ld) 17441e612dd6SRichard Henderson{ 174560c452a1SRichard Henderson TCGType addr_type = s->addr_type; 17461e612dd6SRichard Henderson TCGLabelQemuLdst *ldst = NULL; 17471e612dd6SRichard Henderson MemOp opc = get_memop(oi); 1748929124ecSRichard Henderson MemOp s_bits = opc & MO_SIZE; 174964741d99SRichard Henderson unsigned a_mask; 175064741d99SRichard Henderson 175164741d99SRichard Henderson h->aa = atom_and_align_for_opc(s, opc, 175264741d99SRichard Henderson have_lse2 ? MO_ATOM_WITHIN16 175364741d99SRichard Henderson : MO_ATOM_IFALIGN, 1754929124ecSRichard Henderson s_bits == MO_128); 175564741d99SRichard Henderson a_mask = (1 << h->aa.align) - 1; 17561e612dd6SRichard Henderson 1757e2b7a40dSRichard Henderson if (tcg_use_softmmu) { 17581e612dd6SRichard Henderson unsigned s_mask = (1u << s_bits) - 1; 17591e612dd6SRichard Henderson unsigned mem_index = get_mmuidx(oi); 1760285a691fSRichard Henderson TCGReg addr_adj; 17611e612dd6SRichard Henderson TCGType mask_type; 17621e612dd6SRichard Henderson uint64_t compare_mask; 17631e612dd6SRichard Henderson 17641e612dd6SRichard Henderson ldst = new_ldst_label(s); 17651e612dd6SRichard Henderson ldst->is_ld = is_ld; 17661e612dd6SRichard Henderson ldst->oi = oi; 17671e612dd6SRichard Henderson ldst->addrlo_reg = addr_reg; 17681e612dd6SRichard Henderson 1769a66efde1SRichard Henderson mask_type = (s->page_bits + s->tlb_dyn_max_bits > 32 17701e612dd6SRichard Henderson ? TCG_TYPE_I64 : TCG_TYPE_I32); 17711e612dd6SRichard Henderson 1772623912ccSAnton Johansson /* Load cpu->neg.tlb.f[mmu_idx].{mask,table} into {tmp0,tmp1}. */ 17731e612dd6SRichard Henderson QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, mask) != 0); 17741e612dd6SRichard Henderson QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, table) != 8); 1775285a691fSRichard Henderson tcg_out_insn(s, 3314, LDP, TCG_REG_TMP0, TCG_REG_TMP1, TCG_AREG0, 1776d0a9bb5eSRichard Henderson tlb_mask_table_ofs(s, mem_index), 1, 0); 17771e612dd6SRichard Henderson 17781e612dd6SRichard Henderson /* Extract the TLB index from the address into X0. */ 17791e612dd6SRichard Henderson tcg_out_insn(s, 3502S, AND_LSR, mask_type == TCG_TYPE_I64, 1780285a691fSRichard Henderson TCG_REG_TMP0, TCG_REG_TMP0, addr_reg, 1781aece72b7SRichard Henderson s->page_bits - CPU_TLB_ENTRY_BITS); 17821e612dd6SRichard Henderson 1783e2b7a40dSRichard Henderson /* Add the tlb_table pointer, forming the CPUTLBEntry address. */ 1784285a691fSRichard Henderson tcg_out_insn(s, 3502, ADD, 1, TCG_REG_TMP1, TCG_REG_TMP1, TCG_REG_TMP0); 17851e612dd6SRichard Henderson 1786e2b7a40dSRichard Henderson /* Load the tlb comparator into TMP0, and the fast path addend. */ 1787238f4380SRichard Henderson QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN); 1788285a691fSRichard Henderson tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP1, 17891e612dd6SRichard Henderson is_ld ? offsetof(CPUTLBEntry, addr_read) 17901e612dd6SRichard Henderson : offsetof(CPUTLBEntry, addr_write)); 1791285a691fSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_REG_TMP1, 17921e612dd6SRichard Henderson offsetof(CPUTLBEntry, addend)); 17931e612dd6SRichard Henderson 17941e612dd6SRichard Henderson /* 1795e2b7a40dSRichard Henderson * For aligned accesses, we check the first byte and include 1796e2b7a40dSRichard Henderson * the alignment bits within the address. For unaligned access, 1797e2b7a40dSRichard Henderson * we check that we don't cross pages using the address of the 1798e2b7a40dSRichard Henderson * last byte of the access. 17991e612dd6SRichard Henderson */ 180064741d99SRichard Henderson if (a_mask >= s_mask) { 1801285a691fSRichard Henderson addr_adj = addr_reg; 18021e612dd6SRichard Henderson } else { 1803285a691fSRichard Henderson addr_adj = TCG_REG_TMP2; 180460c452a1SRichard Henderson tcg_out_insn(s, 3401, ADDI, addr_type, 1805285a691fSRichard Henderson addr_adj, addr_reg, s_mask - a_mask); 18061e612dd6SRichard Henderson } 1807aece72b7SRichard Henderson compare_mask = (uint64_t)s->page_mask | a_mask; 18081e612dd6SRichard Henderson 1809285a691fSRichard Henderson /* Store the page mask part of the address into TMP2. */ 1810285a691fSRichard Henderson tcg_out_logicali(s, I3404_ANDI, addr_type, TCG_REG_TMP2, 1811285a691fSRichard Henderson addr_adj, compare_mask); 18121e612dd6SRichard Henderson 18131e612dd6SRichard Henderson /* Perform the address comparison. */ 1814339adf2fSRichard Henderson tcg_out_cmp(s, addr_type, TCG_COND_NE, TCG_REG_TMP0, TCG_REG_TMP2, 0); 18151e612dd6SRichard Henderson 18161e612dd6SRichard Henderson /* If not equal, we jump to the slow path. */ 18171e612dd6SRichard Henderson ldst->label_ptr[0] = s->code_ptr; 18181e612dd6SRichard Henderson tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0); 18191e612dd6SRichard Henderson 1820285a691fSRichard Henderson h->base = TCG_REG_TMP1; 182164741d99SRichard Henderson h->index = addr_reg; 182264741d99SRichard Henderson h->index_ext = addr_type; 1823e2b7a40dSRichard Henderson } else { 18241e612dd6SRichard Henderson if (a_mask) { 18251e612dd6SRichard Henderson ldst = new_ldst_label(s); 18261e612dd6SRichard Henderson 18271e612dd6SRichard Henderson ldst->is_ld = is_ld; 18281e612dd6SRichard Henderson ldst->oi = oi; 18291e612dd6SRichard Henderson ldst->addrlo_reg = addr_reg; 18301e612dd6SRichard Henderson 18311e612dd6SRichard Henderson /* tst addr, #mask */ 18321e612dd6SRichard Henderson tcg_out_logicali(s, I3404_ANDSI, 0, TCG_REG_XZR, addr_reg, a_mask); 18331e612dd6SRichard Henderson 18341e612dd6SRichard Henderson /* b.ne slow_path */ 18351e612dd6SRichard Henderson ldst->label_ptr[0] = s->code_ptr; 18361e612dd6SRichard Henderson tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0); 18371e612dd6SRichard Henderson } 18381e612dd6SRichard Henderson 183952533157SRichard Henderson if (guest_base || addr_type == TCG_TYPE_I32) { 184064741d99SRichard Henderson h->base = TCG_REG_GUEST_BASE; 184164741d99SRichard Henderson h->index = addr_reg; 184264741d99SRichard Henderson h->index_ext = addr_type; 18431e612dd6SRichard Henderson } else { 184464741d99SRichard Henderson h->base = addr_reg; 184564741d99SRichard Henderson h->index = TCG_REG_XZR; 184664741d99SRichard Henderson h->index_ext = TCG_TYPE_I64; 18471e612dd6SRichard Henderson } 1848e2b7a40dSRichard Henderson } 18491e612dd6SRichard Henderson 18501e612dd6SRichard Henderson return ldst; 18511e612dd6SRichard Henderson} 18521e612dd6SRichard Henderson 1853139c1837SPaolo Bonzinistatic void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext, 18547f65be51SRichard Henderson TCGReg data_r, HostAddress h) 1855139c1837SPaolo Bonzini{ 1856139c1837SPaolo Bonzini switch (memop & MO_SSIZE) { 1857139c1837SPaolo Bonzini case MO_UB: 18587f65be51SRichard Henderson tcg_out_ldst_r(s, I3312_LDRB, data_r, h.base, h.index_ext, h.index); 1859139c1837SPaolo Bonzini break; 1860139c1837SPaolo Bonzini case MO_SB: 1861139c1837SPaolo Bonzini tcg_out_ldst_r(s, ext ? I3312_LDRSBX : I3312_LDRSBW, 18627f65be51SRichard Henderson data_r, h.base, h.index_ext, h.index); 1863139c1837SPaolo Bonzini break; 1864139c1837SPaolo Bonzini case MO_UW: 18657f65be51SRichard Henderson tcg_out_ldst_r(s, I3312_LDRH, data_r, h.base, h.index_ext, h.index); 1866139c1837SPaolo Bonzini break; 1867139c1837SPaolo Bonzini case MO_SW: 1868139c1837SPaolo Bonzini tcg_out_ldst_r(s, (ext ? I3312_LDRSHX : I3312_LDRSHW), 18697f65be51SRichard Henderson data_r, h.base, h.index_ext, h.index); 1870139c1837SPaolo Bonzini break; 1871139c1837SPaolo Bonzini case MO_UL: 18727f65be51SRichard Henderson tcg_out_ldst_r(s, I3312_LDRW, data_r, h.base, h.index_ext, h.index); 1873139c1837SPaolo Bonzini break; 1874139c1837SPaolo Bonzini case MO_SL: 18757f65be51SRichard Henderson tcg_out_ldst_r(s, I3312_LDRSWX, data_r, h.base, h.index_ext, h.index); 1876139c1837SPaolo Bonzini break; 1877fc313c64SFrédéric Pétrot case MO_UQ: 18787f65be51SRichard Henderson tcg_out_ldst_r(s, I3312_LDRX, data_r, h.base, h.index_ext, h.index); 1879139c1837SPaolo Bonzini break; 1880139c1837SPaolo Bonzini default: 1881732e89f4SRichard Henderson g_assert_not_reached(); 1882139c1837SPaolo Bonzini } 1883139c1837SPaolo Bonzini} 1884139c1837SPaolo Bonzini 1885139c1837SPaolo Bonzinistatic void tcg_out_qemu_st_direct(TCGContext *s, MemOp memop, 18867f65be51SRichard Henderson TCGReg data_r, HostAddress h) 1887139c1837SPaolo Bonzini{ 1888139c1837SPaolo Bonzini switch (memop & MO_SIZE) { 1889139c1837SPaolo Bonzini case MO_8: 18907f65be51SRichard Henderson tcg_out_ldst_r(s, I3312_STRB, data_r, h.base, h.index_ext, h.index); 1891139c1837SPaolo Bonzini break; 1892139c1837SPaolo Bonzini case MO_16: 18937f65be51SRichard Henderson tcg_out_ldst_r(s, I3312_STRH, data_r, h.base, h.index_ext, h.index); 1894139c1837SPaolo Bonzini break; 1895139c1837SPaolo Bonzini case MO_32: 18967f65be51SRichard Henderson tcg_out_ldst_r(s, I3312_STRW, data_r, h.base, h.index_ext, h.index); 1897139c1837SPaolo Bonzini break; 1898139c1837SPaolo Bonzini case MO_64: 18997f65be51SRichard Henderson tcg_out_ldst_r(s, I3312_STRX, data_r, h.base, h.index_ext, h.index); 1900139c1837SPaolo Bonzini break; 1901139c1837SPaolo Bonzini default: 1902732e89f4SRichard Henderson g_assert_not_reached(); 1903139c1837SPaolo Bonzini } 1904139c1837SPaolo Bonzini} 1905139c1837SPaolo Bonzini 1906139c1837SPaolo Bonzinistatic void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, 1907ff0cc85eSRichard Henderson MemOpIdx oi, TCGType data_type) 1908139c1837SPaolo Bonzini{ 19091e612dd6SRichard Henderson TCGLabelQemuLdst *ldst; 19107f65be51SRichard Henderson HostAddress h; 1911f85ab3d2SRichard Henderson 19121e612dd6SRichard Henderson ldst = prepare_host_addr(s, &h, addr_reg, oi, true); 19131e612dd6SRichard Henderson tcg_out_qemu_ld_direct(s, get_memop(oi), data_type, data_reg, h); 1914f85ab3d2SRichard Henderson 19151e612dd6SRichard Henderson if (ldst) { 19161e612dd6SRichard Henderson ldst->type = data_type; 19171e612dd6SRichard Henderson ldst->datalo_reg = data_reg; 19181e612dd6SRichard Henderson ldst->raddr = tcg_splitwx_to_rx(s->code_ptr); 1919f85ab3d2SRichard Henderson } 1920139c1837SPaolo Bonzini} 1921139c1837SPaolo Bonzini 1922139c1837SPaolo Bonzinistatic void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, 1923ff0cc85eSRichard Henderson MemOpIdx oi, TCGType data_type) 1924139c1837SPaolo Bonzini{ 19251e612dd6SRichard Henderson TCGLabelQemuLdst *ldst; 19267f65be51SRichard Henderson HostAddress h; 1927f85ab3d2SRichard Henderson 19281e612dd6SRichard Henderson ldst = prepare_host_addr(s, &h, addr_reg, oi, false); 19291e612dd6SRichard Henderson tcg_out_qemu_st_direct(s, get_memop(oi), data_reg, h); 1930f85ab3d2SRichard Henderson 19311e612dd6SRichard Henderson if (ldst) { 19321e612dd6SRichard Henderson ldst->type = data_type; 19331e612dd6SRichard Henderson ldst->datalo_reg = data_reg; 19341e612dd6SRichard Henderson ldst->raddr = tcg_splitwx_to_rx(s->code_ptr); 1935f85ab3d2SRichard Henderson } 1936139c1837SPaolo Bonzini} 1937139c1837SPaolo Bonzini 1938929124ecSRichard Hendersonstatic void tcg_out_qemu_ldst_i128(TCGContext *s, TCGReg datalo, TCGReg datahi, 1939929124ecSRichard Henderson TCGReg addr_reg, MemOpIdx oi, bool is_ld) 1940929124ecSRichard Henderson{ 1941929124ecSRichard Henderson TCGLabelQemuLdst *ldst; 1942929124ecSRichard Henderson HostAddress h; 1943929124ecSRichard Henderson TCGReg base; 1944929124ecSRichard Henderson bool use_pair; 1945929124ecSRichard Henderson 1946929124ecSRichard Henderson ldst = prepare_host_addr(s, &h, addr_reg, oi, is_ld); 1947929124ecSRichard Henderson 1948929124ecSRichard Henderson /* Compose the final address, as LDP/STP have no indexing. */ 1949929124ecSRichard Henderson if (h.index == TCG_REG_XZR) { 1950929124ecSRichard Henderson base = h.base; 1951929124ecSRichard Henderson } else { 1952929124ecSRichard Henderson base = TCG_REG_TMP2; 1953929124ecSRichard Henderson if (h.index_ext == TCG_TYPE_I32) { 1954929124ecSRichard Henderson /* add base, base, index, uxtw */ 1955929124ecSRichard Henderson tcg_out_insn(s, 3501, ADD, TCG_TYPE_I64, base, 1956929124ecSRichard Henderson h.base, h.index, MO_32, 0); 1957929124ecSRichard Henderson } else { 1958929124ecSRichard Henderson /* add base, base, index */ 1959929124ecSRichard Henderson tcg_out_insn(s, 3502, ADD, 1, base, h.base, h.index); 1960929124ecSRichard Henderson } 1961929124ecSRichard Henderson } 1962929124ecSRichard Henderson 1963929124ecSRichard Henderson use_pair = h.aa.atom < MO_128 || have_lse2; 1964929124ecSRichard Henderson 1965929124ecSRichard Henderson if (!use_pair) { 1966929124ecSRichard Henderson tcg_insn_unit *branch = NULL; 1967929124ecSRichard Henderson TCGReg ll, lh, sl, sh; 1968929124ecSRichard Henderson 1969929124ecSRichard Henderson /* 1970929124ecSRichard Henderson * If we have already checked for 16-byte alignment, that's all 1971929124ecSRichard Henderson * we need. Otherwise we have determined that misaligned atomicity 1972929124ecSRichard Henderson * may be handled with two 8-byte loads. 1973929124ecSRichard Henderson */ 1974929124ecSRichard Henderson if (h.aa.align < MO_128) { 1975929124ecSRichard Henderson /* 1976929124ecSRichard Henderson * TODO: align should be MO_64, so we only need test bit 3, 1977929124ecSRichard Henderson * which means we could use TBNZ instead of ANDS+B_C. 1978929124ecSRichard Henderson */ 1979929124ecSRichard Henderson tcg_out_logicali(s, I3404_ANDSI, 0, TCG_REG_XZR, addr_reg, 15); 1980929124ecSRichard Henderson branch = s->code_ptr; 1981929124ecSRichard Henderson tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0); 1982929124ecSRichard Henderson use_pair = true; 1983929124ecSRichard Henderson } 1984929124ecSRichard Henderson 1985929124ecSRichard Henderson if (is_ld) { 1986929124ecSRichard Henderson /* 1987929124ecSRichard Henderson * 16-byte atomicity without LSE2 requires LDXP+STXP loop: 1988929124ecSRichard Henderson * ldxp lo, hi, [base] 1989929124ecSRichard Henderson * stxp t0, lo, hi, [base] 1990929124ecSRichard Henderson * cbnz t0, .-8 1991929124ecSRichard Henderson * Require no overlap between data{lo,hi} and base. 1992929124ecSRichard Henderson */ 1993929124ecSRichard Henderson if (datalo == base || datahi == base) { 1994929124ecSRichard Henderson tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_TMP2, base); 1995929124ecSRichard Henderson base = TCG_REG_TMP2; 1996929124ecSRichard Henderson } 1997929124ecSRichard Henderson ll = sl = datalo; 1998929124ecSRichard Henderson lh = sh = datahi; 1999929124ecSRichard Henderson } else { 2000929124ecSRichard Henderson /* 2001929124ecSRichard Henderson * 16-byte atomicity without LSE2 requires LDXP+STXP loop: 2002929124ecSRichard Henderson * 1: ldxp t0, t1, [base] 2003929124ecSRichard Henderson * stxp t0, lo, hi, [base] 2004929124ecSRichard Henderson * cbnz t0, 1b 2005929124ecSRichard Henderson */ 2006929124ecSRichard Henderson tcg_debug_assert(base != TCG_REG_TMP0 && base != TCG_REG_TMP1); 2007929124ecSRichard Henderson ll = TCG_REG_TMP0; 2008929124ecSRichard Henderson lh = TCG_REG_TMP1; 2009929124ecSRichard Henderson sl = datalo; 2010929124ecSRichard Henderson sh = datahi; 2011929124ecSRichard Henderson } 2012929124ecSRichard Henderson 2013929124ecSRichard Henderson tcg_out_insn(s, 3306, LDXP, TCG_REG_XZR, ll, lh, base); 2014929124ecSRichard Henderson tcg_out_insn(s, 3306, STXP, TCG_REG_TMP0, sl, sh, base); 2015929124ecSRichard Henderson tcg_out_insn(s, 3201, CBNZ, 0, TCG_REG_TMP0, -2); 2016929124ecSRichard Henderson 2017929124ecSRichard Henderson if (use_pair) { 2018929124ecSRichard Henderson /* "b .+8", branching across the one insn of use_pair. */ 2019929124ecSRichard Henderson tcg_out_insn(s, 3206, B, 2); 2020929124ecSRichard Henderson reloc_pc19(branch, tcg_splitwx_to_rx(s->code_ptr)); 2021929124ecSRichard Henderson } 2022929124ecSRichard Henderson } 2023929124ecSRichard Henderson 2024929124ecSRichard Henderson if (use_pair) { 2025929124ecSRichard Henderson if (is_ld) { 2026929124ecSRichard Henderson tcg_out_insn(s, 3314, LDP, datalo, datahi, base, 0, 1, 0); 2027929124ecSRichard Henderson } else { 2028929124ecSRichard Henderson tcg_out_insn(s, 3314, STP, datalo, datahi, base, 0, 1, 0); 2029929124ecSRichard Henderson } 2030929124ecSRichard Henderson } 2031929124ecSRichard Henderson 2032929124ecSRichard Henderson if (ldst) { 2033929124ecSRichard Henderson ldst->type = TCG_TYPE_I128; 2034929124ecSRichard Henderson ldst->datalo_reg = datalo; 2035929124ecSRichard Henderson ldst->datahi_reg = datahi; 2036929124ecSRichard Henderson ldst->raddr = tcg_splitwx_to_rx(s->code_ptr); 2037929124ecSRichard Henderson } 2038929124ecSRichard Henderson} 2039929124ecSRichard Henderson 2040ffba3eb3SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr; 2041139c1837SPaolo Bonzini 2042b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) 2043b55a8d9dSRichard Henderson{ 20445826a0dbSRichard Henderson const tcg_insn_unit *target; 20455826a0dbSRichard Henderson ptrdiff_t offset; 20465826a0dbSRichard Henderson 2047b55a8d9dSRichard Henderson /* Reuse the zeroing that exists for goto_ptr. */ 2048b55a8d9dSRichard Henderson if (a0 == 0) { 20495826a0dbSRichard Henderson target = tcg_code_gen_epilogue; 2050b55a8d9dSRichard Henderson } else { 2051b55a8d9dSRichard Henderson tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0); 20525826a0dbSRichard Henderson target = tb_ret_addr; 20535826a0dbSRichard Henderson } 20545826a0dbSRichard Henderson 20555826a0dbSRichard Henderson offset = tcg_pcrel_diff(s, target) >> 2; 20565826a0dbSRichard Henderson if (offset == sextract64(offset, 0, 26)) { 20575826a0dbSRichard Henderson tcg_out_insn(s, 3206, B, offset); 20585826a0dbSRichard Henderson } else { 20595826a0dbSRichard Henderson /* 20605826a0dbSRichard Henderson * Only x16/x17 generate BTI type Jump (2), 20615826a0dbSRichard Henderson * other registers generate BTI type Jump|Call (3). 20625826a0dbSRichard Henderson */ 20635826a0dbSRichard Henderson QEMU_BUILD_BUG_ON(TCG_REG_TMP0 != TCG_REG_X16); 20645826a0dbSRichard Henderson tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, (intptr_t)target); 20655826a0dbSRichard Henderson tcg_out_insn(s, 3207, BR, TCG_REG_TMP0); 2066b55a8d9dSRichard Henderson } 2067b55a8d9dSRichard Henderson} 2068b55a8d9dSRichard Henderson 2069cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which) 2070cf7d6b8eSRichard Henderson{ 2071cf7d6b8eSRichard Henderson /* 2072d59d83a1SRichard Henderson * Direct branch, or indirect address load, will be patched 2073d59d83a1SRichard Henderson * by tb_target_set_jmp_target. Assert indirect load offset 2074d59d83a1SRichard Henderson * in range early, regardless of direct branch distance. 2075cf7d6b8eSRichard Henderson */ 2076d59d83a1SRichard Henderson intptr_t i_off = tcg_pcrel_diff(s, (void *)get_jmp_target_addr(s, which)); 2077d59d83a1SRichard Henderson tcg_debug_assert(i_off == sextract64(i_off, 0, 21)); 2078d59d83a1SRichard Henderson 2079cf7d6b8eSRichard Henderson set_jmp_insn_offset(s, which); 2080d59d83a1SRichard Henderson tcg_out32(s, I3206_B); 2081d67bcbddSRichard Henderson tcg_out_insn(s, 3207, BR, TCG_REG_TMP0); 2082cf7d6b8eSRichard Henderson set_jmp_reset_offset(s, which); 20835826a0dbSRichard Henderson tcg_out_bti(s, BTI_J); 2084cf7d6b8eSRichard Henderson} 2085cf7d6b8eSRichard Henderson 2086d59d83a1SRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n, 2087d59d83a1SRichard Henderson uintptr_t jmp_rx, uintptr_t jmp_rw) 2088d59d83a1SRichard Henderson{ 2089d59d83a1SRichard Henderson uintptr_t d_addr = tb->jmp_target_addr[n]; 2090d59d83a1SRichard Henderson ptrdiff_t d_offset = d_addr - jmp_rx; 2091d59d83a1SRichard Henderson tcg_insn_unit insn; 2092d59d83a1SRichard Henderson 2093d59d83a1SRichard Henderson /* Either directly branch, or indirect branch load. */ 2094d59d83a1SRichard Henderson if (d_offset == sextract64(d_offset, 0, 28)) { 2095d59d83a1SRichard Henderson insn = deposit32(I3206_B, 0, 26, d_offset >> 2); 2096d59d83a1SRichard Henderson } else { 2097d59d83a1SRichard Henderson uintptr_t i_addr = (uintptr_t)&tb->jmp_target_addr[n]; 2098d59d83a1SRichard Henderson ptrdiff_t i_offset = i_addr - jmp_rx; 2099d59d83a1SRichard Henderson 2100d59d83a1SRichard Henderson /* Note that we asserted this in range in tcg_out_goto_tb. */ 2101d67bcbddSRichard Henderson insn = deposit32(I3305_LDR | TCG_REG_TMP0, 5, 19, i_offset >> 2); 2102d59d83a1SRichard Henderson } 2103d59d83a1SRichard Henderson qatomic_set((uint32_t *)jmp_rw, insn); 2104d59d83a1SRichard Henderson flush_idcache_range(jmp_rx, jmp_rw, 4); 2105d59d83a1SRichard Henderson} 2106d59d83a1SRichard Henderson 2107139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc, 2108139c1837SPaolo Bonzini const TCGArg args[TCG_MAX_OP_ARGS], 2109139c1837SPaolo Bonzini const int const_args[TCG_MAX_OP_ARGS]) 2110139c1837SPaolo Bonzini{ 2111139c1837SPaolo Bonzini /* 99% of the time, we can signal the use of extension registers 2112139c1837SPaolo Bonzini by looking to see if the opcode handles 64-bit data. */ 2113139c1837SPaolo Bonzini TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0; 2114139c1837SPaolo Bonzini 2115139c1837SPaolo Bonzini /* Hoist the loads of the most common arguments. */ 2116139c1837SPaolo Bonzini TCGArg a0 = args[0]; 2117139c1837SPaolo Bonzini TCGArg a1 = args[1]; 2118139c1837SPaolo Bonzini TCGArg a2 = args[2]; 2119139c1837SPaolo Bonzini int c2 = const_args[2]; 2120139c1837SPaolo Bonzini 2121139c1837SPaolo Bonzini /* Some operands are defined with "rZ" constraint, a register or 2122139c1837SPaolo Bonzini the zero register. These need not actually test args[I] == 0. */ 2123139c1837SPaolo Bonzini#define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I]) 2124139c1837SPaolo Bonzini 2125139c1837SPaolo Bonzini switch (opc) { 2126139c1837SPaolo Bonzini case INDEX_op_goto_ptr: 2127139c1837SPaolo Bonzini tcg_out_insn(s, 3207, BR, a0); 2128139c1837SPaolo Bonzini break; 2129139c1837SPaolo Bonzini 2130139c1837SPaolo Bonzini case INDEX_op_br: 2131139c1837SPaolo Bonzini tcg_out_goto_label(s, arg_label(a0)); 2132139c1837SPaolo Bonzini break; 2133139c1837SPaolo Bonzini 2134139c1837SPaolo Bonzini case INDEX_op_ld8u_i32: 2135139c1837SPaolo Bonzini case INDEX_op_ld8u_i64: 2136139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_LDRB, a0, a1, a2, 0); 2137139c1837SPaolo Bonzini break; 2138139c1837SPaolo Bonzini case INDEX_op_ld8s_i32: 2139139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_LDRSBW, a0, a1, a2, 0); 2140139c1837SPaolo Bonzini break; 2141139c1837SPaolo Bonzini case INDEX_op_ld8s_i64: 2142139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_LDRSBX, a0, a1, a2, 0); 2143139c1837SPaolo Bonzini break; 2144139c1837SPaolo Bonzini case INDEX_op_ld16u_i32: 2145139c1837SPaolo Bonzini case INDEX_op_ld16u_i64: 2146139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_LDRH, a0, a1, a2, 1); 2147139c1837SPaolo Bonzini break; 2148139c1837SPaolo Bonzini case INDEX_op_ld16s_i32: 2149139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_LDRSHW, a0, a1, a2, 1); 2150139c1837SPaolo Bonzini break; 2151139c1837SPaolo Bonzini case INDEX_op_ld16s_i64: 2152139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_LDRSHX, a0, a1, a2, 1); 2153139c1837SPaolo Bonzini break; 2154139c1837SPaolo Bonzini case INDEX_op_ld_i32: 2155139c1837SPaolo Bonzini case INDEX_op_ld32u_i64: 2156139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_LDRW, a0, a1, a2, 2); 2157139c1837SPaolo Bonzini break; 2158139c1837SPaolo Bonzini case INDEX_op_ld32s_i64: 2159139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_LDRSWX, a0, a1, a2, 2); 2160139c1837SPaolo Bonzini break; 2161139c1837SPaolo Bonzini case INDEX_op_ld_i64: 2162139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_LDRX, a0, a1, a2, 3); 2163139c1837SPaolo Bonzini break; 2164139c1837SPaolo Bonzini 2165139c1837SPaolo Bonzini case INDEX_op_st8_i32: 2166139c1837SPaolo Bonzini case INDEX_op_st8_i64: 2167139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_STRB, REG0(0), a1, a2, 0); 2168139c1837SPaolo Bonzini break; 2169139c1837SPaolo Bonzini case INDEX_op_st16_i32: 2170139c1837SPaolo Bonzini case INDEX_op_st16_i64: 2171139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_STRH, REG0(0), a1, a2, 1); 2172139c1837SPaolo Bonzini break; 2173139c1837SPaolo Bonzini case INDEX_op_st_i32: 2174139c1837SPaolo Bonzini case INDEX_op_st32_i64: 2175139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_STRW, REG0(0), a1, a2, 2); 2176139c1837SPaolo Bonzini break; 2177139c1837SPaolo Bonzini case INDEX_op_st_i64: 2178139c1837SPaolo Bonzini tcg_out_ldst(s, I3312_STRX, REG0(0), a1, a2, 3); 2179139c1837SPaolo Bonzini break; 2180139c1837SPaolo Bonzini 2181139c1837SPaolo Bonzini case INDEX_op_add_i32: 2182139c1837SPaolo Bonzini a2 = (int32_t)a2; 2183139c1837SPaolo Bonzini /* FALLTHRU */ 2184139c1837SPaolo Bonzini case INDEX_op_add_i64: 2185139c1837SPaolo Bonzini if (c2) { 2186139c1837SPaolo Bonzini tcg_out_addsubi(s, ext, a0, a1, a2); 2187139c1837SPaolo Bonzini } else { 2188139c1837SPaolo Bonzini tcg_out_insn(s, 3502, ADD, ext, a0, a1, a2); 2189139c1837SPaolo Bonzini } 2190139c1837SPaolo Bonzini break; 2191139c1837SPaolo Bonzini 2192139c1837SPaolo Bonzini case INDEX_op_sub_i32: 2193139c1837SPaolo Bonzini a2 = (int32_t)a2; 2194139c1837SPaolo Bonzini /* FALLTHRU */ 2195139c1837SPaolo Bonzini case INDEX_op_sub_i64: 2196139c1837SPaolo Bonzini if (c2) { 2197139c1837SPaolo Bonzini tcg_out_addsubi(s, ext, a0, a1, -a2); 2198139c1837SPaolo Bonzini } else { 2199139c1837SPaolo Bonzini tcg_out_insn(s, 3502, SUB, ext, a0, a1, a2); 2200139c1837SPaolo Bonzini } 2201139c1837SPaolo Bonzini break; 2202139c1837SPaolo Bonzini 2203139c1837SPaolo Bonzini case INDEX_op_neg_i64: 2204139c1837SPaolo Bonzini case INDEX_op_neg_i32: 2205139c1837SPaolo Bonzini tcg_out_insn(s, 3502, SUB, ext, a0, TCG_REG_XZR, a1); 2206139c1837SPaolo Bonzini break; 2207139c1837SPaolo Bonzini 2208139c1837SPaolo Bonzini case INDEX_op_and_i32: 2209139c1837SPaolo Bonzini a2 = (int32_t)a2; 2210139c1837SPaolo Bonzini /* FALLTHRU */ 2211139c1837SPaolo Bonzini case INDEX_op_and_i64: 2212139c1837SPaolo Bonzini if (c2) { 2213139c1837SPaolo Bonzini tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, a2); 2214139c1837SPaolo Bonzini } else { 2215139c1837SPaolo Bonzini tcg_out_insn(s, 3510, AND, ext, a0, a1, a2); 2216139c1837SPaolo Bonzini } 2217139c1837SPaolo Bonzini break; 2218139c1837SPaolo Bonzini 2219139c1837SPaolo Bonzini case INDEX_op_andc_i32: 2220139c1837SPaolo Bonzini a2 = (int32_t)a2; 2221139c1837SPaolo Bonzini /* FALLTHRU */ 2222139c1837SPaolo Bonzini case INDEX_op_andc_i64: 2223139c1837SPaolo Bonzini if (c2) { 2224139c1837SPaolo Bonzini tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, ~a2); 2225139c1837SPaolo Bonzini } else { 2226139c1837SPaolo Bonzini tcg_out_insn(s, 3510, BIC, ext, a0, a1, a2); 2227139c1837SPaolo Bonzini } 2228139c1837SPaolo Bonzini break; 2229139c1837SPaolo Bonzini 2230139c1837SPaolo Bonzini case INDEX_op_or_i32: 2231139c1837SPaolo Bonzini a2 = (int32_t)a2; 2232139c1837SPaolo Bonzini /* FALLTHRU */ 2233139c1837SPaolo Bonzini case INDEX_op_or_i64: 2234139c1837SPaolo Bonzini if (c2) { 2235139c1837SPaolo Bonzini tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, a2); 2236139c1837SPaolo Bonzini } else { 2237139c1837SPaolo Bonzini tcg_out_insn(s, 3510, ORR, ext, a0, a1, a2); 2238139c1837SPaolo Bonzini } 2239139c1837SPaolo Bonzini break; 2240139c1837SPaolo Bonzini 2241139c1837SPaolo Bonzini case INDEX_op_orc_i32: 2242139c1837SPaolo Bonzini a2 = (int32_t)a2; 2243139c1837SPaolo Bonzini /* FALLTHRU */ 2244139c1837SPaolo Bonzini case INDEX_op_orc_i64: 2245139c1837SPaolo Bonzini if (c2) { 2246139c1837SPaolo Bonzini tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, ~a2); 2247139c1837SPaolo Bonzini } else { 2248139c1837SPaolo Bonzini tcg_out_insn(s, 3510, ORN, ext, a0, a1, a2); 2249139c1837SPaolo Bonzini } 2250139c1837SPaolo Bonzini break; 2251139c1837SPaolo Bonzini 2252139c1837SPaolo Bonzini case INDEX_op_xor_i32: 2253139c1837SPaolo Bonzini a2 = (int32_t)a2; 2254139c1837SPaolo Bonzini /* FALLTHRU */ 2255139c1837SPaolo Bonzini case INDEX_op_xor_i64: 2256139c1837SPaolo Bonzini if (c2) { 2257139c1837SPaolo Bonzini tcg_out_logicali(s, I3404_EORI, ext, a0, a1, a2); 2258139c1837SPaolo Bonzini } else { 2259139c1837SPaolo Bonzini tcg_out_insn(s, 3510, EOR, ext, a0, a1, a2); 2260139c1837SPaolo Bonzini } 2261139c1837SPaolo Bonzini break; 2262139c1837SPaolo Bonzini 2263139c1837SPaolo Bonzini case INDEX_op_eqv_i32: 2264139c1837SPaolo Bonzini a2 = (int32_t)a2; 2265139c1837SPaolo Bonzini /* FALLTHRU */ 2266139c1837SPaolo Bonzini case INDEX_op_eqv_i64: 2267139c1837SPaolo Bonzini if (c2) { 2268139c1837SPaolo Bonzini tcg_out_logicali(s, I3404_EORI, ext, a0, a1, ~a2); 2269139c1837SPaolo Bonzini } else { 2270139c1837SPaolo Bonzini tcg_out_insn(s, 3510, EON, ext, a0, a1, a2); 2271139c1837SPaolo Bonzini } 2272139c1837SPaolo Bonzini break; 2273139c1837SPaolo Bonzini 2274139c1837SPaolo Bonzini case INDEX_op_not_i64: 2275139c1837SPaolo Bonzini case INDEX_op_not_i32: 2276139c1837SPaolo Bonzini tcg_out_insn(s, 3510, ORN, ext, a0, TCG_REG_XZR, a1); 2277139c1837SPaolo Bonzini break; 2278139c1837SPaolo Bonzini 2279139c1837SPaolo Bonzini case INDEX_op_mul_i64: 2280139c1837SPaolo Bonzini case INDEX_op_mul_i32: 2281139c1837SPaolo Bonzini tcg_out_insn(s, 3509, MADD, ext, a0, a1, a2, TCG_REG_XZR); 2282139c1837SPaolo Bonzini break; 2283139c1837SPaolo Bonzini 2284139c1837SPaolo Bonzini case INDEX_op_div_i64: 2285139c1837SPaolo Bonzini case INDEX_op_div_i32: 2286139c1837SPaolo Bonzini tcg_out_insn(s, 3508, SDIV, ext, a0, a1, a2); 2287139c1837SPaolo Bonzini break; 2288139c1837SPaolo Bonzini case INDEX_op_divu_i64: 2289139c1837SPaolo Bonzini case INDEX_op_divu_i32: 2290139c1837SPaolo Bonzini tcg_out_insn(s, 3508, UDIV, ext, a0, a1, a2); 2291139c1837SPaolo Bonzini break; 2292139c1837SPaolo Bonzini 2293139c1837SPaolo Bonzini case INDEX_op_rem_i64: 2294139c1837SPaolo Bonzini case INDEX_op_rem_i32: 2295d67bcbddSRichard Henderson tcg_out_insn(s, 3508, SDIV, ext, TCG_REG_TMP0, a1, a2); 2296d67bcbddSRichard Henderson tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP0, a2, a1); 2297139c1837SPaolo Bonzini break; 2298139c1837SPaolo Bonzini case INDEX_op_remu_i64: 2299139c1837SPaolo Bonzini case INDEX_op_remu_i32: 2300d67bcbddSRichard Henderson tcg_out_insn(s, 3508, UDIV, ext, TCG_REG_TMP0, a1, a2); 2301d67bcbddSRichard Henderson tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP0, a2, a1); 2302139c1837SPaolo Bonzini break; 2303139c1837SPaolo Bonzini 2304139c1837SPaolo Bonzini case INDEX_op_shl_i64: 2305139c1837SPaolo Bonzini case INDEX_op_shl_i32: 2306139c1837SPaolo Bonzini if (c2) { 2307139c1837SPaolo Bonzini tcg_out_shl(s, ext, a0, a1, a2); 2308139c1837SPaolo Bonzini } else { 2309139c1837SPaolo Bonzini tcg_out_insn(s, 3508, LSLV, ext, a0, a1, a2); 2310139c1837SPaolo Bonzini } 2311139c1837SPaolo Bonzini break; 2312139c1837SPaolo Bonzini 2313139c1837SPaolo Bonzini case INDEX_op_shr_i64: 2314139c1837SPaolo Bonzini case INDEX_op_shr_i32: 2315139c1837SPaolo Bonzini if (c2) { 2316139c1837SPaolo Bonzini tcg_out_shr(s, ext, a0, a1, a2); 2317139c1837SPaolo Bonzini } else { 2318139c1837SPaolo Bonzini tcg_out_insn(s, 3508, LSRV, ext, a0, a1, a2); 2319139c1837SPaolo Bonzini } 2320139c1837SPaolo Bonzini break; 2321139c1837SPaolo Bonzini 2322139c1837SPaolo Bonzini case INDEX_op_sar_i64: 2323139c1837SPaolo Bonzini case INDEX_op_sar_i32: 2324139c1837SPaolo Bonzini if (c2) { 2325139c1837SPaolo Bonzini tcg_out_sar(s, ext, a0, a1, a2); 2326139c1837SPaolo Bonzini } else { 2327139c1837SPaolo Bonzini tcg_out_insn(s, 3508, ASRV, ext, a0, a1, a2); 2328139c1837SPaolo Bonzini } 2329139c1837SPaolo Bonzini break; 2330139c1837SPaolo Bonzini 2331139c1837SPaolo Bonzini case INDEX_op_rotr_i64: 2332139c1837SPaolo Bonzini case INDEX_op_rotr_i32: 2333139c1837SPaolo Bonzini if (c2) { 2334139c1837SPaolo Bonzini tcg_out_rotr(s, ext, a0, a1, a2); 2335139c1837SPaolo Bonzini } else { 2336139c1837SPaolo Bonzini tcg_out_insn(s, 3508, RORV, ext, a0, a1, a2); 2337139c1837SPaolo Bonzini } 2338139c1837SPaolo Bonzini break; 2339139c1837SPaolo Bonzini 2340139c1837SPaolo Bonzini case INDEX_op_rotl_i64: 2341139c1837SPaolo Bonzini case INDEX_op_rotl_i32: 2342139c1837SPaolo Bonzini if (c2) { 2343139c1837SPaolo Bonzini tcg_out_rotl(s, ext, a0, a1, a2); 2344139c1837SPaolo Bonzini } else { 2345d67bcbddSRichard Henderson tcg_out_insn(s, 3502, SUB, 0, TCG_REG_TMP0, TCG_REG_XZR, a2); 2346d67bcbddSRichard Henderson tcg_out_insn(s, 3508, RORV, ext, a0, a1, TCG_REG_TMP0); 2347139c1837SPaolo Bonzini } 2348139c1837SPaolo Bonzini break; 2349139c1837SPaolo Bonzini 2350139c1837SPaolo Bonzini case INDEX_op_clz_i64: 2351139c1837SPaolo Bonzini case INDEX_op_clz_i32: 2352139c1837SPaolo Bonzini tcg_out_cltz(s, ext, a0, a1, a2, c2, false); 2353139c1837SPaolo Bonzini break; 2354139c1837SPaolo Bonzini case INDEX_op_ctz_i64: 2355139c1837SPaolo Bonzini case INDEX_op_ctz_i32: 2356139c1837SPaolo Bonzini tcg_out_cltz(s, ext, a0, a1, a2, c2, true); 2357139c1837SPaolo Bonzini break; 2358139c1837SPaolo Bonzini 2359139c1837SPaolo Bonzini case INDEX_op_brcond_i32: 2360139c1837SPaolo Bonzini a1 = (int32_t)a1; 2361139c1837SPaolo Bonzini /* FALLTHRU */ 2362139c1837SPaolo Bonzini case INDEX_op_brcond_i64: 2363139c1837SPaolo Bonzini tcg_out_brcond(s, ext, a2, a0, a1, const_args[1], arg_label(args[3])); 2364139c1837SPaolo Bonzini break; 2365139c1837SPaolo Bonzini 2366139c1837SPaolo Bonzini case INDEX_op_setcond_i32: 2367139c1837SPaolo Bonzini a2 = (int32_t)a2; 2368139c1837SPaolo Bonzini /* FALLTHRU */ 2369139c1837SPaolo Bonzini case INDEX_op_setcond_i64: 2370339adf2fSRichard Henderson tcg_out_cmp(s, ext, args[3], a1, a2, c2); 2371139c1837SPaolo Bonzini /* Use CSET alias of CSINC Wd, WZR, WZR, invert(cond). */ 2372139c1837SPaolo Bonzini tcg_out_insn(s, 3506, CSINC, TCG_TYPE_I32, a0, TCG_REG_XZR, 2373139c1837SPaolo Bonzini TCG_REG_XZR, tcg_invert_cond(args[3])); 2374139c1837SPaolo Bonzini break; 2375139c1837SPaolo Bonzini 2376f58a7deaSRichard Henderson case INDEX_op_negsetcond_i32: 2377f58a7deaSRichard Henderson a2 = (int32_t)a2; 2378f58a7deaSRichard Henderson /* FALLTHRU */ 2379f58a7deaSRichard Henderson case INDEX_op_negsetcond_i64: 2380339adf2fSRichard Henderson tcg_out_cmp(s, ext, args[3], a1, a2, c2); 2381f58a7deaSRichard Henderson /* Use CSETM alias of CSINV Wd, WZR, WZR, invert(cond). */ 2382f58a7deaSRichard Henderson tcg_out_insn(s, 3506, CSINV, ext, a0, TCG_REG_XZR, 2383f58a7deaSRichard Henderson TCG_REG_XZR, tcg_invert_cond(args[3])); 2384f58a7deaSRichard Henderson break; 2385f58a7deaSRichard Henderson 2386139c1837SPaolo Bonzini case INDEX_op_movcond_i32: 2387139c1837SPaolo Bonzini a2 = (int32_t)a2; 2388139c1837SPaolo Bonzini /* FALLTHRU */ 2389139c1837SPaolo Bonzini case INDEX_op_movcond_i64: 2390339adf2fSRichard Henderson tcg_out_cmp(s, ext, args[5], a1, a2, c2); 2391139c1837SPaolo Bonzini tcg_out_insn(s, 3506, CSEL, ext, a0, REG0(3), REG0(4), args[5]); 2392139c1837SPaolo Bonzini break; 2393139c1837SPaolo Bonzini 2394fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32: 2395fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32: 2396fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64: 2397fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64: 2398139c1837SPaolo Bonzini tcg_out_qemu_ld(s, a0, a1, a2, ext); 2399139c1837SPaolo Bonzini break; 2400fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32: 2401fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32: 2402fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64: 2403fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64: 2404ff0cc85eSRichard Henderson tcg_out_qemu_st(s, REG0(0), a1, a2, ext); 2405139c1837SPaolo Bonzini break; 2406929124ecSRichard Henderson case INDEX_op_qemu_ld_a32_i128: 2407929124ecSRichard Henderson case INDEX_op_qemu_ld_a64_i128: 2408929124ecSRichard Henderson tcg_out_qemu_ldst_i128(s, a0, a1, a2, args[3], true); 2409929124ecSRichard Henderson break; 2410929124ecSRichard Henderson case INDEX_op_qemu_st_a32_i128: 2411929124ecSRichard Henderson case INDEX_op_qemu_st_a64_i128: 2412929124ecSRichard Henderson tcg_out_qemu_ldst_i128(s, REG0(0), REG0(1), a2, args[3], false); 2413929124ecSRichard Henderson break; 2414139c1837SPaolo Bonzini 2415139c1837SPaolo Bonzini case INDEX_op_bswap64_i64: 2416dfa24dfaSRichard Henderson tcg_out_rev(s, TCG_TYPE_I64, MO_64, a0, a1); 2417139c1837SPaolo Bonzini break; 2418139c1837SPaolo Bonzini case INDEX_op_bswap32_i64: 24198fcfc6bfSRichard Henderson tcg_out_rev(s, TCG_TYPE_I32, MO_32, a0, a1); 24208fcfc6bfSRichard Henderson if (a2 & TCG_BSWAP_OS) { 242152bf3398SRichard Henderson tcg_out_ext32s(s, a0, a0); 24228fcfc6bfSRichard Henderson } 24238fcfc6bfSRichard Henderson break; 2424139c1837SPaolo Bonzini case INDEX_op_bswap32_i32: 2425dfa24dfaSRichard Henderson tcg_out_rev(s, TCG_TYPE_I32, MO_32, a0, a1); 2426139c1837SPaolo Bonzini break; 2427139c1837SPaolo Bonzini case INDEX_op_bswap16_i64: 2428139c1837SPaolo Bonzini case INDEX_op_bswap16_i32: 2429dfa24dfaSRichard Henderson tcg_out_rev(s, TCG_TYPE_I32, MO_16, a0, a1); 24308fcfc6bfSRichard Henderson if (a2 & TCG_BSWAP_OS) { 24318fcfc6bfSRichard Henderson /* Output must be sign-extended. */ 2432753e42eaSRichard Henderson tcg_out_ext16s(s, ext, a0, a0); 24338fcfc6bfSRichard Henderson } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) { 24348fcfc6bfSRichard Henderson /* Output must be zero-extended, but input isn't. */ 2435379afdffSRichard Henderson tcg_out_ext16u(s, a0, a0); 24368fcfc6bfSRichard Henderson } 2437139c1837SPaolo Bonzini break; 2438139c1837SPaolo Bonzini 2439139c1837SPaolo Bonzini case INDEX_op_deposit_i64: 2440139c1837SPaolo Bonzini case INDEX_op_deposit_i32: 2441139c1837SPaolo Bonzini tcg_out_dep(s, ext, a0, REG0(2), args[3], args[4]); 2442139c1837SPaolo Bonzini break; 2443139c1837SPaolo Bonzini 2444139c1837SPaolo Bonzini case INDEX_op_extract_i64: 2445139c1837SPaolo Bonzini case INDEX_op_extract_i32: 2446139c1837SPaolo Bonzini tcg_out_ubfm(s, ext, a0, a1, a2, a2 + args[3] - 1); 2447139c1837SPaolo Bonzini break; 2448139c1837SPaolo Bonzini 2449139c1837SPaolo Bonzini case INDEX_op_sextract_i64: 2450139c1837SPaolo Bonzini case INDEX_op_sextract_i32: 2451139c1837SPaolo Bonzini tcg_out_sbfm(s, ext, a0, a1, a2, a2 + args[3] - 1); 2452139c1837SPaolo Bonzini break; 2453139c1837SPaolo Bonzini 2454139c1837SPaolo Bonzini case INDEX_op_extract2_i64: 2455139c1837SPaolo Bonzini case INDEX_op_extract2_i32: 2456139c1837SPaolo Bonzini tcg_out_extr(s, ext, a0, REG0(2), REG0(1), args[3]); 2457139c1837SPaolo Bonzini break; 2458139c1837SPaolo Bonzini 2459139c1837SPaolo Bonzini case INDEX_op_add2_i32: 2460139c1837SPaolo Bonzini tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3), 2461139c1837SPaolo Bonzini (int32_t)args[4], args[5], const_args[4], 2462139c1837SPaolo Bonzini const_args[5], false); 2463139c1837SPaolo Bonzini break; 2464139c1837SPaolo Bonzini case INDEX_op_add2_i64: 2465139c1837SPaolo Bonzini tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4], 2466139c1837SPaolo Bonzini args[5], const_args[4], const_args[5], false); 2467139c1837SPaolo Bonzini break; 2468139c1837SPaolo Bonzini case INDEX_op_sub2_i32: 2469139c1837SPaolo Bonzini tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3), 2470139c1837SPaolo Bonzini (int32_t)args[4], args[5], const_args[4], 2471139c1837SPaolo Bonzini const_args[5], true); 2472139c1837SPaolo Bonzini break; 2473139c1837SPaolo Bonzini case INDEX_op_sub2_i64: 2474139c1837SPaolo Bonzini tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4], 2475139c1837SPaolo Bonzini args[5], const_args[4], const_args[5], true); 2476139c1837SPaolo Bonzini break; 2477139c1837SPaolo Bonzini 2478139c1837SPaolo Bonzini case INDEX_op_muluh_i64: 2479139c1837SPaolo Bonzini tcg_out_insn(s, 3508, UMULH, TCG_TYPE_I64, a0, a1, a2); 2480139c1837SPaolo Bonzini break; 2481139c1837SPaolo Bonzini case INDEX_op_mulsh_i64: 2482139c1837SPaolo Bonzini tcg_out_insn(s, 3508, SMULH, TCG_TYPE_I64, a0, a1, a2); 2483139c1837SPaolo Bonzini break; 2484139c1837SPaolo Bonzini 2485139c1837SPaolo Bonzini case INDEX_op_mb: 2486139c1837SPaolo Bonzini tcg_out_mb(s, a0); 2487139c1837SPaolo Bonzini break; 2488139c1837SPaolo Bonzini 2489139c1837SPaolo Bonzini case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ 2490139c1837SPaolo Bonzini case INDEX_op_mov_i64: 2491139c1837SPaolo Bonzini case INDEX_op_call: /* Always emitted via tcg_out_call. */ 2492b55a8d9dSRichard Henderson case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ 2493cf7d6b8eSRichard Henderson case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ 2494678155b2SRichard Henderson case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */ 2495678155b2SRichard Henderson case INDEX_op_ext8s_i64: 2496d0e66c89SRichard Henderson case INDEX_op_ext8u_i32: 2497d0e66c89SRichard Henderson case INDEX_op_ext8u_i64: 2498753e42eaSRichard Henderson case INDEX_op_ext16s_i64: 2499753e42eaSRichard Henderson case INDEX_op_ext16s_i32: 2500379afdffSRichard Henderson case INDEX_op_ext16u_i64: 2501379afdffSRichard Henderson case INDEX_op_ext16u_i32: 250252bf3398SRichard Henderson case INDEX_op_ext32s_i64: 25039ecf5f61SRichard Henderson case INDEX_op_ext32u_i64: 25049c6aa274SRichard Henderson case INDEX_op_ext_i32_i64: 2505b9bfe000SRichard Henderson case INDEX_op_extu_i32_i64: 2506b8b94ac6SRichard Henderson case INDEX_op_extrl_i64_i32: 2507139c1837SPaolo Bonzini default: 2508139c1837SPaolo Bonzini g_assert_not_reached(); 2509139c1837SPaolo Bonzini } 2510139c1837SPaolo Bonzini 2511139c1837SPaolo Bonzini#undef REG0 2512139c1837SPaolo Bonzini} 2513139c1837SPaolo Bonzini 2514139c1837SPaolo Bonzinistatic void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, 2515139c1837SPaolo Bonzini unsigned vecl, unsigned vece, 25165e8892dbSMiroslav Rezanina const TCGArg args[TCG_MAX_OP_ARGS], 25175e8892dbSMiroslav Rezanina const int const_args[TCG_MAX_OP_ARGS]) 2518139c1837SPaolo Bonzini{ 2519d81bad24SRichard Henderson static const AArch64Insn cmp_vec_insn[16] = { 2520139c1837SPaolo Bonzini [TCG_COND_EQ] = I3616_CMEQ, 2521139c1837SPaolo Bonzini [TCG_COND_GT] = I3616_CMGT, 2522139c1837SPaolo Bonzini [TCG_COND_GE] = I3616_CMGE, 2523139c1837SPaolo Bonzini [TCG_COND_GTU] = I3616_CMHI, 2524139c1837SPaolo Bonzini [TCG_COND_GEU] = I3616_CMHS, 2525139c1837SPaolo Bonzini }; 2526d81bad24SRichard Henderson static const AArch64Insn cmp_scalar_insn[16] = { 2527d81bad24SRichard Henderson [TCG_COND_EQ] = I3611_CMEQ, 2528d81bad24SRichard Henderson [TCG_COND_GT] = I3611_CMGT, 2529d81bad24SRichard Henderson [TCG_COND_GE] = I3611_CMGE, 2530d81bad24SRichard Henderson [TCG_COND_GTU] = I3611_CMHI, 2531d81bad24SRichard Henderson [TCG_COND_GEU] = I3611_CMHS, 2532d81bad24SRichard Henderson }; 2533d81bad24SRichard Henderson static const AArch64Insn cmp0_vec_insn[16] = { 2534139c1837SPaolo Bonzini [TCG_COND_EQ] = I3617_CMEQ0, 2535139c1837SPaolo Bonzini [TCG_COND_GT] = I3617_CMGT0, 2536139c1837SPaolo Bonzini [TCG_COND_GE] = I3617_CMGE0, 2537139c1837SPaolo Bonzini [TCG_COND_LT] = I3617_CMLT0, 2538139c1837SPaolo Bonzini [TCG_COND_LE] = I3617_CMLE0, 2539139c1837SPaolo Bonzini }; 2540d81bad24SRichard Henderson static const AArch64Insn cmp0_scalar_insn[16] = { 2541d81bad24SRichard Henderson [TCG_COND_EQ] = I3612_CMEQ0, 2542d81bad24SRichard Henderson [TCG_COND_GT] = I3612_CMGT0, 2543d81bad24SRichard Henderson [TCG_COND_GE] = I3612_CMGE0, 2544d81bad24SRichard Henderson [TCG_COND_LT] = I3612_CMLT0, 2545d81bad24SRichard Henderson [TCG_COND_LE] = I3612_CMLE0, 2546d81bad24SRichard Henderson }; 2547139c1837SPaolo Bonzini 2548139c1837SPaolo Bonzini TCGType type = vecl + TCG_TYPE_V64; 2549139c1837SPaolo Bonzini unsigned is_q = vecl; 2550d81bad24SRichard Henderson bool is_scalar = !is_q && vece == MO_64; 2551139c1837SPaolo Bonzini TCGArg a0, a1, a2, a3; 2552139c1837SPaolo Bonzini int cmode, imm8; 2553139c1837SPaolo Bonzini 2554139c1837SPaolo Bonzini a0 = args[0]; 2555139c1837SPaolo Bonzini a1 = args[1]; 2556139c1837SPaolo Bonzini a2 = args[2]; 2557139c1837SPaolo Bonzini 2558139c1837SPaolo Bonzini switch (opc) { 2559139c1837SPaolo Bonzini case INDEX_op_ld_vec: 2560139c1837SPaolo Bonzini tcg_out_ld(s, type, a0, a1, a2); 2561139c1837SPaolo Bonzini break; 2562139c1837SPaolo Bonzini case INDEX_op_st_vec: 2563139c1837SPaolo Bonzini tcg_out_st(s, type, a0, a1, a2); 2564139c1837SPaolo Bonzini break; 2565139c1837SPaolo Bonzini case INDEX_op_dupm_vec: 2566139c1837SPaolo Bonzini tcg_out_dupm_vec(s, type, vece, a0, a1, a2); 2567139c1837SPaolo Bonzini break; 2568139c1837SPaolo Bonzini case INDEX_op_add_vec: 2569d81bad24SRichard Henderson if (is_scalar) { 2570d81bad24SRichard Henderson tcg_out_insn(s, 3611, ADD, vece, a0, a1, a2); 2571d81bad24SRichard Henderson } else { 2572139c1837SPaolo Bonzini tcg_out_insn(s, 3616, ADD, is_q, vece, a0, a1, a2); 2573d81bad24SRichard Henderson } 2574139c1837SPaolo Bonzini break; 2575139c1837SPaolo Bonzini case INDEX_op_sub_vec: 2576d81bad24SRichard Henderson if (is_scalar) { 2577d81bad24SRichard Henderson tcg_out_insn(s, 3611, SUB, vece, a0, a1, a2); 2578d81bad24SRichard Henderson } else { 2579139c1837SPaolo Bonzini tcg_out_insn(s, 3616, SUB, is_q, vece, a0, a1, a2); 2580d81bad24SRichard Henderson } 2581139c1837SPaolo Bonzini break; 2582139c1837SPaolo Bonzini case INDEX_op_mul_vec: 2583139c1837SPaolo Bonzini tcg_out_insn(s, 3616, MUL, is_q, vece, a0, a1, a2); 2584139c1837SPaolo Bonzini break; 2585139c1837SPaolo Bonzini case INDEX_op_neg_vec: 2586d81bad24SRichard Henderson if (is_scalar) { 2587d81bad24SRichard Henderson tcg_out_insn(s, 3612, NEG, vece, a0, a1); 2588d81bad24SRichard Henderson } else { 2589139c1837SPaolo Bonzini tcg_out_insn(s, 3617, NEG, is_q, vece, a0, a1); 2590d81bad24SRichard Henderson } 2591139c1837SPaolo Bonzini break; 2592139c1837SPaolo Bonzini case INDEX_op_abs_vec: 2593d81bad24SRichard Henderson if (is_scalar) { 2594d81bad24SRichard Henderson tcg_out_insn(s, 3612, ABS, vece, a0, a1); 2595d81bad24SRichard Henderson } else { 2596139c1837SPaolo Bonzini tcg_out_insn(s, 3617, ABS, is_q, vece, a0, a1); 2597d81bad24SRichard Henderson } 2598139c1837SPaolo Bonzini break; 2599139c1837SPaolo Bonzini case INDEX_op_and_vec: 2600139c1837SPaolo Bonzini if (const_args[2]) { 2601139c1837SPaolo Bonzini is_shimm1632(~a2, &cmode, &imm8); 2602139c1837SPaolo Bonzini if (a0 == a1) { 2603139c1837SPaolo Bonzini tcg_out_insn(s, 3606, BIC, is_q, a0, 0, cmode, imm8); 2604139c1837SPaolo Bonzini return; 2605139c1837SPaolo Bonzini } 2606139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MVNI, is_q, a0, 0, cmode, imm8); 2607139c1837SPaolo Bonzini a2 = a0; 2608139c1837SPaolo Bonzini } 2609139c1837SPaolo Bonzini tcg_out_insn(s, 3616, AND, is_q, 0, a0, a1, a2); 2610139c1837SPaolo Bonzini break; 2611139c1837SPaolo Bonzini case INDEX_op_or_vec: 2612139c1837SPaolo Bonzini if (const_args[2]) { 2613139c1837SPaolo Bonzini is_shimm1632(a2, &cmode, &imm8); 2614139c1837SPaolo Bonzini if (a0 == a1) { 2615139c1837SPaolo Bonzini tcg_out_insn(s, 3606, ORR, is_q, a0, 0, cmode, imm8); 2616139c1837SPaolo Bonzini return; 2617139c1837SPaolo Bonzini } 2618139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MOVI, is_q, a0, 0, cmode, imm8); 2619139c1837SPaolo Bonzini a2 = a0; 2620139c1837SPaolo Bonzini } 2621139c1837SPaolo Bonzini tcg_out_insn(s, 3616, ORR, is_q, 0, a0, a1, a2); 2622139c1837SPaolo Bonzini break; 2623139c1837SPaolo Bonzini case INDEX_op_andc_vec: 2624139c1837SPaolo Bonzini if (const_args[2]) { 2625139c1837SPaolo Bonzini is_shimm1632(a2, &cmode, &imm8); 2626139c1837SPaolo Bonzini if (a0 == a1) { 2627139c1837SPaolo Bonzini tcg_out_insn(s, 3606, BIC, is_q, a0, 0, cmode, imm8); 2628139c1837SPaolo Bonzini return; 2629139c1837SPaolo Bonzini } 2630139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MOVI, is_q, a0, 0, cmode, imm8); 2631139c1837SPaolo Bonzini a2 = a0; 2632139c1837SPaolo Bonzini } 2633139c1837SPaolo Bonzini tcg_out_insn(s, 3616, BIC, is_q, 0, a0, a1, a2); 2634139c1837SPaolo Bonzini break; 2635139c1837SPaolo Bonzini case INDEX_op_orc_vec: 2636139c1837SPaolo Bonzini if (const_args[2]) { 2637139c1837SPaolo Bonzini is_shimm1632(~a2, &cmode, &imm8); 2638139c1837SPaolo Bonzini if (a0 == a1) { 2639139c1837SPaolo Bonzini tcg_out_insn(s, 3606, ORR, is_q, a0, 0, cmode, imm8); 2640139c1837SPaolo Bonzini return; 2641139c1837SPaolo Bonzini } 2642139c1837SPaolo Bonzini tcg_out_insn(s, 3606, MVNI, is_q, a0, 0, cmode, imm8); 2643139c1837SPaolo Bonzini a2 = a0; 2644139c1837SPaolo Bonzini } 2645139c1837SPaolo Bonzini tcg_out_insn(s, 3616, ORN, is_q, 0, a0, a1, a2); 2646139c1837SPaolo Bonzini break; 2647139c1837SPaolo Bonzini case INDEX_op_xor_vec: 2648139c1837SPaolo Bonzini tcg_out_insn(s, 3616, EOR, is_q, 0, a0, a1, a2); 2649139c1837SPaolo Bonzini break; 2650139c1837SPaolo Bonzini case INDEX_op_ssadd_vec: 2651d81bad24SRichard Henderson if (is_scalar) { 2652d81bad24SRichard Henderson tcg_out_insn(s, 3611, SQADD, vece, a0, a1, a2); 2653d81bad24SRichard Henderson } else { 2654139c1837SPaolo Bonzini tcg_out_insn(s, 3616, SQADD, is_q, vece, a0, a1, a2); 2655d81bad24SRichard Henderson } 2656139c1837SPaolo Bonzini break; 2657139c1837SPaolo Bonzini case INDEX_op_sssub_vec: 2658d81bad24SRichard Henderson if (is_scalar) { 2659d81bad24SRichard Henderson tcg_out_insn(s, 3611, SQSUB, vece, a0, a1, a2); 2660d81bad24SRichard Henderson } else { 2661139c1837SPaolo Bonzini tcg_out_insn(s, 3616, SQSUB, is_q, vece, a0, a1, a2); 2662d81bad24SRichard Henderson } 2663139c1837SPaolo Bonzini break; 2664139c1837SPaolo Bonzini case INDEX_op_usadd_vec: 2665d81bad24SRichard Henderson if (is_scalar) { 2666d81bad24SRichard Henderson tcg_out_insn(s, 3611, UQADD, vece, a0, a1, a2); 2667d81bad24SRichard Henderson } else { 2668139c1837SPaolo Bonzini tcg_out_insn(s, 3616, UQADD, is_q, vece, a0, a1, a2); 2669d81bad24SRichard Henderson } 2670139c1837SPaolo Bonzini break; 2671139c1837SPaolo Bonzini case INDEX_op_ussub_vec: 2672d81bad24SRichard Henderson if (is_scalar) { 2673d81bad24SRichard Henderson tcg_out_insn(s, 3611, UQSUB, vece, a0, a1, a2); 2674d81bad24SRichard Henderson } else { 2675139c1837SPaolo Bonzini tcg_out_insn(s, 3616, UQSUB, is_q, vece, a0, a1, a2); 2676d81bad24SRichard Henderson } 2677139c1837SPaolo Bonzini break; 2678139c1837SPaolo Bonzini case INDEX_op_smax_vec: 2679139c1837SPaolo Bonzini tcg_out_insn(s, 3616, SMAX, is_q, vece, a0, a1, a2); 2680139c1837SPaolo Bonzini break; 2681139c1837SPaolo Bonzini case INDEX_op_smin_vec: 2682139c1837SPaolo Bonzini tcg_out_insn(s, 3616, SMIN, is_q, vece, a0, a1, a2); 2683139c1837SPaolo Bonzini break; 2684139c1837SPaolo Bonzini case INDEX_op_umax_vec: 2685139c1837SPaolo Bonzini tcg_out_insn(s, 3616, UMAX, is_q, vece, a0, a1, a2); 2686139c1837SPaolo Bonzini break; 2687139c1837SPaolo Bonzini case INDEX_op_umin_vec: 2688139c1837SPaolo Bonzini tcg_out_insn(s, 3616, UMIN, is_q, vece, a0, a1, a2); 2689139c1837SPaolo Bonzini break; 2690139c1837SPaolo Bonzini case INDEX_op_not_vec: 2691139c1837SPaolo Bonzini tcg_out_insn(s, 3617, NOT, is_q, 0, a0, a1); 2692139c1837SPaolo Bonzini break; 2693139c1837SPaolo Bonzini case INDEX_op_shli_vec: 2694d81bad24SRichard Henderson if (is_scalar) { 2695d81bad24SRichard Henderson tcg_out_insn(s, 3609, SHL, a0, a1, a2 + (8 << vece)); 2696d81bad24SRichard Henderson } else { 2697139c1837SPaolo Bonzini tcg_out_insn(s, 3614, SHL, is_q, a0, a1, a2 + (8 << vece)); 2698d81bad24SRichard Henderson } 2699139c1837SPaolo Bonzini break; 2700139c1837SPaolo Bonzini case INDEX_op_shri_vec: 2701d81bad24SRichard Henderson if (is_scalar) { 2702d81bad24SRichard Henderson tcg_out_insn(s, 3609, USHR, a0, a1, (16 << vece) - a2); 2703d81bad24SRichard Henderson } else { 2704139c1837SPaolo Bonzini tcg_out_insn(s, 3614, USHR, is_q, a0, a1, (16 << vece) - a2); 2705d81bad24SRichard Henderson } 2706139c1837SPaolo Bonzini break; 2707139c1837SPaolo Bonzini case INDEX_op_sari_vec: 2708d81bad24SRichard Henderson if (is_scalar) { 2709d81bad24SRichard Henderson tcg_out_insn(s, 3609, SSHR, a0, a1, (16 << vece) - a2); 2710d81bad24SRichard Henderson } else { 2711139c1837SPaolo Bonzini tcg_out_insn(s, 3614, SSHR, is_q, a0, a1, (16 << vece) - a2); 2712d81bad24SRichard Henderson } 2713139c1837SPaolo Bonzini break; 2714139c1837SPaolo Bonzini case INDEX_op_aa64_sli_vec: 2715d81bad24SRichard Henderson if (is_scalar) { 2716d81bad24SRichard Henderson tcg_out_insn(s, 3609, SLI, a0, a2, args[3] + (8 << vece)); 2717d81bad24SRichard Henderson } else { 2718139c1837SPaolo Bonzini tcg_out_insn(s, 3614, SLI, is_q, a0, a2, args[3] + (8 << vece)); 2719d81bad24SRichard Henderson } 2720139c1837SPaolo Bonzini break; 2721139c1837SPaolo Bonzini case INDEX_op_shlv_vec: 2722d81bad24SRichard Henderson if (is_scalar) { 2723d81bad24SRichard Henderson tcg_out_insn(s, 3611, USHL, vece, a0, a1, a2); 2724d81bad24SRichard Henderson } else { 2725139c1837SPaolo Bonzini tcg_out_insn(s, 3616, USHL, is_q, vece, a0, a1, a2); 2726d81bad24SRichard Henderson } 2727139c1837SPaolo Bonzini break; 2728139c1837SPaolo Bonzini case INDEX_op_aa64_sshl_vec: 2729d81bad24SRichard Henderson if (is_scalar) { 2730d81bad24SRichard Henderson tcg_out_insn(s, 3611, SSHL, vece, a0, a1, a2); 2731d81bad24SRichard Henderson } else { 2732139c1837SPaolo Bonzini tcg_out_insn(s, 3616, SSHL, is_q, vece, a0, a1, a2); 2733d81bad24SRichard Henderson } 2734139c1837SPaolo Bonzini break; 2735139c1837SPaolo Bonzini case INDEX_op_cmp_vec: 2736139c1837SPaolo Bonzini { 2737139c1837SPaolo Bonzini TCGCond cond = args[3]; 2738139c1837SPaolo Bonzini AArch64Insn insn; 2739139c1837SPaolo Bonzini 2740*b04574d4SRichard Henderson switch (cond) { 2741*b04574d4SRichard Henderson case TCG_COND_NE: 2742139c1837SPaolo Bonzini if (const_args[2]) { 2743d81bad24SRichard Henderson if (is_scalar) { 2744d81bad24SRichard Henderson tcg_out_insn(s, 3611, CMTST, vece, a0, a1, a1); 2745d81bad24SRichard Henderson } else { 2746139c1837SPaolo Bonzini tcg_out_insn(s, 3616, CMTST, is_q, vece, a0, a1, a1); 2747d81bad24SRichard Henderson } 2748d81bad24SRichard Henderson } else { 2749d81bad24SRichard Henderson if (is_scalar) { 2750d81bad24SRichard Henderson tcg_out_insn(s, 3611, CMEQ, vece, a0, a1, a2); 2751139c1837SPaolo Bonzini } else { 2752139c1837SPaolo Bonzini tcg_out_insn(s, 3616, CMEQ, is_q, vece, a0, a1, a2); 2753d81bad24SRichard Henderson } 2754139c1837SPaolo Bonzini tcg_out_insn(s, 3617, NOT, is_q, 0, a0, a0); 2755139c1837SPaolo Bonzini } 2756*b04574d4SRichard Henderson break; 2757*b04574d4SRichard Henderson 2758*b04574d4SRichard Henderson case TCG_COND_TSTNE: 2759*b04574d4SRichard Henderson case TCG_COND_TSTEQ: 2760*b04574d4SRichard Henderson if (const_args[2]) { 2761*b04574d4SRichard Henderson /* (x & 0) == 0 */ 2762*b04574d4SRichard Henderson tcg_out_dupi_vec(s, type, MO_8, a0, 2763*b04574d4SRichard Henderson -(cond == TCG_COND_TSTEQ)); 2764*b04574d4SRichard Henderson break; 2765*b04574d4SRichard Henderson } 2766*b04574d4SRichard Henderson if (is_scalar) { 2767*b04574d4SRichard Henderson tcg_out_insn(s, 3611, CMTST, vece, a0, a1, a2); 2768139c1837SPaolo Bonzini } else { 2769*b04574d4SRichard Henderson tcg_out_insn(s, 3616, CMTST, is_q, vece, a0, a1, a2); 2770*b04574d4SRichard Henderson } 2771*b04574d4SRichard Henderson if (cond == TCG_COND_TSTEQ) { 2772*b04574d4SRichard Henderson tcg_out_insn(s, 3617, NOT, is_q, 0, a0, a0); 2773*b04574d4SRichard Henderson } 2774*b04574d4SRichard Henderson break; 2775*b04574d4SRichard Henderson 2776*b04574d4SRichard Henderson default: 2777139c1837SPaolo Bonzini if (const_args[2]) { 2778d81bad24SRichard Henderson if (is_scalar) { 2779d81bad24SRichard Henderson insn = cmp0_scalar_insn[cond]; 2780d81bad24SRichard Henderson if (insn) { 2781d81bad24SRichard Henderson tcg_out_insn_3612(s, insn, vece, a0, a1); 2782d81bad24SRichard Henderson break; 2783d81bad24SRichard Henderson } 2784d81bad24SRichard Henderson } else { 2785d81bad24SRichard Henderson insn = cmp0_vec_insn[cond]; 2786139c1837SPaolo Bonzini if (insn) { 2787139c1837SPaolo Bonzini tcg_out_insn_3617(s, insn, is_q, vece, a0, a1); 2788139c1837SPaolo Bonzini break; 2789139c1837SPaolo Bonzini } 2790d81bad24SRichard Henderson } 2791d67bcbddSRichard Henderson tcg_out_dupi_vec(s, type, MO_8, TCG_VEC_TMP0, 0); 2792d67bcbddSRichard Henderson a2 = TCG_VEC_TMP0; 2793139c1837SPaolo Bonzini } 2794d81bad24SRichard Henderson if (is_scalar) { 2795d81bad24SRichard Henderson insn = cmp_scalar_insn[cond]; 2796139c1837SPaolo Bonzini if (insn == 0) { 2797139c1837SPaolo Bonzini TCGArg t; 2798139c1837SPaolo Bonzini t = a1, a1 = a2, a2 = t; 2799139c1837SPaolo Bonzini cond = tcg_swap_cond(cond); 2800d81bad24SRichard Henderson insn = cmp_scalar_insn[cond]; 2801d81bad24SRichard Henderson tcg_debug_assert(insn != 0); 2802d81bad24SRichard Henderson } 2803d81bad24SRichard Henderson tcg_out_insn_3611(s, insn, vece, a0, a1, a2); 2804d81bad24SRichard Henderson } else { 2805d81bad24SRichard Henderson insn = cmp_vec_insn[cond]; 2806d81bad24SRichard Henderson if (insn == 0) { 2807d81bad24SRichard Henderson TCGArg t; 2808d81bad24SRichard Henderson t = a1, a1 = a2, a2 = t; 2809d81bad24SRichard Henderson cond = tcg_swap_cond(cond); 2810d81bad24SRichard Henderson insn = cmp_vec_insn[cond]; 2811139c1837SPaolo Bonzini tcg_debug_assert(insn != 0); 2812139c1837SPaolo Bonzini } 2813139c1837SPaolo Bonzini tcg_out_insn_3616(s, insn, is_q, vece, a0, a1, a2); 2814139c1837SPaolo Bonzini } 2815*b04574d4SRichard Henderson break; 2816139c1837SPaolo Bonzini } 2817d81bad24SRichard Henderson } 2818139c1837SPaolo Bonzini break; 2819139c1837SPaolo Bonzini 2820139c1837SPaolo Bonzini case INDEX_op_bitsel_vec: 2821139c1837SPaolo Bonzini a3 = args[3]; 2822139c1837SPaolo Bonzini if (a0 == a3) { 2823139c1837SPaolo Bonzini tcg_out_insn(s, 3616, BIT, is_q, 0, a0, a2, a1); 2824139c1837SPaolo Bonzini } else if (a0 == a2) { 2825139c1837SPaolo Bonzini tcg_out_insn(s, 3616, BIF, is_q, 0, a0, a3, a1); 2826139c1837SPaolo Bonzini } else { 2827139c1837SPaolo Bonzini if (a0 != a1) { 2828139c1837SPaolo Bonzini tcg_out_mov(s, type, a0, a1); 2829139c1837SPaolo Bonzini } 2830139c1837SPaolo Bonzini tcg_out_insn(s, 3616, BSL, is_q, 0, a0, a2, a3); 2831139c1837SPaolo Bonzini } 2832139c1837SPaolo Bonzini break; 2833139c1837SPaolo Bonzini 2834139c1837SPaolo Bonzini case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov. */ 2835139c1837SPaolo Bonzini case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec. */ 2836139c1837SPaolo Bonzini default: 2837139c1837SPaolo Bonzini g_assert_not_reached(); 2838139c1837SPaolo Bonzini } 2839139c1837SPaolo Bonzini} 2840139c1837SPaolo Bonzini 2841139c1837SPaolo Bonziniint tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) 2842139c1837SPaolo Bonzini{ 2843139c1837SPaolo Bonzini switch (opc) { 2844139c1837SPaolo Bonzini case INDEX_op_add_vec: 2845139c1837SPaolo Bonzini case INDEX_op_sub_vec: 2846139c1837SPaolo Bonzini case INDEX_op_and_vec: 2847139c1837SPaolo Bonzini case INDEX_op_or_vec: 2848139c1837SPaolo Bonzini case INDEX_op_xor_vec: 2849139c1837SPaolo Bonzini case INDEX_op_andc_vec: 2850139c1837SPaolo Bonzini case INDEX_op_orc_vec: 2851139c1837SPaolo Bonzini case INDEX_op_neg_vec: 2852139c1837SPaolo Bonzini case INDEX_op_abs_vec: 2853139c1837SPaolo Bonzini case INDEX_op_not_vec: 2854139c1837SPaolo Bonzini case INDEX_op_cmp_vec: 2855139c1837SPaolo Bonzini case INDEX_op_shli_vec: 2856139c1837SPaolo Bonzini case INDEX_op_shri_vec: 2857139c1837SPaolo Bonzini case INDEX_op_sari_vec: 2858139c1837SPaolo Bonzini case INDEX_op_ssadd_vec: 2859139c1837SPaolo Bonzini case INDEX_op_sssub_vec: 2860139c1837SPaolo Bonzini case INDEX_op_usadd_vec: 2861139c1837SPaolo Bonzini case INDEX_op_ussub_vec: 2862139c1837SPaolo Bonzini case INDEX_op_shlv_vec: 2863139c1837SPaolo Bonzini case INDEX_op_bitsel_vec: 2864139c1837SPaolo Bonzini return 1; 2865139c1837SPaolo Bonzini case INDEX_op_rotli_vec: 2866139c1837SPaolo Bonzini case INDEX_op_shrv_vec: 2867139c1837SPaolo Bonzini case INDEX_op_sarv_vec: 2868139c1837SPaolo Bonzini case INDEX_op_rotlv_vec: 2869139c1837SPaolo Bonzini case INDEX_op_rotrv_vec: 2870139c1837SPaolo Bonzini return -1; 2871139c1837SPaolo Bonzini case INDEX_op_mul_vec: 2872139c1837SPaolo Bonzini case INDEX_op_smax_vec: 2873139c1837SPaolo Bonzini case INDEX_op_smin_vec: 2874139c1837SPaolo Bonzini case INDEX_op_umax_vec: 2875139c1837SPaolo Bonzini case INDEX_op_umin_vec: 2876139c1837SPaolo Bonzini return vece < MO_64; 2877139c1837SPaolo Bonzini 2878139c1837SPaolo Bonzini default: 2879139c1837SPaolo Bonzini return 0; 2880139c1837SPaolo Bonzini } 2881139c1837SPaolo Bonzini} 2882139c1837SPaolo Bonzini 2883139c1837SPaolo Bonzinivoid tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, 2884139c1837SPaolo Bonzini TCGArg a0, ...) 2885139c1837SPaolo Bonzini{ 2886139c1837SPaolo Bonzini va_list va; 288710061ffeSRichard Henderson TCGv_vec v0, v1, v2, t1, t2, c1; 2888139c1837SPaolo Bonzini TCGArg a2; 2889139c1837SPaolo Bonzini 2890139c1837SPaolo Bonzini va_start(va, a0); 2891139c1837SPaolo Bonzini v0 = temp_tcgv_vec(arg_temp(a0)); 2892139c1837SPaolo Bonzini v1 = temp_tcgv_vec(arg_temp(va_arg(va, TCGArg))); 2893139c1837SPaolo Bonzini a2 = va_arg(va, TCGArg); 28942dfa2f18SRichard Henderson va_end(va); 2895139c1837SPaolo Bonzini 2896139c1837SPaolo Bonzini switch (opc) { 2897139c1837SPaolo Bonzini case INDEX_op_rotli_vec: 2898139c1837SPaolo Bonzini t1 = tcg_temp_new_vec(type); 2899139c1837SPaolo Bonzini tcg_gen_shri_vec(vece, t1, v1, -a2 & ((8 << vece) - 1)); 2900139c1837SPaolo Bonzini vec_gen_4(INDEX_op_aa64_sli_vec, type, vece, 2901139c1837SPaolo Bonzini tcgv_vec_arg(v0), tcgv_vec_arg(t1), tcgv_vec_arg(v1), a2); 2902139c1837SPaolo Bonzini tcg_temp_free_vec(t1); 2903139c1837SPaolo Bonzini break; 2904139c1837SPaolo Bonzini 2905139c1837SPaolo Bonzini case INDEX_op_shrv_vec: 2906139c1837SPaolo Bonzini case INDEX_op_sarv_vec: 2907139c1837SPaolo Bonzini /* Right shifts are negative left shifts for AArch64. */ 29082dfa2f18SRichard Henderson v2 = temp_tcgv_vec(arg_temp(a2)); 2909139c1837SPaolo Bonzini t1 = tcg_temp_new_vec(type); 2910139c1837SPaolo Bonzini tcg_gen_neg_vec(vece, t1, v2); 2911139c1837SPaolo Bonzini opc = (opc == INDEX_op_shrv_vec 2912139c1837SPaolo Bonzini ? INDEX_op_shlv_vec : INDEX_op_aa64_sshl_vec); 2913139c1837SPaolo Bonzini vec_gen_3(opc, type, vece, tcgv_vec_arg(v0), 2914139c1837SPaolo Bonzini tcgv_vec_arg(v1), tcgv_vec_arg(t1)); 2915139c1837SPaolo Bonzini tcg_temp_free_vec(t1); 2916139c1837SPaolo Bonzini break; 2917139c1837SPaolo Bonzini 2918139c1837SPaolo Bonzini case INDEX_op_rotlv_vec: 29192dfa2f18SRichard Henderson v2 = temp_tcgv_vec(arg_temp(a2)); 2920139c1837SPaolo Bonzini t1 = tcg_temp_new_vec(type); 292110061ffeSRichard Henderson c1 = tcg_constant_vec(type, vece, 8 << vece); 292210061ffeSRichard Henderson tcg_gen_sub_vec(vece, t1, v2, c1); 2923139c1837SPaolo Bonzini /* Right shifts are negative left shifts for AArch64. */ 2924139c1837SPaolo Bonzini vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1), 2925139c1837SPaolo Bonzini tcgv_vec_arg(v1), tcgv_vec_arg(t1)); 2926139c1837SPaolo Bonzini vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(v0), 2927139c1837SPaolo Bonzini tcgv_vec_arg(v1), tcgv_vec_arg(v2)); 2928139c1837SPaolo Bonzini tcg_gen_or_vec(vece, v0, v0, t1); 2929139c1837SPaolo Bonzini tcg_temp_free_vec(t1); 2930139c1837SPaolo Bonzini break; 2931139c1837SPaolo Bonzini 2932139c1837SPaolo Bonzini case INDEX_op_rotrv_vec: 29332dfa2f18SRichard Henderson v2 = temp_tcgv_vec(arg_temp(a2)); 2934139c1837SPaolo Bonzini t1 = tcg_temp_new_vec(type); 2935139c1837SPaolo Bonzini t2 = tcg_temp_new_vec(type); 293610061ffeSRichard Henderson c1 = tcg_constant_vec(type, vece, 8 << vece); 2937139c1837SPaolo Bonzini tcg_gen_neg_vec(vece, t1, v2); 293810061ffeSRichard Henderson tcg_gen_sub_vec(vece, t2, c1, v2); 2939139c1837SPaolo Bonzini /* Right shifts are negative left shifts for AArch64. */ 2940139c1837SPaolo Bonzini vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1), 2941139c1837SPaolo Bonzini tcgv_vec_arg(v1), tcgv_vec_arg(t1)); 2942139c1837SPaolo Bonzini vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t2), 2943139c1837SPaolo Bonzini tcgv_vec_arg(v1), tcgv_vec_arg(t2)); 2944139c1837SPaolo Bonzini tcg_gen_or_vec(vece, v0, t1, t2); 2945139c1837SPaolo Bonzini tcg_temp_free_vec(t1); 2946139c1837SPaolo Bonzini tcg_temp_free_vec(t2); 2947139c1837SPaolo Bonzini break; 2948139c1837SPaolo Bonzini 2949139c1837SPaolo Bonzini default: 2950139c1837SPaolo Bonzini g_assert_not_reached(); 2951139c1837SPaolo Bonzini } 2952139c1837SPaolo Bonzini} 2953139c1837SPaolo Bonzini 295439e7522bSRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) 2955139c1837SPaolo Bonzini{ 2956139c1837SPaolo Bonzini switch (op) { 2957139c1837SPaolo Bonzini case INDEX_op_goto_ptr: 295839e7522bSRichard Henderson return C_O0_I1(r); 2959139c1837SPaolo Bonzini 2960139c1837SPaolo Bonzini case INDEX_op_ld8u_i32: 2961139c1837SPaolo Bonzini case INDEX_op_ld8s_i32: 2962139c1837SPaolo Bonzini case INDEX_op_ld16u_i32: 2963139c1837SPaolo Bonzini case INDEX_op_ld16s_i32: 2964139c1837SPaolo Bonzini case INDEX_op_ld_i32: 2965139c1837SPaolo Bonzini case INDEX_op_ld8u_i64: 2966139c1837SPaolo Bonzini case INDEX_op_ld8s_i64: 2967139c1837SPaolo Bonzini case INDEX_op_ld16u_i64: 2968139c1837SPaolo Bonzini case INDEX_op_ld16s_i64: 2969139c1837SPaolo Bonzini case INDEX_op_ld32u_i64: 2970139c1837SPaolo Bonzini case INDEX_op_ld32s_i64: 2971139c1837SPaolo Bonzini case INDEX_op_ld_i64: 2972139c1837SPaolo Bonzini case INDEX_op_neg_i32: 2973139c1837SPaolo Bonzini case INDEX_op_neg_i64: 2974139c1837SPaolo Bonzini case INDEX_op_not_i32: 2975139c1837SPaolo Bonzini case INDEX_op_not_i64: 2976139c1837SPaolo Bonzini case INDEX_op_bswap16_i32: 2977139c1837SPaolo Bonzini case INDEX_op_bswap32_i32: 2978139c1837SPaolo Bonzini case INDEX_op_bswap16_i64: 2979139c1837SPaolo Bonzini case INDEX_op_bswap32_i64: 2980139c1837SPaolo Bonzini case INDEX_op_bswap64_i64: 2981139c1837SPaolo Bonzini case INDEX_op_ext8s_i32: 2982139c1837SPaolo Bonzini case INDEX_op_ext16s_i32: 2983139c1837SPaolo Bonzini case INDEX_op_ext8u_i32: 2984139c1837SPaolo Bonzini case INDEX_op_ext16u_i32: 2985139c1837SPaolo Bonzini case INDEX_op_ext8s_i64: 2986139c1837SPaolo Bonzini case INDEX_op_ext16s_i64: 2987139c1837SPaolo Bonzini case INDEX_op_ext32s_i64: 2988139c1837SPaolo Bonzini case INDEX_op_ext8u_i64: 2989139c1837SPaolo Bonzini case INDEX_op_ext16u_i64: 2990139c1837SPaolo Bonzini case INDEX_op_ext32u_i64: 2991139c1837SPaolo Bonzini case INDEX_op_ext_i32_i64: 2992139c1837SPaolo Bonzini case INDEX_op_extu_i32_i64: 2993139c1837SPaolo Bonzini case INDEX_op_extract_i32: 2994139c1837SPaolo Bonzini case INDEX_op_extract_i64: 2995139c1837SPaolo Bonzini case INDEX_op_sextract_i32: 2996139c1837SPaolo Bonzini case INDEX_op_sextract_i64: 299739e7522bSRichard Henderson return C_O1_I1(r, r); 2998139c1837SPaolo Bonzini 2999139c1837SPaolo Bonzini case INDEX_op_st8_i32: 3000139c1837SPaolo Bonzini case INDEX_op_st16_i32: 3001139c1837SPaolo Bonzini case INDEX_op_st_i32: 3002139c1837SPaolo Bonzini case INDEX_op_st8_i64: 3003139c1837SPaolo Bonzini case INDEX_op_st16_i64: 3004139c1837SPaolo Bonzini case INDEX_op_st32_i64: 3005139c1837SPaolo Bonzini case INDEX_op_st_i64: 300639e7522bSRichard Henderson return C_O0_I2(rZ, r); 3007139c1837SPaolo Bonzini 3008139c1837SPaolo Bonzini case INDEX_op_add_i32: 3009139c1837SPaolo Bonzini case INDEX_op_add_i64: 3010139c1837SPaolo Bonzini case INDEX_op_sub_i32: 3011139c1837SPaolo Bonzini case INDEX_op_sub_i64: 3012339adf2fSRichard Henderson return C_O1_I2(r, r, rA); 3013339adf2fSRichard Henderson 3014139c1837SPaolo Bonzini case INDEX_op_setcond_i32: 3015139c1837SPaolo Bonzini case INDEX_op_setcond_i64: 3016f58a7deaSRichard Henderson case INDEX_op_negsetcond_i32: 3017f58a7deaSRichard Henderson case INDEX_op_negsetcond_i64: 3018339adf2fSRichard Henderson return C_O1_I2(r, r, rC); 3019139c1837SPaolo Bonzini 3020139c1837SPaolo Bonzini case INDEX_op_mul_i32: 3021139c1837SPaolo Bonzini case INDEX_op_mul_i64: 3022139c1837SPaolo Bonzini case INDEX_op_div_i32: 3023139c1837SPaolo Bonzini case INDEX_op_div_i64: 3024139c1837SPaolo Bonzini case INDEX_op_divu_i32: 3025139c1837SPaolo Bonzini case INDEX_op_divu_i64: 3026139c1837SPaolo Bonzini case INDEX_op_rem_i32: 3027139c1837SPaolo Bonzini case INDEX_op_rem_i64: 3028139c1837SPaolo Bonzini case INDEX_op_remu_i32: 3029139c1837SPaolo Bonzini case INDEX_op_remu_i64: 3030139c1837SPaolo Bonzini case INDEX_op_muluh_i64: 3031139c1837SPaolo Bonzini case INDEX_op_mulsh_i64: 303239e7522bSRichard Henderson return C_O1_I2(r, r, r); 3033139c1837SPaolo Bonzini 3034139c1837SPaolo Bonzini case INDEX_op_and_i32: 3035139c1837SPaolo Bonzini case INDEX_op_and_i64: 3036139c1837SPaolo Bonzini case INDEX_op_or_i32: 3037139c1837SPaolo Bonzini case INDEX_op_or_i64: 3038139c1837SPaolo Bonzini case INDEX_op_xor_i32: 3039139c1837SPaolo Bonzini case INDEX_op_xor_i64: 3040139c1837SPaolo Bonzini case INDEX_op_andc_i32: 3041139c1837SPaolo Bonzini case INDEX_op_andc_i64: 3042139c1837SPaolo Bonzini case INDEX_op_orc_i32: 3043139c1837SPaolo Bonzini case INDEX_op_orc_i64: 3044139c1837SPaolo Bonzini case INDEX_op_eqv_i32: 3045139c1837SPaolo Bonzini case INDEX_op_eqv_i64: 304639e7522bSRichard Henderson return C_O1_I2(r, r, rL); 3047139c1837SPaolo Bonzini 3048139c1837SPaolo Bonzini case INDEX_op_shl_i32: 3049139c1837SPaolo Bonzini case INDEX_op_shr_i32: 3050139c1837SPaolo Bonzini case INDEX_op_sar_i32: 3051139c1837SPaolo Bonzini case INDEX_op_rotl_i32: 3052139c1837SPaolo Bonzini case INDEX_op_rotr_i32: 3053139c1837SPaolo Bonzini case INDEX_op_shl_i64: 3054139c1837SPaolo Bonzini case INDEX_op_shr_i64: 3055139c1837SPaolo Bonzini case INDEX_op_sar_i64: 3056139c1837SPaolo Bonzini case INDEX_op_rotl_i64: 3057139c1837SPaolo Bonzini case INDEX_op_rotr_i64: 305839e7522bSRichard Henderson return C_O1_I2(r, r, ri); 3059139c1837SPaolo Bonzini 3060139c1837SPaolo Bonzini case INDEX_op_clz_i32: 3061139c1837SPaolo Bonzini case INDEX_op_ctz_i32: 3062139c1837SPaolo Bonzini case INDEX_op_clz_i64: 3063139c1837SPaolo Bonzini case INDEX_op_ctz_i64: 306439e7522bSRichard Henderson return C_O1_I2(r, r, rAL); 3065139c1837SPaolo Bonzini 3066139c1837SPaolo Bonzini case INDEX_op_brcond_i32: 3067139c1837SPaolo Bonzini case INDEX_op_brcond_i64: 3068339adf2fSRichard Henderson return C_O0_I2(r, rC); 3069139c1837SPaolo Bonzini 3070139c1837SPaolo Bonzini case INDEX_op_movcond_i32: 3071139c1837SPaolo Bonzini case INDEX_op_movcond_i64: 3072339adf2fSRichard Henderson return C_O1_I4(r, r, rC, rZ, rZ); 3073139c1837SPaolo Bonzini 3074fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32: 3075fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32: 3076fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64: 3077fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64: 3078285a691fSRichard Henderson return C_O1_I1(r, r); 3079929124ecSRichard Henderson case INDEX_op_qemu_ld_a32_i128: 3080929124ecSRichard Henderson case INDEX_op_qemu_ld_a64_i128: 3081929124ecSRichard Henderson return C_O2_I1(r, r, r); 3082fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32: 3083fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32: 3084fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64: 3085fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64: 3086285a691fSRichard Henderson return C_O0_I2(rZ, r); 3087929124ecSRichard Henderson case INDEX_op_qemu_st_a32_i128: 3088929124ecSRichard Henderson case INDEX_op_qemu_st_a64_i128: 3089929124ecSRichard Henderson return C_O0_I3(rZ, rZ, r); 3090139c1837SPaolo Bonzini 3091139c1837SPaolo Bonzini case INDEX_op_deposit_i32: 3092139c1837SPaolo Bonzini case INDEX_op_deposit_i64: 309339e7522bSRichard Henderson return C_O1_I2(r, 0, rZ); 3094139c1837SPaolo Bonzini 3095139c1837SPaolo Bonzini case INDEX_op_extract2_i32: 3096139c1837SPaolo Bonzini case INDEX_op_extract2_i64: 309739e7522bSRichard Henderson return C_O1_I2(r, rZ, rZ); 3098139c1837SPaolo Bonzini 3099139c1837SPaolo Bonzini case INDEX_op_add2_i32: 3100139c1837SPaolo Bonzini case INDEX_op_add2_i64: 3101139c1837SPaolo Bonzini case INDEX_op_sub2_i32: 3102139c1837SPaolo Bonzini case INDEX_op_sub2_i64: 310339e7522bSRichard Henderson return C_O2_I4(r, r, rZ, rZ, rA, rMZ); 3104139c1837SPaolo Bonzini 3105139c1837SPaolo Bonzini case INDEX_op_add_vec: 3106139c1837SPaolo Bonzini case INDEX_op_sub_vec: 3107139c1837SPaolo Bonzini case INDEX_op_mul_vec: 3108139c1837SPaolo Bonzini case INDEX_op_xor_vec: 3109139c1837SPaolo Bonzini case INDEX_op_ssadd_vec: 3110139c1837SPaolo Bonzini case INDEX_op_sssub_vec: 3111139c1837SPaolo Bonzini case INDEX_op_usadd_vec: 3112139c1837SPaolo Bonzini case INDEX_op_ussub_vec: 3113139c1837SPaolo Bonzini case INDEX_op_smax_vec: 3114139c1837SPaolo Bonzini case INDEX_op_smin_vec: 3115139c1837SPaolo Bonzini case INDEX_op_umax_vec: 3116139c1837SPaolo Bonzini case INDEX_op_umin_vec: 3117139c1837SPaolo Bonzini case INDEX_op_shlv_vec: 3118139c1837SPaolo Bonzini case INDEX_op_shrv_vec: 3119139c1837SPaolo Bonzini case INDEX_op_sarv_vec: 3120139c1837SPaolo Bonzini case INDEX_op_aa64_sshl_vec: 312139e7522bSRichard Henderson return C_O1_I2(w, w, w); 3122139c1837SPaolo Bonzini case INDEX_op_not_vec: 3123139c1837SPaolo Bonzini case INDEX_op_neg_vec: 3124139c1837SPaolo Bonzini case INDEX_op_abs_vec: 3125139c1837SPaolo Bonzini case INDEX_op_shli_vec: 3126139c1837SPaolo Bonzini case INDEX_op_shri_vec: 3127139c1837SPaolo Bonzini case INDEX_op_sari_vec: 312839e7522bSRichard Henderson return C_O1_I1(w, w); 3129139c1837SPaolo Bonzini case INDEX_op_ld_vec: 3130139c1837SPaolo Bonzini case INDEX_op_dupm_vec: 313139e7522bSRichard Henderson return C_O1_I1(w, r); 313239e7522bSRichard Henderson case INDEX_op_st_vec: 313339e7522bSRichard Henderson return C_O0_I2(w, r); 3134139c1837SPaolo Bonzini case INDEX_op_dup_vec: 313539e7522bSRichard Henderson return C_O1_I1(w, wr); 3136139c1837SPaolo Bonzini case INDEX_op_or_vec: 3137139c1837SPaolo Bonzini case INDEX_op_andc_vec: 313839e7522bSRichard Henderson return C_O1_I2(w, w, wO); 3139139c1837SPaolo Bonzini case INDEX_op_and_vec: 3140139c1837SPaolo Bonzini case INDEX_op_orc_vec: 314139e7522bSRichard Henderson return C_O1_I2(w, w, wN); 3142139c1837SPaolo Bonzini case INDEX_op_cmp_vec: 314339e7522bSRichard Henderson return C_O1_I2(w, w, wZ); 3144139c1837SPaolo Bonzini case INDEX_op_bitsel_vec: 314539e7522bSRichard Henderson return C_O1_I3(w, w, w, w); 3146139c1837SPaolo Bonzini case INDEX_op_aa64_sli_vec: 314739e7522bSRichard Henderson return C_O1_I2(w, 0, w); 3148139c1837SPaolo Bonzini 3149139c1837SPaolo Bonzini default: 315039e7522bSRichard Henderson g_assert_not_reached(); 3151139c1837SPaolo Bonzini } 3152139c1837SPaolo Bonzini} 3153139c1837SPaolo Bonzini 3154139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s) 3155139c1837SPaolo Bonzini{ 3156139c1837SPaolo Bonzini tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffffu; 3157139c1837SPaolo Bonzini tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffffu; 3158139c1837SPaolo Bonzini tcg_target_available_regs[TCG_TYPE_V64] = 0xffffffff00000000ull; 3159139c1837SPaolo Bonzini tcg_target_available_regs[TCG_TYPE_V128] = 0xffffffff00000000ull; 3160139c1837SPaolo Bonzini 3161139c1837SPaolo Bonzini tcg_target_call_clobber_regs = -1ull; 3162139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X19); 3163139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X20); 3164139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X21); 3165139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X22); 3166139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X23); 3167139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X24); 3168139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X25); 3169139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X26); 3170139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X27); 3171139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X28); 3172139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X29); 3173139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V8); 3174139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V9); 3175139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V10); 3176139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V11); 3177139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V12); 3178139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V13); 3179139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V14); 3180139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V15); 3181139c1837SPaolo Bonzini 3182139c1837SPaolo Bonzini s->reserved_regs = 0; 3183139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); 3184139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP); 3185139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */ 3186d67bcbddSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0); 3187da4d0d95SRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); 3188da4d0d95SRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); 3189d67bcbddSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_VEC_TMP0); 3190139c1837SPaolo Bonzini} 3191139c1837SPaolo Bonzini 3192139c1837SPaolo Bonzini/* Saving pairs: (X19, X20) .. (X27, X28), (X29(fp), X30(lr)). */ 3193139c1837SPaolo Bonzini#define PUSH_SIZE ((30 - 19 + 1) * 8) 3194139c1837SPaolo Bonzini 3195139c1837SPaolo Bonzini#define FRAME_SIZE \ 3196139c1837SPaolo Bonzini ((PUSH_SIZE \ 3197139c1837SPaolo Bonzini + TCG_STATIC_CALL_ARGS_SIZE \ 3198139c1837SPaolo Bonzini + CPU_TEMP_BUF_NLONGS * sizeof(long) \ 3199139c1837SPaolo Bonzini + TCG_TARGET_STACK_ALIGN - 1) \ 3200139c1837SPaolo Bonzini & ~(TCG_TARGET_STACK_ALIGN - 1)) 3201139c1837SPaolo Bonzini 3202139c1837SPaolo Bonzini/* We're expecting a 2 byte uleb128 encoded value. */ 3203139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14)); 3204139c1837SPaolo Bonzini 3205139c1837SPaolo Bonzini/* We're expecting to use a single ADDI insn. */ 3206139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE - PUSH_SIZE > 0xfff); 3207139c1837SPaolo Bonzini 3208139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s) 3209139c1837SPaolo Bonzini{ 3210139c1837SPaolo Bonzini TCGReg r; 3211139c1837SPaolo Bonzini 32125826a0dbSRichard Henderson tcg_out_bti(s, BTI_C); 32135826a0dbSRichard Henderson 3214139c1837SPaolo Bonzini /* Push (FP, LR) and allocate space for all saved registers. */ 3215139c1837SPaolo Bonzini tcg_out_insn(s, 3314, STP, TCG_REG_FP, TCG_REG_LR, 3216139c1837SPaolo Bonzini TCG_REG_SP, -PUSH_SIZE, 1, 1); 3217139c1837SPaolo Bonzini 3218139c1837SPaolo Bonzini /* Set up frame pointer for canonical unwinding. */ 3219139c1837SPaolo Bonzini tcg_out_movr_sp(s, TCG_TYPE_I64, TCG_REG_FP, TCG_REG_SP); 3220139c1837SPaolo Bonzini 3221139c1837SPaolo Bonzini /* Store callee-preserved regs x19..x28. */ 3222139c1837SPaolo Bonzini for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) { 3223139c1837SPaolo Bonzini int ofs = (r - TCG_REG_X19 + 2) * 8; 3224139c1837SPaolo Bonzini tcg_out_insn(s, 3314, STP, r, r + 1, TCG_REG_SP, ofs, 1, 0); 3225139c1837SPaolo Bonzini } 3226139c1837SPaolo Bonzini 3227139c1837SPaolo Bonzini /* Make stack space for TCG locals. */ 3228139c1837SPaolo Bonzini tcg_out_insn(s, 3401, SUBI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP, 3229139c1837SPaolo Bonzini FRAME_SIZE - PUSH_SIZE); 3230139c1837SPaolo Bonzini 3231139c1837SPaolo Bonzini /* Inform TCG about how to find TCG locals with register, offset, size. */ 3232139c1837SPaolo Bonzini tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, 3233139c1837SPaolo Bonzini CPU_TEMP_BUF_NLONGS * sizeof(long)); 3234139c1837SPaolo Bonzini 3235e2b7a40dSRichard Henderson if (!tcg_use_softmmu) { 323652533157SRichard Henderson /* 323752533157SRichard Henderson * Note that XZR cannot be encoded in the address base register slot, 32384daad8d9SMichael Tokarev * as that actually encodes SP. Depending on the guest, we may need 323952533157SRichard Henderson * to zero-extend the guest address via the address index register slot, 324052533157SRichard Henderson * therefore we need to load even a zero guest base into a register. 324152533157SRichard Henderson */ 3242139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, guest_base); 3243139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE); 3244e2b7a40dSRichard Henderson } 3245139c1837SPaolo Bonzini 3246139c1837SPaolo Bonzini tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); 3247139c1837SPaolo Bonzini tcg_out_insn(s, 3207, BR, tcg_target_call_iarg_regs[1]); 3248139c1837SPaolo Bonzini 3249139c1837SPaolo Bonzini /* 3250139c1837SPaolo Bonzini * Return path for goto_ptr. Set return value to 0, a-la exit_tb, 3251139c1837SPaolo Bonzini * and fall through to the rest of the epilogue. 3252139c1837SPaolo Bonzini */ 3253c8bc1168SRichard Henderson tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr); 32545826a0dbSRichard Henderson tcg_out_bti(s, BTI_J); 3255139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_X0, 0); 3256139c1837SPaolo Bonzini 3257139c1837SPaolo Bonzini /* TB epilogue */ 3258ffba3eb3SRichard Henderson tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr); 32595826a0dbSRichard Henderson tcg_out_bti(s, BTI_J); 3260139c1837SPaolo Bonzini 3261139c1837SPaolo Bonzini /* Remove TCG locals stack space. */ 3262139c1837SPaolo Bonzini tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP, 3263139c1837SPaolo Bonzini FRAME_SIZE - PUSH_SIZE); 3264139c1837SPaolo Bonzini 3265139c1837SPaolo Bonzini /* Restore registers x19..x28. */ 3266139c1837SPaolo Bonzini for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) { 3267139c1837SPaolo Bonzini int ofs = (r - TCG_REG_X19 + 2) * 8; 3268139c1837SPaolo Bonzini tcg_out_insn(s, 3314, LDP, r, r + 1, TCG_REG_SP, ofs, 1, 0); 3269139c1837SPaolo Bonzini } 3270139c1837SPaolo Bonzini 3271139c1837SPaolo Bonzini /* Pop (FP, LR), restore SP to previous frame. */ 3272139c1837SPaolo Bonzini tcg_out_insn(s, 3314, LDP, TCG_REG_FP, TCG_REG_LR, 3273139c1837SPaolo Bonzini TCG_REG_SP, PUSH_SIZE, 0, 1); 3274139c1837SPaolo Bonzini tcg_out_insn(s, 3207, RET, TCG_REG_LR); 3275139c1837SPaolo Bonzini} 3276139c1837SPaolo Bonzini 32779358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s) 32789358fbbfSRichard Henderson{ 32795826a0dbSRichard Henderson tcg_out_bti(s, BTI_J); 32809358fbbfSRichard Henderson} 32819358fbbfSRichard Henderson 3282139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count) 3283139c1837SPaolo Bonzini{ 3284139c1837SPaolo Bonzini int i; 3285139c1837SPaolo Bonzini for (i = 0; i < count; ++i) { 3286139c1837SPaolo Bonzini p[i] = NOP; 3287139c1837SPaolo Bonzini } 3288139c1837SPaolo Bonzini} 3289139c1837SPaolo Bonzini 3290139c1837SPaolo Bonzinitypedef struct { 3291139c1837SPaolo Bonzini DebugFrameHeader h; 3292139c1837SPaolo Bonzini uint8_t fde_def_cfa[4]; 3293139c1837SPaolo Bonzini uint8_t fde_reg_ofs[24]; 3294139c1837SPaolo Bonzini} DebugFrame; 3295139c1837SPaolo Bonzini 3296139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_AARCH64 3297139c1837SPaolo Bonzini 3298139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = { 3299139c1837SPaolo Bonzini .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */ 3300139c1837SPaolo Bonzini .h.cie.id = -1, 3301139c1837SPaolo Bonzini .h.cie.version = 1, 3302139c1837SPaolo Bonzini .h.cie.code_align = 1, 3303139c1837SPaolo Bonzini .h.cie.data_align = 0x78, /* sleb128 -8 */ 3304139c1837SPaolo Bonzini .h.cie.return_column = TCG_REG_LR, 3305139c1837SPaolo Bonzini 3306139c1837SPaolo Bonzini /* Total FDE size does not include the "len" member. */ 3307139c1837SPaolo Bonzini .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), 3308139c1837SPaolo Bonzini 3309139c1837SPaolo Bonzini .fde_def_cfa = { 3310139c1837SPaolo Bonzini 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ 3311139c1837SPaolo Bonzini (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ 3312139c1837SPaolo Bonzini (FRAME_SIZE >> 7) 3313139c1837SPaolo Bonzini }, 3314139c1837SPaolo Bonzini .fde_reg_ofs = { 3315139c1837SPaolo Bonzini 0x80 + 28, 1, /* DW_CFA_offset, x28, -8 */ 3316139c1837SPaolo Bonzini 0x80 + 27, 2, /* DW_CFA_offset, x27, -16 */ 3317139c1837SPaolo Bonzini 0x80 + 26, 3, /* DW_CFA_offset, x26, -24 */ 3318139c1837SPaolo Bonzini 0x80 + 25, 4, /* DW_CFA_offset, x25, -32 */ 3319139c1837SPaolo Bonzini 0x80 + 24, 5, /* DW_CFA_offset, x24, -40 */ 3320139c1837SPaolo Bonzini 0x80 + 23, 6, /* DW_CFA_offset, x23, -48 */ 3321139c1837SPaolo Bonzini 0x80 + 22, 7, /* DW_CFA_offset, x22, -56 */ 3322139c1837SPaolo Bonzini 0x80 + 21, 8, /* DW_CFA_offset, x21, -64 */ 3323139c1837SPaolo Bonzini 0x80 + 20, 9, /* DW_CFA_offset, x20, -72 */ 3324139c1837SPaolo Bonzini 0x80 + 19, 10, /* DW_CFA_offset, x1p, -80 */ 3325139c1837SPaolo Bonzini 0x80 + 30, 11, /* DW_CFA_offset, lr, -88 */ 3326139c1837SPaolo Bonzini 0x80 + 29, 12, /* DW_CFA_offset, fp, -96 */ 3327139c1837SPaolo Bonzini } 3328139c1837SPaolo Bonzini}; 3329139c1837SPaolo Bonzini 3330755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size) 3331139c1837SPaolo Bonzini{ 3332139c1837SPaolo Bonzini tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); 3333139c1837SPaolo Bonzini} 3334