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
;
232 /* various optimized jumps cases */
234 void OPPROTO
glue(op_jb_sub
, SUFFIX
)(void)
237 src1
= CC_DST
+ CC_SRC
;
240 if ((DATA_TYPE
)src1
< (DATA_TYPE
)src2
)
241 JUMP_TB(glue(op_jb_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
243 JUMP_TB(glue(op_jb_sub
, SUFFIX
), PARAM1
, 1, PARAM3
);
247 void OPPROTO
glue(op_jz_sub
, SUFFIX
)(void)
249 if ((DATA_TYPE
)CC_DST
== 0)
250 JUMP_TB(glue(op_jz_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
252 JUMP_TB(glue(op_jz_sub
, SUFFIX
), PARAM1
, 1, PARAM3
);
256 void OPPROTO
glue(op_jbe_sub
, SUFFIX
)(void)
259 src1
= CC_DST
+ CC_SRC
;
262 if ((DATA_TYPE
)src1
<= (DATA_TYPE
)src2
)
263 JUMP_TB(glue(op_jbe_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
265 JUMP_TB(glue(op_jbe_sub
, SUFFIX
), PARAM1
, 1, PARAM3
);
269 void OPPROTO
glue(op_js_sub
, SUFFIX
)(void)
271 if (CC_DST
& SIGN_MASK
)
272 JUMP_TB(glue(op_js_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
274 JUMP_TB(glue(op_js_sub
, SUFFIX
), PARAM1
, 1, PARAM3
);
278 void OPPROTO
glue(op_jl_sub
, SUFFIX
)(void)
281 src1
= CC_DST
+ CC_SRC
;
284 if ((DATA_STYPE
)src1
< (DATA_STYPE
)src2
)
285 JUMP_TB(glue(op_jl_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
287 JUMP_TB(glue(op_jl_sub
, SUFFIX
), PARAM1
, 1, PARAM3
);
291 void OPPROTO
glue(op_jle_sub
, SUFFIX
)(void)
294 src1
= CC_DST
+ CC_SRC
;
297 if ((DATA_STYPE
)src1
<= (DATA_STYPE
)src2
)
298 JUMP_TB(glue(op_jle_sub
, SUFFIX
), PARAM1
, 0, PARAM2
);
300 JUMP_TB(glue(op_jle_sub
, SUFFIX
), 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)
364 src1
= CC_DST
+ CC_SRC
;
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)
378 src1
= CC_DST
+ CC_SRC
;
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)
392 src1
= CC_DST
+ CC_SRC
;
395 T0
= ((DATA_STYPE
)src1
< (DATA_STYPE
)src2
);
398 void OPPROTO
glue(op_setle_T0_sub
, SUFFIX
)(void)
401 src1
= CC_DST
+ CC_SRC
;
404 T0
= ((DATA_STYPE
)src1
<= (DATA_STYPE
)src2
);
409 void OPPROTO
glue(glue(op_shl
, SUFFIX
), _T0_T1
)(void)
417 void OPPROTO
glue(glue(op_shr
, SUFFIX
), _T0_T1
)(void)
426 void OPPROTO
glue(glue(op_sar
, SUFFIX
), _T0_T1
)(void)
430 src
= (DATA_STYPE
)T0
;
436 #include "ops_template_mem.h"
439 #include "ops_template_mem.h"
444 void OPPROTO
glue(glue(op_bt
, SUFFIX
), _T0_T1_cc
)(void)
447 count
= T1
& SHIFT_MASK
;
448 CC_SRC
= T0
>> count
;
451 void OPPROTO
glue(glue(op_bts
, SUFFIX
), _T0_T1_cc
)(void)
454 count
= T1
& SHIFT_MASK
;
459 void OPPROTO
glue(glue(op_btr
, SUFFIX
), _T0_T1_cc
)(void)
462 count
= T1
& SHIFT_MASK
;
467 void OPPROTO
glue(glue(op_btc
, SUFFIX
), _T0_T1_cc
)(void)
470 count
= T1
& SHIFT_MASK
;
475 void OPPROTO
glue(glue(op_bsf
, SUFFIX
), _T0_cc
)(void)
478 res
= T0
& DATA_MASK
;
481 while ((res
& 1) == 0) {
486 CC_DST
= 1; /* ZF = 1 */
488 CC_DST
= 0; /* ZF = 1 */
493 void OPPROTO
glue(glue(op_bsr
, SUFFIX
), _T0_cc
)(void)
496 res
= T0
& DATA_MASK
;
498 count
= DATA_BITS
- 1;
499 while ((res
& SIGN_MASK
) == 0) {
504 CC_DST
= 1; /* ZF = 1 */
506 CC_DST
= 0; /* ZF = 1 */
514 void OPPROTO
op_update_bt_cc(void)
520 /* string operations */
522 void OPPROTO
glue(op_movl_T0_Dshift
, SUFFIX
)(void)
527 void OPPROTO
glue(op_string_jz_sub
, SUFFIX
)(void)
529 if ((DATA_TYPE
)CC_DST
== 0)
530 JUMP_TB2(glue(op_string_jz_sub
, SUFFIX
), PARAM1
, 1);
534 void OPPROTO
glue(op_string_jnz_sub
, SUFFIX
)(void)
536 if ((DATA_TYPE
)CC_DST
!= 0)
537 JUMP_TB2(glue(op_string_jnz_sub
, SUFFIX
), PARAM1
, 1);
541 void OPPROTO
glue(glue(op_string_jz_sub
, SUFFIX
), _im
)(void)
543 if ((DATA_TYPE
)CC_DST
== 0) {
545 if (env
->eflags
& TF_MASK
) {
546 raise_exception(EXCP01_SSTP
);
554 void OPPROTO
glue(glue(op_string_jnz_sub
, SUFFIX
), _im
)(void)
556 if ((DATA_TYPE
)CC_DST
!= 0) {
558 if (env
->eflags
& TF_MASK
) {
559 raise_exception(EXCP01_SSTP
);
568 void OPPROTO
glue(op_jz_ecx
, SUFFIX
)(void)
570 if ((DATA_TYPE
)ECX
== 0)
571 JUMP_TB(glue(op_jz_ecx
, SUFFIX
), PARAM1
, 1, PARAM2
);
575 void OPPROTO
glue(glue(op_jz_ecx
, SUFFIX
), _im
)(void)
577 if ((DATA_TYPE
)ECX
== 0) {
579 if (env
->eflags
& TF_MASK
) {
580 raise_exception(EXCP01_SSTP
);
591 void OPPROTO
glue(glue(op_out
, SUFFIX
), _T0_T1
)(void)
593 glue(cpu_x86_out
, SUFFIX
)(env
, T0
& 0xffff, T1
& DATA_MASK
);
596 void OPPROTO
glue(glue(op_in
, SUFFIX
), _T0_T1
)(void)
598 T1
= glue(cpu_x86_in
, SUFFIX
)(env
, T0
& 0xffff);
601 void OPPROTO
glue(glue(op_in
, SUFFIX
), _DX_T0
)(void)
603 T0
= glue(cpu_x86_in
, SUFFIX
)(env
, EDX
& 0xffff);
606 void OPPROTO
glue(glue(op_out
, SUFFIX
), _DX_T0
)(void)
608 glue(cpu_x86_out
, SUFFIX
)(env
, EDX
& 0xffff, T0
);