converted bit test operations to TCG
[qemu] / target-i386 / ops_template.h
1 /*
2  *  i386 micro operations (included several times to generate
3  *  different operand sizes)
4  *
5  *  Copyright (c) 2003 Fabrice Bellard
6  *
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.
11  *
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.
16  *
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
20  */
21 #define DATA_BITS (1 << (3 + SHIFT))
22 #define SHIFT_MASK (DATA_BITS - 1)
23 #define SIGN_MASK (((target_ulong)1) << (DATA_BITS - 1))
24 #if DATA_BITS <= 32
25 #define SHIFT1_MASK 0x1f
26 #else
27 #define SHIFT1_MASK 0x3f
28 #endif
29
30 #if DATA_BITS == 8
31 #define SUFFIX b
32 #define DATA_TYPE uint8_t
33 #define DATA_STYPE int8_t
34 #define DATA_MASK 0xff
35 #elif DATA_BITS == 16
36 #define SUFFIX w
37 #define DATA_TYPE uint16_t
38 #define DATA_STYPE int16_t
39 #define DATA_MASK 0xffff
40 #elif DATA_BITS == 32
41 #define SUFFIX l
42 #define DATA_TYPE uint32_t
43 #define DATA_STYPE int32_t
44 #define DATA_MASK 0xffffffff
45 #elif DATA_BITS == 64
46 #define SUFFIX q
47 #define DATA_TYPE uint64_t
48 #define DATA_STYPE int64_t
49 #define DATA_MASK 0xffffffffffffffffULL
50 #else
51 #error unhandled operand size
52 #endif
53
54 /* various optimized jumps cases */
55
56 void OPPROTO glue(op_jb_sub, SUFFIX)(void)
57 {
58     target_long src1, src2;
59     src1 = CC_DST + CC_SRC;
60     src2 = CC_SRC;
61
62     if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
63         GOTO_LABEL_PARAM(1);
64     FORCE_RET();
65 }
66
67 void OPPROTO glue(op_jz_sub, SUFFIX)(void)
68 {
69     if ((DATA_TYPE)CC_DST == 0)
70         GOTO_LABEL_PARAM(1);
71     FORCE_RET();
72 }
73
74 void OPPROTO glue(op_jnz_sub, SUFFIX)(void)
75 {
76     if ((DATA_TYPE)CC_DST != 0)
77         GOTO_LABEL_PARAM(1);
78     FORCE_RET();
79 }
80
81 void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
82 {
83     target_long src1, src2;
84     src1 = CC_DST + CC_SRC;
85     src2 = CC_SRC;
86
87     if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
88         GOTO_LABEL_PARAM(1);
89     FORCE_RET();
90 }
91
92 void OPPROTO glue(op_js_sub, SUFFIX)(void)
93 {
94     if (CC_DST & SIGN_MASK)
95         GOTO_LABEL_PARAM(1);
96     FORCE_RET();
97 }
98
99 void OPPROTO glue(op_jl_sub, SUFFIX)(void)
100 {
101     target_long src1, src2;
102     src1 = CC_DST + CC_SRC;
103     src2 = CC_SRC;
104
105     if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
106         GOTO_LABEL_PARAM(1);
107     FORCE_RET();
108 }
109
110 void OPPROTO glue(op_jle_sub, SUFFIX)(void)
111 {
112     target_long src1, src2;
113     src1 = CC_DST + CC_SRC;
114     src2 = CC_SRC;
115
116     if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
117         GOTO_LABEL_PARAM(1);
118     FORCE_RET();
119 }
120
121 /* oldies */
122
123 #if DATA_BITS >= 16
124
125 void OPPROTO glue(op_loopnz, SUFFIX)(void)
126 {
127     if ((DATA_TYPE)ECX != 0 && !(T0 & CC_Z))
128         GOTO_LABEL_PARAM(1);
129     FORCE_RET();
130 }
131
132 void OPPROTO glue(op_loopz, SUFFIX)(void)
133 {
134     if ((DATA_TYPE)ECX != 0 && (T0 & CC_Z))
135         GOTO_LABEL_PARAM(1);
136     FORCE_RET();
137 }
138
139 void OPPROTO glue(op_jz_ecx, SUFFIX)(void)
140 {
141     if ((DATA_TYPE)ECX == 0)
142         GOTO_LABEL_PARAM(1);
143     FORCE_RET();
144 }
145
146 void OPPROTO glue(op_jnz_ecx, SUFFIX)(void)
147 {
148     if ((DATA_TYPE)ECX != 0)
149         GOTO_LABEL_PARAM(1);
150     FORCE_RET();
151 }
152
153 #endif
154
155 /* various optimized set cases */
156
157 void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
158 {
159     target_long src1, src2;
160     src1 = CC_DST + CC_SRC;
161     src2 = CC_SRC;
162
163     T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
164 }
165
166 void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
167 {
168     T0 = ((DATA_TYPE)CC_DST == 0);
169 }
170
171 void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
172 {
173     target_long src1, src2;
174     src1 = CC_DST + CC_SRC;
175     src2 = CC_SRC;
176
177     T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
178 }
179
180 void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
181 {
182     T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
183 }
184
185 void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
186 {
187     target_long src1, src2;
188     src1 = CC_DST + CC_SRC;
189     src2 = CC_SRC;
190
191     T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
192 }
193
194 void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
195 {
196     target_long src1, src2;
197     src1 = CC_DST + CC_SRC;
198     src2 = CC_SRC;
199
200     T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
201 }
202
203 /* bit operations */
204 #if DATA_BITS >= 16
205
206 void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
207 {
208     int count;
209     target_long res;
210
211     res = T0 & DATA_MASK;
212     if (res != 0) {
213         count = 0;
214         while ((res & 1) == 0) {
215             count++;
216             res >>= 1;
217         }
218         T1 = count;
219         CC_DST = 1; /* ZF = 0 */
220     } else {
221         CC_DST = 0; /* ZF = 1 */
222     }
223     FORCE_RET();
224 }
225
226 void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
227 {
228     int count;
229     target_long res;
230
231     res = T0 & DATA_MASK;
232     if (res != 0) {
233         count = DATA_BITS - 1;
234         while ((res & SIGN_MASK) == 0) {
235             count--;
236             res <<= 1;
237         }
238         T1 = count;
239         CC_DST = 1; /* ZF = 0 */
240     } else {
241         CC_DST = 0; /* ZF = 1 */
242     }
243     FORCE_RET();
244 }
245
246 #endif
247
248 /* string operations */
249
250 void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void)
251 {
252     T0 = DF << SHIFT;
253 }
254
255 #undef DATA_BITS
256 #undef SHIFT_MASK
257 #undef SHIFT1_MASK
258 #undef SIGN_MASK
259 #undef DATA_TYPE
260 #undef DATA_STYPE
261 #undef DATA_MASK
262 #undef SUFFIX