fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/cpu/e68000/ea.c *
7 * Created: 2006-05-17 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2005-2018 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include "e68000.h"
28#include "internal.h"
29
30
31/*
32 * valid ea mask:
33 * 0 001: Dx
34 * 1 002: Ax
35 * 2 004: (Ax)
36 * 3 008: (Ax)+
37 * 4 010: -(Ax)
38 * 5 020: XXXX(Ax)
39 * 6 040: XX(Ax, Rx.S)
40 * 7 080: XXXX
41 * 8 100: XXXXXXXX
42 * 9 200: XXXX(PC)
43 * 10 400: XX(PC, Rx.S)
44 * 11 800: #XXXX
45*/
46
47
48static
49int e68_ea_full (e68000_t *c, unsigned ext, unsigned mask)
50{
51 uint32_t ix, bd, od;
52 unsigned scale;
53 int bs, is;
54
55 /* base register is in c->ea_val */
56
57 bs = (ext & 0x0080) != 0;
58 is = (ext & 0x0040) != 0;
59
60 if (bs) {
61 c->ea_val = 0;
62 }
63
64 scale = (ext >> 9) & 3;
65
66 if (is) {
67 ix = 0;
68 }
69 else {
70 if (ext & 0x8000) {
71 ix = e68_get_areg32 (c, (ext >> 12) & 7);
72 }
73 else {
74 ix = e68_get_dreg32 (c, (ext >> 12) & 7);
75 }
76
77 if ((ext & 0x0800) == 0) {
78 ix = e68_exts16 (ix);
79 }
80 }
81
82 bd = 0;
83
84 switch ((ext >> 4) & 3) {
85 case 0:
86 e68_exception_illegal (c);
87 return (1);
88
89 case 1:
90 bd = 0;
91 break;
92
93 case 2:
94 if (e68_prefetch (c)) {
95 return (1);
96 }
97 bd = e68_exts16 (c->ir[1]);
98 break;
99
100 case 3:
101 if (e68_prefetch (c)) {
102 return (1);
103 }
104 bd = c->ir[1];
105 if (e68_prefetch (c)) {
106 return (1);
107 }
108 bd = (bd << 16) | c->ir[1];
109 break;
110 }
111
112 if ((ext & 7) == 0) {
113 c->ea_val += (ix << scale) + bd;
114 return (0);
115 }
116
117 od = 0;
118
119 switch (ext & 3) {
120 case 0:
121 e68_exception_illegal (c);
122 return (1);
123
124 case 1:
125 od = 0;
126 break;
127
128 case 2:
129 if (e68_prefetch (c)) {
130 return (1);
131 }
132 od = e68_exts16 (c->ir[1]);
133 break;
134
135 case 3:
136 if (e68_prefetch (c)) {
137 return (1);
138 }
139 od = c->ir[1];
140 if (e68_prefetch (c)) {
141 return (1);
142 }
143 od = (od << 16) | c->ir[1];
144 break;
145 }
146
147 if (ext & 4) {
148 /* indirect postindexed */
149 if (is) {
150 e68_exception_illegal (c);
151 return (1);
152 }
153
154 c->ea_val = e68_get_mem32 (c, c->ea_val + bd);
155 c->ea_val += (ix << scale) + od;
156 }
157 else {
158 /* indirect preindexed */
159 c->ea_val = e68_get_mem32 (c, c->ea_val + bd + (ix << scale));
160 c->ea_val += od;
161 }
162
163 return (0);
164}
165
166/* Dx */
167static
168int e68_ea_000_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
169{
170 if ((mask & 0x0001) == 0) {
171 e68_exception_illegal (c);
172 return (1);
173 }
174
175 c->ea_typ = E68_EA_TYPE_REG;
176 c->ea_val = ea & 7;
177
178 return (0);
179}
180
181/* Ax */
182static
183int e68_ea_001_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
184{
185 if ((mask & 0x0002) == 0) {
186 e68_exception_illegal (c);
187 return (1);
188 }
189
190 c->ea_typ = E68_EA_TYPE_REG;
191 c->ea_val = (ea & 7) + 8;
192
193 return (0);
194}
195
196/* (Ax) */
197static
198int e68_ea_010_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
199{
200 if ((mask & 0x0004) == 0) {
201 e68_exception_illegal (c);
202 return (1);
203 }
204
205 c->ea_typ = E68_EA_TYPE_MEM;
206 c->ea_val = e68_get_areg32 (c, ea & 7);
207
208 return (0);
209}
210
211/* (Ax)+ */
212static
213int e68_ea_011_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
214{
215 unsigned reg;
216
217 if ((mask & 0x0008) == 0) {
218 e68_exception_illegal (c);
219 return (1);
220 }
221
222 reg = ea & 7;
223
224 c->ea_typ = E68_EA_TYPE_MEM;
225 c->ea_val = e68_get_areg32 (c, reg);
226
227 e68_set_areg32 (c, reg, c->ea_val + (size >> 3));
228
229 return (0);
230}
231
232/* (A7)+ */
233static
234int e68_ea_011_111 (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
235{
236 if ((mask & 0x0008) == 0) {
237 e68_exception_illegal (c);
238 return (1);
239 }
240
241 if (size == 8) {
242 size = 16;
243 }
244
245 c->ea_typ = E68_EA_TYPE_MEM;
246 c->ea_val = e68_get_areg32 (c, 7);
247
248 e68_set_areg32 (c, 7, c->ea_val + (size >> 3));
249
250 return (0);
251}
252
253/* -(Ax) */
254static
255int e68_ea_100_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
256{
257 unsigned reg;
258
259 if ((mask & 0x0010) == 0) {
260 e68_exception_illegal (c);
261 return (1);
262 }
263
264 reg = ea & 7;
265
266 c->ea_typ = E68_EA_TYPE_MEM;
267 c->ea_val = e68_get_areg32 (c, reg) - (size >> 3);
268
269 e68_set_areg32 (c, reg, c->ea_val);
270 e68_set_clk (c, 2);
271
272 return (0);
273}
274
275/* -(A7) */
276static
277int e68_ea_100_111 (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
278{
279 if ((mask & 0x0010) == 0) {
280 e68_exception_illegal (c);
281 return (1);
282 }
283
284 if (size == 8) {
285 size = 16;
286 }
287
288 c->ea_typ = E68_EA_TYPE_MEM;
289 c->ea_val = e68_get_areg32 (c, 7) - (size >> 3);
290
291 e68_set_areg32 (c, 7, c->ea_val);
292 e68_set_clk (c, 2);
293
294 return (0);
295}
296
297/* XXXX(Ax) */
298static
299int e68_ea_101_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
300{
301 if ((mask & 0x0020) == 0) {
302 e68_exception_illegal (c);
303 return (1);
304 }
305
306 if (e68_prefetch (c)) {
307 return (1);
308 }
309
310 c->ea_typ = E68_EA_TYPE_MEM;
311 c->ea_val = e68_get_areg32 (c, ea & 7) + e68_exts16 (c->ir[1]);
312
313 e68_set_clk (c, 4);
314
315 return (0);
316}
317
318/* XX(Ax, Rx.S) */
319static
320int e68_ea_110_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
321{
322 uint32_t idx;
323 unsigned scale;
324
325 if ((mask & 0x0040) == 0) {
326 e68_exception_illegal (c);
327 return (1);
328 }
329
330 if (e68_prefetch (c)) {
331 return (1);
332 }
333
334 c->ea_typ = E68_EA_TYPE_MEM;
335 c->ea_val = e68_get_areg32 (c, ea & 7);
336
337 if (c->flags & E68_FLAG_68020) {
338 if (c->ir[1] & 0x0100) {
339 return (e68_ea_full (c, c->ir[1], mask));
340 }
341 else {
342 scale = (c->ir[1] >> 9) & 3;
343 }
344 }
345 else {
346 scale = 0;
347 }
348
349 c->ea_val += e68_exts8 (c->ir[1]);
350
351 if (c->ir[1] & 0x8000) {
352 idx = e68_get_areg32 (c, (c->ir[1] >> 12) & 7);
353 }
354 else {
355 idx = e68_get_dreg32 (c, (c->ir[1] >> 12) & 7);
356 }
357
358 if ((c->ir[1] & 0x0800) == 0) {
359 idx = e68_exts16 (idx);
360 }
361
362 c->ea_val += idx << scale;
363
364 e68_set_clk (c, 6);
365
366 return (0);
367}
368
369/* XXXX */
370static
371int e68_ea_111_000 (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
372{
373 if ((mask & 0x0080) == 0) {
374 e68_exception_illegal (c);
375 return (1);
376 }
377
378 if (e68_prefetch (c)) {
379 return (1);
380 }
381
382 c->ea_typ = E68_EA_TYPE_MEM;
383 c->ea_val = e68_exts16 (c->ir[1]);
384
385 e68_set_clk (c, 4);
386
387 return (0);
388}
389
390/* XXXXXXXX */
391static
392int e68_ea_111_001 (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
393{
394 if ((mask & 0x0100) == 0) {
395 e68_exception_illegal (c);
396 return (1);
397 }
398
399 if (e68_prefetch (c)) {
400 return (1);
401 }
402
403 c->ea_typ = E68_EA_TYPE_MEM;
404 c->ea_val = c->ir[1];
405
406 if (e68_prefetch (c)) {
407 return (1);
408 }
409
410 c->ea_val = (c->ea_val << 16) | c->ir[1];
411
412 e68_set_clk (c, 8);
413
414 return (0);
415}
416
417/* XXXX(PC) */
418static
419int e68_ea_111_010 (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
420{
421 if ((mask & 0x0200) == 0) {
422 e68_exception_illegal (c);
423 return (1);
424 }
425
426 c->ea_typ = E68_EA_TYPE_MEM;
427 c->ea_val = e68_get_ir_pc (c) - 2;
428
429 if (e68_prefetch (c)) {
430 return (1);
431 }
432
433 c->ea_val += e68_exts16 (c->ir[1]);
434
435 e68_set_clk (c, 4);
436
437 return (0);
438}
439
440/* XX(PC, Rx.S) */
441static
442int e68_ea_111_011 (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
443{
444 uint32_t idx;
445 unsigned scale;
446
447 if ((mask & 0x0400) == 0) {
448 e68_exception_illegal (c);
449 return (1);
450 }
451
452 c->ea_typ = E68_EA_TYPE_MEM;
453 c->ea_val = e68_get_ir_pc (c) - 2;
454
455 if (e68_prefetch (c)) {
456 return (1);
457 }
458
459 if (c->flags & E68_FLAG_68020) {
460 if (c->ir[1] & 0x0100) {
461 return (e68_ea_full (c, c->ir[1], mask));
462 }
463 else {
464 scale = (c->ir[1] >> 9) & 3;
465 }
466 }
467 else {
468 scale = 0;
469 }
470
471 c->ea_val += e68_exts8 (c->ir[1]);
472
473 if (c->ir[1] & 0x8000) {
474 idx = e68_get_areg32 (c, (c->ir[1] >> 12) & 7);
475 }
476 else {
477 idx = e68_get_dreg32 (c, (c->ir[1] >> 12) & 7);
478 }
479
480 if ((c->ir[1] & 0x0800) == 0) {
481 idx = e68_exts16 (idx);
482 }
483
484 c->ea_val += idx << scale;
485
486 e68_set_clk (c, 6);
487
488 return (0);
489}
490
491/* #XXXX */
492static
493int e68_ea_111_100 (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
494{
495 if ((mask & 0x0800) == 0) {
496 e68_exception_illegal (c);
497 return (1);
498 }
499
500 if (e68_prefetch (c)) {
501 return (1);
502 }
503
504 c->ea_typ = E68_EA_TYPE_IMM;
505 c->ea_val = c->ir[1];
506
507 if (size == 32) {
508 if (e68_prefetch (c)) {
509 return (1);
510 }
511 c->ea_val = (c->ea_val << 16) | c->ir[1];
512 e68_set_clk (c, 8);
513 }
514 else if (size == 16) {
515 e68_set_clk (c, 4);
516 }
517 else {
518 c->ea_val &= 0xff;
519 e68_set_clk (c, 4);
520 }
521
522 return (0);
523}
524
525static
526int e68_ea_111_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size)
527{
528 e68_exception_illegal (c);
529
530 return (1);
531}
532
533e68_get_ea_ptr_f e68_ea_tab[64] = {
534 e68_ea_000_xxx, e68_ea_000_xxx, e68_ea_000_xxx, e68_ea_000_xxx,
535 e68_ea_000_xxx, e68_ea_000_xxx, e68_ea_000_xxx, e68_ea_000_xxx,
536
537 e68_ea_001_xxx, e68_ea_001_xxx, e68_ea_001_xxx, e68_ea_001_xxx,
538 e68_ea_001_xxx, e68_ea_001_xxx, e68_ea_001_xxx, e68_ea_001_xxx,
539
540 e68_ea_010_xxx, e68_ea_010_xxx, e68_ea_010_xxx, e68_ea_010_xxx,
541 e68_ea_010_xxx, e68_ea_010_xxx, e68_ea_010_xxx, e68_ea_010_xxx,
542
543 e68_ea_011_xxx, e68_ea_011_xxx, e68_ea_011_xxx, e68_ea_011_xxx,
544 e68_ea_011_xxx, e68_ea_011_xxx, e68_ea_011_xxx, e68_ea_011_111,
545
546 e68_ea_100_xxx, e68_ea_100_xxx, e68_ea_100_xxx, e68_ea_100_xxx,
547 e68_ea_100_xxx, e68_ea_100_xxx, e68_ea_100_xxx, e68_ea_100_111,
548
549 e68_ea_101_xxx, e68_ea_101_xxx, e68_ea_101_xxx, e68_ea_101_xxx,
550 e68_ea_101_xxx, e68_ea_101_xxx, e68_ea_101_xxx, e68_ea_101_xxx,
551
552 e68_ea_110_xxx, e68_ea_110_xxx, e68_ea_110_xxx, e68_ea_110_xxx,
553 e68_ea_110_xxx, e68_ea_110_xxx, e68_ea_110_xxx, e68_ea_110_xxx,
554
555 e68_ea_111_000, e68_ea_111_001, e68_ea_111_010, e68_ea_111_011,
556 e68_ea_111_100, e68_ea_111_xxx, e68_ea_111_xxx, e68_ea_111_xxx,
557};
558
559
560int e68_ea_get_val8 (e68000_t *c, uint8_t *val)
561{
562 switch (c->ea_typ) {
563 case E68_EA_TYPE_IMM:
564 *val = c->ea_val & 0xff;
565 return (0);
566
567 case E68_EA_TYPE_REG:
568 if (c->ea_val < 8) {
569 *val = e68_get_dreg8 (c, c->ea_val);
570 }
571 else {
572 e68_exception_illegal (c);
573 return (1);
574 }
575 return (0);
576
577 case E68_EA_TYPE_MEM:
578 *val = e68_get_mem8 (c, c->ea_val);
579 e68_set_clk (c, 4);
580
581 if (c->bus_error) {
582 e68_exception_bus (c, c->ea_val, 1, 0);
583 return (1);
584 }
585
586 return (0);
587 }
588
589 e68_exception_illegal (c);
590
591 return (1);
592}
593
594int e68_ea_get_val16 (e68000_t *c, uint16_t *val)
595{
596 switch (c->ea_typ) {
597 case E68_EA_TYPE_IMM:
598 *val = c->ea_val & 0xffff;
599 return (0);
600
601 case E68_EA_TYPE_REG:
602 if (c->ea_val < 8) {
603 *val = e68_get_dreg16 (c, c->ea_val);
604 }
605 else if (c->ea_val < 16) {
606 *val = e68_get_areg16 (c, c->ea_val - 8);
607 }
608 else {
609 e68_exception_illegal (c);
610 return (1);
611 }
612 return (0);
613
614 case E68_EA_TYPE_MEM:
615 if (c->ea_val & 1) {
616 if ((c->flags & E68_FLAG_NOADDR) == 0) {
617 e68_exception_address (c, c->ea_val, 1, 0);
618 return (1);
619 }
620 }
621
622 *val = e68_get_mem16 (c, c->ea_val);
623 e68_set_clk (c, 4);
624
625 if (c->bus_error) {
626 e68_exception_bus (c, c->ea_val, 1, 0);
627 return (1);
628 }
629
630 return (0);
631 }
632
633 e68_exception_illegal (c);
634
635 return (1);
636}
637
638int e68_ea_get_val32 (e68000_t *c, uint32_t *val)
639{
640 switch (c->ea_typ) {
641 case E68_EA_TYPE_IMM:
642 *val = c->ea_val & 0xffffffff;
643 return (0);
644
645 case E68_EA_TYPE_REG:
646 if (c->ea_val < 8) {
647 *val = e68_get_dreg32 (c, c->ea_val);
648 }
649 else if (c->ea_val < 16) {
650 *val = e68_get_areg32 (c, c->ea_val - 8);
651 }
652 else {
653 e68_exception_illegal (c);
654 return (1);
655 }
656 return (0);
657
658 case E68_EA_TYPE_MEM:
659 if (c->ea_val & 1) {
660 if ((c->flags & E68_FLAG_NOADDR) == 0) {
661 e68_exception_address (c, c->ea_val, 1, 0);
662 return (1);
663 }
664 }
665
666 *val = e68_get_mem32 (c, c->ea_val);
667 e68_set_clk (c, 8);
668
669 if (c->bus_error) {
670 e68_exception_bus (c, c->ea_val, 1, 0);
671 return (1);
672 }
673
674 return (0);
675 }
676
677 e68_exception_illegal (c);
678
679 return (1);
680}
681
682int e68_ea_set_val8 (e68000_t *c, uint8_t val)
683{
684 switch (c->ea_typ) {
685 case E68_EA_TYPE_IMM:
686 e68_exception_illegal (c);
687 return (1);
688
689 case E68_EA_TYPE_REG:
690 if (c->ea_val < 8) {
691 e68_set_dreg8 (c, c->ea_val, val);
692 }
693 else {
694 e68_exception_illegal (c);
695 return (1);
696 }
697 return (0);
698
699 case E68_EA_TYPE_MEM:
700 e68_set_mem8 (c, c->ea_val, val);
701 e68_set_clk (c, 4);
702
703 if (c->bus_error) {
704 e68_exception_bus (c, c->ea_val, 1, 1);
705 return (1);
706 }
707
708 return (0);
709 }
710
711 e68_exception_illegal (c);
712
713 return (1);
714}
715
716int e68_ea_set_val16 (e68000_t *c, uint16_t val)
717{
718 switch (c->ea_typ) {
719 case E68_EA_TYPE_IMM:
720 e68_exception_illegal (c);
721 return (1);
722
723 case E68_EA_TYPE_REG:
724 if (c->ea_val < 8) {
725 e68_set_dreg16 (c, c->ea_val, val);
726 }
727 else if (c->ea_val < 16) {
728 e68_set_areg16 (c, c->ea_val - 8, val);
729 }
730 else {
731 e68_exception_illegal (c);
732 return (1);
733 }
734 return (0);
735
736 case E68_EA_TYPE_MEM:
737 if (c->ea_val & 1) {
738 if ((c->flags & E68_FLAG_NOADDR) == 0) {
739 e68_exception_address (c, c->ea_val, 1, 1);
740 return (1);
741 }
742 }
743
744 e68_set_mem16 (c, c->ea_val, val);
745 e68_set_clk (c, 4);
746
747 if (c->bus_error) {
748 e68_exception_bus (c, c->ea_val, 1, 1);
749 return (1);
750 }
751
752 return (0);
753 }
754
755 e68_exception_illegal (c);
756
757 return (1);
758}
759
760int e68_ea_set_val32 (e68000_t *c, uint32_t val)
761{
762 switch (c->ea_typ) {
763 case E68_EA_TYPE_IMM:
764 e68_exception_illegal (c);
765 return (1);
766
767 case E68_EA_TYPE_REG:
768 if (c->ea_val < 8) {
769 e68_set_dreg32 (c, c->ea_val, val);
770 }
771 else if (c->ea_val < 16) {
772 e68_set_areg32 (c, c->ea_val - 8, val);
773 }
774 else {
775 e68_exception_illegal (c);
776 return (1);
777 }
778 return (0);
779
780 case E68_EA_TYPE_MEM:
781 if (c->ea_val & 1) {
782 if ((c->flags & E68_FLAG_NOADDR) == 0) {
783 e68_exception_address (c, c->ea_val, 1, 1);
784 return (1);
785 }
786 }
787
788 e68_set_mem32 (c, c->ea_val, val);
789 e68_set_clk (c, 8);
790
791 if (c->bus_error) {
792 e68_exception_bus (c, c->ea_val, 1, 1);
793 return (1);
794 }
795
796 return (0);
797 }
798
799 e68_exception_illegal (c);
800
801 return (1);
802}