First Commit of my working state
[simh.git] / AltairZ80 / i86.h
CommitLineData
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/* 8086 support structs and definitions */\r
25/* definition of the registers */\r
26\r
27/* general EAX,EBX,ECX, EDX type registers.\r
28 Note that for portability, and speed, the issue of byte\r
29 swapping is not addressed in the registers. All registers\r
30 are stored in the default format available on the\r
31 host machine. The only critical issue is that the\r
32 registers should line up EXACTLY in the same manner as\r
33 they do in the 386. That is:\r
34\r
35 EAX & 0xff === AL\r
36 EAX & 0xffff == AX\r
37\r
38 etc. The result is that alot of the calculations can then be\r
39 done using the native instruction set fully.\r
40*/\r
41\r
42/* Endian Logic\r
43Priority 1: If LOWFIRST is defined, use it. LOWFIRST must be 1 if the\r
44 lower part of a 16 bit quantity comes first in memory, otherwise\r
45 LOWFIRST must be 0\r
46Priority 2: If __BIG_ENDIAN__ is defined, use it to define LOWFIRST accordingly\r
47Priority 3: OS 9 on Macintosh needs LOWFIRST 0\r
48Priority 4: Use LOWFIRST 1 as default\r
49*/\r
50\r
51#ifndef LOWFIRST\r
52#ifdef __BIG_ENDIAN__\r
53#if __BIG_ENDIAN__\r
54#define LOWFIRST 0\r
55#else\r
56#define LOWFIRST 1\r
57#endif\r
58#elif defined (__MWERKS__) && defined (macintosh)\r
59#define LOWFIRST 0\r
60#else\r
61#define LOWFIRST 1\r
62#endif\r
63#endif\r
64\r
65#if LOWFIRST\r
66typedef struct { uint16 x_reg; } I16_reg_t;\r
67typedef struct { uint8 l_reg, h_reg; } I8_reg_t;\r
68#else\r
69typedef struct { uint16 x_reg; } I16_reg_t;\r
70typedef struct { uint8 h_reg, l_reg; } I8_reg_t;\r
71#endif\r
72\r
73typedef union\r
74{\r
75 I16_reg_t I16_reg;\r
76 I8_reg_t I8_reg;\r
77} i386_general_register;\r
78\r
79struct i386_general_regs\r
80{\r
81 i386_general_register A, B, C, D;\r
82};\r
83\r
84typedef struct i386_general_regs Gen_reg_t;\r
85\r
86struct i386_special_regs\r
87{\r
88 i386_general_register SP, BP, SI, DI, IP;\r
89 uint32 FLAGS;\r
90};\r
91\r
92/*\r
93 * segment registers here represent the 16 bit quantities\r
94 * CS, DS, ES, SS\r
95 *\r
96 * segment pointers --- used to speed up the expressions:\r
97 * q = m->R_CSP + m->R_IP;\r
98 * fetched = *q;\r
99 * m->R_IP += 1;\r
100 * compared to:\r
101 * fetched = GetBYTEExtended(((uint32)m->R_CS << 4) + (m->R_IP++));\r
102 * Save at least one shift, more if doing two byte moves.\r
103 */\r
104struct i386_segment_regs\r
105{\r
106 uint16 CS, DS, SS, ES, FS, GS;\r
107};\r
108\r
109/* 8 bit registers */\r
110#define R_AH Gn_regs.A.I8_reg.h_reg\r
111#define R_AL Gn_regs.A.I8_reg.l_reg\r
112#define R_BH Gn_regs.B.I8_reg.h_reg\r
113#define R_BL Gn_regs.B.I8_reg.l_reg\r
114#define R_CH Gn_regs.C.I8_reg.h_reg\r
115#define R_CL Gn_regs.C.I8_reg.l_reg\r
116#define R_DH Gn_regs.D.I8_reg.h_reg\r
117#define R_DL Gn_regs.D.I8_reg.l_reg\r
118\r
119/* 16 bit registers */\r
120#define R_AX Gn_regs.A.I16_reg.x_reg\r
121#define R_BX Gn_regs.B.I16_reg.x_reg\r
122#define R_CX Gn_regs.C.I16_reg.x_reg\r
123#define R_DX Gn_regs.D.I16_reg.x_reg\r
124\r
125/* special registers */\r
126#define R_SP Sp_regs.SP.I16_reg.x_reg\r
127#define R_BP Sp_regs.BP.I16_reg.x_reg\r
128#define R_SI Sp_regs.SI.I16_reg.x_reg\r
129#define R_DI Sp_regs.DI.I16_reg.x_reg\r
130#define R_IP Sp_regs.IP.I16_reg.x_reg\r
131#define R_FLG Sp_regs.FLAGS\r
132\r
133/* segment registers */\r
134#define R_CS Sg_regs.CS\r
135#define R_DS Sg_regs.DS\r
136#define R_SS Sg_regs.SS\r
137#define R_ES Sg_regs.ES\r
138\r
139/* 8088 has top 4 bits of the flags set to 1 */\r
140/* Also, bit#1 is set. This is (not well) documented behavior. */\r
141/* see note in userman.tex about the subtleties of dealing with */\r
142/* code which attempts to detect the host processor. */\r
143/* This is def'd as F_ALWAYS_ON */\r
144#define F_ALWAYS_ON (0xf002) /* flag bits always on */\r
145\r
146/* following bits masked in to a 16bit quantity */\r
147#define F_CF 0x1 /* CARRY flag */\r
148#define F_PF 0x4 /* PARITY flag */\r
149#define F_AF 0x10 /* AUX flag */\r
150#define F_ZF 0x40 /* ZERO flag */\r
151#define F_SF 0x80 /* SIGN flag */\r
152#define F_TF 0x100 /* TRAP flag */\r
153#define F_IF 0x200 /* INTERRUPT ENABLE flag */\r
154#define F_DF 0x400 /* DIR flag */\r
155#define F_OF 0x800 /* OVERFLOW flag */\r
156\r
157/*\r
158 * DEFINE A MASK FOR ONLY THOSE FLAG BITS WE WILL EVER PASS BACK\r
159 * (via PUSHF)\r
160 */\r
161#define F_MSK (F_CF|F_PF|F_AF|F_ZF|F_SF|F_TF|F_IF|F_DF|F_OF)\r
162\r
163#define TOGGLE_FLAG(M,FLAG) (M)->R_FLG ^= FLAG\r
164#define SET_FLAG(M,FLAG) (M)->R_FLG |= FLAG\r
165#define CLEAR_FLAG(M, FLAG) (M)->R_FLG &= ~FLAG\r
166#define ACCESS_FLAG(M,FLAG) ((M)->R_FLG & (FLAG))\r
167\r
168#define CONDITIONAL_SET_FLAG(COND,M,FLAG) \\r
169 if (COND) SET_FLAG(M,FLAG); else CLEAR_FLAG(M,FLAG)\r
170\r
171/* emulator machine state. */\r
172/* segment usage control */\r
173#define SYSMODE_SEG_DS_SS 0x01\r
174#define SYSMODE_SEGOVR_CS 0x02\r
175#define SYSMODE_SEGOVR_DS 0x04\r
176#define SYSMODE_SEGOVR_ES 0x08\r
177#define SYSMODE_SEGOVR_SS 0x10\r
178\r
179#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | SYSMODE_SEGOVR_CS | \\r
180 SYSMODE_SEGOVR_DS | SYSMODE_SEGOVR_ES | SYSMODE_SEGOVR_SS)\r
181\r
182#define SYSMODE_PREFIX_REPE 0x20\r
183#define SYSMODE_PREFIX_REPNE 0x40\r
184\r
185#define INTR_SYNCH 0x1\r
186#define INTR_HALTED 0x4\r
187#define INTR_ILLEGAL_OPCODE 0x8\r
188\f\r
189/* INSTRUCTION DECODING STUFF */\r
190#define FETCH_DECODE_MODRM(m,mod,rh,rl) fetch_decode_modrm(m,&mod,&rh,&rl)\r
191#define DECODE_RM_BYTE_REGISTER(m,r) decode_rm_byte_register(m,r)\r
192#define DECODE_RM_WORD_REGISTER(m,r) decode_rm_word_register(m,r)\r
193#define DECODE_CLEAR_SEGOVR(m) m->sysmode &= ~(SYSMODE_SEGMASK)\r
194\r
195typedef struct pc_env PC_ENV;\r
196struct pc_env\r
197{\r
198 /* The registers!! */\r
199 struct i386_general_regs Gn_regs;\r
200 struct i386_special_regs Sp_regs;\r
201 struct i386_segment_regs Sg_regs;\r
202 /* our flags structrure. This contains information on\r
203 REPE prefix 2 bits repe,repne\r
204 SEGMENT overrides 5 bits normal,DS,SS,CS,ES\r
205 Delayed flag set 3 bits (zero, signed, parity)\r
206 reserved 6 bits\r
207 interrupt # 8 bits instruction raised interrupt\r
208 BIOS video segregs 4 bits\r
209 Interrupt Pending 1 bits\r
210 Extern interrupt 1 bits\r
211 Halted 1 bits\r
212 */\r
213 long sysmode;\r
214 uint8 intno;\r
215};\r
216\r
217/* GLOBAL */\r
218volatile int intr;\r
219\r
220void halt_sys (PC_ENV *sys);\r
221void fetch_decode_modrm (PC_ENV *m, uint16 *mod, uint16 *regh, uint16 *regl);\r
222uint8 *decode_rm_byte_register (PC_ENV *m, int reg);\r
223uint16 *decode_rm_word_register (PC_ENV *m, int reg);\r
224uint16 *decode_rm_seg_register (PC_ENV *m, int reg);\r
225uint8 fetch_byte_imm (PC_ENV *m);\r
226uint16 fetch_word_imm (PC_ENV *m);\r
227uint16 decode_rm00_address (PC_ENV *m, int rm);\r
228uint16 decode_rm01_address (PC_ENV *m, int rm);\r
229uint16 decode_rm10_address (PC_ENV *m, int rm);\r
230uint8 fetch_data_byte (PC_ENV *m, uint16 offset);\r
231uint8 fetch_data_byte_abs (PC_ENV *m, uint16 segment, uint16 offset);\r
232uint16 fetch_data_word (PC_ENV *m, uint16 offset);\r
233uint16 fetch_data_word_abs (PC_ENV *m, uint16 segment, uint16 offset);\r
234void store_data_byte (PC_ENV *m, uint16 offset, uint8 val);\r
235void store_data_byte_abs (PC_ENV *m, uint16 segment, uint16 offset, uint8 val);\r
236void store_data_word (PC_ENV *m, uint16 offset, uint16 val);\r
237void store_data_word_abs (PC_ENV *m, uint16 segment, uint16 offset, uint16 val);\r
238\r
239typedef void (*OP)(PC_ENV *m);\r
240extern OP i86_optab[256];\r
241\r
242/* PRIMITIVE OPERATIONS */\r
243\r
244uint8 aad_word (PC_ENV *m, uint16 d);\r
245uint16 aam_word (PC_ENV *m, uint8 d);\r
246uint8 adc_byte (PC_ENV *m, uint8 d, uint8 s);\r
247uint16 adc_word (PC_ENV *m, uint16 d, uint16 s);\r
248uint8 add_byte (PC_ENV *m, uint8 d, uint8 s);\r
249uint16 add_word (PC_ENV *m, uint16 d, uint16 s);\r
250uint8 and_byte (PC_ENV *m, uint8 d, uint8 s);\r
251uint16 and_word (PC_ENV *m, uint16 d, uint16 s);\r
252uint8 cmp_byte (PC_ENV *m, uint8 d, uint8 s);\r
253uint16 cmp_word (PC_ENV *m, uint16 d, uint16 s);\r
254uint8 dec_byte (PC_ENV *m, uint8 d);\r
255uint16 dec_word (PC_ENV *m, uint16 d);\r
256uint8 inc_byte (PC_ENV *m, uint8 d);\r
257uint16 inc_word (PC_ENV *m, uint16 d);\r
258uint8 or_byte (PC_ENV *m, uint8 d, uint8 s);\r
259uint16 or_word (PC_ENV *m, uint16 d, uint16 s);\r
260uint8 neg_byte (PC_ENV *m, uint8 s);\r
261uint16 neg_word (PC_ENV *m, uint16 s);\r
262uint8 not_byte (PC_ENV *m, uint8 s);\r
263uint16 not_word (PC_ENV *m, uint16 s);\r
264uint16 mem_access_word (PC_ENV *m, int addr);\r
265void push_word (PC_ENV *m, uint16 w);\r
266uint16 pop_word (PC_ENV *m);\r
267uint8 rcl_byte (PC_ENV *m, uint8 d, uint8 s);\r
268uint16 rcl_word (PC_ENV *m, uint16 d, uint16 s);\r
269uint8 rcr_byte (PC_ENV *m, uint8 d, uint8 s);\r
270uint16 rcr_word (PC_ENV *m, uint16 d, uint16 s);\r
271uint8 rol_byte (PC_ENV *m, uint8 d, uint8 s);\r
272uint16 rol_word (PC_ENV *m, uint16 d, uint16 s);\r
273uint8 ror_byte (PC_ENV *m, uint8 d, uint8 s);\r
274uint16 ror_word (PC_ENV *m, uint16 d, uint16 s);\r
275uint8 shl_byte (PC_ENV *m, uint8 d, uint8 s) ;\r
276uint16 shl_word (PC_ENV *m, uint16 d, uint16 s);\r
277uint8 shr_byte (PC_ENV *m, uint8 d, uint8 s);\r
278uint16 shr_word (PC_ENV *m, uint16 d, uint16 s);\r
279uint8 sar_byte (PC_ENV *m, uint8 d, uint8 s);\r
280uint16 sar_word (PC_ENV *m, uint16 d, uint16 s);\r
281uint8 sbb_byte (PC_ENV *m, uint8 d, uint8 s);\r
282uint16 sbb_word (PC_ENV *m, uint16 d, uint16 s);\r
283uint8 sub_byte (PC_ENV *m, uint8 d, uint8 s);\r
284uint16 sub_word (PC_ENV *m, uint16 d, uint16 s);\r
285void test_byte (PC_ENV *m, uint8 d, uint8 s);\r
286void test_word (PC_ENV *m, uint16 d, uint16 s);\r
287uint8 xor_byte (PC_ENV *m, uint8 d, uint8 s);\r
288uint16 xor_word (PC_ENV *m, uint16 d, uint16 s);\r
289void imul_byte (PC_ENV *m, uint8 s);\r
290void imul_word (PC_ENV *m, uint16 s);\r
291void mul_byte (PC_ENV *m, uint8 s);\r
292void mul_word (PC_ENV *m, uint16 s);\r
293void idiv_byte (PC_ENV *m, uint8 s);\r
294void idiv_word (PC_ENV *m, uint16 s);\r
295void div_byte (PC_ENV *m, uint8 s);\r
296void div_word (PC_ENV *m, uint16 s);\r