Commit cf7c2ca5ff568d4a46674757b8ad545cfb9f6ab4
1 parent
f02ca5cb
Implement brcond, ldst with large offset; fix direct jump, prologue
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4461 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
71 additions
and
14 deletions
tcg/sparc/tcg-target.c
| @@ -169,14 +169,31 @@ static inline int tcg_target_const_match(tcg_target_long val, | @@ -169,14 +169,31 @@ static inline int tcg_target_const_match(tcg_target_long val, | ||
| 169 | #define INSN_OFF22(x) (((x) >> 2) & 0x3fffff) | 169 | #define INSN_OFF22(x) (((x) >> 2) & 0x3fffff) |
| 170 | 170 | ||
| 171 | #define INSN_COND(x, a) (((x) << 25) | ((a) << 29)) | 171 | #define INSN_COND(x, a) (((x) << 25) | ((a) << 29)) |
| 172 | +#define COND_N 0x0 | ||
| 173 | +#define COND_E 0x1 | ||
| 174 | +#define COND_LE 0x2 | ||
| 175 | +#define COND_L 0x3 | ||
| 176 | +#define COND_LEU 0x4 | ||
| 177 | +#define COND_CS 0x5 | ||
| 178 | +#define COND_NEG 0x6 | ||
| 179 | +#define COND_VS 0x7 | ||
| 172 | #define COND_A 0x8 | 180 | #define COND_A 0x8 |
| 181 | +#define COND_NE 0x9 | ||
| 182 | +#define COND_G 0xa | ||
| 183 | +#define COND_GE 0xb | ||
| 184 | +#define COND_GU 0xc | ||
| 185 | +#define COND_CC 0xd | ||
| 186 | +#define COND_POS 0xe | ||
| 187 | +#define COND_VC 0xf | ||
| 173 | #define BA (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2)) | 188 | #define BA (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2)) |
| 174 | 189 | ||
| 175 | #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00)) | 190 | #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00)) |
| 176 | #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01)) | 191 | #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01)) |
| 192 | +#define ARITH_ANDCC (INSN_OP(2) | INSN_OP3(0x11)) | ||
| 177 | #define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02)) | 193 | #define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02)) |
| 178 | #define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03)) | 194 | #define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03)) |
| 179 | #define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x08)) | 195 | #define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x08)) |
| 196 | +#define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x18)) | ||
| 180 | #define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x10)) | 197 | #define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x10)) |
| 181 | #define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c)) | 198 | #define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c)) |
| 182 | #define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a)) | 199 | #define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a)) |
| @@ -264,8 +281,11 @@ static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, in | @@ -264,8 +281,11 @@ static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, in | ||
| 264 | if (check_fit(offset, 13)) | 281 | if (check_fit(offset, 13)) |
| 265 | tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) | | 282 | tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) | |
| 266 | INSN_IMM13(offset)); | 283 | INSN_IMM13(offset)); |
| 267 | - else | ||
| 268 | - fprintf(stderr, "unimplemented %s with offset %d\n", __func__, offset); | 284 | + else { |
| 285 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset); | ||
| 286 | + tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) | | ||
| 287 | + INSN_RS2(addr)); | ||
| 288 | + } | ||
| 269 | } | 289 | } |
| 270 | 290 | ||
| 271 | static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret, | 291 | static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret, |
| @@ -323,12 +343,52 @@ static inline void tcg_out_nop(TCGContext *s) | @@ -323,12 +343,52 @@ static inline void tcg_out_nop(TCGContext *s) | ||
| 323 | tcg_out32(s, SETHI | INSN_RD(TCG_REG_G0) | 0); | 343 | tcg_out32(s, SETHI | INSN_RD(TCG_REG_G0) | 0); |
| 324 | } | 344 | } |
| 325 | 345 | ||
| 346 | +static void tcg_out_branch(TCGContext *s, int opc, int label_index) | ||
| 347 | +{ | ||
| 348 | + int32_t val; | ||
| 349 | + TCGLabel *l = &s->labels[label_index]; | ||
| 350 | + | ||
| 351 | + if (l->has_value) { | ||
| 352 | + val = l->u.value - (tcg_target_long)s->code_ptr; | ||
| 353 | + tcg_out32(s, (INSN_OP(0) | opc | INSN_OP2(0x2) | ||
| 354 | + | INSN_OFF22(l->u.value - (unsigned long)s->code_ptr))); | ||
| 355 | + } else | ||
| 356 | + fprintf(stderr, "unimplemented branch\n"); | ||
| 357 | +} | ||
| 358 | + | ||
| 359 | +static const uint8_t tcg_cond_to_bcond[10] = { | ||
| 360 | + [TCG_COND_EQ] = COND_E, | ||
| 361 | + [TCG_COND_NE] = COND_NE, | ||
| 362 | + [TCG_COND_LT] = COND_L, | ||
| 363 | + [TCG_COND_GE] = COND_GE, | ||
| 364 | + [TCG_COND_LE] = COND_LE, | ||
| 365 | + [TCG_COND_GT] = COND_G, | ||
| 366 | + [TCG_COND_LTU] = COND_CS, | ||
| 367 | + [TCG_COND_GEU] = COND_CC, | ||
| 368 | + [TCG_COND_LEU] = COND_LEU, | ||
| 369 | + [TCG_COND_GTU] = COND_GU, | ||
| 370 | +}; | ||
| 371 | + | ||
| 372 | +static void tcg_out_brcond(TCGContext *s, int cond, | ||
| 373 | + TCGArg arg1, TCGArg arg2, int const_arg2, | ||
| 374 | + int label_index) | ||
| 375 | +{ | ||
| 376 | + if (const_arg2 && arg2 == 0) | ||
| 377 | + /* andcc r, r, %g0 */ | ||
| 378 | + tcg_out_arithi(s, TCG_REG_G0, arg1, arg1, ARITH_ANDCC); | ||
| 379 | + else | ||
| 380 | + /* subcc r1, r2, %g0 */ | ||
| 381 | + tcg_out_arith(s, TCG_REG_G0, arg1, arg2, ARITH_SUBCC); | ||
| 382 | + tcg_out_branch(s, tcg_cond_to_bcond[cond], label_index); | ||
| 383 | + tcg_out_nop(s); | ||
| 384 | +} | ||
| 385 | + | ||
| 326 | /* Generate global QEMU prologue and epilogue code */ | 386 | /* Generate global QEMU prologue and epilogue code */ |
| 327 | void tcg_target_qemu_prologue(TCGContext *s) | 387 | void tcg_target_qemu_prologue(TCGContext *s) |
| 328 | { | 388 | { |
| 329 | tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) | | 389 | tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) | |
| 330 | INSN_IMM13(-TCG_TARGET_STACK_MINFRAME)); | 390 | INSN_IMM13(-TCG_TARGET_STACK_MINFRAME)); |
| 331 | - tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_O0) | | 391 | + tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I0) | |
| 332 | INSN_RS2(TCG_REG_G0)); | 392 | INSN_RS2(TCG_REG_G0)); |
| 333 | tcg_out_nop(s); | 393 | tcg_out_nop(s); |
| 334 | } | 394 | } |
| @@ -349,14 +409,10 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -349,14 +409,10 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 349 | case INDEX_op_goto_tb: | 409 | case INDEX_op_goto_tb: |
| 350 | if (s->tb_jmp_offset) { | 410 | if (s->tb_jmp_offset) { |
| 351 | /* direct jump method */ | 411 | /* direct jump method */ |
| 352 | - if (check_fit(args[0] - (unsigned long)s->code_ptr, 26)) { | ||
| 353 | - tcg_out32(s, BA | | ||
| 354 | - INSN_OFF22(args[0] - (unsigned long)s->code_ptr)); | ||
| 355 | - } else { | ||
| 356 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, args[0]); | ||
| 357 | - tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) | | ||
| 358 | - INSN_RS2(TCG_REG_G0)); | ||
| 359 | - } | 412 | + tcg_out32(s, SETHI | INSN_RD(TCG_REG_I5) | |
| 413 | + ((args[0] & 0xffffe000) >> 10)); | ||
| 414 | + tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) | | ||
| 415 | + INSN_IMM13((args[0] & 0x1fff))); | ||
| 360 | s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; | 416 | s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; |
| 361 | } else { | 417 | } else { |
| 362 | /* indirect jump method */ | 418 | /* indirect jump method */ |
| @@ -374,8 +430,8 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -374,8 +430,8 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 374 | & 0x3fffffff)); | 430 | & 0x3fffffff)); |
| 375 | tcg_out_nop(s); | 431 | tcg_out_nop(s); |
| 376 | } else { | 432 | } else { |
| 377 | - tcg_out_ld_ptr(s, TCG_REG_O7, (tcg_target_long)(s->tb_next + args[0])); | ||
| 378 | - tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_O7) | | 433 | + tcg_out_ld_ptr(s, TCG_REG_I5, (tcg_target_long)(s->tb_next + args[0])); |
| 434 | + tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_I5) | | ||
| 379 | INSN_RS2(TCG_REG_G0)); | 435 | INSN_RS2(TCG_REG_G0)); |
| 380 | tcg_out_nop(s); | 436 | tcg_out_nop(s); |
| 381 | } | 437 | } |
| @@ -475,7 +531,8 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -475,7 +531,8 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 475 | #endif | 531 | #endif |
| 476 | 532 | ||
| 477 | case INDEX_op_brcond_i32: | 533 | case INDEX_op_brcond_i32: |
| 478 | - fprintf(stderr, "unimplemented brcond\n"); | 534 | + tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], |
| 535 | + args[3]); | ||
| 479 | break; | 536 | break; |
| 480 | 537 | ||
| 481 | case INDEX_op_qemu_ld8u: | 538 | case INDEX_op_qemu_ld8u: |