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
;
96 src1
= CC_DST
+ CC_SRC
;
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)
110 src1
= CC_DST
+ CC_SRC
;
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
;
120 src1
= CC_DST
+ CC_SRC
+ 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)
134 src1
= CC_DST
+ CC_SRC
+ 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
;
233 static int glue(compute_c_mul
, SUFFIX
)(void)
241 /* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
242 CF are modified and it is slower to do that. */
243 static int glue(compute_all_mul
, SUFFIX
)(void)
245 int cf
, pf
, af
, zf
, sf
, of
;
247 pf
= parity_table
[(uint8_t)CC_DST
];
248 af
= 0; /* undefined */
249 zf
= ((DATA_TYPE
)CC_DST
== 0) << 6;
250 sf
= lshift(CC_DST
, 8 - DATA_BITS
) & 0x80;
252 return cf
| pf
| af
| zf
| sf
| of
;
255 /* various optimized jumps cases */
257 void OPPROTO
glue(op_jb_sub
, SUFFIX
)(void)
260 src1
= CC_DST
+ CC_SRC
;
263 if ((DATA_TYPE
)src1
< (DATA_TYPE
)src2
)
264 JUMP_TB(glue(op_jb_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
266 JUMP_TB(glue(op_jb_sub
, SUFFIX
), PARAM1
, 1, PARAM3
);
270 void OPPROTO
glue(op_jz_sub
, SUFFIX
)(void)
272 if ((DATA_TYPE
)CC_DST
== 0)
273 JUMP_TB(glue(op_jz_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
275 JUMP_TB(glue(op_jz_sub
, SUFFIX
), PARAM1
, 1, PARAM3
);
279 void OPPROTO
glue(op_jbe_sub
, SUFFIX
)(void)
282 src1
= CC_DST
+ CC_SRC
;
285 if ((DATA_TYPE
)src1
<= (DATA_TYPE
)src2
)
286 JUMP_TB(glue(op_jbe_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
288 JUMP_TB(glue(op_jbe_sub
, SUFFIX
), PARAM1
, 1, PARAM3
);
292 void OPPROTO
glue(op_js_sub
, SUFFIX
)(void)
294 if (CC_DST
& SIGN_MASK
)
295 JUMP_TB(glue(op_js_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
297 JUMP_TB(glue(op_js_sub
, SUFFIX
), PARAM1
, 1, PARAM3
);
301 void OPPROTO
glue(op_jl_sub
, SUFFIX
)(void)
304 src1
= CC_DST
+ CC_SRC
;
307 if ((DATA_STYPE
)src1
< (DATA_STYPE
)src2
)
308 JUMP_TB(glue(op_jl_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
310 JUMP_TB(glue(op_jl_sub
, SUFFIX
), PARAM1
, 1, PARAM3
);
314 void OPPROTO
glue(op_jle_sub
, SUFFIX
)(void)
317 src1
= CC_DST
+ CC_SRC
;
320 if ((DATA_STYPE
)src1
<= (DATA_STYPE
)src2
)
321 JUMP_TB(glue(op_jle_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
323 JUMP_TB(glue(op_jle_sub
, SUFFIX
), PARAM1
, 1, PARAM3
);
331 void OPPROTO
glue(op_loopnz
, SUFFIX
)(void)
335 eflags
= cc_table
[CC_OP
].compute_all();
336 tmp
= (ECX
- 1) & DATA_MASK
;
337 ECX
= (ECX
& ~DATA_MASK
) | tmp
;
338 if (tmp
!= 0 && !(eflags
& CC_Z
))
345 void OPPROTO
glue(op_loopz
, SUFFIX
)(void)
349 eflags
= cc_table
[CC_OP
].compute_all();
350 tmp
= (ECX
- 1) & DATA_MASK
;
351 ECX
= (ECX
& ~DATA_MASK
) | tmp
;
352 if (tmp
!= 0 && (eflags
& CC_Z
))
359 void OPPROTO
glue(op_loop
, SUFFIX
)(void)
362 tmp
= (ECX
- 1) & DATA_MASK
;
363 ECX
= (ECX
& ~DATA_MASK
) | tmp
;
371 void OPPROTO
glue(op_jecxz
, SUFFIX
)(void)
373 if ((DATA_TYPE
)ECX
== 0)
382 /* various optimized set cases */
384 void OPPROTO
glue(op_setb_T0_sub
, SUFFIX
)(void)
387 src1
= CC_DST
+ CC_SRC
;
390 T0
= ((DATA_TYPE
)src1
< (DATA_TYPE
)src2
);
393 void OPPROTO
glue(op_setz_T0_sub
, SUFFIX
)(void)
395 T0
= ((DATA_TYPE
)CC_DST
== 0);
398 void OPPROTO
glue(op_setbe_T0_sub
, SUFFIX
)(void)
401 src1
= CC_DST
+ CC_SRC
;
404 T0
= ((DATA_TYPE
)src1
<= (DATA_TYPE
)src2
);
407 void OPPROTO
glue(op_sets_T0_sub
, SUFFIX
)(void)
409 T0
= lshift(CC_DST
, -(DATA_BITS
- 1)) & 1;
412 void OPPROTO
glue(op_setl_T0_sub
, SUFFIX
)(void)
415 src1
= CC_DST
+ CC_SRC
;
418 T0
= ((DATA_STYPE
)src1
< (DATA_STYPE
)src2
);
421 void OPPROTO
glue(op_setle_T0_sub
, SUFFIX
)(void)
424 src1
= CC_DST
+ CC_SRC
;
427 T0
= ((DATA_STYPE
)src1
<= (DATA_STYPE
)src2
);
432 void OPPROTO
glue(glue(op_shl
, SUFFIX
), _T0_T1
)(void)
440 void OPPROTO
glue(glue(op_shr
, SUFFIX
), _T0_T1
)(void)
449 void OPPROTO
glue(glue(op_sar
, SUFFIX
), _T0_T1
)(void)
453 src
= (DATA_STYPE
)T0
;
459 #include "ops_template_mem.h"
462 #include "ops_template_mem.h"
467 void OPPROTO
glue(glue(op_bt
, SUFFIX
), _T0_T1_cc
)(void)
470 count
= T1
& SHIFT_MASK
;
471 CC_SRC
= T0
>> count
;
474 void OPPROTO
glue(glue(op_bts
, SUFFIX
), _T0_T1_cc
)(void)
477 count
= T1
& SHIFT_MASK
;
482 void OPPROTO
glue(glue(op_btr
, SUFFIX
), _T0_T1_cc
)(void)
485 count
= T1
& SHIFT_MASK
;
490 void OPPROTO
glue(glue(op_btc
, SUFFIX
), _T0_T1_cc
)(void)
493 count
= T1
& SHIFT_MASK
;
498 void OPPROTO
glue(glue(op_bsf
, SUFFIX
), _T0_cc
)(void)
501 res
= T0
& DATA_MASK
;
504 while ((res
& 1) == 0) {
509 CC_DST
= 1; /* ZF = 1 */
511 CC_DST
= 0; /* ZF = 1 */
516 void OPPROTO
glue(glue(op_bsr
, SUFFIX
), _T0_cc
)(void)
519 res
= T0
& DATA_MASK
;
521 count
= DATA_BITS
- 1;
522 while ((res
& SIGN_MASK
) == 0) {
527 CC_DST
= 1; /* ZF = 1 */
529 CC_DST
= 0; /* ZF = 1 */
537 void OPPROTO
op_update_bt_cc(void)
543 /* string operations */
545 void OPPROTO
glue(op_movl_T0_Dshift
, SUFFIX
)(void)
550 void OPPROTO
glue(op_string_jz_sub
, SUFFIX
)(void)
552 if ((DATA_TYPE
)CC_DST
== 0)
553 JUMP_TB2(glue(op_string_jz_sub
, SUFFIX
), PARAM1
, 1);
557 void OPPROTO
glue(op_string_jnz_sub
, SUFFIX
)(void)
559 if ((DATA_TYPE
)CC_DST
!= 0)
560 JUMP_TB2(glue(op_string_jnz_sub
, SUFFIX
), PARAM1
, 1);
564 void OPPROTO
glue(glue(op_string_jz_sub
, SUFFIX
), _im
)(void)
566 if ((DATA_TYPE
)CC_DST
== 0) {
568 if (env
->eflags
& TF_MASK
) {
569 raise_exception(EXCP01_SSTP
);
577 void OPPROTO
glue(glue(op_string_jnz_sub
, SUFFIX
), _im
)(void)
579 if ((DATA_TYPE
)CC_DST
!= 0) {
581 if (env
->eflags
& TF_MASK
) {
582 raise_exception(EXCP01_SSTP
);
591 void OPPROTO
glue(op_jz_ecx
, SUFFIX
)(void)
593 if ((DATA_TYPE
)ECX
== 0)
594 JUMP_TB(glue(op_jz_ecx
, SUFFIX
), PARAM1
, 1, PARAM2
);
598 void OPPROTO
glue(glue(op_jz_ecx
, SUFFIX
), _im
)(void)
600 if ((DATA_TYPE
)ECX
== 0) {
602 if (env
->eflags
& TF_MASK
) {
603 raise_exception(EXCP01_SSTP
);
614 void OPPROTO
glue(glue(op_out
, SUFFIX
), _T0_T1
)(void)
616 glue(cpu_x86_out
, SUFFIX
)(env
, T0
& 0xffff, T1
& DATA_MASK
);
619 void OPPROTO
glue(glue(op_in
, SUFFIX
), _T0_T1
)(void)
621 T1
= glue(cpu_x86_in
, SUFFIX
)(env
, T0
& 0xffff);
624 void OPPROTO
glue(glue(op_in
, SUFFIX
), _DX_T0
)(void)
626 T0
= glue(cpu_x86_in
, SUFFIX
)(env
, EDX
& 0xffff);
629 void OPPROTO
glue(glue(op_out
, SUFFIX
), _DX_T0
)(void)
631 glue(cpu_x86_out
, SUFFIX
)(env
, EDX
& 0xffff, T0
);
634 void OPPROTO
glue(glue(op_check_io
, SUFFIX
), _T0
)(void)
636 glue(glue(check_io
, SUFFIX
), _T0
)();
639 void OPPROTO
glue(glue(op_check_io
, SUFFIX
), _DX
)(void)
641 glue(glue(check_io
, SUFFIX
), _DX
)();