1/* 2 * Tiny Code Generator for QEMU 3 * 4 * Copyright (c) 2021 WANG Xuerui <git@xen0n.name> 5 * 6 * Based on tcg/riscv/tcg-target.c.inc 7 * 8 * Copyright (c) 2018 SiFive, Inc 9 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org> 10 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net> 11 * Copyright (c) 2008 Fabrice Bellard 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining a copy 14 * of this software and associated documentation files (the "Software"), to deal 15 * in the Software without restriction, including without limitation the rights 16 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 * copies of the Software, and to permit persons to whom the Software is 18 * furnished to do so, subject to the following conditions: 19 * 20 * The above copyright notice and this permission notice shall be included in 21 * all copies or substantial portions of the Software. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 * THE SOFTWARE. 30 */ 31 32#include "../tcg-ldst.c.inc" 33 34#ifdef CONFIG_DEBUG_TCG 35static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { 36 "zero", 37 "ra", 38 "tp", 39 "sp", 40 "a0", 41 "a1", 42 "a2", 43 "a3", 44 "a4", 45 "a5", 46 "a6", 47 "a7", 48 "t0", 49 "t1", 50 "t2", 51 "t3", 52 "t4", 53 "t5", 54 "t6", 55 "t7", 56 "t8", 57 "r21", /* reserved in the LP64* ABI, hence no ABI name */ 58 "s9", 59 "s0", 60 "s1", 61 "s2", 62 "s3", 63 "s4", 64 "s5", 65 "s6", 66 "s7", 67 "s8" 68}; 69#endif 70 71static const int tcg_target_reg_alloc_order[] = { 72 /* Registers preserved across calls */ 73 /* TCG_REG_S0 reserved for TCG_AREG0 */ 74 TCG_REG_S1, 75 TCG_REG_S2, 76 TCG_REG_S3, 77 TCG_REG_S4, 78 TCG_REG_S5, 79 TCG_REG_S6, 80 TCG_REG_S7, 81 TCG_REG_S8, 82 TCG_REG_S9, 83 84 /* Registers (potentially) clobbered across calls */ 85 TCG_REG_T0, 86 TCG_REG_T1, 87 TCG_REG_T2, 88 TCG_REG_T3, 89 TCG_REG_T4, 90 TCG_REG_T5, 91 TCG_REG_T6, 92 TCG_REG_T7, 93 TCG_REG_T8, 94 95 /* Argument registers, opposite order of allocation. */ 96 TCG_REG_A7, 97 TCG_REG_A6, 98 TCG_REG_A5, 99 TCG_REG_A4, 100 TCG_REG_A3, 101 TCG_REG_A2, 102 TCG_REG_A1, 103 TCG_REG_A0, 104}; 105 106static const int tcg_target_call_iarg_regs[] = { 107 TCG_REG_A0, 108 TCG_REG_A1, 109 TCG_REG_A2, 110 TCG_REG_A3, 111 TCG_REG_A4, 112 TCG_REG_A5, 113 TCG_REG_A6, 114 TCG_REG_A7, 115}; 116 117static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot) 118{ 119 tcg_debug_assert(kind == TCG_CALL_RET_NORMAL); 120 tcg_debug_assert(slot >= 0 && slot <= 1); 121 return TCG_REG_A0 + slot; 122} 123 124#ifndef CONFIG_SOFTMMU 125#define USE_GUEST_BASE (guest_base != 0) 126#define TCG_GUEST_BASE_REG TCG_REG_S1 127#endif 128 129#define TCG_CT_CONST_ZERO 0x100 130#define TCG_CT_CONST_S12 0x200 131#define TCG_CT_CONST_S32 0x400 132#define TCG_CT_CONST_U12 0x800 133#define TCG_CT_CONST_C12 0x1000 134#define TCG_CT_CONST_WSZ 0x2000 135 136#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32) 137/* 138 * For softmmu, we need to avoid conflicts with the first 5 139 * argument registers to call the helper. Some of these are 140 * also used for the tlb lookup. 141 */ 142#ifdef CONFIG_SOFTMMU 143#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_A0, 5) 144#else 145#define SOFTMMU_RESERVE_REGS 0 146#endif 147 148 149static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len) 150{ 151 return sextract64(val, pos, len); 152} 153 154/* test if a constant matches the constraint */ 155static bool tcg_target_const_match(int64_t val, TCGType type, int ct) 156{ 157 if (ct & TCG_CT_CONST) { 158 return true; 159 } 160 if ((ct & TCG_CT_CONST_ZERO) && val == 0) { 161 return true; 162 } 163 if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) { 164 return true; 165 } 166 if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) { 167 return true; 168 } 169 if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) { 170 return true; 171 } 172 if ((ct & TCG_CT_CONST_C12) && ~val >= 0 && ~val <= 0xfff) { 173 return true; 174 } 175 if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) { 176 return true; 177 } 178 return false; 179} 180 181/* 182 * Relocations 183 */ 184 185/* 186 * Relocation records defined in LoongArch ELF psABI v1.00 is way too 187 * complicated; a whopping stack machine is needed to stuff the fields, at 188 * the very least one SOP_PUSH and one SOP_POP (of the correct format) are 189 * needed. 190 * 191 * Hence, define our own simpler relocation types. Numbers are chosen as to 192 * not collide with potential future additions to the true ELF relocation 193 * type enum. 194 */ 195 196/* Field Sk16, shifted right by 2; suitable for conditional jumps */ 197#define R_LOONGARCH_BR_SK16 256 198/* Field Sd10k16, shifted right by 2; suitable for B and BL */ 199#define R_LOONGARCH_BR_SD10K16 257 200 201static bool reloc_br_sk16(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 202{ 203 const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 204 intptr_t offset = (intptr_t)target - (intptr_t)src_rx; 205 206 tcg_debug_assert((offset & 3) == 0); 207 offset >>= 2; 208 if (offset == sextreg(offset, 0, 16)) { 209 *src_rw = deposit64(*src_rw, 10, 16, offset); 210 return true; 211 } 212 213 return false; 214} 215 216static bool reloc_br_sd10k16(tcg_insn_unit *src_rw, 217 const tcg_insn_unit *target) 218{ 219 const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 220 intptr_t offset = (intptr_t)target - (intptr_t)src_rx; 221 222 tcg_debug_assert((offset & 3) == 0); 223 offset >>= 2; 224 if (offset == sextreg(offset, 0, 26)) { 225 *src_rw = deposit64(*src_rw, 0, 10, offset >> 16); /* slot d10 */ 226 *src_rw = deposit64(*src_rw, 10, 16, offset); /* slot k16 */ 227 return true; 228 } 229 230 return false; 231} 232 233static bool patch_reloc(tcg_insn_unit *code_ptr, int type, 234 intptr_t value, intptr_t addend) 235{ 236 tcg_debug_assert(addend == 0); 237 switch (type) { 238 case R_LOONGARCH_BR_SK16: 239 return reloc_br_sk16(code_ptr, (tcg_insn_unit *)value); 240 case R_LOONGARCH_BR_SD10K16: 241 return reloc_br_sd10k16(code_ptr, (tcg_insn_unit *)value); 242 default: 243 g_assert_not_reached(); 244 } 245} 246 247#include "tcg-insn-defs.c.inc" 248 249/* 250 * TCG intrinsics 251 */ 252 253static void tcg_out_mb(TCGContext *s, TCGArg a0) 254{ 255 /* Baseline LoongArch only has the full barrier, unfortunately. */ 256 tcg_out_opc_dbar(s, 0); 257} 258 259static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 260{ 261 if (ret == arg) { 262 return true; 263 } 264 switch (type) { 265 case TCG_TYPE_I32: 266 case TCG_TYPE_I64: 267 /* 268 * Conventional register-register move used in LoongArch is 269 * `or dst, src, zero`. 270 */ 271 tcg_out_opc_or(s, ret, arg, TCG_REG_ZERO); 272 break; 273 default: 274 g_assert_not_reached(); 275 } 276 return true; 277} 278 279/* Loads a 32-bit immediate into rd, sign-extended. */ 280static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val) 281{ 282 tcg_target_long lo = sextreg(val, 0, 12); 283 tcg_target_long hi12 = sextreg(val, 12, 20); 284 285 /* Single-instruction cases. */ 286 if (hi12 == 0) { 287 /* val fits in uimm12: ori rd, zero, val */ 288 tcg_out_opc_ori(s, rd, TCG_REG_ZERO, val); 289 return; 290 } 291 if (hi12 == sextreg(lo, 12, 20)) { 292 /* val fits in simm12: addi.w rd, zero, val */ 293 tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val); 294 return; 295 } 296 297 /* High bits must be set; load with lu12i.w + optional ori. */ 298 tcg_out_opc_lu12i_w(s, rd, hi12); 299 if (lo != 0) { 300 tcg_out_opc_ori(s, rd, rd, lo & 0xfff); 301 } 302} 303 304static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, 305 tcg_target_long val) 306{ 307 /* 308 * LoongArch conventionally loads 64-bit immediates in at most 4 steps, 309 * with dedicated instructions for filling the respective bitfields 310 * below: 311 * 312 * 6 5 4 3 313 * 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 314 * +-----------------------+---------------------------------------+... 315 * | hi52 | hi32 | 316 * +-----------------------+---------------------------------------+... 317 * 3 2 1 318 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 319 * ...+-------------------------------------+-------------------------+ 320 * | hi12 | lo | 321 * ...+-------------------------------------+-------------------------+ 322 * 323 * Check if val belong to one of the several fast cases, before falling 324 * back to the slow path. 325 */ 326 327 intptr_t pc_offset; 328 tcg_target_long val_lo, val_hi, pc_hi, offset_hi; 329 tcg_target_long hi12, hi32, hi52; 330 331 /* Value fits in signed i32. */ 332 if (type == TCG_TYPE_I32 || val == (int32_t)val) { 333 tcg_out_movi_i32(s, rd, val); 334 return; 335 } 336 337 /* PC-relative cases. */ 338 pc_offset = tcg_pcrel_diff(s, (void *)val); 339 if (pc_offset == sextreg(pc_offset, 0, 22) && (pc_offset & 3) == 0) { 340 /* Single pcaddu2i. */ 341 tcg_out_opc_pcaddu2i(s, rd, pc_offset >> 2); 342 return; 343 } 344 345 if (pc_offset == (int32_t)pc_offset) { 346 /* Offset within 32 bits; load with pcalau12i + ori. */ 347 val_lo = sextreg(val, 0, 12); 348 val_hi = val >> 12; 349 pc_hi = (val - pc_offset) >> 12; 350 offset_hi = val_hi - pc_hi; 351 352 tcg_debug_assert(offset_hi == sextreg(offset_hi, 0, 20)); 353 tcg_out_opc_pcalau12i(s, rd, offset_hi); 354 if (val_lo != 0) { 355 tcg_out_opc_ori(s, rd, rd, val_lo & 0xfff); 356 } 357 return; 358 } 359 360 hi12 = sextreg(val, 12, 20); 361 hi32 = sextreg(val, 32, 20); 362 hi52 = sextreg(val, 52, 12); 363 364 /* Single cu52i.d case. */ 365 if ((hi52 != 0) && (ctz64(val) >= 52)) { 366 tcg_out_opc_cu52i_d(s, rd, TCG_REG_ZERO, hi52); 367 return; 368 } 369 370 /* Slow path. Initialize the low 32 bits, then concat high bits. */ 371 tcg_out_movi_i32(s, rd, val); 372 373 /* Load hi32 and hi52 explicitly when they are unexpected values. */ 374 if (hi32 != sextreg(hi12, 20, 20)) { 375 tcg_out_opc_cu32i_d(s, rd, hi32); 376 } 377 378 if (hi52 != sextreg(hi32, 20, 12)) { 379 tcg_out_opc_cu52i_d(s, rd, rd, hi52); 380 } 381} 382 383static void tcg_out_addi(TCGContext *s, TCGType type, TCGReg rd, 384 TCGReg rs, tcg_target_long imm) 385{ 386 tcg_target_long lo12 = sextreg(imm, 0, 12); 387 tcg_target_long hi16 = sextreg(imm - lo12, 16, 16); 388 389 /* 390 * Note that there's a hole in between hi16 and lo12: 391 * 392 * 3 2 1 0 393 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 394 * ...+-------------------------------+-------+-----------------------+ 395 * | hi16 | | lo12 | 396 * ...+-------------------------------+-------+-----------------------+ 397 * 398 * For bits within that hole, it's more efficient to use LU12I and ADD. 399 */ 400 if (imm == (hi16 << 16) + lo12) { 401 if (hi16) { 402 tcg_out_opc_addu16i_d(s, rd, rs, hi16); 403 rs = rd; 404 } 405 if (type == TCG_TYPE_I32) { 406 tcg_out_opc_addi_w(s, rd, rs, lo12); 407 } else if (lo12) { 408 tcg_out_opc_addi_d(s, rd, rs, lo12); 409 } else { 410 tcg_out_mov(s, type, rd, rs); 411 } 412 } else { 413 tcg_out_movi(s, type, TCG_REG_TMP0, imm); 414 if (type == TCG_TYPE_I32) { 415 tcg_out_opc_add_w(s, rd, rs, TCG_REG_TMP0); 416 } else { 417 tcg_out_opc_add_d(s, rd, rs, TCG_REG_TMP0); 418 } 419 } 420} 421 422static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs, 423 tcg_target_long imm) 424{ 425 /* This function is only used for passing structs by reference. */ 426 g_assert_not_reached(); 427} 428 429static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg) 430{ 431 tcg_out_opc_andi(s, ret, arg, 0xff); 432} 433 434static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) 435{ 436 tcg_out_opc_bstrpick_w(s, ret, arg, 0, 15); 437} 438 439static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) 440{ 441 tcg_out_opc_bstrpick_d(s, ret, arg, 0, 31); 442} 443 444static void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) 445{ 446 tcg_out_opc_sext_b(s, ret, arg); 447} 448 449static void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg) 450{ 451 tcg_out_opc_sext_h(s, ret, arg); 452} 453 454static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) 455{ 456 tcg_out_opc_addi_w(s, ret, arg, 0); 457} 458 459static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc, 460 TCGReg a0, TCGReg a1, TCGReg a2, 461 bool c2, bool is_32bit) 462{ 463 if (c2) { 464 /* 465 * Fast path: semantics already satisfied due to constraint and 466 * insn behavior, single instruction is enough. 467 */ 468 tcg_debug_assert(a2 == (is_32bit ? 32 : 64)); 469 /* all clz/ctz insns belong to DJ-format */ 470 tcg_out32(s, encode_dj_insn(opc, a0, a1)); 471 return; 472 } 473 474 tcg_out32(s, encode_dj_insn(opc, TCG_REG_TMP0, a1)); 475 /* a0 = a1 ? REG_TMP0 : a2 */ 476 tcg_out_opc_maskeqz(s, TCG_REG_TMP0, TCG_REG_TMP0, a1); 477 tcg_out_opc_masknez(s, a0, a2, a1); 478 tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0); 479} 480 481#define SETCOND_INV TCG_TARGET_NB_REGS 482#define SETCOND_NEZ (SETCOND_INV << 1) 483#define SETCOND_FLAGS (SETCOND_INV | SETCOND_NEZ) 484 485static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret, 486 TCGReg arg1, tcg_target_long arg2, bool c2) 487{ 488 int flags = 0; 489 490 switch (cond) { 491 case TCG_COND_EQ: /* -> NE */ 492 case TCG_COND_GE: /* -> LT */ 493 case TCG_COND_GEU: /* -> LTU */ 494 case TCG_COND_GT: /* -> LE */ 495 case TCG_COND_GTU: /* -> LEU */ 496 cond = tcg_invert_cond(cond); 497 flags ^= SETCOND_INV; 498 break; 499 default: 500 break; 501 } 502 503 switch (cond) { 504 case TCG_COND_LE: 505 case TCG_COND_LEU: 506 /* 507 * If we have a constant input, the most efficient way to implement 508 * LE is by adding 1 and using LT. Watch out for wrap around for LEU. 509 * We don't need to care for this for LE because the constant input 510 * is still constrained to int32_t, and INT32_MAX+1 is representable 511 * in the 64-bit temporary register. 512 */ 513 if (c2) { 514 if (cond == TCG_COND_LEU) { 515 /* unsigned <= -1 is true */ 516 if (arg2 == -1) { 517 tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV)); 518 return ret; 519 } 520 cond = TCG_COND_LTU; 521 } else { 522 cond = TCG_COND_LT; 523 } 524 arg2 += 1; 525 } else { 526 TCGReg tmp = arg2; 527 arg2 = arg1; 528 arg1 = tmp; 529 cond = tcg_swap_cond(cond); /* LE -> GE */ 530 cond = tcg_invert_cond(cond); /* GE -> LT */ 531 flags ^= SETCOND_INV; 532 } 533 break; 534 default: 535 break; 536 } 537 538 switch (cond) { 539 case TCG_COND_NE: 540 flags |= SETCOND_NEZ; 541 if (!c2) { 542 tcg_out_opc_xor(s, ret, arg1, arg2); 543 } else if (arg2 == 0) { 544 ret = arg1; 545 } else if (arg2 >= 0 && arg2 <= 0xfff) { 546 tcg_out_opc_xori(s, ret, arg1, arg2); 547 } else { 548 tcg_out_addi(s, TCG_TYPE_REG, ret, arg1, -arg2); 549 } 550 break; 551 552 case TCG_COND_LT: 553 case TCG_COND_LTU: 554 if (c2) { 555 if (arg2 >= -0x800 && arg2 <= 0x7ff) { 556 if (cond == TCG_COND_LT) { 557 tcg_out_opc_slti(s, ret, arg1, arg2); 558 } else { 559 tcg_out_opc_sltui(s, ret, arg1, arg2); 560 } 561 break; 562 } 563 tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2); 564 arg2 = TCG_REG_TMP0; 565 } 566 if (cond == TCG_COND_LT) { 567 tcg_out_opc_slt(s, ret, arg1, arg2); 568 } else { 569 tcg_out_opc_sltu(s, ret, arg1, arg2); 570 } 571 break; 572 573 default: 574 g_assert_not_reached(); 575 break; 576 } 577 578 return ret | flags; 579} 580 581static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, 582 TCGReg arg1, tcg_target_long arg2, bool c2) 583{ 584 int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2); 585 586 if (tmpflags != ret) { 587 TCGReg tmp = tmpflags & ~SETCOND_FLAGS; 588 589 switch (tmpflags & SETCOND_FLAGS) { 590 case SETCOND_INV: 591 /* Intermediate result is boolean: simply invert. */ 592 tcg_out_opc_xori(s, ret, tmp, 1); 593 break; 594 case SETCOND_NEZ: 595 /* Intermediate result is zero/non-zero: test != 0. */ 596 tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp); 597 break; 598 case SETCOND_NEZ | SETCOND_INV: 599 /* Intermediate result is zero/non-zero: test == 0. */ 600 tcg_out_opc_sltui(s, ret, tmp, 1); 601 break; 602 default: 603 g_assert_not_reached(); 604 } 605 } 606} 607 608static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, 609 TCGReg c1, tcg_target_long c2, bool const2, 610 TCGReg v1, TCGReg v2) 611{ 612 int tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, c1, c2, const2); 613 TCGReg t; 614 615 /* Standardize the test below to t != 0. */ 616 if (tmpflags & SETCOND_INV) { 617 t = v1, v1 = v2, v2 = t; 618 } 619 620 t = tmpflags & ~SETCOND_FLAGS; 621 if (v1 == TCG_REG_ZERO) { 622 tcg_out_opc_masknez(s, ret, v2, t); 623 } else if (v2 == TCG_REG_ZERO) { 624 tcg_out_opc_maskeqz(s, ret, v1, t); 625 } else { 626 tcg_out_opc_masknez(s, TCG_REG_TMP2, v2, t); /* t ? 0 : v2 */ 627 tcg_out_opc_maskeqz(s, TCG_REG_TMP1, v1, t); /* t ? v1 : 0 */ 628 tcg_out_opc_or(s, ret, TCG_REG_TMP1, TCG_REG_TMP2); 629 } 630} 631 632/* 633 * Branch helpers 634 */ 635 636static const struct { 637 LoongArchInsn op; 638 bool swap; 639} tcg_brcond_to_loongarch[] = { 640 [TCG_COND_EQ] = { OPC_BEQ, false }, 641 [TCG_COND_NE] = { OPC_BNE, false }, 642 [TCG_COND_LT] = { OPC_BGT, true }, 643 [TCG_COND_GE] = { OPC_BLE, true }, 644 [TCG_COND_LE] = { OPC_BLE, false }, 645 [TCG_COND_GT] = { OPC_BGT, false }, 646 [TCG_COND_LTU] = { OPC_BGTU, true }, 647 [TCG_COND_GEU] = { OPC_BLEU, true }, 648 [TCG_COND_LEU] = { OPC_BLEU, false }, 649 [TCG_COND_GTU] = { OPC_BGTU, false } 650}; 651 652static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, 653 TCGReg arg2, TCGLabel *l) 654{ 655 LoongArchInsn op = tcg_brcond_to_loongarch[cond].op; 656 657 tcg_debug_assert(op != 0); 658 659 if (tcg_brcond_to_loongarch[cond].swap) { 660 TCGReg t = arg1; 661 arg1 = arg2; 662 arg2 = t; 663 } 664 665 /* all conditional branch insns belong to DJSk16-format */ 666 tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SK16, l, 0); 667 tcg_out32(s, encode_djsk16_insn(op, arg1, arg2, 0)); 668} 669 670static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) 671{ 672 TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; 673 ptrdiff_t offset = tcg_pcrel_diff(s, arg); 674 675 tcg_debug_assert((offset & 3) == 0); 676 if (offset == sextreg(offset, 0, 28)) { 677 /* short jump: +/- 256MiB */ 678 if (tail) { 679 tcg_out_opc_b(s, offset >> 2); 680 } else { 681 tcg_out_opc_bl(s, offset >> 2); 682 } 683 } else if (offset == sextreg(offset, 0, 38)) { 684 /* long jump: +/- 256GiB */ 685 tcg_target_long lo = sextreg(offset, 0, 18); 686 tcg_target_long hi = offset - lo; 687 tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, hi >> 18); 688 tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2); 689 } else { 690 /* far jump: 64-bit */ 691 tcg_target_long lo = sextreg((tcg_target_long)arg, 0, 18); 692 tcg_target_long hi = (tcg_target_long)arg - lo; 693 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, hi); 694 tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2); 695 } 696} 697 698static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg, 699 const TCGHelperInfo *info) 700{ 701 tcg_out_call_int(s, arg, false); 702} 703 704/* 705 * Load/store helpers 706 */ 707 708static void tcg_out_ldst(TCGContext *s, LoongArchInsn opc, TCGReg data, 709 TCGReg addr, intptr_t offset) 710{ 711 intptr_t imm12 = sextreg(offset, 0, 12); 712 713 if (offset != imm12) { 714 intptr_t diff = tcg_pcrel_diff(s, (void *)offset); 715 716 if (addr == TCG_REG_ZERO && diff == (int32_t)diff) { 717 imm12 = sextreg(diff, 0, 12); 718 tcg_out_opc_pcaddu12i(s, TCG_REG_TMP2, (diff - imm12) >> 12); 719 } else { 720 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12); 721 if (addr != TCG_REG_ZERO) { 722 tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, addr); 723 } 724 } 725 addr = TCG_REG_TMP2; 726 } 727 728 switch (opc) { 729 case OPC_LD_B: 730 case OPC_LD_BU: 731 case OPC_LD_H: 732 case OPC_LD_HU: 733 case OPC_LD_W: 734 case OPC_LD_WU: 735 case OPC_LD_D: 736 case OPC_ST_B: 737 case OPC_ST_H: 738 case OPC_ST_W: 739 case OPC_ST_D: 740 tcg_out32(s, encode_djsk12_insn(opc, data, addr, imm12)); 741 break; 742 default: 743 g_assert_not_reached(); 744 } 745} 746 747static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, 748 TCGReg arg1, intptr_t arg2) 749{ 750 bool is_32bit = type == TCG_TYPE_I32; 751 tcg_out_ldst(s, is_32bit ? OPC_LD_W : OPC_LD_D, arg, arg1, arg2); 752} 753 754static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, 755 TCGReg arg1, intptr_t arg2) 756{ 757 bool is_32bit = type == TCG_TYPE_I32; 758 tcg_out_ldst(s, is_32bit ? OPC_ST_W : OPC_ST_D, arg, arg1, arg2); 759} 760 761static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, 762 TCGReg base, intptr_t ofs) 763{ 764 if (val == 0) { 765 tcg_out_st(s, type, TCG_REG_ZERO, base, ofs); 766 return true; 767 } 768 return false; 769} 770 771/* 772 * Load/store helpers for SoftMMU, and qemu_ld/st implementations 773 */ 774 775#if defined(CONFIG_SOFTMMU) 776/* 777 * helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, 778 * MemOpIdx oi, uintptr_t ra) 779 */ 780static void * const qemu_ld_helpers[4] = { 781 [MO_8] = helper_ret_ldub_mmu, 782 [MO_16] = helper_le_lduw_mmu, 783 [MO_32] = helper_le_ldul_mmu, 784 [MO_64] = helper_le_ldq_mmu, 785}; 786 787/* 788 * helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, 789 * uintxx_t val, MemOpIdx oi, 790 * uintptr_t ra) 791 */ 792static void * const qemu_st_helpers[4] = { 793 [MO_8] = helper_ret_stb_mmu, 794 [MO_16] = helper_le_stw_mmu, 795 [MO_32] = helper_le_stl_mmu, 796 [MO_64] = helper_le_stq_mmu, 797}; 798 799/* We expect to use a 12-bit negative offset from ENV. */ 800QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0); 801QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11)); 802 803static bool tcg_out_goto(TCGContext *s, const tcg_insn_unit *target) 804{ 805 tcg_out_opc_b(s, 0); 806 return reloc_br_sd10k16(s->code_ptr - 1, target); 807} 808 809/* 810 * Emits common code for TLB addend lookup, that eventually loads the 811 * addend in TCG_REG_TMP2. 812 */ 813static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl, MemOpIdx oi, 814 tcg_insn_unit **label_ptr, bool is_load) 815{ 816 MemOp opc = get_memop(oi); 817 unsigned s_bits = opc & MO_SIZE; 818 unsigned a_bits = get_alignment_bits(opc); 819 tcg_target_long compare_mask; 820 int mem_index = get_mmuidx(oi); 821 int fast_ofs = TLB_MASK_TABLE_OFS(mem_index); 822 int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask); 823 int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table); 824 825 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs); 826 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs); 827 828 tcg_out_opc_srli_d(s, TCG_REG_TMP2, addrl, 829 TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 830 tcg_out_opc_and(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0); 831 tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1); 832 833 /* Load the tlb comparator and the addend. */ 834 tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP0, TCG_REG_TMP2, 835 is_load ? offsetof(CPUTLBEntry, addr_read) 836 : offsetof(CPUTLBEntry, addr_write)); 837 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2, 838 offsetof(CPUTLBEntry, addend)); 839 840 /* We don't support unaligned accesses. */ 841 if (a_bits < s_bits) { 842 a_bits = s_bits; 843 } 844 /* Clear the non-page, non-alignment bits from the address. */ 845 compare_mask = (tcg_target_long)TARGET_PAGE_MASK | ((1 << a_bits) - 1); 846 tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_TMP1, compare_mask); 847 tcg_out_opc_and(s, TCG_REG_TMP1, TCG_REG_TMP1, addrl); 848 849 /* Compare masked address with the TLB entry. */ 850 label_ptr[0] = s->code_ptr; 851 tcg_out_opc_bne(s, TCG_REG_TMP0, TCG_REG_TMP1, 0); 852 853 /* TLB Hit - addend in TCG_REG_TMP2, ready for use. */ 854} 855 856static void add_qemu_ldst_label(TCGContext *s, int is_ld, MemOpIdx oi, 857 TCGType type, 858 TCGReg datalo, TCGReg addrlo, 859 void *raddr, tcg_insn_unit **label_ptr) 860{ 861 TCGLabelQemuLdst *label = new_ldst_label(s); 862 863 label->is_ld = is_ld; 864 label->oi = oi; 865 label->type = type; 866 label->datalo_reg = datalo; 867 label->datahi_reg = 0; /* unused */ 868 label->addrlo_reg = addrlo; 869 label->addrhi_reg = 0; /* unused */ 870 label->raddr = tcg_splitwx_to_rx(raddr); 871 label->label_ptr[0] = label_ptr[0]; 872} 873 874static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 875{ 876 MemOpIdx oi = l->oi; 877 MemOp opc = get_memop(oi); 878 MemOp size = opc & MO_SIZE; 879 TCGType type = l->type; 880 881 /* resolve label address */ 882 if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { 883 return false; 884 } 885 886 /* call load helper */ 887 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); 888 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg); 889 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A2, oi); 890 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, (tcg_target_long)l->raddr); 891 892 tcg_out_call_int(s, qemu_ld_helpers[size], false); 893 894 switch (opc & MO_SSIZE) { 895 case MO_SB: 896 tcg_out_ext8s(s, l->datalo_reg, TCG_REG_A0); 897 break; 898 case MO_SW: 899 tcg_out_ext16s(s, l->datalo_reg, TCG_REG_A0); 900 break; 901 case MO_SL: 902 tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0); 903 break; 904 case MO_UL: 905 if (type == TCG_TYPE_I32) { 906 /* MO_UL loads of i32 should be sign-extended too */ 907 tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0); 908 break; 909 } 910 /* fallthrough */ 911 default: 912 tcg_out_mov(s, type, l->datalo_reg, TCG_REG_A0); 913 break; 914 } 915 916 return tcg_out_goto(s, l->raddr); 917} 918 919static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 920{ 921 MemOpIdx oi = l->oi; 922 MemOp opc = get_memop(oi); 923 MemOp size = opc & MO_SIZE; 924 925 /* resolve label address */ 926 if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { 927 return false; 928 } 929 930 /* call store helper */ 931 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); 932 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg); 933 switch (size) { 934 case MO_8: 935 tcg_out_ext8u(s, TCG_REG_A2, l->datalo_reg); 936 break; 937 case MO_16: 938 tcg_out_ext16u(s, TCG_REG_A2, l->datalo_reg); 939 break; 940 case MO_32: 941 tcg_out_ext32u(s, TCG_REG_A2, l->datalo_reg); 942 break; 943 case MO_64: 944 tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_A2, l->datalo_reg); 945 break; 946 default: 947 g_assert_not_reached(); 948 break; 949 } 950 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, oi); 951 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A4, (tcg_target_long)l->raddr); 952 953 tcg_out_call_int(s, qemu_st_helpers[size], false); 954 955 return tcg_out_goto(s, l->raddr); 956} 957#else 958 959/* 960 * Alignment helpers for user-mode emulation 961 */ 962 963static void tcg_out_test_alignment(TCGContext *s, bool is_ld, TCGReg addr_reg, 964 unsigned a_bits) 965{ 966 TCGLabelQemuLdst *l = new_ldst_label(s); 967 968 l->is_ld = is_ld; 969 l->addrlo_reg = addr_reg; 970 971 /* 972 * Without micro-architecture details, we don't know which of bstrpick or 973 * andi is faster, so use bstrpick as it's not constrained by imm field 974 * width. (Not to say alignments >= 2^12 are going to happen any time 975 * soon, though) 976 */ 977 tcg_out_opc_bstrpick_d(s, TCG_REG_TMP1, addr_reg, 0, a_bits - 1); 978 979 l->label_ptr[0] = s->code_ptr; 980 tcg_out_opc_bne(s, TCG_REG_TMP1, TCG_REG_ZERO, 0); 981 982 l->raddr = tcg_splitwx_to_rx(s->code_ptr); 983} 984 985static bool tcg_out_fail_alignment(TCGContext *s, TCGLabelQemuLdst *l) 986{ 987 /* resolve label address */ 988 if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { 989 return false; 990 } 991 992 tcg_out_mov(s, TCG_TYPE_TL, TCG_REG_A1, l->addrlo_reg); 993 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); 994 995 /* tail call, with the return address back inline. */ 996 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (uintptr_t)l->raddr); 997 tcg_out_call_int(s, (const void *)(l->is_ld ? helper_unaligned_ld 998 : helper_unaligned_st), true); 999 return true; 1000} 1001 1002static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1003{ 1004 return tcg_out_fail_alignment(s, l); 1005} 1006 1007static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1008{ 1009 return tcg_out_fail_alignment(s, l); 1010} 1011 1012#endif /* CONFIG_SOFTMMU */ 1013 1014/* 1015 * `ext32u` the address register into the temp register given, 1016 * if target is 32-bit, no-op otherwise. 1017 * 1018 * Returns the address register ready for use with TLB addend. 1019 */ 1020static TCGReg tcg_out_zext_addr_if_32_bit(TCGContext *s, 1021 TCGReg addr, TCGReg tmp) 1022{ 1023 if (TARGET_LONG_BITS == 32) { 1024 tcg_out_ext32u(s, tmp, addr); 1025 return tmp; 1026 } 1027 return addr; 1028} 1029 1030static void tcg_out_qemu_ld_indexed(TCGContext *s, TCGReg rd, TCGReg rj, 1031 TCGReg rk, MemOp opc, TCGType type) 1032{ 1033 /* Byte swapping is left to middle-end expansion. */ 1034 tcg_debug_assert((opc & MO_BSWAP) == 0); 1035 1036 switch (opc & MO_SSIZE) { 1037 case MO_UB: 1038 tcg_out_opc_ldx_bu(s, rd, rj, rk); 1039 break; 1040 case MO_SB: 1041 tcg_out_opc_ldx_b(s, rd, rj, rk); 1042 break; 1043 case MO_UW: 1044 tcg_out_opc_ldx_hu(s, rd, rj, rk); 1045 break; 1046 case MO_SW: 1047 tcg_out_opc_ldx_h(s, rd, rj, rk); 1048 break; 1049 case MO_UL: 1050 if (type == TCG_TYPE_I64) { 1051 tcg_out_opc_ldx_wu(s, rd, rj, rk); 1052 break; 1053 } 1054 /* fallthrough */ 1055 case MO_SL: 1056 tcg_out_opc_ldx_w(s, rd, rj, rk); 1057 break; 1058 case MO_UQ: 1059 tcg_out_opc_ldx_d(s, rd, rj, rk); 1060 break; 1061 default: 1062 g_assert_not_reached(); 1063 } 1064} 1065 1066static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGType type) 1067{ 1068 TCGReg addr_regl; 1069 TCGReg data_regl; 1070 MemOpIdx oi; 1071 MemOp opc; 1072#if defined(CONFIG_SOFTMMU) 1073 tcg_insn_unit *label_ptr[1]; 1074#else 1075 unsigned a_bits; 1076#endif 1077 TCGReg base; 1078 1079 data_regl = *args++; 1080 addr_regl = *args++; 1081 oi = *args++; 1082 opc = get_memop(oi); 1083 1084#if defined(CONFIG_SOFTMMU) 1085 tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 1); 1086 base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); 1087 tcg_out_qemu_ld_indexed(s, data_regl, base, TCG_REG_TMP2, opc, type); 1088 add_qemu_ldst_label(s, 1, oi, type, 1089 data_regl, addr_regl, 1090 s->code_ptr, label_ptr); 1091#else 1092 a_bits = get_alignment_bits(opc); 1093 if (a_bits) { 1094 tcg_out_test_alignment(s, true, addr_regl, a_bits); 1095 } 1096 base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); 1097 TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; 1098 tcg_out_qemu_ld_indexed(s, data_regl, base, guest_base_reg, opc, type); 1099#endif 1100} 1101 1102static void tcg_out_qemu_st_indexed(TCGContext *s, TCGReg data, 1103 TCGReg rj, TCGReg rk, MemOp opc) 1104{ 1105 /* Byte swapping is left to middle-end expansion. */ 1106 tcg_debug_assert((opc & MO_BSWAP) == 0); 1107 1108 switch (opc & MO_SIZE) { 1109 case MO_8: 1110 tcg_out_opc_stx_b(s, data, rj, rk); 1111 break; 1112 case MO_16: 1113 tcg_out_opc_stx_h(s, data, rj, rk); 1114 break; 1115 case MO_32: 1116 tcg_out_opc_stx_w(s, data, rj, rk); 1117 break; 1118 case MO_64: 1119 tcg_out_opc_stx_d(s, data, rj, rk); 1120 break; 1121 default: 1122 g_assert_not_reached(); 1123 } 1124} 1125 1126static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args) 1127{ 1128 TCGReg addr_regl; 1129 TCGReg data_regl; 1130 MemOpIdx oi; 1131 MemOp opc; 1132#if defined(CONFIG_SOFTMMU) 1133 tcg_insn_unit *label_ptr[1]; 1134#else 1135 unsigned a_bits; 1136#endif 1137 TCGReg base; 1138 1139 data_regl = *args++; 1140 addr_regl = *args++; 1141 oi = *args++; 1142 opc = get_memop(oi); 1143 1144#if defined(CONFIG_SOFTMMU) 1145 tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 0); 1146 base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); 1147 tcg_out_qemu_st_indexed(s, data_regl, base, TCG_REG_TMP2, opc); 1148 add_qemu_ldst_label(s, 0, oi, 1149 0, /* type param is unused for stores */ 1150 data_regl, addr_regl, 1151 s->code_ptr, label_ptr); 1152#else 1153 a_bits = get_alignment_bits(opc); 1154 if (a_bits) { 1155 tcg_out_test_alignment(s, false, addr_regl, a_bits); 1156 } 1157 base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); 1158 TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; 1159 tcg_out_qemu_st_indexed(s, data_regl, base, guest_base_reg, opc); 1160#endif 1161} 1162 1163/* 1164 * Entry-points 1165 */ 1166 1167static const tcg_insn_unit *tb_ret_addr; 1168 1169static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) 1170{ 1171 /* Reuse the zeroing that exists for goto_ptr. */ 1172 if (a0 == 0) { 1173 tcg_out_call_int(s, tcg_code_gen_epilogue, true); 1174 } else { 1175 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); 1176 tcg_out_call_int(s, tb_ret_addr, true); 1177 } 1178} 1179 1180static void tcg_out_goto_tb(TCGContext *s, int which) 1181{ 1182 /* 1183 * Direct branch, or load indirect address, to be patched 1184 * by tb_target_set_jmp_target. Check indirect load offset 1185 * in range early, regardless of direct branch distance, 1186 * via assert within tcg_out_opc_pcaddu2i. 1187 */ 1188 uintptr_t i_addr = get_jmp_target_addr(s, which); 1189 intptr_t i_disp = tcg_pcrel_diff(s, (void *)i_addr); 1190 1191 set_jmp_insn_offset(s, which); 1192 tcg_out_opc_pcaddu2i(s, TCG_REG_TMP0, i_disp >> 2); 1193 1194 /* Finish the load and indirect branch. */ 1195 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_TMP0, 0); 1196 tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0); 1197 set_jmp_reset_offset(s, which); 1198} 1199 1200void tb_target_set_jmp_target(const TranslationBlock *tb, int n, 1201 uintptr_t jmp_rx, uintptr_t jmp_rw) 1202{ 1203 uintptr_t d_addr = tb->jmp_target_addr[n]; 1204 ptrdiff_t d_disp = (ptrdiff_t)(d_addr - jmp_rx) >> 2; 1205 tcg_insn_unit insn; 1206 1207 /* Either directly branch, or load slot address for indirect branch. */ 1208 if (d_disp == sextreg(d_disp, 0, 26)) { 1209 insn = encode_sd10k16_insn(OPC_B, d_disp); 1210 } else { 1211 uintptr_t i_addr = (uintptr_t)&tb->jmp_target_addr[n]; 1212 intptr_t i_disp = i_addr - jmp_rx; 1213 insn = encode_dsj20_insn(OPC_PCADDU2I, TCG_REG_TMP0, i_disp >> 2); 1214 } 1215 1216 qatomic_set((tcg_insn_unit *)jmp_rw, insn); 1217 flush_idcache_range(jmp_rx, jmp_rw, 4); 1218} 1219 1220static void tcg_out_op(TCGContext *s, TCGOpcode opc, 1221 const TCGArg args[TCG_MAX_OP_ARGS], 1222 const int const_args[TCG_MAX_OP_ARGS]) 1223{ 1224 TCGArg a0 = args[0]; 1225 TCGArg a1 = args[1]; 1226 TCGArg a2 = args[2]; 1227 int c2 = const_args[2]; 1228 1229 switch (opc) { 1230 case INDEX_op_mb: 1231 tcg_out_mb(s, a0); 1232 break; 1233 1234 case INDEX_op_goto_ptr: 1235 tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0); 1236 break; 1237 1238 case INDEX_op_br: 1239 tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SD10K16, arg_label(a0), 1240 0); 1241 tcg_out_opc_b(s, 0); 1242 break; 1243 1244 case INDEX_op_brcond_i32: 1245 case INDEX_op_brcond_i64: 1246 tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); 1247 break; 1248 1249 case INDEX_op_ext8s_i32: 1250 case INDEX_op_ext8s_i64: 1251 tcg_out_ext8s(s, a0, a1); 1252 break; 1253 1254 case INDEX_op_ext8u_i32: 1255 case INDEX_op_ext8u_i64: 1256 tcg_out_ext8u(s, a0, a1); 1257 break; 1258 1259 case INDEX_op_ext16s_i32: 1260 case INDEX_op_ext16s_i64: 1261 tcg_out_ext16s(s, a0, a1); 1262 break; 1263 1264 case INDEX_op_ext16u_i32: 1265 case INDEX_op_ext16u_i64: 1266 tcg_out_ext16u(s, a0, a1); 1267 break; 1268 1269 case INDEX_op_ext32u_i64: 1270 case INDEX_op_extu_i32_i64: 1271 tcg_out_ext32u(s, a0, a1); 1272 break; 1273 1274 case INDEX_op_ext32s_i64: 1275 case INDEX_op_extrl_i64_i32: 1276 case INDEX_op_ext_i32_i64: 1277 tcg_out_ext32s(s, a0, a1); 1278 break; 1279 1280 case INDEX_op_extrh_i64_i32: 1281 tcg_out_opc_srai_d(s, a0, a1, 32); 1282 break; 1283 1284 case INDEX_op_not_i32: 1285 case INDEX_op_not_i64: 1286 tcg_out_opc_nor(s, a0, a1, TCG_REG_ZERO); 1287 break; 1288 1289 case INDEX_op_nor_i32: 1290 case INDEX_op_nor_i64: 1291 if (c2) { 1292 tcg_out_opc_ori(s, a0, a1, a2); 1293 tcg_out_opc_nor(s, a0, a0, TCG_REG_ZERO); 1294 } else { 1295 tcg_out_opc_nor(s, a0, a1, a2); 1296 } 1297 break; 1298 1299 case INDEX_op_andc_i32: 1300 case INDEX_op_andc_i64: 1301 if (c2) { 1302 /* guaranteed to fit due to constraint */ 1303 tcg_out_opc_andi(s, a0, a1, ~a2); 1304 } else { 1305 tcg_out_opc_andn(s, a0, a1, a2); 1306 } 1307 break; 1308 1309 case INDEX_op_orc_i32: 1310 case INDEX_op_orc_i64: 1311 if (c2) { 1312 /* guaranteed to fit due to constraint */ 1313 tcg_out_opc_ori(s, a0, a1, ~a2); 1314 } else { 1315 tcg_out_opc_orn(s, a0, a1, a2); 1316 } 1317 break; 1318 1319 case INDEX_op_and_i32: 1320 case INDEX_op_and_i64: 1321 if (c2) { 1322 tcg_out_opc_andi(s, a0, a1, a2); 1323 } else { 1324 tcg_out_opc_and(s, a0, a1, a2); 1325 } 1326 break; 1327 1328 case INDEX_op_or_i32: 1329 case INDEX_op_or_i64: 1330 if (c2) { 1331 tcg_out_opc_ori(s, a0, a1, a2); 1332 } else { 1333 tcg_out_opc_or(s, a0, a1, a2); 1334 } 1335 break; 1336 1337 case INDEX_op_xor_i32: 1338 case INDEX_op_xor_i64: 1339 if (c2) { 1340 tcg_out_opc_xori(s, a0, a1, a2); 1341 } else { 1342 tcg_out_opc_xor(s, a0, a1, a2); 1343 } 1344 break; 1345 1346 case INDEX_op_extract_i32: 1347 tcg_out_opc_bstrpick_w(s, a0, a1, a2, a2 + args[3] - 1); 1348 break; 1349 case INDEX_op_extract_i64: 1350 tcg_out_opc_bstrpick_d(s, a0, a1, a2, a2 + args[3] - 1); 1351 break; 1352 1353 case INDEX_op_deposit_i32: 1354 tcg_out_opc_bstrins_w(s, a0, a2, args[3], args[3] + args[4] - 1); 1355 break; 1356 case INDEX_op_deposit_i64: 1357 tcg_out_opc_bstrins_d(s, a0, a2, args[3], args[3] + args[4] - 1); 1358 break; 1359 1360 case INDEX_op_bswap16_i32: 1361 case INDEX_op_bswap16_i64: 1362 tcg_out_opc_revb_2h(s, a0, a1); 1363 if (a2 & TCG_BSWAP_OS) { 1364 tcg_out_ext16s(s, a0, a0); 1365 } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) { 1366 tcg_out_ext16u(s, a0, a0); 1367 } 1368 break; 1369 1370 case INDEX_op_bswap32_i32: 1371 /* All 32-bit values are computed sign-extended in the register. */ 1372 a2 = TCG_BSWAP_OS; 1373 /* fallthrough */ 1374 case INDEX_op_bswap32_i64: 1375 tcg_out_opc_revb_2w(s, a0, a1); 1376 if (a2 & TCG_BSWAP_OS) { 1377 tcg_out_ext32s(s, a0, a0); 1378 } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) { 1379 tcg_out_ext32u(s, a0, a0); 1380 } 1381 break; 1382 1383 case INDEX_op_bswap64_i64: 1384 tcg_out_opc_revb_d(s, a0, a1); 1385 break; 1386 1387 case INDEX_op_clz_i32: 1388 tcg_out_clzctz(s, OPC_CLZ_W, a0, a1, a2, c2, true); 1389 break; 1390 case INDEX_op_clz_i64: 1391 tcg_out_clzctz(s, OPC_CLZ_D, a0, a1, a2, c2, false); 1392 break; 1393 1394 case INDEX_op_ctz_i32: 1395 tcg_out_clzctz(s, OPC_CTZ_W, a0, a1, a2, c2, true); 1396 break; 1397 case INDEX_op_ctz_i64: 1398 tcg_out_clzctz(s, OPC_CTZ_D, a0, a1, a2, c2, false); 1399 break; 1400 1401 case INDEX_op_shl_i32: 1402 if (c2) { 1403 tcg_out_opc_slli_w(s, a0, a1, a2 & 0x1f); 1404 } else { 1405 tcg_out_opc_sll_w(s, a0, a1, a2); 1406 } 1407 break; 1408 case INDEX_op_shl_i64: 1409 if (c2) { 1410 tcg_out_opc_slli_d(s, a0, a1, a2 & 0x3f); 1411 } else { 1412 tcg_out_opc_sll_d(s, a0, a1, a2); 1413 } 1414 break; 1415 1416 case INDEX_op_shr_i32: 1417 if (c2) { 1418 tcg_out_opc_srli_w(s, a0, a1, a2 & 0x1f); 1419 } else { 1420 tcg_out_opc_srl_w(s, a0, a1, a2); 1421 } 1422 break; 1423 case INDEX_op_shr_i64: 1424 if (c2) { 1425 tcg_out_opc_srli_d(s, a0, a1, a2 & 0x3f); 1426 } else { 1427 tcg_out_opc_srl_d(s, a0, a1, a2); 1428 } 1429 break; 1430 1431 case INDEX_op_sar_i32: 1432 if (c2) { 1433 tcg_out_opc_srai_w(s, a0, a1, a2 & 0x1f); 1434 } else { 1435 tcg_out_opc_sra_w(s, a0, a1, a2); 1436 } 1437 break; 1438 case INDEX_op_sar_i64: 1439 if (c2) { 1440 tcg_out_opc_srai_d(s, a0, a1, a2 & 0x3f); 1441 } else { 1442 tcg_out_opc_sra_d(s, a0, a1, a2); 1443 } 1444 break; 1445 1446 case INDEX_op_rotl_i32: 1447 /* transform into equivalent rotr/rotri */ 1448 if (c2) { 1449 tcg_out_opc_rotri_w(s, a0, a1, (32 - a2) & 0x1f); 1450 } else { 1451 tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2); 1452 tcg_out_opc_rotr_w(s, a0, a1, TCG_REG_TMP0); 1453 } 1454 break; 1455 case INDEX_op_rotl_i64: 1456 /* transform into equivalent rotr/rotri */ 1457 if (c2) { 1458 tcg_out_opc_rotri_d(s, a0, a1, (64 - a2) & 0x3f); 1459 } else { 1460 tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2); 1461 tcg_out_opc_rotr_d(s, a0, a1, TCG_REG_TMP0); 1462 } 1463 break; 1464 1465 case INDEX_op_rotr_i32: 1466 if (c2) { 1467 tcg_out_opc_rotri_w(s, a0, a1, a2 & 0x1f); 1468 } else { 1469 tcg_out_opc_rotr_w(s, a0, a1, a2); 1470 } 1471 break; 1472 case INDEX_op_rotr_i64: 1473 if (c2) { 1474 tcg_out_opc_rotri_d(s, a0, a1, a2 & 0x3f); 1475 } else { 1476 tcg_out_opc_rotr_d(s, a0, a1, a2); 1477 } 1478 break; 1479 1480 case INDEX_op_add_i32: 1481 if (c2) { 1482 tcg_out_addi(s, TCG_TYPE_I32, a0, a1, a2); 1483 } else { 1484 tcg_out_opc_add_w(s, a0, a1, a2); 1485 } 1486 break; 1487 case INDEX_op_add_i64: 1488 if (c2) { 1489 tcg_out_addi(s, TCG_TYPE_I64, a0, a1, a2); 1490 } else { 1491 tcg_out_opc_add_d(s, a0, a1, a2); 1492 } 1493 break; 1494 1495 case INDEX_op_sub_i32: 1496 if (c2) { 1497 tcg_out_addi(s, TCG_TYPE_I32, a0, a1, -a2); 1498 } else { 1499 tcg_out_opc_sub_w(s, a0, a1, a2); 1500 } 1501 break; 1502 case INDEX_op_sub_i64: 1503 if (c2) { 1504 tcg_out_addi(s, TCG_TYPE_I64, a0, a1, -a2); 1505 } else { 1506 tcg_out_opc_sub_d(s, a0, a1, a2); 1507 } 1508 break; 1509 1510 case INDEX_op_mul_i32: 1511 tcg_out_opc_mul_w(s, a0, a1, a2); 1512 break; 1513 case INDEX_op_mul_i64: 1514 tcg_out_opc_mul_d(s, a0, a1, a2); 1515 break; 1516 1517 case INDEX_op_mulsh_i32: 1518 tcg_out_opc_mulh_w(s, a0, a1, a2); 1519 break; 1520 case INDEX_op_mulsh_i64: 1521 tcg_out_opc_mulh_d(s, a0, a1, a2); 1522 break; 1523 1524 case INDEX_op_muluh_i32: 1525 tcg_out_opc_mulh_wu(s, a0, a1, a2); 1526 break; 1527 case INDEX_op_muluh_i64: 1528 tcg_out_opc_mulh_du(s, a0, a1, a2); 1529 break; 1530 1531 case INDEX_op_div_i32: 1532 tcg_out_opc_div_w(s, a0, a1, a2); 1533 break; 1534 case INDEX_op_div_i64: 1535 tcg_out_opc_div_d(s, a0, a1, a2); 1536 break; 1537 1538 case INDEX_op_divu_i32: 1539 tcg_out_opc_div_wu(s, a0, a1, a2); 1540 break; 1541 case INDEX_op_divu_i64: 1542 tcg_out_opc_div_du(s, a0, a1, a2); 1543 break; 1544 1545 case INDEX_op_rem_i32: 1546 tcg_out_opc_mod_w(s, a0, a1, a2); 1547 break; 1548 case INDEX_op_rem_i64: 1549 tcg_out_opc_mod_d(s, a0, a1, a2); 1550 break; 1551 1552 case INDEX_op_remu_i32: 1553 tcg_out_opc_mod_wu(s, a0, a1, a2); 1554 break; 1555 case INDEX_op_remu_i64: 1556 tcg_out_opc_mod_du(s, a0, a1, a2); 1557 break; 1558 1559 case INDEX_op_setcond_i32: 1560 case INDEX_op_setcond_i64: 1561 tcg_out_setcond(s, args[3], a0, a1, a2, c2); 1562 break; 1563 1564 case INDEX_op_movcond_i32: 1565 case INDEX_op_movcond_i64: 1566 tcg_out_movcond(s, args[5], a0, a1, a2, c2, args[3], args[4]); 1567 break; 1568 1569 case INDEX_op_ld8s_i32: 1570 case INDEX_op_ld8s_i64: 1571 tcg_out_ldst(s, OPC_LD_B, a0, a1, a2); 1572 break; 1573 case INDEX_op_ld8u_i32: 1574 case INDEX_op_ld8u_i64: 1575 tcg_out_ldst(s, OPC_LD_BU, a0, a1, a2); 1576 break; 1577 case INDEX_op_ld16s_i32: 1578 case INDEX_op_ld16s_i64: 1579 tcg_out_ldst(s, OPC_LD_H, a0, a1, a2); 1580 break; 1581 case INDEX_op_ld16u_i32: 1582 case INDEX_op_ld16u_i64: 1583 tcg_out_ldst(s, OPC_LD_HU, a0, a1, a2); 1584 break; 1585 case INDEX_op_ld_i32: 1586 case INDEX_op_ld32s_i64: 1587 tcg_out_ldst(s, OPC_LD_W, a0, a1, a2); 1588 break; 1589 case INDEX_op_ld32u_i64: 1590 tcg_out_ldst(s, OPC_LD_WU, a0, a1, a2); 1591 break; 1592 case INDEX_op_ld_i64: 1593 tcg_out_ldst(s, OPC_LD_D, a0, a1, a2); 1594 break; 1595 1596 case INDEX_op_st8_i32: 1597 case INDEX_op_st8_i64: 1598 tcg_out_ldst(s, OPC_ST_B, a0, a1, a2); 1599 break; 1600 case INDEX_op_st16_i32: 1601 case INDEX_op_st16_i64: 1602 tcg_out_ldst(s, OPC_ST_H, a0, a1, a2); 1603 break; 1604 case INDEX_op_st_i32: 1605 case INDEX_op_st32_i64: 1606 tcg_out_ldst(s, OPC_ST_W, a0, a1, a2); 1607 break; 1608 case INDEX_op_st_i64: 1609 tcg_out_ldst(s, OPC_ST_D, a0, a1, a2); 1610 break; 1611 1612 case INDEX_op_qemu_ld_i32: 1613 tcg_out_qemu_ld(s, args, TCG_TYPE_I32); 1614 break; 1615 case INDEX_op_qemu_ld_i64: 1616 tcg_out_qemu_ld(s, args, TCG_TYPE_I64); 1617 break; 1618 case INDEX_op_qemu_st_i32: 1619 tcg_out_qemu_st(s, args); 1620 break; 1621 case INDEX_op_qemu_st_i64: 1622 tcg_out_qemu_st(s, args); 1623 break; 1624 1625 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ 1626 case INDEX_op_mov_i64: 1627 case INDEX_op_call: /* Always emitted via tcg_out_call. */ 1628 case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ 1629 case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ 1630 default: 1631 g_assert_not_reached(); 1632 } 1633} 1634 1635static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) 1636{ 1637 switch (op) { 1638 case INDEX_op_goto_ptr: 1639 return C_O0_I1(r); 1640 1641 case INDEX_op_st8_i32: 1642 case INDEX_op_st8_i64: 1643 case INDEX_op_st16_i32: 1644 case INDEX_op_st16_i64: 1645 case INDEX_op_st32_i64: 1646 case INDEX_op_st_i32: 1647 case INDEX_op_st_i64: 1648 return C_O0_I2(rZ, r); 1649 1650 case INDEX_op_brcond_i32: 1651 case INDEX_op_brcond_i64: 1652 return C_O0_I2(rZ, rZ); 1653 1654 case INDEX_op_qemu_st_i32: 1655 case INDEX_op_qemu_st_i64: 1656 return C_O0_I2(LZ, L); 1657 1658 case INDEX_op_ext8s_i32: 1659 case INDEX_op_ext8s_i64: 1660 case INDEX_op_ext8u_i32: 1661 case INDEX_op_ext8u_i64: 1662 case INDEX_op_ext16s_i32: 1663 case INDEX_op_ext16s_i64: 1664 case INDEX_op_ext16u_i32: 1665 case INDEX_op_ext16u_i64: 1666 case INDEX_op_ext32s_i64: 1667 case INDEX_op_ext32u_i64: 1668 case INDEX_op_extu_i32_i64: 1669 case INDEX_op_extrl_i64_i32: 1670 case INDEX_op_extrh_i64_i32: 1671 case INDEX_op_ext_i32_i64: 1672 case INDEX_op_not_i32: 1673 case INDEX_op_not_i64: 1674 case INDEX_op_extract_i32: 1675 case INDEX_op_extract_i64: 1676 case INDEX_op_bswap16_i32: 1677 case INDEX_op_bswap16_i64: 1678 case INDEX_op_bswap32_i32: 1679 case INDEX_op_bswap32_i64: 1680 case INDEX_op_bswap64_i64: 1681 case INDEX_op_ld8s_i32: 1682 case INDEX_op_ld8s_i64: 1683 case INDEX_op_ld8u_i32: 1684 case INDEX_op_ld8u_i64: 1685 case INDEX_op_ld16s_i32: 1686 case INDEX_op_ld16s_i64: 1687 case INDEX_op_ld16u_i32: 1688 case INDEX_op_ld16u_i64: 1689 case INDEX_op_ld32s_i64: 1690 case INDEX_op_ld32u_i64: 1691 case INDEX_op_ld_i32: 1692 case INDEX_op_ld_i64: 1693 return C_O1_I1(r, r); 1694 1695 case INDEX_op_qemu_ld_i32: 1696 case INDEX_op_qemu_ld_i64: 1697 return C_O1_I1(r, L); 1698 1699 case INDEX_op_andc_i32: 1700 case INDEX_op_andc_i64: 1701 case INDEX_op_orc_i32: 1702 case INDEX_op_orc_i64: 1703 /* 1704 * LoongArch insns for these ops don't have reg-imm forms, but we 1705 * can express using andi/ori if ~constant satisfies 1706 * TCG_CT_CONST_U12. 1707 */ 1708 return C_O1_I2(r, r, rC); 1709 1710 case INDEX_op_shl_i32: 1711 case INDEX_op_shl_i64: 1712 case INDEX_op_shr_i32: 1713 case INDEX_op_shr_i64: 1714 case INDEX_op_sar_i32: 1715 case INDEX_op_sar_i64: 1716 case INDEX_op_rotl_i32: 1717 case INDEX_op_rotl_i64: 1718 case INDEX_op_rotr_i32: 1719 case INDEX_op_rotr_i64: 1720 return C_O1_I2(r, r, ri); 1721 1722 case INDEX_op_add_i32: 1723 return C_O1_I2(r, r, ri); 1724 case INDEX_op_add_i64: 1725 return C_O1_I2(r, r, rJ); 1726 1727 case INDEX_op_and_i32: 1728 case INDEX_op_and_i64: 1729 case INDEX_op_nor_i32: 1730 case INDEX_op_nor_i64: 1731 case INDEX_op_or_i32: 1732 case INDEX_op_or_i64: 1733 case INDEX_op_xor_i32: 1734 case INDEX_op_xor_i64: 1735 /* LoongArch reg-imm bitops have their imms ZERO-extended */ 1736 return C_O1_I2(r, r, rU); 1737 1738 case INDEX_op_clz_i32: 1739 case INDEX_op_clz_i64: 1740 case INDEX_op_ctz_i32: 1741 case INDEX_op_ctz_i64: 1742 return C_O1_I2(r, r, rW); 1743 1744 case INDEX_op_deposit_i32: 1745 case INDEX_op_deposit_i64: 1746 /* Must deposit into the same register as input */ 1747 return C_O1_I2(r, 0, rZ); 1748 1749 case INDEX_op_sub_i32: 1750 case INDEX_op_setcond_i32: 1751 return C_O1_I2(r, rZ, ri); 1752 case INDEX_op_sub_i64: 1753 case INDEX_op_setcond_i64: 1754 return C_O1_I2(r, rZ, rJ); 1755 1756 case INDEX_op_mul_i32: 1757 case INDEX_op_mul_i64: 1758 case INDEX_op_mulsh_i32: 1759 case INDEX_op_mulsh_i64: 1760 case INDEX_op_muluh_i32: 1761 case INDEX_op_muluh_i64: 1762 case INDEX_op_div_i32: 1763 case INDEX_op_div_i64: 1764 case INDEX_op_divu_i32: 1765 case INDEX_op_divu_i64: 1766 case INDEX_op_rem_i32: 1767 case INDEX_op_rem_i64: 1768 case INDEX_op_remu_i32: 1769 case INDEX_op_remu_i64: 1770 return C_O1_I2(r, rZ, rZ); 1771 1772 case INDEX_op_movcond_i32: 1773 case INDEX_op_movcond_i64: 1774 return C_O1_I4(r, rZ, rJ, rZ, rZ); 1775 1776 default: 1777 g_assert_not_reached(); 1778 } 1779} 1780 1781static const int tcg_target_callee_save_regs[] = { 1782 TCG_REG_S0, /* used for the global env (TCG_AREG0) */ 1783 TCG_REG_S1, 1784 TCG_REG_S2, 1785 TCG_REG_S3, 1786 TCG_REG_S4, 1787 TCG_REG_S5, 1788 TCG_REG_S6, 1789 TCG_REG_S7, 1790 TCG_REG_S8, 1791 TCG_REG_S9, 1792 TCG_REG_RA, /* should be last for ABI compliance */ 1793}; 1794 1795/* Stack frame parameters. */ 1796#define REG_SIZE (TCG_TARGET_REG_BITS / 8) 1797#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE) 1798#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long)) 1799#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \ 1800 + TCG_TARGET_STACK_ALIGN - 1) \ 1801 & -TCG_TARGET_STACK_ALIGN) 1802#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE) 1803 1804/* We're expecting to be able to use an immediate for frame allocation. */ 1805QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff); 1806 1807/* Generate global QEMU prologue and epilogue code */ 1808static void tcg_target_qemu_prologue(TCGContext *s) 1809{ 1810 int i; 1811 1812 tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE); 1813 1814 /* TB prologue */ 1815 tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE); 1816 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { 1817 tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], 1818 TCG_REG_SP, SAVE_OFS + i * REG_SIZE); 1819 } 1820 1821#if !defined(CONFIG_SOFTMMU) 1822 if (USE_GUEST_BASE) { 1823 tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base); 1824 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); 1825 } 1826#endif 1827 1828 /* Call generated code */ 1829 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); 1830 tcg_out_opc_jirl(s, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0); 1831 1832 /* Return path for goto_ptr. Set return value to 0 */ 1833 tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr); 1834 tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO); 1835 1836 /* TB epilogue */ 1837 tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr); 1838 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { 1839 tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], 1840 TCG_REG_SP, SAVE_OFS + i * REG_SIZE); 1841 } 1842 1843 tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE); 1844 tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_RA, 0); 1845} 1846 1847static void tcg_target_init(TCGContext *s) 1848{ 1849 tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS; 1850 tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS; 1851 1852 tcg_target_call_clobber_regs = ALL_GENERAL_REGS; 1853 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0); 1854 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1); 1855 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2); 1856 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3); 1857 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4); 1858 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5); 1859 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6); 1860 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7); 1861 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8); 1862 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9); 1863 1864 s->reserved_regs = 0; 1865 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); 1866 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0); 1867 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); 1868 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); 1869 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); 1870 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP); 1871 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RESERVED); 1872} 1873 1874typedef struct { 1875 DebugFrameHeader h; 1876 uint8_t fde_def_cfa[4]; 1877 uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; 1878} DebugFrame; 1879 1880#define ELF_HOST_MACHINE EM_LOONGARCH 1881 1882static const DebugFrame debug_frame = { 1883 .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */ 1884 .h.cie.id = -1, 1885 .h.cie.version = 1, 1886 .h.cie.code_align = 1, 1887 .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */ 1888 .h.cie.return_column = TCG_REG_RA, 1889 1890 /* Total FDE size does not include the "len" member. */ 1891 .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), 1892 1893 .fde_def_cfa = { 1894 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ 1895 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ 1896 (FRAME_SIZE >> 7) 1897 }, 1898 .fde_reg_ofs = { 1899 0x80 + 23, 11, /* DW_CFA_offset, s0, -88 */ 1900 0x80 + 24, 10, /* DW_CFA_offset, s1, -80 */ 1901 0x80 + 25, 9, /* DW_CFA_offset, s2, -72 */ 1902 0x80 + 26, 8, /* DW_CFA_offset, s3, -64 */ 1903 0x80 + 27, 7, /* DW_CFA_offset, s4, -56 */ 1904 0x80 + 28, 6, /* DW_CFA_offset, s5, -48 */ 1905 0x80 + 29, 5, /* DW_CFA_offset, s6, -40 */ 1906 0x80 + 30, 4, /* DW_CFA_offset, s7, -32 */ 1907 0x80 + 31, 3, /* DW_CFA_offset, s8, -24 */ 1908 0x80 + 22, 2, /* DW_CFA_offset, s9, -16 */ 1909 0x80 + 1 , 1, /* DW_CFA_offset, ra, -8 */ 1910 } 1911}; 1912 1913void tcg_register_jit(const void *buf, size_t buf_size) 1914{ 1915 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); 1916} 1917