Revision bd7a7b33
b/target-i386/TODO | ||
---|---|---|
1 | 1 |
Correctness issues: |
2 | 2 |
|
3 |
- some eflags manipulation incorrectly reset the bit 0x2. |
|
3 | 4 |
- rework eflags optimization (will be a consequence of TCG port) |
4 | 5 |
- SVM: rework the implementation: simplify code, move most intercept |
5 | 6 |
tests as dynamic, correct segment access, verify exception safety, |
b/target-i386/helper.c | ||
---|---|---|
108 | 108 |
spin_unlock(&global_cpu_lock); |
109 | 109 |
} |
110 | 110 |
|
111 |
void helper_write_eflags(target_ulong t0, uint32_t update_mask) |
|
112 |
{ |
|
113 |
load_eflags(t0, update_mask); |
|
114 |
} |
|
115 |
|
|
116 |
target_ulong helper_read_eflags(void) |
|
117 |
{ |
|
118 |
uint32_t eflags; |
|
119 |
eflags = cc_table[CC_OP].compute_all(); |
|
120 |
eflags |= (DF & DF_MASK); |
|
121 |
eflags |= env->eflags & ~(VM_MASK | RF_MASK); |
|
122 |
return eflags; |
|
123 |
} |
|
124 |
|
|
111 | 125 |
/* return non zero if error */ |
112 | 126 |
static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr, |
113 | 127 |
int selector) |
b/target-i386/helper.h | ||
---|---|---|
2 | 2 |
|
3 | 3 |
void helper_lock(void); |
4 | 4 |
void helper_unlock(void); |
5 |
void helper_write_eflags(target_ulong t0, uint32_t update_mask); |
|
6 |
target_ulong helper_read_eflags(void); |
|
5 | 7 |
void helper_divb_AL(target_ulong t0); |
6 | 8 |
void helper_idivb_AL(target_ulong t0); |
7 | 9 |
void helper_divw_AX(target_ulong t0); |
b/target-i386/op.c | ||
---|---|---|
255 | 255 |
{ |
256 | 256 |
T0 ^= 1; |
257 | 257 |
} |
258 |
|
|
259 |
/* XXX: clear VIF/VIP in all ops ? */ |
|
260 |
|
|
261 |
void OPPROTO op_movl_eflags_T0(void) |
|
262 |
{ |
|
263 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK)); |
|
264 |
} |
|
265 |
|
|
266 |
void OPPROTO op_movw_eflags_T0(void) |
|
267 |
{ |
|
268 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff); |
|
269 |
} |
|
270 |
|
|
271 |
void OPPROTO op_movl_eflags_T0_io(void) |
|
272 |
{ |
|
273 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK)); |
|
274 |
} |
|
275 |
|
|
276 |
void OPPROTO op_movw_eflags_T0_io(void) |
|
277 |
{ |
|
278 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff); |
|
279 |
} |
|
280 |
|
|
281 |
void OPPROTO op_movl_eflags_T0_cpl0(void) |
|
282 |
{ |
|
283 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK)); |
|
284 |
} |
|
285 |
|
|
286 |
void OPPROTO op_movw_eflags_T0_cpl0(void) |
|
287 |
{ |
|
288 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff); |
|
289 |
} |
|
290 |
|
|
291 |
#if 0 |
|
292 |
/* vm86plus version */ |
|
293 |
void OPPROTO op_movw_eflags_T0_vm(void) |
|
294 |
{ |
|
295 |
int eflags; |
|
296 |
eflags = T0; |
|
297 |
CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
|
298 |
DF = 1 - (2 * ((eflags >> 10) & 1)); |
|
299 |
/* we also update some system flags as in user mode */ |
|
300 |
env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) | |
|
301 |
(eflags & FL_UPDATE_MASK16); |
|
302 |
if (eflags & IF_MASK) { |
|
303 |
env->eflags |= VIF_MASK; |
|
304 |
if (env->eflags & VIP_MASK) { |
|
305 |
EIP = PARAM1; |
|
306 |
raise_exception(EXCP0D_GPF); |
|
307 |
} |
|
308 |
} |
|
309 |
FORCE_RET(); |
|
310 |
} |
|
311 |
|
|
312 |
void OPPROTO op_movl_eflags_T0_vm(void) |
|
313 |
{ |
|
314 |
int eflags; |
|
315 |
eflags = T0; |
|
316 |
CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
|
317 |
DF = 1 - (2 * ((eflags >> 10) & 1)); |
|
318 |
/* we also update some system flags as in user mode */ |
|
319 |
env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) | |
|
320 |
(eflags & FL_UPDATE_MASK32); |
|
321 |
if (eflags & IF_MASK) { |
|
322 |
env->eflags |= VIF_MASK; |
|
323 |
if (env->eflags & VIP_MASK) { |
|
324 |
EIP = PARAM1; |
|
325 |
raise_exception(EXCP0D_GPF); |
|
326 |
} |
|
327 |
} |
|
328 |
FORCE_RET(); |
|
329 |
} |
|
330 |
#endif |
|
331 |
|
|
332 |
/* XXX: compute only O flag */ |
|
333 |
void OPPROTO op_movb_eflags_T0(void) |
|
334 |
{ |
|
335 |
int of; |
|
336 |
of = cc_table[CC_OP].compute_all() & CC_O; |
|
337 |
CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of; |
|
338 |
} |
|
339 |
|
|
340 |
void OPPROTO op_movl_T0_eflags(void) |
|
341 |
{ |
|
342 |
int eflags; |
|
343 |
eflags = cc_table[CC_OP].compute_all(); |
|
344 |
eflags |= (DF & DF_MASK); |
|
345 |
eflags |= env->eflags & ~(VM_MASK | RF_MASK); |
|
346 |
T0 = eflags; |
|
347 |
} |
|
348 |
|
|
349 |
/* vm86plus version */ |
|
350 |
#if 0 |
|
351 |
void OPPROTO op_movl_T0_eflags_vm(void) |
|
352 |
{ |
|
353 |
int eflags; |
|
354 |
eflags = cc_table[CC_OP].compute_all(); |
|
355 |
eflags |= (DF & DF_MASK); |
|
356 |
eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK); |
|
357 |
if (env->eflags & VIF_MASK) |
|
358 |
eflags |= IF_MASK; |
|
359 |
T0 = eflags; |
|
360 |
} |
|
361 |
#endif |
|
362 |
|
|
363 |
void OPPROTO op_clc(void) |
|
364 |
{ |
|
365 |
int eflags; |
|
366 |
eflags = cc_table[CC_OP].compute_all(); |
|
367 |
eflags &= ~CC_C; |
|
368 |
CC_SRC = eflags; |
|
369 |
} |
|
370 |
|
|
371 |
void OPPROTO op_stc(void) |
|
372 |
{ |
|
373 |
int eflags; |
|
374 |
eflags = cc_table[CC_OP].compute_all(); |
|
375 |
eflags |= CC_C; |
|
376 |
CC_SRC = eflags; |
|
377 |
} |
|
378 |
|
|
379 |
void OPPROTO op_cmc(void) |
|
380 |
{ |
|
381 |
int eflags; |
|
382 |
eflags = cc_table[CC_OP].compute_all(); |
|
383 |
eflags ^= CC_C; |
|
384 |
CC_SRC = eflags; |
|
385 |
} |
|
386 |
|
|
387 |
void OPPROTO op_salc(void) |
|
388 |
{ |
|
389 |
int cf; |
|
390 |
cf = cc_table[CC_OP].compute_c(); |
|
391 |
EAX = (EAX & ~0xff) | ((-cf) & 0xff); |
|
392 |
} |
b/target-i386/translate.c | ||
---|---|---|
5733 | 5733 |
} else { |
5734 | 5734 |
if (s->cc_op != CC_OP_DYNAMIC) |
5735 | 5735 |
gen_op_set_cc_op(s->cc_op); |
5736 |
gen_op_movl_T0_eflags();
|
|
5736 |
tcg_gen_helper_1_0(helper_read_eflags, cpu_T[0]);
|
|
5737 | 5737 |
gen_push_T0(s); |
5738 | 5738 |
} |
5739 | 5739 |
break; |
... | ... | |
5746 | 5746 |
gen_pop_T0(s); |
5747 | 5747 |
if (s->cpl == 0) { |
5748 | 5748 |
if (s->dflag) { |
5749 |
gen_op_movl_eflags_T0_cpl0(); |
|
5749 |
tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
|
5750 |
tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK))); |
|
5750 | 5751 |
} else { |
5751 |
gen_op_movw_eflags_T0_cpl0(); |
|
5752 |
tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
|
5753 |
tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff)); |
|
5752 | 5754 |
} |
5753 | 5755 |
} else { |
5754 | 5756 |
if (s->cpl <= s->iopl) { |
5755 | 5757 |
if (s->dflag) { |
5756 |
gen_op_movl_eflags_T0_io(); |
|
5758 |
tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
|
5759 |
tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK))); |
|
5757 | 5760 |
} else { |
5758 |
gen_op_movw_eflags_T0_io(); |
|
5761 |
tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
|
5762 |
tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff)); |
|
5759 | 5763 |
} |
5760 | 5764 |
} else { |
5761 | 5765 |
if (s->dflag) { |
5762 |
gen_op_movl_eflags_T0(); |
|
5766 |
tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
|
5767 |
tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK))); |
|
5763 | 5768 |
} else { |
5764 |
gen_op_movw_eflags_T0(); |
|
5769 |
tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], |
|
5770 |
tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff)); |
|
5765 | 5771 |
} |
5766 | 5772 |
} |
5767 | 5773 |
} |
... | ... | |
5778 | 5784 |
gen_op_mov_TN_reg(OT_BYTE, 0, R_AH); |
5779 | 5785 |
if (s->cc_op != CC_OP_DYNAMIC) |
5780 | 5786 |
gen_op_set_cc_op(s->cc_op); |
5781 |
gen_op_movb_eflags_T0(); |
|
5787 |
gen_compute_eflags(cpu_cc_src); |
|
5788 |
tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O); |
|
5789 |
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C); |
|
5790 |
tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]); |
|
5782 | 5791 |
s->cc_op = CC_OP_EFLAGS; |
5783 | 5792 |
break; |
5784 | 5793 |
case 0x9f: /* lahf */ |
... | ... | |
5786 | 5795 |
goto illegal_op; |
5787 | 5796 |
if (s->cc_op != CC_OP_DYNAMIC) |
5788 | 5797 |
gen_op_set_cc_op(s->cc_op); |
5789 |
gen_op_movl_T0_eflags(); |
|
5798 |
gen_compute_eflags(cpu_T[0]); |
|
5799 |
/* Note: gen_compute_eflags() only gives the condition codes */ |
|
5800 |
tcg_gen_ori_tl(cpu_T[0], cpu_T[0], 0x02); |
|
5790 | 5801 |
gen_op_mov_reg_T0(OT_BYTE, R_AH); |
5791 | 5802 |
break; |
5792 | 5803 |
case 0xf5: /* cmc */ |
5793 | 5804 |
if (s->cc_op != CC_OP_DYNAMIC) |
5794 | 5805 |
gen_op_set_cc_op(s->cc_op); |
5795 |
gen_op_cmc(); |
|
5806 |
gen_compute_eflags(cpu_cc_src); |
|
5807 |
tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C); |
|
5796 | 5808 |
s->cc_op = CC_OP_EFLAGS; |
5797 | 5809 |
break; |
5798 | 5810 |
case 0xf8: /* clc */ |
5799 | 5811 |
if (s->cc_op != CC_OP_DYNAMIC) |
5800 | 5812 |
gen_op_set_cc_op(s->cc_op); |
5801 |
gen_op_clc(); |
|
5813 |
gen_compute_eflags(cpu_cc_src); |
|
5814 |
tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C); |
|
5802 | 5815 |
s->cc_op = CC_OP_EFLAGS; |
5803 | 5816 |
break; |
5804 | 5817 |
case 0xf9: /* stc */ |
5805 | 5818 |
if (s->cc_op != CC_OP_DYNAMIC) |
5806 | 5819 |
gen_op_set_cc_op(s->cc_op); |
5807 |
gen_op_stc(); |
|
5820 |
gen_compute_eflags(cpu_cc_src); |
|
5821 |
tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C); |
|
5808 | 5822 |
s->cc_op = CC_OP_EFLAGS; |
5809 | 5823 |
break; |
5810 | 5824 |
case 0xfc: /* cld */ |
... | ... | |
6127 | 6141 |
goto illegal_op; |
6128 | 6142 |
if (s->cc_op != CC_OP_DYNAMIC) |
6129 | 6143 |
gen_op_set_cc_op(s->cc_op); |
6130 |
gen_op_salc(); |
|
6144 |
gen_compute_eflags_c(cpu_T[0]); |
|
6145 |
tcg_gen_neg_tl(cpu_T[0], cpu_T[0]); |
|
6146 |
gen_op_mov_reg_T0(OT_BYTE, R_EAX); |
|
6131 | 6147 |
break; |
6132 | 6148 |
case 0xe0: /* loopnz */ |
6133 | 6149 |
case 0xe1: /* loopz */ |
Also available in: Unified diff