Commit | Line | Data |
---|---|---|
196ba1fc PH |
1 | /*\r |
2 | * Dos/PC Emulator\r | |
3 | * Copyright (C) 1991 Jim Hudgens\r | |
4 | *\r | |
5 | *\r | |
6 | * The file is part of GDE.\r | |
7 | *\r | |
8 | * GDE is free software; you can redistribute it and/or modify\r | |
9 | * it under the terms of the GNU General Public License as published by\r | |
10 | * the Free Software Foundation; either version 1, or (at your option)\r | |
11 | * any later version.\r | |
12 | *\r | |
13 | * GDE is distributed in the hope that it will be useful,\r | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of\r | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r | |
16 | * GNU General Public License for more details.\r | |
17 | *\r | |
18 | * You should have received a copy of the GNU General Public License\r | |
19 | * along with GDE; see the file COPYING. If not, write to\r | |
20 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\r | |
21 | *\r | |
22 | */\r | |
23 | \r | |
24 | #include "altairz80_defs.h"\r | |
25 | #include "i86.h"\r | |
26 | \r | |
27 | extern uint32 GetBYTEExtended(register uint32 Addr);\r | |
28 | extern void PutBYTEExtended(register uint32 Addr, const register uint32 Value);\r | |
29 | extern char messageBuffer[];\r | |
30 | extern void printMessage(void);\r | |
31 | extern int32 AX_S; /* AX register (8086) */\r | |
32 | extern int32 BX_S; /* BX register (8086) */\r | |
33 | extern int32 CX_S; /* CX register (8086) */\r | |
34 | extern int32 DX_S; /* DX register (8086) */\r | |
35 | extern int32 CS_S; /* CS register (8086) */\r | |
36 | extern int32 DS_S; /* DS register (8086) */\r | |
37 | extern int32 ES_S; /* ES register (8086) */\r | |
38 | extern int32 SS_S; /* SS register (8086) */\r | |
39 | extern int32 DI_S; /* DI register (8086) */\r | |
40 | extern int32 SI_S; /* SI register (8086) */\r | |
41 | extern int32 BP_S; /* BP register (8086) */\r | |
42 | extern int32 SP8086_S; /* SP register (8086) */\r | |
43 | extern int32 IP_S; /* IP register (8086) */\r | |
44 | extern int32 FLAGS_S; /* flags register (8086) */\r | |
45 | extern int32 PC_S; /* PC register (8080/Z80/8086), 20 bit */\r | |
46 | extern int32 sim_interval;\r | |
47 | extern uint32 PCX; /* external view of PC */\r | |
48 | extern uint32 sim_brk_summ;\r | |
49 | extern UNIT cpu_unit;\r | |
50 | \r | |
51 | void i86_intr_raise(PC_ENV *m,uint8 intrnum);\r | |
52 | void cpu8086reset(void);\r | |
53 | t_stat sim_instr_8086(void);\r | |
54 | \r | |
55 | /* $Log: $\r | |
56 | * Revision 0.05 1992/04/12 23:16:42 hudgens\r | |
57 | * Many changes. Added support for the QUICK_FETCH option,\r | |
58 | * so that memory accesses are faster. Now compiles with gcc -Wall\r | |
59 | * and gcc -traditional and Sun cc.\r | |
60 | *\r | |
61 | * Revision 0.04 1991/07/30 01:59:56 hudgens\r | |
62 | * added copyright.\r | |
63 | *\r | |
64 | * Revision 0.03 1991/06/03 01:02:09 hudgens\r | |
65 | * fixed minor problems due to unsigned to signed short integer\r | |
66 | * promotions.\r | |
67 | *\r | |
68 | * Revision 0.02 1991/03/31 01:29:39 hudgens\r | |
69 | * Fixed segment handling (overrides, default segment accessed) in\r | |
70 | * routines decode_rmXX_address and the {fetch,store}_data_{byte,word}.\r | |
71 | *\r | |
72 | * Revision 0.01 1991/03/30 21:59:49 hudgens\r | |
73 | * Initial checkin.\r | |
74 | *\r | |
75 | *\r | |
76 | */\r | |
77 | \r | |
78 | /* this file includes subroutines which do:\r | |
79 | stuff involving decoding instruction formats.\r | |
80 | stuff involving accessess of immediate data via IP.\r | |
81 | etc.\r | |
82 | */\r | |
83 | \r | |
84 | static void i86_intr_handle(PC_ENV *m)\r | |
85 | { uint16 tmp;\r | |
86 | uint8 intno;\r | |
87 | if (intr & INTR_SYNCH) /* raised by something */\r | |
88 | {\r | |
89 | intno = m->intno;\r | |
90 | tmp = (uint16) mem_access_word(m, intno * 4);\r | |
91 | {\r | |
92 | tmp = m->R_FLG;\r | |
93 | push_word(m, tmp);\r | |
94 | CLEAR_FLAG(m, F_IF);\r | |
95 | CLEAR_FLAG(m, F_TF);\r | |
96 | /* [JCE] If we're interrupting between a segment override (or REP override)\r | |
97 | * and the following instruction, decrease IP to get back to the prefix */\r | |
98 | if (m->sysmode & (SYSMODE_SEGMASK | SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))\r | |
99 | {\r | |
100 | --m->R_IP;\r | |
101 | }\r | |
102 | /* [JCE] CS and IP were the wrong way round... */\r | |
103 | push_word(m, m->R_CS);\r | |
104 | push_word(m, m->R_IP);\r | |
105 | tmp = mem_access_word(m, intno * 4);\r | |
106 | m->R_IP = tmp;\r | |
107 | tmp = mem_access_word(m, intno * 4 + 2);\r | |
108 | m->R_CS = tmp;\r | |
109 | }\r | |
110 | intr &= ~INTR_SYNCH; /* [JCE] Dealt with, reset flag */\r | |
111 | }\r | |
112 | /* The interrupt code can't pick up the segment override status. */\r | |
113 | DECODE_CLEAR_SEGOVR(m);\r | |
114 | }\r | |
115 | \r | |
116 | void i86_intr_raise(PC_ENV *m,uint8 intrnum)\r | |
117 | {\r | |
118 | m->intno = intrnum;\r | |
119 | intr |= INTR_SYNCH;\r | |
120 | }\r | |
121 | \r | |
122 | static PC_ENV cpu8086;\r | |
123 | \r | |
124 | static void setViewRegisters(void) {\r | |
125 | FLAGS_S = cpu8086.R_FLG;\r | |
126 | AX_S = cpu8086.R_AX;\r | |
127 | BX_S = cpu8086.R_BX;\r | |
128 | CX_S = cpu8086.R_CX;\r | |
129 | DX_S = cpu8086.R_DX;\r | |
130 | SP8086_S = cpu8086.R_SP;\r | |
131 | BP_S = cpu8086.R_BP;\r | |
132 | SI_S = cpu8086.R_SI;\r | |
133 | DI_S = cpu8086.R_DI;\r | |
134 | ES_S = cpu8086.R_ES;\r | |
135 | CS_S = cpu8086.R_CS;\r | |
136 | SS_S = cpu8086.R_SS;\r | |
137 | DS_S = cpu8086.R_DS;\r | |
138 | IP_S = cpu8086.R_IP;\r | |
139 | }\r | |
140 | \r | |
141 | static void setCPURegisters(void) {\r | |
142 | cpu8086.R_FLG = FLAGS_S;\r | |
143 | cpu8086.R_AX = AX_S;\r | |
144 | cpu8086.R_BX = BX_S;\r | |
145 | cpu8086.R_CX = CX_S;\r | |
146 | cpu8086.R_DX = DX_S;\r | |
147 | cpu8086.R_SP = SP8086_S;\r | |
148 | cpu8086.R_BP = BP_S;\r | |
149 | cpu8086.R_SI = SI_S;\r | |
150 | cpu8086.R_DI = DI_S;\r | |
151 | cpu8086.R_ES = ES_S;\r | |
152 | cpu8086.R_CS = CS_S;\r | |
153 | cpu8086.R_SS = SS_S;\r | |
154 | cpu8086.R_DS = DS_S;\r | |
155 | cpu8086.R_IP = IP_S;\r | |
156 | }\r | |
157 | \r | |
158 | void cpu8086reset(void) {\r | |
159 | cpu8086.R_AX = 0x1961;\r | |
160 | if ((cpu8086.R_AH != 0x19) || (cpu8086.R_AL != 0x61)) {\r | |
161 | printf("Fatal endian error - make sure to compile with '#define LOWFIRST %i'\n", 1 - LOWFIRST);\r | |
162 | exit(1);\r | |
163 | }\r | |
164 | /* 16 bit registers */\r | |
165 | cpu8086.R_AX = 0;\r | |
166 | cpu8086.R_BX = 0;\r | |
167 | cpu8086.R_CX = 0;\r | |
168 | cpu8086.R_DX = 0;\r | |
169 | /* special registers */\r | |
170 | cpu8086.R_SP = 0;\r | |
171 | cpu8086.R_BP = 0;\r | |
172 | cpu8086.R_SI = 0;\r | |
173 | cpu8086.R_DI = 0;\r | |
174 | cpu8086.R_IP = 0;\r | |
175 | cpu8086.R_FLG = F_ALWAYS_ON;\r | |
176 | /* segment registers */\r | |
177 | cpu8086.R_CS = 0;\r | |
178 | cpu8086.R_DS = 0;\r | |
179 | cpu8086.R_SS = 0;\r | |
180 | cpu8086.R_ES = 0;\r | |
181 | setViewRegisters();\r | |
182 | }\r | |
183 | \r | |
184 | static uint32 getFullPC(void) {\r | |
185 | return cpu8086.R_IP + (cpu8086.R_CS << 4);\r | |
186 | }\r | |
187 | \r | |
188 | t_stat sim_instr_8086(void) {\r | |
189 | t_stat reason = SCPE_OK;\r | |
190 | uint8 op1;\r | |
191 | int32 newIP;\r | |
192 | setCPURegisters();\r | |
193 | intr = 0;\r | |
194 | newIP = PC_S - 16 * CS_S;\r | |
195 | if ((0 <= newIP) && (newIP <= 0xffff)) cpu8086.R_IP = newIP;\r | |
196 | else {\r | |
197 | if (CS_S != ((PC_S & 0xf0000) >> 4)) {\r | |
198 | cpu8086.R_CS = (PC_S & 0xf0000) >> 4;\r | |
199 | if (cpu_unit.flags & UNIT_CPU_VERBOSE) {\r | |
200 | MESSAGE_2("Segment register CS set to %04x", cpu8086.R_CS);\r | |
201 | }\r | |
202 | }\r | |
203 | cpu8086.R_IP = PC_S & 0xffff;\r | |
204 | }\r | |
205 | while (TRUE) { /* loop until halted */\r | |
206 | if (sim_interval <= 0) { /* check clock queue */\r | |
207 | #if !UNIX_PLATFORM\r | |
208 | if ((reason = sim_os_poll_kbd()) == SCPE_STOP) /* poll on platforms without reliable signalling */\r | |
209 | break;\r | |
210 | #endif\r | |
211 | if ( (reason = sim_process_event()) ) break;\r | |
212 | }\r | |
213 | if (sim_brk_summ && sim_brk_test(getFullPC(), SWMASK('E'))) { /* breakpoint? */\r | |
214 | reason = STOP_IBKPT; /* stop simulation */\r | |
215 | break;\r | |
216 | }\r | |
217 | PCX = getFullPC();\r | |
218 | op1 = GetBYTEExtended((((uint32)cpu8086.R_CS<<4) + cpu8086.R_IP) & 0xFFFFF);\r | |
219 | if (sim_brk_summ && sim_brk_test(op1, (1u << SIM_BKPT_V_SPC) | SWMASK('I'))) { /* instruction breakpoint? */\r | |
220 | reason = STOP_IBKPT; /* stop simulation */\r | |
221 | break;\r | |
222 | }\r | |
223 | sim_interval--;\r | |
224 | cpu8086.R_IP++;\r | |
225 | (*(i86_optab[op1]))(&cpu8086);\r | |
226 | if (intr & INTR_HALTED) {\r | |
227 | reason = STOP_HALT;\r | |
228 | intr &= ~INTR_HALTED;\r | |
229 | break;\r | |
230 | }\r | |
231 | if (intr & INTR_ILLEGAL_OPCODE) {\r | |
232 | intr &= ~INTR_ILLEGAL_OPCODE;\r | |
233 | if (cpu_unit.flags & UNIT_CPU_OPSTOP) {\r | |
234 | reason = STOP_OPCODE;\r | |
235 | break;\r | |
236 | }\r | |
237 | }\r | |
238 | if (((intr & INTR_SYNCH) && (cpu8086.intno == 0 || cpu8086.intno == 2)) ||\r | |
239 | (ACCESS_FLAG(&cpu8086, F_IF))) {\r | |
240 | /* [JCE] Reversed the sense of this ACCESS_FLAG; it's set for interrupts\r | |
241 | enabled, not interrupts blocked i.e. either not blockable (intr 0 or 2)\r | |
242 | or the IF flag not set so interrupts not blocked */\r | |
243 | /* hharte: if a segment override exists, then treat that as "atomic" and do not handle\r | |
244 | * an interrupt until the override is cleared.\r | |
245 | * Not sure if this is the way an 8086 really works, need to find out for sure.\r | |
246 | * Also, what about the REPE prefix?\r | |
247 | */\r | |
248 | if((cpu8086.sysmode & SYSMODE_SEGMASK) == 0) {\r | |
249 | i86_intr_handle(&cpu8086);\r | |
250 | }\r | |
251 | }\r | |
252 | }\r | |
253 | PC_S = (reason == STOP_HALT) | (reason == STOP_OPCODE) ? PCX : getFullPC();\r | |
254 | setViewRegisters();\r | |
255 | return reason;\r | |
256 | }\r | |
257 | \r | |
258 | void halt_sys(PC_ENV *m)\r | |
259 | {\r | |
260 | intr |= INTR_HALTED;\r | |
261 | }\r | |
262 | \r | |
263 | /* once the instruction is fetched, an optional byte follows which\r | |
264 | has 3 fields encoded in it. This routine fetches the byte\r | |
265 | and breaks into the three fields.\r | |
266 | This has been changed, in an attempt to reduce the amount of\r | |
267 | executed code for this frequently executed subroutine. If this\r | |
268 | works, then it may pay to somehow inline it.\r | |
269 | */\r | |
270 | \r | |
271 | #ifdef NOTDEF\r | |
272 | /* this code generated the following table */\r | |
273 | main()\r | |
274 | { int i;\r | |
275 | printf("\n\nstruct modrm{ uint8 mod,rh,rl;} modrmtab[] = {\n");\r | |
276 | for (i=0; i<256; i++)\r | |
277 | {\r | |
278 | printf("{%d,%d,%d}, ",((i&0xc0)>>6),((i&0x38)>>3),(i&0x07));\r | |
279 | if (i%4==3)\r | |
280 | printf("/* %d to %d */\n",i&0xfc,i);\r | |
281 | }\r | |
282 | printf("};\n\n");\r | |
283 | }\r | |
284 | #endif\r | |
285 | \r | |
286 | struct modrm { uint16 mod, rh, rl; };\r | |
287 | static struct modrm modrmtab[] = {\r | |
288 | {0,0,0}, {0,0,1}, {0,0,2}, {0,0,3}, /* 0 to 3 */\r | |
289 | {0,0,4}, {0,0,5}, {0,0,6}, {0,0,7}, /* 4 to 7 */\r | |
290 | {0,1,0}, {0,1,1}, {0,1,2}, {0,1,3}, /* 8 to 11 */\r | |
291 | {0,1,4}, {0,1,5}, {0,1,6}, {0,1,7}, /* 12 to 15 */\r | |
292 | {0,2,0}, {0,2,1}, {0,2,2}, {0,2,3}, /* 16 to 19 */\r | |
293 | {0,2,4}, {0,2,5}, {0,2,6}, {0,2,7}, /* 20 to 23 */\r | |
294 | {0,3,0}, {0,3,1}, {0,3,2}, {0,3,3}, /* 24 to 27 */\r | |
295 | {0,3,4}, {0,3,5}, {0,3,6}, {0,3,7}, /* 28 to 31 */\r | |
296 | {0,4,0}, {0,4,1}, {0,4,2}, {0,4,3}, /* 32 to 35 */\r | |
297 | {0,4,4}, {0,4,5}, {0,4,6}, {0,4,7}, /* 36 to 39 */\r | |
298 | {0,5,0}, {0,5,1}, {0,5,2}, {0,5,3}, /* 40 to 43 */\r | |
299 | {0,5,4}, {0,5,5}, {0,5,6}, {0,5,7}, /* 44 to 47 */\r | |
300 | {0,6,0}, {0,6,1}, {0,6,2}, {0,6,3}, /* 48 to 51 */\r | |
301 | {0,6,4}, {0,6,5}, {0,6,6}, {0,6,7}, /* 52 to 55 */\r | |
302 | {0,7,0}, {0,7,1}, {0,7,2}, {0,7,3}, /* 56 to 59 */\r | |
303 | {0,7,4}, {0,7,5}, {0,7,6}, {0,7,7}, /* 60 to 63 */\r | |
304 | {1,0,0}, {1,0,1}, {1,0,2}, {1,0,3}, /* 64 to 67 */\r | |
305 | {1,0,4}, {1,0,5}, {1,0,6}, {1,0,7}, /* 68 to 71 */\r | |
306 | {1,1,0}, {1,1,1}, {1,1,2}, {1,1,3}, /* 72 to 75 */\r | |
307 | {1,1,4}, {1,1,5}, {1,1,6}, {1,1,7}, /* 76 to 79 */\r | |
308 | {1,2,0}, {1,2,1}, {1,2,2}, {1,2,3}, /* 80 to 83 */\r | |
309 | {1,2,4}, {1,2,5}, {1,2,6}, {1,2,7}, /* 84 to 87 */\r | |
310 | {1,3,0}, {1,3,1}, {1,3,2}, {1,3,3}, /* 88 to 91 */\r | |
311 | {1,3,4}, {1,3,5}, {1,3,6}, {1,3,7}, /* 92 to 95 */\r | |
312 | {1,4,0}, {1,4,1}, {1,4,2}, {1,4,3}, /* 96 to 99 */\r | |
313 | {1,4,4}, {1,4,5}, {1,4,6}, {1,4,7}, /* 100 to 103 */\r | |
314 | {1,5,0}, {1,5,1}, {1,5,2}, {1,5,3}, /* 104 to 107 */\r | |
315 | {1,5,4}, {1,5,5}, {1,5,6}, {1,5,7}, /* 108 to 111 */\r | |
316 | {1,6,0}, {1,6,1}, {1,6,2}, {1,6,3}, /* 112 to 115 */\r | |
317 | {1,6,4}, {1,6,5}, {1,6,6}, {1,6,7}, /* 116 to 119 */\r | |
318 | {1,7,0}, {1,7,1}, {1,7,2}, {1,7,3}, /* 120 to 123 */\r | |
319 | {1,7,4}, {1,7,5}, {1,7,6}, {1,7,7}, /* 124 to 127 */\r | |
320 | {2,0,0}, {2,0,1}, {2,0,2}, {2,0,3}, /* 128 to 131 */\r | |
321 | {2,0,4}, {2,0,5}, {2,0,6}, {2,0,7}, /* 132 to 135 */\r | |
322 | {2,1,0}, {2,1,1}, {2,1,2}, {2,1,3}, /* 136 to 139 */\r | |
323 | {2,1,4}, {2,1,5}, {2,1,6}, {2,1,7}, /* 140 to 143 */\r | |
324 | {2,2,0}, {2,2,1}, {2,2,2}, {2,2,3}, /* 144 to 147 */\r | |
325 | {2,2,4}, {2,2,5}, {2,2,6}, {2,2,7}, /* 148 to 151 */\r | |
326 | {2,3,0}, {2,3,1}, {2,3,2}, {2,3,3}, /* 152 to 155 */\r | |
327 | {2,3,4}, {2,3,5}, {2,3,6}, {2,3,7}, /* 156 to 159 */\r | |
328 | {2,4,0}, {2,4,1}, {2,4,2}, {2,4,3}, /* 160 to 163 */\r | |
329 | {2,4,4}, {2,4,5}, {2,4,6}, {2,4,7}, /* 164 to 167 */\r | |
330 | {2,5,0}, {2,5,1}, {2,5,2}, {2,5,3}, /* 168 to 171 */\r | |
331 | {2,5,4}, {2,5,5}, {2,5,6}, {2,5,7}, /* 172 to 175 */\r | |
332 | {2,6,0}, {2,6,1}, {2,6,2}, {2,6,3}, /* 176 to 179 */\r | |
333 | {2,6,4}, {2,6,5}, {2,6,6}, {2,6,7}, /* 180 to 183 */\r | |
334 | {2,7,0}, {2,7,1}, {2,7,2}, {2,7,3}, /* 184 to 187 */\r | |
335 | {2,7,4}, {2,7,5}, {2,7,6}, {2,7,7}, /* 188 to 191 */\r | |
336 | {3,0,0}, {3,0,1}, {3,0,2}, {3,0,3}, /* 192 to 195 */\r | |
337 | {3,0,4}, {3,0,5}, {3,0,6}, {3,0,7}, /* 196 to 199 */\r | |
338 | {3,1,0}, {3,1,1}, {3,1,2}, {3,1,3}, /* 200 to 203 */\r | |
339 | {3,1,4}, {3,1,5}, {3,1,6}, {3,1,7}, /* 204 to 207 */\r | |
340 | {3,2,0}, {3,2,1}, {3,2,2}, {3,2,3}, /* 208 to 211 */\r | |
341 | {3,2,4}, {3,2,5}, {3,2,6}, {3,2,7}, /* 212 to 215 */\r | |
342 | {3,3,0}, {3,3,1}, {3,3,2}, {3,3,3}, /* 216 to 219 */\r | |
343 | {3,3,4}, {3,3,5}, {3,3,6}, {3,3,7}, /* 220 to 223 */\r | |
344 | {3,4,0}, {3,4,1}, {3,4,2}, {3,4,3}, /* 224 to 227 */\r | |
345 | {3,4,4}, {3,4,5}, {3,4,6}, {3,4,7}, /* 228 to 231 */\r | |
346 | {3,5,0}, {3,5,1}, {3,5,2}, {3,5,3}, /* 232 to 235 */\r | |
347 | {3,5,4}, {3,5,5}, {3,5,6}, {3,5,7}, /* 236 to 239 */\r | |
348 | {3,6,0}, {3,6,1}, {3,6,2}, {3,6,3}, /* 240 to 243 */\r | |
349 | {3,6,4}, {3,6,5}, {3,6,6}, {3,6,7}, /* 244 to 247 */\r | |
350 | {3,7,0}, {3,7,1}, {3,7,2}, {3,7,3}, /* 248 to 251 */\r | |
351 | {3,7,4}, {3,7,5}, {3,7,6}, {3,7,7}, /* 252 to 255 */\r | |
352 | };\r | |
353 | \r | |
354 | void fetch_decode_modrm(PC_ENV *m, uint16 *mod, uint16 *regh, uint16 *regl)\r | |
355 | { uint8 fetched;\r | |
356 | register struct modrm *p;\r | |
357 | /* do the fetch in real mode. Shift the CS segment register\r | |
358 | over by 4 bits, and add in the IP register. Index into\r | |
359 | the system memory.\r | |
360 | */\r | |
361 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
362 | fetched = GetBYTEExtended(((m->R_CS << 4) + (m->R_IP++)) & 0xFFFFF);\r | |
363 | \r | |
364 | #ifdef NOTDEF\r | |
365 | *mod = ((fetched&0xc0)>>6);\r | |
366 | *regh= ((fetched&0x38)>>3);\r | |
367 | *regl= (fetched&0x7);\r | |
368 | #else\r | |
369 | p = modrmtab + fetched;\r | |
370 | *mod = p->mod;\r | |
371 | *regh= p->rh;\r | |
372 | *regl= p->rl;\r | |
373 | #endif\r | |
374 | \r | |
375 | }\r | |
376 | \r | |
377 | /*\r | |
378 | return a pointer to the register given by the R/RM field of\r | |
379 | the modrm byte, for byte operands.\r | |
380 | Also enables the decoding of instructions.\r | |
381 | */\r | |
382 | uint8 *decode_rm_byte_register(PC_ENV *m, int reg)\r | |
383 | {\r | |
384 | switch(reg)\r | |
385 | {\r | |
386 | case 0:\r | |
387 | return &m->R_AL;\r | |
388 | break;\r | |
389 | case 1:\r | |
390 | return &m->R_CL;\r | |
391 | break;\r | |
392 | case 2:\r | |
393 | return &m->R_DL;\r | |
394 | break;\r | |
395 | case 3:\r | |
396 | return &m->R_BL;\r | |
397 | break;\r | |
398 | case 4:\r | |
399 | return &m->R_AH;\r | |
400 | break;\r | |
401 | case 5:\r | |
402 | return &m->R_CH;\r | |
403 | break;\r | |
404 | case 6:\r | |
405 | return &m->R_DH;\r | |
406 | break;\r | |
407 | case 7:\r | |
408 | return &m->R_BH;\r | |
409 | break;\r | |
410 | }\r | |
411 | halt_sys(m);\r | |
412 | return NULL; /* NOT REACHED OR REACHED ON ERROR */\r | |
413 | }\r | |
414 | \r | |
415 | /*\r | |
416 | return a pointer to the register given by the R/RM field of\r | |
417 | the modrm byte, for word operands.\r | |
418 | Also enables the decoding of instructions.\r | |
419 | */\r | |
420 | uint16 *decode_rm_word_register(PC_ENV *m, int reg)\r | |
421 | {\r | |
422 | switch(reg)\r | |
423 | {\r | |
424 | case 0:\r | |
425 | return &m->R_AX;\r | |
426 | break;\r | |
427 | case 1:\r | |
428 | return &m->R_CX;\r | |
429 | break;\r | |
430 | case 2:\r | |
431 | return &m->R_DX;\r | |
432 | break;\r | |
433 | case 3:\r | |
434 | return &m->R_BX;\r | |
435 | break;\r | |
436 | case 4:\r | |
437 | return &m->R_SP;\r | |
438 | break;\r | |
439 | case 5:\r | |
440 | return &m->R_BP;\r | |
441 | break;\r | |
442 | case 6:\r | |
443 | return &m->R_SI;\r | |
444 | break;\r | |
445 | case 7:\r | |
446 | return &m->R_DI;\r | |
447 | break;\r | |
448 | }\r | |
449 | halt_sys(m);\r | |
450 | return NULL; /* NOTREACHED OR REACHED ON ERROR*/\r | |
451 | }\r | |
452 | \r | |
453 | /*\r | |
454 | return a pointer to the register given by the R/RM field of\r | |
455 | the modrm byte, for word operands, modified from above\r | |
456 | for the weirdo special case of segreg operands.\r | |
457 | Also enables the decoding of instructions.\r | |
458 | */\r | |
459 | uint16 *decode_rm_seg_register(PC_ENV *m, int reg)\r | |
460 | {\r | |
461 | switch(reg)\r | |
462 | {\r | |
463 | case 0:\r | |
464 | return &m->R_ES;\r | |
465 | break;\r | |
466 | case 1:\r | |
467 | return &m->R_CS;\r | |
468 | break;\r | |
469 | case 2:\r | |
470 | return &m->R_SS;\r | |
471 | break;\r | |
472 | case 3:\r | |
473 | return &m->R_DS;\r | |
474 | break;\r | |
475 | case 4:\r | |
476 | case 5:\r | |
477 | case 6:\r | |
478 | case 7:\r | |
479 | break;\r | |
480 | }\r | |
481 | halt_sys(m);\r | |
482 | return NULL; /* NOT REACHED OR REACHED ON ERROR */\r | |
483 | }\r | |
484 | \r | |
485 | /* once the instruction is fetched, an optional byte follows which\r | |
486 | has 3 fields encoded in it. This routine fetches the byte\r | |
487 | and breaks into the three fields.\r | |
488 | */\r | |
489 | uint8 fetch_byte_imm(PC_ENV *m)\r | |
490 | {\r | |
491 | uint8 fetched;\r | |
492 | /* do the fetch in real mode. Shift the CS segment register\r | |
493 | over by 4 bits, and add in the IP register. Index into\r | |
494 | the system memory.\r | |
495 | */\r | |
496 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
497 | fetched = GetBYTEExtended((((uint32)m->R_CS << 4) + (m->R_IP++)) & 0xFFFFF);\r | |
498 | return fetched;\r | |
499 | }\r | |
500 | \r | |
501 | uint16 fetch_word_imm(PC_ENV *m)\r | |
502 | {\r | |
503 | uint16 fetched;\r | |
504 | /* do the fetch in real mode. Shift the CS segment register\r | |
505 | over by 4 bits, and add in the IP register. Index into\r | |
506 | the system PC_ENVory.\r | |
507 | */\r | |
508 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
509 | fetched = GetBYTEExtended((((uint32)m->R_CS << 4) + (m->R_IP++)) & 0xFFFFF);\r | |
510 | fetched |= (GetBYTEExtended((((uint32)m->R_CS << 4) + (m->R_IP++)) & 0xFFFFF) << 8);\r | |
511 | return fetched;\r | |
512 | }\r | |
513 | \r | |
514 | /*\r | |
515 | return the offset given by mod=00 addressing.\r | |
516 | Also enables the decoding of instructions.\r | |
517 | */\r | |
518 | uint16 decode_rm00_address(PC_ENV *m, int rm)\r | |
519 | {\r | |
520 | uint16 offset;\r | |
521 | /* note the code which specifies the corresponding segment (ds vs ss)\r | |
522 | below in the case of [BP+..]. The assumption here is that at the\r | |
523 | point that this subroutine is called, the bit corresponding to\r | |
524 | SYSMODE_SEG_DS_SS will be zero. After every instruction\r | |
525 | except the segment override instructions, this bit (as well\r | |
526 | as any bits indicating segment overrides) will be clear. So\r | |
527 | if a SS access is needed, set this bit. Otherwise, DS access\r | |
528 | occurs (unless any of the segment override bits are set).\r | |
529 | */\r | |
530 | switch(rm)\r | |
531 | {\r | |
532 | case 0:\r | |
533 | return (int16)m->R_BX + (int16)m->R_SI;\r | |
534 | break;\r | |
535 | case 1:\r | |
536 | return (int16)m->R_BX + (int16)m->R_DI;\r | |
537 | break;\r | |
538 | case 2:\r | |
539 | m->sysmode |= SYSMODE_SEG_DS_SS;\r | |
540 | return (int16)m->R_BP + (int16)m->R_SI;\r | |
541 | break;\r | |
542 | case 3:\r | |
543 | m->sysmode |= SYSMODE_SEG_DS_SS;\r | |
544 | return (int16)m->R_BP + (int16)m->R_DI;\r | |
545 | break;\r | |
546 | case 4:\r | |
547 | return m->R_SI;\r | |
548 | break;\r | |
549 | case 5:\r | |
550 | return m->R_DI;\r | |
551 | break;\r | |
552 | case 6:\r | |
553 | offset = (int16)fetch_word_imm(m);\r | |
554 | return offset;\r | |
555 | break;\r | |
556 | case 7:\r | |
557 | return m->R_BX;\r | |
558 | }\r | |
559 | halt_sys(m);\r | |
560 | return 0;\r | |
561 | }\r | |
562 | \r | |
563 | /*\r | |
564 | return the offset given by mod=01 addressing.\r | |
565 | Also enables the decoding of instructions.\r | |
566 | */\r | |
567 | uint16 decode_rm01_address(PC_ENV *m, int rm)\r | |
568 | {\r | |
569 | int8 displacement;\r | |
570 | /* note comment on decode_rm00_address above */\r | |
571 | displacement = (int8)fetch_byte_imm(m); /* !!!! Check this */\r | |
572 | switch(rm)\r | |
573 | {\r | |
574 | case 0:\r | |
575 | return (int16)m->R_BX + (int16)m->R_SI + displacement;\r | |
576 | break;\r | |
577 | case 1:\r | |
578 | return (int16)m->R_BX + (int16)m->R_DI + displacement;\r | |
579 | break;\r | |
580 | case 2:\r | |
581 | m->sysmode |= SYSMODE_SEG_DS_SS;\r | |
582 | return (int16)m->R_BP + (int16)m->R_SI + displacement;\r | |
583 | break;\r | |
584 | case 3:\r | |
585 | m->sysmode |= SYSMODE_SEG_DS_SS;\r | |
586 | return (int16)m->R_BP + (int16)m->R_DI + displacement;\r | |
587 | break;\r | |
588 | case 4:\r | |
589 | return (int16)m->R_SI + displacement;\r | |
590 | break;\r | |
591 | case 5:\r | |
592 | return (int16)m->R_DI + displacement;\r | |
593 | break;\r | |
594 | case 6:\r | |
595 | m->sysmode |= SYSMODE_SEG_DS_SS;\r | |
596 | return (int16)m->R_BP + displacement;\r | |
597 | break;\r | |
598 | case 7:\r | |
599 | return (int16)m->R_BX + displacement;\r | |
600 | break;\r | |
601 | }\r | |
602 | halt_sys(m);\r | |
603 | return 0; /* SHOULD NOT HAPPEN */\r | |
604 | }\r | |
605 | \r | |
606 | /*\r | |
607 | return the offset given by mod=01 addressing.\r | |
608 | Also enables the decoding of instructions.\r | |
609 | */\r | |
610 | uint16 decode_rm10_address(PC_ENV *m, int rm)\r | |
611 | {\r | |
612 | int16 displacement;\r | |
613 | /* note comment on decode_rm00_address above */\r | |
614 | displacement = (int16)fetch_word_imm(m);\r | |
615 | switch(rm)\r | |
616 | {\r | |
617 | case 0:\r | |
618 | return (int16)m->R_BX + (int16)m->R_SI + displacement;\r | |
619 | break;\r | |
620 | case 1:\r | |
621 | return (int16)m->R_BX + (int16)m->R_DI + displacement;\r | |
622 | break;\r | |
623 | case 2:\r | |
624 | m->sysmode |= SYSMODE_SEG_DS_SS;\r | |
625 | return (int16)m->R_BP + (int16)m->R_SI + displacement;\r | |
626 | break;\r | |
627 | case 3:\r | |
628 | m->sysmode |= SYSMODE_SEG_DS_SS;\r | |
629 | return (int16)m->R_BP + (int16)m->R_DI + displacement;\r | |
630 | break;\r | |
631 | case 4:\r | |
632 | return (int16)m->R_SI + displacement;\r | |
633 | break;\r | |
634 | case 5:\r | |
635 | return (int16)m->R_DI + displacement;\r | |
636 | break;\r | |
637 | case 6:\r | |
638 | m->sysmode |= SYSMODE_SEG_DS_SS;\r | |
639 | return (int16)m->R_BP + displacement;\r | |
640 | break;\r | |
641 | case 7:\r | |
642 | return (int16)m->R_BX + displacement;\r | |
643 | break;\r | |
644 | }\r | |
645 | halt_sys(m);\r | |
646 | return 0;\r | |
647 | /*NOTREACHED */\r | |
648 | }\r | |
649 | \r | |
650 | /* fetch a byte of data, given an offset, the current register set,\r | |
651 | and a descriptor for memory.\r | |
652 | */\r | |
653 | uint8 fetch_data_byte(PC_ENV *m, uint16 offset)\r | |
654 | {\r | |
655 | register uint8 value;\r | |
656 | /* this code originally completely broken, and never showed\r | |
657 | up since the DS segments === SS segment in all test cases.\r | |
658 | It had been originally assumed, that all access to data would\r | |
659 | involve the DS register unless there was a segment override.\r | |
660 | Not so. Address modes such as -3[BP] or 10[BP+SI] all\r | |
661 | refer to addresses relative to the SS. So, at the minimum,\r | |
662 | all decodings of addressing modes would have to set/clear\r | |
663 | a bit describing whether the access is relative to DS or SS.\r | |
664 | That is the function of the cpu-state-varible m->sysmode.\r | |
665 | There are several potential states:\r | |
666 | repe prefix seen (handled elsewhere)\r | |
667 | repne prefix seen (ditto)\r | |
668 | cs segment override\r | |
669 | ds segment override\r | |
670 | es segment override\r | |
671 | ss segment override\r | |
672 | ds/ss select (in absense of override)\r | |
673 | Each of the above 7 items are handled with a bit in the sysmode\r | |
674 | field.\r | |
675 | The latter 5 can be implemented as a simple state machine:\r | |
676 | */\r | |
677 | switch(m->sysmode & SYSMODE_SEGMASK)\r | |
678 | {\r | |
679 | case 0:\r | |
680 | /* default case: use ds register */\r | |
681 | value = GetBYTEExtended(((uint32)m->R_DS<<4) + offset);\r | |
682 | break;\r | |
683 | case SYSMODE_SEG_DS_SS:\r | |
684 | /* non-overridden, use ss register */\r | |
685 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
686 | value = GetBYTEExtended((((uint32)m->R_SS << 4) + offset) & 0xFFFFF);\r | |
687 | break;\r | |
688 | case SYSMODE_SEGOVR_CS:\r | |
689 | /* ds overridden */\r | |
690 | case SYSMODE_SEGOVR_CS|SYSMODE_SEG_DS_SS:\r | |
691 | /* ss overridden, use cs register */\r | |
692 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
693 | value = GetBYTEExtended((((uint32)m->R_CS << 4) + offset) & 0xFFFFF);\r | |
694 | break;\r | |
695 | case SYSMODE_SEGOVR_DS:\r | |
696 | /* ds overridden --- shouldn't happen, but hey. */\r | |
697 | case SYSMODE_SEGOVR_DS|SYSMODE_SEG_DS_SS:\r | |
698 | /* ss overridden, use ds register */\r | |
699 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
700 | value = GetBYTEExtended((((uint32)m->R_DS << 4) + offset) & 0xFFFFF);\r | |
701 | break;\r | |
702 | case SYSMODE_SEGOVR_ES:\r | |
703 | /* ds overridden */\r | |
704 | case SYSMODE_SEGOVR_ES|SYSMODE_SEG_DS_SS:\r | |
705 | /* ss overridden, use es register */\r | |
706 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
707 | value = GetBYTEExtended((((uint32)m->R_ES << 4) + offset) & 0xFFFFF);\r | |
708 | break;\r | |
709 | case SYSMODE_SEGOVR_SS:\r | |
710 | /* ds overridden */\r | |
711 | case SYSMODE_SEGOVR_SS|SYSMODE_SEG_DS_SS:\r | |
712 | /* ss overridden, use ss register === should not happen */\r | |
713 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
714 | value = GetBYTEExtended((((uint32)m->R_SS << 4) + offset) & 0xFFFFF);\r | |
715 | break;\r | |
716 | default:\r | |
717 | printf("error: should not happen: multiple overrides. " NLP);\r | |
718 | value = 0;\r | |
719 | halt_sys(m);\r | |
720 | }\r | |
721 | return value;\r | |
722 | }\r | |
723 | \r | |
724 | /* fetch a byte of data, given an offset, the current register set,\r | |
725 | and a descriptor for memory.\r | |
726 | */\r | |
727 | uint8 fetch_data_byte_abs(PC_ENV *m, uint16 segment, uint16 offset)\r | |
728 | {\r | |
729 | register uint8 value;\r | |
730 | uint32 addr;\r | |
731 | /* note, cannot change this, since we do not know the ID of the segment. */\r | |
732 | /* [JCE] Simulate wrap at top of memory (the A20 gate) */\r | |
733 | /* addr = (segment << 4) + offset; */\r | |
734 | addr = ((segment << 4) + offset) & 0xFFFFF;\r | |
735 | value = GetBYTEExtended(addr);\r | |
736 | return value;\r | |
737 | }\r | |
738 | \r | |
739 | /* fetch a byte of data, given an offset, the current register set,\r | |
740 | and a descriptor for memory.\r | |
741 | */\r | |
742 | uint16 fetch_data_word(PC_ENV *m, uint16 offset)\r | |
743 | {\r | |
744 | uint16 value;\r | |
745 | /* See note above in fetch_data_byte. */\r | |
746 | switch(m->sysmode & SYSMODE_SEGMASK)\r | |
747 | {\r | |
748 | case 0:\r | |
749 | /* default case: use ds register */\r | |
750 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
751 | value = GetBYTEExtended((((uint32)m->R_DS << 4) + offset) & 0xFFFFF)\r | |
752 | | (GetBYTEExtended((((uint32)m->R_DS << 4) +\r | |
753 | (uint16)(offset + 1)) & 0xFFFFF) << 8);\r | |
754 | break;\r | |
755 | case SYSMODE_SEG_DS_SS:\r | |
756 | /* non-overridden, use ss register */\r | |
757 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
758 | value = GetBYTEExtended((((uint32)m->R_SS << 4) + offset) & 0xFFFFF)\r | |
759 | | (GetBYTEExtended((((uint32)m->R_SS << 4)\r | |
760 | + (uint16)(offset + 1)) & 0xFFFFF) << 8);\r | |
761 | break;\r | |
762 | case SYSMODE_SEGOVR_CS:\r | |
763 | /* ds overridden */\r | |
764 | case SYSMODE_SEGOVR_CS|SYSMODE_SEG_DS_SS:\r | |
765 | /* ss overridden, use cs register */\r | |
766 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
767 | value = GetBYTEExtended((((uint32)m->R_CS << 4) + offset) & 0xFFFFF)\r | |
768 | | (GetBYTEExtended((((uint32)m->R_CS << 4)\r | |
769 | + (uint16)(offset + 1)) & 0xFFFFF) << 8);\r | |
770 | break;\r | |
771 | case SYSMODE_SEGOVR_DS:\r | |
772 | /* ds overridden --- shouldn't happen, but hey. */\r | |
773 | case SYSMODE_SEGOVR_DS|SYSMODE_SEG_DS_SS:\r | |
774 | /* ss overridden, use ds register */\r | |
775 | /* [JCE] Wrap at 1Mb (the A20 gate) */\r | |
776 | value = GetBYTEExtended((((uint32)m->R_DS << 4) + offset) & 0xFFFFF)\r | |
777 | | (GetBYTEExtended((((uint32)m->R_DS << 4)\r | |
778 | + (uint16)(offset + 1)) & 0xFFFFF) << 8);\r | |
779 | break;\r | |
780 | case SYSMODE_SEGOVR_ES:\r | |
781 | /* ds overridden */\r | |
782 | case SYSMODE_SEGOVR_ES|SYSMODE_SEG_DS_SS:\r | |
783 | /* ss overridden, use es register */\r | |
784 | value = GetBYTEExtended((((uint32)m->R_ES << 4) + offset) & 0xFFFFF)\r | |
785 | | (GetBYTEExtended((((uint32)m->R_ES << 4) +\r | |
786 | (uint16)(offset + 1)) & 0xFFFFF) << 8);\r | |
787 | break;\r | |
788 | case SYSMODE_SEGOVR_SS:\r | |
789 | /* ds overridden */\r | |
790 | case SYSMODE_SEGOVR_SS|SYSMODE_SEG_DS_SS:\r | |
791 | /* ss overridden, use ss register === should not happen */\r | |
792 | value = GetBYTEExtended((((uint32)m->R_SS << 4) + offset) & 0xFFFFF)\r | |
793 | | (GetBYTEExtended((((uint32)m->R_SS << 4)\r | |
794 | + (uint16)(offset + 1)) & 0xFFFFF) << 8);\r | |
795 | break;\r | |
796 | default:\r | |
797 | printf("error: should not happen: multiple overrides. " NLP);\r | |
798 | value = 0;\r | |
799 | halt_sys(m);\r | |
800 | }\r | |
801 | return value;\r | |
802 | }\r | |
803 | \r | |
804 | /* fetch a byte of data, given an offset, the current register set,\r | |
805 | and a descriptor for memory.\r | |
806 | */\r | |
807 | uint16 fetch_data_word_abs(PC_ENV *m, uint16 segment, uint16 offset)\r | |
808 | {\r | |
809 | uint16 value;\r | |
810 | uint32 addr;\r | |
811 | /* [JCE] Simulate wrap at top of memory (the A20 gate) */\r | |
812 | /* addr = (segment << 4) + offset; */\r | |
813 | addr = ((segment << 4) + offset) & 0xFFFFF;\r | |
814 | value = GetBYTEExtended(addr) | (GetBYTEExtended(addr + 1) << 8);\r | |
815 | return value;\r | |
816 | }\r | |
817 | \r | |
818 | /* Store a byte of data, given an offset, the current register set,\r | |
819 | and a descriptor for memory.\r | |
820 | */\r | |
821 | void store_data_byte(PC_ENV *m, uint16 offset, uint8 val)\r | |
822 | {\r | |
823 | /* See note above in fetch_data_byte. */\r | |
824 | uint32 addr;\r | |
825 | register uint16 segment;\r | |
826 | switch(m->sysmode & SYSMODE_SEGMASK)\r | |
827 | {\r | |
828 | case 0:\r | |
829 | /* default case: use ds register */\r | |
830 | segment = m->R_DS;\r | |
831 | break;\r | |
832 | case SYSMODE_SEG_DS_SS:\r | |
833 | /* non-overridden, use ss register */\r | |
834 | segment = m->R_SS;\r | |
835 | break;\r | |
836 | case SYSMODE_SEGOVR_CS:\r | |
837 | /* ds overridden */\r | |
838 | case SYSMODE_SEGOVR_CS|SYSMODE_SEG_DS_SS:\r | |
839 | /* ss overridden, use cs register */\r | |
840 | segment = m->R_CS;\r | |
841 | break;\r | |
842 | case SYSMODE_SEGOVR_DS:\r | |
843 | /* ds overridden --- shouldn't happen, but hey. */\r | |
844 | case SYSMODE_SEGOVR_DS|SYSMODE_SEG_DS_SS:\r | |
845 | /* ss overridden, use ds register */\r | |
846 | segment = m->R_DS;\r | |
847 | break;\r | |
848 | case SYSMODE_SEGOVR_ES:\r | |
849 | /* ds overridden */\r | |
850 | case SYSMODE_SEGOVR_ES|SYSMODE_SEG_DS_SS:\r | |
851 | /* ss overridden, use es register */\r | |
852 | segment = m->R_ES;\r | |
853 | break;\r | |
854 | case SYSMODE_SEGOVR_SS:\r | |
855 | /* ds overridden */\r | |
856 | case SYSMODE_SEGOVR_SS|SYSMODE_SEG_DS_SS:\r | |
857 | /* ss overridden, use ss register === should not happen */\r | |
858 | segment = m->R_SS;\r | |
859 | break;\r | |
860 | default:\r | |
861 | printf("error: should not happen: multiple overrides. " NLP);\r | |
862 | segment = 0;\r | |
863 | halt_sys(m);\r | |
864 | }\r | |
865 | /* [JCE] Simulate wrap at top of memory (the A20 gate) */\r | |
866 | /* addr = (segment << 4) + offset; */\r | |
867 | addr = (((uint32)segment << 4) + offset) & 0xFFFFF;\r | |
868 | PutBYTEExtended(addr, val);\r | |
869 | }\r | |
870 | \r | |
871 | void store_data_byte_abs(PC_ENV *m, uint16 segment, uint16 offset, uint8 val)\r | |
872 | {\r | |
873 | register uint32 addr;\r | |
874 | /* [JCE] Simulate wrap at top of memory (the A20 gate) */\r | |
875 | /* addr = (segment << 4) + offset; */\r | |
876 | addr = (((uint32)segment << 4) + offset) & 0xFFFFF;\r | |
877 | PutBYTEExtended(addr, val);\r | |
878 | }\r | |
879 | \r | |
880 | /* Store a word of data, given an offset, the current register set,\r | |
881 | and a descriptor for memory.\r | |
882 | */\r | |
883 | void store_data_word(PC_ENV *m, uint16 offset, uint16 val)\r | |
884 | {\r | |
885 | register uint32 addr;\r | |
886 | register uint16 segment;\r | |
887 | /* See note above in fetch_data_byte. */\r | |
888 | switch(m->sysmode & SYSMODE_SEGMASK)\r | |
889 | {\r | |
890 | case 0:\r | |
891 | /* default case: use ds register */\r | |
892 | segment = m->R_DS;\r | |
893 | break;\r | |
894 | case SYSMODE_SEG_DS_SS:\r | |
895 | /* non-overridden, use ss register */\r | |
896 | segment = m->R_SS;\r | |
897 | break;\r | |
898 | case SYSMODE_SEGOVR_CS:\r | |
899 | /* ds overridden */\r | |
900 | case SYSMODE_SEGOVR_CS|SYSMODE_SEG_DS_SS:\r | |
901 | /* ss overridden, use cs register */\r | |
902 | segment = m->R_CS;\r | |
903 | break;\r | |
904 | case SYSMODE_SEGOVR_DS:\r | |
905 | /* ds overridden --- shouldn't happen, but hey. */\r | |
906 | case SYSMODE_SEGOVR_DS|SYSMODE_SEG_DS_SS:\r | |
907 | /* ss overridden, use ds register */\r | |
908 | segment = m->R_DS;\r | |
909 | break;\r | |
910 | case SYSMODE_SEGOVR_ES:\r | |
911 | /* ds overridden */\r | |
912 | case SYSMODE_SEGOVR_ES|SYSMODE_SEG_DS_SS:\r | |
913 | /* ss overridden, use es register */\r | |
914 | segment = m->R_ES;\r | |
915 | break;\r | |
916 | case SYSMODE_SEGOVR_SS:\r | |
917 | /* ds overridden */\r | |
918 | case SYSMODE_SEGOVR_SS|SYSMODE_SEG_DS_SS:\r | |
919 | /* ss overridden, use ss register === should not happen */\r | |
920 | segment = m->R_SS;\r | |
921 | break;\r | |
922 | default:\r | |
923 | printf("error: should not happen: multiple overrides." NLP);\r | |
924 | segment = 0;\r | |
925 | halt_sys(m);\r | |
926 | }\r | |
927 | /* [JCE] Simulate wrap at top of memory (the A20 gate) */\r | |
928 | /* addr = (segment << 4) + offset; */\r | |
929 | addr = (((uint32)segment << 4) + offset) & 0xFFFFF;\r | |
930 | PutBYTEExtended(addr, val & 0xff);\r | |
931 | PutBYTEExtended(addr + 1, val >> 8);\r | |
932 | }\r | |
933 | \r | |
934 | void store_data_word_abs(PC_ENV *m, uint16 segment, uint16 offset, uint16 val)\r | |
935 | {\r | |
936 | register uint32 addr;\r | |
937 | /* [JCE] Wrap at top of memory */\r | |
938 | addr = ((segment << 4) + offset) & 0xFFFFF;\r | |
939 | PutBYTEExtended(addr, val & 0xff);\r | |
940 | PutBYTEExtended(addr + 1, val >> 8);\r | |
941 | }\r |