]>
Commit | Line | Data |
---|---|---|
e477b8b8 FB |
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 | #ifdef MEM_WRITE | |
22 | ||
23 | #if DATA_BITS == 8 | |
24 | #define MEM_SUFFIX b_mem | |
25 | #elif DATA_BITS == 16 | |
26 | #define MEM_SUFFIX w_mem | |
27 | #elif DATA_BITS == 32 | |
28 | #define MEM_SUFFIX l_mem | |
29 | #endif | |
30 | ||
31 | #else | |
32 | ||
33 | #define MEM_SUFFIX SUFFIX | |
34 | ||
35 | #endif | |
36 | ||
37 | void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1_cc)(void) | |
38 | { | |
39 | int count, src; | |
40 | count = T1 & SHIFT_MASK; | |
41 | if (count) { | |
42 | src = T0; | |
43 | T0 &= DATA_MASK; | |
44 | T0 = (T0 << count) | (T0 >> (DATA_BITS - count)); | |
45 | #ifdef MEM_WRITE | |
46 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
47 | #endif | |
48 | CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) | | |
49 | (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
50 | (T0 & CC_C); | |
51 | CC_OP = CC_OP_EFLAGS; | |
52 | } | |
53 | FORCE_RET(); | |
54 | } | |
55 | ||
56 | void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1_cc)(void) | |
57 | { | |
58 | int count, src; | |
59 | count = T1 & SHIFT_MASK; | |
60 | if (count) { | |
61 | src = T0; | |
62 | T0 &= DATA_MASK; | |
63 | T0 = (T0 >> count) | (T0 << (DATA_BITS - count)); | |
64 | #ifdef MEM_WRITE | |
65 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
66 | #endif | |
67 | CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) | | |
68 | (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
69 | ((T0 >> (DATA_BITS - 1)) & CC_C); | |
70 | CC_OP = CC_OP_EFLAGS; | |
71 | } | |
72 | FORCE_RET(); | |
73 | } | |
74 | ||
75 | void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1)(void) | |
76 | { | |
77 | int count; | |
78 | count = T1 & SHIFT_MASK; | |
79 | if (count) { | |
80 | T0 &= DATA_MASK; | |
81 | T0 = (T0 << count) | (T0 >> (DATA_BITS - count)); | |
82 | #ifdef MEM_WRITE | |
83 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
84 | #endif | |
85 | } | |
86 | FORCE_RET(); | |
87 | } | |
88 | ||
89 | void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1)(void) | |
90 | { | |
91 | int count; | |
92 | count = T1 & SHIFT_MASK; | |
93 | if (count) { | |
94 | T0 &= DATA_MASK; | |
95 | T0 = (T0 >> count) | (T0 << (DATA_BITS - count)); | |
96 | #ifdef MEM_WRITE | |
97 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
98 | #endif | |
99 | } | |
100 | FORCE_RET(); | |
101 | } | |
102 | ||
103 | void OPPROTO glue(glue(op_rcl, MEM_SUFFIX), _T0_T1_cc)(void) | |
104 | { | |
105 | int count, res, eflags; | |
106 | unsigned int src; | |
107 | ||
108 | count = T1 & 0x1f; | |
109 | #if DATA_BITS == 16 | |
110 | count = rclw_table[count]; | |
111 | #elif DATA_BITS == 8 | |
112 | count = rclb_table[count]; | |
113 | #endif | |
114 | if (count) { | |
115 | eflags = cc_table[CC_OP].compute_all(); | |
116 | T0 &= DATA_MASK; | |
117 | src = T0; | |
118 | res = (T0 << count) | ((eflags & CC_C) << (count - 1)); | |
119 | if (count > 1) | |
120 | res |= T0 >> (DATA_BITS + 1 - count); | |
121 | T0 = res; | |
122 | #ifdef MEM_WRITE | |
123 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
124 | #endif | |
125 | CC_SRC = (eflags & ~(CC_C | CC_O)) | | |
126 | (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
127 | ((src >> (DATA_BITS - count)) & CC_C); | |
128 | CC_OP = CC_OP_EFLAGS; | |
129 | } | |
130 | FORCE_RET(); | |
131 | } | |
132 | ||
133 | void OPPROTO glue(glue(op_rcr, MEM_SUFFIX), _T0_T1_cc)(void) | |
134 | { | |
135 | int count, res, eflags; | |
136 | unsigned int src; | |
137 | ||
138 | count = T1 & 0x1f; | |
139 | #if DATA_BITS == 16 | |
140 | count = rclw_table[count]; | |
141 | #elif DATA_BITS == 8 | |
142 | count = rclb_table[count]; | |
143 | #endif | |
144 | if (count) { | |
145 | eflags = cc_table[CC_OP].compute_all(); | |
146 | T0 &= DATA_MASK; | |
147 | src = T0; | |
148 | res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count)); | |
149 | if (count > 1) | |
150 | res |= T0 << (DATA_BITS + 1 - count); | |
151 | T0 = res; | |
152 | #ifdef MEM_WRITE | |
153 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
154 | #endif | |
155 | CC_SRC = (eflags & ~(CC_C | CC_O)) | | |
156 | (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
157 | ((src >> (count - 1)) & CC_C); | |
158 | CC_OP = CC_OP_EFLAGS; | |
159 | } | |
160 | FORCE_RET(); | |
161 | } | |
162 | ||
163 | void OPPROTO glue(glue(op_shl, MEM_SUFFIX), _T0_T1_cc)(void) | |
164 | { | |
165 | int count, src; | |
166 | count = T1 & 0x1f; | |
167 | if (count) { | |
168 | src = (DATA_TYPE)T0 << (count - 1); | |
169 | T0 = T0 << count; | |
170 | #ifdef MEM_WRITE | |
171 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
172 | #endif | |
173 | CC_SRC = src; | |
174 | CC_DST = T0; | |
175 | CC_OP = CC_OP_SHLB + SHIFT; | |
176 | } | |
177 | FORCE_RET(); | |
178 | } | |
179 | ||
180 | void OPPROTO glue(glue(op_shr, MEM_SUFFIX), _T0_T1_cc)(void) | |
181 | { | |
182 | int count, src; | |
183 | count = T1 & 0x1f; | |
184 | if (count) { | |
185 | T0 &= DATA_MASK; | |
186 | src = T0 >> (count - 1); | |
187 | T0 = T0 >> count; | |
188 | #ifdef MEM_WRITE | |
189 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
190 | #endif | |
191 | CC_SRC = src; | |
192 | CC_DST = T0; | |
193 | CC_OP = CC_OP_SARB + SHIFT; | |
194 | } | |
195 | FORCE_RET(); | |
196 | } | |
197 | ||
198 | void OPPROTO glue(glue(op_sar, MEM_SUFFIX), _T0_T1_cc)(void) | |
199 | { | |
200 | int count, src; | |
201 | count = T1 & 0x1f; | |
202 | if (count) { | |
203 | src = (DATA_STYPE)T0; | |
204 | T0 = src >> count; | |
205 | src = src >> (count - 1); | |
206 | #ifdef MEM_WRITE | |
207 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
208 | #endif | |
209 | CC_SRC = src; | |
210 | CC_DST = T0; | |
211 | CC_OP = CC_OP_SARB + SHIFT; | |
212 | } | |
213 | FORCE_RET(); | |
214 | } | |
215 | ||
216 | #if DATA_BITS == 16 | |
217 | /* XXX: overflow flag might be incorrect in some cases in shldw */ | |
218 | void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void) | |
219 | { | |
220 | int count; | |
221 | unsigned int res, tmp; | |
222 | count = PARAM1; | |
223 | T1 &= 0xffff; | |
224 | res = T1 | (T0 << 16); | |
225 | tmp = res >> (32 - count); | |
226 | res <<= count; | |
227 | if (count > 16) | |
228 | res |= T1 << (count - 16); | |
229 | T0 = res >> 16; | |
230 | #ifdef MEM_WRITE | |
231 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
232 | #endif | |
233 | CC_SRC = tmp; | |
234 | CC_DST = T0; | |
235 | } | |
236 | ||
237 | void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void) | |
238 | { | |
239 | int count; | |
240 | unsigned int res, tmp; | |
241 | count = ECX & 0x1f; | |
242 | if (count) { | |
243 | T1 &= 0xffff; | |
244 | res = T1 | (T0 << 16); | |
245 | tmp = res >> (32 - count); | |
246 | res <<= count; | |
247 | if (count > 16) | |
248 | res |= T1 << (count - 16); | |
249 | T0 = res >> 16; | |
250 | #ifdef MEM_WRITE | |
251 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
252 | #endif | |
253 | CC_SRC = tmp; | |
254 | CC_DST = T0; | |
255 | CC_OP = CC_OP_SARB + SHIFT; | |
256 | } | |
257 | FORCE_RET(); | |
258 | } | |
259 | ||
260 | void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void) | |
261 | { | |
262 | int count; | |
263 | unsigned int res, tmp; | |
264 | ||
265 | count = PARAM1; | |
266 | res = (T0 & 0xffff) | (T1 << 16); | |
267 | tmp = res >> (count - 1); | |
268 | res >>= count; | |
269 | if (count > 16) | |
270 | res |= T1 << (32 - count); | |
271 | T0 = res; | |
272 | #ifdef MEM_WRITE | |
273 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
274 | #endif | |
275 | CC_SRC = tmp; | |
276 | CC_DST = T0; | |
277 | } | |
278 | ||
279 | ||
280 | void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void) | |
281 | { | |
282 | int count; | |
283 | unsigned int res, tmp; | |
284 | ||
285 | count = ECX & 0x1f; | |
286 | if (count) { | |
287 | res = (T0 & 0xffff) | (T1 << 16); | |
288 | tmp = res >> (count - 1); | |
289 | res >>= count; | |
290 | if (count > 16) | |
291 | res |= T1 << (32 - count); | |
292 | T0 = res; | |
293 | #ifdef MEM_WRITE | |
294 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
295 | #endif | |
296 | CC_SRC = tmp; | |
297 | CC_DST = T0; | |
298 | CC_OP = CC_OP_SARB + SHIFT; | |
299 | } | |
300 | FORCE_RET(); | |
301 | } | |
302 | #endif | |
303 | ||
304 | #if DATA_BITS == 32 | |
305 | void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void) | |
306 | { | |
307 | int count, tmp; | |
308 | count = PARAM1; | |
309 | T0 &= DATA_MASK; | |
310 | T1 &= DATA_MASK; | |
311 | tmp = T0 << (count - 1); | |
312 | T0 = (T0 << count) | (T1 >> (DATA_BITS - count)); | |
313 | #ifdef MEM_WRITE | |
314 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
315 | #endif | |
316 | CC_SRC = tmp; | |
317 | CC_DST = T0; | |
318 | } | |
319 | ||
320 | void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void) | |
321 | { | |
322 | int count, tmp; | |
323 | count = ECX & 0x1f; | |
324 | if (count) { | |
325 | T0 &= DATA_MASK; | |
326 | T1 &= DATA_MASK; | |
327 | tmp = T0 << (count - 1); | |
328 | T0 = (T0 << count) | (T1 >> (DATA_BITS - count)); | |
329 | #ifdef MEM_WRITE | |
330 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
331 | #endif | |
332 | CC_SRC = tmp; | |
333 | CC_DST = T0; | |
334 | CC_OP = CC_OP_SHLB + SHIFT; | |
335 | } | |
336 | FORCE_RET(); | |
337 | } | |
338 | ||
339 | void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void) | |
340 | { | |
341 | int count, tmp; | |
342 | count = PARAM1; | |
343 | T0 &= DATA_MASK; | |
344 | T1 &= DATA_MASK; | |
345 | tmp = T0 >> (count - 1); | |
346 | T0 = (T0 >> count) | (T1 << (DATA_BITS - count)); | |
347 | #ifdef MEM_WRITE | |
348 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
349 | #endif | |
350 | CC_SRC = tmp; | |
351 | CC_DST = T0; | |
352 | } | |
353 | ||
354 | ||
355 | void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void) | |
356 | { | |
357 | int count, tmp; | |
358 | count = ECX & 0x1f; | |
359 | if (count) { | |
360 | T0 &= DATA_MASK; | |
361 | T1 &= DATA_MASK; | |
362 | tmp = T0 >> (count - 1); | |
363 | T0 = (T0 >> count) | (T1 << (DATA_BITS - count)); | |
364 | #ifdef MEM_WRITE | |
365 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
366 | #endif | |
367 | CC_SRC = tmp; | |
368 | CC_DST = T0; | |
369 | CC_OP = CC_OP_SARB + SHIFT; | |
370 | } | |
371 | FORCE_RET(); | |
372 | } | |
373 | #endif | |
374 | ||
375 | /* carry add/sub (we only need to set CC_OP differently) */ | |
376 | ||
377 | void OPPROTO glue(glue(op_adc, MEM_SUFFIX), _T0_T1_cc)(void) | |
378 | { | |
379 | int cf; | |
380 | cf = cc_table[CC_OP].compute_c(); | |
381 | T0 = T0 + T1 + cf; | |
382 | #ifdef MEM_WRITE | |
383 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
384 | #endif | |
385 | CC_SRC = T1; | |
386 | CC_DST = T0; | |
387 | CC_OP = CC_OP_ADDB + SHIFT + cf * 3; | |
388 | } | |
389 | ||
390 | void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void) | |
391 | { | |
392 | int cf; | |
393 | cf = cc_table[CC_OP].compute_c(); | |
394 | T0 = T0 - T1 - cf; | |
395 | #ifdef MEM_WRITE | |
396 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
397 | #endif | |
398 | CC_SRC = T1; | |
399 | CC_DST = T0; | |
400 | CC_OP = CC_OP_SUBB + SHIFT + cf * 3; | |
401 | } | |
402 | ||
403 | void OPPROTO glue(glue(op_cmpxchg, MEM_SUFFIX), _T0_T1_EAX_cc)(void) | |
404 | { | |
405 | unsigned int src, dst; | |
406 | ||
407 | src = T0; | |
408 | dst = EAX - T0; | |
409 | if ((DATA_TYPE)dst == 0) { | |
410 | T0 = T1; | |
411 | } else { | |
412 | EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK); | |
413 | } | |
414 | #ifdef MEM_WRITE | |
415 | glue(st, SUFFIX)((uint8_t *)A0, T0); | |
416 | #endif | |
417 | CC_SRC = src; | |
418 | CC_DST = dst; | |
419 | FORCE_RET(); | |
420 | } | |
421 | ||
422 | #undef MEM_SUFFIX | |
423 | #undef MEM_WRITE |