]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/misc_helper.c
softmmu: introduce cpu_ldst.h
[mirror_qemu.git] / target-i386 / misc_helper.c
CommitLineData
f7b2429f
BS
1/*
2 * x86 misc helpers
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "cpu.h"
022c62cb 21#include "exec/ioport.h"
2ef6175a 22#include "exec/helper-proto.h"
f08b6170 23#include "exec/cpu_ldst.h"
92fc4b58 24
f7b2429f 25/* check if Port I/O is allowed in TSS */
4a7443be 26static inline void check_io(CPUX86State *env, int addr, int size)
f7b2429f
BS
27{
28 int io_offset, val, mask;
29
30 /* TSS must be a valid 32 bit one */
31 if (!(env->tr.flags & DESC_P_MASK) ||
32 ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
33 env->tr.limit < 103) {
34 goto fail;
35 }
4a7443be 36 io_offset = cpu_lduw_kernel(env, env->tr.base + 0x66);
f7b2429f
BS
37 io_offset += (addr >> 3);
38 /* Note: the check needs two bytes */
39 if ((io_offset + 1) > env->tr.limit) {
40 goto fail;
41 }
4a7443be 42 val = cpu_lduw_kernel(env, env->tr.base + io_offset);
f7b2429f
BS
43 val >>= (addr & 7);
44 mask = (1 << size) - 1;
45 /* all bits must be zero to allow the I/O */
46 if ((val & mask) != 0) {
47 fail:
48 raise_exception_err(env, EXCP0D_GPF, 0);
49 }
50}
51
4a7443be 52void helper_check_iob(CPUX86State *env, uint32_t t0)
f7b2429f 53{
4a7443be 54 check_io(env, t0, 1);
f7b2429f
BS
55}
56
4a7443be 57void helper_check_iow(CPUX86State *env, uint32_t t0)
f7b2429f 58{
4a7443be 59 check_io(env, t0, 2);
f7b2429f
BS
60}
61
4a7443be 62void helper_check_iol(CPUX86State *env, uint32_t t0)
f7b2429f 63{
4a7443be 64 check_io(env, t0, 4);
f7b2429f
BS
65}
66
67void helper_outb(uint32_t port, uint32_t data)
68{
69 cpu_outb(port, data & 0xff);
70}
71
72target_ulong helper_inb(uint32_t port)
73{
74 return cpu_inb(port);
75}
76
77void helper_outw(uint32_t port, uint32_t data)
78{
79 cpu_outw(port, data & 0xffff);
80}
81
82target_ulong helper_inw(uint32_t port)
83{
84 return cpu_inw(port);
85}
86
87void helper_outl(uint32_t port, uint32_t data)
88{
89 cpu_outl(port, data);
90}
91
92target_ulong helper_inl(uint32_t port)
93{
94 return cpu_inl(port);
95}
96
4a7443be 97void helper_into(CPUX86State *env, int next_eip_addend)
f7b2429f
BS
98{
99 int eflags;
100
f0967a1a 101 eflags = cpu_cc_compute_all(env, CC_OP);
f7b2429f
BS
102 if (eflags & CC_O) {
103 raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend);
104 }
105}
106
4a7443be 107void helper_single_step(CPUX86State *env)
f7b2429f
BS
108{
109#ifndef CONFIG_USER_ONLY
e175bce5 110 check_hw_breakpoints(env, true);
f7b2429f
BS
111 env->dr[6] |= DR6_BS;
112#endif
113 raise_exception(env, EXCP01_DB);
114}
115
4a7443be 116void helper_cpuid(CPUX86State *env)
f7b2429f
BS
117{
118 uint32_t eax, ebx, ecx, edx;
119
120 cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0);
121
90a2541b
LG
122 cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
123 &eax, &ebx, &ecx, &edx);
4b34e3ad 124 env->regs[R_EAX] = eax;
70b51365 125 env->regs[R_EBX] = ebx;
a4165610 126 env->regs[R_ECX] = ecx;
00f5e6f2 127 env->regs[R_EDX] = edx;
f7b2429f
BS
128}
129
130#if defined(CONFIG_USER_ONLY)
4a7443be 131target_ulong helper_read_crN(CPUX86State *env, int reg)
f7b2429f
BS
132{
133 return 0;
134}
135
4a7443be 136void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
f7b2429f
BS
137{
138}
139
4a7443be 140void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0)
f7b2429f
BS
141{
142}
143#else
4a7443be 144target_ulong helper_read_crN(CPUX86State *env, int reg)
f7b2429f
BS
145{
146 target_ulong val;
147
148 cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0);
149 switch (reg) {
150 default:
151 val = env->cr[reg];
152 break;
153 case 8:
154 if (!(env->hflags2 & HF2_VINTR_MASK)) {
02e51483 155 val = cpu_get_apic_tpr(x86_env_get_cpu(env)->apic_state);
f7b2429f
BS
156 } else {
157 val = env->v_tpr;
158 }
159 break;
160 }
161 return val;
162}
163
4a7443be 164void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
f7b2429f
BS
165{
166 cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0);
167 switch (reg) {
168 case 0:
169 cpu_x86_update_cr0(env, t0);
170 break;
171 case 3:
172 cpu_x86_update_cr3(env, t0);
173 break;
174 case 4:
175 cpu_x86_update_cr4(env, t0);
176 break;
177 case 8:
178 if (!(env->hflags2 & HF2_VINTR_MASK)) {
02e51483 179 cpu_set_apic_tpr(x86_env_get_cpu(env)->apic_state, t0);
f7b2429f
BS
180 }
181 env->v_tpr = t0 & 0x0f;
182 break;
183 default:
184 env->cr[reg] = t0;
185 break;
186 }
187}
188
4a7443be 189void helper_movl_drN_T0(CPUX86State *env, int reg, target_ulong t0)
f7b2429f
BS
190{
191 int i;
192
193 if (reg < 4) {
194 hw_breakpoint_remove(env, reg);
195 env->dr[reg] = t0;
196 hw_breakpoint_insert(env, reg);
197 } else if (reg == 7) {
428065ce 198 for (i = 0; i < DR7_MAX_BP; i++) {
f7b2429f
BS
199 hw_breakpoint_remove(env, i);
200 }
201 env->dr[7] = t0;
428065ce 202 for (i = 0; i < DR7_MAX_BP; i++) {
f7b2429f
BS
203 hw_breakpoint_insert(env, i);
204 }
205 } else {
206 env->dr[reg] = t0;
207 }
208}
209#endif
210
4a7443be 211void helper_lmsw(CPUX86State *env, target_ulong t0)
f7b2429f
BS
212{
213 /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
214 if already set to one. */
215 t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
4a7443be 216 helper_write_crN(env, 0, t0);
f7b2429f
BS
217}
218
4a7443be 219void helper_invlpg(CPUX86State *env, target_ulong addr)
f7b2429f 220{
31b030d4
AF
221 X86CPU *cpu = x86_env_get_cpu(env);
222
f7b2429f 223 cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0);
31b030d4 224 tlb_flush_page(CPU(cpu), addr);
f7b2429f
BS
225}
226
4a7443be 227void helper_rdtsc(CPUX86State *env)
f7b2429f
BS
228{
229 uint64_t val;
230
231 if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
232 raise_exception(env, EXCP0D_GPF);
233 }
234 cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0);
235
236 val = cpu_get_tsc(env) + env->tsc_offset;
4b34e3ad 237 env->regs[R_EAX] = (uint32_t)(val);
00f5e6f2 238 env->regs[R_EDX] = (uint32_t)(val >> 32);
f7b2429f
BS
239}
240
4a7443be 241void helper_rdtscp(CPUX86State *env)
f7b2429f 242{
4a7443be 243 helper_rdtsc(env);
a4165610 244 env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
f7b2429f
BS
245}
246
4a7443be 247void helper_rdpmc(CPUX86State *env)
f7b2429f
BS
248{
249 if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
250 raise_exception(env, EXCP0D_GPF);
251 }
252 cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0);
253
254 /* currently unimplemented */
255 qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
256 raise_exception_err(env, EXCP06_ILLOP, 0);
257}
258
259#if defined(CONFIG_USER_ONLY)
4a7443be 260void helper_wrmsr(CPUX86State *env)
f7b2429f
BS
261{
262}
263
4a7443be 264void helper_rdmsr(CPUX86State *env)
f7b2429f
BS
265{
266}
267#else
4a7443be 268void helper_wrmsr(CPUX86State *env)
f7b2429f
BS
269{
270 uint64_t val;
271
272 cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1);
273
90a2541b
LG
274 val = ((uint32_t)env->regs[R_EAX]) |
275 ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
f7b2429f 276
a4165610 277 switch ((uint32_t)env->regs[R_ECX]) {
f7b2429f
BS
278 case MSR_IA32_SYSENTER_CS:
279 env->sysenter_cs = val & 0xffff;
280 break;
281 case MSR_IA32_SYSENTER_ESP:
282 env->sysenter_esp = val;
283 break;
284 case MSR_IA32_SYSENTER_EIP:
285 env->sysenter_eip = val;
286 break;
287 case MSR_IA32_APICBASE:
02e51483 288 cpu_set_apic_base(x86_env_get_cpu(env)->apic_state, val);
f7b2429f
BS
289 break;
290 case MSR_EFER:
291 {
292 uint64_t update_mask;
293
294 update_mask = 0;
0514ef2f 295 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
f7b2429f
BS
296 update_mask |= MSR_EFER_SCE;
297 }
0514ef2f 298 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
f7b2429f
BS
299 update_mask |= MSR_EFER_LME;
300 }
0514ef2f 301 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
f7b2429f
BS
302 update_mask |= MSR_EFER_FFXSR;
303 }
0514ef2f 304 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
f7b2429f
BS
305 update_mask |= MSR_EFER_NXE;
306 }
0514ef2f 307 if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
f7b2429f
BS
308 update_mask |= MSR_EFER_SVME;
309 }
0514ef2f 310 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
f7b2429f
BS
311 update_mask |= MSR_EFER_FFXSR;
312 }
313 cpu_load_efer(env, (env->efer & ~update_mask) |
314 (val & update_mask));
315 }
316 break;
317 case MSR_STAR:
318 env->star = val;
319 break;
320 case MSR_PAT:
321 env->pat = val;
322 break;
323 case MSR_VM_HSAVE_PA:
324 env->vm_hsave = val;
325 break;
326#ifdef TARGET_X86_64
327 case MSR_LSTAR:
328 env->lstar = val;
329 break;
330 case MSR_CSTAR:
331 env->cstar = val;
332 break;
333 case MSR_FMASK:
334 env->fmask = val;
335 break;
336 case MSR_FSBASE:
337 env->segs[R_FS].base = val;
338 break;
339 case MSR_GSBASE:
340 env->segs[R_GS].base = val;
341 break;
342 case MSR_KERNELGSBASE:
343 env->kernelgsbase = val;
344 break;
345#endif
346 case MSR_MTRRphysBase(0):
347 case MSR_MTRRphysBase(1):
348 case MSR_MTRRphysBase(2):
349 case MSR_MTRRphysBase(3):
350 case MSR_MTRRphysBase(4):
351 case MSR_MTRRphysBase(5):
352 case MSR_MTRRphysBase(6):
353 case MSR_MTRRphysBase(7):
90a2541b
LG
354 env->mtrr_var[((uint32_t)env->regs[R_ECX] -
355 MSR_MTRRphysBase(0)) / 2].base = val;
f7b2429f
BS
356 break;
357 case MSR_MTRRphysMask(0):
358 case MSR_MTRRphysMask(1):
359 case MSR_MTRRphysMask(2):
360 case MSR_MTRRphysMask(3):
361 case MSR_MTRRphysMask(4):
362 case MSR_MTRRphysMask(5):
363 case MSR_MTRRphysMask(6):
364 case MSR_MTRRphysMask(7):
90a2541b
LG
365 env->mtrr_var[((uint32_t)env->regs[R_ECX] -
366 MSR_MTRRphysMask(0)) / 2].mask = val;
f7b2429f
BS
367 break;
368 case MSR_MTRRfix64K_00000:
90a2541b
LG
369 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
370 MSR_MTRRfix64K_00000] = val;
f7b2429f
BS
371 break;
372 case MSR_MTRRfix16K_80000:
373 case MSR_MTRRfix16K_A0000:
90a2541b
LG
374 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
375 MSR_MTRRfix16K_80000 + 1] = val;
f7b2429f
BS
376 break;
377 case MSR_MTRRfix4K_C0000:
378 case MSR_MTRRfix4K_C8000:
379 case MSR_MTRRfix4K_D0000:
380 case MSR_MTRRfix4K_D8000:
381 case MSR_MTRRfix4K_E0000:
382 case MSR_MTRRfix4K_E8000:
383 case MSR_MTRRfix4K_F0000:
384 case MSR_MTRRfix4K_F8000:
90a2541b
LG
385 env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
386 MSR_MTRRfix4K_C0000 + 3] = val;
f7b2429f
BS
387 break;
388 case MSR_MTRRdefType:
389 env->mtrr_deftype = val;
390 break;
391 case MSR_MCG_STATUS:
392 env->mcg_status = val;
393 break;
394 case MSR_MCG_CTL:
395 if ((env->mcg_cap & MCG_CTL_P)
396 && (val == 0 || val == ~(uint64_t)0)) {
397 env->mcg_ctl = val;
398 }
399 break;
400 case MSR_TSC_AUX:
401 env->tsc_aux = val;
402 break;
403 case MSR_IA32_MISC_ENABLE:
404 env->msr_ia32_misc_enable = val;
405 break;
406 default:
a4165610 407 if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
90a2541b
LG
408 && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
409 (4 * env->mcg_cap & 0xff)) {
a4165610 410 uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
f7b2429f
BS
411 if ((offset & 0x3) != 0
412 || (val == 0 || val == ~(uint64_t)0)) {
413 env->mce_banks[offset] = val;
414 }
415 break;
416 }
417 /* XXX: exception? */
418 break;
419 }
420}
421
4a7443be 422void helper_rdmsr(CPUX86State *env)
f7b2429f
BS
423{
424 uint64_t val;
425
426 cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0);
427
a4165610 428 switch ((uint32_t)env->regs[R_ECX]) {
f7b2429f
BS
429 case MSR_IA32_SYSENTER_CS:
430 val = env->sysenter_cs;
431 break;
432 case MSR_IA32_SYSENTER_ESP:
433 val = env->sysenter_esp;
434 break;
435 case MSR_IA32_SYSENTER_EIP:
436 val = env->sysenter_eip;
437 break;
438 case MSR_IA32_APICBASE:
02e51483 439 val = cpu_get_apic_base(x86_env_get_cpu(env)->apic_state);
f7b2429f
BS
440 break;
441 case MSR_EFER:
442 val = env->efer;
443 break;
444 case MSR_STAR:
445 val = env->star;
446 break;
447 case MSR_PAT:
448 val = env->pat;
449 break;
450 case MSR_VM_HSAVE_PA:
451 val = env->vm_hsave;
452 break;
453 case MSR_IA32_PERF_STATUS:
454 /* tsc_increment_by_tick */
455 val = 1000ULL;
456 /* CPU multiplier */
457 val |= (((uint64_t)4ULL) << 40);
458 break;
459#ifdef TARGET_X86_64
460 case MSR_LSTAR:
461 val = env->lstar;
462 break;
463 case MSR_CSTAR:
464 val = env->cstar;
465 break;
466 case MSR_FMASK:
467 val = env->fmask;
468 break;
469 case MSR_FSBASE:
470 val = env->segs[R_FS].base;
471 break;
472 case MSR_GSBASE:
473 val = env->segs[R_GS].base;
474 break;
475 case MSR_KERNELGSBASE:
476 val = env->kernelgsbase;
477 break;
478 case MSR_TSC_AUX:
479 val = env->tsc_aux;
480 break;
481#endif
482 case MSR_MTRRphysBase(0):
483 case MSR_MTRRphysBase(1):
484 case MSR_MTRRphysBase(2):
485 case MSR_MTRRphysBase(3):
486 case MSR_MTRRphysBase(4):
487 case MSR_MTRRphysBase(5):
488 case MSR_MTRRphysBase(6):
489 case MSR_MTRRphysBase(7):
90a2541b
LG
490 val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
491 MSR_MTRRphysBase(0)) / 2].base;
f7b2429f
BS
492 break;
493 case MSR_MTRRphysMask(0):
494 case MSR_MTRRphysMask(1):
495 case MSR_MTRRphysMask(2):
496 case MSR_MTRRphysMask(3):
497 case MSR_MTRRphysMask(4):
498 case MSR_MTRRphysMask(5):
499 case MSR_MTRRphysMask(6):
500 case MSR_MTRRphysMask(7):
90a2541b
LG
501 val = env->mtrr_var[((uint32_t)env->regs[R_ECX] -
502 MSR_MTRRphysMask(0)) / 2].mask;
f7b2429f
BS
503 break;
504 case MSR_MTRRfix64K_00000:
505 val = env->mtrr_fixed[0];
506 break;
507 case MSR_MTRRfix16K_80000:
508 case MSR_MTRRfix16K_A0000:
90a2541b
LG
509 val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
510 MSR_MTRRfix16K_80000 + 1];
f7b2429f
BS
511 break;
512 case MSR_MTRRfix4K_C0000:
513 case MSR_MTRRfix4K_C8000:
514 case MSR_MTRRfix4K_D0000:
515 case MSR_MTRRfix4K_D8000:
516 case MSR_MTRRfix4K_E0000:
517 case MSR_MTRRfix4K_E8000:
518 case MSR_MTRRfix4K_F0000:
519 case MSR_MTRRfix4K_F8000:
90a2541b
LG
520 val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] -
521 MSR_MTRRfix4K_C0000 + 3];
f7b2429f
BS
522 break;
523 case MSR_MTRRdefType:
524 val = env->mtrr_deftype;
525 break;
526 case MSR_MTRRcap:
0514ef2f 527 if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
f7b2429f
BS
528 val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
529 MSR_MTRRcap_WC_SUPPORTED;
530 } else {
531 /* XXX: exception? */
532 val = 0;
533 }
534 break;
535 case MSR_MCG_CAP:
536 val = env->mcg_cap;
537 break;
538 case MSR_MCG_CTL:
539 if (env->mcg_cap & MCG_CTL_P) {
540 val = env->mcg_ctl;
541 } else {
542 val = 0;
543 }
544 break;
545 case MSR_MCG_STATUS:
546 val = env->mcg_status;
547 break;
548 case MSR_IA32_MISC_ENABLE:
549 val = env->msr_ia32_misc_enable;
550 break;
551 default:
a4165610 552 if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
90a2541b
LG
553 && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
554 (4 * env->mcg_cap & 0xff)) {
a4165610 555 uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL;
f7b2429f
BS
556 val = env->mce_banks[offset];
557 break;
558 }
559 /* XXX: exception? */
560 val = 0;
561 break;
562 }
4b34e3ad 563 env->regs[R_EAX] = (uint32_t)(val);
00f5e6f2 564 env->regs[R_EDX] = (uint32_t)(val >> 32);
f7b2429f
BS
565}
566#endif
567
81f3053b
PB
568static void do_pause(X86CPU *cpu)
569{
27103424 570 CPUState *cs = CPU(cpu);
81f3053b
PB
571
572 /* Just let another CPU run. */
27103424 573 cs->exception_index = EXCP_INTERRUPT;
5638d180 574 cpu_loop_exit(cs);
81f3053b
PB
575}
576
259186a7 577static void do_hlt(X86CPU *cpu)
f7b2429f 578{
259186a7
AF
579 CPUState *cs = CPU(cpu);
580 CPUX86State *env = &cpu->env;
581
f7b2429f 582 env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
259186a7 583 cs->halted = 1;
27103424 584 cs->exception_index = EXCP_HLT;
5638d180 585 cpu_loop_exit(cs);
f7b2429f
BS
586}
587
4a7443be 588void helper_hlt(CPUX86State *env, int next_eip_addend)
f7b2429f 589{
259186a7
AF
590 X86CPU *cpu = x86_env_get_cpu(env);
591
f7b2429f 592 cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0);
a78d0eab 593 env->eip += next_eip_addend;
f7b2429f 594
259186a7 595 do_hlt(cpu);
f7b2429f
BS
596}
597
4a7443be 598void helper_monitor(CPUX86State *env, target_ulong ptr)
f7b2429f 599{
a4165610 600 if ((uint32_t)env->regs[R_ECX] != 0) {
f7b2429f
BS
601 raise_exception(env, EXCP0D_GPF);
602 }
603 /* XXX: store address? */
604 cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0);
605}
606
4a7443be 607void helper_mwait(CPUX86State *env, int next_eip_addend)
f7b2429f 608{
259186a7
AF
609 CPUState *cs;
610 X86CPU *cpu;
55e5c285 611
a4165610 612 if ((uint32_t)env->regs[R_ECX] != 0) {
f7b2429f
BS
613 raise_exception(env, EXCP0D_GPF);
614 }
615 cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0);
a78d0eab 616 env->eip += next_eip_addend;
f7b2429f 617
259186a7
AF
618 cpu = x86_env_get_cpu(env);
619 cs = CPU(cpu);
f7b2429f 620 /* XXX: not complete but not completely erroneous */
bdc44640 621 if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
81f3053b 622 do_pause(cpu);
f7b2429f 623 } else {
259186a7 624 do_hlt(cpu);
f7b2429f
BS
625 }
626}
627
81f3053b
PB
628void helper_pause(CPUX86State *env, int next_eip_addend)
629{
630 X86CPU *cpu = x86_env_get_cpu(env);
631
632 cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0);
633 env->eip += next_eip_addend;
634
635 do_pause(cpu);
636}
637
4a7443be 638void helper_debug(CPUX86State *env)
f7b2429f 639{
27103424
AF
640 CPUState *cs = CPU(x86_env_get_cpu(env));
641
642 cs->exception_index = EXCP_DEBUG;
5638d180 643 cpu_loop_exit(cs);
f7b2429f 644}