]> Git Repo - qemu.git/blame - op-i386.c
added helper-i386.c - alpha fixes
[qemu.git] / op-i386.c
CommitLineData
7d13299d
FB
1/*
2 * i386 micro operations
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
3ef693a0
FB
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
7d13299d 10 *
3ef693a0
FB
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
7d13299d 15 *
3ef693a0
FB
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7d13299d
FB
19 */
20#include "exec-i386.h"
7bfdb6d1 21
0ecfa993 22/* NOTE: data are not static to force relocation generation by GCC */
367e86e8 23
7bfdb6d1
FB
24uint8_t parity_table[256] = {
25 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
26 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
27 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
28 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
29 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
30 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
31 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
32 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
33 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
34 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
35 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
36 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
37 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
38 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
39 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
40 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
41 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
42 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
43 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
44 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
45 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
46 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
47 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
48 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
49 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
50 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
51 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
52 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
53 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
54 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
55 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
56 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
57};
58
367e86e8
FB
59/* modulo 17 table */
60const uint8_t rclw_table[32] = {
61 0, 1, 2, 3, 4, 5, 6, 7,
62 8, 9,10,11,12,13,14,15,
63 16, 0, 1, 2, 3, 4, 5, 6,
64 7, 8, 9,10,11,12,13,14,
65};
7bfdb6d1 66
367e86e8
FB
67/* modulo 9 table */
68const uint8_t rclb_table[32] = {
69 0, 1, 2, 3, 4, 5, 6, 7,
70 8, 0, 1, 2, 3, 4, 5, 6,
71 7, 8, 0, 1, 2, 3, 4, 5,
72 6, 7, 8, 0, 1, 2, 3, 4,
73};
7bfdb6d1 74
927f621e
FB
75#ifdef USE_X86LDOUBLE
76/* an array of Intel 80-bit FP constants, to be loaded via integer ops */
77typedef unsigned short f15ld[5];
78const f15ld f15rk[] =
79{
80/*0*/ {0x0000,0x0000,0x0000,0x0000,0x0000},
81/*1*/ {0x0000,0x0000,0x0000,0x8000,0x3fff},
82/*pi*/ {0xc235,0x2168,0xdaa2,0xc90f,0x4000},
83/*lg2*/ {0xf799,0xfbcf,0x9a84,0x9a20,0x3ffd},
84/*ln2*/ {0x79ac,0xd1cf,0x17f7,0xb172,0x3ffe},
85/*l2e*/ {0xf0bc,0x5c17,0x3b29,0xb8aa,0x3fff},
86/*l2t*/ {0x8afe,0xcd1b,0x784b,0xd49a,0x4000}
87};
88#else
89/* the same, 64-bit version */
90typedef unsigned short f15ld[4];
91const f15ld f15rk[] =
92{
93#ifndef WORDS_BIGENDIAN
94/*0*/ {0x0000,0x0000,0x0000,0x0000},
95/*1*/ {0x0000,0x0000,0x0000,0x3ff0},
96/*pi*/ {0x2d18,0x5444,0x21fb,0x4009},
97/*lg2*/ {0x79ff,0x509f,0x4413,0x3fd3},
98/*ln2*/ {0x39ef,0xfefa,0x2e42,0x3fe6},
99/*l2e*/ {0x82fe,0x652b,0x1547,0x3ff7},
100/*l2t*/ {0xa371,0x0979,0x934f,0x400a}
101#else
102/*0*/ {0x0000,0x0000,0x0000,0x0000},
103/*1*/ {0x3ff0,0x0000,0x0000,0x0000},
104/*pi*/ {0x4009,0x21fb,0x5444,0x2d18},
105/*lg2*/ {0x3fd3,0x4413,0x509f,0x79ff},
106/*ln2*/ {0x3fe6,0x2e42,0xfefa,0x39ef},
107/*l2e*/ {0x3ff7,0x1547,0x652b,0x82fe},
108/*l2t*/ {0x400a,0x934f,0x0979,0xa371}
109#endif
110};
111#endif
112
367e86e8
FB
113/* n must be a constant to be efficient */
114static inline int lshift(int x, int n)
7bfdb6d1 115{
367e86e8
FB
116 if (n >= 0)
117 return x << n;
118 else
119 return x >> (-n);
7bfdb6d1 120}
7bfdb6d1
FB
121
122/* we define the various pieces of code used by the JIT */
123
124#define REG EAX
125#define REGNAME _EAX
126#include "opreg_template.h"
127#undef REG
128#undef REGNAME
129
130#define REG ECX
131#define REGNAME _ECX
132#include "opreg_template.h"
133#undef REG
134#undef REGNAME
135
136#define REG EDX
137#define REGNAME _EDX
138#include "opreg_template.h"
139#undef REG
140#undef REGNAME
141
142#define REG EBX
143#define REGNAME _EBX
144#include "opreg_template.h"
145#undef REG
146#undef REGNAME
147
148#define REG ESP
149#define REGNAME _ESP
150#include "opreg_template.h"
151#undef REG
152#undef REGNAME
153
154#define REG EBP
155#define REGNAME _EBP
156#include "opreg_template.h"
157#undef REG
158#undef REGNAME
159
160#define REG ESI
161#define REGNAME _ESI
162#include "opreg_template.h"
163#undef REG
164#undef REGNAME
165
166#define REG EDI
167#define REGNAME _EDI
168#include "opreg_template.h"
169#undef REG
170#undef REGNAME
171
dc99065b 172/* operations with flags */
7bfdb6d1
FB
173
174void OPPROTO op_addl_T0_T1_cc(void)
175{
176 CC_SRC = T0;
177 T0 += T1;
178 CC_DST = T0;
179}
180
181void OPPROTO op_orl_T0_T1_cc(void)
182{
183 T0 |= T1;
184 CC_DST = T0;
185}
186
7bfdb6d1
FB
187void OPPROTO op_andl_T0_T1_cc(void)
188{
189 T0 &= T1;
190 CC_DST = T0;
191}
192
193void OPPROTO op_subl_T0_T1_cc(void)
194{
195 CC_SRC = T0;
196 T0 -= T1;
197 CC_DST = T0;
198}
199
200void OPPROTO op_xorl_T0_T1_cc(void)
201{
202 T0 ^= T1;
203 CC_DST = T0;
204}
205
206void OPPROTO op_cmpl_T0_T1_cc(void)
207{
208 CC_SRC = T0;
209 CC_DST = T0 - T1;
210}
211
7bfdb6d1
FB
212void OPPROTO op_negl_T0_cc(void)
213{
214 CC_SRC = 0;
215 T0 = -T0;
216 CC_DST = T0;
217}
218
219void OPPROTO op_incl_T0_cc(void)
220{
4b74fe1f 221 CC_SRC = cc_table[CC_OP].compute_c();
7bfdb6d1
FB
222 T0++;
223 CC_DST = T0;
224}
225
226void OPPROTO op_decl_T0_cc(void)
227{
4b74fe1f 228 CC_SRC = cc_table[CC_OP].compute_c();
7bfdb6d1
FB
229 T0--;
230 CC_DST = T0;
231}
232
233void OPPROTO op_testl_T0_T1_cc(void)
234{
7bfdb6d1
FB
235 CC_DST = T0 & T1;
236}
237
dc99065b
FB
238/* operations without flags */
239
240void OPPROTO op_addl_T0_T1(void)
241{
242 T0 += T1;
243}
244
245void OPPROTO op_orl_T0_T1(void)
246{
247 T0 |= T1;
248}
249
250void OPPROTO op_andl_T0_T1(void)
251{
252 T0 &= T1;
253}
254
255void OPPROTO op_subl_T0_T1(void)
256{
257 T0 -= T1;
258}
259
260void OPPROTO op_xorl_T0_T1(void)
261{
262 T0 ^= T1;
263}
264
265void OPPROTO op_negl_T0(void)
266{
267 T0 = -T0;
268}
269
270void OPPROTO op_incl_T0(void)
271{
272 T0++;
273}
274
275void OPPROTO op_decl_T0(void)
276{
277 T0--;
278}
279
280void OPPROTO op_notl_T0(void)
281{
282 T0 = ~T0;
283}
284
4b74fe1f
FB
285void OPPROTO op_bswapl_T0(void)
286{
287 T0 = bswap32(T0);
288}
289
7bfdb6d1
FB
290/* multiply/divide */
291void OPPROTO op_mulb_AL_T0(void)
292{
293 unsigned int res;
294 res = (uint8_t)EAX * (uint8_t)T0;
295 EAX = (EAX & 0xffff0000) | res;
296 CC_SRC = (res & 0xff00);
297}
298
299void OPPROTO op_imulb_AL_T0(void)
300{
301 int res;
302 res = (int8_t)EAX * (int8_t)T0;
303 EAX = (EAX & 0xffff0000) | (res & 0xffff);
304 CC_SRC = (res != (int8_t)res);
305}
306
307void OPPROTO op_mulw_AX_T0(void)
308{
309 unsigned int res;
310 res = (uint16_t)EAX * (uint16_t)T0;
311 EAX = (EAX & 0xffff0000) | (res & 0xffff);
312 EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
313 CC_SRC = res >> 16;
314}
315
316void OPPROTO op_imulw_AX_T0(void)
317{
318 int res;
319 res = (int16_t)EAX * (int16_t)T0;
320 EAX = (EAX & 0xffff0000) | (res & 0xffff);
321 EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff);
322 CC_SRC = (res != (int16_t)res);
323}
324
325void OPPROTO op_mull_EAX_T0(void)
326{
327 uint64_t res;
328 res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0);
329 EAX = res;
330 EDX = res >> 32;
331 CC_SRC = res >> 32;
332}
333
334void OPPROTO op_imull_EAX_T0(void)
335{
336 int64_t res;
337 res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0);
338 EAX = res;
339 EDX = res >> 32;
340 CC_SRC = (res != (int32_t)res);
341}
342
343void OPPROTO op_imulw_T0_T1(void)
344{
345 int res;
346 res = (int16_t)T0 * (int16_t)T1;
347 T0 = res;
348 CC_SRC = (res != (int16_t)res);
349}
350
351void OPPROTO op_imull_T0_T1(void)
352{
353 int64_t res;
4b74fe1f 354 res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
7bfdb6d1
FB
355 T0 = res;
356 CC_SRC = (res != (int32_t)res);
357}
358
359/* division, flags are undefined */
9de5e440 360/* XXX: add exceptions for overflow */
7bfdb6d1
FB
361void OPPROTO op_divb_AL_T0(void)
362{
363 unsigned int num, den, q, r;
364
365 num = (EAX & 0xffff);
366 den = (T0 & 0xff);
f4beb510
FB
367 if (den == 0) {
368 EIP = PARAM1;
9de5e440 369 raise_exception(EXCP00_DIVZ);
f4beb510 370 }
7bfdb6d1
FB
371 q = (num / den) & 0xff;
372 r = (num % den) & 0xff;
373 EAX = (EAX & 0xffff0000) | (r << 8) | q;
374}
375
376void OPPROTO op_idivb_AL_T0(void)
377{
378 int num, den, q, r;
379
380 num = (int16_t)EAX;
381 den = (int8_t)T0;
f4beb510
FB
382 if (den == 0) {
383 EIP = PARAM1;
9de5e440 384 raise_exception(EXCP00_DIVZ);
f4beb510 385 }
7bfdb6d1
FB
386 q = (num / den) & 0xff;
387 r = (num % den) & 0xff;
388 EAX = (EAX & 0xffff0000) | (r << 8) | q;
389}
390
391void OPPROTO op_divw_AX_T0(void)
392{
393 unsigned int num, den, q, r;
394
395 num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
396 den = (T0 & 0xffff);
f4beb510
FB
397 if (den == 0) {
398 EIP = PARAM1;
9de5e440 399 raise_exception(EXCP00_DIVZ);
f4beb510 400 }
7bfdb6d1
FB
401 q = (num / den) & 0xffff;
402 r = (num % den) & 0xffff;
403 EAX = (EAX & 0xffff0000) | q;
404 EDX = (EDX & 0xffff0000) | r;
405}
406
407void OPPROTO op_idivw_AX_T0(void)
408{
409 int num, den, q, r;
410
411 num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
412 den = (int16_t)T0;
f4beb510
FB
413 if (den == 0) {
414 EIP = PARAM1;
9de5e440 415 raise_exception(EXCP00_DIVZ);
f4beb510 416 }
7bfdb6d1
FB
417 q = (num / den) & 0xffff;
418 r = (num % den) & 0xffff;
419 EAX = (EAX & 0xffff0000) | q;
420 EDX = (EDX & 0xffff0000) | r;
421}
422
51fe6890
FB
423#ifdef BUGGY_GCC_DIV64
424/* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
425 call it from another function */
426uint32_t div64(uint32_t *q_ptr, uint64_t num, uint32_t den)
427{
428 *q_ptr = num / den;
429 return num % den;
430}
431
432int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den)
433{
434 *q_ptr = num / den;
435 return num % den;
436}
437#endif
438
7bfdb6d1
FB
439void OPPROTO op_divl_EAX_T0(void)
440{
441 unsigned int den, q, r;
442 uint64_t num;
443
444 num = EAX | ((uint64_t)EDX << 32);
445 den = T0;
f4beb510
FB
446 if (den == 0) {
447 EIP = PARAM1;
9de5e440 448 raise_exception(EXCP00_DIVZ);
f4beb510 449 }
51fe6890
FB
450#ifdef BUGGY_GCC_DIV64
451 r = div64(&q, num, den);
452#else
7bfdb6d1
FB
453 q = (num / den);
454 r = (num % den);
51fe6890 455#endif
7bfdb6d1
FB
456 EAX = q;
457 EDX = r;
458}
459
460void OPPROTO op_idivl_EAX_T0(void)
461{
462 int den, q, r;
4b74fe1f 463 int64_t num;
7bfdb6d1
FB
464
465 num = EAX | ((uint64_t)EDX << 32);
4b74fe1f 466 den = T0;
f4beb510
FB
467 if (den == 0) {
468 EIP = PARAM1;
9de5e440 469 raise_exception(EXCP00_DIVZ);
f4beb510 470 }
51fe6890
FB
471#ifdef BUGGY_GCC_DIV64
472 r = idiv64(&q, num, den);
473#else
7bfdb6d1
FB
474 q = (num / den);
475 r = (num % den);
51fe6890 476#endif
7bfdb6d1
FB
477 EAX = q;
478 EDX = r;
479}
480
dab2ed99 481/* constant load & misc op */
7bfdb6d1 482
ba1c6e37 483void OPPROTO op_movl_T0_im(void)
7bfdb6d1
FB
484{
485 T0 = PARAM1;
486}
487
dab2ed99
FB
488void OPPROTO op_addl_T0_im(void)
489{
490 T0 += PARAM1;
491}
492
493void OPPROTO op_andl_T0_ffff(void)
494{
495 T0 = T0 & 0xffff;
496}
497
498void OPPROTO op_movl_T0_T1(void)
499{
500 T0 = T1;
501}
502
ba1c6e37 503void OPPROTO op_movl_T1_im(void)
7bfdb6d1
FB
504{
505 T1 = PARAM1;
506}
507
dab2ed99
FB
508void OPPROTO op_addl_T1_im(void)
509{
510 T1 += PARAM1;
511}
512
513void OPPROTO op_movl_T1_A0(void)
514{
515 T1 = A0;
516}
517
ba1c6e37 518void OPPROTO op_movl_A0_im(void)
7bfdb6d1
FB
519{
520 A0 = PARAM1;
521}
522
4b74fe1f
FB
523void OPPROTO op_addl_A0_im(void)
524{
525 A0 += PARAM1;
526}
527
31bb950b
FB
528void OPPROTO op_addl_A0_AL(void)
529{
530 A0 += (EAX & 0xff);
531}
532
4b74fe1f
FB
533void OPPROTO op_andl_A0_ffff(void)
534{
535 A0 = A0 & 0xffff;
536}
537
7bfdb6d1
FB
538/* memory access */
539
540void OPPROTO op_ldub_T0_A0(void)
541{
542 T0 = ldub((uint8_t *)A0);
543}
544
545void OPPROTO op_ldsb_T0_A0(void)
546{
547 T0 = ldsb((int8_t *)A0);
548}
549
550void OPPROTO op_lduw_T0_A0(void)
551{
552 T0 = lduw((uint8_t *)A0);
553}
554
555void OPPROTO op_ldsw_T0_A0(void)
556{
557 T0 = ldsw((int8_t *)A0);
558}
559
560void OPPROTO op_ldl_T0_A0(void)
561{
562 T0 = ldl((uint8_t *)A0);
563}
564
565void OPPROTO op_ldub_T1_A0(void)
566{
567 T1 = ldub((uint8_t *)A0);
568}
569
570void OPPROTO op_ldsb_T1_A0(void)
571{
572 T1 = ldsb((int8_t *)A0);
573}
574
575void OPPROTO op_lduw_T1_A0(void)
576{
577 T1 = lduw((uint8_t *)A0);
578}
579
580void OPPROTO op_ldsw_T1_A0(void)
581{
582 T1 = ldsw((int8_t *)A0);
583}
584
585void OPPROTO op_ldl_T1_A0(void)
586{
587 T1 = ldl((uint8_t *)A0);
588}
589
590void OPPROTO op_stb_T0_A0(void)
591{
592 stb((uint8_t *)A0, T0);
593}
594
595void OPPROTO op_stw_T0_A0(void)
596{
597 stw((uint8_t *)A0, T0);
598}
599
600void OPPROTO op_stl_T0_A0(void)
601{
602 stl((uint8_t *)A0, T0);
603}
604
4b74fe1f
FB
605/* used for bit operations */
606
607void OPPROTO op_add_bitw_A0_T1(void)
608{
609 A0 += ((int32_t)T1 >> 4) << 1;
610}
611
612void OPPROTO op_add_bitl_A0_T1(void)
613{
614 A0 += ((int32_t)T1 >> 5) << 2;
615}
7bfdb6d1
FB
616
617/* indirect jump */
0ecfa993 618
7bfdb6d1
FB
619void OPPROTO op_jmp_T0(void)
620{
dab2ed99 621 EIP = T0;
7bfdb6d1
FB
622}
623
624void OPPROTO op_jmp_im(void)
625{
dab2ed99 626 EIP = PARAM1;
7bfdb6d1
FB
627}
628
f4beb510 629void OPPROTO op_raise_interrupt(void)
0ecfa993 630{
504e56eb 631 int intno;
f4beb510 632 unsigned int next_eip;
504e56eb 633 intno = PARAM1;
f4beb510
FB
634 next_eip = PARAM2;
635 raise_interrupt(intno, 1, 0, next_eip);
0ecfa993
FB
636}
637
564c8f99 638void OPPROTO op_raise_exception(void)
0ecfa993 639{
564c8f99
FB
640 int exception_index;
641 exception_index = PARAM1;
642 raise_exception(exception_index);
0ecfa993
FB
643}
644
645void OPPROTO op_into(void)
646{
647 int eflags;
648 eflags = cc_table[CC_OP].compute_all();
649 if (eflags & CC_O) {
f4beb510 650 raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
a4a0ffdb 651 }
504e56eb 652 FORCE_RET();
a4a0ffdb
FB
653}
654
504e56eb
FB
655void OPPROTO op_cli(void)
656{
657 env->eflags &= ~IF_MASK;
658}
659
f631ef9b
FB
660void OPPROTO op_sti(void)
661{
504e56eb 662 env->eflags |= IF_MASK;
f631ef9b
FB
663}
664
3acace13 665#if 0
f631ef9b 666/* vm86plus instructions */
f631ef9b
FB
667void OPPROTO op_cli_vm(void)
668{
669 env->eflags &= ~VIF_MASK;
670}
671
672void OPPROTO op_sti_vm(void)
673{
674 env->eflags |= VIF_MASK;
675 if (env->eflags & VIP_MASK) {
676 EIP = PARAM1;
677 raise_exception(EXCP0D_GPF);
678 }
679 FORCE_RET();
680}
3acace13 681#endif
f631ef9b 682
a4a0ffdb
FB
683void OPPROTO op_boundw(void)
684{
685 int low, high, v;
686 low = ldsw((uint8_t *)A0);
687 high = ldsw((uint8_t *)A0 + 2);
688 v = (int16_t)T0;
f4beb510
FB
689 if (v < low || v > high) {
690 EIP = PARAM1;
a4a0ffdb 691 raise_exception(EXCP05_BOUND);
f4beb510 692 }
a4a0ffdb
FB
693 FORCE_RET();
694}
695
696void OPPROTO op_boundl(void)
697{
698 int low, high, v;
699 low = ldl((uint8_t *)A0);
700 high = ldl((uint8_t *)A0 + 4);
701 v = T0;
f4beb510
FB
702 if (v < low || v > high) {
703 EIP = PARAM1;
a4a0ffdb 704 raise_exception(EXCP05_BOUND);
f4beb510 705 }
a4a0ffdb
FB
706 FORCE_RET();
707}
708
709void OPPROTO op_cmpxchg8b(void)
710{
711 uint64_t d;
712 int eflags;
713
714 eflags = cc_table[CC_OP].compute_all();
715 d = ldq((uint8_t *)A0);
716 if (d == (((uint64_t)EDX << 32) | EAX)) {
717 stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX);
718 eflags |= CC_Z;
0ecfa993 719 } else {
a4a0ffdb
FB
720 EDX = d >> 32;
721 EAX = d;
722 eflags &= ~CC_Z;
0ecfa993 723 }
a4a0ffdb
FB
724 CC_SRC = eflags;
725 FORCE_RET();
0ecfa993
FB
726}
727
d4e8164f
FB
728#if defined(__powerpc__)
729
730/* on PowerPC we patch the jump instruction directly */
731#define JUMP_TB(tbparam, n, eip)\
732do {\
733 static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
734 asm volatile ("b %0" : : "i" (&__op_jmp ## n));\
735label ## n:\
736 T0 = (long)(tbparam) + (n);\
737 EIP = eip;\
738} while (0)
739
740#else
741
742/* jump to next block operations (more portable code, does not need
743 cache flushing, but slower because of indirect jump) */
744#define JUMP_TB(tbparam, n, eip)\
745do {\
746 static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
3ec9c4fc 747 goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
d4e8164f
FB
748label ## n:\
749 T0 = (long)(tbparam) + (n);\
750 EIP = eip;\
751} while (0)
752
753#endif
754
755void OPPROTO op_jmp_tb_next(void)
756{
757 JUMP_TB(PARAM1, 0, PARAM2);
758}
759
760void OPPROTO op_movl_T0_0(void)
761{
762 T0 = 0;
763}
764
765/* multiple size ops */
7bfdb6d1
FB
766
767#define ldul ldl
768
7bfdb6d1 769#define SHIFT 0
367e86e8 770#include "ops_template.h"
7bfdb6d1
FB
771#undef SHIFT
772
7bfdb6d1 773#define SHIFT 1
367e86e8 774#include "ops_template.h"
7bfdb6d1
FB
775#undef SHIFT
776
7bfdb6d1 777#define SHIFT 2
367e86e8 778#include "ops_template.h"
7bfdb6d1
FB
779#undef SHIFT
780
781/* sign extend */
782
783void OPPROTO op_movsbl_T0_T0(void)
784{
785 T0 = (int8_t)T0;
786}
787
788void OPPROTO op_movzbl_T0_T0(void)
789{
790 T0 = (uint8_t)T0;
791}
792
793void OPPROTO op_movswl_T0_T0(void)
794{
795 T0 = (int16_t)T0;
796}
797
798void OPPROTO op_movzwl_T0_T0(void)
799{
800 T0 = (uint16_t)T0;
801}
802
803void OPPROTO op_movswl_EAX_AX(void)
804{
805 EAX = (int16_t)EAX;
806}
807
808void OPPROTO op_movsbw_AX_AL(void)
809{
810 EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff);
811}
812
813void OPPROTO op_movslq_EDX_EAX(void)
814{
815 EDX = (int32_t)EAX >> 31;
816}
817
818void OPPROTO op_movswl_DX_AX(void)
819{
820 EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
821}
822
823/* push/pop */
7bfdb6d1
FB
824
825void op_pushl_T0(void)
826{
827 uint32_t offset;
828 offset = ESP - 4;
829 stl((void *)offset, T0);
830 /* modify ESP after to handle exceptions correctly */
831 ESP = offset;
832}
833
dab2ed99
FB
834void op_pushw_T0(void)
835{
836 uint32_t offset;
837 offset = ESP - 2;
838 stw((void *)offset, T0);
839 /* modify ESP after to handle exceptions correctly */
840 ESP = offset;
841}
842
843void op_pushl_ss32_T0(void)
7bfdb6d1
FB
844{
845 uint32_t offset;
846 offset = ESP - 4;
dab2ed99
FB
847 stl(env->seg_cache[R_SS].base + offset, T0);
848 /* modify ESP after to handle exceptions correctly */
849 ESP = offset;
850}
851
852void op_pushw_ss32_T0(void)
853{
854 uint32_t offset;
855 offset = ESP - 2;
856 stw(env->seg_cache[R_SS].base + offset, T0);
7bfdb6d1
FB
857 /* modify ESP after to handle exceptions correctly */
858 ESP = offset;
859}
860
dab2ed99
FB
861void op_pushl_ss16_T0(void)
862{
863 uint32_t offset;
864 offset = (ESP - 4) & 0xffff;
865 stl(env->seg_cache[R_SS].base + offset, T0);
866 /* modify ESP after to handle exceptions correctly */
867 ESP = (ESP & ~0xffff) | offset;
868}
869
870void op_pushw_ss16_T0(void)
871{
872 uint32_t offset;
873 offset = (ESP - 2) & 0xffff;
874 stw(env->seg_cache[R_SS].base + offset, T0);
875 /* modify ESP after to handle exceptions correctly */
876 ESP = (ESP & ~0xffff) | offset;
877}
878
879/* NOTE: ESP update is done after */
7bfdb6d1
FB
880void op_popl_T0(void)
881{
882 T0 = ldl((void *)ESP);
dab2ed99
FB
883}
884
885void op_popw_T0(void)
886{
887 T0 = lduw((void *)ESP);
888}
889
890void op_popl_ss32_T0(void)
891{
892 T0 = ldl(env->seg_cache[R_SS].base + ESP);
893}
894
895void op_popw_ss32_T0(void)
896{
897 T0 = lduw(env->seg_cache[R_SS].base + ESP);
898}
899
900void op_popl_ss16_T0(void)
901{
902 T0 = ldl(env->seg_cache[R_SS].base + (ESP & 0xffff));
903}
904
905void op_popw_ss16_T0(void)
906{
907 T0 = lduw(env->seg_cache[R_SS].base + (ESP & 0xffff));
908}
909
910void op_addl_ESP_4(void)
911{
7bfdb6d1
FB
912 ESP += 4;
913}
914
dab2ed99
FB
915void op_addl_ESP_2(void)
916{
917 ESP += 2;
918}
919
920void op_addw_ESP_4(void)
921{
922 ESP = (ESP & ~0xffff) | ((ESP + 4) & 0xffff);
923}
924
925void op_addw_ESP_2(void)
926{
927 ESP = (ESP & ~0xffff) | ((ESP + 2) & 0xffff);
928}
929
7bfdb6d1
FB
930void op_addl_ESP_im(void)
931{
932 ESP += PARAM1;
933}
367e86e8 934
dab2ed99
FB
935void op_addw_ESP_im(void)
936{
937 ESP = (ESP & ~0xffff) | ((ESP + PARAM1) & 0xffff);
27362c82
FB
938}
939
940/* rdtsc */
941#ifndef __i386__
942uint64_t emu_time;
943#endif
a4a0ffdb
FB
944
945void OPPROTO op_rdtsc(void)
27362c82
FB
946{
947 uint64_t val;
948#ifdef __i386__
949 asm("rdtsc" : "=A" (val));
950#else
951 /* better than nothing: the time increases */
952 val = emu_time++;
953#endif
954 EAX = val;
955 EDX = val >> 32;
956}
957
a4a0ffdb
FB
958void OPPROTO op_cpuid(void)
959{
960 helper_cpuid();
961}
962
27362c82
FB
963/* bcd */
964
965/* XXX: exception */
966void OPPROTO op_aam(void)
967{
968 int base = PARAM1;
969 int al, ah;
970 al = EAX & 0xff;
971 ah = al / base;
972 al = al % base;
973 EAX = (EAX & ~0xffff) | al | (ah << 8);
974 CC_DST = al;
975}
976
977void OPPROTO op_aad(void)
978{
979 int base = PARAM1;
980 int al, ah;
981 al = EAX & 0xff;
982 ah = (EAX >> 8) & 0xff;
983 al = ((ah * base) + al) & 0xff;
984 EAX = (EAX & ~0xffff) | al;
985 CC_DST = al;
986}
987
988void OPPROTO op_aaa(void)
989{
990 int icarry;
991 int al, ah, af;
992 int eflags;
993
994 eflags = cc_table[CC_OP].compute_all();
995 af = eflags & CC_A;
996 al = EAX & 0xff;
997 ah = (EAX >> 8) & 0xff;
998
999 icarry = (al > 0xf9);
1000 if (((al & 0x0f) > 9 ) || af) {
1001 al = (al + 6) & 0x0f;
1002 ah = (ah + 1 + icarry) & 0xff;
1003 eflags |= CC_C | CC_A;
1004 } else {
1005 eflags &= ~(CC_C | CC_A);
1006 al &= 0x0f;
1007 }
1008 EAX = (EAX & ~0xffff) | al | (ah << 8);
1009 CC_SRC = eflags;
1010}
1011
1012void OPPROTO op_aas(void)
1013{
1014 int icarry;
1015 int al, ah, af;
1016 int eflags;
1017
1018 eflags = cc_table[CC_OP].compute_all();
1019 af = eflags & CC_A;
1020 al = EAX & 0xff;
1021 ah = (EAX >> 8) & 0xff;
1022
1023 icarry = (al < 6);
1024 if (((al & 0x0f) > 9 ) || af) {
1025 al = (al - 6) & 0x0f;
1026 ah = (ah - 1 - icarry) & 0xff;
1027 eflags |= CC_C | CC_A;
1028 } else {
1029 eflags &= ~(CC_C | CC_A);
1030 al &= 0x0f;
1031 }
1032 EAX = (EAX & ~0xffff) | al | (ah << 8);
1033 CC_SRC = eflags;
1034}
1035
1036void OPPROTO op_daa(void)
1037{
1038 int al, af, cf;
1039 int eflags;
1040
1041 eflags = cc_table[CC_OP].compute_all();
1042 cf = eflags & CC_C;
1043 af = eflags & CC_A;
1044 al = EAX & 0xff;
1045
1046 eflags = 0;
1047 if (((al & 0x0f) > 9 ) || af) {
1048 al = (al + 6) & 0xff;
1049 eflags |= CC_A;
1050 }
1051 if ((al > 0x9f) || cf) {
1052 al = (al + 0x60) & 0xff;
1053 eflags |= CC_C;
1054 }
1055 EAX = (EAX & ~0xff) | al;
1056 /* well, speed is not an issue here, so we compute the flags by hand */
1057 eflags |= (al == 0) << 6; /* zf */
1058 eflags |= parity_table[al]; /* pf */
1059 eflags |= (al & 0x80); /* sf */
1060 CC_SRC = eflags;
1061}
1062
1063void OPPROTO op_das(void)
1064{
1065 int al, al1, af, cf;
1066 int eflags;
1067
1068 eflags = cc_table[CC_OP].compute_all();
1069 cf = eflags & CC_C;
1070 af = eflags & CC_A;
1071 al = EAX & 0xff;
1072
1073 eflags = 0;
1074 al1 = al;
1075 if (((al & 0x0f) > 9 ) || af) {
1076 eflags |= CC_A;
1077 if (al < 6 || cf)
1078 eflags |= CC_C;
1079 al = (al - 6) & 0xff;
1080 }
1081 if ((al1 > 0x99) || cf) {
1082 al = (al - 0x60) & 0xff;
1083 eflags |= CC_C;
1084 }
1085 EAX = (EAX & ~0xff) | al;
1086 /* well, speed is not an issue here, so we compute the flags by hand */
1087 eflags |= (al == 0) << 6; /* zf */
1088 eflags |= parity_table[al]; /* pf */
1089 eflags |= (al & 0x80); /* sf */
1090 CC_SRC = eflags;
1091}
1092
6dbad63e
FB
1093/* segment handling */
1094
6dbad63e
FB
1095void OPPROTO op_movl_seg_T0(void)
1096{
f4beb510
FB
1097 load_seg(PARAM1, T0 & 0xffff, PARAM2);
1098}
1099
1100/* faster VM86 version */
1101void OPPROTO op_movl_seg_T0_vm(void)
1102{
1103 int selector;
1104
1105 selector = T0 & 0xffff;
1106 /* env->segs[] access */
1107 *(uint32_t *)((char *)env + PARAM1) = selector;
1108 /* env->seg_cache[] access */
1109 ((SegmentCache *)((char *)env + PARAM2))->base = (void *)(selector << 4);
6dbad63e
FB
1110}
1111
1112void OPPROTO op_movl_T0_seg(void)
1113{
1114 T0 = env->segs[PARAM1];
1115}
1116
a4a0ffdb
FB
1117void OPPROTO op_movl_A0_seg(void)
1118{
1119 A0 = *(unsigned long *)((char *)env + PARAM1);
1120}
1121
6dbad63e
FB
1122void OPPROTO op_addl_A0_seg(void)
1123{
1124 A0 += *(unsigned long *)((char *)env + PARAM1);
1125}
1126
2792c4f2
FB
1127void OPPROTO op_lsl(void)
1128{
1129 helper_lsl();
1130}
1131
2792c4f2
FB
1132void OPPROTO op_lar(void)
1133{
1134 helper_lar();
1135}
1136
367e86e8
FB
1137/* flags handling */
1138
d4e8164f
FB
1139/* slow jumps cases : in order to avoid calling a function with a
1140 pointer (which can generate a stack frame on PowerPC), we use
1141 op_setcc to set T0 and then call op_jcc. */
1142void OPPROTO op_jcc(void)
367e86e8 1143{
d4e8164f
FB
1144 if (T0)
1145 JUMP_TB(PARAM1, 0, PARAM2);
367e86e8 1146 else
d4e8164f 1147 JUMP_TB(PARAM1, 1, PARAM3);
0ecfa993 1148 FORCE_RET();
367e86e8
FB
1149}
1150
1151/* slow set cases (compute x86 flags) */
1152void OPPROTO op_seto_T0_cc(void)
1153{
1154 int eflags;
1155 eflags = cc_table[CC_OP].compute_all();
1156 T0 = (eflags >> 11) & 1;
1157}
1158
1159void OPPROTO op_setb_T0_cc(void)
1160{
1161 T0 = cc_table[CC_OP].compute_c();
1162}
1163
1164void OPPROTO op_setz_T0_cc(void)
1165{
1166 int eflags;
1167 eflags = cc_table[CC_OP].compute_all();
1168 T0 = (eflags >> 6) & 1;
1169}
1170
1171void OPPROTO op_setbe_T0_cc(void)
1172{
1173 int eflags;
1174 eflags = cc_table[CC_OP].compute_all();
1175 T0 = (eflags & (CC_Z | CC_C)) != 0;
1176}
1177
1178void OPPROTO op_sets_T0_cc(void)
1179{
1180 int eflags;
1181 eflags = cc_table[CC_OP].compute_all();
1182 T0 = (eflags >> 7) & 1;
1183}
1184
1185void OPPROTO op_setp_T0_cc(void)
1186{
1187 int eflags;
1188 eflags = cc_table[CC_OP].compute_all();
1189 T0 = (eflags >> 2) & 1;
1190}
1191
1192void OPPROTO op_setl_T0_cc(void)
1193{
1194 int eflags;
1195 eflags = cc_table[CC_OP].compute_all();
1196 T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
1197}
1198
1199void OPPROTO op_setle_T0_cc(void)
1200{
1201 int eflags;
1202 eflags = cc_table[CC_OP].compute_all();
1203 T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
1204}
1205
1206void OPPROTO op_xor_T0_1(void)
1207{
1208 T0 ^= 1;
1209}
1210
1211void OPPROTO op_set_cc_op(void)
1212{
1213 CC_OP = PARAM1;
1214}
1215
f631ef9b
FB
1216#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK)
1217#define FL_UPDATE_MASK16 (TF_MASK)
a4a0ffdb 1218
367e86e8
FB
1219void OPPROTO op_movl_eflags_T0(void)
1220{
a4a0ffdb
FB
1221 int eflags;
1222 eflags = T0;
1223 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1224 DF = 1 - (2 * ((eflags >> 10) & 1));
1225 /* we also update some system flags as in user mode */
f631ef9b
FB
1226 env->eflags = (env->eflags & ~FL_UPDATE_MASK32) | (eflags & FL_UPDATE_MASK32);
1227}
1228
1229void OPPROTO op_movw_eflags_T0(void)
1230{
1231 int eflags;
1232 eflags = T0;
1233 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1234 DF = 1 - (2 * ((eflags >> 10) & 1));
1235 /* we also update some system flags as in user mode */
1236 env->eflags = (env->eflags & ~FL_UPDATE_MASK16) | (eflags & FL_UPDATE_MASK16);
1237}
1238
3acace13
FB
1239#if 0
1240/* vm86plus version */
f631ef9b
FB
1241void OPPROTO op_movw_eflags_T0_vm(void)
1242{
1243 int eflags;
1244 eflags = T0;
1245 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1246 DF = 1 - (2 * ((eflags >> 10) & 1));
1247 /* we also update some system flags as in user mode */
1248 env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
1249 (eflags & FL_UPDATE_MASK16);
1250 if (eflags & IF_MASK) {
1251 env->eflags |= VIF_MASK;
1252 if (env->eflags & VIP_MASK) {
1253 EIP = PARAM1;
1254 raise_exception(EXCP0D_GPF);
1255 }
1256 }
1257 FORCE_RET();
1258}
1259
1260void OPPROTO op_movl_eflags_T0_vm(void)
1261{
1262 int eflags;
1263 eflags = T0;
1264 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1265 DF = 1 - (2 * ((eflags >> 10) & 1));
1266 /* we also update some system flags as in user mode */
1267 env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
1268 (eflags & FL_UPDATE_MASK32);
1269 if (eflags & IF_MASK) {
1270 env->eflags |= VIF_MASK;
1271 if (env->eflags & VIP_MASK) {
1272 EIP = PARAM1;
1273 raise_exception(EXCP0D_GPF);
1274 }
1275 }
1276 FORCE_RET();
367e86e8 1277}
3acace13 1278#endif
367e86e8
FB
1279
1280/* XXX: compute only O flag */
1281void OPPROTO op_movb_eflags_T0(void)
1282{
1283 int of;
1284 of = cc_table[CC_OP].compute_all() & CC_O;
a4a0ffdb 1285 CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
367e86e8
FB
1286}
1287
1288void OPPROTO op_movl_T0_eflags(void)
1289{
a4a0ffdb
FB
1290 int eflags;
1291 eflags = cc_table[CC_OP].compute_all();
1292 eflags |= (DF & DF_MASK);
1293 eflags |= env->eflags & ~(VM_MASK | RF_MASK);
1294 T0 = eflags;
367e86e8
FB
1295}
1296
3acace13
FB
1297/* vm86plus version */
1298#if 0
f631ef9b
FB
1299void OPPROTO op_movl_T0_eflags_vm(void)
1300{
1301 int eflags;
1302 eflags = cc_table[CC_OP].compute_all();
1303 eflags |= (DF & DF_MASK);
1304 eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
1305 if (env->eflags & VIF_MASK)
1306 eflags |= IF_MASK;
1307 T0 = eflags;
1308}
3acace13 1309#endif
f631ef9b 1310
367e86e8
FB
1311void OPPROTO op_cld(void)
1312{
1313 DF = 1;
1314}
1315
1316void OPPROTO op_std(void)
1317{
1318 DF = -1;
1319}
1320
1321void OPPROTO op_clc(void)
1322{
1323 int eflags;
1324 eflags = cc_table[CC_OP].compute_all();
1325 eflags &= ~CC_C;
1326 CC_SRC = eflags;
1327}
1328
1329void OPPROTO op_stc(void)
1330{
1331 int eflags;
1332 eflags = cc_table[CC_OP].compute_all();
1333 eflags |= CC_C;
1334 CC_SRC = eflags;
1335}
1336
1337void OPPROTO op_cmc(void)
1338{
1339 int eflags;
1340 eflags = cc_table[CC_OP].compute_all();
1341 eflags ^= CC_C;
1342 CC_SRC = eflags;
1343}
1344
27362c82
FB
1345void OPPROTO op_salc(void)
1346{
1347 int cf;
1348 cf = cc_table[CC_OP].compute_c();
1349 EAX = (EAX & ~0xff) | ((-cf) & 0xff);
1350}
1351
367e86e8
FB
1352static int compute_all_eflags(void)
1353{
1354 return CC_SRC;
1355}
1356
1357static int compute_c_eflags(void)
1358{
1359 return CC_SRC & CC_C;
1360}
1361
1362static int compute_c_mul(void)
1363{
1364 int cf;
1365 cf = (CC_SRC != 0);
1366 return cf;
1367}
1368
1369static int compute_all_mul(void)
1370{
1371 int cf, pf, af, zf, sf, of;
1372 cf = (CC_SRC != 0);
1373 pf = 0; /* undefined */
1374 af = 0; /* undefined */
1375 zf = 0; /* undefined */
1376 sf = 0; /* undefined */
1377 of = cf << 11;
1378 return cf | pf | af | zf | sf | of;
1379}
1380
1381CCTable cc_table[CC_OP_NB] = {
1382 [CC_OP_DYNAMIC] = { /* should never happen */ },
1383
1384 [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
1385
1386 [CC_OP_MUL] = { compute_all_mul, compute_c_mul },
1387
1388 [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
1389 [CC_OP_ADDW] = { compute_all_addw, compute_c_addw },
1390 [CC_OP_ADDL] = { compute_all_addl, compute_c_addl },
1391
4b74fe1f
FB
1392 [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
1393 [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw },
1394 [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl },
1395
367e86e8
FB
1396 [CC_OP_SUBB] = { compute_all_subb, compute_c_subb },
1397 [CC_OP_SUBW] = { compute_all_subw, compute_c_subw },
1398 [CC_OP_SUBL] = { compute_all_subl, compute_c_subl },
1399
4b74fe1f
FB
1400 [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb },
1401 [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw },
1402 [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl },
1403
367e86e8
FB
1404 [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
1405 [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
1406 [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
1407
4b74fe1f
FB
1408 [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
1409 [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
367e86e8
FB
1410 [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
1411
4b74fe1f
FB
1412 [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
1413 [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
367e86e8
FB
1414 [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
1415
2792c4f2
FB
1416 [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
1417 [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
367e86e8 1418 [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
4b74fe1f 1419
2792c4f2
FB
1420 [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
1421 [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
1422 [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
367e86e8 1423};
927f621e 1424
f631ef9b
FB
1425/* floating point support. Some of the code for complicated x87
1426 functions comes from the LGPL'ed x86 emulator found in the Willows
1427 TWIN windows emulator. */
927f621e 1428
51fe6890
FB
1429#if defined(__powerpc__)
1430extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble);
1431
1432/* correct (but slow) PowerPC rint() (glibc version is incorrect) */
1433double qemu_rint(double x)
1434{
1435 double y = 4503599627370496.0;
1436 if (fabs(x) >= y)
1437 return x;
1438 if (x < 0)
1439 y = -y;
1440 y = (x + y) - y;
1441 if (y == 0.0)
1442 y = copysign(y, x);
1443 return y;
1444}
1445
1446#define rint qemu_rint
1447#endif
1448
927f621e
FB
1449/* fp load FT0 */
1450
1451void OPPROTO op_flds_FT0_A0(void)
1452{
d014c98c
FB
1453#ifdef USE_FP_CONVERT
1454 FP_CONVERT.i32 = ldl((void *)A0);
1455 FT0 = FP_CONVERT.f;
1456#else
927f621e 1457 FT0 = ldfl((void *)A0);
d014c98c 1458#endif
927f621e
FB
1459}
1460
1461void OPPROTO op_fldl_FT0_A0(void)
1462{
d014c98c
FB
1463#ifdef USE_FP_CONVERT
1464 FP_CONVERT.i64 = ldq((void *)A0);
1465 FT0 = FP_CONVERT.d;
1466#else
927f621e 1467 FT0 = ldfq((void *)A0);
d014c98c 1468#endif
927f621e
FB
1469}
1470
04369ff2
FB
1471/* helpers are needed to avoid static constant reference. XXX: find a better way */
1472#ifdef USE_INT_TO_FLOAT_HELPERS
1473
1474void helper_fild_FT0_A0(void)
1475{
1476 FT0 = (CPU86_LDouble)ldsw((void *)A0);
1477}
1478
1479void helper_fildl_FT0_A0(void)
1480{
1481 FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1482}
1483
1484void helper_fildll_FT0_A0(void)
1485{
1486 FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1487}
1488
1489void OPPROTO op_fild_FT0_A0(void)
1490{
1491 helper_fild_FT0_A0();
1492}
1493
1494void OPPROTO op_fildl_FT0_A0(void)
1495{
1496 helper_fildl_FT0_A0();
1497}
1498
1499void OPPROTO op_fildll_FT0_A0(void)
1500{
1501 helper_fildll_FT0_A0();
1502}
1503
1504#else
1505
927f621e
FB
1506void OPPROTO op_fild_FT0_A0(void)
1507{
d014c98c
FB
1508#ifdef USE_FP_CONVERT
1509 FP_CONVERT.i32 = ldsw((void *)A0);
1510 FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1511#else
927f621e 1512 FT0 = (CPU86_LDouble)ldsw((void *)A0);
d014c98c 1513#endif
927f621e
FB
1514}
1515
1516void OPPROTO op_fildl_FT0_A0(void)
1517{
d014c98c
FB
1518#ifdef USE_FP_CONVERT
1519 FP_CONVERT.i32 = (int32_t) ldl((void *)A0);
1520 FT0 = (CPU86_LDouble)FP_CONVERT.i32;
1521#else
927f621e 1522 FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
d014c98c 1523#endif
927f621e
FB
1524}
1525
1526void OPPROTO op_fildll_FT0_A0(void)
1527{
d014c98c
FB
1528#ifdef USE_FP_CONVERT
1529 FP_CONVERT.i64 = (int64_t) ldq((void *)A0);
1530 FT0 = (CPU86_LDouble)FP_CONVERT.i64;
1531#else
927f621e 1532 FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
d014c98c 1533#endif
927f621e 1534}
04369ff2 1535#endif
927f621e
FB
1536
1537/* fp load ST0 */
1538
1539void OPPROTO op_flds_ST0_A0(void)
1540{
d014c98c
FB
1541#ifdef USE_FP_CONVERT
1542 FP_CONVERT.i32 = ldl((void *)A0);
1543 ST0 = FP_CONVERT.f;
1544#else
927f621e 1545 ST0 = ldfl((void *)A0);
d014c98c 1546#endif
927f621e
FB
1547}
1548
1549void OPPROTO op_fldl_ST0_A0(void)
1550{
d014c98c
FB
1551#ifdef USE_FP_CONVERT
1552 FP_CONVERT.i64 = ldq((void *)A0);
1553 ST0 = FP_CONVERT.d;
1554#else
927f621e 1555 ST0 = ldfq((void *)A0);
d014c98c 1556#endif
927f621e
FB
1557}
1558
77f8dd5a
FB
1559#ifdef USE_X86LDOUBLE
1560void OPPROTO op_fldt_ST0_A0(void)
1561{
1562 ST0 = *(long double *)A0;
1563}
1564#else
77f8dd5a
FB
1565void OPPROTO op_fldt_ST0_A0(void)
1566{
1567 helper_fldt_ST0_A0();
1568}
1569#endif
1570
04369ff2
FB
1571/* helpers are needed to avoid static constant reference. XXX: find a better way */
1572#ifdef USE_INT_TO_FLOAT_HELPERS
1573
1574void helper_fild_ST0_A0(void)
1575{
1576 ST0 = (CPU86_LDouble)ldsw((void *)A0);
1577}
1578
1579void helper_fildl_ST0_A0(void)
1580{
1581 ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
1582}
1583
1584void helper_fildll_ST0_A0(void)
1585{
1586 ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
1587}
1588
1589void OPPROTO op_fild_ST0_A0(void)
1590{
1591 helper_fild_ST0_A0();
1592}
1593
1594void OPPROTO op_fildl_ST0_A0(void)
1595{
1596 helper_fildl_ST0_A0();
1597}
1598
1599void OPPROTO op_fildll_ST0_A0(void)
1600{
1601 helper_fildll_ST0_A0();
1602}
1603
1604#else
1605
927f621e
FB
1606void OPPROTO op_fild_ST0_A0(void)
1607{
d014c98c
FB
1608#ifdef USE_FP_CONVERT
1609 FP_CONVERT.i32 = ldsw((void *)A0);
1610 ST0 = (CPU86_LDouble)FP_CONVERT.i32;
1611#else
927f621e 1612 ST0 = (CPU86_LDouble)ldsw((void *)A0);
d014c98c 1613#endif
927f621e
FB
1614}
1615
1616void OPPROTO op_fildl_ST0_A0(void)
1617{
d014c98c
FB
1618#ifdef USE_FP_CONVERT
1619 FP_CONVERT.i32 = (int32_t) ldl((void *)A0);
1620 ST0 = (CPU86_LDouble)FP_CONVERT.i32;
1621#else
927f621e 1622 ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
d014c98c 1623#endif
927f621e
FB
1624}
1625
1626void OPPROTO op_fildll_ST0_A0(void)
1627{
d014c98c
FB
1628#ifdef USE_FP_CONVERT
1629 FP_CONVERT.i64 = (int64_t) ldq((void *)A0);
1630 ST0 = (CPU86_LDouble)FP_CONVERT.i64;
1631#else
927f621e 1632 ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
d014c98c 1633#endif
927f621e
FB
1634}
1635
04369ff2
FB
1636#endif
1637
927f621e
FB
1638/* fp store */
1639
1640void OPPROTO op_fsts_ST0_A0(void)
1641{
d014c98c
FB
1642#ifdef USE_FP_CONVERT
1643 FP_CONVERT.d = ST0;
1644 stfl((void *)A0, FP_CONVERT.f);
1645#else
927f621e 1646 stfl((void *)A0, (float)ST0);
d014c98c 1647#endif
927f621e
FB
1648}
1649
1650void OPPROTO op_fstl_ST0_A0(void)
1651{
77f8dd5a 1652 stfq((void *)A0, (double)ST0);
927f621e
FB
1653}
1654
77f8dd5a
FB
1655#ifdef USE_X86LDOUBLE
1656void OPPROTO op_fstt_ST0_A0(void)
1657{
1658 *(long double *)A0 = ST0;
1659}
1660#else
77f8dd5a
FB
1661void OPPROTO op_fstt_ST0_A0(void)
1662{
1663 helper_fstt_ST0_A0();
1664}
1665#endif
1666
927f621e
FB
1667void OPPROTO op_fist_ST0_A0(void)
1668{
d014c98c
FB
1669#if defined(__sparc__) && !defined(__sparc_v9__)
1670 register CPU86_LDouble d asm("o0");
1671#else
1672 CPU86_LDouble d;
1673#endif
927f621e 1674 int val;
d014c98c
FB
1675
1676 d = ST0;
1677 val = lrint(d);
927f621e
FB
1678 stw((void *)A0, val);
1679}
1680
1681void OPPROTO op_fistl_ST0_A0(void)
1682{
d014c98c
FB
1683#if defined(__sparc__) && !defined(__sparc_v9__)
1684 register CPU86_LDouble d asm("o0");
1685#else
1686 CPU86_LDouble d;
1687#endif
927f621e 1688 int val;
d014c98c
FB
1689
1690 d = ST0;
1691 val = lrint(d);
927f621e
FB
1692 stl((void *)A0, val);
1693}
1694
1695void OPPROTO op_fistll_ST0_A0(void)
1696{
d014c98c
FB
1697#if defined(__sparc__) && !defined(__sparc_v9__)
1698 register CPU86_LDouble d asm("o0");
1699#else
1700 CPU86_LDouble d;
1701#endif
927f621e 1702 int64_t val;
d014c98c
FB
1703
1704 d = ST0;
1705 val = llrint(d);
927f621e
FB
1706 stq((void *)A0, val);
1707}
1708
77f8dd5a
FB
1709void OPPROTO op_fbld_ST0_A0(void)
1710{
1711 helper_fbld_ST0_A0();
1712}
1713
77f8dd5a
FB
1714void OPPROTO op_fbst_ST0_A0(void)
1715{
1716 helper_fbst_ST0_A0();
1717}
1718
927f621e
FB
1719/* FPU move */
1720
927f621e
FB
1721void OPPROTO op_fpush(void)
1722{
1723 fpush();
1724}
1725
1726void OPPROTO op_fpop(void)
1727{
1728 fpop();
1729}
1730
1731void OPPROTO op_fdecstp(void)
1732{
1733 env->fpstt = (env->fpstt - 1) & 7;
1734 env->fpus &= (~0x4700);
1735}
1736
1737void OPPROTO op_fincstp(void)
1738{
1739 env->fpstt = (env->fpstt + 1) & 7;
1740 env->fpus &= (~0x4700);
1741}
1742
1743void OPPROTO op_fmov_ST0_FT0(void)
1744{
1745 ST0 = FT0;
1746}
1747
1748void OPPROTO op_fmov_FT0_STN(void)
1749{
1750 FT0 = ST(PARAM1);
1751}
1752
1753void OPPROTO op_fmov_ST0_STN(void)
1754{
1755 ST0 = ST(PARAM1);
1756}
1757
1758void OPPROTO op_fmov_STN_ST0(void)
1759{
1760 ST(PARAM1) = ST0;
1761}
1762
1763void OPPROTO op_fxchg_ST0_STN(void)
1764{
1765 CPU86_LDouble tmp;
1766 tmp = ST(PARAM1);
1767 ST(PARAM1) = ST0;
1768 ST0 = tmp;
1769}
1770
1771/* FPU operations */
1772
1773/* XXX: handle nans */
1774void OPPROTO op_fcom_ST0_FT0(void)
1775{
1776 env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */
1777 if (ST0 < FT0)
1778 env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */
1779 else if (ST0 == FT0)
1780 env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1781 FORCE_RET();
1782}
1783
77f8dd5a
FB
1784/* XXX: handle nans */
1785void OPPROTO op_fucom_ST0_FT0(void)
1786{
1787 env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */
1788 if (ST0 < FT0)
1789 env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */
1790 else if (ST0 == FT0)
1791 env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
1792 FORCE_RET();
1793}
1794
d0a1ffc9
FB
1795/* XXX: handle nans */
1796void OPPROTO op_fcomi_ST0_FT0(void)
1797{
1798 int eflags;
1799 eflags = cc_table[CC_OP].compute_all();
1800 eflags &= ~(CC_Z | CC_P | CC_C);
1801 if (ST0 < FT0)
1802 eflags |= CC_C;
1803 else if (ST0 == FT0)
1804 eflags |= CC_Z;
1805 CC_SRC = eflags;
1806 FORCE_RET();
1807}
1808
1809/* XXX: handle nans */
1810void OPPROTO op_fucomi_ST0_FT0(void)
1811{
1812 int eflags;
1813 eflags = cc_table[CC_OP].compute_all();
1814 eflags &= ~(CC_Z | CC_P | CC_C);
1815 if (ST0 < FT0)
1816 eflags |= CC_C;
1817 else if (ST0 == FT0)
1818 eflags |= CC_Z;
1819 CC_SRC = eflags;
1820 FORCE_RET();
1821}
1822
927f621e
FB
1823void OPPROTO op_fadd_ST0_FT0(void)
1824{
1825 ST0 += FT0;
1826}
1827
1828void OPPROTO op_fmul_ST0_FT0(void)
1829{
1830 ST0 *= FT0;
1831}
1832
1833void OPPROTO op_fsub_ST0_FT0(void)
1834{
1835 ST0 -= FT0;
1836}
1837
1838void OPPROTO op_fsubr_ST0_FT0(void)
1839{
1840 ST0 = FT0 - ST0;
1841}
1842
1843void OPPROTO op_fdiv_ST0_FT0(void)
1844{
1845 ST0 /= FT0;
1846}
1847
1848void OPPROTO op_fdivr_ST0_FT0(void)
1849{
1850 ST0 = FT0 / ST0;
1851}
1852
1853/* fp operations between STN and ST0 */
1854
1855void OPPROTO op_fadd_STN_ST0(void)
1856{
1857 ST(PARAM1) += ST0;
1858}
1859
1860void OPPROTO op_fmul_STN_ST0(void)
1861{
1862 ST(PARAM1) *= ST0;
1863}
1864
1865void OPPROTO op_fsub_STN_ST0(void)
1866{
1867 ST(PARAM1) -= ST0;
1868}
1869
1870void OPPROTO op_fsubr_STN_ST0(void)
1871{
1872 CPU86_LDouble *p;
1873 p = &ST(PARAM1);
1874 *p = ST0 - *p;
1875}
1876
1877void OPPROTO op_fdiv_STN_ST0(void)
1878{
1879 ST(PARAM1) /= ST0;
1880}
1881
1882void OPPROTO op_fdivr_STN_ST0(void)
1883{
1884 CPU86_LDouble *p;
1885 p = &ST(PARAM1);
1886 *p = ST0 / *p;
1887}
1888
1889/* misc FPU operations */
1890void OPPROTO op_fchs_ST0(void)
1891{
1892 ST0 = -ST0;
1893}
1894
1895void OPPROTO op_fabs_ST0(void)
1896{
1897 ST0 = fabs(ST0);
1898}
1899
77f8dd5a
FB
1900void OPPROTO op_fxam_ST0(void)
1901{
1902 helper_fxam_ST0();
927f621e
FB
1903}
1904
1905void OPPROTO op_fld1_ST0(void)
1906{
1907 ST0 = *(CPU86_LDouble *)&f15rk[1];
1908}
1909
77f8dd5a 1910void OPPROTO op_fldl2t_ST0(void)
927f621e
FB
1911{
1912 ST0 = *(CPU86_LDouble *)&f15rk[6];
1913}
1914
77f8dd5a 1915void OPPROTO op_fldl2e_ST0(void)
927f621e
FB
1916{
1917 ST0 = *(CPU86_LDouble *)&f15rk[5];
1918}
1919
1920void OPPROTO op_fldpi_ST0(void)
1921{
1922 ST0 = *(CPU86_LDouble *)&f15rk[2];
1923}
1924
1925void OPPROTO op_fldlg2_ST0(void)
1926{
1927 ST0 = *(CPU86_LDouble *)&f15rk[3];
1928}
1929
1930void OPPROTO op_fldln2_ST0(void)
1931{
1932 ST0 = *(CPU86_LDouble *)&f15rk[4];
1933}
1934
1935void OPPROTO op_fldz_ST0(void)
1936{
1937 ST0 = *(CPU86_LDouble *)&f15rk[0];
1938}
1939
1940void OPPROTO op_fldz_FT0(void)
1941{
1942 ST0 = *(CPU86_LDouble *)&f15rk[0];
1943}
1944
927f621e
FB
1945/* associated heplers to reduce generated code length and to simplify
1946 relocation (FP constants are usually stored in .rodata section) */
1947
1948void OPPROTO op_f2xm1(void)
1949{
1950 helper_f2xm1();
1951}
1952
1953void OPPROTO op_fyl2x(void)
1954{
1955 helper_fyl2x();
1956}
1957
1958void OPPROTO op_fptan(void)
1959{
1960 helper_fptan();
1961}
1962
1963void OPPROTO op_fpatan(void)
1964{
1965 helper_fpatan();
1966}
1967
1968void OPPROTO op_fxtract(void)
1969{
1970 helper_fxtract();
1971}
1972
1973void OPPROTO op_fprem1(void)
1974{
1975 helper_fprem1();
1976}
1977
1978
1979void OPPROTO op_fprem(void)
1980{
1981 helper_fprem();
1982}
1983
1984void OPPROTO op_fyl2xp1(void)
1985{
1986 helper_fyl2xp1();
1987}
1988
1989void OPPROTO op_fsqrt(void)
1990{
1991 helper_fsqrt();
1992}
1993
1994void OPPROTO op_fsincos(void)
1995{
1996 helper_fsincos();
1997}
1998
1999void OPPROTO op_frndint(void)
2000{
2001 helper_frndint();
2002}
2003
2004void OPPROTO op_fscale(void)
2005{
2006 helper_fscale();
2007}
2008
2009void OPPROTO op_fsin(void)
2010{
2011 helper_fsin();
2012}
2013
2014void OPPROTO op_fcos(void)
2015{
2016 helper_fcos();
2017}
2018
4b74fe1f
FB
2019void OPPROTO op_fnstsw_A0(void)
2020{
2021 int fpus;
2022 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2023 stw((void *)A0, fpus);
2024}
2025
77f8dd5a
FB
2026void OPPROTO op_fnstsw_EAX(void)
2027{
2028 int fpus;
2029 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2030 EAX = (EAX & 0xffff0000) | fpus;
2031}
2032
4b74fe1f
FB
2033void OPPROTO op_fnstcw_A0(void)
2034{
2035 stw((void *)A0, env->fpuc);
2036}
2037
2038void OPPROTO op_fldcw_A0(void)
2039{
2040 int rnd_type;
2041 env->fpuc = lduw((void *)A0);
2042 /* set rounding mode */
2043 switch(env->fpuc & RC_MASK) {
2044 default:
2045 case RC_NEAR:
2046 rnd_type = FE_TONEAREST;
2047 break;
2048 case RC_DOWN:
2049 rnd_type = FE_DOWNWARD;
2050 break;
2051 case RC_UP:
2052 rnd_type = FE_UPWARD;
2053 break;
2054 case RC_CHOP:
2055 rnd_type = FE_TOWARDZERO;
2056 break;
2057 }
2058 fesetround(rnd_type);
2059}
2060
1a9353d2
FB
2061void OPPROTO op_fclex(void)
2062{
2063 env->fpus &= 0x7f00;
2064}
2065
2066void OPPROTO op_fninit(void)
2067{
2068 env->fpus = 0;
2069 env->fpstt = 0;
2070 env->fpuc = 0x37f;
2071 env->fptags[0] = 1;
2072 env->fptags[1] = 1;
2073 env->fptags[2] = 1;
2074 env->fptags[3] = 1;
2075 env->fptags[4] = 1;
2076 env->fptags[5] = 1;
2077 env->fptags[6] = 1;
2078 env->fptags[7] = 1;
2079}
1b6b029e 2080
d0a1ffc9
FB
2081void OPPROTO op_fnstenv_A0(void)
2082{
2083 helper_fstenv((uint8_t *)A0, PARAM1);
2084}
2085
2086void OPPROTO op_fldenv_A0(void)
2087{
2088 helper_fldenv((uint8_t *)A0, PARAM1);
2089}
2090
2091void OPPROTO op_fnsave_A0(void)
2092{
2093 helper_fsave((uint8_t *)A0, PARAM1);
2094}
2095
2096void OPPROTO op_frstor_A0(void)
2097{
2098 helper_frstor((uint8_t *)A0, PARAM1);
2099}
2100
1b6b029e
FB
2101/* threading support */
2102void OPPROTO op_lock(void)
2103{
2104 cpu_lock();
2105}
2106
2107void OPPROTO op_unlock(void)
2108{
2109 cpu_unlock();
2110}
3ec9c4fc 2111
This page took 0.282619 seconds and 4 git commands to generate.