1 | /* |
---|
2 | * i386 micro operations |
---|
3 | * |
---|
4 | * Copyright (c) 2003 Fabrice Bellard |
---|
5 | * |
---|
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. |
---|
10 | * |
---|
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. |
---|
15 | * |
---|
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 |
---|
19 | */ |
---|
20 | |
---|
21 | #define ASM_SOFTMMU |
---|
22 | #include "exec.h" |
---|
23 | |
---|
24 | /* n must be a constant to be efficient */ |
---|
25 | static inline target_long lshift(target_long x, int n) |
---|
26 | { |
---|
27 | if (n >= 0) |
---|
28 | return x << n; |
---|
29 | else |
---|
30 | return x >> (-n); |
---|
31 | } |
---|
32 | |
---|
33 | /* we define the various pieces of code used by the JIT */ |
---|
34 | |
---|
35 | #define REG EAX |
---|
36 | #define REGNAME _EAX |
---|
37 | #include "opreg_template.h" |
---|
38 | #undef REG |
---|
39 | #undef REGNAME |
---|
40 | |
---|
41 | #define REG ECX |
---|
42 | #define REGNAME _ECX |
---|
43 | #include "opreg_template.h" |
---|
44 | #undef REG |
---|
45 | #undef REGNAME |
---|
46 | |
---|
47 | #define REG EDX |
---|
48 | #define REGNAME _EDX |
---|
49 | #include "opreg_template.h" |
---|
50 | #undef REG |
---|
51 | #undef REGNAME |
---|
52 | |
---|
53 | #define REG EBX |
---|
54 | #define REGNAME _EBX |
---|
55 | #include "opreg_template.h" |
---|
56 | #undef REG |
---|
57 | #undef REGNAME |
---|
58 | |
---|
59 | #define REG ESP |
---|
60 | #define REGNAME _ESP |
---|
61 | #include "opreg_template.h" |
---|
62 | #undef REG |
---|
63 | #undef REGNAME |
---|
64 | |
---|
65 | #define REG EBP |
---|
66 | #define REGNAME _EBP |
---|
67 | #include "opreg_template.h" |
---|
68 | #undef REG |
---|
69 | #undef REGNAME |
---|
70 | |
---|
71 | #define REG ESI |
---|
72 | #define REGNAME _ESI |
---|
73 | #include "opreg_template.h" |
---|
74 | #undef REG |
---|
75 | #undef REGNAME |
---|
76 | |
---|
77 | #define REG EDI |
---|
78 | #define REGNAME _EDI |
---|
79 | #include "opreg_template.h" |
---|
80 | #undef REG |
---|
81 | #undef REGNAME |
---|
82 | |
---|
83 | #ifdef TARGET_X86_64 |
---|
84 | |
---|
85 | #define REG (env->regs[8]) |
---|
86 | #define REGNAME _R8 |
---|
87 | #include "opreg_template.h" |
---|
88 | #undef REG |
---|
89 | #undef REGNAME |
---|
90 | |
---|
91 | #define REG (env->regs[9]) |
---|
92 | #define REGNAME _R9 |
---|
93 | #include "opreg_template.h" |
---|
94 | #undef REG |
---|
95 | #undef REGNAME |
---|
96 | |
---|
97 | #define REG (env->regs[10]) |
---|
98 | #define REGNAME _R10 |
---|
99 | #include "opreg_template.h" |
---|
100 | #undef REG |
---|
101 | #undef REGNAME |
---|
102 | |
---|
103 | #define REG (env->regs[11]) |
---|
104 | #define REGNAME _R11 |
---|
105 | #include "opreg_template.h" |
---|
106 | #undef REG |
---|
107 | #undef REGNAME |
---|
108 | |
---|
109 | #define REG (env->regs[12]) |
---|
110 | #define REGNAME _R12 |
---|
111 | #include "opreg_template.h" |
---|
112 | #undef REG |
---|
113 | #undef REGNAME |
---|
114 | |
---|
115 | #define REG (env->regs[13]) |
---|
116 | #define REGNAME _R13 |
---|
117 | #include "opreg_template.h" |
---|
118 | #undef REG |
---|
119 | #undef REGNAME |
---|
120 | |
---|
121 | #define REG (env->regs[14]) |
---|
122 | #define REGNAME _R14 |
---|
123 | #include "opreg_template.h" |
---|
124 | #undef REG |
---|
125 | #undef REGNAME |
---|
126 | |
---|
127 | #define REG (env->regs[15]) |
---|
128 | #define REGNAME _R15 |
---|
129 | #include "opreg_template.h" |
---|
130 | #undef REG |
---|
131 | #undef REGNAME |
---|
132 | |
---|
133 | #endif |
---|
134 | |
---|
135 | /* operations with flags */ |
---|
136 | |
---|
137 | /* update flags with T0 and T1 (add/sub case) */ |
---|
138 | void OPPROTO op_update2_cc(void) |
---|
139 | { |
---|
140 | CC_SRC = T1; |
---|
141 | CC_DST = T0; |
---|
142 | } |
---|
143 | |
---|
144 | /* update flags with T0 (logic operation case) */ |
---|
145 | void OPPROTO op_update1_cc(void) |
---|
146 | { |
---|
147 | CC_DST = T0; |
---|
148 | } |
---|
149 | |
---|
150 | void OPPROTO op_update_neg_cc(void) |
---|
151 | { |
---|
152 | CC_SRC = -T0; |
---|
153 | CC_DST = T0; |
---|
154 | } |
---|
155 | |
---|
156 | void OPPROTO op_cmpl_T0_T1_cc(void) |
---|
157 | { |
---|
158 | CC_SRC = T1; |
---|
159 | CC_DST = T0 - T1; |
---|
160 | } |
---|
161 | |
---|
162 | void OPPROTO op_update_inc_cc(void) |
---|
163 | { |
---|
164 | CC_SRC = cc_table[CC_OP].compute_c(); |
---|
165 | CC_DST = T0; |
---|
166 | } |
---|
167 | |
---|
168 | void OPPROTO op_testl_T0_T1_cc(void) |
---|
169 | { |
---|
170 | CC_DST = T0 & T1; |
---|
171 | } |
---|
172 | |
---|
173 | /* operations without flags */ |
---|
174 | |
---|
175 | void OPPROTO op_addl_T0_T1(void) |
---|
176 | { |
---|
177 | T0 += T1; |
---|
178 | } |
---|
179 | |
---|
180 | void OPPROTO op_orl_T0_T1(void) |
---|
181 | { |
---|
182 | T0 |= T1; |
---|
183 | } |
---|
184 | |
---|
185 | void OPPROTO op_andl_T0_T1(void) |
---|
186 | { |
---|
187 | T0 &= T1; |
---|
188 | } |
---|
189 | |
---|
190 | void OPPROTO op_subl_T0_T1(void) |
---|
191 | { |
---|
192 | T0 -= T1; |
---|
193 | } |
---|
194 | |
---|
195 | void OPPROTO op_xorl_T0_T1(void) |
---|
196 | { |
---|
197 | T0 ^= T1; |
---|
198 | } |
---|
199 | |
---|
200 | void OPPROTO op_negl_T0(void) |
---|
201 | { |
---|
202 | T0 = -T0; |
---|
203 | } |
---|
204 | |
---|
205 | void OPPROTO op_incl_T0(void) |
---|
206 | { |
---|
207 | T0++; |
---|
208 | } |
---|
209 | |
---|
210 | void OPPROTO op_decl_T0(void) |
---|
211 | { |
---|
212 | T0--; |
---|
213 | } |
---|
214 | |
---|
215 | void OPPROTO op_notl_T0(void) |
---|
216 | { |
---|
217 | T0 = ~T0; |
---|
218 | } |
---|
219 | |
---|
220 | void OPPROTO op_bswapl_T0(void) |
---|
221 | { |
---|
222 | T0 = bswap32(T0); |
---|
223 | } |
---|
224 | |
---|
225 | #ifdef TARGET_X86_64 |
---|
226 | void OPPROTO op_bswapq_T0(void) |
---|
227 | { |
---|
228 | helper_bswapq_T0(); |
---|
229 | } |
---|
230 | #endif |
---|
231 | |
---|
232 | /* multiply/divide */ |
---|
233 | |
---|
234 | /* XXX: add eflags optimizations */ |
---|
235 | /* XXX: add non P4 style flags */ |
---|
236 | |
---|
237 | void OPPROTO op_mulb_AL_T0(void) |
---|
238 | { |
---|
239 | unsigned int res; |
---|
240 | res = (uint8_t)EAX * (uint8_t)T0; |
---|
241 | EAX = (EAX & ~0xffff) | res; |
---|
242 | CC_DST = res; |
---|
243 | CC_SRC = (res & 0xff00); |
---|
244 | } |
---|
245 | |
---|
246 | void OPPROTO op_imulb_AL_T0(void) |
---|
247 | { |
---|
248 | int res; |
---|
249 | res = (int8_t)EAX * (int8_t)T0; |
---|
250 | EAX = (EAX & ~0xffff) | (res & 0xffff); |
---|
251 | CC_DST = res; |
---|
252 | CC_SRC = (res != (int8_t)res); |
---|
253 | } |
---|
254 | |
---|
255 | void OPPROTO op_mulw_AX_T0(void) |
---|
256 | { |
---|
257 | unsigned int res; |
---|
258 | res = (uint16_t)EAX * (uint16_t)T0; |
---|
259 | EAX = (EAX & ~0xffff) | (res & 0xffff); |
---|
260 | EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff); |
---|
261 | CC_DST = res; |
---|
262 | CC_SRC = res >> 16; |
---|
263 | } |
---|
264 | |
---|
265 | void OPPROTO op_imulw_AX_T0(void) |
---|
266 | { |
---|
267 | int res; |
---|
268 | res = (int16_t)EAX * (int16_t)T0; |
---|
269 | EAX = (EAX & ~0xffff) | (res & 0xffff); |
---|
270 | EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff); |
---|
271 | CC_DST = res; |
---|
272 | CC_SRC = (res != (int16_t)res); |
---|
273 | } |
---|
274 | |
---|
275 | void OPPROTO op_mull_EAX_T0(void) |
---|
276 | { |
---|
277 | uint64_t res; |
---|
278 | res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0); |
---|
279 | EAX = (uint32_t)res; |
---|
280 | EDX = (uint32_t)(res >> 32); |
---|
281 | CC_DST = (uint32_t)res; |
---|
282 | CC_SRC = (uint32_t)(res >> 32); |
---|
283 | } |
---|
284 | |
---|
285 | void OPPROTO op_imull_EAX_T0(void) |
---|
286 | { |
---|
287 | int64_t res; |
---|
288 | res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0); |
---|
289 | EAX = (uint32_t)(res); |
---|
290 | EDX = (uint32_t)(res >> 32); |
---|
291 | CC_DST = res; |
---|
292 | CC_SRC = (res != (int32_t)res); |
---|
293 | } |
---|
294 | |
---|
295 | void OPPROTO op_imulw_T0_T1(void) |
---|
296 | { |
---|
297 | int res; |
---|
298 | res = (int16_t)T0 * (int16_t)T1; |
---|
299 | T0 = res; |
---|
300 | CC_DST = res; |
---|
301 | CC_SRC = (res != (int16_t)res); |
---|
302 | } |
---|
303 | |
---|
304 | void OPPROTO op_imull_T0_T1(void) |
---|
305 | { |
---|
306 | int64_t res; |
---|
307 | res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); |
---|
308 | T0 = res; |
---|
309 | CC_DST = res; |
---|
310 | CC_SRC = (res != (int32_t)res); |
---|
311 | } |
---|
312 | |
---|
313 | #ifdef TARGET_X86_64 |
---|
314 | void OPPROTO op_mulq_EAX_T0(void) |
---|
315 | { |
---|
316 | helper_mulq_EAX_T0(); |
---|
317 | } |
---|
318 | |
---|
319 | void OPPROTO op_imulq_EAX_T0(void) |
---|
320 | { |
---|
321 | helper_imulq_EAX_T0(); |
---|
322 | } |
---|
323 | |
---|
324 | void OPPROTO op_imulq_T0_T1(void) |
---|
325 | { |
---|
326 | helper_imulq_T0_T1(); |
---|
327 | } |
---|
328 | #endif |
---|
329 | |
---|
330 | /* division, flags are undefined */ |
---|
331 | |
---|
332 | void OPPROTO op_divb_AL_T0(void) |
---|
333 | { |
---|
334 | unsigned int num, den, q, r; |
---|
335 | |
---|
336 | num = (EAX & 0xffff); |
---|
337 | den = (T0 & 0xff); |
---|
338 | if (den == 0) { |
---|
339 | raise_exception(EXCP00_DIVZ); |
---|
340 | } |
---|
341 | q = (num / den); |
---|
342 | if (q > 0xff) |
---|
343 | raise_exception(EXCP00_DIVZ); |
---|
344 | q &= 0xff; |
---|
345 | r = (num % den) & 0xff; |
---|
346 | EAX = (EAX & ~0xffff) | (r << 8) | q; |
---|
347 | } |
---|
348 | |
---|
349 | void OPPROTO op_idivb_AL_T0(void) |
---|
350 | { |
---|
351 | int num, den, q, r; |
---|
352 | |
---|
353 | num = (int16_t)EAX; |
---|
354 | den = (int8_t)T0; |
---|
355 | if (den == 0) { |
---|
356 | raise_exception(EXCP00_DIVZ); |
---|
357 | } |
---|
358 | q = (num / den); |
---|
359 | if (q != (int8_t)q) |
---|
360 | raise_exception(EXCP00_DIVZ); |
---|
361 | q &= 0xff; |
---|
362 | r = (num % den) & 0xff; |
---|
363 | EAX = (EAX & ~0xffff) | (r << 8) | q; |
---|
364 | } |
---|
365 | |
---|
366 | void OPPROTO op_divw_AX_T0(void) |
---|
367 | { |
---|
368 | unsigned int num, den, q, r; |
---|
369 | |
---|
370 | num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); |
---|
371 | den = (T0 & 0xffff); |
---|
372 | if (den == 0) { |
---|
373 | raise_exception(EXCP00_DIVZ); |
---|
374 | } |
---|
375 | q = (num / den); |
---|
376 | if (q > 0xffff) |
---|
377 | raise_exception(EXCP00_DIVZ); |
---|
378 | q &= 0xffff; |
---|
379 | r = (num % den) & 0xffff; |
---|
380 | EAX = (EAX & ~0xffff) | q; |
---|
381 | EDX = (EDX & ~0xffff) | r; |
---|
382 | } |
---|
383 | |
---|
384 | void OPPROTO op_idivw_AX_T0(void) |
---|
385 | { |
---|
386 | int num, den, q, r; |
---|
387 | |
---|
388 | num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); |
---|
389 | den = (int16_t)T0; |
---|
390 | if (den == 0) { |
---|
391 | raise_exception(EXCP00_DIVZ); |
---|
392 | } |
---|
393 | q = (num / den); |
---|
394 | if (q != (int16_t)q) |
---|
395 | raise_exception(EXCP00_DIVZ); |
---|
396 | q &= 0xffff; |
---|
397 | r = (num % den) & 0xffff; |
---|
398 | EAX = (EAX & ~0xffff) | q; |
---|
399 | EDX = (EDX & ~0xffff) | r; |
---|
400 | } |
---|
401 | |
---|
402 | void OPPROTO op_divl_EAX_T0(void) |
---|
403 | { |
---|
404 | helper_divl_EAX_T0(); |
---|
405 | } |
---|
406 | |
---|
407 | void OPPROTO op_idivl_EAX_T0(void) |
---|
408 | { |
---|
409 | helper_idivl_EAX_T0(); |
---|
410 | } |
---|
411 | |
---|
412 | #ifdef TARGET_X86_64 |
---|
413 | void OPPROTO op_divq_EAX_T0(void) |
---|
414 | { |
---|
415 | helper_divq_EAX_T0(); |
---|
416 | } |
---|
417 | |
---|
418 | void OPPROTO op_idivq_EAX_T0(void) |
---|
419 | { |
---|
420 | helper_idivq_EAX_T0(); |
---|
421 | } |
---|
422 | #endif |
---|
423 | |
---|
424 | /* constant load & misc op */ |
---|
425 | |
---|
426 | /* XXX: consistent names */ |
---|
427 | void OPPROTO op_movl_T0_imu(void) |
---|
428 | { |
---|
429 | T0 = (uint32_t)PARAM1; |
---|
430 | } |
---|
431 | |
---|
432 | void OPPROTO op_movl_T0_im(void) |
---|
433 | { |
---|
434 | T0 = (int32_t)PARAM1; |
---|
435 | } |
---|
436 | |
---|
437 | void OPPROTO op_addl_T0_im(void) |
---|
438 | { |
---|
439 | T0 += PARAM1; |
---|
440 | } |
---|
441 | |
---|
442 | void OPPROTO op_andl_T0_ffff(void) |
---|
443 | { |
---|
444 | T0 = T0 & 0xffff; |
---|
445 | } |
---|
446 | |
---|
447 | void OPPROTO op_andl_T0_im(void) |
---|
448 | { |
---|
449 | T0 = T0 & PARAM1; |
---|
450 | } |
---|
451 | |
---|
452 | void OPPROTO op_movl_T0_T1(void) |
---|
453 | { |
---|
454 | T0 = T1; |
---|
455 | } |
---|
456 | |
---|
457 | void OPPROTO op_movl_T1_imu(void) |
---|
458 | { |
---|
459 | T1 = (uint32_t)PARAM1; |
---|
460 | } |
---|
461 | |
---|
462 | void OPPROTO op_movl_T1_im(void) |
---|
463 | { |
---|
464 | T1 = (int32_t)PARAM1; |
---|
465 | } |
---|
466 | |
---|
467 | void OPPROTO op_addl_T1_im(void) |
---|
468 | { |
---|
469 | T1 += PARAM1; |
---|
470 | } |
---|
471 | |
---|
472 | void OPPROTO op_movl_T1_A0(void) |
---|
473 | { |
---|
474 | T1 = A0; |
---|
475 | } |
---|
476 | |
---|
477 | void OPPROTO op_movl_A0_im(void) |
---|
478 | { |
---|
479 | A0 = (uint32_t)PARAM1; |
---|
480 | } |
---|
481 | |
---|
482 | void OPPROTO op_addl_A0_im(void) |
---|
483 | { |
---|
484 | A0 = (uint32_t)(A0 + PARAM1); |
---|
485 | } |
---|
486 | |
---|
487 | void OPPROTO op_movl_A0_seg(void) |
---|
488 | { |
---|
489 | A0 = (uint32_t)*(target_ulong *)((char *)env + PARAM1); |
---|
490 | } |
---|
491 | |
---|
492 | void OPPROTO op_addl_A0_seg(void) |
---|
493 | { |
---|
494 | A0 = (uint32_t)(A0 + *(target_ulong *)((char *)env + PARAM1)); |
---|
495 | } |
---|
496 | |
---|
497 | void OPPROTO op_addl_A0_AL(void) |
---|
498 | { |
---|
499 | A0 = (uint32_t)(A0 + (EAX & 0xff)); |
---|
500 | } |
---|
501 | |
---|
502 | #ifdef WORDS_BIGENDIAN |
---|
503 | typedef union UREG64 { |
---|
504 | struct { uint16_t v3, v2, v1, v0; } w; |
---|
505 | struct { uint32_t v1, v0; } l; |
---|
506 | uint64_t q; |
---|
507 | } UREG64; |
---|
508 | #else |
---|
509 | typedef union UREG64 { |
---|
510 | struct { uint16_t v0, v1, v2, v3; } w; |
---|
511 | struct { uint32_t v0, v1; } l; |
---|
512 | uint64_t q; |
---|
513 | } UREG64; |
---|
514 | #endif |
---|
515 | |
---|
516 | #ifdef TARGET_X86_64 |
---|
517 | |
---|
518 | #define PARAMQ1 \ |
---|
519 | ({\ |
---|
520 | UREG64 __p;\ |
---|
521 | __p.l.v1 = PARAM1;\ |
---|
522 | __p.l.v0 = PARAM2;\ |
---|
523 | __p.q;\ |
---|
524 | }) |
---|
525 | |
---|
526 | void OPPROTO op_movq_T0_im64(void) |
---|
527 | { |
---|
528 | T0 = PARAMQ1; |
---|
529 | } |
---|
530 | |
---|
531 | void OPPROTO op_movq_T1_im64(void) |
---|
532 | { |
---|
533 | T1 = PARAMQ1; |
---|
534 | } |
---|
535 | |
---|
536 | void OPPROTO op_movq_A0_im(void) |
---|
537 | { |
---|
538 | A0 = (int32_t)PARAM1; |
---|
539 | } |
---|
540 | |
---|
541 | void OPPROTO op_movq_A0_im64(void) |
---|
542 | { |
---|
543 | A0 = PARAMQ1; |
---|
544 | } |
---|
545 | |
---|
546 | void OPPROTO op_addq_A0_im(void) |
---|
547 | { |
---|
548 | A0 = (A0 + (int32_t)PARAM1); |
---|
549 | } |
---|
550 | |
---|
551 | void OPPROTO op_addq_A0_im64(void) |
---|
552 | { |
---|
553 | A0 = (A0 + PARAMQ1); |
---|
554 | } |
---|
555 | |
---|
556 | void OPPROTO op_movq_A0_seg(void) |
---|
557 | { |
---|
558 | A0 = *(target_ulong *)((char *)env + PARAM1); |
---|
559 | } |
---|
560 | |
---|
561 | void OPPROTO op_addq_A0_seg(void) |
---|
562 | { |
---|
563 | A0 += *(target_ulong *)((char *)env + PARAM1); |
---|
564 | } |
---|
565 | |
---|
566 | void OPPROTO op_addq_A0_AL(void) |
---|
567 | { |
---|
568 | A0 = (A0 + (EAX & 0xff)); |
---|
569 | } |
---|
570 | |
---|
571 | #endif |
---|
572 | |
---|
573 | void OPPROTO op_andl_A0_ffff(void) |
---|
574 | { |
---|
575 | A0 = A0 & 0xffff; |
---|
576 | } |
---|
577 | |
---|
578 | /* memory access */ |
---|
579 | |
---|
580 | #define MEMSUFFIX _raw |
---|
581 | #include "ops_mem.h" |
---|
582 | |
---|
583 | #if !defined(CONFIG_USER_ONLY) |
---|
584 | #define MEMSUFFIX _kernel |
---|
585 | #include "ops_mem.h" |
---|
586 | |
---|
587 | #define MEMSUFFIX _user |
---|
588 | #include "ops_mem.h" |
---|
589 | #endif |
---|
590 | |
---|
591 | /* indirect jump */ |
---|
592 | |
---|
593 | void OPPROTO op_jmp_T0(void) |
---|
594 | { |
---|
595 | EIP = T0; |
---|
596 | } |
---|
597 | |
---|
598 | void OPPROTO op_movl_eip_im(void) |
---|
599 | { |
---|
600 | EIP = (uint32_t)PARAM1; |
---|
601 | } |
---|
602 | |
---|
603 | #ifdef TARGET_X86_64 |
---|
604 | void OPPROTO op_movq_eip_im(void) |
---|
605 | { |
---|
606 | EIP = (int32_t)PARAM1; |
---|
607 | } |
---|
608 | |
---|
609 | void OPPROTO op_movq_eip_im64(void) |
---|
610 | { |
---|
611 | EIP = PARAMQ1; |
---|
612 | } |
---|
613 | #endif |
---|
614 | |
---|
615 | void OPPROTO op_hlt(void) |
---|
616 | { |
---|
617 | helper_hlt(); |
---|
618 | } |
---|
619 | |
---|
620 | void OPPROTO op_monitor(void) |
---|
621 | { |
---|
622 | helper_monitor(); |
---|
623 | } |
---|
624 | |
---|
625 | void OPPROTO op_mwait(void) |
---|
626 | { |
---|
627 | helper_mwait(); |
---|
628 | } |
---|
629 | |
---|
630 | void OPPROTO op_debug(void) |
---|
631 | { |
---|
632 | env->exception_index = EXCP_DEBUG; |
---|
633 | cpu_loop_exit(); |
---|
634 | } |
---|
635 | |
---|
636 | void OPPROTO op_raise_interrupt(void) |
---|
637 | { |
---|
638 | int intno, next_eip_addend; |
---|
639 | intno = PARAM1; |
---|
640 | next_eip_addend = PARAM2; |
---|
641 | raise_interrupt(intno, 1, 0, next_eip_addend); |
---|
642 | } |
---|
643 | |
---|
644 | void OPPROTO op_raise_exception(void) |
---|
645 | { |
---|
646 | int exception_index; |
---|
647 | exception_index = PARAM1; |
---|
648 | raise_exception(exception_index); |
---|
649 | } |
---|
650 | |
---|
651 | void OPPROTO op_into(void) |
---|
652 | { |
---|
653 | int eflags; |
---|
654 | eflags = cc_table[CC_OP].compute_all(); |
---|
655 | if (eflags & CC_O) { |
---|
656 | raise_interrupt(EXCP04_INTO, 1, 0, PARAM1); |
---|
657 | } |
---|
658 | FORCE_RET(); |
---|
659 | } |
---|
660 | |
---|
661 | void OPPROTO op_cli(void) |
---|
662 | { |
---|
663 | env->eflags &= ~IF_MASK; |
---|
664 | } |
---|
665 | |
---|
666 | void OPPROTO op_sti(void) |
---|
667 | { |
---|
668 | env->eflags |= IF_MASK; |
---|
669 | } |
---|
670 | |
---|
671 | void OPPROTO op_set_inhibit_irq(void) |
---|
672 | { |
---|
673 | env->hflags |= HF_INHIBIT_IRQ_MASK; |
---|
674 | } |
---|
675 | |
---|
676 | void OPPROTO op_reset_inhibit_irq(void) |
---|
677 | { |
---|
678 | env->hflags &= ~HF_INHIBIT_IRQ_MASK; |
---|
679 | } |
---|
680 | |
---|
681 | #if 0 |
---|
682 | /* vm86plus instructions */ |
---|
683 | void OPPROTO op_cli_vm(void) |
---|
684 | { |
---|
685 | env->eflags &= ~VIF_MASK; |
---|
686 | } |
---|
687 | |
---|
688 | void OPPROTO op_sti_vm(void) |
---|
689 | { |
---|
690 | env->eflags |= VIF_MASK; |
---|
691 | if (env->eflags & VIP_MASK) { |
---|
692 | EIP = PARAM1; |
---|
693 | raise_exception(EXCP0D_GPF); |
---|
694 | } |
---|
695 | FORCE_RET(); |
---|
696 | } |
---|
697 | #endif |
---|
698 | |
---|
699 | void OPPROTO op_boundw(void) |
---|
700 | { |
---|
701 | int low, high, v; |
---|
702 | low = ldsw(A0); |
---|
703 | high = ldsw(A0 + 2); |
---|
704 | v = (int16_t)T0; |
---|
705 | if (v < low || v > high) { |
---|
706 | raise_exception(EXCP05_BOUND); |
---|
707 | } |
---|
708 | FORCE_RET(); |
---|
709 | } |
---|
710 | |
---|
711 | void OPPROTO op_boundl(void) |
---|
712 | { |
---|
713 | int low, high, v; |
---|
714 | low = ldl(A0); |
---|
715 | high = ldl(A0 + 4); |
---|
716 | v = T0; |
---|
717 | if (v < low || v > high) { |
---|
718 | raise_exception(EXCP05_BOUND); |
---|
719 | } |
---|
720 | FORCE_RET(); |
---|
721 | } |
---|
722 | |
---|
723 | void OPPROTO op_cmpxchg8b(void) |
---|
724 | { |
---|
725 | helper_cmpxchg8b(); |
---|
726 | } |
---|
727 | |
---|
728 | void OPPROTO op_movl_T0_0(void) |
---|
729 | { |
---|
730 | T0 = 0; |
---|
731 | } |
---|
732 | |
---|
733 | void OPPROTO op_exit_tb(void) |
---|
734 | { |
---|
735 | EXIT_TB(); |
---|
736 | } |
---|
737 | |
---|
738 | /* multiple size ops */ |
---|
739 | |
---|
740 | #define ldul ldl |
---|
741 | |
---|
742 | #define SHIFT 0 |
---|
743 | #include "ops_template.h" |
---|
744 | #undef SHIFT |
---|
745 | |
---|
746 | #define SHIFT 1 |
---|
747 | #include "ops_template.h" |
---|
748 | #undef SHIFT |
---|
749 | |
---|
750 | #define SHIFT 2 |
---|
751 | #include "ops_template.h" |
---|
752 | #undef SHIFT |
---|
753 | |
---|
754 | #ifdef TARGET_X86_64 |
---|
755 | |
---|
756 | #define SHIFT 3 |
---|
757 | #include "ops_template.h" |
---|
758 | #undef SHIFT |
---|
759 | |
---|
760 | #endif |
---|
761 | |
---|
762 | /* sign extend */ |
---|
763 | |
---|
764 | void OPPROTO op_movsbl_T0_T0(void) |
---|
765 | { |
---|
766 | T0 = (int8_t)T0; |
---|
767 | } |
---|
768 | |
---|
769 | void OPPROTO op_movzbl_T0_T0(void) |
---|
770 | { |
---|
771 | T0 = (uint8_t)T0; |
---|
772 | } |
---|
773 | |
---|
774 | void OPPROTO op_movswl_T0_T0(void) |
---|
775 | { |
---|
776 | T0 = (int16_t)T0; |
---|
777 | } |
---|
778 | |
---|
779 | void OPPROTO op_movzwl_T0_T0(void) |
---|
780 | { |
---|
781 | T0 = (uint16_t)T0; |
---|
782 | } |
---|
783 | |
---|
784 | void OPPROTO op_movswl_EAX_AX(void) |
---|
785 | { |
---|
786 | EAX = (int16_t)EAX; |
---|
787 | } |
---|
788 | |
---|
789 | #ifdef TARGET_X86_64 |
---|
790 | void OPPROTO op_movslq_T0_T0(void) |
---|
791 | { |
---|
792 | T0 = (int32_t)T0; |
---|
793 | } |
---|
794 | |
---|
795 | void OPPROTO op_movslq_RAX_EAX(void) |
---|
796 | { |
---|
797 | EAX = (int32_t)EAX; |
---|
798 | } |
---|
799 | #endif |
---|
800 | |
---|
801 | void OPPROTO op_movsbw_AX_AL(void) |
---|
802 | { |
---|
803 | EAX = (EAX & ~0xffff) | ((int8_t)EAX & 0xffff); |
---|
804 | } |
---|
805 | |
---|
806 | void OPPROTO op_movslq_EDX_EAX(void) |
---|
807 | { |
---|
808 | EDX = (int32_t)EAX >> 31; |
---|
809 | } |
---|
810 | |
---|
811 | void OPPROTO op_movswl_DX_AX(void) |
---|
812 | { |
---|
813 | EDX = (EDX & ~0xffff) | (((int16_t)EAX >> 15) & 0xffff); |
---|
814 | } |
---|
815 | |
---|
816 | #ifdef TARGET_X86_64 |
---|
817 | void OPPROTO op_movsqo_RDX_RAX(void) |
---|
818 | { |
---|
819 | EDX = (int64_t)EAX >> 63; |
---|
820 | } |
---|
821 | #endif |
---|
822 | |
---|
823 | /* string ops helpers */ |
---|
824 | |
---|
825 | void OPPROTO op_addl_ESI_T0(void) |
---|
826 | { |
---|
827 | ESI = (uint32_t)(ESI + T0); |
---|
828 | } |
---|
829 | |
---|
830 | void OPPROTO op_addw_ESI_T0(void) |
---|
831 | { |
---|
832 | ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff); |
---|
833 | } |
---|
834 | |
---|
835 | void OPPROTO op_addl_EDI_T0(void) |
---|
836 | { |
---|
837 | EDI = (uint32_t)(EDI + T0); |
---|
838 | } |
---|
839 | |
---|
840 | void OPPROTO op_addw_EDI_T0(void) |
---|
841 | { |
---|
842 | EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff); |
---|
843 | } |
---|
844 | |
---|
845 | void OPPROTO op_decl_ECX(void) |
---|
846 | { |
---|
847 | ECX = (uint32_t)(ECX - 1); |
---|
848 | } |
---|
849 | |
---|
850 | void OPPROTO op_decw_ECX(void) |
---|
851 | { |
---|
852 | ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff); |
---|
853 | } |
---|
854 | |
---|
855 | #ifdef TARGET_X86_64 |
---|
856 | void OPPROTO op_addq_ESI_T0(void) |
---|
857 | { |
---|
858 | ESI = (ESI + T0); |
---|
859 | } |
---|
860 | |
---|
861 | void OPPROTO op_addq_EDI_T0(void) |
---|
862 | { |
---|
863 | EDI = (EDI + T0); |
---|
864 | } |
---|
865 | |
---|
866 | void OPPROTO op_decq_ECX(void) |
---|
867 | { |
---|
868 | ECX--; |
---|
869 | } |
---|
870 | #endif |
---|
871 | |
---|
872 | /* push/pop utils */ |
---|
873 | |
---|
874 | void op_addl_A0_SS(void) |
---|
875 | { |
---|
876 | A0 = (uint32_t)(A0 + env->segs[R_SS].base); |
---|
877 | } |
---|
878 | |
---|
879 | void op_subl_A0_2(void) |
---|
880 | { |
---|
881 | A0 = (uint32_t)(A0 - 2); |
---|
882 | } |
---|
883 | |
---|
884 | void op_subl_A0_4(void) |
---|
885 | { |
---|
886 | A0 = (uint32_t)(A0 - 4); |
---|
887 | } |
---|
888 | |
---|
889 | void op_addl_ESP_4(void) |
---|
890 | { |
---|
891 | ESP = (uint32_t)(ESP + 4); |
---|
892 | } |
---|
893 | |
---|
894 | void op_addl_ESP_2(void) |
---|
895 | { |
---|
896 | ESP = (uint32_t)(ESP + 2); |
---|
897 | } |
---|
898 | |
---|
899 | void op_addw_ESP_4(void) |
---|
900 | { |
---|
901 | ESP = (ESP & ~0xffff) | ((ESP + 4) & 0xffff); |
---|
902 | } |
---|
903 | |
---|
904 | void op_addw_ESP_2(void) |
---|
905 | { |
---|
906 | ESP = (ESP & ~0xffff) | ((ESP + 2) & 0xffff); |
---|
907 | } |
---|
908 | |
---|
909 | void op_addl_ESP_im(void) |
---|
910 | { |
---|
911 | ESP = (uint32_t)(ESP + PARAM1); |
---|
912 | } |
---|
913 | |
---|
914 | void op_addw_ESP_im(void) |
---|
915 | { |
---|
916 | ESP = (ESP & ~0xffff) | ((ESP + PARAM1) & 0xffff); |
---|
917 | } |
---|
918 | |
---|
919 | #ifdef TARGET_X86_64 |
---|
920 | void op_subq_A0_2(void) |
---|
921 | { |
---|
922 | A0 -= 2; |
---|
923 | } |
---|
924 | |
---|
925 | void op_subq_A0_8(void) |
---|
926 | { |
---|
927 | A0 -= 8; |
---|
928 | } |
---|
929 | |
---|
930 | void op_addq_ESP_8(void) |
---|
931 | { |
---|
932 | ESP += 8; |
---|
933 | } |
---|
934 | |
---|
935 | void op_addq_ESP_im(void) |
---|
936 | { |
---|
937 | ESP += PARAM1; |
---|
938 | } |
---|
939 | #endif |
---|
940 | |
---|
941 | void OPPROTO op_rdtsc(void) |
---|
942 | { |
---|
943 | helper_rdtsc(); |
---|
944 | } |
---|
945 | |
---|
946 | void OPPROTO op_cpuid(void) |
---|
947 | { |
---|
948 | helper_cpuid(); |
---|
949 | } |
---|
950 | |
---|
951 | void OPPROTO op_enter_level(void) |
---|
952 | { |
---|
953 | helper_enter_level(PARAM1, PARAM2); |
---|
954 | } |
---|
955 | |
---|
956 | #ifdef TARGET_X86_64 |
---|
957 | void OPPROTO op_enter64_level(void) |
---|
958 | { |
---|
959 | helper_enter64_level(PARAM1, PARAM2); |
---|
960 | } |
---|
961 | #endif |
---|
962 | |
---|
963 | void OPPROTO op_sysenter(void) |
---|
964 | { |
---|
965 | helper_sysenter(); |
---|
966 | } |
---|
967 | |
---|
968 | void OPPROTO op_sysexit(void) |
---|
969 | { |
---|
970 | helper_sysexit(); |
---|
971 | } |
---|
972 | |
---|
973 | #ifdef TARGET_X86_64 |
---|
974 | void OPPROTO op_syscall(void) |
---|
975 | { |
---|
976 | helper_syscall(PARAM1); |
---|
977 | } |
---|
978 | |
---|
979 | void OPPROTO op_sysret(void) |
---|
980 | { |
---|
981 | helper_sysret(PARAM1); |
---|
982 | } |
---|
983 | #endif |
---|
984 | |
---|
985 | void OPPROTO op_rdmsr(void) |
---|
986 | { |
---|
987 | helper_rdmsr(); |
---|
988 | } |
---|
989 | |
---|
990 | void OPPROTO op_wrmsr(void) |
---|
991 | { |
---|
992 | helper_wrmsr(); |
---|
993 | } |
---|
994 | |
---|
995 | /* bcd */ |
---|
996 | |
---|
997 | /* XXX: exception */ |
---|
998 | void OPPROTO op_aam(void) |
---|
999 | { |
---|
1000 | int base = PARAM1; |
---|
1001 | int al, ah; |
---|
1002 | al = EAX & 0xff; |
---|
1003 | ah = al / base; |
---|
1004 | al = al % base; |
---|
1005 | EAX = (EAX & ~0xffff) | al | (ah << 8); |
---|
1006 | CC_DST = al; |
---|
1007 | } |
---|
1008 | |
---|
1009 | void OPPROTO op_aad(void) |
---|
1010 | { |
---|
1011 | int base = PARAM1; |
---|
1012 | int al, ah; |
---|
1013 | al = EAX & 0xff; |
---|
1014 | ah = (EAX >> 8) & 0xff; |
---|
1015 | al = ((ah * base) + al) & 0xff; |
---|
1016 | EAX = (EAX & ~0xffff) | al; |
---|
1017 | CC_DST = al; |
---|
1018 | } |
---|
1019 | |
---|
1020 | void OPPROTO op_aaa(void) |
---|
1021 | { |
---|
1022 | int icarry; |
---|
1023 | int al, ah, af; |
---|
1024 | int eflags; |
---|
1025 | |
---|
1026 | eflags = cc_table[CC_OP].compute_all(); |
---|
1027 | af = eflags & CC_A; |
---|
1028 | al = EAX & 0xff; |
---|
1029 | ah = (EAX >> 8) & 0xff; |
---|
1030 | |
---|
1031 | icarry = (al > 0xf9); |
---|
1032 | if (((al & 0x0f) > 9 ) || af) { |
---|
1033 | al = (al + 6) & 0x0f; |
---|
1034 | ah = (ah + 1 + icarry) & 0xff; |
---|
1035 | eflags |= CC_C | CC_A; |
---|
1036 | } else { |
---|
1037 | eflags &= ~(CC_C | CC_A); |
---|
1038 | al &= 0x0f; |
---|
1039 | } |
---|
1040 | EAX = (EAX & ~0xffff) | al | (ah << 8); |
---|
1041 | CC_SRC = eflags; |
---|
1042 | FORCE_RET(); |
---|
1043 | } |
---|
1044 | |
---|
1045 | void OPPROTO op_aas(void) |
---|
1046 | { |
---|
1047 | int icarry; |
---|
1048 | int al, ah, af; |
---|
1049 | int eflags; |
---|
1050 | |
---|
1051 | eflags = cc_table[CC_OP].compute_all(); |
---|
1052 | af = eflags & CC_A; |
---|
1053 | al = EAX & 0xff; |
---|
1054 | ah = (EAX >> 8) & 0xff; |
---|
1055 | |
---|
1056 | icarry = (al < 6); |
---|
1057 | if (((al & 0x0f) > 9 ) || af) { |
---|
1058 | al = (al - 6) & 0x0f; |
---|
1059 | ah = (ah - 1 - icarry) & 0xff; |
---|
1060 | eflags |= CC_C | CC_A; |
---|
1061 | } else { |
---|
1062 | eflags &= ~(CC_C | CC_A); |
---|
1063 | al &= 0x0f; |
---|
1064 | } |
---|
1065 | EAX = (EAX & ~0xffff) | al | (ah << 8); |
---|
1066 | CC_SRC = eflags; |
---|
1067 | FORCE_RET(); |
---|
1068 | } |
---|
1069 | |
---|
1070 | void OPPROTO op_daa(void) |
---|
1071 | { |
---|
1072 | int al, af, cf; |
---|
1073 | int eflags; |
---|
1074 | |
---|
1075 | eflags = cc_table[CC_OP].compute_all(); |
---|
1076 | cf = eflags & CC_C; |
---|
1077 | af = eflags & CC_A; |
---|
1078 | al = EAX & 0xff; |
---|
1079 | |
---|
1080 | eflags = 0; |
---|
1081 | if (((al & 0x0f) > 9 ) || af) { |
---|
1082 | al = (al + 6) & 0xff; |
---|
1083 | eflags |= CC_A; |
---|
1084 | } |
---|
1085 | if ((al > 0x9f) || cf) { |
---|
1086 | al = (al + 0x60) & 0xff; |
---|
1087 | eflags |= CC_C; |
---|
1088 | } |
---|
1089 | EAX = (EAX & ~0xff) | al; |
---|
1090 | /* well, speed is not an issue here, so we compute the flags by hand */ |
---|
1091 | eflags |= (al == 0) << 6; /* zf */ |
---|
1092 | eflags |= parity_table[al]; /* pf */ |
---|
1093 | eflags |= (al & 0x80); /* sf */ |
---|
1094 | CC_SRC = eflags; |
---|
1095 | FORCE_RET(); |
---|
1096 | } |
---|
1097 | |
---|
1098 | void OPPROTO op_das(void) |
---|
1099 | { |
---|
1100 | int al, al1, af, cf; |
---|
1101 | int eflags; |
---|
1102 | |
---|
1103 | eflags = cc_table[CC_OP].compute_all(); |
---|
1104 | cf = eflags & CC_C; |
---|
1105 | af = eflags & CC_A; |
---|
1106 | al = EAX & 0xff; |
---|
1107 | |
---|
1108 | eflags = 0; |
---|
1109 | al1 = al; |
---|
1110 | if (((al & 0x0f) > 9 ) || af) { |
---|
1111 | eflags |= CC_A; |
---|
1112 | if (al < 6 || cf) |
---|
1113 | eflags |= CC_C; |
---|
1114 | al = (al - 6) & 0xff; |
---|
1115 | } |
---|
1116 | if ((al1 > 0x99) || cf) { |
---|
1117 | al = (al - 0x60) & 0xff; |
---|
1118 | eflags |= CC_C; |
---|
1119 | } |
---|
1120 | EAX = (EAX & ~0xff) | al; |
---|
1121 | /* well, speed is not an issue here, so we compute the flags by hand */ |
---|
1122 | eflags |= (al == 0) << 6; /* zf */ |
---|
1123 | eflags |= parity_table[al]; /* pf */ |
---|
1124 | eflags |= (al & 0x80); /* sf */ |
---|
1125 | CC_SRC = eflags; |
---|
1126 | FORCE_RET(); |
---|
1127 | } |
---|
1128 | |
---|
1129 | /* segment handling */ |
---|
1130 | |
---|
1131 | /* never use it with R_CS */ |
---|
1132 | void OPPROTO op_movl_seg_T0(void) |
---|
1133 | { |
---|
1134 | load_seg(PARAM1, T0); |
---|
1135 | } |
---|
1136 | |
---|
1137 | /* faster VM86 version */ |
---|
1138 | void OPPROTO op_movl_seg_T0_vm(void) |
---|
1139 | { |
---|
1140 | int selector; |
---|
1141 | SegmentCache *sc; |
---|
1142 | |
---|
1143 | selector = T0 & 0xffff; |
---|
1144 | /* env->segs[] access */ |
---|
1145 | sc = (SegmentCache *)((char *)env + PARAM1); |
---|
1146 | sc->selector = selector; |
---|
1147 | sc->base = (selector << 4); |
---|
1148 | } |
---|
1149 | |
---|
1150 | void OPPROTO op_movl_T0_seg(void) |
---|
1151 | { |
---|
1152 | T0 = env->segs[PARAM1].selector; |
---|
1153 | } |
---|
1154 | |
---|
1155 | void OPPROTO op_lsl(void) |
---|
1156 | { |
---|
1157 | helper_lsl(); |
---|
1158 | } |
---|
1159 | |
---|
1160 | void OPPROTO op_lar(void) |
---|
1161 | { |
---|
1162 | helper_lar(); |
---|
1163 | } |
---|
1164 | |
---|
1165 | void OPPROTO op_verr(void) |
---|
1166 | { |
---|
1167 | helper_verr(); |
---|
1168 | } |
---|
1169 | |
---|
1170 | void OPPROTO op_verw(void) |
---|
1171 | { |
---|
1172 | helper_verw(); |
---|
1173 | } |
---|
1174 | |
---|
1175 | void OPPROTO op_arpl(void) |
---|
1176 | { |
---|
1177 | if ((T0 & 3) < (T1 & 3)) { |
---|
1178 | /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */ |
---|
1179 | T0 = (T0 & ~3) | (T1 & 3); |
---|
1180 | T1 = CC_Z; |
---|
1181 | } else { |
---|
1182 | T1 = 0; |
---|
1183 | } |
---|
1184 | FORCE_RET(); |
---|
1185 | } |
---|
1186 | |
---|
1187 | void OPPROTO op_arpl_update(void) |
---|
1188 | { |
---|
1189 | int eflags; |
---|
1190 | eflags = cc_table[CC_OP].compute_all(); |
---|
1191 | CC_SRC = (eflags & ~CC_Z) | T1; |
---|
1192 | } |
---|
1193 | |
---|
1194 | /* T0: segment, T1:eip */ |
---|
1195 | void OPPROTO op_ljmp_protected_T0_T1(void) |
---|
1196 | { |
---|
1197 | helper_ljmp_protected_T0_T1(PARAM1); |
---|
1198 | } |
---|
1199 | |
---|
1200 | void OPPROTO op_lcall_real_T0_T1(void) |
---|
1201 | { |
---|
1202 | helper_lcall_real_T0_T1(PARAM1, PARAM2); |
---|
1203 | } |
---|
1204 | |
---|
1205 | void OPPROTO op_lcall_protected_T0_T1(void) |
---|
1206 | { |
---|
1207 | helper_lcall_protected_T0_T1(PARAM1, PARAM2); |
---|
1208 | } |
---|
1209 | |
---|
1210 | void OPPROTO op_iret_real(void) |
---|
1211 | { |
---|
1212 | helper_iret_real(PARAM1); |
---|
1213 | } |
---|
1214 | |
---|
1215 | void OPPROTO op_iret_protected(void) |
---|
1216 | { |
---|
1217 | helper_iret_protected(PARAM1, PARAM2); |
---|
1218 | } |
---|
1219 | |
---|
1220 | void OPPROTO op_lret_protected(void) |
---|
1221 | { |
---|
1222 | helper_lret_protected(PARAM1, PARAM2); |
---|
1223 | } |
---|
1224 | |
---|
1225 | void OPPROTO op_lldt_T0(void) |
---|
1226 | { |
---|
1227 | helper_lldt_T0(); |
---|
1228 | } |
---|
1229 | |
---|
1230 | void OPPROTO op_ltr_T0(void) |
---|
1231 | { |
---|
1232 | helper_ltr_T0(); |
---|
1233 | } |
---|
1234 | |
---|
1235 | /* CR registers access */ |
---|
1236 | void OPPROTO op_movl_crN_T0(void) |
---|
1237 | { |
---|
1238 | helper_movl_crN_T0(PARAM1); |
---|
1239 | } |
---|
1240 | |
---|
1241 | #if !defined(CONFIG_USER_ONLY) |
---|
1242 | void OPPROTO op_movtl_T0_cr8(void) |
---|
1243 | { |
---|
1244 | T0 = cpu_get_apic_tpr(env); |
---|
1245 | } |
---|
1246 | #endif |
---|
1247 | |
---|
1248 | /* DR registers access */ |
---|
1249 | void OPPROTO op_movl_drN_T0(void) |
---|
1250 | { |
---|
1251 | helper_movl_drN_T0(PARAM1); |
---|
1252 | } |
---|
1253 | |
---|
1254 | void OPPROTO op_lmsw_T0(void) |
---|
1255 | { |
---|
1256 | /* only 4 lower bits of CR0 are modified. PE cannot be set to zero |
---|
1257 | if already set to one. */ |
---|
1258 | T0 = (env->cr[0] & ~0xe) | (T0 & 0xf); |
---|
1259 | helper_movl_crN_T0(0); |
---|
1260 | } |
---|
1261 | |
---|
1262 | void OPPROTO op_invlpg_A0(void) |
---|
1263 | { |
---|
1264 | helper_invlpg(A0); |
---|
1265 | } |
---|
1266 | |
---|
1267 | void OPPROTO op_movl_T0_env(void) |
---|
1268 | { |
---|
1269 | T0 = *(uint32_t *)((char *)env + PARAM1); |
---|
1270 | } |
---|
1271 | |
---|
1272 | void OPPROTO op_movl_env_T0(void) |
---|
1273 | { |
---|
1274 | *(uint32_t *)((char *)env + PARAM1) = T0; |
---|
1275 | } |
---|
1276 | |
---|
1277 | void OPPROTO op_movl_env_T1(void) |
---|
1278 | { |
---|
1279 | *(uint32_t *)((char *)env + PARAM1) = T1; |
---|
1280 | } |
---|
1281 | |
---|
1282 | void OPPROTO op_movtl_T0_env(void) |
---|
1283 | { |
---|
1284 | T0 = *(target_ulong *)((char *)env + PARAM1); |
---|
1285 | } |
---|
1286 | |
---|
1287 | void OPPROTO op_movtl_env_T0(void) |
---|
1288 | { |
---|
1289 | *(target_ulong *)((char *)env + PARAM1) = T0; |
---|
1290 | } |
---|
1291 | |
---|
1292 | void OPPROTO op_movtl_T1_env(void) |
---|
1293 | { |
---|
1294 | T1 = *(target_ulong *)((char *)env + PARAM1); |
---|
1295 | } |
---|
1296 | |
---|
1297 | void OPPROTO op_movtl_env_T1(void) |
---|
1298 | { |
---|
1299 | *(target_ulong *)((char *)env + PARAM1) = T1; |
---|
1300 | } |
---|
1301 | |
---|
1302 | void OPPROTO op_clts(void) |
---|
1303 | { |
---|
1304 | env->cr[0] &= ~CR0_TS_MASK; |
---|
1305 | env->hflags &= ~HF_TS_MASK; |
---|
1306 | } |
---|
1307 | |
---|
1308 | /* flags handling */ |
---|
1309 | |
---|
1310 | void OPPROTO op_goto_tb0(void) |
---|
1311 | { |
---|
1312 | GOTO_TB(op_goto_tb0, PARAM1, 0); |
---|
1313 | } |
---|
1314 | |
---|
1315 | void OPPROTO op_goto_tb1(void) |
---|
1316 | { |
---|
1317 | GOTO_TB(op_goto_tb1, PARAM1, 1); |
---|
1318 | } |
---|
1319 | |
---|
1320 | void OPPROTO op_jmp_label(void) |
---|
1321 | { |
---|
1322 | GOTO_LABEL_PARAM(1); |
---|
1323 | } |
---|
1324 | |
---|
1325 | void OPPROTO op_jnz_T0_label(void) |
---|
1326 | { |
---|
1327 | if (T0) |
---|
1328 | GOTO_LABEL_PARAM(1); |
---|
1329 | FORCE_RET(); |
---|
1330 | } |
---|
1331 | |
---|
1332 | void OPPROTO op_jz_T0_label(void) |
---|
1333 | { |
---|
1334 | if (!T0) |
---|
1335 | GOTO_LABEL_PARAM(1); |
---|
1336 | FORCE_RET(); |
---|
1337 | } |
---|
1338 | |
---|
1339 | /* slow set cases (compute x86 flags) */ |
---|
1340 | void OPPROTO op_seto_T0_cc(void) |
---|
1341 | { |
---|
1342 | int eflags; |
---|
1343 | eflags = cc_table[CC_OP].compute_all(); |
---|
1344 | T0 = (eflags >> 11) & 1; |
---|
1345 | } |
---|
1346 | |
---|
1347 | void OPPROTO op_setb_T0_cc(void) |
---|
1348 | { |
---|
1349 | T0 = cc_table[CC_OP].compute_c(); |
---|
1350 | } |
---|
1351 | |
---|
1352 | void OPPROTO op_setz_T0_cc(void) |
---|
1353 | { |
---|
1354 | int eflags; |
---|
1355 | eflags = cc_table[CC_OP].compute_all(); |
---|
1356 | T0 = (eflags >> 6) & 1; |
---|
1357 | } |
---|
1358 | |
---|
1359 | void OPPROTO op_setbe_T0_cc(void) |
---|
1360 | { |
---|
1361 | int eflags; |
---|
1362 | eflags = cc_table[CC_OP].compute_all(); |
---|
1363 | T0 = (eflags & (CC_Z | CC_C)) != 0; |
---|
1364 | } |
---|
1365 | |
---|
1366 | void OPPROTO op_sets_T0_cc(void) |
---|
1367 | { |
---|
1368 | int eflags; |
---|
1369 | eflags = cc_table[CC_OP].compute_all(); |
---|
1370 | T0 = (eflags >> 7) & 1; |
---|
1371 | } |
---|
1372 | |
---|
1373 | void OPPROTO op_setp_T0_cc(void) |
---|
1374 | { |
---|
1375 | int eflags; |
---|
1376 | eflags = cc_table[CC_OP].compute_all(); |
---|
1377 | T0 = (eflags >> 2) & 1; |
---|
1378 | } |
---|
1379 | |
---|
1380 | void OPPROTO op_setl_T0_cc(void) |
---|
1381 | { |
---|
1382 | int eflags; |
---|
1383 | eflags = cc_table[CC_OP].compute_all(); |
---|
1384 | T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1; |
---|
1385 | } |
---|
1386 | |
---|
1387 | void OPPROTO op_setle_T0_cc(void) |
---|
1388 | { |
---|
1389 | int eflags; |
---|
1390 | eflags = cc_table[CC_OP].compute_all(); |
---|
1391 | T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0; |
---|
1392 | } |
---|
1393 | |
---|
1394 | void OPPROTO op_xor_T0_1(void) |
---|
1395 | { |
---|
1396 | T0 ^= 1; |
---|
1397 | } |
---|
1398 | |
---|
1399 | void OPPROTO op_set_cc_op(void) |
---|
1400 | { |
---|
1401 | CC_OP = PARAM1; |
---|
1402 | } |
---|
1403 | |
---|
1404 | void OPPROTO op_mov_T0_cc(void) |
---|
1405 | { |
---|
1406 | T0 = cc_table[CC_OP].compute_all(); |
---|
1407 | } |
---|
1408 | |
---|
1409 | /* XXX: clear VIF/VIP in all ops ? */ |
---|
1410 | |
---|
1411 | void OPPROTO op_movl_eflags_T0(void) |
---|
1412 | { |
---|
1413 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK)); |
---|
1414 | } |
---|
1415 | |
---|
1416 | void OPPROTO op_movw_eflags_T0(void) |
---|
1417 | { |
---|
1418 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff); |
---|
1419 | } |
---|
1420 | |
---|
1421 | void OPPROTO op_movl_eflags_T0_io(void) |
---|
1422 | { |
---|
1423 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK)); |
---|
1424 | } |
---|
1425 | |
---|
1426 | void OPPROTO op_movw_eflags_T0_io(void) |
---|
1427 | { |
---|
1428 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff); |
---|
1429 | } |
---|
1430 | |
---|
1431 | void OPPROTO op_movl_eflags_T0_cpl0(void) |
---|
1432 | { |
---|
1433 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK)); |
---|
1434 | } |
---|
1435 | |
---|
1436 | void OPPROTO op_movw_eflags_T0_cpl0(void) |
---|
1437 | { |
---|
1438 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff); |
---|
1439 | } |
---|
1440 | |
---|
1441 | #if 0 |
---|
1442 | /* vm86plus version */ |
---|
1443 | void OPPROTO op_movw_eflags_T0_vm(void) |
---|
1444 | { |
---|
1445 | int eflags; |
---|
1446 | eflags = T0; |
---|
1447 | CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
---|
1448 | DF = 1 - (2 * ((eflags >> 10) & 1)); |
---|
1449 | /* we also update some system flags as in user mode */ |
---|
1450 | env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) | |
---|
1451 | (eflags & FL_UPDATE_MASK16); |
---|
1452 | if (eflags & IF_MASK) { |
---|
1453 | env->eflags |= VIF_MASK; |
---|
1454 | if (env->eflags & VIP_MASK) { |
---|
1455 | EIP = PARAM1; |
---|
1456 | raise_exception(EXCP0D_GPF); |
---|
1457 | } |
---|
1458 | } |
---|
1459 | FORCE_RET(); |
---|
1460 | } |
---|
1461 | |
---|
1462 | void OPPROTO op_movl_eflags_T0_vm(void) |
---|
1463 | { |
---|
1464 | int eflags; |
---|
1465 | eflags = T0; |
---|
1466 | CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
---|
1467 | DF = 1 - (2 * ((eflags >> 10) & 1)); |
---|
1468 | /* we also update some system flags as in user mode */ |
---|
1469 | env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) | |
---|
1470 | (eflags & FL_UPDATE_MASK32); |
---|
1471 | if (eflags & IF_MASK) { |
---|
1472 | env->eflags |= VIF_MASK; |
---|
1473 | if (env->eflags & VIP_MASK) { |
---|
1474 | EIP = PARAM1; |
---|
1475 | raise_exception(EXCP0D_GPF); |
---|
1476 | } |
---|
1477 | } |
---|
1478 | FORCE_RET(); |
---|
1479 | } |
---|
1480 | #endif |
---|
1481 | |
---|
1482 | /* XXX: compute only O flag */ |
---|
1483 | void OPPROTO op_movb_eflags_T0(void) |
---|
1484 | { |
---|
1485 | int of; |
---|
1486 | of = cc_table[CC_OP].compute_all() & CC_O; |
---|
1487 | CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of; |
---|
1488 | } |
---|
1489 | |
---|
1490 | void OPPROTO op_movl_T0_eflags(void) |
---|
1491 | { |
---|
1492 | int eflags; |
---|
1493 | eflags = cc_table[CC_OP].compute_all(); |
---|
1494 | eflags |= (DF & DF_MASK); |
---|
1495 | eflags |= env->eflags & ~(VM_MASK | RF_MASK); |
---|
1496 | T0 = eflags; |
---|
1497 | } |
---|
1498 | |
---|
1499 | /* vm86plus version */ |
---|
1500 | #if 0 |
---|
1501 | void OPPROTO op_movl_T0_eflags_vm(void) |
---|
1502 | { |
---|
1503 | int eflags; |
---|
1504 | eflags = cc_table[CC_OP].compute_all(); |
---|
1505 | eflags |= (DF & DF_MASK); |
---|
1506 | eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK); |
---|
1507 | if (env->eflags & VIF_MASK) |
---|
1508 | eflags |= IF_MASK; |
---|
1509 | T0 = eflags; |
---|
1510 | } |
---|
1511 | #endif |
---|
1512 | |
---|
1513 | void OPPROTO op_cld(void) |
---|
1514 | { |
---|
1515 | DF = 1; |
---|
1516 | } |
---|
1517 | |
---|
1518 | void OPPROTO op_std(void) |
---|
1519 | { |
---|
1520 | DF = -1; |
---|
1521 | } |
---|
1522 | |
---|
1523 | void OPPROTO op_clc(void) |
---|
1524 | { |
---|
1525 | int eflags; |
---|
1526 | eflags = cc_table[CC_OP].compute_all(); |
---|
1527 | eflags &= ~CC_C; |
---|
1528 | CC_SRC = eflags; |
---|
1529 | } |
---|
1530 | |
---|
1531 | void OPPROTO op_stc(void) |
---|
1532 | { |
---|
1533 | int eflags; |
---|
1534 | eflags = cc_table[CC_OP].compute_all(); |
---|
1535 | eflags |= CC_C; |
---|
1536 | CC_SRC = eflags; |
---|
1537 | } |
---|
1538 | |
---|
1539 | void OPPROTO op_cmc(void) |
---|
1540 | { |
---|
1541 | int eflags; |
---|
1542 | eflags = cc_table[CC_OP].compute_all(); |
---|
1543 | eflags ^= CC_C; |
---|
1544 | CC_SRC = eflags; |
---|
1545 | } |
---|
1546 | |
---|
1547 | void OPPROTO op_salc(void) |
---|
1548 | { |
---|
1549 | int cf; |
---|
1550 | cf = cc_table[CC_OP].compute_c(); |
---|
1551 | EAX = (EAX & ~0xff) | ((-cf) & 0xff); |
---|
1552 | } |
---|
1553 | |
---|
1554 | static int compute_all_eflags(void) |
---|
1555 | { |
---|
1556 | return CC_SRC; |
---|
1557 | } |
---|
1558 | |
---|
1559 | static int compute_c_eflags(void) |
---|
1560 | { |
---|
1561 | return CC_SRC & CC_C; |
---|
1562 | } |
---|
1563 | |
---|
1564 | CCTable cc_table[CC_OP_NB] = { |
---|
1565 | [CC_OP_DYNAMIC] = { /* should never happen */ }, |
---|
1566 | |
---|
1567 | [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags }, |
---|
1568 | |
---|
1569 | [CC_OP_MULB] = { compute_all_mulb, compute_c_mull }, |
---|
1570 | [CC_OP_MULW] = { compute_all_mulw, compute_c_mull }, |
---|
1571 | [CC_OP_MULL] = { compute_all_mull, compute_c_mull }, |
---|
1572 | |
---|
1573 | [CC_OP_ADDB] = { compute_all_addb, compute_c_addb }, |
---|
1574 | [CC_OP_ADDW] = { compute_all_addw, compute_c_addw }, |
---|
1575 | [CC_OP_ADDL] = { compute_all_addl, compute_c_addl }, |
---|
1576 | |
---|
1577 | [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb }, |
---|
1578 | [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw }, |
---|
1579 | [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl }, |
---|
1580 | |
---|
1581 | [CC_OP_SUBB] = { compute_all_subb, compute_c_subb }, |
---|
1582 | [CC_OP_SUBW] = { compute_all_subw, compute_c_subw }, |
---|
1583 | [CC_OP_SUBL] = { compute_all_subl, compute_c_subl }, |
---|
1584 | |
---|
1585 | [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb }, |
---|
1586 | [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw }, |
---|
1587 | [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl }, |
---|
1588 | |
---|
1589 | [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb }, |
---|
1590 | [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw }, |
---|
1591 | [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl }, |
---|
1592 | |
---|
1593 | [CC_OP_INCB] = { compute_all_incb, compute_c_incl }, |
---|
1594 | [CC_OP_INCW] = { compute_all_incw, compute_c_incl }, |
---|
1595 | [CC_OP_INCL] = { compute_all_incl, compute_c_incl }, |
---|
1596 | |
---|
1597 | [CC_OP_DECB] = { compute_all_decb, compute_c_incl }, |
---|
1598 | [CC_OP_DECW] = { compute_all_decw, compute_c_incl }, |
---|
1599 | [CC_OP_DECL] = { compute_all_decl, compute_c_incl }, |
---|
1600 | |
---|
1601 | [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb }, |
---|
1602 | [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw }, |
---|
1603 | [CC_OP_SHLL] = { compute_all_shll, compute_c_shll }, |
---|
1604 | |
---|
1605 | [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl }, |
---|
1606 | [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl }, |
---|
1607 | [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl }, |
---|
1608 | |
---|
1609 | #ifdef TARGET_X86_64 |
---|
1610 | [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull }, |
---|
1611 | |
---|
1612 | [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq }, |
---|
1613 | |
---|
1614 | [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq }, |
---|
1615 | |
---|
1616 | [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq }, |
---|
1617 | |
---|
1618 | [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq }, |
---|
1619 | |
---|
1620 | [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq }, |
---|
1621 | |
---|
1622 | [CC_OP_INCQ] = { compute_all_incq, compute_c_incl }, |
---|
1623 | |
---|
1624 | [CC_OP_DECQ] = { compute_all_decq, compute_c_incl }, |
---|
1625 | |
---|
1626 | [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq }, |
---|
1627 | |
---|
1628 | [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl }, |
---|
1629 | #endif |
---|
1630 | }; |
---|
1631 | |
---|
1632 | /* floating point support. Some of the code for complicated x87 |
---|
1633 | functions comes from the LGPL'ed x86 emulator found in the Willows |
---|
1634 | TWIN windows emulator. */ |
---|
1635 | |
---|
1636 | /* fp load FT0 */ |
---|
1637 | |
---|
1638 | void OPPROTO op_flds_FT0_A0(void) |
---|
1639 | { |
---|
1640 | #ifdef USE_FP_CONVERT |
---|
1641 | FP_CONVERT.i32 = ldl(A0); |
---|
1642 | FT0 = FP_CONVERT.f; |
---|
1643 | #else |
---|
1644 | FT0 = ldfl(A0); |
---|
1645 | #endif |
---|
1646 | } |
---|
1647 | |
---|
1648 | void OPPROTO op_fldl_FT0_A0(void) |
---|
1649 | { |
---|
1650 | #ifdef USE_FP_CONVERT |
---|
1651 | FP_CONVERT.i64 = ldq(A0); |
---|
1652 | FT0 = FP_CONVERT.d; |
---|
1653 | #else |
---|
1654 | FT0 = ldfq(A0); |
---|
1655 | #endif |
---|
1656 | } |
---|
1657 | |
---|
1658 | /* helpers are needed to avoid static constant reference. XXX: find a better way */ |
---|
1659 | #ifdef USE_INT_TO_FLOAT_HELPERS |
---|
1660 | |
---|
1661 | void helper_fild_FT0_A0(void) |
---|
1662 | { |
---|
1663 | FT0 = (CPU86_LDouble)ldsw(A0); |
---|
1664 | } |
---|
1665 | |
---|
1666 | void helper_fildl_FT0_A0(void) |
---|
1667 | { |
---|
1668 | FT0 = (CPU86_LDouble)((int32_t)ldl(A0)); |
---|
1669 | } |
---|
1670 | |
---|
1671 | void helper_fildll_FT0_A0(void) |
---|
1672 | { |
---|
1673 | FT0 = (CPU86_LDouble)((int64_t)ldq(A0)); |
---|
1674 | } |
---|
1675 | |
---|
1676 | void OPPROTO op_fild_FT0_A0(void) |
---|
1677 | { |
---|
1678 | helper_fild_FT0_A0(); |
---|
1679 | } |
---|
1680 | |
---|
1681 | void OPPROTO op_fildl_FT0_A0(void) |
---|
1682 | { |
---|
1683 | helper_fildl_FT0_A0(); |
---|
1684 | } |
---|
1685 | |
---|
1686 | void OPPROTO op_fildll_FT0_A0(void) |
---|
1687 | { |
---|
1688 | helper_fildll_FT0_A0(); |
---|
1689 | } |
---|
1690 | |
---|
1691 | #else |
---|
1692 | |
---|
1693 | void OPPROTO op_fild_FT0_A0(void) |
---|
1694 | { |
---|
1695 | #ifdef USE_FP_CONVERT |
---|
1696 | FP_CONVERT.i32 = ldsw(A0); |
---|
1697 | FT0 = (CPU86_LDouble)FP_CONVERT.i32; |
---|
1698 | #else |
---|
1699 | FT0 = (CPU86_LDouble)ldsw(A0); |
---|
1700 | #endif |
---|
1701 | } |
---|
1702 | |
---|
1703 | void OPPROTO op_fildl_FT0_A0(void) |
---|
1704 | { |
---|
1705 | #ifdef USE_FP_CONVERT |
---|
1706 | FP_CONVERT.i32 = (int32_t) ldl(A0); |
---|
1707 | FT0 = (CPU86_LDouble)FP_CONVERT.i32; |
---|
1708 | #else |
---|
1709 | FT0 = (CPU86_LDouble)((int32_t)ldl(A0)); |
---|
1710 | #endif |
---|
1711 | } |
---|
1712 | |
---|
1713 | void OPPROTO op_fildll_FT0_A0(void) |
---|
1714 | { |
---|
1715 | #ifdef USE_FP_CONVERT |
---|
1716 | FP_CONVERT.i64 = (int64_t) ldq(A0); |
---|
1717 | FT0 = (CPU86_LDouble)FP_CONVERT.i64; |
---|
1718 | #else |
---|
1719 | FT0 = (CPU86_LDouble)((int64_t)ldq(A0)); |
---|
1720 | #endif |
---|
1721 | } |
---|
1722 | #endif |
---|
1723 | |
---|
1724 | /* fp load ST0 */ |
---|
1725 | |
---|
1726 | void OPPROTO op_flds_ST0_A0(void) |
---|
1727 | { |
---|
1728 | int new_fpstt; |
---|
1729 | new_fpstt = (env->fpstt - 1) & 7; |
---|
1730 | #ifdef USE_FP_CONVERT |
---|
1731 | FP_CONVERT.i32 = ldl(A0); |
---|
1732 | env->fpregs[new_fpstt].d = FP_CONVERT.f; |
---|
1733 | #else |
---|
1734 | env->fpregs[new_fpstt].d = ldfl(A0); |
---|
1735 | #endif |
---|
1736 | env->fpstt = new_fpstt; |
---|
1737 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
---|
1738 | } |
---|
1739 | |
---|
1740 | void OPPROTO op_fldl_ST0_A0(void) |
---|
1741 | { |
---|
1742 | int new_fpstt; |
---|
1743 | new_fpstt = (env->fpstt - 1) & 7; |
---|
1744 | #ifdef USE_FP_CONVERT |
---|
1745 | FP_CONVERT.i64 = ldq(A0); |
---|
1746 | env->fpregs[new_fpstt].d = FP_CONVERT.d; |
---|
1747 | #else |
---|
1748 | env->fpregs[new_fpstt].d = ldfq(A0); |
---|
1749 | #endif |
---|
1750 | env->fpstt = new_fpstt; |
---|
1751 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
---|
1752 | } |
---|
1753 | |
---|
1754 | void OPPROTO op_fldt_ST0_A0(void) |
---|
1755 | { |
---|
1756 | helper_fldt_ST0_A0(); |
---|
1757 | } |
---|
1758 | |
---|
1759 | /* helpers are needed to avoid static constant reference. XXX: find a better way */ |
---|
1760 | #ifdef USE_INT_TO_FLOAT_HELPERS |
---|
1761 | |
---|
1762 | void helper_fild_ST0_A0(void) |
---|
1763 | { |
---|
1764 | int new_fpstt; |
---|
1765 | new_fpstt = (env->fpstt - 1) & 7; |
---|
1766 | env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0); |
---|
1767 | env->fpstt = new_fpstt; |
---|
1768 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
---|
1769 | } |
---|
1770 | |
---|
1771 | void helper_fildl_ST0_A0(void) |
---|
1772 | { |
---|
1773 | int new_fpstt; |
---|
1774 | new_fpstt = (env->fpstt - 1) & 7; |
---|
1775 | env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0)); |
---|
1776 | env->fpstt = new_fpstt; |
---|
1777 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
---|
1778 | } |
---|
1779 | |
---|
1780 | void helper_fildll_ST0_A0(void) |
---|
1781 | { |
---|
1782 | int new_fpstt; |
---|
1783 | new_fpstt = (env->fpstt - 1) & 7; |
---|
1784 | env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0)); |
---|
1785 | env->fpstt = new_fpstt; |
---|
1786 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
---|
1787 | } |
---|
1788 | |
---|
1789 | void OPPROTO op_fild_ST0_A0(void) |
---|
1790 | { |
---|
1791 | helper_fild_ST0_A0(); |
---|
1792 | } |
---|
1793 | |
---|
1794 | void OPPROTO op_fildl_ST0_A0(void) |
---|
1795 | { |
---|
1796 | helper_fildl_ST0_A0(); |
---|
1797 | } |
---|
1798 | |
---|
1799 | void OPPROTO op_fildll_ST0_A0(void) |
---|
1800 | { |
---|
1801 | helper_fildll_ST0_A0(); |
---|
1802 | } |
---|
1803 | |
---|
1804 | #else |
---|
1805 | |
---|
1806 | void OPPROTO op_fild_ST0_A0(void) |
---|
1807 | { |
---|
1808 | int new_fpstt; |
---|
1809 | new_fpstt = (env->fpstt - 1) & 7; |
---|
1810 | #ifdef USE_FP_CONVERT |
---|
1811 | FP_CONVERT.i32 = ldsw(A0); |
---|
1812 | env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32; |
---|
1813 | #else |
---|
1814 | env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0); |
---|
1815 | #endif |
---|
1816 | env->fpstt = new_fpstt; |
---|
1817 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
---|
1818 | } |
---|
1819 | |
---|
1820 | void OPPROTO op_fildl_ST0_A0(void) |
---|
1821 | { |
---|
1822 | int new_fpstt; |
---|
1823 | new_fpstt = (env->fpstt - 1) & 7; |
---|
1824 | #ifdef USE_FP_CONVERT |
---|
1825 | FP_CONVERT.i32 = (int32_t) ldl(A0); |
---|
1826 | env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32; |
---|
1827 | #else |
---|
1828 | env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0)); |
---|
1829 | #endif |
---|
1830 | env->fpstt = new_fpstt; |
---|
1831 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
---|
1832 | } |
---|
1833 | |
---|
1834 | void OPPROTO op_fildll_ST0_A0(void) |
---|
1835 | { |
---|
1836 | int new_fpstt; |
---|
1837 | new_fpstt = (env->fpstt - 1) & 7; |
---|
1838 | #ifdef USE_FP_CONVERT |
---|
1839 | FP_CONVERT.i64 = (int64_t) ldq(A0); |
---|
1840 | env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i64; |
---|
1841 | #else |
---|
1842 | env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0)); |
---|
1843 | #endif |
---|
1844 | env->fpstt = new_fpstt; |
---|
1845 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
---|
1846 | } |
---|
1847 | |
---|
1848 | #endif |
---|
1849 | |
---|
1850 | /* fp store */ |
---|
1851 | |
---|
1852 | void OPPROTO op_fsts_ST0_A0(void) |
---|
1853 | { |
---|
1854 | #ifdef USE_FP_CONVERT |
---|
1855 | FP_CONVERT.f = (float)ST0; |
---|
1856 | stfl(A0, FP_CONVERT.f); |
---|
1857 | #else |
---|
1858 | stfl(A0, (float)ST0); |
---|
1859 | #endif |
---|
1860 | FORCE_RET(); |
---|
1861 | } |
---|
1862 | |
---|
1863 | void OPPROTO op_fstl_ST0_A0(void) |
---|
1864 | { |
---|
1865 | stfq(A0, (double)ST0); |
---|
1866 | FORCE_RET(); |
---|
1867 | } |
---|
1868 | |
---|
1869 | void OPPROTO op_fstt_ST0_A0(void) |
---|
1870 | { |
---|
1871 | helper_fstt_ST0_A0(); |
---|
1872 | } |
---|
1873 | |
---|
1874 | void OPPROTO op_fist_ST0_A0(void) |
---|
1875 | { |
---|
1876 | #if defined(__sparc__) && !defined(__sparc_v9__) |
---|
1877 | register CPU86_LDouble d asm("o0"); |
---|
1878 | #else |
---|
1879 | CPU86_LDouble d; |
---|
1880 | #endif |
---|
1881 | int val; |
---|
1882 | |
---|
1883 | d = ST0; |
---|
1884 | val = floatx_to_int32(d, &env->fp_status); |
---|
1885 | if (val != (int16_t)val) |
---|
1886 | val = -32768; |
---|
1887 | stw(A0, val); |
---|
1888 | FORCE_RET(); |
---|
1889 | } |
---|
1890 | |
---|
1891 | void OPPROTO op_fistl_ST0_A0(void) |
---|
1892 | { |
---|
1893 | #if defined(__sparc__) && !defined(__sparc_v9__) |
---|
1894 | register CPU86_LDouble d asm("o0"); |
---|
1895 | #else |
---|
1896 | CPU86_LDouble d; |
---|
1897 | #endif |
---|
1898 | int val; |
---|
1899 | |
---|
1900 | d = ST0; |
---|
1901 | val = floatx_to_int32(d, &env->fp_status); |
---|
1902 | stl(A0, val); |
---|
1903 | FORCE_RET(); |
---|
1904 | } |
---|
1905 | |
---|
1906 | void OPPROTO op_fistll_ST0_A0(void) |
---|
1907 | { |
---|
1908 | #if defined(__sparc__) && !defined(__sparc_v9__) |
---|
1909 | register CPU86_LDouble d asm("o0"); |
---|
1910 | #else |
---|
1911 | CPU86_LDouble d; |
---|
1912 | #endif |
---|
1913 | int64_t val; |
---|
1914 | |
---|
1915 | d = ST0; |
---|
1916 | val = floatx_to_int64(d, &env->fp_status); |
---|
1917 | stq(A0, val); |
---|
1918 | FORCE_RET(); |
---|
1919 | } |
---|
1920 | |
---|
1921 | void OPPROTO op_fistt_ST0_A0(void) |
---|
1922 | { |
---|
1923 | #if defined(__sparc__) && !defined(__sparc_v9__) |
---|
1924 | register CPU86_LDouble d asm("o0"); |
---|
1925 | #else |
---|
1926 | CPU86_LDouble d; |
---|
1927 | #endif |
---|
1928 | int val; |
---|
1929 | |
---|
1930 | d = ST0; |
---|
1931 | val = floatx_to_int32_round_to_zero(d, &env->fp_status); |
---|
1932 | if (val != (int16_t)val) |
---|
1933 | val = -32768; |
---|
1934 | stw(A0, val); |
---|
1935 | FORCE_RET(); |
---|
1936 | } |
---|
1937 | |
---|
1938 | void OPPROTO op_fisttl_ST0_A0(void) |
---|
1939 | { |
---|
1940 | #if defined(__sparc__) && !defined(__sparc_v9__) |
---|
1941 | register CPU86_LDouble d asm("o0"); |
---|
1942 | #else |
---|
1943 | CPU86_LDouble d; |
---|
1944 | #endif |
---|
1945 | int val; |
---|
1946 | |
---|
1947 | d = ST0; |
---|
1948 | val = floatx_to_int32_round_to_zero(d, &env->fp_status); |
---|
1949 | stl(A0, val); |
---|
1950 | FORCE_RET(); |
---|
1951 | } |
---|
1952 | |
---|
1953 | void OPPROTO op_fisttll_ST0_A0(void) |
---|
1954 | { |
---|
1955 | #if defined(__sparc__) && !defined(__sparc_v9__) |
---|
1956 | register CPU86_LDouble d asm("o0"); |
---|
1957 | #else |
---|
1958 | CPU86_LDouble d; |
---|
1959 | #endif |
---|
1960 | int64_t val; |
---|
1961 | |
---|
1962 | d = ST0; |
---|
1963 | val = floatx_to_int64_round_to_zero(d, &env->fp_status); |
---|
1964 | stq(A0, val); |
---|
1965 | FORCE_RET(); |
---|
1966 | } |
---|
1967 | |
---|
1968 | void OPPROTO op_fbld_ST0_A0(void) |
---|
1969 | { |
---|
1970 | helper_fbld_ST0_A0(); |
---|
1971 | } |
---|
1972 | |
---|
1973 | void OPPROTO op_fbst_ST0_A0(void) |
---|
1974 | { |
---|
1975 | helper_fbst_ST0_A0(); |
---|
1976 | } |
---|
1977 | |
---|
1978 | /* FPU move */ |
---|
1979 | |
---|
1980 | void OPPROTO op_fpush(void) |
---|
1981 | { |
---|
1982 | fpush(); |
---|
1983 | } |
---|
1984 | |
---|
1985 | void OPPROTO op_fpop(void) |
---|
1986 | { |
---|
1987 | fpop(); |
---|
1988 | } |
---|
1989 | |
---|
1990 | void OPPROTO op_fdecstp(void) |
---|
1991 | { |
---|
1992 | env->fpstt = (env->fpstt - 1) & 7; |
---|
1993 | env->fpus &= (~0x4700); |
---|
1994 | } |
---|
1995 | |
---|
1996 | void OPPROTO op_fincstp(void) |
---|
1997 | { |
---|
1998 | env->fpstt = (env->fpstt + 1) & 7; |
---|
1999 | env->fpus &= (~0x4700); |
---|
2000 | } |
---|
2001 | |
---|
2002 | void OPPROTO op_ffree_STN(void) |
---|
2003 | { |
---|
2004 | env->fptags[(env->fpstt + PARAM1) & 7] = 1; |
---|
2005 | } |
---|
2006 | |
---|
2007 | void OPPROTO op_fmov_ST0_FT0(void) |
---|
2008 | { |
---|
2009 | ST0 = FT0; |
---|
2010 | } |
---|
2011 | |
---|
2012 | void OPPROTO op_fmov_FT0_STN(void) |
---|
2013 | { |
---|
2014 | FT0 = ST(PARAM1); |
---|
2015 | } |
---|
2016 | |
---|
2017 | void OPPROTO op_fmov_ST0_STN(void) |
---|
2018 | { |
---|
2019 | ST0 = ST(PARAM1); |
---|
2020 | } |
---|
2021 | |
---|
2022 | void OPPROTO op_fmov_STN_ST0(void) |
---|
2023 | { |
---|
2024 | ST(PARAM1) = ST0; |
---|
2025 | } |
---|
2026 | |
---|
2027 | void OPPROTO op_fxchg_ST0_STN(void) |
---|
2028 | { |
---|
2029 | CPU86_LDouble tmp; |
---|
2030 | tmp = ST(PARAM1); |
---|
2031 | ST(PARAM1) = ST0; |
---|
2032 | ST0 = tmp; |
---|
2033 | } |
---|
2034 | |
---|
2035 | /* FPU operations */ |
---|
2036 | |
---|
2037 | const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500}; |
---|
2038 | |
---|
2039 | void OPPROTO op_fcom_ST0_FT0(void) |
---|
2040 | { |
---|
2041 | int ret; |
---|
2042 | |
---|
2043 | ret = floatx_compare(ST0, FT0, &env->fp_status); |
---|
2044 | env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; |
---|
2045 | FORCE_RET(); |
---|
2046 | } |
---|
2047 | |
---|
2048 | void OPPROTO op_fucom_ST0_FT0(void) |
---|
2049 | { |
---|
2050 | int ret; |
---|
2051 | |
---|
2052 | ret = floatx_compare_quiet(ST0, FT0, &env->fp_status); |
---|
2053 | env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1]; |
---|
2054 | FORCE_RET(); |
---|
2055 | } |
---|
2056 | |
---|
2057 | const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C}; |
---|
2058 | |
---|
2059 | void OPPROTO op_fcomi_ST0_FT0(void) |
---|
2060 | { |
---|
2061 | int eflags; |
---|
2062 | int ret; |
---|
2063 | |
---|
2064 | ret = floatx_compare(ST0, FT0, &env->fp_status); |
---|
2065 | eflags = cc_table[CC_OP].compute_all(); |
---|
2066 | eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; |
---|
2067 | CC_SRC = eflags; |
---|
2068 | FORCE_RET(); |
---|
2069 | } |
---|
2070 | |
---|
2071 | void OPPROTO op_fucomi_ST0_FT0(void) |
---|
2072 | { |
---|
2073 | int eflags; |
---|
2074 | int ret; |
---|
2075 | |
---|
2076 | ret = floatx_compare_quiet(ST0, FT0, &env->fp_status); |
---|
2077 | eflags = cc_table[CC_OP].compute_all(); |
---|
2078 | eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; |
---|
2079 | CC_SRC = eflags; |
---|
2080 | FORCE_RET(); |
---|
2081 | } |
---|
2082 | |
---|
2083 | void OPPROTO op_fcmov_ST0_STN_T0(void) |
---|
2084 | { |
---|
2085 | if (T0) { |
---|
2086 | ST0 = ST(PARAM1); |
---|
2087 | } |
---|
2088 | FORCE_RET(); |
---|
2089 | } |
---|
2090 | |
---|
2091 | void OPPROTO op_fadd_ST0_FT0(void) |
---|
2092 | { |
---|
2093 | ST0 += FT0; |
---|
2094 | } |
---|
2095 | |
---|
2096 | void OPPROTO op_fmul_ST0_FT0(void) |
---|
2097 | { |
---|
2098 | ST0 *= FT0; |
---|
2099 | } |
---|
2100 | |
---|
2101 | void OPPROTO op_fsub_ST0_FT0(void) |
---|
2102 | { |
---|
2103 | ST0 -= FT0; |
---|
2104 | } |
---|
2105 | |
---|
2106 | void OPPROTO op_fsubr_ST0_FT0(void) |
---|
2107 | { |
---|
2108 | ST0 = FT0 - ST0; |
---|
2109 | } |
---|
2110 | |
---|
2111 | void OPPROTO op_fdiv_ST0_FT0(void) |
---|
2112 | { |
---|
2113 | ST0 = helper_fdiv(ST0, FT0); |
---|
2114 | } |
---|
2115 | |
---|
2116 | void OPPROTO op_fdivr_ST0_FT0(void) |
---|
2117 | { |
---|
2118 | ST0 = helper_fdiv(FT0, ST0); |
---|
2119 | } |
---|
2120 | |
---|
2121 | /* fp operations between STN and ST0 */ |
---|
2122 | |
---|
2123 | void OPPROTO op_fadd_STN_ST0(void) |
---|
2124 | { |
---|
2125 | ST(PARAM1) += ST0; |
---|
2126 | } |
---|
2127 | |
---|
2128 | void OPPROTO op_fmul_STN_ST0(void) |
---|
2129 | { |
---|
2130 | ST(PARAM1) *= ST0; |
---|
2131 | } |
---|
2132 | |
---|
2133 | void OPPROTO op_fsub_STN_ST0(void) |
---|
2134 | { |
---|
2135 | ST(PARAM1) -= ST0; |
---|
2136 | } |
---|
2137 | |
---|
2138 | void OPPROTO op_fsubr_STN_ST0(void) |
---|
2139 | { |
---|
2140 | CPU86_LDouble *p; |
---|
2141 | p = &ST(PARAM1); |
---|
2142 | *p = ST0 - *p; |
---|
2143 | } |
---|
2144 | |
---|
2145 | void OPPROTO op_fdiv_STN_ST0(void) |
---|
2146 | { |
---|
2147 | CPU86_LDouble *p; |
---|
2148 | p = &ST(PARAM1); |
---|
2149 | *p = helper_fdiv(*p, ST0); |
---|
2150 | } |
---|
2151 | |
---|
2152 | void OPPROTO op_fdivr_STN_ST0(void) |
---|
2153 | { |
---|
2154 | CPU86_LDouble *p; |
---|
2155 | p = &ST(PARAM1); |
---|
2156 | *p = helper_fdiv(ST0, *p); |
---|
2157 | } |
---|
2158 | |
---|
2159 | /* misc FPU operations */ |
---|
2160 | void OPPROTO op_fchs_ST0(void) |
---|
2161 | { |
---|
2162 | ST0 = floatx_chs(ST0); |
---|
2163 | } |
---|
2164 | |
---|
2165 | void OPPROTO op_fabs_ST0(void) |
---|
2166 | { |
---|
2167 | ST0 = floatx_abs(ST0); |
---|
2168 | } |
---|
2169 | |
---|
2170 | void OPPROTO op_fxam_ST0(void) |
---|
2171 | { |
---|
2172 | helper_fxam_ST0(); |
---|
2173 | } |
---|
2174 | |
---|
2175 | void OPPROTO op_fld1_ST0(void) |
---|
2176 | { |
---|
2177 | ST0 = f15rk[1]; |
---|
2178 | } |
---|
2179 | |
---|
2180 | void OPPROTO op_fldl2t_ST0(void) |
---|
2181 | { |
---|
2182 | ST0 = f15rk[6]; |
---|
2183 | } |
---|
2184 | |
---|
2185 | void OPPROTO op_fldl2e_ST0(void) |
---|
2186 | { |
---|
2187 | ST0 = f15rk[5]; |
---|
2188 | } |
---|
2189 | |
---|
2190 | void OPPROTO op_fldpi_ST0(void) |
---|
2191 | { |
---|
2192 | ST0 = f15rk[2]; |
---|
2193 | } |
---|
2194 | |
---|
2195 | void OPPROTO op_fldlg2_ST0(void) |
---|
2196 | { |
---|
2197 | ST0 = f15rk[3]; |
---|
2198 | } |
---|
2199 | |
---|
2200 | void OPPROTO op_fldln2_ST0(void) |
---|
2201 | { |
---|
2202 | ST0 = f15rk[4]; |
---|
2203 | } |
---|
2204 | |
---|
2205 | void OPPROTO op_fldz_ST0(void) |
---|
2206 | { |
---|
2207 | ST0 = f15rk[0]; |
---|
2208 | } |
---|
2209 | |
---|
2210 | void OPPROTO op_fldz_FT0(void) |
---|
2211 | { |
---|
2212 | FT0 = f15rk[0]; |
---|
2213 | } |
---|
2214 | |
---|
2215 | /* associated heplers to reduce generated code length and to simplify |
---|
2216 | relocation (FP constants are usually stored in .rodata section) */ |
---|
2217 | |
---|
2218 | void OPPROTO op_f2xm1(void) |
---|
2219 | { |
---|
2220 | helper_f2xm1(); |
---|
2221 | } |
---|
2222 | |
---|
2223 | void OPPROTO op_fyl2x(void) |
---|
2224 | { |
---|
2225 | helper_fyl2x(); |
---|
2226 | } |
---|
2227 | |
---|
2228 | void OPPROTO op_fptan(void) |
---|
2229 | { |
---|
2230 | helper_fptan(); |
---|
2231 | } |
---|
2232 | |
---|
2233 | void OPPROTO op_fpatan(void) |
---|
2234 | { |
---|
2235 | helper_fpatan(); |
---|
2236 | } |
---|
2237 | |
---|
2238 | void OPPROTO op_fxtract(void) |
---|
2239 | { |
---|
2240 | helper_fxtract(); |
---|
2241 | } |
---|
2242 | |
---|
2243 | void OPPROTO op_fprem1(void) |
---|
2244 | { |
---|
2245 | helper_fprem1(); |
---|
2246 | } |
---|
2247 | |
---|
2248 | |
---|
2249 | void OPPROTO op_fprem(void) |
---|
2250 | { |
---|
2251 | helper_fprem(); |
---|
2252 | } |
---|
2253 | |
---|
2254 | void OPPROTO op_fyl2xp1(void) |
---|
2255 | { |
---|
2256 | helper_fyl2xp1(); |
---|
2257 | } |
---|
2258 | |
---|
2259 | void OPPROTO op_fsqrt(void) |
---|
2260 | { |
---|
2261 | helper_fsqrt(); |
---|
2262 | } |
---|
2263 | |
---|
2264 | void OPPROTO op_fsincos(void) |
---|
2265 | { |
---|
2266 | helper_fsincos(); |
---|
2267 | } |
---|
2268 | |
---|
2269 | void OPPROTO op_frndint(void) |
---|
2270 | { |
---|
2271 | helper_frndint(); |
---|
2272 | } |
---|
2273 | |
---|
2274 | void OPPROTO op_fscale(void) |
---|
2275 | { |
---|
2276 | helper_fscale(); |
---|
2277 | } |
---|
2278 | |
---|
2279 | void OPPROTO op_fsin(void) |
---|
2280 | { |
---|
2281 | helper_fsin(); |
---|
2282 | } |
---|
2283 | |
---|
2284 | void OPPROTO op_fcos(void) |
---|
2285 | { |
---|
2286 | helper_fcos(); |
---|
2287 | } |
---|
2288 | |
---|
2289 | void OPPROTO op_fnstsw_A0(void) |
---|
2290 | { |
---|
2291 | int fpus; |
---|
2292 | fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; |
---|
2293 | stw(A0, fpus); |
---|
2294 | FORCE_RET(); |
---|
2295 | } |
---|
2296 | |
---|
2297 | void OPPROTO op_fnstsw_EAX(void) |
---|
2298 | { |
---|
2299 | int fpus; |
---|
2300 | fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; |
---|
2301 | EAX = (EAX & ~0xffff) | fpus; |
---|
2302 | } |
---|
2303 | |
---|
2304 | void OPPROTO op_fnstcw_A0(void) |
---|
2305 | { |
---|
2306 | stw(A0, env->fpuc); |
---|
2307 | FORCE_RET(); |
---|
2308 | } |
---|
2309 | |
---|
2310 | void OPPROTO op_fldcw_A0(void) |
---|
2311 | { |
---|
2312 | env->fpuc = lduw(A0); |
---|
2313 | update_fp_status(); |
---|
2314 | } |
---|
2315 | |
---|
2316 | void OPPROTO op_fclex(void) |
---|
2317 | { |
---|
2318 | env->fpus &= 0x7f00; |
---|
2319 | } |
---|
2320 | |
---|
2321 | void OPPROTO op_fwait(void) |
---|
2322 | { |
---|
2323 | if (env->fpus & FPUS_SE) |
---|
2324 | fpu_raise_exception(); |
---|
2325 | FORCE_RET(); |
---|
2326 | } |
---|
2327 | |
---|
2328 | void OPPROTO op_fninit(void) |
---|
2329 | { |
---|
2330 | env->fpus = 0; |
---|
2331 | env->fpstt = 0; |
---|
2332 | env->fpuc = 0x37f; |
---|
2333 | env->fptags[0] = 1; |
---|
2334 | env->fptags[1] = 1; |
---|
2335 | env->fptags[2] = 1; |
---|
2336 | env->fptags[3] = 1; |
---|
2337 | env->fptags[4] = 1; |
---|
2338 | env->fptags[5] = 1; |
---|
2339 | env->fptags[6] = 1; |
---|
2340 | env->fptags[7] = 1; |
---|
2341 | } |
---|
2342 | |
---|
2343 | void OPPROTO op_fnstenv_A0(void) |
---|
2344 | { |
---|
2345 | helper_fstenv(A0, PARAM1); |
---|
2346 | } |
---|
2347 | |
---|
2348 | void OPPROTO op_fldenv_A0(void) |
---|
2349 | { |
---|
2350 | helper_fldenv(A0, PARAM1); |
---|
2351 | } |
---|
2352 | |
---|
2353 | void OPPROTO op_fnsave_A0(void) |
---|
2354 | { |
---|
2355 | helper_fsave(A0, PARAM1); |
---|
2356 | } |
---|
2357 | |
---|
2358 | void OPPROTO op_frstor_A0(void) |
---|
2359 | { |
---|
2360 | helper_frstor(A0, PARAM1); |
---|
2361 | } |
---|
2362 | |
---|
2363 | /* threading support */ |
---|
2364 | void OPPROTO op_lock(void) |
---|
2365 | { |
---|
2366 | cpu_lock(); |
---|
2367 | } |
---|
2368 | |
---|
2369 | void OPPROTO op_unlock(void) |
---|
2370 | { |
---|
2371 | cpu_unlock(); |
---|
2372 | } |
---|
2373 | |
---|
2374 | /* SSE support */ |
---|
2375 | static inline void memcpy16(void *d, void *s) |
---|
2376 | { |
---|
2377 | ((uint32_t *)d)[0] = ((uint32_t *)s)[0]; |
---|
2378 | ((uint32_t *)d)[1] = ((uint32_t *)s)[1]; |
---|
2379 | ((uint32_t *)d)[2] = ((uint32_t *)s)[2]; |
---|
2380 | ((uint32_t *)d)[3] = ((uint32_t *)s)[3]; |
---|
2381 | } |
---|
2382 | |
---|
2383 | void OPPROTO op_movo(void) |
---|
2384 | { |
---|
2385 | /* XXX: badly generated code */ |
---|
2386 | XMMReg *d, *s; |
---|
2387 | d = (XMMReg *)((char *)env + PARAM1); |
---|
2388 | s = (XMMReg *)((char *)env + PARAM2); |
---|
2389 | memcpy16(d, s); |
---|
2390 | } |
---|
2391 | |
---|
2392 | void OPPROTO op_movq(void) |
---|
2393 | { |
---|
2394 | uint64_t *d, *s; |
---|
2395 | d = (uint64_t *)((char *)env + PARAM1); |
---|
2396 | s = (uint64_t *)((char *)env + PARAM2); |
---|
2397 | *d = *s; |
---|
2398 | } |
---|
2399 | |
---|
2400 | void OPPROTO op_movl(void) |
---|
2401 | { |
---|
2402 | uint32_t *d, *s; |
---|
2403 | d = (uint32_t *)((char *)env + PARAM1); |
---|
2404 | s = (uint32_t *)((char *)env + PARAM2); |
---|
2405 | *d = *s; |
---|
2406 | } |
---|
2407 | |
---|
2408 | void OPPROTO op_movq_env_0(void) |
---|
2409 | { |
---|
2410 | uint64_t *d; |
---|
2411 | d = (uint64_t *)((char *)env + PARAM1); |
---|
2412 | *d = 0; |
---|
2413 | } |
---|
2414 | |
---|
2415 | void OPPROTO op_fxsave_A0(void) |
---|
2416 | { |
---|
2417 | helper_fxsave(A0, PARAM1); |
---|
2418 | } |
---|
2419 | |
---|
2420 | void OPPROTO op_fxrstor_A0(void) |
---|
2421 | { |
---|
2422 | helper_fxrstor(A0, PARAM1); |
---|
2423 | } |
---|
2424 | |
---|
2425 | /* XXX: optimize by storing fptt and fptags in the static cpu state */ |
---|
2426 | void OPPROTO op_enter_mmx(void) |
---|
2427 | { |
---|
2428 | env->fpstt = 0; |
---|
2429 | *(uint32_t *)(env->fptags) = 0; |
---|
2430 | *(uint32_t *)(env->fptags + 4) = 0; |
---|
2431 | } |
---|
2432 | |
---|
2433 | void OPPROTO op_emms(void) |
---|
2434 | { |
---|
2435 | /* set to empty state */ |
---|
2436 | *(uint32_t *)(env->fptags) = 0x01010101; |
---|
2437 | *(uint32_t *)(env->fptags + 4) = 0x01010101; |
---|
2438 | } |
---|
2439 | |
---|
2440 | #define SHIFT 0 |
---|
2441 | #include "ops_sse.h" |
---|
2442 | |
---|
2443 | #define SHIFT 1 |
---|
2444 | #include "ops_sse.h" |
---|