|
|
1.1 root 1: /*
2: * m68k micro operations
1.1.1.2 ! root 3: *
! 4: * Copyright (c) 2006-2007 CodeSourcery
1.1 root 5: * Written by Paul Brook
6: *
7: * This library is free software; you can redistribute it and/or
8: * modify it under the terms of the GNU Lesser General Public
9: * License as published by the Free Software Foundation; either
10: * version 2 of the License, or (at your option) any later version.
11: *
12: * This library is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU Lesser General Public
18: * License along with this library; if not, write to the Free Software
19: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20: */
21:
22: #include "exec.h"
23: #include "m68k-qreg.h"
24:
25: #ifndef offsetof
26: #define offsetof(type, field) ((size_t) &((type *)0)->field)
27: #endif
28:
29: static long qreg_offsets[] = {
30: #define DEFO32(name, offset) offsetof(CPUState, offset),
31: #define DEFR(name, reg, mode) -1,
32: #define DEFF64(name, offset) offsetof(CPUState, offset),
33: 0,
34: #include "qregs.def"
35: };
36:
37: #define CPU_FP_STATUS env->fp_status
38:
39: #define RAISE_EXCEPTION(n) do { \
40: env->exception_index = n; \
41: cpu_loop_exit(); \
42: } while(0)
43:
44: #define get_op helper_get_op
45: #define set_op helper_set_op
46: #define get_opf64 helper_get_opf64
47: #define set_opf64 helper_set_opf64
48: uint32_t
49: get_op(int qreg)
50: {
1.1.1.2 ! root 51: if (qreg >= TARGET_NUM_QREGS) {
! 52: return env->qregs[qreg - TARGET_NUM_QREGS];
! 53: } else if (qreg == QREG_T0) {
1.1 root 54: return T0;
55: } else {
1.1.1.2 ! root 56: return *(uint32_t *)(((long)env) + qreg_offsets[qreg]);
1.1 root 57: }
58: }
59:
60: void set_op(int qreg, uint32_t val)
61: {
1.1.1.2 ! root 62: if (qreg >= TARGET_NUM_QREGS) {
! 63: env->qregs[qreg - TARGET_NUM_QREGS] = val;
! 64: } else if (qreg == QREG_T0) {
1.1 root 65: T0 = val;
66: } else {
1.1.1.2 ! root 67: *(uint32_t *)(((long)env) + qreg_offsets[qreg]) = val;
1.1 root 68: }
69: }
70:
71: float64 get_opf64(int qreg)
72: {
73: if (qreg < TARGET_NUM_QREGS) {
74: return *(float64 *)(((long)env) + qreg_offsets[qreg]);
75: } else {
76: return *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS];
77: }
78: }
79:
80: void set_opf64(int qreg, float64 val)
81: {
82: if (qreg < TARGET_NUM_QREGS) {
83: *(float64 *)(((long)env) + qreg_offsets[qreg]) = val;
84: } else {
85: *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS] = val;
86: }
87: }
88:
1.1.1.2 ! root 89: #define OP(name) void OPPROTO glue(op_,name) (void)
1.1 root 90:
91: OP(mov32)
92: {
93: set_op(PARAM1, get_op(PARAM2));
94: FORCE_RET();
95: }
96:
97: OP(mov32_im)
98: {
99: set_op(PARAM1, PARAM2);
100: FORCE_RET();
101: }
102:
103: OP(movf64)
104: {
105: set_opf64(PARAM1, get_opf64(PARAM2));
106: FORCE_RET();
107: }
108:
109: OP(zerof64)
110: {
1.1.1.2 ! root 111: set_opf64(PARAM1, float64_zero);
1.1 root 112: FORCE_RET();
113: }
114:
115: OP(add32)
116: {
117: uint32_t op2 = get_op(PARAM2);
118: uint32_t op3 = get_op(PARAM3);
119: set_op(PARAM1, op2 + op3);
120: FORCE_RET();
121: }
122:
123: OP(sub32)
124: {
125: uint32_t op2 = get_op(PARAM2);
126: uint32_t op3 = get_op(PARAM3);
127: set_op(PARAM1, op2 - op3);
128: FORCE_RET();
129: }
130:
131: OP(mul32)
132: {
133: uint32_t op2 = get_op(PARAM2);
134: uint32_t op3 = get_op(PARAM3);
135: set_op(PARAM1, op2 * op3);
136: FORCE_RET();
137: }
138:
139: OP(not32)
140: {
141: uint32_t arg = get_op(PARAM2);
142: set_op(PARAM1, ~arg);
143: FORCE_RET();
144: }
145:
146: OP(neg32)
147: {
148: uint32_t arg = get_op(PARAM2);
149: set_op(PARAM1, -arg);
150: FORCE_RET();
151: }
152:
153: OP(bswap32)
154: {
155: uint32_t arg = get_op(PARAM2);
156: arg = (arg >> 24) | (arg << 24)
157: | ((arg >> 16) & 0xff00) | ((arg << 16) & 0xff0000);
158: set_op(PARAM1, arg);
159: FORCE_RET();
160: }
161:
162: OP(btest)
163: {
164: uint32_t op1 = get_op(PARAM1);
165: uint32_t op2 = get_op(PARAM2);
166: if (op1 & op2)
167: env->cc_dest &= ~CCF_Z;
168: else
169: env->cc_dest |= CCF_Z;
170: FORCE_RET();
171: }
172:
1.1.1.2 ! root 173: OP(ff1)
! 174: {
! 175: uint32_t arg = get_op(PARAM2);
! 176: int n;
! 177: for (n = 32; arg; n--)
! 178: arg >>= 1;
! 179: set_op(PARAM1, n);
! 180: FORCE_RET();
! 181: }
! 182:
! 183: OP(subx_cc)
1.1 root 184: {
185: uint32_t op1 = get_op(PARAM1);
186: uint32_t op2 = get_op(PARAM2);
187: uint32_t res;
188: if (env->cc_x) {
189: env->cc_x = (op1 <= op2);
190: env->cc_op = CC_OP_SUBX;
191: res = op1 - (op2 + 1);
192: } else {
193: env->cc_x = (op1 < op2);
194: env->cc_op = CC_OP_SUB;
195: res = op1 - op2;
196: }
197: set_op(PARAM1, res);
198: FORCE_RET();
199: }
200:
1.1.1.2 ! root 201: OP(addx_cc)
1.1 root 202: {
203: uint32_t op1 = get_op(PARAM1);
204: uint32_t op2 = get_op(PARAM2);
205: uint32_t res;
206: if (env->cc_x) {
207: res = op1 + op2 + 1;
208: env->cc_x = (res <= op2);
209: env->cc_op = CC_OP_ADDX;
210: } else {
211: res = op1 + op2;
212: env->cc_x = (res < op2);
213: env->cc_op = CC_OP_ADD;
214: }
215: set_op(PARAM1, res);
216: FORCE_RET();
217: }
218:
219: /* Logic ops. */
220:
221: OP(and32)
222: {
223: uint32_t op2 = get_op(PARAM2);
224: uint32_t op3 = get_op(PARAM3);
225: set_op(PARAM1, op2 & op3);
226: FORCE_RET();
227: }
228:
229: OP(or32)
230: {
231: uint32_t op2 = get_op(PARAM2);
232: uint32_t op3 = get_op(PARAM3);
233: set_op(PARAM1, op2 | op3);
234: FORCE_RET();
235: }
236:
237: OP(xor32)
238: {
239: uint32_t op2 = get_op(PARAM2);
240: uint32_t op3 = get_op(PARAM3);
241: set_op(PARAM1, op2 ^ op3);
242: FORCE_RET();
243: }
244:
245: /* Shifts. */
246: OP(shl32)
247: {
248: uint32_t op2 = get_op(PARAM2);
249: uint32_t op3 = get_op(PARAM3);
250: uint32_t result;
251: result = op2 << op3;
252: set_op(PARAM1, result);
253: FORCE_RET();
254: }
255:
256: OP(shl_cc)
257: {
258: uint32_t op1 = get_op(PARAM1);
259: uint32_t op2 = get_op(PARAM2);
260: uint32_t result;
261: result = op1 << op2;
262: set_op(PARAM1, result);
263: env->cc_x = (op1 << (op2 - 1)) & 1;
264: FORCE_RET();
265: }
266:
267: OP(shr32)
268: {
269: uint32_t op2 = get_op(PARAM2);
270: uint32_t op3 = get_op(PARAM3);
271: uint32_t result;
272: result = op2 >> op3;
273: set_op(PARAM1, result);
274: FORCE_RET();
275: }
276:
277: OP(shr_cc)
278: {
279: uint32_t op1 = get_op(PARAM1);
280: uint32_t op2 = get_op(PARAM2);
281: uint32_t result;
282: result = op1 >> op2;
283: set_op(PARAM1, result);
284: env->cc_x = (op1 >> (op2 - 1)) & 1;
285: FORCE_RET();
286: }
287:
1.1.1.2 ! root 288: OP(sar32)
! 289: {
! 290: int32_t op2 = get_op(PARAM2);
! 291: uint32_t op3 = get_op(PARAM3);
! 292: uint32_t result;
! 293: result = op2 >> op3;
! 294: set_op(PARAM1, result);
! 295: FORCE_RET();
! 296: }
! 297:
1.1 root 298: OP(sar_cc)
299: {
300: int32_t op1 = get_op(PARAM1);
301: uint32_t op2 = get_op(PARAM2);
302: uint32_t result;
303: result = op1 >> op2;
304: set_op(PARAM1, result);
305: env->cc_x = (op1 >> (op2 - 1)) & 1;
306: FORCE_RET();
307: }
308:
309: /* Value extend. */
310:
311: OP(ext8u32)
312: {
313: uint32_t op2 = get_op(PARAM2);
314: set_op(PARAM1, (uint8_t)op2);
315: FORCE_RET();
316: }
317:
318: OP(ext8s32)
319: {
320: uint32_t op2 = get_op(PARAM2);
321: set_op(PARAM1, (int8_t)op2);
322: FORCE_RET();
323: }
324:
325: OP(ext16u32)
326: {
327: uint32_t op2 = get_op(PARAM2);
328: set_op(PARAM1, (uint16_t)op2);
329: FORCE_RET();
330: }
331:
332: OP(ext16s32)
333: {
334: uint32_t op2 = get_op(PARAM2);
335: set_op(PARAM1, (int16_t)op2);
336: FORCE_RET();
337: }
338:
339: OP(flush_flags)
340: {
1.1.1.2 ! root 341: cpu_m68k_flush_flags(env, env->cc_op);
1.1 root 342: FORCE_RET();
343: }
344:
345: OP(divu)
346: {
347: uint32_t num;
348: uint32_t den;
349: uint32_t quot;
350: uint32_t rem;
351: uint32_t flags;
1.1.1.2 ! root 352:
1.1 root 353: num = env->div1;
354: den = env->div2;
355: /* ??? This needs to make sure the throwing location is accurate. */
356: if (den == 0)
357: RAISE_EXCEPTION(EXCP_DIV0);
358: quot = num / den;
359: rem = num % den;
360: flags = 0;
361: /* Avoid using a PARAM1 of zero. This breaks dyngen because it uses
362: the address of a symbol, and gcc knows symbols can't have address
363: zero. */
364: if (PARAM1 == 2 && quot > 0xffff)
365: flags |= CCF_V;
366: if (quot == 0)
367: flags |= CCF_Z;
368: else if ((int32_t)quot < 0)
369: flags |= CCF_N;
370: env->div1 = quot;
371: env->div2 = rem;
372: env->cc_dest = flags;
373: FORCE_RET();
374: }
375:
376: OP(divs)
377: {
378: int32_t num;
379: int32_t den;
380: int32_t quot;
381: int32_t rem;
382: int32_t flags;
1.1.1.2 ! root 383:
1.1 root 384: num = env->div1;
385: den = env->div2;
386: if (den == 0)
387: RAISE_EXCEPTION(EXCP_DIV0);
388: quot = num / den;
389: rem = num % den;
390: flags = 0;
391: if (PARAM1 == 2 && quot != (int16_t)quot)
392: flags |= CCF_V;
393: if (quot == 0)
394: flags |= CCF_Z;
395: else if (quot < 0)
396: flags |= CCF_N;
397: env->div1 = quot;
398: env->div2 = rem;
399: env->cc_dest = flags;
400: FORCE_RET();
401: }
402:
1.1.1.2 ! root 403: /* Halt is special because it may be a semihosting call. */
! 404: OP(halt)
! 405: {
! 406: RAISE_EXCEPTION(EXCP_HALT_INSN);
! 407: FORCE_RET();
! 408: }
! 409:
! 410: OP(stop)
! 411: {
! 412: env->halted = 1;
! 413: RAISE_EXCEPTION(EXCP_HLT);
! 414: FORCE_RET();
! 415: }
! 416:
1.1 root 417: OP(raise_exception)
418: {
419: RAISE_EXCEPTION(PARAM1);
420: FORCE_RET();
421: }
422:
423: /* Floating point comparison sets flags differently to other instructions. */
424:
425: OP(sub_cmpf64)
426: {
427: float64 src0;
428: float64 src1;
429: src0 = get_opf64(PARAM2);
430: src1 = get_opf64(PARAM3);
431: set_opf64(PARAM1, helper_sub_cmpf64(env, src0, src1));
432: FORCE_RET();
433: }
434:
435: OP(update_xflag_tst)
436: {
437: uint32_t op1 = get_op(PARAM1);
438: env->cc_x = op1;
439: FORCE_RET();
440: }
441:
442: OP(update_xflag_lt)
443: {
444: uint32_t op1 = get_op(PARAM1);
445: uint32_t op2 = get_op(PARAM2);
446: env->cc_x = (op1 < op2);
447: FORCE_RET();
448: }
449:
450: OP(get_xflag)
451: {
452: set_op(PARAM1, env->cc_x);
453: FORCE_RET();
454: }
455:
456: OP(logic_cc)
457: {
458: uint32_t op1 = get_op(PARAM1);
459: env->cc_dest = op1;
460: FORCE_RET();
461: }
462:
463: OP(update_cc_add)
464: {
465: uint32_t op1 = get_op(PARAM1);
466: uint32_t op2 = get_op(PARAM2);
467: env->cc_dest = op1;
468: env->cc_src = op2;
469: FORCE_RET();
470: }
471:
472: OP(fp_result)
473: {
474: env->fp_result = get_opf64(PARAM1);
475: FORCE_RET();
476: }
477:
1.1.1.2 ! root 478: OP(set_sr)
! 479: {
! 480: env->sr = get_op(PARAM1) & 0xffff;
! 481: m68k_switch_sp(env);
! 482: FORCE_RET();
! 483: }
! 484:
1.1 root 485: OP(jmp)
486: {
487: GOTO_LABEL_PARAM(1);
488: }
489:
1.1.1.2 ! root 490: OP(set_T0_z32)
1.1 root 491: {
492: uint32_t arg = get_op(PARAM1);
1.1.1.2 ! root 493: T0 = (arg == 0);
1.1 root 494: FORCE_RET();
495: }
496:
1.1.1.2 ! root 497: OP(set_T0_nz32)
1.1 root 498: {
499: uint32_t arg = get_op(PARAM1);
1.1.1.2 ! root 500: T0 = (arg != 0);
1.1 root 501: FORCE_RET();
502: }
503:
1.1.1.2 ! root 504: OP(set_T0_s32)
1.1 root 505: {
506: int32_t arg = get_op(PARAM1);
1.1.1.2 ! root 507: T0 = (arg > 0);
1.1 root 508: FORCE_RET();
509: }
510:
1.1.1.2 ! root 511: OP(set_T0_ns32)
1.1 root 512: {
513: int32_t arg = get_op(PARAM1);
1.1.1.2 ! root 514: T0 = (arg >= 0);
! 515: FORCE_RET();
! 516: }
! 517:
! 518: OP(jmp_T0)
! 519: {
! 520: if (T0)
! 521: GOTO_LABEL_PARAM(1);
1.1 root 522: FORCE_RET();
523: }
524:
525: void OPPROTO op_goto_tb0(void)
526: {
527: GOTO_TB(op_goto_tb0, PARAM1, 0);
528: }
529:
530: void OPPROTO op_goto_tb1(void)
531: {
532: GOTO_TB(op_goto_tb1, PARAM1, 1);
533: }
534:
535: OP(exit_tb)
536: {
537: EXIT_TB();
538: }
539:
540:
541: /* Floating point. */
542: OP(f64_to_i32)
543: {
544: set_op(PARAM1, float64_to_int32(get_opf64(PARAM2), &CPU_FP_STATUS));
545: FORCE_RET();
546: }
547:
548: OP(f64_to_f32)
549: {
550: union {
551: float32 f;
552: uint32_t i;
553: } u;
554: u.f = float64_to_float32(get_opf64(PARAM2), &CPU_FP_STATUS);
555: set_op(PARAM1, u.i);
556: FORCE_RET();
557: }
558:
559: OP(i32_to_f64)
560: {
561: set_opf64(PARAM1, int32_to_float64(get_op(PARAM2), &CPU_FP_STATUS));
562: FORCE_RET();
563: }
564:
565: OP(f32_to_f64)
566: {
567: union {
568: float32 f;
569: uint32_t i;
570: } u;
571: u.i = get_op(PARAM2);
572: set_opf64(PARAM1, float32_to_float64(u.f, &CPU_FP_STATUS));
573: FORCE_RET();
574: }
575:
576: OP(absf64)
577: {
578: float64 op0 = get_opf64(PARAM2);
579: set_opf64(PARAM1, float64_abs(op0));
580: FORCE_RET();
581: }
582:
583: OP(chsf64)
584: {
585: float64 op0 = get_opf64(PARAM2);
586: set_opf64(PARAM1, float64_chs(op0));
587: FORCE_RET();
588: }
589:
590: OP(sqrtf64)
591: {
592: float64 op0 = get_opf64(PARAM2);
593: set_opf64(PARAM1, float64_sqrt(op0, &CPU_FP_STATUS));
594: FORCE_RET();
595: }
596:
597: OP(addf64)
598: {
599: float64 op0 = get_opf64(PARAM2);
600: float64 op1 = get_opf64(PARAM3);
601: set_opf64(PARAM1, float64_add(op0, op1, &CPU_FP_STATUS));
602: FORCE_RET();
603: }
604:
605: OP(subf64)
606: {
607: float64 op0 = get_opf64(PARAM2);
608: float64 op1 = get_opf64(PARAM3);
609: set_opf64(PARAM1, float64_sub(op0, op1, &CPU_FP_STATUS));
610: FORCE_RET();
611: }
612:
613: OP(mulf64)
614: {
615: float64 op0 = get_opf64(PARAM2);
616: float64 op1 = get_opf64(PARAM3);
617: set_opf64(PARAM1, float64_mul(op0, op1, &CPU_FP_STATUS));
618: FORCE_RET();
619: }
620:
621: OP(divf64)
622: {
623: float64 op0 = get_opf64(PARAM2);
624: float64 op1 = get_opf64(PARAM3);
625: set_opf64(PARAM1, float64_div(op0, op1, &CPU_FP_STATUS));
626: FORCE_RET();
627: }
628:
629: OP(iround_f64)
630: {
631: float64 op0 = get_opf64(PARAM2);
632: set_opf64(PARAM1, float64_round_to_int(op0, &CPU_FP_STATUS));
633: FORCE_RET();
634: }
635:
636: OP(itrunc_f64)
637: {
638: float64 op0 = get_opf64(PARAM2);
639: set_opf64(PARAM1, float64_trunc_to_int(op0, &CPU_FP_STATUS));
640: FORCE_RET();
641: }
642:
643: OP(compare_quietf64)
644: {
645: float64 op0 = get_opf64(PARAM2);
646: float64 op1 = get_opf64(PARAM3);
647: set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS));
648: FORCE_RET();
649: }
1.1.1.2 ! root 650:
! 651: OP(movec)
! 652: {
! 653: int op1 = get_op(PARAM1);
! 654: uint32_t op2 = get_op(PARAM2);
! 655: helper_movec(env, op1, op2);
! 656: }
! 657:
! 658: /* Memory access. */
! 659:
! 660: #define MEMSUFFIX _raw
! 661: #include "op_mem.h"
! 662:
! 663: #if !defined(CONFIG_USER_ONLY)
! 664: #define MEMSUFFIX _user
! 665: #include "op_mem.h"
! 666: #define MEMSUFFIX _kernel
! 667: #include "op_mem.h"
! 668: #endif
! 669:
! 670: /* MAC unit. */
! 671: /* TODO: The MAC instructions use 64-bit arithmetic fairly extensively.
! 672: This results in fairly large ops (and sometimes other issues) on 32-bit
! 673: hosts. Maybe move most of them into helpers. */
! 674: OP(macmuls)
! 675: {
! 676: uint32_t op1 = get_op(PARAM1);
! 677: uint32_t op2 = get_op(PARAM2);
! 678: int64_t product;
! 679: int64_t res;
! 680:
! 681: product = (uint64_t)op1 * op2;
! 682: res = (product << 24) >> 24;
! 683: if (res != product) {
! 684: env->macsr |= MACSR_V;
! 685: if (env->macsr & MACSR_OMC) {
! 686: /* Make sure the accumulate operation overflows. */
! 687: if (product < 0)
! 688: res = ~(1ll << 50);
! 689: else
! 690: res = 1ll << 50;
! 691: }
! 692: }
! 693: env->mactmp = res;
! 694: FORCE_RET();
! 695: }
! 696:
! 697: OP(macmulu)
! 698: {
! 699: uint32_t op1 = get_op(PARAM1);
! 700: uint32_t op2 = get_op(PARAM2);
! 701: uint64_t product;
! 702:
! 703: product = (uint64_t)op1 * op2;
! 704: if (product & (0xffffffull << 40)) {
! 705: env->macsr |= MACSR_V;
! 706: if (env->macsr & MACSR_OMC) {
! 707: /* Make sure the accumulate operation overflows. */
! 708: product = 1ll << 50;
! 709: } else {
! 710: product &= ((1ull << 40) - 1);
! 711: }
! 712: }
! 713: env->mactmp = product;
! 714: FORCE_RET();
! 715: }
! 716:
! 717: OP(macmulf)
! 718: {
! 719: int32_t op1 = get_op(PARAM1);
! 720: int32_t op2 = get_op(PARAM2);
! 721: uint64_t product;
! 722: uint32_t remainder;
! 723:
! 724: product = (uint64_t)op1 * op2;
! 725: if (env->macsr & MACSR_RT) {
! 726: remainder = product & 0xffffff;
! 727: product >>= 24;
! 728: if (remainder > 0x800000)
! 729: product++;
! 730: else if (remainder == 0x800000)
! 731: product += (product & 1);
! 732: } else {
! 733: product >>= 24;
! 734: }
! 735: env->mactmp = product;
! 736: FORCE_RET();
! 737: }
! 738:
! 739: OP(macshl)
! 740: {
! 741: env->mactmp <<= 1;
! 742: }
! 743:
! 744: OP(macshr)
! 745: {
! 746: env->mactmp >>= 1;
! 747: }
! 748:
! 749: OP(macadd)
! 750: {
! 751: int acc = PARAM1;
! 752: env->macc[acc] += env->mactmp;
! 753: FORCE_RET();
! 754: }
! 755:
! 756: OP(macsub)
! 757: {
! 758: int acc = PARAM1;
! 759: env->macc[acc] -= env->mactmp;
! 760: FORCE_RET();
! 761: }
! 762:
! 763: OP(macsats)
! 764: {
! 765: int acc = PARAM1;
! 766: int64_t sum;
! 767: int64_t result;
! 768:
! 769: sum = env->macc[acc];
! 770: result = (sum << 16) >> 16;
! 771: if (result != sum) {
! 772: env->macsr |= MACSR_V;
! 773: }
! 774: if (env->macsr & MACSR_V) {
! 775: env->macsr |= MACSR_PAV0 << acc;
! 776: if (env->macsr & MACSR_OMC) {
! 777: /* The result is saturated to 32 bits, despite overflow occuring
! 778: at 48 bits. Seems weird, but that's what the hardware docs
! 779: say. */
! 780: result = (result >> 63) ^ 0x7fffffff;
! 781: }
! 782: }
! 783: env->macc[acc] = result;
! 784: FORCE_RET();
! 785: }
! 786:
! 787: OP(macsatu)
! 788: {
! 789: int acc = PARAM1;
! 790: uint64_t sum;
! 791:
! 792: sum = env->macc[acc];
! 793: if (sum & (0xffffull << 48)) {
! 794: env->macsr |= MACSR_V;
! 795: }
! 796: if (env->macsr & MACSR_V) {
! 797: env->macsr |= MACSR_PAV0 << acc;
! 798: if (env->macsr & MACSR_OMC) {
! 799: if (sum > (1ull << 53))
! 800: sum = 0;
! 801: else
! 802: sum = (1ull << 48) - 1;
! 803: } else {
! 804: sum &= ((1ull << 48) - 1);
! 805: }
! 806: }
! 807: FORCE_RET();
! 808: }
! 809:
! 810: OP(macsatf)
! 811: {
! 812: int acc = PARAM1;
! 813: int64_t sum;
! 814: int64_t result;
! 815:
! 816: sum = env->macc[acc];
! 817: result = (sum << 16) >> 16;
! 818: if (result != sum) {
! 819: env->macsr |= MACSR_V;
! 820: }
! 821: if (env->macsr & MACSR_V) {
! 822: env->macsr |= MACSR_PAV0 << acc;
! 823: if (env->macsr & MACSR_OMC) {
! 824: result = (result >> 63) ^ 0x7fffffffffffll;
! 825: }
! 826: }
! 827: env->macc[acc] = result;
! 828: FORCE_RET();
! 829: }
! 830:
! 831: OP(mac_clear_flags)
! 832: {
! 833: env->macsr &= ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV);
! 834: }
! 835:
! 836: OP(mac_set_flags)
! 837: {
! 838: int acc = PARAM1;
! 839: uint64_t val;
! 840: val = env->macc[acc];
! 841: if (val == 0)
! 842: env->macsr |= MACSR_Z;
! 843: else if (val & (1ull << 47));
! 844: env->macsr |= MACSR_N;
! 845: if (env->macsr & (MACSR_PAV0 << acc)) {
! 846: env->macsr |= MACSR_V;
! 847: }
! 848: if (env->macsr & MACSR_FI) {
! 849: val = ((int64_t)val) >> 40;
! 850: if (val != 0 && val != -1)
! 851: env->macsr |= MACSR_EV;
! 852: } else if (env->macsr & MACSR_SU) {
! 853: val = ((int64_t)val) >> 32;
! 854: if (val != 0 && val != -1)
! 855: env->macsr |= MACSR_EV;
! 856: } else {
! 857: if ((val >> 32) != 0)
! 858: env->macsr |= MACSR_EV;
! 859: }
! 860: FORCE_RET();
! 861: }
! 862:
! 863: OP(get_macf)
! 864: {
! 865: int acc = PARAM2;
! 866: int64_t val;
! 867: int rem;
! 868: uint32_t result;
! 869:
! 870: val = env->macc[acc];
! 871: if (env->macsr & MACSR_SU) {
! 872: /* 16-bit rounding. */
! 873: rem = val & 0xffffff;
! 874: val = (val >> 24) & 0xffffu;
! 875: if (rem > 0x800000)
! 876: val++;
! 877: else if (rem == 0x800000)
! 878: val += (val & 1);
! 879: } else if (env->macsr & MACSR_RT) {
! 880: /* 32-bit rounding. */
! 881: rem = val & 0xff;
! 882: val >>= 8;
! 883: if (rem > 0x80)
! 884: val++;
! 885: else if (rem == 0x80)
! 886: val += (val & 1);
! 887: } else {
! 888: /* No rounding. */
! 889: val >>= 8;
! 890: }
! 891: if (env->macsr & MACSR_OMC) {
! 892: /* Saturate. */
! 893: if (env->macsr & MACSR_SU) {
! 894: if (val != (uint16_t) val) {
! 895: result = ((val >> 63) ^ 0x7fff) & 0xffff;
! 896: } else {
! 897: result = val & 0xffff;
! 898: }
! 899: } else {
! 900: if (val != (uint32_t)val) {
! 901: result = ((uint32_t)(val >> 63) & 0x7fffffff);
! 902: } else {
! 903: result = (uint32_t)val;
! 904: }
! 905: }
! 906: } else {
! 907: /* No saturation. */
! 908: if (env->macsr & MACSR_SU) {
! 909: result = val & 0xffff;
! 910: } else {
! 911: result = (uint32_t)val;
! 912: }
! 913: }
! 914: set_op(PARAM1, result);
! 915: FORCE_RET();
! 916: }
! 917:
! 918: OP(get_maci)
! 919: {
! 920: int acc = PARAM2;
! 921: set_op(PARAM1, (uint32_t)env->macc[acc]);
! 922: FORCE_RET();
! 923: }
! 924:
! 925: OP(get_macs)
! 926: {
! 927: int acc = PARAM2;
! 928: int64_t val = env->macc[acc];
! 929: uint32_t result;
! 930: if (val == (int32_t)val) {
! 931: result = (int32_t)val;
! 932: } else {
! 933: result = (val >> 61) ^ 0x7fffffff;
! 934: }
! 935: set_op(PARAM1, result);
! 936: FORCE_RET();
! 937: }
! 938:
! 939: OP(get_macu)
! 940: {
! 941: int acc = PARAM2;
! 942: uint64_t val = env->macc[acc];
! 943: uint32_t result;
! 944: if ((val >> 32) == 0) {
! 945: result = (uint32_t)val;
! 946: } else {
! 947: result = 0xffffffffu;
! 948: }
! 949: set_op(PARAM1, result);
! 950: FORCE_RET();
! 951: }
! 952:
! 953: OP(clear_mac)
! 954: {
! 955: int acc = PARAM1;
! 956:
! 957: env->macc[acc] = 0;
! 958: env->macsr &= ~(MACSR_PAV0 << acc);
! 959: FORCE_RET();
! 960: }
! 961:
! 962: OP(move_mac)
! 963: {
! 964: int dest = PARAM1;
! 965: int src = PARAM2;
! 966: uint32_t mask;
! 967: env->macc[dest] = env->macc[src];
! 968: mask = MACSR_PAV0 << dest;
! 969: if (env->macsr & (MACSR_PAV0 << src))
! 970: env->macsr |= mask;
! 971: else
! 972: env->macsr &= ~mask;
! 973: FORCE_RET();
! 974: }
! 975:
! 976: OP(get_mac_extf)
! 977: {
! 978: uint32_t val;
! 979: int acc = PARAM2;
! 980: val = env->macc[acc] & 0x00ff;
! 981: val = (env->macc[acc] >> 32) & 0xff00;
! 982: val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
! 983: val |= (env->macc[acc + 1] >> 16) & 0xff000000;
! 984: set_op(PARAM1, val);
! 985: FORCE_RET();
! 986: }
! 987:
! 988: OP(get_mac_exti)
! 989: {
! 990: uint32_t val;
! 991: int acc = PARAM2;
! 992: val = (env->macc[acc] >> 32) & 0xffff;
! 993: val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
! 994: set_op(PARAM1, val);
! 995: FORCE_RET();
! 996: }
! 997:
! 998: OP(set_macf)
! 999: {
! 1000: int acc = PARAM2;
! 1001: int32_t val = get_op(PARAM1);
! 1002: env->macc[acc] = ((int64_t)val) << 8;
! 1003: env->macsr &= ~(MACSR_PAV0 << acc);
! 1004: FORCE_RET();
! 1005: }
! 1006:
! 1007: OP(set_macs)
! 1008: {
! 1009: int acc = PARAM2;
! 1010: int32_t val = get_op(PARAM1);
! 1011: env->macc[acc] = val;
! 1012: env->macsr &= ~(MACSR_PAV0 << acc);
! 1013: FORCE_RET();
! 1014: }
! 1015:
! 1016: OP(set_macu)
! 1017: {
! 1018: int acc = PARAM2;
! 1019: uint32_t val = get_op(PARAM1);
! 1020: env->macc[acc] = val;
! 1021: env->macsr &= ~(MACSR_PAV0 << acc);
! 1022: FORCE_RET();
! 1023: }
! 1024:
! 1025: OP(set_mac_extf)
! 1026: {
! 1027: int acc = PARAM2;
! 1028: int32_t val = get_op(PARAM1);
! 1029: int64_t res;
! 1030: int32_t tmp;
! 1031: res = env->macc[acc] & 0xffffffff00ull;
! 1032: tmp = (int16_t)(val & 0xff00);
! 1033: res |= ((int64_t)tmp) << 32;
! 1034: res |= val & 0xff;
! 1035: env->macc[acc] = res;
! 1036: res = env->macc[acc + 1] & 0xffffffff00ull;
! 1037: tmp = (val & 0xff000000);
! 1038: res |= ((int64_t)tmp) << 16;
! 1039: res |= (val >> 16) & 0xff;
! 1040: env->macc[acc + 1] = res;
! 1041: }
! 1042:
! 1043: OP(set_mac_exts)
! 1044: {
! 1045: int acc = PARAM2;
! 1046: int32_t val = get_op(PARAM1);
! 1047: int64_t res;
! 1048: int32_t tmp;
! 1049: res = (uint32_t)env->macc[acc];
! 1050: tmp = (int16_t)val;
! 1051: res |= ((int64_t)tmp) << 32;
! 1052: env->macc[acc] = res;
! 1053: res = (uint32_t)env->macc[acc + 1];
! 1054: tmp = val & 0xffff0000;
! 1055: res |= (int64_t)tmp << 16;
! 1056: env->macc[acc + 1] = res;
! 1057: }
! 1058:
! 1059: OP(set_mac_extu)
! 1060: {
! 1061: int acc = PARAM2;
! 1062: int32_t val = get_op(PARAM1);
! 1063: uint64_t res;
! 1064: res = (uint32_t)env->macc[acc];
! 1065: res |= ((uint64_t)(val & 0xffff)) << 32;
! 1066: env->macc[acc] = res;
! 1067: res = (uint32_t)env->macc[acc + 1];
! 1068: res |= (uint64_t)(val & 0xffff0000) << 16;
! 1069: env->macc[acc + 1] = res;
! 1070: }
! 1071:
! 1072: OP(set_macsr)
! 1073: {
! 1074: m68k_set_macsr(env, get_op(PARAM1));
! 1075: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.