* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#define CPU_NO_GLOBAL_REGS
+
#include "exec.h"
#include "exec-all.h"
#include "host-utils.h"
+#include "ioport.h"
//#define DEBUG_PCALL
new_segs[R_GS] = 0;
new_trap = 0;
}
+ /* XXX: avoid a compiler warning, see
+ http://support.amd.com/us/Processor_TechDocs/24593.pdf
+ chapters 12.2.5 and 13.2.4 on how to implement TSS Trap bit */
+ (void)new_trap;
/* NOTE: we must avoid memory exceptions during the task switch,
so we make dummy accesses before */
#if 0
{
int i;
- uint8_t *ptr;
+ target_ulong ptr;
qemu_log(" code=");
ptr = env->segs[R_CS].base + env->eip;
for(i = 0; i < 16; i++) {
raise_interrupt(exception_index, 0, 0, 0);
}
+void raise_exception_env(int exception_index, CPUState *nenv)
+{
+ env = nenv;
+ raise_exception(exception_index);
+}
/* SMM support */
#if defined(CONFIG_USER_ONLY)
break;
case 8:
if (!(env->hflags2 & HF2_VINTR_MASK)) {
- val = cpu_get_apic_tpr(env);
+ val = cpu_get_apic_tpr(env->apic_state);
} else {
val = env->v_tpr;
}
break;
case 8:
if (!(env->hflags2 & HF2_VINTR_MASK)) {
- cpu_set_apic_tpr(env, t0);
+ cpu_set_apic_tpr(env->apic_state, t0);
}
env->v_tpr = t0 & 0x0f;
break;
EDX = (uint32_t)(val >> 32);
}
+void helper_rdtscp(void)
+{
+ helper_rdtsc();
+ ECX = (uint32_t)(env->tsc_aux);
+}
+
void helper_rdpmc(void)
{
if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
env->sysenter_eip = val;
break;
case MSR_IA32_APICBASE:
- cpu_set_apic_base(env, val);
+ cpu_set_apic_base(env->apic_state, val);
break;
case MSR_EFER:
{
&& (val == 0 || val == ~(uint64_t)0))
env->mcg_ctl = val;
break;
+ case MSR_TSC_AUX:
+ env->tsc_aux = val;
+ break;
default:
if ((uint32_t)ECX >= MSR_MC0_CTL
&& (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
val = env->sysenter_eip;
break;
case MSR_IA32_APICBASE:
- val = cpu_get_apic_base(env);
+ val = cpu_get_apic_base(env->apic_state);
break;
case MSR_EFER:
val = env->efer;
case MSR_KERNELGSBASE:
val = env->kernelgsbase;
break;
+ case MSR_TSC_AUX:
+ val = env->tsc_aux;
+ break;
#endif
case MSR_MTRRphysBase(0):
case MSR_MTRRphysBase(1):
void helper_fadd_ST0_FT0(void)
{
- ST0 += FT0;
+ ST0 = floatx_add(ST0, FT0, &env->fp_status);
}
void helper_fmul_ST0_FT0(void)
{
- ST0 *= FT0;
+ ST0 = floatx_mul(ST0, FT0, &env->fp_status);
}
void helper_fsub_ST0_FT0(void)
{
- ST0 -= FT0;
+ ST0 = floatx_sub(ST0, FT0, &env->fp_status);
}
void helper_fsubr_ST0_FT0(void)
{
- ST0 = FT0 - ST0;
+ ST0 = floatx_sub(FT0, ST0, &env->fp_status);
}
void helper_fdiv_ST0_FT0(void)
void helper_fadd_STN_ST0(int st_index)
{
- ST(st_index) += ST0;
+ ST(st_index) = floatx_add(ST(st_index), ST0, &env->fp_status);
}
void helper_fmul_STN_ST0(int st_index)
{
- ST(st_index) *= ST0;
+ ST(st_index) = floatx_mul(ST(st_index), ST0, &env->fp_status);
}
void helper_fsub_STN_ST0(int st_index)
{
- ST(st_index) -= ST0;
+ ST(st_index) = floatx_sub(ST(st_index), ST0, &env->fp_status);
}
void helper_fsubr_STN_ST0(int st_index)
{
- CPU86_LDouble *p;
- p = &ST(st_index);
- *p = ST0 - *p;
+ ST(st_index) = floatx_sub(ST0, ST(st_index), &env->fp_status);
}
void helper_fdiv_STN_ST0(int st_index)
v = ldub(ptr + i);
val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
}
- tmp = val;
- if (ldub(ptr + 9) & 0x80)
- tmp = -tmp;
+ tmp = int64_to_floatx(val, &env->fp_status);
+ if (ldub(ptr + 9) & 0x80) {
+ floatx_chs(tmp);
+ }
fpush();
ST0 = tmp;
}
void helper_fxtract(void)
{
CPU86_LDoubleU temp;
- unsigned int expdif;
temp.d = ST0;
- expdif = EXPD(temp) - EXPBIAS;
- /*DP exponent bias*/
- ST0 = expdif;
- fpush();
- BIASEXPONENT(temp);
- ST0 = temp.d;
+
+ if (floatx_is_zero(ST0)) {
+ /* Easy way to generate -inf and raising division by 0 exception */
+ ST0 = floatx_div(floatx_chs(floatx_one), floatx_zero, &env->fp_status);
+ fpush();
+ ST0 = temp.d;
+ } else {
+ int expdif;
+
+ expdif = EXPD(temp) - EXPBIAS;
+ /*DP exponent bias*/
+ ST0 = int32_to_floatx(expdif, &env->fp_status);
+ fpush();
+ BIASEXPONENT(temp);
+ ST0 = temp.d;
+ }
}
void helper_fprem1(void)
void helper_fscale(void)
{
- ST0 = ldexp (ST0, (int)(ST1));
+ if (floatx_is_any_nan(ST1)) {
+ ST0 = ST1;
+ } else {
+ int n = floatx_to_int32_round_to_zero(ST1, &env->fp_status);
+ ST0 = floatx_scalbn(ST0, n, &env->fp_status);
+ }
}
void helper_fsin(void)
CPU86_LDouble tmp;
target_ulong addr;
+ /* The operand must be 16 byte aligned */
+ if (ptr & 0xf) {
+ raise_exception(EXCP0D_GPF);
+ }
+
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
fptag = 0;
for(i = 0; i < 8; i++) {
CPU86_LDouble tmp;
target_ulong addr;
+ /* The operand must be 16 byte aligned */
+ if (ptr & 0xf) {
+ raise_exception(EXCP0D_GPF);
+ }
+
env->fpuc = lduw(ptr);
fpus = lduw(ptr + 2);
fptag = lduw(ptr + 4);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
raise_exception_err(env->exception_index, env->error_code);
switch((uint32_t)ECX) {
case 0 ... 0x1fff:
t0 = (ECX * 2) % 8;
- t1 = ECX / 8;
+ t1 = (ECX * 2) / 8;
break;
case 0xc0000000 ... 0xc0001fff:
t0 = (8192 + ECX - 0xc0000000) * 2;
ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)));
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info_err),
ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err)));
+ stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), 0);
env->hflags2 &= ~HF2_GIF_MASK;
/* FIXME: Resets the current ASID register to zero (host ASID). */
return count;
}
-target_ulong helper_bsr(target_ulong t0)
+target_ulong helper_lzcnt(target_ulong t0, int wordsize)
{
int count;
target_ulong res, mask;
-
+
+ if (wordsize > 0 && t0 == 0) {
+ return wordsize;
+ }
res = t0;
count = TARGET_LONG_BITS - 1;
mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
count--;
res <<= 1;
}
+ if (wordsize > 0) {
+ return wordsize - 1 - count;
+ }
return count;
}
+target_ulong helper_bsr(target_ulong t0)
+{
+ return helper_lzcnt(t0, 0);
+}
static int compute_all_eflags(void)
{