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