PCem
view src/x86_ops_mov_seg.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 | 9bc3bcf7c871 |
| children | 8523e78e0e48 |
line source
1 static int opMOV_w_seg_a16(uint32_t fetchdat)
2 {
3 fetch_ea_16(fetchdat);
5 switch (rmdat & 0x38)
6 {
7 case 0x00: /*ES*/
8 seteaw(ES);
9 break;
10 case 0x08: /*CS*/
11 seteaw(CS);
12 break;
13 case 0x18: /*DS*/
14 seteaw(DS);
15 break;
16 case 0x10: /*SS*/
17 seteaw(SS);
18 break;
19 case 0x20: /*FS*/
20 seteaw(FS);
21 break;
22 case 0x28: /*GS*/
23 seteaw(GS);
24 break;
25 }
27 cycles -= ((mod == 3) ? 2 : 3);
28 return 0;
29 }
30 static int opMOV_w_seg_a32(uint32_t fetchdat)
31 {
32 fetch_ea_32(fetchdat);
34 switch (rmdat & 0x38)
35 {
36 case 0x00: /*ES*/
37 seteaw(ES);
38 break;
39 case 0x08: /*CS*/
40 seteaw(CS);
41 break;
42 case 0x18: /*DS*/
43 seteaw(DS);
44 break;
45 case 0x10: /*SS*/
46 seteaw(SS);
47 break;
48 case 0x20: /*FS*/
49 seteaw(FS);
50 break;
51 case 0x28: /*GS*/
52 seteaw(GS);
53 break;
54 }
56 cycles -= ((mod == 3) ? 2 : 3);
57 return 0;
58 }
60 static int opMOV_l_seg_a16(uint32_t fetchdat)
61 {
62 fetch_ea_16(fetchdat);
64 switch (rmdat & 0x38)
65 {
66 case 0x00: /*ES*/
67 if (mod == 3) regs[rm].l = ES;
68 else seteaw(ES);
69 break;
70 case 0x08: /*CS*/
71 if (mod == 3) regs[rm].l = CS;
72 else seteaw(CS);
73 break;
74 case 0x18: /*DS*/
75 if (mod == 3) regs[rm].l = DS;
76 else seteaw(DS);
77 break;
78 case 0x10: /*SS*/
79 if (mod == 3) regs[rm].l = SS;
80 else seteaw(SS);
81 break;
82 case 0x20: /*FS*/
83 if (mod == 3) regs[rm].l = FS;
84 else seteaw(FS);
85 break;
86 case 0x28: /*GS*/
87 if (mod == 3) regs[rm].l = GS;
88 else seteaw(GS);
89 break;
90 }
92 cycles -= ((mod == 3) ? 2 : 3);
93 return 0;
94 }
95 static int opMOV_l_seg_a32(uint32_t fetchdat)
96 {
97 fetch_ea_32(fetchdat);
99 switch (rmdat & 0x38)
100 {
101 case 0x00: /*ES*/
102 if (mod == 3) regs[rm].l = ES;
103 else seteaw(ES);
104 break;
105 case 0x08: /*CS*/
106 if (mod == 3) regs[rm].l = CS;
107 else seteaw(CS);
108 break;
109 case 0x18: /*DS*/
110 if (mod == 3) regs[rm].l = DS;
111 else seteaw(DS);
112 break;
113 case 0x10: /*SS*/
114 if (mod == 3) regs[rm].l = SS;
115 else seteaw(SS);
116 break;
117 case 0x20: /*FS*/
118 if (mod == 3) regs[rm].l = FS;
119 else seteaw(FS);
120 break;
121 case 0x28: /*GS*/
122 if (mod == 3) regs[rm].l = GS;
123 else seteaw(GS);
124 break;
125 }
127 cycles -= ((mod == 3) ? 2 : 3);
128 return 0;
129 }
131 static int opMOV_seg_w_a16(uint32_t fetchdat)
132 {
133 uint16_t new_seg;
135 fetch_ea_16(fetchdat);
137 new_seg=geteaw(); if (abrt) return 0;
139 switch (rmdat & 0x38)
140 {
141 case 0x00: /*ES*/
142 loadseg(new_seg, &_es);
143 break;
144 case 0x18: /*DS*/
145 loadseg(new_seg, &_ds);
146 break;
147 case 0x10: /*SS*/
148 loadseg(new_seg, &_ss);
149 op32 = use32;
150 return 1;
151 case 0x20: /*FS*/
152 loadseg(new_seg, &_fs);
153 break;
154 case 0x28: /*GS*/
155 loadseg(new_seg, &_gs);
156 break;
157 }
159 cycles -= ((mod == 3) ? 2 : 5);
160 return 0;
161 }
162 static int opMOV_seg_w_a32(uint32_t fetchdat)
163 {
164 uint16_t new_seg;
166 fetch_ea_32(fetchdat);
168 new_seg=geteaw(); if (abrt) return 0;
170 switch (rmdat & 0x38)
171 {
172 case 0x00: /*ES*/
173 loadseg(new_seg, &_es);
174 break;
175 case 0x18: /*DS*/
176 loadseg(new_seg, &_ds);
177 break;
178 case 0x10: /*SS*/
179 loadseg(new_seg, &_ss);
180 op32 = use32;
181 return 1;
182 case 0x20: /*FS*/
183 loadseg(new_seg, &_fs);
184 break;
185 case 0x28: /*GS*/
186 loadseg(new_seg, &_gs);
187 break;
188 }
190 cycles -= ((mod == 3) ? 2 : 5);
191 return 0;
192 }
195 static int opLDS_w_a16(uint32_t fetchdat)
196 {
197 uint16_t addr, seg;
199 fetch_ea_16(fetchdat);
200 ILLEGAL_ON(mod == 3);
201 addr = readmemw(easeg, eaaddr);
202 seg = readmemw(easeg, eaaddr + 2); if (abrt) return 0;
203 loadseg(seg, &_ds); if (abrt) return 0;
204 regs[reg].w = addr;
206 cycles -= 7;
207 return 0;
208 }
209 static int opLDS_w_a32(uint32_t fetchdat)
210 {
211 uint16_t addr, seg;
213 fetch_ea_32(fetchdat);
214 ILLEGAL_ON(mod == 3);
215 addr = readmemw(easeg, eaaddr);
216 seg = readmemw(easeg, eaaddr + 2); if (abrt) return 0;
217 loadseg(seg, &_ds); if (abrt) return 0;
218 regs[reg].w = addr;
220 cycles -= 7;
221 return 0;
222 }
223 static int opLDS_l_a16(uint32_t fetchdat)
224 {
225 uint32_t addr;
226 uint16_t seg;
228 fetch_ea_16(fetchdat);
229 ILLEGAL_ON(mod == 3);
230 addr = readmeml(easeg, eaaddr);
231 seg = readmemw(easeg, eaaddr + 4); if (abrt) return 0;
232 loadseg(seg, &_ds); if (abrt) return 0;
233 regs[reg].l = addr;
235 cycles -= 7;
236 return 0;
237 }
238 static int opLDS_l_a32(uint32_t fetchdat)
239 {
240 uint32_t addr;
241 uint16_t seg;
243 fetch_ea_32(fetchdat);
244 ILLEGAL_ON(mod == 3);
245 addr = readmeml(easeg, eaaddr);
246 seg = readmemw(easeg, eaaddr + 4); if (abrt) return 0;
247 loadseg(seg, &_ds); if (abrt) return 0;
248 regs[reg].l = addr;
250 cycles -= 7;
251 return 0;
252 }
254 static int opLSS_w_a16(uint32_t fetchdat)
255 {
256 uint16_t addr, seg;
258 fetch_ea_16(fetchdat);
259 ILLEGAL_ON(mod == 3);
260 addr = readmemw(easeg, eaaddr);
261 seg = readmemw(easeg, eaaddr + 2); if (abrt) return 0;
262 loadseg(seg, &_ss); if (abrt) return 0;
263 regs[reg].w = addr;
264 oldss = ss;
266 cycles -= 7;
267 return 0;
268 }
269 static int opLSS_w_a32(uint32_t fetchdat)
270 {
271 uint16_t addr, seg;
273 fetch_ea_32(fetchdat);
274 ILLEGAL_ON(mod == 3);
275 addr = readmemw(easeg, eaaddr);
276 seg = readmemw(easeg, eaaddr + 2); if (abrt) return 0;
277 loadseg(seg, &_ss); if (abrt) return 0;
278 regs[reg].w = addr;
279 oldss = ss;
281 cycles -= 7;
282 return 0;
283 }
284 static int opLSS_l_a16(uint32_t fetchdat)
285 {
286 uint32_t addr;
287 uint16_t seg;
289 fetch_ea_16(fetchdat);
290 ILLEGAL_ON(mod == 3);
291 addr = readmeml(easeg, eaaddr);
292 seg = readmemw(easeg, eaaddr + 4); if (abrt) return 0;
293 loadseg(seg, &_ss); if (abrt) return 0;
294 regs[reg].l = addr;
295 oldss = ss;
297 cycles -= 7;
298 return 0;
299 }
300 static int opLSS_l_a32(uint32_t fetchdat)
301 {
302 uint32_t addr;
303 uint16_t seg;
305 fetch_ea_32(fetchdat);
306 ILLEGAL_ON(mod == 3);
307 addr = readmeml(easeg, eaaddr);
308 seg = readmemw(easeg, eaaddr + 4); if (abrt) return 0;
309 loadseg(seg, &_ss); if (abrt) return 0;
310 regs[reg].l = addr;
311 oldss = ss;
313 cycles -= 7;
314 return 0;
315 }
317 #define opLsel(name, sel) \
318 static int opL ## name ## _w_a16(uint32_t fetchdat) \
319 { \
320 uint16_t addr, seg; \
321 \
322 fetch_ea_16(fetchdat); \
323 ILLEGAL_ON(mod == 3); \
324 addr = readmemw(easeg, eaaddr); \
325 seg = readmemw(easeg, eaaddr + 2); if (abrt) return 0; \
326 loadseg(seg, &sel); if (abrt) return 0; \
327 regs[reg].w = addr; \
328 \
329 cycles -= 7; \
330 return 0; \
331 } \
332 \
333 static int opL ## name ## _w_a32(uint32_t fetchdat) \
334 { \
335 uint16_t addr, seg; \
336 \
337 fetch_ea_32(fetchdat); \
338 ILLEGAL_ON(mod == 3); \
339 addr = readmemw(easeg, eaaddr); \
340 seg = readmemw(easeg, eaaddr + 2); if (abrt) return 0; \
341 loadseg(seg, &sel); if (abrt) return 0; \
342 regs[reg].w = addr; \
343 \
344 cycles -= 7; \
345 return 0; \
346 } \
347 \
348 static int opL ## name ## _l_a16(uint32_t fetchdat) \
349 { \
350 uint32_t addr; \
351 uint16_t seg; \
352 \
353 fetch_ea_16(fetchdat); \
354 ILLEGAL_ON(mod == 3); \
355 addr = readmeml(easeg, eaaddr); \
356 seg = readmemw(easeg, eaaddr + 4); if (abrt) return 0; \
357 loadseg(seg, &sel); if (abrt) return 0; \
358 regs[reg].l = addr; \
359 \
360 cycles -= 7; \
361 return 0; \
362 } \
363 \
364 static int opL ## name ## _l_a32(uint32_t fetchdat) \
365 { \
366 uint32_t addr; \
367 uint16_t seg; \
368 \
369 fetch_ea_32(fetchdat); \
370 ILLEGAL_ON(mod == 3); \
371 addr = readmeml(easeg, eaaddr); \
372 seg = readmemw(easeg, eaaddr + 4); if (abrt) return 0; \
373 loadseg(seg, &sel); if (abrt) return 0; \
374 regs[reg].l = addr; \
375 \
376 cycles -= 7; \
377 return 0; \
378 }
380 opLsel(ES, _es)
381 opLsel(FS, _fs)
382 opLsel(GS, _gs)
