PCem
view src/x86_ops_ret.h @ 142:bd46c39a78e8
Implemented selector limits on some instructions - fixes LBA2.
GPFs in real mode now work.
Selectors correctly zeroed on far return to lower privilege.
| author | TomW |
|---|---|
| date | Wed Aug 13 20:33:56 2014 +0100 |
| parents | 64fa8cf6ba95 |
| children |
line source
1 #define RETF_a16(stack_offset) \
2 if ((msw&1) && !(eflags&VM_FLAG)) \
3 { \
4 pmoderetf(0, stack_offset); \
5 return 0; \
6 } \
7 oxpc = pc; \
8 if (stack32) \
9 { \
10 pc = readmemw(ss, ESP); \
11 loadcs(readmemw(ss, ESP + 2)); \
12 } \
13 else \
14 { \
15 pc = readmemw(ss, SP); \
16 loadcs(readmemw(ss, SP + 2)); \
17 } \
18 if (abrt) return 0; \
19 if (stack32) ESP += 4 + stack_offset; \
20 else SP += 4 + stack_offset; \
21 cycles -= is486 ? 13 : 18;
23 #define RETF_a32(stack_offset) \
24 if ((msw&1) && !(eflags&VM_FLAG)) \
25 { \
26 pmoderetf(1, stack_offset); \
27 return 0; \
28 } \
29 oxpc = pc; \
30 if (stack32) \
31 { \
32 pc = readmeml(ss, ESP); \
33 loadcs(readmeml(ss, ESP + 4) & 0xffff); \
34 } \
35 else \
36 { \
37 pc = readmeml(ss, SP); \
38 loadcs(readmeml(ss, SP + 4) & 0xffff); \
39 } \
40 if (abrt) return 0; \
41 if (stack32) ESP += 8 + stack_offset; \
42 else SP += 8 + stack_offset; \
43 cycles -= is486 ? 13 : 18;
45 static int opRETF_a16(uint32_t fetchdat)
46 {
47 RETF_a16(0);
48 return 0;
49 }
50 static int opRETF_a32(uint32_t fetchdat)
51 {
52 RETF_a32(0);
53 return 0;
54 }
56 static int opRETF_a16_imm(uint32_t fetchdat)
57 {
58 uint16_t offset = getwordf();
59 RETF_a16(offset);
60 return 0;
61 }
62 static int opRETF_a32_imm(uint32_t fetchdat)
63 {
64 uint16_t offset = getwordf();
65 RETF_a32(offset);
66 return 0;
67 }
69 static int opIRET_286(uint32_t fetchdat)
70 {
71 if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
72 {
73 x86gpf(NULL,0);
74 return 0;
75 }
76 if (msw&1)
77 {
78 optype = IRET;
79 pmodeiret(0);
80 optype = 0;
81 }
82 else
83 {
84 uint16_t new_cs;
85 oxpc = pc;
86 if (stack32)
87 {
88 pc = readmemw(ss, ESP);
89 new_cs = readmemw(ss, ESP + 2);
90 flags = (flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2;
91 ESP += 6;
92 }
93 else
94 {
95 pc = readmemw(ss, SP);
96 new_cs = readmemw(ss, ((SP + 2) & 0xffff));
97 flags = (flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2;
98 SP += 6;
99 }
100 loadcs(new_cs);
101 }
102 flags_extract();
103 cycles -= is486 ? 15 : 22;
104 nmi_enable = 1;
105 return 0;
106 }
108 static int opIRET(uint32_t fetchdat)
109 {
110 if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
111 {
112 x86gpf(NULL,0);
113 return 0;
114 }
115 if (msw&1)
116 {
117 optype = IRET;
118 pmodeiret(0);
119 optype = 0;
120 }
121 else
122 {
123 uint16_t new_cs;
124 oxpc = pc;
125 if (stack32)
126 {
127 pc = readmemw(ss, ESP);
128 new_cs = readmemw(ss, ESP + 2);
129 flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2;
130 ESP += 6;
131 }
132 else
133 {
134 pc = readmemw(ss, SP);
135 new_cs = readmemw(ss, ((SP + 2) & 0xffff));
136 flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2;
137 SP += 6;
138 }
139 loadcs(new_cs);
140 }
141 flags_extract();
142 cycles -= is486 ? 15 : 22;
143 nmi_enable = 1;
144 return 0;
145 }
147 static int opIRETD(uint32_t fetchdat)
148 {
149 if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
150 {
151 x86gpf(NULL,0);
152 return 0;
153 }
154 if (msw & 1)
155 {
156 optype = IRET;
157 pmodeiret(1);
158 optype = 0;
159 }
160 else
161 {
162 uint16_t new_cs;
163 oxpc = pc;
164 if (stack32)
165 {
166 pc = readmeml(ss, ESP);
167 new_cs = readmemw(ss, ESP + 4);
168 flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2;
169 eflags = readmemw(ss, ESP + 10);
170 ESP += 12;
171 }
172 else
173 {
174 pc = readmeml(ss, SP);
175 new_cs = readmemw(ss, ((SP + 4) & 0xffff));
176 flags = (readmemw(ss,(SP + 8) & 0xffff) & 0xffd5) | 2;
177 eflags = readmemw(ss, (SP + 10) & 0xffff);
178 SP += 12;
179 }
180 loadcs(new_cs);
181 }
182 flags_extract();
183 cycles -= is486 ? 15 : 22;
184 nmi_enable = 1;
185 return 0;
186 }
