forked from prirun/p50em
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathea32i.h
114 lines (101 loc) · 3.46 KB
/
ea32i.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#define IMM_EA 0x80000000
static inline ea_t ea32i (ea_t earp, unsigned short inst, unsigned int *immu32, unsigned long long *immu64) {
int tm, sr, br, ring;
unsigned short d;
ea_t ea, ip;
*immu32 = 0xAAAAAAAA;
*immu64 = 0xAAAAAAAAAAAAAAAALL;
tm = (inst >> 5) & 3;
sr = (inst >> 2) & 7;
br = inst & 3;
ring = RP & RINGMASK32;
TRACE(T_EAI, " tm=%d, sr=%d, dr=%d, br=%d\n", tm, sr, (inst >> 7) & 7, br);
switch (tm) {
case 0:
switch (br) {
case 0: /* reg-reg */
*immu32 = getgr32(sr);
return IMM_EA;
case 1:
d = iget16(RP);
RPL++;
if (sr == 0) /* imm type 1 */
*immu32 = d << 16;
else /* imm type 2 */
*(int *)immu32 = *(short *)&d;
return IMM_EA;
case 2:
switch (sr) {
case 0: /* imm type 3 */
d = iget16(RP);
INCRP;
*immu64 = (((long long)(d & 0xFF00)) << 48) | (d & 0xFF);
return IMM_EA;
case 1: /* FAC0 source */
*immu64 = getgr64(FAC0);
return IMM_EA;
case 3: /* FAC1 source */
*immu64 = getgr64(FAC1);
return IMM_EA;
case 2:
case 4:
case 5:
case 6:
case 7:
fault(UIIFAULT, RPL, RP);
fatal("ea32i: return from UII fault!");
default:
fatal("ea32i: sr < 0 or > 7?");
}
fatal("ea32i: case tm=0 br=2 fall-through");
case 3: /* GR relative */
d = iget16(RP);
INCRP;
ea = (getgr32(sr) & 0xFFFF0000) | ((getgr32(sr) + d) & 0xFFFF);
TRACE(T_EAI, " GRR, d=%x, [sr]=%o/%o, ea=%o/%o\n", d, getgr32(sr)>>16, getgr32(sr)&0xFFFF, ea>>16, ea&0xFFFF);
if (ea & 0x80000000)
fault(POINTERFAULT, ea>>16, ea);
return ea | ring;
default:
fatal("ea32i: tm=0, br < 0 or > 3?");
}
fatal("ea32i: tm=0 fall-through");
case 1: /* TM=1: Direct and Indexed */
d = iget16(RP);
INCRP;
if (sr == 0)
ea = (getgr32(BR+br) & 0xFFFF0000) | ((getgr32(BR+br) + d) & 0xFFFF);
else
ea = (getgr32(BR+br) & 0xFFFF0000) | ((getgr32(BR+br) + d + getgr16(sr)) & 0xFFFF);
return ea | ring;
case 2: /* TM=2: Indirect and Indirect Preindexed */
d = iget16(RP);
INCRP;
if (sr == 0)
ea = (getgr32(BR+br) & 0xFFFF0000) | ((getgr32(BR+br) + d) & 0xFFFF);
else
ea = (getgr32(BR+br) & 0xFFFF0000) | ((getgr32(BR+br) + d + getgr16(sr)) & 0xFFFF);
ip = get32(ea | ring);
if (ip & 0x80000000)
fault(POINTERFAULT, ip>>16, ea);
return ip | ring;
case 3: /* TM=3: Indirect and Indirect Postindexed */
TRACE(T_EAI, " TM=3: Indirect [Postindexed]");
d = iget16(RP);
INCRP;
ea = (getgr32(BR+br) & 0xFFFF0000) | ((getgr32(BR+br) + d) & 0xFFFF);
TRACE(T_EAI, " BR[%d]=%o/%o, d=%o, ip ea=%o/%o\n", br, getgr32(BR+br)>>16, getgr32(BR+br)&0xFFFF, d, ea>>16, ea&0xFFFF);
ip = get32(ea | ring);
TRACE(T_EAI, " after indirect, ea=%o/%o\n", ip>>16, ip&0xFFFF);
if (ip & 0x80000000)
fault(POINTERFAULT, ip>>16, ea);
if (sr > 0) {
ip = (ip & 0xFFFF0000) | ((ip + getgr16(sr)) & 0xFFFF);
TRACE(T_EAI, " index by gr%d='%o/%d, ea=%o/%o\n", sr, getgr16(sr), getgr16(sr), ea>>16, ea&0xFFFF);
}
return ip | ring;
default:
fatal("ea32i: tm out of range!");
}
fatal("ea32i: main switch fall through");
}