Index: hw/apic.c =================================================================== RCS file: /cvsroot/qemu/qemu/hw/apic.c,v retrieving revision 1.1 diff -u -r1.1 apic.c --- hw/apic.c 3 Jan 2005 23:27:31 -0000 1.1 +++ hw/apic.c 21 Jan 2005 20:13:30 -0000 @@ -100,6 +100,18 @@ return s->apicbase; } +void cpu_set_apic_tpr(CPUState *env, uint8_t val) +{ + APICState *s = env->apic_state; + s->tpr = val; +} + +uint8_t cpu_get_apic_tpr(CPUState *env) +{ + APICState *s = env->apic_state; + return s->tpr; +} + /* return -1 if no bit is set */ static int get_highest_priority_int(uint32_t *tab) { Index: target-i386/exec.h =================================================================== RCS file: /cvsroot/qemu/qemu/target-i386/exec.h,v retrieving revision 1.20 diff -u -r1.20 exec.h --- target-i386/exec.h 8 Jan 2005 18:58:29 -0000 1.20 +++ target-i386/exec.h 21 Jan 2005 20:23:30 -0000 @@ -167,6 +167,8 @@ void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr); int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, int is_write, int is_user, int is_softmmu); +void cpu_set_apic_tpr(CPUX86State *env, uint8_t val); +uint8_t cpu_get_apic_tpr(CPUX86State *env); void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr); void __hidden cpu_lock(void); Index: target-i386/helper.c =================================================================== RCS file: /cvsroot/qemu/qemu/target-i386/helper.c,v retrieving revision 1.40 diff -u -r1.40 helper.c --- target-i386/helper.c 16 Jan 2005 23:35:43 -0000 1.40 +++ target-i386/helper.c 21 Jan 2005 22:18:01 -0000 @@ -1454,8 +1454,12 @@ selector &= 0xffff; if ((selector & 0xfffc) == 0) { /* null selector case */ - if (seg_reg == R_SS) - raise_exception_err(EXCP0D_GPF, 0); + if (seg_reg == R_SS) { +#ifdef TARGET_X86_64 + if (!env->hflags & HF_CS64_MASK) +#endif + raise_exception_err(EXCP0D_GPF, 0); + } cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0); } else { @@ -2156,6 +2160,11 @@ case 4: cpu_x86_update_cr4(env, T0); break; +#ifdef TARGET_X86_64 + case 8: + cpu_set_apic_tpr(env, (T0 & 0xf) << 4); + break; +#endif default: env->cr[reg] = T0; break; Index: target-i386/op.c =================================================================== RCS file: /cvsroot/qemu/qemu/target-i386/op.c,v retrieving revision 1.28 diff -u -r1.28 op.c --- target-i386/op.c 9 Jan 2005 00:07:04 -0000 1.28 +++ target-i386/op.c 21 Jan 2005 22:09:18 -0000 @@ -1198,6 +1198,11 @@ helper_movl_crN_T0(PARAM1); } +void OPPROTO op_movtl_T0_cr8(void) +{ + T0 = (cpu_get_apic_tpr(env) & 0xf0) >> 4; +} + /* DR registers access */ void OPPROTO op_movl_drN_T0(void) { Index: target-i386/translate.c =================================================================== RCS file: /cvsroot/qemu/qemu/target-i386/translate.c,v retrieving revision 1.41 diff -u -r1.41 translate.c --- target-i386/translate.c 16 Jan 2005 01:07:28 -0000 1.41 +++ target-i386/translate.c 21 Jan 2005 22:09:23 -0000 @@ -5641,7 +5641,19 @@ gen_op_mov_reg_T0[ot][rm](); } break; - /* XXX: add CR8 for x86_64 */ +#ifdef TARGET_X86_64 + case 8: + if (b & 2) { + gen_op_mov_TN_reg[ot][0][rm](); + gen_op_movl_crN_T0(reg); + gen_jmp_im(s->pc - s->cs_base); + gen_eob(s); + } else { + gen_op_movtl_T0_cr8(); + gen_op_mov_reg_T0[ot][rm](); + } + break; +#endif default: goto illegal_op; }