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: |