target-alpha: Introduce functions for source/sink

This will allow cleaner handling of $31 and $f31.
Convert opcodes 0x08, 0x09, 0x10 as examples.

Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2014-03-18 22:55:48 -07:00
parent 64f45e4991
commit 194cfb43d5

View File

@ -49,6 +49,12 @@ struct DisasContext {
/* implver value for this CPU. */ /* implver value for this CPU. */
int implver; int implver;
/* Temporaries for $31 and $f31 as source and destination. */
TCGv zero;
TCGv sink;
/* Temporary for immediate constants. */
TCGv lit;
bool singlestep_enabled; bool singlestep_enabled;
}; };
@ -144,6 +150,71 @@ void alpha_translate_init(void)
done_init = 1; done_init = 1;
} }
static TCGv load_zero(DisasContext *ctx)
{
if (TCGV_IS_UNUSED_I64(ctx->zero)) {
ctx->zero = tcg_const_local_i64(0);
}
return ctx->zero;
}
static TCGv dest_sink(DisasContext *ctx)
{
if (TCGV_IS_UNUSED_I64(ctx->sink)) {
ctx->sink = tcg_temp_local_new();
}
return ctx->sink;
}
static TCGv load_gpr(DisasContext *ctx, unsigned reg)
{
if (likely(reg < 31)) {
return cpu_ir[reg];
} else {
return load_zero(ctx);
}
}
static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
uint8_t lit, bool islit)
{
if (islit) {
ctx->lit = tcg_const_i64(lit);
return ctx->lit;
} else if (likely(reg < 31)) {
return cpu_ir[reg];
} else {
return load_zero(ctx);
}
}
static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
{
if (likely(reg < 31)) {
return cpu_ir[reg];
} else {
return dest_sink(ctx);
}
}
static TCGv __attribute__((unused)) load_fpr(DisasContext *ctx, unsigned reg)
{
if (likely(reg < 31)) {
return cpu_fir[reg];
} else {
return load_zero(ctx);
}
}
static TCGv __attribute__((unused)) dest_fpr(DisasContext *ctx, unsigned reg)
{
if (likely(reg < 31)) {
return cpu_fir[reg];
} else {
return dest_sink(ctx);
}
}
static void gen_excp_1(int exception, int error_code) static void gen_excp_1(int exception, int error_code)
{ {
TCGv_i32 tmp1, tmp2; TCGv_i32 tmp1, tmp2;
@ -1787,8 +1858,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
int32_t disp12; int32_t disp12;
#endif #endif
uint16_t fn11; uint16_t fn11;
uint8_t opc, ra, rb, rc, fpfn, fn7, islit; uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
uint8_t lit; bool islit;
TCGv va, vb, vc, tmp;
ExitStatus ret; ExitStatus ret;
/* Decode all instruction fields */ /* Decode all instruction fields */
@ -1800,8 +1872,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
if (rb == 31 && !islit) { if (rb == 31 && !islit) {
islit = 1; islit = 1;
lit = 0; lit = 0;
} else } else {
lit = (insn >> 13) & 0xFF; lit = (insn >> 13) & 0xFF;
}
palcode = insn & 0x03FFFFFF; palcode = insn & 0x03FFFFFF;
disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11; disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
disp16 = (int16_t)(insn & 0x0000FFFF); disp16 = (int16_t)(insn & 0x0000FFFF);
@ -1841,26 +1914,22 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0x07: case 0x07:
/* OPC07 */ /* OPC07 */
goto invalid_opc; goto invalid_opc;
case 0x08:
/* LDA */
if (likely(ra != 31)) {
if (rb != 31) {
tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16);
} else {
tcg_gen_movi_i64(cpu_ir[ra], disp16);
}
}
break;
case 0x09: case 0x09:
/* LDAH */ /* LDAH */
if (likely(ra != 31)) { disp16 = (uint32_t)disp16 << 16;
if (rb != 31) { /* fall through */
tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16 << 16); case 0x08:
} else { /* LDA */
tcg_gen_movi_i64(cpu_ir[ra], disp16 << 16); va = dest_gpr(ctx, ra);
} /* It's worth special-casing immediate loads. */
if (rb == 31) {
tcg_gen_movi_i64(va, disp16);
} else {
tcg_gen_addi_i64(va, load_gpr(ctx, rb), disp16);
} }
break; break;
case 0x0A: case 0x0A:
/* LDBU */ /* LDBU */
REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX); REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
@ -1889,92 +1958,51 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
/* STQ_U */ /* STQ_U */
gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1); gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
break; break;
case 0x10: case 0x10:
vc = dest_gpr(ctx, rc);
vb = load_gpr_lit(ctx, rb, lit, islit);
if (ra == 31) {
if (fn7 == 0x00) {
/* Special case ADDL as SEXTL. */
tcg_gen_ext32s_i64(vc, vb);
break;
}
if (fn7 == 0x29) {
/* Special case SUBQ as NEGQ. */
tcg_gen_neg_i64(vc, vb);
break;
}
}
va = load_gpr(ctx, ra);
switch (fn7) { switch (fn7) {
case 0x00: case 0x00:
/* ADDL */ /* ADDL */
if (likely(rc != 31)) { tcg_gen_add_i64(vc, va, vb);
if (ra != 31) { tcg_gen_ext32s_i64(vc, vc);
if (islit) {
tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
} else {
tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
}
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], lit);
} else {
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
}
}
}
break; break;
case 0x02: case 0x02:
/* S4ADDL */ /* S4ADDL */
if (likely(rc != 31)) { tmp = tcg_temp_new();
if (ra != 31) { tcg_gen_shli_i64(tmp, va, 2);
TCGv tmp = tcg_temp_new(); tcg_gen_add_i64(tmp, tmp, vb);
tcg_gen_shli_i64(tmp, cpu_ir[ra], 2); tcg_gen_ext32s_i64(vc, tmp);
if (islit) { tcg_temp_free(tmp);
tcg_gen_addi_i64(tmp, tmp, lit);
} else {
tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
}
tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
tcg_temp_free(tmp);
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], lit);
} else {
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
}
}
}
break; break;
case 0x09: case 0x09:
/* SUBL */ /* SUBL */
if (likely(rc != 31)) { tcg_gen_sub_i64(vc, va, vb);
if (ra != 31) { tcg_gen_ext32s_i64(vc, vc);
if (islit) {
tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
} else {
tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
}
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], -lit);
} else {
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
}
}
}
break; break;
case 0x0B: case 0x0B:
/* S4SUBL */ /* S4SUBL */
if (likely(rc != 31)) { tmp = tcg_temp_new();
if (ra != 31) { tcg_gen_shli_i64(tmp, va, 2);
TCGv tmp = tcg_temp_new(); tcg_gen_sub_i64(tmp, tmp, vb);
tcg_gen_shli_i64(tmp, cpu_ir[ra], 2); tcg_gen_ext32s_i64(vc, tmp);
if (islit) { tcg_temp_free(tmp);
tcg_gen_subi_i64(tmp, tmp, lit);
} else {
tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
}
tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
tcg_temp_free(tmp);
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], -lit);
} else {
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
}
}
}
break; break;
case 0x0F: case 0x0F:
/* CMPBGE */ /* CMPBGE */
@ -1982,48 +2010,19 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break; break;
case 0x12: case 0x12:
/* S8ADDL */ /* S8ADDL */
if (likely(rc != 31)) { tmp = tcg_temp_new();
if (ra != 31) { tcg_gen_shli_i64(tmp, va, 3);
TCGv tmp = tcg_temp_new(); tcg_gen_add_i64(tmp, tmp, vb);
tcg_gen_shli_i64(tmp, cpu_ir[ra], 3); tcg_gen_ext32s_i64(vc, tmp);
if (islit) { tcg_temp_free(tmp);
tcg_gen_addi_i64(tmp, tmp, lit);
} else {
tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
}
tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
tcg_temp_free(tmp);
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], lit);
} else {
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
}
}
}
break; break;
case 0x1B: case 0x1B:
/* S8SUBL */ /* S8SUBL */
if (likely(rc != 31)) { tmp = tcg_temp_new();
if (ra != 31) { tcg_gen_shli_i64(tmp, va, 3);
TCGv tmp = tcg_temp_new(); tcg_gen_sub_i64(tmp, tmp, vb);
tcg_gen_shli_i64(tmp, cpu_ir[ra], 3); tcg_gen_ext32s_i64(vc, tmp);
if (islit) { tcg_temp_free(tmp);
tcg_gen_subi_i64(tmp, tmp, lit);
} else {
tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
}
tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
tcg_temp_free(tmp);
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], -lit);
} else {
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
}
}
}
break; break;
case 0x1D: case 0x1D:
/* CMPULT */ /* CMPULT */
@ -2031,81 +2030,25 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break; break;
case 0x20: case 0x20:
/* ADDQ */ /* ADDQ */
if (likely(rc != 31)) { tcg_gen_add_i64(vc, va, vb);
if (ra != 31) {
if (islit) {
tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
} else {
tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
}
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], lit);
} else {
tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
}
}
}
break; break;
case 0x22: case 0x22:
/* S4ADDQ */ /* S4ADDQ */
if (likely(rc != 31)) { tmp = tcg_temp_new();
if (ra != 31) { tcg_gen_shli_i64(tmp, va, 2);
TCGv tmp = tcg_temp_new(); tcg_gen_add_i64(vc, tmp, vb);
tcg_gen_shli_i64(tmp, cpu_ir[ra], 2); tcg_temp_free(tmp);
if (islit) {
tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
} else {
tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
}
tcg_temp_free(tmp);
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], lit);
} else {
tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
}
}
}
break; break;
case 0x29: case 0x29:
/* SUBQ */ /* SUBQ */
if (likely(rc != 31)) { tcg_gen_sub_i64(vc, va, vb);
if (ra != 31) {
if (islit) {
tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
} else {
tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
}
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], -lit);
} else {
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
}
}
}
break; break;
case 0x2B: case 0x2B:
/* S4SUBQ */ /* S4SUBQ */
if (likely(rc != 31)) { tmp = tcg_temp_new();
if (ra != 31) { tcg_gen_shli_i64(tmp, va, 2);
TCGv tmp = tcg_temp_new(); tcg_gen_sub_i64(vc, tmp, vb);
tcg_gen_shli_i64(tmp, cpu_ir[ra], 2); tcg_temp_free(tmp);
if (islit) {
tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
} else {
tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
}
tcg_temp_free(tmp);
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], -lit);
} else {
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
}
}
}
break; break;
case 0x2D: case 0x2D:
/* CMPEQ */ /* CMPEQ */
@ -2113,45 +2056,17 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break; break;
case 0x32: case 0x32:
/* S8ADDQ */ /* S8ADDQ */
if (likely(rc != 31)) { tmp = tcg_temp_new();
if (ra != 31) { tcg_gen_shli_i64(tmp, va, 3);
TCGv tmp = tcg_temp_new(); tcg_gen_add_i64(vc, tmp, vb);
tcg_gen_shli_i64(tmp, cpu_ir[ra], 3); tcg_temp_free(tmp);
if (islit) {
tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
} else {
tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
}
tcg_temp_free(tmp);
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], lit);
} else {
tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
}
}
}
break; break;
case 0x3B: case 0x3B:
/* S8SUBQ */ /* S8SUBQ */
if (likely(rc != 31)) { tmp = tcg_temp_new();
if (ra != 31) { tcg_gen_shli_i64(tmp, va, 3);
TCGv tmp = tcg_temp_new(); tcg_gen_sub_i64(vc, tmp, vb);
tcg_gen_shli_i64(tmp, cpu_ir[ra], 3); tcg_temp_free(tmp);
if (islit) {
tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
} else {
tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
}
tcg_temp_free(tmp);
} else {
if (islit) {
tcg_gen_movi_i64(cpu_ir[rc], -lit);
} else {
tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
}
}
}
break; break;
case 0x3D: case 0x3D:
/* CMPULE */ /* CMPULE */
@ -3506,9 +3421,24 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
tcg_gen_debug_insn_start(ctx.pc); tcg_gen_debug_insn_start(ctx.pc);
} }
TCGV_UNUSED_I64(ctx.zero);
TCGV_UNUSED_I64(ctx.sink);
TCGV_UNUSED_I64(ctx.lit);
ctx.pc += 4; ctx.pc += 4;
ret = translate_one(ctxp, insn); ret = translate_one(ctxp, insn);
if (!TCGV_IS_UNUSED_I64(ctx.sink)) {
tcg_gen_discard_i64(ctx.sink);
tcg_temp_free(ctx.sink);
}
if (!TCGV_IS_UNUSED_I64(ctx.zero)) {
tcg_temp_free(ctx.zero);
}
if (!TCGV_IS_UNUSED_I64(ctx.lit)) {
tcg_temp_free(ctx.lit);
}
/* If we reach a page boundary, are single stepping, /* If we reach a page boundary, are single stepping,
or exhaust instruction count, stop generation. */ or exhaust instruction count, stop generation. */
if (ret == NO_EXIT if (ret == NO_EXIT