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>
master
Richard Henderson 2014-03-18 22:55:48 -07:00
parent 64f45e4991
commit 194cfb43d5
1 changed files with 163 additions and 233 deletions

View File

@ -49,6 +49,12 @@ struct DisasContext {
/* implver value for this CPU. */
int implver;
/* Temporaries for $31 and $f31 as source and destination. */
TCGv zero;
TCGv sink;
/* Temporary for immediate constants. */
TCGv lit;
bool singlestep_enabled;
};
@ -144,6 +150,71 @@ void alpha_translate_init(void)
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)
{
TCGv_i32 tmp1, tmp2;
@ -1787,8 +1858,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
int32_t disp12;
#endif
uint16_t fn11;
uint8_t opc, ra, rb, rc, fpfn, fn7, islit;
uint8_t lit;
uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
bool islit;
TCGv va, vb, vc, tmp;
ExitStatus ret;
/* Decode all instruction fields */
@ -1800,8 +1872,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
if (rb == 31 && !islit) {
islit = 1;
lit = 0;
} else
} else {
lit = (insn >> 13) & 0xFF;
}
palcode = insn & 0x03FFFFFF;
disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
disp16 = (int16_t)(insn & 0x0000FFFF);
@ -1841,26 +1914,22 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0x07:
/* OPC07 */
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:
/* LDAH */
if (likely(ra != 31)) {
if (rb != 31) {
tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16 << 16);
} else {
tcg_gen_movi_i64(cpu_ir[ra], disp16 << 16);
}
disp16 = (uint32_t)disp16 << 16;
/* fall through */
case 0x08:
/* LDA */
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;
case 0x0A:
/* LDBU */
REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
@ -1889,92 +1958,51 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
/* STQ_U */
gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
break;
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) {
case 0x00:
/* ADDL */
if (likely(rc != 31)) {
if (ra != 31) {
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]);
}
}
}
tcg_gen_add_i64(vc, va, vb);
tcg_gen_ext32s_i64(vc, vc);
break;
case 0x02:
/* S4ADDL */
if (likely(rc != 31)) {
if (ra != 31) {
TCGv tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
if (islit) {
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]);
}
}
}
tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, va, 2);
tcg_gen_add_i64(tmp, tmp, vb);
tcg_gen_ext32s_i64(vc, tmp);
tcg_temp_free(tmp);
break;
case 0x09:
/* SUBL */
if (likely(rc != 31)) {
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]);
}
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]);
}
}
}
tcg_gen_sub_i64(vc, va, vb);
tcg_gen_ext32s_i64(vc, vc);
break;
case 0x0B:
/* S4SUBL */
if (likely(rc != 31)) {
if (ra != 31) {
TCGv tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
if (islit) {
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]);
}
}
}
tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, va, 2);
tcg_gen_sub_i64(tmp, tmp, vb);
tcg_gen_ext32s_i64(vc, tmp);
tcg_temp_free(tmp);
break;
case 0x0F:
/* CMPBGE */
@ -1982,48 +2010,19 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x12:
/* S8ADDL */
if (likely(rc != 31)) {
if (ra != 31) {
TCGv tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
if (islit) {
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]);
}
}
}
tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, va, 3);
tcg_gen_add_i64(tmp, tmp, vb);
tcg_gen_ext32s_i64(vc, tmp);
tcg_temp_free(tmp);
break;
case 0x1B:
/* S8SUBL */
if (likely(rc != 31)) {
if (ra != 31) {
TCGv tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
if (islit) {
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]);
}
}
}
tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, va, 3);
tcg_gen_sub_i64(tmp, tmp, vb);
tcg_gen_ext32s_i64(vc, tmp);
tcg_temp_free(tmp);
break;
case 0x1D:
/* CMPULT */
@ -2031,81 +2030,25 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x20:
/* ADDQ */
if (likely(rc != 31)) {
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]);
}
}
}
tcg_gen_add_i64(vc, va, vb);
break;
case 0x22:
/* S4ADDQ */
if (likely(rc != 31)) {
if (ra != 31) {
TCGv tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
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]);
}
}
}
tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, va, 2);
tcg_gen_add_i64(vc, tmp, vb);
tcg_temp_free(tmp);
break;
case 0x29:
/* SUBQ */
if (likely(rc != 31)) {
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]);
}
}
}
tcg_gen_sub_i64(vc, va, vb);
break;
case 0x2B:
/* S4SUBQ */
if (likely(rc != 31)) {
if (ra != 31) {
TCGv tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
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]);
}
}
}
tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, va, 2);
tcg_gen_sub_i64(vc, tmp, vb);
tcg_temp_free(tmp);
break;
case 0x2D:
/* CMPEQ */
@ -2113,45 +2056,17 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x32:
/* S8ADDQ */
if (likely(rc != 31)) {
if (ra != 31) {
TCGv tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
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]);
}
}
}
tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, va, 3);
tcg_gen_add_i64(vc, tmp, vb);
tcg_temp_free(tmp);
break;
case 0x3B:
/* S8SUBQ */
if (likely(rc != 31)) {
if (ra != 31) {
TCGv tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
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]);
}
}
}
tmp = tcg_temp_new();
tcg_gen_shli_i64(tmp, va, 3);
tcg_gen_sub_i64(vc, tmp, vb);
tcg_temp_free(tmp);
break;
case 0x3D:
/* CMPULE */
@ -3506,9 +3421,24 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
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;
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,
or exhaust instruction count, stop generation. */
if (ret == NO_EXIT