]> git.proxmox.com Git - qemu.git/blame - ops_template.h
added float 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;
36 zf = ((DATA_TYPE)CC_DST != 0) << 6;
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
50static int glue(compute_all_sub, SUFFIX)(void)
51{
52 int cf, pf, af, zf, sf, of;
53 int src1, src2;
54 src1 = CC_SRC;
55 src2 = CC_SRC - CC_DST;
56 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
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_sub, SUFFIX)(void)
66{
67 int src1, src2, cf;
68 src1 = CC_SRC;
69 src2 = CC_SRC - CC_DST;
70 cf = (DATA_TYPE)src1 < (DATA_TYPE)src1;
71 return cf;
72}
73
74static int glue(compute_all_logic, SUFFIX)(void)
75{
76 int cf, pf, af, zf, sf, of;
77 cf = 0;
78 pf = parity_table[(uint8_t)CC_DST];
79 af = 0;
80 zf = ((DATA_TYPE)CC_DST != 0) << 6;
81 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
82 of = 0;
83 return cf | pf | af | zf | sf | of;
84}
85
86static int glue(compute_c_logic, SUFFIX)(void)
87{
88 return 0;
89}
90
91static int glue(compute_all_inc, SUFFIX)(void)
92{
93 int cf, pf, af, zf, sf, of;
94 int src1, src2;
95 src1 = CC_DST - 1;
96 src2 = 1;
97 cf = CC_SRC;
98 pf = parity_table[(uint8_t)CC_DST];
99 af = (CC_DST ^ src1 ^ src2) & 0x10;
100 zf = ((DATA_TYPE)CC_DST != 0) << 6;
101 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
102 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
103 return cf | pf | af | zf | sf | of;
104}
105
106static int glue(compute_c_inc, SUFFIX)(void)
107{
108 return CC_SRC;
109}
110
111static int glue(compute_all_dec, SUFFIX)(void)
112{
113 int cf, pf, af, zf, sf, of;
114 int src1, src2;
115 src1 = CC_DST + 1;
116 src2 = 1;
117 cf = CC_SRC;
118 pf = parity_table[(uint8_t)CC_DST];
119 af = (CC_DST ^ src1 ^ src2) & 0x10;
120 zf = ((DATA_TYPE)CC_DST != 0) << 6;
121 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
122 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
123 return cf | pf | af | zf | sf | of;
124}
125
126static int glue(compute_all_shl, SUFFIX)(void)
127{
128 int cf, pf, af, zf, sf, of;
129 cf = CC_SRC & 1;
130 pf = parity_table[(uint8_t)CC_DST];
131 af = 0; /* undefined */
132 zf = ((DATA_TYPE)CC_DST != 0) << 6;
133 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
134 of = sf << 4; /* only meaniful for shr with count == 1 */
135 return cf | pf | af | zf | sf | of;
136}
137
138static int glue(compute_c_shl, SUFFIX)(void)
139{
140 return CC_SRC & 1;
141}
142
143/* various optimized jumps cases */
144
145void OPPROTO glue(op_jb_sub, SUFFIX)(void)
146{
147 int src1, src2;
148 src1 = CC_SRC;
149 src2 = CC_SRC - CC_DST;
150
151 if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
152 PC += PARAM1;
153 else
154 PC += PARAM2;
155 FORCE_RET();
156}
157
158void OPPROTO glue(op_jz_sub, SUFFIX)(void)
159{
160 if ((DATA_TYPE)CC_DST != 0)
161 PC += PARAM1;
162 else
163 PC += PARAM2;
164 FORCE_RET();
165}
166
167void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
168{
169 int src1, src2;
170 src1 = CC_SRC;
171 src2 = CC_SRC - CC_DST;
172
173 if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
174 PC += PARAM1;
175 else
176 PC += PARAM2;
177 FORCE_RET();
178}
179
180void OPPROTO glue(op_js_sub, SUFFIX)(void)
181{
182 if (CC_DST & SIGN_MASK)
183 PC += PARAM1;
184 else
185 PC += PARAM2;
186 FORCE_RET();
187}
188
189void OPPROTO glue(op_jl_sub, SUFFIX)(void)
190{
191 int src1, src2;
192 src1 = CC_SRC;
193 src2 = CC_SRC - CC_DST;
194
195 if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
196 PC += PARAM1;
197 else
198 PC += PARAM2;
199 FORCE_RET();
200}
201
202void OPPROTO glue(op_jle_sub, SUFFIX)(void)
203{
204 int src1, src2;
205 src1 = CC_SRC;
206 src2 = CC_SRC - CC_DST;
207
208 if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
209 PC += PARAM1;
210 else
211 PC += PARAM2;
212 FORCE_RET();
213}
214
215/* various optimized set cases */
216
217void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
218{
219 int src1, src2;
220 src1 = CC_SRC;
221 src2 = CC_SRC - CC_DST;
222
223 T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
224}
225
226void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
227{
228 T0 = ((DATA_TYPE)CC_DST != 0);
229}
230
231void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
232{
233 int src1, src2;
234 src1 = CC_SRC;
235 src2 = CC_SRC - CC_DST;
236
237 T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
238}
239
240void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
241{
242 T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
243}
244
245void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
246{
247 int src1, src2;
248 src1 = CC_SRC;
249 src2 = CC_SRC - CC_DST;
250
251 T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
252}
253
254void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
255{
256 int src1, src2;
257 src1 = CC_SRC;
258 src2 = CC_SRC - CC_DST;
259
260 T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
261}
262
263/* shifts */
264
265void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
266{
267 int count, src;
268 count = T1 & SHIFT_MASK;
269 if (count) {
270 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
271 src = T0;
272 T0 &= DATA_MASK;
273 T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
274 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
275 (T0 & CC_C);
276 CC_OP = CC_OP_EFLAGS;
277 }
278}
279
280void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
281{
282 int count, src;
283 count = T1 & SHIFT_MASK;
284 if (count) {
285 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
286 src = T0;
287 T0 &= DATA_MASK;
288 T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
289 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
290 ((T0 >> (DATA_BITS - 1)) & CC_C);
291 CC_OP = CC_OP_EFLAGS;
292 }
293}
294
295void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
296{
297 int count, res, eflags;
298 unsigned int src;
299
300 count = T1 & 0x1f;
301#if DATA_BITS == 16
302 count = rclw_table[count];
303#elif DATA_BITS == 8
304 count = rclb_table[count];
305#endif
306 if (count) {
307 eflags = cc_table[CC_OP].compute_all();
308 src = T0;
309 res = (T0 << count) | ((eflags & CC_C) << (count - 1));
310 if (count > 1)
311 res |= T0 >> (DATA_BITS + 1 - count);
312 T0 = res;
313 CC_SRC = (eflags & ~(CC_C | CC_O)) |
314 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
315 ((src >> (DATA_BITS - count)) & CC_C);
316 CC_OP = CC_OP_EFLAGS;
317 }
318}
319
320void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
321{
322 int count, res, eflags;
323 unsigned int src;
324
325 count = T1 & 0x1f;
326#if DATA_BITS == 16
327 count = rclw_table[count];
328#elif DATA_BITS == 8
329 count = rclb_table[count];
330#endif
331 if (count) {
332 eflags = cc_table[CC_OP].compute_all();
333 src = T0;
334 res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
335 if (count > 1)
336 res |= T0 << (DATA_BITS + 1 - count);
337 T0 = res;
338 CC_SRC = (eflags & ~(CC_C | CC_O)) |
339 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
340 ((src >> (count - 1)) & CC_C);
341 CC_OP = CC_OP_EFLAGS;
342 }
343}
344
345void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
346{
347 int count;
348 count = T1 & 0x1f;
349 if (count == 1) {
350 CC_SRC = T0;
351 T0 = T0 << 1;
352 CC_DST = T0;
353 CC_OP = CC_OP_ADDB + SHIFT;
354 } else if (count) {
355 CC_SRC = T0 >> (DATA_BITS - count);
356 T0 = T0 << count;
357 CC_DST = T0;
358 CC_OP = CC_OP_SHLB + SHIFT;
359 }
360}
361
362void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
363{
364 int count;
365 count = T1 & 0x1f;
366 if (count) {
367 T0 &= DATA_MASK;
368 CC_SRC = T0 >> (count - 1);
369 T0 = T0 >> count;
370 CC_DST = T0;
371 CC_OP = CC_OP_SHLB + SHIFT;
372 }
373}
374
375void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
376{
377 int count, src;
378 count = T1 & 0x1f;
379 if (count) {
380 src = (DATA_STYPE)T0;
381 CC_SRC = src >> (count - 1);
382 T0 = src >> count;
383 CC_DST = T0;
384 CC_OP = CC_OP_SHLB + SHIFT;
385 }
386}
387
388/* string operations */
389/* XXX: maybe use lower level instructions to ease exception handling */
390
391void OPPROTO glue(op_movs, SUFFIX)(void)
392{
393 int v;
394 v = glue(ldu, SUFFIX)((void *)ESI);
395 glue(st, SUFFIX)((void *)EDI, v);
396 ESI += (DF << SHIFT);
397 EDI += (DF << SHIFT);
398}
399
400void OPPROTO glue(op_rep_movs, SUFFIX)(void)
401{
402 int v, inc;
403 inc = (DF << SHIFT);
404 while (ECX != 0) {
405 v = glue(ldu, SUFFIX)((void *)ESI);
406 glue(st, SUFFIX)((void *)EDI, v);
407 ESI += inc;
408 EDI += inc;
409 ECX--;
410 }
411}
412
413void OPPROTO glue(op_stos, SUFFIX)(void)
414{
415 glue(st, SUFFIX)((void *)EDI, EAX);
416 EDI += (DF << SHIFT);
417}
418
419void OPPROTO glue(op_rep_stos, SUFFIX)(void)
420{
421 int inc;
422 inc = (DF << SHIFT);
423 while (ECX != 0) {
424 glue(st, SUFFIX)((void *)EDI, EAX);
425 EDI += inc;
426 ECX--;
427 }
428}
429
430void OPPROTO glue(op_lods, SUFFIX)(void)
431{
432 int v;
433 v = glue(ldu, SUFFIX)((void *)ESI);
434#if SHIFT == 0
435 EAX = (EAX & ~0xff) | v;
436#elif SHIFT == 1
437 EAX = (EAX & ~0xffff) | v;
438#else
439 EAX = v;
440#endif
441 ESI += (DF << SHIFT);
442}
443
444/* don't know if it is used */
445void OPPROTO glue(op_rep_lods, SUFFIX)(void)
446{
447 int v, inc;
448 inc = (DF << SHIFT);
449 while (ECX != 0) {
450 v = glue(ldu, SUFFIX)((void *)ESI);
451#if SHIFT == 0
452 EAX = (EAX & ~0xff) | v;
453#elif SHIFT == 1
454 EAX = (EAX & ~0xffff) | v;
455#else
456 EAX = v;
457#endif
458 ESI += inc;
459 ECX--;
460 }
461}
462
463void OPPROTO glue(op_scas, SUFFIX)(void)
464{
465 int v;
466
467 v = glue(ldu, SUFFIX)((void *)ESI);
468 ESI += (DF << SHIFT);
469 CC_SRC = EAX;
470 CC_DST = EAX - v;
471}
472
473void OPPROTO glue(op_repz_scas, SUFFIX)(void)
474{
475 int v1, v2, inc;
476
477 if (ECX != 0) {
478 /* NOTE: the flags are not modified if ECX == 0 */
479#if SHIFT == 0
480 v1 = EAX & 0xff;
481#elif SHIFT == 1
482 v1 = EAX & 0xffff;
483#else
484 v1 = EAX;
485#endif
486 inc = (DF << SHIFT);
487 do {
488 v2 = glue(ldu, SUFFIX)((void *)ESI);
489 if (v1 != v2)
490 break;
491 ESI += inc;
492 ECX--;
493 } while (ECX != 0);
494 CC_SRC = v1;
495 CC_DST = v1 - v2;
496 CC_OP = CC_OP_SUBB + SHIFT;
497 }
498}
499
500void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
501{
502 int v1, v2, inc;
503
504 if (ECX != 0) {
505 /* NOTE: the flags are not modified if ECX == 0 */
506#if SHIFT == 0
507 v1 = EAX & 0xff;
508#elif SHIFT == 1
509 v1 = EAX & 0xffff;
510#else
511 v1 = EAX;
512#endif
513 inc = (DF << SHIFT);
514 do {
515 v2 = glue(ldu, SUFFIX)((void *)ESI);
516 if (v1 == v2)
517 break;
518 ESI += inc;
519 ECX--;
520 } while (ECX != 0);
521 CC_SRC = v1;
522 CC_DST = v1 - v2;
523 CC_OP = CC_OP_SUBB + SHIFT;
524 }
525}
526
527void OPPROTO glue(op_cmps, SUFFIX)(void)
528{
529 int v1, v2;
530 v1 = glue(ldu, SUFFIX)((void *)ESI);
531 v2 = glue(ldu, SUFFIX)((void *)EDI);
532 ESI += (DF << SHIFT);
533 EDI += (DF << SHIFT);
534 CC_SRC = v1;
535 CC_DST = v1 - v2;
536}
537
538void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
539{
540 int v1, v2, inc;
541 if (ECX != 0) {
542 inc = (DF << SHIFT);
543 do {
544 v1 = glue(ldu, SUFFIX)((void *)ESI);
545 v2 = glue(ldu, SUFFIX)((void *)EDI);
546 if (v1 != v2)
547 break;
548 ESI += inc;
549 EDI += inc;
550 ECX--;
551 } while (ECX != 0);
552 CC_SRC = v1;
553 CC_DST = v1 - v2;
554 CC_OP = CC_OP_SUBB + SHIFT;
555 }
556}
557
558void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
559{
560 int v1, v2, inc;
561 if (ECX != 0) {
562 inc = (DF << SHIFT);
563 do {
564 v1 = glue(ldu, SUFFIX)((void *)ESI);
565 v2 = glue(ldu, SUFFIX)((void *)EDI);
566 if (v1 == v2)
567 break;
568 ESI += inc;
569 EDI += inc;
570 ECX--;
571 } while (ECX != 0);
572 CC_SRC = v1;
573 CC_DST = v1 - v2;
574 CC_OP = CC_OP_SUBB + SHIFT;
575 }
576}
577
578void OPPROTO glue(op_outs, SUFFIX)(void)
579{
580 int v, dx;
581 dx = EDX & 0xffff;
582 v = glue(ldu, SUFFIX)((void *)ESI);
583 glue(port_out, SUFFIX)(dx, v);
584 ESI += (DF << SHIFT);
585}
586
587void OPPROTO glue(op_rep_outs, SUFFIX)(void)
588{
589 int v, dx, inc;
590 inc = (DF << SHIFT);
591 dx = EDX & 0xffff;
592 while (ECX != 0) {
593 v = glue(ldu, SUFFIX)((void *)ESI);
594 glue(port_out, SUFFIX)(dx, v);
595 ESI += inc;
596 ECX--;
597 }
598}
599
600void OPPROTO glue(op_ins, SUFFIX)(void)
601{
602 int v, dx;
603 dx = EDX & 0xffff;
604 v = glue(port_in, SUFFIX)(dx);
605 glue(st, SUFFIX)((void *)EDI, v);
606 EDI += (DF << SHIFT);
607}
608
609void OPPROTO glue(op_rep_ins, SUFFIX)(void)
610{
611 int v, dx, inc;
612 inc = (DF << SHIFT);
613 dx = EDX & 0xffff;
614 while (ECX != 0) {
615 v = glue(port_in, SUFFIX)(dx);
616 glue(st, SUFFIX)((void *)EDI, v);
617 EDI += (DF << SHIFT);
618 ECX--;
619 }
620}
621
622#undef DATA_BITS
623#undef SHIFT_MASK
624#undef SIGN_MASK
625#undef DATA_TYPE
626#undef DATA_STYPE
627#undef DATA_MASK
628#undef SUFFIX