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