1/* 2 * Tiny Code Generator for QEMU 3 * 4 * Copyright (c) 2009, 2011 Stefan Weil 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25/* Used for function call generation. */ 26#define TCG_TARGET_CALL_STACK_OFFSET 0 27#define TCG_TARGET_STACK_ALIGN 8 28#if TCG_TARGET_REG_BITS == 32 29# define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_EVEN 30# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_EVEN 31# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN 32#else 33# define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL 34# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL 35# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL 36#endif 37#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL 38 39static TCGConstraintSetIndex 40tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) 41{ 42 return C_NotImplemented; 43} 44 45static const int tcg_target_reg_alloc_order[] = { 46 TCG_REG_R4, 47 TCG_REG_R5, 48 TCG_REG_R6, 49 TCG_REG_R7, 50 TCG_REG_R8, 51 TCG_REG_R9, 52 TCG_REG_R10, 53 TCG_REG_R11, 54 TCG_REG_R12, 55 TCG_REG_R13, 56 TCG_REG_R14, 57 TCG_REG_R15, 58 /* Either 2 or 4 of these are call clobbered, so use them last. */ 59 TCG_REG_R3, 60 TCG_REG_R2, 61 TCG_REG_R1, 62 TCG_REG_R0, 63}; 64 65/* No call arguments via registers. All will be stored on the "stack". */ 66static const int tcg_target_call_iarg_regs[] = { }; 67 68static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot) 69{ 70 tcg_debug_assert(kind == TCG_CALL_RET_NORMAL); 71 tcg_debug_assert(slot >= 0 && slot < 128 / TCG_TARGET_REG_BITS); 72 return TCG_REG_R0 + slot; 73} 74 75#ifdef CONFIG_DEBUG_TCG 76static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { 77 "r00", 78 "r01", 79 "r02", 80 "r03", 81 "r04", 82 "r05", 83 "r06", 84 "r07", 85 "r08", 86 "r09", 87 "r10", 88 "r11", 89 "r12", 90 "r13", 91 "r14", 92 "r15", 93}; 94#endif 95 96static bool patch_reloc(tcg_insn_unit *code_ptr, int type, 97 intptr_t value, intptr_t addend) 98{ 99 intptr_t diff = value - (intptr_t)(code_ptr + 1); 100 101 tcg_debug_assert(addend == 0); 102 tcg_debug_assert(type == 20); 103 104 if (diff == sextract32(diff, 0, type)) { 105 tcg_patch32(code_ptr, deposit32(*code_ptr, 32 - type, type, diff)); 106 return true; 107 } 108 return false; 109} 110 111static void stack_bounds_check(TCGReg base, intptr_t offset) 112{ 113 if (base == TCG_REG_CALL_STACK) { 114 tcg_debug_assert(offset >= 0); 115 tcg_debug_assert(offset < (TCG_STATIC_CALL_ARGS_SIZE + 116 TCG_STATIC_FRAME_SIZE)); 117 } 118} 119 120static void tcg_out_op_l(TCGContext *s, TCGOpcode op, TCGLabel *l0) 121{ 122 tcg_insn_unit insn = 0; 123 124 tcg_out_reloc(s, s->code_ptr, 20, l0, 0); 125 insn = deposit32(insn, 0, 8, op); 126 tcg_out32(s, insn); 127} 128 129static void tcg_out_op_p(TCGContext *s, TCGOpcode op, void *p0) 130{ 131 tcg_insn_unit insn = 0; 132 intptr_t diff; 133 134 /* Special case for exit_tb: map null -> 0. */ 135 if (p0 == NULL) { 136 diff = 0; 137 } else { 138 diff = p0 - (void *)(s->code_ptr + 1); 139 tcg_debug_assert(diff != 0); 140 if (diff != sextract32(diff, 0, 20)) { 141 tcg_raise_tb_overflow(s); 142 } 143 } 144 insn = deposit32(insn, 0, 8, op); 145 insn = deposit32(insn, 12, 20, diff); 146 tcg_out32(s, insn); 147} 148 149static void tcg_out_op_r(TCGContext *s, TCGOpcode op, TCGReg r0) 150{ 151 tcg_insn_unit insn = 0; 152 153 insn = deposit32(insn, 0, 8, op); 154 insn = deposit32(insn, 8, 4, r0); 155 tcg_out32(s, insn); 156} 157 158static void tcg_out_op_v(TCGContext *s, TCGOpcode op) 159{ 160 tcg_out32(s, (uint8_t)op); 161} 162 163static void tcg_out_op_ri(TCGContext *s, TCGOpcode op, TCGReg r0, int32_t i1) 164{ 165 tcg_insn_unit insn = 0; 166 167 tcg_debug_assert(i1 == sextract32(i1, 0, 20)); 168 insn = deposit32(insn, 0, 8, op); 169 insn = deposit32(insn, 8, 4, r0); 170 insn = deposit32(insn, 12, 20, i1); 171 tcg_out32(s, insn); 172} 173 174static void tcg_out_op_rl(TCGContext *s, TCGOpcode op, TCGReg r0, TCGLabel *l1) 175{ 176 tcg_insn_unit insn = 0; 177 178 tcg_out_reloc(s, s->code_ptr, 20, l1, 0); 179 insn = deposit32(insn, 0, 8, op); 180 insn = deposit32(insn, 8, 4, r0); 181 tcg_out32(s, insn); 182} 183 184static void tcg_out_op_rr(TCGContext *s, TCGOpcode op, TCGReg r0, TCGReg r1) 185{ 186 tcg_insn_unit insn = 0; 187 188 insn = deposit32(insn, 0, 8, op); 189 insn = deposit32(insn, 8, 4, r0); 190 insn = deposit32(insn, 12, 4, r1); 191 tcg_out32(s, insn); 192} 193 194static void tcg_out_op_rrm(TCGContext *s, TCGOpcode op, 195 TCGReg r0, TCGReg r1, TCGArg m2) 196{ 197 tcg_insn_unit insn = 0; 198 199 tcg_debug_assert(m2 == extract32(m2, 0, 16)); 200 insn = deposit32(insn, 0, 8, op); 201 insn = deposit32(insn, 8, 4, r0); 202 insn = deposit32(insn, 12, 4, r1); 203 insn = deposit32(insn, 16, 16, m2); 204 tcg_out32(s, insn); 205} 206 207static void tcg_out_op_rrr(TCGContext *s, TCGOpcode op, 208 TCGReg r0, TCGReg r1, TCGReg r2) 209{ 210 tcg_insn_unit insn = 0; 211 212 insn = deposit32(insn, 0, 8, op); 213 insn = deposit32(insn, 8, 4, r0); 214 insn = deposit32(insn, 12, 4, r1); 215 insn = deposit32(insn, 16, 4, r2); 216 tcg_out32(s, insn); 217} 218 219static void tcg_out_op_rrs(TCGContext *s, TCGOpcode op, 220 TCGReg r0, TCGReg r1, intptr_t i2) 221{ 222 tcg_insn_unit insn = 0; 223 224 tcg_debug_assert(i2 == sextract32(i2, 0, 16)); 225 insn = deposit32(insn, 0, 8, op); 226 insn = deposit32(insn, 8, 4, r0); 227 insn = deposit32(insn, 12, 4, r1); 228 insn = deposit32(insn, 16, 16, i2); 229 tcg_out32(s, insn); 230} 231 232static void tcg_out_op_rrbb(TCGContext *s, TCGOpcode op, TCGReg r0, 233 TCGReg r1, uint8_t b2, uint8_t b3) 234{ 235 tcg_insn_unit insn = 0; 236 237 tcg_debug_assert(b2 == extract32(b2, 0, 6)); 238 tcg_debug_assert(b3 == extract32(b3, 0, 6)); 239 insn = deposit32(insn, 0, 8, op); 240 insn = deposit32(insn, 8, 4, r0); 241 insn = deposit32(insn, 12, 4, r1); 242 insn = deposit32(insn, 16, 6, b2); 243 insn = deposit32(insn, 22, 6, b3); 244 tcg_out32(s, insn); 245} 246 247static void tcg_out_op_rrrc(TCGContext *s, TCGOpcode op, 248 TCGReg r0, TCGReg r1, TCGReg r2, TCGCond c3) 249{ 250 tcg_insn_unit insn = 0; 251 252 insn = deposit32(insn, 0, 8, op); 253 insn = deposit32(insn, 8, 4, r0); 254 insn = deposit32(insn, 12, 4, r1); 255 insn = deposit32(insn, 16, 4, r2); 256 insn = deposit32(insn, 20, 4, c3); 257 tcg_out32(s, insn); 258} 259 260static void tcg_out_op_rrrbb(TCGContext *s, TCGOpcode op, TCGReg r0, 261 TCGReg r1, TCGReg r2, uint8_t b3, uint8_t b4) 262{ 263 tcg_insn_unit insn = 0; 264 265 tcg_debug_assert(b3 == extract32(b3, 0, 6)); 266 tcg_debug_assert(b4 == extract32(b4, 0, 6)); 267 insn = deposit32(insn, 0, 8, op); 268 insn = deposit32(insn, 8, 4, r0); 269 insn = deposit32(insn, 12, 4, r1); 270 insn = deposit32(insn, 16, 4, r2); 271 insn = deposit32(insn, 20, 6, b3); 272 insn = deposit32(insn, 26, 6, b4); 273 tcg_out32(s, insn); 274} 275 276static void tcg_out_op_rrrr(TCGContext *s, TCGOpcode op, 277 TCGReg r0, TCGReg r1, TCGReg r2, TCGReg r3) 278{ 279 tcg_insn_unit insn = 0; 280 281 insn = deposit32(insn, 0, 8, op); 282 insn = deposit32(insn, 8, 4, r0); 283 insn = deposit32(insn, 12, 4, r1); 284 insn = deposit32(insn, 16, 4, r2); 285 insn = deposit32(insn, 20, 4, r3); 286 tcg_out32(s, insn); 287} 288 289static void tcg_out_op_rrrrrc(TCGContext *s, TCGOpcode op, 290 TCGReg r0, TCGReg r1, TCGReg r2, 291 TCGReg r3, TCGReg r4, TCGCond c5) 292{ 293 tcg_insn_unit insn = 0; 294 295 insn = deposit32(insn, 0, 8, op); 296 insn = deposit32(insn, 8, 4, r0); 297 insn = deposit32(insn, 12, 4, r1); 298 insn = deposit32(insn, 16, 4, r2); 299 insn = deposit32(insn, 20, 4, r3); 300 insn = deposit32(insn, 24, 4, r4); 301 insn = deposit32(insn, 28, 4, c5); 302 tcg_out32(s, insn); 303} 304 305static void tcg_out_ldst(TCGContext *s, TCGOpcode op, TCGReg val, 306 TCGReg base, intptr_t offset) 307{ 308 stack_bounds_check(base, offset); 309 if (offset != sextract32(offset, 0, 16)) { 310 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, offset); 311 tcg_out_op_rrr(s, INDEX_op_add, TCG_REG_TMP, TCG_REG_TMP, base); 312 base = TCG_REG_TMP; 313 offset = 0; 314 } 315 tcg_out_op_rrs(s, op, val, base, offset); 316} 317 318static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg val, TCGReg base, 319 intptr_t offset) 320{ 321 TCGOpcode op = INDEX_op_ld; 322 323 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) { 324 op = INDEX_op_ld32u; 325 } 326 tcg_out_ldst(s, op, val, base, offset); 327} 328 329static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 330{ 331 tcg_out_op_rr(s, INDEX_op_mov, ret, arg); 332 return true; 333} 334 335static void tcg_out_movi(TCGContext *s, TCGType type, 336 TCGReg ret, tcg_target_long arg) 337{ 338 switch (type) { 339 case TCG_TYPE_I32: 340#if TCG_TARGET_REG_BITS == 64 341 arg = (int32_t)arg; 342 /* fall through */ 343 case TCG_TYPE_I64: 344#endif 345 break; 346 default: 347 g_assert_not_reached(); 348 } 349 350 if (arg == sextract32(arg, 0, 20)) { 351 tcg_out_op_ri(s, INDEX_op_tci_movi, ret, arg); 352 } else { 353 tcg_insn_unit insn = 0; 354 355 new_pool_label(s, arg, 20, s->code_ptr, 0); 356 insn = deposit32(insn, 0, 8, INDEX_op_tci_movl); 357 insn = deposit32(insn, 8, 4, ret); 358 tcg_out32(s, insn); 359 } 360} 361 362static void tcg_out_extract(TCGContext *s, TCGType type, TCGReg rd, 363 TCGReg rs, unsigned pos, unsigned len) 364{ 365 tcg_out_op_rrbb(s, INDEX_op_extract, rd, rs, pos, len); 366} 367 368static const TCGOutOpExtract outop_extract = { 369 .base.static_constraint = C_O1_I1(r, r), 370 .out_rr = tcg_out_extract, 371}; 372 373static void tcg_out_sextract(TCGContext *s, TCGType type, TCGReg rd, 374 TCGReg rs, unsigned pos, unsigned len) 375{ 376 tcg_out_op_rrbb(s, INDEX_op_sextract, rd, rs, pos, len); 377} 378 379static const TCGOutOpExtract outop_sextract = { 380 .base.static_constraint = C_O1_I1(r, r), 381 .out_rr = tcg_out_sextract, 382}; 383 384static const TCGOutOpExtract2 outop_extract2 = { 385 .base.static_constraint = C_NotImplemented, 386}; 387 388static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs) 389{ 390 tcg_out_sextract(s, type, rd, rs, 0, 8); 391} 392 393static void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rs) 394{ 395 tcg_out_extract(s, TCG_TYPE_REG, rd, rs, 0, 8); 396} 397 398static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs) 399{ 400 tcg_out_sextract(s, type, rd, rs, 0, 16); 401} 402 403static void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rs) 404{ 405 tcg_out_extract(s, TCG_TYPE_REG, rd, rs, 0, 16); 406} 407 408static void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rs) 409{ 410 tcg_debug_assert(TCG_TARGET_REG_BITS == 64); 411 tcg_out_sextract(s, TCG_TYPE_I64, rd, rs, 0, 32); 412} 413 414static void tcg_out_ext32u(TCGContext *s, TCGReg rd, TCGReg rs) 415{ 416 tcg_debug_assert(TCG_TARGET_REG_BITS == 64); 417 tcg_out_extract(s, TCG_TYPE_I64, rd, rs, 0, 32); 418} 419 420static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs) 421{ 422 tcg_out_ext32s(s, rd, rs); 423} 424 425static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs) 426{ 427 tcg_out_ext32u(s, rd, rs); 428} 429 430static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rs) 431{ 432 tcg_debug_assert(TCG_TARGET_REG_BITS == 64); 433 tcg_out_mov(s, TCG_TYPE_I32, rd, rs); 434} 435 436static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2) 437{ 438 return false; 439} 440 441static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs, 442 tcg_target_long imm) 443{ 444 /* This function is only used for passing structs by reference. */ 445 g_assert_not_reached(); 446} 447 448static void tcg_out_call(TCGContext *s, const tcg_insn_unit *func, 449 const TCGHelperInfo *info) 450{ 451 ffi_cif *cif = info->cif; 452 tcg_insn_unit insn = 0; 453 uint8_t which; 454 455 if (cif->rtype == &ffi_type_void) { 456 which = 0; 457 } else { 458 tcg_debug_assert(cif->rtype->size == 4 || 459 cif->rtype->size == 8 || 460 cif->rtype->size == 16); 461 which = ctz32(cif->rtype->size) - 1; 462 } 463 new_pool_l2(s, 20, s->code_ptr, 0, (uintptr_t)func, (uintptr_t)cif); 464 insn = deposit32(insn, 0, 8, INDEX_op_call); 465 insn = deposit32(insn, 8, 4, which); 466 tcg_out32(s, insn); 467} 468 469static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg) 470{ 471 tcg_out_op_p(s, INDEX_op_exit_tb, (void *)arg); 472} 473 474static void tcg_out_goto_tb(TCGContext *s, int which) 475{ 476 /* indirect jump method. */ 477 tcg_out_op_p(s, INDEX_op_goto_tb, (void *)get_jmp_target_addr(s, which)); 478 set_jmp_reset_offset(s, which); 479} 480 481static void tcg_out_goto_ptr(TCGContext *s, TCGReg a0) 482{ 483 tcg_out_op_r(s, INDEX_op_goto_ptr, a0); 484} 485 486void tb_target_set_jmp_target(const TranslationBlock *tb, int n, 487 uintptr_t jmp_rx, uintptr_t jmp_rw) 488{ 489 /* Always indirect, nothing to do */ 490} 491 492static void tgen_add(TCGContext *s, TCGType type, 493 TCGReg a0, TCGReg a1, TCGReg a2) 494{ 495 tcg_out_op_rrr(s, INDEX_op_add, a0, a1, a2); 496} 497 498static const TCGOutOpBinary outop_add = { 499 .base.static_constraint = C_O1_I2(r, r, r), 500 .out_rrr = tgen_add, 501}; 502 503static TCGConstraintSetIndex cset_addsubcarry(TCGType type, unsigned flags) 504{ 505 return type == TCG_TYPE_REG ? C_O1_I2(r, r, r) : C_NotImplemented; 506} 507 508static void tgen_addco(TCGContext *s, TCGType type, 509 TCGReg a0, TCGReg a1, TCGReg a2) 510{ 511 tcg_out_op_rrr(s, INDEX_op_addco, a0, a1, a2); 512} 513 514static const TCGOutOpBinary outop_addco = { 515 .base.static_constraint = C_Dynamic, 516 .base.dynamic_constraint = cset_addsubcarry, 517 .out_rrr = tgen_addco, 518}; 519 520static void tgen_addci(TCGContext *s, TCGType type, 521 TCGReg a0, TCGReg a1, TCGReg a2) 522{ 523 tcg_out_op_rrr(s, INDEX_op_addci, a0, a1, a2); 524} 525 526static const TCGOutOpAddSubCarry outop_addci = { 527 .base.static_constraint = C_Dynamic, 528 .base.dynamic_constraint = cset_addsubcarry, 529 .out_rrr = tgen_addci, 530}; 531 532static void tgen_addcio(TCGContext *s, TCGType type, 533 TCGReg a0, TCGReg a1, TCGReg a2) 534{ 535 tcg_out_op_rrr(s, INDEX_op_addcio, a0, a1, a2); 536} 537 538static const TCGOutOpBinary outop_addcio = { 539 .base.static_constraint = C_Dynamic, 540 .base.dynamic_constraint = cset_addsubcarry, 541 .out_rrr = tgen_addcio, 542}; 543 544static void tcg_out_set_carry(TCGContext *s) 545{ 546 tcg_out_op_v(s, INDEX_op_tci_setcarry); 547} 548 549static void tgen_and(TCGContext *s, TCGType type, 550 TCGReg a0, TCGReg a1, TCGReg a2) 551{ 552 tcg_out_op_rrr(s, INDEX_op_and, a0, a1, a2); 553} 554 555static const TCGOutOpBinary outop_and = { 556 .base.static_constraint = C_O1_I2(r, r, r), 557 .out_rrr = tgen_and, 558}; 559 560static void tgen_andc(TCGContext *s, TCGType type, 561 TCGReg a0, TCGReg a1, TCGReg a2) 562{ 563 tcg_out_op_rrr(s, INDEX_op_andc, a0, a1, a2); 564} 565 566static const TCGOutOpBinary outop_andc = { 567 .base.static_constraint = C_O1_I2(r, r, r), 568 .out_rrr = tgen_andc, 569}; 570 571static void tgen_clz(TCGContext *s, TCGType type, 572 TCGReg a0, TCGReg a1, TCGReg a2) 573{ 574 TCGOpcode opc = (type == TCG_TYPE_I32 575 ? INDEX_op_tci_clz32 576 : INDEX_op_clz); 577 tcg_out_op_rrr(s, opc, a0, a1, a2); 578} 579 580static const TCGOutOpBinary outop_clz = { 581 .base.static_constraint = C_O1_I2(r, r, r), 582 .out_rrr = tgen_clz, 583}; 584 585static void tgen_ctz(TCGContext *s, TCGType type, 586 TCGReg a0, TCGReg a1, TCGReg a2) 587{ 588 TCGOpcode opc = (type == TCG_TYPE_I32 589 ? INDEX_op_tci_ctz32 590 : INDEX_op_ctz); 591 tcg_out_op_rrr(s, opc, a0, a1, a2); 592} 593 594static const TCGOutOpBinary outop_ctz = { 595 .base.static_constraint = C_O1_I2(r, r, r), 596 .out_rrr = tgen_ctz, 597}; 598 599static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, 600 TCGReg a2, unsigned ofs, unsigned len) 601{ 602 tcg_out_op_rrrbb(s, INDEX_op_deposit, a0, a1, a2, ofs, len); 603} 604 605static const TCGOutOpDeposit outop_deposit = { 606 .base.static_constraint = C_O1_I2(r, r, r), 607 .out_rrr = tgen_deposit, 608}; 609 610static void tgen_divs(TCGContext *s, TCGType type, 611 TCGReg a0, TCGReg a1, TCGReg a2) 612{ 613 TCGOpcode opc = (type == TCG_TYPE_I32 614 ? INDEX_op_tci_divs32 615 : INDEX_op_divs); 616 tcg_out_op_rrr(s, opc, a0, a1, a2); 617} 618 619static const TCGOutOpBinary outop_divs = { 620 .base.static_constraint = C_O1_I2(r, r, r), 621 .out_rrr = tgen_divs, 622}; 623 624static const TCGOutOpDivRem outop_divs2 = { 625 .base.static_constraint = C_NotImplemented, 626}; 627 628static void tgen_divu(TCGContext *s, TCGType type, 629 TCGReg a0, TCGReg a1, TCGReg a2) 630{ 631 TCGOpcode opc = (type == TCG_TYPE_I32 632 ? INDEX_op_tci_divu32 633 : INDEX_op_divu); 634 tcg_out_op_rrr(s, opc, a0, a1, a2); 635} 636 637static const TCGOutOpBinary outop_divu = { 638 .base.static_constraint = C_O1_I2(r, r, r), 639 .out_rrr = tgen_divu, 640}; 641 642static const TCGOutOpDivRem outop_divu2 = { 643 .base.static_constraint = C_NotImplemented, 644}; 645 646static void tgen_eqv(TCGContext *s, TCGType type, 647 TCGReg a0, TCGReg a1, TCGReg a2) 648{ 649 tcg_out_op_rrr(s, INDEX_op_eqv, a0, a1, a2); 650} 651 652static const TCGOutOpBinary outop_eqv = { 653 .base.static_constraint = C_O1_I2(r, r, r), 654 .out_rrr = tgen_eqv, 655}; 656 657#if TCG_TARGET_REG_BITS == 64 658static void tgen_extrh_i64_i32(TCGContext *s, TCGType t, TCGReg a0, TCGReg a1) 659{ 660 tcg_out_extract(s, TCG_TYPE_I64, a0, a1, 32, 32); 661} 662 663static const TCGOutOpUnary outop_extrh_i64_i32 = { 664 .base.static_constraint = C_O1_I1(r, r), 665 .out_rr = tgen_extrh_i64_i32, 666}; 667#endif 668 669static void tgen_mul(TCGContext *s, TCGType type, 670 TCGReg a0, TCGReg a1, TCGReg a2) 671{ 672 tcg_out_op_rrr(s, INDEX_op_mul, a0, a1, a2); 673} 674 675static const TCGOutOpBinary outop_mul = { 676 .base.static_constraint = C_O1_I2(r, r, r), 677 .out_rrr = tgen_mul, 678}; 679 680static TCGConstraintSetIndex cset_mul2(TCGType type, unsigned flags) 681{ 682 return type == TCG_TYPE_REG ? C_O2_I2(r, r, r, r) : C_NotImplemented; 683} 684 685static void tgen_muls2(TCGContext *s, TCGType type, 686 TCGReg a0, TCGReg a1, TCGReg a2, TCGReg a3) 687{ 688 tcg_out_op_rrrr(s, INDEX_op_muls2, a0, a1, a2, a3); 689} 690 691static const TCGOutOpMul2 outop_muls2 = { 692 .base.static_constraint = C_Dynamic, 693 .base.dynamic_constraint = cset_mul2, 694 .out_rrrr = tgen_muls2, 695}; 696 697static const TCGOutOpBinary outop_mulsh = { 698 .base.static_constraint = C_NotImplemented, 699}; 700 701static void tgen_mulu2(TCGContext *s, TCGType type, 702 TCGReg a0, TCGReg a1, TCGReg a2, TCGReg a3) 703{ 704 tcg_out_op_rrrr(s, INDEX_op_mulu2, a0, a1, a2, a3); 705} 706 707static const TCGOutOpMul2 outop_mulu2 = { 708 .base.static_constraint = C_Dynamic, 709 .base.dynamic_constraint = cset_mul2, 710 .out_rrrr = tgen_mulu2, 711}; 712 713static const TCGOutOpBinary outop_muluh = { 714 .base.static_constraint = C_NotImplemented, 715}; 716 717static void tgen_nand(TCGContext *s, TCGType type, 718 TCGReg a0, TCGReg a1, TCGReg a2) 719{ 720 tcg_out_op_rrr(s, INDEX_op_nand, a0, a1, a2); 721} 722 723static const TCGOutOpBinary outop_nand = { 724 .base.static_constraint = C_O1_I2(r, r, r), 725 .out_rrr = tgen_nand, 726}; 727 728static void tgen_nor(TCGContext *s, TCGType type, 729 TCGReg a0, TCGReg a1, TCGReg a2) 730{ 731 tcg_out_op_rrr(s, INDEX_op_nor, a0, a1, a2); 732} 733 734static const TCGOutOpBinary outop_nor = { 735 .base.static_constraint = C_O1_I2(r, r, r), 736 .out_rrr = tgen_nor, 737}; 738 739static void tgen_or(TCGContext *s, TCGType type, 740 TCGReg a0, TCGReg a1, TCGReg a2) 741{ 742 tcg_out_op_rrr(s, INDEX_op_or, a0, a1, a2); 743} 744 745static const TCGOutOpBinary outop_or = { 746 .base.static_constraint = C_O1_I2(r, r, r), 747 .out_rrr = tgen_or, 748}; 749 750static void tgen_orc(TCGContext *s, TCGType type, 751 TCGReg a0, TCGReg a1, TCGReg a2) 752{ 753 tcg_out_op_rrr(s, INDEX_op_orc, a0, a1, a2); 754} 755 756static const TCGOutOpBinary outop_orc = { 757 .base.static_constraint = C_O1_I2(r, r, r), 758 .out_rrr = tgen_orc, 759}; 760 761static void tgen_rems(TCGContext *s, TCGType type, 762 TCGReg a0, TCGReg a1, TCGReg a2) 763{ 764 TCGOpcode opc = (type == TCG_TYPE_I32 765 ? INDEX_op_tci_rems32 766 : INDEX_op_rems); 767 tcg_out_op_rrr(s, opc, a0, a1, a2); 768} 769 770static const TCGOutOpBinary outop_rems = { 771 .base.static_constraint = C_O1_I2(r, r, r), 772 .out_rrr = tgen_rems, 773}; 774 775static void tgen_remu(TCGContext *s, TCGType type, 776 TCGReg a0, TCGReg a1, TCGReg a2) 777{ 778 TCGOpcode opc = (type == TCG_TYPE_I32 779 ? INDEX_op_tci_remu32 780 : INDEX_op_remu); 781 tcg_out_op_rrr(s, opc, a0, a1, a2); 782} 783 784static const TCGOutOpBinary outop_remu = { 785 .base.static_constraint = C_O1_I2(r, r, r), 786 .out_rrr = tgen_remu, 787}; 788 789static void tgen_rotl(TCGContext *s, TCGType type, 790 TCGReg a0, TCGReg a1, TCGReg a2) 791{ 792 TCGOpcode opc = (type == TCG_TYPE_I32 793 ? INDEX_op_tci_rotl32 794 : INDEX_op_rotl); 795 tcg_out_op_rrr(s, opc, a0, a1, a2); 796} 797 798static const TCGOutOpBinary outop_rotl = { 799 .base.static_constraint = C_O1_I2(r, r, r), 800 .out_rrr = tgen_rotl, 801}; 802 803static void tgen_rotr(TCGContext *s, TCGType type, 804 TCGReg a0, TCGReg a1, TCGReg a2) 805{ 806 TCGOpcode opc = (type == TCG_TYPE_I32 807 ? INDEX_op_tci_rotr32 808 : INDEX_op_rotr); 809 tcg_out_op_rrr(s, opc, a0, a1, a2); 810} 811 812static const TCGOutOpBinary outop_rotr = { 813 .base.static_constraint = C_O1_I2(r, r, r), 814 .out_rrr = tgen_rotr, 815}; 816 817static void tgen_sar(TCGContext *s, TCGType type, 818 TCGReg a0, TCGReg a1, TCGReg a2) 819{ 820 if (type < TCG_TYPE_REG) { 821 tcg_out_ext32s(s, TCG_REG_TMP, a1); 822 a1 = TCG_REG_TMP; 823 } 824 tcg_out_op_rrr(s, INDEX_op_sar, a0, a1, a2); 825} 826 827static const TCGOutOpBinary outop_sar = { 828 .base.static_constraint = C_O1_I2(r, r, r), 829 .out_rrr = tgen_sar, 830}; 831 832static void tgen_shl(TCGContext *s, TCGType type, 833 TCGReg a0, TCGReg a1, TCGReg a2) 834{ 835 tcg_out_op_rrr(s, INDEX_op_shl, a0, a1, a2); 836} 837 838static const TCGOutOpBinary outop_shl = { 839 .base.static_constraint = C_O1_I2(r, r, r), 840 .out_rrr = tgen_shl, 841}; 842 843static void tgen_shr(TCGContext *s, TCGType type, 844 TCGReg a0, TCGReg a1, TCGReg a2) 845{ 846 if (type < TCG_TYPE_REG) { 847 tcg_out_ext32u(s, TCG_REG_TMP, a1); 848 a1 = TCG_REG_TMP; 849 } 850 tcg_out_op_rrr(s, INDEX_op_shr, a0, a1, a2); 851} 852 853static const TCGOutOpBinary outop_shr = { 854 .base.static_constraint = C_O1_I2(r, r, r), 855 .out_rrr = tgen_shr, 856}; 857 858static void tgen_sub(TCGContext *s, TCGType type, 859 TCGReg a0, TCGReg a1, TCGReg a2) 860{ 861 tcg_out_op_rrr(s, INDEX_op_sub, a0, a1, a2); 862} 863 864static const TCGOutOpSubtract outop_sub = { 865 .base.static_constraint = C_O1_I2(r, r, r), 866 .out_rrr = tgen_sub, 867}; 868 869static void tgen_subbo(TCGContext *s, TCGType type, 870 TCGReg a0, TCGReg a1, TCGReg a2) 871{ 872 tcg_out_op_rrr(s, INDEX_op_subbo, a0, a1, a2); 873} 874 875static const TCGOutOpAddSubCarry outop_subbo = { 876 .base.static_constraint = C_Dynamic, 877 .base.dynamic_constraint = cset_addsubcarry, 878 .out_rrr = tgen_subbo, 879}; 880 881static void tgen_subbi(TCGContext *s, TCGType type, 882 TCGReg a0, TCGReg a1, TCGReg a2) 883{ 884 tcg_out_op_rrr(s, INDEX_op_subbi, a0, a1, a2); 885} 886 887static const TCGOutOpAddSubCarry outop_subbi = { 888 .base.static_constraint = C_Dynamic, 889 .base.dynamic_constraint = cset_addsubcarry, 890 .out_rrr = tgen_subbi, 891}; 892 893static void tgen_subbio(TCGContext *s, TCGType type, 894 TCGReg a0, TCGReg a1, TCGReg a2) 895{ 896 tcg_out_op_rrr(s, INDEX_op_subbio, a0, a1, a2); 897} 898 899static const TCGOutOpAddSubCarry outop_subbio = { 900 .base.static_constraint = C_Dynamic, 901 .base.dynamic_constraint = cset_addsubcarry, 902 .out_rrr = tgen_subbio, 903}; 904 905static void tcg_out_set_borrow(TCGContext *s) 906{ 907 tcg_out_op_v(s, INDEX_op_tci_setcarry); /* borrow == carry */ 908} 909 910static void tgen_xor(TCGContext *s, TCGType type, 911 TCGReg a0, TCGReg a1, TCGReg a2) 912{ 913 tcg_out_op_rrr(s, INDEX_op_xor, a0, a1, a2); 914} 915 916static const TCGOutOpBinary outop_xor = { 917 .base.static_constraint = C_O1_I2(r, r, r), 918 .out_rrr = tgen_xor, 919}; 920 921static void tgen_ctpop(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1) 922{ 923 tcg_out_op_rr(s, INDEX_op_ctpop, a0, a1); 924} 925 926static TCGConstraintSetIndex cset_ctpop(TCGType type, unsigned flags) 927{ 928 return type == TCG_TYPE_REG ? C_O1_I1(r, r) : C_NotImplemented; 929} 930 931static const TCGOutOpUnary outop_ctpop = { 932 .base.static_constraint = C_Dynamic, 933 .base.dynamic_constraint = cset_ctpop, 934 .out_rr = tgen_ctpop, 935}; 936 937static void tgen_bswap16(TCGContext *s, TCGType type, 938 TCGReg a0, TCGReg a1, unsigned flags) 939{ 940 tcg_out_op_rr(s, INDEX_op_bswap16, a0, a1); 941 if (flags & TCG_BSWAP_OS) { 942 tcg_out_sextract(s, TCG_TYPE_REG, a0, a0, 0, 16); 943 } 944} 945 946static const TCGOutOpBswap outop_bswap16 = { 947 .base.static_constraint = C_O1_I1(r, r), 948 .out_rr = tgen_bswap16, 949}; 950 951static void tgen_bswap32(TCGContext *s, TCGType type, 952 TCGReg a0, TCGReg a1, unsigned flags) 953{ 954 tcg_out_op_rr(s, INDEX_op_bswap32, a0, a1); 955 if (flags & TCG_BSWAP_OS) { 956 tcg_out_sextract(s, TCG_TYPE_REG, a0, a0, 0, 32); 957 } 958} 959 960static const TCGOutOpBswap outop_bswap32 = { 961 .base.static_constraint = C_O1_I1(r, r), 962 .out_rr = tgen_bswap32, 963}; 964 965#if TCG_TARGET_REG_BITS == 64 966static void tgen_bswap64(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1) 967{ 968 tcg_out_op_rr(s, INDEX_op_bswap64, a0, a1); 969} 970 971static const TCGOutOpUnary outop_bswap64 = { 972 .base.static_constraint = C_O1_I1(r, r), 973 .out_rr = tgen_bswap64, 974}; 975#endif 976 977static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1) 978{ 979 tcg_out_op_rr(s, INDEX_op_neg, a0, a1); 980} 981 982static const TCGOutOpUnary outop_neg = { 983 .base.static_constraint = C_O1_I1(r, r), 984 .out_rr = tgen_neg, 985}; 986 987static void tgen_not(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1) 988{ 989 tcg_out_op_rr(s, INDEX_op_not, a0, a1); 990} 991 992static const TCGOutOpUnary outop_not = { 993 .base.static_constraint = C_O1_I1(r, r), 994 .out_rr = tgen_not, 995}; 996 997static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond, 998 TCGReg dest, TCGReg arg1, TCGReg arg2) 999{ 1000 TCGOpcode opc = (type == TCG_TYPE_I32 1001 ? INDEX_op_tci_setcond32 1002 : INDEX_op_setcond); 1003 tcg_out_op_rrrc(s, opc, dest, arg1, arg2, cond); 1004} 1005 1006static const TCGOutOpSetcond outop_setcond = { 1007 .base.static_constraint = C_O1_I2(r, r, r), 1008 .out_rrr = tgen_setcond, 1009}; 1010 1011static void tgen_negsetcond(TCGContext *s, TCGType type, TCGCond cond, 1012 TCGReg dest, TCGReg arg1, TCGReg arg2) 1013{ 1014 tgen_setcond(s, type, cond, dest, arg1, arg2); 1015 tgen_neg(s, type, dest, dest); 1016} 1017 1018static const TCGOutOpSetcond outop_negsetcond = { 1019 .base.static_constraint = C_O1_I2(r, r, r), 1020 .out_rrr = tgen_negsetcond, 1021}; 1022 1023static void tgen_brcond(TCGContext *s, TCGType type, TCGCond cond, 1024 TCGReg arg0, TCGReg arg1, TCGLabel *l) 1025{ 1026 tgen_setcond(s, type, cond, TCG_REG_TMP, arg0, arg1); 1027 tcg_out_op_rl(s, INDEX_op_brcond, TCG_REG_TMP, l); 1028} 1029 1030static const TCGOutOpBrcond outop_brcond = { 1031 .base.static_constraint = C_O0_I2(r, r), 1032 .out_rr = tgen_brcond, 1033}; 1034 1035static void tgen_movcond(TCGContext *s, TCGType type, TCGCond cond, 1036 TCGReg ret, TCGReg c1, TCGArg c2, bool const_c2, 1037 TCGArg vt, bool const_vt, TCGArg vf, bool consf_vf) 1038{ 1039 TCGOpcode opc = (type == TCG_TYPE_I32 1040 ? INDEX_op_tci_movcond32 1041 : INDEX_op_movcond); 1042 tcg_out_op_rrrrrc(s, opc, ret, c1, c2, vt, vf, cond); 1043} 1044 1045static const TCGOutOpMovcond outop_movcond = { 1046 .base.static_constraint = C_O1_I4(r, r, r, r, r), 1047 .out = tgen_movcond, 1048}; 1049 1050static void tgen_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah, 1051 TCGArg bl, bool const_bl, 1052 TCGArg bh, bool const_bh, TCGLabel *l) 1053{ 1054 tcg_out_op_rrrrrc(s, INDEX_op_setcond2_i32, TCG_REG_TMP, 1055 al, ah, bl, bh, cond); 1056 tcg_out_op_rl(s, INDEX_op_brcond, TCG_REG_TMP, l); 1057} 1058 1059#if TCG_TARGET_REG_BITS != 32 1060__attribute__((unused)) 1061#endif 1062static const TCGOutOpBrcond2 outop_brcond2 = { 1063 .base.static_constraint = C_O0_I4(r, r, r, r), 1064 .out = tgen_brcond2, 1065}; 1066 1067static void tgen_setcond2(TCGContext *s, TCGCond cond, TCGReg ret, 1068 TCGReg al, TCGReg ah, 1069 TCGArg bl, bool const_bl, 1070 TCGArg bh, bool const_bh) 1071{ 1072 tcg_out_op_rrrrrc(s, INDEX_op_setcond2_i32, ret, al, ah, bl, bh, cond); 1073} 1074 1075#if TCG_TARGET_REG_BITS != 32 1076__attribute__((unused)) 1077#endif 1078static const TCGOutOpSetcond2 outop_setcond2 = { 1079 .base.static_constraint = C_O1_I4(r, r, r, r, r), 1080 .out = tgen_setcond2, 1081}; 1082 1083static void tcg_out_mb(TCGContext *s, unsigned a0) 1084{ 1085 tcg_out_op_v(s, INDEX_op_mb); 1086} 1087 1088static void tcg_out_br(TCGContext *s, TCGLabel *l) 1089{ 1090 tcg_out_op_l(s, INDEX_op_br, l); 1091} 1092 1093static void tgen_ld8u(TCGContext *s, TCGType type, TCGReg dest, 1094 TCGReg base, ptrdiff_t offset) 1095{ 1096 tcg_out_ldst(s, INDEX_op_ld8u, dest, base, offset); 1097} 1098 1099static const TCGOutOpLoad outop_ld8u = { 1100 .base.static_constraint = C_O1_I1(r, r), 1101 .out = tgen_ld8u, 1102}; 1103 1104static void tgen_ld8s(TCGContext *s, TCGType type, TCGReg dest, 1105 TCGReg base, ptrdiff_t offset) 1106{ 1107 tcg_out_ldst(s, INDEX_op_ld8s, dest, base, offset); 1108} 1109 1110static const TCGOutOpLoad outop_ld8s = { 1111 .base.static_constraint = C_O1_I1(r, r), 1112 .out = tgen_ld8s, 1113}; 1114 1115static void tgen_ld16u(TCGContext *s, TCGType type, TCGReg dest, 1116 TCGReg base, ptrdiff_t offset) 1117{ 1118 tcg_out_ldst(s, INDEX_op_ld16u, dest, base, offset); 1119} 1120 1121static const TCGOutOpLoad outop_ld16u = { 1122 .base.static_constraint = C_O1_I1(r, r), 1123 .out = tgen_ld16u, 1124}; 1125 1126static void tgen_ld16s(TCGContext *s, TCGType type, TCGReg dest, 1127 TCGReg base, ptrdiff_t offset) 1128{ 1129 tcg_out_ldst(s, INDEX_op_ld16s, dest, base, offset); 1130} 1131 1132static const TCGOutOpLoad outop_ld16s = { 1133 .base.static_constraint = C_O1_I1(r, r), 1134 .out = tgen_ld16s, 1135}; 1136 1137#if TCG_TARGET_REG_BITS == 64 1138static void tgen_ld32u(TCGContext *s, TCGType type, TCGReg dest, 1139 TCGReg base, ptrdiff_t offset) 1140{ 1141 tcg_out_ldst(s, INDEX_op_ld32u, dest, base, offset); 1142} 1143 1144static const TCGOutOpLoad outop_ld32u = { 1145 .base.static_constraint = C_O1_I1(r, r), 1146 .out = tgen_ld32u, 1147}; 1148 1149static void tgen_ld32s(TCGContext *s, TCGType type, TCGReg dest, 1150 TCGReg base, ptrdiff_t offset) 1151{ 1152 tcg_out_ldst(s, INDEX_op_ld32s, dest, base, offset); 1153} 1154 1155static const TCGOutOpLoad outop_ld32s = { 1156 .base.static_constraint = C_O1_I1(r, r), 1157 .out = tgen_ld32s, 1158}; 1159#endif 1160 1161static void tgen_st8(TCGContext *s, TCGType type, TCGReg data, 1162 TCGReg base, ptrdiff_t offset) 1163{ 1164 tcg_out_ldst(s, INDEX_op_st8, data, base, offset); 1165} 1166 1167static const TCGOutOpStore outop_st8 = { 1168 .base.static_constraint = C_O0_I2(r, r), 1169 .out_r = tgen_st8, 1170}; 1171 1172static void tgen_st16(TCGContext *s, TCGType type, TCGReg data, 1173 TCGReg base, ptrdiff_t offset) 1174{ 1175 tcg_out_ldst(s, INDEX_op_st16, data, base, offset); 1176} 1177 1178static const TCGOutOpStore outop_st16 = { 1179 .base.static_constraint = C_O0_I2(r, r), 1180 .out_r = tgen_st16, 1181}; 1182 1183static const TCGOutOpStore outop_st = { 1184 .base.static_constraint = C_O0_I2(r, r), 1185 .out_r = tcg_out_st, 1186}; 1187 1188static void tgen_qemu_ld(TCGContext *s, TCGType type, TCGReg data, 1189 TCGReg addr, MemOpIdx oi) 1190{ 1191 tcg_out_op_rrm(s, INDEX_op_qemu_ld, data, addr, oi); 1192} 1193 1194static const TCGOutOpQemuLdSt outop_qemu_ld = { 1195 .base.static_constraint = C_O1_I1(r, r), 1196 .out = tgen_qemu_ld, 1197}; 1198 1199static void tgen_qemu_ld2(TCGContext *s, TCGType type, TCGReg datalo, 1200 TCGReg datahi, TCGReg addr, MemOpIdx oi) 1201{ 1202 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_TMP, oi); 1203 tcg_out_op_rrrr(s, INDEX_op_qemu_ld2, datalo, datahi, addr, TCG_REG_TMP); 1204} 1205 1206static const TCGOutOpQemuLdSt2 outop_qemu_ld2 = { 1207 .base.static_constraint = 1208 TCG_TARGET_REG_BITS == 64 ? C_NotImplemented : C_O2_I1(r, r, r), 1209 .out = 1210 TCG_TARGET_REG_BITS == 64 ? NULL : tgen_qemu_ld2, 1211}; 1212 1213static void tgen_qemu_st(TCGContext *s, TCGType type, TCGReg data, 1214 TCGReg addr, MemOpIdx oi) 1215{ 1216 tcg_out_op_rrm(s, INDEX_op_qemu_st, data, addr, oi); 1217} 1218 1219static const TCGOutOpQemuLdSt outop_qemu_st = { 1220 .base.static_constraint = C_O0_I2(r, r), 1221 .out = tgen_qemu_st, 1222}; 1223 1224static void tgen_qemu_st2(TCGContext *s, TCGType type, TCGReg datalo, 1225 TCGReg datahi, TCGReg addr, MemOpIdx oi) 1226{ 1227 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_TMP, oi); 1228 tcg_out_op_rrrr(s, INDEX_op_qemu_st2, datalo, datahi, addr, TCG_REG_TMP); 1229} 1230 1231static const TCGOutOpQemuLdSt2 outop_qemu_st2 = { 1232 .base.static_constraint = 1233 TCG_TARGET_REG_BITS == 64 ? C_NotImplemented : C_O0_I3(r, r, r), 1234 .out = 1235 TCG_TARGET_REG_BITS == 64 ? NULL : tgen_qemu_st2, 1236}; 1237 1238static void tcg_out_st(TCGContext *s, TCGType type, TCGReg val, TCGReg base, 1239 intptr_t offset) 1240{ 1241 TCGOpcode op = INDEX_op_st; 1242 1243 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) { 1244 op = INDEX_op_st32; 1245 } 1246 tcg_out_ldst(s, op, val, base, offset); 1247} 1248 1249static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, 1250 TCGReg base, intptr_t ofs) 1251{ 1252 return false; 1253} 1254 1255/* Test if a constant matches the constraint. */ 1256static bool tcg_target_const_match(int64_t val, int ct, 1257 TCGType type, TCGCond cond, int vece) 1258{ 1259 return ct & TCG_CT_CONST; 1260} 1261 1262static void tcg_out_nop_fill(tcg_insn_unit *p, int count) 1263{ 1264 memset(p, 0, sizeof(*p) * count); 1265} 1266 1267static void tcg_target_init(TCGContext *s) 1268{ 1269 /* The current code uses uint8_t for tcg operations. */ 1270 tcg_debug_assert(tcg_op_defs_max <= UINT8_MAX); 1271 1272 /* Registers available for 32 bit operations. */ 1273 tcg_target_available_regs[TCG_TYPE_I32] = BIT(TCG_TARGET_NB_REGS) - 1; 1274 /* Registers available for 64 bit operations. */ 1275 tcg_target_available_regs[TCG_TYPE_I64] = BIT(TCG_TARGET_NB_REGS) - 1; 1276 /* 1277 * The interpreter "registers" are in the local stack frame and 1278 * cannot be clobbered by the called helper functions. However, 1279 * the interpreter assumes a 128-bit return value and assigns to 1280 * the return value registers. 1281 */ 1282 tcg_target_call_clobber_regs = 1283 MAKE_64BIT_MASK(TCG_REG_R0, 128 / TCG_TARGET_REG_BITS); 1284 1285 s->reserved_regs = 0; 1286 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP); 1287 tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK); 1288 1289 /* The call arguments come first, followed by the temp storage. */ 1290 tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE, 1291 TCG_STATIC_FRAME_SIZE); 1292} 1293 1294/* Generate global QEMU prologue and epilogue code. */ 1295static inline void tcg_target_qemu_prologue(TCGContext *s) 1296{ 1297} 1298 1299static void tcg_out_tb_start(TCGContext *s) 1300{ 1301 /* nothing to do */ 1302} 1303 1304bool tcg_target_has_memory_bswap(MemOp memop) 1305{ 1306 return true; 1307} 1308 1309static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1310{ 1311 g_assert_not_reached(); 1312} 1313 1314static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1315{ 1316 g_assert_not_reached(); 1317} 1318