4 * Copyright (c) 2003 Fabrice Bellard
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.
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.
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/>.
19 #define CPU_NO_GLOBAL_REGS
22 #include "host-utils.h"
28 # define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
29 # define LOG_PCALL_STATE(env) \
30 log_cpu_state_mask(CPU_LOG_PCALL, (env), X86_DUMP_CCOP)
32 # define LOG_PCALL(...) do { } while (0)
33 # define LOG_PCALL_STATE(env) do { } while (0)
38 #define raise_exception_err(a, b)\
40 qemu_log("raise_exception line=%d\n", __LINE__);\
41 (raise_exception_err)(a, b);\
45 static const uint8_t parity_table
[256] = {
46 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
47 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
48 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
49 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
50 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
51 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
52 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
53 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
54 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
55 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
56 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
57 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
58 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
59 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
60 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
61 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
62 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
63 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
64 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
65 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
66 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
67 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
68 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
69 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
70 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
71 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
72 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
73 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
74 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
75 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
76 CC_P
, 0, 0, CC_P
, 0, CC_P
, CC_P
, 0,
77 0, CC_P
, CC_P
, 0, CC_P
, 0, 0, CC_P
,
81 static const uint8_t rclw_table
[32] = {
82 0, 1, 2, 3, 4, 5, 6, 7,
83 8, 9,10,11,12,13,14,15,
84 16, 0, 1, 2, 3, 4, 5, 6,
85 7, 8, 9,10,11,12,13,14,
89 static const uint8_t rclb_table
[32] = {
90 0, 1, 2, 3, 4, 5, 6, 7,
91 8, 0, 1, 2, 3, 4, 5, 6,
92 7, 8, 0, 1, 2, 3, 4, 5,
93 6, 7, 8, 0, 1, 2, 3, 4,
96 static const CPU86_LDouble f15rk
[7] =
98 0.00000000000000000000L,
99 1.00000000000000000000L,
100 3.14159265358979323851L, /*pi*/
101 0.30102999566398119523L, /*lg2*/
102 0.69314718055994530943L, /*ln2*/
103 1.44269504088896340739L, /*l2e*/
104 3.32192809488736234781L, /*l2t*/
107 /* broken thread support */
109 static spinlock_t global_cpu_lock
= SPIN_LOCK_UNLOCKED
;
111 void helper_lock(void)
113 spin_lock(&global_cpu_lock
);
116 void helper_unlock(void)
118 spin_unlock(&global_cpu_lock
);
121 void helper_write_eflags(target_ulong t0
, uint32_t update_mask
)
123 load_eflags(t0
, update_mask
);
126 target_ulong
helper_read_eflags(void)
129 eflags
= helper_cc_compute_all(CC_OP
);
130 eflags
|= (DF
& DF_MASK
);
131 eflags
|= env
->eflags
& ~(VM_MASK
| RF_MASK
);
135 /* return non zero if error */
136 static inline int load_segment(uint32_t *e1_ptr
, uint32_t *e2_ptr
,
147 index
= selector
& ~7;
148 if ((index
+ 7) > dt
->limit
)
150 ptr
= dt
->base
+ index
;
151 *e1_ptr
= ldl_kernel(ptr
);
152 *e2_ptr
= ldl_kernel(ptr
+ 4);
156 static inline unsigned int get_seg_limit(uint32_t e1
, uint32_t e2
)
159 limit
= (e1
& 0xffff) | (e2
& 0x000f0000);
160 if (e2
& DESC_G_MASK
)
161 limit
= (limit
<< 12) | 0xfff;
165 static inline uint32_t get_seg_base(uint32_t e1
, uint32_t e2
)
167 return ((e1
>> 16) | ((e2
& 0xff) << 16) | (e2
& 0xff000000));
170 static inline void load_seg_cache_raw_dt(SegmentCache
*sc
, uint32_t e1
, uint32_t e2
)
172 sc
->base
= get_seg_base(e1
, e2
);
173 sc
->limit
= get_seg_limit(e1
, e2
);
177 /* init the segment cache in vm86 mode. */
178 static inline void load_seg_vm(int seg
, int selector
)
181 cpu_x86_load_seg_cache(env
, seg
, selector
,
182 (selector
<< 4), 0xffff, 0);
185 static inline void get_ss_esp_from_tss(uint32_t *ss_ptr
,
186 uint32_t *esp_ptr
, int dpl
)
188 int type
, index
, shift
;
193 printf("TR: base=%p limit=%x\n", env
->tr
.base
, env
->tr
.limit
);
194 for(i
=0;i
<env
->tr
.limit
;i
++) {
195 printf("%02x ", env
->tr
.base
[i
]);
196 if ((i
& 7) == 7) printf("\n");
202 if (!(env
->tr
.flags
& DESC_P_MASK
))
203 cpu_abort(env
, "invalid tss");
204 type
= (env
->tr
.flags
>> DESC_TYPE_SHIFT
) & 0xf;
206 cpu_abort(env
, "invalid tss type");
208 index
= (dpl
* 4 + 2) << shift
;
209 if (index
+ (4 << shift
) - 1 > env
->tr
.limit
)
210 raise_exception_err(EXCP0A_TSS
, env
->tr
.selector
& 0xfffc);
212 *esp_ptr
= lduw_kernel(env
->tr
.base
+ index
);
213 *ss_ptr
= lduw_kernel(env
->tr
.base
+ index
+ 2);
215 *esp_ptr
= ldl_kernel(env
->tr
.base
+ index
);
216 *ss_ptr
= lduw_kernel(env
->tr
.base
+ index
+ 4);
220 /* XXX: merge with load_seg() */
221 static void tss_load_seg(int seg_reg
, int selector
)
226 if ((selector
& 0xfffc) != 0) {
227 if (load_segment(&e1
, &e2
, selector
) != 0)
228 raise_exception_err(EXCP0A_TSS
, selector
& 0xfffc);
229 if (!(e2
& DESC_S_MASK
))
230 raise_exception_err(EXCP0A_TSS
, selector
& 0xfffc);
232 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
233 cpl
= env
->hflags
& HF_CPL_MASK
;
234 if (seg_reg
== R_CS
) {
235 if (!(e2
& DESC_CS_MASK
))
236 raise_exception_err(EXCP0A_TSS
, selector
& 0xfffc);
237 /* XXX: is it correct ? */
239 raise_exception_err(EXCP0A_TSS
, selector
& 0xfffc);
240 if ((e2
& DESC_C_MASK
) && dpl
> rpl
)
241 raise_exception_err(EXCP0A_TSS
, selector
& 0xfffc);
242 } else if (seg_reg
== R_SS
) {
243 /* SS must be writable data */
244 if ((e2
& DESC_CS_MASK
) || !(e2
& DESC_W_MASK
))
245 raise_exception_err(EXCP0A_TSS
, selector
& 0xfffc);
246 if (dpl
!= cpl
|| dpl
!= rpl
)
247 raise_exception_err(EXCP0A_TSS
, selector
& 0xfffc);
249 /* not readable code */
250 if ((e2
& DESC_CS_MASK
) && !(e2
& DESC_R_MASK
))
251 raise_exception_err(EXCP0A_TSS
, selector
& 0xfffc);
252 /* if data or non conforming code, checks the rights */
253 if (((e2
>> DESC_TYPE_SHIFT
) & 0xf) < 12) {
254 if (dpl
< cpl
|| dpl
< rpl
)
255 raise_exception_err(EXCP0A_TSS
, selector
& 0xfffc);
258 if (!(e2
& DESC_P_MASK
))
259 raise_exception_err(EXCP0B_NOSEG
, selector
& 0xfffc);
260 cpu_x86_load_seg_cache(env
, seg_reg
, selector
,
261 get_seg_base(e1
, e2
),
262 get_seg_limit(e1
, e2
),
265 if (seg_reg
== R_SS
|| seg_reg
== R_CS
)
266 raise_exception_err(EXCP0A_TSS
, selector
& 0xfffc);
270 #define SWITCH_TSS_JMP 0
271 #define SWITCH_TSS_IRET 1
272 #define SWITCH_TSS_CALL 2
274 /* XXX: restore CPU state in registers (PowerPC case) */
275 static void switch_tss(int tss_selector
,
276 uint32_t e1
, uint32_t e2
, int source
,
279 int tss_limit
, tss_limit_max
, type
, old_tss_limit_max
, old_type
, v1
, v2
, i
;
280 target_ulong tss_base
;
281 uint32_t new_regs
[8], new_segs
[6];
282 uint32_t new_eflags
, new_eip
, new_cr3
, new_ldt
, new_trap
;
283 uint32_t old_eflags
, eflags_mask
;
288 type
= (e2
>> DESC_TYPE_SHIFT
) & 0xf;
289 LOG_PCALL("switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector
, type
, source
);
291 /* if task gate, we read the TSS segment and we load it */
293 if (!(e2
& DESC_P_MASK
))
294 raise_exception_err(EXCP0B_NOSEG
, tss_selector
& 0xfffc);
295 tss_selector
= e1
>> 16;
296 if (tss_selector
& 4)
297 raise_exception_err(EXCP0A_TSS
, tss_selector
& 0xfffc);
298 if (load_segment(&e1
, &e2
, tss_selector
) != 0)
299 raise_exception_err(EXCP0D_GPF
, tss_selector
& 0xfffc);
300 if (e2
& DESC_S_MASK
)
301 raise_exception_err(EXCP0D_GPF
, tss_selector
& 0xfffc);
302 type
= (e2
>> DESC_TYPE_SHIFT
) & 0xf;
304 raise_exception_err(EXCP0D_GPF
, tss_selector
& 0xfffc);
307 if (!(e2
& DESC_P_MASK
))
308 raise_exception_err(EXCP0B_NOSEG
, tss_selector
& 0xfffc);
314 tss_limit
= get_seg_limit(e1
, e2
);
315 tss_base
= get_seg_base(e1
, e2
);
316 if ((tss_selector
& 4) != 0 ||
317 tss_limit
< tss_limit_max
)
318 raise_exception_err(EXCP0A_TSS
, tss_selector
& 0xfffc);
319 old_type
= (env
->tr
.flags
>> DESC_TYPE_SHIFT
) & 0xf;
321 old_tss_limit_max
= 103;
323 old_tss_limit_max
= 43;
325 /* read all the registers from the new TSS */
328 new_cr3
= ldl_kernel(tss_base
+ 0x1c);
329 new_eip
= ldl_kernel(tss_base
+ 0x20);
330 new_eflags
= ldl_kernel(tss_base
+ 0x24);
331 for(i
= 0; i
< 8; i
++)
332 new_regs
[i
] = ldl_kernel(tss_base
+ (0x28 + i
* 4));
333 for(i
= 0; i
< 6; i
++)
334 new_segs
[i
] = lduw_kernel(tss_base
+ (0x48 + i
* 4));
335 new_ldt
= lduw_kernel(tss_base
+ 0x60);
336 new_trap
= ldl_kernel(tss_base
+ 0x64);
340 new_eip
= lduw_kernel(tss_base
+ 0x0e);
341 new_eflags
= lduw_kernel(tss_base
+ 0x10);
342 for(i
= 0; i
< 8; i
++)
343 new_regs
[i
] = lduw_kernel(tss_base
+ (0x12 + i
* 2)) | 0xffff0000;
344 for(i
= 0; i
< 4; i
++)
345 new_segs
[i
] = lduw_kernel(tss_base
+ (0x22 + i
* 4));
346 new_ldt
= lduw_kernel(tss_base
+ 0x2a);
352 /* NOTE: we must avoid memory exceptions during the task switch,
353 so we make dummy accesses before */
354 /* XXX: it can still fail in some cases, so a bigger hack is
355 necessary to valid the TLB after having done the accesses */
357 v1
= ldub_kernel(env
->tr
.base
);
358 v2
= ldub_kernel(env
->tr
.base
+ old_tss_limit_max
);
359 stb_kernel(env
->tr
.base
, v1
);
360 stb_kernel(env
->tr
.base
+ old_tss_limit_max
, v2
);
362 /* clear busy bit (it is restartable) */
363 if (source
== SWITCH_TSS_JMP
|| source
== SWITCH_TSS_IRET
) {
366 ptr
= env
->gdt
.base
+ (env
->tr
.selector
& ~7);
367 e2
= ldl_kernel(ptr
+ 4);
368 e2
&= ~DESC_TSS_BUSY_MASK
;
369 stl_kernel(ptr
+ 4, e2
);
371 old_eflags
= compute_eflags();
372 if (source
== SWITCH_TSS_IRET
)
373 old_eflags
&= ~NT_MASK
;
375 /* save the current state in the old TSS */
378 stl_kernel(env
->tr
.base
+ 0x20, next_eip
);
379 stl_kernel(env
->tr
.base
+ 0x24, old_eflags
);
380 stl_kernel(env
->tr
.base
+ (0x28 + 0 * 4), EAX
);
381 stl_kernel(env
->tr
.base
+ (0x28 + 1 * 4), ECX
);
382 stl_kernel(env
->tr
.base
+ (0x28 + 2 * 4), EDX
);
383 stl_kernel(env
->tr
.base
+ (0x28 + 3 * 4), EBX
);
384 stl_kernel(env
->tr
.base
+ (0x28 + 4 * 4), ESP
);
385 stl_kernel(env
->tr
.base
+ (0x28 + 5 * 4), EBP
);
386 stl_kernel(env
->tr
.base
+ (0x28 + 6 * 4), ESI
);
387 stl_kernel(env
->tr
.base
+ (0x28 + 7 * 4), EDI
);
388 for(i
= 0; i
< 6; i
++)
389 stw_kernel(env
->tr
.base
+ (0x48 + i
* 4), env
->segs
[i
].selector
);
392 stw_kernel(env
->tr
.base
+ 0x0e, next_eip
);
393 stw_kernel(env
->tr
.base
+ 0x10, old_eflags
);
394 stw_kernel(env
->tr
.base
+ (0x12 + 0 * 2), EAX
);
395 stw_kernel(env
->tr
.base
+ (0x12 + 1 * 2), ECX
);
396 stw_kernel(env
->tr
.base
+ (0x12 + 2 * 2), EDX
);
397 stw_kernel(env
->tr
.base
+ (0x12 + 3 * 2), EBX
);
398 stw_kernel(env
->tr
.base
+ (0x12 + 4 * 2), ESP
);
399 stw_kernel(env
->tr
.base
+ (0x12 + 5 * 2), EBP
);
400 stw_kernel(env
->tr
.base
+ (0x12 + 6 * 2), ESI
);
401 stw_kernel(env
->tr
.base
+ (0x12 + 7 * 2), EDI
);
402 for(i
= 0; i
< 4; i
++)
403 stw_kernel(env
->tr
.base
+ (0x22 + i
* 4), env
->segs
[i
].selector
);
406 /* now if an exception occurs, it will occurs in the next task
409 if (source
== SWITCH_TSS_CALL
) {
410 stw_kernel(tss_base
, env
->tr
.selector
);
411 new_eflags
|= NT_MASK
;
415 if (source
== SWITCH_TSS_JMP
|| source
== SWITCH_TSS_CALL
) {
418 ptr
= env
->gdt
.base
+ (tss_selector
& ~7);
419 e2
= ldl_kernel(ptr
+ 4);
420 e2
|= DESC_TSS_BUSY_MASK
;
421 stl_kernel(ptr
+ 4, e2
);
424 /* set the new CPU state */
425 /* from this point, any exception which occurs can give problems */
426 env
->cr
[0] |= CR0_TS_MASK
;
427 env
->hflags
|= HF_TS_MASK
;
428 env
->tr
.selector
= tss_selector
;
429 env
->tr
.base
= tss_base
;
430 env
->tr
.limit
= tss_limit
;
431 env
->tr
.flags
= e2
& ~DESC_TSS_BUSY_MASK
;
433 if ((type
& 8) && (env
->cr
[0] & CR0_PG_MASK
)) {
434 cpu_x86_update_cr3(env
, new_cr3
);
437 /* load all registers without an exception, then reload them with
438 possible exception */
440 eflags_mask
= TF_MASK
| AC_MASK
| ID_MASK
|
441 IF_MASK
| IOPL_MASK
| VM_MASK
| RF_MASK
| NT_MASK
;
443 eflags_mask
&= 0xffff;
444 load_eflags(new_eflags
, eflags_mask
);
445 /* XXX: what to do in 16 bit case ? */
454 if (new_eflags
& VM_MASK
) {
455 for(i
= 0; i
< 6; i
++)
456 load_seg_vm(i
, new_segs
[i
]);
457 /* in vm86, CPL is always 3 */
458 cpu_x86_set_cpl(env
, 3);
460 /* CPL is set the RPL of CS */
461 cpu_x86_set_cpl(env
, new_segs
[R_CS
] & 3);
462 /* first just selectors as the rest may trigger exceptions */
463 for(i
= 0; i
< 6; i
++)
464 cpu_x86_load_seg_cache(env
, i
, new_segs
[i
], 0, 0, 0);
467 env
->ldt
.selector
= new_ldt
& ~4;
474 raise_exception_err(EXCP0A_TSS
, new_ldt
& 0xfffc);
476 if ((new_ldt
& 0xfffc) != 0) {
478 index
= new_ldt
& ~7;
479 if ((index
+ 7) > dt
->limit
)
480 raise_exception_err(EXCP0A_TSS
, new_ldt
& 0xfffc);
481 ptr
= dt
->base
+ index
;
482 e1
= ldl_kernel(ptr
);
483 e2
= ldl_kernel(ptr
+ 4);
484 if ((e2
& DESC_S_MASK
) || ((e2
>> DESC_TYPE_SHIFT
) & 0xf) != 2)
485 raise_exception_err(EXCP0A_TSS
, new_ldt
& 0xfffc);
486 if (!(e2
& DESC_P_MASK
))
487 raise_exception_err(EXCP0A_TSS
, new_ldt
& 0xfffc);
488 load_seg_cache_raw_dt(&env
->ldt
, e1
, e2
);
491 /* load the segments */
492 if (!(new_eflags
& VM_MASK
)) {
493 tss_load_seg(R_CS
, new_segs
[R_CS
]);
494 tss_load_seg(R_SS
, new_segs
[R_SS
]);
495 tss_load_seg(R_ES
, new_segs
[R_ES
]);
496 tss_load_seg(R_DS
, new_segs
[R_DS
]);
497 tss_load_seg(R_FS
, new_segs
[R_FS
]);
498 tss_load_seg(R_GS
, new_segs
[R_GS
]);
501 /* check that EIP is in the CS segment limits */
502 if (new_eip
> env
->segs
[R_CS
].limit
) {
503 /* XXX: different exception if CALL ? */
504 raise_exception_err(EXCP0D_GPF
, 0);
507 #ifndef CONFIG_USER_ONLY
508 /* reset local breakpoints */
509 if (env
->dr
[7] & 0x55) {
510 for (i
= 0; i
< 4; i
++) {
511 if (hw_breakpoint_enabled(env
->dr
[7], i
) == 0x1)
512 hw_breakpoint_remove(env
, i
);
519 /* check if Port I/O is allowed in TSS */
520 static inline void check_io(int addr
, int size
)
522 int io_offset
, val
, mask
;
524 /* TSS must be a valid 32 bit one */
525 if (!(env
->tr
.flags
& DESC_P_MASK
) ||
526 ((env
->tr
.flags
>> DESC_TYPE_SHIFT
) & 0xf) != 9 ||
529 io_offset
= lduw_kernel(env
->tr
.base
+ 0x66);
530 io_offset
+= (addr
>> 3);
531 /* Note: the check needs two bytes */
532 if ((io_offset
+ 1) > env
->tr
.limit
)
534 val
= lduw_kernel(env
->tr
.base
+ io_offset
);
536 mask
= (1 << size
) - 1;
537 /* all bits must be zero to allow the I/O */
538 if ((val
& mask
) != 0) {
540 raise_exception_err(EXCP0D_GPF
, 0);
544 void helper_check_iob(uint32_t t0
)
549 void helper_check_iow(uint32_t t0
)
554 void helper_check_iol(uint32_t t0
)
559 void helper_outb(uint32_t port
, uint32_t data
)
561 cpu_outb(port
, data
& 0xff);
564 target_ulong
helper_inb(uint32_t port
)
566 return cpu_inb(port
);
569 void helper_outw(uint32_t port
, uint32_t data
)
571 cpu_outw(port
, data
& 0xffff);
574 target_ulong
helper_inw(uint32_t port
)
576 return cpu_inw(port
);
579 void helper_outl(uint32_t port
, uint32_t data
)
581 cpu_outl(port
, data
);
584 target_ulong
helper_inl(uint32_t port
)
586 return cpu_inl(port
);
589 static inline unsigned int get_sp_mask(unsigned int e2
)
591 if (e2
& DESC_B_MASK
)
597 static int exeption_has_error_code(int intno
)
613 #define SET_ESP(val, sp_mask)\
615 if ((sp_mask) == 0xffff)\
616 ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
617 else if ((sp_mask) == 0xffffffffLL)\
618 ESP = (uint32_t)(val);\
623 #define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
626 /* in 64-bit machines, this can overflow. So this segment addition macro
627 * can be used to trim the value to 32-bit whenever needed */
628 #define SEG_ADDL(ssp, sp, sp_mask) ((uint32_t)((ssp) + (sp & (sp_mask))))
630 /* XXX: add a is_user flag to have proper security support */
631 #define PUSHW(ssp, sp, sp_mask, val)\
634 stw_kernel((ssp) + (sp & (sp_mask)), (val));\
637 #define PUSHL(ssp, sp, sp_mask, val)\
640 stl_kernel(SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val));\
643 #define POPW(ssp, sp, sp_mask, val)\
645 val = lduw_kernel((ssp) + (sp & (sp_mask)));\
649 #define POPL(ssp, sp, sp_mask, val)\
651 val = (uint32_t)ldl_kernel(SEG_ADDL(ssp, sp, sp_mask));\
655 /* protected mode interrupt */
656 static void do_interrupt_protected(int intno
, int is_int
, int error_code
,
657 unsigned int next_eip
, int is_hw
)
660 target_ulong ptr
, ssp
;
661 int type
, dpl
, selector
, ss_dpl
, cpl
;
662 int has_error_code
, new_stack
, shift
;
663 uint32_t e1
, e2
, offset
, ss
= 0, esp
, ss_e1
= 0, ss_e2
= 0;
664 uint32_t old_eip
, sp_mask
;
667 if (!is_int
&& !is_hw
)
668 has_error_code
= exeption_has_error_code(intno
);
675 if (intno
* 8 + 7 > dt
->limit
)
676 raise_exception_err(EXCP0D_GPF
, intno
* 8 + 2);
677 ptr
= dt
->base
+ intno
* 8;
678 e1
= ldl_kernel(ptr
);
679 e2
= ldl_kernel(ptr
+ 4);
680 /* check gate type */
681 type
= (e2
>> DESC_TYPE_SHIFT
) & 0x1f;
683 case 5: /* task gate */
684 /* must do that check here to return the correct error code */
685 if (!(e2
& DESC_P_MASK
))
686 raise_exception_err(EXCP0B_NOSEG
, intno
* 8 + 2);
687 switch_tss(intno
* 8, e1
, e2
, SWITCH_TSS_CALL
, old_eip
);
688 if (has_error_code
) {
691 /* push the error code */
692 type
= (env
->tr
.flags
>> DESC_TYPE_SHIFT
) & 0xf;
694 if (env
->segs
[R_SS
].flags
& DESC_B_MASK
)
698 esp
= (ESP
- (2 << shift
)) & mask
;
699 ssp
= env
->segs
[R_SS
].base
+ esp
;
701 stl_kernel(ssp
, error_code
);
703 stw_kernel(ssp
, error_code
);
707 case 6: /* 286 interrupt gate */
708 case 7: /* 286 trap gate */
709 case 14: /* 386 interrupt gate */
710 case 15: /* 386 trap gate */
713 raise_exception_err(EXCP0D_GPF
, intno
* 8 + 2);
716 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
717 cpl
= env
->hflags
& HF_CPL_MASK
;
718 /* check privilege if software int */
719 if (is_int
&& dpl
< cpl
)
720 raise_exception_err(EXCP0D_GPF
, intno
* 8 + 2);
721 /* check valid bit */
722 if (!(e2
& DESC_P_MASK
))
723 raise_exception_err(EXCP0B_NOSEG
, intno
* 8 + 2);
725 offset
= (e2
& 0xffff0000) | (e1
& 0x0000ffff);
726 if ((selector
& 0xfffc) == 0)
727 raise_exception_err(EXCP0D_GPF
, 0);
729 if (load_segment(&e1
, &e2
, selector
) != 0)
730 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
731 if (!(e2
& DESC_S_MASK
) || !(e2
& (DESC_CS_MASK
)))
732 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
733 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
735 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
736 if (!(e2
& DESC_P_MASK
))
737 raise_exception_err(EXCP0B_NOSEG
, selector
& 0xfffc);
738 if (!(e2
& DESC_C_MASK
) && dpl
< cpl
) {
739 /* to inner privilege */
740 get_ss_esp_from_tss(&ss
, &esp
, dpl
);
741 if ((ss
& 0xfffc) == 0)
742 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
744 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
745 if (load_segment(&ss_e1
, &ss_e2
, ss
) != 0)
746 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
747 ss_dpl
= (ss_e2
>> DESC_DPL_SHIFT
) & 3;
749 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
750 if (!(ss_e2
& DESC_S_MASK
) ||
751 (ss_e2
& DESC_CS_MASK
) ||
752 !(ss_e2
& DESC_W_MASK
))
753 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
754 if (!(ss_e2
& DESC_P_MASK
))
755 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
757 sp_mask
= get_sp_mask(ss_e2
);
758 ssp
= get_seg_base(ss_e1
, ss_e2
);
759 } else if ((e2
& DESC_C_MASK
) || dpl
== cpl
) {
760 /* to same privilege */
761 if (env
->eflags
& VM_MASK
)
762 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
764 sp_mask
= get_sp_mask(env
->segs
[R_SS
].flags
);
765 ssp
= env
->segs
[R_SS
].base
;
769 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
770 new_stack
= 0; /* avoid warning */
771 sp_mask
= 0; /* avoid warning */
772 ssp
= 0; /* avoid warning */
773 esp
= 0; /* avoid warning */
779 /* XXX: check that enough room is available */
780 push_size
= 6 + (new_stack
<< 2) + (has_error_code
<< 1);
781 if (env
->eflags
& VM_MASK
)
787 if (env
->eflags
& VM_MASK
) {
788 PUSHL(ssp
, esp
, sp_mask
, env
->segs
[R_GS
].selector
);
789 PUSHL(ssp
, esp
, sp_mask
, env
->segs
[R_FS
].selector
);
790 PUSHL(ssp
, esp
, sp_mask
, env
->segs
[R_DS
].selector
);
791 PUSHL(ssp
, esp
, sp_mask
, env
->segs
[R_ES
].selector
);
793 PUSHL(ssp
, esp
, sp_mask
, env
->segs
[R_SS
].selector
);
794 PUSHL(ssp
, esp
, sp_mask
, ESP
);
796 PUSHL(ssp
, esp
, sp_mask
, compute_eflags());
797 PUSHL(ssp
, esp
, sp_mask
, env
->segs
[R_CS
].selector
);
798 PUSHL(ssp
, esp
, sp_mask
, old_eip
);
799 if (has_error_code
) {
800 PUSHL(ssp
, esp
, sp_mask
, error_code
);
804 if (env
->eflags
& VM_MASK
) {
805 PUSHW(ssp
, esp
, sp_mask
, env
->segs
[R_GS
].selector
);
806 PUSHW(ssp
, esp
, sp_mask
, env
->segs
[R_FS
].selector
);
807 PUSHW(ssp
, esp
, sp_mask
, env
->segs
[R_DS
].selector
);
808 PUSHW(ssp
, esp
, sp_mask
, env
->segs
[R_ES
].selector
);
810 PUSHW(ssp
, esp
, sp_mask
, env
->segs
[R_SS
].selector
);
811 PUSHW(ssp
, esp
, sp_mask
, ESP
);
813 PUSHW(ssp
, esp
, sp_mask
, compute_eflags());
814 PUSHW(ssp
, esp
, sp_mask
, env
->segs
[R_CS
].selector
);
815 PUSHW(ssp
, esp
, sp_mask
, old_eip
);
816 if (has_error_code
) {
817 PUSHW(ssp
, esp
, sp_mask
, error_code
);
822 if (env
->eflags
& VM_MASK
) {
823 cpu_x86_load_seg_cache(env
, R_ES
, 0, 0, 0, 0);
824 cpu_x86_load_seg_cache(env
, R_DS
, 0, 0, 0, 0);
825 cpu_x86_load_seg_cache(env
, R_FS
, 0, 0, 0, 0);
826 cpu_x86_load_seg_cache(env
, R_GS
, 0, 0, 0, 0);
828 ss
= (ss
& ~3) | dpl
;
829 cpu_x86_load_seg_cache(env
, R_SS
, ss
,
830 ssp
, get_seg_limit(ss_e1
, ss_e2
), ss_e2
);
832 SET_ESP(esp
, sp_mask
);
834 selector
= (selector
& ~3) | dpl
;
835 cpu_x86_load_seg_cache(env
, R_CS
, selector
,
836 get_seg_base(e1
, e2
),
837 get_seg_limit(e1
, e2
),
839 cpu_x86_set_cpl(env
, dpl
);
842 /* interrupt gate clear IF mask */
843 if ((type
& 1) == 0) {
844 env
->eflags
&= ~IF_MASK
;
846 env
->eflags
&= ~(TF_MASK
| VM_MASK
| RF_MASK
| NT_MASK
);
851 #define PUSHQ(sp, val)\
854 stq_kernel(sp, (val));\
857 #define POPQ(sp, val)\
859 val = ldq_kernel(sp);\
863 static inline target_ulong
get_rsp_from_tss(int level
)
868 printf("TR: base=" TARGET_FMT_lx
" limit=%x\n",
869 env
->tr
.base
, env
->tr
.limit
);
872 if (!(env
->tr
.flags
& DESC_P_MASK
))
873 cpu_abort(env
, "invalid tss");
874 index
= 8 * level
+ 4;
875 if ((index
+ 7) > env
->tr
.limit
)
876 raise_exception_err(EXCP0A_TSS
, env
->tr
.selector
& 0xfffc);
877 return ldq_kernel(env
->tr
.base
+ index
);
880 /* 64 bit interrupt */
881 static void do_interrupt64(int intno
, int is_int
, int error_code
,
882 target_ulong next_eip
, int is_hw
)
886 int type
, dpl
, selector
, cpl
, ist
;
887 int has_error_code
, new_stack
;
888 uint32_t e1
, e2
, e3
, ss
;
889 target_ulong old_eip
, esp
, offset
;
892 if (!is_int
&& !is_hw
)
893 has_error_code
= exeption_has_error_code(intno
);
900 if (intno
* 16 + 15 > dt
->limit
)
901 raise_exception_err(EXCP0D_GPF
, intno
* 16 + 2);
902 ptr
= dt
->base
+ intno
* 16;
903 e1
= ldl_kernel(ptr
);
904 e2
= ldl_kernel(ptr
+ 4);
905 e3
= ldl_kernel(ptr
+ 8);
906 /* check gate type */
907 type
= (e2
>> DESC_TYPE_SHIFT
) & 0x1f;
909 case 14: /* 386 interrupt gate */
910 case 15: /* 386 trap gate */
913 raise_exception_err(EXCP0D_GPF
, intno
* 16 + 2);
916 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
917 cpl
= env
->hflags
& HF_CPL_MASK
;
918 /* check privilege if software int */
919 if (is_int
&& dpl
< cpl
)
920 raise_exception_err(EXCP0D_GPF
, intno
* 16 + 2);
921 /* check valid bit */
922 if (!(e2
& DESC_P_MASK
))
923 raise_exception_err(EXCP0B_NOSEG
, intno
* 16 + 2);
925 offset
= ((target_ulong
)e3
<< 32) | (e2
& 0xffff0000) | (e1
& 0x0000ffff);
927 if ((selector
& 0xfffc) == 0)
928 raise_exception_err(EXCP0D_GPF
, 0);
930 if (load_segment(&e1
, &e2
, selector
) != 0)
931 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
932 if (!(e2
& DESC_S_MASK
) || !(e2
& (DESC_CS_MASK
)))
933 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
934 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
936 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
937 if (!(e2
& DESC_P_MASK
))
938 raise_exception_err(EXCP0B_NOSEG
, selector
& 0xfffc);
939 if (!(e2
& DESC_L_MASK
) || (e2
& DESC_B_MASK
))
940 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
941 if ((!(e2
& DESC_C_MASK
) && dpl
< cpl
) || ist
!= 0) {
942 /* to inner privilege */
944 esp
= get_rsp_from_tss(ist
+ 3);
946 esp
= get_rsp_from_tss(dpl
);
947 esp
&= ~0xfLL
; /* align stack */
950 } else if ((e2
& DESC_C_MASK
) || dpl
== cpl
) {
951 /* to same privilege */
952 if (env
->eflags
& VM_MASK
)
953 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
956 esp
= get_rsp_from_tss(ist
+ 3);
959 esp
&= ~0xfLL
; /* align stack */
962 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
963 new_stack
= 0; /* avoid warning */
964 esp
= 0; /* avoid warning */
967 PUSHQ(esp
, env
->segs
[R_SS
].selector
);
969 PUSHQ(esp
, compute_eflags());
970 PUSHQ(esp
, env
->segs
[R_CS
].selector
);
972 if (has_error_code
) {
973 PUSHQ(esp
, error_code
);
978 cpu_x86_load_seg_cache(env
, R_SS
, ss
, 0, 0, 0);
982 selector
= (selector
& ~3) | dpl
;
983 cpu_x86_load_seg_cache(env
, R_CS
, selector
,
984 get_seg_base(e1
, e2
),
985 get_seg_limit(e1
, e2
),
987 cpu_x86_set_cpl(env
, dpl
);
990 /* interrupt gate clear IF mask */
991 if ((type
& 1) == 0) {
992 env
->eflags
&= ~IF_MASK
;
994 env
->eflags
&= ~(TF_MASK
| VM_MASK
| RF_MASK
| NT_MASK
);
999 #if defined(CONFIG_USER_ONLY)
1000 void helper_syscall(int next_eip_addend
)
1002 env
->exception_index
= EXCP_SYSCALL
;
1003 env
->exception_next_eip
= env
->eip
+ next_eip_addend
;
1007 void helper_syscall(int next_eip_addend
)
1011 if (!(env
->efer
& MSR_EFER_SCE
)) {
1012 raise_exception_err(EXCP06_ILLOP
, 0);
1014 selector
= (env
->star
>> 32) & 0xffff;
1015 if (env
->hflags
& HF_LMA_MASK
) {
1018 ECX
= env
->eip
+ next_eip_addend
;
1019 env
->regs
[11] = compute_eflags();
1021 code64
= env
->hflags
& HF_CS64_MASK
;
1023 cpu_x86_set_cpl(env
, 0);
1024 cpu_x86_load_seg_cache(env
, R_CS
, selector
& 0xfffc,
1026 DESC_G_MASK
| DESC_P_MASK
|
1028 DESC_CS_MASK
| DESC_R_MASK
| DESC_A_MASK
| DESC_L_MASK
);
1029 cpu_x86_load_seg_cache(env
, R_SS
, (selector
+ 8) & 0xfffc,
1031 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
1033 DESC_W_MASK
| DESC_A_MASK
);
1034 env
->eflags
&= ~env
->fmask
;
1035 load_eflags(env
->eflags
, 0);
1037 env
->eip
= env
->lstar
;
1039 env
->eip
= env
->cstar
;
1041 ECX
= (uint32_t)(env
->eip
+ next_eip_addend
);
1043 cpu_x86_set_cpl(env
, 0);
1044 cpu_x86_load_seg_cache(env
, R_CS
, selector
& 0xfffc,
1046 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
1048 DESC_CS_MASK
| DESC_R_MASK
| DESC_A_MASK
);
1049 cpu_x86_load_seg_cache(env
, R_SS
, (selector
+ 8) & 0xfffc,
1051 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
1053 DESC_W_MASK
| DESC_A_MASK
);
1054 env
->eflags
&= ~(IF_MASK
| RF_MASK
| VM_MASK
);
1055 env
->eip
= (uint32_t)env
->star
;
1061 #ifdef TARGET_X86_64
1062 void helper_sysret(int dflag
)
1066 if (!(env
->efer
& MSR_EFER_SCE
)) {
1067 raise_exception_err(EXCP06_ILLOP
, 0);
1069 cpl
= env
->hflags
& HF_CPL_MASK
;
1070 if (!(env
->cr
[0] & CR0_PE_MASK
) || cpl
!= 0) {
1071 raise_exception_err(EXCP0D_GPF
, 0);
1073 selector
= (env
->star
>> 48) & 0xffff;
1074 if (env
->hflags
& HF_LMA_MASK
) {
1076 cpu_x86_load_seg_cache(env
, R_CS
, (selector
+ 16) | 3,
1078 DESC_G_MASK
| DESC_P_MASK
|
1079 DESC_S_MASK
| (3 << DESC_DPL_SHIFT
) |
1080 DESC_CS_MASK
| DESC_R_MASK
| DESC_A_MASK
|
1084 cpu_x86_load_seg_cache(env
, R_CS
, selector
| 3,
1086 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
1087 DESC_S_MASK
| (3 << DESC_DPL_SHIFT
) |
1088 DESC_CS_MASK
| DESC_R_MASK
| DESC_A_MASK
);
1089 env
->eip
= (uint32_t)ECX
;
1091 cpu_x86_load_seg_cache(env
, R_SS
, selector
+ 8,
1093 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
1094 DESC_S_MASK
| (3 << DESC_DPL_SHIFT
) |
1095 DESC_W_MASK
| DESC_A_MASK
);
1096 load_eflags((uint32_t)(env
->regs
[11]), TF_MASK
| AC_MASK
| ID_MASK
|
1097 IF_MASK
| IOPL_MASK
| VM_MASK
| RF_MASK
| NT_MASK
);
1098 cpu_x86_set_cpl(env
, 3);
1100 cpu_x86_load_seg_cache(env
, R_CS
, selector
| 3,
1102 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
1103 DESC_S_MASK
| (3 << DESC_DPL_SHIFT
) |
1104 DESC_CS_MASK
| DESC_R_MASK
| DESC_A_MASK
);
1105 env
->eip
= (uint32_t)ECX
;
1106 cpu_x86_load_seg_cache(env
, R_SS
, selector
+ 8,
1108 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
1109 DESC_S_MASK
| (3 << DESC_DPL_SHIFT
) |
1110 DESC_W_MASK
| DESC_A_MASK
);
1111 env
->eflags
|= IF_MASK
;
1112 cpu_x86_set_cpl(env
, 3);
1117 /* real mode interrupt */
1118 static void do_interrupt_real(int intno
, int is_int
, int error_code
,
1119 unsigned int next_eip
)
1122 target_ulong ptr
, ssp
;
1124 uint32_t offset
, esp
;
1125 uint32_t old_cs
, old_eip
;
1127 /* real mode (simpler !) */
1129 if (intno
* 4 + 3 > dt
->limit
)
1130 raise_exception_err(EXCP0D_GPF
, intno
* 8 + 2);
1131 ptr
= dt
->base
+ intno
* 4;
1132 offset
= lduw_kernel(ptr
);
1133 selector
= lduw_kernel(ptr
+ 2);
1135 ssp
= env
->segs
[R_SS
].base
;
1140 old_cs
= env
->segs
[R_CS
].selector
;
1141 /* XXX: use SS segment size ? */
1142 PUSHW(ssp
, esp
, 0xffff, compute_eflags());
1143 PUSHW(ssp
, esp
, 0xffff, old_cs
);
1144 PUSHW(ssp
, esp
, 0xffff, old_eip
);
1146 /* update processor state */
1147 ESP
= (ESP
& ~0xffff) | (esp
& 0xffff);
1149 env
->segs
[R_CS
].selector
= selector
;
1150 env
->segs
[R_CS
].base
= (selector
<< 4);
1151 env
->eflags
&= ~(IF_MASK
| TF_MASK
| AC_MASK
| RF_MASK
);
1154 /* fake user mode interrupt */
1155 void do_interrupt_user(int intno
, int is_int
, int error_code
,
1156 target_ulong next_eip
)
1160 int dpl
, cpl
, shift
;
1164 if (env
->hflags
& HF_LMA_MASK
) {
1169 ptr
= dt
->base
+ (intno
<< shift
);
1170 e2
= ldl_kernel(ptr
+ 4);
1172 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
1173 cpl
= env
->hflags
& HF_CPL_MASK
;
1174 /* check privilege if software int */
1175 if (is_int
&& dpl
< cpl
)
1176 raise_exception_err(EXCP0D_GPF
, (intno
<< shift
) + 2);
1178 /* Since we emulate only user space, we cannot do more than
1179 exiting the emulation with the suitable exception and error
1185 #if !defined(CONFIG_USER_ONLY)
1186 static void handle_even_inj(int intno
, int is_int
, int error_code
,
1189 uint32_t event_inj
= ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.event_inj
));
1190 if (!(event_inj
& SVM_EVTINJ_VALID
)) {
1193 type
= SVM_EVTINJ_TYPE_SOFT
;
1195 type
= SVM_EVTINJ_TYPE_EXEPT
;
1196 event_inj
= intno
| type
| SVM_EVTINJ_VALID
;
1197 if (!rm
&& exeption_has_error_code(intno
)) {
1198 event_inj
|= SVM_EVTINJ_VALID_ERR
;
1199 stl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.event_inj_err
), error_code
);
1201 stl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.event_inj
), event_inj
);
1207 * Begin execution of an interruption. is_int is TRUE if coming from
1208 * the int instruction. next_eip is the EIP value AFTER the interrupt
1209 * instruction. It is only relevant if is_int is TRUE.
1211 void do_interrupt(int intno
, int is_int
, int error_code
,
1212 target_ulong next_eip
, int is_hw
)
1214 if (qemu_loglevel_mask(CPU_LOG_INT
)) {
1215 if ((env
->cr
[0] & CR0_PE_MASK
)) {
1217 qemu_log("%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx
" pc=" TARGET_FMT_lx
" SP=%04x:" TARGET_FMT_lx
,
1218 count
, intno
, error_code
, is_int
,
1219 env
->hflags
& HF_CPL_MASK
,
1220 env
->segs
[R_CS
].selector
, EIP
,
1221 (int)env
->segs
[R_CS
].base
+ EIP
,
1222 env
->segs
[R_SS
].selector
, ESP
);
1223 if (intno
== 0x0e) {
1224 qemu_log(" CR2=" TARGET_FMT_lx
, env
->cr
[2]);
1226 qemu_log(" EAX=" TARGET_FMT_lx
, EAX
);
1229 log_cpu_state(env
, X86_DUMP_CCOP
);
1235 ptr
= env
->segs
[R_CS
].base
+ env
->eip
;
1236 for(i
= 0; i
< 16; i
++) {
1237 qemu_log(" %02x", ldub(ptr
+ i
));
1245 if (env
->cr
[0] & CR0_PE_MASK
) {
1246 #if !defined(CONFIG_USER_ONLY)
1247 if (env
->hflags
& HF_SVMI_MASK
)
1248 handle_even_inj(intno
, is_int
, error_code
, is_hw
, 0);
1250 #ifdef TARGET_X86_64
1251 if (env
->hflags
& HF_LMA_MASK
) {
1252 do_interrupt64(intno
, is_int
, error_code
, next_eip
, is_hw
);
1256 do_interrupt_protected(intno
, is_int
, error_code
, next_eip
, is_hw
);
1259 #if !defined(CONFIG_USER_ONLY)
1260 if (env
->hflags
& HF_SVMI_MASK
)
1261 handle_even_inj(intno
, is_int
, error_code
, is_hw
, 1);
1263 do_interrupt_real(intno
, is_int
, error_code
, next_eip
);
1266 #if !defined(CONFIG_USER_ONLY)
1267 if (env
->hflags
& HF_SVMI_MASK
) {
1268 uint32_t event_inj
= ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.event_inj
));
1269 stl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.event_inj
), event_inj
& ~SVM_EVTINJ_VALID
);
1274 /* This should come from sysemu.h - if we could include it here... */
1275 void qemu_system_reset_request(void);
1278 * Check nested exceptions and change to double or triple fault if
1279 * needed. It should only be called, if this is not an interrupt.
1280 * Returns the new exception number.
1282 static int check_exception(int intno
, int *error_code
)
1284 int first_contributory
= env
->old_exception
== 0 ||
1285 (env
->old_exception
>= 10 &&
1286 env
->old_exception
<= 13);
1287 int second_contributory
= intno
== 0 ||
1288 (intno
>= 10 && intno
<= 13);
1290 qemu_log_mask(CPU_LOG_INT
, "check_exception old: 0x%x new 0x%x\n",
1291 env
->old_exception
, intno
);
1293 #if !defined(CONFIG_USER_ONLY)
1294 if (env
->old_exception
== EXCP08_DBLE
) {
1295 if (env
->hflags
& HF_SVMI_MASK
)
1296 helper_vmexit(SVM_EXIT_SHUTDOWN
, 0); /* does not return */
1298 qemu_log_mask(CPU_LOG_RESET
, "Triple fault\n");
1300 qemu_system_reset_request();
1305 if ((first_contributory
&& second_contributory
)
1306 || (env
->old_exception
== EXCP0E_PAGE
&&
1307 (second_contributory
|| (intno
== EXCP0E_PAGE
)))) {
1308 intno
= EXCP08_DBLE
;
1312 if (second_contributory
|| (intno
== EXCP0E_PAGE
) ||
1313 (intno
== EXCP08_DBLE
))
1314 env
->old_exception
= intno
;
1320 * Signal an interruption. It is executed in the main CPU loop.
1321 * is_int is TRUE if coming from the int instruction. next_eip is the
1322 * EIP value AFTER the interrupt instruction. It is only relevant if
1325 static void QEMU_NORETURN
raise_interrupt(int intno
, int is_int
, int error_code
,
1326 int next_eip_addend
)
1329 helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE
+ intno
, error_code
);
1330 intno
= check_exception(intno
, &error_code
);
1332 helper_svm_check_intercept_param(SVM_EXIT_SWINT
, 0);
1335 env
->exception_index
= intno
;
1336 env
->error_code
= error_code
;
1337 env
->exception_is_int
= is_int
;
1338 env
->exception_next_eip
= env
->eip
+ next_eip_addend
;
1342 /* shortcuts to generate exceptions */
1344 void raise_exception_err(int exception_index
, int error_code
)
1346 raise_interrupt(exception_index
, 0, error_code
, 0);
1349 void raise_exception(int exception_index
)
1351 raise_interrupt(exception_index
, 0, 0, 0);
1356 #if defined(CONFIG_USER_ONLY)
1358 void do_smm_enter(void)
1362 void helper_rsm(void)
1368 #ifdef TARGET_X86_64
1369 #define SMM_REVISION_ID 0x00020064
1371 #define SMM_REVISION_ID 0x00020000
1374 void do_smm_enter(void)
1376 target_ulong sm_state
;
1380 qemu_log_mask(CPU_LOG_INT
, "SMM: enter\n");
1381 log_cpu_state_mask(CPU_LOG_INT
, env
, X86_DUMP_CCOP
);
1383 env
->hflags
|= HF_SMM_MASK
;
1384 cpu_smm_update(env
);
1386 sm_state
= env
->smbase
+ 0x8000;
1388 #ifdef TARGET_X86_64
1389 for(i
= 0; i
< 6; i
++) {
1391 offset
= 0x7e00 + i
* 16;
1392 stw_phys(sm_state
+ offset
, dt
->selector
);
1393 stw_phys(sm_state
+ offset
+ 2, (dt
->flags
>> 8) & 0xf0ff);
1394 stl_phys(sm_state
+ offset
+ 4, dt
->limit
);
1395 stq_phys(sm_state
+ offset
+ 8, dt
->base
);
1398 stq_phys(sm_state
+ 0x7e68, env
->gdt
.base
);
1399 stl_phys(sm_state
+ 0x7e64, env
->gdt
.limit
);
1401 stw_phys(sm_state
+ 0x7e70, env
->ldt
.selector
);
1402 stq_phys(sm_state
+ 0x7e78, env
->ldt
.base
);
1403 stl_phys(sm_state
+ 0x7e74, env
->ldt
.limit
);
1404 stw_phys(sm_state
+ 0x7e72, (env
->ldt
.flags
>> 8) & 0xf0ff);
1406 stq_phys(sm_state
+ 0x7e88, env
->idt
.base
);
1407 stl_phys(sm_state
+ 0x7e84, env
->idt
.limit
);
1409 stw_phys(sm_state
+ 0x7e90, env
->tr
.selector
);
1410 stq_phys(sm_state
+ 0x7e98, env
->tr
.base
);
1411 stl_phys(sm_state
+ 0x7e94, env
->tr
.limit
);
1412 stw_phys(sm_state
+ 0x7e92, (env
->tr
.flags
>> 8) & 0xf0ff);
1414 stq_phys(sm_state
+ 0x7ed0, env
->efer
);
1416 stq_phys(sm_state
+ 0x7ff8, EAX
);
1417 stq_phys(sm_state
+ 0x7ff0, ECX
);
1418 stq_phys(sm_state
+ 0x7fe8, EDX
);
1419 stq_phys(sm_state
+ 0x7fe0, EBX
);
1420 stq_phys(sm_state
+ 0x7fd8, ESP
);
1421 stq_phys(sm_state
+ 0x7fd0, EBP
);
1422 stq_phys(sm_state
+ 0x7fc8, ESI
);
1423 stq_phys(sm_state
+ 0x7fc0, EDI
);
1424 for(i
= 8; i
< 16; i
++)
1425 stq_phys(sm_state
+ 0x7ff8 - i
* 8, env
->regs
[i
]);
1426 stq_phys(sm_state
+ 0x7f78, env
->eip
);
1427 stl_phys(sm_state
+ 0x7f70, compute_eflags());
1428 stl_phys(sm_state
+ 0x7f68, env
->dr
[6]);
1429 stl_phys(sm_state
+ 0x7f60, env
->dr
[7]);
1431 stl_phys(sm_state
+ 0x7f48, env
->cr
[4]);
1432 stl_phys(sm_state
+ 0x7f50, env
->cr
[3]);
1433 stl_phys(sm_state
+ 0x7f58, env
->cr
[0]);
1435 stl_phys(sm_state
+ 0x7efc, SMM_REVISION_ID
);
1436 stl_phys(sm_state
+ 0x7f00, env
->smbase
);
1438 stl_phys(sm_state
+ 0x7ffc, env
->cr
[0]);
1439 stl_phys(sm_state
+ 0x7ff8, env
->cr
[3]);
1440 stl_phys(sm_state
+ 0x7ff4, compute_eflags());
1441 stl_phys(sm_state
+ 0x7ff0, env
->eip
);
1442 stl_phys(sm_state
+ 0x7fec, EDI
);
1443 stl_phys(sm_state
+ 0x7fe8, ESI
);
1444 stl_phys(sm_state
+ 0x7fe4, EBP
);
1445 stl_phys(sm_state
+ 0x7fe0, ESP
);
1446 stl_phys(sm_state
+ 0x7fdc, EBX
);
1447 stl_phys(sm_state
+ 0x7fd8, EDX
);
1448 stl_phys(sm_state
+ 0x7fd4, ECX
);
1449 stl_phys(sm_state
+ 0x7fd0, EAX
);
1450 stl_phys(sm_state
+ 0x7fcc, env
->dr
[6]);
1451 stl_phys(sm_state
+ 0x7fc8, env
->dr
[7]);
1453 stl_phys(sm_state
+ 0x7fc4, env
->tr
.selector
);
1454 stl_phys(sm_state
+ 0x7f64, env
->tr
.base
);
1455 stl_phys(sm_state
+ 0x7f60, env
->tr
.limit
);
1456 stl_phys(sm_state
+ 0x7f5c, (env
->tr
.flags
>> 8) & 0xf0ff);
1458 stl_phys(sm_state
+ 0x7fc0, env
->ldt
.selector
);
1459 stl_phys(sm_state
+ 0x7f80, env
->ldt
.base
);
1460 stl_phys(sm_state
+ 0x7f7c, env
->ldt
.limit
);
1461 stl_phys(sm_state
+ 0x7f78, (env
->ldt
.flags
>> 8) & 0xf0ff);
1463 stl_phys(sm_state
+ 0x7f74, env
->gdt
.base
);
1464 stl_phys(sm_state
+ 0x7f70, env
->gdt
.limit
);
1466 stl_phys(sm_state
+ 0x7f58, env
->idt
.base
);
1467 stl_phys(sm_state
+ 0x7f54, env
->idt
.limit
);
1469 for(i
= 0; i
< 6; i
++) {
1472 offset
= 0x7f84 + i
* 12;
1474 offset
= 0x7f2c + (i
- 3) * 12;
1475 stl_phys(sm_state
+ 0x7fa8 + i
* 4, dt
->selector
);
1476 stl_phys(sm_state
+ offset
+ 8, dt
->base
);
1477 stl_phys(sm_state
+ offset
+ 4, dt
->limit
);
1478 stl_phys(sm_state
+ offset
, (dt
->flags
>> 8) & 0xf0ff);
1480 stl_phys(sm_state
+ 0x7f14, env
->cr
[4]);
1482 stl_phys(sm_state
+ 0x7efc, SMM_REVISION_ID
);
1483 stl_phys(sm_state
+ 0x7ef8, env
->smbase
);
1485 /* init SMM cpu state */
1487 #ifdef TARGET_X86_64
1488 cpu_load_efer(env
, 0);
1490 load_eflags(0, ~(CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
| DF_MASK
));
1491 env
->eip
= 0x00008000;
1492 cpu_x86_load_seg_cache(env
, R_CS
, (env
->smbase
>> 4) & 0xffff, env
->smbase
,
1494 cpu_x86_load_seg_cache(env
, R_DS
, 0, 0, 0xffffffff, 0);
1495 cpu_x86_load_seg_cache(env
, R_ES
, 0, 0, 0xffffffff, 0);
1496 cpu_x86_load_seg_cache(env
, R_SS
, 0, 0, 0xffffffff, 0);
1497 cpu_x86_load_seg_cache(env
, R_FS
, 0, 0, 0xffffffff, 0);
1498 cpu_x86_load_seg_cache(env
, R_GS
, 0, 0, 0xffffffff, 0);
1500 cpu_x86_update_cr0(env
,
1501 env
->cr
[0] & ~(CR0_PE_MASK
| CR0_EM_MASK
| CR0_TS_MASK
| CR0_PG_MASK
));
1502 cpu_x86_update_cr4(env
, 0);
1503 env
->dr
[7] = 0x00000400;
1504 CC_OP
= CC_OP_EFLAGS
;
1507 void helper_rsm(void)
1509 target_ulong sm_state
;
1513 sm_state
= env
->smbase
+ 0x8000;
1514 #ifdef TARGET_X86_64
1515 cpu_load_efer(env
, ldq_phys(sm_state
+ 0x7ed0));
1517 for(i
= 0; i
< 6; i
++) {
1518 offset
= 0x7e00 + i
* 16;
1519 cpu_x86_load_seg_cache(env
, i
,
1520 lduw_phys(sm_state
+ offset
),
1521 ldq_phys(sm_state
+ offset
+ 8),
1522 ldl_phys(sm_state
+ offset
+ 4),
1523 (lduw_phys(sm_state
+ offset
+ 2) & 0xf0ff) << 8);
1526 env
->gdt
.base
= ldq_phys(sm_state
+ 0x7e68);
1527 env
->gdt
.limit
= ldl_phys(sm_state
+ 0x7e64);
1529 env
->ldt
.selector
= lduw_phys(sm_state
+ 0x7e70);
1530 env
->ldt
.base
= ldq_phys(sm_state
+ 0x7e78);
1531 env
->ldt
.limit
= ldl_phys(sm_state
+ 0x7e74);
1532 env
->ldt
.flags
= (lduw_phys(sm_state
+ 0x7e72) & 0xf0ff) << 8;
1534 env
->idt
.base
= ldq_phys(sm_state
+ 0x7e88);
1535 env
->idt
.limit
= ldl_phys(sm_state
+ 0x7e84);
1537 env
->tr
.selector
= lduw_phys(sm_state
+ 0x7e90);
1538 env
->tr
.base
= ldq_phys(sm_state
+ 0x7e98);
1539 env
->tr
.limit
= ldl_phys(sm_state
+ 0x7e94);
1540 env
->tr
.flags
= (lduw_phys(sm_state
+ 0x7e92) & 0xf0ff) << 8;
1542 EAX
= ldq_phys(sm_state
+ 0x7ff8);
1543 ECX
= ldq_phys(sm_state
+ 0x7ff0);
1544 EDX
= ldq_phys(sm_state
+ 0x7fe8);
1545 EBX
= ldq_phys(sm_state
+ 0x7fe0);
1546 ESP
= ldq_phys(sm_state
+ 0x7fd8);
1547 EBP
= ldq_phys(sm_state
+ 0x7fd0);
1548 ESI
= ldq_phys(sm_state
+ 0x7fc8);
1549 EDI
= ldq_phys(sm_state
+ 0x7fc0);
1550 for(i
= 8; i
< 16; i
++)
1551 env
->regs
[i
] = ldq_phys(sm_state
+ 0x7ff8 - i
* 8);
1552 env
->eip
= ldq_phys(sm_state
+ 0x7f78);
1553 load_eflags(ldl_phys(sm_state
+ 0x7f70),
1554 ~(CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
| DF_MASK
));
1555 env
->dr
[6] = ldl_phys(sm_state
+ 0x7f68);
1556 env
->dr
[7] = ldl_phys(sm_state
+ 0x7f60);
1558 cpu_x86_update_cr4(env
, ldl_phys(sm_state
+ 0x7f48));
1559 cpu_x86_update_cr3(env
, ldl_phys(sm_state
+ 0x7f50));
1560 cpu_x86_update_cr0(env
, ldl_phys(sm_state
+ 0x7f58));
1562 val
= ldl_phys(sm_state
+ 0x7efc); /* revision ID */
1563 if (val
& 0x20000) {
1564 env
->smbase
= ldl_phys(sm_state
+ 0x7f00) & ~0x7fff;
1567 cpu_x86_update_cr0(env
, ldl_phys(sm_state
+ 0x7ffc));
1568 cpu_x86_update_cr3(env
, ldl_phys(sm_state
+ 0x7ff8));
1569 load_eflags(ldl_phys(sm_state
+ 0x7ff4),
1570 ~(CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
| DF_MASK
));
1571 env
->eip
= ldl_phys(sm_state
+ 0x7ff0);
1572 EDI
= ldl_phys(sm_state
+ 0x7fec);
1573 ESI
= ldl_phys(sm_state
+ 0x7fe8);
1574 EBP
= ldl_phys(sm_state
+ 0x7fe4);
1575 ESP
= ldl_phys(sm_state
+ 0x7fe0);
1576 EBX
= ldl_phys(sm_state
+ 0x7fdc);
1577 EDX
= ldl_phys(sm_state
+ 0x7fd8);
1578 ECX
= ldl_phys(sm_state
+ 0x7fd4);
1579 EAX
= ldl_phys(sm_state
+ 0x7fd0);
1580 env
->dr
[6] = ldl_phys(sm_state
+ 0x7fcc);
1581 env
->dr
[7] = ldl_phys(sm_state
+ 0x7fc8);
1583 env
->tr
.selector
= ldl_phys(sm_state
+ 0x7fc4) & 0xffff;
1584 env
->tr
.base
= ldl_phys(sm_state
+ 0x7f64);
1585 env
->tr
.limit
= ldl_phys(sm_state
+ 0x7f60);
1586 env
->tr
.flags
= (ldl_phys(sm_state
+ 0x7f5c) & 0xf0ff) << 8;
1588 env
->ldt
.selector
= ldl_phys(sm_state
+ 0x7fc0) & 0xffff;
1589 env
->ldt
.base
= ldl_phys(sm_state
+ 0x7f80);
1590 env
->ldt
.limit
= ldl_phys(sm_state
+ 0x7f7c);
1591 env
->ldt
.flags
= (ldl_phys(sm_state
+ 0x7f78) & 0xf0ff) << 8;
1593 env
->gdt
.base
= ldl_phys(sm_state
+ 0x7f74);
1594 env
->gdt
.limit
= ldl_phys(sm_state
+ 0x7f70);
1596 env
->idt
.base
= ldl_phys(sm_state
+ 0x7f58);
1597 env
->idt
.limit
= ldl_phys(sm_state
+ 0x7f54);
1599 for(i
= 0; i
< 6; i
++) {
1601 offset
= 0x7f84 + i
* 12;
1603 offset
= 0x7f2c + (i
- 3) * 12;
1604 cpu_x86_load_seg_cache(env
, i
,
1605 ldl_phys(sm_state
+ 0x7fa8 + i
* 4) & 0xffff,
1606 ldl_phys(sm_state
+ offset
+ 8),
1607 ldl_phys(sm_state
+ offset
+ 4),
1608 (ldl_phys(sm_state
+ offset
) & 0xf0ff) << 8);
1610 cpu_x86_update_cr4(env
, ldl_phys(sm_state
+ 0x7f14));
1612 val
= ldl_phys(sm_state
+ 0x7efc); /* revision ID */
1613 if (val
& 0x20000) {
1614 env
->smbase
= ldl_phys(sm_state
+ 0x7ef8) & ~0x7fff;
1617 CC_OP
= CC_OP_EFLAGS
;
1618 env
->hflags
&= ~HF_SMM_MASK
;
1619 cpu_smm_update(env
);
1621 qemu_log_mask(CPU_LOG_INT
, "SMM: after RSM\n");
1622 log_cpu_state_mask(CPU_LOG_INT
, env
, X86_DUMP_CCOP
);
1625 #endif /* !CONFIG_USER_ONLY */
1628 /* division, flags are undefined */
1630 void helper_divb_AL(target_ulong t0
)
1632 unsigned int num
, den
, q
, r
;
1634 num
= (EAX
& 0xffff);
1637 raise_exception(EXCP00_DIVZ
);
1641 raise_exception(EXCP00_DIVZ
);
1643 r
= (num
% den
) & 0xff;
1644 EAX
= (EAX
& ~0xffff) | (r
<< 8) | q
;
1647 void helper_idivb_AL(target_ulong t0
)
1654 raise_exception(EXCP00_DIVZ
);
1658 raise_exception(EXCP00_DIVZ
);
1660 r
= (num
% den
) & 0xff;
1661 EAX
= (EAX
& ~0xffff) | (r
<< 8) | q
;
1664 void helper_divw_AX(target_ulong t0
)
1666 unsigned int num
, den
, q
, r
;
1668 num
= (EAX
& 0xffff) | ((EDX
& 0xffff) << 16);
1669 den
= (t0
& 0xffff);
1671 raise_exception(EXCP00_DIVZ
);
1675 raise_exception(EXCP00_DIVZ
);
1677 r
= (num
% den
) & 0xffff;
1678 EAX
= (EAX
& ~0xffff) | q
;
1679 EDX
= (EDX
& ~0xffff) | r
;
1682 void helper_idivw_AX(target_ulong t0
)
1686 num
= (EAX
& 0xffff) | ((EDX
& 0xffff) << 16);
1689 raise_exception(EXCP00_DIVZ
);
1692 if (q
!= (int16_t)q
)
1693 raise_exception(EXCP00_DIVZ
);
1695 r
= (num
% den
) & 0xffff;
1696 EAX
= (EAX
& ~0xffff) | q
;
1697 EDX
= (EDX
& ~0xffff) | r
;
1700 void helper_divl_EAX(target_ulong t0
)
1702 unsigned int den
, r
;
1705 num
= ((uint32_t)EAX
) | ((uint64_t)((uint32_t)EDX
) << 32);
1708 raise_exception(EXCP00_DIVZ
);
1713 raise_exception(EXCP00_DIVZ
);
1718 void helper_idivl_EAX(target_ulong t0
)
1723 num
= ((uint32_t)EAX
) | ((uint64_t)((uint32_t)EDX
) << 32);
1726 raise_exception(EXCP00_DIVZ
);
1730 if (q
!= (int32_t)q
)
1731 raise_exception(EXCP00_DIVZ
);
1738 /* XXX: exception */
1739 void helper_aam(int base
)
1745 EAX
= (EAX
& ~0xffff) | al
| (ah
<< 8);
1749 void helper_aad(int base
)
1753 ah
= (EAX
>> 8) & 0xff;
1754 al
= ((ah
* base
) + al
) & 0xff;
1755 EAX
= (EAX
& ~0xffff) | al
;
1759 void helper_aaa(void)
1765 eflags
= helper_cc_compute_all(CC_OP
);
1768 ah
= (EAX
>> 8) & 0xff;
1770 icarry
= (al
> 0xf9);
1771 if (((al
& 0x0f) > 9 ) || af
) {
1772 al
= (al
+ 6) & 0x0f;
1773 ah
= (ah
+ 1 + icarry
) & 0xff;
1774 eflags
|= CC_C
| CC_A
;
1776 eflags
&= ~(CC_C
| CC_A
);
1779 EAX
= (EAX
& ~0xffff) | al
| (ah
<< 8);
1783 void helper_aas(void)
1789 eflags
= helper_cc_compute_all(CC_OP
);
1792 ah
= (EAX
>> 8) & 0xff;
1795 if (((al
& 0x0f) > 9 ) || af
) {
1796 al
= (al
- 6) & 0x0f;
1797 ah
= (ah
- 1 - icarry
) & 0xff;
1798 eflags
|= CC_C
| CC_A
;
1800 eflags
&= ~(CC_C
| CC_A
);
1803 EAX
= (EAX
& ~0xffff) | al
| (ah
<< 8);
1807 void helper_daa(void)
1812 eflags
= helper_cc_compute_all(CC_OP
);
1818 if (((al
& 0x0f) > 9 ) || af
) {
1819 al
= (al
+ 6) & 0xff;
1822 if ((al
> 0x9f) || cf
) {
1823 al
= (al
+ 0x60) & 0xff;
1826 EAX
= (EAX
& ~0xff) | al
;
1827 /* well, speed is not an issue here, so we compute the flags by hand */
1828 eflags
|= (al
== 0) << 6; /* zf */
1829 eflags
|= parity_table
[al
]; /* pf */
1830 eflags
|= (al
& 0x80); /* sf */
1834 void helper_das(void)
1836 int al
, al1
, af
, cf
;
1839 eflags
= helper_cc_compute_all(CC_OP
);
1846 if (((al
& 0x0f) > 9 ) || af
) {
1850 al
= (al
- 6) & 0xff;
1852 if ((al1
> 0x99) || cf
) {
1853 al
= (al
- 0x60) & 0xff;
1856 EAX
= (EAX
& ~0xff) | al
;
1857 /* well, speed is not an issue here, so we compute the flags by hand */
1858 eflags
|= (al
== 0) << 6; /* zf */
1859 eflags
|= parity_table
[al
]; /* pf */
1860 eflags
|= (al
& 0x80); /* sf */
1864 void helper_into(int next_eip_addend
)
1867 eflags
= helper_cc_compute_all(CC_OP
);
1868 if (eflags
& CC_O
) {
1869 raise_interrupt(EXCP04_INTO
, 1, 0, next_eip_addend
);
1873 void helper_cmpxchg8b(target_ulong a0
)
1878 eflags
= helper_cc_compute_all(CC_OP
);
1880 if (d
== (((uint64_t)EDX
<< 32) | (uint32_t)EAX
)) {
1881 stq(a0
, ((uint64_t)ECX
<< 32) | (uint32_t)EBX
);
1884 /* always do the store */
1886 EDX
= (uint32_t)(d
>> 32);
1893 #ifdef TARGET_X86_64
1894 void helper_cmpxchg16b(target_ulong a0
)
1899 if ((a0
& 0xf) != 0)
1900 raise_exception(EXCP0D_GPF
);
1901 eflags
= helper_cc_compute_all(CC_OP
);
1904 if (d0
== EAX
&& d1
== EDX
) {
1909 /* always do the store */
1920 void helper_single_step(void)
1922 #ifndef CONFIG_USER_ONLY
1923 check_hw_breakpoints(env
, 1);
1924 env
->dr
[6] |= DR6_BS
;
1926 raise_exception(EXCP01_DB
);
1929 void helper_cpuid(void)
1931 uint32_t eax
, ebx
, ecx
, edx
;
1933 helper_svm_check_intercept_param(SVM_EXIT_CPUID
, 0);
1935 cpu_x86_cpuid(env
, (uint32_t)EAX
, (uint32_t)ECX
, &eax
, &ebx
, &ecx
, &edx
);
1942 void helper_enter_level(int level
, int data32
, target_ulong t1
)
1945 uint32_t esp_mask
, esp
, ebp
;
1947 esp_mask
= get_sp_mask(env
->segs
[R_SS
].flags
);
1948 ssp
= env
->segs
[R_SS
].base
;
1957 stl(ssp
+ (esp
& esp_mask
), ldl(ssp
+ (ebp
& esp_mask
)));
1960 stl(ssp
+ (esp
& esp_mask
), t1
);
1967 stw(ssp
+ (esp
& esp_mask
), lduw(ssp
+ (ebp
& esp_mask
)));
1970 stw(ssp
+ (esp
& esp_mask
), t1
);
1974 #ifdef TARGET_X86_64
1975 void helper_enter64_level(int level
, int data64
, target_ulong t1
)
1977 target_ulong esp
, ebp
;
1997 stw(esp
, lduw(ebp
));
2005 void helper_lldt(int selector
)
2009 int index
, entry_limit
;
2013 if ((selector
& 0xfffc) == 0) {
2014 /* XXX: NULL selector case: invalid LDT */
2019 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2021 index
= selector
& ~7;
2022 #ifdef TARGET_X86_64
2023 if (env
->hflags
& HF_LMA_MASK
)
2028 if ((index
+ entry_limit
) > dt
->limit
)
2029 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2030 ptr
= dt
->base
+ index
;
2031 e1
= ldl_kernel(ptr
);
2032 e2
= ldl_kernel(ptr
+ 4);
2033 if ((e2
& DESC_S_MASK
) || ((e2
>> DESC_TYPE_SHIFT
) & 0xf) != 2)
2034 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2035 if (!(e2
& DESC_P_MASK
))
2036 raise_exception_err(EXCP0B_NOSEG
, selector
& 0xfffc);
2037 #ifdef TARGET_X86_64
2038 if (env
->hflags
& HF_LMA_MASK
) {
2040 e3
= ldl_kernel(ptr
+ 8);
2041 load_seg_cache_raw_dt(&env
->ldt
, e1
, e2
);
2042 env
->ldt
.base
|= (target_ulong
)e3
<< 32;
2046 load_seg_cache_raw_dt(&env
->ldt
, e1
, e2
);
2049 env
->ldt
.selector
= selector
;
2052 void helper_ltr(int selector
)
2056 int index
, type
, entry_limit
;
2060 if ((selector
& 0xfffc) == 0) {
2061 /* NULL selector case: invalid TR */
2067 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2069 index
= selector
& ~7;
2070 #ifdef TARGET_X86_64
2071 if (env
->hflags
& HF_LMA_MASK
)
2076 if ((index
+ entry_limit
) > dt
->limit
)
2077 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2078 ptr
= dt
->base
+ index
;
2079 e1
= ldl_kernel(ptr
);
2080 e2
= ldl_kernel(ptr
+ 4);
2081 type
= (e2
>> DESC_TYPE_SHIFT
) & 0xf;
2082 if ((e2
& DESC_S_MASK
) ||
2083 (type
!= 1 && type
!= 9))
2084 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2085 if (!(e2
& DESC_P_MASK
))
2086 raise_exception_err(EXCP0B_NOSEG
, selector
& 0xfffc);
2087 #ifdef TARGET_X86_64
2088 if (env
->hflags
& HF_LMA_MASK
) {
2090 e3
= ldl_kernel(ptr
+ 8);
2091 e4
= ldl_kernel(ptr
+ 12);
2092 if ((e4
>> DESC_TYPE_SHIFT
) & 0xf)
2093 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2094 load_seg_cache_raw_dt(&env
->tr
, e1
, e2
);
2095 env
->tr
.base
|= (target_ulong
)e3
<< 32;
2099 load_seg_cache_raw_dt(&env
->tr
, e1
, e2
);
2101 e2
|= DESC_TSS_BUSY_MASK
;
2102 stl_kernel(ptr
+ 4, e2
);
2104 env
->tr
.selector
= selector
;
2107 /* only works if protected mode and not VM86. seg_reg must be != R_CS */
2108 void helper_load_seg(int seg_reg
, int selector
)
2117 cpl
= env
->hflags
& HF_CPL_MASK
;
2118 if ((selector
& 0xfffc) == 0) {
2119 /* null selector case */
2121 #ifdef TARGET_X86_64
2122 && (!(env
->hflags
& HF_CS64_MASK
) || cpl
== 3)
2125 raise_exception_err(EXCP0D_GPF
, 0);
2126 cpu_x86_load_seg_cache(env
, seg_reg
, selector
, 0, 0, 0);
2133 index
= selector
& ~7;
2134 if ((index
+ 7) > dt
->limit
)
2135 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2136 ptr
= dt
->base
+ index
;
2137 e1
= ldl_kernel(ptr
);
2138 e2
= ldl_kernel(ptr
+ 4);
2140 if (!(e2
& DESC_S_MASK
))
2141 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2143 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
2144 if (seg_reg
== R_SS
) {
2145 /* must be writable segment */
2146 if ((e2
& DESC_CS_MASK
) || !(e2
& DESC_W_MASK
))
2147 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2148 if (rpl
!= cpl
|| dpl
!= cpl
)
2149 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2151 /* must be readable segment */
2152 if ((e2
& (DESC_CS_MASK
| DESC_R_MASK
)) == DESC_CS_MASK
)
2153 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2155 if (!(e2
& DESC_CS_MASK
) || !(e2
& DESC_C_MASK
)) {
2156 /* if not conforming code, test rights */
2157 if (dpl
< cpl
|| dpl
< rpl
)
2158 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2162 if (!(e2
& DESC_P_MASK
)) {
2163 if (seg_reg
== R_SS
)
2164 raise_exception_err(EXCP0C_STACK
, selector
& 0xfffc);
2166 raise_exception_err(EXCP0B_NOSEG
, selector
& 0xfffc);
2169 /* set the access bit if not already set */
2170 if (!(e2
& DESC_A_MASK
)) {
2172 stl_kernel(ptr
+ 4, e2
);
2175 cpu_x86_load_seg_cache(env
, seg_reg
, selector
,
2176 get_seg_base(e1
, e2
),
2177 get_seg_limit(e1
, e2
),
2180 qemu_log("load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2181 selector
, (unsigned long)sc
->base
, sc
->limit
, sc
->flags
);
2186 /* protected mode jump */
2187 void helper_ljmp_protected(int new_cs
, target_ulong new_eip
,
2188 int next_eip_addend
)
2191 uint32_t e1
, e2
, cpl
, dpl
, rpl
, limit
;
2192 target_ulong next_eip
;
2194 if ((new_cs
& 0xfffc) == 0)
2195 raise_exception_err(EXCP0D_GPF
, 0);
2196 if (load_segment(&e1
, &e2
, new_cs
) != 0)
2197 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2198 cpl
= env
->hflags
& HF_CPL_MASK
;
2199 if (e2
& DESC_S_MASK
) {
2200 if (!(e2
& DESC_CS_MASK
))
2201 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2202 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
2203 if (e2
& DESC_C_MASK
) {
2204 /* conforming code segment */
2206 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2208 /* non conforming code segment */
2211 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2213 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2215 if (!(e2
& DESC_P_MASK
))
2216 raise_exception_err(EXCP0B_NOSEG
, new_cs
& 0xfffc);
2217 limit
= get_seg_limit(e1
, e2
);
2218 if (new_eip
> limit
&&
2219 !(env
->hflags
& HF_LMA_MASK
) && !(e2
& DESC_L_MASK
))
2220 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2221 cpu_x86_load_seg_cache(env
, R_CS
, (new_cs
& 0xfffc) | cpl
,
2222 get_seg_base(e1
, e2
), limit
, e2
);
2225 /* jump to call or task gate */
2226 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
2228 cpl
= env
->hflags
& HF_CPL_MASK
;
2229 type
= (e2
>> DESC_TYPE_SHIFT
) & 0xf;
2231 case 1: /* 286 TSS */
2232 case 9: /* 386 TSS */
2233 case 5: /* task gate */
2234 if (dpl
< cpl
|| dpl
< rpl
)
2235 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2236 next_eip
= env
->eip
+ next_eip_addend
;
2237 switch_tss(new_cs
, e1
, e2
, SWITCH_TSS_JMP
, next_eip
);
2238 CC_OP
= CC_OP_EFLAGS
;
2240 case 4: /* 286 call gate */
2241 case 12: /* 386 call gate */
2242 if ((dpl
< cpl
) || (dpl
< rpl
))
2243 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2244 if (!(e2
& DESC_P_MASK
))
2245 raise_exception_err(EXCP0B_NOSEG
, new_cs
& 0xfffc);
2247 new_eip
= (e1
& 0xffff);
2249 new_eip
|= (e2
& 0xffff0000);
2250 if (load_segment(&e1
, &e2
, gate_cs
) != 0)
2251 raise_exception_err(EXCP0D_GPF
, gate_cs
& 0xfffc);
2252 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
2253 /* must be code segment */
2254 if (((e2
& (DESC_S_MASK
| DESC_CS_MASK
)) !=
2255 (DESC_S_MASK
| DESC_CS_MASK
)))
2256 raise_exception_err(EXCP0D_GPF
, gate_cs
& 0xfffc);
2257 if (((e2
& DESC_C_MASK
) && (dpl
> cpl
)) ||
2258 (!(e2
& DESC_C_MASK
) && (dpl
!= cpl
)))
2259 raise_exception_err(EXCP0D_GPF
, gate_cs
& 0xfffc);
2260 if (!(e2
& DESC_P_MASK
))
2261 raise_exception_err(EXCP0D_GPF
, gate_cs
& 0xfffc);
2262 limit
= get_seg_limit(e1
, e2
);
2263 if (new_eip
> limit
)
2264 raise_exception_err(EXCP0D_GPF
, 0);
2265 cpu_x86_load_seg_cache(env
, R_CS
, (gate_cs
& 0xfffc) | cpl
,
2266 get_seg_base(e1
, e2
), limit
, e2
);
2270 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2276 /* real mode call */
2277 void helper_lcall_real(int new_cs
, target_ulong new_eip1
,
2278 int shift
, int next_eip
)
2281 uint32_t esp
, esp_mask
;
2286 esp_mask
= get_sp_mask(env
->segs
[R_SS
].flags
);
2287 ssp
= env
->segs
[R_SS
].base
;
2289 PUSHL(ssp
, esp
, esp_mask
, env
->segs
[R_CS
].selector
);
2290 PUSHL(ssp
, esp
, esp_mask
, next_eip
);
2292 PUSHW(ssp
, esp
, esp_mask
, env
->segs
[R_CS
].selector
);
2293 PUSHW(ssp
, esp
, esp_mask
, next_eip
);
2296 SET_ESP(esp
, esp_mask
);
2298 env
->segs
[R_CS
].selector
= new_cs
;
2299 env
->segs
[R_CS
].base
= (new_cs
<< 4);
2302 /* protected mode call */
2303 void helper_lcall_protected(int new_cs
, target_ulong new_eip
,
2304 int shift
, int next_eip_addend
)
2307 uint32_t e1
, e2
, cpl
, dpl
, rpl
, selector
, offset
, param_count
;
2308 uint32_t ss
= 0, ss_e1
= 0, ss_e2
= 0, sp
, type
, ss_dpl
, sp_mask
;
2309 uint32_t val
, limit
, old_sp_mask
;
2310 target_ulong ssp
, old_ssp
, next_eip
;
2312 next_eip
= env
->eip
+ next_eip_addend
;
2313 LOG_PCALL("lcall %04x:%08x s=%d\n", new_cs
, (uint32_t)new_eip
, shift
);
2314 LOG_PCALL_STATE(env
);
2315 if ((new_cs
& 0xfffc) == 0)
2316 raise_exception_err(EXCP0D_GPF
, 0);
2317 if (load_segment(&e1
, &e2
, new_cs
) != 0)
2318 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2319 cpl
= env
->hflags
& HF_CPL_MASK
;
2320 LOG_PCALL("desc=%08x:%08x\n", e1
, e2
);
2321 if (e2
& DESC_S_MASK
) {
2322 if (!(e2
& DESC_CS_MASK
))
2323 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2324 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
2325 if (e2
& DESC_C_MASK
) {
2326 /* conforming code segment */
2328 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2330 /* non conforming code segment */
2333 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2335 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2337 if (!(e2
& DESC_P_MASK
))
2338 raise_exception_err(EXCP0B_NOSEG
, new_cs
& 0xfffc);
2340 #ifdef TARGET_X86_64
2341 /* XXX: check 16/32 bit cases in long mode */
2346 PUSHQ(rsp
, env
->segs
[R_CS
].selector
);
2347 PUSHQ(rsp
, next_eip
);
2348 /* from this point, not restartable */
2350 cpu_x86_load_seg_cache(env
, R_CS
, (new_cs
& 0xfffc) | cpl
,
2351 get_seg_base(e1
, e2
),
2352 get_seg_limit(e1
, e2
), e2
);
2358 sp_mask
= get_sp_mask(env
->segs
[R_SS
].flags
);
2359 ssp
= env
->segs
[R_SS
].base
;
2361 PUSHL(ssp
, sp
, sp_mask
, env
->segs
[R_CS
].selector
);
2362 PUSHL(ssp
, sp
, sp_mask
, next_eip
);
2364 PUSHW(ssp
, sp
, sp_mask
, env
->segs
[R_CS
].selector
);
2365 PUSHW(ssp
, sp
, sp_mask
, next_eip
);
2368 limit
= get_seg_limit(e1
, e2
);
2369 if (new_eip
> limit
)
2370 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2371 /* from this point, not restartable */
2372 SET_ESP(sp
, sp_mask
);
2373 cpu_x86_load_seg_cache(env
, R_CS
, (new_cs
& 0xfffc) | cpl
,
2374 get_seg_base(e1
, e2
), limit
, e2
);
2378 /* check gate type */
2379 type
= (e2
>> DESC_TYPE_SHIFT
) & 0x1f;
2380 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
2383 case 1: /* available 286 TSS */
2384 case 9: /* available 386 TSS */
2385 case 5: /* task gate */
2386 if (dpl
< cpl
|| dpl
< rpl
)
2387 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2388 switch_tss(new_cs
, e1
, e2
, SWITCH_TSS_CALL
, next_eip
);
2389 CC_OP
= CC_OP_EFLAGS
;
2391 case 4: /* 286 call gate */
2392 case 12: /* 386 call gate */
2395 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2400 if (dpl
< cpl
|| dpl
< rpl
)
2401 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2402 /* check valid bit */
2403 if (!(e2
& DESC_P_MASK
))
2404 raise_exception_err(EXCP0B_NOSEG
, new_cs
& 0xfffc);
2405 selector
= e1
>> 16;
2406 offset
= (e2
& 0xffff0000) | (e1
& 0x0000ffff);
2407 param_count
= e2
& 0x1f;
2408 if ((selector
& 0xfffc) == 0)
2409 raise_exception_err(EXCP0D_GPF
, 0);
2411 if (load_segment(&e1
, &e2
, selector
) != 0)
2412 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2413 if (!(e2
& DESC_S_MASK
) || !(e2
& (DESC_CS_MASK
)))
2414 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2415 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
2417 raise_exception_err(EXCP0D_GPF
, selector
& 0xfffc);
2418 if (!(e2
& DESC_P_MASK
))
2419 raise_exception_err(EXCP0B_NOSEG
, selector
& 0xfffc);
2421 if (!(e2
& DESC_C_MASK
) && dpl
< cpl
) {
2422 /* to inner privilege */
2423 get_ss_esp_from_tss(&ss
, &sp
, dpl
);
2424 LOG_PCALL("new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx
"\n",
2425 ss
, sp
, param_count
, ESP
);
2426 if ((ss
& 0xfffc) == 0)
2427 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
2428 if ((ss
& 3) != dpl
)
2429 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
2430 if (load_segment(&ss_e1
, &ss_e2
, ss
) != 0)
2431 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
2432 ss_dpl
= (ss_e2
>> DESC_DPL_SHIFT
) & 3;
2434 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
2435 if (!(ss_e2
& DESC_S_MASK
) ||
2436 (ss_e2
& DESC_CS_MASK
) ||
2437 !(ss_e2
& DESC_W_MASK
))
2438 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
2439 if (!(ss_e2
& DESC_P_MASK
))
2440 raise_exception_err(EXCP0A_TSS
, ss
& 0xfffc);
2442 // push_size = ((param_count * 2) + 8) << shift;
2444 old_sp_mask
= get_sp_mask(env
->segs
[R_SS
].flags
);
2445 old_ssp
= env
->segs
[R_SS
].base
;
2447 sp_mask
= get_sp_mask(ss_e2
);
2448 ssp
= get_seg_base(ss_e1
, ss_e2
);
2450 PUSHL(ssp
, sp
, sp_mask
, env
->segs
[R_SS
].selector
);
2451 PUSHL(ssp
, sp
, sp_mask
, ESP
);
2452 for(i
= param_count
- 1; i
>= 0; i
--) {
2453 val
= ldl_kernel(old_ssp
+ ((ESP
+ i
* 4) & old_sp_mask
));
2454 PUSHL(ssp
, sp
, sp_mask
, val
);
2457 PUSHW(ssp
, sp
, sp_mask
, env
->segs
[R_SS
].selector
);
2458 PUSHW(ssp
, sp
, sp_mask
, ESP
);
2459 for(i
= param_count
- 1; i
>= 0; i
--) {
2460 val
= lduw_kernel(old_ssp
+ ((ESP
+ i
* 2) & old_sp_mask
));
2461 PUSHW(ssp
, sp
, sp_mask
, val
);
2466 /* to same privilege */
2468 sp_mask
= get_sp_mask(env
->segs
[R_SS
].flags
);
2469 ssp
= env
->segs
[R_SS
].base
;
2470 // push_size = (4 << shift);
2475 PUSHL(ssp
, sp
, sp_mask
, env
->segs
[R_CS
].selector
);
2476 PUSHL(ssp
, sp
, sp_mask
, next_eip
);
2478 PUSHW(ssp
, sp
, sp_mask
, env
->segs
[R_CS
].selector
);
2479 PUSHW(ssp
, sp
, sp_mask
, next_eip
);
2482 /* from this point, not restartable */
2485 ss
= (ss
& ~3) | dpl
;
2486 cpu_x86_load_seg_cache(env
, R_SS
, ss
,
2488 get_seg_limit(ss_e1
, ss_e2
),
2492 selector
= (selector
& ~3) | dpl
;
2493 cpu_x86_load_seg_cache(env
, R_CS
, selector
,
2494 get_seg_base(e1
, e2
),
2495 get_seg_limit(e1
, e2
),
2497 cpu_x86_set_cpl(env
, dpl
);
2498 SET_ESP(sp
, sp_mask
);
2503 /* real and vm86 mode iret */
2504 void helper_iret_real(int shift
)
2506 uint32_t sp
, new_cs
, new_eip
, new_eflags
, sp_mask
;
2510 sp_mask
= 0xffff; /* XXXX: use SS segment size ? */
2512 ssp
= env
->segs
[R_SS
].base
;
2515 POPL(ssp
, sp
, sp_mask
, new_eip
);
2516 POPL(ssp
, sp
, sp_mask
, new_cs
);
2518 POPL(ssp
, sp
, sp_mask
, new_eflags
);
2521 POPW(ssp
, sp
, sp_mask
, new_eip
);
2522 POPW(ssp
, sp
, sp_mask
, new_cs
);
2523 POPW(ssp
, sp
, sp_mask
, new_eflags
);
2525 ESP
= (ESP
& ~sp_mask
) | (sp
& sp_mask
);
2526 env
->segs
[R_CS
].selector
= new_cs
;
2527 env
->segs
[R_CS
].base
= (new_cs
<< 4);
2529 if (env
->eflags
& VM_MASK
)
2530 eflags_mask
= TF_MASK
| AC_MASK
| ID_MASK
| IF_MASK
| RF_MASK
| NT_MASK
;
2532 eflags_mask
= TF_MASK
| AC_MASK
| ID_MASK
| IF_MASK
| IOPL_MASK
| RF_MASK
| NT_MASK
;
2534 eflags_mask
&= 0xffff;
2535 load_eflags(new_eflags
, eflags_mask
);
2536 env
->hflags2
&= ~HF2_NMI_MASK
;
2539 static inline void validate_seg(int seg_reg
, int cpl
)
2544 /* XXX: on x86_64, we do not want to nullify FS and GS because
2545 they may still contain a valid base. I would be interested to
2546 know how a real x86_64 CPU behaves */
2547 if ((seg_reg
== R_FS
|| seg_reg
== R_GS
) &&
2548 (env
->segs
[seg_reg
].selector
& 0xfffc) == 0)
2551 e2
= env
->segs
[seg_reg
].flags
;
2552 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
2553 if (!(e2
& DESC_CS_MASK
) || !(e2
& DESC_C_MASK
)) {
2554 /* data or non conforming code segment */
2556 cpu_x86_load_seg_cache(env
, seg_reg
, 0, 0, 0, 0);
2561 /* protected mode iret */
2562 static inline void helper_ret_protected(int shift
, int is_iret
, int addend
)
2564 uint32_t new_cs
, new_eflags
, new_ss
;
2565 uint32_t new_es
, new_ds
, new_fs
, new_gs
;
2566 uint32_t e1
, e2
, ss_e1
, ss_e2
;
2567 int cpl
, dpl
, rpl
, eflags_mask
, iopl
;
2568 target_ulong ssp
, sp
, new_eip
, new_esp
, sp_mask
;
2570 #ifdef TARGET_X86_64
2575 sp_mask
= get_sp_mask(env
->segs
[R_SS
].flags
);
2577 ssp
= env
->segs
[R_SS
].base
;
2578 new_eflags
= 0; /* avoid warning */
2579 #ifdef TARGET_X86_64
2585 POPQ(sp
, new_eflags
);
2591 POPL(ssp
, sp
, sp_mask
, new_eip
);
2592 POPL(ssp
, sp
, sp_mask
, new_cs
);
2595 POPL(ssp
, sp
, sp_mask
, new_eflags
);
2596 if (new_eflags
& VM_MASK
)
2597 goto return_to_vm86
;
2601 POPW(ssp
, sp
, sp_mask
, new_eip
);
2602 POPW(ssp
, sp
, sp_mask
, new_cs
);
2604 POPW(ssp
, sp
, sp_mask
, new_eflags
);
2606 LOG_PCALL("lret new %04x:" TARGET_FMT_lx
" s=%d addend=0x%x\n",
2607 new_cs
, new_eip
, shift
, addend
);
2608 LOG_PCALL_STATE(env
);
2609 if ((new_cs
& 0xfffc) == 0)
2610 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2611 if (load_segment(&e1
, &e2
, new_cs
) != 0)
2612 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2613 if (!(e2
& DESC_S_MASK
) ||
2614 !(e2
& DESC_CS_MASK
))
2615 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2616 cpl
= env
->hflags
& HF_CPL_MASK
;
2619 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2620 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
2621 if (e2
& DESC_C_MASK
) {
2623 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2626 raise_exception_err(EXCP0D_GPF
, new_cs
& 0xfffc);
2628 if (!(e2
& DESC_P_MASK
))
2629 raise_exception_err(EXCP0B_NOSEG
, new_cs
& 0xfffc);
2632 if (rpl
== cpl
&& (!(env
->hflags
& HF_CS64_MASK
) ||
2633 ((env
->hflags
& HF_CS64_MASK
) && !is_iret
))) {
2634 /* return to same privilege level */
2635 cpu_x86_load_seg_cache(env
, R_CS
, new_cs
,
2636 get_seg_base(e1
, e2
),
2637 get_seg_limit(e1
, e2
),
2640 /* return to different privilege level */
2641 #ifdef TARGET_X86_64
2650 POPL(ssp
, sp
, sp_mask
, new_esp
);
2651 POPL(ssp
, sp
, sp_mask
, new_ss
);
2655 POPW(ssp
, sp
, sp_mask
, new_esp
);
2656 POPW(ssp
, sp
, sp_mask
, new_ss
);
2658 LOG_PCALL("new ss:esp=%04x:" TARGET_FMT_lx
"\n",
2660 if ((new_ss
& 0xfffc) == 0) {
2661 #ifdef TARGET_X86_64
2662 /* NULL ss is allowed in long mode if cpl != 3*/
2663 /* XXX: test CS64 ? */
2664 if ((env
->hflags
& HF_LMA_MASK
) && rpl
!= 3) {
2665 cpu_x86_load_seg_cache(env
, R_SS
, new_ss
,
2667 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
2668 DESC_S_MASK
| (rpl
<< DESC_DPL_SHIFT
) |
2669 DESC_W_MASK
| DESC_A_MASK
);
2670 ss_e2
= DESC_B_MASK
; /* XXX: should not be needed ? */
2674 raise_exception_err(EXCP0D_GPF
, 0);
2677 if ((new_ss
& 3) != rpl
)
2678 raise_exception_err(EXCP0D_GPF
, new_ss
& 0xfffc);
2679 if (load_segment(&ss_e1
, &ss_e2
, new_ss
) != 0)
2680 raise_exception_err(EXCP0D_GPF
, new_ss
& 0xfffc);
2681 if (!(ss_e2
& DESC_S_MASK
) ||
2682 (ss_e2
& DESC_CS_MASK
) ||
2683 !(ss_e2
& DESC_W_MASK
))
2684 raise_exception_err(EXCP0D_GPF
, new_ss
& 0xfffc);
2685 dpl
= (ss_e2
>> DESC_DPL_SHIFT
) & 3;
2687 raise_exception_err(EXCP0D_GPF
, new_ss
& 0xfffc);
2688 if (!(ss_e2
& DESC_P_MASK
))
2689 raise_exception_err(EXCP0B_NOSEG
, new_ss
& 0xfffc);
2690 cpu_x86_load_seg_cache(env
, R_SS
, new_ss
,
2691 get_seg_base(ss_e1
, ss_e2
),
2692 get_seg_limit(ss_e1
, ss_e2
),
2696 cpu_x86_load_seg_cache(env
, R_CS
, new_cs
,
2697 get_seg_base(e1
, e2
),
2698 get_seg_limit(e1
, e2
),
2700 cpu_x86_set_cpl(env
, rpl
);
2702 #ifdef TARGET_X86_64
2703 if (env
->hflags
& HF_CS64_MASK
)
2707 sp_mask
= get_sp_mask(ss_e2
);
2709 /* validate data segments */
2710 validate_seg(R_ES
, rpl
);
2711 validate_seg(R_DS
, rpl
);
2712 validate_seg(R_FS
, rpl
);
2713 validate_seg(R_GS
, rpl
);
2717 SET_ESP(sp
, sp_mask
);
2720 /* NOTE: 'cpl' is the _old_ CPL */
2721 eflags_mask
= TF_MASK
| AC_MASK
| ID_MASK
| RF_MASK
| NT_MASK
;
2723 eflags_mask
|= IOPL_MASK
;
2724 iopl
= (env
->eflags
>> IOPL_SHIFT
) & 3;
2726 eflags_mask
|= IF_MASK
;
2728 eflags_mask
&= 0xffff;
2729 load_eflags(new_eflags
, eflags_mask
);
2734 POPL(ssp
, sp
, sp_mask
, new_esp
);
2735 POPL(ssp
, sp
, sp_mask
, new_ss
);
2736 POPL(ssp
, sp
, sp_mask
, new_es
);
2737 POPL(ssp
, sp
, sp_mask
, new_ds
);
2738 POPL(ssp
, sp
, sp_mask
, new_fs
);
2739 POPL(ssp
, sp
, sp_mask
, new_gs
);
2741 /* modify processor state */
2742 load_eflags(new_eflags
, TF_MASK
| AC_MASK
| ID_MASK
|
2743 IF_MASK
| IOPL_MASK
| VM_MASK
| NT_MASK
| VIF_MASK
| VIP_MASK
);
2744 load_seg_vm(R_CS
, new_cs
& 0xffff);
2745 cpu_x86_set_cpl(env
, 3);
2746 load_seg_vm(R_SS
, new_ss
& 0xffff);
2747 load_seg_vm(R_ES
, new_es
& 0xffff);
2748 load_seg_vm(R_DS
, new_ds
& 0xffff);
2749 load_seg_vm(R_FS
, new_fs
& 0xffff);
2750 load_seg_vm(R_GS
, new_gs
& 0xffff);
2752 env
->eip
= new_eip
& 0xffff;
2756 void helper_iret_protected(int shift
, int next_eip
)
2758 int tss_selector
, type
;
2761 /* specific case for TSS */
2762 if (env
->eflags
& NT_MASK
) {
2763 #ifdef TARGET_X86_64
2764 if (env
->hflags
& HF_LMA_MASK
)
2765 raise_exception_err(EXCP0D_GPF
, 0);
2767 tss_selector
= lduw_kernel(env
->tr
.base
+ 0);
2768 if (tss_selector
& 4)
2769 raise_exception_err(EXCP0A_TSS
, tss_selector
& 0xfffc);
2770 if (load_segment(&e1
, &e2
, tss_selector
) != 0)
2771 raise_exception_err(EXCP0A_TSS
, tss_selector
& 0xfffc);
2772 type
= (e2
>> DESC_TYPE_SHIFT
) & 0x17;
2773 /* NOTE: we check both segment and busy TSS */
2775 raise_exception_err(EXCP0A_TSS
, tss_selector
& 0xfffc);
2776 switch_tss(tss_selector
, e1
, e2
, SWITCH_TSS_IRET
, next_eip
);
2778 helper_ret_protected(shift
, 1, 0);
2780 env
->hflags2
&= ~HF2_NMI_MASK
;
2783 void helper_lret_protected(int shift
, int addend
)
2785 helper_ret_protected(shift
, 0, addend
);
2788 void helper_sysenter(void)
2790 if (env
->sysenter_cs
== 0) {
2791 raise_exception_err(EXCP0D_GPF
, 0);
2793 env
->eflags
&= ~(VM_MASK
| IF_MASK
| RF_MASK
);
2794 cpu_x86_set_cpl(env
, 0);
2796 #ifdef TARGET_X86_64
2797 if (env
->hflags
& HF_LMA_MASK
) {
2798 cpu_x86_load_seg_cache(env
, R_CS
, env
->sysenter_cs
& 0xfffc,
2800 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
2802 DESC_CS_MASK
| DESC_R_MASK
| DESC_A_MASK
| DESC_L_MASK
);
2806 cpu_x86_load_seg_cache(env
, R_CS
, env
->sysenter_cs
& 0xfffc,
2808 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
2810 DESC_CS_MASK
| DESC_R_MASK
| DESC_A_MASK
);
2812 cpu_x86_load_seg_cache(env
, R_SS
, (env
->sysenter_cs
+ 8) & 0xfffc,
2814 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
2816 DESC_W_MASK
| DESC_A_MASK
);
2817 ESP
= env
->sysenter_esp
;
2818 EIP
= env
->sysenter_eip
;
2821 void helper_sysexit(int dflag
)
2825 cpl
= env
->hflags
& HF_CPL_MASK
;
2826 if (env
->sysenter_cs
== 0 || cpl
!= 0) {
2827 raise_exception_err(EXCP0D_GPF
, 0);
2829 cpu_x86_set_cpl(env
, 3);
2830 #ifdef TARGET_X86_64
2832 cpu_x86_load_seg_cache(env
, R_CS
, ((env
->sysenter_cs
+ 32) & 0xfffc) | 3,
2834 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
2835 DESC_S_MASK
| (3 << DESC_DPL_SHIFT
) |
2836 DESC_CS_MASK
| DESC_R_MASK
| DESC_A_MASK
| DESC_L_MASK
);
2837 cpu_x86_load_seg_cache(env
, R_SS
, ((env
->sysenter_cs
+ 40) & 0xfffc) | 3,
2839 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
2840 DESC_S_MASK
| (3 << DESC_DPL_SHIFT
) |
2841 DESC_W_MASK
| DESC_A_MASK
);
2845 cpu_x86_load_seg_cache(env
, R_CS
, ((env
->sysenter_cs
+ 16) & 0xfffc) | 3,
2847 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
2848 DESC_S_MASK
| (3 << DESC_DPL_SHIFT
) |
2849 DESC_CS_MASK
| DESC_R_MASK
| DESC_A_MASK
);
2850 cpu_x86_load_seg_cache(env
, R_SS
, ((env
->sysenter_cs
+ 24) & 0xfffc) | 3,
2852 DESC_G_MASK
| DESC_B_MASK
| DESC_P_MASK
|
2853 DESC_S_MASK
| (3 << DESC_DPL_SHIFT
) |
2854 DESC_W_MASK
| DESC_A_MASK
);
2860 #if defined(CONFIG_USER_ONLY)
2861 target_ulong
helper_read_crN(int reg
)
2866 void helper_write_crN(int reg
, target_ulong t0
)
2870 void helper_movl_drN_T0(int reg
, target_ulong t0
)
2874 target_ulong
helper_read_crN(int reg
)
2878 helper_svm_check_intercept_param(SVM_EXIT_READ_CR0
+ reg
, 0);
2884 if (!(env
->hflags2
& HF2_VINTR_MASK
)) {
2885 val
= cpu_get_apic_tpr(env
);
2894 void helper_write_crN(int reg
, target_ulong t0
)
2896 helper_svm_check_intercept_param(SVM_EXIT_WRITE_CR0
+ reg
, 0);
2899 cpu_x86_update_cr0(env
, t0
);
2902 cpu_x86_update_cr3(env
, t0
);
2905 cpu_x86_update_cr4(env
, t0
);
2908 if (!(env
->hflags2
& HF2_VINTR_MASK
)) {
2909 cpu_set_apic_tpr(env
, t0
);
2911 env
->v_tpr
= t0
& 0x0f;
2919 void helper_movl_drN_T0(int reg
, target_ulong t0
)
2924 hw_breakpoint_remove(env
, reg
);
2926 hw_breakpoint_insert(env
, reg
);
2927 } else if (reg
== 7) {
2928 for (i
= 0; i
< 4; i
++)
2929 hw_breakpoint_remove(env
, i
);
2931 for (i
= 0; i
< 4; i
++)
2932 hw_breakpoint_insert(env
, i
);
2938 void helper_lmsw(target_ulong t0
)
2940 /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
2941 if already set to one. */
2942 t0
= (env
->cr
[0] & ~0xe) | (t0
& 0xf);
2943 helper_write_crN(0, t0
);
2946 void helper_clts(void)
2948 env
->cr
[0] &= ~CR0_TS_MASK
;
2949 env
->hflags
&= ~HF_TS_MASK
;
2952 void helper_invlpg(target_ulong addr
)
2954 helper_svm_check_intercept_param(SVM_EXIT_INVLPG
, 0);
2955 tlb_flush_page(env
, addr
);
2958 void helper_rdtsc(void)
2962 if ((env
->cr
[4] & CR4_TSD_MASK
) && ((env
->hflags
& HF_CPL_MASK
) != 0)) {
2963 raise_exception(EXCP0D_GPF
);
2965 helper_svm_check_intercept_param(SVM_EXIT_RDTSC
, 0);
2967 val
= cpu_get_tsc(env
) + env
->tsc_offset
;
2968 EAX
= (uint32_t)(val
);
2969 EDX
= (uint32_t)(val
>> 32);
2972 void helper_rdtscp(void)
2975 ECX
= (uint32_t)(env
->tsc_aux
);
2978 void helper_rdpmc(void)
2980 if ((env
->cr
[4] & CR4_PCE_MASK
) && ((env
->hflags
& HF_CPL_MASK
) != 0)) {
2981 raise_exception(EXCP0D_GPF
);
2983 helper_svm_check_intercept_param(SVM_EXIT_RDPMC
, 0);
2985 /* currently unimplemented */
2986 raise_exception_err(EXCP06_ILLOP
, 0);
2989 #if defined(CONFIG_USER_ONLY)
2990 void helper_wrmsr(void)
2994 void helper_rdmsr(void)
2998 void helper_wrmsr(void)
3002 helper_svm_check_intercept_param(SVM_EXIT_MSR
, 1);
3004 val
= ((uint32_t)EAX
) | ((uint64_t)((uint32_t)EDX
) << 32);
3006 switch((uint32_t)ECX
) {
3007 case MSR_IA32_SYSENTER_CS
:
3008 env
->sysenter_cs
= val
& 0xffff;
3010 case MSR_IA32_SYSENTER_ESP
:
3011 env
->sysenter_esp
= val
;
3013 case MSR_IA32_SYSENTER_EIP
:
3014 env
->sysenter_eip
= val
;
3016 case MSR_IA32_APICBASE
:
3017 cpu_set_apic_base(env
, val
);
3021 uint64_t update_mask
;
3023 if (env
->cpuid_ext2_features
& CPUID_EXT2_SYSCALL
)
3024 update_mask
|= MSR_EFER_SCE
;
3025 if (env
->cpuid_ext2_features
& CPUID_EXT2_LM
)
3026 update_mask
|= MSR_EFER_LME
;
3027 if (env
->cpuid_ext2_features
& CPUID_EXT2_FFXSR
)
3028 update_mask
|= MSR_EFER_FFXSR
;
3029 if (env
->cpuid_ext2_features
& CPUID_EXT2_NX
)
3030 update_mask
|= MSR_EFER_NXE
;
3031 if (env
->cpuid_ext3_features
& CPUID_EXT3_SVM
)
3032 update_mask
|= MSR_EFER_SVME
;
3033 if (env
->cpuid_ext2_features
& CPUID_EXT2_FFXSR
)
3034 update_mask
|= MSR_EFER_FFXSR
;
3035 cpu_load_efer(env
, (env
->efer
& ~update_mask
) |
3036 (val
& update_mask
));
3045 case MSR_VM_HSAVE_PA
:
3046 env
->vm_hsave
= val
;
3048 #ifdef TARGET_X86_64
3059 env
->segs
[R_FS
].base
= val
;
3062 env
->segs
[R_GS
].base
= val
;
3064 case MSR_KERNELGSBASE
:
3065 env
->kernelgsbase
= val
;
3068 case MSR_MTRRphysBase(0):
3069 case MSR_MTRRphysBase(1):
3070 case MSR_MTRRphysBase(2):
3071 case MSR_MTRRphysBase(3):
3072 case MSR_MTRRphysBase(4):
3073 case MSR_MTRRphysBase(5):
3074 case MSR_MTRRphysBase(6):
3075 case MSR_MTRRphysBase(7):
3076 env
->mtrr_var
[((uint32_t)ECX
- MSR_MTRRphysBase(0)) / 2].base
= val
;
3078 case MSR_MTRRphysMask(0):
3079 case MSR_MTRRphysMask(1):
3080 case MSR_MTRRphysMask(2):
3081 case MSR_MTRRphysMask(3):
3082 case MSR_MTRRphysMask(4):
3083 case MSR_MTRRphysMask(5):
3084 case MSR_MTRRphysMask(6):
3085 case MSR_MTRRphysMask(7):
3086 env
->mtrr_var
[((uint32_t)ECX
- MSR_MTRRphysMask(0)) / 2].mask
= val
;
3088 case MSR_MTRRfix64K_00000
:
3089 env
->mtrr_fixed
[(uint32_t)ECX
- MSR_MTRRfix64K_00000
] = val
;
3091 case MSR_MTRRfix16K_80000
:
3092 case MSR_MTRRfix16K_A0000
:
3093 env
->mtrr_fixed
[(uint32_t)ECX
- MSR_MTRRfix16K_80000
+ 1] = val
;
3095 case MSR_MTRRfix4K_C0000
:
3096 case MSR_MTRRfix4K_C8000
:
3097 case MSR_MTRRfix4K_D0000
:
3098 case MSR_MTRRfix4K_D8000
:
3099 case MSR_MTRRfix4K_E0000
:
3100 case MSR_MTRRfix4K_E8000
:
3101 case MSR_MTRRfix4K_F0000
:
3102 case MSR_MTRRfix4K_F8000
:
3103 env
->mtrr_fixed
[(uint32_t)ECX
- MSR_MTRRfix4K_C0000
+ 3] = val
;
3105 case MSR_MTRRdefType
:
3106 env
->mtrr_deftype
= val
;
3108 case MSR_MCG_STATUS
:
3109 env
->mcg_status
= val
;
3112 if ((env
->mcg_cap
& MCG_CTL_P
)
3113 && (val
== 0 || val
== ~(uint64_t)0))
3120 if ((uint32_t)ECX
>= MSR_MC0_CTL
3121 && (uint32_t)ECX
< MSR_MC0_CTL
+ (4 * env
->mcg_cap
& 0xff)) {
3122 uint32_t offset
= (uint32_t)ECX
- MSR_MC0_CTL
;
3123 if ((offset
& 0x3) != 0
3124 || (val
== 0 || val
== ~(uint64_t)0))
3125 env
->mce_banks
[offset
] = val
;
3128 /* XXX: exception ? */
3133 void helper_rdmsr(void)
3137 helper_svm_check_intercept_param(SVM_EXIT_MSR
, 0);
3139 switch((uint32_t)ECX
) {
3140 case MSR_IA32_SYSENTER_CS
:
3141 val
= env
->sysenter_cs
;
3143 case MSR_IA32_SYSENTER_ESP
:
3144 val
= env
->sysenter_esp
;
3146 case MSR_IA32_SYSENTER_EIP
:
3147 val
= env
->sysenter_eip
;
3149 case MSR_IA32_APICBASE
:
3150 val
= cpu_get_apic_base(env
);
3161 case MSR_VM_HSAVE_PA
:
3162 val
= env
->vm_hsave
;
3164 case MSR_IA32_PERF_STATUS
:
3165 /* tsc_increment_by_tick */
3167 /* CPU multiplier */
3168 val
|= (((uint64_t)4ULL) << 40);
3170 #ifdef TARGET_X86_64
3181 val
= env
->segs
[R_FS
].base
;
3184 val
= env
->segs
[R_GS
].base
;
3186 case MSR_KERNELGSBASE
:
3187 val
= env
->kernelgsbase
;
3193 case MSR_MTRRphysBase(0):
3194 case MSR_MTRRphysBase(1):
3195 case MSR_MTRRphysBase(2):
3196 case MSR_MTRRphysBase(3):
3197 case MSR_MTRRphysBase(4):
3198 case MSR_MTRRphysBase(5):
3199 case MSR_MTRRphysBase(6):
3200 case MSR_MTRRphysBase(7):
3201 val
= env
->mtrr_var
[((uint32_t)ECX
- MSR_MTRRphysBase(0)) / 2].base
;
3203 case MSR_MTRRphysMask(0):
3204 case MSR_MTRRphysMask(1):
3205 case MSR_MTRRphysMask(2):
3206 case MSR_MTRRphysMask(3):
3207 case MSR_MTRRphysMask(4):
3208 case MSR_MTRRphysMask(5):
3209 case MSR_MTRRphysMask(6):
3210 case MSR_MTRRphysMask(7):
3211 val
= env
->mtrr_var
[((uint32_t)ECX
- MSR_MTRRphysMask(0)) / 2].mask
;
3213 case MSR_MTRRfix64K_00000
:
3214 val
= env
->mtrr_fixed
[0];
3216 case MSR_MTRRfix16K_80000
:
3217 case MSR_MTRRfix16K_A0000
:
3218 val
= env
->mtrr_fixed
[(uint32_t)ECX
- MSR_MTRRfix16K_80000
+ 1];
3220 case MSR_MTRRfix4K_C0000
:
3221 case MSR_MTRRfix4K_C8000
:
3222 case MSR_MTRRfix4K_D0000
:
3223 case MSR_MTRRfix4K_D8000
:
3224 case MSR_MTRRfix4K_E0000
:
3225 case MSR_MTRRfix4K_E8000
:
3226 case MSR_MTRRfix4K_F0000
:
3227 case MSR_MTRRfix4K_F8000
:
3228 val
= env
->mtrr_fixed
[(uint32_t)ECX
- MSR_MTRRfix4K_C0000
+ 3];
3230 case MSR_MTRRdefType
:
3231 val
= env
->mtrr_deftype
;
3234 if (env
->cpuid_features
& CPUID_MTRR
)
3235 val
= MSR_MTRRcap_VCNT
| MSR_MTRRcap_FIXRANGE_SUPPORT
| MSR_MTRRcap_WC_SUPPORTED
;
3237 /* XXX: exception ? */
3244 if (env
->mcg_cap
& MCG_CTL_P
)
3249 case MSR_MCG_STATUS
:
3250 val
= env
->mcg_status
;
3253 if ((uint32_t)ECX
>= MSR_MC0_CTL
3254 && (uint32_t)ECX
< MSR_MC0_CTL
+ (4 * env
->mcg_cap
& 0xff)) {
3255 uint32_t offset
= (uint32_t)ECX
- MSR_MC0_CTL
;
3256 val
= env
->mce_banks
[offset
];
3259 /* XXX: exception ? */
3263 EAX
= (uint32_t)(val
);
3264 EDX
= (uint32_t)(val
>> 32);
3268 target_ulong
helper_lsl(target_ulong selector1
)
3271 uint32_t e1
, e2
, eflags
, selector
;
3272 int rpl
, dpl
, cpl
, type
;
3274 selector
= selector1
& 0xffff;
3275 eflags
= helper_cc_compute_all(CC_OP
);
3276 if ((selector
& 0xfffc) == 0)
3278 if (load_segment(&e1
, &e2
, selector
) != 0)
3281 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
3282 cpl
= env
->hflags
& HF_CPL_MASK
;
3283 if (e2
& DESC_S_MASK
) {
3284 if ((e2
& DESC_CS_MASK
) && (e2
& DESC_C_MASK
)) {
3287 if (dpl
< cpl
|| dpl
< rpl
)
3291 type
= (e2
>> DESC_TYPE_SHIFT
) & 0xf;
3302 if (dpl
< cpl
|| dpl
< rpl
) {
3304 CC_SRC
= eflags
& ~CC_Z
;
3308 limit
= get_seg_limit(e1
, e2
);
3309 CC_SRC
= eflags
| CC_Z
;
3313 target_ulong
helper_lar(target_ulong selector1
)
3315 uint32_t e1
, e2
, eflags
, selector
;
3316 int rpl
, dpl
, cpl
, type
;
3318 selector
= selector1
& 0xffff;
3319 eflags
= helper_cc_compute_all(CC_OP
);
3320 if ((selector
& 0xfffc) == 0)
3322 if (load_segment(&e1
, &e2
, selector
) != 0)
3325 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
3326 cpl
= env
->hflags
& HF_CPL_MASK
;
3327 if (e2
& DESC_S_MASK
) {
3328 if ((e2
& DESC_CS_MASK
) && (e2
& DESC_C_MASK
)) {
3331 if (dpl
< cpl
|| dpl
< rpl
)
3335 type
= (e2
>> DESC_TYPE_SHIFT
) & 0xf;
3349 if (dpl
< cpl
|| dpl
< rpl
) {
3351 CC_SRC
= eflags
& ~CC_Z
;
3355 CC_SRC
= eflags
| CC_Z
;
3356 return e2
& 0x00f0ff00;
3359 void helper_verr(target_ulong selector1
)
3361 uint32_t e1
, e2
, eflags
, selector
;
3364 selector
= selector1
& 0xffff;
3365 eflags
= helper_cc_compute_all(CC_OP
);
3366 if ((selector
& 0xfffc) == 0)
3368 if (load_segment(&e1
, &e2
, selector
) != 0)
3370 if (!(e2
& DESC_S_MASK
))
3373 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
3374 cpl
= env
->hflags
& HF_CPL_MASK
;
3375 if (e2
& DESC_CS_MASK
) {
3376 if (!(e2
& DESC_R_MASK
))
3378 if (!(e2
& DESC_C_MASK
)) {
3379 if (dpl
< cpl
|| dpl
< rpl
)
3383 if (dpl
< cpl
|| dpl
< rpl
) {
3385 CC_SRC
= eflags
& ~CC_Z
;
3389 CC_SRC
= eflags
| CC_Z
;
3392 void helper_verw(target_ulong selector1
)
3394 uint32_t e1
, e2
, eflags
, selector
;
3397 selector
= selector1
& 0xffff;
3398 eflags
= helper_cc_compute_all(CC_OP
);
3399 if ((selector
& 0xfffc) == 0)
3401 if (load_segment(&e1
, &e2
, selector
) != 0)
3403 if (!(e2
& DESC_S_MASK
))
3406 dpl
= (e2
>> DESC_DPL_SHIFT
) & 3;
3407 cpl
= env
->hflags
& HF_CPL_MASK
;
3408 if (e2
& DESC_CS_MASK
) {
3411 if (dpl
< cpl
|| dpl
< rpl
)
3413 if (!(e2
& DESC_W_MASK
)) {
3415 CC_SRC
= eflags
& ~CC_Z
;
3419 CC_SRC
= eflags
| CC_Z
;
3422 /* x87 FPU helpers */
3424 static void fpu_set_exception(int mask
)
3427 if (env
->fpus
& (~env
->fpuc
& FPUC_EM
))
3428 env
->fpus
|= FPUS_SE
| FPUS_B
;
3431 static inline CPU86_LDouble
helper_fdiv(CPU86_LDouble a
, CPU86_LDouble b
)
3434 fpu_set_exception(FPUS_ZE
);
3438 static void fpu_raise_exception(void)
3440 if (env
->cr
[0] & CR0_NE_MASK
) {
3441 raise_exception(EXCP10_COPR
);
3443 #if !defined(CONFIG_USER_ONLY)
3450 void helper_flds_FT0(uint32_t val
)
3457 FT0
= float32_to_floatx(u
.f
, &env
->fp_status
);
3460 void helper_fldl_FT0(uint64_t val
)
3467 FT0
= float64_to_floatx(u
.f
, &env
->fp_status
);
3470 void helper_fildl_FT0(int32_t val
)
3472 FT0
= int32_to_floatx(val
, &env
->fp_status
);
3475 void helper_flds_ST0(uint32_t val
)
3482 new_fpstt
= (env
->fpstt
- 1) & 7;
3484 env
->fpregs
[new_fpstt
].d
= float32_to_floatx(u
.f
, &env
->fp_status
);
3485 env
->fpstt
= new_fpstt
;
3486 env
->fptags
[new_fpstt
] = 0; /* validate stack entry */
3489 void helper_fldl_ST0(uint64_t val
)
3496 new_fpstt
= (env
->fpstt
- 1) & 7;
3498 env
->fpregs
[new_fpstt
].d
= float64_to_floatx(u
.f
, &env
->fp_status
);
3499 env
->fpstt
= new_fpstt
;
3500 env
->fptags
[new_fpstt
] = 0; /* validate stack entry */
3503 void helper_fildl_ST0(int32_t val
)
3506 new_fpstt
= (env
->fpstt
- 1) & 7;
3507 env
->fpregs
[new_fpstt
].d
= int32_to_floatx(val
, &env
->fp_status
);
3508 env
->fpstt
= new_fpstt
;
3509 env
->fptags
[new_fpstt
] = 0; /* validate stack entry */
3512 void helper_fildll_ST0(int64_t val
)
3515 new_fpstt
= (env
->fpstt
- 1) & 7;
3516 env
->fpregs
[new_fpstt
].d
= int64_to_floatx(val
, &env
->fp_status
);
3517 env
->fpstt
= new_fpstt
;
3518 env
->fptags
[new_fpstt
] = 0; /* validate stack entry */
3521 uint32_t helper_fsts_ST0(void)
3527 u
.f
= floatx_to_float32(ST0
, &env
->fp_status
);
3531 uint64_t helper_fstl_ST0(void)
3537 u
.f
= floatx_to_float64(ST0
, &env
->fp_status
);
3541 int32_t helper_fist_ST0(void)
3544 val
= floatx_to_int32(ST0
, &env
->fp_status
);
3545 if (val
!= (int16_t)val
)
3550 int32_t helper_fistl_ST0(void)
3553 val
= floatx_to_int32(ST0
, &env
->fp_status
);
3557 int64_t helper_fistll_ST0(void)
3560 val
= floatx_to_int64(ST0
, &env
->fp_status
);
3564 int32_t helper_fistt_ST0(void)
3567 val
= floatx_to_int32_round_to_zero(ST0
, &env
->fp_status
);
3568 if (val
!= (int16_t)val
)
3573 int32_t helper_fisttl_ST0(void)
3576 val
= floatx_to_int32_round_to_zero(ST0
, &env
->fp_status
);
3580 int64_t helper_fisttll_ST0(void)
3583 val
= floatx_to_int64_round_to_zero(ST0
, &env
->fp_status
);
3587 void helper_fldt_ST0(target_ulong ptr
)
3590 new_fpstt
= (env
->fpstt
- 1) & 7;
3591 env
->fpregs
[new_fpstt
].d
= helper_fldt(ptr
);
3592 env
->fpstt
= new_fpstt
;
3593 env
->fptags
[new_fpstt
] = 0; /* validate stack entry */
3596 void helper_fstt_ST0(target_ulong ptr
)
3598 helper_fstt(ST0
, ptr
);
3601 void helper_fpush(void)
3606 void helper_fpop(void)
3611 void helper_fdecstp(void)
3613 env
->fpstt
= (env
->fpstt
- 1) & 7;
3614 env
->fpus
&= (~0x4700);
3617 void helper_fincstp(void)
3619 env
->fpstt
= (env
->fpstt
+ 1) & 7;
3620 env
->fpus
&= (~0x4700);
3625 void helper_ffree_STN(int st_index
)
3627 env
->fptags
[(env
->fpstt
+ st_index
) & 7] = 1;
3630 void helper_fmov_ST0_FT0(void)
3635 void helper_fmov_FT0_STN(int st_index
)
3640 void helper_fmov_ST0_STN(int st_index
)
3645 void helper_fmov_STN_ST0(int st_index
)
3650 void helper_fxchg_ST0_STN(int st_index
)
3658 /* FPU operations */
3660 static const int fcom_ccval
[4] = {0x0100, 0x4000, 0x0000, 0x4500};
3662 void helper_fcom_ST0_FT0(void)
3666 ret
= floatx_compare(ST0
, FT0
, &env
->fp_status
);
3667 env
->fpus
= (env
->fpus
& ~0x4500) | fcom_ccval
[ret
+ 1];
3670 void helper_fucom_ST0_FT0(void)
3674 ret
= floatx_compare_quiet(ST0
, FT0
, &env
->fp_status
);
3675 env
->fpus
= (env
->fpus
& ~0x4500) | fcom_ccval
[ret
+ 1];
3678 static const int fcomi_ccval
[4] = {CC_C
, CC_Z
, 0, CC_Z
| CC_P
| CC_C
};
3680 void helper_fcomi_ST0_FT0(void)
3685 ret
= floatx_compare(ST0
, FT0
, &env
->fp_status
);
3686 eflags
= helper_cc_compute_all(CC_OP
);
3687 eflags
= (eflags
& ~(CC_Z
| CC_P
| CC_C
)) | fcomi_ccval
[ret
+ 1];
3691 void helper_fucomi_ST0_FT0(void)
3696 ret
= floatx_compare_quiet(ST0
, FT0
, &env
->fp_status
);
3697 eflags
= helper_cc_compute_all(CC_OP
);
3698 eflags
= (eflags
& ~(CC_Z
| CC_P
| CC_C
)) | fcomi_ccval
[ret
+ 1];
3702 void helper_fadd_ST0_FT0(void)
3707 void helper_fmul_ST0_FT0(void)
3712 void helper_fsub_ST0_FT0(void)
3717 void helper_fsubr_ST0_FT0(void)
3722 void helper_fdiv_ST0_FT0(void)
3724 ST0
= helper_fdiv(ST0
, FT0
);
3727 void helper_fdivr_ST0_FT0(void)
3729 ST0
= helper_fdiv(FT0
, ST0
);
3732 /* fp operations between STN and ST0 */
3734 void helper_fadd_STN_ST0(int st_index
)
3736 ST(st_index
) += ST0
;
3739 void helper_fmul_STN_ST0(int st_index
)
3741 ST(st_index
) *= ST0
;
3744 void helper_fsub_STN_ST0(int st_index
)
3746 ST(st_index
) -= ST0
;
3749 void helper_fsubr_STN_ST0(int st_index
)
3756 void helper_fdiv_STN_ST0(int st_index
)
3760 *p
= helper_fdiv(*p
, ST0
);
3763 void helper_fdivr_STN_ST0(int st_index
)
3767 *p
= helper_fdiv(ST0
, *p
);
3770 /* misc FPU operations */
3771 void helper_fchs_ST0(void)
3773 ST0
= floatx_chs(ST0
);
3776 void helper_fabs_ST0(void)
3778 ST0
= floatx_abs(ST0
);
3781 void helper_fld1_ST0(void)
3786 void helper_fldl2t_ST0(void)
3791 void helper_fldl2e_ST0(void)
3796 void helper_fldpi_ST0(void)
3801 void helper_fldlg2_ST0(void)
3806 void helper_fldln2_ST0(void)
3811 void helper_fldz_ST0(void)
3816 void helper_fldz_FT0(void)
3821 uint32_t helper_fnstsw(void)
3823 return (env
->fpus
& ~0x3800) | (env
->fpstt
& 0x7) << 11;
3826 uint32_t helper_fnstcw(void)
3831 static void update_fp_status(void)
3835 /* set rounding mode */
3836 switch(env
->fpuc
& RC_MASK
) {
3839 rnd_type
= float_round_nearest_even
;
3842 rnd_type
= float_round_down
;
3845 rnd_type
= float_round_up
;
3848 rnd_type
= float_round_to_zero
;
3851 set_float_rounding_mode(rnd_type
, &env
->fp_status
);
3853 switch((env
->fpuc
>> 8) & 3) {
3865 set_floatx80_rounding_precision(rnd_type
, &env
->fp_status
);
3869 void helper_fldcw(uint32_t val
)
3875 void helper_fclex(void)
3877 env
->fpus
&= 0x7f00;
3880 void helper_fwait(void)
3882 if (env
->fpus
& FPUS_SE
)
3883 fpu_raise_exception();
3886 void helper_fninit(void)
3903 void helper_fbld_ST0(target_ulong ptr
)
3911 for(i
= 8; i
>= 0; i
--) {
3913 val
= (val
* 100) + ((v
>> 4) * 10) + (v
& 0xf);
3916 if (ldub(ptr
+ 9) & 0x80)
3922 void helper_fbst_ST0(target_ulong ptr
)
3925 target_ulong mem_ref
, mem_end
;
3928 val
= floatx_to_int64(ST0
, &env
->fp_status
);
3930 mem_end
= mem_ref
+ 9;
3937 while (mem_ref
< mem_end
) {
3942 v
= ((v
/ 10) << 4) | (v
% 10);
3945 while (mem_ref
< mem_end
) {
3950 void helper_f2xm1(void)
3952 ST0
= pow(2.0,ST0
) - 1.0;
3955 void helper_fyl2x(void)
3957 CPU86_LDouble fptemp
;
3961 fptemp
= log(fptemp
)/log(2.0); /* log2(ST) */
3965 env
->fpus
&= (~0x4700);
3970 void helper_fptan(void)
3972 CPU86_LDouble fptemp
;
3975 if((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
3981 env
->fpus
&= (~0x400); /* C2 <-- 0 */
3982 /* the above code is for |arg| < 2**52 only */
3986 void helper_fpatan(void)
3988 CPU86_LDouble fptemp
, fpsrcop
;
3992 ST1
= atan2(fpsrcop
,fptemp
);
3996 void helper_fxtract(void)
3998 CPU86_LDoubleU temp
;
3999 unsigned int expdif
;
4002 expdif
= EXPD(temp
) - EXPBIAS
;
4003 /*DP exponent bias*/
4010 void helper_fprem1(void)
4012 CPU86_LDouble dblq
, fpsrcop
, fptemp
;
4013 CPU86_LDoubleU fpsrcop1
, fptemp1
;
4015 signed long long int q
;
4017 if (isinf(ST0
) || isnan(ST0
) || isnan(ST1
) || (ST1
== 0.0)) {
4018 ST0
= 0.0 / 0.0; /* NaN */
4019 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4025 fpsrcop1
.d
= fpsrcop
;
4027 expdif
= EXPD(fpsrcop1
) - EXPD(fptemp1
);
4030 /* optimisation? taken from the AMD docs */
4031 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4032 /* ST0 is unchanged */
4037 dblq
= fpsrcop
/ fptemp
;
4038 /* round dblq towards nearest integer */
4040 ST0
= fpsrcop
- fptemp
* dblq
;
4042 /* convert dblq to q by truncating towards zero */
4044 q
= (signed long long int)(-dblq
);
4046 q
= (signed long long int)dblq
;
4048 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4049 /* (C0,C3,C1) <-- (q2,q1,q0) */
4050 env
->fpus
|= (q
& 0x4) << (8 - 2); /* (C0) <-- q2 */
4051 env
->fpus
|= (q
& 0x2) << (14 - 1); /* (C3) <-- q1 */
4052 env
->fpus
|= (q
& 0x1) << (9 - 0); /* (C1) <-- q0 */
4054 env
->fpus
|= 0x400; /* C2 <-- 1 */
4055 fptemp
= pow(2.0, expdif
- 50);
4056 fpsrcop
= (ST0
/ ST1
) / fptemp
;
4057 /* fpsrcop = integer obtained by chopping */
4058 fpsrcop
= (fpsrcop
< 0.0) ?
4059 -(floor(fabs(fpsrcop
))) : floor(fpsrcop
);
4060 ST0
-= (ST1
* fpsrcop
* fptemp
);
4064 void helper_fprem(void)
4066 CPU86_LDouble dblq
, fpsrcop
, fptemp
;
4067 CPU86_LDoubleU fpsrcop1
, fptemp1
;
4069 signed long long int q
;
4071 if (isinf(ST0
) || isnan(ST0
) || isnan(ST1
) || (ST1
== 0.0)) {
4072 ST0
= 0.0 / 0.0; /* NaN */
4073 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4077 fpsrcop
= (CPU86_LDouble
)ST0
;
4078 fptemp
= (CPU86_LDouble
)ST1
;
4079 fpsrcop1
.d
= fpsrcop
;
4081 expdif
= EXPD(fpsrcop1
) - EXPD(fptemp1
);
4084 /* optimisation? taken from the AMD docs */
4085 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4086 /* ST0 is unchanged */
4090 if ( expdif
< 53 ) {
4091 dblq
= fpsrcop
/*ST0*/ / fptemp
/*ST1*/;
4092 /* round dblq towards zero */
4093 dblq
= (dblq
< 0.0) ? ceil(dblq
) : floor(dblq
);
4094 ST0
= fpsrcop
/*ST0*/ - fptemp
* dblq
;
4096 /* convert dblq to q by truncating towards zero */
4098 q
= (signed long long int)(-dblq
);
4100 q
= (signed long long int)dblq
;
4102 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4103 /* (C0,C3,C1) <-- (q2,q1,q0) */
4104 env
->fpus
|= (q
& 0x4) << (8 - 2); /* (C0) <-- q2 */
4105 env
->fpus
|= (q
& 0x2) << (14 - 1); /* (C3) <-- q1 */
4106 env
->fpus
|= (q
& 0x1) << (9 - 0); /* (C1) <-- q0 */
4108 int N
= 32 + (expdif
% 32); /* as per AMD docs */
4109 env
->fpus
|= 0x400; /* C2 <-- 1 */
4110 fptemp
= pow(2.0, (double)(expdif
- N
));
4111 fpsrcop
= (ST0
/ ST1
) / fptemp
;
4112 /* fpsrcop = integer obtained by chopping */
4113 fpsrcop
= (fpsrcop
< 0.0) ?
4114 -(floor(fabs(fpsrcop
))) : floor(fpsrcop
);
4115 ST0
-= (ST1
* fpsrcop
* fptemp
);
4119 void helper_fyl2xp1(void)
4121 CPU86_LDouble fptemp
;
4124 if ((fptemp
+1.0)>0.0) {
4125 fptemp
= log(fptemp
+1.0) / log(2.0); /* log2(ST+1.0) */
4129 env
->fpus
&= (~0x4700);
4134 void helper_fsqrt(void)
4136 CPU86_LDouble fptemp
;
4140 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4146 void helper_fsincos(void)
4148 CPU86_LDouble fptemp
;
4151 if ((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
4157 env
->fpus
&= (~0x400); /* C2 <-- 0 */
4158 /* the above code is for |arg| < 2**63 only */
4162 void helper_frndint(void)
4164 ST0
= floatx_round_to_int(ST0
, &env
->fp_status
);
4167 void helper_fscale(void)
4169 ST0
= ldexp (ST0
, (int)(ST1
));
4172 void helper_fsin(void)
4174 CPU86_LDouble fptemp
;
4177 if ((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
4181 env
->fpus
&= (~0x400); /* C2 <-- 0 */
4182 /* the above code is for |arg| < 2**53 only */
4186 void helper_fcos(void)
4188 CPU86_LDouble fptemp
;
4191 if((fptemp
> MAXTAN
)||(fptemp
< -MAXTAN
)) {
4195 env
->fpus
&= (~0x400); /* C2 <-- 0 */
4196 /* the above code is for |arg5 < 2**63 only */
4200 void helper_fxam_ST0(void)
4202 CPU86_LDoubleU temp
;
4207 env
->fpus
&= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4209 env
->fpus
|= 0x200; /* C1 <-- 1 */
4211 /* XXX: test fptags too */
4212 expdif
= EXPD(temp
);
4213 if (expdif
== MAXEXPD
) {
4214 #ifdef USE_X86LDOUBLE
4215 if (MANTD(temp
) == 0x8000000000000000ULL
)
4217 if (MANTD(temp
) == 0)
4219 env
->fpus
|= 0x500 /*Infinity*/;
4221 env
->fpus
|= 0x100 /*NaN*/;
4222 } else if (expdif
== 0) {
4223 if (MANTD(temp
) == 0)
4224 env
->fpus
|= 0x4000 /*Zero*/;
4226 env
->fpus
|= 0x4400 /*Denormal*/;
4232 void helper_fstenv(target_ulong ptr
, int data32
)
4234 int fpus
, fptag
, exp
, i
;
4238 fpus
= (env
->fpus
& ~0x3800) | (env
->fpstt
& 0x7) << 11;
4240 for (i
=7; i
>=0; i
--) {
4242 if (env
->fptags
[i
]) {
4245 tmp
.d
= env
->fpregs
[i
].d
;
4248 if (exp
== 0 && mant
== 0) {
4251 } else if (exp
== 0 || exp
== MAXEXPD
4252 #ifdef USE_X86LDOUBLE
4253 || (mant
& (1LL << 63)) == 0
4256 /* NaNs, infinity, denormal */
4263 stl(ptr
, env
->fpuc
);
4265 stl(ptr
+ 8, fptag
);
4266 stl(ptr
+ 12, 0); /* fpip */
4267 stl(ptr
+ 16, 0); /* fpcs */
4268 stl(ptr
+ 20, 0); /* fpoo */
4269 stl(ptr
+ 24, 0); /* fpos */
4272 stw(ptr
, env
->fpuc
);
4274 stw(ptr
+ 4, fptag
);
4282 void helper_fldenv(target_ulong ptr
, int data32
)
4287 env
->fpuc
= lduw(ptr
);
4288 fpus
= lduw(ptr
+ 4);
4289 fptag
= lduw(ptr
+ 8);
4292 env
->fpuc
= lduw(ptr
);
4293 fpus
= lduw(ptr
+ 2);
4294 fptag
= lduw(ptr
+ 4);
4296 env
->fpstt
= (fpus
>> 11) & 7;
4297 env
->fpus
= fpus
& ~0x3800;
4298 for(i
= 0;i
< 8; i
++) {
4299 env
->fptags
[i
] = ((fptag
& 3) == 3);
4304 void helper_fsave(target_ulong ptr
, int data32
)
4309 helper_fstenv(ptr
, data32
);
4311 ptr
+= (14 << data32
);
4312 for(i
= 0;i
< 8; i
++) {
4314 helper_fstt(tmp
, ptr
);
4332 void helper_frstor(target_ulong ptr
, int data32
)
4337 helper_fldenv(ptr
, data32
);
4338 ptr
+= (14 << data32
);
4340 for(i
= 0;i
< 8; i
++) {
4341 tmp
= helper_fldt(ptr
);
4347 void helper_fxsave(target_ulong ptr
, int data64
)
4349 int fpus
, fptag
, i
, nb_xmm_regs
;
4353 /* The operand must be 16 byte aligned */
4355 raise_exception(EXCP0D_GPF
);
4358 fpus
= (env
->fpus
& ~0x3800) | (env
->fpstt
& 0x7) << 11;
4360 for(i
= 0; i
< 8; i
++) {
4361 fptag
|= (env
->fptags
[i
] << i
);
4363 stw(ptr
, env
->fpuc
);
4365 stw(ptr
+ 4, fptag
^ 0xff);
4366 #ifdef TARGET_X86_64
4368 stq(ptr
+ 0x08, 0); /* rip */
4369 stq(ptr
+ 0x10, 0); /* rdp */
4373 stl(ptr
+ 0x08, 0); /* eip */
4374 stl(ptr
+ 0x0c, 0); /* sel */
4375 stl(ptr
+ 0x10, 0); /* dp */
4376 stl(ptr
+ 0x14, 0); /* sel */
4380 for(i
= 0;i
< 8; i
++) {
4382 helper_fstt(tmp
, addr
);
4386 if (env
->cr
[4] & CR4_OSFXSR_MASK
) {
4387 /* XXX: finish it */
4388 stl(ptr
+ 0x18, env
->mxcsr
); /* mxcsr */
4389 stl(ptr
+ 0x1c, 0x0000ffff); /* mxcsr_mask */
4390 if (env
->hflags
& HF_CS64_MASK
)
4395 /* Fast FXSAVE leaves out the XMM registers */
4396 if (!(env
->efer
& MSR_EFER_FFXSR
)
4397 || (env
->hflags
& HF_CPL_MASK
)
4398 || !(env
->hflags
& HF_LMA_MASK
)) {
4399 for(i
= 0; i
< nb_xmm_regs
; i
++) {
4400 stq(addr
, env
->xmm_regs
[i
].XMM_Q(0));
4401 stq(addr
+ 8, env
->xmm_regs
[i
].XMM_Q(1));
4408 void helper_fxrstor(target_ulong ptr
, int data64
)
4410 int i
, fpus
, fptag
, nb_xmm_regs
;
4414 /* The operand must be 16 byte aligned */
4416 raise_exception(EXCP0D_GPF
);
4419 env
->fpuc
= lduw(ptr
);
4420 fpus
= lduw(ptr
+ 2);
4421 fptag
= lduw(ptr
+ 4);
4422 env
->fpstt
= (fpus
>> 11) & 7;
4423 env
->fpus
= fpus
& ~0x3800;
4425 for(i
= 0;i
< 8; i
++) {
4426 env
->fptags
[i
] = ((fptag
>> i
) & 1);
4430 for(i
= 0;i
< 8; i
++) {
4431 tmp
= helper_fldt(addr
);
4436 if (env
->cr
[4] & CR4_OSFXSR_MASK
) {
4437 /* XXX: finish it */
4438 env
->mxcsr
= ldl(ptr
+ 0x18);
4440 if (env
->hflags
& HF_CS64_MASK
)
4445 /* Fast FXRESTORE leaves out the XMM registers */
4446 if (!(env
->efer
& MSR_EFER_FFXSR
)
4447 || (env
->hflags
& HF_CPL_MASK
)
4448 || !(env
->hflags
& HF_LMA_MASK
)) {
4449 for(i
= 0; i
< nb_xmm_regs
; i
++) {
4450 env
->xmm_regs
[i
].XMM_Q(0) = ldq(addr
);
4451 env
->xmm_regs
[i
].XMM_Q(1) = ldq(addr
+ 8);
4458 #ifndef USE_X86LDOUBLE
4460 void cpu_get_fp80(uint64_t *pmant
, uint16_t *pexp
, CPU86_LDouble f
)
4462 CPU86_LDoubleU temp
;
4467 *pmant
= (MANTD(temp
) << 11) | (1LL << 63);
4468 /* exponent + sign */
4469 e
= EXPD(temp
) - EXPBIAS
+ 16383;
4470 e
|= SIGND(temp
) >> 16;
4474 CPU86_LDouble
cpu_set_fp80(uint64_t mant
, uint16_t upper
)
4476 CPU86_LDoubleU temp
;
4480 /* XXX: handle overflow ? */
4481 e
= (upper
& 0x7fff) - 16383 + EXPBIAS
; /* exponent */
4482 e
|= (upper
>> 4) & 0x800; /* sign */
4483 ll
= (mant
>> 11) & ((1LL << 52) - 1);
4485 temp
.l
.upper
= (e
<< 20) | (ll
>> 32);
4488 temp
.ll
= ll
| ((uint64_t)e
<< 52);
4495 void cpu_get_fp80(uint64_t *pmant
, uint16_t *pexp
, CPU86_LDouble f
)
4497 CPU86_LDoubleU temp
;
4500 *pmant
= temp
.l
.lower
;
4501 *pexp
= temp
.l
.upper
;
4504 CPU86_LDouble
cpu_set_fp80(uint64_t mant
, uint16_t upper
)
4506 CPU86_LDoubleU temp
;
4508 temp
.l
.upper
= upper
;
4509 temp
.l
.lower
= mant
;
4514 #ifdef TARGET_X86_64
4516 //#define DEBUG_MULDIV
4518 static void add128(uint64_t *plow
, uint64_t *phigh
, uint64_t a
, uint64_t b
)
4527 static void neg128(uint64_t *plow
, uint64_t *phigh
)
4531 add128(plow
, phigh
, 1, 0);
4534 /* return TRUE if overflow */
4535 static int div64(uint64_t *plow
, uint64_t *phigh
, uint64_t b
)
4537 uint64_t q
, r
, a1
, a0
;
4550 /* XXX: use a better algorithm */
4551 for(i
= 0; i
< 64; i
++) {
4553 a1
= (a1
<< 1) | (a0
>> 63);
4554 if (ab
|| a1
>= b
) {
4560 a0
= (a0
<< 1) | qb
;
4562 #if defined(DEBUG_MULDIV)
4563 printf("div: 0x%016" PRIx64
"%016" PRIx64
" / 0x%016" PRIx64
": q=0x%016" PRIx64
" r=0x%016" PRIx64
"\n",
4564 *phigh
, *plow
, b
, a0
, a1
);
4572 /* return TRUE if overflow */
4573 static int idiv64(uint64_t *plow
, uint64_t *phigh
, int64_t b
)
4576 sa
= ((int64_t)*phigh
< 0);
4578 neg128(plow
, phigh
);
4582 if (div64(plow
, phigh
, b
) != 0)
4585 if (*plow
> (1ULL << 63))
4589 if (*plow
>= (1ULL << 63))
4597 void helper_mulq_EAX_T0(target_ulong t0
)
4601 mulu64(&r0
, &r1
, EAX
, t0
);
4608 void helper_imulq_EAX_T0(target_ulong t0
)
4612 muls64(&r0
, &r1
, EAX
, t0
);
4616 CC_SRC
= ((int64_t)r1
!= ((int64_t)r0
>> 63));
4619 target_ulong
helper_imulq_T0_T1(target_ulong t0
, target_ulong t1
)
4623 muls64(&r0
, &r1
, t0
, t1
);
4625 CC_SRC
= ((int64_t)r1
!= ((int64_t)r0
>> 63));
4629 void helper_divq_EAX(target_ulong t0
)
4633 raise_exception(EXCP00_DIVZ
);
4637 if (div64(&r0
, &r1
, t0
))
4638 raise_exception(EXCP00_DIVZ
);
4643 void helper_idivq_EAX(target_ulong t0
)
4647 raise_exception(EXCP00_DIVZ
);
4651 if (idiv64(&r0
, &r1
, t0
))
4652 raise_exception(EXCP00_DIVZ
);
4658 static void do_hlt(void)
4660 env
->hflags
&= ~HF_INHIBIT_IRQ_MASK
; /* needed if sti is just before */
4662 env
->exception_index
= EXCP_HLT
;
4666 void helper_hlt(int next_eip_addend
)
4668 helper_svm_check_intercept_param(SVM_EXIT_HLT
, 0);
4669 EIP
+= next_eip_addend
;
4674 void helper_monitor(target_ulong ptr
)
4676 if ((uint32_t)ECX
!= 0)
4677 raise_exception(EXCP0D_GPF
);
4678 /* XXX: store address ? */
4679 helper_svm_check_intercept_param(SVM_EXIT_MONITOR
, 0);
4682 void helper_mwait(int next_eip_addend
)
4684 if ((uint32_t)ECX
!= 0)
4685 raise_exception(EXCP0D_GPF
);
4686 helper_svm_check_intercept_param(SVM_EXIT_MWAIT
, 0);
4687 EIP
+= next_eip_addend
;
4689 /* XXX: not complete but not completely erroneous */
4690 if (env
->cpu_index
!= 0 || env
->next_cpu
!= NULL
) {
4691 /* more than one CPU: do not sleep because another CPU may
4698 void helper_debug(void)
4700 env
->exception_index
= EXCP_DEBUG
;
4704 void helper_reset_rf(void)
4706 env
->eflags
&= ~RF_MASK
;
4709 void helper_raise_interrupt(int intno
, int next_eip_addend
)
4711 raise_interrupt(intno
, 1, 0, next_eip_addend
);
4714 void helper_raise_exception(int exception_index
)
4716 raise_exception(exception_index
);
4719 void helper_cli(void)
4721 env
->eflags
&= ~IF_MASK
;
4724 void helper_sti(void)
4726 env
->eflags
|= IF_MASK
;
4730 /* vm86plus instructions */
4731 void helper_cli_vm(void)
4733 env
->eflags
&= ~VIF_MASK
;
4736 void helper_sti_vm(void)
4738 env
->eflags
|= VIF_MASK
;
4739 if (env
->eflags
& VIP_MASK
) {
4740 raise_exception(EXCP0D_GPF
);
4745 void helper_set_inhibit_irq(void)
4747 env
->hflags
|= HF_INHIBIT_IRQ_MASK
;
4750 void helper_reset_inhibit_irq(void)
4752 env
->hflags
&= ~HF_INHIBIT_IRQ_MASK
;
4755 void helper_boundw(target_ulong a0
, int v
)
4759 high
= ldsw(a0
+ 2);
4761 if (v
< low
|| v
> high
) {
4762 raise_exception(EXCP05_BOUND
);
4766 void helper_boundl(target_ulong a0
, int v
)
4771 if (v
< low
|| v
> high
) {
4772 raise_exception(EXCP05_BOUND
);
4776 static float approx_rsqrt(float a
)
4778 return 1.0 / sqrt(a
);
4781 static float approx_rcp(float a
)
4786 #if !defined(CONFIG_USER_ONLY)
4788 #define MMUSUFFIX _mmu
4791 #include "softmmu_template.h"
4794 #include "softmmu_template.h"
4797 #include "softmmu_template.h"
4800 #include "softmmu_template.h"
4804 #if !defined(CONFIG_USER_ONLY)
4805 /* try to fill the TLB and return an exception if error. If retaddr is
4806 NULL, it means that the function was called in C code (i.e. not
4807 from generated code or from helper.c) */
4808 /* XXX: fix it to restore all registers */
4809 void tlb_fill(target_ulong addr
, int is_write
, int mmu_idx
, void *retaddr
)
4811 TranslationBlock
*tb
;
4814 CPUX86State
*saved_env
;
4816 /* XXX: hack to restore env in all cases, even if not called from
4819 env
= cpu_single_env
;
4821 ret
= cpu_x86_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
, 1);
4824 /* now we have a real cpu fault */
4825 pc
= (unsigned long)retaddr
;
4826 tb
= tb_find_pc(pc
);
4828 /* the PC is inside the translated code. It means that we have
4829 a virtual CPU fault */
4830 cpu_restore_state(tb
, env
, pc
, NULL
);
4833 raise_exception_err(env
->exception_index
, env
->error_code
);
4839 /* Secure Virtual Machine helpers */
4841 #if defined(CONFIG_USER_ONLY)
4843 void helper_vmrun(int aflag
, int next_eip_addend
)
4846 void helper_vmmcall(void)
4849 void helper_vmload(int aflag
)
4852 void helper_vmsave(int aflag
)
4855 void helper_stgi(void)
4858 void helper_clgi(void)
4861 void helper_skinit(void)
4864 void helper_invlpga(int aflag
)
4867 void helper_vmexit(uint32_t exit_code
, uint64_t exit_info_1
)
4870 void helper_svm_check_intercept_param(uint32_t type
, uint64_t param
)
4874 void helper_svm_check_io(uint32_t port
, uint32_t param
,
4875 uint32_t next_eip_addend
)
4880 static inline void svm_save_seg(target_phys_addr_t addr
,
4881 const SegmentCache
*sc
)
4883 stw_phys(addr
+ offsetof(struct vmcb_seg
, selector
),
4885 stq_phys(addr
+ offsetof(struct vmcb_seg
, base
),
4887 stl_phys(addr
+ offsetof(struct vmcb_seg
, limit
),
4889 stw_phys(addr
+ offsetof(struct vmcb_seg
, attrib
),
4890 ((sc
->flags
>> 8) & 0xff) | ((sc
->flags
>> 12) & 0x0f00));
4893 static inline void svm_load_seg(target_phys_addr_t addr
, SegmentCache
*sc
)
4897 sc
->selector
= lduw_phys(addr
+ offsetof(struct vmcb_seg
, selector
));
4898 sc
->base
= ldq_phys(addr
+ offsetof(struct vmcb_seg
, base
));
4899 sc
->limit
= ldl_phys(addr
+ offsetof(struct vmcb_seg
, limit
));
4900 flags
= lduw_phys(addr
+ offsetof(struct vmcb_seg
, attrib
));
4901 sc
->flags
= ((flags
& 0xff) << 8) | ((flags
& 0x0f00) << 12);
4904 static inline void svm_load_seg_cache(target_phys_addr_t addr
,
4905 CPUState
*env
, int seg_reg
)
4907 SegmentCache sc1
, *sc
= &sc1
;
4908 svm_load_seg(addr
, sc
);
4909 cpu_x86_load_seg_cache(env
, seg_reg
, sc
->selector
,
4910 sc
->base
, sc
->limit
, sc
->flags
);
4913 void helper_vmrun(int aflag
, int next_eip_addend
)
4919 helper_svm_check_intercept_param(SVM_EXIT_VMRUN
, 0);
4924 addr
= (uint32_t)EAX
;
4926 qemu_log_mask(CPU_LOG_TB_IN_ASM
, "vmrun! " TARGET_FMT_lx
"\n", addr
);
4928 env
->vm_vmcb
= addr
;
4930 /* save the current CPU state in the hsave page */
4931 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.gdtr
.base
), env
->gdt
.base
);
4932 stl_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.gdtr
.limit
), env
->gdt
.limit
);
4934 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.idtr
.base
), env
->idt
.base
);
4935 stl_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.idtr
.limit
), env
->idt
.limit
);
4937 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.cr0
), env
->cr
[0]);
4938 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.cr2
), env
->cr
[2]);
4939 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.cr3
), env
->cr
[3]);
4940 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.cr4
), env
->cr
[4]);
4941 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.dr6
), env
->dr
[6]);
4942 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.dr7
), env
->dr
[7]);
4944 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.efer
), env
->efer
);
4945 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.rflags
), compute_eflags());
4947 svm_save_seg(env
->vm_hsave
+ offsetof(struct vmcb
, save
.es
),
4949 svm_save_seg(env
->vm_hsave
+ offsetof(struct vmcb
, save
.cs
),
4951 svm_save_seg(env
->vm_hsave
+ offsetof(struct vmcb
, save
.ss
),
4953 svm_save_seg(env
->vm_hsave
+ offsetof(struct vmcb
, save
.ds
),
4956 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.rip
),
4957 EIP
+ next_eip_addend
);
4958 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.rsp
), ESP
);
4959 stq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.rax
), EAX
);
4961 /* load the interception bitmaps so we do not need to access the
4963 env
->intercept
= ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.intercept
));
4964 env
->intercept_cr_read
= lduw_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.intercept_cr_read
));
4965 env
->intercept_cr_write
= lduw_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.intercept_cr_write
));
4966 env
->intercept_dr_read
= lduw_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.intercept_dr_read
));
4967 env
->intercept_dr_write
= lduw_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.intercept_dr_write
));
4968 env
->intercept_exceptions
= ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.intercept_exceptions
));
4970 /* enable intercepts */
4971 env
->hflags
|= HF_SVMI_MASK
;
4973 env
->tsc_offset
= ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.tsc_offset
));
4975 env
->gdt
.base
= ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.gdtr
.base
));
4976 env
->gdt
.limit
= ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.gdtr
.limit
));
4978 env
->idt
.base
= ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.idtr
.base
));
4979 env
->idt
.limit
= ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.idtr
.limit
));
4981 /* clear exit_info_2 so we behave like the real hardware */
4982 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.exit_info_2
), 0);
4984 cpu_x86_update_cr0(env
, ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cr0
)));
4985 cpu_x86_update_cr4(env
, ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cr4
)));
4986 cpu_x86_update_cr3(env
, ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cr3
)));
4987 env
->cr
[2] = ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cr2
));
4988 int_ctl
= ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.int_ctl
));
4989 env
->hflags2
&= ~(HF2_HIF_MASK
| HF2_VINTR_MASK
);
4990 if (int_ctl
& V_INTR_MASKING_MASK
) {
4991 env
->v_tpr
= int_ctl
& V_TPR_MASK
;
4992 env
->hflags2
|= HF2_VINTR_MASK
;
4993 if (env
->eflags
& IF_MASK
)
4994 env
->hflags2
|= HF2_HIF_MASK
;
4998 ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.efer
)));
5000 load_eflags(ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.rflags
)),
5001 ~(CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
| DF_MASK
));
5002 CC_OP
= CC_OP_EFLAGS
;
5004 svm_load_seg_cache(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.es
),
5006 svm_load_seg_cache(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cs
),
5008 svm_load_seg_cache(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.ss
),
5010 svm_load_seg_cache(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.ds
),
5013 EIP
= ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.rip
));
5015 ESP
= ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.rsp
));
5016 EAX
= ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.rax
));
5017 env
->dr
[7] = ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.dr7
));
5018 env
->dr
[6] = ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.dr6
));
5019 cpu_x86_set_cpl(env
, ldub_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cpl
)));
5021 /* FIXME: guest state consistency checks */
5023 switch(ldub_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.tlb_ctl
))) {
5024 case TLB_CONTROL_DO_NOTHING
:
5026 case TLB_CONTROL_FLUSH_ALL_ASID
:
5027 /* FIXME: this is not 100% correct but should work for now */
5032 env
->hflags2
|= HF2_GIF_MASK
;
5034 if (int_ctl
& V_IRQ_MASK
) {
5035 env
->interrupt_request
|= CPU_INTERRUPT_VIRQ
;
5038 /* maybe we need to inject an event */
5039 event_inj
= ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.event_inj
));
5040 if (event_inj
& SVM_EVTINJ_VALID
) {
5041 uint8_t vector
= event_inj
& SVM_EVTINJ_VEC_MASK
;
5042 uint16_t valid_err
= event_inj
& SVM_EVTINJ_VALID_ERR
;
5043 uint32_t event_inj_err
= ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.event_inj_err
));
5045 qemu_log_mask(CPU_LOG_TB_IN_ASM
, "Injecting(%#hx): ", valid_err
);
5046 /* FIXME: need to implement valid_err */
5047 switch (event_inj
& SVM_EVTINJ_TYPE_MASK
) {
5048 case SVM_EVTINJ_TYPE_INTR
:
5049 env
->exception_index
= vector
;
5050 env
->error_code
= event_inj_err
;
5051 env
->exception_is_int
= 0;
5052 env
->exception_next_eip
= -1;
5053 qemu_log_mask(CPU_LOG_TB_IN_ASM
, "INTR");
5054 /* XXX: is it always correct ? */
5055 do_interrupt(vector
, 0, 0, 0, 1);
5057 case SVM_EVTINJ_TYPE_NMI
:
5058 env
->exception_index
= EXCP02_NMI
;
5059 env
->error_code
= event_inj_err
;
5060 env
->exception_is_int
= 0;
5061 env
->exception_next_eip
= EIP
;
5062 qemu_log_mask(CPU_LOG_TB_IN_ASM
, "NMI");
5065 case SVM_EVTINJ_TYPE_EXEPT
:
5066 env
->exception_index
= vector
;
5067 env
->error_code
= event_inj_err
;
5068 env
->exception_is_int
= 0;
5069 env
->exception_next_eip
= -1;
5070 qemu_log_mask(CPU_LOG_TB_IN_ASM
, "EXEPT");
5073 case SVM_EVTINJ_TYPE_SOFT
:
5074 env
->exception_index
= vector
;
5075 env
->error_code
= event_inj_err
;
5076 env
->exception_is_int
= 1;
5077 env
->exception_next_eip
= EIP
;
5078 qemu_log_mask(CPU_LOG_TB_IN_ASM
, "SOFT");
5082 qemu_log_mask(CPU_LOG_TB_IN_ASM
, " %#x %#x\n", env
->exception_index
, env
->error_code
);
5086 void helper_vmmcall(void)
5088 helper_svm_check_intercept_param(SVM_EXIT_VMMCALL
, 0);
5089 raise_exception(EXCP06_ILLOP
);
5092 void helper_vmload(int aflag
)
5095 helper_svm_check_intercept_param(SVM_EXIT_VMLOAD
, 0);
5100 addr
= (uint32_t)EAX
;
5102 qemu_log_mask(CPU_LOG_TB_IN_ASM
, "vmload! " TARGET_FMT_lx
"\nFS: %016" PRIx64
" | " TARGET_FMT_lx
"\n",
5103 addr
, ldq_phys(addr
+ offsetof(struct vmcb
, save
.fs
.base
)),
5104 env
->segs
[R_FS
].base
);
5106 svm_load_seg_cache(addr
+ offsetof(struct vmcb
, save
.fs
),
5108 svm_load_seg_cache(addr
+ offsetof(struct vmcb
, save
.gs
),
5110 svm_load_seg(addr
+ offsetof(struct vmcb
, save
.tr
),
5112 svm_load_seg(addr
+ offsetof(struct vmcb
, save
.ldtr
),
5115 #ifdef TARGET_X86_64
5116 env
->kernelgsbase
= ldq_phys(addr
+ offsetof(struct vmcb
, save
.kernel_gs_base
));
5117 env
->lstar
= ldq_phys(addr
+ offsetof(struct vmcb
, save
.lstar
));
5118 env
->cstar
= ldq_phys(addr
+ offsetof(struct vmcb
, save
.cstar
));
5119 env
->fmask
= ldq_phys(addr
+ offsetof(struct vmcb
, save
.sfmask
));
5121 env
->star
= ldq_phys(addr
+ offsetof(struct vmcb
, save
.star
));
5122 env
->sysenter_cs
= ldq_phys(addr
+ offsetof(struct vmcb
, save
.sysenter_cs
));
5123 env
->sysenter_esp
= ldq_phys(addr
+ offsetof(struct vmcb
, save
.sysenter_esp
));
5124 env
->sysenter_eip
= ldq_phys(addr
+ offsetof(struct vmcb
, save
.sysenter_eip
));
5127 void helper_vmsave(int aflag
)
5130 helper_svm_check_intercept_param(SVM_EXIT_VMSAVE
, 0);
5135 addr
= (uint32_t)EAX
;
5137 qemu_log_mask(CPU_LOG_TB_IN_ASM
, "vmsave! " TARGET_FMT_lx
"\nFS: %016" PRIx64
" | " TARGET_FMT_lx
"\n",
5138 addr
, ldq_phys(addr
+ offsetof(struct vmcb
, save
.fs
.base
)),
5139 env
->segs
[R_FS
].base
);
5141 svm_save_seg(addr
+ offsetof(struct vmcb
, save
.fs
),
5143 svm_save_seg(addr
+ offsetof(struct vmcb
, save
.gs
),
5145 svm_save_seg(addr
+ offsetof(struct vmcb
, save
.tr
),
5147 svm_save_seg(addr
+ offsetof(struct vmcb
, save
.ldtr
),
5150 #ifdef TARGET_X86_64
5151 stq_phys(addr
+ offsetof(struct vmcb
, save
.kernel_gs_base
), env
->kernelgsbase
);
5152 stq_phys(addr
+ offsetof(struct vmcb
, save
.lstar
), env
->lstar
);
5153 stq_phys(addr
+ offsetof(struct vmcb
, save
.cstar
), env
->cstar
);
5154 stq_phys(addr
+ offsetof(struct vmcb
, save
.sfmask
), env
->fmask
);
5156 stq_phys(addr
+ offsetof(struct vmcb
, save
.star
), env
->star
);
5157 stq_phys(addr
+ offsetof(struct vmcb
, save
.sysenter_cs
), env
->sysenter_cs
);
5158 stq_phys(addr
+ offsetof(struct vmcb
, save
.sysenter_esp
), env
->sysenter_esp
);
5159 stq_phys(addr
+ offsetof(struct vmcb
, save
.sysenter_eip
), env
->sysenter_eip
);
5162 void helper_stgi(void)
5164 helper_svm_check_intercept_param(SVM_EXIT_STGI
, 0);
5165 env
->hflags2
|= HF2_GIF_MASK
;
5168 void helper_clgi(void)
5170 helper_svm_check_intercept_param(SVM_EXIT_CLGI
, 0);
5171 env
->hflags2
&= ~HF2_GIF_MASK
;
5174 void helper_skinit(void)
5176 helper_svm_check_intercept_param(SVM_EXIT_SKINIT
, 0);
5177 /* XXX: not implemented */
5178 raise_exception(EXCP06_ILLOP
);
5181 void helper_invlpga(int aflag
)
5184 helper_svm_check_intercept_param(SVM_EXIT_INVLPGA
, 0);
5189 addr
= (uint32_t)EAX
;
5191 /* XXX: could use the ASID to see if it is needed to do the
5193 tlb_flush_page(env
, addr
);
5196 void helper_svm_check_intercept_param(uint32_t type
, uint64_t param
)
5198 if (likely(!(env
->hflags
& HF_SVMI_MASK
)))
5201 case SVM_EXIT_READ_CR0
... SVM_EXIT_READ_CR0
+ 8:
5202 if (env
->intercept_cr_read
& (1 << (type
- SVM_EXIT_READ_CR0
))) {
5203 helper_vmexit(type
, param
);
5206 case SVM_EXIT_WRITE_CR0
... SVM_EXIT_WRITE_CR0
+ 8:
5207 if (env
->intercept_cr_write
& (1 << (type
- SVM_EXIT_WRITE_CR0
))) {
5208 helper_vmexit(type
, param
);
5211 case SVM_EXIT_READ_DR0
... SVM_EXIT_READ_DR0
+ 7:
5212 if (env
->intercept_dr_read
& (1 << (type
- SVM_EXIT_READ_DR0
))) {
5213 helper_vmexit(type
, param
);
5216 case SVM_EXIT_WRITE_DR0
... SVM_EXIT_WRITE_DR0
+ 7:
5217 if (env
->intercept_dr_write
& (1 << (type
- SVM_EXIT_WRITE_DR0
))) {
5218 helper_vmexit(type
, param
);
5221 case SVM_EXIT_EXCP_BASE
... SVM_EXIT_EXCP_BASE
+ 31:
5222 if (env
->intercept_exceptions
& (1 << (type
- SVM_EXIT_EXCP_BASE
))) {
5223 helper_vmexit(type
, param
);
5227 if (env
->intercept
& (1ULL << (SVM_EXIT_MSR
- SVM_EXIT_INTR
))) {
5228 /* FIXME: this should be read in at vmrun (faster this way?) */
5229 uint64_t addr
= ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.msrpm_base_pa
));
5231 switch((uint32_t)ECX
) {
5236 case 0xc0000000 ... 0xc0001fff:
5237 t0
= (8192 + ECX
- 0xc0000000) * 2;
5241 case 0xc0010000 ... 0xc0011fff:
5242 t0
= (16384 + ECX
- 0xc0010000) * 2;
5247 helper_vmexit(type
, param
);
5252 if (ldub_phys(addr
+ t1
) & ((1 << param
) << t0
))
5253 helper_vmexit(type
, param
);
5257 if (env
->intercept
& (1ULL << (type
- SVM_EXIT_INTR
))) {
5258 helper_vmexit(type
, param
);
5264 void helper_svm_check_io(uint32_t port
, uint32_t param
,
5265 uint32_t next_eip_addend
)
5267 if (env
->intercept
& (1ULL << (SVM_EXIT_IOIO
- SVM_EXIT_INTR
))) {
5268 /* FIXME: this should be read in at vmrun (faster this way?) */
5269 uint64_t addr
= ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.iopm_base_pa
));
5270 uint16_t mask
= (1 << ((param
>> 4) & 7)) - 1;
5271 if(lduw_phys(addr
+ port
/ 8) & (mask
<< (port
& 7))) {
5273 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.exit_info_2
),
5274 env
->eip
+ next_eip_addend
);
5275 helper_vmexit(SVM_EXIT_IOIO
, param
| (port
<< 16));
5280 /* Note: currently only 32 bits of exit_code are used */
5281 void helper_vmexit(uint32_t exit_code
, uint64_t exit_info_1
)
5285 qemu_log_mask(CPU_LOG_TB_IN_ASM
, "vmexit(%08x, %016" PRIx64
", %016" PRIx64
", " TARGET_FMT_lx
")!\n",
5286 exit_code
, exit_info_1
,
5287 ldq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.exit_info_2
)),
5290 if(env
->hflags
& HF_INHIBIT_IRQ_MASK
) {
5291 stl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.int_state
), SVM_INTERRUPT_SHADOW_MASK
);
5292 env
->hflags
&= ~HF_INHIBIT_IRQ_MASK
;
5294 stl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.int_state
), 0);
5297 /* Save the VM state in the vmcb */
5298 svm_save_seg(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.es
),
5300 svm_save_seg(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cs
),
5302 svm_save_seg(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.ss
),
5304 svm_save_seg(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.ds
),
5307 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.gdtr
.base
), env
->gdt
.base
);
5308 stl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.gdtr
.limit
), env
->gdt
.limit
);
5310 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.idtr
.base
), env
->idt
.base
);
5311 stl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.idtr
.limit
), env
->idt
.limit
);
5313 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.efer
), env
->efer
);
5314 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cr0
), env
->cr
[0]);
5315 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cr2
), env
->cr
[2]);
5316 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cr3
), env
->cr
[3]);
5317 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cr4
), env
->cr
[4]);
5319 int_ctl
= ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.int_ctl
));
5320 int_ctl
&= ~(V_TPR_MASK
| V_IRQ_MASK
);
5321 int_ctl
|= env
->v_tpr
& V_TPR_MASK
;
5322 if (env
->interrupt_request
& CPU_INTERRUPT_VIRQ
)
5323 int_ctl
|= V_IRQ_MASK
;
5324 stl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.int_ctl
), int_ctl
);
5326 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.rflags
), compute_eflags());
5327 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.rip
), env
->eip
);
5328 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.rsp
), ESP
);
5329 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.rax
), EAX
);
5330 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.dr7
), env
->dr
[7]);
5331 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.dr6
), env
->dr
[6]);
5332 stb_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, save
.cpl
), env
->hflags
& HF_CPL_MASK
);
5334 /* Reload the host state from vm_hsave */
5335 env
->hflags2
&= ~(HF2_HIF_MASK
| HF2_VINTR_MASK
);
5336 env
->hflags
&= ~HF_SVMI_MASK
;
5338 env
->intercept_exceptions
= 0;
5339 env
->interrupt_request
&= ~CPU_INTERRUPT_VIRQ
;
5340 env
->tsc_offset
= 0;
5342 env
->gdt
.base
= ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.gdtr
.base
));
5343 env
->gdt
.limit
= ldl_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.gdtr
.limit
));
5345 env
->idt
.base
= ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.idtr
.base
));
5346 env
->idt
.limit
= ldl_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.idtr
.limit
));
5348 cpu_x86_update_cr0(env
, ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.cr0
)) | CR0_PE_MASK
);
5349 cpu_x86_update_cr4(env
, ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.cr4
)));
5350 cpu_x86_update_cr3(env
, ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.cr3
)));
5351 /* we need to set the efer after the crs so the hidden flags get
5354 ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.efer
)));
5356 load_eflags(ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.rflags
)),
5357 ~(CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
| DF_MASK
));
5358 CC_OP
= CC_OP_EFLAGS
;
5360 svm_load_seg_cache(env
->vm_hsave
+ offsetof(struct vmcb
, save
.es
),
5362 svm_load_seg_cache(env
->vm_hsave
+ offsetof(struct vmcb
, save
.cs
),
5364 svm_load_seg_cache(env
->vm_hsave
+ offsetof(struct vmcb
, save
.ss
),
5366 svm_load_seg_cache(env
->vm_hsave
+ offsetof(struct vmcb
, save
.ds
),
5369 EIP
= ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.rip
));
5370 ESP
= ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.rsp
));
5371 EAX
= ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.rax
));
5373 env
->dr
[6] = ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.dr6
));
5374 env
->dr
[7] = ldq_phys(env
->vm_hsave
+ offsetof(struct vmcb
, save
.dr7
));
5377 cpu_x86_set_cpl(env
, 0);
5378 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.exit_code
), exit_code
);
5379 stq_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.exit_info_1
), exit_info_1
);
5381 stl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.exit_int_info
),
5382 ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.event_inj
)));
5383 stl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.exit_int_info_err
),
5384 ldl_phys(env
->vm_vmcb
+ offsetof(struct vmcb
, control
.event_inj_err
)));
5386 env
->hflags2
&= ~HF2_GIF_MASK
;
5387 /* FIXME: Resets the current ASID register to zero (host ASID). */
5389 /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
5391 /* Clears the TSC_OFFSET inside the processor. */
5393 /* If the host is in PAE mode, the processor reloads the host's PDPEs
5394 from the page table indicated the host's CR3. If the PDPEs contain
5395 illegal state, the processor causes a shutdown. */
5397 /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
5398 env
->cr
[0] |= CR0_PE_MASK
;
5399 env
->eflags
&= ~VM_MASK
;
5401 /* Disables all breakpoints in the host DR7 register. */
5403 /* Checks the reloaded host state for consistency. */
5405 /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
5406 host's code segment or non-canonical (in the case of long mode), a
5407 #GP fault is delivered inside the host.) */
5409 /* remove any pending exception */
5410 env
->exception_index
= -1;
5411 env
->error_code
= 0;
5412 env
->old_exception
= -1;
5420 /* XXX: optimize by storing fptt and fptags in the static cpu state */
5421 void helper_enter_mmx(void)
5424 *(uint32_t *)(env
->fptags
) = 0;
5425 *(uint32_t *)(env
->fptags
+ 4) = 0;
5428 void helper_emms(void)
5430 /* set to empty state */
5431 *(uint32_t *)(env
->fptags
) = 0x01010101;
5432 *(uint32_t *)(env
->fptags
+ 4) = 0x01010101;
5436 void helper_movq(void *d
, void *s
)
5438 *(uint64_t *)d
= *(uint64_t *)s
;
5442 #include "ops_sse.h"
5445 #include "ops_sse.h"
5448 #include "helper_template.h"
5452 #include "helper_template.h"
5456 #include "helper_template.h"
5459 #ifdef TARGET_X86_64
5462 #include "helper_template.h"
5467 /* bit operations */
5468 target_ulong
helper_bsf(target_ulong t0
)
5475 while ((res
& 1) == 0) {
5482 target_ulong
helper_lzcnt(target_ulong t0
, int wordsize
)
5485 target_ulong res
, mask
;
5487 if (wordsize
> 0 && t0
== 0) {
5491 count
= TARGET_LONG_BITS
- 1;
5492 mask
= (target_ulong
)1 << (TARGET_LONG_BITS
- 1);
5493 while ((res
& mask
) == 0) {
5498 return wordsize
- 1 - count
;
5503 target_ulong
helper_bsr(target_ulong t0
)
5505 return helper_lzcnt(t0
, 0);
5508 static int compute_all_eflags(void)
5513 static int compute_c_eflags(void)
5515 return CC_SRC
& CC_C
;
5518 uint32_t helper_cc_compute_all(int op
)
5521 default: /* should never happen */ return 0;
5523 case CC_OP_EFLAGS
: return compute_all_eflags();
5525 case CC_OP_MULB
: return compute_all_mulb();
5526 case CC_OP_MULW
: return compute_all_mulw();
5527 case CC_OP_MULL
: return compute_all_mull();
5529 case CC_OP_ADDB
: return compute_all_addb();
5530 case CC_OP_ADDW
: return compute_all_addw();
5531 case CC_OP_ADDL
: return compute_all_addl();
5533 case CC_OP_ADCB
: return compute_all_adcb();
5534 case CC_OP_ADCW
: return compute_all_adcw();
5535 case CC_OP_ADCL
: return compute_all_adcl();
5537 case CC_OP_SUBB
: return compute_all_subb();
5538 case CC_OP_SUBW
: return compute_all_subw();
5539 case CC_OP_SUBL
: return compute_all_subl();
5541 case CC_OP_SBBB
: return compute_all_sbbb();
5542 case CC_OP_SBBW
: return compute_all_sbbw();
5543 case CC_OP_SBBL
: return compute_all_sbbl();
5545 case CC_OP_LOGICB
: return compute_all_logicb();
5546 case CC_OP_LOGICW
: return compute_all_logicw();
5547 case CC_OP_LOGICL
: return compute_all_logicl();
5549 case CC_OP_INCB
: return compute_all_incb();
5550 case CC_OP_INCW
: return compute_all_incw();
5551 case CC_OP_INCL
: return compute_all_incl();
5553 case CC_OP_DECB
: return compute_all_decb();
5554 case CC_OP_DECW
: return compute_all_decw();
5555 case CC_OP_DECL
: return compute_all_decl();
5557 case CC_OP_SHLB
: return compute_all_shlb();
5558 case CC_OP_SHLW
: return compute_all_shlw();
5559 case CC_OP_SHLL
: return compute_all_shll();
5561 case CC_OP_SARB
: return compute_all_sarb();
5562 case CC_OP_SARW
: return compute_all_sarw();
5563 case CC_OP_SARL
: return compute_all_sarl();
5565 #ifdef TARGET_X86_64
5566 case CC_OP_MULQ
: return compute_all_mulq();
5568 case CC_OP_ADDQ
: return compute_all_addq();
5570 case CC_OP_ADCQ
: return compute_all_adcq();
5572 case CC_OP_SUBQ
: return compute_all_subq();
5574 case CC_OP_SBBQ
: return compute_all_sbbq();
5576 case CC_OP_LOGICQ
: return compute_all_logicq();
5578 case CC_OP_INCQ
: return compute_all_incq();
5580 case CC_OP_DECQ
: return compute_all_decq();
5582 case CC_OP_SHLQ
: return compute_all_shlq();
5584 case CC_OP_SARQ
: return compute_all_sarq();
5589 uint32_t helper_cc_compute_c(int op
)
5592 default: /* should never happen */ return 0;
5594 case CC_OP_EFLAGS
: return compute_c_eflags();
5596 case CC_OP_MULB
: return compute_c_mull();
5597 case CC_OP_MULW
: return compute_c_mull();
5598 case CC_OP_MULL
: return compute_c_mull();
5600 case CC_OP_ADDB
: return compute_c_addb();
5601 case CC_OP_ADDW
: return compute_c_addw();
5602 case CC_OP_ADDL
: return compute_c_addl();
5604 case CC_OP_ADCB
: return compute_c_adcb();
5605 case CC_OP_ADCW
: return compute_c_adcw();
5606 case CC_OP_ADCL
: return compute_c_adcl();
5608 case CC_OP_SUBB
: return compute_c_subb();
5609 case CC_OP_SUBW
: return compute_c_subw();
5610 case CC_OP_SUBL
: return compute_c_subl();
5612 case CC_OP_SBBB
: return compute_c_sbbb();
5613 case CC_OP_SBBW
: return compute_c_sbbw();
5614 case CC_OP_SBBL
: return compute_c_sbbl();
5616 case CC_OP_LOGICB
: return compute_c_logicb();
5617 case CC_OP_LOGICW
: return compute_c_logicw();
5618 case CC_OP_LOGICL
: return compute_c_logicl();
5620 case CC_OP_INCB
: return compute_c_incl();
5621 case CC_OP_INCW
: return compute_c_incl();
5622 case CC_OP_INCL
: return compute_c_incl();
5624 case CC_OP_DECB
: return compute_c_incl();
5625 case CC_OP_DECW
: return compute_c_incl();
5626 case CC_OP_DECL
: return compute_c_incl();
5628 case CC_OP_SHLB
: return compute_c_shlb();
5629 case CC_OP_SHLW
: return compute_c_shlw();
5630 case CC_OP_SHLL
: return compute_c_shll();
5632 case CC_OP_SARB
: return compute_c_sarl();
5633 case CC_OP_SARW
: return compute_c_sarl();
5634 case CC_OP_SARL
: return compute_c_sarl();
5636 #ifdef TARGET_X86_64
5637 case CC_OP_MULQ
: return compute_c_mull();
5639 case CC_OP_ADDQ
: return compute_c_addq();
5641 case CC_OP_ADCQ
: return compute_c_adcq();
5643 case CC_OP_SUBQ
: return compute_c_subq();
5645 case CC_OP_SBBQ
: return compute_c_sbbq();
5647 case CC_OP_LOGICQ
: return compute_c_logicq();
5649 case CC_OP_INCQ
: return compute_c_incl();
5651 case CC_OP_DECQ
: return compute_c_incl();
5653 case CC_OP_SHLQ
: return compute_c_shlq();
5655 case CC_OP_SARQ
: return compute_c_sarl();