]>
git.proxmox.com Git - qemu.git/blob - ops_template.h
2 * i386 micro operations (included several times to generate
3 * different operand sizes)
5 * Copyright (c) 2003 Fabrice Bellard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define DATA_BITS (1 << (3 + SHIFT))
22 #define SHIFT_MASK (DATA_BITS - 1)
23 #define SIGN_MASK (1 << (DATA_BITS - 1))
27 #define DATA_TYPE uint8_t
28 #define DATA_STYPE int8_t
29 #define DATA_MASK 0xff
32 #define DATA_TYPE uint16_t
33 #define DATA_STYPE int16_t
34 #define DATA_MASK 0xffff
37 #define DATA_TYPE uint32_t
38 #define DATA_STYPE int32_t
39 #define DATA_MASK 0xffffffff
41 #error unhandled operand size
44 /* dynamic flags computation */
46 static int glue(compute_all_add
, SUFFIX
)(void)
48 int cf
, pf
, af
, zf
, sf
, of
;
51 src2
= CC_DST
- CC_SRC
;
52 cf
= (DATA_TYPE
)CC_DST
< (DATA_TYPE
)src1
;
53 pf
= parity_table
[(uint8_t)CC_DST
];
54 af
= (CC_DST
^ src1
^ src2
) & 0x10;
55 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
56 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
57 of
= lshift((src1
^ src2
^ -1) & (src1
^ CC_DST
), 12 - DATA_BITS
) & CC_O
;
58 return cf
| pf
| af
| zf
| sf
| of
;
61 static int glue(compute_c_add
, SUFFIX
)(void)
65 cf
= (DATA_TYPE
)CC_DST
< (DATA_TYPE
)src1
;
69 static int glue(compute_all_adc
, SUFFIX
)(void)
71 int cf
, pf
, af
, zf
, sf
, of
;
74 src2
= CC_DST
- CC_SRC
- 1;
75 cf
= (DATA_TYPE
)CC_DST
<= (DATA_TYPE
)src1
;
76 pf
= parity_table
[(uint8_t)CC_DST
];
77 af
= (CC_DST
^ src1
^ src2
) & 0x10;
78 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
79 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
80 of
= lshift((src1
^ src2
^ -1) & (src1
^ CC_DST
), 12 - DATA_BITS
) & CC_O
;
81 return cf
| pf
| af
| zf
| sf
| of
;
84 static int glue(compute_c_adc
, SUFFIX
)(void)
88 cf
= (DATA_TYPE
)CC_DST
<= (DATA_TYPE
)src1
;
92 static int glue(compute_all_sub
, SUFFIX
)(void)
94 int cf
, pf
, af
, zf
, sf
, of
;
97 src2
= CC_SRC
- CC_DST
;
98 cf
= (DATA_TYPE
)src1
< (DATA_TYPE
)src2
;
99 pf
= parity_table
[(uint8_t)CC_DST
];
100 af
= (CC_DST
^ src1
^ src2
) & 0x10;
101 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
102 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
103 of
= lshift((src1
^ src2
) & (src1
^ CC_DST
), 12 - DATA_BITS
) & CC_O
;
104 return cf
| pf
| af
| zf
| sf
| of
;
107 static int glue(compute_c_sub
, SUFFIX
)(void)
111 src2
= CC_SRC
- CC_DST
;
112 cf
= (DATA_TYPE
)src1
< (DATA_TYPE
)src2
;
116 static int glue(compute_all_sbb
, SUFFIX
)(void)
118 int cf
, pf
, af
, zf
, sf
, of
;
121 src2
= CC_SRC
- CC_DST
- 1;
122 cf
= (DATA_TYPE
)src1
<= (DATA_TYPE
)src2
;
123 pf
= parity_table
[(uint8_t)CC_DST
];
124 af
= (CC_DST
^ src1
^ src2
) & 0x10;
125 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
126 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
127 of
= lshift((src1
^ src2
) & (src1
^ CC_DST
), 12 - DATA_BITS
) & CC_O
;
128 return cf
| pf
| af
| zf
| sf
| of
;
131 static int glue(compute_c_sbb
, SUFFIX
)(void)
135 src2
= CC_SRC
- CC_DST
- 1;
136 cf
= (DATA_TYPE
)src1
<= (DATA_TYPE
)src2
;
140 static int glue(compute_all_logic
, SUFFIX
)(void)
142 int cf
, pf
, af
, zf
, sf
, of
;
144 pf
= parity_table
[(uint8_t)CC_DST
];
146 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
147 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
149 return cf
| pf
| af
| zf
| sf
| of
;
152 static int glue(compute_c_logic
, SUFFIX
)(void)
157 static int glue(compute_all_inc
, SUFFIX
)(void)
159 int cf
, pf
, af
, zf
, sf
, of
;
164 pf
= parity_table
[(uint8_t)CC_DST
];
165 af
= (CC_DST
^ src1
^ src2
) & 0x10;
166 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
167 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
168 of
= ((CC_DST
& DATA_MASK
) == SIGN_MASK
) << 11;
169 return cf
| pf
| af
| zf
| sf
| of
;
173 static int glue(compute_c_inc
, SUFFIX
)(void)
179 static int glue(compute_all_dec
, SUFFIX
)(void)
181 int cf
, pf
, af
, zf
, sf
, of
;
186 pf
= parity_table
[(uint8_t)CC_DST
];
187 af
= (CC_DST
^ src1
^ src2
) & 0x10;
188 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
189 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
190 of
= ((CC_DST
& DATA_MASK
) == ((uint32_t)SIGN_MASK
- 1)) << 11;
191 return cf
| pf
| af
| zf
| sf
| of
;
194 static int glue(compute_all_shl
, SUFFIX
)(void)
196 int cf
, pf
, af
, zf
, sf
, of
;
197 cf
= (CC_SRC
>> (DATA_BITS
- 1)) & CC_C
;
198 pf
= parity_table
[(uint8_t)CC_DST
];
199 af
= 0; /* undefined */
200 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
201 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
202 /* of is defined if shift count == 1 */
203 of
= lshift(CC_SRC
^ CC_DST
, 12 - DATA_BITS
) & CC_O
;
204 return cf
| pf
| af
| zf
| sf
| of
;
207 static int glue(compute_c_shl
, SUFFIX
)(void)
209 return (CC_SRC
>> (DATA_BITS
- 1)) & CC_C
;
213 static int glue(compute_c_sar
, SUFFIX
)(void)
219 static int glue(compute_all_sar
, SUFFIX
)(void)
221 int cf
, pf
, af
, zf
, sf
, of
;
223 pf
= parity_table
[(uint8_t)CC_DST
];
224 af
= 0; /* undefined */
225 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
226 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
227 /* of is defined if shift count == 1 */
228 of
= lshift(CC_SRC
^ CC_DST
, 12 - DATA_BITS
) & CC_O
;
229 return cf
| pf
| af
| zf
| sf
| of
;
232 /* various optimized jumps cases */
234 void OPPROTO
glue(op_jb_sub
, SUFFIX
)(void)
238 src2
= CC_SRC
- CC_DST
;
240 if ((DATA_TYPE
)src1
< (DATA_TYPE
)src2
)
241 JUMP_TB(PARAM1
, 0, PARAM2
);
243 JUMP_TB(PARAM1
, 1, PARAM3
);
247 void OPPROTO
glue(op_jz_sub
, SUFFIX
)(void)
249 if ((DATA_TYPE
)CC_DST
== 0)
250 JUMP_TB(PARAM1
, 0, PARAM2
);
252 JUMP_TB(PARAM1
, 1, PARAM3
);
256 void OPPROTO
glue(op_jbe_sub
, SUFFIX
)(void)
260 src2
= CC_SRC
- CC_DST
;
262 if ((DATA_TYPE
)src1
<= (DATA_TYPE
)src2
)
263 JUMP_TB(PARAM1
, 0, PARAM2
);
265 JUMP_TB(PARAM1
, 1, PARAM3
);
269 void OPPROTO
glue(op_js_sub
, SUFFIX
)(void)
271 if (CC_DST
& SIGN_MASK
)
272 JUMP_TB(PARAM1
, 0, PARAM2
);
274 JUMP_TB(PARAM1
, 1, PARAM3
);
278 void OPPROTO
glue(op_jl_sub
, SUFFIX
)(void)
282 src2
= CC_SRC
- CC_DST
;
284 if ((DATA_STYPE
)src1
< (DATA_STYPE
)src2
)
285 JUMP_TB(PARAM1
, 0, PARAM2
);
287 JUMP_TB(PARAM1
, 1, PARAM3
);
291 void OPPROTO
glue(op_jle_sub
, SUFFIX
)(void)
295 src2
= CC_SRC
- CC_DST
;
297 if ((DATA_STYPE
)src1
<= (DATA_STYPE
)src2
)
298 JUMP_TB(PARAM1
, 0, PARAM2
);
300 JUMP_TB(PARAM1
, 1, PARAM3
);
308 void OPPROTO
glue(op_loopnz
, SUFFIX
)(void)
312 eflags
= cc_table
[CC_OP
].compute_all();
313 tmp
= (ECX
- 1) & DATA_MASK
;
314 ECX
= (ECX
& ~DATA_MASK
) | tmp
;
315 if (tmp
!= 0 && !(eflags
& CC_Z
))
322 void OPPROTO
glue(op_loopz
, SUFFIX
)(void)
326 eflags
= cc_table
[CC_OP
].compute_all();
327 tmp
= (ECX
- 1) & DATA_MASK
;
328 ECX
= (ECX
& ~DATA_MASK
) | tmp
;
329 if (tmp
!= 0 && (eflags
& CC_Z
))
336 void OPPROTO
glue(op_loop
, SUFFIX
)(void)
339 tmp
= (ECX
- 1) & DATA_MASK
;
340 ECX
= (ECX
& ~DATA_MASK
) | tmp
;
348 void OPPROTO
glue(op_jecxz
, SUFFIX
)(void)
350 if ((DATA_TYPE
)ECX
== 0)
359 /* various optimized set cases */
361 void OPPROTO
glue(op_setb_T0_sub
, SUFFIX
)(void)
365 src2
= CC_SRC
- CC_DST
;
367 T0
= ((DATA_TYPE
)src1
< (DATA_TYPE
)src2
);
370 void OPPROTO
glue(op_setz_T0_sub
, SUFFIX
)(void)
372 T0
= ((DATA_TYPE
)CC_DST
== 0);
375 void OPPROTO
glue(op_setbe_T0_sub
, SUFFIX
)(void)
379 src2
= CC_SRC
- CC_DST
;
381 T0
= ((DATA_TYPE
)src1
<= (DATA_TYPE
)src2
);
384 void OPPROTO
glue(op_sets_T0_sub
, SUFFIX
)(void)
386 T0
= lshift(CC_DST
, -(DATA_BITS
- 1)) & 1;
389 void OPPROTO
glue(op_setl_T0_sub
, SUFFIX
)(void)
393 src2
= CC_SRC
- CC_DST
;
395 T0
= ((DATA_STYPE
)src1
< (DATA_STYPE
)src2
);
398 void OPPROTO
glue(op_setle_T0_sub
, SUFFIX
)(void)
402 src2
= CC_SRC
- CC_DST
;
404 T0
= ((DATA_STYPE
)src1
<= (DATA_STYPE
)src2
);
409 void OPPROTO
glue(glue(op_rol
, SUFFIX
), _T0_T1_cc
)(void)
412 count
= T1
& SHIFT_MASK
;
414 CC_SRC
= cc_table
[CC_OP
].compute_all() & ~(CC_O
| CC_C
);
417 T0
= (T0
<< count
) | (T0
>> (DATA_BITS
- count
));
418 CC_SRC
|= (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
420 CC_OP
= CC_OP_EFLAGS
;
425 void OPPROTO
glue(glue(op_rol
, SUFFIX
), _T0_T1
)(void)
428 count
= T1
& SHIFT_MASK
;
431 T0
= (T0
<< count
) | (T0
>> (DATA_BITS
- count
));
436 void OPPROTO
glue(glue(op_ror
, SUFFIX
), _T0_T1_cc
)(void)
439 count
= T1
& SHIFT_MASK
;
441 CC_SRC
= cc_table
[CC_OP
].compute_all() & ~(CC_O
| CC_C
);
444 T0
= (T0
>> count
) | (T0
<< (DATA_BITS
- count
));
445 CC_SRC
|= (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
446 ((T0
>> (DATA_BITS
- 1)) & CC_C
);
447 CC_OP
= CC_OP_EFLAGS
;
452 void OPPROTO
glue(glue(op_ror
, SUFFIX
), _T0_T1
)(void)
455 count
= T1
& SHIFT_MASK
;
458 T0
= (T0
>> count
) | (T0
<< (DATA_BITS
- count
));
463 void OPPROTO
glue(glue(op_rcl
, SUFFIX
), _T0_T1_cc
)(void)
465 int count
, res
, eflags
;
470 count
= rclw_table
[count
];
472 count
= rclb_table
[count
];
475 eflags
= cc_table
[CC_OP
].compute_all();
478 res
= (T0
<< count
) | ((eflags
& CC_C
) << (count
- 1));
480 res
|= T0
>> (DATA_BITS
+ 1 - count
);
482 CC_SRC
= (eflags
& ~(CC_C
| CC_O
)) |
483 (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
484 ((src
>> (DATA_BITS
- count
)) & CC_C
);
485 CC_OP
= CC_OP_EFLAGS
;
490 void OPPROTO
glue(glue(op_rcr
, SUFFIX
), _T0_T1_cc
)(void)
492 int count
, res
, eflags
;
497 count
= rclw_table
[count
];
499 count
= rclb_table
[count
];
502 eflags
= cc_table
[CC_OP
].compute_all();
505 res
= (T0
>> count
) | ((eflags
& CC_C
) << (DATA_BITS
- count
));
507 res
|= T0
<< (DATA_BITS
+ 1 - count
);
509 CC_SRC
= (eflags
& ~(CC_C
| CC_O
)) |
510 (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
511 ((src
>> (count
- 1)) & CC_C
);
512 CC_OP
= CC_OP_EFLAGS
;
517 void OPPROTO
glue(glue(op_shl
, SUFFIX
), _T0_T1_cc
)(void)
522 CC_SRC
= (DATA_TYPE
)T0
<< (count
- 1);
525 CC_OP
= CC_OP_SHLB
+ SHIFT
;
530 void OPPROTO
glue(glue(op_shl
, SUFFIX
), _T0_T1
)(void)
538 void OPPROTO
glue(glue(op_shr
, SUFFIX
), _T0_T1_cc
)(void)
544 CC_SRC
= T0
>> (count
- 1);
547 CC_OP
= CC_OP_SARB
+ SHIFT
;
552 void OPPROTO
glue(glue(op_shr
, SUFFIX
), _T0_T1
)(void)
561 void OPPROTO
glue(glue(op_sar
, SUFFIX
), _T0_T1_cc
)(void)
566 src
= (DATA_STYPE
)T0
;
567 CC_SRC
= src
>> (count
- 1);
570 CC_OP
= CC_OP_SARB
+ SHIFT
;
575 void OPPROTO
glue(glue(op_sar
, SUFFIX
), _T0_T1
)(void)
579 src
= (DATA_STYPE
)T0
;
585 /* XXX: overflow flag might be incorrect in some cases in shldw */
586 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_im_cc
)(void)
592 res
= T1
| (T0
<< 16);
593 CC_SRC
= res
>> (32 - count
);
596 res
|= T1
<< (count
- 16);
601 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_ECX_cc
)(void)
608 res
= T1
| (T0
<< 16);
609 CC_SRC
= res
>> (32 - count
);
612 res
|= T1
<< (count
- 16);
615 CC_OP
= CC_OP_SARB
+ SHIFT
;
620 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_im_cc
)(void)
626 res
= (T0
& 0xffff) | (T1
<< 16);
627 CC_SRC
= res
>> (count
- 1);
630 res
|= T1
<< (32 - count
);
636 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_ECX_cc
)(void)
643 res
= (T0
& 0xffff) | (T1
<< 16);
644 CC_SRC
= res
>> (count
- 1);
647 res
|= T1
<< (32 - count
);
650 CC_OP
= CC_OP_SARB
+ SHIFT
;
657 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_im_cc
)(void)
663 CC_SRC
= T0
<< (count
- 1);
664 T0
= (T0
<< count
) | (T1
>> (DATA_BITS
- count
));
668 void OPPROTO
glue(glue(op_shld
, SUFFIX
), _T0_T1_ECX_cc
)(void)
675 CC_SRC
= T0
<< (count
- 1);
676 T0
= (T0
<< count
) | (T1
>> (DATA_BITS
- count
));
678 CC_OP
= CC_OP_SHLB
+ SHIFT
;
683 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_im_cc
)(void)
689 CC_SRC
= T0
>> (count
- 1);
690 T0
= (T0
>> count
) | (T1
<< (DATA_BITS
- count
));
695 void OPPROTO
glue(glue(op_shrd
, SUFFIX
), _T0_T1_ECX_cc
)(void)
702 CC_SRC
= T0
>> (count
- 1);
703 T0
= (T0
>> count
) | (T1
<< (DATA_BITS
- count
));
705 CC_OP
= CC_OP_SARB
+ SHIFT
;
711 /* carry add/sub (we only need to set CC_OP differently) */
713 void OPPROTO
glue(glue(op_adc
, SUFFIX
), _T0_T1_cc
)(void)
716 cf
= cc_table
[CC_OP
].compute_c();
720 CC_OP
= CC_OP_ADDB
+ SHIFT
+ cf
* 3;
723 void OPPROTO
glue(glue(op_sbb
, SUFFIX
), _T0_T1_cc
)(void)
726 cf
= cc_table
[CC_OP
].compute_c();
730 CC_OP
= CC_OP_SUBB
+ SHIFT
+ cf
* 3;
733 void OPPROTO
glue(glue(op_cmpxchg
, SUFFIX
), _T0_T1_EAX_cc
)(void)
737 if ((DATA_TYPE
)CC_DST
== 0) {
740 EAX
= (EAX
& ~DATA_MASK
) | (T0
& DATA_MASK
);
748 void OPPROTO
glue(glue(op_bt
, SUFFIX
), _T0_T1_cc
)(void)
751 count
= T1
& SHIFT_MASK
;
752 CC_SRC
= T0
>> count
;
755 void OPPROTO
glue(glue(op_bts
, SUFFIX
), _T0_T1_cc
)(void)
758 count
= T1
& SHIFT_MASK
;
759 CC_SRC
= T0
>> count
;
763 void OPPROTO
glue(glue(op_btr
, SUFFIX
), _T0_T1_cc
)(void)
766 count
= T1
& SHIFT_MASK
;
767 CC_SRC
= T0
>> count
;
771 void OPPROTO
glue(glue(op_btc
, SUFFIX
), _T0_T1_cc
)(void)
774 count
= T1
& SHIFT_MASK
;
775 CC_SRC
= T0
>> count
;
779 void OPPROTO
glue(glue(op_bsf
, SUFFIX
), _T0_cc
)(void)
782 res
= T0
& DATA_MASK
;
785 while ((res
& 1) == 0) {
790 CC_DST
= 1; /* ZF = 1 */
792 CC_DST
= 0; /* ZF = 1 */
797 void OPPROTO
glue(glue(op_bsr
, SUFFIX
), _T0_cc
)(void)
800 res
= T0
& DATA_MASK
;
802 count
= DATA_BITS
- 1;
803 while ((res
& SIGN_MASK
) == 0) {
808 CC_DST
= 1; /* ZF = 1 */
810 CC_DST
= 0; /* ZF = 1 */
817 /* string operations */
818 /* XXX: maybe use lower level instructions to ease 16 bit / segment handling */
820 #define STRING_SUFFIX _fast
821 #define SI_ADDR (void *)ESI
822 #define DI_ADDR (void *)EDI
823 #define INC_SI() ESI += inc
824 #define INC_DI() EDI += inc
826 #define DEC_CX() ECX--
827 #include "op_string.h"
829 #define STRING_SUFFIX _a32
830 #define SI_ADDR (uint8_t *)A0 + ESI
831 #define DI_ADDR env->seg_cache[R_ES].base + EDI
832 #define INC_SI() ESI += inc
833 #define INC_DI() EDI += inc
835 #define DEC_CX() ECX--
836 #include "op_string.h"
838 #define STRING_SUFFIX _a16
839 #define SI_ADDR (uint8_t *)A0 + (ESI & 0xffff)
840 #define DI_ADDR env->seg_cache[R_ES].base + (EDI & 0xffff)
841 #define INC_SI() ESI = (ESI & ~0xffff) | ((ESI + inc) & 0xffff)
842 #define INC_DI() EDI = (EDI & ~0xffff) | ((EDI + inc) & 0xffff)
843 #define CX (ECX & 0xffff)
844 #define DEC_CX() ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff)
845 #include "op_string.h"
849 void OPPROTO
glue(glue(op_out
, SUFFIX
), _T0_T1
)(void)
851 glue(cpu_x86_out
, SUFFIX
)(env
, T0
& 0xffff, T1
& DATA_MASK
);
854 void OPPROTO
glue(glue(op_in
, SUFFIX
), _T0_T1
)(void)
856 T1
= glue(cpu_x86_in
, SUFFIX
)(env
, T0
& 0xffff);