target-ppc: add support for extended mtfsf/mtfsfi forms
Power ISA 2.05 adds support for extended mtfsf/mtfsfi form, with a new W field to select the upper part of the FPCSR register. For that the helper is changed to handle 64-bit input values and mask with up to 16 bits. The mtfsf/mtfsfi instructions do not have the W bit marked as invalid anymore. Instead this is checked in the helper, which therefore needs to access to the insns/insns_flags2. They are added in the DisasContext struct. Finally change all accesses to the opcode fields through extract helpers, prefixed with FP for consistency. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
44bc0c4d3e
commit
7d08d85645
@ -430,20 +430,17 @@ void helper_fpscr_setbit(CPUPPCState *env, uint32_t bit)
|
||||
|
||||
void helper_store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
|
||||
{
|
||||
/*
|
||||
* We use only the 32 LSB of the incoming fpr
|
||||
*/
|
||||
uint32_t prev, new;
|
||||
target_ulong prev, new;
|
||||
int i;
|
||||
|
||||
prev = env->fpscr;
|
||||
new = (uint32_t)arg;
|
||||
new &= ~0x60000000;
|
||||
new |= prev & 0x60000000;
|
||||
for (i = 0; i < 8; i++) {
|
||||
new = (target_ulong)arg;
|
||||
new &= ~0x60000000LL;
|
||||
new |= prev & 0x60000000LL;
|
||||
for (i = 0; i < sizeof(target_ulong) * 2; i++) {
|
||||
if (mask & (1 << i)) {
|
||||
env->fpscr &= ~(0xF << (4 * i));
|
||||
env->fpscr |= new & (0xF << (4 * i));
|
||||
env->fpscr &= ~(0xFLL << (4 * i));
|
||||
env->fpscr |= new & (0xFLL << (4 * i));
|
||||
}
|
||||
}
|
||||
/* Update VX and FEX */
|
||||
|
@ -202,6 +202,8 @@ typedef struct DisasContext {
|
||||
int spe_enabled;
|
||||
ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
|
||||
int singlestep_enabled;
|
||||
uint64_t insns_flags;
|
||||
uint64_t insns_flags2;
|
||||
} DisasContext;
|
||||
|
||||
/* True when active word size < size of target_long. */
|
||||
@ -423,9 +425,14 @@ EXTRACT_HELPER(ME, 1, 5);
|
||||
EXTRACT_HELPER(TO, 21, 5);
|
||||
|
||||
EXTRACT_HELPER(CRM, 12, 8);
|
||||
EXTRACT_HELPER(FM, 17, 8);
|
||||
EXTRACT_HELPER(SR, 16, 4);
|
||||
|
||||
/* mtfsf/mtfsfi */
|
||||
EXTRACT_HELPER(FPBF, 19, 3);
|
||||
EXTRACT_HELPER(FPIMM, 12, 4);
|
||||
EXTRACT_HELPER(FPL, 21, 1);
|
||||
EXTRACT_HELPER(FPFLM, 17, 8);
|
||||
EXTRACT_HELPER(FPW, 16, 1);
|
||||
|
||||
/*** Jump target decoding ***/
|
||||
/* Displacement */
|
||||
@ -2360,19 +2367,27 @@ static void gen_mtfsb1(DisasContext *ctx)
|
||||
static void gen_mtfsf(DisasContext *ctx)
|
||||
{
|
||||
TCGv_i32 t0;
|
||||
int L = ctx->opcode & 0x02000000;
|
||||
int flm, l, w;
|
||||
|
||||
if (unlikely(!ctx->fpu_enabled)) {
|
||||
gen_exception(ctx, POWERPC_EXCP_FPU);
|
||||
return;
|
||||
}
|
||||
flm = FPFLM(ctx->opcode);
|
||||
l = FPL(ctx->opcode);
|
||||
w = FPW(ctx->opcode);
|
||||
if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
|
||||
return;
|
||||
}
|
||||
/* NIP cannot be restored if the memory exception comes from an helper */
|
||||
gen_update_nip(ctx, ctx->nip - 4);
|
||||
gen_reset_fpstatus();
|
||||
if (L)
|
||||
t0 = tcg_const_i32(0xff);
|
||||
else
|
||||
t0 = tcg_const_i32(FM(ctx->opcode));
|
||||
if (l) {
|
||||
t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff);
|
||||
} else {
|
||||
t0 = tcg_const_i32(flm << (w * 8));
|
||||
}
|
||||
gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
|
||||
tcg_temp_free_i32(t0);
|
||||
if (unlikely(Rc(ctx->opcode) != 0)) {
|
||||
@ -2386,7 +2401,7 @@ static void gen_mtfsf(DisasContext *ctx)
|
||||
/* mtfsfi */
|
||||
static void gen_mtfsfi(DisasContext *ctx)
|
||||
{
|
||||
int bf, sh;
|
||||
int bf, sh, w;
|
||||
TCGv_i64 t0;
|
||||
TCGv_i32 t1;
|
||||
|
||||
@ -2394,12 +2409,17 @@ static void gen_mtfsfi(DisasContext *ctx)
|
||||
gen_exception(ctx, POWERPC_EXCP_FPU);
|
||||
return;
|
||||
}
|
||||
bf = crbD(ctx->opcode) >> 2;
|
||||
sh = 7 - bf;
|
||||
w = FPW(ctx->opcode);
|
||||
bf = FPBF(ctx->opcode);
|
||||
if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
|
||||
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
|
||||
return;
|
||||
}
|
||||
sh = (8 * w) + 7 - bf;
|
||||
/* NIP cannot be restored if the memory exception comes from an helper */
|
||||
gen_update_nip(ctx, ctx->nip - 4);
|
||||
gen_reset_fpstatus();
|
||||
t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
|
||||
t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
|
||||
t1 = tcg_const_i32(1 << sh);
|
||||
gen_helper_store_fpscr(cpu_env, t0, t1);
|
||||
tcg_temp_free_i64(t0);
|
||||
@ -8689,8 +8709,8 @@ GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
|
||||
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
|
||||
GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
|
||||
GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
|
||||
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT),
|
||||
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT),
|
||||
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00000000, PPC_FLOAT),
|
||||
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006e0800, PPC_FLOAT),
|
||||
#if defined(TARGET_PPC64)
|
||||
GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
|
||||
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
|
||||
@ -9728,6 +9748,8 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
|
||||
ctx.exception = POWERPC_EXCP_NONE;
|
||||
ctx.spr_cb = env->spr_cb;
|
||||
ctx.mem_idx = env->mmu_idx;
|
||||
ctx.insns_flags = env->insns_flags;
|
||||
ctx.insns_flags2 = env->insns_flags2;
|
||||
ctx.access_type = -1;
|
||||
ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
|
||||
#if defined(TARGET_PPC64)
|
||||
|
Loading…
Reference in New Issue
Block a user