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