root / target-i386 / op.c @ b8b6a50b
History | View | Annotate | Download (17.3 kB)
1 |
/*
|
---|---|
2 |
* i386 micro operations
|
3 |
*
|
4 |
* Copyright (c) 2003 Fabrice Bellard
|
5 |
*
|
6 |
* This library is free software; you can redistribute it and/or
|
7 |
* modify it under the terms of the GNU Lesser General Public
|
8 |
* License as published by the Free Software Foundation; either
|
9 |
* version 2 of the License, or (at your option) any later version.
|
10 |
*
|
11 |
* This library is distributed in the hope that it will be useful,
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 |
* Lesser General Public License for more details.
|
15 |
*
|
16 |
* You should have received a copy of the GNU Lesser General Public
|
17 |
* License along with this library; if not, write to the Free Software
|
18 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19 |
*/
|
20 |
|
21 |
#define ASM_SOFTMMU
|
22 |
#include "exec.h" |
23 |
|
24 |
/* n must be a constant to be efficient */
|
25 |
static inline target_long lshift(target_long x, int n) |
26 |
{ |
27 |
if (n >= 0) |
28 |
return x << n;
|
29 |
else
|
30 |
return x >> (-n);
|
31 |
} |
32 |
|
33 |
/* we define the various pieces of code used by the JIT */
|
34 |
|
35 |
#define REG EAX
|
36 |
#define REGNAME _EAX
|
37 |
#include "opreg_template.h" |
38 |
#undef REG
|
39 |
#undef REGNAME
|
40 |
|
41 |
#define REG ECX
|
42 |
#define REGNAME _ECX
|
43 |
#include "opreg_template.h" |
44 |
#undef REG
|
45 |
#undef REGNAME
|
46 |
|
47 |
#define REG EDX
|
48 |
#define REGNAME _EDX
|
49 |
#include "opreg_template.h" |
50 |
#undef REG
|
51 |
#undef REGNAME
|
52 |
|
53 |
#define REG EBX
|
54 |
#define REGNAME _EBX
|
55 |
#include "opreg_template.h" |
56 |
#undef REG
|
57 |
#undef REGNAME
|
58 |
|
59 |
#define REG ESP
|
60 |
#define REGNAME _ESP
|
61 |
#include "opreg_template.h" |
62 |
#undef REG
|
63 |
#undef REGNAME
|
64 |
|
65 |
#define REG EBP
|
66 |
#define REGNAME _EBP
|
67 |
#include "opreg_template.h" |
68 |
#undef REG
|
69 |
#undef REGNAME
|
70 |
|
71 |
#define REG ESI
|
72 |
#define REGNAME _ESI
|
73 |
#include "opreg_template.h" |
74 |
#undef REG
|
75 |
#undef REGNAME
|
76 |
|
77 |
#define REG EDI
|
78 |
#define REGNAME _EDI
|
79 |
#include "opreg_template.h" |
80 |
#undef REG
|
81 |
#undef REGNAME
|
82 |
|
83 |
#ifdef TARGET_X86_64
|
84 |
|
85 |
#define REG (env->regs[8]) |
86 |
#define REGNAME _R8
|
87 |
#include "opreg_template.h" |
88 |
#undef REG
|
89 |
#undef REGNAME
|
90 |
|
91 |
#define REG (env->regs[9]) |
92 |
#define REGNAME _R9
|
93 |
#include "opreg_template.h" |
94 |
#undef REG
|
95 |
#undef REGNAME
|
96 |
|
97 |
#define REG (env->regs[10]) |
98 |
#define REGNAME _R10
|
99 |
#include "opreg_template.h" |
100 |
#undef REG
|
101 |
#undef REGNAME
|
102 |
|
103 |
#define REG (env->regs[11]) |
104 |
#define REGNAME _R11
|
105 |
#include "opreg_template.h" |
106 |
#undef REG
|
107 |
#undef REGNAME
|
108 |
|
109 |
#define REG (env->regs[12]) |
110 |
#define REGNAME _R12
|
111 |
#include "opreg_template.h" |
112 |
#undef REG
|
113 |
#undef REGNAME
|
114 |
|
115 |
#define REG (env->regs[13]) |
116 |
#define REGNAME _R13
|
117 |
#include "opreg_template.h" |
118 |
#undef REG
|
119 |
#undef REGNAME
|
120 |
|
121 |
#define REG (env->regs[14]) |
122 |
#define REGNAME _R14
|
123 |
#include "opreg_template.h" |
124 |
#undef REG
|
125 |
#undef REGNAME
|
126 |
|
127 |
#define REG (env->regs[15]) |
128 |
#define REGNAME _R15
|
129 |
#include "opreg_template.h" |
130 |
#undef REG
|
131 |
#undef REGNAME
|
132 |
|
133 |
#endif
|
134 |
|
135 |
/* operations with flags */
|
136 |
|
137 |
/* update flags with T0 and T1 (add/sub case) */
|
138 |
void OPPROTO op_update2_cc(void) |
139 |
{ |
140 |
CC_SRC = T1; |
141 |
CC_DST = T0; |
142 |
} |
143 |
|
144 |
/* update flags with T0 (logic operation case) */
|
145 |
void OPPROTO op_update1_cc(void) |
146 |
{ |
147 |
CC_DST = T0; |
148 |
} |
149 |
|
150 |
void OPPROTO op_update_neg_cc(void) |
151 |
{ |
152 |
CC_SRC = -T0; |
153 |
CC_DST = T0; |
154 |
} |
155 |
|
156 |
void OPPROTO op_cmpl_T0_T1_cc(void) |
157 |
{ |
158 |
CC_SRC = T1; |
159 |
CC_DST = T0 - T1; |
160 |
} |
161 |
|
162 |
void OPPROTO op_update_inc_cc(void) |
163 |
{ |
164 |
CC_SRC = cc_table[CC_OP].compute_c(); |
165 |
CC_DST = T0; |
166 |
} |
167 |
|
168 |
void OPPROTO op_testl_T0_T1_cc(void) |
169 |
{ |
170 |
CC_DST = T0 & T1; |
171 |
} |
172 |
|
173 |
/* operations without flags */
|
174 |
|
175 |
void OPPROTO op_negl_T0(void) |
176 |
{ |
177 |
T0 = -T0; |
178 |
} |
179 |
|
180 |
void OPPROTO op_incl_T0(void) |
181 |
{ |
182 |
T0++; |
183 |
} |
184 |
|
185 |
void OPPROTO op_decl_T0(void) |
186 |
{ |
187 |
T0--; |
188 |
} |
189 |
|
190 |
void OPPROTO op_notl_T0(void) |
191 |
{ |
192 |
T0 = ~T0; |
193 |
} |
194 |
|
195 |
/* multiply/divide */
|
196 |
|
197 |
/* XXX: add eflags optimizations */
|
198 |
/* XXX: add non P4 style flags */
|
199 |
|
200 |
void OPPROTO op_mulb_AL_T0(void) |
201 |
{ |
202 |
unsigned int res; |
203 |
res = (uint8_t)EAX * (uint8_t)T0; |
204 |
EAX = (EAX & ~0xffff) | res;
|
205 |
CC_DST = res; |
206 |
CC_SRC = (res & 0xff00);
|
207 |
} |
208 |
|
209 |
void OPPROTO op_imulb_AL_T0(void) |
210 |
{ |
211 |
int res;
|
212 |
res = (int8_t)EAX * (int8_t)T0; |
213 |
EAX = (EAX & ~0xffff) | (res & 0xffff); |
214 |
CC_DST = res; |
215 |
CC_SRC = (res != (int8_t)res); |
216 |
} |
217 |
|
218 |
void OPPROTO op_mulw_AX_T0(void) |
219 |
{ |
220 |
unsigned int res; |
221 |
res = (uint16_t)EAX * (uint16_t)T0; |
222 |
EAX = (EAX & ~0xffff) | (res & 0xffff); |
223 |
EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff); |
224 |
CC_DST = res; |
225 |
CC_SRC = res >> 16;
|
226 |
} |
227 |
|
228 |
void OPPROTO op_imulw_AX_T0(void) |
229 |
{ |
230 |
int res;
|
231 |
res = (int16_t)EAX * (int16_t)T0; |
232 |
EAX = (EAX & ~0xffff) | (res & 0xffff); |
233 |
EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff); |
234 |
CC_DST = res; |
235 |
CC_SRC = (res != (int16_t)res); |
236 |
} |
237 |
|
238 |
void OPPROTO op_mull_EAX_T0(void) |
239 |
{ |
240 |
uint64_t res; |
241 |
res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0); |
242 |
EAX = (uint32_t)res; |
243 |
EDX = (uint32_t)(res >> 32);
|
244 |
CC_DST = (uint32_t)res; |
245 |
CC_SRC = (uint32_t)(res >> 32);
|
246 |
} |
247 |
|
248 |
void OPPROTO op_imull_EAX_T0(void) |
249 |
{ |
250 |
int64_t res; |
251 |
res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0); |
252 |
EAX = (uint32_t)(res); |
253 |
EDX = (uint32_t)(res >> 32);
|
254 |
CC_DST = res; |
255 |
CC_SRC = (res != (int32_t)res); |
256 |
} |
257 |
|
258 |
void OPPROTO op_imulw_T0_T1(void) |
259 |
{ |
260 |
int res;
|
261 |
res = (int16_t)T0 * (int16_t)T1; |
262 |
T0 = res; |
263 |
CC_DST = res; |
264 |
CC_SRC = (res != (int16_t)res); |
265 |
} |
266 |
|
267 |
void OPPROTO op_imull_T0_T1(void) |
268 |
{ |
269 |
int64_t res; |
270 |
res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); |
271 |
T0 = res; |
272 |
CC_DST = res; |
273 |
CC_SRC = (res != (int32_t)res); |
274 |
} |
275 |
|
276 |
#ifdef TARGET_X86_64
|
277 |
void OPPROTO op_mulq_EAX_T0(void) |
278 |
{ |
279 |
helper_mulq_EAX_T0(T0); |
280 |
} |
281 |
|
282 |
void OPPROTO op_imulq_EAX_T0(void) |
283 |
{ |
284 |
helper_imulq_EAX_T0(T0); |
285 |
} |
286 |
|
287 |
void OPPROTO op_imulq_T0_T1(void) |
288 |
{ |
289 |
T0 = helper_imulq_T0_T1(T0, T1); |
290 |
} |
291 |
#endif
|
292 |
|
293 |
/* constant load & misc op */
|
294 |
|
295 |
/* XXX: consistent names */
|
296 |
void OPPROTO op_addl_T1_im(void) |
297 |
{ |
298 |
T1 += PARAM1; |
299 |
} |
300 |
|
301 |
void OPPROTO op_movl_T1_A0(void) |
302 |
{ |
303 |
T1 = A0; |
304 |
} |
305 |
|
306 |
void OPPROTO op_addl_A0_AL(void) |
307 |
{ |
308 |
A0 = (uint32_t)(A0 + (EAX & 0xff));
|
309 |
} |
310 |
|
311 |
#ifdef WORDS_BIGENDIAN
|
312 |
typedef union UREG64 { |
313 |
struct { uint16_t v3, v2, v1, v0; } w;
|
314 |
struct { uint32_t v1, v0; } l;
|
315 |
uint64_t q; |
316 |
} UREG64; |
317 |
#else
|
318 |
typedef union UREG64 { |
319 |
struct { uint16_t v0, v1, v2, v3; } w;
|
320 |
struct { uint32_t v0, v1; } l;
|
321 |
uint64_t q; |
322 |
} UREG64; |
323 |
#endif
|
324 |
|
325 |
#define PARAMQ1 \
|
326 |
({\ |
327 |
UREG64 __p;\ |
328 |
__p.l.v1 = PARAM1;\ |
329 |
__p.l.v0 = PARAM2;\ |
330 |
__p.q;\ |
331 |
}) |
332 |
|
333 |
#ifdef TARGET_X86_64
|
334 |
|
335 |
void OPPROTO op_addq_A0_AL(void) |
336 |
{ |
337 |
A0 = (A0 + (EAX & 0xff));
|
338 |
} |
339 |
|
340 |
#endif
|
341 |
|
342 |
void OPPROTO op_into(void) |
343 |
{ |
344 |
int eflags;
|
345 |
eflags = cc_table[CC_OP].compute_all(); |
346 |
if (eflags & CC_O) {
|
347 |
raise_interrupt(EXCP04_INTO, 1, 0, PARAM1); |
348 |
} |
349 |
FORCE_RET(); |
350 |
} |
351 |
|
352 |
void OPPROTO op_cmpxchg8b(void) |
353 |
{ |
354 |
helper_cmpxchg8b(A0); |
355 |
} |
356 |
|
357 |
/* multiple size ops */
|
358 |
|
359 |
#define ldul ldl
|
360 |
|
361 |
#define SHIFT 0 |
362 |
#include "ops_template.h" |
363 |
#undef SHIFT
|
364 |
|
365 |
#define SHIFT 1 |
366 |
#include "ops_template.h" |
367 |
#undef SHIFT
|
368 |
|
369 |
#define SHIFT 2 |
370 |
#include "ops_template.h" |
371 |
#undef SHIFT
|
372 |
|
373 |
#ifdef TARGET_X86_64
|
374 |
|
375 |
#define SHIFT 3 |
376 |
#include "ops_template.h" |
377 |
#undef SHIFT
|
378 |
|
379 |
#endif
|
380 |
|
381 |
/* sign extend */
|
382 |
|
383 |
void OPPROTO op_movsbl_T0_T0(void) |
384 |
{ |
385 |
T0 = (int8_t)T0; |
386 |
} |
387 |
|
388 |
void OPPROTO op_movzbl_T0_T0(void) |
389 |
{ |
390 |
T0 = (uint8_t)T0; |
391 |
} |
392 |
|
393 |
void OPPROTO op_movswl_T0_T0(void) |
394 |
{ |
395 |
T0 = (int16_t)T0; |
396 |
} |
397 |
|
398 |
void OPPROTO op_movzwl_T0_T0(void) |
399 |
{ |
400 |
T0 = (uint16_t)T0; |
401 |
} |
402 |
|
403 |
void OPPROTO op_movswl_EAX_AX(void) |
404 |
{ |
405 |
EAX = (uint32_t)((int16_t)EAX); |
406 |
} |
407 |
|
408 |
#ifdef TARGET_X86_64
|
409 |
void OPPROTO op_movslq_T0_T0(void) |
410 |
{ |
411 |
T0 = (int32_t)T0; |
412 |
} |
413 |
|
414 |
void OPPROTO op_movslq_RAX_EAX(void) |
415 |
{ |
416 |
EAX = (int32_t)EAX; |
417 |
} |
418 |
#endif
|
419 |
|
420 |
void OPPROTO op_movsbw_AX_AL(void) |
421 |
{ |
422 |
EAX = (EAX & ~0xffff) | ((int8_t)EAX & 0xffff); |
423 |
} |
424 |
|
425 |
void OPPROTO op_movslq_EDX_EAX(void) |
426 |
{ |
427 |
EDX = (uint32_t)((int32_t)EAX >> 31);
|
428 |
} |
429 |
|
430 |
void OPPROTO op_movswl_DX_AX(void) |
431 |
{ |
432 |
EDX = (EDX & ~0xffff) | (((int16_t)EAX >> 15) & 0xffff); |
433 |
} |
434 |
|
435 |
#ifdef TARGET_X86_64
|
436 |
void OPPROTO op_movsqo_RDX_RAX(void) |
437 |
{ |
438 |
EDX = (int64_t)EAX >> 63;
|
439 |
} |
440 |
#endif
|
441 |
|
442 |
/* string ops helpers */
|
443 |
|
444 |
void OPPROTO op_addl_ESI_T0(void) |
445 |
{ |
446 |
ESI = (uint32_t)(ESI + T0); |
447 |
} |
448 |
|
449 |
void OPPROTO op_addw_ESI_T0(void) |
450 |
{ |
451 |
ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff); |
452 |
} |
453 |
|
454 |
void OPPROTO op_addl_EDI_T0(void) |
455 |
{ |
456 |
EDI = (uint32_t)(EDI + T0); |
457 |
} |
458 |
|
459 |
void OPPROTO op_addw_EDI_T0(void) |
460 |
{ |
461 |
EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff); |
462 |
} |
463 |
|
464 |
void OPPROTO op_decl_ECX(void) |
465 |
{ |
466 |
ECX = (uint32_t)(ECX - 1);
|
467 |
} |
468 |
|
469 |
void OPPROTO op_decw_ECX(void) |
470 |
{ |
471 |
ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff); |
472 |
} |
473 |
|
474 |
#ifdef TARGET_X86_64
|
475 |
void OPPROTO op_addq_ESI_T0(void) |
476 |
{ |
477 |
ESI = (ESI + T0); |
478 |
} |
479 |
|
480 |
void OPPROTO op_addq_EDI_T0(void) |
481 |
{ |
482 |
EDI = (EDI + T0); |
483 |
} |
484 |
|
485 |
void OPPROTO op_decq_ECX(void) |
486 |
{ |
487 |
ECX--; |
488 |
} |
489 |
#endif
|
490 |
|
491 |
/* bcd */
|
492 |
|
493 |
void OPPROTO op_aam(void) |
494 |
{ |
495 |
helper_aam(PARAM1); |
496 |
} |
497 |
|
498 |
void OPPROTO op_aad(void) |
499 |
{ |
500 |
helper_aad(PARAM1); |
501 |
} |
502 |
|
503 |
void OPPROTO op_aaa(void) |
504 |
{ |
505 |
helper_aaa(); |
506 |
} |
507 |
|
508 |
void OPPROTO op_aas(void) |
509 |
{ |
510 |
helper_aas(); |
511 |
} |
512 |
|
513 |
void OPPROTO op_daa(void) |
514 |
{ |
515 |
helper_daa(); |
516 |
} |
517 |
|
518 |
void OPPROTO op_das(void) |
519 |
{ |
520 |
helper_das(); |
521 |
} |
522 |
|
523 |
/* segment handling */
|
524 |
|
525 |
/* faster VM86 version */
|
526 |
void OPPROTO op_movl_seg_T0_vm(void) |
527 |
{ |
528 |
int selector;
|
529 |
SegmentCache *sc; |
530 |
|
531 |
selector = T0 & 0xffff;
|
532 |
/* env->segs[] access */
|
533 |
sc = (SegmentCache *)((char *)env + PARAM1);
|
534 |
sc->selector = selector; |
535 |
sc->base = (selector << 4);
|
536 |
} |
537 |
|
538 |
void OPPROTO op_movl_T0_seg(void) |
539 |
{ |
540 |
T0 = env->segs[PARAM1].selector; |
541 |
} |
542 |
|
543 |
void OPPROTO op_lsl(void) |
544 |
{ |
545 |
uint32_t val; |
546 |
val = helper_lsl(T0); |
547 |
if (CC_SRC & CC_Z)
|
548 |
T1 = val; |
549 |
FORCE_RET(); |
550 |
} |
551 |
|
552 |
void OPPROTO op_lar(void) |
553 |
{ |
554 |
uint32_t val; |
555 |
val = helper_lar(T0); |
556 |
if (CC_SRC & CC_Z)
|
557 |
T1 = val; |
558 |
FORCE_RET(); |
559 |
} |
560 |
|
561 |
void OPPROTO op_verr(void) |
562 |
{ |
563 |
helper_verr(T0); |
564 |
} |
565 |
|
566 |
void OPPROTO op_verw(void) |
567 |
{ |
568 |
helper_verw(T0); |
569 |
} |
570 |
|
571 |
void OPPROTO op_arpl(void) |
572 |
{ |
573 |
if ((T0 & 3) < (T1 & 3)) { |
574 |
/* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
|
575 |
T0 = (T0 & ~3) | (T1 & 3); |
576 |
T1 = CC_Z; |
577 |
} else {
|
578 |
T1 = 0;
|
579 |
} |
580 |
FORCE_RET(); |
581 |
} |
582 |
|
583 |
void OPPROTO op_arpl_update(void) |
584 |
{ |
585 |
int eflags;
|
586 |
eflags = cc_table[CC_OP].compute_all(); |
587 |
CC_SRC = (eflags & ~CC_Z) | T1; |
588 |
} |
589 |
|
590 |
void OPPROTO op_movl_T0_env(void) |
591 |
{ |
592 |
T0 = *(uint32_t *)((char *)env + PARAM1);
|
593 |
} |
594 |
|
595 |
void OPPROTO op_movl_env_T0(void) |
596 |
{ |
597 |
*(uint32_t *)((char *)env + PARAM1) = T0;
|
598 |
} |
599 |
|
600 |
void OPPROTO op_movl_env_T1(void) |
601 |
{ |
602 |
*(uint32_t *)((char *)env + PARAM1) = T1;
|
603 |
} |
604 |
|
605 |
void OPPROTO op_movtl_T0_env(void) |
606 |
{ |
607 |
T0 = *(target_ulong *)((char *)env + PARAM1);
|
608 |
} |
609 |
|
610 |
void OPPROTO op_movtl_env_T0(void) |
611 |
{ |
612 |
*(target_ulong *)((char *)env + PARAM1) = T0;
|
613 |
} |
614 |
|
615 |
void OPPROTO op_movtl_T1_env(void) |
616 |
{ |
617 |
T1 = *(target_ulong *)((char *)env + PARAM1);
|
618 |
} |
619 |
|
620 |
void OPPROTO op_movtl_env_T1(void) |
621 |
{ |
622 |
*(target_ulong *)((char *)env + PARAM1) = T1;
|
623 |
} |
624 |
|
625 |
/* flags handling */
|
626 |
|
627 |
void OPPROTO op_jmp_label(void) |
628 |
{ |
629 |
GOTO_LABEL_PARAM(1);
|
630 |
} |
631 |
|
632 |
void OPPROTO op_jnz_T0_label(void) |
633 |
{ |
634 |
if (T0)
|
635 |
GOTO_LABEL_PARAM(1);
|
636 |
FORCE_RET(); |
637 |
} |
638 |
|
639 |
void OPPROTO op_jz_T0_label(void) |
640 |
{ |
641 |
if (!T0)
|
642 |
GOTO_LABEL_PARAM(1);
|
643 |
FORCE_RET(); |
644 |
} |
645 |
|
646 |
/* slow set cases (compute x86 flags) */
|
647 |
void OPPROTO op_seto_T0_cc(void) |
648 |
{ |
649 |
int eflags;
|
650 |
eflags = cc_table[CC_OP].compute_all(); |
651 |
T0 = (eflags >> 11) & 1; |
652 |
} |
653 |
|
654 |
void OPPROTO op_setb_T0_cc(void) |
655 |
{ |
656 |
T0 = cc_table[CC_OP].compute_c(); |
657 |
} |
658 |
|
659 |
void OPPROTO op_setz_T0_cc(void) |
660 |
{ |
661 |
int eflags;
|
662 |
eflags = cc_table[CC_OP].compute_all(); |
663 |
T0 = (eflags >> 6) & 1; |
664 |
} |
665 |
|
666 |
void OPPROTO op_setbe_T0_cc(void) |
667 |
{ |
668 |
int eflags;
|
669 |
eflags = cc_table[CC_OP].compute_all(); |
670 |
T0 = (eflags & (CC_Z | CC_C)) != 0;
|
671 |
} |
672 |
|
673 |
void OPPROTO op_sets_T0_cc(void) |
674 |
{ |
675 |
int eflags;
|
676 |
eflags = cc_table[CC_OP].compute_all(); |
677 |
T0 = (eflags >> 7) & 1; |
678 |
} |
679 |
|
680 |
void OPPROTO op_setp_T0_cc(void) |
681 |
{ |
682 |
int eflags;
|
683 |
eflags = cc_table[CC_OP].compute_all(); |
684 |
T0 = (eflags >> 2) & 1; |
685 |
} |
686 |
|
687 |
void OPPROTO op_setl_T0_cc(void) |
688 |
{ |
689 |
int eflags;
|
690 |
eflags = cc_table[CC_OP].compute_all(); |
691 |
T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1; |
692 |
} |
693 |
|
694 |
void OPPROTO op_setle_T0_cc(void) |
695 |
{ |
696 |
int eflags;
|
697 |
eflags = cc_table[CC_OP].compute_all(); |
698 |
T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0; |
699 |
} |
700 |
|
701 |
void OPPROTO op_xor_T0_1(void) |
702 |
{ |
703 |
T0 ^= 1;
|
704 |
} |
705 |
|
706 |
void OPPROTO op_mov_T0_cc(void) |
707 |
{ |
708 |
T0 = cc_table[CC_OP].compute_all(); |
709 |
} |
710 |
|
711 |
/* XXX: clear VIF/VIP in all ops ? */
|
712 |
|
713 |
void OPPROTO op_movl_eflags_T0(void) |
714 |
{ |
715 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK)); |
716 |
} |
717 |
|
718 |
void OPPROTO op_movw_eflags_T0(void) |
719 |
{ |
720 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
|
721 |
} |
722 |
|
723 |
void OPPROTO op_movl_eflags_T0_io(void) |
724 |
{ |
725 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK)); |
726 |
} |
727 |
|
728 |
void OPPROTO op_movw_eflags_T0_io(void) |
729 |
{ |
730 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
|
731 |
} |
732 |
|
733 |
void OPPROTO op_movl_eflags_T0_cpl0(void) |
734 |
{ |
735 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK)); |
736 |
} |
737 |
|
738 |
void OPPROTO op_movw_eflags_T0_cpl0(void) |
739 |
{ |
740 |
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
|
741 |
} |
742 |
|
743 |
#if 0
|
744 |
/* vm86plus version */
|
745 |
void OPPROTO op_movw_eflags_T0_vm(void)
|
746 |
{
|
747 |
int eflags;
|
748 |
eflags = T0;
|
749 |
CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
|
750 |
DF = 1 - (2 * ((eflags >> 10) & 1));
|
751 |
/* we also update some system flags as in user mode */
|
752 |
env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
|
753 |
(eflags & FL_UPDATE_MASK16);
|
754 |
if (eflags & IF_MASK) {
|
755 |
env->eflags |= VIF_MASK;
|
756 |
if (env->eflags & VIP_MASK) {
|
757 |
EIP = PARAM1;
|
758 |
raise_exception(EXCP0D_GPF);
|
759 |
}
|
760 |
}
|
761 |
FORCE_RET();
|
762 |
}
|
763 |
|
764 |
void OPPROTO op_movl_eflags_T0_vm(void)
|
765 |
{
|
766 |
int eflags;
|
767 |
eflags = T0;
|
768 |
CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
|
769 |
DF = 1 - (2 * ((eflags >> 10) & 1));
|
770 |
/* we also update some system flags as in user mode */
|
771 |
env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
|
772 |
(eflags & FL_UPDATE_MASK32);
|
773 |
if (eflags & IF_MASK) {
|
774 |
env->eflags |= VIF_MASK;
|
775 |
if (env->eflags & VIP_MASK) {
|
776 |
EIP = PARAM1;
|
777 |
raise_exception(EXCP0D_GPF);
|
778 |
}
|
779 |
}
|
780 |
FORCE_RET();
|
781 |
}
|
782 |
#endif
|
783 |
|
784 |
/* XXX: compute only O flag */
|
785 |
void OPPROTO op_movb_eflags_T0(void) |
786 |
{ |
787 |
int of;
|
788 |
of = cc_table[CC_OP].compute_all() & CC_O; |
789 |
CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of; |
790 |
} |
791 |
|
792 |
void OPPROTO op_movl_T0_eflags(void) |
793 |
{ |
794 |
int eflags;
|
795 |
eflags = cc_table[CC_OP].compute_all(); |
796 |
eflags |= (DF & DF_MASK); |
797 |
eflags |= env->eflags & ~(VM_MASK | RF_MASK); |
798 |
T0 = eflags; |
799 |
} |
800 |
|
801 |
/* vm86plus version */
|
802 |
#if 0
|
803 |
void OPPROTO op_movl_T0_eflags_vm(void)
|
804 |
{
|
805 |
int eflags;
|
806 |
eflags = cc_table[CC_OP].compute_all();
|
807 |
eflags |= (DF & DF_MASK);
|
808 |
eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
|
809 |
if (env->eflags & VIF_MASK)
|
810 |
eflags |= IF_MASK;
|
811 |
T0 = eflags;
|
812 |
}
|
813 |
#endif
|
814 |
|
815 |
void OPPROTO op_clc(void) |
816 |
{ |
817 |
int eflags;
|
818 |
eflags = cc_table[CC_OP].compute_all(); |
819 |
eflags &= ~CC_C; |
820 |
CC_SRC = eflags; |
821 |
} |
822 |
|
823 |
void OPPROTO op_stc(void) |
824 |
{ |
825 |
int eflags;
|
826 |
eflags = cc_table[CC_OP].compute_all(); |
827 |
eflags |= CC_C; |
828 |
CC_SRC = eflags; |
829 |
} |
830 |
|
831 |
void OPPROTO op_cmc(void) |
832 |
{ |
833 |
int eflags;
|
834 |
eflags = cc_table[CC_OP].compute_all(); |
835 |
eflags ^= CC_C; |
836 |
CC_SRC = eflags; |
837 |
} |
838 |
|
839 |
void OPPROTO op_salc(void) |
840 |
{ |
841 |
int cf;
|
842 |
cf = cc_table[CC_OP].compute_c(); |
843 |
EAX = (EAX & ~0xff) | ((-cf) & 0xff); |
844 |
} |
845 |
|
846 |
static int compute_all_eflags(void) |
847 |
{ |
848 |
return CC_SRC;
|
849 |
} |
850 |
|
851 |
static int compute_c_eflags(void) |
852 |
{ |
853 |
return CC_SRC & CC_C;
|
854 |
} |
855 |
|
856 |
CCTable cc_table[CC_OP_NB] = { |
857 |
[CC_OP_DYNAMIC] = { /* should never happen */ },
|
858 |
|
859 |
[CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags }, |
860 |
|
861 |
[CC_OP_MULB] = { compute_all_mulb, compute_c_mull }, |
862 |
[CC_OP_MULW] = { compute_all_mulw, compute_c_mull }, |
863 |
[CC_OP_MULL] = { compute_all_mull, compute_c_mull }, |
864 |
|
865 |
[CC_OP_ADDB] = { compute_all_addb, compute_c_addb }, |
866 |
[CC_OP_ADDW] = { compute_all_addw, compute_c_addw }, |
867 |
[CC_OP_ADDL] = { compute_all_addl, compute_c_addl }, |
868 |
|
869 |
[CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb }, |
870 |
[CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw }, |
871 |
[CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl }, |
872 |
|
873 |
[CC_OP_SUBB] = { compute_all_subb, compute_c_subb }, |
874 |
[CC_OP_SUBW] = { compute_all_subw, compute_c_subw }, |
875 |
[CC_OP_SUBL] = { compute_all_subl, compute_c_subl }, |
876 |
|
877 |
[CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb }, |
878 |
[CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw }, |
879 |
[CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl }, |
880 |
|
881 |
[CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb }, |
882 |
[CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw }, |
883 |
[CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl }, |
884 |
|
885 |
[CC_OP_INCB] = { compute_all_incb, compute_c_incl }, |
886 |
[CC_OP_INCW] = { compute_all_incw, compute_c_incl }, |
887 |
[CC_OP_INCL] = { compute_all_incl, compute_c_incl }, |
888 |
|
889 |
[CC_OP_DECB] = { compute_all_decb, compute_c_incl }, |
890 |
[CC_OP_DECW] = { compute_all_decw, compute_c_incl }, |
891 |
[CC_OP_DECL] = { compute_all_decl, compute_c_incl }, |
892 |
|
893 |
[CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb }, |
894 |
[CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw }, |
895 |
[CC_OP_SHLL] = { compute_all_shll, compute_c_shll }, |
896 |
|
897 |
[CC_OP_SARB] = { compute_all_sarb, compute_c_sarl }, |
898 |
[CC_OP_SARW] = { compute_all_sarw, compute_c_sarl }, |
899 |
[CC_OP_SARL] = { compute_all_sarl, compute_c_sarl }, |
900 |
|
901 |
#ifdef TARGET_X86_64
|
902 |
[CC_OP_MULQ] = { compute_all_mulq, compute_c_mull }, |
903 |
|
904 |
[CC_OP_ADDQ] = { compute_all_addq, compute_c_addq }, |
905 |
|
906 |
[CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq }, |
907 |
|
908 |
[CC_OP_SUBQ] = { compute_all_subq, compute_c_subq }, |
909 |
|
910 |
[CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq }, |
911 |
|
912 |
[CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq }, |
913 |
|
914 |
[CC_OP_INCQ] = { compute_all_incq, compute_c_incl }, |
915 |
|
916 |
[CC_OP_DECQ] = { compute_all_decq, compute_c_incl }, |
917 |
|
918 |
[CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq }, |
919 |
|
920 |
[CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl }, |
921 |
#endif
|
922 |
}; |
923 |
|
924 |
void OPPROTO op_fcomi_dummy(void) |
925 |
{ |
926 |
T0 = 0;
|
927 |
} |
928 |
|
929 |
/* SSE support */
|
930 |
void OPPROTO op_com_dummy(void) |
931 |
{ |
932 |
T0 = 0;
|
933 |
} |