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
26 #define MEM_SUFFIX b_raw
28 #define MEM_SUFFIX w_raw
30 #define MEM_SUFFIX l_raw
32 #define MEM_SUFFIX q_raw
38 #define MEM_SUFFIX b_kernel
40 #define MEM_SUFFIX w_kernel
42 #define MEM_SUFFIX l_kernel
44 #define MEM_SUFFIX q_kernel
50 #define MEM_SUFFIX b_user
52 #define MEM_SUFFIX w_user
54 #define MEM_SUFFIX l_user
56 #define MEM_SUFFIX q_user
61 #error invalid MEM_WRITE
67 #define MEM_SUFFIX SUFFIX
71 void OPPROTO
glue(glue(op_rol
, MEM_SUFFIX
), _T0_T1_cc
)(void)
76 if (T1
& SHIFT1_MASK
) {
77 count
= T1
& SHIFT_MASK
;
80 T0
= (T0
<< count
) | (T0
>> (DATA_BITS
- count
));
82 glue(st
, MEM_SUFFIX
)(A0
, T0
);
84 /* gcc 3.2 workaround. This is really a bug in gcc. */
85 asm volatile("" : : "r" (T0
));
87 CC_SRC
= (cc_table
[CC_OP
].compute_all() & ~(CC_O
| CC_C
)) |
88 (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
95 void OPPROTO
glue(glue(op_ror
, MEM_SUFFIX
), _T0_T1_cc
)(void)
100 if (T1
& SHIFT1_MASK
) {
101 count
= T1
& SHIFT_MASK
;
104 T0
= (T0
>> count
) | (T0
<< (DATA_BITS
- count
));
106 glue(st
, MEM_SUFFIX
)(A0
, T0
);
108 /* gcc 3.2 workaround. This is really a bug in gcc. */
109 asm volatile("" : : "r" (T0
));
111 CC_SRC
= (cc_table
[CC_OP
].compute_all() & ~(CC_O
| CC_C
)) |
112 (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
113 ((T0
>> (DATA_BITS
- 1)) & CC_C
);
114 CC_OP
= CC_OP_EFLAGS
;
119 void OPPROTO
glue(glue(op_rol
, MEM_SUFFIX
), _T0_T1
)(void)
122 count
= T1
& SHIFT_MASK
;
125 T0
= (T0
<< count
) | (T0
>> (DATA_BITS
- count
));
127 glue(st
, MEM_SUFFIX
)(A0
, T0
);
133 void OPPROTO
glue(glue(op_ror
, MEM_SUFFIX
), _T0_T1
)(void)
136 count
= T1
& SHIFT_MASK
;
139 T0
= (T0
>> count
) | (T0
<< (DATA_BITS
- count
));
141 glue(st
, MEM_SUFFIX
)(A0
, T0
);
147 void OPPROTO
glue(glue(op_rcl
, MEM_SUFFIX
), _T0_T1_cc
)(void)
153 count
= T1
& SHIFT1_MASK
;
155 count
= rclw_table
[count
];
157 count
= rclb_table
[count
];
160 eflags
= cc_table
[CC_OP
].compute_all();
163 res
= (T0
<< count
) | ((target_ulong
)(eflags
& CC_C
) << (count
- 1));
165 res
|= T0
>> (DATA_BITS
+ 1 - count
);
168 glue(st
, MEM_SUFFIX
)(A0
, T0
);
170 CC_SRC
= (eflags
& ~(CC_C
| CC_O
)) |
171 (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
172 ((src
>> (DATA_BITS
- count
)) & CC_C
);
173 CC_OP
= CC_OP_EFLAGS
;
178 void OPPROTO
glue(glue(op_rcr
, MEM_SUFFIX
), _T0_T1_cc
)(void)
184 count
= T1
& SHIFT1_MASK
;
186 count
= rclw_table
[count
];
188 count
= rclb_table
[count
];
191 eflags
= cc_table
[CC_OP
].compute_all();
194 res
= (T0
>> count
) | ((target_ulong
)(eflags
& CC_C
) << (DATA_BITS
- count
));
196 res
|= T0
<< (DATA_BITS
+ 1 - count
);
199 glue(st
, MEM_SUFFIX
)(A0
, T0
);
201 CC_SRC
= (eflags
& ~(CC_C
| CC_O
)) |
202 (lshift(src
^ T0
, 11 - (DATA_BITS
- 1)) & CC_O
) |
203 ((src
>> (count
- 1)) & CC_C
);
204 CC_OP
= CC_OP_EFLAGS
;
209 void OPPROTO
glue(glue(op_shl
, MEM_SUFFIX
), _T0_T1_cc
)(void)
214 count
= T1
& SHIFT1_MASK
;
216 src
= (DATA_TYPE
)T0
<< (count
- 1);
219 glue(st
, MEM_SUFFIX
)(A0
, T0
);
223 CC_OP
= CC_OP_SHLB
+ SHIFT
;
228 void OPPROTO
glue(glue(op_shr
, MEM_SUFFIX
), _T0_T1_cc
)(void)
233 count
= T1
& SHIFT1_MASK
;
236 src
= T0
>> (count
- 1);
239 glue(st
, MEM_SUFFIX
)(A0
, T0
);
243 CC_OP
= CC_OP_SARB
+ SHIFT
;
248 void OPPROTO
glue(glue(op_sar
, MEM_SUFFIX
), _T0_T1_cc
)(void)
253 count
= T1
& SHIFT1_MASK
;
255 src
= (DATA_STYPE
)T0
;
257 src
= src
>> (count
- 1);
259 glue(st
, MEM_SUFFIX
)(A0
, T0
);
263 CC_OP
= CC_OP_SARB
+ SHIFT
;
269 /* XXX: overflow flag might be incorrect in some cases in shldw */
270 void OPPROTO
glue(glue(op_shld
, MEM_SUFFIX
), _T0_T1_im_cc
)(void)
273 unsigned int res
, tmp
;
276 res
= T1
| (T0
<< 16);
277 tmp
= res
>> (32 - count
);
280 res
|= T1
<< (count
- 16);
283 glue(st
, MEM_SUFFIX
)(A0
, T0
);
289 void OPPROTO
glue(glue(op_shld
, MEM_SUFFIX
), _T0_T1_ECX_cc
)(void)
292 unsigned int res
, tmp
;
296 res
= T1
| (T0
<< 16);
297 tmp
= res
>> (32 - count
);
300 res
|= T1
<< (count
- 16);
303 glue(st
, MEM_SUFFIX
)(A0
, T0
);
307 CC_OP
= CC_OP_SARB
+ SHIFT
;
312 void OPPROTO
glue(glue(op_shrd
, MEM_SUFFIX
), _T0_T1_im_cc
)(void)
315 unsigned int res
, tmp
;
318 res
= (T0
& 0xffff) | (T1
<< 16);
319 tmp
= res
>> (count
- 1);
322 res
|= T1
<< (32 - count
);
325 glue(st
, MEM_SUFFIX
)(A0
, T0
);
332 void OPPROTO
glue(glue(op_shrd
, MEM_SUFFIX
), _T0_T1_ECX_cc
)(void)
335 unsigned int res
, tmp
;
339 res
= (T0
& 0xffff) | (T1
<< 16);
340 tmp
= res
>> (count
- 1);
343 res
|= T1
<< (32 - count
);
346 glue(st
, MEM_SUFFIX
)(A0
, T0
);
350 CC_OP
= CC_OP_SARB
+ SHIFT
;
357 void OPPROTO
glue(glue(op_shld
, MEM_SUFFIX
), _T0_T1_im_cc
)(void)
365 tmp
= T0
<< (count
- 1);
366 T0
= (T0
<< count
) | (T1
>> (DATA_BITS
- count
));
368 glue(st
, MEM_SUFFIX
)(A0
, T0
);
374 void OPPROTO
glue(glue(op_shld
, MEM_SUFFIX
), _T0_T1_ECX_cc
)(void)
379 count
= ECX
& SHIFT1_MASK
;
383 tmp
= T0
<< (count
- 1);
384 T0
= (T0
<< count
) | (T1
>> (DATA_BITS
- count
));
386 glue(st
, MEM_SUFFIX
)(A0
, T0
);
390 CC_OP
= CC_OP_SHLB
+ SHIFT
;
395 void OPPROTO
glue(glue(op_shrd
, MEM_SUFFIX
), _T0_T1_im_cc
)(void)
403 tmp
= T0
>> (count
- 1);
404 T0
= (T0
>> count
) | (T1
<< (DATA_BITS
- count
));
406 glue(st
, MEM_SUFFIX
)(A0
, T0
);
413 void OPPROTO
glue(glue(op_shrd
, MEM_SUFFIX
), _T0_T1_ECX_cc
)(void)
418 count
= ECX
& SHIFT1_MASK
;
422 tmp
= T0
>> (count
- 1);
423 T0
= (T0
>> count
) | (T1
<< (DATA_BITS
- count
));
425 glue(st
, MEM_SUFFIX
)(A0
, T0
);
429 CC_OP
= CC_OP_SARB
+ SHIFT
;
435 /* carry add/sub (we only need to set CC_OP differently) */
437 void OPPROTO
glue(glue(op_adc
, MEM_SUFFIX
), _T0_T1_cc
)(void)
440 cf
= cc_table
[CC_OP
].compute_c();
443 glue(st
, MEM_SUFFIX
)(A0
, T0
);
447 CC_OP
= CC_OP_ADDB
+ SHIFT
+ cf
* 4;
450 void OPPROTO
glue(glue(op_sbb
, MEM_SUFFIX
), _T0_T1_cc
)(void)
453 cf
= cc_table
[CC_OP
].compute_c();
456 glue(st
, MEM_SUFFIX
)(A0
, T0
);
460 CC_OP
= CC_OP_SUBB
+ SHIFT
+ cf
* 4;
463 void OPPROTO
glue(glue(op_cmpxchg
, MEM_SUFFIX
), _T0_T1_EAX_cc
)(void)
465 target_ulong src
, dst
;
469 if ((DATA_TYPE
)dst
== 0) {
472 glue(st
, MEM_SUFFIX
)(A0
, T0
);
475 EAX
= (EAX
& ~DATA_MASK
) | (T0
& DATA_MASK
);