|
|
1.1 root 1:
2:
3: #include "sysconfig.h"
4: #include "sysdeps.h"
5:
6: #define MOVEC_DEBUG 0
7:
8: #include "main.h"
9: #include "hatari-glue.h"
10:
11: #include "options_cpu.h"
12: #include "memory.h"
13: #include "newcpu.h"
14: #include "cpummu.h"
15: #include "cpummu030.h"
16: #include "host.h"
17:
18: void val_move2c2 (int regno, uae_u32 val)
19: {
20: switch (regno) {
21: case 0: regs.sfc = val; break;
22: case 1: regs.dfc = val; break;
23: case 2: regs.cacr = val; break;
24: case 3: regs.tcr = val; break;
25: case 4: regs.itt0 = val; break;
26: case 5: regs.itt1 = val; break;
27: case 6: regs.dtt0 = val; break;
28: case 7: regs.dtt1 = val; break;
29: case 8: regs.buscr = val; break;
30: case 0x800: regs.usp = val; break;
31: case 0x801: regs.vbr = val; break;
32: case 0x802: regs.caar = val; break;
33: case 0x803: regs.msp = val; break;
34: case 0x804: regs.isp = val; break;
35: case 0x805: regs.mmusr = val; break;
36: case 0x806: regs.urp = val; break;
37: case 0x807: regs.srp = val; break;
38: case 0x808: regs.pcr = val; break;
39: }
40: }
41:
42: uae_u32 val_move2c (int regno)
43: {
44: switch (regno) {
45: case 0: return regs.sfc;
46: case 1: return regs.dfc;
47: case 2: return regs.cacr;
48: case 3: return regs.tcr;
49: case 4: return regs.itt0;
50: case 5: return regs.itt1;
51: case 6: return regs.dtt0;
52: case 7: return regs.dtt1;
53: case 8: return regs.buscr;
54: case 0x800: return regs.usp;
55: case 0x801: return regs.vbr;
56: case 0x802: return regs.caar;
57: case 0x803: return regs.msp;
58: case 0x804: return regs.isp;
59: case 0x805: return regs.mmusr;
60: case 0x806: return regs.urp;
61: case 0x807: return regs.srp;
62: case 0x808: return regs.pcr;
63: default: return 0;
64: }
65: }
66:
67: #ifndef CPUEMU_68000_ONLY
68:
69: int movec_illg (int regno)
70: {
71: int regno2 = regno & 0x7ff;
72:
73: if (currprefs.cpu_model == 68060) {
74: if (regno <= 8)
75: return 0;
76: if (regno == 0x800 || regno == 0x801 ||
77: regno == 0x806 || regno == 0x807 || regno == 0x808)
78: return 0;
79: return 1;
80: } else if (currprefs.cpu_model == 68010) {
81: if (regno2 < 2)
82: return 0;
83: return 1;
84: } else if (currprefs.cpu_model == 68020) {
85: if (regno == 3)
86: return 1; /* 68040/060 only */
87: /* 4 is >=68040, but 0x804 is in 68020 */
88: if (regno2 < 4 || regno == 0x804)
89: return 0;
90: return 1;
91: } else if (currprefs.cpu_model == 68030) {
92: if (regno2 <= 2)
93: return 0;
94: if (regno == 0x803 || regno == 0x804)
95: return 0;
96: return 1;
97: } else if (currprefs.cpu_model == 68040) {
98: if (regno == 0x802)
99: return 1; /* 68020/030 only */
100: if (regno2 < 8) return 0;
101: return 1;
102: }
103: return 1;
104: }
105:
106: int m68k_move2c (int regno, uae_u32 *regp)
107: {
108: #if MOVEC_DEBUG > 0
109: write_log (_T("move2c %04X <- %08X PC=%x\n"), regno, *regp, M68K_GETPC);
110: #endif
111: if (movec_illg (regno)) {
112: op_illg (0x4E7B);
113: return 0;
114: } else {
115: switch (regno) {
116: case 0: regs.sfc = *regp & 7; break;
117: case 1: regs.dfc = *regp & 7; break;
118: case 2:
119: {
120: uae_u32 cacr_mask = 0;
121: if (currprefs.cpu_model == 68020)
122: cacr_mask = 0x0000000f;
123: else if (currprefs.cpu_model == 68030)
124: cacr_mask = 0x00003f1f;
125: else if (currprefs.cpu_model == 68040)
126: cacr_mask = 0x80008000;
127: else if (currprefs.cpu_model == 68060)
128: cacr_mask = 0xf8e0e000;
129: regs.cacr = *regp & cacr_mask;
130: set_cpu_caches (false);
131: }
132: break;
133: /* 68040/060 only */
134: case 3:
135: regs.tcr = *regp & (currprefs.cpu_model == 68060 ? 0xfffe : 0xc000);
136: if (currprefs.mmu_model)
137: mmu_set_tc (regs.tcr);
138: break;
139:
140: /* no differences between 68040 and 68060 */
141: case 4: regs.itt0 = *regp & 0xffffe364; mmu_tt_modified (); break;
142: case 5: regs.itt1 = *regp & 0xffffe364; mmu_tt_modified (); break;
143: case 6: regs.dtt0 = *regp & 0xffffe364; mmu_tt_modified (); break;
144: case 7: regs.dtt1 = *regp & 0xffffe364; mmu_tt_modified (); break;
145: /* 68060 only */
146: case 8: regs.buscr = *regp & 0xf0000000; break;
147:
148: case 0x800: regs.usp = *regp; break;
149: case 0x801: regs.vbr = *regp; break;
150: case 0x802: regs.caar = *regp; break;
151: case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg (regs, 7) = regs.msp; break;
152: case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg (regs, 7) = regs.isp; break;
153: /* 68040 only */
154: case 0x805: regs.mmusr = *regp; break;
155: /* 68040 stores all bits, 68060 zeroes low 9 bits */
156: case 0x806: regs.urp = *regp & (currprefs.cpu_model == 68060 ? 0xfffffe00 : 0xffffffff); break;
157: case 0x807:
158: regs.srp = *regp & (currprefs.cpu_model == 68060 ? 0xfffffe00 : 0xffffffff);
159: host_darkmatter(regs.srp == regs.urp);
160: break;
161: /* 68060 only */
162: case 0x808:
163: {
164: uae_u32 opcr = regs.pcr;
165: regs.pcr &= ~(0x40 | 2 | 1);
166: regs.pcr |= (*regp) & (0x40 | 2 | 1);
167: if (currprefs.fpu_model <= 0)
168: regs.pcr |= 2;
169: if (((opcr ^ regs.pcr) & 2) == 2) {
170: write_log (_T("68060 FPU state: %s\n"), regs.pcr & 2 ? _T("disabled") : _T("enabled"));
171: /* flush possible already translated FPU instructions */
172: flush_icache (3);
173: }
174: }
175: break;
176: default:
177: op_illg (0x4E7B);
178: return 0;
179: }
180: }
181: return 1;
182: }
183:
184: int m68k_movec2 (int regno, uae_u32 *regp)
185: {
186: #if MOVEC_DEBUG > 0
187: write_log (_T("movec2 %04X PC=%x\n"), regno, M68K_GETPC);
188: #endif
189: if (movec_illg (regno)) {
190: op_illg (0x4E7A);
191: return 0;
192: } else {
193: switch (regno) {
194: case 0: *regp = regs.sfc; break;
195: case 1: *regp = regs.dfc; break;
196: case 2:
197: {
198: uae_u32 v = regs.cacr;
199: uae_u32 cacr_mask = 0;
200: if (currprefs.cpu_model == 68020)
201: cacr_mask = 0x00000003;
202: else if (currprefs.cpu_model == 68030)
203: cacr_mask = 0x00003313;
204: else if (currprefs.cpu_model == 68040)
205: cacr_mask = 0x80008000;
206: else if (currprefs.cpu_model == 68060)
207: cacr_mask = 0xf880e000;
208: *regp = v & cacr_mask;
209: }
210: break;
211: case 3: *regp = regs.tcr; break;
212: case 4: *regp = regs.itt0; break;
213: case 5: *regp = regs.itt1; break;
214: case 6: *regp = regs.dtt0; break;
215: case 7: *regp = regs.dtt1; break;
216: case 8: *regp = regs.buscr; break;
217:
218: case 0x800: *regp = regs.usp; break;
219: case 0x801: *regp = regs.vbr; break;
220: case 0x802: *regp = regs.caar; break;
221: case 0x803: *regp = regs.m == 1 ? m68k_areg (regs, 7) : regs.msp; break;
222: case 0x804: *regp = regs.m == 0 ? m68k_areg (regs, 7) : regs.isp; break;
223: case 0x805: *regp = regs.mmusr; break;
224: case 0x806: *regp = regs.urp; break;
225: case 0x807: *regp = regs.srp; break;
226: case 0x808: *regp = regs.pcr; break;
227:
228: default:
229: op_illg (0x4E7A);
230: return 0;
231: }
232: }
233: #if MOVEC_DEBUG > 0
234: write_log (_T("-> %08X\n"), *regp);
235: #endif
236: return 1;
237: }
238:
239: #endif
240:
241:
242: /*
243: * extract bitfield data from memory and return it in the MSBs
244: * bdata caches the unmodified data for put_bitfield()
245: */
246: uae_u32 REGPARAM2 get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width)
247: {
248: uae_u32 tmp, res, mask;
249:
250: offset &= 7;
251: mask = 0xffffffffu << (32 - width);
252: switch ((offset + width + 7) >> 3) {
253: case 1:
254: tmp = get_byte (src);
255: res = tmp << (24 + offset);
256: bdata[0] = tmp & ~(mask >> (24 + offset));
257: break;
258: case 2:
259: tmp = get_word (src);
260: res = tmp << (16 + offset);
261: bdata[0] = tmp & ~(mask >> (16 + offset));
262: break;
263: case 3:
264: tmp = get_word (src);
265: res = tmp << (16 + offset);
266: bdata[0] = tmp & ~(mask >> (16 + offset));
267: tmp = get_byte (src + 2);
268: res |= tmp << (8 + offset);
269: bdata[1] = tmp & ~(mask >> (8 + offset));
270: break;
271: case 4:
272: tmp = get_long (src);
273: res = tmp << offset;
274: bdata[0] = tmp & ~(mask >> offset);
275: break;
276: case 5:
277: tmp = get_long (src);
278: res = tmp << offset;
279: bdata[0] = tmp & ~(mask >> offset);
280: tmp = get_byte (src + 4);
281: res |= tmp >> (8 - offset);
282: bdata[1] = tmp & ~(mask << (8 - offset));
283: break;
284: default:
285: /* Panic? */
286: write_log (_T("get_bitfield() can't happen %d\n"), (offset + width + 7) >> 3);
287: res = 0;
288: break;
289: }
290: return res;
291: }
292: /*
293: * write bitfield data (in the LSBs) back to memory, upper bits
294: * must be cleared already.
295: */
296: void REGPARAM2 put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width)
297: {
298: offset = (offset & 7) + width;
299: switch ((offset + 7) >> 3) {
300: case 1:
301: put_byte (dst, bdata[0] | (val << (8 - offset)));
302: break;
303: case 2:
304: put_word (dst, bdata[0] | (val << (16 - offset)));
305: break;
306: case 3:
307: put_word (dst, bdata[0] | (val >> (offset - 16)));
308: put_byte (dst + 2, bdata[1] | (val << (24 - offset)));
309: break;
310: case 4:
311: put_long (dst, bdata[0] | (val << (32 - offset)));
312: break;
313: case 5:
314: put_long (dst, bdata[0] | (val >> (offset - 32)));
315: put_byte (dst + 4, bdata[1] | (val << (40 - offset)));
316: break;
317: default:
318: write_log (_T("put_bitfield() can't happen %d\n"), (offset + 7) >> 3);
319: break;
320: }
321: }
322:
323: uae_u32 REGPARAM2 x_get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width)
324: {
325: uae_u32 tmp1, tmp2, res, mask;
326:
327: offset &= 7;
328: mask = 0xffffffffu << (32 - width);
329: switch ((offset + width + 7) >> 3) {
330: case 1:
331: tmp1 = x_cp_get_byte (src);
332: res = tmp1 << (24 + offset);
333: bdata[0] = tmp1 & ~(mask >> (24 + offset));
334: break;
335: case 2:
336: tmp1 = x_cp_get_word (src);
337: res = tmp1 << (16 + offset);
338: bdata[0] = tmp1 & ~(mask >> (16 + offset));
339: break;
340: case 3:
341: tmp1 = x_cp_get_word (src);
342: tmp2 = x_cp_get_byte (src + 2);
343: res = tmp1 << (16 + offset);
344: bdata[0] = tmp1 & ~(mask >> (16 + offset));
345: res |= tmp2 << (8 + offset);
346: bdata[1] = tmp2 & ~(mask >> (8 + offset));
347: break;
348: case 4:
349: tmp1 = x_cp_get_long (src);
350: res = tmp1 << offset;
351: bdata[0] = tmp1 & ~(mask >> offset);
352: break;
353: case 5:
354: tmp1 = x_cp_get_long (src);
355: tmp2 = x_cp_get_byte (src + 4);
356: res = tmp1 << offset;
357: bdata[0] = tmp1 & ~(mask >> offset);
358: res |= tmp2 >> (8 - offset);
359: bdata[1] = tmp2 & ~(mask << (8 - offset));
360: break;
361: default:
362: /* Panic? */
363: write_log (_T("x_get_bitfield() can't happen %d\n"), (offset + width + 7) >> 3);
364: res = 0;
365: break;
366: }
367: return res;
368: }
369:
370: void REGPARAM2 x_put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width)
371: {
372: offset = (offset & 7) + width;
373: switch ((offset + 7) >> 3) {
374: case 1:
375: x_cp_put_byte (dst, bdata[0] | (val << (8 - offset)));
376: break;
377: case 2:
378: x_cp_put_word (dst, bdata[0] | (val << (16 - offset)));
379: break;
380: case 3:
381: x_cp_put_word (dst, bdata[0] | (val >> (offset - 16)));
382: x_cp_put_byte (dst + 2, bdata[1] | (val << (24 - offset)));
383: break;
384: case 4:
385: x_cp_put_long (dst, bdata[0] | (val << (32 - offset)));
386: break;
387: case 5:
388: x_cp_put_long (dst, bdata[0] | (val >> (offset - 32)));
389: x_cp_put_byte (dst + 4, bdata[1] | (val << (40 - offset)));
390: break;
391: default:
392: write_log (_T("x_put_bitfield() can't happen %d\n"), (offset + 7) >> 3);
393: break;
394: }
395: }
396:
397: uae_u32 REGPARAM2 get_disp_ea_020 (uae_u32 base, int idx)
398: {
399: uae_u16 dp = next_diword ();
400: int reg = (dp >> 12) & 15;
401: uae_s32 regd = regs.regs[reg];
402: if ((dp & 0x800) == 0)
403: regd = (uae_s32)(uae_s16)regd;
404: regd <<= (dp >> 9) & 3;
405: if (dp & 0x100) {
406: uae_s32 outer = 0;
407: if (dp & 0x80) base = 0;
408: if (dp & 0x40) regd = 0;
409:
410: if ((dp & 0x30) == 0x20)
411: base += (uae_s32)(uae_s16) next_diword ();
412: if ((dp & 0x30) == 0x30)
413: base += next_dilong ();
414:
415: if ((dp & 0x3) == 0x2)
416: outer = (uae_s32)(uae_s16) next_diword ();
417: if ((dp & 0x3) == 0x3)
418: outer = next_dilong ();
419:
420: if ((dp & 0x4) == 0)
421: base += regd;
422: if (dp & 0x3)
423: base = get_long (base);
424: if (dp & 0x4)
425: base += regd;
426:
427: return base + outer;
428: } else {
429: return base + (uae_s32)((uae_s8)dp) + regd;
430: }
431: }
432:
433: uae_u32 REGPARAM2 x_get_disp_ea_020 (uae_u32 base, int idx)
434: {
435: uae_u16 dp = x_next_iword ();
436: int reg = (dp >> 12) & 15;
437: int cycles = 0;
438: uae_u32 v;
439:
440: uae_s32 regd = regs.regs[reg];
441: if ((dp & 0x800) == 0)
442: regd = (uae_s32)(uae_s16)regd;
443: regd <<= (dp >> 9) & 3;
444: if (dp & 0x100) {
445: uae_s32 outer = 0;
446: if (dp & 0x80)
447: base = 0;
448: if (dp & 0x40)
449: regd = 0;
450:
451: if ((dp & 0x30) == 0x20) {
452: base += (uae_s32)(uae_s16) x_next_iword ();
453: cycles++;
454: }
455: if ((dp & 0x30) == 0x30) {
456: base += x_next_ilong ();
457: cycles++;
458: }
459:
460: if ((dp & 0x3) == 0x2) {
461: outer = (uae_s32)(uae_s16) x_next_iword ();
462: cycles++;
463: }
464: if ((dp & 0x3) == 0x3) {
465: outer = x_next_ilong ();
466: cycles++;
467: }
468:
469: if ((dp & 0x4) == 0) {
470: base += regd;
471: cycles++;
472: }
473: if (dp & 0x3) {
474: base = x_get_long (base);
475: cycles++;
476: }
477: if (dp & 0x4) {
478: base += regd;
479: cycles++;
480: }
481: v = base + outer;
482: } else {
483: v = base + (uae_s32)((uae_s8)dp) + regd;
484: }
485: return v;
486: }
487:
488: /*
489: * Compute exact number of CPU cycles taken
490: * by DIVU and DIVS on a 68000 processor.
491: *
492: * Copyright (c) 2005 by Jorge Cwik, [email protected]
493: *
494: * This is free software; you can redistribute it and/or modify
495: * it under the terms of the GNU General Public License as published by
496: * the Free Software Foundation; either version 2 of the License, or
497: * (at your option) any later version.
498: *
499: * This software is distributed in the hope that it will be useful,
500: * but WITHOUT ANY WARRANTY; without even the implied warranty of
501: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
502: * GNU General Public License for more details.
503: *
504: * You should have received a copy of the GNU General Public License
505: * along with this software; if not, write to the Free Software
506: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
507: *
508: */
509:
510:
511: /*
512:
513: The routines below take dividend and divisor as parameters.
514: They return 0 if division by zero, or exact number of cycles otherwise.
515:
516: The number of cycles returned assumes a register operand.
517: Effective address time must be added if memory operand.
518:
519: For 68000 only (not 68010, 68012, 68020, etc).
520: Probably valid for 68008 after adding the extra prefetch cycle.
521:
522:
523: Best and worst cases for register operand:
524: (Note the difference with the documented range.)
525:
526:
527: DIVU:
528:
529: Overflow (always): 10 cycles.
530: Worst case: 136 cycles.
531: Best case: 76 cycles.
532:
533:
534: DIVS:
535:
536: Absolute overflow: 16-18 cycles.
537: Signed overflow is not detected prematurely.
538:
539: Worst case: 156 cycles.
540: Best case without signed overflow: 122 cycles.
541: Best case with signed overflow: 120 cycles
542:
543:
544: */
545:
546: int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor)
547: {
548: int mcycles;
549: uae_u32 hdivisor;
550: int i;
551:
552: if (divisor == 0)
553: return 0;
554:
555: // Overflow
556: if ((dividend >> 16) >= divisor)
557: return (mcycles = 5) * 2;
558:
559: mcycles = 38;
560: hdivisor = divisor << 16;
561:
562: for (i = 0; i < 15; i++) {
563: uae_u32 temp;
564: temp = dividend;
565:
566: dividend <<= 1;
567:
568: // If carry from shift
569: if ((uae_s32)temp < 0)
570: dividend -= hdivisor;
571: else {
572: mcycles += 2;
573: if (dividend >= hdivisor) {
574: dividend -= hdivisor;
575: mcycles--;
576: }
577: }
578: }
579: return mcycles * 2;
580: }
581:
582: int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor)
583: {
584: int mcycles;
585: uae_u32 aquot;
586: int i;
587:
588: if (divisor == 0)
589: return 0;
590:
591: mcycles = 6;
592:
593: if (dividend < 0)
594: mcycles++;
595:
596: // Check for absolute overflow
597: if (((uae_u32)abs (dividend) >> 16) >= (uae_u16)abs (divisor))
598: return (mcycles + 2) * 2;
599:
600: // Absolute quotient
601: aquot = (uae_u32) abs (dividend) / (uae_u16)abs (divisor);
602:
603: mcycles += 55;
604:
605: if (divisor >= 0) {
606: if (dividend >= 0)
607: mcycles--;
608: else
609: mcycles++;
610: }
611:
612: // Count 15 msbits in absolute of quotient
613:
614: for (i = 0; i < 15; i++) {
615: if ((uae_s16)aquot >= 0)
616: mcycles++;
617: aquot <<= 1;
618: }
619:
620: return mcycles * 2;
621: }
622:
623: /* 68000 Z=1. NVC=0
624: * 68020 and 68030: Signed: Z=1 NVC=0. Unsigned: V=1, N<dst, Z=!N, C=0.
625: * 68040/68060 C=0.
626: */
627: void divbyzero_special (bool issigned, uae_s32 dst)
628: {
629: if (currprefs.cpu_model == 68020 || currprefs.cpu_model == 68030) {
630: CLEAR_CZNV ();
631: if (issigned == false) {
632: if (dst < 0)
633: SET_NFLG (1);
634: SET_ZFLG (!GET_NFLG ());
635: SET_VFLG (1);
636: } else {
637: SET_ZFLG (1);
638: }
639: } else if (currprefs.cpu_model >= 68040) {
640: SET_CFLG (0);
641: } else {
642: // 68000/010
643: CLEAR_CZNV ();
644: }
645: }
646:
647: /* DIVU overflow
648: *
649: * 68000: V=1 N=1
650: * 68020: V=1 N=X
651: * 68040: V=1
652: * 68060: V=1
653: *
654: * X) N is set if original 32-bit destination value is negative.
655: *
656: */
657:
658: void setdivuoverflowflags(uae_u32 dividend, uae_u16 divisor)
659: {
660: if (currprefs.cpu_model >= 68040) {
661: SET_VFLG(1);
662: } else if (currprefs.cpu_model >= 68020) {
663: SET_VFLG(1);
664: if ((uae_s32)dividend < 0)
665: SET_NFLG(1);
666: } else {
667: SET_VFLG(1);
668: SET_NFLG(1);
669: }
670: }
671:
672: /*
673: * DIVS overflow
674: *
675: * 68000: V = 1 N = 1
676: * 68020: V = 1 ZN = X
677: * 68040: V = 1
678: * 68060: V = 1
679: *
680: * X) if absolute overflow(Check getDivs68kCycles for details) : Z = 0, N = 0
681: * if not absolute overflow : N is set if internal result BYTE is negative, Z is set if it is zero!
682: *
683: */
684:
685: void setdivsoverflowflags(uae_s32 dividend, uae_s16 divisor)
686: {
687: if (currprefs.cpu_model >= 68040) {
688: SET_VFLG(1);
689: } else if (currprefs.cpu_model >= 68020) {
690: SET_VFLG(1);
691: // absolute overflow?
692: if (((uae_u32)abs(dividend) >> 16) >= (uae_u16)abs(divisor))
693: return;
694: uae_u32 aquot = (uae_u32)abs(dividend) / (uae_u16)abs(divisor);
695: if ((uae_s8)aquot == 0)
696: SET_ZFLG(1);
697: if ((uae_s8)aquot < 0)
698: SET_NFLG(1);
699: } else {
700: SET_VFLG(1);
701: SET_NFLG(1);
702: }
703: }
704:
705: #ifndef CPUEMU_68000_ONLY
706:
707: #if !defined (uae_s64)
708: STATIC_INLINE int div_unsigned (uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
709: {
710: uae_u32 q = 0, cbit = 0;
711: int i;
712:
713: if (div <= src_hi) {
714: return 1;
715: }
716: for (i = 0 ; i < 32 ; i++) {
717: cbit = src_hi & 0x80000000ul;
718: src_hi <<= 1;
719: if (src_lo & 0x80000000ul) src_hi++;
720: src_lo <<= 1;
721: q = q << 1;
722: if (cbit || div <= src_hi) {
723: q |= 1;
724: src_hi -= div;
725: }
726: }
727: *quot = q;
728: *rem = src_hi;
729: return 0;
730: }
731: #endif
732:
733: bool m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra)
734: {
735: if (src == 0) {
736: Exception_cpu (5);
737: return false;
738: }
739: #if defined (uae_s64)
740: if (extra & 0x800) {
741: /* signed variant */
742: uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
743: uae_s64 quot, rem;
744:
745: if (extra & 0x400) {
746: a &= 0xffffffffu;
747: a |= (uae_s64)m68k_dreg (regs, extra & 7) << 32;
748: }
749:
750: if ((uae_u64)a == 0x8000000000000000UL && src == ~0u) {
751: SET_VFLG (1);
752: SET_NFLG (1);
753: SET_CFLG (0);
754: } else {
755: rem = a % (uae_s64)(uae_s32)src;
756: quot = a / (uae_s64)(uae_s32)src;
757: if ((quot & UVAL64 (0xffffffff80000000)) != 0
758: && (quot & UVAL64 (0xffffffff80000000)) != UVAL64 (0xffffffff80000000))
759: {
760: SET_VFLG (1);
761: SET_NFLG (1);
762: SET_CFLG (0);
763: } else {
764: if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
765: SET_VFLG (0);
766: SET_CFLG (0);
767: SET_ZFLG (((uae_s32)quot) == 0);
768: SET_NFLG (((uae_s32)quot) < 0);
769: m68k_dreg (regs, extra & 7) = (uae_u32)rem;
770: m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)quot;
771: }
772: }
773: } else {
774: /* unsigned */
775: uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
776: uae_u64 quot, rem;
777:
778: if (extra & 0x400) {
779: a &= 0xffffffffu;
780: a |= (uae_u64)m68k_dreg (regs, extra & 7) << 32;
781: }
782: rem = a % (uae_u64)src;
783: quot = a / (uae_u64)src;
784: if (quot > 0xffffffffu) {
785: SET_VFLG (1);
786: SET_NFLG (1);
787: SET_CFLG (0);
788: } else {
789: SET_VFLG (0);
790: SET_CFLG (0);
791: SET_ZFLG (((uae_s32)quot) == 0);
792: SET_NFLG (((uae_s32)quot) < 0);
793: m68k_dreg (regs, extra & 7) = (uae_u32)rem;
794: m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)quot;
795: }
796: }
797: #else
798: if (extra & 0x800) {
799: /* signed variant */
800: uae_s32 lo = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
801: uae_s32 hi = lo < 0 ? -1 : 0;
802: uae_s32 save_high;
803: uae_u32 quot, rem;
804: uae_u32 sign;
805:
806: if (extra & 0x400) {
807: hi = (uae_s32)m68k_dreg (regs, extra & 7);
808: }
809: save_high = hi;
810: sign = (hi ^ src);
811: if (hi < 0) {
812: hi = ~hi;
813: lo = -lo;
814: if (lo == 0) hi++;
815: }
816: if ((uae_s32)src < 0) src = -src;
817: if (div_unsigned (hi, lo, src, ", &rem) ||
818: (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
819: SET_VFLG (1);
820: SET_NFLG (1);
821: SET_CFLG (0);
822: } else {
823: if (sign & 0x80000000) quot = -quot;
824: if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
825: SET_VFLG (0);
826: SET_CFLG (0);
827: SET_ZFLG (((uae_s32)quot) == 0);
828: SET_NFLG (((uae_s32)quot) < 0);
829: m68k_dreg (regs, extra & 7) = rem;
830: m68k_dreg (regs, (extra >> 12) & 7) = quot;
831: }
832: } else {
833: /* unsigned */
834: uae_u32 lo = (uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
835: uae_u32 hi = 0;
836: uae_u32 quot, rem;
837:
838: if (extra & 0x400) {
839: hi = (uae_u32)m68k_dreg (regs, extra & 7);
840: }
841: if (div_unsigned (hi, lo, src, ", &rem)) {
842: SET_VFLG (1);
843: SET_NFLG (1);
844: SET_CFLG (0);
845: } else {
846: SET_VFLG (0);
847: SET_CFLG (0);
848: SET_ZFLG (((uae_s32)quot) == 0);
849: SET_NFLG (((uae_s32)quot) < 0);
850: m68k_dreg (regs, extra & 7) = rem;
851: m68k_dreg (regs, (extra >> 12) & 7) = quot;
852: }
853: }
854: #endif
855: return true;
856: }
857:
858: #if !defined (uae_s64)
859: STATIC_INLINE void mul_unsigned (uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
860: {
861: uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
862: uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
863: uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
864: uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
865: uae_u32 lo;
866:
867: lo = r0 + ((r1 << 16) & 0xffff0000ul);
868: if (lo < r0) r3++;
869: r0 = lo;
870: lo = r0 + ((r2 << 16) & 0xffff0000ul);
871: if (lo < r0) r3++;
872: r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
873: *dst_lo = lo;
874: *dst_hi = r3;
875: }
876: #endif
877:
878: bool m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
879: {
880: #if defined (uae_s64)
881: if (extra & 0x800) {
882: /* signed variant */
883: uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
884:
885: a *= (uae_s64)(uae_s32)src;
886: SET_VFLG (0);
887: SET_CFLG (0);
888: SET_ZFLG (a == 0);
889: SET_NFLG (a < 0);
890: if (extra & 0x400) {
891: m68k_dreg (regs, extra & 7) = (uae_u32)(a >> 32);
892: } else if ((a & UVAL64 (0xffffffff80000000)) != 0
893: && (a & UVAL64 (0xffffffff80000000)) != UVAL64 (0xffffffff80000000))
894: {
895: SET_VFLG (1);
896: }
897: m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a;
898: } else {
899: /* unsigned */
900: uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
901:
902: a *= (uae_u64)src;
903: SET_VFLG (0);
904: SET_CFLG (0);
905: SET_ZFLG (a == 0);
906: SET_NFLG (((uae_s64)a) < 0);
907: if (extra & 0x400) {
908: m68k_dreg (regs, extra & 7) = (uae_u32)(a >> 32);
909: } else if ((a & UVAL64 (0xffffffff00000000)) != 0) {
910: SET_VFLG (1);
911: }
912: m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a;
913: }
914: #else
915: if (extra & 0x800) {
916: /* signed variant */
917: uae_s32 src1, src2;
918: uae_u32 dst_lo, dst_hi;
919: uae_u32 sign;
920:
921: src1 = (uae_s32)src;
922: src2 = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
923: sign = (src1 ^ src2);
924: if (src1 < 0) src1 = -src1;
925: if (src2 < 0) src2 = -src2;
926: mul_unsigned ((uae_u32)src1, (uae_u32)src2, &dst_hi, &dst_lo);
927: if (sign & 0x80000000) {
928: dst_hi = ~dst_hi;
929: dst_lo = -dst_lo;
930: if (dst_lo == 0) dst_hi++;
931: }
932: SET_VFLG (0);
933: SET_CFLG (0);
934: SET_ZFLG (dst_hi == 0 && dst_lo == 0);
935: SET_NFLG (((uae_s32)dst_hi) < 0);
936: if (extra & 0x400)
937: m68k_dreg (regs, extra & 7) = dst_hi;
938: else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0)
939: && ((dst_hi & 0xffffffff) != 0xffffffff
940: || (dst_lo & 0x80000000) != 0x80000000))
941: {
942: SET_VFLG (1);
943: }
944: m68k_dreg (regs, (extra >> 12) & 7) = dst_lo;
945: } else {
946: /* unsigned */
947: uae_u32 dst_lo, dst_hi;
948:
949: mul_unsigned (src, (uae_u32)m68k_dreg (regs, (extra >> 12) & 7), &dst_hi, &dst_lo);
950:
951: SET_VFLG (0);
952: SET_CFLG (0);
953: SET_ZFLG (dst_hi == 0 && dst_lo == 0);
954: SET_NFLG (((uae_s32)dst_hi) < 0);
955: if (extra & 0x400)
956: m68k_dreg (regs, extra & 7) = dst_hi;
957: else if (dst_hi != 0) {
958: SET_VFLG (1);
959: }
960: m68k_dreg (regs, (extra >> 12) & 7) = dst_lo;
961: }
962: #endif
963: return true;
964: }
965:
966: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.