Revision cf7c2ca5
b/tcg/sparc/tcg-target.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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: |
Also available in: Unified diff