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