diff options
author | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-12-06 12:19:14 +0000 |
---|---|---|
committer | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-12-06 12:19:14 +0000 |
commit | 22e0e173376d702bdd9757d308924b6df7cd6529 (patch) | |
tree | 102fa053e511450ad57df19e14bbfbf77db7a7d8 /target-ppc/op_helper.c | |
parent | 3b63c04e1bcf626ca24d3fa92b5872c73f1ba8d5 (diff) |
target-ppc: convert POWER bridge instructions to TCG
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5891 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/op_helper.c')
-rw-r--r-- | target-ppc/op_helper.c | 133 |
1 files changed, 44 insertions, 89 deletions
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index de6369a9bb..7f028fa791 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -1587,147 +1587,101 @@ void do_POWER_abso (void) } } -void do_POWER_clcs (void) +target_ulong helper_clcs (uint32_t arg) { - switch (T0) { + switch (arg) { case 0x0CUL: /* Instruction cache line size */ - T0 = env->icache_line_size; + return env->icache_line_size; break; case 0x0DUL: /* Data cache line size */ - T0 = env->dcache_line_size; + return env->dcache_line_size; break; case 0x0EUL: /* Minimum cache line size */ - T0 = env->icache_line_size < env->dcache_line_size ? - env->icache_line_size : env->dcache_line_size; + return (env->icache_line_size < env->dcache_line_size) ? + env->icache_line_size : env->dcache_line_size; break; case 0x0FUL: /* Maximum cache line size */ - T0 = env->icache_line_size > env->dcache_line_size ? - env->icache_line_size : env->dcache_line_size; + return (env->icache_line_size > env->dcache_line_size) ? + env->icache_line_size : env->dcache_line_size; break; default: /* Undefined */ + return 0; break; } } -void do_POWER_div (void) +target_ulong helper_div (target_ulong arg1, target_ulong arg2) { - uint64_t tmp; + uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ]; - if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || - (int32_t)T1 == 0) { - T0 = UINT32_MAX * ((uint32_t)T0 >> 31); + if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || + (int32_t)arg2 == 0) { env->spr[SPR_MQ] = 0; + return INT32_MIN; } else { - tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ]; - env->spr[SPR_MQ] = tmp % T1; - T0 = tmp / (int32_t)T1; + env->spr[SPR_MQ] = tmp % arg2; + return tmp / (int32_t)arg2; } } -void do_POWER_divo (void) +target_ulong helper_divo (target_ulong arg1, target_ulong arg2) { - int64_t tmp; + uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ]; - if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || - (int32_t)T1 == 0) { - T0 = UINT32_MAX * ((uint32_t)T0 >> 31); - env->spr[SPR_MQ] = 0; + if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || + (int32_t)arg2 == 0) { env->xer |= (1 << XER_OV) | (1 << XER_SO); - } else { - tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ]; - env->spr[SPR_MQ] = tmp % T1; - tmp /= (int32_t)T1; - if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) { - env->xer |= (1 << XER_OV) | (1 << XER_SO); - } else { - env->xer &= ~(1 << XER_OV); - } - T0 = tmp; - } -} - -void do_POWER_divs (void) -{ - if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || - (int32_t)T1 == 0) { - T0 = UINT32_MAX * ((uint32_t)T0 >> 31); - env->spr[SPR_MQ] = 0; - } else { - env->spr[SPR_MQ] = T0 % T1; - T0 = (int32_t)T0 / (int32_t)T1; - } -} - -void do_POWER_divso (void) -{ - if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || - (int32_t)T1 == 0) { - T0 = UINT32_MAX * ((uint32_t)T0 >> 31); env->spr[SPR_MQ] = 0; - env->xer |= (1 << XER_OV) | (1 << XER_SO); + return INT32_MIN; } else { - T0 = (int32_t)T0 / (int32_t)T1; - env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1; - env->xer &= ~(1 << XER_OV); - } -} - -void do_POWER_dozo (void) -{ - if ((int32_t)T1 > (int32_t)T0) { - T2 = T0; - T0 = T1 - T0; - if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) & - ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) { + env->spr[SPR_MQ] = tmp % arg2; + tmp /= (int32_t)arg2; + if ((int32_t)tmp != tmp) { env->xer |= (1 << XER_OV) | (1 << XER_SO); } else { env->xer &= ~(1 << XER_OV); } - } else { - T0 = 0; - env->xer &= ~(1 << XER_OV); + return tmp; } } -void do_POWER_maskg (void) +target_ulong helper_divs (target_ulong arg1, target_ulong arg2) { - uint32_t ret; - - if ((uint32_t)T0 == (uint32_t)(T1 + 1)) { - ret = UINT32_MAX; + if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || + (int32_t)arg2 == 0) { + env->spr[SPR_MQ] = 0; + return INT32_MIN; } else { - ret = (UINT32_MAX >> ((uint32_t)T0)) ^ - ((UINT32_MAX >> ((uint32_t)T1)) >> 1); - if ((uint32_t)T0 > (uint32_t)T1) - ret = ~ret; + env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2; + return (int32_t)arg1 / (int32_t)arg2; } - T0 = ret; } -void do_POWER_mulo (void) +target_ulong helper_divso (target_ulong arg1, target_ulong arg2) { - uint64_t tmp; - - tmp = (uint64_t)T0 * (uint64_t)T1; - env->spr[SPR_MQ] = tmp >> 32; - T0 = tmp; - if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) { + if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) || + (int32_t)arg2 == 0) { env->xer |= (1 << XER_OV) | (1 << XER_SO); + env->spr[SPR_MQ] = 0; + return INT32_MIN; } else { env->xer &= ~(1 << XER_OV); + env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2; + return (int32_t)arg1 / (int32_t)arg2; } } #if !defined (CONFIG_USER_ONLY) -void do_POWER_rac (void) +target_ulong helper_rac (target_ulong addr) { mmu_ctx_t ctx; int nb_BATs; + target_ulong ret = 0; /* We don't have to generate many instances of this instruction, * as rac is supervisor only. @@ -1735,9 +1689,10 @@ void do_POWER_rac (void) /* XXX: FIX THIS: Pretend we have no BAT */ nb_BATs = env->nb_BATs; env->nb_BATs = 0; - if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT) == 0) - T0 = ctx.raddr; + if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) + ret = ctx.raddr; env->nb_BATs = nb_BATs; + return ret; } void helper_rfsvc (void) |