3 * Copyright (C) 1991 Jim Hudgens
6 * The file is part of GDE.
8 * GDE is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 1, or (at your option)
13 * GDE is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with GDE; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "altairz80_defs.h"
27 extern uint32
GetBYTEExtended(register uint32 Addr
);
28 extern void PutBYTEExtended(register uint32 Addr
, const register uint32 Value
);
29 extern char messageBuffer
[];
30 extern void printMessage(void);
31 extern int32 AX_S
; /* AX register (8086) */
32 extern int32 BX_S
; /* BX register (8086) */
33 extern int32 CX_S
; /* CX register (8086) */
34 extern int32 DX_S
; /* DX register (8086) */
35 extern int32 CS_S
; /* CS register (8086) */
36 extern int32 DS_S
; /* DS register (8086) */
37 extern int32 ES_S
; /* ES register (8086) */
38 extern int32 SS_S
; /* SS register (8086) */
39 extern int32 DI_S
; /* DI register (8086) */
40 extern int32 SI_S
; /* SI register (8086) */
41 extern int32 BP_S
; /* BP register (8086) */
42 extern int32 SP8086_S
; /* SP register (8086) */
43 extern int32 IP_S
; /* IP register (8086) */
44 extern int32 FLAGS_S
; /* flags register (8086) */
45 extern int32 PC_S
; /* PC register (8080/Z80/8086), 20 bit */
46 extern int32 sim_interval
;
47 extern uint32 PCX
; /* external view of PC */
48 extern uint32 sim_brk_summ
;
51 void i86_intr_raise(PC_ENV
*m
,uint8 intrnum
);
52 void cpu8086reset(void);
53 t_stat
sim_instr_8086(void);
56 * Revision 0.05 1992/04/12 23:16:42 hudgens
57 * Many changes. Added support for the QUICK_FETCH option,
58 * so that memory accesses are faster. Now compiles with gcc -Wall
59 * and gcc -traditional and Sun cc.
61 * Revision 0.04 1991/07/30 01:59:56 hudgens
64 * Revision 0.03 1991/06/03 01:02:09 hudgens
65 * fixed minor problems due to unsigned to signed short integer
68 * Revision 0.02 1991/03/31 01:29:39 hudgens
69 * Fixed segment handling (overrides, default segment accessed) in
70 * routines decode_rmXX_address and the {fetch,store}_data_{byte,word}.
72 * Revision 0.01 1991/03/30 21:59:49 hudgens
78 /* this file includes subroutines which do:
79 stuff involving decoding instruction formats.
80 stuff involving accessess of immediate data via IP.
84 static void i86_intr_handle(PC_ENV
*m
)
87 if (intr
& INTR_SYNCH
) /* raised by something */
90 tmp
= (uint16
) mem_access_word(m
, intno
* 4);
96 /* [JCE] If we're interrupting between a segment override (or REP override)
97 * and the following instruction, decrease IP to get back to the prefix */
98 if (m
->sysmode
& (SYSMODE_SEGMASK
| SYSMODE_PREFIX_REPE
| SYSMODE_PREFIX_REPNE
))
102 /* [JCE] CS and IP were the wrong way round... */
103 push_word(m
, m
->R_CS
);
104 push_word(m
, m
->R_IP
);
105 tmp
= mem_access_word(m
, intno
* 4);
107 tmp
= mem_access_word(m
, intno
* 4 + 2);
110 intr
&= ~INTR_SYNCH
; /* [JCE] Dealt with, reset flag */
112 /* The interrupt code can't pick up the segment override status. */
113 DECODE_CLEAR_SEGOVR(m
);
116 void i86_intr_raise(PC_ENV
*m
,uint8 intrnum
)
122 static PC_ENV cpu8086
;
124 static void setViewRegisters(void) {
125 FLAGS_S
= cpu8086
.R_FLG
;
130 SP8086_S
= cpu8086
.R_SP
;
141 static void setCPURegisters(void) {
142 cpu8086
.R_FLG
= FLAGS_S
;
147 cpu8086
.R_SP
= SP8086_S
;
158 void cpu8086reset(void) {
159 cpu8086
.R_AX
= 0x1961;
160 if ((cpu8086
.R_AH
!= 0x19) || (cpu8086
.R_AL
!= 0x61)) {
161 printf("Fatal endian error - make sure to compile with '#define LOWFIRST %i'\n", 1 - LOWFIRST
);
164 /* 16 bit registers */
169 /* special registers */
175 cpu8086
.R_FLG
= F_ALWAYS_ON
;
176 /* segment registers */
184 static uint32
getFullPC(void) {
185 return cpu8086
.R_IP
+ (cpu8086
.R_CS
<< 4);
188 t_stat
sim_instr_8086(void) {
189 t_stat reason
= SCPE_OK
;
194 newIP
= PC_S
- 16 * CS_S
;
195 if ((0 <= newIP
) && (newIP
<= 0xffff)) cpu8086
.R_IP
= newIP
;
197 if (CS_S
!= ((PC_S
& 0xf0000) >> 4)) {
198 cpu8086
.R_CS
= (PC_S
& 0xf0000) >> 4;
199 if (cpu_unit
.flags
& UNIT_CPU_VERBOSE
) {
200 MESSAGE_2("Segment register CS set to %04x", cpu8086
.R_CS
);
203 cpu8086
.R_IP
= PC_S
& 0xffff;
205 while (TRUE
) { /* loop until halted */
206 if (sim_interval
<= 0) { /* check clock queue */
208 if ((reason
= sim_os_poll_kbd()) == SCPE_STOP
) /* poll on platforms without reliable signalling */
211 if ( (reason
= sim_process_event()) ) break;
213 if (sim_brk_summ
&& sim_brk_test(getFullPC(), SWMASK('E'))) { /* breakpoint? */
214 reason
= STOP_IBKPT
; /* stop simulation */
218 op1
= GetBYTEExtended((((uint32
)cpu8086
.R_CS
<<4) + cpu8086
.R_IP
) & 0xFFFFF);
219 if (sim_brk_summ
&& sim_brk_test(op1
, (1u << SIM_BKPT_V_SPC
) | SWMASK('I'))) { /* instruction breakpoint? */
220 reason
= STOP_IBKPT
; /* stop simulation */
225 (*(i86_optab
[op1
]))(&cpu8086
);
226 if (intr
& INTR_HALTED
) {
228 intr
&= ~INTR_HALTED
;
231 if (intr
& INTR_ILLEGAL_OPCODE
) {
232 intr
&= ~INTR_ILLEGAL_OPCODE
;
233 if (cpu_unit
.flags
& UNIT_CPU_OPSTOP
) {
234 reason
= STOP_OPCODE
;
238 if (((intr
& INTR_SYNCH
) && (cpu8086
.intno
== 0 || cpu8086
.intno
== 2)) ||
239 (ACCESS_FLAG(&cpu8086
, F_IF
))) {
240 /* [JCE] Reversed the sense of this ACCESS_FLAG; it's set for interrupts
241 enabled, not interrupts blocked i.e. either not blockable (intr 0 or 2)
242 or the IF flag not set so interrupts not blocked */
243 /* hharte: if a segment override exists, then treat that as "atomic" and do not handle
244 * an interrupt until the override is cleared.
245 * Not sure if this is the way an 8086 really works, need to find out for sure.
246 * Also, what about the REPE prefix?
248 if((cpu8086
.sysmode
& SYSMODE_SEGMASK
) == 0) {
249 i86_intr_handle(&cpu8086
);
253 PC_S
= (reason
== STOP_HALT
) | (reason
== STOP_OPCODE
) ? PCX
: getFullPC();
258 void halt_sys(PC_ENV
*m
)
263 /* once the instruction is fetched, an optional byte follows which
264 has 3 fields encoded in it. This routine fetches the byte
265 and breaks into the three fields.
266 This has been changed, in an attempt to reduce the amount of
267 executed code for this frequently executed subroutine. If this
268 works, then it may pay to somehow inline it.
272 /* this code generated the following table */
275 printf("\n\nstruct modrm{ uint8 mod,rh,rl;} modrmtab[] = {\n");
276 for (i
=0; i
<256; i
++)
278 printf("{%d,%d,%d}, ",((i
&0xc0)>>6),((i
&0x38)>>3),(i
&0x07));
280 printf("/* %d to %d */\n",i
&0xfc,i
);
286 struct modrm
{ uint16 mod
, rh
, rl
; };
287 static struct modrm modrmtab
[] = {
288 {0,0,0}, {0,0,1}, {0,0,2}, {0,0,3}, /* 0 to 3 */
289 {0,0,4}, {0,0,5}, {0,0,6}, {0,0,7}, /* 4 to 7 */
290 {0,1,0}, {0,1,1}, {0,1,2}, {0,1,3}, /* 8 to 11 */
291 {0,1,4}, {0,1,5}, {0,1,6}, {0,1,7}, /* 12 to 15 */
292 {0,2,0}, {0,2,1}, {0,2,2}, {0,2,3}, /* 16 to 19 */
293 {0,2,4}, {0,2,5}, {0,2,6}, {0,2,7}, /* 20 to 23 */
294 {0,3,0}, {0,3,1}, {0,3,2}, {0,3,3}, /* 24 to 27 */
295 {0,3,4}, {0,3,5}, {0,3,6}, {0,3,7}, /* 28 to 31 */
296 {0,4,0}, {0,4,1}, {0,4,2}, {0,4,3}, /* 32 to 35 */
297 {0,4,4}, {0,4,5}, {0,4,6}, {0,4,7}, /* 36 to 39 */
298 {0,5,0}, {0,5,1}, {0,5,2}, {0,5,3}, /* 40 to 43 */
299 {0,5,4}, {0,5,5}, {0,5,6}, {0,5,7}, /* 44 to 47 */
300 {0,6,0}, {0,6,1}, {0,6,2}, {0,6,3}, /* 48 to 51 */
301 {0,6,4}, {0,6,5}, {0,6,6}, {0,6,7}, /* 52 to 55 */
302 {0,7,0}, {0,7,1}, {0,7,2}, {0,7,3}, /* 56 to 59 */
303 {0,7,4}, {0,7,5}, {0,7,6}, {0,7,7}, /* 60 to 63 */
304 {1,0,0}, {1,0,1}, {1,0,2}, {1,0,3}, /* 64 to 67 */
305 {1,0,4}, {1,0,5}, {1,0,6}, {1,0,7}, /* 68 to 71 */
306 {1,1,0}, {1,1,1}, {1,1,2}, {1,1,3}, /* 72 to 75 */
307 {1,1,4}, {1,1,5}, {1,1,6}, {1,1,7}, /* 76 to 79 */
308 {1,2,0}, {1,2,1}, {1,2,2}, {1,2,3}, /* 80 to 83 */
309 {1,2,4}, {1,2,5}, {1,2,6}, {1,2,7}, /* 84 to 87 */
310 {1,3,0}, {1,3,1}, {1,3,2}, {1,3,3}, /* 88 to 91 */
311 {1,3,4}, {1,3,5}, {1,3,6}, {1,3,7}, /* 92 to 95 */
312 {1,4,0}, {1,4,1}, {1,4,2}, {1,4,3}, /* 96 to 99 */
313 {1,4,4}, {1,4,5}, {1,4,6}, {1,4,7}, /* 100 to 103 */
314 {1,5,0}, {1,5,1}, {1,5,2}, {1,5,3}, /* 104 to 107 */
315 {1,5,4}, {1,5,5}, {1,5,6}, {1,5,7}, /* 108 to 111 */
316 {1,6,0}, {1,6,1}, {1,6,2}, {1,6,3}, /* 112 to 115 */
317 {1,6,4}, {1,6,5}, {1,6,6}, {1,6,7}, /* 116 to 119 */
318 {1,7,0}, {1,7,1}, {1,7,2}, {1,7,3}, /* 120 to 123 */
319 {1,7,4}, {1,7,5}, {1,7,6}, {1,7,7}, /* 124 to 127 */
320 {2,0,0}, {2,0,1}, {2,0,2}, {2,0,3}, /* 128 to 131 */
321 {2,0,4}, {2,0,5}, {2,0,6}, {2,0,7}, /* 132 to 135 */
322 {2,1,0}, {2,1,1}, {2,1,2}, {2,1,3}, /* 136 to 139 */
323 {2,1,4}, {2,1,5}, {2,1,6}, {2,1,7}, /* 140 to 143 */
324 {2,2,0}, {2,2,1}, {2,2,2}, {2,2,3}, /* 144 to 147 */
325 {2,2,4}, {2,2,5}, {2,2,6}, {2,2,7}, /* 148 to 151 */
326 {2,3,0}, {2,3,1}, {2,3,2}, {2,3,3}, /* 152 to 155 */
327 {2,3,4}, {2,3,5}, {2,3,6}, {2,3,7}, /* 156 to 159 */
328 {2,4,0}, {2,4,1}, {2,4,2}, {2,4,3}, /* 160 to 163 */
329 {2,4,4}, {2,4,5}, {2,4,6}, {2,4,7}, /* 164 to 167 */
330 {2,5,0}, {2,5,1}, {2,5,2}, {2,5,3}, /* 168 to 171 */
331 {2,5,4}, {2,5,5}, {2,5,6}, {2,5,7}, /* 172 to 175 */
332 {2,6,0}, {2,6,1}, {2,6,2}, {2,6,3}, /* 176 to 179 */
333 {2,6,4}, {2,6,5}, {2,6,6}, {2,6,7}, /* 180 to 183 */
334 {2,7,0}, {2,7,1}, {2,7,2}, {2,7,3}, /* 184 to 187 */
335 {2,7,4}, {2,7,5}, {2,7,6}, {2,7,7}, /* 188 to 191 */
336 {3,0,0}, {3,0,1}, {3,0,2}, {3,0,3}, /* 192 to 195 */
337 {3,0,4}, {3,0,5}, {3,0,6}, {3,0,7}, /* 196 to 199 */
338 {3,1,0}, {3,1,1}, {3,1,2}, {3,1,3}, /* 200 to 203 */
339 {3,1,4}, {3,1,5}, {3,1,6}, {3,1,7}, /* 204 to 207 */
340 {3,2,0}, {3,2,1}, {3,2,2}, {3,2,3}, /* 208 to 211 */
341 {3,2,4}, {3,2,5}, {3,2,6}, {3,2,7}, /* 212 to 215 */
342 {3,3,0}, {3,3,1}, {3,3,2}, {3,3,3}, /* 216 to 219 */
343 {3,3,4}, {3,3,5}, {3,3,6}, {3,3,7}, /* 220 to 223 */
344 {3,4,0}, {3,4,1}, {3,4,2}, {3,4,3}, /* 224 to 227 */
345 {3,4,4}, {3,4,5}, {3,4,6}, {3,4,7}, /* 228 to 231 */
346 {3,5,0}, {3,5,1}, {3,5,2}, {3,5,3}, /* 232 to 235 */
347 {3,5,4}, {3,5,5}, {3,5,6}, {3,5,7}, /* 236 to 239 */
348 {3,6,0}, {3,6,1}, {3,6,2}, {3,6,3}, /* 240 to 243 */
349 {3,6,4}, {3,6,5}, {3,6,6}, {3,6,7}, /* 244 to 247 */
350 {3,7,0}, {3,7,1}, {3,7,2}, {3,7,3}, /* 248 to 251 */
351 {3,7,4}, {3,7,5}, {3,7,6}, {3,7,7}, /* 252 to 255 */
354 void fetch_decode_modrm(PC_ENV
*m
, uint16
*mod
, uint16
*regh
, uint16
*regl
)
356 register struct modrm
*p
;
357 /* do the fetch in real mode. Shift the CS segment register
358 over by 4 bits, and add in the IP register. Index into
361 /* [JCE] Wrap at 1Mb (the A20 gate) */
362 fetched
= GetBYTEExtended(((m
->R_CS
<< 4) + (m
->R_IP
++)) & 0xFFFFF);
365 *mod
= ((fetched
&0xc0)>>6);
366 *regh
= ((fetched
&0x38)>>3);
367 *regl
= (fetched
&0x7);
369 p
= modrmtab
+ fetched
;
378 return a pointer to the register given by the R/RM field of
379 the modrm byte, for byte operands.
380 Also enables the decoding of instructions.
382 uint8
*decode_rm_byte_register(PC_ENV
*m
, int reg
)
412 return NULL
; /* NOT REACHED OR REACHED ON ERROR */
416 return a pointer to the register given by the R/RM field of
417 the modrm byte, for word operands.
418 Also enables the decoding of instructions.
420 uint16
*decode_rm_word_register(PC_ENV
*m
, int reg
)
450 return NULL
; /* NOTREACHED OR REACHED ON ERROR*/
454 return a pointer to the register given by the R/RM field of
455 the modrm byte, for word operands, modified from above
456 for the weirdo special case of segreg operands.
457 Also enables the decoding of instructions.
459 uint16
*decode_rm_seg_register(PC_ENV
*m
, int reg
)
482 return NULL
; /* NOT REACHED OR REACHED ON ERROR */
485 /* once the instruction is fetched, an optional byte follows which
486 has 3 fields encoded in it. This routine fetches the byte
487 and breaks into the three fields.
489 uint8
fetch_byte_imm(PC_ENV
*m
)
492 /* do the fetch in real mode. Shift the CS segment register
493 over by 4 bits, and add in the IP register. Index into
496 /* [JCE] Wrap at 1Mb (the A20 gate) */
497 fetched
= GetBYTEExtended((((uint32
)m
->R_CS
<< 4) + (m
->R_IP
++)) & 0xFFFFF);
501 uint16
fetch_word_imm(PC_ENV
*m
)
504 /* do the fetch in real mode. Shift the CS segment register
505 over by 4 bits, and add in the IP register. Index into
506 the system PC_ENVory.
508 /* [JCE] Wrap at 1Mb (the A20 gate) */
509 fetched
= GetBYTEExtended((((uint32
)m
->R_CS
<< 4) + (m
->R_IP
++)) & 0xFFFFF);
510 fetched
|= (GetBYTEExtended((((uint32
)m
->R_CS
<< 4) + (m
->R_IP
++)) & 0xFFFFF) << 8);
515 return the offset given by mod=00 addressing.
516 Also enables the decoding of instructions.
518 uint16
decode_rm00_address(PC_ENV
*m
, int rm
)
521 /* note the code which specifies the corresponding segment (ds vs ss)
522 below in the case of [BP+..]. The assumption here is that at the
523 point that this subroutine is called, the bit corresponding to
524 SYSMODE_SEG_DS_SS will be zero. After every instruction
525 except the segment override instructions, this bit (as well
526 as any bits indicating segment overrides) will be clear. So
527 if a SS access is needed, set this bit. Otherwise, DS access
528 occurs (unless any of the segment override bits are set).
533 return (int16
)m
->R_BX
+ (int16
)m
->R_SI
;
536 return (int16
)m
->R_BX
+ (int16
)m
->R_DI
;
539 m
->sysmode
|= SYSMODE_SEG_DS_SS
;
540 return (int16
)m
->R_BP
+ (int16
)m
->R_SI
;
543 m
->sysmode
|= SYSMODE_SEG_DS_SS
;
544 return (int16
)m
->R_BP
+ (int16
)m
->R_DI
;
553 offset
= (int16
)fetch_word_imm(m
);
564 return the offset given by mod=01 addressing.
565 Also enables the decoding of instructions.
567 uint16
decode_rm01_address(PC_ENV
*m
, int rm
)
570 /* note comment on decode_rm00_address above */
571 displacement
= (int8
)fetch_byte_imm(m
); /* !!!! Check this */
575 return (int16
)m
->R_BX
+ (int16
)m
->R_SI
+ displacement
;
578 return (int16
)m
->R_BX
+ (int16
)m
->R_DI
+ displacement
;
581 m
->sysmode
|= SYSMODE_SEG_DS_SS
;
582 return (int16
)m
->R_BP
+ (int16
)m
->R_SI
+ displacement
;
585 m
->sysmode
|= SYSMODE_SEG_DS_SS
;
586 return (int16
)m
->R_BP
+ (int16
)m
->R_DI
+ displacement
;
589 return (int16
)m
->R_SI
+ displacement
;
592 return (int16
)m
->R_DI
+ displacement
;
595 m
->sysmode
|= SYSMODE_SEG_DS_SS
;
596 return (int16
)m
->R_BP
+ displacement
;
599 return (int16
)m
->R_BX
+ displacement
;
603 return 0; /* SHOULD NOT HAPPEN */
607 return the offset given by mod=01 addressing.
608 Also enables the decoding of instructions.
610 uint16
decode_rm10_address(PC_ENV
*m
, int rm
)
613 /* note comment on decode_rm00_address above */
614 displacement
= (int16
)fetch_word_imm(m
);
618 return (int16
)m
->R_BX
+ (int16
)m
->R_SI
+ displacement
;
621 return (int16
)m
->R_BX
+ (int16
)m
->R_DI
+ displacement
;
624 m
->sysmode
|= SYSMODE_SEG_DS_SS
;
625 return (int16
)m
->R_BP
+ (int16
)m
->R_SI
+ displacement
;
628 m
->sysmode
|= SYSMODE_SEG_DS_SS
;
629 return (int16
)m
->R_BP
+ (int16
)m
->R_DI
+ displacement
;
632 return (int16
)m
->R_SI
+ displacement
;
635 return (int16
)m
->R_DI
+ displacement
;
638 m
->sysmode
|= SYSMODE_SEG_DS_SS
;
639 return (int16
)m
->R_BP
+ displacement
;
642 return (int16
)m
->R_BX
+ displacement
;
650 /* fetch a byte of data, given an offset, the current register set,
651 and a descriptor for memory.
653 uint8
fetch_data_byte(PC_ENV
*m
, uint16 offset
)
655 register uint8 value
;
656 /* this code originally completely broken, and never showed
657 up since the DS segments === SS segment in all test cases.
658 It had been originally assumed, that all access to data would
659 involve the DS register unless there was a segment override.
660 Not so. Address modes such as -3[BP] or 10[BP+SI] all
661 refer to addresses relative to the SS. So, at the minimum,
662 all decodings of addressing modes would have to set/clear
663 a bit describing whether the access is relative to DS or SS.
664 That is the function of the cpu-state-varible m->sysmode.
665 There are several potential states:
666 repe prefix seen (handled elsewhere)
667 repne prefix seen (ditto)
672 ds/ss select (in absense of override)
673 Each of the above 7 items are handled with a bit in the sysmode
675 The latter 5 can be implemented as a simple state machine:
677 switch(m
->sysmode
& SYSMODE_SEGMASK
)
680 /* default case: use ds register */
681 value
= GetBYTEExtended(((uint32
)m
->R_DS
<<4) + offset
);
683 case SYSMODE_SEG_DS_SS
:
684 /* non-overridden, use ss register */
685 /* [JCE] Wrap at 1Mb (the A20 gate) */
686 value
= GetBYTEExtended((((uint32
)m
->R_SS
<< 4) + offset
) & 0xFFFFF);
688 case SYSMODE_SEGOVR_CS
:
690 case SYSMODE_SEGOVR_CS
|SYSMODE_SEG_DS_SS
:
691 /* ss overridden, use cs register */
692 /* [JCE] Wrap at 1Mb (the A20 gate) */
693 value
= GetBYTEExtended((((uint32
)m
->R_CS
<< 4) + offset
) & 0xFFFFF);
695 case SYSMODE_SEGOVR_DS
:
696 /* ds overridden --- shouldn't happen, but hey. */
697 case SYSMODE_SEGOVR_DS
|SYSMODE_SEG_DS_SS
:
698 /* ss overridden, use ds register */
699 /* [JCE] Wrap at 1Mb (the A20 gate) */
700 value
= GetBYTEExtended((((uint32
)m
->R_DS
<< 4) + offset
) & 0xFFFFF);
702 case SYSMODE_SEGOVR_ES
:
704 case SYSMODE_SEGOVR_ES
|SYSMODE_SEG_DS_SS
:
705 /* ss overridden, use es register */
706 /* [JCE] Wrap at 1Mb (the A20 gate) */
707 value
= GetBYTEExtended((((uint32
)m
->R_ES
<< 4) + offset
) & 0xFFFFF);
709 case SYSMODE_SEGOVR_SS
:
711 case SYSMODE_SEGOVR_SS
|SYSMODE_SEG_DS_SS
:
712 /* ss overridden, use ss register === should not happen */
713 /* [JCE] Wrap at 1Mb (the A20 gate) */
714 value
= GetBYTEExtended((((uint32
)m
->R_SS
<< 4) + offset
) & 0xFFFFF);
717 printf("error: should not happen: multiple overrides. " NLP
);
724 /* fetch a byte of data, given an offset, the current register set,
725 and a descriptor for memory.
727 uint8
fetch_data_byte_abs(PC_ENV
*m
, uint16 segment
, uint16 offset
)
729 register uint8 value
;
731 /* note, cannot change this, since we do not know the ID of the segment. */
732 /* [JCE] Simulate wrap at top of memory (the A20 gate) */
733 /* addr = (segment << 4) + offset; */
734 addr
= ((segment
<< 4) + offset
) & 0xFFFFF;
735 value
= GetBYTEExtended(addr
);
739 /* fetch a byte of data, given an offset, the current register set,
740 and a descriptor for memory.
742 uint16
fetch_data_word(PC_ENV
*m
, uint16 offset
)
745 /* See note above in fetch_data_byte. */
746 switch(m
->sysmode
& SYSMODE_SEGMASK
)
749 /* default case: use ds register */
750 /* [JCE] Wrap at 1Mb (the A20 gate) */
751 value
= GetBYTEExtended((((uint32
)m
->R_DS
<< 4) + offset
) & 0xFFFFF)
752 | (GetBYTEExtended((((uint32
)m
->R_DS
<< 4) +
753 (uint16
)(offset
+ 1)) & 0xFFFFF) << 8);
755 case SYSMODE_SEG_DS_SS
:
756 /* non-overridden, use ss register */
757 /* [JCE] Wrap at 1Mb (the A20 gate) */
758 value
= GetBYTEExtended((((uint32
)m
->R_SS
<< 4) + offset
) & 0xFFFFF)
759 | (GetBYTEExtended((((uint32
)m
->R_SS
<< 4)
760 + (uint16
)(offset
+ 1)) & 0xFFFFF) << 8);
762 case SYSMODE_SEGOVR_CS
:
764 case SYSMODE_SEGOVR_CS
|SYSMODE_SEG_DS_SS
:
765 /* ss overridden, use cs register */
766 /* [JCE] Wrap at 1Mb (the A20 gate) */
767 value
= GetBYTEExtended((((uint32
)m
->R_CS
<< 4) + offset
) & 0xFFFFF)
768 | (GetBYTEExtended((((uint32
)m
->R_CS
<< 4)
769 + (uint16
)(offset
+ 1)) & 0xFFFFF) << 8);
771 case SYSMODE_SEGOVR_DS
:
772 /* ds overridden --- shouldn't happen, but hey. */
773 case SYSMODE_SEGOVR_DS
|SYSMODE_SEG_DS_SS
:
774 /* ss overridden, use ds register */
775 /* [JCE] Wrap at 1Mb (the A20 gate) */
776 value
= GetBYTEExtended((((uint32
)m
->R_DS
<< 4) + offset
) & 0xFFFFF)
777 | (GetBYTEExtended((((uint32
)m
->R_DS
<< 4)
778 + (uint16
)(offset
+ 1)) & 0xFFFFF) << 8);
780 case SYSMODE_SEGOVR_ES
:
782 case SYSMODE_SEGOVR_ES
|SYSMODE_SEG_DS_SS
:
783 /* ss overridden, use es register */
784 value
= GetBYTEExtended((((uint32
)m
->R_ES
<< 4) + offset
) & 0xFFFFF)
785 | (GetBYTEExtended((((uint32
)m
->R_ES
<< 4) +
786 (uint16
)(offset
+ 1)) & 0xFFFFF) << 8);
788 case SYSMODE_SEGOVR_SS
:
790 case SYSMODE_SEGOVR_SS
|SYSMODE_SEG_DS_SS
:
791 /* ss overridden, use ss register === should not happen */
792 value
= GetBYTEExtended((((uint32
)m
->R_SS
<< 4) + offset
) & 0xFFFFF)
793 | (GetBYTEExtended((((uint32
)m
->R_SS
<< 4)
794 + (uint16
)(offset
+ 1)) & 0xFFFFF) << 8);
797 printf("error: should not happen: multiple overrides. " NLP
);
804 /* fetch a byte of data, given an offset, the current register set,
805 and a descriptor for memory.
807 uint16
fetch_data_word_abs(PC_ENV
*m
, uint16 segment
, uint16 offset
)
811 /* [JCE] Simulate wrap at top of memory (the A20 gate) */
812 /* addr = (segment << 4) + offset; */
813 addr
= ((segment
<< 4) + offset
) & 0xFFFFF;
814 value
= GetBYTEExtended(addr
) | (GetBYTEExtended(addr
+ 1) << 8);
818 /* Store a byte of data, given an offset, the current register set,
819 and a descriptor for memory.
821 void store_data_byte(PC_ENV
*m
, uint16 offset
, uint8 val
)
823 /* See note above in fetch_data_byte. */
825 register uint16 segment
;
826 switch(m
->sysmode
& SYSMODE_SEGMASK
)
829 /* default case: use ds register */
832 case SYSMODE_SEG_DS_SS
:
833 /* non-overridden, use ss register */
836 case SYSMODE_SEGOVR_CS
:
838 case SYSMODE_SEGOVR_CS
|SYSMODE_SEG_DS_SS
:
839 /* ss overridden, use cs register */
842 case SYSMODE_SEGOVR_DS
:
843 /* ds overridden --- shouldn't happen, but hey. */
844 case SYSMODE_SEGOVR_DS
|SYSMODE_SEG_DS_SS
:
845 /* ss overridden, use ds register */
848 case SYSMODE_SEGOVR_ES
:
850 case SYSMODE_SEGOVR_ES
|SYSMODE_SEG_DS_SS
:
851 /* ss overridden, use es register */
854 case SYSMODE_SEGOVR_SS
:
856 case SYSMODE_SEGOVR_SS
|SYSMODE_SEG_DS_SS
:
857 /* ss overridden, use ss register === should not happen */
861 printf("error: should not happen: multiple overrides. " NLP
);
865 /* [JCE] Simulate wrap at top of memory (the A20 gate) */
866 /* addr = (segment << 4) + offset; */
867 addr
= (((uint32
)segment
<< 4) + offset
) & 0xFFFFF;
868 PutBYTEExtended(addr
, val
);
871 void store_data_byte_abs(PC_ENV
*m
, uint16 segment
, uint16 offset
, uint8 val
)
873 register uint32 addr
;
874 /* [JCE] Simulate wrap at top of memory (the A20 gate) */
875 /* addr = (segment << 4) + offset; */
876 addr
= (((uint32
)segment
<< 4) + offset
) & 0xFFFFF;
877 PutBYTEExtended(addr
, val
);
880 /* Store a word of data, given an offset, the current register set,
881 and a descriptor for memory.
883 void store_data_word(PC_ENV
*m
, uint16 offset
, uint16 val
)
885 register uint32 addr
;
886 register uint16 segment
;
887 /* See note above in fetch_data_byte. */
888 switch(m
->sysmode
& SYSMODE_SEGMASK
)
891 /* default case: use ds register */
894 case SYSMODE_SEG_DS_SS
:
895 /* non-overridden, use ss register */
898 case SYSMODE_SEGOVR_CS
:
900 case SYSMODE_SEGOVR_CS
|SYSMODE_SEG_DS_SS
:
901 /* ss overridden, use cs register */
904 case SYSMODE_SEGOVR_DS
:
905 /* ds overridden --- shouldn't happen, but hey. */
906 case SYSMODE_SEGOVR_DS
|SYSMODE_SEG_DS_SS
:
907 /* ss overridden, use ds register */
910 case SYSMODE_SEGOVR_ES
:
912 case SYSMODE_SEGOVR_ES
|SYSMODE_SEG_DS_SS
:
913 /* ss overridden, use es register */
916 case SYSMODE_SEGOVR_SS
:
918 case SYSMODE_SEGOVR_SS
|SYSMODE_SEG_DS_SS
:
919 /* ss overridden, use ss register === should not happen */
923 printf("error: should not happen: multiple overrides." NLP
);
927 /* [JCE] Simulate wrap at top of memory (the A20 gate) */
928 /* addr = (segment << 4) + offset; */
929 addr
= (((uint32
)segment
<< 4) + offset
) & 0xFFFFF;
930 PutBYTEExtended(addr
, val
& 0xff);
931 PutBYTEExtended(addr
+ 1, val
>> 8);
934 void store_data_word_abs(PC_ENV
*m
, uint16 segment
, uint16 offset
, uint16 val
)
936 register uint32 addr
;
937 /* [JCE] Wrap at top of memory */
938 addr
= ((segment
<< 4) + offset
) & 0xFFFFF;
939 PutBYTEExtended(addr
, val
& 0xff);
940 PutBYTEExtended(addr
+ 1, val
>> 8);