target-s390: Convert FP LOAD

Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2012-09-05 12:24:24 -07:00
parent e1eaada955
commit d764a8d12b
2 changed files with 74 additions and 35 deletions

View File

@ -173,6 +173,13 @@
C(0xb914, LGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, 0)
C(0xe304, LG, RXY_a, Z, 0, a2, r1, 0, ld64, 0)
C(0xe314, LGF, RXY_a, Z, 0, a2, r1, 0, ld32s, 0)
C(0x2800, LDR, RR_a, Z, 0, f2_o, 0, f1, mov2, 0)
C(0x6800, LD, RX_a, Z, 0, m2_64, 0, f1, mov2, 0)
C(0xed65, LDY, RXY_a, LD, 0, m2_64, 0, f1, mov2, 0)
C(0x3800, LER, RR_a, Z, 0, e2, 0, cond_e1e2, mov2, 0)
C(0x7800, LE, RX_a, Z, 0, m2_32u, 0, e1, mov2, 0)
C(0xed64, LEY, RXY_a, LD, 0, m2_32u, 0, e1, mov2, 0)
C(0xb365, LXR, RRE, Z, 0, x2_o, 0, x1, movx, 0)
/* LOAD IMMEDIATE */
C(0xc001, LGFI, RIL_a, EI, 0, i2, 0, r1, mov2, 0)
/* LOAD RELATIVE LONG */

View File

@ -224,6 +224,13 @@ static inline TCGv_i32 load_freg32(int reg)
return r;
}
static inline TCGv_i64 load_freg32_i64(int reg)
{
TCGv_i64 r = tcg_temp_new_i64();
tcg_gen_shri_i64(r, fregs[reg], 32);
return r;
}
static inline TCGv_i32 load_reg32(int reg)
{
TCGv_i32 r = tcg_temp_new_i32();
@ -293,6 +300,11 @@ static inline void store_freg32(int reg, TCGv_i32 v)
#endif
}
static inline void store_freg32_i64(int reg, TCGv_i64 v)
{
tcg_gen_deposit_i64(fregs[reg], fregs[reg], v, 32, 32);
}
static inline void return_low128(TCGv_i64 dest)
{
tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
@ -2371,20 +2383,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
case 0x28: /* LDR R1,R2 [RR] */
insn = ld_code2(env, s->pc);
decode_rr(s, insn, &r1, &r2);
tmp = load_freg(r2);
store_freg(r1, tmp);
tcg_temp_free_i64(tmp);
break;
case 0x38: /* LER R1,R2 [RR] */
insn = ld_code2(env, s->pc);
decode_rr(s, insn, &r1, &r2);
tmp32_1 = load_freg32(r2);
store_freg32(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
case 0x43: /* IC R1,D2(X2,B2) [RX] */
insn = ld_code4(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@ -2427,15 +2425,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
case 0x68: /* LD R1,D2(X2,B2) [RX] */
insn = ld_code4(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
tmp2 = tcg_temp_new_i64();
tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
store_freg(r1, tmp2);
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
case 0x70: /* STE R1,D2(X2,B2) [RX] */
insn = ld_code4(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@ -2447,18 +2436,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
case 0x78: /* LE R1,D2(X2,B2) [RX] */
insn = ld_code4(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
tmp2 = tcg_temp_new_i64();
tmp32_1 = tcg_temp_new_i32();
tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
store_freg32(r1, tmp32_1);
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
#ifndef CONFIG_USER_ONLY
case 0x80: /* SSM D2(B2) [S] */
/* Set System Mask */
@ -3596,6 +3573,18 @@ static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
static ExitStatus op_movx(DisasContext *s, DisasOps *o)
{
o->out = o->in1;
o->out2 = o->in2;
o->g_out = o->g_in1;
o->g_out2 = o->g_in2;
TCGV_UNUSED_I64(o->in1);
TCGV_UNUSED_I64(o->in2);
o->g_in1 = o->g_in2 = false;
return NO_EXIT;
}
static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
{
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
@ -3955,6 +3944,23 @@ static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
store_reg32_i64(r1, o->out);
}
static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o)
{
store_freg32_i64(get_field(f, r1), o->out);
}
static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
{
store_freg(get_field(f, r1), o->out);
}
static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
{
int f1 = get_field(s->fields, r1);
store_freg(f1, o->out);
store_freg((f1 + 2) & 15, o->out2);
}
static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
if (get_field(f, r1) != get_field(f, r2)) {
@ -3962,6 +3968,13 @@ static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
}
}
static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
{
if (get_field(f, r1) != get_field(f, r2)) {
store_freg32_i64(get_field(f, r1), o->out);
}
}
static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
@ -4137,6 +4150,25 @@ static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
}
static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = load_freg32_i64(get_field(f, r2));
}
static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = fregs[get_field(f, r2)];
o->g_in2 = true;
}
static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
int f2 = get_field(f, r2);
o->in1 = fregs[f2];
o->in2 = fregs[(f2 + 2) & 15];
o->g_in1 = o->g_in2 = true;
}
static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
{
int x2 = have_field(f, x2) ? get_field(f, x2) : 0;