]> git.proxmox.com Git - qemu.git/blame - ops_template.h
float fixes - added bsr/bsf support
[qemu.git] / ops_template.h
CommitLineData
367e86e8
FB
1
2#define DATA_BITS (1 << (3 + SHIFT))
3#define SHIFT_MASK (DATA_BITS - 1)
4#define SIGN_MASK (1 << (DATA_BITS - 1))
5
6#if DATA_BITS == 8
7#define SUFFIX b
8#define DATA_TYPE uint8_t
9#define DATA_STYPE int8_t
10#define DATA_MASK 0xff
11#elif DATA_BITS == 16
12#define SUFFIX w
13#define DATA_TYPE uint16_t
14#define DATA_STYPE int16_t
15#define DATA_MASK 0xffff
16#elif DATA_BITS == 32
17#define SUFFIX l
18#define DATA_TYPE uint32_t
19#define DATA_STYPE int32_t
20#define DATA_MASK 0xffffffff
21#else
22#error unhandled operand size
23#endif
24
25/* dynamic flags computation */
26
27static int glue(compute_all_add, SUFFIX)(void)
28{
29 int cf, pf, af, zf, sf, of;
30 int src1, src2;
31 src1 = CC_SRC;
32 src2 = CC_DST - CC_SRC;
33 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
34 pf = parity_table[(uint8_t)CC_DST];
35 af = (CC_DST ^ src1 ^ src2) & 0x10;
4b74fe1f 36 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8
FB
37 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
38 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
39 return cf | pf | af | zf | sf | of;
40}
41
42static int glue(compute_c_add, SUFFIX)(void)
43{
44 int src1, cf;
45 src1 = CC_SRC;
46 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
47 return cf;
48}
49
4b74fe1f
FB
50static int glue(compute_all_adc, SUFFIX)(void)
51{
52 int cf, pf, af, zf, sf, of;
53 int src1, src2;
54 src1 = CC_SRC;
55 src2 = CC_DST - CC_SRC - 1;
56 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
57 pf = parity_table[(uint8_t)CC_DST];
58 af = (CC_DST ^ src1 ^ src2) & 0x10;
59 zf = ((DATA_TYPE)CC_DST == 0) << 6;
60 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
61 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
62 return cf | pf | af | zf | sf | of;
63}
64
65static int glue(compute_c_adc, SUFFIX)(void)
66{
67 int src1, cf;
68 src1 = CC_SRC;
69 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
70 return cf;
71}
72
367e86e8
FB
73static int glue(compute_all_sub, SUFFIX)(void)
74{
75 int cf, pf, af, zf, sf, of;
76 int src1, src2;
77 src1 = CC_SRC;
78 src2 = CC_SRC - CC_DST;
79 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
80 pf = parity_table[(uint8_t)CC_DST];
81 af = (CC_DST ^ src1 ^ src2) & 0x10;
4b74fe1f 82 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8 83 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
4b74fe1f 84 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
367e86e8
FB
85 return cf | pf | af | zf | sf | of;
86}
87
88static int glue(compute_c_sub, SUFFIX)(void)
89{
90 int src1, src2, cf;
91 src1 = CC_SRC;
92 src2 = CC_SRC - CC_DST;
4b74fe1f
FB
93 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
94 return cf;
95}
96
97static int glue(compute_all_sbb, SUFFIX)(void)
98{
99 int cf, pf, af, zf, sf, of;
100 int src1, src2;
101 src1 = CC_SRC;
102 src2 = CC_SRC - CC_DST - 1;
103 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
104 pf = parity_table[(uint8_t)CC_DST];
105 af = (CC_DST ^ src1 ^ src2) & 0x10;
106 zf = ((DATA_TYPE)CC_DST == 0) << 6;
107 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
108 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
109 return cf | pf | af | zf | sf | of;
110}
111
112static int glue(compute_c_sbb, SUFFIX)(void)
113{
114 int src1, src2, cf;
115 src1 = CC_SRC;
116 src2 = CC_SRC - CC_DST - 1;
117 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
367e86e8
FB
118 return cf;
119}
120
121static int glue(compute_all_logic, SUFFIX)(void)
122{
123 int cf, pf, af, zf, sf, of;
124 cf = 0;
125 pf = parity_table[(uint8_t)CC_DST];
126 af = 0;
4b74fe1f 127 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8
FB
128 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
129 of = 0;
130 return cf | pf | af | zf | sf | of;
131}
132
133static int glue(compute_c_logic, SUFFIX)(void)
134{
135 return 0;
136}
137
138static int glue(compute_all_inc, SUFFIX)(void)
139{
140 int cf, pf, af, zf, sf, of;
141 int src1, src2;
142 src1 = CC_DST - 1;
143 src2 = 1;
144 cf = CC_SRC;
145 pf = parity_table[(uint8_t)CC_DST];
146 af = (CC_DST ^ src1 ^ src2) & 0x10;
4b74fe1f 147 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8 148 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
4b74fe1f 149 of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
367e86e8
FB
150 return cf | pf | af | zf | sf | of;
151}
152
4b74fe1f 153#if DATA_BITS == 32
367e86e8
FB
154static int glue(compute_c_inc, SUFFIX)(void)
155{
156 return CC_SRC;
157}
4b74fe1f 158#endif
367e86e8
FB
159
160static int glue(compute_all_dec, SUFFIX)(void)
161{
162 int cf, pf, af, zf, sf, of;
163 int src1, src2;
164 src1 = CC_DST + 1;
165 src2 = 1;
166 cf = CC_SRC;
167 pf = parity_table[(uint8_t)CC_DST];
168 af = (CC_DST ^ src1 ^ src2) & 0x10;
4b74fe1f 169 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8 170 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
4b74fe1f 171 of = ((CC_DST & DATA_MASK) == ((uint32_t)SIGN_MASK - 1)) << 11;
367e86e8
FB
172 return cf | pf | af | zf | sf | of;
173}
174
175static int glue(compute_all_shl, SUFFIX)(void)
176{
177 int cf, pf, af, zf, sf, of;
d57c4e01 178 cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
367e86e8
FB
179 pf = parity_table[(uint8_t)CC_DST];
180 af = 0; /* undefined */
4b74fe1f 181 zf = ((DATA_TYPE)CC_DST == 0) << 6;
367e86e8 182 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
d57c4e01
FB
183 /* of is defined if shift count == 1 */
184 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
367e86e8
FB
185 return cf | pf | af | zf | sf | of;
186}
187
4b74fe1f 188#if DATA_BITS == 32
367e86e8
FB
189static int glue(compute_c_shl, SUFFIX)(void)
190{
191 return CC_SRC & 1;
192}
4b74fe1f
FB
193#endif
194
195static int glue(compute_all_sar, SUFFIX)(void)
196{
197 int cf, pf, af, zf, sf, of;
198 cf = CC_SRC & 1;
199 pf = parity_table[(uint8_t)CC_DST];
200 af = 0; /* undefined */
201 zf = ((DATA_TYPE)CC_DST == 0) << 6;
202 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
d57c4e01
FB
203 /* of is defined if shift count == 1 */
204 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
4b74fe1f
FB
205 return cf | pf | af | zf | sf | of;
206}
367e86e8
FB
207
208/* various optimized jumps cases */
209
210void OPPROTO glue(op_jb_sub, SUFFIX)(void)
211{
212 int src1, src2;
213 src1 = CC_SRC;
214 src2 = CC_SRC - CC_DST;
215
216 if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
0ecfa993 217 PC = PARAM1;
367e86e8 218 else
0ecfa993 219 PC = PARAM2;
367e86e8
FB
220 FORCE_RET();
221}
222
223void OPPROTO glue(op_jz_sub, SUFFIX)(void)
224{
4b74fe1f 225 if ((DATA_TYPE)CC_DST == 0)
0ecfa993 226 PC = PARAM1;
367e86e8 227 else
0ecfa993 228 PC = PARAM2;
367e86e8
FB
229 FORCE_RET();
230}
231
232void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
233{
234 int src1, src2;
235 src1 = CC_SRC;
236 src2 = CC_SRC - CC_DST;
237
238 if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
0ecfa993 239 PC = PARAM1;
367e86e8 240 else
0ecfa993 241 PC = PARAM2;
367e86e8
FB
242 FORCE_RET();
243}
244
245void OPPROTO glue(op_js_sub, SUFFIX)(void)
246{
247 if (CC_DST & SIGN_MASK)
0ecfa993 248 PC = PARAM1;
367e86e8 249 else
0ecfa993 250 PC = PARAM2;
367e86e8
FB
251 FORCE_RET();
252}
253
254void OPPROTO glue(op_jl_sub, SUFFIX)(void)
255{
256 int src1, src2;
257 src1 = CC_SRC;
258 src2 = CC_SRC - CC_DST;
259
260 if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
0ecfa993 261 PC = PARAM1;
367e86e8 262 else
0ecfa993 263 PC = PARAM2;
367e86e8
FB
264 FORCE_RET();
265}
266
267void OPPROTO glue(op_jle_sub, SUFFIX)(void)
268{
269 int src1, src2;
270 src1 = CC_SRC;
271 src2 = CC_SRC - CC_DST;
272
273 if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
0ecfa993 274 PC = PARAM1;
367e86e8 275 else
0ecfa993 276 PC = PARAM2;
367e86e8
FB
277 FORCE_RET();
278}
279
280/* various optimized set cases */
281
282void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
283{
284 int src1, src2;
285 src1 = CC_SRC;
286 src2 = CC_SRC - CC_DST;
287
288 T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
289}
290
291void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
292{
4b74fe1f 293 T0 = ((DATA_TYPE)CC_DST == 0);
367e86e8
FB
294}
295
296void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
297{
298 int src1, src2;
299 src1 = CC_SRC;
300 src2 = CC_SRC - CC_DST;
301
302 T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
303}
304
305void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
306{
307 T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
308}
309
310void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
311{
312 int src1, src2;
313 src1 = CC_SRC;
314 src2 = CC_SRC - CC_DST;
315
316 T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
317}
318
319void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
320{
321 int src1, src2;
322 src1 = CC_SRC;
323 src2 = CC_SRC - CC_DST;
324
325 T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
326}
327
328/* shifts */
329
330void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
331{
332 int count, src;
333 count = T1 & SHIFT_MASK;
334 if (count) {
335 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
336 src = T0;
337 T0 &= DATA_MASK;
338 T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
339 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
340 (T0 & CC_C);
341 CC_OP = CC_OP_EFLAGS;
342 }
4b74fe1f 343 FORCE_RET();
367e86e8
FB
344}
345
346void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
347{
348 int count, src;
349 count = T1 & SHIFT_MASK;
350 if (count) {
351 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
352 src = T0;
353 T0 &= DATA_MASK;
354 T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
355 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
356 ((T0 >> (DATA_BITS - 1)) & CC_C);
357 CC_OP = CC_OP_EFLAGS;
358 }
4b74fe1f 359 FORCE_RET();
367e86e8
FB
360}
361
362void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
363{
364 int count, res, eflags;
365 unsigned int src;
366
367 count = T1 & 0x1f;
368#if DATA_BITS == 16
369 count = rclw_table[count];
370#elif DATA_BITS == 8
371 count = rclb_table[count];
372#endif
373 if (count) {
374 eflags = cc_table[CC_OP].compute_all();
4b74fe1f 375 T0 &= DATA_MASK;
367e86e8
FB
376 src = T0;
377 res = (T0 << count) | ((eflags & CC_C) << (count - 1));
378 if (count > 1)
379 res |= T0 >> (DATA_BITS + 1 - count);
380 T0 = res;
381 CC_SRC = (eflags & ~(CC_C | CC_O)) |
382 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
383 ((src >> (DATA_BITS - count)) & CC_C);
384 CC_OP = CC_OP_EFLAGS;
385 }
4b74fe1f 386 FORCE_RET();
367e86e8
FB
387}
388
389void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
390{
391 int count, res, eflags;
392 unsigned int src;
393
394 count = T1 & 0x1f;
395#if DATA_BITS == 16
396 count = rclw_table[count];
397#elif DATA_BITS == 8
398 count = rclb_table[count];
399#endif
400 if (count) {
401 eflags = cc_table[CC_OP].compute_all();
4b74fe1f 402 T0 &= DATA_MASK;
367e86e8
FB
403 src = T0;
404 res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
405 if (count > 1)
406 res |= T0 << (DATA_BITS + 1 - count);
407 T0 = res;
408 CC_SRC = (eflags & ~(CC_C | CC_O)) |
409 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
410 ((src >> (count - 1)) & CC_C);
411 CC_OP = CC_OP_EFLAGS;
412 }
4b74fe1f 413 FORCE_RET();
367e86e8
FB
414}
415
416void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
417{
418 int count;
419 count = T1 & 0x1f;
d57c4e01
FB
420 if (count) {
421 CC_SRC = (DATA_TYPE)T0 << (count - 1);
367e86e8
FB
422 T0 = T0 << count;
423 CC_DST = T0;
424 CC_OP = CC_OP_SHLB + SHIFT;
425 }
4b74fe1f 426 FORCE_RET();
367e86e8
FB
427}
428
429void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
430{
431 int count;
432 count = T1 & 0x1f;
433 if (count) {
434 T0 &= DATA_MASK;
435 CC_SRC = T0 >> (count - 1);
436 T0 = T0 >> count;
437 CC_DST = T0;
d57c4e01 438 CC_OP = CC_OP_SARB + SHIFT;
367e86e8 439 }
4b74fe1f 440 FORCE_RET();
367e86e8
FB
441}
442
443void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
444{
445 int count, src;
446 count = T1 & 0x1f;
447 if (count) {
448 src = (DATA_STYPE)T0;
d57c4e01 449 CC_SRC = src >> (count - 1);
367e86e8
FB
450 T0 = src >> count;
451 CC_DST = T0;
4b74fe1f 452 CC_OP = CC_OP_SARB + SHIFT;
367e86e8 453 }
4b74fe1f 454 FORCE_RET();
367e86e8
FB
455}
456
d57c4e01
FB
457#if DATA_BITS == 16
458/* XXX: overflow flag might be incorrect in some cases in shldw */
459void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
460{
461 int count;
462 unsigned int res;
463 count = PARAM1;
464 T1 &= 0xffff;
465 res = T1 | (T0 << 16);
466 CC_SRC = res >> (32 - count);
467 res <<= count;
468 if (count > 16)
469 res |= T1 << (count - 16);
470 T0 = res >> 16;
471 CC_DST = T0;
472}
473
474void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
475{
476 int count;
477 unsigned int res;
478 count = ECX & 0x1f;
479 if (count) {
480 T1 &= 0xffff;
481 res = T1 | (T0 << 16);
482 CC_SRC = res >> (32 - count);
483 res <<= count;
484 if (count > 16)
485 res |= T1 << (count - 16);
486 T0 = res >> 16;
487 CC_DST = T0;
488 CC_OP = CC_OP_SARB + SHIFT;
489 }
490}
491
492void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
493{
494 int count;
495 unsigned int res;
496
497 count = PARAM1;
498 res = (T0 & 0xffff) | (T1 << 16);
499 CC_SRC = res >> (count - 1);
500 res >>= count;
501 if (count > 16)
502 res |= T1 << (32 - count);
503 T0 = res;
504 CC_DST = T0;
505}
506
507
508void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
509{
510 int count;
511 unsigned int res;
512
513 count = ECX & 0x1f;
514 if (count) {
515 res = (T0 & 0xffff) | (T1 << 16);
516 CC_SRC = res >> (count - 1);
517 res >>= count;
518 if (count > 16)
519 res |= T1 << (32 - count);
520 T0 = res;
521 CC_DST = T0;
522 CC_OP = CC_OP_SARB + SHIFT;
523 }
524}
525#endif
526
527#if DATA_BITS == 32
528void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
529{
530 int count;
531 count = PARAM1;
532 T0 &= DATA_MASK;
533 T1 &= DATA_MASK;
534 CC_SRC = T0 << (count - 1);
535 T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
536 CC_DST = T0;
537}
538
539void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
540{
541 int count;
542 count = ECX & 0x1f;
543 if (count) {
544 T0 &= DATA_MASK;
545 T1 &= DATA_MASK;
546 CC_SRC = T0 << (count - 1);
547 T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
548 CC_DST = T0;
549 CC_OP = CC_OP_SHLB + SHIFT;
550 }
551}
552
553void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
554{
555 int count;
556 count = PARAM1;
557 T0 &= DATA_MASK;
558 T1 &= DATA_MASK;
559 CC_SRC = T0 >> (count - 1);
560 T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
561 CC_DST = T0;
562}
563
564
565void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
566{
567 int count;
568 count = ECX & 0x1f;
569 if (count) {
570 T0 &= DATA_MASK;
571 T1 &= DATA_MASK;
572 CC_SRC = T0 >> (count - 1);
573 T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
574 CC_DST = T0;
575 CC_OP = CC_OP_SARB + SHIFT;
576 }
577}
578#endif
579
4b74fe1f
FB
580/* carry add/sub (we only need to set CC_OP differently) */
581
582void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
583{
584 int cf;
585 cf = cc_table[CC_OP].compute_c();
586 CC_SRC = T0;
587 T0 = T0 + T1 + cf;
588 CC_DST = T0;
589 CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
590}
591
592void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
593{
594 int cf;
595 cf = cc_table[CC_OP].compute_c();
596 CC_SRC = T0;
597 T0 = T0 - T1 - cf;
598 CC_DST = T0;
599 CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
600}
601
602/* bit operations */
603#if DATA_BITS >= 16
604
605void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
606{
607 int count;
608 count = T1 & SHIFT_MASK;
609 CC_SRC = T0 >> count;
610}
611
612void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
613{
614 int count;
615 count = T1 & SHIFT_MASK;
616 CC_SRC = T0 >> count;
617 T0 |= (1 << count);
618}
619
620void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
621{
622 int count;
623 count = T1 & SHIFT_MASK;
624 CC_SRC = T0 >> count;
625 T0 &= ~(1 << count);
626}
627
628void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
629{
630 int count;
631 count = T1 & SHIFT_MASK;
632 CC_SRC = T0 >> count;
633 T0 ^= (1 << count);
634}
635
77f8dd5a
FB
636void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
637{
638 int res, count;
639 res = T0 & DATA_MASK;
640 if (res != 0) {
641 count = 0;
642 while ((res & 1) == 0) {
643 count++;
644 res >>= 1;
645 }
646 T0 = count;
647 CC_DST = 1; /* ZF = 1 */
648 } else {
649 CC_DST = 0; /* ZF = 1 */
650 }
651 FORCE_RET();
652}
653
654void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
655{
656 int res, count;
657 res = T0 & DATA_MASK;
658 if (res != 0) {
659 count = DATA_BITS - 1;
660 while ((res & SIGN_MASK) == 0) {
661 count--;
662 res <<= 1;
663 }
664 T0 = count;
665 CC_DST = 1; /* ZF = 1 */
666 } else {
667 CC_DST = 0; /* ZF = 1 */
668 }
669 FORCE_RET();
670}
671
4b74fe1f
FB
672#endif
673
367e86e8
FB
674/* string operations */
675/* XXX: maybe use lower level instructions to ease exception handling */
676
677void OPPROTO glue(op_movs, SUFFIX)(void)
678{
679 int v;
680 v = glue(ldu, SUFFIX)((void *)ESI);
681 glue(st, SUFFIX)((void *)EDI, v);
682 ESI += (DF << SHIFT);
683 EDI += (DF << SHIFT);
684}
685
686void OPPROTO glue(op_rep_movs, SUFFIX)(void)
687{
688 int v, inc;
689 inc = (DF << SHIFT);
690 while (ECX != 0) {
691 v = glue(ldu, SUFFIX)((void *)ESI);
692 glue(st, SUFFIX)((void *)EDI, v);
693 ESI += inc;
694 EDI += inc;
695 ECX--;
696 }
697}
698
699void OPPROTO glue(op_stos, SUFFIX)(void)
700{
701 glue(st, SUFFIX)((void *)EDI, EAX);
702 EDI += (DF << SHIFT);
703}
704
705void OPPROTO glue(op_rep_stos, SUFFIX)(void)
706{
707 int inc;
708 inc = (DF << SHIFT);
709 while (ECX != 0) {
710 glue(st, SUFFIX)((void *)EDI, EAX);
711 EDI += inc;
712 ECX--;
713 }
714}
715
716void OPPROTO glue(op_lods, SUFFIX)(void)
717{
718 int v;
719 v = glue(ldu, SUFFIX)((void *)ESI);
720#if SHIFT == 0
721 EAX = (EAX & ~0xff) | v;
722#elif SHIFT == 1
723 EAX = (EAX & ~0xffff) | v;
724#else
725 EAX = v;
726#endif
727 ESI += (DF << SHIFT);
728}
729
730/* don't know if it is used */
731void OPPROTO glue(op_rep_lods, SUFFIX)(void)
732{
733 int v, inc;
734 inc = (DF << SHIFT);
735 while (ECX != 0) {
736 v = glue(ldu, SUFFIX)((void *)ESI);
737#if SHIFT == 0
738 EAX = (EAX & ~0xff) | v;
739#elif SHIFT == 1
740 EAX = (EAX & ~0xffff) | v;
741#else
742 EAX = v;
743#endif
744 ESI += inc;
745 ECX--;
746 }
747}
748
749void OPPROTO glue(op_scas, SUFFIX)(void)
750{
751 int v;
752
4b74fe1f
FB
753 v = glue(ldu, SUFFIX)((void *)EDI);
754 EDI += (DF << SHIFT);
367e86e8
FB
755 CC_SRC = EAX;
756 CC_DST = EAX - v;
757}
758
759void OPPROTO glue(op_repz_scas, SUFFIX)(void)
760{
761 int v1, v2, inc;
762
763 if (ECX != 0) {
764 /* NOTE: the flags are not modified if ECX == 0 */
4b74fe1f 765 v1 = EAX & DATA_MASK;
367e86e8
FB
766 inc = (DF << SHIFT);
767 do {
4b74fe1f
FB
768 v2 = glue(ldu, SUFFIX)((void *)EDI);
769 EDI += inc;
770 ECX--;
367e86e8
FB
771 if (v1 != v2)
772 break;
367e86e8
FB
773 } while (ECX != 0);
774 CC_SRC = v1;
775 CC_DST = v1 - v2;
776 CC_OP = CC_OP_SUBB + SHIFT;
777 }
778}
779
780void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
781{
782 int v1, v2, inc;
783
784 if (ECX != 0) {
785 /* NOTE: the flags are not modified if ECX == 0 */
4b74fe1f 786 v1 = EAX & DATA_MASK;
367e86e8
FB
787 inc = (DF << SHIFT);
788 do {
4b74fe1f
FB
789 v2 = glue(ldu, SUFFIX)((void *)EDI);
790 EDI += inc;
791 ECX--;
367e86e8
FB
792 if (v1 == v2)
793 break;
367e86e8
FB
794 } while (ECX != 0);
795 CC_SRC = v1;
796 CC_DST = v1 - v2;
797 CC_OP = CC_OP_SUBB + SHIFT;
798 }
799}
800
801void OPPROTO glue(op_cmps, SUFFIX)(void)
802{
803 int v1, v2;
804 v1 = glue(ldu, SUFFIX)((void *)ESI);
805 v2 = glue(ldu, SUFFIX)((void *)EDI);
806 ESI += (DF << SHIFT);
807 EDI += (DF << SHIFT);
808 CC_SRC = v1;
809 CC_DST = v1 - v2;
810}
811
812void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
813{
814 int v1, v2, inc;
815 if (ECX != 0) {
816 inc = (DF << SHIFT);
817 do {
818 v1 = glue(ldu, SUFFIX)((void *)ESI);
819 v2 = glue(ldu, SUFFIX)((void *)EDI);
367e86e8
FB
820 ESI += inc;
821 EDI += inc;
822 ECX--;
4b74fe1f
FB
823 if (v1 != v2)
824 break;
367e86e8
FB
825 } while (ECX != 0);
826 CC_SRC = v1;
827 CC_DST = v1 - v2;
828 CC_OP = CC_OP_SUBB + SHIFT;
829 }
830}
831
832void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
833{
834 int v1, v2, inc;
835 if (ECX != 0) {
836 inc = (DF << SHIFT);
837 do {
838 v1 = glue(ldu, SUFFIX)((void *)ESI);
839 v2 = glue(ldu, SUFFIX)((void *)EDI);
367e86e8
FB
840 ESI += inc;
841 EDI += inc;
842 ECX--;
4b74fe1f
FB
843 if (v1 == v2)
844 break;
367e86e8
FB
845 } while (ECX != 0);
846 CC_SRC = v1;
847 CC_DST = v1 - v2;
848 CC_OP = CC_OP_SUBB + SHIFT;
849 }
850}
851
ba1c6e37
FB
852/* port I/O */
853
367e86e8
FB
854void OPPROTO glue(op_outs, SUFFIX)(void)
855{
856 int v, dx;
857 dx = EDX & 0xffff;
858 v = glue(ldu, SUFFIX)((void *)ESI);
ba1c6e37 859 glue(cpu_x86_out, SUFFIX)(dx, v);
367e86e8
FB
860 ESI += (DF << SHIFT);
861}
862
863void OPPROTO glue(op_rep_outs, SUFFIX)(void)
864{
865 int v, dx, inc;
866 inc = (DF << SHIFT);
867 dx = EDX & 0xffff;
868 while (ECX != 0) {
869 v = glue(ldu, SUFFIX)((void *)ESI);
ba1c6e37 870 glue(cpu_x86_out, SUFFIX)(dx, v);
367e86e8
FB
871 ESI += inc;
872 ECX--;
873 }
874}
875
876void OPPROTO glue(op_ins, SUFFIX)(void)
877{
878 int v, dx;
879 dx = EDX & 0xffff;
ba1c6e37 880 v = glue(cpu_x86_in, SUFFIX)(dx);
367e86e8
FB
881 glue(st, SUFFIX)((void *)EDI, v);
882 EDI += (DF << SHIFT);
883}
884
885void OPPROTO glue(op_rep_ins, SUFFIX)(void)
886{
887 int v, dx, inc;
888 inc = (DF << SHIFT);
889 dx = EDX & 0xffff;
890 while (ECX != 0) {
ba1c6e37 891 v = glue(cpu_x86_in, SUFFIX)(dx);
367e86e8
FB
892 glue(st, SUFFIX)((void *)EDI, v);
893 EDI += (DF << SHIFT);
894 ECX--;
895 }
896}
897
ba1c6e37
FB
898void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
899{
900 glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK);
901}
902
903void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
904{
905 T1 = glue(cpu_x86_in, SUFFIX)(T0 & 0xffff);
906}
907
367e86e8
FB
908#undef DATA_BITS
909#undef SHIFT_MASK
910#undef SIGN_MASK
911#undef DATA_TYPE
912#undef DATA_STYPE
913#undef DATA_MASK
914#undef SUFFIX