Commit cf7c2ca5ff568d4a46674757b8ad545cfb9f6ab4

Authored by blueswir1
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 169 #define INSN_OFF22(x) (((x) >> 2) & 0x3fffff)
170 170  
171 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 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 188 #define BA (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2))
174 189  
175 190 #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00))
176 191 #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01))
  192 +#define ARITH_ANDCC (INSN_OP(2) | INSN_OP3(0x11))
177 193 #define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02))
178 194 #define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03))
179 195 #define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x08))
  196 +#define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x18))
180 197 #define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x10))
181 198 #define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c))
182 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 281 if (check_fit(offset, 13))
265 282 tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |
266 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 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 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 386 /* Generate global QEMU prologue and epilogue code */
327 387 void tcg_target_qemu_prologue(TCGContext *s)
328 388 {
329 389 tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
330 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 392 INSN_RS2(TCG_REG_G0));
333 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 409 case INDEX_op_goto_tb:
350 410 if (s->tb_jmp_offset) {
351 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 416 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
361 417 } else {
362 418 /* indirect jump method */
... ... @@ -374,8 +430,8 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
374 430 & 0x3fffffff));
375 431 tcg_out_nop(s);
376 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 435 INSN_RS2(TCG_REG_G0));
380 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 531 #endif
476 532  
477 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 536 break;
480 537  
481 538 case INDEX_op_qemu_ld8u:
... ...