From f03e370c6f0ab3bfc27a1020f2da438020ec1ad6 Mon Sep 17 00:00:00 2001 From: Bill Beech Date: Wed, 3 Aug 2022 13:15:03 -0700 Subject: [PATCH] Intel-MDS: Update to the latest and fix inconsistent REGister declarations --- Intel-Systems/Intel-MDS/imds_sys.c | 2 +- Intel-Systems/Intel-MDS/system_defs.h | 13 +- Intel-Systems/common/i3214.c | 49 +- Intel-Systems/common/i8080.c | 315 +- Intel-Systems/common/i8088.c | 8282 ++++++++++------------- Intel-Systems/common/i8237.c | 563 +- Intel-Systems/common/i8251.c | 21 +- Intel-Systems/common/i8253.c | 373 +- Intel-Systems/common/i8255.c | 11 +- Intel-Systems/common/i8259.c | 38 +- Intel-Systems/common/ieprom.c | 5 +- Intel-Systems/common/ioc-cont.c | 10 +- Intel-Systems/common/ipc-cont.c | 10 +- Intel-Systems/common/iram8.c | 8 +- Intel-Systems/common/irq.c | 5 +- Intel-Systems/common/isbc064.c | 19 +- Intel-Systems/common/isbc201.c | 10 +- Intel-Systems/common/isbc202.c | 27 +- Intel-Systems/common/isbc206.c | 15 +- Intel-Systems/common/isbc208.c | 2656 ++++---- Intel-Systems/common/isbc464.c | 12 +- Intel-Systems/common/mem.c | 27 +- Intel-Systems/common/multibus.c | 18 +- Intel-Systems/common/port.c | 5 +- Intel-Systems/common/sys.c | 168 +- Intel-Systems/common/zx200a.c | 86 +- Visual Studio Projects/Intel-MDS.vcproj | 4 + 27 files changed, 6081 insertions(+), 6671 deletions(-) diff --git a/Intel-Systems/Intel-MDS/imds_sys.c b/Intel-Systems/Intel-MDS/imds_sys.c index 22208d2b..61bf1161 100644 --- a/Intel-Systems/Intel-MDS/imds_sys.c +++ b/Intel-Systems/Intel-MDS/imds_sys.c @@ -1,4 +1,4 @@ -/* mds210_sys.c: multibus system interface +/* imds_sys.c: multibus system interface Copyright (c) 2017, William A. Beech diff --git a/Intel-Systems/Intel-MDS/system_defs.h b/Intel-Systems/Intel-MDS/system_defs.h index ce9b9ee8..f1391548 100644 --- a/Intel-Systems/Intel-MDS/system_defs.h +++ b/Intel-Systems/Intel-MDS/system_defs.h @@ -87,18 +87,18 @@ #define SBC206_NUM 0 /* set the base I/O address for the iSBC 208 */ -#define SBC208_BASE 0x40 -#define SBC208_INT INT_1 +//#define SBC208_BASE 0x40 +//#define SBC208_INT INT_1 #define SBC208_NUM 0 /* set the base for the zx-200a disk controller */ -#define ZX200A_BASE 0x78 -#define ZX200A_INT INT_1 +//#define ZX200A_BASE 0x78 +//#define ZX200A_INT INT_1 #define ZX200A_NUM 0 /* set the base and size for the iSBC 464 ROM */ -#define SBC464_BASE 0xA800 -#define SBC464_SIZE 0x47FF +//#define SBC464_BASE 0xA800 +//#define SBC464_SIZE 0x47FF #define SBC464_NUM 0 /* set the base and size for the iSBC 064 RAM */ @@ -132,6 +132,7 @@ #define MAXMEMSIZE 0x0FFFF /* 8080 max memory size */ #define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ #define ADDRMASK (MAXMEMSIZE) /* 8080 address mask */ +#define BYTEMASK 0xff //byte mask #define MEM_ADDR_OK(x) (((uint16) (x)) <= MEMSIZE) /* debug definitions */ diff --git a/Intel-Systems/common/i3214.c b/Intel-Systems/common/i3214.c index 9529b5a4..34418713 100644 --- a/Intel-Systems/common/i3214.c +++ b/Intel-Systems/common/i3214.c @@ -39,9 +39,9 @@ */ #include "system_defs.h" -#define IPC 0 - -#define i3214_NAME "Intel i3214 Perpherial Interrupt Contrlooer Chip" +#define UNIT_V_BOOT (UNIT_V_UF+1) /* BOOT/RUN switch */ +#define UNIT_BOOT (1 << UNIT_V_BOOT) +#define i3214_NAME "Intel i3214 Perpherial Interrupt Controller Chip" /* external globals */ @@ -62,8 +62,8 @@ static const char* i3214_desc(DEVICE *dptr) { return i3214_NAME; } int i3214_baseport = -1; //base port -uint8 i3214_intnum = 0; //interrupt number -uint8 i3214_verb = 0; //verbose flag +uint8 i3214_intnum = 0; //interrupt number +uint8 i3214_verb = 0; //verbose flag /* function prototypes */ @@ -98,14 +98,14 @@ DEBTAB i3214_debug[] = { { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, { NULL } }; MTAB i3214_mod[] = { + { UNIT_BOOT, 0, "BOOT", "BOOT", NULL }, + { UNIT_BOOT, UNIT_BOOT, "RUN", "RUN", NULL }, { MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, i3214_show_param, NULL, - "show configured parametes for i3214" }, + "show configured parameters for i3214" }, { 0 } }; @@ -144,7 +144,7 @@ DEVICE i3214_dev = { t_stat i3214_cfg(uint16 base, uint16 devnum, uint8 dummy) { - i3214_baseport = base & 0xff; + i3214_baseport = base & BYTEMASK; sim_printf(" i3214: at base port 0%02XH\n", i3214_baseport); reg_dev(i3214_do_mask, i3214_baseport, 0, 0); @@ -213,18 +213,18 @@ t_stat i3214_reset_dev (uint8 devnum) uint8 i3214_do_mask(t_bool io, uint8 data, uint8 devnum) { - if (io == 0) /* read status port */ + if (io == 0) //read port return i3214_mask; - else + else //write port i3214_mask = data; return 0; } uint8 i3214_do_status(t_bool io, uint8 data, uint8 devnum) { - if (io == 0) + if (io == 0) //read port return 0; - else { + else { //write port i3214_cnt--; } return 0; @@ -232,18 +232,31 @@ uint8 i3214_do_status(t_bool io, uint8 data, uint8 devnum) uint8 i3214_cpu_bus_override(t_bool io, uint8 data, uint8 devnum) { - if (io == 0) /* read status port */ + if (io == 0) //read port return 0; - else + else //write port BUS_OVERRIDE = data & 0x01; return 0; } uint8 i3214_monitor_do_boot(t_bool io, uint8 data, uint8 devnum) { - if (io == 0) /* read status port */ - return monitor_boot; - else + UNIT *uptr; + static uint8 onetime = 1; + + uptr = i3214_unit; + if (io == 0) //read port + if (uptr->flags & UNIT_BOOT) { //toggle response + monitor_boot = 0; + printf(" Boot Switch set to BOOT\n"); + } else { + monitor_boot = 0x02; + if (onetime) { + printf(" Boot Switch set to RUN\n"); + onetime = 0; + } + } + else //write port monitor_boot = data; return 0; } diff --git a/Intel-Systems/common/i8080.c b/Intel-Systems/common/i8080.c index 76eace34..d7500489 100644 --- a/Intel-Systems/common/i8080.c +++ b/Intel-Systems/common/i8080.c @@ -113,10 +113,10 @@ #define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */ #define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) -#define UNIT_V_8085 (UNIT_V_UF+1) /* 8080/8085 switch */ +#define UNIT_V_MSTOP (UNIT_V_UF+1) /* Stop on Invalid memory? */ +#define UNIT_MSTOP (1 << UNIT_V_MSTOP) +#define UNIT_V_8085 (UNIT_V_UF+2) /* 8080/8085 switch */ #define UNIT_8085 (1 << UNIT_V_8085) -#define UNIT_V_TRACE (UNIT_V_UF+2) /* Trace switch */ -#define UNIT_TRACE (1 << UNIT_V_TRACE) #define UNIT_V_XACK (UNIT_V_UF+3) /* XACK switch */ #define UNIT_XACK (1 << UNIT_V_XACK) @@ -159,6 +159,24 @@ #define i8080_NAME "Intel i8080/85 Processor Chip" +#define HIST_MIN 64 +#define HIST_MAX (1u << 18) +#define HIST_ILNT 3 /* max inst length */ + +typedef struct { + uint16 pc; + uint16 sp; + uint8 psw; + uint8 a; + uint8 b; + uint8 c; + uint8 d; + uint8 e; + uint8 h; + uint8 l; + t_value inst[HIST_ILNT]; + } InstHistory; + /* storage for the rest of the registers */ uint32 PSW = 0; /* program status word */ uint32 A = 0; /* accumulator */ @@ -179,6 +197,11 @@ uint16 port; //port used in any IN/OUT uint16 addr; //addr used for operand fetch uint32 IR; uint16 devnum = 0; +uint8 cpu_onetime = 0; + +int32 hst_p = 0; /* history pointer */ +int32 hst_lnt = 0; /* history length */ +InstHistory *hst = NULL; /* instruction history */ static const char* i8080_desc(DEVICE *dptr) { return i8080_NAME; @@ -203,6 +226,8 @@ void putpush(int32 reg, int32 data); void putpair(int32 reg, int32 val); void parity(int32 reg); int32 cond(int32 con); +t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat i8080_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); t_stat i8080_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); t_stat i8080_reset (DEVICE *dptr); @@ -256,14 +281,16 @@ REG i8080_reg[] = { }; MTAB i8080_mod[] = { + { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL }, + { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL }, + { UNIT_MSTOP, UNIT_MSTOP, "MTRAP", "MTRAP", NULL }, + { UNIT_MSTOP, 0, "NOMTRAP", "NOMTRAP", NULL }, { UNIT_8085, 0, "8080", "8080", NULL }, { UNIT_8085, UNIT_8085, "8085", "8085", NULL }, - { UNIT_OPSTOP, 0, "ITRAP", "ITRAP", NULL }, - { UNIT_OPSTOP, UNIT_OPSTOP, "NOITRAP", "NOITRAP", NULL }, - { UNIT_TRACE, 0, "NOTRACE", "NOTRACE", NULL }, - { UNIT_TRACE, UNIT_TRACE, "TRACE", "TRACE", NULL }, { UNIT_XACK, 0, "NOXACK", "NOXACK", NULL }, { UNIT_XACK, UNIT_XACK, "XACK", "XACK", NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP|MTAB_NC, 0, "HISTORY", "HISTORY=n", + &cpu_set_hist, &cpu_show_hist, NULL, "Enable/Display instruction history" }, { 0 } }; @@ -272,15 +299,12 @@ DEBTAB i8080_debug[] = { { "FLOW", DEBUG_flow }, { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { "REG", DEBUG_reg }, - { "ASM", DEBUG_asm }, + { "XACK", DEBUG_xack }, { NULL } }; DEVICE i8080_dev = { - "I8080", //name + "CPU", //name &i8080_unit, //units i8080_reg, //registers i8080_mod, //modifiers @@ -292,7 +316,7 @@ DEVICE i8080_dev = { 8, //dwidth &i8080_ex, //examine &i8080_dep, //deposit - NULL, //reset + &i8080_reset, //reset NULL, //boot NULL, //attach NULL, //detach @@ -405,15 +429,17 @@ void set_cpuint(int32 int_num) int32 sim_instr(void) { extern int32 sim_interval; - uint32 OP, DAR, reason, adr, i8080_onetime = 0; + uint32 OP, DAR, reason, adr; + int i; + InstHistory *hst_ent = NULL; PC = saved_PC & WORD_R; /* load local PC */ reason = 0; uptr = i8080_dev.units; - if (i8080_onetime++ == 0) { - if (uptr->flags & UNIT_8085) + if (cpu_onetime++ == 0) { + if ((uptr->flags & UNIT_8085)) sim_printf(" CPU = 8085\n"); else sim_printf(" CPU = 8080\n"); @@ -462,7 +488,7 @@ int32 sim_instr(void) if (IM & IE) { /* enabled? */ INTA = 1; push_word(PC); /* do an RST 2 */ - PC = 0x0010; + PC = 0x0038; int_req = 0; // sim_printf("8080 Interrupt\n"); } @@ -471,13 +497,28 @@ int32 sim_instr(void) if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ +// dumpregs(); reason = STOP_IBKPT; /* stop simulation */ break; } - if (uptr->flags & UNIT_TRACE) { - dumpregs(); -// sim_printf("\n"); + if (hst_lnt) { /* record history? */ + hst_ent = &hst[hst_p]; + hst_ent->pc = PC; + hst_ent->sp = SP; + hst_ent->psw = PSW; + hst_ent->a = A; + hst_ent->b = (BC >> 8) & 0xFF; + hst_ent->c = (BC & 0xFF); + hst_ent->d = (DE >> 8) & 0xFF; + hst_ent->e = (DE & 0xFF); + hst_ent->h = (HL >> 8) & 0xFF; + hst_ent->l = (HL & 0xFF); + for (i = 0; i < HIST_ILNT; i++) + hst_ent->inst[i] = (t_value)get_mbyte (PC + i); + hst_p = (hst_p + 1); + if (hst_p >= hst_lnt) + hst_p = 0; } sim_interval--; /* countdown clock */ @@ -897,13 +938,13 @@ int32 sim_instr(void) case 0xDB: /* IN */ SET_XACK(1); /* good I/O address */ port = fetch_byte(1); - A = dev_table[port].routine(0, 0, dev_table[port].devnum & 0xff); + A = dev_table[port].routine(0, 0, dev_table[port].devnum & BYTEMASK); break; case 0xD3: /* OUT */ SET_XACK(1); /* good I/O address */ port = fetch_byte(1); - dev_table[port].routine(1, A, dev_table[port].devnum & 0xff); + dev_table[port].routine(1, A, dev_table[port].devnum & BYTEMASK); break; default: /* undefined opcode */ @@ -955,7 +996,7 @@ int32 fetch_byte(int32 flag) val = get_mbyte(PC) & 0xFF; /* fetch byte */ PC = (PC + 1) & ADDRMASK; /* increment PC */ - addr = val & 0xff; + addr = val & BYTEMASK; return val; } @@ -1240,7 +1281,7 @@ void putpair(int32 reg, int32 val) /* Reset routine */ -t_stat i8080_reset (DEVICE *dptr) +t_stat i8080_reset(DEVICE *dptr) { PSW = PSW_ALWAYS_ON; CLR_FLAG(CF); @@ -1253,54 +1294,106 @@ t_stat i8080_reset (DEVICE *dptr) return SCPE_OK; } -/* Memory examine */ - -t_stat i8080_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ - if (addr >= MEMSIZE) - return SCPE_NXM; - if (vptr != NULL) - *vptr = get_mbyte(addr); - return SCPE_OK; -} - -/* Memory deposit */ - -t_stat i8080_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ - if (addr >= MEMSIZE) - return SCPE_NXM; - put_mbyte(addr, val); - return SCPE_OK; -} - -/* This is the binary loader. The input file is considered to be - a string of literal bytes with no special format. The load - starts at the current value of the PC. +/* This is the dumper/loader. This command uses the -h to signify a + hex dump/load vice a binary one. If no address is given to load, it + takes the address from the hex record or the current PC for binary. */ -int32 sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) -{ - int32 i, addr = 0, cnt = 0; +#define HLEN 16 - if ((*cptr != 0)) return SCPE_ARG; - if (flag == 0) { //load -// addr = saved_PC; - while ((i = getc (fileref)) != EOF) { - put_mbyte(addr, i); - addr++; - cnt++; - } /* end while */ - sim_printf ("%d Bytes loaded.\n", cnt); +int32 sim_load(FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) +{ + int32 i, addr = 0, addr0 = 0, cnt = 0, cnt0 = 0, start = 0x10000; + int32 addr1 = 0, end = 0, byte, chk, rtype, flag0 = 1; + char buf[128], data[128], *p; + + printf("sim_load cptr=%s fnam=%s flag=%d\n", cptr, fnam, flag); + cnt = sscanf(cptr, " %04X %04X", &start, &end); + addr=start; + printf("cnt=%d start=%05X end=%05X\n", cnt, start, end); + if (flag == 0) { //load + if (sim_switches & SWMASK ('H')) { //hex + if (cnt > 1) //2 arguments - error + return SCPE_ARG; + cnt = 0; + while (fgets(buf, sizeof(buf)-1, fileref)) { + sscanf(buf, " :%02x%04x%02x%s", &cnt, &addr, &rtype, data); + if (rtype == 0) { + chk = 0; + chk -= HLEN; + chk -= addr & BYTEMASK; + chk -= addr >> 8; + p = (char *) data; + for (i=0; i<=cnt; i++) { + sscanf (p, "%2x", &byte); + p += 2; + put_mbyte(addr + i, byte); + chk -= byte; chk &= BYTEMASK; + cnt++; + } + sscanf (p, "%2x", &byte); + if (chk == 0) + printf("+"); + else + printf("-"); + } else + return SCPE_ARG; + } + } else { //binary + cnt = 0; + addr1 = addr; + while ((i = getc (fileref)) != EOF) { + put_mbyte(addr, i); + addr++; cnt++; + } + } + printf ("%d Bytes loaded at %04X\n", cnt, addr1); return (SCPE_OK); } else { //dump -// addr = saved_PC; - while (addr <= 0xffff) { - i = get_mbyte(addr); - putc(i, fileref); - addr++; - cnt++; + if (cnt != 2) //must be 2 arguments + return SCPE_ARG; + cnt = 0; + addr0 = addr; + if (sim_switches & SWMASK ('H')) { //hex + while((addr + HLEN) < end) { //full records + fprintf(fileref,":%02X%04X00", HLEN, addr); + chk = 0; + chk -= HLEN; + chk -= addr & BYTEMASK; + chk -= addr >> 8; + for (i=0; i> 8; + for (i=0; i<=(end - addr); i++) { + byte = get_mbyte(addr + i); + fprintf(fileref, "%02X", byte & BYTEMASK); + chk -= byte; chk &= BYTEMASK; + cnt++; + } + fprintf(fileref, "%02X\n", chk); + addr = end; + } + fprintf(fileref,":00000001FF\n"); //EOF record + } else { //binary + while (addr <= end) { + i = get_mbyte(addr); + putc(i, fileref); + addr++; cnt++; + } } + printf ("%d Bytes dumped from %04X\n", cnt, addr0); } return (SCPE_OK); } @@ -1316,7 +1409,7 @@ int32 sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) status = error code */ -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, +t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) { int32 cflag, c1, c2, inst, adr; @@ -1364,7 +1457,7 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, status = error status */ -t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) +t_stat parse_sym(CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) { int32 cflag, i = 0, j, r; char gbuf[CBUFSIZE]; @@ -1448,4 +1541,90 @@ t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 return (-2); } +/* Set history */ + +t_stat cpu_set_hist(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + int i, lnt; + t_stat r; + + if (cptr == NULL) { + for (i = 0; i < hst_lnt; i++) + hst[i].pc = 0; + hst_p = 0; + return SCPE_OK; + } + lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); + if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) + return SCPE_ARG; + hst_p = 0; + if (hst_lnt) { + free (hst); + hst_lnt = 0; + hst = NULL; + } + if (lnt) { + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) + return SCPE_MEM; + hst_lnt = lnt; + } + return SCPE_OK; +} + +/* Show history */ + +t_stat cpu_show_hist(FILE *st, UNIT *uptr, int32 val, CONST void *desc) +{ + int k, di, lnt, ir; + const char *cptr = (const char *) desc; + t_stat r; + InstHistory *h; + + if (hst_lnt == 0) /* enabled? */ + return SCPE_NOFNC; + if (cptr) { + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) + return SCPE_ARG; + } + else lnt = hst_lnt; + di = hst_p - lnt; /* work forward */ + if (di < 0) + di = di + hst_lnt; + fprintf (st, "PC SP CC A B C D E F H L Instruction\n\n"); + for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(di++) % hst_lnt]; /* entry pointer */ + ir = h->inst[0]; + fprintf (st, "%04X %04X %02X ", h->pc , h->sp, h->psw); + fprintf (st, "%02X %02X %02X %02X %02X %02X %02X ", + h->a, h->b, h->c, h->d, h->e, h->h, h->l); + if ((fprint_sym (st, h->pc, h->inst, &i8080_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %02X", h->inst[0]); + fputc ('\n', st); /* end line */ + } + return SCPE_OK; +} + +/* Memory examine */ + +t_stat i8080_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) +{ + if (addr >= MEMSIZE) + return SCPE_NXM; + if (vptr != NULL) + *vptr = get_mbyte(addr); + return SCPE_OK; +} + +/* Memory deposit */ + +t_stat i8080_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) +{ + if (addr >= MEMSIZE) + return SCPE_NXM; + put_mbyte(addr, val); + return SCPE_OK; +} + /* end of i8080.c */ diff --git a/Intel-Systems/common/i8088.c b/Intel-Systems/common/i8088.c index 0bf628fd..724fd061 100644 --- a/Intel-Systems/common/i8088.c +++ b/Intel-Systems/common/i8088.c @@ -1,375 +1,26 @@ -/* i8088.c: Intel 8086/8088 CPU simulator - - Copyright (C) 1991 Jim Hudgens - - The file is part of GDE. - - GDE is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) - any later version. - - GDE is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GDE; see the file COPYING. If not, write to - the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - - This software was modified by Bill Beech, Mar 2011, from the software GDE - of Jim Hudgens as provided with the SIMH AltairZ80 emulation package. - - Copyright (c) 2011, William A. Beech - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of William A. Beech shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from William A. Beech. - - cpu 8088 CPU - - 17 Mar 11 WAB Original code - - The register state for the 8088 CPU is: - - AX<0:15> AH/AL Register Pair - BX<0:15> BH/BL Register Pair - CX<0:15> CH/CL Register Pair - DX<0:15> DH/DL Register Pair - SI<0:15> Source Index Register - DI<0:15> Destination Index Register - BP<0:15> Base Pointer - SP<0:15> Stack Pointer - CS<0:15> Code Segment Register - DS<0:15> Date Segment Register - SS<0:15> Stack Segment Register - ES<0:15> Extra Segment Register - IP<0:15> Program Counter - - PSW<0:15> Program Status Word - Contains the following flags: - - AF Auxillary Flag - CF Carry Flag - OF Overflow Flag - SF Sign Flag - PF Parity Flag - ZF Zero Flag - DF Direction Flag - IF Interrupt Enable Flag - TF Trap Flag - - in bit positions: - 15 8 7 0 - |--|--|--|--|OF|DF|IF|TF|SF|ZF|--|AF|--|PF|--|CF| - - The 8088 is an 8-bit CPU, which uses 16-bit offset and segment registers - in combination with a dedicated adder to address up to 1MB of memory directly. - The offset register is added to the segment register shifted left 4 places - to obtain the 20-bit address. - - The CPU utilizes two separate processing units - the Execution Unit (EU) and - the Bus Interface Unit (BIU). The EU executes instructions. The BIU fetches - instructions, reads operands and writes results. The two units can operate - independently of one another and are able, under most circumstances, to - extensively overlap instruction fetch with execution. - - The BIUs of the 8086 and 8088 are functionally identical, but are implemented - differently to match the structure and performance characteristics of their - respective buses. - - The almost 300 instructions come in 1, 2, 3, 4, 5, 6 and 7-byte flavors. - - This routine is the simulator for the 8088. It is called from the - simulator control program to execute instructions in simulated memory, - starting at the simulated IP. It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - I/O error in I/O simulator - Invalid OP code (if ITRAP is set on CPU) - - 2. Interrupts. - There are 256 possible levels of interrupt, and in effect they - do a hardware CALL instruction to one of 256 possible low - memory addresses. - - 3. Non-existent memory. On the 8088, reads to non-existent memory - return 0FFh, and writes are ignored. - - Some algorithms were pulled from the GDE Dos/IP Emulator by Jim Hudgens - -*/ -/* - This algorithm was pulled from the GDE Dos/IP Emulator by Jim Hudgens - -CARRY CHAIN CALCULATION. - This represents a somewhat expensive calculation which is - apparently required to emulate the setting of the OF and - AF flag. The latter is not so important, but the former is. - The overflow flag is the XOR of the top two bits of the - carry chain for an addition (similar for subtraction). - Since we do not want to simulate the addition in a bitwise - manner, we try to calculate the carry chain given the - two operands and the result. - - So, given the following table, which represents the - addition of two bits, we can derive a formula for - the carry chain. - - a b cin r cout - 0 0 0 0 0 - 0 0 1 1 0 - 0 1 0 1 0 - 0 1 1 0 1 - 1 0 0 1 0 - 1 0 1 0 1 - 1 1 0 0 1 - 1 1 1 1 1 - - Construction of table for cout: - - ab - r \ 00 01 11 10 - |------------------ - 0 | 0 1 1 1 - 1 | 0 0 1 0 - - By inspection, one gets: cc = ab + r'(a + b) - - That represents alot of operations, but NO CHOICE.... - -BORROW CHAIN CALCULATION. - The following table represents the - subtraction of two bits, from which we can derive a formula for - the borrow chain. - - a b bin r bout - 0 0 0 0 0 - 0 0 1 1 1 - 0 1 0 1 1 - 0 1 1 0 1 - 1 0 0 1 0 - 1 0 1 0 0 - 1 1 0 0 0 - 1 1 1 1 1 - - Construction of table for cout: - - ab - r \ 00 01 11 10 - |------------------ - 0 | 0 1 0 0 - 1 | 1 1 1 0 - - By inspection, one gets: bc = a'b + r(a' + b) - - Segment register selection and overrides are handled as follows: - If there is a segment override, the register number is stored - in seg_ovr. If there is no override, seg_ovr is zero. Seg_ovr - is set to zero after each instruction except segment override - instructions. - - Get_ea sets the value of seg_reg to the override if present - otherwise to the default value for the registers used in the - effective address calculation. - - The get/put_smword/byte routines use the register number in - seg_reg to obtain the segment value to calculate the absolute - memory address for the operation. - */ - -#include -#include "system_defs.h" - -#define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */ -#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) -#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8088 or 8086 */ -#define UNIT_CHIP (1 << UNIT_V_CHIP) - -/* Flag values to set proper positions in PSW */ -#define CF 0x0001 -#define PF 0x0004 -#define AF 0x0010 -#define ZF 0x0040 -#define SF 0x0080 -#define TF 0x0100 -#define IF 0x0200 -#define DF 0x0400 -#define OF 0x0800 - -/* Macros to handle the flags in the PSW - 8088 has top 4 bits of the flags set to 1 - also, bit#1 is set. This is (not well) documented behavior. */ -#define PSW_ALWAYS_ON (0xF002) /* for 8086 */ -#define PSW_MSK (CF|PF|AF|ZF|SF|TF|IF|DF|OF) -#define TOGGLE_FLAG(FLAG) (PSW ^= FLAG) -#define SET_FLAG(FLAG) (PSW |= FLAG) -#define CLR_FLAG(FLAG) (PSW &= ~FLAG) -#define GET_FLAG(FLAG) (PSW & FLAG) -#define CONDITIONAL_SET_FLAG(COND,FLAG) \ - if (COND) SET_FLAG(FLAG); else CLR_FLAG(FLAG) - -/* union of byte and word registers */ -union { - uint8 b[2]; /* two bytes */ - uint16 w; /* one word */ -} A, B, C, D; /* storage for AX, BX, CX and DX */ - -/* macros for byte registers */ -#define AH (A.b[1]) -#define AL (A.b[0]) -#define BH (B.b[1]) -#define BL (B.b[0]) -#define CH (C.b[1]) -#define CL (C.b[0]) -#define DH (D.b[1]) -#define DL (D.b[0]) - -/* macros for word registers */ -#define AX (A.w) -#define BX (B.w) -#define CX (C.w) -#define DX (D.w) - -/* storage for the rest of the registers */ -int32 DI; /* Source Index Register */ -int32 SI; /* Destination Index Register */ -int32 BP; /* Base Pointer Register */ -int32 SP; /* Stack Pointer Register */ -int32 CS; /* Code Segment Register */ -int32 DS; /* Data Segment Register */ -int32 SS; /* Stack Segment Register */ -int32 ES; /* Extra Segment Register */ -uint32 IP; /* Program Counter */ -int32 PSW; /* Program Status Word (Flags) */ -uint32 saved_PC = 0; /* saved program counter */ -int32 int_req = 0; /* Interrupt request 0x01 = int, 0x02 = NMI*/ -uint16 port; //port called in dev_table[port] -int32 chip = 0; /* 0 = 8088 chip, 1 = 8086 chip */ -#define CHIP_8088 0 /* processor types */ -#define CHIP_8086 1 -#define CHIP_80188 2 -#define CHIP_80186 3 -#define CHIP_80286 4 - -int32 seg_ovr = 0; /* segment override register */ -int32 seg_reg = 0; /* segment register to use for EA */ -#define SEG_NONE 0 /* segmenr override register values */ -#define SEG_CS 8 -#define SEG_DS 9 -#define SEG_ES 10 -#define SEG_SS 11 - -int32 PCX; /* External view of IP */ - -/* handle prefix instructions */ -uint32 sysmode = 0; /* prefix flags */ -#define SYSMODE_SEG_DS_SS 0x01 -#define SYSMODE_SEGOVR_CS 0x02 -#define SYSMODE_SEGOVR_DS 0x04 -#define SYSMODE_SEGOVR_ES 0x08 -#define SYSMODE_SEGOVR_SS 0x10 -#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | SYSMODE_SEGOVR_CS | \ - SYSMODE_SEGOVR_DS | SYSMODE_SEGOVR_ES | SYSMODE_SEGOVR_SS) -#define SYSMODE_PREFIX_REPE 0x20 -#define SYSMODE_PREFIX_REPNE 0x40 - -/* function prototypes */ -int32 sign_ext(int32 val); -int32 fetch_byte(int32 flag); -int32 fetch_word(void); -int32 parity(int32 val); -void i86_intr_raise(uint8 num); -uint32 get_rbyte(uint32 reg); -uint32 get_rword(uint32 reg); -void put_rbyte(uint32 reg, uint32 val); -void put_rword(uint32 reg, uint32 val); -uint32 get_ea(uint32 mrr); -void set_segreg(uint32 reg); -void get_mrr_dec(uint32 mrr, uint32 *mod, uint32 *reg, uint32 *rm); -void rm_byte_dec(uint32 rm); -void rm_word_dec(uint32 rm); -void rm_seg_dec(uint32 rm); - -/* emulator primitives function prototypes */ -uint8 aad_word(uint16 d); -uint16 aam_word(uint8 d); -uint8 adc_byte(uint8 d, uint8 s); -uint16 adc_word(uint16 d, uint16 s); -uint8 add_byte(uint8 d, uint8 s); -uint16 add_word(uint16 d, uint16 s); -uint8 and_byte(uint8 d, uint8 s); -uint16 cmp_word(uint16 d, uint16 s); -uint8 cmp_byte(uint8 d, uint8 s); -uint16 and_word(uint16 d, uint16 s); -uint8 dec_byte(uint8 d); -uint16 dec_word(uint16 d); -void div_byte(uint8 s); -void div_word(uint16 s); -void idiv_byte(uint8 s); -void idiv_word(uint16 s); -void imul_byte(uint8 s); -void imul_word(uint16 s); -uint8 inc_byte(uint8 d); -uint16 inc_word(uint16 d); -void mul_byte(uint8 s); -void mul_word(uint16 s); -uint8 neg_byte(uint8 s); -uint16 neg_word(uint16 s); -uint8 not_byte(uint8 s); -uint16 not_word(uint16 s); -uint8 or_byte(uint8 d, uint8 s); -uint16 or_word(uint16 d, uint16 s); -void push_word(uint16 val); -uint16 pop_word(void); -uint8 rcl_byte(uint8 d, uint8 s); -uint16 rcl_word(uint16 d, uint16 s); -uint8 rcr_byte(uint8 d, uint8 s); -uint16 rcr_word(uint16 d, uint16 s); -uint8 rol_byte(uint8 d, uint8 s); -uint16 rol_word(uint16 d, uint16 s); -uint8 ror_byte(uint8 d, uint8 s); -uint16 ror_word(uint16 d, uint16 s); -uint8 shl_byte(uint8 d, uint8 s); -uint16 shl_word(uint16 d, uint16 s); -uint8 shr_byte(uint8 d, uint8 s); -uint16 shr_word(uint16 d, uint16 s); -uint8 sar_byte(uint8 d, uint8 s); -uint16 sar_word(uint16 d, uint16 s); -uint8 sbb_byte(uint8 d, uint8 s); -uint16 sbb_word(uint16 d, uint16 s); -uint8 sub_byte(uint8 d, uint8 s); -uint16 sub_word(uint16 d, uint16 s); -void test_byte(uint8 d, uint8 s); -void test_word(uint16 d, uint16 s); -uint8 xor_byte(uint8 d, uint8 s); -uint16 xor_word(uint16 d, uint16 s); -int32 get_smbyte(int32 segreg, int32 addr); -int32 get_smword(int32 segreg, int32 addr); -void put_smbyte(int32 segreg, int32 addr, int32 val); -void put_smword(int32 segreg, int32 addr, int32 val); - +/* + Fake86: A portable, open-source 8086 PC emulator. + Copyright (C)2010-2012 Mike Chambers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* cpu.c: functions to emulate the 8086/V20 CPU in software. the heart of Fake86. */ + +#include "cpu.h" + /* simulator routines */ void set_cpuint(int32 int_num); int32 sim_instr(void); @@ -377,22 +28,151 @@ t_stat i8088_reset (DEVICE *dptr); t_stat i8088_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); t_stat i8088_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -/* external references */ - /* memory read and write absolute address routines */ extern uint8 get_mbyte(uint32 addr); extern uint16 get_mword(uint32 addr); extern void put_mbyte(uint32 addr, uint8 val); extern void put_mword(uint32 addr, uint16 val); -extern int32 sim_int_char; -extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - +extern void do_trace(void); +uint16 port; //port called in dev_table[port] + struct idev { - int32 (*routine)(); + uint8 (*routine)(t_bool io, uint8 data, uint8 devnum); + uint16 port; + uint16 devnum; + uint8 dummy; }; + extern struct idev dev_table[]; +uint64 curtimer, lasttimer, timerfreq; + +uint8 byteregtable[8] = { regal, regcl, regdl, regbl, regah, regch, regdh, regbh }; + +static const uint8 parity[0x100] = { + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 +}; + +uint8 RAM[0x100000], readonly[0x100000]; +uint8 OP, segoverride, reptype, bootdrive = 0, hdcount = 0; +uint16 segregs[4], SEG, OFF, IP, useseg, oldsp; +uint8 tempcf, oldcf, cf, pf, af, zf, sf, tf, ifl, df, of, MOD, REGX, RM; +uint16 oper1, oper2, res16, disp16, temp16, dummy, stacksize, frametemp; +uint8 oper1b, oper2b, res8, disp8, temp8, nestlev, addrbyte; +uint32 temp1, temp2, temp3, temp4, temp5, temp32, tempaddr32, EA; +int32 result; +uint64 totalexec; + +int32 AX, BX, CX, DX, DI, SI, BP, SP, CS, DS, SS, ES, PSW, PCX, SGX, DISP, DATA8, DATA16; + +//extern uint16 VGA_SC[0x100], VGA_CRTC[0x100], VGA_ATTR[0x100], VGA_GC[0x100]; +//extern uint8 updatedscreen; +union _bytewordregs_ regs; + +//uint8 portram[0x10000]; +uint8 running = 0, debugmode, showcsip, verbose, mouseemu, didbootstrap = 0; +//uint8 ethif; + +//extern uint8 vidmode; +extern uint8 verbose; +uint32 saved_PC = 0; /* saved program counter */ +int32 int_req = 0; /* Interrupt request 0x01 = int, 0x02 = NMI*/ + +//extern void vidinterrupt(); + +//extern uint8 readVGA (uint32 addr32); + +void intcall86 (uint8 intnum); + +#define makeflagsword() \ + ( \ + 2 | (uint16) cf | ((uint16) pf << 2) | ((uint16) af << 4) | ((uint16) zf << 6) | ((uint16) sf << 7) | \ + ((uint16) tf << 8) | ((uint16) ifl << 9) | ((uint16) df << 10) | ((uint16) of << 11) \ + ) + +#define decodeflagsword(x) { \ + temp16 = x; \ + cf = temp16 & 1; \ + pf = (temp16 >> 2) & 1; \ + af = (temp16 >> 4) & 1; \ + zf = (temp16 >> 6) & 1; \ + sf = (temp16 >> 7) & 1; \ + tf = (temp16 >> 8) & 1; \ + ifl = (temp16 >> 9) & 1; \ + df = (temp16 >> 10) & 1; \ + of = (temp16 >> 11) & 1; \ + } + +//extern void writeVGA (uint32 addr32, uint8 value); +//extern void portout (uint16 portnum, uint8 value); +//extern void portout16 (uint16 portnum, uint16 value); +//extern uint8 portin (uint16 portnum); +//extern uint16 portin16 (uint16 portnum); + +/* +void write86 (uint32 addr32, uint8 value) { + tempaddr32 = addr32 & 0xFFFFF; + if (readonly[tempaddr32] || (tempaddr32 >= 0xC0000) ) { + return; + } + + if ( (tempaddr32 >= 0xA0000) && (tempaddr32 <= 0xBFFFF) ) { + if ( (vidmode != 0x13) && (vidmode != 0x12) && (vidmode != 0xD) && (vidmode != 0x10) ) { + RAM[tempaddr32] = value; + updatedscreen = 1; + } + else if ( ( (VGA_SC[4] & 6) == 0) && (vidmode != 0xD) && (vidmode != 0x10) && (vidmode != 0x12) ) { + RAM[tempaddr32] = value; + updatedscreen = 1; + } + else { + writeVGA (tempaddr32 - 0xA0000, value); + } + + updatedscreen = 1; + } + else { + RAM[tempaddr32] = value; + } +} + +void writew86 (uint32 addr32, uint16 value) { + write86 (addr32, (uint8) value); + write86 (addr32 + 1, (uint8) (value >> 8) ); +} + +uint8 read86 (uint32 addr32) { + addr32 &= 0xFFFFF; + if ( (addr32 >= 0xA0000) && (addr32 <= 0xBFFFF) ) { + if ( (vidmode == 0xD) || (vidmode == 0xE) || (vidmode == 0x10) ) return (readVGA (addr32 - 0xA0000) ); + if ( (vidmode != 0x13) && (vidmode != 0x12) && (vidmode != 0xD) ) return (RAM[addr32]); + if ( (VGA_SC[4] & 6) == 0) + return (RAM[addr32]); + else + return (readVGA (addr32 - 0xA0000) ); + } + + if (!didbootstrap) { + RAM[0x410] = 0x41; //ugly hack to make BIOS always believe we have an EGA/VGA card installed + RAM[0x475] = hdcount; //the BIOS doesn't have any concept of hard drives, so here's another hack + } + + return (RAM[addr32]); +} + +uint16 readw86 (uint32 addr32) { + return ( (uint16) read86 (addr32) | (uint16) (read86 (addr32 + 1) << 8) ); +} +*/ + /* 8088 CPU data structures i8088_dev CPU device descriptor @@ -405,28 +185,11 @@ UNIT i8088_unit = { UDATA (NULL, 0, 0) }; REG i8088_reg[] = { { HRDATA (IP, saved_PC, 16) }, /* must be first for sim_PC */ - { HRDATA (AX, AX, 16) }, - { HRDATA (BX, BX, 16) }, - { HRDATA (CX, CX, 16) }, - { HRDATA (DX, DX, 16) }, - { HRDATA (DI, DI, 16) }, - { HRDATA (SI, SI, 16) }, - { HRDATA (BP, BP, 16) }, - { HRDATA (SP, SP, 16) }, - { HRDATA (CS, CS, 16) }, - { HRDATA (DS, DS, 16) }, - { HRDATA (SS, SS, 16) }, - { HRDATA (ES, ES, 16) }, - { HRDATA (PSW, PSW, 16) }, { HRDATA (WRU, sim_int_char, 8) }, { NULL } }; MTAB i8088_mod[] = { - { UNIT_CHIP, UNIT_CHIP, "8086", "8086", NULL }, - { UNIT_CHIP, 0, "8088", "8088", NULL }, - { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL }, - { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL }, { 0 } }; @@ -443,7 +206,7 @@ DEBTAB i8088_debug[] = { }; DEVICE i8088_dev = { - "8088", //name + "I8088", //name &i8088_unit, //units i8088_reg, //registers i8088_mod, //modifiers @@ -461,137 +224,1208 @@ DEVICE i8088_dev = { NULL, //detach NULL, //ctxt DEV_DEBUG, //flags -// 0, //dctrl - DEBUG_asm+DEBUG_level1, //dctrl -// DEBUG_reg+DEBUG_asm+DEBUG_level1, //dctrl -// DEBUG_asm, //dctrl + DEBUG_reg+DEBUG_asm,//dctrl i8088_debug, //debflags NULL, //msize NULL //lname }; -uint8 xor_3_tab[] = { 0, 1, 1, 0 }; - -static const char *opcode[256] = { -"ADD\t", "ADD\t", "ADD\t", "ADD\t", /* 0x00 */ -"ADD\tAL,", "ADD\tAX,", "PUSH\tES", "POP\tES", -"OR\t", "OR\t", "OR\t", "OR\t", -"OR\tAL,", "OR\tAX,", "PUSH\tCS", "0F\t", -"ADC\t", "ADC\t", "ADC\t", "ADC\t", /* 0x10 */ -"ADC\tAL,", "ADC\tAX,", "PUSH\tSS", "POP\tSS", -"SBB\t", "SBB\t", "SBB\t", "SBB\t", -"SBB\tAL,", "SBB\tAX,", "PUSH\tDS", "POP\tDS", -"AND\t", "AND\t", "AND\t", "AND\t", /* 0x20 */ -"AND\tAL,", "AND\tAX,", "ES:", "DAA", -"SUB\t", "SUB\t", "SUB\t", "SUB\t", -"SUB\tAL,", "SUB\tAX,", "CS:", "DAS", -"XOR\t", "XOR\t", "XOR\t", "XOR\t", /* 0x30 */ -"XOR\tAL,", "XOR\tAX,", "SS:", "AAA", -"CMP\t", "CMP\t", "CMP\t", "CMP\t", -"CMP\tAL,", "CMP\tAX,", "DS:", "AAS", -"INC\tAX", "INC\tCX", "INC\tDX", "INC\tBX", /* 0x40 */ -"INC\tSP", "INC\tBP", "INC\tSI", "INC\tDI", -"DEC\tAX", "DEC\tCX", "DEC\tDX", "DEC\tBX", -"DEC\tSP", "DEC\tBP", "DEC\tSI", "DEC\tDI", -"PUSH\tAX", "PUSH\tCX", "PUSH\tDX", "PUSH\tBX", /* 0x50 */ -"PUSH\tSP", "PUSH\tBP", "PUSH\tSI", "PUSH\tDI", -"POP\tAX", "POP\tCX", "POP\tDX", "POP\tBX", -"POP\tSP", "POP\tBP", "POP\tSI", "POP\tDI", -"60\t", "61\t", "62\t", "63\t", /* 0x60 */ -"64\t", "65\t", "66\t", "67\t", -"68\t", "69\t", "6A\t", "6B\t", -"6C\t", "6D\t", "6E\t", "6F\t", -"JO\t", "JNO\t", "JC\t", "JNC\t", /* 0x70 */ -"JZ\t", "JNZ\t", "JNA\t", "JA\t", -"JS\t", "JNS\t", "JP\t", "JNP\t", -"JL\t", "JNL\t", "JLE\t", "JNLE\t", -"80\t", "81\t", "82\t", "83\t", /* 0x80 */ -"TEST\t", "TEST\t", "XCHG\t", "XCHG\t", -"MOV\t", "MOV\t", "MOV\t", "MOV\t", -"MOV\t", "LEA\t", "MOV\t", "POP\t", -"NOP", "XCHG\tAX,CX", "XCHG\tAX,DX", "XCHG\tAX,BX",/* 0x90 */ -"XCHG\tAX,SP", "XCHG\tAX,BP", "XCHG\tAX,SI", "XCHG\tAX,DI", -"CBW", "CWD", "CALL\t", "WAIT", -"PUSHF", "POPF", "SAHF", "LAHF", -"MOV\tAL,", "MOV\tAX,", "MOV\t", "MOV\t", /* 0xA0 */ -"MOVSB", "MOVSW", "CMPSB", "CMPSW", -"TEST\tAL,", "TEST\tAX,", "STOSB", "STOSW", -"LODSB", "LODSW", "SCASB", "SCASW", -"MOV\tAL,", "MOV\tCL,", "MOV\tDL,", "MOV\tBL,", /* 0xB0 */ -"MOV\tAH,", "MOV\tCH,", "MOV\tDH,", "MOV\tBH,", -"MOV\tAX,", "MOV\tCX,", "MOV\tDX,", "MOV\tBX,", -"MOV\tSP,", "MOV\tBP,", "MOV\tSI,", "MOV\tDI," -"C0\t", "C1\t", "RET ", "RET ", /* 0xC0 */ -"LES\t", "LDS\t", "MOV\t", "MOV\t", -"C8\t", "C9\t", "RET ", "RET", -"INT\t3", "INT\t", "INTO", "IRET", -"SHL\t", "D1\t", "SHR\t", "D3\t", /* 0xD0 */ -"AAM", "AAD", "D6\t", "XLATB", -"ESC\t", "ESC\t", "ESC\t", "ESC\t", -"ESC\t", "ESC\t", "ESC\t", "ESC\t", -"LOOPNZ\t", "LOOPZ\t", "LOOP\t", "JCXZ\t", /* 0xE0 */ -"IN\tAL,", "IN\tAX,", "OUT\t", "OUT\t", -"CALL\t", "JMP\t", "JMP\t", "JMP\t", -"IN\tAL,DX", "IN\tAX,DX", "OUT\tDX,AL", "OUT\tDX,AX", -"LOCK", "F1\t", "REPNZ", "REPZ", /* 0xF0 */ -"HLT", "CMC", "F6\t", "F7\t", -"CLC", "STC", "CLI", "STI", -"CLD", "STD", "FE\t", "FF\t" -}; - -/* -0 = 1 byte opcode -1 = d8 -2 = d16 -3 = rel8 -4 = rel16 -5 = r/m8,r8 -6 = r/m16,r16 -7 = r/m8 -8 = r/m16 -20 = I haven't figured it out yet! +void flag_szp8 (uint8 value) { + if (!value) { + zf = 1; + } + else { + zf = 0; /* set or clear zero flag */ + } + + if (value & 0x80) { + sf = 1; + } + else { + sf = 0; /* set or clear sign flag */ + } + + pf = parity[value]; /* retrieve parity state from lookup table */ +} + +void flag_szp16 (uint16 value) { + if (!value) { + zf = 1; + } + else { + zf = 0; /* set or clear zero flag */ + } + + if (value & 0x8000) { + sf = 1; + } + else { + sf = 0; /* set or clear sign flag */ + } + + pf = parity[value & 255]; /* retrieve parity state from lookup table */ +} + +void flag_log8 (uint8 value) { + flag_szp8 (value); + cf = 0; + of = 0; /* bitwise logic ops always clear carry and overflow */ +} + +void flag_log16 (uint16 value) { + flag_szp16 (value); + cf = 0; + of = 0; /* bitwise logic ops always clear carry and overflow */ +} + +void flag_adc8 (uint8 v1, uint8 v2, uint8 v3) { + + /* v1 = destination operand, v2 = source operand, v3 = carry flag */ + uint16 dst; + + dst = (uint16) v1 + (uint16) v2 + (uint16) v3; + flag_szp8 ( (uint8) dst); + if ( ( (dst ^ v1) & (dst ^ v2) & 0x80) == 0x80) { + of = 1; + } + else { + of = 0; /* set or clear overflow flag */ + } + + if (dst & 0xFF00) { + cf = 1; + } + else { + cf = 0; /* set or clear carry flag */ + } + + if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) { + af = 1; + } + else { + af = 0; /* set or clear auxilliary flag */ + } +} + +void flag_adc16 (uint16 v1, uint16 v2, uint16 v3) { + + uint32 dst; + + dst = (uint32) v1 + (uint32) v2 + (uint32) v3; + flag_szp16 ( (uint16) dst); + if ( ( ( (dst ^ v1) & (dst ^ v2) ) & 0x8000) == 0x8000) { + of = 1; + } + else { + of = 0; + } + + if (dst & 0xFFFF0000) { + cf = 1; + } + else { + cf = 0; + } + + if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) { + af = 1; + } + else { + af = 0; + } +} + +void flag_add8 (uint8 v1, uint8 v2) { + /* v1 = destination operand, v2 = source operand */ + uint16 dst; + + dst = (uint16) v1 + (uint16) v2; + flag_szp8 ( (uint8) dst); + if (dst & 0xFF00) { + cf = 1; + } + else { + cf = 0; + } + + if ( ( (dst ^ v1) & (dst ^ v2) & 0x80) == 0x80) { + of = 1; + } + else { + of = 0; + } + + if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) { + af = 1; + } + else { + af = 0; + } +} + +void flag_add16 (uint16 v1, uint16 v2) { + /* v1 = destination operand, v2 = source operand */ + uint32 dst; + + dst = (uint32) v1 + (uint32) v2; + flag_szp16 ( (uint16) dst); + if (dst & 0xFFFF0000) { + cf = 1; + } + else { + cf = 0; + } + + if ( ( (dst ^ v1) & (dst ^ v2) & 0x8000) == 0x8000) { + of = 1; + } + else { + of = 0; + } + + if ( ( (v1 ^ v2 ^ dst) & 0x10) == 0x10) { + af = 1; + } + else { + af = 0; + } +} + +void flag_sbb8 (uint8 v1, uint8 v2, uint8 v3) { + + /* v1 = destination operand, v2 = source operand, v3 = carry flag */ + uint16 dst; + + v2 += v3; + dst = (uint16) v1 - (uint16) v2; + flag_szp8 ( (uint8) dst); + if (dst & 0xFF00) { + cf = 1; + } + else { + cf = 0; + } + + if ( (dst ^ v1) & (v1 ^ v2) & 0x80) { + of = 1; + } + else { + of = 0; + } + + if ( (v1 ^ v2 ^ dst) & 0x10) { + af = 1; + } + else { + af = 0; + } +} + +void flag_sbb16 (uint16 v1, uint16 v2, uint16 v3) { + + /* v1 = destination operand, v2 = source operand, v3 = carry flag */ + uint32 dst; + + v2 += v3; + dst = (uint32) v1 - (uint32) v2; + flag_szp16 ( (uint16) dst); + if (dst & 0xFFFF0000) { + cf = 1; + } + else { + cf = 0; + } + + if ( (dst ^ v1) & (v1 ^ v2) & 0x8000) { + of = 1; + } + else { + of = 0; + } + + if ( (v1 ^ v2 ^ dst) & 0x10) { + af = 1; + } + else { + af = 0; + } +} + +void flag_sub8 (uint8 v1, uint8 v2) { + + /* v1 = destination operand, v2 = source operand */ + uint16 dst; + + dst = (uint16) v1 - (uint16) v2; + flag_szp8 ( (uint8) dst); + if (dst & 0xFF00) { + cf = 1; + } + else { + cf = 0; + } + + if ( (dst ^ v1) & (v1 ^ v2) & 0x80) { + of = 1; + } + else { + of = 0; + } + + if ( (v1 ^ v2 ^ dst) & 0x10) { + af = 1; + } + else { + af = 0; + } +} + +void flag_sub16 (uint16 v1, uint16 v2) { + + /* v1 = destination operand, v2 = source operand */ + uint32 dst; + + dst = (uint32) v1 - (uint32) v2; + flag_szp16 ( (uint16) dst); + if (dst & 0xFFFF0000) { + cf = 1; + } + else { + cf = 0; + } + + if ( (dst ^ v1) & (v1 ^ v2) & 0x8000) { + of = 1; + } + else { + of = 0; + } + + if ( (v1 ^ v2 ^ dst) & 0x10) { + af = 1; + } + else { + af = 0; + } +} + +void op_adc8() { + res8 = oper1b + oper2b + cf; + flag_adc8 (oper1b, oper2b, cf); +} + +void op_adc16() { + res16 = oper1 + oper2 + cf; + flag_adc16 (oper1, oper2, cf); +} + +void op_add8() { + res8 = oper1b + oper2b; + flag_add8 (oper1b, oper2b); +} + +void op_add16() { + res16 = oper1 + oper2; + flag_add16 (oper1, oper2); +} + +void op_and8() { + res8 = oper1b & oper2b; + flag_log8 (res8); +} + +void op_and16() { + res16 = oper1 & oper2; + flag_log16 (res16); +} + +void op_or8() { + res8 = oper1b | oper2b; + flag_log8 (res8); +} + +void op_or16() { + res16 = oper1 | oper2; + flag_log16 (res16); +} + +void op_xor8() { + res8 = oper1b ^ oper2b; + flag_log8 (res8); +} + +void op_xor16() { + res16 = oper1 ^ oper2; + flag_log16 (res16); +} + +void op_sub8() { + res8 = oper1b - oper2b; + flag_sub8 (oper1b, oper2b); +} + +void op_sub16() { + res16 = oper1 - oper2; + flag_sub16 (oper1, oper2); +} + +void op_sbb8() { + res8 = oper1b - (oper2b + cf); + flag_sbb8 (oper1b, oper2b, cf); +} + +void op_sbb16() { + res16 = oper1 - (oper2 + cf); + flag_sbb16 (oper1, oper2, cf); +} + +#define modregrm() { \ + addrbyte = getmem8(segregs[regcs], IP); \ + StepIP(1); \ + MOD = addrbyte >> 6; \ + REGX = (addrbyte >> 3) & 7; \ + RM = addrbyte & 7; \ + switch(MOD) \ + { \ + case 0: \ + if(RM == 6) { \ + disp16 = getmem16(segregs[regcs], IP); \ + StepIP(2); \ + } \ + if(((RM == 2) || (RM == 3)) && !segoverride) { \ + useseg = segregs[regss]; \ + } \ + break; \ + \ + case 1: \ + disp16 = signext(getmem8(segregs[regcs], IP)); \ + StepIP(1); \ + if(((RM == 2) || (RM == 3) || (RM == 6)) && !segoverride) { \ + useseg = segregs[regss]; \ + } \ + break; \ + \ + case 2: \ + disp16 = getmem16(segregs[regcs], IP); \ + StepIP(2); \ + if(((RM == 2) || (RM == 3) || (RM == 6)) && !segoverride) { \ + useseg = segregs[regss]; \ + } \ + break; \ + \ + default: \ + disp8 = 0; \ + disp16 = 0; \ + } \ + } + +void getea (uint8 rmval) { + uint32 tempea; + + tempea = 0; + switch (MOD) { + case 0: + switch (rmval) { + case 0: + tempea = regs.wordregs[regbx] + regs.wordregs[regsi]; + break; + case 1: + tempea = regs.wordregs[regbx] + regs.wordregs[regdi]; + break; + case 2: + tempea = regs.wordregs[regbp] + regs.wordregs[regsi]; + break; + case 3: + tempea = regs.wordregs[regbp] + regs.wordregs[regdi]; + break; + case 4: + tempea = regs.wordregs[regsi]; + break; + case 5: + tempea = regs.wordregs[regdi]; + break; + case 6: + tempea = disp16; + break; + case 7: + tempea = regs.wordregs[regbx]; + break; + } + break; + + case 1: + case 2: + switch (rmval) { + case 0: + tempea = regs.wordregs[regbx] + regs.wordregs[regsi] + disp16; + break; + case 1: + tempea = regs.wordregs[regbx] + regs.wordregs[regdi] + disp16; + break; + case 2: + tempea = regs.wordregs[regbp] + regs.wordregs[regsi] + disp16; + break; + case 3: + tempea = regs.wordregs[regbp] + regs.wordregs[regdi] + disp16; + break; + case 4: + tempea = regs.wordregs[regsi] + disp16; + break; + case 5: + tempea = regs.wordregs[regdi] + disp16; + break; + case 6: + tempea = regs.wordregs[regbp] + disp16; + break; + case 7: + tempea = regs.wordregs[regbx] + disp16; + break; + } + break; + } + + EA = (tempea & 0xFFFF) + (useseg << 4); +} + +void push (uint16 pushval) { + putreg16 (regsp, getreg16 (regsp) - 2); + putmem16 (segregs[regss], getreg16 (regsp), pushval); +} + +uint16 pop() { + + uint16 tempval; + + tempval = getmem16 (segregs[regss], getreg16 (regsp) ); + putreg16 (regsp, getreg16 (regsp) + 2); + return tempval; +} + +t_stat i8088_reset(DEVICE *dptr) { + //what about the flags? + segregs[regcs] = 0xFFFF; + IP = 0x0000; + //regs.wordregs[regsp] = 0xFFFE; + return SCPE_OK; +} + +uint16 readrm16 (uint8 rmval) { + if (MOD < 3) { + getea (rmval); +// return read86 (EA) | ( (uint16) read86 (EA + 1) << 8); + return get_mbyte (EA) | (uint16) get_mbyte ((EA + 1) << 8); + } + else { + return getreg16 (rmval); + } +} + +uint8 readrm8 (uint8 rmval) { + if (MOD < 3) { + getea (rmval); +// return read86 (EA); + return get_mbyte (EA); + } + else { + return getreg8 (rmval); + } +} + +void writerm16 (uint8 rmval, uint16 value) { + if (MOD < 3) { + getea (rmval); +// write86 (EA, value & 0xFF); +// write86 (EA + 1, value >> 8); + put_mbyte (EA, value & 0xFF); + put_mbyte (EA + 1, value >> 8); + } + else { + putreg16 (rmval, value); + } +} + +void writerm8 (uint8 rmval, uint8 value) { + if (MOD < 3) { + getea (rmval); +// write86 (EA, value); + put_mbyte (EA, value); + } + else { + putreg8 (rmval, value); + } +} + +uint8 op_grp2_8 (uint8 cnt) { + + uint16 s; + uint16 shift; + uint16 oldcf; + uint16 msb; + + s = oper1b; + oldcf = cf; +#ifdef CPU_V20 //80186/V20 class CPUs limit shift count to 31 + cnt &= 0x1F; +#endif + switch (REGX) { + case 0: /* ROL r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + if (s & 0x80) { + cf = 1; + } + else { + cf = 0; + } + + s = s << 1; + s = s | cf; + } + + if (cnt == 1) { + of = cf ^ ( (s >> 7) & 1); + } + break; + + case 1: /* ROR r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + cf = s & 1; + s = (s >> 1) | (cf << 7); + } + + if (cnt == 1) { + of = (s >> 7) ^ ( (s >> 6) & 1); + } + break; + + case 2: /* RCL r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + oldcf = cf; + if (s & 0x80) { + cf = 1; + } + else { + cf = 0; + } + + s = s << 1; + s = s | oldcf; + } + + if (cnt == 1) { + of = cf ^ ( (s >> 7) & 1); + } + break; + + case 3: /* RCR r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + oldcf = cf; + cf = s & 1; + s = (s >> 1) | (oldcf << 7); + } + + if (cnt == 1) { + of = (s >> 7) ^ ( (s >> 6) & 1); + } + break; + + case 4: + case 6: /* SHL r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + if (s & 0x80) { + cf = 1; + } + else { + cf = 0; + } + + s = (s << 1) & 0xFF; + } + + if ( (cnt == 1) && (cf == (s >> 7) ) ) { + of = 0; + } + else { + of = 1; + } + + flag_szp8 ( (uint8) s); + break; + + case 5: /* SHR r/m8 */ + if ( (cnt == 1) && (s & 0x80) ) { + of = 1; + } + else { + of = 0; + } + + for (shift = 1; shift <= cnt; shift++) { + cf = s & 1; + s = s >> 1; + } + + flag_szp8 ( (uint8) s); + break; + + case 7: /* SAR r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + msb = s & 0x80; + cf = s & 1; + s = (s >> 1) | msb; + } + + of = 0; + flag_szp8 ( (uint8) s); + break; + } + + return s & 0xFF; +} + +uint16 op_grp2_16 (uint8 cnt) { + + uint32 s; + uint32 shift; + uint32 oldcf; + uint32 msb; + + s = oper1; + oldcf = cf; +#ifdef CPU_V20 //80186/V20 class CPUs limit shift count to 31 + cnt &= 0x1F; +#endif + switch (REGX) { + case 0: /* ROL r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + if (s & 0x8000) { + cf = 1; + } + else { + cf = 0; + } + + s = s << 1; + s = s | cf; + } + + if (cnt == 1) { + of = cf ^ ( (s >> 15) & 1); + } + break; + + case 1: /* ROR r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + cf = s & 1; + s = (s >> 1) | (cf << 15); + } + + if (cnt == 1) { + of = (s >> 15) ^ ( (s >> 14) & 1); + } + break; + + case 2: /* RCL r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + oldcf = cf; + if (s & 0x8000) { + cf = 1; + } + else { + cf = 0; + } + + s = s << 1; + s = s | oldcf; + } + + if (cnt == 1) { + of = cf ^ ( (s >> 15) & 1); + } + break; + + case 3: /* RCR r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + oldcf = cf; + cf = s & 1; + s = (s >> 1) | (oldcf << 15); + } + + if (cnt == 1) { + of = (s >> 15) ^ ( (s >> 14) & 1); + } + break; + + case 4: + case 6: /* SHL r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + if (s & 0x8000) { + cf = 1; + } + else { + cf = 0; + } + + s = (s << 1) & 0xFFFF; + } + + if ( (cnt == 1) && (cf == (s >> 15) ) ) { + of = 0; + } + else { + of = 1; + } + + flag_szp16 ( (uint16) s); + break; + + case 5: /* SHR r/m8 */ + if ( (cnt == 1) && (s & 0x8000) ) { + of = 1; + } + else { + of = 0; + } + + for (shift = 1; shift <= cnt; shift++) { + cf = s & 1; + s = s >> 1; + } + + flag_szp16 ( (uint16) s); + break; + + case 7: /* SAR r/m8 */ + for (shift = 1; shift <= cnt; shift++) { + msb = s & 0x8000; + cf = s & 1; + s = (s >> 1) | msb; + } + + of = 0; + flag_szp16 ( (uint16) s); + break; + } + + return (uint16) s & 0xFFFF; +} + +void op_div8 (uint16 valdiv, uint8 divisor) { + if (divisor == 0) { + intcall86 (0); + return; + } + + if ( (valdiv / (uint16) divisor) > 0xFF) { + intcall86 (0); + return; + } + + regs.byteregs[regah] = valdiv % (uint16) divisor; + regs.byteregs[regal] = valdiv / (uint16) divisor; +} + +void op_idiv8 (uint16 valdiv, uint8 divisor) { + + uint16 s1; + uint16 s2; + uint16 d1; + uint16 d2; + int sign; + + if (divisor == 0) { + intcall86 (0); + return; + } + + s1 = valdiv; + s2 = divisor; + sign = ( ( (s1 ^ s2) & 0x8000) != 0); + s1 = (s1 < 0x8000) ? s1 : ( (~s1 + 1) & 0xffff); + s2 = (s2 < 0x8000) ? s2 : ( (~s2 + 1) & 0xffff); + d1 = s1 / s2; + d2 = s1 % s2; + if (d1 & 0xFF00) { + intcall86 (0); + return; + } + + if (sign) { + d1 = (~d1 + 1) & 0xff; + d2 = (~d2 + 1) & 0xff; + } + + regs.byteregs[regah] = (uint8) d2; + regs.byteregs[regal] = (uint8) d1; +} + +void op_grp3_8() { + oper1 = signext (oper1b); + oper2 = signext (oper2b); + switch (REGX) { + case 0: + case 1: /* TEST */ + flag_log8 (oper1b & getmem8 (segregs[regcs], IP) ); + StepIP (1); + break; + + case 2: /* NOT */ + res8 = ~oper1b; + break; + + case 3: /* NEG */ + res8 = (~oper1b) + 1; + flag_sub8 (0, oper1b); + if (res8 == 0) { + cf = 0; + } + else { + cf = 1; + } + break; + + case 4: /* MUL */ + temp1 = (uint32) oper1b * (uint32) regs.byteregs[regal]; + putreg16 (regax, temp1 & 0xFFFF); + flag_szp8 ( (uint8) temp1); + if (regs.byteregs[regah]) { + cf = 1; + of = 1; + } + else { + cf = 0; + of = 0; + } +#ifndef CPU_V20 + zf = 0; +#endif + break; + + case 5: /* IMUL */ + oper1 = signext (oper1b); + temp1 = signext (regs.byteregs[regal]); + temp2 = oper1; + if ( (temp1 & 0x80) == 0x80) { + temp1 = temp1 | 0xFFFFFF00; + } + + if ( (temp2 & 0x80) == 0x80) { + temp2 = temp2 | 0xFFFFFF00; + } + + temp3 = (temp1 * temp2) & 0xFFFF; + putreg16 (regax, temp3 & 0xFFFF); + if (regs.byteregs[regah]) { + cf = 1; + of = 1; + } + else { + cf = 0; + of = 0; + } +#ifndef CPU_V20 + zf = 0; +#endif + break; + + case 6: /* DIV */ + op_div8 (getreg16 (regax), oper1b); + break; + + case 7: /* IDIV */ + op_idiv8 (getreg16 (regax), oper1b); + break; + } +} + +void op_div16 (uint32 valdiv, uint16 divisor) { + if (divisor == 0) { + intcall86 (0); + return; + } + + if ( (valdiv / (uint32) divisor) > 0xFFFF) { + intcall86 (0); + return; + } + + putreg16 (regdx, valdiv % (uint32) divisor); + putreg16 (regax, valdiv / (uint32) divisor); +} + +void op_idiv16 (uint32 valdiv, uint16 divisor) { + + uint32 d1; + uint32 d2; + uint32 s1; + uint32 s2; + int sign; + + if (divisor == 0) { + intcall86 (0); + return; + } + + s1 = valdiv; + s2 = divisor; + s2 = (s2 & 0x8000) ? (s2 | 0xffff0000) : s2; + sign = ( ( (s1 ^ s2) & 0x80000000) != 0); + s1 = (s1 < 0x80000000) ? s1 : ( (~s1 + 1) & 0xffffffff); + s2 = (s2 < 0x80000000) ? s2 : ( (~s2 + 1) & 0xffffffff); + d1 = s1 / s2; + d2 = s1 % s2; + if (d1 & 0xFFFF0000) { + intcall86 (0); + return; + } + + if (sign) { + d1 = (~d1 + 1) & 0xffff; + d2 = (~d2 + 1) & 0xffff; + } + + putreg16 (regax, d1); + putreg16 (regdx, d2); +} + +void op_grp3_16() { + switch (REGX) { + case 0: + case 1: /* TEST */ + flag_log16 (oper1 & getmem16 (segregs[regcs], IP) ); + StepIP (2); + break; + + case 2: /* NOT */ + res16 = ~oper1; + break; + + case 3: /* NEG */ + res16 = (~oper1) + 1; + flag_sub16 (0, oper1); + if (res16) { + cf = 1; + } + else { + cf = 0; + } + break; + + case 4: /* MUL */ + temp1 = (uint32) oper1 * (uint32) getreg16 (regax); + putreg16 (regax, temp1 & 0xFFFF); + putreg16 (regdx, temp1 >> 16); + flag_szp16 ( (uint16) temp1); + if (getreg16 (regdx) ) { + cf = 1; + of = 1; + } + else { + cf = 0; + of = 0; + } +#ifndef CPU_V20 + zf = 0; +#endif + break; + + case 5: /* IMUL */ + temp1 = getreg16 (regax); + temp2 = oper1; + if (temp1 & 0x8000) { + temp1 |= 0xFFFF0000; + } + + if (temp2 & 0x8000) { + temp2 |= 0xFFFF0000; + } + + temp3 = temp1 * temp2; + putreg16 (regax, temp3 & 0xFFFF); /* into register ax */ + putreg16 (regdx, temp3 >> 16); /* into register dx */ + if (getreg16 (regdx) ) { + cf = 1; + of = 1; + } + else { + cf = 0; + of = 0; + } +#ifndef CPU_V20 + zf = 0; +#endif + break; + + case 6: /* DIV */ + op_div16 ( ( (uint32) getreg16 (regdx) << 16) + getreg16 (regax), oper1); + break; + + case 7: /* DIV */ + op_idiv16 ( ( (uint32) getreg16 (regdx) << 16) + getreg16 (regax), oper1); + break; + } +} + +void op_grp5() { + switch (REGX) { + case 0: /* INC Ev */ + oper2 = 1; + tempcf = cf; + op_add16(); + cf = tempcf; + writerm16 (RM, res16); + break; + + case 1: /* DEC Ev */ + oper2 = 1; + tempcf = cf; + op_sub16(); + cf = tempcf; + writerm16 (RM, res16); + break; + + case 2: /* CALL Ev */ + push (IP); + IP = oper1; + break; + + case 3: /* CALL Mp */ + push (segregs[regcs]); + push (IP); + getea (RM); +// IP = (uint16) read86 (EA) + (uint16) read86 (EA + 1) * 256; +// segregs[regcs] = (uint16) read86 (EA + 2) + (uint16) read86 (EA + 3) * 256; + IP = (uint16) get_mbyte (EA) + (uint16) get_mbyte ((EA + 1) * 256); + segregs[regcs] = (uint16) get_mbyte (EA + 2) + (uint16) get_mbyte ((EA + 3) * 256); + break; + + case 4: /* JMP Ev */ + IP = oper1; + break; + + case 5: /* JMP Mp */ + getea (RM); +// IP = (uint16) read86 (EA) + (uint16) read86 (EA + 1) * 256; +// segregs[regcs] = (uint16) read86 (EA + 2) + (uint16) read86 (EA + 3) * 256; + IP = (uint16) get_mbyte (EA) + (uint16) get_mbyte ((EA + 1) * 256); + segregs[regcs] = (uint16) get_mbyte (EA + 2) + (uint16) get_mbyte ((EA + 3) * 256); + break; + + case 6: /* PUSH Ev */ + push (oper1); + break; + } +} + +uint8 dolog = 0, didintr = 0; +FILE *logout; +uint8 printops = 0; + +//#ifdef NETWORKING_ENABLED +//extern void nethandler(); +//#endif +//extern void diskhandler(); +//extern void readdisk (uint8 drivenum, uint16 dstseg, uint16 dstoff, uint16 cyl, uint16 sect, uint16 head, uint16 sectcount); + +void intcall86 (uint8 intnum) { + static uint16 lastint10ax; +// uint16 oldregax; + didintr = 1; + + if (intnum == 0x19) didbootstrap = 1; + + /* + switch (intnum) { + case 0x10: + updatedscreen = 1; + if ( (regs.byteregs[regah]==0x00) || (regs.byteregs[regah]==0x10) ) { + oldregax = regs.wordregs[regax]; + vidinterrupt(); + regs.wordregs[regax] = oldregax; + if (regs.byteregs[regah]==0x10) return; + if (vidmode==9) return; + } + if ( (regs.byteregs[regah]==0x1A) && (lastint10ax!=0x0100) ) { //the 0x0100 is a cheap hack to make it not do this if DOS EDIT/QBASIC + regs.byteregs[regal] = 0x1A; + regs.byteregs[regbl] = 0x8; + return; + } + lastint10ax = regs.wordregs[regax]; + break; +#ifndef DISK_CONTROLLER_ATA + case 0x19: //bootstrap + if (bootdrive<255) { //read first sector of boot drive into 07C0:0000 and execute it + regs.byteregs[regdl] = bootdrive; + readdisk (regs.byteregs[regdl], 0x07C0, 0x0000, 0, 1, 0, 1); + segregs[regcs] = 0x0000; + IP = 0x7C00; + } + else { + segregs[regcs] = 0xF600; //start ROM BASIC at bootstrap if requested + IP = 0x0000; + } + return; + + case 0x13: + case 0xFD: + diskhandler(); + return; +#endif +#ifdef NETWORKING_OLDCARD + case 0xFC: +#ifdef NETWORKING_ENABLED + nethandler(); +#endif + return; +#endif + } +*/ + push (makeflagsword() ); + push (segregs[regcs]); + push (IP); + segregs[regcs] = getmem16 (0, (uint16) intnum * 4 + 2); + IP = getmem16 (0, (uint16) intnum * 4); + ifl = 0; + tf = 0; +} +/* +#if defined(NETWORKING_ENABLED) +extern struct netstruct { + uint8 enabled; + uint8 canrecv; + uint16 pktlen; +} net; +#endif +uint64 frametimer = 0, didwhen = 0, didticks = 0; +uint32 makeupticks = 0; +extern float timercomp; +uint64 timerticks = 0, realticks = 0; +uint64 lastcountertimer = 0, counterticks = 10000; +extern uint8 nextintr(); +extern void timing(); */ - -int32 oplen[256] = { - 5, 6, 5, 6, 1, 2, 0, 0, 5, 6, 5, 6, 1, 2, 0, 0, //0x00 - 5, 6, 5, 6, 1, 2, 0, 0, 5, 6, 5, 6, 1, 2, 0, 0, //0x10 - 5, 6, 5, 6, 1, 2, 0, 0, 5, 6, 5, 6, 1, 2, 0, 0, //0x20 - 5, 6, 5, 6, 1, 2, 0, 0, 5, 6, 5, 6, 1, 2, 0, 0, //0x30 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x40 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x50 -20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20, //0x60 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, //0x70 - 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, //0x80 - 0, 0, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0, 0, 0, 0, //0x90 -20,20,20,20, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, //0xA0 - 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, //0xB0 - 0, 0, 2, 0,20,20,20,20, 0, 0, 2, 0, 0, 1, 0, 0, //0xC0 -20,20,20,20, 0, 0, 0, 0, 20,20,20,20,20,20,20,20, //0xD0 - 3, 3, 3, 3, 1, 1, 1, 1, 4, 4,20, 3, 0, 0, 0, 0, //0xE0 - 0, 0, 0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 0, 0, 7, 8 //0xF0 -}; - + void set_cpuint(int32 int_num) { int_req |= int_num; } - -int32 sim_instr (void) -{ - extern int32 sim_interval; - uint32 IR, OP, reason; - uint32 MRR, REG, EA, MOD, RM, VAL, DATA, OFF, SEG, INC, VAL1; - - IP = saved_PC & ADDRMASK16; /* load local IP */ +int32 sim_instr (void) { + +// uint32 loopcount; + uint32 reason; + uint8 docontinue; + static uint16 firstip; + static uint16 trap_toggle = 0; + +// counterticks = (uint64) ( (double) timerfreq / (double) 65536.0); + +// for (loopcount = 0; loopcount < execloops; loopcount++) { + reason = 0; /* clear stop reason */ /* Main instruction fetch/decode loop */ while (reason == 0) { /* loop until halted */ - if (i8088_dev.dctrl & DEBUG_asm) - sim_printf("\n"); - if (sim_interval <= 0) { /* check clock queue */ if ((reason = sim_process_event())) break; } @@ -608,4085 +1442,2241 @@ int32 sim_instr (void) sim_interval--; /* countdown clock */ PCX = IP; - IR = OP = fetch_byte(0); /* fetch instruction */ - - /* The Big Instruction Decode Switch */ - - switch (IR) { - - /* instructions in numerical order */ - - case 0x00: /* ADD byte - REG = REG + (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = add_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = add_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x01: /* ADD word - (EA) = (EA) + REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = add_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = add_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x02: /* ADD byte - REG = REG + (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = add_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = add_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x03: /* ADD word - (EA) = (EA) + REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = adc_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x04: /* ADD byte - AL = AL + DATA */ - DATA = fetch_byte(1); - VAL = add_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x05: /* ADD word - (EA) = (EA) + REG */ - DATA = fetch_word(); - VAL = add_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x06: /* PUSH ES */ - push_word(ES); - break; - - case 0x07: /* POP ES */ - ES = pop_word(); - break; - - case 0x08: /* OR byte - REG = REG OR (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = or_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = or_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x09: /* OR word - (EA) = (EA) OR REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = or_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = or_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x0A: /* OR byte - REG = REG OR (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = or_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = or_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x0B: /* OR word - (EA) = (EA) OR REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = or_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = or_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x0C: /* OR byte - AL = AL OR DATA */ - DATA = fetch_byte(1); - VAL = or_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x0D: /* OR word - (EA) = (EA) OR REG */ - DATA = fetch_word(); - VAL = or_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x0E: /* PUSH CS */ - push_word(CS); - break; - - /* 0x0F - Not implemented on 8086/8088 */ - - case 0x10: /* ADC byte - REG = REG + (EA) + CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = adc_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = adc_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x11: /* ADC word - (EA) = (EA) + REG + CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = adc_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x12: /* ADC byte - REG = REG + (EA) + CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = adc_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = adc_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x13: /* ADC word - (EA) = (EA) + REG + CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = adc_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x14: /* ADC byte - AL = AL + DATA + CF */ - DATA = fetch_byte(1); - VAL = adc_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x15: /* ADC word - (EA) = (EA) + REG + CF */ - DATA = fetch_word(); - VAL = adc_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x16: /* PUSH SS */ - push_word(SS); - break; - - case 0x17: /* POP SS */ - SS = pop_word(); - break; - - case 0x18: /* SBB byte - REG = REG - (EA) - CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sbb_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sbb_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x19: /* SBB word - (EA) = (EA) - REG - CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sbb_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sbb_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x1A: /* SBB byte - REG = REG - (EA) - CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sbb_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sbb_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x1B: /* SBB word - (EA) = (EA) - REG - CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sbb_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sbb_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x1C: /* SBB byte - AL = AL - DATA - CF */ - DATA = fetch_byte(1); - VAL = sbb_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x1D: /* SBB word - (EA) = (EA) - REG - CF */ - DATA = fetch_word(); - VAL = sbb_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x1E: /* PUSH DS */ - push_word(DS); - break; - - case 0x1F: /* POP DS */ - DS = pop_word(); - break; - - case 0x20: /* AND byte - REG = REG AND (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = and_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = and_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x21: /* AND word - (EA) = (EA) AND REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = and_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = and_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x22: /* AND byte - REG = REG AND (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = and_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = and_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x23: /* AND word - (EA) = (EA) AND REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = and_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = and_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x24: /* AND byte - AL = AL AND DATA */ - DATA = fetch_byte(1); - VAL = and_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x25: /* AND word - (EA) = (EA) AND REG */ - DATA = fetch_word(); - VAL = and_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x26: /* ES: - segment override prefix */ - seg_ovr = SEG_ES; - sysmode |= SYSMODE_SEGOVR_ES; - break; - - case 0x27: /* DAA */ - if (((AL & 0xF) > 9) || GET_FLAG(AF)) { - AL += 6; - SET_FLAG(AF); - } - if ((AL > 0x9F) || GET_FLAG(CF)) { - AL += 0x60; - SET_FLAG(CF); - } - break; - - case 0x28: /* SUB byte - REG = REG - (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sub_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sub_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x29: /* SUB word - (EA) = (EA) - REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sub_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sub_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x2A: /* SUB byte - REG = REG - (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sub_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sub_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x2B: /* SUB word - (EA) = (EA) - REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sub_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sub_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x2C: /* SUB byte - AL = AL - DATA */ - DATA = fetch_byte(1); - VAL = sub_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x2D: /* SUB word - (EA) = (EA) - REG */ - DATA = fetch_word(); - VAL = sub_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x2E: /* DS: - segment override prefix */ - seg_ovr = SEG_DS; - sysmode |= SYSMODE_SEGOVR_DS; - break; - - case 0x2F: /* DAS */ - if (((AL & 0xF) > 9) || GET_FLAG(AF)) { - AL -= 6; - SET_FLAG(AF); - } - if ((AL > 0x9F) || GET_FLAG(CF)) { - AL -= 0x60; - SET_FLAG(CF); - } - break; - - case 0x30: /* XOR byte - REG = REG XOR (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x31: /* XOR word - (EA) = (EA) XOR REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x32: /* XOR byte - REG = REG XOR (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x33: /* XOR word - (EA) = (EA) XOR REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x34: /* XOR byte - AL = AL XOR DATA */ - DATA = fetch_byte(1); - VAL = xor_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x35: /* XOR word - (EA) = (EA) XOR REG */ - DATA = fetch_word(); - VAL = xor_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x36: /* SS: - segment override prefix */ - seg_ovr = SEG_SS; - sysmode |= SYSMODE_SEGOVR_SS; - break; - - case 0x37: /* AAA */ - if (((AL & 0xF) > 9) || GET_FLAG(AF)) { - AL += 6; - AH++; - SET_FLAG(AF); - } - CONDITIONAL_SET_FLAG(GET_FLAG(AF), CF); - AL &= 0xF; - break; - - case 0x38: /* CMP byte - CMP (REG, (EA)) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x39: /* CMP word - CMP ((EA), REG) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x3A: /* CMP byte - CMP (REG, (EA)) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x3B: /* CMP word - CMP ((EA), REG) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x3C: /* CMP byte - CMP (AL, DATA) */ - DATA = fetch_byte(1); - VAL = xor_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x3D: /* CMP word - CMP ((EA), REG) */ - DATA = fetch_word(); - VAL = xor_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x3E: /* DS: - segment override prefix */ - seg_ovr = SEG_DS; - sysmode |= SYSMODE_SEGOVR_DS; - break; - - case 0x3F: /* AAS */ - if (((AL & 0xF) > 9) || GET_FLAG(AF)) { - AL -= 6; - AH--; - SET_FLAG(AF); - } - CONDITIONAL_SET_FLAG(GET_FLAG(AF), CF); - AL &= 0xF; - break; - - case 0x40: /* INC AX */ - AX = inc_word(AX); - break; - - case 0x41: /* INC CX */ - CX = inc_word(CX); - break; - - case 0x42: /* INC DX */ - DX = inc_word(DX); - break; - - case 0x43: /* INC BX */ - BX = inc_word(BX); - break; - - case 0x44: /* INC SP */ - SP = inc_word(SP); - break; - - case 0x45: /* INC BP */ - BP = inc_word(BP); - break; - - case 0x46: /* INC SI */ - SI = inc_word(SI); - break; - - case 0x47: /* INC DI */ - DI = inc_word(DI); - break; - - case 0x48: /* DEC AX */ - AX = dec_word(AX); - break; - - case 0x49: /* DEC CX */ - CX = dec_word(CX); - break; - - case 0x4A: /* DEC DX */ - DX = dec_word(DX); - break; - - case 0x4B: /* DEC BX */ - BX = dec_word(BX); - break; - - case 0x4C: /* DEC SP */ - SP = dec_word(SP); - break; - - case 0x4D: /* DEC BP */ - BP = dec_word(BP); - break; - - case 0x4E: /* DEC SI */ - SI = dec_word(SI); - break; - - case 0x4F: /* DEC DI */ - DI = dec_word(DI); - break; - - case 0x50: /* PUSH AX */ - push_word(AX); - break; - - case 0x51: /* PUSH CX */ - push_word(CX); - break; - - case 0x52: /* PUSH DX */ - push_word(DX); - break; - - case 0x53: /* PUSH BX */ - push_word(BX); - break; - - case 0x54: /* PUSH SP */ - push_word(SP); - break; - - case 0x55: /* PUSH BP */ - push_word(BP); - break; - - case 0x56: /* PUSH SI */ - push_word(SI); - break; - - case 0x57: /* PUSH DI */ - push_word(DI); - break; - - case 0x58: /* POP AX */ - AX = pop_word(); - break; - - case 0x59: /* POP CX */ - CX = pop_word(); - break; - - case 0x5A: /* POP DX */ - DX = pop_word(); - break; - - case 0x5B: /* POP BX */ - BX = pop_word(); - break; - - case 0x5C: /* POP SP */ - SP = pop_word(); - break; - - case 0x5D: /* POP BP */ - BP = pop_word(); - break; - - case 0x5E: /* POP SI */ - SI = pop_word(); - break; - - case 0x5F: /* POP DI */ - DI = pop_word(); - break; - - /* 0x60 - 0x6F - Not implemented on 8086/8088 */ - - case 0x70: /* JO short label */ - /* jump to byte offset if overflow flag is set */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(OF)) - IP = EA; - break; - - case 0x71: /* JNO short label */ - /* jump to byte offset if overflow flag is clear */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!GET_FLAG(OF)) - IP = EA; - break; - - case 0x72: /* JB/JNAE/JC short label */ - /* jump to byte offset if carry flag is set. */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(CF)) - IP = EA; - break; - - case 0x73: /* JNB/JAE/JNC short label */ - /* jump to byte offset if carry flsg is clear */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!GET_FLAG(CF)) - IP = EA; - break; - - case 0x74: /* JE/JZ short label */ - /* jump to byte offset if zero flag is set */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(ZF)) - IP = EA; - break; - - case 0x75: /* JNE/JNZ short label */ - /* jump to byte offset if zero flag is clear */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!GET_FLAG(ZF)) - IP = EA; - break; - - case 0x76: /* JBE/JNA short label */ - /* jump to byte offset if carry flag is set or if the zero - flag is set. */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(CF) || GET_FLAG(ZF)) - IP = EA; - break; - - case 0x77: /* JNBE/JA short label */ - /* jump to byte offset if carry flag is clear and if the zero - flag is clear */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!(GET_FLAG(CF) || GET_FLAG(ZF))) - IP = EA; - break; - - case 0x78: /* JS short label */ - /* jump to byte offset if sign flag is set */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(SF)) - IP = EA; - break; - - case 0x79: /* JNS short label */ - /* jump to byte offset if sign flag is clear */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!GET_FLAG(SF)) - IP = EA; - break; - - case 0x7A: /* JP/JPE short label */ - /* jump to byte offset if parity flag is set (even) */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(PF)) - IP = EA; - break; - - case 0x7B: /* JNP/JPO short label */ - /* jump to byte offset if parity flsg is clear (odd) */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!GET_FLAG(PF)) - IP = EA; - break; - - case 0x7C: /* JL/JNGE short label */ - /* jump to byte offset if sign flag not equal to overflow flag. */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if ((GET_FLAG(SF) != 0) ^ (GET_FLAG(OF) != 0)) - IP = EA; - break; - - case 0x7D: /* JNL/JGE short label */ - /* jump to byte offset if sign flag equal to overflow flag. */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if ((GET_FLAG(SF) != 0) == (GET_FLAG(OF) != 0)) - IP = EA; - break; - - case 0x7E: /* JLE/JNG short label */ - /* jump to byte offset if sign flag not equal to overflow flag - or the zero flag is set */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (((GET_FLAG(SF) != 0) ^ (GET_FLAG(OF) != 0)) || GET_FLAG(ZF)) - IP = EA; - break; - - case 0x7F: /* JNLE/JG short label */ - /* jump to byte offset if sign flag equal to overflow flag. - and the zero flag is clear*/ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (((GET_FLAG(SF) != 0) == (GET_FLAG(OF) != 0)) || !GET_FLAG(ZF)) - IP = EA; - break; - - case 0x80: /* ADD/OR/ADC/SBB/AND/SUB/XOR/CMP byte operands */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = fetch_byte(1); /* must be done after DISP is collected */ - switch(REG) { - case 0: - VAL = add_byte(get_smbyte(seg_reg, EA), DATA); /* ADD mem8, immed8 */ - break; - case 1: - VAL = or_byte(get_smbyte(seg_reg, EA), DATA); /* OR mem8, immed8 */ - break; - case 2: - VAL = adc_byte(get_smbyte(seg_reg, EA), DATA); /* ADC mem8, immed8 */ - break; - case 3: - VAL = sbb_byte(get_smbyte(seg_reg, EA), DATA); /* SBB mem8, immed8 */ - break; - case 4: - VAL = and_byte(get_smbyte(seg_reg, EA), DATA); /* AND mem8, immed8 */ - break; - case 5: - VAL = sub_byte(get_smbyte(seg_reg, EA), DATA); /* SUB mem8, immed8 */ - break; - case 6: - VAL = xor_byte(get_smbyte(seg_reg, EA), DATA); /* XOR mem8, immed8 */ - break; - case 7: - VAL = cmp_byte(get_smbyte(seg_reg, EA), DATA); /* CMP mem8, immed8 */ - break; - } - put_rbyte(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = add_byte(get_rbyte(RM), DATA); /* ADD REG8, immed8 */ - break; - case 1: - VAL = or_byte(get_rbyte(RM), DATA); /* OR REG8, immed8 */ - break; - case 2: - VAL = adc_byte(get_rbyte(RM), DATA); /* ADC REG8, immed8 */ - break; - case 3: - VAL = sbb_byte(get_rbyte(RM), DATA); /* SBB REG8, immed8 */ - break; - case 4: - VAL = and_byte(get_rbyte(RM), DATA); /* AND REG8, immed8 */ - break; - case 5: - VAL = sub_byte(get_rbyte(RM), DATA); /* SUB REG8, immed8 */ - break; - case 6: - VAL = xor_byte(get_rbyte(RM), DATA); /* XOR REG8, immed8 */ - break; - case 7: - VAL = cmp_byte(get_rbyte(RM), DATA); /* CMP REG8, immed8 */ - break; - } - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x81: /* word operands */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = fetch_byte(1) << 8; /* must be done after DISP is collected */ - DATA |= fetch_byte(1); - switch(REG) { - case 0: - VAL = add_word(get_smword(seg_reg, EA), DATA); /* ADD mem16, immed16 */ - break; - case 1: - VAL = or_word(get_smword(seg_reg, EA), DATA); /* OR mem16, immed16 */ - break; - case 2: - VAL = adc_word(get_smword(seg_reg, EA), DATA); /* ADC mem16, immed16 */ - break; - case 3: - VAL = sbb_word(get_smword(seg_reg, EA), DATA); /* SBB mem16, immed16 */ - break; - case 4: - VAL = and_word(get_smword(seg_reg, EA), DATA); /* AND mem16, immed16 */ - break; - case 5: - VAL = sub_word(get_smword(seg_reg, EA), DATA); /* SUB mem16, immed16 */ - break; - case 6: - VAL = xor_word(get_smword(seg_reg, EA), DATA); /* XOR mem16, immed16 */ - break; - case 7: - VAL = cmp_word(get_smword(seg_reg, EA), DATA); /* CMP mem16, immed16 */ - break; - } - put_rword(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = add_word(get_rword(RM), DATA); /* ADD reg16, immed16 */ - break; - case 1: - VAL = or_word(get_rword(RM), DATA); /* OR reg16, immed16 */ - break; - case 2: - VAL = adc_word(get_rword(RM), DATA); /* ADC reg16, immed16 */ - break; - case 3: - VAL = sbb_word(get_rword(RM), DATA); /* SBB reg16, immed16 */ - break; - case 4: - VAL = and_word(get_rword(RM), DATA); /* AND reg16, immed16 */ - break; - case 5: - VAL = sub_word(get_rword(RM), DATA); /* SUB reg16, immed16 */ - break; - case 6: - VAL = xor_word(get_rword(RM), DATA); /* XOR reg16, immed16 */ - break; - case 7: - VAL = cmp_word(get_rword(RM), DATA); /* CMP reg16, immed16 */ - break; - } - put_rword(RM, VAL); /* store result */ - } - break; - - case 0x82: /* byte operands */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = fetch_byte(1); /* must be done after DISP is collected */ - switch(REG) { - case 0: - VAL = add_byte(get_smbyte(seg_reg, EA), DATA); /* ADD mem8, immed8 */ - break; - case 2: - VAL = adc_byte(get_smbyte(seg_reg, EA), DATA); /* ADC mem8, immed8 */ - break; - case 3: - VAL = sbb_byte(get_smbyte(seg_reg, EA), DATA); /* SBB mem8, immed8 */ - break; - case 5: - VAL = sub_byte(get_smbyte(seg_reg, EA), DATA); /* SUB mem8, immed8 */ - break; - case 7: - VAL = cmp_byte(get_smbyte(seg_reg, EA), DATA); /* CMP mem8, immed8 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = add_byte(get_rbyte(RM), DATA); /* ADD reg8, immed8 */ - break; - case 2: - VAL = adc_byte(get_rbyte(RM), DATA); /* ADC reg8, immed8 */ - break; - case 3: - VAL = sbb_byte(get_rbyte(RM), DATA); /* SBB reg8, immed8 */ - break; - case 5: - VAL = sub_byte(get_rbyte(RM), DATA); /* SUB reg8, immed8 */ - break; - case 7: - VAL = cmp_byte(get_rbyte(RM), DATA); /* CMP reg8, immed8 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x83: /* word operands */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = fetch_byte(1) << 8; /* must be done after DISP is collected */ - if (DATA & 0x80) - DATA |= 0xFF00; - else - DATA &= 0xFF; - switch(REG) { - case 0: - VAL = add_word(get_smword(seg_reg, EA), DATA); /* ADD mem16, immed8-SX */ - break; - case 2: - VAL = adc_word(get_smword(seg_reg, EA), DATA); /* ADC mem16, immed8-SX */ - break; - case 3: - VAL = sbb_word(get_smword(seg_reg, EA), DATA); /* SBB mem16, immed8-SX */ - break; - case 5: - VAL = sub_word(get_smword(seg_reg, EA), DATA); /* SUB mem16, immed8-SX */ - break; - case 7: - VAL = cmp_word(get_smword(seg_reg, EA), DATA); /* CMP mem16, immed8-SX */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rword(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = add_word(get_rword(RM), DATA); /* ADD reg16, immed8-SX */ - break; - case 2: - VAL = adc_word(get_rword(RM), DATA); /* ADC reg16, immed8-SX */ - break; - case 3: - VAL = sbb_word(get_rword(RM), DATA); /* SBB reg16, immed8-SX */ - break; - case 5: - VAL = sub_word(get_rword(RM), DATA); /* CUB reg16, immed8-SX */ - break; - case 7: - VAL = cmp_word(get_rword(RM), DATA); /* CMP reg16, immed8-SX */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rword(RM, VAL); /* store result */ - } - break; - - case 0x84: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - test_byte(get_smbyte(seg_reg, EA),get_rbyte(REG)); /* TEST mem8, reg8 */ - } else { - test_byte(get_rbyte(REG),get_rbyte(RM)); /* TEST reg8, reg8 */ - } - break; - - case 0x85: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - test_word(get_smword(seg_reg, EA),get_rword(REG)); /* TEST mem16, reg16 */ - } else { - test_word(get_rword(REG),get_rword(RM)); /* TEST reg16, reg16 */ - } - break; - - case 0x86: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = get_rbyte(REG);/* XCHG mem8, reg8 */ - put_rbyte(REG, get_smbyte(seg_reg, EA)); - put_smbyte(seg_reg, EA, VAL); - } else { - VAL = get_rbyte(RM);/* XCHG reg8, reg8 */ - put_rbyte(RM, get_rbyte(REG)); - put_rbyte(REG, VAL); - } - break; - - case 0x87: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = get_rword(REG);/* XCHG mem16, reg16 */ - put_rword(REG, get_smword(seg_reg, EA)); - put_smword(seg_reg, EA, VAL); - } else { - VAL = get_rword(RM);/* XCHG reg16, reg16 */ - put_rword(RM, get_rword(REG)); - put_rword(REG, VAL); - } - break; - - case 0x88: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_smbyte(seg_reg, EA, get_rbyte(REG)); /* MOV mem8, reg8 */ - } else - put_rbyte(REG, get_rbyte(RM)); /* MOV reg8, reg8 */ - break; - - case 0x89: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_smword(seg_reg, EA, get_rword(REG)); /* MOV mem16, reg16 */ - } else - put_rword(REG, get_rword(RM)); /* MOV reg16, reg16 */ - break; - - case 0x8A: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_rbyte(REG, get_smbyte(seg_reg, EA)); /* MOV reg8, mem8 */ - } else - put_rbyte(REG, get_rbyte(RM)); /* MOV reg8, reg8 */ - break; - - case 0x8B: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_rword(REG, get_smword(seg_reg, EA)); /* MOV reg16, mem16 */ - } else - put_rword(REG, get_rword(RM)); /* MOV reg16, reg16 */ - break; - - case 0x8C: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* MOV mem16, ES */ - put_smword(seg_reg, EA, ES); - break; - case 1: /* MOV mem16, CS */ - put_smword(seg_reg, EA, CS); - break; - case 2: /* MOV mem16, SS */ - put_smword(seg_reg, EA, SS); - break; - case 3: /* MOV mem16, DS */ - put_smword(seg_reg, EA, DS); - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { - switch(REG) { - case 0: /* MOV reg16, ES */ - put_rword(RM, ES); - break; - case 1: /* MOV reg16, CS */ - put_rword(RM, CS); - break; - case 2: /* MOV reg16, SS */ - put_rword(RM, SS); - break; - case 3: /* MOV reg16, DS */ - put_rword(RM, DS); - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } - break; - - case 0x8D: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_rword(REG, EA); /* LEA reg16, mem16 */ - } else { - reason = STOP_OPCODE; - IP -= 2; - } - break; - - case 0x8E: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* MOV ES, mem16 */ - ES = get_smword(seg_reg, EA); - break; - case 1: /* MOV CS, mem16 */ - CS = get_smword(seg_reg, EA); - break; - case 2: /* MOV SS, mem16 */ - SS = get_smword(seg_reg, EA); - break; - case 3: /* MOV DS, mem16 */ - DS = get_smword(seg_reg, EA); - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { - switch(REG) { - case 0: /* MOV ES, reg16 */ - ES = get_rword(RM); - break; - case 1: /* MOV CS, reg16 */ - CS = get_rword(RM); - break; - case 2: /* MOV SS, reg16 */ - SS = get_rword(RM); - break; - case 3: /* MOV DS, reg16 */ - DS = get_rword(RM); - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } - break; - - case 0x8f: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_smword(seg_reg, EA, pop_word()); - } else { - reason = STOP_OPCODE; - IP -= 2; - } - break; - - case 0x90: /* NOP */ - break; - - case 0x91: /* XCHG AX, CX */ - VAL = AX; - AX = CX; - CX = VAL; - break; - - case 0x92: /* XCHG AX, DX */ - VAL = AX; - AX = DX; - DX = VAL; - break; - - case 0x93: /* XCHG AX, BX */ - VAL = AX; - AX = BX; - BX = VAL; - break; - - case 0x94: /* XCHG AX, SP */ - VAL = AX; - AX = SP; - SP = VAL; - break; - - case 0x95: /* XCHG AX, BP */ - VAL = AX; - AX = BP; - BP = VAL; - break; - - case 0x96: /* XCHG AX, SI */ - VAL = AX; - AX = SI; - SI = VAL; - break; - - case 0x97: /* XCHG AX, DI */ - VAL = AX; - AX = DI; - DI = VAL; - break; - - case 0x98: /* cbw */ - if (AL & 0x80) - AH = 0xFF; - else - AH = 0; - break; - - case 0x99: /* cbw */ - if (AX & 0x8000) - DX = 0xffff; - else - DX = 0x0; - break; - - case 0x9A: /* CALL FAR proc */ - OFF = fetch_word(); /* do operation */ - SEG = fetch_word(); - push_word(CS); - CS = SEG; - push_word(IP); - IP = OFF; - break; - - case 0x9B: /* WAIT */ - break; - - case 0x9C: /* PUSHF */ - VAL = PSW; - VAL &= PSW_MSK; - VAL |= PSW_ALWAYS_ON; - push_word(VAL); - break; - - case 0x9D: /* POPF */ - PSW = pop_word(); - break; - - case 0x9E: /* SAHF */ - PSW &= 0xFFFFFF00; - PSW |= AH; - break; - - case 0x9F: /* LAHF */ - AH = PSW & 0xFF; - AH |= 0x2; - break; - - case 0xA0: /* MOV AL, mem8 */ - OFF = fetch_word(); - set_segreg(SEG_DS); /* to allow segment override */ - AL = get_smbyte(seg_reg, OFF); - break; - - case 0xA1: /* MOV AX, mem16 */ - OFF = fetch_word(); - set_segreg(SEG_DS); /* to allow segment override */ - AX = get_smword(seg_reg, OFF); - break; - - case 0xA2: /* MOV mem8, AL */ - OFF = fetch_word(); - set_segreg(SEG_DS); /* to allow segment override */ - put_smbyte(seg_reg, OFF, AL); - break; - - case 0xA3: /* MOV mem16, AX */ - OFF = fetch_word(); - set_segreg(SEG_DS); /* to allow segment override */ - put_smword(seg_reg, OFF, AX); - break; - - case 0xA4: /* MOVS dest-str8, src-str8 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - while (CX != 0) { - VAL = get_smbyte(seg_reg, SI); - put_smbyte(ES, DI, VAL); - CX--; - SI += INC; - DI += INC; - } - break; - - case 0xA5: /* MOVS dest-str16, src-str16 */ - if (GET_FLAG(DF)) /* down */ - INC = -2; - else - INC = 2; - while (CX != 0) { - VAL = get_smword(seg_reg, SI); - put_smword(ES, DI, VAL); - CX--; - SI += INC; - DI += INC; - } - break; - - case 0xA6: /* CMPS dest-str8, src-str8 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - while (CX != 0) { - VAL = get_smbyte(seg_reg, SI); - VAL1 = get_smbyte(ES, DI); - cmp_byte(VAL, VAL1); - CX--; - SI += INC; - DI += INC; - if (GET_FLAG(ZF) == 0) - break; - } - break; - - case 0xA7: /* CMPS dest-str16, src-str16 */ - if (GET_FLAG(DF)) /* down */ - INC = -2; - else - INC = 2; - while (CX != 0) { - VAL = get_smword(seg_reg, SI); - VAL1 = get_smword(ES, DI); - cmp_word(VAL, VAL1); - CX--; - SI += INC; - DI += INC; - if (GET_FLAG(ZF) == 0) - break; - } - break; - - case 0xA8: /* TEST AL, immed8 */ - VAL = fetch_byte(1); - test_byte(AL, VAL); - break; - - case 0xA9: /* TEST AX, immed8 */ - VAL = fetch_word(); - test_word(AX, VAL); - break; - - case 0xAA: /* STOS dest-str8 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - put_smbyte(ES, DI, AL); - CX--; - DI += INC; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - put_smbyte(ES, DI, AL); - DI += INC; - } - break; - - case 0xAB: /* STOS dest-str16 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - put_smword(ES, DI, AX); - CX--; - DI += INC; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - put_smword(ES, DI, AL); - DI += INC; - } - break; - - case 0xAC: /* LODS dest-str8 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - set_segreg(SEG_DS); /* allow overrides */ - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - AL = get_smbyte(seg_reg, SI); - CX--; - SI += INC; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - AL = get_smbyte(seg_reg, SI); - SI += INC; - } - break; - - case 0xAD: /* LODS dest-str16 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - set_segreg(SEG_DS); /* allow overrides */ - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - AX = get_smword(seg_reg, SI); - CX--; - SI += INC; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - AX = get_smword(seg_reg, SI); - SI += INC; - } - break; - - case 0xAE: /* SCAS dest-str8 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - VAL = get_smbyte(ES, DI); - cmp_byte(AL, VAL); - CX--; - DI += INC; - if (GET_FLAG(ZF) == 0) - break; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - VAL = get_smbyte(ES, DI); - cmp_byte(AL, VAL); - DI += INC; - } - break; - - case 0xAF: /* SCAS dest-str16 */ - if (GET_FLAG(DF)) /* down */ - INC = -2; - else - INC = 2; - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - VAL = get_smword(ES, DI); - cmp_word(AX, VAL); - CX--; - DI += INC; - if (GET_FLAG(ZF) == 0) - break; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - VAL = get_smword(ES, DI); - cmp_byte(AL, VAL); - DI += INC; - } - break; - - case 0xB0: /* MOV AL,immed8 */ - AL = fetch_byte(1); - break; - - case 0xB1: /* MOV CL,immed8 */ - CL = fetch_byte(1); - break; - - case 0xB2: /* MOV DL,immed8 */ - DL = fetch_byte(1); - break; - - case 0xB3: /* MOV BL,immed8 */ - BL = fetch_byte(1); - break; - - case 0xB4: /* MOV AH,immed8 */ - AH = fetch_byte(1); - break; - - case 0xB5: /* MOV CH,immed8 */ - CH = fetch_byte(1); - break; - - case 0xB6: /* MOV DH,immed8 */ - DH = fetch_byte(1); - break; - - case 0xB7: /* MOV BH,immed8 */ - BH = fetch_byte(1); - break; - - case 0xB8: /* MOV AX,immed16 */ - AX = fetch_word(); - break; - - case 0xB9: /* MOV CX,immed16 */ - CX = fetch_word(); - break; - - case 0xBA: /* MOV DX,immed16 */ - DX = fetch_word(); - break; - - case 0xBB: /* MOV BX,immed16 */ - BX = fetch_word(); - break; - - case 0xBC: /* MOV SP,immed16 */ - SP = fetch_word(); - break; - - case 0xBD: /* MOV BP,immed16 */ - BP = fetch_word(); - break; - - case 0xBE: /* MOV SI,immed16 */ - SI = fetch_word(); - break; - - case 0xBF: /* MOV DI,immed16 */ - DI = fetch_word(); - break; - - /* 0xC0 - 0xC1 - Not implemented on 8086/8088 */ - - case 0xC2: /* RET immed16 (intrasegment) */ - OFF = fetch_word(); - IP = pop_word(); - SP += OFF; - break; - - case 0xC3: /* RET (intrasegment) */ - IP = pop_word(); - break; - - case 0xC4: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_rword(REG, get_smword(seg_reg, EA)); /* LES mem16 */ - ES = get_smword(seg_reg, EA + 2); - } else { -// put_rword(REG, get_rword(RM)); /* LES reg16 */ -// ES = get_rword(RM) + 2; - /* not defined for 8086 */ - reason = STOP_OPCODE; - IP -= 2; - } - break; - - case 0xC5: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_rword(REG, get_smword(seg_reg, EA)); /* LDS mem16 */ - DS = get_smword(seg_reg, EA + 2); - } else { -// put_rword(REG, get_rword(RM)); /* LDS reg16 */ -// DS = get_rword(RM) + 2; - /* not defined for 8086 */ - reason = STOP_OPCODE; - IP -= 2; - } - break; - - case 0xC6: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (REG) { /* has to be 0 */ - reason = STOP_OPCODE; - IP -= 2; - } - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = fetch_byte(1); /* has to be after DISP */ - put_smbyte(seg_reg, EA, DATA); /* MOV mem8, immed8 */ - } else { - put_rbyte(RM, DATA); /* MOV reg8, immed8 */ - } - break; - - case 0xC7: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (REG) { /* has to be 0 */ - reason = STOP_OPCODE; - IP -= 2; - } - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = get_mword(IP); /* has to be after DISP */ - put_smword(seg_reg, EA, DATA); /* MOV mem16, immed16 */ - } else { - put_rword(RM, DATA); /* MOV reg16, immed16 */ - } - break; - - /* 0xC8 - 0xC9 - Not implemented on 8086/8088 */ - - case 0xCA: /* RET immed16 (intersegment) */ - OFF = fetch_word(); - IP = pop_word(); - CS = pop_word(); - SP += OFF; - break; - - case 0xCB: /* RET (intersegment) */ - IP = pop_word(); - CS = pop_word(); - break; - - case 0xCC: /* INT 3 */ - push_word(PSW); - CLR_FLAG(IF); - CLR_FLAG(TF); - push_word(CS); - push_word(IP); - CS = get_mword(14); - IP = get_mword(12); - break; - - case 0xCD: /* INT immed8 */ - OFF = fetch_byte(1); - push_word(PSW); - CLR_FLAG(IF); - CLR_FLAG(TF); - push_word(CS); - push_word(IP); - CS = get_mword((OFF * 4) + 2); - IP = get_mword(OFF * 4); - break; - - case 0xCE: /* INT0 */ - push_word(PSW); - CLR_FLAG(IF); - CLR_FLAG(TF); - push_word(CS); - push_word(IP); - CS = get_mword(18); - IP = get_mword(16); - break; - - case 0xCF: /* IRET */ - IP = pop_word(); - CS = pop_word(); - PSW = pop_word(); - break; - - case 0xD0: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: - VAL = rol_byte(get_smbyte(seg_reg, EA), 1); /* ROL mem8, 1 */ - break; - case 1: - VAL = ror_byte(get_smbyte(seg_reg, EA), 1); /* ROR mem8, 1 */ - break; - case 2: - VAL = rcl_byte(get_smbyte(seg_reg, EA), 1); /* RCL mem8, 1 */ - break; - case 3: - VAL = rcr_byte(get_smbyte(seg_reg, EA), 1); /* RCR mem8, 1 */ - break; - case 4: - VAL = shl_byte(get_smbyte(seg_reg, EA), 1); /* SAL/SHL mem8, 1 */ - break; - case 5: - VAL = shr_byte(get_smbyte(seg_reg, EA), 1); /* SHR mem8, 1 */ - break; - case 7: - VAL = sar_byte(get_smbyte(seg_reg, EA), 1); /* SAR mem8, 1 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = rol_byte(get_rbyte(RM), 1); /* RCL reg8, 1 */ - break; - case 1: - VAL = ror_byte(get_rbyte(RM), 1); /* ROR reg8, 1 */ - break; - case 2: - VAL = rcl_byte(get_rbyte(RM), 1); /* RCL reg8, 1 */ - break; - case 3: - VAL = rcr_byte(get_rbyte(RM), 1); /* RCR reg8, 1 */ - break; - case 4: - VAL = shl_byte(get_rbyte(RM), 1); /* SHL/SAL reg8, 1*/ - break; - case 5: - VAL = shr_byte(get_rbyte(RM), 1); /* SHR reg8, 1 */ - break; - case 7: - VAL = sar_byte(get_rbyte(RM), 1); /* SAR reg8, 1 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xD1: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: - VAL = rol_word(get_smword(seg_reg, EA), 1); /* ROL mem16, 1 */ - break; - case 1: - VAL = ror_word(get_smword(seg_reg, EA), 1); /* ROR mem16, 1 */ - break; - case 2: - VAL = rcl_word(get_smword(seg_reg, EA), 1); /* RCL mem16, 1 */ - break; - case 3: - VAL = rcr_word(get_smword(seg_reg, EA), 1); /* RCR mem16, 1 */ - break; - case 4: - VAL = shl_word(get_smword(seg_reg, EA), 1); /* SAL/SHL mem16, 1 */ - break; - case 5: - VAL = shr_word(get_smword(seg_reg, EA), 1); /* SHR mem16, 1 */ - break; - case 7: - VAL = sar_word(get_smword(seg_reg, EA), 1); /* SAR mem16, 1 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rword(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = rol_word(get_rword(RM), 1); /* RCL reg16, 1 */ - break; - case 1: - VAL = ror_word(get_rword(RM), 1); /* ROR reg16, 1 */ - break; - case 2: - VAL = rcl_word(get_rword(RM), 1); /* RCL reg16, 1 */ - break; - case 3: - VAL = rcr_word(get_rword(RM), 1); /* RCR reg16, 1 */ - break; - case 4: - VAL = shl_word(get_rword(RM), 1); /* SHL/SAL reg16, 1 */ - break; - case 5: - VAL = shr_word(get_rword(RM), 1); /* SHR reg16, 1 */ - break; - case 7: - VAL = sar_word(get_rword(RM), 1); /* SAR reg16, 1 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xD2: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: - VAL = rol_byte(get_smbyte(seg_reg, EA), CL); /* ROL mem8, CL */ - break; - case 1: - VAL = ror_byte(get_smbyte(seg_reg, EA), CL); /* ROR mem8, CL */ - break; - case 2: - VAL = rcl_byte(get_smbyte(seg_reg, EA), CL); /* RCL mem8, CL */ - break; - case 3: - VAL = rcr_byte(get_smbyte(seg_reg, EA), CL); /* RCR mem8, CL */ - break; - case 4: - VAL = shl_byte(get_smbyte(seg_reg, EA), CL); /* SAL/SHL mem8, CL */ - break; - case 5: - VAL = shr_byte(get_smbyte(seg_reg, EA), CL); /* SHR mem8, CL */ - break; - case 7: - VAL = sar_byte(get_smbyte(seg_reg, EA), CL); /* SAR mem8, CL */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = rol_byte(get_rbyte(RM), CL); /* RCL reg8, CL */ - break; - case 1: - VAL = ror_byte(get_rbyte(RM), CL); /* ROR reg8, CL */ - break; - case 2: - VAL = rcl_byte(get_rbyte(RM), CL); /* RCL reg8, CL */ - break; - case 3: - VAL = rcr_byte(get_rbyte(RM), CL); /* RCR reg8, CL */ - break; - case 4: - VAL = shl_byte(get_rbyte(RM), CL); /* SHL/SAL reg8, CL*/ - break; - case 5: - VAL = shr_byte(get_rbyte(RM), CL); /* SHR reg8, CL */ - break; - case 7: - VAL = sar_byte(get_rbyte(RM), CL); /* SAR reg8, CL */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xD3: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: - VAL = rol_word(get_smword(seg_reg, EA), CL); /* ROL mem16, CL */ - break; - case 1: - VAL = ror_word(get_smword(seg_reg, EA), CL); /* ROR mem16, CL */ - break; - case 2: - VAL = rcl_word(get_smword(seg_reg, EA), CL); /* RCL mem16, CL */ - break; - case 3: - VAL = rcr_word(get_smword(seg_reg, EA), CL); /* RCR mem16, CL */ - break; - case 4: - VAL = shl_word(get_smword(seg_reg, EA), CL); /* SAL/SHL mem16, CL */ - break; - case 5: - VAL = shr_word(get_smword(seg_reg, EA), CL); /* SHR mem16, CL */ - break; - case 7: - VAL = sar_word(get_smword(seg_reg, EA), CL); /* SAR mem16, CL */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rword(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = rol_word(get_rword(RM), CL); /* RCL reg16, CL */ - break; - case 1: - VAL = ror_word(get_rword(RM), CL); /* ROR reg16, CL */ - break; - case 2: - VAL = rcl_word(get_rword(RM), CL); /* RCL reg16, CL */ - break; - case 3: - VAL = rcr_word(get_rword(RM), CL); /* RCR reg16, CL */ - break; - case 4: - VAL = shl_word(get_rword(RM), CL); /* SHL/SAL reg16, CL */ - break; - case 5: - VAL = shr_word(get_rword(RM), CL); /* SHR reg16, CL */ - break; - case 7: - VAL = sar_word(get_rword(RM), CL); /* SAR reg16, CL */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xD4: /* AAM */ - VAL = fetch_word(); - if (VAL != 10) { - reason = STOP_OPCODE; - IP -= 2; - } - /* note the type change here --- returning AL and AH in AX. */ - AX = aam_word(AL); - break; - - case 0xD5: /* AAD */ - VAL = fetch_word(); - if (VAL != 10) { - reason = STOP_OPCODE; - IP -= 2; - } - AX = aad_word(AX); - break; - - /* 0xD6 - Not implemented on 8086/8088 */ - - case 0xD7: /* XLAT */ - OFF = BX + (uint8)AL; - AL = get_smbyte(SEG_CS, OFF); - break; - - case 0xD8: /* ESC */ - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: - /* for now, do nothing, NOP for 8088 */ - break; - - case 0xE0: /* LOOPNE label */ - OFF = fetch_byte(1); - OFF = sign_ext(OFF); - OFF += (int16)IP; - CX -= 1; - if (CX != 0 && !GET_FLAG(ZF)) /* CX != 0 and !ZF */ - IP = OFF; - break; - - case 0xE1: /* LOOPE label */ - OFF = fetch_byte(1); - OFF = sign_ext(OFF); - OFF += (int16)IP; - CX -= 1; - if (CX != 0 && GET_FLAG(ZF)) /* CX != 0 and ZF */ - IP = OFF; - break; - - case 0xE2: /* LOOP label */ - OFF = fetch_byte(1); - OFF = sign_ext(OFF); - OFF += (int16)IP; - CX -= 1; - if (CX != 0) /* CX != 0 */ - IP = OFF; - break; - - case 0xE3: /* JCXZ label */ - OFF = fetch_byte(1); - OFF = sign_ext(OFF); - OFF += (int16)IP; - if (CX == 0) /* CX != 0 */ - IP = OFF; - break; - - case 0xE4: /* IN AL, port8 */ - DATA = fetch_byte(1); - port = DATA; - AL = dev_table[DATA].routine(0, 0); - break; - - case 0xE5: /* IN AX, port16 */ - DATA = fetch_byte(1); - port = DATA; - AH = dev_table[DATA].routine(0, 0); - AL = dev_table[DATA+1].routine(0, 0); - break; - - case 0xE6: /* OUT AL, port8 */ - DATA = fetch_byte(1); - port = DATA; - dev_table[DATA].routine(1, AL); - //sim_printf("OUT AL: DATA=%04X\n", DATA); - break; - - case 0xE7: /* OUT AX, port16 */ - DATA = fetch_byte(1); - port = DATA; - dev_table[DATA].routine(1, AH); - dev_table[DATA+1].routine(1, AL); - break; - - case 0xE8: /* CALL NEAR proc */ - OFF = fetch_word(); - push_word(IP); - IP = (OFF + IP) & ADDRMASK16; - break; - - case 0xE9: /* JMP NEAR label */ - OFF = fetch_word(); - IP = (OFF + IP) & ADDRMASK16; - break; - - case 0xEA: /* JMP FAR label */ - OFF = fetch_word(); - SEG = fetch_word(); - CS = SEG; - IP = OFF; - break; - - case 0xEB: /* JMP short-label */ - OFF = fetch_byte(1); - if (OFF & 0x80) /* if negative, sign extend */ - OFF |= 0XFF00; - IP = (IP + OFF) & ADDRMASK16; - break; - - case 0xEC: /* IN AL,DX */ - port = DX; - AL = dev_table[DX].routine(0, 0); - break; - - case 0xED: /* IN AX,DX */ - port = DX; - AH = dev_table[DX].routine(0, 0); - AL = dev_table[DX+1].routine(0, 0); - break; - - case 0xEE: /* OUT AL,DX */ - port = DX; - dev_table[DX].routine(1, AL); - break; - - case 0xEF: /* OUT AX,DX */ - port = DX; - dev_table[DX].routine(1, AH); - dev_table[DX+1].routine(1, AL); - break; - - case 0xF0: /* LOCK */ - /* do nothing for now */ - break; - - /* 0xF1 - Not implemented on 8086/8088 */ - - case 0xF2: /* REPNE/REPNZ */ - sysmode |= SYSMODE_PREFIX_REPNE; - break; - - case 0xF3: /* REP/REPE/REPZ */ - sysmode |= SYSMODE_PREFIX_REPE; - break; - - case 0xF4: /* HLT */ - reason = STOP_HALT; - IP--; - break; - - case 0xF5: /* CMC */ - TOGGLE_FLAG(CF); - break; - - case 0xF6: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* TEST mem8, immed8 */ - DATA = fetch_byte(1); - test_byte(get_smbyte(seg_reg, EA), DATA); - break; - case 2: /* NOT mem8 */ - VAL = not_byte(get_smbyte(seg_reg, EA)); - put_smbyte(seg_reg, EA, VAL); /* store result */ - break; - case 3: /* NEG mem8 */ - VAL = neg_byte(get_smbyte(seg_reg, EA)); - put_smbyte(seg_reg, EA, VAL); /* store result */ - break; - case 4: /* MUL mem8 */ - mul_byte(get_smbyte(seg_reg, EA)); - break; - case 5: /* IMUL mem8 */ - imul_byte(get_smbyte(seg_reg, EA)); - break; - case 6: /* DIV mem8 */ - div_byte(get_smbyte(seg_reg, EA)); - break; - case 7: /* IDIV mem8 */ - idiv_byte(get_smbyte(seg_reg, EA)); - break; - default: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { /* RM is second register */ - switch(REG) { - case 0: /* TEST reg8, immed8 */ - DATA = fetch_byte(1); - test_byte(get_rbyte(RM), DATA); - break; - case 2: /* NOT reg8 */ - VAL = not_byte(get_rbyte(RM)); - put_rbyte(RM, VAL); /* store result */ - break; - case 3: /* NEG reg8 */ - VAL = neg_byte(get_rbyte(RM)); - put_rbyte(RM, VAL); /* store result */ - break; - case 4: /* MUL reg8 */ - mul_byte(get_rbyte(RM)); - break; - case 5: /* IMUL reg8 */ - imul_byte(get_rbyte(RM)); - break; - case 6: /* DIV reg8 */ - div_byte(get_rbyte(RM)); - break; - case 7: /* IDIV reg8 */ - idiv_byte(get_rbyte(RM)); - break; - default: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xF7: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* TEST mem16, immed16 */ - DATA = fetch_word(); - test_word(get_smword(seg_reg, EA), DATA); - break; - case 2: /* NOT mem16 */ - VAL = not_word(get_smword(seg_reg, EA)); - put_smword(seg_reg, EA, VAL); /* store result */ - break; - case 3: /* NEG mem16 */ - VAL = neg_word(get_smword(seg_reg, EA)); - put_smword(seg_reg, EA, VAL); /* store result */ - break; - case 4: /* MUL mem16 */ - mul_word(get_smword(seg_reg, EA)); - break; - case 5: /* IMUL mem16 */ - imul_word(get_smword(seg_reg, EA)); - break; - case 6: /* DIV mem16 */ - div_word(get_smword(seg_reg, EA)); - break; - case 7: /* IDIV mem16 */ - idiv_word(get_smword(seg_reg, EA)); - break; - default: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { /* RM is second register */ - switch(REG) { - case 0: /* TEST reg16, immed16 */ - DATA = fetch_word(); - test_word(get_rword(RM), DATA); - break; - case 2: /* NOT reg16 */ - VAL = not_word(get_rword(RM)); - put_rword(RM, VAL); /* store result */ - break; - case 3: /* NEG reg16 */ - VAL = neg_word(get_rword(RM)); - put_rword(RM, VAL); /* store result */ - break; - case 4: /* MUL reg16 */ - mul_word(get_rword(RM)); - break; - case 5: /* IMUL reg16 */ - imul_word(get_rword(RM)); - break; - case 6: /* DIV reg16 */ - div_word(get_rword(RM)); - break; - case 7: /* IDIV reg16 */ - idiv_word(get_rword(RM)); - break; - default: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xF8: /* CLC */ - CLR_FLAG(CF); - break; - - case 0xF9: /* STC */ - SET_FLAG(CF); - break; - - case 0xFA: /* CLI */ - CLR_FLAG(IF); - break; - - case 0xFB: /* STI */ - SET_FLAG(IF); - break; - - case 0xFC: /* CLD */ - CLR_FLAG(DF); - break; - - case 0xFD: /* STD */ - SET_FLAG(DF); - break; - - case 0xFE: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* INC mem16 */ - VAL = inc_byte(get_smbyte(seg_reg, EA)); /* do operation */ - put_smbyte(seg_reg, EA, VAL); /* store result */ - break; - case 1: /* DEC mem16 */ - VAL = dec_byte(get_smbyte(seg_reg, EA)); /* do operation */ - put_smbyte(seg_reg, EA, VAL); /* store result */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = inc_byte(get_rbyte(RM)); /* do operation */ - put_rbyte(RM, VAL); /* store result */ - break; - case 1: - VAL = dec_byte(get_rbyte(RM)); /* do operation */ - put_rbyte(RM, VAL); /* store result */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xFF: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* INC mem16 */ - VAL = inc_word(get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - break; - case 1: /* DEC mem16 */ - VAL = dec_word(get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - break; - case 2: /* CALL NEAR mem16 */ - OFF = get_smword(SEG_CS, EA); /* do operation */ - push_word(IP); - IP = OFF; - break; - case 3: /* CALL FAR mem16 */ - OFF = get_smword(SEG_CS, EA); /* do operation */ - SEG = get_smword(SEG_CS, EA + 2); - push_word(CS); - CS = SEG; - push_word(IP); - IP = OFF; - break; - case 4: /* JMP NEAR mem16 */ - OFF = get_smword(SEG_CS, EA); /* do operation */ - IP = OFF; - break; - case 5: /* JMP FAR mem16 */ - OFF = get_smword(SEG_CS, EA); /* do operation */ - SEG = get_smword(SEG_CS, EA + 2); - CS = SEG; - IP = OFF; - break; - case 6: /* PUSH mem16 */ - VAL = get_smword(seg_reg, EA); /* do operation */ - push_word(VAL); - break; - case 7: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { /* RM is second register */ - switch(REG) { - case 2: /* CALL NEAR reg16 */ - OFF = get_rword(RM); /* do operation */ - push_word(IP); - IP = OFF; - break; - case 4: /* JMP NEAR reg16 */ - OFF = get_rword(RM); /* do operation */ - IP = OFF; - break; - default: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - - default: -// if (i8088_unit.flags & UNIT_OPSTOP) { - reason = STOP_OPCODE; - IP--; -// } - break; - } - /* not segment override */ - if ((IR == 0x26) || (IR == 0x2E) || (IR == 0x36) || (IR == 0x3E)) { - seg_ovr = SEG_NONE; /* clear segment override */ - sysmode &= 0x0000001E; /* clear flags */ - sysmode |= 0x00000001; - } - if (i8088_dev.dctrl & DEBUG_asm) { - sim_printf("%04X:%04X %s", CS, IP, opcode[IR]); - switch (oplen[IR]) { - case 0: //one byte opcode - break; - case 1: //IMMED8 - sim_printf(" 0%02XH", DATA); - break; - case 2: //IMMED16 - sim_printf(" 0%04XH", DATA); - break; - case 3: //IP-INC8 - sim_printf(" 0%02XH", EA); - break; - case 4: //IP-INC16 - sim_printf(" 0%04XH", EA); - break; - /* - case 5: //MAR - sim_printf(" 0%02XH", MAR); - break; - */ - default: - break; - } - } - if (i8088_dev.dctrl & DEBUG_reg) { - sim_printf("\nRegs: AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X IP=%04X\n", - AX, BX, CX, DX, SP, BP, SI, DI, IP); - sim_printf("Segs: CS=%04X DS=%04X ES=%04X SS=%04X Flags: %04X\n", CS, DS, ES, SS, PSW); - } - } -/* Simulation halted */ - + SGX = CS; + +// if ( (totalexec & 31) == 0) timing(); + + if (trap_toggle) { + intcall86 (1); + } + + if (tf) { + trap_toggle = 1; + } + else { + trap_toggle = 0; + } + +// if (!trap_toggle && (ifl && (i8259.irr & (~i8259.imr) ) ) ) { +// intcall86 (nextintr() ); /* get next interrupt from the i8259, if any */ +// } + + reptype = 0; + segoverride = 0; + useseg = segregs[regds]; + docontinue = 0; + firstip = IP; + +// if ( (segregs[regcs] == 0xF000) && (IP == 0xE066) ) didbootstrap = 0; //detect if we hit the BIOS entry point to clear didbootstrap because we've rebooted + + while (!docontinue) { + segregs[regcs] = segregs[regcs] & 0xFFFF; + IP = IP & 0xFFFF; + SEG = segregs[regcs]; + OFF = IP; + OP = getmem8 (segregs[regcs], IP); + StepIP (1); + + switch (OP) { + /* segment prefix check */ + case 0x2E: /* segment segregs[regcs] */ + useseg = segregs[regcs]; + segoverride = 1; + break; + + case 0x3E: /* segment segregs[regds] */ + useseg = segregs[regds]; + segoverride = 1; + break; + + case 0x26: /* segment segregs[reges] */ + useseg = segregs[reges]; + segoverride = 1; + break; + + case 0x36: /* segment segregs[regss] */ + useseg = segregs[regss]; + segoverride = 1; + break; + + /* repetition prefix check */ + case 0xF3: /* REP/REPE/REPZ */ + reptype = 1; + break; + + case 0xF2: /* REPNE/REPNZ */ + reptype = 2; + break; + + default: + docontinue = 1; + break; + } + } + + totalexec++; + + /* + * if (printops == 1) { printf("%04X:%04X - %s\n", SEG, OFF, oplist[OP]); + * } + */ + switch (OP) { + case 0x0: /* 00 ADD Eb Gb */ + modregrm(); + oper1b = readrm8 (RM); + oper2b = getreg8 (REGX); + op_add8(); + writerm8 (RM, res8); + break; + + case 0x1: /* 01 ADD Ev Gv */ + modregrm(); + oper1 = readrm16 (RM); + oper2 = getreg16 (REGX); + op_add16(); + writerm16 (RM, res16); + break; + + case 0x2: /* 02 ADD Gb Eb */ + modregrm(); + oper1b = getreg8 (REGX); + oper2b = readrm8 (RM); + op_add8(); + putreg8 (REGX, res8); + break; + + case 0x3: /* 03 ADD Gv Ev */ + modregrm(); + oper1 = getreg16 (REGX); + oper2 = readrm16 (RM); + op_add16(); + putreg16 (REGX, res16); + break; + + case 0x4: /* 04 ADD regs.byteregs[regal] Ib */ + oper1b = regs.byteregs[regal]; + oper2b = getmem8 (segregs[regcs], IP); + StepIP (1); + op_add8(); + regs.byteregs[regal] = res8; + break; + + case 0x5: /* 05 ADD eAX Iv */ + oper1 = (getreg16 (regax) ); + oper2 = getmem16 (segregs[regcs], IP); + StepIP (2); + op_add16(); + putreg16 (regax, res16); + break; + + case 0x6: /* 06 PUSH segregs[reges] */ + push (segregs[reges]); + break; + + case 0x7: /* 07 POP segregs[reges] */ + segregs[reges] = pop(); + break; + + case 0x8: /* 08 OR Eb Gb */ + modregrm(); + oper1b = readrm8 (RM); + oper2b = getreg8 (REGX); + op_or8(); + writerm8 (RM, res8); + break; + + case 0x9: /* 09 OR Ev Gv */ + modregrm(); + oper1 = readrm16 (RM); + oper2 = getreg16 (REGX); + op_or16(); + writerm16 (RM, res16); + break; + + case 0xA: /* 0A OR Gb Eb */ + modregrm(); + oper1b = getreg8 (REGX); + oper2b = readrm8 (RM); + op_or8(); + putreg8 (REGX, res8); + break; + + case 0xB: /* 0B OR Gv Ev */ + modregrm(); + oper1 = getreg16 (REGX); + oper2 = readrm16 (RM); + op_or16(); + if ( (oper1 == 0xF802) && (oper2 == 0xF802) ) { + sf = 0; /* cheap hack to make Wolf 3D think we're a 286 so it plays */ + } + + putreg16 (REGX, res16); + break; + + case 0xC: /* 0C OR regs.byteregs[regal] Ib */ + oper1b = regs.byteregs[regal]; + oper2b = getmem8 (segregs[regcs], IP); + StepIP (1); + op_or8(); + regs.byteregs[regal] = res8; + break; + + case 0xD: /* 0D OR eAX Iv */ + oper1 = getreg16 (regax); + oper2 = getmem16 (segregs[regcs], IP); + StepIP (2); + op_or16(); + putreg16 (regax, res16); + break; + + case 0xE: /* 0E PUSH segregs[regcs] */ + push (segregs[regcs]); + break; + + case 0xF: //0F POP CS +#ifndef CPU_V20 + segregs[regcs] = pop(); +#endif + break; + + case 0x10: /* 10 ADC Eb Gb */ + modregrm(); + oper1b = readrm8 (RM); + oper2b = getreg8 (REGX); + op_adc8(); + writerm8 (RM, res8); + break; + + case 0x11: /* 11 ADC Ev Gv */ + modregrm(); + oper1 = readrm16 (RM); + oper2 = getreg16 (REGX); + op_adc16(); + writerm16 (RM, res16); + break; + + case 0x12: /* 12 ADC Gb Eb */ + modregrm(); + oper1b = getreg8 (REGX); + oper2b = readrm8 (RM); + op_adc8(); + putreg8 (REGX, res8); + break; + + case 0x13: /* 13 ADC Gv Ev */ + modregrm(); + oper1 = getreg16 (REGX); + oper2 = readrm16 (RM); + op_adc16(); + putreg16 (REGX, res16); + break; + + case 0x14: /* 14 ADC regs.byteregs[regal] Ib */ + oper1b = regs.byteregs[regal]; + oper2b = getmem8 (segregs[regcs], IP); + StepIP (1); + op_adc8(); + regs.byteregs[regal] = res8; + break; + + case 0x15: /* 15 ADC eAX Iv */ + oper1 = getreg16 (regax); + oper2 = getmem16 (segregs[regcs], IP); + StepIP (2); + op_adc16(); + putreg16 (regax, res16); + break; + + case 0x16: /* 16 PUSH segregs[regss] */ + push (segregs[regss]); + break; + + case 0x17: /* 17 POP segregs[regss] */ + segregs[regss] = pop(); + break; + + case 0x18: /* 18 SBB Eb Gb */ + modregrm(); + oper1b = readrm8 (RM); + oper2b = getreg8 (REGX); + op_sbb8(); + writerm8 (RM, res8); + break; + + case 0x19: /* 19 SBB Ev Gv */ + modregrm(); + oper1 = readrm16 (RM); + oper2 = getreg16 (REGX); + op_sbb16(); + writerm16 (RM, res16); + break; + + case 0x1A: /* 1A SBB Gb Eb */ + modregrm(); + oper1b = getreg8 (REGX); + oper2b = readrm8 (RM); + op_sbb8(); + putreg8 (REGX, res8); + break; + + case 0x1B: /* 1B SBB Gv Ev */ + modregrm(); + oper1 = getreg16 (REGX); + oper2 = readrm16 (RM); + op_sbb16(); + putreg16 (REGX, res16); + break; + + case 0x1C: /* 1C SBB regs.byteregs[regal] Ib */ + oper1b = regs.byteregs[regal]; + oper2b = getmem8 (segregs[regcs], IP); + StepIP (1); + op_sbb8(); + regs.byteregs[regal] = res8; + break; + + case 0x1D: /* 1D SBB eAX Iv */ + oper1 = getreg16 (regax); + oper2 = getmem16 (segregs[regcs], IP); + StepIP (2); + op_sbb16(); + putreg16 (regax, res16); + break; + + case 0x1E: /* 1E PUSH segregs[regds] */ + push (segregs[regds]); + break; + + case 0x1F: /* 1F POP segregs[regds] */ + segregs[regds] = pop(); + break; + + case 0x20: /* 20 AND Eb Gb */ + modregrm(); + oper1b = readrm8 (RM); + oper2b = getreg8 (REGX); + op_and8(); + writerm8 (RM, res8); + break; + + case 0x21: /* 21 AND Ev Gv */ + modregrm(); + oper1 = readrm16 (RM); + oper2 = getreg16 (REGX); + op_and16(); + writerm16 (RM, res16); + break; + + case 0x22: /* 22 AND Gb Eb */ + modregrm(); + oper1b = getreg8 (REGX); + oper2b = readrm8 (RM); + op_and8(); + putreg8 (REGX, res8); + break; + + case 0x23: /* 23 AND Gv Ev */ + modregrm(); + oper1 = getreg16 (REGX); + oper2 = readrm16 (RM); + op_and16(); + putreg16 (REGX, res16); + break; + + case 0x24: /* 24 AND regs.byteregs[regal] Ib */ + oper1b = regs.byteregs[regal]; + oper2b = getmem8 (segregs[regcs], IP); + StepIP (1); + op_and8(); + regs.byteregs[regal] = res8; + break; + + case 0x25: /* 25 AND eAX Iv */ + oper1 = getreg16 (regax); + oper2 = getmem16 (segregs[regcs], IP); + StepIP (2); + op_and16(); + putreg16 (regax, res16); + break; + + case 0x27: /* 27 DAA */ + if ( ( (regs.byteregs[regal] & 0xF) > 9) || (af == 1) ) { + oper1 = regs.byteregs[regal] + 6; + regs.byteregs[regal] = oper1 & 255; + if (oper1 & 0xFF00) { + cf = 1; + } + else { + cf = 0; + } + + af = 1; + } + else { + af = 0; + } + + if ( ( (regs.byteregs[regal] & 0xF0) > 0x90) || (cf == 1) ) { + regs.byteregs[regal] = regs.byteregs[regal] + 0x60; + cf = 1; + } + else { + cf = 0; + } + + regs.byteregs[regal] = regs.byteregs[regal] & 255; + flag_szp8 (regs.byteregs[regal]); + break; + + case 0x28: /* 28 SUB Eb Gb */ + modregrm(); + oper1b = readrm8 (RM); + oper2b = getreg8 (REGX); + op_sub8(); + writerm8 (RM, res8); + break; + + case 0x29: /* 29 SUB Ev Gv */ + modregrm(); + oper1 = readrm16 (RM); + oper2 = getreg16 (REGX); + op_sub16(); + writerm16 (RM, res16); + break; + + case 0x2A: /* 2A SUB Gb Eb */ + modregrm(); + oper1b = getreg8 (REGX); + oper2b = readrm8 (RM); + op_sub8(); + putreg8 (REGX, res8); + break; + + case 0x2B: /* 2B SUB Gv Ev */ + modregrm(); + oper1 = getreg16 (REGX); + oper2 = readrm16 (RM); + op_sub16(); + putreg16 (REGX, res16); + break; + + case 0x2C: /* 2C SUB regs.byteregs[regal] Ib */ + oper1b = regs.byteregs[regal]; + oper2b = getmem8 (segregs[regcs], IP); + StepIP (1); + op_sub8(); + regs.byteregs[regal] = res8; + break; + + case 0x2D: /* 2D SUB eAX Iv */ + oper1 = getreg16 (regax); + oper2 = getmem16 (segregs[regcs], IP); + StepIP (2); + op_sub16(); + putreg16 (regax, res16); + break; + + case 0x2F: /* 2F DAS */ + if ( ( (regs.byteregs[regal] & 15) > 9) || (af == 1) ) { + oper1 = regs.byteregs[regal] - 6; + regs.byteregs[regal] = oper1 & 255; + if (oper1 & 0xFF00) { + cf = 1; + } + else { + cf = 0; + } + + af = 1; + } + else { + af = 0; + } + + if ( ( (regs.byteregs[regal] & 0xF0) > 0x90) || (cf == 1) ) { + regs.byteregs[regal] = regs.byteregs[regal] - 0x60; + cf = 1; + } + else { + cf = 0; + } + + flag_szp8 (regs.byteregs[regal]); + break; + + case 0x30: /* 30 XOR Eb Gb */ + modregrm(); + oper1b = readrm8 (RM); + oper2b = getreg8 (REGX); + op_xor8(); + writerm8 (RM, res8); + break; + + case 0x31: /* 31 XOR Ev Gv */ + modregrm(); + oper1 = readrm16 (RM); + oper2 = getreg16 (REGX); + op_xor16(); + writerm16 (RM, res16); + break; + + case 0x32: /* 32 XOR Gb Eb */ + modregrm(); + oper1b = getreg8 (REGX); + oper2b = readrm8 (RM); + op_xor8(); + putreg8 (REGX, res8); + break; + + case 0x33: /* 33 XOR Gv Ev */ + modregrm(); + oper1 = getreg16 (REGX); + oper2 = readrm16 (RM); + op_xor16(); + putreg16 (REGX, res16); + break; + + case 0x34: /* 34 XOR regs.byteregs[regal] Ib */ + oper1b = regs.byteregs[regal]; + oper2b = getmem8 (segregs[regcs], IP); + StepIP (1); + op_xor8(); + regs.byteregs[regal] = res8; + break; + + case 0x35: /* 35 XOR eAX Iv */ + oper1 = getreg16 (regax); + oper2 = getmem16 (segregs[regcs], IP); + StepIP (2); + op_xor16(); + putreg16 (regax, res16); + break; + + case 0x37: /* 37 AAA ASCII */ + if ( ( (regs.byteregs[regal] & 0xF) > 9) || (af == 1) ) { + regs.byteregs[regal] = regs.byteregs[regal] + 6; + regs.byteregs[regah] = regs.byteregs[regah] + 1; + af = 1; + cf = 1; + } + else { + af = 0; + cf = 0; + } + + regs.byteregs[regal] = regs.byteregs[regal] & 0xF; + break; + + case 0x38: /* 38 CMP Eb Gb */ + modregrm(); + oper1b = readrm8 (RM); + oper2b = getreg8 (REGX); + flag_sub8 (oper1b, oper2b); + break; + + case 0x39: /* 39 CMP Ev Gv */ + modregrm(); + oper1 = readrm16 (RM); + oper2 = getreg16 (REGX); + flag_sub16 (oper1, oper2); + break; + + case 0x3A: /* 3A CMP Gb Eb */ + modregrm(); + oper1b = getreg8 (REGX); + oper2b = readrm8 (RM); + flag_sub8 (oper1b, oper2b); + break; + + case 0x3B: /* 3B CMP Gv Ev */ + modregrm(); + oper1 = getreg16 (REGX); + oper2 = readrm16 (RM); + flag_sub16 (oper1, oper2); + break; + + case 0x3C: /* 3C CMP regs.byteregs[regal] Ib */ + oper1b = regs.byteregs[regal]; + oper2b = getmem8 (segregs[regcs], IP); + StepIP (1); + flag_sub8 (oper1b, oper2b); + break; + + case 0x3D: /* 3D CMP eAX Iv */ + oper1 = getreg16 (regax); + oper2 = getmem16 (segregs[regcs], IP); + StepIP (2); + flag_sub16 (oper1, oper2); + break; + + case 0x3F: /* 3F AAS ASCII */ + if ( ( (regs.byteregs[regal] & 0xF) > 9) || (af == 1) ) { + regs.byteregs[regal] = regs.byteregs[regal] - 6; + regs.byteregs[regah] = regs.byteregs[regah] - 1; + af = 1; + cf = 1; + } + else { + af = 0; + cf = 0; + } + + regs.byteregs[regal] = regs.byteregs[regal] & 0xF; + break; + + case 0x40: /* 40 INC eAX */ + oldcf = cf; + oper1 = getreg16 (regax); + oper2 = 1; + op_add16(); + cf = oldcf; + putreg16 (regax, res16); + break; + + case 0x41: /* 41 INC eCX */ + oldcf = cf; + oper1 = getreg16 (regcx); + oper2 = 1; + op_add16(); + cf = oldcf; + putreg16 (regcx, res16); + break; + + case 0x42: /* 42 INC eDX */ + oldcf = cf; + oper1 = getreg16 (regdx); + oper2 = 1; + op_add16(); + cf = oldcf; + putreg16 (regdx, res16); + break; + + case 0x43: /* 43 INC eBX */ + oldcf = cf; + oper1 = getreg16 (regbx); + oper2 = 1; + op_add16(); + cf = oldcf; + putreg16 (regbx, res16); + break; + + case 0x44: /* 44 INC eSP */ + oldcf = cf; + oper1 = getreg16 (regsp); + oper2 = 1; + op_add16(); + cf = oldcf; + putreg16 (regsp, res16); + break; + + case 0x45: /* 45 INC eBP */ + oldcf = cf; + oper1 = getreg16 (regbp); + oper2 = 1; + op_add16(); + cf = oldcf; + putreg16 (regbp, res16); + break; + + case 0x46: /* 46 INC eSI */ + oldcf = cf; + oper1 = getreg16 (regsi); + oper2 = 1; + op_add16(); + cf = oldcf; + putreg16 (regsi, res16); + break; + + case 0x47: /* 47 INC eDI */ + oldcf = cf; + oper1 = getreg16 (regdi); + oper2 = 1; + op_add16(); + cf = oldcf; + putreg16 (regdi, res16); + break; + + case 0x48: /* 48 DEC eAX */ + oldcf = cf; + oper1 = getreg16 (regax); + oper2 = 1; + op_sub16(); + cf = oldcf; + putreg16 (regax, res16); + break; + + case 0x49: /* 49 DEC eCX */ + oldcf = cf; + oper1 = getreg16 (regcx); + oper2 = 1; + op_sub16(); + cf = oldcf; + putreg16 (regcx, res16); + break; + + case 0x4A: /* 4A DEC eDX */ + oldcf = cf; + oper1 = getreg16 (regdx); + oper2 = 1; + op_sub16(); + cf = oldcf; + putreg16 (regdx, res16); + break; + + case 0x4B: /* 4B DEC eBX */ + oldcf = cf; + oper1 = getreg16 (regbx); + oper2 = 1; + op_sub16(); + cf = oldcf; + putreg16 (regbx, res16); + break; + + case 0x4C: /* 4C DEC eSP */ + oldcf = cf; + oper1 = getreg16 (regsp); + oper2 = 1; + op_sub16(); + cf = oldcf; + putreg16 (regsp, res16); + break; + + case 0x4D: /* 4D DEC eBP */ + oldcf = cf; + oper1 = getreg16 (regbp); + oper2 = 1; + op_sub16(); + cf = oldcf; + putreg16 (regbp, res16); + break; + + case 0x4E: /* 4E DEC eSI */ + oldcf = cf; + oper1 = getreg16 (regsi); + oper2 = 1; + op_sub16(); + cf = oldcf; + putreg16 (regsi, res16); + break; + + case 0x4F: /* 4F DEC eDI */ + oldcf = cf; + oper1 = getreg16 (regdi); + oper2 = 1; + op_sub16(); + cf = oldcf; + putreg16 (regdi, res16); + break; + + case 0x50: /* 50 PUSH eAX */ + push (getreg16 (regax) ); + break; + + case 0x51: /* 51 PUSH eCX */ + push (getreg16 (regcx) ); + break; + + case 0x52: /* 52 PUSH eDX */ + push (getreg16 (regdx) ); + break; + + case 0x53: /* 53 PUSH eBX */ + push (getreg16 (regbx) ); + break; + + case 0x54: /* 54 PUSH eSP */ + push (getreg16 (regsp) - 2); + break; + + case 0x55: /* 55 PUSH eBP */ + push (getreg16 (regbp) ); + break; + + case 0x56: /* 56 PUSH eSI */ + push (getreg16 (regsi) ); + break; + + case 0x57: /* 57 PUSH eDI */ + push (getreg16 (regdi) ); + break; + + case 0x58: /* 58 POP eAX */ + putreg16 (regax, pop() ); + break; + + case 0x59: /* 59 POP eCX */ + putreg16 (regcx, pop() ); + break; + + case 0x5A: /* 5A POP eDX */ + putreg16 (regdx, pop() ); + break; + + case 0x5B: /* 5B POP eBX */ + putreg16 (regbx, pop() ); + break; + + case 0x5C: /* 5C POP eSP */ + putreg16 (regsp, pop() ); + break; + + case 0x5D: /* 5D POP eBP */ + putreg16 (regbp, pop() ); + break; + + case 0x5E: /* 5E POP eSI */ + putreg16 (regsi, pop() ); + break; + + case 0x5F: /* 5F POP eDI */ + putreg16 (regdi, pop() ); + break; + +#ifdef CPU_V20 + case 0x60: /* 60 PUSHA (80186+) */ + oldsp = getreg16 (regsp); + push (getreg16 (regax) ); + push (getreg16 (regcx) ); + push (getreg16 (regdx) ); + push (getreg16 (regbx) ); + push (oldsp); + push (getreg16 (regbp) ); + push (getreg16 (regsi) ); + push (getreg16 (regdi) ); + break; + + case 0x61: /* 61 POPA (80186+) */ + putreg16 (regdi, pop() ); + putreg16 (regsi, pop() ); + putreg16 (regbp, pop() ); + dummy = pop(); + putreg16 (regbx, pop() ); + putreg16 (regdx, pop() ); + putreg16 (regcx, pop() ); + putreg16 (regax, pop() ); + break; + + case 0x62: /* 62 BOUND Gv, Ev (80186+) */ + modregrm(); + getea (RM); + if (signext32 (getreg16 (REGX) ) < signext32 ( getmem16 (EA >> 4, EA & 15) ) ) { + intcall86 (5); //bounds check exception + } + else { + EA += 2; + if (signext32 (getreg16 (REGX) ) > signext32 ( getmem16 (EA >> 4, EA & 15) ) ) { + intcall86(5); //bounds check exception + } + } + break; + + case 0x68: /* 68 PUSH Iv (80186+) */ + push (getmem16 (segregs[regcs], IP) ); + StepIP (2); + break; + + case 0x69: /* 69 IMUL Gv Ev Iv (80186+) */ + modregrm(); + temp1 = readrm16 (RM); + temp2 = getmem16 (segregs[regcs], IP); + StepIP (2); + if ( (temp1 & 0x8000L) == 0x8000L) { + temp1 = temp1 | 0xFFFF0000L; + } + + if ( (temp2 & 0x8000L) == 0x8000L) { + temp2 = temp2 | 0xFFFF0000L; + } + + temp3 = temp1 * temp2; + putreg16 (REGX, temp3 & 0xFFFFL); + if (temp3 & 0xFFFF0000L) { + cf = 1; + of = 1; + } + else { + cf = 0; + of = 0; + } + break; + + case 0x6A: /* 6A PUSH Ib (80186+) */ + push (getmem8 (segregs[regcs], IP) ); + StepIP (1); + break; + + case 0x6B: /* 6B IMUL Gv Eb Ib (80186+) */ + modregrm(); + temp1 = readrm16 (RM); + temp2 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if ( (temp1 & 0x8000L) == 0x8000L) { + temp1 = temp1 | 0xFFFF0000L; + } + + if ( (temp2 & 0x8000L) == 0x8000L) { + temp2 = temp2 | 0xFFFF0000L; + } + + temp3 = temp1 * temp2; + putreg16 (REGX, temp3 & 0xFFFFL); + if (temp3 & 0xFFFF0000L) { + cf = 1; + of = 1; + } + else { + cf = 0; + of = 0; + } + break; + + case 0x6C: /* 6E INSB */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + putmem8 (useseg, getreg16 (regsi) , portin (regs.wordregs[regdx]) ); + if (df) { + putreg16 (regsi, getreg16 (regsi) - 1); + putreg16 (regdi, getreg16 (regdi) - 1); + } + else { + putreg16 (regsi, getreg16 (regsi) + 1); + putreg16 (regdi, getreg16 (regdi) + 1); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0x6D: /* 6F INSW */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + putmem16 (useseg, getreg16 (regsi) , portin16 (regs.wordregs[regdx]) ); + if (df) { + putreg16 (regsi, getreg16 (regsi) - 2); + putreg16 (regdi, getreg16 (regdi) - 2); + } + else { + putreg16 (regsi, getreg16 (regsi) + 2); + putreg16 (regdi, getreg16 (regdi) + 2); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0x6E: /* 6E OUTSB */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + portout (regs.wordregs[regdx], getmem8 (useseg, getreg16 (regsi) ) ); + if (df) { + putreg16 (regsi, getreg16 (regsi) - 1); + putreg16 (regdi, getreg16 (regdi) - 1); + } + else { + putreg16 (regsi, getreg16 (regsi) + 1); + putreg16 (regdi, getreg16 (regdi) + 1); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0x6F: /* 6F OUTSW */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + portout16 (regs.wordregs[regdx], getmem16 (useseg, getreg16 (regsi) ) ); + if (df) { + putreg16 (regsi, getreg16 (regsi) - 2); + putreg16 (regdi, getreg16 (regdi) - 2); + } + else { + putreg16 (regsi, getreg16 (regsi) + 2); + putreg16 (regdi, getreg16 (regdi) + 2); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; +#endif + + case 0x70: /* 70 JO Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (of) { + IP = IP + temp16; + } + break; + + case 0x71: /* 71 JNO Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (!of) { + IP = IP + temp16; + } + break; + + case 0x72: /* 72 JB Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (cf) { + IP = IP + temp16; + } + break; + + case 0x73: /* 73 JNB Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (!cf) { + IP = IP + temp16; + } + break; + + case 0x74: /* 74 JZ Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (zf) { + IP = IP + temp16; + } + break; + + case 0x75: /* 75 JNZ Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (!zf) { + IP = IP + temp16; + } + break; + + case 0x76: /* 76 JBE Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (cf || zf) { + IP = IP + temp16; + } + break; + + case 0x77: /* 77 JA Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (!cf && !zf) { + IP = IP + temp16; + } + break; + + case 0x78: /* 78 JS Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (sf) { + IP = IP + temp16; + } + break; + + case 0x79: /* 79 JNS Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (!sf) { + IP = IP + temp16; + } + break; + + case 0x7A: /* 7A JPE Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (pf) { + IP = IP + temp16; + } + break; + + case 0x7B: /* 7B JPO Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (!pf) { + IP = IP + temp16; + } + break; + + case 0x7C: /* 7C JL Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (sf != of) { + IP = IP + temp16; + } + break; + + case 0x7D: /* 7D JGE Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (sf == of) { + IP = IP + temp16; + } + break; + + case 0x7E: /* 7E JLE Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if ( (sf != of) || zf) { + IP = IP + temp16; + } + break; + + case 0x7F: /* 7F JG Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (!zf && (sf == of) ) { + IP = IP + temp16; + } + break; + + case 0x80: + case 0x82: /* 80/82 GRP1 Eb Ib */ + modregrm(); + oper1b = readrm8 (RM); + oper2b = getmem8 (segregs[regcs], IP); + StepIP (1); + switch (REGX) { + case 0: + op_add8(); + break; + case 1: + op_or8(); + break; + case 2: + op_adc8(); + break; + case 3: + op_sbb8(); + break; + case 4: + op_and8(); + break; + case 5: + op_sub8(); + break; + case 6: + op_xor8(); + break; + case 7: + flag_sub8 (oper1b, oper2b); + break; + default: + break; /* to avoid compiler warnings */ + } + + if (REGX < 7) { + writerm8 (RM, res8); + } + break; + + case 0x81: /* 81 GRP1 Ev Iv */ + case 0x83: /* 83 GRP1 Ev Ib */ + modregrm(); + oper1 = readrm16 (RM); + if (OP == 0x81) { + oper2 = getmem16 (segregs[regcs], IP); + StepIP (2); + } + else { + oper2 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + } + + switch (REGX) { + case 0: + op_add16(); + break; + case 1: + op_or16(); + break; + case 2: + op_adc16(); + break; + case 3: + op_sbb16(); + break; + case 4: + op_and16(); + break; + case 5: + op_sub16(); + break; + case 6: + op_xor16(); + break; + case 7: + flag_sub16 (oper1, oper2); + break; + default: + break; /* to avoid compiler warnings */ + } + + if (REGX < 7) { + writerm16 (RM, res16); + } + break; + + case 0x84: /* 84 TEST Gb Eb */ + modregrm(); + oper1b = getreg8 (REGX); + oper2b = readrm8 (RM); + flag_log8 (oper1b & oper2b); + break; + + case 0x85: /* 85 TEST Gv Ev */ + modregrm(); + oper1 = getreg16 (REGX); + oper2 = readrm16 (RM); + flag_log16 (oper1 & oper2); + break; + + case 0x86: /* 86 XCHG Gb Eb */ + modregrm(); + oper1b = getreg8 (REGX); + putreg8 (REGX, readrm8 (RM) ); + writerm8 (RM, oper1b); + break; + + case 0x87: /* 87 XCHG Gv Ev */ + modregrm(); + oper1 = getreg16 (REGX); + putreg16 (REGX, readrm16 (RM) ); + writerm16 (RM, oper1); + break; + + case 0x88: /* 88 MOV Eb Gb */ + modregrm(); + writerm8 (RM, getreg8 (REGX) ); + break; + + case 0x89: /* 89 MOV Ev Gv */ + modregrm(); + writerm16 (RM, getreg16 (REGX) ); + break; + + case 0x8A: /* 8A MOV Gb Eb */ + modregrm(); + putreg8 (REGX, readrm8 (RM) ); + break; + + case 0x8B: /* 8B MOV Gv Ev */ + modregrm(); + putreg16 (REGX, readrm16 (RM) ); + break; + + case 0x8C: /* 8C MOV Ew Sw */ + modregrm(); + writerm16 (RM, getsegreg (REGX) ); + break; + + case 0x8D: /* 8D LEA Gv M */ + modregrm(); + getea (RM); + putreg16 (REGX, EA - segbase (useseg) ); + break; + + case 0x8E: /* 8E MOV Sw Ew */ + modregrm(); + putsegreg (REGX, readrm16 (RM) ); + break; + + case 0x8F: /* 8F POP Ev */ + modregrm(); + writerm16 (RM, pop() ); + break; + + case 0x90: /* 90 NOP */ + break; + + case 0x91: /* 91 XCHG eCX eAX */ + oper1 = getreg16 (regcx); + putreg16 (regcx, getreg16 (regax) ); + putreg16 (regax, oper1); + break; + + case 0x92: /* 92 XCHG eDX eAX */ + oper1 = getreg16 (regdx); + putreg16 (regdx, getreg16 (regax) ); + putreg16 (regax, oper1); + break; + + case 0x93: /* 93 XCHG eBX eAX */ + oper1 = getreg16 (regbx); + putreg16 (regbx, getreg16 (regax) ); + putreg16 (regax, oper1); + break; + + case 0x94: /* 94 XCHG eSP eAX */ + oper1 = getreg16 (regsp); + putreg16 (regsp, getreg16 (regax) ); + putreg16 (regax, oper1); + break; + + case 0x95: /* 95 XCHG eBP eAX */ + oper1 = getreg16 (regbp); + putreg16 (regbp, getreg16 (regax) ); + putreg16 (regax, oper1); + break; + + case 0x96: /* 96 XCHG eSI eAX */ + oper1 = getreg16 (regsi); + putreg16 (regsi, getreg16 (regax) ); + putreg16 (regax, oper1); + break; + + case 0x97: /* 97 XCHG eDI eAX */ + oper1 = getreg16 (regdi); + putreg16 (regdi, getreg16 (regax) ); + putreg16 (regax, oper1); + break; + + case 0x98: /* 98 CBW */ + if ( (regs.byteregs[regal] & 0x80) == 0x80) { + regs.byteregs[regah] = 0xFF; + } + else { + regs.byteregs[regah] = 0; + } + break; + + case 0x99: /* 99 CWD */ + if ( (regs.byteregs[regah] & 0x80) == 0x80) { + putreg16 (regdx, 0xFFFF); + } + else { + putreg16 (regdx, 0); + } + break; + + case 0x9A: /* 9A CALL Ap */ + oper1 = getmem16 (segregs[regcs], IP); + StepIP (2); + oper2 = getmem16 (segregs[regcs], IP); + StepIP (2); + push (segregs[regcs]); + push (IP); + IP = oper1; + segregs[regcs] = oper2; + break; + + case 0x9B: /* 9B WAIT */ + break; + + case 0x9C: /* 9C PUSHF */ + push (makeflagsword() | 0xF800); + break; + + case 0x9D: /* 9D POPF */ + temp16 = pop(); + decodeflagsword (temp16); + break; + + case 0x9E: /* 9E SAHF */ + decodeflagsword ( (makeflagsword() & 0xFF00) | regs.byteregs[regah]); + break; + + case 0x9F: /* 9F LAHF */ + regs.byteregs[regah] = makeflagsword() & 0xFF; + break; + + case 0xA0: /* A0 MOV regs.byteregs[regal] Ob */ + regs.byteregs[regal] = getmem8 (useseg, getmem16 (segregs[regcs], IP) ); + StepIP (2); + break; + + case 0xA1: /* A1 MOV eAX Ov */ + oper1 = getmem16 (useseg, getmem16 (segregs[regcs], IP) ); + StepIP (2); + putreg16 (regax, oper1); + break; + + case 0xA2: /* A2 MOV Ob regs.byteregs[regal] */ + putmem8 (useseg, getmem16 (segregs[regcs], IP), regs.byteregs[regal]); + StepIP (2); + break; + + case 0xA3: /* A3 MOV Ov eAX */ + putmem16 (useseg, getmem16 (segregs[regcs], IP), getreg16 (regax) ); + StepIP (2); + break; + + case 0xA4: /* A4 MOVSB */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + putmem8 (segregs[reges], getreg16 (regdi), getmem8 (useseg, getreg16 (regsi) ) ); + if (df) { + putreg16 (regsi, getreg16 (regsi) - 1); + putreg16 (regdi, getreg16 (regdi) - 1); + } + else { + putreg16 (regsi, getreg16 (regsi) + 1); + putreg16 (regdi, getreg16 (regdi) + 1); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0xA5: /* A5 MOVSW */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + putmem16 (segregs[reges], getreg16 (regdi), getmem16 (useseg, getreg16 (regsi) ) ); + if (df) { + putreg16 (regsi, getreg16 (regsi) - 2); + putreg16 (regdi, getreg16 (regdi) - 2); + } + else { + putreg16 (regsi, getreg16 (regsi) + 2); + putreg16 (regdi, getreg16 (regdi) + 2); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0xA6: /* A6 CMPSB */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + oper1b = getmem8 (useseg, getreg16 (regsi) ); + oper2b = getmem8 (segregs[reges], getreg16 (regdi) ); + if (df) { + putreg16 (regsi, getreg16 (regsi) - 1); + putreg16 (regdi, getreg16 (regdi) - 1); + } + else { + putreg16 (regsi, getreg16 (regsi) + 1); + putreg16 (regdi, getreg16 (regdi) + 1); + } + + flag_sub8 (oper1b, oper2b); + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + if ( (reptype == 1) && !zf) { + break; + } + else if ( (reptype == 2) && (zf == 1) ) { + break; + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0xA7: /* A7 CMPSW */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + oper1 = getmem16 (useseg, getreg16 (regsi) ); + oper2 = getmem16 (segregs[reges], getreg16 (regdi) ); + if (df) { + putreg16 (regsi, getreg16 (regsi) - 2); + putreg16 (regdi, getreg16 (regdi) - 2); + } + else { + putreg16 (regsi, getreg16 (regsi) + 2); + putreg16 (regdi, getreg16 (regdi) + 2); + } + + flag_sub16 (oper1, oper2); + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + if ( (reptype == 1) && !zf) { + break; + } + + if ( (reptype == 2) && (zf == 1) ) { + break; + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0xA8: /* A8 TEST regs.byteregs[regal] Ib */ + oper1b = regs.byteregs[regal]; + oper2b = getmem8 (segregs[regcs], IP); + StepIP (1); + flag_log8 (oper1b & oper2b); + break; + + case 0xA9: /* A9 TEST eAX Iv */ + oper1 = getreg16 (regax); + oper2 = getmem16 (segregs[regcs], IP); + StepIP (2); + flag_log16 (oper1 & oper2); + break; + + case 0xAA: /* AA STOSB */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + putmem8 (segregs[reges], getreg16 (regdi), regs.byteregs[regal]); + if (df) { + putreg16 (regdi, getreg16 (regdi) - 1); + } + else { + putreg16 (regdi, getreg16 (regdi) + 1); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + totalexec++; + // loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0xAB: /* AB STOSW */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + putmem16 (segregs[reges], getreg16 (regdi), getreg16 (regax) ); + if (df) { + putreg16 (regdi, getreg16 (regdi) - 2); + } + else { + putreg16 (regdi, getreg16 (regdi) + 2); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0xAC: /* AC LODSB */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + regs.byteregs[regal] = getmem8 (useseg, getreg16 (regsi) ); + if (df) { + putreg16 (regsi, getreg16 (regsi) - 1); + } + else { + putreg16 (regsi, getreg16 (regsi) + 1); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0xAD: /* AD LODSW */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + oper1 = getmem16 (useseg, getreg16 (regsi) ); + putreg16 (regax, oper1); + if (df) { + putreg16 (regsi, getreg16 (regsi) - 2); + } + else { + putreg16 (regsi, getreg16 (regsi) + 2); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0xAE: /* AE SCASB */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + oper1b = getmem8 (segregs[reges], getreg16 (regdi) ); + oper2b = regs.byteregs[regal]; + flag_sub8 (oper1b, oper2b); + if (df) { + putreg16 (regdi, getreg16 (regdi) - 1); + } + else { + putreg16 (regdi, getreg16 (regdi) + 1); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + if ( (reptype == 1) && !zf) { + break; + } + else if ( (reptype == 2) && (zf == 1) ) { + break; + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0xAF: /* AF SCASW */ + if (reptype && (getreg16 (regcx) == 0) ) { + break; + } + + oper1 = getmem16 (segregs[reges], getreg16 (regdi) ); + oper2 = getreg16 (regax); + flag_sub16 (oper1, oper2); + if (df) { + putreg16 (regdi, getreg16 (regdi) - 2); + } + else { + putreg16 (regdi, getreg16 (regdi) + 2); + } + + if (reptype) { + putreg16 (regcx, getreg16 (regcx) - 1); + } + + if ( (reptype == 1) && !zf) { + break; + } + else if ( (reptype == 2) & (zf == 1) ) { + break; + } + + totalexec++; +// loopcount++; + if (!reptype) { + break; + } + + IP = firstip; + break; + + case 0xB0: /* B0 MOV regs.byteregs[regal] Ib */ + DATA8 = regs.byteregs[regal] = getmem8 (segregs[regcs], IP); + StepIP (1); + break; + + case 0xB1: /* B1 MOV regs.byteregs[regcl] Ib */ + DATA8 = regs.byteregs[regcl] = getmem8 (segregs[regcs], IP); + StepIP (1); + break; + + case 0xB2: /* B2 MOV regs.byteregs[regdl] Ib */ + DATA8 = regs.byteregs[regdl] = getmem8 (segregs[regcs], IP); + StepIP (1); + break; + + case 0xB3: /* B3 MOV regs.byteregs[regbl] Ib */ + DATA8 = regs.byteregs[regbl] = getmem8 (segregs[regcs], IP); + StepIP (1); + break; + + case 0xB4: /* B4 MOV regs.byteregs[regah] Ib */ + DATA8 = regs.byteregs[regah] = getmem8 (segregs[regcs], IP); + StepIP (1); + break; + + case 0xB5: /* B5 MOV regs.byteregs[regch] Ib */ + DATA8 = regs.byteregs[regch] = getmem8 (segregs[regcs], IP); + StepIP (1); + break; + + case 0xB6: /* B6 MOV regs.byteregs[regdh] Ib */ + DATA8 = regs.byteregs[regdh] = getmem8 (segregs[regcs], IP); + StepIP (1); + break; + + case 0xB7: /* B7 MOV regs.byteregs[regbh] Ib */ + DATA8 = regs.byteregs[regbh] = getmem8 (segregs[regcs], IP); + StepIP (1); + break; + + case 0xB8: /* B8 MOV eAX Iv */ + DATA16 = oper1 = getmem16 (segregs[regcs], IP); + StepIP (2); + putreg16 (regax, oper1); + break; + + case 0xB9: /* B9 MOV eCX Iv */ + DATA16 = oper1 = getmem16 (segregs[regcs], IP); + StepIP (2); + putreg16 (regcx, oper1); + break; + + case 0xBA: /* BA MOV eDX Iv */ + DATA16 = oper1 = getmem16 (segregs[regcs], IP); + StepIP (2); + putreg16 (regdx, oper1); + break; + + case 0xBB: /* BB MOV eBX Iv */ + DATA16 = oper1 = getmem16 (segregs[regcs], IP); + StepIP (2); + putreg16 (regbx, oper1); + break; + + case 0xBC: /* BC MOV eSP Iv */ + putreg16 (regsp, DATA16 = getmem16 (segregs[regcs], IP) ); + StepIP (2); + break; + + case 0xBD: /* BD MOV eBP Iv */ + putreg16 (regbp, DATA16 = getmem16 (segregs[regcs], IP) ); + StepIP (2); + break; + + case 0xBE: /* BE MOV eSI Iv */ + putreg16 (regsi, DATA16 = getmem16 (segregs[regcs], IP) ); + StepIP (2); + break; + + case 0xBF: /* BF MOV eDI Iv */ + putreg16 (regdi, DATA16 = getmem16 (segregs[regcs], IP) ); + StepIP (2); + break; + + case 0xC0: /* C0 GRP2 byte imm8 (80186+) */ + modregrm(); + oper1b = readrm8 (RM); + DATA8 = oper2b = getmem8 (segregs[regcs], IP); + StepIP (1); + writerm8 (RM, op_grp2_8 (oper2b) ); + break; + + case 0xC1: /* C1 GRP2 word imm8 (80186+) */ + modregrm(); + oper1 = readrm16 (RM); + DATA8 = oper2 = getmem8 (segregs[regcs], IP); + StepIP (1); + writerm16 (RM, op_grp2_16 ( (uint8) oper2) ); + break; + + case 0xC2: /* C2 RET Iw */ + DATA16 = oper1 = getmem16 (segregs[regcs], IP); + IP = pop(); + putreg16 (regsp, getreg16 (regsp) + oper1); + break; + + case 0xC3: /* C3 RET */ + IP = pop(); + break; + + case 0xC4: /* C4 LES Gv Mp */ + modregrm(); + getea (RM); +// putreg16 (REGX, read86 (EA) + read86 (EA + 1) * 256); +// segregs[reges] = read86 (EA + 2) + read86 (EA + 3) * 256; + putreg16 (REGX, get_mbyte (EA) + get_mbyte ((EA + 1) * 256)); + segregs[reges] = get_mbyte (EA + 2) + get_mbyte ((EA + 3) * 256); + break; + + case 0xC5: /* C5 LDS Gv Mp */ + modregrm(); + getea (RM); +// putreg16 (REGX, read86 (EA) + read86 (EA + 1) * 256); +// segregs[regds] = read86 (EA + 2) + read86 (EA + 3) * 256; + putreg16 (REGX, get_mbyte (EA) + get_mbyte ((EA + 1) * 256)); + segregs[regds] = get_mbyte (EA + 2) + get_mbyte ((EA + 3) * 256); + break; + + case 0xC6: /* C6 MOV Eb Ib */ + modregrm(); + writerm8 (RM, getmem8 (segregs[regcs], IP) ); + StepIP (1); + break; + + case 0xC7: /* C7 MOV Ev Iv */ + modregrm(); + writerm16 (RM, getmem16 (segregs[regcs], IP) ); + StepIP (2); + break; + + case 0xC8: /* C8 ENTER (80186+) */ + stacksize = getmem16 (segregs[regcs], IP); + StepIP (2); + nestlev = getmem8 (segregs[regcs], IP); + StepIP (1); + push (getreg16 (regbp) ); + frametemp = getreg16 (regsp); + if (nestlev) { + for (temp16 = 1; temp16 < nestlev; temp16++) { + putreg16 (regbp, getreg16 (regbp) - 2); + push (getreg16 (regbp) ); + } + + push (getreg16 (regsp) ); + } + + putreg16 (regbp, frametemp); + putreg16 (regsp, getreg16 (regbp) - stacksize); + + break; + + case 0xC9: /* C9 LEAVE (80186+) */ + putreg16 (regsp, getreg16 (regbp) ); + putreg16 (regbp, pop() ); + + break; + + case 0xCA: /* CA RETF Iw */ + oper1 = getmem16 (segregs[regcs], IP); + IP = pop(); + segregs[regcs] = pop(); + putreg16 (regsp, getreg16 (regsp) + oper1); + break; + + case 0xCB: /* CB RETF */ + IP = pop();; + segregs[regcs] = pop(); + break; + + case 0xCC: /* CC INT 3 */ + intcall86 (3); + break; + + case 0xCD: /* CD INT Ib */ + oper1b = getmem8 (segregs[regcs], IP); + StepIP (1); + intcall86 (oper1b); + break; + + case 0xCE: /* CE INTO */ + if (of) { + intcall86 (4); + } + break; + + case 0xCF: /* CF IRET */ + IP = pop(); + segregs[regcs] = pop(); + decodeflagsword (pop() ); + + /* + * if (net.enabled) net.canrecv = 1; + */ + break; + + case 0xD0: /* D0 GRP2 Eb 1 */ + modregrm(); + oper1b = readrm8 (RM); + writerm8 (RM, op_grp2_8 (1) ); + break; + + case 0xD1: /* D1 GRP2 Ev 1 */ + modregrm(); + oper1 = readrm16 (RM); + writerm16 (RM, op_grp2_16 (1) ); + break; + + case 0xD2: /* D2 GRP2 Eb regs.byteregs[regcl] */ + modregrm(); + oper1b = readrm8 (RM); + writerm8 (RM, op_grp2_8 (regs.byteregs[regcl]) ); + break; + + case 0xD3: /* D3 GRP2 Ev regs.byteregs[regcl] */ + modregrm(); + oper1 = readrm16 (RM); + writerm16 (RM, op_grp2_16 (regs.byteregs[regcl]) ); + break; + + case 0xD4: /* D4 AAM I0 */ + oper1 = getmem8 (segregs[regcs], IP); + StepIP (1); + if (!oper1) { + intcall86 (0); + break; + } /* division by zero */ + + regs.byteregs[regah] = (regs.byteregs[regal] / oper1) & 255; + regs.byteregs[regal] = (regs.byteregs[regal] % oper1) & 255; + flag_szp16 (getreg16 (regax) ); + break; + + case 0xD5: /* D5 AAD I0 */ + oper1 = getmem8 (segregs[regcs], IP); + StepIP (1); + regs.byteregs[regal] = (regs.byteregs[regah] * oper1 + regs.byteregs[regal]) & 255; + regs.byteregs[regah] = 0; + flag_szp16 (regs.byteregs[regah] * oper1 + regs.byteregs[regal]); + sf = 0; + break; + + case 0xD6: /* D6 XLAT on V20/V30, SALC on 8086/8088 */ +#ifndef CPU_V20 + regs.byteregs[regal] = cf ? 0xFF : 0x00; + break; +#endif + + case 0xD7: /* D7 XLAT */ +// regs.byteregs[regal] = read86(useseg * 16 + (regs.wordregs[regbx]) + regs.byteregs[regal]); + regs.byteregs[regal] = get_mbyte(useseg * 16 + (regs.wordregs[regbx]) + regs.byteregs[regal]); + break; + + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDE: + case 0xDD: + case 0xDF: /* escape to x87 FPU (unsupported) */ + modregrm(); + break; + + case 0xE0: /* E0 LOOPNZ Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + putreg16 (regcx, getreg16 (regcx) - 1); + if ( (getreg16 (regcx) ) && !zf) { + IP = IP + temp16; + } + break; + + case 0xE1: /* E1 LOOPZ Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + putreg16 (regcx, (getreg16 (regcx) ) - 1); + if ( (getreg16 (regcx) ) && (zf == 1) ) { + IP = IP + temp16; + } + break; + + case 0xE2: /* E2 LOOP Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + putreg16 (regcx, (getreg16 (regcx) ) - 1); + if (getreg16 (regcx) ) { + IP = IP + temp16; + } + break; + + case 0xE3: /* E3 JCXZ Jb */ + temp16 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + if (! (getreg16 (regcx) ) ) { + IP = IP + temp16; + } + break; + + case 0xE4: /* E4 IN regs.byteregs[regal] Ib */ + port = DATA8 = oper1b = getmem8 (segregs[regcs], IP); + StepIP (1); +// regs.byteregs[regal] = (uint8) portin (oper1b); + regs.byteregs[regal] = dev_table[oper1b].routine(0, 0, dev_table[oper1b].devnum & 0xff); + break; + + case 0xE5: /* E5 IN eAX Ib */ + port = DATA8 = oper1b = getmem8 (segregs[regcs], IP); + StepIP (1); +// putreg16 (regax, portin16 (oper1b) ); +// putreg16 (regax, + putreg8(regal, dev_table[oper1b+1].routine(0, 0, dev_table[oper1b+1].devnum & 0xff)); + putreg8(regah, dev_table[oper1b].routine(0, 0, dev_table[oper1b].devnum & 0xff)); + break; + + case 0xE6: /* E6 OUT Ib regs.byteregs[regal] */ + port = DATA8 = oper1b = getmem8 (segregs[regcs], IP); + StepIP (1); +// portout (oper1b, regs.byteregs[regal]); + dev_table[oper1b].routine(1, regs.byteregs[regal], dev_table[oper1b].devnum & 0xff); + break; + + case 0xE7: /* E7 OUT Ib eAX */ + port = DATA8 = oper1b = getmem8 (segregs[regcs], IP); + StepIP (1); +// portout16 (oper1b, (getreg16 (regax) ) ); + dev_table[oper1b].routine(1, regs.byteregs[regah], dev_table[oper1b].devnum & 0xff); + dev_table[oper1b+1].routine(1, regs.byteregs[regal], dev_table[oper1b+1].devnum & 0xff); + break; + + case 0xE8: /* E8 CALL Jv */ + oper1 = getmem16 (segregs[regcs], IP); + StepIP (2); + push (IP); + IP = IP + oper1; + break; + + case 0xE9: /* E9 JMP Jv */ + oper1 = getmem16 (segregs[regcs], IP); + StepIP (2); + IP = IP + oper1; + break; + + case 0xEA: /* EA JMP Ap */ + oper1 = getmem16 (segregs[regcs], IP); + StepIP (2); + oper2 = getmem16 (segregs[regcs], IP); + IP = oper1; + CS = segregs[regcs] = oper2; + break; + + case 0xEB: /* EB JMP Jb */ + oper1 = signext (getmem8 (segregs[regcs], IP) ); + StepIP (1); + IP = IP + oper1; + break; + + case 0xEC: /* EC IN regs.byteregs[regal] regdx */ + port = oper1 = (getreg16 (regdx) ); +// regs.byteregs[regal] = (uint8) portin (oper1); + regs.byteregs[regal] = dev_table[oper1].routine(0, 0, dev_table[oper1].devnum & 0xff); + break; + + case 0xED: /* ED IN eAX regdx */ + port = oper1 = (getreg16 (regdx) ); +// putreg16 (regax, portin16 (oper1) ); + regs.byteregs[regah] = dev_table[oper1].routine(0, 0, dev_table[oper1].devnum & 0xff); + regs.byteregs[regal] = dev_table[oper1+1].routine(0, 0, dev_table[oper1+1].devnum & 0xff); + break; + + case 0xEE: /* EE OUT regdx regs.byteregs[regal] */ + port = oper1 = (getreg16 (regdx) ); +// portout (oper1, regs.byteregs[regal]); + dev_table[oper1].routine(1, regs.byteregs[regal], dev_table[oper1].devnum & 0xff); + break; + + case 0xEF: /* EF OUT regdx eAX */ + port = oper1 = (getreg16 (regdx) ); +// portout16 (oper1, (getreg16 (regax) ) ); + dev_table[oper1].routine(1, regs.byteregs[regah], dev_table[oper1].devnum & 0xff); + dev_table[oper1+1].routine(1, regs.byteregs[regal], dev_table[oper1+1].devnum & 0xff); + break; + + case 0xF0: /* F0 LOCK */ + break; + + case 0xF4: /* F4 HLT */ + reason = STOP_HALT; + IP--; + break; + + case 0xF5: /* F5 CMC */ + if (!cf) { + cf = 1; + } + else { + cf = 0; + } + break; + + case 0xF6: /* F6 GRP3a Eb */ + modregrm(); + oper1b = readrm8 (RM); + op_grp3_8(); + if ( (REGX > 1) && (REGX < 4) ) { + writerm8 (RM, res8); + } + break; + + case 0xF7: /* F7 GRP3b Ev */ + modregrm(); + oper1 = readrm16 (RM); + op_grp3_16(); + if ( (REGX > 1) && (REGX < 4) ) { + writerm16 (RM, res16); + } + break; + + case 0xF8: /* F8 CLC */ + cf = 0; + break; + + case 0xF9: /* F9 STC */ + cf = 1; + break; + + case 0xFA: /* FA CLI */ + ifl = 0; + break; + + case 0xFB: /* FB STI */ + ifl = 1; + break; + + case 0xFC: /* FC CLD */ + df = 0; + break; + + case 0xFD: /* FD STD */ + df = 1; + break; + + case 0xFE: /* FE GRP4 Eb */ + modregrm(); + oper1b = readrm8 (RM); + oper2b = 1; + if (!REGX) { + tempcf = cf; + res8 = oper1b + oper2b; + flag_add8 (oper1b, oper2b); + cf = tempcf; + writerm8 (RM, res8); + } + else { + tempcf = cf; + res8 = oper1b - oper2b; + flag_sub8 (oper1b, oper2b); + cf = tempcf; + writerm8 (RM, res8); + } + break; + + case 0xFF: /* FF GRP5 Ev */ + modregrm(); + oper1 = readrm16 (RM); + op_grp5(); + break; + + default: +#ifdef CPU_V20 + intcall86 (6); /* trip invalid OP exception (this occurs on the 80186+, 8086/8088 CPUs treat them as NOPs. */ + /* technically they aren't exactly like NOPs in most cases, but for our pursoses, that's accurate enough. */ +#endif + if (verbose) { + printf ("Illegal OP: %02X @ %04X:%04X\n", OP, SEG, OFF); + } + break; + } + if (i8088_dev.dctrl & DEBUG_asm) { + AX = (getreg16 (regax) ); + BX = (getreg16 (regbx) ); + CX = (getreg16 (regcx) ); + DX = (getreg16 (regdx) ); + SP = (getreg16 (regsp) ); + BP = (getreg16 (regbp) ); + SI = (getreg16 (regsi) ); + DI = (getreg16 (regdi) ); + DISP = temp16; + PSW = makeflagsword(); + do_trace(); + } + if (i8088_dev.dctrl & DEBUG_reg) { + sim_printf("Regs: AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X IP=%04X\n", + AX, BX, CX, DX, SP, BP, SI, DI, IP); + sim_printf("Segs: CS=%04X DS=%04X ES=%04X SS=%04X Flags: %04X\n", CS, DS, ES, SS, PSW); + } + +// if (!running) { +// return; +// } +// } + } saved_PC = IP; return reason; -} - -/* emulation subfunctions */ - -int32 sign_ext(int32 val) -{ - int32 res; - - res = val; - if (val & 0x80) - res |= 0xFF00; - return res; -} - -int32 fetch_byte(int32 flag) -{ - uint8 val; - - val = get_smbyte(SEG_CS, IP) & 0xFF; /* fetch byte */ - if (i8088_dev.dctrl & DEBUG_asm) { /* display source code */ - switch (flag) { - case 0: /* opcode fetch */ -// if (i8088_dev.dctrl & DEBUG_asm) -// sim_printf("%04X:%04X %02X %s ", CS, IP, val, opcode[val]); - break; - case 1: /* byte operand fetch */ -// if (i8088_dev.dctrl & DEBUG_asm) -// sim_printf("0%02XH", val); - break; - } - } - IP++; /* increment IP */ - IP &= ADDRMASK16; - return val; -} - -int32 fetch_word(void) -{ - uint16 val; - - val = get_smbyte(SEG_CS, IP) & 0xFF; /* fetch low byte */ - val |= get_smbyte(SEG_CS, IP + 1) << 8; /* fetch high byte */ -// if (i8088_dev.dctrl & DEBUG_asm) -// sim_printf("0%04XH", val); - IP += 2;; /* increment IP */ - IP &= ADDRMASK16; - return val; -} - -/* calculate parity on a 8- or 16-bit value */ - -int32 parity(int32 val) -{ - int32 bc = 0; - - if (val & 0x0001) bc++; - if (val & 0x0002) bc++; - if (val & 0x0004) bc++; - if (val & 0x0008) bc++; - if (val & 0x0010) bc++; - if (val & 0x0020) bc++; - if (val & 0x0040) bc++; - if (val & 0x0080) bc++; - if (val & 0x0100) bc++; - if (val & 0x0200) bc++; - if (val & 0x0400) bc++; - if (val & 0x0800) bc++; - if (val & 0x1000) bc++; - if (val & 0x2000) bc++; - if (val & 0x4000) bc++; - if (val & 0x8000) bc++; - return bc & 1; -} - -void i86_intr_raise(uint8 num) -{ - /* do nothing for now */ -} - -/* return byte register */ - -uint32 get_rbyte(uint32 reg) -{ - uint32 val = 0; - - switch(reg) { - case 0: val = AL; break; - case 1: val = CL; break; - case 2: val = DL; break; - case 3: val = BL; break; - case 4: val = AH; break; - case 5: val = CH; break; - case 6: val = DH; break; - case 7: val = BH; break; - } - return val; -} - -/* return word register - added segment registers as 8-11 */ - -uint32 get_rword(uint32 reg) -{ - uint32 val = 0; - - switch(reg) { - case 0: val = AX; break; - case 1: val = CX; break; - case 2: val = DX; break; - case 3: val = BX; break; - case 4: val = SP; break; - case 5: val = BP; break; - case 6: val = SI; break; - case 7: val = DI; break; - case 8: val = CS; break; - case 9: val = DS; break; - case 10: val = ES; break; - case 11: val = SS; break; - } - return val; -} - -/* set byte register */ - -void put_rbyte(uint32 reg, uint32 val) -{ - val &= 0xFF; /* force byte */ - switch(reg){ - case 0: AL = val; break; - case 1: CL = val; break; - case 2: DL = val; break; - case 3: BL = val; break; - case 4: AH = val; break; - case 5: CH = val; break; - case 6: DH = val; break; - case 7: BH = val; break; - } -} - -/* set word register */ - -void put_rword(uint32 reg, uint32 val) -{ - val &= 0xFFFF; /* force word */ - switch(reg){ - case 0: AX = val; break; - case 1: CX = val; break; - case 2: DX = val; break; - case 3: BX = val; break; - case 4: SP = val; break; - case 5: BP = val; break; - case 6: SI = val; break; - case 7: DI = val; break; - } -} - -/* set seg_reg as required for EA */ - -void set_segreg(uint32 reg) -{ - if (seg_ovr) - seg_reg = seg_ovr; - else - seg_reg = seg_ovr = reg; -} - -/* return effective address from mrr - also set seg_reg */ - -uint32 get_ea(uint32 mrr) -{ - uint32 MOD, REG, RM, DISP, EA = 0; - - get_mrr_dec(mrr, &MOD, ®, &RM); - switch(MOD) { - case 0: /* DISP = 0 */ - DISP = 0; - switch(RM) { - case 0: - EA = BX + SI; - set_segreg(SEG_DS); - break; - case 1: - EA = BX + DI; - set_segreg(SEG_DS); - break; - case 2: - EA = BP + SI; - set_segreg(SEG_SS); - break; - case 3: - EA = BP + DI; - set_segreg(SEG_SS); - break; - case 4: - EA = SI; - set_segreg(SEG_DS); - break; - case 5: - EA = DI; - set_segreg(SEG_ES); - break; - case 6: - DISP = fetch_word(); - EA = DISP; - set_segreg(SEG_DS); - break; - case 7: - EA = BX; - set_segreg(SEG_DS); - break; - } - break; - case 1: /* DISP is byte */ - DISP = fetch_byte(1); - switch(RM) { - case 0: - EA = BX + SI + DISP; - set_segreg(SEG_DS); - break; - case 1: - EA = BX + DI + DISP; - set_segreg(SEG_DS); - break; - case 2: - EA = BP + SI + DISP; - set_segreg(SEG_SS); - break; - case 3: - EA = BP + DI + DISP; - set_segreg(SEG_SS); - break; - case 4: - EA = SI + DISP; - set_segreg(SEG_DS); - break; - case 5: - EA = DI + DISP; - set_segreg(SEG_ES); - break; - case 6: - EA = BP + DISP; - set_segreg(SEG_SS); - break; - case 7: - EA = BX + DISP; - set_segreg(SEG_DS); - break; - } - break; - case 2: /* DISP is word */ - DISP = fetch_word(); - switch(RM) { - case 0: - EA = BX + SI + DISP; - set_segreg(SEG_DS); - break; - case 1: - EA = BX + DI + DISP; - set_segreg(SEG_DS); - break; - case 2: - EA = BP + SI + DISP; - set_segreg(SEG_SS); - break; - case 3: - EA = BP + DI + DISP; - set_segreg(SEG_SS); - break; - case 4: - EA = SI + DISP; - set_segreg(SEG_DS); - break; - case 5: - EA = DI + DISP; - set_segreg(SEG_ES); - break; - case 6: - EA = BP + DISP; - set_segreg(SEG_SS); - break; - case 7: - EA = BX + DISP; - set_segreg(SEG_SS); - break; - } - break; - case 3: /* RM is register field */ - break; - } -// if (i8088_dev.dctrl & DEBUG_level1) -// sim_printf("get_ea: DISP=%04X EA=%04X\n", -// DISP, EA); - return EA; -} -/* return mod, reg and rm field from mrr */ - -void get_mrr_dec(uint32 mrr, uint32 *mod, uint32 *reg, uint32 *rm) -{ - *mod = (mrr >> 6) & 0x3; - *reg = (mrr >> 3) & 0x7; - *rm = mrr & 0x7; -// if (i8088_dev.dctrl & DEBUG_level1) -// sim_printf("get_mrr_dec: MRR=%02X MOD=%02X REG=%02X R/M=%02X\n", -// mrr, *mod, *reg, *rm); -} - -/* decode byte register for disassembly */ - -void rm_byte_dec(uint32 rm) -{ - switch (rm) { - case 0: - sim_printf("AL"); - break; - case 1: - sim_printf("CL"); - break; - case 2: - sim_printf("DL"); - break; - case 3: - sim_printf("BL"); - break; - case 4: - sim_printf("AH"); - break; - case 5: - sim_printf("CH"); - break; - case 6: - sim_printf("DH"); - break; - case 7: - sim_printf("CH"); - break; - } -} -/* decode word register for disassembly */ - -void rm_word_dec(uint32 rm) -{ - switch (rm) { - case 0: - sim_printf("AX"); - break; - case 1: - sim_printf("CX"); - break; - case 2: - sim_printf("DX"); - break; - case 3: - sim_printf("BX"); - break; - case 4: - sim_printf("SP"); - break; - case 5: - sim_printf("BP"); - break; - case 6: - sim_printf("SI"); - break; - case 7: - sim_printf("DI"); - break; - } -} - -/* decode segment register for disassembly */ - -void rm_seg_dec(uint32 rm) -{ - switch (rm) { - case 0: - sim_printf("ES"); - break; - case 1: - sim_printf("CS"); - break; - case 2: - sim_printf("SS"); - break; - case 3: - sim_printf("DS"); - break; - } -} - -/* - Most of the primitive algorithms were pulled from the GDE Dos/IP Emulator by Jim Hudgens -*/ - -/* aad primitive */ -uint8 aad_word(uint16 d) -{ - uint16 VAL; - uint8 HI, LOW; - - HI = (d >> 8) & 0xFF; - LOW = d & 0xFF; - VAL = LOW + 10 * HI; - CONDITIONAL_SET_FLAG(VAL & 0x80, SF); - CONDITIONAL_SET_FLAG(VAL == 0, ZF); - CONDITIONAL_SET_FLAG(parity(VAL & 0xFF), PF); - return (uint8) VAL; -} - -/* aam primitive */ -uint16 aam_word(uint8 d) -{ - uint16 VAL, HI; - - HI = d / 10; - VAL = d % 10; - VAL |= (HI << 8); - CONDITIONAL_SET_FLAG(VAL & 0x80, SF); - CONDITIONAL_SET_FLAG(VAL == 0, ZF); - CONDITIONAL_SET_FLAG(parity(VAL & 0xFF), PF); - return VAL; -} - -/* add with carry byte primitive */ -uint8 adc_byte(uint8 d, uint8 s) -{ - register uint16 res; - register uint16 cc; - - if (GET_FLAG(CF)) - res = 1 + d + s; - else - res = d + s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x0100, CF); - CONDITIONAL_SET_FLAG((res & 0xff) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = (s & d) | ((~res) & (s | d)); - /* set the flags based on the carry chain */ - CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 6) & 0x3], OF); - CONDITIONAL_SET_FLAG(cc & 0x08, AF); - return (uint8) res; -} - -/* add with carry word primitive */ -uint16 adc_word(uint16 d, uint16 s) -{ - register uint32 res; - register uint32 cc; - - if (GET_FLAG(CF)) - res = 1 + d + s; - else - res = d + s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x10000, CF); - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = (s & d) | ((~res) & (s | d)); - /* set the flags based on the carry chain */ - CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 14) & 0x3], OF); - CONDITIONAL_SET_FLAG(cc & 0x08, AF); - return res; -} - -/* add byte primitive */ -uint8 add_byte(uint8 d, uint8 s) -{ - register uint16 res; - register uint16 cc; - - res = d + s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x0100, CF); - CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = (s & d) | ((~res) & (s | d)); - /* set the flags based on the carry chain */ - CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 6) & 0x3], OF); - CONDITIONAL_SET_FLAG(cc & 0x08, AF); - return (uint8) res; -} - -/* add word primitive */ -uint16 add_word(uint16 d, uint16 s) -{ - register uint32 res; - register uint32 cc; - - res = d + s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x10000, CF); - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = (s & d) | ((~res) & (s | d)); - /* set the flags based on the carry chain */ - CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 14) & 0x3], OF); - CONDITIONAL_SET_FLAG(cc & 0x08, AF); - return res; -} - -/* and byte primitive */ -uint8 and_byte(uint8 d, uint8 s) -{ - register uint8 res; - res = d & s; - - /* clear flags */ - CLR_FLAG(OF); - CLR_FLAG(CF); - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res), PF); - return res; -} - -/* and word primitive */ -uint16 and_word(uint16 d, uint16 s) -{ - register uint16 res; - res = d & s; - - /* clear flags */ - CLR_FLAG(OF); - CLR_FLAG(CF); - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - return res; -} - -/* cmp byte primitive */ -uint8 cmp_byte(uint8 d, uint8 s) -{ - register uint32 res; - register uint32 bc; - - res = d - s; - /* clear flags */ - CLR_FLAG(CF); - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG((res & 0xFF)==0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(bc & 0x80, CF); - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); - return d; /* long story why this is needed. Look at opcode - 0x80 in ops.c, for an idea why this is necessary.*/ -} - -/* cmp word primitive */ -uint16 cmp_word(uint16 d, uint16 s) -{ - register uint32 res; - register uint32 bc; - - res = d - s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the borrow chain. See note at top */ - bc = (res & (~d | s)) | (~d &s); - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(bc & 0x8000, CF); - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 14) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); - return d; /* long story why this is needed. Look at opcode - 0x80 in ops.c, for an idea why this is necessary.*/ -} - -/* dec byte primitive */ -uint8 dec_byte(uint8 d) -{ - register uint32 res; - register uint32 bc; - - res = d - 1; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG((res & 0xff)==0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); - /* calculate the borrow chain. See note at top */ - /* based on sub_byte, uses s=1. */ - bc = (res & (~d | 1)) | (~d & 1); - /* carry flag unchanged */ - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); - return res; -} - -/* dec word primitive */ -uint16 dec_word(uint16 d) -{ - register uint32 res; - register uint32 bc; - - res = d - 1; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG((res & 0xffff) == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); - /* calculate the borrow chain. See note at top */ - /* based on the sub_byte routine, with s==1 */ - bc = (res & (~d | 1)) | (~d & 1); - /* carry flag unchanged */ - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 14) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); - return res; -} - -/* div byte primitive */ -void div_byte(uint8 s) -{ - uint32 dvd, dvs, div, mod; - - dvs = s; - dvd = AX; - if (s == 0) { - i86_intr_raise(0); - return; - } - div = dvd / dvs; - mod = dvd % dvs; - if (abs(div) > 0xFF) { - i86_intr_raise(0); - return; - } - /* Undef --- Can't hurt */ - CLR_FLAG(SF); - CONDITIONAL_SET_FLAG(div == 0, ZF); - AL = (uint8)div; - AH = (uint8)mod; -} - -/* div word primitive */ -void div_word(uint16 s) -{ - uint32 dvd, dvs, div, mod; - - dvd = DX; - dvd = (dvd << 16) | AX; - dvs = s; - if (dvs == 0) { - i86_intr_raise(0); - return; - } - div = dvd / dvs; - mod = dvd % dvs; - if (abs(div) > 0xFFFF) { - i86_intr_raise(0); - return; - } - /* Undef --- Can't hurt */ - CLR_FLAG(SF); - CONDITIONAL_SET_FLAG(div == 0, ZF); - AX = div; - DX = mod; -} - -/* idiv byte primitive */ -void idiv_byte(uint8 s) -{ - int32 dvd, div, mod; - - dvd = (int16)AX; - if (s == 0) { - i86_intr_raise(0); - return; - } - div = dvd / (int8)s; - mod = dvd % (int8)s; - if (abs(div) > 0x7F) { - i86_intr_raise(0); - return; - } - /* Undef --- Can't hurt */ - CONDITIONAL_SET_FLAG(div & 0x80, SF); - CONDITIONAL_SET_FLAG(div == 0, ZF); - AL = (int8)div; - AH = (int8)mod; -} - -/* idiv word primitive */ -void idiv_word(uint16 s) -{ - int32 dvd, dvs, div, mod; - - dvd = DX; - dvd = (dvd << 16) | AX; - if (s == 0) { - i86_intr_raise(0); - return; - } - dvs = (int16)s; - div = dvd / dvs; - mod = dvd % dvs; - if (abs(div) > 0x7FFF) { - i86_intr_raise(0); - return; - } - /* Undef --- Can't hurt */ - CONDITIONAL_SET_FLAG(div & 0x8000, SF); - CONDITIONAL_SET_FLAG(div == 0, ZF); - AX = div; - DX = mod; -} - -/* imul byte primitive */ -void imul_byte(uint8 s) -{ - int16 res; - - res = (int8)AL * (int8)s; - AX = res; - /* Undef --- Can't hurt */ - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - if ( AH == 0 || AH == 0xFF) { - CLR_FLAG(CF); - CLR_FLAG(OF); - } else { - SET_FLAG(CF); - SET_FLAG(OF); - } -} - -/* imul word primitive */ -void imul_word(uint16 s) -{ - int32 res; - - res = (int16)AX * (int16)s; - AX = res & 0xFFFF; - DX = (res >> 16) & 0xFFFF; - /* Undef --- Can't hurt */ - CONDITIONAL_SET_FLAG(res & 0x80000000, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - if (DX == 0 || DX == 0xFFFF) { - CLR_FLAG(CF); - CLR_FLAG(OF); - } else { - SET_FLAG(CF); - SET_FLAG(OF); - } -} - -/* inc byte primitive */ -uint8 inc_byte(uint8 d) -{ - register uint32 res; - register uint32 cc; - - res = d + 1; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = ((1 & d) | (~res)) & (1 | d); - /* set the flags based on the carry chain */ - CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 6) & 0x3], OF); - CONDITIONAL_SET_FLAG(cc & 0x8, AF); - return res; -} - -/* inc word primitive */ -uint16 inc_word(uint16 d) -{ - register uint32 res; - register uint32 cc; - - res = d + 1; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = (1 & d) | ((~res) & (1 | d)); - /* set the flags based on the carry chain */ - CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 14) & 0x3], OF); - CONDITIONAL_SET_FLAG(cc & 0x8, AF); - return res ; -} - -/* mul byte primitive */ -void mul_byte(uint8 s) -{ - uint16 res; - - res = AL * s; - AX = res; - /* Undef --- Can't hurt */ - CLR_FLAG(SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - if (AH == 0) { - CLR_FLAG(CF); - CLR_FLAG(OF); - } else { - SET_FLAG(CF); - SET_FLAG(OF); - } -} - -/* mul word primitive */ -void mul_word(uint16 s) -{ - uint32 res; - - res = AX * s; - /* Undef --- Can't hurt */ - CLR_FLAG(SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - AX = res & 0xFFFF; - DX = (res >> 16) & 0xFFFF; - if (DX == 0) { - CLR_FLAG(CF); - CLR_FLAG(OF); - } else { - SET_FLAG(CF); - SET_FLAG(OF); - } -} - -/* neg byte primitive */ -uint8 neg_byte(uint8 s) -{ - register uint8 res; - register uint8 bc; - - CONDITIONAL_SET_FLAG(s != 0, CF); - res = -s; - CONDITIONAL_SET_FLAG((res & 0xff) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(parity(res), PF); - /* calculate the borrow chain --- modified such that d=0. */ - bc= res | s; - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); - return res; -} - -/* neg word primitive */ -uint16 neg_word(uint16 s) -{ - register uint16 res; - register uint16 bc; - - CONDITIONAL_SET_FLAG(s != 0, CF); - res = -s; - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the borrow chain --- modified such that d=0 */ - bc= res | s; - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); - return res; -} - -/* not byte primitive */ -uint8 not_byte(uint8 s) -{ - return ~s; -} - -/* not word primitive */ -uint16 not_word(uint16 s) -{ - return ~s; -} - -/* or byte primitive */ -uint8 or_byte(uint8 d, uint8 s) -{ - register uint8 res; - - res = d | s; - /* clear flags */ - CLR_FLAG(OF); - CLR_FLAG(CF); - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res), PF); - return res; -} - -/* or word primitive */ -uint16 or_word(uint16 d, uint16 s) -{ - register uint16 res; - - res = d | s; - /* clear flags */ - CLR_FLAG(OF); - CLR_FLAG(CF); - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - return res; -} - -/* push word primitive */ -void push_word(uint16 val) -{ - SP--; - put_smbyte(SEG_SS, SP, val >> 8); - SP--; - put_smbyte(SEG_SS, SP, val & 0xFF); -} - -/* pop word primitive */ -uint16 pop_word(void) -{ - register uint16 res; - - //sim_printf("pop_word: entered SS=%04X SP=%04X\n", get_rword(SEG_SS), SP); - res = get_smbyte(SEG_SS, SP); - SP++; - //sim_printf("pop_word: first byte=%04X SS=%04X SP=%04X\n", res, get_rword(SEG_SS), SP); - res |= (get_smbyte(SEG_SS, SP) << 8); - SP++; - //sim_printf("pop_word: val=%04X SS=%04X SP=%04X\n", res, get_rword(SEG_SS), SP); - return res; -} - -/* rcl byte primitive */ -uint8 rcl_byte(uint8 d, uint8 s) -{ - register uint32 res, cnt, mask, cf; - - res = d; - if ((cnt = s % 9)) - { - cf = (d >> (8-cnt)) & 0x1; - res = (d << cnt) & 0xFF; - mask = (1<<(cnt-1)) - 1; - res |= (d >> (9-cnt)) & mask; - if (GET_FLAG(CF)) - res |= 1 << (cnt-1); - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[cf + ((res >> 6) & 0x2)], OF); - } - return res & 0xFF; -} - -/* rcl word primitive */ -uint16 rcl_word(uint16 d, uint16 s) -{ - register uint32 res, cnt, mask, cf; - - res = d; - if ((cnt = s % 17)) - { - cf = (d >> (16-cnt)) & 0x1; - res = (d << cnt) & 0xFFFF; - mask = (1<<(cnt-1)) - 1; - res |= (d >> (17-cnt)) & mask; - if (GET_FLAG(CF)) - res |= 1 << (cnt-1); - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[cf + ((res >> 14) & 0x2)], OF); - } - return res & 0xFFFF; -} - -/* rcr byte primitive */ -uint8 rcr_byte(uint8 d, uint8 s) -{ - uint8 res, cnt; - uint8 mask, cf, ocf = 0; - - res = d; - - if ((cnt = s % 9)) { - if (cnt == 1) { - cf = d & 0x1; - ocf = GET_FLAG(CF) != 0; - } else - cf = (d >> (cnt - 1)) & 0x1; - mask = (1 <<( 8 - cnt)) - 1; - res = (d >> cnt) & mask; - res |= (d << (9-cnt)); - if (GET_FLAG(CF)) - res |= 1 << (8 - cnt); - CONDITIONAL_SET_FLAG(cf, CF); - if (cnt == 1) - CONDITIONAL_SET_FLAG(xor_3_tab[ocf + ((d >> 6) & 0x2)], OF); - } - return res; -} - -/* rcr word primitive */ -uint16 rcr_word(uint16 d, uint16 s) -{ - uint16 res, cnt; - uint16 mask, cf, ocf = 0; - - res = d; - if ((cnt = s % 17)) { - if (cnt == 1) { - cf = d & 0x1; - ocf = GET_FLAG(CF) != 0; - } else - cf = (d >> (cnt-1)) & 0x1; - mask = (1 <<( 16 - cnt)) - 1; - res = (d >> cnt) & mask; - res |= (d << (17 - cnt)); - if (GET_FLAG(CF)) - res |= 1 << (16 - cnt); - CONDITIONAL_SET_FLAG(cf, CF); - if (cnt == 1) - CONDITIONAL_SET_FLAG(xor_3_tab[ocf + ((d >> 14) & 0x2)], OF); - } - return res; -} - -/* rol byte primitive */ -uint8 rol_byte(uint8 d, uint8 s) -{ - register uint32 res, cnt, mask; - - res =d; - - if ((cnt = s % 8)) { - res = (d << cnt); - mask = (1 << cnt) - 1; - res |= (d >> (8-cnt)) & mask; - CONDITIONAL_SET_FLAG(res & 0x1, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res & 0x1) + ((res >> 6) & 0x2)], OF); - } - return res & 0xFF; -} - -/* rol word primitive */ -uint16 rol_word(uint16 d, uint16 s) -{ - register uint32 res, cnt, mask; - - res = d; - if ((cnt = s % 16)) { - res = (d << cnt); - mask = (1 << cnt) - 1; - res |= (d >> (16 - cnt)) & mask; - CONDITIONAL_SET_FLAG(res & 0x1, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res & 0x1) + ((res >> 14) & 0x2)], OF); - } - return res&0xFFFF; -} - -/* ror byte primitive */ -uint8 ror_byte(uint8 d, uint8 s) -{ - register uint32 res, cnt, mask; - - res = d; - if ((cnt = s % 8)) { - res = (d << (8-cnt)); - mask = (1 << (8-cnt)) - 1; - res |= (d >> (cnt)) & mask; - CONDITIONAL_SET_FLAG(res & 0x80, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res >> 6) & 0x3], OF); - } - return res & 0xFF; -} - -/* ror word primitive */ -uint16 ror_word(uint16 d, uint16 s) -{ - register uint32 res, cnt, mask; - - res = d; - if ((cnt = s % 16)) { - res = (d << (16-cnt)); - mask = (1 << (16-cnt)) - 1; - res |= (d >> (cnt)) & mask; - CONDITIONAL_SET_FLAG(res & 0x8000, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res >> 14) & 0x3], OF); - } - return res & 0xFFFF; -} - -/* shl byte primitive */ -uint8 shl_byte(uint8 d, uint8 s) -{ - uint32 cnt, res, cf; - - if (s < 8) { - cnt = s % 8; - if (cnt > 0) { - res = d << cnt; - cf = d & (1 << (8 - cnt)); - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG((res & 0xFF)==0, ZF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - } else - res = (uint8) d; - if (cnt == 1) - CONDITIONAL_SET_FLAG((((res & 0x80) == 0x80) ^ - (GET_FLAG( CF) != 0)), OF); - else - CLR_FLAG(OF); - } else { - res = 0; - CONDITIONAL_SET_FLAG((s == 8) && (d & 1), CF); - CLR_FLAG(OF); - CLR_FLAG(SF); - CLR_FLAG(PF); - SET_FLAG(ZF); - } - return res & 0xFF; -} - -/* shl word primitive */ -uint16 shl_word(uint16 d, uint16 s) -{ - uint32 cnt, res, cf; - - if (s < 16) { - cnt = s % 16; - if (cnt > 0) { - res = d << cnt; - cf = d & (1<<(16-cnt)); - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - } else - res = (uint16) d; - if (cnt == 1) - CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ - (GET_FLAG(CF) != 0)), OF); - else - CLR_FLAG(OF); - } else { - res = 0; - CONDITIONAL_SET_FLAG((s == 16) && (d & 1), CF); - CLR_FLAG(OF); - SET_FLAG(ZF); - CLR_FLAG(SF); - CLR_FLAG(PF); - } - return res & 0xFFFF; -} - -/* shr byte primitive */ -uint8 shr_byte(uint8 d, uint8 s) -{ - uint32 cnt, res, cf, mask; - - if (s < 8) { - cnt = s % 8; - if (cnt > 0) { - mask = (1 << (8 - cnt)) - 1; - cf = d & (1 << (cnt - 1)); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - } else - res = (uint8) d; - if (cnt == 1) - CONDITIONAL_SET_FLAG(xor_3_tab[(res >> 6) & 0x3], OF); - else - CLR_FLAG(OF); - } else { - res = 0; - CONDITIONAL_SET_FLAG((s == 8) && (d & 0x80), CF); - CLR_FLAG(OF); - SET_FLAG(ZF); - CLR_FLAG(SF); - CLR_FLAG(PF); - } - return res & 0xFF; -} - -/* shr word primitive */ -uint16 shr_word(uint16 d, uint16 s) -{ - uint32 cnt, res, cf, mask; - - res = d; - if (s < 16) { - cnt = s % 16; - if (cnt > 0) { - mask = (1 << (16 - cnt)) - 1; - cf = d & (1 << (cnt - 1)); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - } else - res = d; - if (cnt == 1) - CONDITIONAL_SET_FLAG(xor_3_tab[(res >> 14) & 0x3], OF); - else - CLR_FLAG(OF); - } else { - res = 0; - CONDITIONAL_SET_FLAG((s == 16) && (d & 0x8000), CF); - CLR_FLAG(OF); - SET_FLAG(ZF); - CLR_FLAG(SF); - CLR_FLAG(PF); - } - return res & 0xFFFF; -} - -/* sar byte primitive */ -uint8 sar_byte(uint8 d, uint8 s) -{ - uint32 cnt, res, cf, mask, sf; - - res = d; - sf = d & 0x80; - cnt = s % 8; - if (cnt > 0 && cnt < 8) { - mask = (1 << (8 - cnt)) - 1; - cf = d & (1 << (cnt -1 )); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, CF); - if (sf) - res |= ~mask; - CONDITIONAL_SET_FLAG((res & 0xFF)==0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - } else if (cnt >= 8) { - if (sf) { - res = 0xFF; - SET_FLAG(CF); - CLR_FLAG(ZF); - SET_FLAG(SF); - SET_FLAG(PF); - } else { - res = 0; - CLR_FLAG(CF); - SET_FLAG(ZF); - CLR_FLAG(SF); - CLR_FLAG(PF); - } - } - return res & 0xFF; -} - -/* sar word primitive */ -uint16 sar_word(uint16 d, uint16 s) -{ - uint32 cnt, res, cf, mask, sf; - - sf = d & 0x8000; - cnt = s % 16; - res = d; - if (cnt > 0 && cnt < 16) { - mask = (1 << (16 - cnt)) - 1; - cf = d & (1 << (cnt - 1)); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, CF); - if (sf) - res |= ~mask; - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - } else if (cnt >= 16) { - if (sf) { - res = 0xFFFF; - SET_FLAG(CF); - CLR_FLAG(ZF); - SET_FLAG(SF); - SET_FLAG(PF); - } else { - res = 0; - CLR_FLAG(CF); - SET_FLAG(ZF); - CLR_FLAG(SF); - CLR_FLAG(PF); - } - } - return res & 0xFFFF; -} - -/* sbb byte primitive */ -uint8 sbb_byte(uint8 d, uint8 s) -{ - register uint32 res; - register uint32 bc; - - if (GET_FLAG(CF)) - res = d - s - 1; - else - res = d - s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(bc & 0x80, CF); - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); -// return res & 0x0FF; - return (uint8) res; -} - -/* sbb word primitive */ -uint16 sbb_word(uint16 d, uint16 s) -{ - register uint32 res; - register uint32 bc; - - if (GET_FLAG(CF)) - res = d - s - 1; - else - res = d - s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(bc & 0x8000, CF); - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 14) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); -// return res & 0xFFFF; - return (uint16) res; -} - -/* sub byte primitive */ -uint8 sub_byte(uint8 d, uint8 s) -{ - register uint32 res; - register uint32 bc; - - res = d - s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(bc & 0x80, CF); - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); -// return res & 0xff; - return (uint8) res; -} - -/* sub word primitive */ -uint16 sub_word(uint16 d, uint16 s) -{ - register uint32 res; - register uint32 bc; - - res = d - s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res &0x8000, SF); - CONDITIONAL_SET_FLAG((res &0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(bc & 0x8000, CF); - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 14) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); -// return res & 0xffff; - return (uint16) res; -} - -/* test byte primitive */ -void test_byte(uint8 d, uint8 s) -{ - register uint32 res; - - res = d & s; - CLR_FLAG(OF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* AF == dont care*/ - CLR_FLAG(CF); -} - -/* test word primitive */ -void test_word(uint16 d, uint16 s) -{ - register uint32 res; - - res = d & s; - CLR_FLAG(OF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); - /* AF == dont care*/ - CLR_FLAG(CF); -} - -/* xor byte primitive */ -uint8 xor_byte(uint8 d, uint8 s) -{ - register uint8 res; - res = d ^ s; - - /* clear flags */ - CLR_FLAG(OF); - CLR_FLAG(CF); - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res), PF); - return res; -} - -/* xor word primitive */ -uint16 xor_word(uint16 d, uint16 s) -{ - register uint16 res; - - res = d ^ s; - /* clear flags */ - CLR_FLAG(OF); - CLR_FLAG(CF); - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - return res; -} - -/* memory routines. These use the segment register (segreg) value and offset - (addr) to calculate the proper source or destination memory address */ - -/* get a byte from memory */ - -int32 get_smbyte(int32 segreg, int32 addr) -{ - int32 abs_addr, val; - - abs_addr = addr + (get_rword(segreg) << 4); - val = get_mbyte(abs_addr); -// if (i8088_dev.dctrl & DEBUG_level1) -// sim_printf("get_smbyte: seg=%04X addr=%04X abs_addr=%05X val=%02X\n", -// get_rword(segreg), addr, abs_addr, val); - return val; -} - -/* get a word from memory using addr and segment register */ - -int32 get_smword(int32 segreg, int32 addr) -{ - int32 val; - - val = get_smbyte(segreg, addr); - val |= (get_smbyte(segreg, addr+1) << 8); - return val; -} - -/* put a byte to memory using addr and segment register */ - -void put_smbyte(int32 segreg, int32 addr, int32 val) -{ - int32 abs_addr; - - abs_addr = addr + (get_rword(segreg) << 4); - put_mbyte(abs_addr, val); -// if (i8088_dev.dctrl & DEBUG_level1) -// sim_printf("put_smbyte: seg=%04X addr=%04X abs_addr=%08X val=%02X\n", -// get_rword(segreg), addr, abs_addr, val); -} - -/* put a word to memory using addr and segment register */ - -void put_smword(int32 segreg, int32 addr, int32 val) -{ - put_smbyte(segreg, addr, val); - put_smbyte(segreg, addr+1, val << 8); -} - -/* Reset routine using addr and segment register */ - -t_stat i8088_reset (DEVICE *dptr) -{ - PSW = 0; - CS = 0xFFFF; - DS = 0; - SS = 0; - ES = 0; - saved_PC = 0; - int_req = 0; - sim_brk_types = sim_brk_dflt = SWMASK ('E'); - sim_printf(" 8088 Reset\n"); - return SCPE_OK; -} - +} + /* Memory examine */ t_stat i8088_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) @@ -4743,38 +3733,7 @@ t_stat sim_load (FILE *fileref, const char *cptr, const char *fnam, int flag) t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) { - int32 cflag, c1, c2, inst, adr; - - cflag = (uptr == NULL) || (uptr == &i8088_unit); - c1 = (val[0] >> 8) & 0177; - c2 = val[0] & 0177; - if (sw & SWMASK ('A')) { - fprintf (of, (c2 < 040)? "<%02X>": "%c", c2); - return SCPE_OK; - } - if (sw & SWMASK ('C')) { - fprintf (of, (c1 < 040)? "<%02X>": "%c", c1); - fprintf (of, (c2 < 040)? "<%02X>": "%c", c2); - return SCPE_OK; - } - if (!(sw & SWMASK ('M'))) return SCPE_ARG; - inst = val[0]; - fprintf (of, "%s", opcode[inst]); - if (oplen[inst] == 2) { - if (strchr(opcode[inst], ' ') != NULL) - fprintf (of, ","); - else fprintf (of, " "); - fprintf (of, "%x", val[1]); - } - if (oplen[inst] == 3) { - adr = val[1] & 0xFF; - adr |= (val[2] << 8) & 0xff00; - if (strchr(opcode[inst], ' ') != NULL) - fprintf (of, ","); - else fprintf (of, " "); - fprintf (of, "%x", adr); - } - return -(oplen[inst] - 1); + return (SCPE_OK); } /* Symbolic input @@ -4791,87 +3750,8 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, t_stat parse_sym (const char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) { - int32 cflag, i = 0, j, r; - char gbuf[CBUFSIZE]; - - memset (gbuf, 0, sizeof (gbuf)); - cflag = (uptr == NULL) || (uptr == &i8088_unit); - while (isspace (*cptr)) cptr++; /* absorb spaces */ - if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (uint32) cptr[0]; - return SCPE_OK; - } - if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((uint32) cptr[0] << 8) + (uint32) cptr[1]; - return SCPE_OK; - } - -/* An instruction: get opcode (all characters until null, comma, - or numeric (including spaces). -*/ - - while (i < sizeof (gbuf) - 4) { - if (*cptr == ',' || *cptr == '\0' || - isdigit(*cptr)) - break; - gbuf[i] = toupper(*cptr); - cptr++; - i++; - } - -/* Allow for RST which has numeric as part of opcode */ - - if (toupper(gbuf[0]) == 'R' && - toupper(gbuf[1]) == 'S' && - toupper(gbuf[2]) == 'T') { - gbuf[i] = toupper(*cptr); - cptr++; - i++; - } - -/* Allow for 'MOV' which is only opcode that has comma in it. */ - - if (toupper(gbuf[0]) == 'M' && - toupper(gbuf[1]) == 'O' && - toupper(gbuf[2]) == 'V') { - gbuf[i] = toupper(*cptr); - cptr++; - i++; - gbuf[i] = toupper(*cptr); - cptr++; - i++; - } - -/* kill trailing spaces if any */ - gbuf[i] = '\0'; - for (j = i - 1; gbuf[j] == ' '; j--) { - gbuf[j] = '\0'; - } - -/* find opcode in table */ - for (j = 0; j < 256; j++) { - if (strcmp(gbuf, opcode[j]) == 0) - break; - } - if (j > 255) /* not found */ - return SCPE_ARG; - - val[0] = j; /* store opcode */ - if (oplen[j] < 2) /* if 1-byter we are done */ - return SCPE_OK; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); /* get address */ - sscanf(gbuf, "%o", &r); - if (oplen[j] == 2) { - val[1] = r & 0xFF; - return (-1); - } - val[1] = r & 0xFF; - val[2] = (r >> 8) & 0xFF; - return (-2); + return (SCPE_OK); } /* end of i8088.c */ - + diff --git a/Intel-Systems/common/i8237.c b/Intel-Systems/common/i8237.c index 72a44c8b..bc6f111c 100644 --- a/Intel-Systems/common/i8237.c +++ b/Intel-Systems/common/i8237.c @@ -235,13 +235,17 @@ #include "system_defs.h" +#define i8237_NAME "Intel i8237 DMA Chip" + /* external globals */ /* internal function prototypes */ -t_stat i8237_svc (UNIT *uptr); +t_stat i8237_cfg(uint16 base, uint16 devnum, uint8 dummy); +t_stat i8237_clr(void); +t_stat i8237_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat i8237_reset (DEVICE *dptr); -void i8237_reset_dev (uint8 devnum); +void i8237_reset_dev (void); t_stat i8237_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); uint8 i8237_r0x(t_bool io, uint8 data, uint8 devnum); uint8 i8237_r1x(t_bool io, uint8 data, uint8 devnum); @@ -263,112 +267,65 @@ uint8 i8237_rFx(t_bool io, uint8 data, uint8 devnum); /* external function prototypes */ extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint8, uint8); +extern uint8 unreg_dev(uint16); /* globals */ +static const char* i8237_desc(DEVICE *dptr) { + return i8237_NAME; +} +int i8237_baseport = -1; //base port +uint8 i8237_verb = 0; //verbose flag + /* 8237 physical register definitions */ -uint16 i8237_r0[4]; // 8237 ch 0 address register -uint16 i8237_r1[4]; // 8237 ch 0 count register -uint16 i8237_r2[4]; // 8237 ch 1 address register -uint16 i8237_r3[4]; // 8237 ch 1 count register -uint16 i8237_r4[4]; // 8237 ch 2 address register -uint16 i8237_r5[4]; // 8237 ch 2 count register -uint16 i8237_r6[4]; // 8237 ch 3 address register -uint16 i8237_r7[4]; // 8237 ch 3 count register -uint8 i8237_r8[4]; // 8237 status register -uint8 i8237_r9[4]; // 8237 command register -uint8 i8237_rA[4]; // 8237 mode register -uint8 i8237_rB[4]; // 8237 mask register -uint8 i8237_rC[4]; // 8237 request register -uint8 i8237_rD[4]; // 8237 first/last ff -uint8 i8237_rE[4]; // 8237 -uint8 i8237_rF[4]; // 8237 +uint16 i8237_r0; // 8237 ch 0 address register +uint16 i8237_r1; // 8237 ch 0 count register +uint16 i8237_r2; // 8237 ch 1 address register +uint16 i8237_r3; // 8237 ch 1 count register +uint16 i8237_r4; // 8237 ch 2 address register +uint16 i8237_r5; // 8237 ch 2 count register +uint16 i8237_r6; // 8237 ch 3 address register +uint16 i8237_r7; // 8237 ch 3 count register +uint8 i8237_r8; // 8237 status register +uint8 i8237_r9; // 8237 command register +uint8 i8237_rA; // 8237 mode register +uint8 i8237_rB; // 8237 mask register +uint8 i8237_rC; // 8237 request register +uint8 i8237_rD; // 8237 first/last ff +uint8 i8237_rE; // 8237 +uint8 i8237_rF; // 8237 /* i8237 physical register definitions */ -uint16 i8237_sr[4]; // 8237 segment register -uint8 i8237_i[4]; // 8237 interrupt register -uint8 i8237_a[4]; // 8237 auxillary port register +uint16 i8237_sr; // 8237 segment register +uint8 i8237_i; // 8237 interrupt register +uint8 i8237_a; // 8237 auxillary port register -/* i8237 Standard SIMH Device Data Structures - 4 units */ +/* i8237 Standard SIMH Device Data Structures - 1 unit */ -UNIT i8237_unit[] = { - { UDATA (0, 0, 0) ,20 }, /* i8237 0 */ - { UDATA (0, 0, 0) ,20 }, /* i8237 1 */ - { UDATA (0, 0, 0) ,20 }, /* i8237 2 */ - { UDATA (0, 0, 0) ,20 } /* i8237 3 */ +UNIT i8237_unit = { + { 0 } }; REG i8237_reg[] = { - { HRDATA (CH0ADR0, i8237_r0[0], 16) }, /* i8237 0 */ - { HRDATA (CH0CNT0, i8237_r1[0], 16) }, - { HRDATA (CH1ADR0, i8237_r2[0], 16) }, - { HRDATA (CH1CNT0, i8237_r3[0], 16) }, - { HRDATA (CH2ADR0, i8237_r4[0], 16) }, - { HRDATA (CH2CNT0, i8237_r5[0], 16) }, - { HRDATA (CH3ADR0, i8237_r6[0], 16) }, - { HRDATA (CH3CNT0, i8237_r7[0], 16) }, - { HRDATA (STAT370, i8237_r8[0], 8) }, - { HRDATA (CMD370, i8237_r9[0], 8) }, - { HRDATA (MODE0, i8237_rA[0], 8) }, - { HRDATA (MASK0, i8237_rB[0], 8) }, - { HRDATA (REQ0, i8237_rC[0], 8) }, - { HRDATA (FF0, i8237_rD[0], 8) }, - { HRDATA (SEGREG0, i8237_sr[0], 8) }, - { HRDATA (AUX0, i8237_a[0], 8) }, - { HRDATA (INT0, i8237_i[0], 8) }, - { HRDATA (CH0ADR1, i8237_r0[1], 16) }, /* i8237 1 */ - { HRDATA (CH0CNT1, i8237_r1[1], 16) }, - { HRDATA (CH1ADR1, i8237_r2[1], 16) }, - { HRDATA (CH1CNT1, i8237_r3[1], 16) }, - { HRDATA (CH2ADR1, i8237_r4[1], 16) }, - { HRDATA (CH2CNT1, i8237_r5[1], 16) }, - { HRDATA (CH3ADR1, i8237_r6[1], 16) }, - { HRDATA (CH3CNT1, i8237_r7[1], 16) }, - { HRDATA (STAT371, i8237_r8[1], 8) }, - { HRDATA (CMD371, i8237_r9[1], 8) }, - { HRDATA (MODE1, i8237_rA[1], 8) }, - { HRDATA (MASK1, i8237_rB[1], 8) }, - { HRDATA (REQ1, i8237_rC[1], 8) }, - { HRDATA (FF1, i8237_rD[1], 8) }, - { HRDATA (SEGREG1, i8237_sr[1], 8) }, - { HRDATA (AUX1, i8237_a[1], 8) }, - { HRDATA (INT1, i8237_i[1], 8) }, - { HRDATA (CH0ADR2, i8237_r0[2], 16) }, /* i8237 2 */ - { HRDATA (CH0CNT2, i8237_r1[2], 16) }, - { HRDATA (CH1ADR2, i8237_r2[2], 16) }, - { HRDATA (CH1CNT2, i8237_r3[2], 16) }, - { HRDATA (CH2ADR2, i8237_r4[2], 16) }, - { HRDATA (CH2CNT2, i8237_r5[2], 16) }, - { HRDATA (CH3ADR2, i8237_r6[2], 16) }, - { HRDATA (CH3CNT2, i8237_r7[2], 16) }, - { HRDATA (STAT372, i8237_r8[2], 8) }, - { HRDATA (CMD372, i8237_r9[2], 8) }, - { HRDATA (MODE2, i8237_rA[2], 8) }, - { HRDATA (MASK2, i8237_rB[2], 8) }, - { HRDATA (REQ2, i8237_rC[2], 8) }, - { HRDATA (FF2, i8237_rD[2], 8) }, - { HRDATA (SEGREG2, i8237_sr[2], 8) }, - { HRDATA (AUX2, i8237_a[2], 8) }, - { HRDATA (INT2, i8237_i[2], 8) }, - { HRDATA (CH0ADR3, i8237_r0[3], 16) }, /* i8237 3 */ - { HRDATA (CH0CNT3, i8237_r1[3], 16) }, - { HRDATA (CH1ADR3, i8237_r2[3], 16) }, - { HRDATA (CH1CNT3, i8237_r3[3], 16) }, - { HRDATA (CH2ADR3, i8237_r4[3], 16) }, - { HRDATA (CH2CNT3, i8237_r5[3], 16) }, - { HRDATA (CH3ADR3, i8237_r6[3], 16) }, - { HRDATA (CH3CNT3, i8237_r7[3], 16) }, - { HRDATA (STAT373, i8237_r8[3], 8) }, - { HRDATA (CMD373, i8237_r9[3], 8) }, - { HRDATA (MODE3, i8237_rA[3], 8) }, - { HRDATA (MASK3, i8237_rB[3], 8) }, - { HRDATA (REQ3, i8237_rC[3], 8) }, - { HRDATA (FF3, i8237_rD[3], 8) }, - { HRDATA (SEGREG3, i8237_sr[3], 8) }, - { HRDATA (AUX3, i8237_a[3], 8) }, - { HRDATA (INT3, i8237_i[3], 8) }, + { HRDATA (CH0ADR0, i8237_r0, 16) }, + { HRDATA (CH0CNT0, i8237_r1, 16) }, + { HRDATA (CH1ADR0, i8237_r2, 16) }, + { HRDATA (CH1CNT0, i8237_r3, 16) }, + { HRDATA (CH2ADR0, i8237_r4, 16) }, + { HRDATA (CH2CNT0, i8237_r5, 16) }, + { HRDATA (CH3ADR0, i8237_r6, 16) }, + { HRDATA (CH3CNT0, i8237_r7, 16) }, + { HRDATA (STAT370, i8237_r8, 8) }, + { HRDATA (CMD370, i8237_r9, 8) }, + { HRDATA (MODE0, i8237_rA, 8) }, + { HRDATA (MASK0, i8237_rB, 8) }, + { HRDATA (REQ0, i8237_rC, 8) }, + { HRDATA (FF0, i8237_rD, 8) }, + { HRDATA (SEGREG0, i8237_sr, 8) }, + { HRDATA (AUX0, i8237_a, 8) }, + { HRDATA (INT0, i8237_i, 8) }, { NULL } }; @@ -389,7 +346,7 @@ DEBTAB i8237_debug[] = { DEVICE i8237_dev = { "8237", //name - i8237_unit, //units + &i8237_unit, //units i8237_reg, //registers i8237_mod, //modifiers I8237_NUM, //numunits @@ -409,40 +366,76 @@ DEVICE i8237_dev = { 0, //dctrl i8237_debug, //debflags NULL, //msize - NULL //lname + NULL, //lname + NULL, //help routine + NULL, //attach help routine + NULL, //help context + &i8237_desc //device description }; /* Service routines to handle simulator functions */ -// i8251 configuration +// i8237 configuration -t_stat i8237_cfg(uint8 base, uint8 devnum) +t_stat i8237_cfg(uint16 base, uint16 devnum, uint8 dummy) { - sim_printf(" i8237[%d]: at base port 0%02XH\n", - devnum, base & 0xFF); - reg_dev(i8237_r1x, base + 1, devnum); - reg_dev(i8237_r2x, base + 2, devnum); - reg_dev(i8237_r3x, base + 3, devnum); - reg_dev(i8237_r4x, base + 4, devnum); - reg_dev(i8237_r5x, base + 5, devnum); - reg_dev(i8237_r6x, base + 6, devnum); - reg_dev(i8237_r7x, base + 7, devnum); - reg_dev(i8237_r8x, base + 8, devnum); - reg_dev(i8237_r9x, base + 9, devnum); - reg_dev(i8237_rAx, base + 10, devnum); - reg_dev(i8237_rBx, base + 11, devnum); - reg_dev(i8237_rCx, base + 12, devnum); - reg_dev(i8237_rDx, base + 13, devnum); - reg_dev(i8237_rEx, base + 14, devnum); - reg_dev(i8237_rFx, base + 15, devnum); + i8237_baseport = base & 0x3ff; + sim_printf(" i8237: at base port 0%03XH\n", + i8237_baseport & 0x3FF); + reg_dev(i8237_r0x, i8237_baseport, 0); + reg_dev(i8237_r1x, i8237_baseport + 1, 0); + reg_dev(i8237_r2x, i8237_baseport + 2, 0); + reg_dev(i8237_r3x, i8237_baseport + 3, 0); + reg_dev(i8237_r4x, i8237_baseport + 4, 0); + reg_dev(i8237_r5x, i8237_baseport + 5, 0); + reg_dev(i8237_r6x, i8237_baseport + 6, 0); + reg_dev(i8237_r7x, i8237_baseport + 7, 0); + reg_dev(i8237_r8x, i8237_baseport + 8, 0); + reg_dev(i8237_r9x, i8237_baseport + 9, 0); + reg_dev(i8237_rAx, i8237_baseport + 10, 0); + reg_dev(i8237_rBx, i8237_baseport + 11, 0); + reg_dev(i8237_rCx, i8237_baseport + 12, 0); + reg_dev(i8237_rDx, i8237_baseport + 13, 0); + reg_dev(i8237_rEx, i8237_baseport + 14, 0); + reg_dev(i8237_rFx, i8237_baseport + 15, 0); return SCPE_OK; } -/* service routine - actually does the simulated DMA */ - -t_stat i8237_svc(UNIT *uptr) +t_stat i8237_clr(void) { - sim_activate (&i8237_unit[uptr->u6], i8237_unit[uptr->u6].wait); + unreg_dev(i8237_baseport); + unreg_dev(i8237_baseport + 1); + unreg_dev(i8237_baseport + 2); + unreg_dev(i8237_baseport + 3); + unreg_dev(i8237_baseport + 4); + unreg_dev(i8237_baseport + 5); + unreg_dev(i8237_baseport + 6); + unreg_dev(i8237_baseport + 7); + unreg_dev(i8237_baseport + 8); + unreg_dev(i8237_baseport + 9); + unreg_dev(i8237_baseport + 10); + unreg_dev(i8237_baseport + 11); + unreg_dev(i8237_baseport + 12); + unreg_dev(i8237_baseport + 13); + unreg_dev(i8237_baseport + 14); + unreg_dev(i8237_baseport + 15); + i8237_baseport = -1; + i8237_verb = 0; + return SCPE_OK; +} + +// show configuration parameters + +t_stat i8237_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc) +{ + if (uptr == NULL) + return SCPE_ARG; + fprintf(st, "Device %s\n", ((i8237_dev.flags & DEV_DIS) == 0) ? "Enabled" : "Disabled"); + fprintf(st, " at Base port "); + fprintf(st, "0%03X ", i8237_baseport); + fprintf(st, "Mode "); + fprintf(st, "%s", i8237_verb ? "Verbose" : "Quiet"); + fprintf(st, "\n"); return SCPE_OK; } @@ -450,49 +443,27 @@ t_stat i8237_svc(UNIT *uptr) t_stat i8237_reset(DEVICE *dptr) { - uint8 devnum; - - for (devnum=0; devnumcapac == 0) { /* if not configured */ -// sim_printf(" SBC208%d: Not configured\n", i); -// if (flag) { -// sim_printf(" ALL: \"set isbc208 en\"\n"); -// sim_printf(" EPROM: \"att isbc2080 \"\n"); -// flag = 0; -// } - uptr->capac = 0; /* initialize unit */ - uptr->u3 = 0; - uptr->u4 = 0; - uptr->u5 = 0; - uptr->u6 = i; /* unit number - only set here! */ - sim_activate (&i8237_unit[uptr->u6], i8237_unit[uptr->u6].wait); - } else { -// sim_printf(" SBC208%d: Configured, Attached to %s\n", i, uptr->filename); - } + uptr = i8237_dev.units; + if (uptr->capac == 0) { /* if not configured */ + uptr->u3 = 0; + uptr->u4 = 0; + uptr->u5 = 0; } - devnum = uptr->u6; - i8237_r8[devnum] = 0; /* status */ - i8237_r9[devnum] = 0; /* command */ - i8237_rB[devnum] = 0x0F; /* mask */ - i8237_rC[devnum] = 0; /* request */ - i8237_rD[devnum] = 0; /* first/last FF */ + i8237_r8 = 0; /* status */ + i8237_r9 = 0; /* command */ + i8237_rB = 0x0F; /* mask */ + i8237_rC = 0; /* request */ + i8237_rD = 0; /* first/last FF */ } - /* i8237 set mode = 8- or 16-bit data bus */ /* always 8-bit mode for current simulators */ @@ -515,24 +486,24 @@ t_stat i8237_set_mode(UNIT *uptr, int32 val, CONST char *cptr, void *desc) uint8 i8237_r0x(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read current address CH 0 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[devnum](H) read as %04X\n", i8237_r0[devnum]); - return (i8237_r0[devnum] >> 8); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(H) read as %04X\n", i8237_r0); + return (i8237_r0 >> 8); } else { /* low byte */ - i8237_rD[devnum]++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[devnum](L) read as %04X\n", i8237_r0[devnum]); - return (i8237_r0[devnum] & 0xFF); + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(L) read as %04X\n", i8237_r0); + return (i8237_r0 & 0xFF); } } else { /* write base & current address CH 0 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - i8237_r0[devnum] |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[devnum](H) set to %04X\n", i8237_r0[devnum]); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r0 |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(H) set to %04X\n", i8237_r0); } else { /* low byte */ - i8237_rD[devnum]++; - i8237_r0[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[devnum](L) set to %04X\n", i8237_r0[devnum]); + i8237_rD++; + i8237_r0 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(L) set to %04X\n", i8237_r0); } } return 0; @@ -541,24 +512,24 @@ uint8 i8237_r0x(t_bool io, uint8 data, uint8 devnum) uint8 i8237_r1x(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read current word count CH 0 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[devnum](H) read as %04X\n", i8237_r1[devnum]); - return (i8237_r1[devnum] >> 8); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(H) read as %04X\n", i8237_r1); + return (i8237_r1 >> 8); } else { /* low byte */ - i8237_rD[devnum]++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[devnum](L) read as %04X\n", i8237_r1[devnum]); - return (i8237_r1[devnum] & 0xFF); + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(L) read as %04X\n", i8237_r1); + return (i8237_r1 & 0xFF); } } else { /* write base & current address CH 0 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - i8237_r1[devnum] |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[devnum](H) set to %04X\n", i8237_r1[devnum]); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r1 |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(H) set to %04X\n", i8237_r1); } else { /* low byte */ - i8237_rD[devnum]++; - i8237_r1[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[devnum](L) set to %04X\n", i8237_r1[devnum]); + i8237_rD++; + i8237_r1 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(L) set to %04X\n", i8237_r1); } } return 0; @@ -567,24 +538,24 @@ uint8 i8237_r1x(t_bool io, uint8 data, uint8 devnum) uint8 i8237_r2x(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read current address CH 1 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[devnum](H) read as %04X\n", i8237_r2[devnum]); - return (i8237_r2[devnum] >> 8); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(H) read as %04X\n", i8237_r2); + return (i8237_r2 >> 8); } else { /* low byte */ - i8237_rD[devnum]++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[devnum](L) read as %04X\n", i8237_r2[devnum]); - return (i8237_r2[devnum] & 0xFF); + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(L) read as %04X\n", i8237_r2); + return (i8237_r2 & 0xFF); } } else { /* write base & current address CH 1 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - i8237_r2[devnum] |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[devnum](H) set to %04X\n", i8237_r2[devnum]); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r2 |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(H) set to %04X\n", i8237_r2); } else { /* low byte */ - i8237_rD[devnum]++; - i8237_r2[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[devnum](L) set to %04X\n", i8237_r2[devnum]); + i8237_rD++; + i8237_r2 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(L) set to %04X\n", i8237_r2); } } return 0; @@ -593,24 +564,24 @@ uint8 i8237_r2x(t_bool io, uint8 data, uint8 devnum) uint8 i8237_r3x(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read current word count CH 1 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3[devnum](H) read as %04X\n", i8237_r3[devnum]); - return (i8237_r3[devnum] >> 8); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(H) read as %04X\n", i8237_r3); + return (i8237_r3 >> 8); } else { /* low byte */ - i8237_rD[devnum]++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3[devnum](L) read as %04X\n", i8237_r3[devnum]); - return (i8237_r3[devnum] & 0xFF); + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(L) read as %04X\n", i8237_r3); + return (i8237_r3 & 0xFF); } } else { /* write base & current address CH 1 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - i8237_r3[devnum] |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3[devnum](H) set to %04X\n", i8237_r3[devnum]); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r3 |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(H) set to %04X\n", i8237_r3); } else { /* low byte */ - i8237_rD[devnum]++; - i8237_r3[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3[devnum](L) set to %04X\n", i8237_r3[devnum]); + i8237_rD++; + i8237_r3 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(L) set to %04X\n", i8237_r3); } } return 0; @@ -619,24 +590,24 @@ uint8 i8237_r3x(t_bool io, uint8 data, uint8 devnum) uint8 i8237_r4x(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read current address CH 2 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4[devnum](H) read as %04X\n", i8237_r4[devnum]); - return (i8237_r4[devnum] >> 8); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(H) read as %04X\n", i8237_r4); + return (i8237_r4 >> 8); } else { /* low byte */ - i8237_rD[devnum]++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4[devnum](L) read as %04X\n", i8237_r4[devnum]); - return (i8237_r4[devnum] & 0xFF); + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(L) read as %04X\n", i8237_r4); + return (i8237_r4 & 0xFF); } } else { /* write base & current address CH 2 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - i8237_r4[devnum] |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4[devnum](H) set to %04X\n", i8237_r4[devnum]); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r4 |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(H) set to %04X\n", i8237_r4); } else { /* low byte */ - i8237_rD[devnum]++; - i8237_r4[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4[devnum](L) set to %04X\n", i8237_r4[devnum]); + i8237_rD++; + i8237_r4 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(L) set to %04X\n", i8237_r4); } } return 0; @@ -645,24 +616,24 @@ uint8 i8237_r4x(t_bool io, uint8 data, uint8 devnum) uint8 i8237_r5x(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read current word count CH 2 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5[devnum](H) read as %04X\n", i8237_r5[devnum]); - return (i8237_r5[devnum] >> 8); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(H) read as %04X\n", i8237_r5); + return (i8237_r5 >> 8); } else { /* low byte */ - i8237_rD[devnum]++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5[devnum](L) read as %04X\n", i8237_r5[devnum]); - return (i8237_r5[devnum] & 0xFF); + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(L) read as %04X\n", i8237_r5); + return (i8237_r5 & 0xFF); } } else { /* write base & current address CH 2 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - i8237_r5[devnum] |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5[devnum](H) set to %04X\n", i8237_r5[devnum]); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r5 |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(H) set to %04X\n", i8237_r5); } else { /* low byte */ - i8237_rD[devnum]++; - i8237_r5[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5[devnum](L) set to %04X\n", i8237_r5[devnum]); + i8237_rD++; + i8237_r5 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(L) set to %04X\n", i8237_r5); } } return 0; @@ -671,24 +642,24 @@ uint8 i8237_r5x(t_bool io, uint8 data, uint8 devnum) uint8 i8237_r6x(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read current address CH 3 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6[devnum](H) read as %04X\n", i8237_r6[devnum]); - return (i8237_r6[devnum] >> 8); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(H) read as %04X\n", i8237_r6); + return (i8237_r6 >> 8); } else { /* low byte */ - i8237_rD[devnum]++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6[devnum](L) read as %04X\n", i8237_r6[devnum]); - return (i8237_r6[devnum] & 0xFF); + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(L) read as %04X\n", i8237_r6); + return (i8237_r6 & 0xFF); } } else { /* write base & current address CH 3 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - i8237_r6[devnum] |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6[devnum](H) set to %04X\n", i8237_r6[devnum]); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r6 |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(H) set to %04X\n", i8237_r6); } else { /* low byte */ - i8237_rD[devnum]++; - i8237_r6[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6[devnum](L) set to %04X\n", i8237_r6[devnum]); + i8237_rD++; + i8237_r6 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(L) set to %04X\n", i8237_r6); } } return 0; @@ -697,24 +668,24 @@ uint8 i8237_r6x(t_bool io, uint8 data, uint8 devnum) uint8 i8237_r7x(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read current word count CH 3 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7[devnum](H) read as %04X\n", i8237_r7[devnum]); - return (i8237_r7[devnum] >> 8); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(H) read as %04X\n", i8237_r7); + return (i8237_r7 >> 8); } else { /* low byte */ - i8237_rD[devnum]++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7[devnum](L) read as %04X\n", i8237_r7[devnum]); - return (i8237_r7[devnum] & 0xFF); + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(L) read as %04X\n", i8237_r7); + return (i8237_r7 & 0xFF); } } else { /* write base & current address CH 3 */ - if (i8237_rD[devnum]) { /* high byte */ - i8237_rD[devnum] = 0; - i8237_r7[devnum] |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7[devnum](H) set to %04X\n", i8237_r7[devnum]); + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r7 |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(H) set to %04X\n", i8237_r7); } else { /* low byte */ - i8237_rD[devnum]++; - i8237_r7[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7[devnum](L) set to %04X\n", i8237_r7[devnum]); + i8237_rD++; + i8237_r7 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(L) set to %04X\n", i8237_r7); } } return 0; @@ -723,11 +694,11 @@ uint8 i8237_r7x(t_bool io, uint8 data, uint8 devnum) uint8 i8237_r8x(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read status register */ - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r8[devnum] (status) read as %02X\n", i8237_r8[devnum]); - return (i8237_r8[devnum]); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r8 (status) read as %02X\n", i8237_r8); + return (i8237_r8); } else { /* write command register */ - i8237_r9[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r9[devnum] (command) set to %02X\n", i8237_r9[devnum]); + i8237_r9 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r9 (command) set to %02X\n", i8237_r9); } return 0; } @@ -735,11 +706,11 @@ uint8 i8237_r8x(t_bool io, uint8 data, uint8 devnum) uint8 i8237_r9x(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_r9[devnum]\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_r9\n"); return 0; } else { /* write request register */ - i8237_rC[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rC[devnum] (request) set to %02X\n", i8237_rC[devnum]); + i8237_rC = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rC (request) set to %02X\n", i8237_rC); } return 0; } @@ -747,36 +718,36 @@ uint8 i8237_r9x(t_bool io, uint8 data, uint8 devnum) uint8 i8237_rAx(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rA[devnum]\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rA\n"); return 0; } else { /* write single mask register */ switch(data & 0x03) { case 0: if (data & 0x04) - i8237_rB[devnum] |= 1; + i8237_rB |= 1; else - i8237_rB[devnum] &= ~1; + i8237_rB &= ~1; break; case 1: if (data & 0x04) - i8237_rB[devnum] |= 2; + i8237_rB |= 2; else - i8237_rB[devnum] &= ~2; + i8237_rB &= ~2; break; case 2: if (data & 0x04) - i8237_rB[devnum] |= 4; + i8237_rB |= 4; else - i8237_rB[devnum] &= ~4; + i8237_rB &= ~4; break; case 3: if (data & 0x04) - i8237_rB[devnum] |= 8; + i8237_rB |= 8; else - i8237_rB[devnum] &= ~8; + i8237_rB &= ~8; break; } - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB[devnum] (mask) set to %02X\n", i8237_rB[devnum]); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); } return 0; } @@ -784,11 +755,11 @@ uint8 i8237_rAx(t_bool io, uint8 data, uint8 devnum) uint8 i8237_rBx(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rB[devnum]\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rB\n"); return 0; } else { /* write mode register */ - i8237_rA[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rA[devnum] (mode) set to %02X\n", i8237_rA[devnum]); + i8237_rA = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rA (mode) set to %02X\n", i8237_rA); } return 0; } @@ -796,11 +767,11 @@ uint8 i8237_rBx(t_bool io, uint8 data, uint8 devnum) uint8 i8237_rCx(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rC[devnum]\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rC\n"); return 0; } else { /* clear byte pointer FF */ - i8237_rD[devnum] = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rD[devnum] (FF) cleared\n"); + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rD (FF) cleared\n"); } return 0; } @@ -808,7 +779,7 @@ uint8 i8237_rCx(t_bool io, uint8 data, uint8 devnum) uint8 i8237_rDx(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read temporary register */ - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rD[devnum]\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rD\n"); return 0; } else { /* master clear */ i8237_reset_dev(devnum); @@ -820,11 +791,11 @@ uint8 i8237_rDx(t_bool io, uint8 data, uint8 devnum) uint8 i8237_rEx(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rE[devnum]\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rE\n"); return 0; } else { /* clear mask register */ - i8237_rB[devnum] = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB[devnum] (mask) cleared\n"); + i8237_rB = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) cleared\n"); } return 0; } @@ -832,11 +803,11 @@ uint8 i8237_rEx(t_bool io, uint8 data, uint8 devnum) uint8 i8237_rFx(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rF[devnum]\n"); + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rF\n"); return 0; } else { /* write all mask register bits */ - i8237_rB[devnum] = data & 0x0F; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB[devnum] (mask) set to %02X\n", i8237_rB[devnum]); + i8237_rB = data & 0x0F; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); } return 0; } diff --git a/Intel-Systems/common/i8251.c b/Intel-Systems/common/i8251.c index f8ace64d..3546f75f 100644 --- a/Intel-Systems/common/i8251.c +++ b/Intel-Systems/common/i8251.c @@ -149,7 +149,7 @@ t_stat i8251_svc (UNIT *uptr); t_stat i8251_reset (DEVICE *dptr); uint8 i8251s(t_bool io, uint8 data, uint8 devnum); uint8 i8251d(t_bool io, uint8 data, uint8 devnum); -void i8251_reset_dev(uint8 devnum); +void i8251_reset_dev(uint16 devnum); /* i8251 Standard I/O Data Structures */ /* up to 4 i8251 devices */ @@ -187,8 +187,6 @@ DEBTAB i8251_debug[] = { { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, { NULL } }; @@ -196,7 +194,7 @@ MTAB i8251_mod[] = { { UNIT_ANSI, 0, "ANSI", "ANSI", NULL }, { UNIT_ANSI, UNIT_ANSI, "TTY", "TTY", NULL }, { MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, i8251_show_param, NULL, - "show configured parametes for i8251" }, + "show configured parameters for i8251" }, { 0 } }; @@ -235,11 +233,14 @@ DEVICE i8251_dev = { t_stat i8251_cfg(uint16 base, uint16 devnum, uint8 dummy) { - i8251_baseport[devnum] = base & 0xff; + i8251_baseport[devnum] = base & BYTEMASK; sim_printf(" i8251%d: installed at base port 0%02XH\n", devnum, i8251_baseport[devnum]); reg_dev(i8251d, i8251_baseport[devnum], devnum, 0); reg_dev(i8251s, i8251_baseport[devnum] + 1, devnum, 0); + i8251_reset_dev(devnum); + if (devnum == 0) + sim_activate (&i8251_unit[devnum], i8251_unit[devnum].wait); /* activate unit 0 */ i8251_num++; //next device return SCPE_OK; } @@ -295,7 +296,7 @@ t_stat i8251_svc (UNIT *uptr) if (uptr->flags & UNIT_ANSI) uptr->buf = toupper(uptr->buf); uptr->u3 |= RXR; /* Set status */ - return SCPE_OK; + return SCPE_OK; } /* Reset routine */ @@ -304,15 +305,15 @@ t_stat i8251_reset (DEVICE *dptr) { uint8 devnum; - for (devnum=0; devnumu6 = i8253_num; i8253_num++; + sim_activate (uptr, uptr->wait); /* start poll */ return SCPE_OK; } +// i8253 unconfiguration + t_stat i8253_clr(void) { int i; @@ -189,11 +214,130 @@ t_stat i8253_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc) return SCPE_OK; } -/* i8253_svc - actually gets char & places in buffer */ +/* i8253_svc - actually does timing */ t_stat i8253_svc (UNIT *uptr) { - sim_activate (&i8253_unit[0], i8253_unit[0].wait); /* continue poll */ + int devnum; + + if (uptr == NULL) + return SCPE_ARG; + devnum = uptr->u6; //get devnum for unit + switch (i8253_T0_control_word[devnum]) { + case 0: //mode 0 + break; + case 1: //mode 1 + break; + case 2: //mode 2 - rate generator + if (i8253_T0_gate[devnum]) { + i8253_T0_out[devnum] = 0; + if (i8253_T0_flag[devnum] == 0x10) { + i8253_T0_count[devnum]--; //decrement counter + if (i8253_T0_count[devnum] == 0) { //if 0, do something + i8253_T0_out[devnum] = 1; + i8253_T0_count[devnum] = i8253_T0_load[devnum]; + } else { + i8253_T0_out[devnum] = 1; + } + } + } + break; + case 3: //mode 3 - square wave rate generator + if (i8253_T0_gate[devnum]) { + i8253_T0_out[devnum] = 0; + if (i8253_T0_flag[devnum] == 0x10) { + i8253_T0_count[devnum]--; //decrement counter + if (i8253_T0_count[devnum] == 0) { //if 0, do something + i8253_T0_out[devnum] = ~i8253_T0_out[devnum]; + i8253_T0_count[devnum] = i8253_T0_load[devnum]; + } else { + i8253_T0_out[devnum] = 1; + } + } + } + break; + case 4: //mode 4 + break; + case 5: //mode 5 + break; + } + switch (i8253_T1_control_word[devnum]) { + case 0: //mode 0 + break; + case 1: //mode 1 + break; + case 2: //mode 2 - rate generator + if (i8253_T1_gate[devnum]) { + i8253_T1_out[devnum] = 0; + if (i8253_T0_flag[devnum] == 0x20) { + i8253_T1_count[devnum]--; //decrement counter + if (i8253_T1_count[devnum] == 0) { //if 0, do something + i8253_T1_out[devnum] = 1; + i8253_T1_count[devnum] = i8253_T1_load[devnum]; + } else { + i8253_T1_out[devnum] = 1; + } + } + } + break; + case 3: //mode 3 - square wave rate generator + if (i8253_T1_gate[devnum]) { + i8253_T1_out[devnum] = 0; + if (i8253_T0_flag[devnum] == 0x20) { + i8253_T1_count[devnum]--; //decrement counter + if (i8253_T1_count[devnum] == 0) { //if 0, do something + i8253_T1_out[devnum] = ~i8253_T1_out[devnum]; + i8253_T1_count[devnum] = i8253_T1_load[devnum]; + } else { + i8253_T1_out[devnum] = 1; + } + } + } + break; + case 4: //mode 4 + break; + case 5: //mode 5 + break; + } + switch (i8253_T2_control_word[devnum]) { + case 0: //mode 0 + break; + case 1: //mode 1 + break; + case 2: //mode 2 - rate generator + if (i8253_T2_gate[devnum]) { + i8253_T2_out[devnum] = 0; + if (i8253_T0_flag[devnum] == 0x40) { + i8253_T2_count[devnum]--; //decrement counter + if (i8253_T2_count[devnum] == 0) { //if 0, do something + i8253_T2_out[devnum] = 1; + i8253_T2_count[devnum] = i8253_T2_load[devnum]; + } else { + i8253_T2_out[devnum] = 1; + } + } + } + break; + case 3: //mode 3 - square wave rate generator + if (i8253_T2_gate[devnum]) { + i8253_T2_out[devnum] = 0; + if (i8253_T0_flag[devnum] == 0x40) { + i8253_T2_count[devnum]--; //decrement counter + if (i8253_T2_count[devnum] == 0) { //if 0, do something + i8253_T2_out[devnum] = ~i8253_T2_out[devnum]; + i8253_T2_count[devnum] = i8253_T2_load[devnum]; + } else { + i8253_T2_out[devnum] = 1; + } + } + } + break; + case 4: //mode 4 + break; + case 5: //mode 5 + break; + } + sim_activate (uptr, uptr->wait); /* continue poll */ return SCPE_OK; } @@ -201,14 +345,15 @@ t_stat i8253_svc (UNIT *uptr) t_stat i8253_reset (DEVICE *dptr) { - uint8 devnum; - - for (devnum=0; devnum> 4) & 0x03; if (io == 0) { /* read data port */ - return i8253_unit[devnum].u3; + switch (rl) { + case 0: //counter latching + i8253_T1_latch[devnum] = i8253_T1_count[devnum]; + break; + case 1: //read/load msb + i8253_T1_latch[devnum] = i8253_T1_count[devnum]; + return (i8253_T1_latch[devnum] >> 8); + break; + case 2: //read/load lsb + i8253_T1_latch[devnum] = i8253_T1_count[devnum]; + return (i8253_T1_latch[devnum] & BYTEMASK); + break; + case 3: //read/load lsb then msb + i8253_T1_latch[devnum] = i8253_T1_count[devnum]; + break; + } + if ((i8253_T1_flag[devnum] & 0x01) == 0) { + i8253_T1_flag[devnum] |= 0x01; + return (i8253_T1_latch[devnum] & BYTEMASK); + } else { + i8253_T1_flag[devnum] &= 0xfe; + return (i8253_T1_latch[devnum] >> 8); + } } else { /* write data port */ - i8253_unit[devnum].u3 = data; - //sim_activate_after (&i8253_unit[devnum], ); - return 0; + switch (rl) { + case 0: //counter latching + i8253_T1_latch[devnum] = i8253_T1_count[devnum]; + break; + case 1: //read/load msb + i8253_T1_load[devnum] = (data << 8); + i8253_T1_flag[devnum] |= 0x10; + break; + case 2: //read/load lsb + i8253_T1_load[devnum] = data; + i8253_T1_flag[devnum] |= 0x10; + break; + case 3: //read/load lsb then msb + if ((i8253_T1_flag[devnum] & 0x01) == 0) { + i8253_T1_load[devnum] = data; + i8253_T1_flag[devnum] |= 0x01; + } else { + i8253_T1_load[devnum] |= (data << 8); + i8253_T1_flag[devnum] &= 0xfe; + i8253_T1_flag[devnum] |= 0x10; + } + break; + } } return 0; } -//read routine: -//sim_activate_time(&i8253_unit[devnum])/sim_inst_per_second() - uint8 i8253t1(t_bool io, uint8 data, uint8 devnum) { + uint8 rl; + + rl = (i8253_T1_control_word[devnum] >> 4) & 0x03; if (io == 0) { /* read data port */ - return i8253_unit[devnum].u4; + switch (rl) { + case 0: //counter latching + i8253_T1_latch[devnum] = i8253_T1_count[devnum]; + break; + case 1: //read/load msb + i8253_T1_latch[devnum] = i8253_T1_count[devnum]; + return (i8253_T1_latch[devnum] >> 8); + break; + case 2: //read/load lsb + i8253_T1_latch[devnum] = i8253_T1_count[devnum]; + return (i8253_T1_latch[devnum] & BYTEMASK); + break; + case 3: //read/load lsb then msb + i8253_T1_latch[devnum] = i8253_T1_count[devnum]; + break; + } + if ((i8253_T1_flag[devnum] & 0x02) == 0) { + i8253_T1_flag[devnum] |= 0x02; + return (i8253_T1_latch[devnum] & BYTEMASK); + } else { + i8253_T1_flag[devnum] &= 0xfd; + return (i8253_T1_latch[devnum] >> 8); + } } else { /* write data port */ - i8253_unit[devnum].u4 = data; - return 0; + switch (rl) { + case 0: //counter latching + i8253_T1_latch[devnum] = i8253_T1_count[devnum]; + break; + case 1: //read/load msb + i8253_T1_load[devnum] = (data << 8); + i8253_T1_flag[devnum] |= 0x20; + break; + case 2: //read/load lsb + i8253_T1_load[devnum] = data; + i8253_T1_flag[devnum] |= 0x20; + break; + case 3: //read/load lsb then msb + if ((i8253_T1_flag[devnum] & 0x02) == 0) { + i8253_T1_load[devnum] = data; + i8253_T1_flag[devnum] |= 0x02; + } else { + i8253_T1_load[devnum] |= (data << 8); + i8253_T1_flag[devnum] &= 0xfd; + i8253_T1_flag[devnum] |= 0x20; + } + break; + } } return 0; } uint8 i8253t2(t_bool io, uint8 data, uint8 devnum) { + uint8 rl; + + rl = (i8253_T2_control_word[devnum] >> 4) & 0x03; if (io == 0) { /* read data port */ - return i8253_unit[devnum].u5; + switch (rl) { + case 0: //counter latching + i8253_T2_latch[devnum] = i8253_T2_count[devnum]; + break; + case 1: //read/load msb + i8253_T2_latch[devnum] = i8253_T2_count[devnum]; + return (i8253_T2_latch[devnum] >> 8); + break; + case 2: //read/load lsb + i8253_T2_latch[devnum] = i8253_T2_count[devnum]; + return (i8253_T2_latch[devnum] & BYTEMASK); + break; + case 3: //read/load lsb then msb + i8253_T2_latch[devnum] = i8253_T2_count[devnum]; + break; + } + if ((i8253_T2_flag[devnum] & 0x04) == 0) { + i8253_T2_flag[devnum] |= 0x04; + return (i8253_T2_latch[devnum] & BYTEMASK); + } + else { + i8253_T2_flag[devnum] &= 0xfb; + return (i8253_T2_latch[devnum] >> 8); + } } else { /* write data port */ - i8253_unit[devnum].u5 = data; - return 0; + switch (rl) { + case 0: //counter latching + i8253_T2_latch[devnum] = i8253_T2_count[devnum]; + break; + case 1: //read/load msb + i8253_T2_load[devnum] = (data << 8); + i8253_T2_flag[devnum] |= 0x40; + break; + case 2: //read/load lsb + i8253_T2_load[devnum] = data; + i8253_T2_flag[devnum] |= 0x40; + break; + case 3: //read/load lsb then msb + if ((i8253_T2_flag[devnum] & 0x04) == 0) { + i8253_T2_load[devnum] = data; + i8253_T2_flag[devnum] |= 0x04; + } else { + i8253_T2_load[devnum] |= (data << 8); + i8253_T2_flag[devnum] &= 0xfb; + i8253_T2_flag[devnum] |= 0x40; + } + break; + } } return 0; } uint8 i8253c(t_bool io, uint8 data, uint8 devnum) { + uint8 sc; + if (io == 0) { /* read status port */ - return i8253_unit[devnum].u6; + return 0xff; } else { /* write data port */ - i8253_unit[devnum].u6 = data; - return 0; + sc = (data >> 6) & 0x03; + switch (sc) { + case 0: + i8253_T0_control_word[devnum] = data; + i8253_T0_flag[devnum] = 0; + break; + case 1: + i8253_T1_control_word[devnum] = data; + i8253_T1_flag[devnum] = 0; + break; + case 2: + i8253_T2_control_word[devnum] = data; + i8253_T2_flag[devnum] = 0; + break; + } } return 0; } diff --git a/Intel-Systems/common/i8255.c b/Intel-Systems/common/i8255.c index 2d871c97..3fc4d5a7 100644 --- a/Intel-Systems/common/i8255.c +++ b/Intel-Systems/common/i8255.c @@ -152,7 +152,7 @@ MTAB i8255_mod[] = { // { MTAB_XTD | MTAB_VDV, 0, NULL, "INT", &isbc202_set_int, // NULL, NULL, "Sets the interrupt number for i8255"}, { MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, i8255_show_param, NULL, - "show configured parametes for i8255" }, + "show configured parameters for i8255" }, { 0 } }; @@ -161,8 +161,7 @@ DEBTAB i8255_debug[] = { { "FLOW", DEBUG_flow }, { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, + { "XACK", DEBUG_xack }, { NULL } }; @@ -204,7 +203,7 @@ t_stat i8255_cfg(uint16 base, uint16 devnum, uint8 dummy) DEVICE *dptr; dptr = find_dev (i8255_dev.name); - i8255_baseport[devnum] = base & 0xff; + i8255_baseport[devnum] = base & BYTEMASK; sim_printf(" i8255%d: installed at base port 0%02XH\n", devnum, i8255_baseport[devnum]); reg_dev(i8255a, i8255_baseport[devnum], devnum, 0); @@ -257,9 +256,7 @@ t_stat i8255_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc) t_stat i8255_reset (DEVICE *dptr) { -// if ((dptr->flags & DEV_DIS) == 0) { // enabled - i8255_reset_dev(); //software reset -// } + i8255_reset_dev(); //software reset return SCPE_OK; } diff --git a/Intel-Systems/common/i8259.c b/Intel-Systems/common/i8259.c index be803321..91d5f666 100644 --- a/Intel-Systems/common/i8259.c +++ b/Intel-Systems/common/i8259.c @@ -92,18 +92,9 @@ UNIT i8259_unit[] = { }; REG i8259_reg[] = { - { HRDATA (IRR0, i8259_unit[0].u3, 8) }, /* i8259 0 */ - { HRDATA (ISR0, i8259_unit[0].u4, 8) }, - { HRDATA (IMR0, i8259_unit[0].u5, 8) }, - { HRDATA (IRR1, i8259_unit[1].u3, 8) }, /* i8259 1 */ - { HRDATA (ISR1, i8259_unit[1].u4, 8) }, - { HRDATA (IMR1, i8259_unit[1].u5, 8) }, - { HRDATA (IRR1, i8259_unit[2].u3, 8) }, /* i8259 2 */ - { HRDATA (ISR1, i8259_unit[2].u4, 8) }, - { HRDATA (IMR1, i8259_unit[2].u5, 8) }, - { HRDATA (IRR1, i8259_unit[3].u3, 8) }, /* i8259 3 */ - { HRDATA (ISR1, i8259_unit[3].u4, 8) }, - { HRDATA (IMR1, i8259_unit[3].u5, 8) }, + { URDATAD(IRR0,i8259_unit[0].u3,16,8,0,4,0,"IRR0") }, + { URDATAD(ISR0,i8259_unit[0].u4,16,8,0,4,0,"ISR0") }, + { URDATAD(IMR0,i8259_unit[0].u5,16,8,0,4,0,"IMR0") }, { NULL } }; @@ -112,14 +103,13 @@ DEBTAB i8259_debug[] = { { "FLOW", DEBUG_flow }, { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, + { "XACK", DEBUG_xack }, { NULL } }; MTAB i8259_mod[] = { { MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, i8259_show_param, NULL, - "show configured parametes for i8259" }, + "show configured parameters for i8259" }, { 0 } }; @@ -130,7 +120,7 @@ DEVICE i8259_dev = { i8259_unit, //units i8259_reg, //registers i8259_mod, //modifiers - I8259_NUM, //numunits + 4, //numunits 16, //aradix 16, //awidth 1, //aincr @@ -162,7 +152,7 @@ DEVICE i8259_dev = { t_stat i8259_cfg(uint16 base, uint16 devnum, uint8 dummy) { - i8259_baseport[devnum] = base & 0xff; + i8259_baseport[devnum] = base & BYTEMASK; sim_printf(" i8259%d: installed at base port 0%02XH\n", devnum, i8259_baseport[devnum]); reg_dev(i8259a, i8259_baseport[devnum], devnum, 0); @@ -213,10 +203,16 @@ t_stat i8259_reset (DEVICE *dptr) { uint8 devnum; - for (devnum=0; devnumcapac, isbc064_dev.units->BASE_ADDR); + isbc064_dev.units->capac, isbc064_dev.units->u3); return SCPE_OK; } @@ -205,8 +201,8 @@ t_stat isbc064_set_base(UNIT *uptr, int32 val, CONST char *cptr, void *desc) sim_printf("SBC064: Base error\n"); return SCPE_ARG; } else { - isbc064_unit.BASE_ADDR = size * 1024; - sim_printf("SBC064: Base=%04XH\n", isbc064_unit.BASE_ADDR); + isbc064_unit.u3 = size * 1024; + sim_printf("SBC064: Base=%04XH\n", isbc064_unit.u3); return SCPE_OK; } } @@ -219,7 +215,7 @@ t_stat isbc064_show_param (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { fprintf(st, "Device %s, Base address=0%04XH, Size=0%04XH ", ((isbc064_dev.flags & DEV_DIS) == 0) ? "Enabled" : "Disabled", - isbc064_unit.BASE_ADDR, isbc064_unit.capac); + isbc064_unit.u3, isbc064_unit.capac); return SCPE_OK; } @@ -229,6 +225,7 @@ t_stat isbc064_reset (DEVICE *dptr) { if (dptr == NULL) return SCPE_ARG; + isbc064_unit.u3 = 0; //BASE=0 return SCPE_OK; } @@ -238,15 +235,15 @@ uint8 isbc064_get_mbyte(uint16 addr) { uint8 val; - val = *((uint8 *)isbc064_unit.filebuf + (addr - isbc064_unit.BASE_ADDR)); - return (val & 0xFF); + val = *((uint8 *)isbc064_unit.filebuf + (addr - isbc064_unit.u3)); + return (val & BYTEMASK); } /* put a byte into memory */ void isbc064_put_mbyte(uint16 addr, uint8 val) { - *((uint8 *)isbc064_unit.filebuf + (addr - isbc064_unit.BASE_ADDR)) = val & 0xFF; + *((uint8 *)isbc064_unit.filebuf + (addr - isbc064_unit.u3)) = val & BYTEMASK; return; } diff --git a/Intel-Systems/common/isbc201.c b/Intel-Systems/common/isbc201.c index d63e1641..d21d4770 100644 --- a/Intel-Systems/common/isbc201.c +++ b/Intel-Systems/common/isbc201.c @@ -290,7 +290,7 @@ MTAB isbc201_mod[] = { { MTAB_XTD | MTAB_VDV, 0, NULL, "INT", &isbc201_set_int, NULL, NULL, "Sets the interrupt number for iSBC201"}, { MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, &isbc201_show_param, NULL, - "show configured parametes for iSBC201" }, + "show configured parameters for iSBC201" }, { 0 } }; @@ -300,8 +300,6 @@ DEBTAB isbc201_debug[] = { { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, { NULL } }; @@ -349,7 +347,7 @@ t_stat isbc201_cfg(uint16 baseport, uint16 devnum, uint8 intnum) uptr->u6 = i; //fdd unit number uptr->flags &= ~UNIT_ATT; } - fdc201.baseport = baseport & 0xff; //set port + fdc201.baseport = baseport & BYTEMASK; //set port fdc201.intnum = intnum; //set interrupt fdc201.verb = 0; //clear verb reg_dev(isbc201r0, fdc201.baseport, 0, 0); //read status @@ -392,11 +390,11 @@ t_stat isbc201_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) if (val & UNIT_WPMODE) { /* write protect */ uptr->flags |= val; if (fdc201.verb) - sim_printf(" sbc201: WP\n"); + sim_printf(" sbc201%d: WP\n", uptr->u6); } else { /* read write */ uptr->flags &= ~val; if (fdc201.verb) - sim_printf(" sbc201: RW\n"); + sim_printf(" sbc201%d: RW\n", uptr->u6); } return SCPE_OK; } diff --git a/Intel-Systems/common/isbc202.c b/Intel-Systems/common/isbc202.c index 68a8eee8..9f398692 100644 --- a/Intel-Systems/common/isbc202.c +++ b/Intel-Systems/common/isbc202.c @@ -284,7 +284,7 @@ MTAB isbc202_mod[] = { { MTAB_XTD | MTAB_VDV, 0, NULL, "INT", &isbc202_set_int, NULL, NULL, "Sets the interrupt number for iSBC202"}, { MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, &isbc202_show_param, NULL, - "show configured parametes for iSBC202" }, + "show configured parameters for iSBC202" }, { 0 } }; @@ -294,8 +294,6 @@ DEBTAB isbc202_debug[] = { { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, { NULL } }; @@ -343,14 +341,14 @@ t_stat isbc202_cfg(uint16 baseport, uint16 devnum, uint8 intnum) uptr->u6 = i; //fdd unit number uptr->flags &= ~UNIT_ATT; } - fdc202.baseport = baseport & 0xff; //set port + fdc202.baseport = baseport & BYTEMASK; //set port fdc202.intnum = intnum; //set interrupt fdc202.verb = 0; //clear verb reg_dev(isbc202r0, fdc202.baseport, 0, 0); //read status reg_dev(isbc202r1, fdc202.baseport + 1, 0, 0); //read rslt type/write IOPB addr-l reg_dev(isbc202r2, fdc202.baseport + 2, 0, 0); //write IOPB addr-h and start reg_dev(isbc202r3, fdc202.baseport + 3, 0, 0); //read rstl byte - reg_dev(isbc202r7, fdc202.baseport + 7, 0, 0); //write reset fdc201 + reg_dev(isbc202r7, fdc202.baseport + 7, 0, 0); //write reset fdc202 isbc202_reset_dev(); //software reset // if (fdc202.verb) sim_printf(" sbc202: Enabled base port at 0%02XH, Interrupt #=%02X, %s\n", @@ -366,7 +364,7 @@ t_stat isbc202_clr(void) unreg_dev(fdc202.baseport + 1); //read rslt type/write IOPB addr-l unreg_dev(fdc202.baseport + 2); //write IOPB addr-h and start unreg_dev(fdc202.baseport + 3); //read rstl byte - unreg_dev(fdc202.baseport + 7); //write reset fdc201 + unreg_dev(fdc202.baseport + 7); //write reset fdc202 // if (fdc202.verb) sim_printf(" sbc202: Disabled\n"); return SCPE_OK; @@ -374,7 +372,7 @@ t_stat isbc202_clr(void) /* isbc202 set mode = Write protect */ -t_stat isbc202_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +t_stat isbc202_set_mode(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { if (uptr == NULL) return SCPE_ARG; @@ -384,11 +382,11 @@ t_stat isbc202_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) if (val & UNIT_WPMODE) { /* write protect */ uptr->flags |= val; // if (fdc202.verb) - sim_printf(" SBC202: WP\n"); + sim_printf(" SBC202%d: WP\n", uptr->u6); } else { /* read write */ uptr->flags &= ~val; // if (fdc202.verb) - sim_printf(" SBC202: RW\n"); + sim_printf(" SBC202%d: RW\n", uptr->u6); } return SCPE_OK; } @@ -409,7 +407,7 @@ t_stat isbc202_set_port(UNIT *uptr, int32 val, CONST char *cptr, void *desc) reg_dev(isbc202r1, fdc202.baseport + 1, 0, 0); //read rslt type/write IOPB addr-l reg_dev(isbc202r2, fdc202.baseport + 2, 0, 0); //write IOPB addr-h and start reg_dev(isbc202r3, fdc202.baseport + 3, 0, 0); //read rstl byte - reg_dev(isbc202r7, fdc202.baseport + 7, 0, 0); //write reset fdc201 + reg_dev(isbc202r7, fdc202.baseport + 7, 0, 0); //write reset fdc202 return SCPE_OK; } @@ -549,7 +547,7 @@ t_stat isbc202_attach (UNIT *uptr, CONST char *cptr) uint8 isbc202r0(t_bool io, uint8 data, uint8 devnum) { if (io == 0) { /* read ststus*/ - return fdc202.stat; + return fdc202.stat; } return 0; } @@ -631,14 +629,17 @@ void isbc202_diskio(void) fddnum = (di & 0x30) >> 4; uptr = isbc202_dev.units + fddnum; fbuf = (uint8 *) uptr->filebuf; - //check for not ready - switch(fddnum) { + if (fdc202.verb) + sim_printf("\n SBC202: FDD %d - nr=%02XH ta=%02XH sa=%02XH IOPB=%04XH PCX=%04XH", + fddnum, nr, ta, sa, fdc202.iopb, PCX); + switch(fddnum) { //check ready status case 0: if ((fdc202.stat & RDY0) == 0) { fdc202.rtype = ROK; fdc202.rbyte0 = RB0NR; fdc202.intff = 1; //set interrupt FF sim_printf("\n SBC202: FDD %d - Ready error", fddnum); + return; } break; case 1: diff --git a/Intel-Systems/common/isbc206.c b/Intel-Systems/common/isbc206.c index 76308559..1c500f12 100644 --- a/Intel-Systems/common/isbc206.c +++ b/Intel-Systems/common/isbc206.c @@ -262,7 +262,7 @@ MTAB isbc206_mod[] = { { MTAB_XTD | MTAB_VDV, 0, NULL, "INT", &isbc206_set_int, NULL, NULL, "Sets the interrupt number for iSBC206"}, { MTAB_XTD | MTAB_VDV, 0, "PARAM", NULL, NULL, &isbc206_show_param, NULL, - "show configured parametes for iSBC206" }, + "show configured parameters for iSBC206" }, { 0 } }; @@ -272,8 +272,6 @@ DEBTAB isbc206_debug[] = { { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, { NULL } }; @@ -320,7 +318,7 @@ t_stat isbc206_cfg(uint16 baseport, uint16 devnum, uint8 intnum) uptr = isbc206_dev.units + i; uptr->u6 = i; //fdd unit number } - hdc206.baseport = baseport & 0xff; //set port + hdc206.baseport = baseport & BYTEMASK; //set port hdc206.intnum = intnum; //set interrupt hdc206.verb = 0; //clear verb reg_dev(isbc206r0, hdc206.baseport, 0, 0); //read status @@ -381,8 +379,13 @@ t_stat isbc206_set_port(UNIT *uptr, int32 val, CONST char *cptr, void *desc) return SCPE_ARG; result = sscanf(cptr, "%02x", &size); hdc206.baseport = size; - if (hdc206.verb) +// if (hdc206.verb) sim_printf("SBC206: Base port=%04X\n", hdc206.baseport); + reg_dev(isbc206r0, hdc206.baseport, 0, 0); //read status + reg_dev(isbc206r1, hdc206.baseport + 1, 0, 0); //read rslt type/write IOPB addr-l + reg_dev(isbc206r2, hdc206.baseport + 2, 0, 0); //write IOPB addr-h and start + reg_dev(isbc206r3, hdc206.baseport + 3, 0, 0); //read rstl byte + reg_dev(isbc206r7, hdc206.baseport + 7, 0, 0); //write reset fdc202 return SCPE_OK; } @@ -396,7 +399,7 @@ t_stat isbc206_set_int(UNIT *uptr, int32 val, CONST char *cptr, void *desc) return SCPE_ARG; result = sscanf(cptr, "%02x", &size); hdc206.intnum = size; - if (hdc206.verb) +// if (hdc206.verb) sim_printf("SBC206: Interrupt number=%04X\n", hdc206.intnum); return SCPE_OK; } diff --git a/Intel-Systems/common/isbc208.c b/Intel-Systems/common/isbc208.c index f1821d74..ae2ab747 100644 --- a/Intel-Systems/common/isbc208.c +++ b/Intel-Systems/common/isbc208.c @@ -1,485 +1,487 @@ -/* isbc208.c: Intel iSBC208 Floppy Disk adapter - 05-03-15 version - - Copyright (c) 2011, William A. Beech - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of William A. Beech shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from William A. Beech. - - MODIFICATIONS: - - ?? ??? 11 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set baseport and size. - 24 Apr 15 -- Modified to use simh_debug - - NOTES: - - These functions support a simulated iSBC208 interface to 4 each 8-, 5 1/4-, or - 3 1/2-inch floppy disk drives. Commands are setup with programmed I/O to the - simulated ports of an i8237 DMA controller and an i8272 FDC. Data transfer - to/from the simulated disks is performed directly with the multibus memory. - - The iSBC-208 can be configured for 8- or 16-bit addresses. It defaults to 8-bit - addresses for the 8080/8085 processors. It can be configured for I/O port - addresses with 3-bits (8-bit address) or 11-bits (16-bit address). Default is - 3-bits set to 0. This defines the port offset to be used to determine the actual - port address. Bus priority can be configured for parallel or serial mode. Default is - serial. The multibus interface interrupt can be configured for interrupt 0-7. - Default is none. Since all channel registers in the i8237 are 16-bit, transfers - are done as two 8-bit operations, low- then high-byte. - - Port addressing is as follows (Port offset = 0): - - Port Mode Command Function - - 00 Write Load DMAC Channel 0 Base and Current Address Regsiters - Read Read DMAC Channel 0 Current Address Register - 01 Write Load DMAC Channel 0 Base and Current Word Count Registers - Read Read DMAC Channel 0 Current Word Count Register - 04 Write Load DMAC Channel 2 Base and Current Address Regsiters - Read Read DMAC Channel 2 Current Address Register - 05 Write Load DMAC Channel 2 Base and Current Word Count Registers - Read Read DMAC Channel 2 Current Word Count Register - 06 Write Load DMAC Channel 3 Base and Current Address Regsiters - Read Read DMAC Channel 3 Current Address Register - 07 Write Load DMAC Channel 3 Base and Current Word Count Registers - Read Read DMAC Channel 3 Current Word Count Register - 08 Write Load DMAC Command Register - Read Read DMAC Status Register - 09 Write Load DMAC Request Register - OA Write Set/Reset DMAC Mask Register - OB Write Load DMAC Mode Register - OC Write Clear DMAC First/Last Flip-Flop - 0D Write DMAC Master Clear - OF Write Load DMAC Mask Register - 10 Read Read FDC Status Register - 11 Write Load FDC Data Register - Read Read FDC Data Register - 12 Write Load Controller Auxiliary Port - Read Poll Interrupt Status - 13 Write Controller Reset - 14 Write Load Controller Low-Byte Segment Address Register - 15 Write Load Controller High-Byte Segment Address Register - 20-2F Read/Write Reserved for iSBX Multimodule Board - - Register usage is defined in the following paragraphs. - - Read/Write DMAC Address Registers - - Used to simultaneously load a channel's current-address register and baseport-address - register with the memory address of the first byte to be transferred. (The Channel - 0 current/baseport address register must be loaded prior to initiating a diskette read - or write operation.) Since each channel's address registers are 16 bits in length - (64K address range), two "write address register" commands must be executed in - order to load the complete current/baseport address registers for any channel. - - Read/Write DMAC Word Count Registers - - The Write DMAC Word Count Register command is used to simultaneously load a - channel's current and baseport word-count registers with the number of bytes - to be transferred during a subsequent DMA operation. Since the word-count - registers are 16-bits in length, two commands must be executed to load both - halves of the registers. - - Write DMAC Command Register - - The Write DMAC Command Register command loads an 8-bit byte into the - DMAC's command register to define the operating characteristics of the - DMAC. The functions of the individual bits in the command register are - defined in the following diagram. Note that only two bits within the - register are applicable to the controller; the remaining bits select - functions that are not supported and, accordingly, must always be set - to zero. - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | 0 0 0 0 0 0 | - +---+---+---+---+---+---+---+---+ - | | - | +---------- 0 CONTROLLER ENABLE - | 1 CONTROLLER DISABLE - | - +------------------ 0 FIXED PRIORITY - 1 ROTATING PRIORITY - - Read DMAC Status Register Command - - The Read DMAC Status Register command accesses an 8-bit status byte that - identifies the DMA channels that have reached terminal count or that - have a pending DMA request. - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | 0 0 | - +---+---+---+---+---+---+---+---+ - | | | | | | - | | | | | +-- CHANNEL 0 TC - | | | | +---------- CHANNEL 2 TC - | | | +-------------- CHANNEL 3 TC - | | +------------------ CHANNEL 0 DMA REQUEST - | +-------------------------- CHANNEL 2 DMA REQUEST - +------------------------------ CHANNEL 3 DMA REQUEST - - Write DMAC Request Register - - The data byte associated with the Write DMAC Request Register command - sets or resets a channel's associated request bit within the DMAC's - internal 4-bit request register. - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | X X X X X | - +---+---+---+---+---+---+---+---+ - | | | - | +---+-- 00 SELECT CHANNEL 0 - | 01 SELECT CHANNEL 1 - | 10 SELECT CHANNEL 2 - | 11 SELECT CHANNEL 3 - | - +---------- 0 RESET REQUEST BIT - 1 SET REQUEST BIT - - Set/Reset DMAC Mask Register - - Prior to a DREQ-initiated DMA transfer, the channel's mask bit must - be reset to enable recognition of the DREQ input. When the transfer - is complete (terminal count reached or external EOP applied) and - the channel is not programmed to autoinitialize, the channel's - mask bit is automatically set (disabling DREQ) and must be reset - prior to a subsequent DMA transfer. All four bits of the mask - register are set (disabling the DREQ inputs) by a DMAC master - clear or controller reset. Additionally, all four bits can be - set/reset by a single Write DMAC Mask Register command. - - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | X X X X X | - +---+---+---+---+---+---+---+---+ - | | | - | +---+-- 00 SELECT CHANNEL 0 - | 01 SELECT CHANNEL 1 - | 10 SELECT CHANNEL 2 - | 11 SELECT CHANNEL 3 - | - +---------- 0 RESET REQUEST BIT - 1 SET REQUEST BIT - - Write DMAC Mode Register - - The Write DMAC Mode Register command is used to define the - operating mode characteristics for each DMA channel. Each - channel has an internal 6-bit mode register; the high-order - six bits of the associated data byte are written into the - mode register addressed by the two low-order bits. - - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | | - +---+---+---+---+---+---+---+---+ - | | | | | | | | - | | | | | | +---+-- 00 SELECT CHANNEL 0 - | | | | | | 01 SELECT CHANNEL 1 - | | | | | | 10 SELECT CHANNEL 2 - | | | | | | 11 SELECT CHANNEL 3 - | | | | | | - | | | | +---+---------- 00 VERIFY TRANSFER - | | | | 01 WRITE TRANSFER - | | | | 10 READ TRANSFER - | | | | - | | | +------------------ 0 AUTOINITIALIZE DISABLE - | | | 1 AUTOINITIALIZE ENABLE - | | | - | | +---------------------- 0 ADDRESS INCREMENT - | | 1 ADDRESS DECREMENT - | | - +---+-------------------------- 00 DEMAND MODE - 01 SINGLE MODE - 10 BLOCK MODE - - Clear DMAC First/Last Flip-Flop - - The Clear DMAC First/Last Flip-Flop command initializes - the DMAC's internal first/last flip-flop so that the - next byte written to or re~d from the 16-bit address - or word-count registers is the low-order byte. The - flip-flop is toggled with each register access so that - a second register read or write command accesses the - high-order byte. - - DMAC Master Clear - - The DMAC Master Clear command clears the DMAC's command, status, - request, and temporary registers to zero, initializes the - first/last flip-flop, and sets the four channel mask bits in - the mask register to disable all DMA requests (i.e., the DMAC - is placed in an idle state). - - Write DMAC Mask Register - - The Write DMAC Mask Register command allows all four bits of the - DMAC's mask register to be written with a single command. - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | X X X X X | - +---+---+---+---+---+---+---+---+ - | | | - | | +-- 0 CLEAR CHANNEL 0 MASK BIT - | | 1 SET CHANNEL 0 MASK BIT - | | - | +---------- 0 CLEAR CHANNEL 2 MASK BIT - | 1 SET CHANNEL 2 MASK BIT - | - +-------------- 0 CLEAR CHANNEL 3 MASK BIT - 1 SET CHANNEL 3 MASK BIT - - Read FDC Status Register - - The Read FDC Status Register command accesses the FDC's main - status register. The individual status register bits are as - follows: - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | | - +---+---+---+---+---+---+---+---+ - | | | | | | | | - | | | | | | | +-- FDD 0 BUSY - | | | | | | +------ FDD 1 BUSY - | | | | | +---------- FDD 2 BUSY - | | | | +-------------- FDD 3 BUSY - | | | +------------------ FDC BUSY - | | +---------------------- NON-DMA MODE - | +-------------------------- DATA INPUT/OUTPUT - +------------------------------ REQUEST FOR MASTER - - Read/Write FDC Data Register - - The Read and Write FDC Data Register commands are used to write - command and parameter bytes to the FDC in order to specify the - operation to be performed (referred to as the "command phase") - and to read status bytes from the FDC following the operation - (referred to as the "result phase"). During the command and - result phases, the 8-bit data register is actually a series of - 8-bit registers in a stack. Each register is accessed in - sequence; the number of registers accessed and the individual - register contents are defined by the specific disk command. - - Write Controller Auxiliary Port - - The Write Controller Auxiliary Port command is used to set or - clear individual bits within the controller's auxiliary port. - The four low-order port bits are dedicated to auxiliary drive - control functions (jumper links are required to connect the - desired port bit to an available pin on the drive interface - connectors). The most common application for these bits is - the "Motor-On" control function for mini-sized drives. - - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | | - +---+---+---+---+---+---+---+---+ - | | | | | | | | - | | | | +---+---+---+-- DRIVE CONTROL - | | | +------------------ ADDR 20 - | | +---------------------- ADDR 21 - | +-------------------------- ADDR 22 - +------------------------------ ADDR 23 - - Poll Interrupt Status - - The Poll Interrupt Status command presents the interrupt - status of the controller and the two interrupt status - lines dedicated to the iSBX Multimodule board. - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | X X X X X | - +---+---+---+---+---+---+---+---+ - | | | - | | +-- CONTROLLER INTERRUPT - | +------ MULTIMODULE BOARD INTERRUPT 0 - +---------- MULTIMODULE BOARD INTERRUPT 1 - - Controller Reset - - The Controller Reset command is the software reset for the - controller. This command clears the controller's auxiliary - port and segment address register, provides a reset signal - to the iSBX Multimodule board and initializes the bus - controller (releases the bus), the DMAC (clears the internal - registers and masks the DREQ inputs), and the FDC (places - the FDC in an idle state and disables the output control - lines to the diskette drive). - - Write Controller Low- And High-Byte Segment Address Registers - - The Write Controller Low- and High-Byte Address Registers - commands are required when the controller uses 20-bit - addressing (memory address range from 0 to OFFFFFH). These - commands are issued prior to initiating a diskette read or - write operation to specify the 16-bit segment address. - - FDC Commands - - The 8272/D765 is capable of performing 15 different - commands. Each command is initiated by a multibyte transfer - from the processor, and the result after execution of the - command may also be a multibyte transfer back to the processor. - Because of this multibyte interchange of information between - the FDC and the processor, it is convenient to consider each - command as consisting of three phases: - - Command Phase: The FDC receives all information required to - perform a particular operation from the processor. - - Execution Phase: The FDC performs the operation it was - instructed to do. - - Result Phase: After completion of the operation, status - and other housekeeping information are made available - to the processor. - - Not all the FDC commands are supported by this emulation. Only the subset - of commands required to build an operable CP/M BIOS are supported. They are: - - Read - Read specified data from the selected FDD. - - Write - Write specified data to the selected FDD. - - Seek - Move the R/W head to the specified cylinder on the specified FDD. - - Specify - Set the characteristics for all the FDDs. - - Sense Interrupt - Sense change in FDD Ready line or end of Seek/Recalibrate - command. - - Sense Drive - Returns status of all the FDDs. - - Recalibrate - Move the R/W head to cylinder 0 on the specified FDD. - - Format Track - Format the current track on the specified FDD. - - Read ID - Reads the first address mark it finds. - - Simulated Floppy Disk Drives - - The units in this device simulate an 8- or 5 1/4- or 3 1/2 inch drives. The - drives can emulate SSSD, SSDD, and DSDD. Drives can be attached to files up - to 1.44MB in size. Drive configuration is selected when a disk is logged onto - the system. An identity sector or identity byte contains information to - configure the OS drivers for the type of drive to emulate. - - uptr->u3 - - uptr->u4 - - uptr->u5 - - uptr->u6 - unit number (0-FDD_NUM) -*/ - -#include "system_defs.h" - -#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */ -#define UNIT_WPMODE (1 << UNIT_V_WPMODE) - -/* master status register definitions */ -#define RQM 0x80 /* Request for master */ -#define DIO 0x40 /* Data I/O Direction 0=W, 1=R */ -#define NDM 0x20 /* Non-DMA mode */ -#define CB 0x10 /* FDC busy */ -#define D3B 0x08 /* FDD 3 busy */` -#define D2B 0x04 /* FDD 2 busy */` -#define D1B 0x02 /* FDD 1 busy */` -#define D0B 0x01 /* FDD 0 busy */` - -/* status register 0 definitions */ -#define IC 0xC0 /* Interrupt code */ -#define IC_NORM 0x00 /* normal completion */ -#define IC_ABNORM 0x40 /* abnormal completion */ -#define IC_INVC 0x80 /* invalid command */ -#define IC_RC 0xC0 /* drive not ready */ -#define SE 0x20 /* Seek end */ -#define EC 0x10 /* Equipment check */ -#define NR 0x08 /* Not ready */ -#define HD 0x04 /* Head selected */ -#define US 0x03 /* Unit selected */ -#define US_0 0x00 /* Unit 0 */ -#define US_1 0x01 /* Unit 1 */ -#define US_2 0x02 /* Unit 2 */ -#define US_3 0x03 /* Unit 3 */ - -/* status register 1 definitions */ -#define EN 0x80 /* End of cylinder */ -#define DE 0x20 /* Data error */ -#define OR 0x10 /* Overrun */ -#define ND 0x04 /* No data */ -#define NW 0x02 /* Not writable */ -#define MA 0x01 /* Missing address mark */ - -/* status register 2 definitions */ -#define CM 0x40 /* Control mark */ -#define DD 0x20 /* Data error in data field */ -#define WC 0x10 /* Wrong cylinder */ -#define BC 0x02 /* Bad cylinder */ -#define MD 0x01 /* Missing address mark in data field */ - -/* status register 3/fddst definitions */ -#define FT 0x80 /* Fault */ -#define WP 0x40 /* Write protect */ -#define RDY 0x20 /* Ready */ -#define T0 0x10 /* Track 0 */ -#define TS 0x08 /* Two sided */ -//#define HD 0x04 /* Head selected */ -//#define US 0x03 /* Unit selected */ - -/* FDC command definitions */ -#define READTRK 0x02 -#define SPEC 0x03 -#define SENDRV 0x04 -#define WRITE 0x05 -#define READ 0x06 -#define HOME 0x07 -#define SENINT 0x08 -#define WRITEDEL 0x09 -#define READID 0x0A -#define READDEL 0x0C -#define FMTTRK 0x0D -#define SEEK 0x0F -#define SCANEQ 0x11 -#define SCANLOEQ 0x19 -#define SCANHIEQ 0x1D - -#define FDD_NUM 4 - +/* isbc208.c: Intel iSBC208 Floppy Disk adapter + 05-03-15 version + + Copyright (c) 2011, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + MODIFICATIONS: + + ?? ??? 11 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set baseport and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + These functions support a simulated iSBC208 interface to 4 each 8-, 5 1/4-, or + 3 1/2-inch floppy disk drives. Commands are setup with programmed I/O to the + simulated ports of an i8237 DMA controller and an i8272 FDC. Data transfer + to/from the simulated disks is performed directly with the multibus memory. + + The iSBC-208 can be configured for 8- or 16-bit addresses. It defaults to 8-bit + addresses for the 8080/8085 processors. It can be configured for I/O port + addresses with 3-bits (8-bit address) or 11-bits (16-bit address). Default is + 3-bits set to 0. This defines the port offset to be used to determine the actual + port address. Bus priority can be configured for parallel or serial mode. Default is + serial. The multibus interface interrupt can be configured for interrupt 0-7. + Default is none. Since all channel registers in the i8237 are 16-bit, transfers + are done as two 8-bit operations, low- then high-byte. + + Port addressing is as follows (Port offset = 0): + + Port Mode Command Function + + 00 Write Load DMAC Channel 0 Base and Current Address Regsiters + Read Read DMAC Channel 0 Current Address Register + 01 Write Load DMAC Channel 0 Base and Current Word Count Registers + Read Read DMAC Channel 0 Current Word Count Register + 04 Write Load DMAC Channel 2 Base and Current Address Regsiters + Read Read DMAC Channel 2 Current Address Register + 05 Write Load DMAC Channel 2 Base and Current Word Count Registers + Read Read DMAC Channel 2 Current Word Count Register + 06 Write Load DMAC Channel 3 Base and Current Address Regsiters + Read Read DMAC Channel 3 Current Address Register + 07 Write Load DMAC Channel 3 Base and Current Word Count Registers + Read Read DMAC Channel 3 Current Word Count Register + 08 Write Load DMAC Command Register + Read Read DMAC Status Register + 09 Write Load DMAC Request Register + OA Write Set/Reset DMAC Mask Register + OB Write Load DMAC Mode Register + OC Write Clear DMAC First/Last Flip-Flop + 0D Write DMAC Master Clear + OF Write Load DMAC Mask Register + 10 Read Read FDC Status Register + 11 Write Load FDC Data Register + Read Read FDC Data Register + 12 Write Load Controller Auxiliary Port + Read Poll Interrupt Status + 13 Write Controller Reset + 14 Write Load Controller Low-Byte Segment Address Register + 15 Write Load Controller High-Byte Segment Address Register + 20-2F Read/Write Reserved for iSBX Multimodule Board + + Register usage is defined in the following paragraphs. + + Read/Write DMAC Address Registers + + Used to simultaneously load a channel's current-address register and baseport-address + register with the memory address of the first byte to be transferred. (The Channel + 0 current/baseport address register must be loaded prior to initiating a diskette read + or write operation.) Since each channel's address registers are 16 bits in length + (64K address range), two "write address register" commands must be executed in + order to load the complete current/baseport address registers for any channel. + + Read/Write DMAC Word Count Registers + + The Write DMAC Word Count Register command is used to simultaneously load a + channel's current and baseport word-count registers with the number of bytes + to be transferred during a subsequent DMA operation. Since the word-count + registers are 16-bits in length, two commands must be executed to load both + halves of the registers. + + Write DMAC Command Register + + The Write DMAC Command Register command loads an 8-bit byte into the + DMAC's command register to define the operating characteristics of the + DMAC. The functions of the individual bits in the command register are + defined in the following diagram. Note that only two bits within the + register are applicable to the controller; the remaining bits select + functions that are not supported and, accordingly, must always be set + to zero. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | 0 0 0 0 0 0 | + +---+---+---+---+---+---+---+---+ + | | + | +---------- 0 CONTROLLER ENABLE + | 1 CONTROLLER DISABLE + | + +------------------ 0 FIXED PRIORITY + 1 ROTATING PRIORITY + + Read DMAC Status Register Command + + The Read DMAC Status Register command accesses an 8-bit status byte that + identifies the DMA channels that have reached terminal count or that + have a pending DMA request. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | 0 0 | + +---+---+---+---+---+---+---+---+ + | | | | | | + | | | | | +-- CHANNEL 0 TC + | | | | +---------- CHANNEL 2 TC + | | | +-------------- CHANNEL 3 TC + | | +------------------ CHANNEL 0 DMA REQUEST + | +-------------------------- CHANNEL 2 DMA REQUEST + +------------------------------ CHANNEL 3 DMA REQUEST + + Write DMAC Request Register + + The data byte associated with the Write DMAC Request Register command + sets or resets a channel's associated request bit within the DMAC's + internal 4-bit request register. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | X X X X X | + +---+---+---+---+---+---+---+---+ + | | | + | +---+-- 00 SELECT CHANNEL 0 + | 01 SELECT CHANNEL 1 + | 10 SELECT CHANNEL 2 + | 11 SELECT CHANNEL 3 + | + +---------- 0 RESET REQUEST BIT + 1 SET REQUEST BIT + + Set/Reset DMAC Mask Register + + Prior to a DREQ-initiated DMA transfer, the channel's mask bit must + be reset to enable recognition of the DREQ input. When the transfer + is complete (terminal count reached or external EOP applied) and + the channel is not programmed to autoinitialize, the channel's + mask bit is automatically set (disabling DREQ) and must be reset + prior to a subsequent DMA transfer. All four bits of the mask + register are set (disabling the DREQ inputs) by a DMAC master + clear or controller reset. Additionally, all four bits can be + set/reset by a single Write DMAC Mask Register command. + + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | X X X X X | + +---+---+---+---+---+---+---+---+ + | | | + | +---+-- 00 SELECT CHANNEL 0 + | 01 SELECT CHANNEL 1 + | 10 SELECT CHANNEL 2 + | 11 SELECT CHANNEL 3 + | + +---------- 0 RESET REQUEST BIT + 1 SET REQUEST BIT + + Write DMAC Mode Register + + The Write DMAC Mode Register command is used to define the + operating mode characteristics for each DMA channel. Each + channel has an internal 6-bit mode register; the high-order + six bits of the associated data byte are written into the + mode register addressed by the two low-order bits. + + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | | + +---+---+---+---+---+---+---+---+ + | | | | | | | | + | | | | | | +---+-- 00 SELECT CHANNEL 0 + | | | | | | 01 SELECT CHANNEL 1 + | | | | | | 10 SELECT CHANNEL 2 + | | | | | | 11 SELECT CHANNEL 3 + | | | | | | + | | | | +---+---------- 00 VERIFY TRANSFER + | | | | 01 WRITE TRANSFER + | | | | 10 READ TRANSFER + | | | | + | | | +------------------ 0 AUTOINITIALIZE DISABLE + | | | 1 AUTOINITIALIZE ENABLE + | | | + | | +---------------------- 0 ADDRESS INCREMENT + | | 1 ADDRESS DECREMENT + | | + +---+-------------------------- 00 DEMAND MODE + 01 SINGLE MODE + 10 BLOCK MODE + + Clear DMAC First/Last Flip-Flop + + The Clear DMAC First/Last Flip-Flop command initializes + the DMAC's internal first/last flip-flop so that the + next byte written to or re~d from the 16-bit address + or word-count registers is the low-order byte. The + flip-flop is toggled with each register access so that + a second register read or write command accesses the + high-order byte. + + DMAC Master Clear + + The DMAC Master Clear command clears the DMAC's command, status, + request, and temporary registers to zero, initializes the + first/last flip-flop, and sets the four channel mask bits in + the mask register to disable all DMA requests (i.e., the DMAC + is placed in an idle state). + + Write DMAC Mask Register + + The Write DMAC Mask Register command allows all four bits of the + DMAC's mask register to be written with a single command. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | X X X X X | + +---+---+---+---+---+---+---+---+ + | | | + | | +-- 0 CLEAR CHANNEL 0 MASK BIT + | | 1 SET CHANNEL 0 MASK BIT + | | + | +---------- 0 CLEAR CHANNEL 2 MASK BIT + | 1 SET CHANNEL 2 MASK BIT + | + +-------------- 0 CLEAR CHANNEL 3 MASK BIT + 1 SET CHANNEL 3 MASK BIT + + Read FDC Status Register + + The Read FDC Status Register command accesses the FDC's main + status register. The individual status register bits are as + follows: + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | | + +---+---+---+---+---+---+---+---+ + | | | | | | | | + | | | | | | | +-- FDD 0 BUSY + | | | | | | +------ FDD 1 BUSY + | | | | | +---------- FDD 2 BUSY + | | | | +-------------- FDD 3 BUSY + | | | +------------------ FDC BUSY + | | +---------------------- NON-DMA MODE + | +-------------------------- DATA INPUT/OUTPUT + +------------------------------ REQUEST FOR MASTER + + Read/Write FDC Data Register + + The Read and Write FDC Data Register commands are used to write + command and parameter bytes to the FDC in order to specify the + operation to be performed (referred to as the "command phase") + and to read status bytes from the FDC following the operation + (referred to as the "result phase"). During the command and + result phases, the 8-bit data register is actually a series of + 8-bit registers in a stack. Each register is accessed in + sequence; the number of registers accessed and the individual + register contents are defined by the specific disk command. + + Write Controller Auxiliary Port + + The Write Controller Auxiliary Port command is used to set or + clear individual bits within the controller's auxiliary port. + The four low-order port bits are dedicated to auxiliary drive + control functions (jumper links are required to connect the + desired port bit to an available pin on the drive interface + connectors). The most common application for these bits is + the "Motor-On" control function for mini-sized drives. + + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | | + +---+---+---+---+---+---+---+---+ + | | | | | | | | + | | | | +---+---+---+-- DRIVE CONTROL + | | | +------------------ ADDR 20 + | | +---------------------- ADDR 21 + | +-------------------------- ADDR 22 + +------------------------------ ADDR 23 + + Poll Interrupt Status + + The Poll Interrupt Status command presents the interrupt + status of the controller and the two interrupt status + lines dedicated to the iSBX Multimodule board. + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | X X X X X | + +---+---+---+---+---+---+---+---+ + | | | + | | +-- CONTROLLER INTERRUPT + | +------ MULTIMODULE BOARD INTERRUPT 0 + +---------- MULTIMODULE BOARD INTERRUPT 1 + + Controller Reset + + The Controller Reset command is the software reset for the + controller. This command clears the controller's auxiliary + port and segment address register, provides a reset signal + to the iSBX Multimodule board and initializes the bus + controller (releases the bus), the DMAC (clears the internal + registers and masks the DREQ inputs), and the FDC (places + the FDC in an idle state and disables the output control + lines to the diskette drive). + + Write Controller Low- And High-Byte Segment Address Registers + + The Write Controller Low- and High-Byte Address Registers + commands are required when the controller uses 20-bit + addressing (memory address range from 0 to OFFFFFH). These + commands are issued prior to initiating a diskette read or + write operation to specify the 16-bit segment address. + + FDC Commands + + The 8272/D765 is capable of performing 15 different + commands. Each command is initiated by a multibyte transfer + from the processor, and the result after execution of the + command may also be a multibyte transfer back to the processor. + Because of this multibyte interchange of information between + the FDC and the processor, it is convenient to consider each + command as consisting of three phases: + + Command Phase: The FDC receives all information required to + perform a particular operation from the processor. + + Execution Phase: The FDC performs the operation it was + instructed to do. + + Result Phase: After completion of the operation, status + and other housekeeping information are made available + to the processor. + + Not all the FDC commands are supported by this emulation. Only the subset + of commands required to build an operable CP/M BIOS are supported. They are: + + Read - Read specified data from the selected FDD. + + Write - Write specified data to the selected FDD. + + Seek - Move the R/W head to the specified cylinder on the specified FDD. + + Specify - Set the characteristics for all the FDDs. + + Sense Interrupt - Sense change in FDD Ready line or end of Seek/Recalibrate + command. + + Sense Drive - Returns status of all the FDDs. + + Recalibrate - Move the R/W head to cylinder 0 on the specified FDD. + + Format Track - Format the current track on the specified FDD. + + Read ID - Reads the first address mark it finds. + + Simulated Floppy Disk Drives + + The units in this device simulate an 8- or 5 1/4- or 3 1/2 inch drives. The + drives can emulate SSSD, SSDD, and DSDD. Drives can be attached to files up + to 1.44MB in size. Drive configuration is selected when a disk is logged onto + the system. An identity sector or identity byte contains information to + configure the OS drivers for the type of drive to emulate. + + uptr->u3 - + uptr->u4 - + uptr->u5 - + uptr->u6 - unit number (0-FDD_NUM) +*/ + +#include "system_defs.h" + +#define UNIT_V_WPMODE (UNIT_V_UF) /* Write protect */ +#define UNIT_WPMODE (1 << UNIT_V_WPMODE) + +/* master status register definitions */ +#define RQM 0x80 /* Request for master */ +#define DIO 0x40 /* Data I/O Direction 0=W, 1=R */ +#define NDM 0x20 /* Non-DMA mode */ +#define CB 0x10 /* FDC busy */ +#define D3B 0x08 /* FDD 3 busy */` +#define D2B 0x04 /* FDD 2 busy */` +#define D1B 0x02 /* FDD 1 busy */` +#define D0B 0x01 /* FDD 0 busy */` + +/* status register 0 definitions */ +#define IC 0xC0 /* Interrupt code */ +#define IC_NORM 0x00 /* normal completion */ +#define IC_ABNORM 0x40 /* abnormal completion */ +#define IC_INVC 0x80 /* invalid command */ +#define IC_RC 0xC0 /* drive not ready */ +#define SE 0x20 /* Seek end */ +#define EC 0x10 /* Equipment check */ +#define NR 0x08 /* Not ready */ +#define HD 0x04 /* Head selected */ +#define US 0x03 /* Unit selected */ +#define US_0 0x00 /* Unit 0 */ +#define US_1 0x01 /* Unit 1 */ +#define US_2 0x02 /* Unit 2 */ +#define US_3 0x03 /* Unit 3 */ + +/* status register 1 definitions */ +#define EN 0x80 /* End of cylinder */ +#define DE 0x20 /* Data error */ +#define OR 0x10 /* Overrun */ +#define ND 0x04 /* No data */ +#define NW 0x02 /* Not writable */ +#define MA 0x01 /* Missing address mark */ + +/* status register 2 definitions */ +#define CM 0x40 /* Control mark */ +#define DD 0x20 /* Data error in data field */ +#define WC 0x10 /* Wrong cylinder */ +#define BC 0x02 /* Bad cylinder */ +#define MD 0x01 /* Missing address mark in data field */ + +/* status register 3/fddst definitions */ +#define FT 0x80 /* Fault */ +#define WP 0x40 /* Write protect */ +#define RDY 0x20 /* Ready */ +#define T0 0x10 /* Track 0 */ +#define TS 0x08 /* Two sided */ +//#define HD 0x04 /* Head selected */ +//#define US 0x03 /* Unit selected */ + +/* FDC command definitions */ +#define READTRK 0x02 +#define SPEC 0x03 +#define SENDRV 0x04 +#define WRITE 0x05 +#define READ 0x06 +#define HOME 0x07 +#define SENINT 0x08 +#define WRITEDEL 0x09 +#define READID 0x0A +#define READDEL 0x0C +#define FMTTRK 0x0D +#define SEEK 0x0F +#define SCANEQ 0x11 +#define SCANLOEQ 0x19 +#define SCANHIEQ 0x1D + +#define FDD_NUM 4 + #define isbc208_NAME "Intel iSBC 208 Floppy Disk Controller Board" -/* internal function prototypes */ - +#define SBC208_INT INT_1 + +/* internal function prototypes */ + t_stat isbc208_cfg(uint16 baseport, uint16 size, uint8 devnum); t_stat isbc208_clr(void); -t_stat isbc208_reset (DEVICE *dptr); -void isbc208_reset1 (void); -t_stat isbc208_attach (UNIT *uptr, const char *cptr); -t_stat isbc208_set_mode (UNIT *uptr, int32 val, const char *cptr, void *desc); -t_stat isbc208_svc (UNIT *uptr); +t_stat isbc208_reset (DEVICE *dptr); +void isbc208_reset1 (void); +t_stat isbc208_attach (UNIT *uptr, const char *cptr); +t_stat isbc208_set_mode (UNIT *uptr, int32 val, const char *cptr, void *desc); +t_stat isbc208_svc (UNIT *uptr); uint8 isbc208_r0(t_bool io, uint8 data, uint8 devnum); uint8 isbc208_r1(t_bool io, uint8 data, uint8 devnum); uint8 isbc208_r2(t_bool io, uint8 data, uint8 devnum); @@ -502,16 +504,16 @@ uint8 isbc208_r12(t_bool io, uint8 data, uint8 devnum); uint8 isbc208_r13(t_bool io, uint8 data, uint8 devnum); uint8 isbc208_r14(t_bool io, uint8 data, uint8 devnum); uint8 isbc208_r15(t_bool io, uint8 data, uint8 devnum); - -/* external function prototypes */ - -extern void set_irq(int32 int_num); -extern void clr_irq(int32 int_num); + +/* external function prototypes */ + +extern void set_irq(int32 int_num); +extern void clr_irq(int32 int_num); extern uint8 reg_dev(uint8 (*routine)(t_bool, uint8, uint8), uint16, uint16, uint8); extern uint8 unreg_dev(uint16); -extern void multibus_put_mbyte(uint16 addr, uint8 val); -extern int32 multibus_get_mbyte(uint16 addr); - +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern int32 multibus_get_mbyte(uint16 addr); + /* external globals */ extern uint16 PCX; @@ -523,167 +525,165 @@ static const char* isbc208_desc(DEVICE *dptr) { return isbc208_NAME; } -/* 8237 physical register definitions */ -uint16 i8237_r0; // 8237 ch 0 address register -uint16 i8237_r1; // 8237 ch 0 count register -uint16 i8237_r2; // 8237 ch 1 address register -uint16 i8237_r3; // 8237 ch 1 count register -uint16 i8237_r4; // 8237 ch 2 address register -uint16 i8237_r5; // 8237 ch 2 count register -uint16 i8237_r6; // 8237 ch 3 address register -uint16 i8237_r7; // 8237 ch 3 count register -uint8 i8237_r8; // 8237 status register -uint8 i8237_r9; // 8237 command register -uint8 i8237_rA; // 8237 mode register -uint8 i8237_rB; // 8237 mask register -uint8 i8237_rC; // 8237 request register -uint8 i8237_rD; // 8237 first/last ff - -/* 8272 physical register definitions */ -/* 8272 command register stack*/ -uint8 i8272_w0; // MT+MFM+SK+command -uint8 i8272_w1; // HDS [HDS=H << 2] + DS1 + DS0 -uint8 i8272_w2; // cylinder # (0-XX) -uint8 i8272_w3; // head # (0 or 1) -uint8 i8272_w4; // sector # (1-XX) -uint8 i8272_w5; // number of bytes (128 << N) -uint8 i8272_w6; // End of track (last sector # on cylinder) -uint8 i8272_w7; // Gap length -uint8 i8272_w8; // Data length (when N=0, size to read or write) - -/* 8272 status register stack */ -uint8 i8272_msr; // main status -uint8 i8272_r0; // ST 0 -uint8 i8272_r1; // ST 1 -uint8 i8272_r2; // ST 2 -uint8 i8272_r3; // ST 3 - -/* iSBC-208 physical register definitions */ -uint16 isbc208_sr; // isbc-208 segment register -uint8 isbc208_i; // iSBC-208 interrupt register -uint8 isbc208_a; // iSBC-208 auxillary port register - -/* data obtained from analyzing command registers/attached file length */ -int32 wsp = 0, rsp = 0; // indexes to write and read stacks (8272 data) -int32 cyl; // current cylinder -int32 hed; // current head [ h << 2] -int32 h; // current head -int32 sec; // current sector -int32 drv; // current drive -uint8 cmd, pcmd; // current command -int32 secn; // N 0-128, 1-256, etc -int32 spt; // sectors per track -int32 ssize; // sector size (128 << N) - -int32 fddst[FDD_NUM] = { // in ST3 format - 0, // status of FDD 0 - 0, // status of FDD 1 - 0, // status of FDD 2 - 0 // status of FDD 3 -}; - -int8 maxcyl[FDD_NUM] = { - 0, // last cylinder + 1 of FDD 0 - 0, // last cylinder + 1 of FDD 1 - 0, // last cylinder + 1 of FDD 2 - 0 // last cylinder + 1 of FDD 3 -}; - -/* isbc208 Standard SIMH Device Data Structures - 4 units */ -UNIT isbc208_unit[] = { - { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 }, - { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 }, - { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 }, - { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 } -}; - -REG isbc208_reg[] = { - { HRDATA (CH0ADR, i8237_r0, 16) }, - { HRDATA (CH0CNT, i8237_r1, 16) }, - { HRDATA (CH1ADR, i8237_r2, 16) }, - { HRDATA (CH1CNT, i8237_r3, 16) }, - { HRDATA (CH2ADR, i8237_r4, 16) }, - { HRDATA (CH2CNT, i8237_r5, 16) }, - { HRDATA (CH3ADR, i8237_r6, 16) }, - { HRDATA (CH3CNT, i8237_r7, 16) }, - { HRDATA (STAT37, i8237_r8, 8) }, - { HRDATA (CMD37, i8237_r9, 8) }, - { HRDATA (MODE, i8237_rA, 8) }, - { HRDATA (MASK, i8237_rB, 8) }, - { HRDATA (REQ, i8237_rC, 8) }, - { HRDATA (FF, i8237_rD, 8) }, - { HRDATA (STAT72, i8272_msr, 8) }, - { HRDATA (STAT720, i8272_r0, 8) }, - { HRDATA (STAT721, i8272_r1, 8) }, - { HRDATA (STAT722, i8272_r2, 8) }, - { HRDATA (STAT723, i8272_r3, 8) }, - { HRDATA (CMD720, i8272_w0, 8) }, - { HRDATA (CMD721, i8272_w1, 8) }, - { HRDATA (CMD722, i8272_w2, 8) }, - { HRDATA (CMD723, i8272_w3, 8) }, - { HRDATA (CMD724, i8272_w4, 8) }, - { HRDATA (CMD725, i8272_w5, 8) }, - { HRDATA (CMD726, i8272_w6, 8) }, - { HRDATA (CMD727, i8272_w7, 8) }, - { HRDATA (CMD728, i8272_w8, 8) }, - { HRDATA (FDD0, fddst[0], 8) }, - { HRDATA (FDD1, fddst[1], 8) }, - { HRDATA (FDD2, fddst[2], 8) }, - { HRDATA (FDD3, fddst[3], 8) }, - { HRDATA (SEGREG, isbc208_sr, 8) }, - { HRDATA (AUX, isbc208_a, 8) }, - { HRDATA (INT, isbc208_i, 8) }, - { NULL } -}; - -MTAB isbc208_mod[] = { - { UNIT_WPMODE, 0, "RW", "RW", &isbc208_set_mode }, - { UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &isbc208_set_mode }, - { 0 } -}; - -DEBTAB isbc208_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { "REG", DEBUG_reg }, - { NULL } -}; - -DEVICE isbc208_dev = { - "SBC208", //name - isbc208_unit, //units - isbc208_reg, //registers - isbc208_mod, //modifiers - FDD_NUM, //numunits - 16, //aradix - 32, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - &isbc208_reset, //reset - NULL, //boot - &isbc208_attach, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags - 0, //dctrl - isbc208_debug, //debflags - NULL, //msize +/* 8237 physical register definitions */ +uint16 i8237_r0; // 8237 ch 0 address register +uint16 i8237_r1; // 8237 ch 0 count register +uint16 i8237_r2; // 8237 ch 1 address register +uint16 i8237_r3; // 8237 ch 1 count register +uint16 i8237_r4; // 8237 ch 2 address register +uint16 i8237_r5; // 8237 ch 2 count register +uint16 i8237_r6; // 8237 ch 3 address register +uint16 i8237_r7; // 8237 ch 3 count register +uint8 i8237_r8; // 8237 status register +uint8 i8237_r9; // 8237 command register +uint8 i8237_rA; // 8237 mode register +uint8 i8237_rB; // 8237 mask register +uint8 i8237_rC; // 8237 request register +uint8 i8237_rD; // 8237 first/last ff + +/* 8272 physical register definitions */ +/* 8272 command register stack*/ +uint8 i8272_w0; // MT+MFM+SK+command +uint8 i8272_w1; // HDS [HDS=H << 2] + DS1 + DS0 +uint8 i8272_w2; // cylinder # (0-XX) +uint8 i8272_w3; // head # (0 or 1) +uint8 i8272_w4; // sector # (1-XX) +uint8 i8272_w5; // number of bytes (128 << N) +uint8 i8272_w6; // End of track (last sector # on cylinder) +uint8 i8272_w7; // Gap length +uint8 i8272_w8; // Data length (when N=0, size to read or write) + +/* 8272 status register stack */ +uint8 i8272_msr; // main status +uint8 i8272_r0; // ST 0 +uint8 i8272_r1; // ST 1 +uint8 i8272_r2; // ST 2 +uint8 i8272_r3; // ST 3 + +/* iSBC-208 physical register definitions */ +uint16 isbc208_sr; // isbc-208 segment register +uint8 isbc208_i; // iSBC-208 interrupt register +uint8 isbc208_a; // iSBC-208 auxillary port register + +/* data obtained from analyzing command registers/attached file length */ +int32 wsp = 0, rsp = 0; // indexes to write and read stacks (8272 data) +int32 cyl; // current cylinder +int32 hed; // current head [ h << 2] +int32 h; // current head +int32 sec; // current sector +int32 drv; // current drive +uint8 cmd, pcmd; // current command +int32 secn; // N 0-128, 1-256, etc +int32 spt; // sectors per track +int32 ssize; // sector size (128 << N) + +int32 fddst[FDD_NUM] = { // in ST3 format + 0, // status of FDD 0 + 0, // status of FDD 1 + 0, // status of FDD 2 + 0 // status of FDD 3 +}; + +int8 maxcyl[FDD_NUM] = { + 0, // last cylinder + 1 of FDD 0 + 0, // last cylinder + 1 of FDD 1 + 0, // last cylinder + 1 of FDD 2 + 0 // last cylinder + 1 of FDD 3 +}; + +/* isbc208 Standard SIMH Device Data Structures - 4 units */ +UNIT isbc208_unit[] = { + { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 }, + { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 }, + { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 }, + { UDATA (&isbc208_svc, UNIT_ATTABLE|UNIT_DISABLE|UNIT_BUFABLE|UNIT_MUSTBUF|UNIT_FIX, 368640), 20 } +}; + +REG isbc208_reg[] = { + { HRDATA (CH0ADR, i8237_r0, 16) }, + { HRDATA (CH0CNT, i8237_r1, 16) }, + { HRDATA (CH1ADR, i8237_r2, 16) }, + { HRDATA (CH1CNT, i8237_r3, 16) }, + { HRDATA (CH2ADR, i8237_r4, 16) }, + { HRDATA (CH2CNT, i8237_r5, 16) }, + { HRDATA (CH3ADR, i8237_r6, 16) }, + { HRDATA (CH3CNT, i8237_r7, 16) }, + { HRDATA (STAT37, i8237_r8, 8) }, + { HRDATA (CMD37, i8237_r9, 8) }, + { HRDATA (MODE, i8237_rA, 8) }, + { HRDATA (MASK, i8237_rB, 8) }, + { HRDATA (REQ, i8237_rC, 8) }, + { HRDATA (FF, i8237_rD, 8) }, + { HRDATA (STAT72, i8272_msr, 8) }, + { HRDATA (STAT720, i8272_r0, 8) }, + { HRDATA (STAT721, i8272_r1, 8) }, + { HRDATA (STAT722, i8272_r2, 8) }, + { HRDATA (STAT723, i8272_r3, 8) }, + { HRDATA (CMD720, i8272_w0, 8) }, + { HRDATA (CMD721, i8272_w1, 8) }, + { HRDATA (CMD722, i8272_w2, 8) }, + { HRDATA (CMD723, i8272_w3, 8) }, + { HRDATA (CMD724, i8272_w4, 8) }, + { HRDATA (CMD725, i8272_w5, 8) }, + { HRDATA (CMD726, i8272_w6, 8) }, + { HRDATA (CMD727, i8272_w7, 8) }, + { HRDATA (CMD728, i8272_w8, 8) }, + { HRDATA (FDD0, fddst[0], 8) }, + { HRDATA (FDD1, fddst[1], 8) }, + { HRDATA (FDD2, fddst[2], 8) }, + { HRDATA (FDD3, fddst[3], 8) }, + { HRDATA (SEGREG, isbc208_sr, 8) }, + { HRDATA (AUX, isbc208_a, 8) }, + { HRDATA (INT, isbc208_i, 8) }, + { NULL } +}; + +MTAB isbc208_mod[] = { + { UNIT_WPMODE, 0, "RW", "RW", &isbc208_set_mode }, + { UNIT_WPMODE, UNIT_WPMODE, "WP", "WP", &isbc208_set_mode }, + { 0 } +}; + +DEBTAB isbc208_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { NULL } +}; + +DEVICE isbc208_dev = { + "SBC208", //name + isbc208_unit, //units + isbc208_reg, //registers + isbc208_mod, //modifiers + FDD_NUM, //numunits + 16, //aradix + 32, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + &isbc208_reset, //reset + NULL, //boot + &isbc208_attach, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags + 0, //dctrl + isbc208_debug, //debflags + NULL, //msize NULL, //lname NULL, //help routine NULL, //attach help routine NULL, //help context &isbc208_desc //device description -}; - -/* Service routines to handle simulator functions */ - +}; + +/* Service routines to handle simulator functions */ + // configuration routine t_stat isbc208_cfg(uint16 baseport, uint16 devnum, uint8 intnum) @@ -742,16 +742,16 @@ t_stat isbc208_clr(void) return SCPE_OK; } -/* Reset routine */ - -t_stat isbc208_reset (DEVICE *dptr) -{ +/* Reset routine */ + +t_stat isbc208_reset (DEVICE *dptr) +{ isbc208_reset1(); return SCPE_OK; -} - -void isbc208_reset1 (void) -{ +} + +void isbc208_reset1 (void) +{ int32 i; UNIT *uptr; @@ -777,12 +777,12 @@ void isbc208_reset1 (void) i8272_msr = RQM; /* 8272 ready for start of command */ // sim_printf(" 8237 Reset\n"); // sim_printf(" 8272 Reset\n"); -} - -/* isbc208 attach - attach an .IMG file to a FDD */ - -t_stat isbc208_attach (UNIT *uptr, const char *cptr) -{ +} + +/* isbc208 attach - attach an .IMG file to a FDD */ + +t_stat isbc208_attach (UNIT *uptr, const char *cptr) +{ t_stat r; int32 c = 0; long len; @@ -822,51 +822,51 @@ t_stat isbc208_attach (UNIT *uptr, const char *cptr) sim_activate (&isbc208_unit[fddnum], isbc208_unit[fddnum].wait); // sim_printf( " iSBC208_attach: Done\n"); return SCPE_OK; -} - -/* isbc208 set mode = WP or RW */ - -t_stat isbc208_set_mode (UNIT *uptr, int32 val, const char *cptr, void *desc) -{ +} + +/* isbc208 set mode = WP or RW */ + +t_stat isbc208_set_mode (UNIT *uptr, int32 val, const char *cptr, void *desc) +{ if (uptr->flags & UNIT_ATT) return sim_messagef (SCPE_ALATT, "%s is already attached to %s\n", sim_uname(uptr), uptr->filename); - if (val & UNIT_WPMODE) { /* write protect */ - fddst[uptr->u6] |= WP; - uptr->flags |= val; - } else { /* read write */ - fddst[uptr->u6] &= ~WP; - uptr->flags &= ~val; - } - return SCPE_OK; -} - -/* service routine - actually does the simulated disk I/O */ - -t_stat isbc208_svc (UNIT *uptr) -{ - int32 i, imgadr, data; - int32 bpt, bpc; + if (val & UNIT_WPMODE) { /* write protect */ + fddst[uptr->u6] |= WP; + uptr->flags |= val; + } else { /* read write */ + fddst[uptr->u6] &= ~WP; + uptr->flags &= ~val; + } + return SCPE_OK; +} + +/* service routine - actually does the simulated disk I/O */ + +t_stat isbc208_svc (UNIT *uptr) +{ + int32 i, imgadr, data; + int32 bpt, bpc; uint8 *fbuf; - - if ((i8272_msr & CB) && cmd && (uptr->u6 == drv)) { /* execution phase */ + + if ((i8272_msr & CB) && cmd && (uptr->u6 == drv)) { /* execution phase */ fbuf = (uint8 *) uptr->filebuf; - switch (cmd) { - case READ: /* 0x06 */ - h = i8272_w3; // h = 0 or 1 - hed = i8272_w3 << 2; // hed = 0 or 4 [h << 2] - sec = i8272_w4; // sector number (1-XX) - secn = i8272_w5; // N (0-5) - spt = i8272_w6; // sectors/track - ssize = 128 << secn; // size of sector (bytes) - bpt = ssize * spt; // bytes/track - bpc = bpt * 2; // bytes/cylinder -// sim_printf("208 Read: FDD=%d h=%d s=%d t=%d n=%d secsiz=%d spt=%d PCX=%04X\n", -// drv, h, sec, cyl, secn, ssize, spt, PCX); - if ((fddst[uptr->u6] & RDY) == 0) { // drive not ready - i8272_r0 = IC_ABNORM | NR | hed | drv; /* command done - Not ready error*/ - i8272_r3 = fddst[uptr->u6]; - i8272_msr |= (RQM | DIO | CB); /* enter result phase */ - } else { // get image addr for this d, h, c, s + switch (cmd) { + case READ: /* 0x06 */ + h = i8272_w3; // h = 0 or 1 + hed = i8272_w3 << 2; // hed = 0 or 4 [h << 2] + sec = i8272_w4; // sector number (1-XX) + secn = i8272_w5; // N (0-5) + spt = i8272_w6; // sectors/track + ssize = 128 << secn; // size of sector (bytes) + bpt = ssize * spt; // bytes/track + bpc = bpt * 2; // bytes/cylinder + sim_printf("208 Read: FDD=%d h=%d s=%d t=%d n=%d secsiz=%d spt=%d PCX=%04X\n", + drv, h, sec, cyl, secn, ssize, spt, PCX); + if ((fddst[uptr->u6] & RDY) == 0) { // drive not ready + i8272_r0 = IC_ABNORM | NR | hed | drv; /* command done - Not ready error*/ + i8272_r3 = fddst[uptr->u6]; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } else { // get image addr for this d, h, c, s if (fddst[uptr->u6] & TS) imgadr = (cyl * bpc) /*+ (h * bpt)*/ + ((sec - 1) * ssize); else { @@ -875,52 +875,52 @@ t_stat isbc208_svc (UNIT *uptr) data = *(fbuf + (imgadr + i)); multibus_put_mbyte(i8237_r0 + i, data); } -//*** need to step return results IAW table 3-11 in 143078-001 - i8272_w4 = ++sec; /* next sector */ - i8272_r0 = hed | drv; /* command done - no error */ - i8272_r3 = fddst[uptr->u6]; - } - i8272_r1 = 0; - i8272_r2 = 0; - i8272_w2 = cyl; /* generate a current address mark */ - i8272_w3 = h; - if (i8272_w4 > i8272_w6) { // beyond last sector of track? - i8272_w4 = 1; // yes, set to sector 1; - if (h) { // on head one? - i8272_w2++; // yes, step cylinder - h = 0; // back to head 0 - } - } - } - i8272_w5 = secn; - i8272_msr |= (RQM | DIO | CB); /* enter result phase */ - rsp = wsp = 0; /* reset indexes */ - set_irq(SBC208_INT); /* set interrupt */ - break; - case WRITE: /* 0x05 */ - h = i8272_w3; // h = 0 or 1 - hed = i8272_w3 << 2; // hed = 0 or 4 [h << 2] - sec = i8272_w4; // sector number (1-XX) - secn = i8272_w5; // N (0-5) - spt = i8272_w6; // sectors/track - ssize = 128 << secn; // size of sector (bytes) - bpt = ssize * spt; // bytes/track - bpc = bpt * 2; // bytes/cylinder - i8272_r1 = 0; // clear ST1 - i8272_r2 = 0; // clear ST2 -// sim_printf("208 Read: FDD=%d h=%d s=%d t=%d n=%d secsiz=%d spt=%d PCX=%04X\n", -// drv, h, sec, cyl, secn, ssize, spt, PCX); - if ((fddst[uptr->u6] & RDY) == 0) { - i8272_r0 = IC_ABNORM | NR | hed | drv; /* Not ready error*/ - i8272_r3 = fddst[uptr->u6]; - i8272_msr |= (RQM | DIO | CB); /* enter result phase */ - } else if (fddst[uptr->u6] & WP) { - i8272_r0 = IC_ABNORM | hed | drv; /* write protect error*/ - i8272_r1 = NW; // set not writable in ST1 - i8272_r3 = fddst[uptr->u6] | WP; - i8272_msr |= (RQM | DIO | CB); /* enter result phase */ - sim_printf("\nWrite Protected fddst[%d]=%02X\n", uptr->u6, fddst[uptr->u6]); - } else { // get image addr for this d, h, c, s +//*** need to step return results IAW table 3-11 in 143078-001 + i8272_w4 = ++sec; /* next sector */ + i8272_r0 = hed | drv; /* command done - no error */ + i8272_r3 = fddst[uptr->u6]; + } + i8272_r1 = 0; + i8272_r2 = 0; + i8272_w2 = cyl; /* generate a current address mark */ + i8272_w3 = h; + if (i8272_w4 > i8272_w6) { // beyond last sector of track? + i8272_w4 = 1; // yes, set to sector 1; + if (h) { // on head one? + i8272_w2++; // yes, step cylinder + h = 0; // back to head 0 + } + } + } + i8272_w5 = secn; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + rsp = wsp = 0; /* reset indexes */ + set_irq(SBC208_INT); /* set interrupt */ + break; + case WRITE: /* 0x05 */ + h = i8272_w3; // h = 0 or 1 + hed = i8272_w3 << 2; // hed = 0 or 4 [h << 2] + sec = i8272_w4; // sector number (1-XX) + secn = i8272_w5; // N (0-5) + spt = i8272_w6; // sectors/track + ssize = 128 << secn; // size of sector (bytes) + bpt = ssize * spt; // bytes/track + bpc = bpt * 2; // bytes/cylinder + i8272_r1 = 0; // clear ST1 + i8272_r2 = 0; // clear ST2 +// sim_printf("208 Read: FDD=%d h=%d s=%d t=%d n=%d secsiz=%d spt=%d PCX=%04X\n", +// drv, h, sec, cyl, secn, ssize, spt, PCX); + if ((fddst[uptr->u6] & RDY) == 0) { + i8272_r0 = IC_ABNORM | NR | hed | drv; /* Not ready error*/ + i8272_r3 = fddst[uptr->u6]; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } else if (fddst[uptr->u6] & WP) { + i8272_r0 = IC_ABNORM | hed | drv; /* write protect error*/ + i8272_r1 = NW; // set not writable in ST1 + i8272_r3 = fddst[uptr->u6] | WP; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + sim_printf("\nWrite Protected fddst[%d]=%02X\n", uptr->u6, fddst[uptr->u6]); + } else { // get image addr for this d, h, c, s if (fddst[uptr->u6] == TS) imgadr = (cyl * bpc) /*+ (h * bpt)*/ + ((sec - 1) * ssize); else { @@ -929,590 +929,590 @@ t_stat isbc208_svc (UNIT *uptr) data = multibus_get_mbyte(i8237_r0 + i); *(fbuf + (imgadr + i)) = data; } - //*** quick fix. Needs more thought! - /* - fp = fopen(uptr->filename, "wb"); // write out modified image - for (i=0; icapac; i++) { - c = *(isbc208_buf[uptr->u6] + i) & 0xFF; - fputc(c, fp); - } - fclose(fp); - */ -//*** need to step return results IAW table 3-11 in 143078-001 - } - i8272_w2 = cyl; /* generate a current address mark */ - i8272_w3 = hed >> 2; - i8272_w4 = ++sec; /* next sector */ - i8272_w5 = secn; - i8272_r0 = hed | drv; /* command done - no error */ - i8272_r3 = fddst[uptr->u6]; - i8272_msr |= (RQM | DIO | CB); /* enter result phase */ - } - rsp = wsp = 0; /* reset indexes */ - set_irq(SBC208_INT); /* set interrupt */ - break; - case FMTTRK: /* 0x0D */ - if ((fddst[uptr->u6] & RDY) == 0) { - i8272_r0 = IC_ABNORM | NR | hed | drv; /* Not ready error*/ - i8272_msr |= (RQM | DIO | CB); /* enter result phase */ - } else if (fddst[uptr->u6] & WP) { - i8272_r0 = IC_ABNORM | hed | drv; /* write protect error*/ - i8272_r3 = fddst[uptr->u6] | WP; - i8272_msr |= (RQM | DIO | CB); /* enter result phase */ - } else { - ; /* do nothing for now */ - i8272_msr |= (RQM | DIO | CB); /* enter result phase */ - } - rsp = wsp = 0; /* reset indexes */ - set_irq(SBC208_INT); /* set interrupt */ - break; - case SENINT: /* 0x08 */ - i8272_msr |= (RQM | DIO | CB); /* enter result phase */ - i8272_r0 = hed | drv; /* command done - no error */ - i8272_r1 = 0; - i8272_r2 = 0; - rsp = wsp = 0; /* reset indexes */ - clr_irq(SBC208_INT); /* clear interrupt */ - break; - case SENDRV: /* 0x04 */ - i8272_msr |= (RQM | DIO | CB); /* enter result phase */ - i8272_r0 = hed | drv; /* command done - no error */ - i8272_r1 = 0; - i8272_r2 = 0; - i8272_r3 = fddst[drv]; /* drv status */ - rsp = wsp = 0; /* reset indexes */ - break; - case HOME: /* 0x07 */ - if ((fddst[uptr->u6] & RDY) == 0) { - i8272_r0 = IC_ABNORM | NR | hed | drv; /* Not ready error*/ - i8272_r3 = fddst[uptr->u6]; - } else { - cyl = 0; /* now on cylinder 0 */ - fddst[drv] |= T0; /* set status flag */ - i8272_r0 = SE | hed | drv; /* seek end - no error */ - } - i8272_r1 = 0; - i8272_r2 = 0; - i8272_msr &= ~(RQM | DIO | CB | hed | drv); /* execution phase done*/ - i8272_msr |= RQM; /* enter COMMAND phase */ - rsp = wsp = 0; /* reset indexes */ - set_irq(SBC208_INT); /* set interrupt */ - break; - case SPEC: /* 0x03 */ - fddst[0] |= TS; //*** bad, bad, bad! - fddst[1] |= TS; - fddst[2] |= TS; - fddst[3] |= TS; - i8272_r0 = hed | drv; /* command done - no error */ - i8272_r1 = 0; - i8272_r2 = 0; - i8272_msr &= ~(RQM | DIO | CB); /* execution phase done*/ -// i8272_msr = 0; // force 0 for now, where does 0x07 come from? - i8272_msr |= RQM; /* enter command phase */ - rsp = wsp = 0; /* reset indexes */ - break; - case READID: /* 0x0A */ - if ((fddst[uptr->u6] & RDY) == 0) { - i8272_r0 = IC_RC | NR | hed | drv; /* Not ready error*/ - i8272_r3 = fddst[uptr->u6]; - } else { - i8272_w2 = cyl; /* generate a valid address mark */ - i8272_w3 = hed >> 2; - i8272_w4 = 1; /* always sector 1 */ - i8272_w5 = secn; - i8272_r0 = hed | drv; /* command done - no error */ - i8272_msr &= ~(RQM | DIO | CB); /* execution phase done*/ - i8272_msr |= RQM; /* enter command phase */ - } - i8272_r1 = 0; - i8272_r2 = 0; - rsp = wsp = 0; /* reset indexes */ - break; - case SEEK: /* 0x0F */ - if ((fddst[uptr->u6] & RDY) == 0) { /* Not ready? */ - i8272_r0 = IC_ABNORM | NR | hed | drv; /* error*/ - i8272_r3 = fddst[uptr->u6]; - } else if (i8272_w2 >= maxcyl[uptr->u6]) { // too many steps - i8272_r0 = IC_ABNORM | RDY | hed | drv; /* seek error*/ - } else { -// i8272_r0 |= SE | hed | drv; /* command done - no error */ - i8272_r0 = SE | hed | drv; /* command done - no error */ - cyl = i8272_w2; /* new cylinder number */ - if (cyl == 0) { /* if cyl 0, set flag */ - fddst[drv] |= T0; /* set T0 status flag */ - i8272_r3 |= T0; - } else { - fddst[drv] &= ~T0; /* clear T0 status flag */ - i8272_r3 &= ~T0; - } - } - i8272_r1 = 0; - i8272_r2 = 0; - i8272_msr &= ~(RQM | DIO | CB | hed | drv); /* execution phase done*/ - i8272_msr |= RQM; /* enter command phase */ - rsp = wsp = 0; /* reset indexes */ - set_irq(SBC208_INT); /* set interrupt */ - break; - default: - i8272_msr &= ~(RQM | DIO | CB); /* execution phase done*/ - i8272_msr |= RQM; /* enter command phase */ - i8272_r0 = IC_INVC | hed | drv; /* set bad command error */ - i8272_r1 = 0; - i8272_r2 = 0; - rsp = wsp = 0; /* reset indexes */ - break; - } - pcmd = cmd; /* save for result phase */ - cmd = 0; /* reset command */ - } - sim_activate (&isbc208_unit[uptr->u6], isbc208_unit[uptr->u6].wait); - return SCPE_OK; -} - -// read/write FDC data register stack -uint8 isbc208_r11(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read FDC data register */ -// sim_printf("208 R11: Read data=%02X pcmd=%02X rsp=%d PCX=%04X\nA", data, pcmd, rsp, PCX); - wsp = 0; /* clear write stack index */ - switch (rsp) { /* read from next stack register */ - case 0: - rsp++; /* step read stack index */ - clr_irq(SBC208_INT); /* clear interrupt */ - if (pcmd == SENDRV) { - i8272_msr = RQM; /* result phase SENDRV done */ - return i8272_r1; // SENDRV return ST1 - } - return i8272_r0; /* ST0 */ - case 1: - rsp++; /* step read stack index */ - if (pcmd == SENINT) { - i8272_msr = RQM; /* result phase SENINT done */ - return cyl; // SENINT return current cylinder - } - return i8272_r1; /* ST1 */ - case 2: - rsp++; /* step read stack index */ - return i8272_r2; /* ST2 */ - case 3: - rsp++; /* step read stack index */ - return i8272_w2; /* C - cylinder */ - case 4: - rsp++; /* step read stack index */ - return i8272_w3; /* H - head */ - case 5: - rsp++; /* step read stack index */ - return i8272_w4; /* R - sector */ - case 6: - i8272_msr = RQM; /* result phase ALL OTHERS done */ - return i8272_w5; /* N - sector size*/ - } - } else { /* write FDC data register */ -// sim_printf("208 R11: Write data=%02X cmd=%02X wsp=%d PCX=%04X\nA", data, cmd, wsp, PCX); - rsp = 0; /* clear read stack index */ - switch (wsp) { /* write to next stack register */ - case 0: - i8272_w0 = data; /* rws = MT + MFM + SK + cmd */ - cmd = data & 0x1F; /* save the current command */ - if (cmd == SENINT) { - i8272_msr = CB; /* command phase SENINT done */ - return 0; - } - wsp++; /* step write stack index */ - break; - case 1: - i8272_w1 = data; /* rws = hed + drv */ - if (cmd != SPEC) - drv = data & 0x03; - if (cmd == HOME || cmd == SENDRV || cmd == READID) { - i8272_msr = CB | hed | drv; /* command phase HOME, READID and SENDRV done */ - return 0; - } - wsp++; /* step write stack index */ - break; - case 2: - i8272_w2 = data; /* rws = C */ - if (cmd == SPEC || cmd == SEEK) { - i8272_msr = CB | hed | drv; /* command phase SPECIFY and SEEK done */ - return 0; - } - wsp++; /* step write stack index */ - break; - case 3: - i8272_w3 = data; /* rw = H */ - hed = data; - wsp++; /* step write stack index */ - break; - case 4: - i8272_w4 = data; /* rw = R */ - sec = data; - wsp++; /* step write stack index */ - break; - case 5: - i8272_w5 = data; /* rw = N */ - if (cmd == FMTTRK) { - i8272_msr = CB | hed | drv; /* command phase FMTTRK done */ - return 0; - } - wsp++; /* step write stack index */ - break; - case 6: - i8272_w6 = data; /* rw = last sector number */ - wsp++; /* step write stack index */ - break; - case 7: - i8272_w7 = data; /* rw = gap length */ - wsp++; /* step write stack index */ - break; - case 8: - i8272_w8 = data; /* rw = bytes to transfer */ - if (cmd == READ || cmd == WRITE) - i8272_msr = CB | hed | drv; /* command phase all others done */ - break; - } - } - return 0; -} - - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. - - Each function is passed an 'io' flag, where 0 means a read from - the port, and 1 means a write to the port. On input, the actual - input is passed as the return value, on output, 'data' is written - to the device. -*/ - -uint8 isbc208_r0(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - return (i8237_r0 >> 8); - } else { /* low byte */ - i8237_rD++; - return (i8237_r0 & 0xFF); - } - } else { /* write baseport & current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r0 |= (data << 8); - } else { /* low byte */ - i8237_rD++; - i8237_r0 = data & 0xFF; - } - return 0; - } -} - -uint8 isbc208_r1(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read current word count CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - return (i8237_r1 >> 8); - } else { /* low byte */ - i8237_rD++; - return (i8237_r1 & 0xFF); - } - } else { /* write baseport & current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r1 |= (data << 8); - } else { /* low byte */ - i8237_rD++; - i8237_r1 = data & 0xFF; - } - return 0; - } -} - -uint8 isbc208_r2(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - return (i8237_r2 >> 8); - } else { /* low byte */ - i8237_rD++; - return (i8237_r2 & 0xFF); - } - } else { /* write baseport & current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r2 |= (data << 8); - } else { /* low byte */ - i8237_rD++; - i8237_r2 = data & 0xFF; - } - return 0; - } -} - -uint8 isbc208_r3(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read current word count CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - return (i8237_r3 >> 8); - } else { /* low byte */ - i8237_rD++; - return (i8237_r3 & 0xFF); - } - } else { /* write baseport & current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r3 |= (data << 8); - } else { /* low byte */ - i8237_rD++; - i8237_r3 = data & 0xFF; - } - return 0; - } -} - -uint8 isbc208_r4(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read current address CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - return (i8237_r4 >> 8); - } else { /* low byte */ - i8237_rD++; - return (i8237_r4 & 0xFF); - } - } else { /* write baseport & current address CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r4 |= (data << 8); - } else { /* low byte */ - i8237_rD++; - i8237_r4 = data & 0xFF; - } - return 0; - } -} - -uint8 isbc208_r5(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read current word count CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - return (i8237_r5 >> 8); - } else { /* low byte */ - i8237_rD++; - return (i8237_r5 & 0xFF); - } - } else { /* write baseport & current address CH 2 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r5 |= (data << 8); - } else { /* low byte */ - i8237_rD++; - i8237_r5 = data & 0xFF; - } - return 0; - } -} - -uint8 isbc208_r6(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read current address CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - return (i8237_r6 >> 8); - } else { /* low byte */ - i8237_rD++; - return (i8237_r6 & 0xFF); - } - } else { /* write baseport & current address CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r6 |= (data << 8); - } else { /* low byte */ - i8237_rD++; - i8237_r6 = data & 0xFF; - } - return 0; - } -} - -uint8 isbc208_r7(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read current word count CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - return (i8237_r7 >> 8); - } else { /* low byte */ - i8237_rD++; - return (i8237_r7 & 0xFF); - } - } else { /* write baseport & current address CH 3 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r7 |= (data << 8); - } else { /* low byte */ - i8237_rD++; - i8237_r7 = data & 0xFF; - } - return 0; - } -} - -uint8 isbc208_r8(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read status register */ - return (i8237_r8); - } else { /* write command register */ - i8237_r9 = data & 0xFF; - return 0; - } -} - -uint8 isbc208_r9(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { - return 0; - } else { /* write request register */ - i8237_rC = data & 0xFF; - return 0; - } -} - -uint8 isbc208_rA(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { - return 0; - } else { /* write single mask register */ - switch(data & 0x03) { - case 0: - if (data & 0x04) - i8237_rB |= 1; - else - i8237_rB &= ~1; - break; - case 1: - if (data & 0x04) - i8237_rB |= 2; - else - i8237_rB &= ~2; - break; - case 2: - if (data & 0x04) - i8237_rB |= 4; - else - i8237_rB &= ~4; - break; - case 3: - if (data & 0x04) - i8237_rB |= 8; - else - i8237_rB &= ~8; - break; - } - return 0; - } -} - -uint8 isbc208_rB(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { - return 0; - } else { /* write mode register */ - i8237_rA = data & 0xFF; - return 0; - } -} - -uint8 isbc208_rC(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { - return 0; - } else { /* clear byte pointer FF */ - i8237_rD = 0; - return 0; - } -} - -uint8 isbc208_rD(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read temporary register */ - return 0; - } else { /* master clear */ - isbc208_reset1(); - return 0; - } -} - -uint8 isbc208_rE(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { - return 0; - } else { /* clear mask register */ - i8237_rB = 0; - return 0; - } -} - -uint8 isbc208_rF(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { - return 0; - } else { /* write all mask register bits */ - i8237_rB = data & 0x0F; - return 0; - } -} - -uint8 isbc208_r10(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read FDC status register */ -// sim_printf("FDC Status=%02X PCX=%04X\n", i8272_msr, PCX); - return i8272_msr; - } else { - return 0; - } -} - -uint8 isbc208_r12(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { /* read interrupt status */ - return (isbc208_i); - } else { /* write controller auxillary port */ - isbc208_a = data & 0xFF; - return 0; - } -} - -uint8 isbc208_r13(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { - return 0; - } else { /* reset controller */ - isbc208_reset1(); - return 0; - } -} - -uint8 isbc208_r14(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { - return 0; - } else { /* Low-Byte Segment Address Register */ - isbc208_sr = data & 0xFF; - return 0; - } -} - -uint8 isbc208_r15(t_bool io, uint8 data, uint8 devnum) -{ - if (io == 0) { - return 0; - } else { /* High-Byte Segment Address Register */ - isbc208_sr |= data << 8; - return 0; - } -} + //*** quick fix. Needs more thought! + /* + fp = fopen(uptr->filename, "wb"); // write out modified image + for (i=0; icapac; i++) { + c = *(isbc208_buf[uptr->u6] + i) & BYTEMASK; + fputc(c, fp); + } + fclose(fp); + */ +//*** need to step return results IAW table 3-11 in 143078-001 + } + i8272_w2 = cyl; /* generate a current address mark */ + i8272_w3 = hed >> 2; + i8272_w4 = ++sec; /* next sector */ + i8272_w5 = secn; + i8272_r0 = hed | drv; /* command done - no error */ + i8272_r3 = fddst[uptr->u6]; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } + rsp = wsp = 0; /* reset indexes */ + set_irq(SBC208_INT); /* set interrupt */ + break; + case FMTTRK: /* 0x0D */ + if ((fddst[uptr->u6] & RDY) == 0) { + i8272_r0 = IC_ABNORM | NR | hed | drv; /* Not ready error*/ + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } else if (fddst[uptr->u6] & WP) { + i8272_r0 = IC_ABNORM | hed | drv; /* write protect error*/ + i8272_r3 = fddst[uptr->u6] | WP; + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } else { + ; /* do nothing for now */ + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + } + rsp = wsp = 0; /* reset indexes */ + set_irq(SBC208_INT); /* set interrupt */ + break; + case SENINT: /* 0x08 */ + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + i8272_r0 = hed | drv; /* command done - no error */ + i8272_r1 = 0; + i8272_r2 = 0; + rsp = wsp = 0; /* reset indexes */ + clr_irq(SBC208_INT); /* clear interrupt */ + break; + case SENDRV: /* 0x04 */ + i8272_msr |= (RQM | DIO | CB); /* enter result phase */ + i8272_r0 = hed | drv; /* command done - no error */ + i8272_r1 = 0; + i8272_r2 = 0; + i8272_r3 = fddst[drv]; /* drv status */ + rsp = wsp = 0; /* reset indexes */ + break; + case HOME: /* 0x07 */ + if ((fddst[uptr->u6] & RDY) == 0) { + i8272_r0 = IC_ABNORM | NR | hed | drv; /* Not ready error*/ + i8272_r3 = fddst[uptr->u6]; + } else { + cyl = 0; /* now on cylinder 0 */ + fddst[drv] |= T0; /* set status flag */ + i8272_r0 = SE | hed | drv; /* seek end - no error */ + } + i8272_r1 = 0; + i8272_r2 = 0; + i8272_msr &= ~(RQM | DIO | CB | hed | drv); /* execution phase done*/ + i8272_msr |= RQM; /* enter COMMAND phase */ + rsp = wsp = 0; /* reset indexes */ + set_irq(SBC208_INT); /* set interrupt */ + break; + case SPEC: /* 0x03 */ + fddst[0] |= TS; //*** bad, bad, bad! + fddst[1] |= TS; + fddst[2] |= TS; + fddst[3] |= TS; + i8272_r0 = hed | drv; /* command done - no error */ + i8272_r1 = 0; + i8272_r2 = 0; + i8272_msr &= ~(RQM | DIO | CB); /* execution phase done*/ +// i8272_msr = 0; // force 0 for now, where does 0x07 come from? + i8272_msr |= RQM; /* enter command phase */ + rsp = wsp = 0; /* reset indexes */ + break; + case READID: /* 0x0A */ + if ((fddst[uptr->u6] & RDY) == 0) { + i8272_r0 = IC_RC | NR | hed | drv; /* Not ready error*/ + i8272_r3 = fddst[uptr->u6]; + } else { + i8272_w2 = cyl; /* generate a valid address mark */ + i8272_w3 = hed >> 2; + i8272_w4 = 1; /* always sector 1 */ + i8272_w5 = secn; + i8272_r0 = hed | drv; /* command done - no error */ + i8272_msr &= ~(RQM | DIO | CB); /* execution phase done*/ + i8272_msr |= RQM; /* enter command phase */ + } + i8272_r1 = 0; + i8272_r2 = 0; + rsp = wsp = 0; /* reset indexes */ + break; + case SEEK: /* 0x0F */ + if ((fddst[uptr->u6] & RDY) == 0) { /* Not ready? */ + i8272_r0 = IC_ABNORM | NR | hed | drv; /* error*/ + i8272_r3 = fddst[uptr->u6]; + } else if (i8272_w2 >= maxcyl[uptr->u6]) { // too many steps + i8272_r0 = IC_ABNORM | RDY | hed | drv; /* seek error*/ + } else { +// i8272_r0 |= SE | hed | drv; /* command done - no error */ + i8272_r0 = SE | hed | drv; /* command done - no error */ + cyl = i8272_w2; /* new cylinder number */ + if (cyl == 0) { /* if cyl 0, set flag */ + fddst[drv] |= T0; /* set T0 status flag */ + i8272_r3 |= T0; + } else { + fddst[drv] &= ~T0; /* clear T0 status flag */ + i8272_r3 &= ~T0; + } + } + i8272_r1 = 0; + i8272_r2 = 0; + i8272_msr &= ~(RQM | DIO | CB | hed | drv); /* execution phase done*/ + i8272_msr |= RQM; /* enter command phase */ + rsp = wsp = 0; /* reset indexes */ + set_irq(SBC208_INT); /* set interrupt */ + break; + default: + i8272_msr &= ~(RQM | DIO | CB); /* execution phase done*/ + i8272_msr |= RQM; /* enter command phase */ + i8272_r0 = IC_INVC | hed | drv; /* set bad command error */ + i8272_r1 = 0; + i8272_r2 = 0; + rsp = wsp = 0; /* reset indexes */ + break; + } + pcmd = cmd; /* save for result phase */ + cmd = 0; /* reset command */ + } + sim_activate (&isbc208_unit[uptr->u6], isbc208_unit[uptr->u6].wait); + return SCPE_OK; +} + +// read/write FDC data register stack +uint8 isbc208_r11(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read FDC data register */ +// sim_printf("208 R11: Read data=%02X pcmd=%02X rsp=%d PCX=%04X\nA", data, pcmd, rsp, PCX); + wsp = 0; /* clear write stack index */ + switch (rsp) { /* read from next stack register */ + case 0: + rsp++; /* step read stack index */ + clr_irq(SBC208_INT); /* clear interrupt */ + if (pcmd == SENDRV) { + i8272_msr = RQM; /* result phase SENDRV done */ + return i8272_r1; // SENDRV return ST1 + } + return i8272_r0; /* ST0 */ + case 1: + rsp++; /* step read stack index */ + if (pcmd == SENINT) { + i8272_msr = RQM; /* result phase SENINT done */ + return cyl; // SENINT return current cylinder + } + return i8272_r1; /* ST1 */ + case 2: + rsp++; /* step read stack index */ + return i8272_r2; /* ST2 */ + case 3: + rsp++; /* step read stack index */ + return i8272_w2; /* C - cylinder */ + case 4: + rsp++; /* step read stack index */ + return i8272_w3; /* H - head */ + case 5: + rsp++; /* step read stack index */ + return i8272_w4; /* R - sector */ + case 6: + i8272_msr = RQM; /* result phase ALL OTHERS done */ + return i8272_w5; /* N - sector size*/ + } + } else { /* write FDC data register */ +// sim_printf("208 R11: Write data=%02X cmd=%02X wsp=%d PCX=%04X\nA", data, cmd, wsp, PCX); + rsp = 0; /* clear read stack index */ + switch (wsp) { /* write to next stack register */ + case 0: + i8272_w0 = data; /* rws = MT + MFM + SK + cmd */ + cmd = data & 0x1F; /* save the current command */ + if (cmd == SENINT) { + i8272_msr = CB; /* command phase SENINT done */ + return 0; + } + wsp++; /* step write stack index */ + break; + case 1: + i8272_w1 = data; /* rws = hed + drv */ + if (cmd != SPEC) + drv = data & 0x03; + if (cmd == HOME || cmd == SENDRV || cmd == READID) { + i8272_msr = CB | hed | drv; /* command phase HOME, READID and SENDRV done */ + return 0; + } + wsp++; /* step write stack index */ + break; + case 2: + i8272_w2 = data; /* rws = C */ + if (cmd == SPEC || cmd == SEEK) { + i8272_msr = CB | hed | drv; /* command phase SPECIFY and SEEK done */ + return 0; + } + wsp++; /* step write stack index */ + break; + case 3: + i8272_w3 = data; /* rw = H */ + hed = data; + wsp++; /* step write stack index */ + break; + case 4: + i8272_w4 = data; /* rw = R */ + sec = data; + wsp++; /* step write stack index */ + break; + case 5: + i8272_w5 = data; /* rw = N */ + if (cmd == FMTTRK) { + i8272_msr = CB | hed | drv; /* command phase FMTTRK done */ + return 0; + } + wsp++; /* step write stack index */ + break; + case 6: + i8272_w6 = data; /* rw = last sector number */ + wsp++; /* step write stack index */ + break; + case 7: + i8272_w7 = data; /* rw = gap length */ + wsp++; /* step write stack index */ + break; + case 8: + i8272_w8 = data; /* rw = bytes to transfer */ + if (cmd == READ || cmd == WRITE) + i8272_msr = CB | hed | drv; /* command phase all others done */ + break; + } + } + return 0; +} + + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. + + Each function is passed an 'io' flag, where 0 means a read from + the port, and 1 means a write to the port. On input, the actual + input is passed as the return value, on output, 'data' is written + to the device. +*/ + +uint8 isbc208_r0(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r0 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r0 & BYTEMASK); + } + } else { /* write baseport & current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r0 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r0 = data & BYTEMASK; + } + return 0; + } +} + +uint8 isbc208_r1(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current word count CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r1 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r1 & BYTEMASK); + } + } else { /* write baseport & current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r1 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r1 = data & BYTEMASK; + } + return 0; + } +} + +uint8 isbc208_r2(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current address CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r2 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r2 & BYTEMASK); + } + } else { /* write baseport & current address CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r2 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r2 = data & BYTEMASK; + } + return 0; + } +} + +uint8 isbc208_r3(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current word count CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r3 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r3 & BYTEMASK); + } + } else { /* write baseport & current address CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r3 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r3 = data & BYTEMASK; + } + return 0; + } +} + +uint8 isbc208_r4(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current address CH 2 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r4 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r4 & BYTEMASK); + } + } else { /* write baseport & current address CH 2 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r4 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r4 = data & BYTEMASK; + } + return 0; + } +} + +uint8 isbc208_r5(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current word count CH 2 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r5 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r5 & BYTEMASK); + } + } else { /* write baseport & current address CH 2 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r5 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r5 = data & BYTEMASK; + } + return 0; + } +} + +uint8 isbc208_r6(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current address CH 3 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r6 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r6 & BYTEMASK); + } + } else { /* write baseport & current address CH 3 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r6 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r6 = data & BYTEMASK; + } + return 0; + } +} + +uint8 isbc208_r7(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read current word count CH 3 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + return (i8237_r7 >> 8); + } else { /* low byte */ + i8237_rD++; + return (i8237_r7 & BYTEMASK); + } + } else { /* write baseport & current address CH 3 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r7 |= (data << 8); + } else { /* low byte */ + i8237_rD++; + i8237_r7 = data & BYTEMASK; + } + return 0; + } +} + +uint8 isbc208_r8(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read status register */ + return (i8237_r8); + } else { /* write command register */ + i8237_r9 = data & BYTEMASK; + return 0; + } +} + +uint8 isbc208_r9(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* write request register */ + i8237_rC = data & BYTEMASK; + return 0; + } +} + +uint8 isbc208_rA(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* write single mask register */ + switch(data & 0x03) { + case 0: + if (data & 0x04) + i8237_rB |= 1; + else + i8237_rB &= ~1; + break; + case 1: + if (data & 0x04) + i8237_rB |= 2; + else + i8237_rB &= ~2; + break; + case 2: + if (data & 0x04) + i8237_rB |= 4; + else + i8237_rB &= ~4; + break; + case 3: + if (data & 0x04) + i8237_rB |= 8; + else + i8237_rB &= ~8; + break; + } + return 0; + } +} + +uint8 isbc208_rB(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* write mode register */ + i8237_rA = data & BYTEMASK; + return 0; + } +} + +uint8 isbc208_rC(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* clear byte pointer FF */ + i8237_rD = 0; + return 0; + } +} + +uint8 isbc208_rD(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read temporary register */ + return 0; + } else { /* master clear */ + isbc208_reset1(); + return 0; + } +} + +uint8 isbc208_rE(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* clear mask register */ + i8237_rB = 0; + return 0; + } +} + +uint8 isbc208_rF(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* write all mask register bits */ + i8237_rB = data & 0x0F; + return 0; + } +} + +uint8 isbc208_r10(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read FDC status register */ +// sim_printf("FDC Status=%02X PCX=%04X\n", i8272_msr, PCX); + return i8272_msr; + } else { + return 0; + } +} + +uint8 isbc208_r12(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { /* read interrupt status */ + return (isbc208_i); + } else { /* write controller auxillary port */ + isbc208_a = data & BYTEMASK; + return 0; + } +} + +uint8 isbc208_r13(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* reset controller */ + isbc208_reset1(); + return 0; + } +} + +uint8 isbc208_r14(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* Low-Byte Segment Address Register */ + isbc208_sr = data & BYTEMASK; + return 0; + } +} + +uint8 isbc208_r15(t_bool io, uint8 data, uint8 devnum) +{ + if (io == 0) { + return 0; + } else { /* High-Byte Segment Address Register */ + isbc208_sr |= data << 8; + return 0; + } +} /* end of isbc208.c */ \ No newline at end of file diff --git a/Intel-Systems/common/isbc464.c b/Intel-Systems/common/isbc464.c index b0f010d5..26db982a 100644 --- a/Intel-Systems/common/isbc464.c +++ b/Intel-Systems/common/isbc464.c @@ -76,7 +76,7 @@ MTAB isbc464_mod[] = { { MTAB_XTD | MTAB_VDV, 0, NULL, "BASE", &isbc464_set_base, NULL, NULL, "Sets the ROM base for iSBC464" }, { MTAB_XTD|MTAB_VDV, 0, "PARAM", NULL, NULL, &isbc464_show_param, NULL, - "Parameter" }, + "show configured parameters for SBC 464" }, { 0 } }; @@ -86,8 +86,6 @@ DEBTAB isbc464_debug[] = { { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, { NULL } }; @@ -231,8 +229,8 @@ t_stat isbc464_reset (DEVICE *dptr) if (dptr == NULL) return SCPE_ARG; if (isbc464_onetime) { - isbc464_dev.units->capac = SBC464_SIZE; //set default size - isbc464_dev.units->BASE_ADDR = SBC464_BASE; //set default base +// isbc464_dev.units->capac = SBC464_SIZE; //set default size +// isbc464_dev.units->BASE_ADDR = SBC464_BASE; //set default base isbc464_onetime = 0; } if ((dptr->flags & DEV_DIS) == 0) { //already enabled @@ -246,7 +244,7 @@ t_stat isbc464_reset (DEVICE *dptr) } else { //disabled if (isbc464_dev.units->filebuf) free(isbc464_dev.units->filebuf); //return allocated memory - sim_printf(" sbc464: Disabled\n"); +// sim_printf(" sbc464: Disabled\n"); } return SCPE_OK; } @@ -272,7 +270,7 @@ uint8 isbc464_get_mbyte(uint16 addr) uint8 val; val = *((uint8 *)isbc464_unit.filebuf + (addr - isbc464_unit.BASE_ADDR)); - return (val & 0xFF); + return (val & BYTEMASK); } /* end of isbc464.c */ diff --git a/Intel-Systems/common/mem.c b/Intel-Systems/common/mem.c index 6f121f0f..7d199c61 100644 --- a/Intel-Systems/common/mem.c +++ b/Intel-Systems/common/mem.c @@ -56,7 +56,8 @@ extern uint8 xack; /* XACK signal */ extern UNIT i8255_unit; //for isbc memory control extern UNIT ipc_cont_unit; extern UNIT ioc_cont_unit; -extern uint8 i8255_C[4]; //port C byte I/O +extern uint8 i8255_C[4]; //port C byte I/O + /* get a byte from memory - handle MODEL, RAM, ROM and Multibus memory */ @@ -65,7 +66,7 @@ uint8 get_mbyte(uint16 addr) uint8 val; SET_XACK(0); /* clear xack */ - if ((mem_map <= 1) && (addr >= 0xF800)) { //monitor ROM - always there IPB/IPC + if ((mem_map <= 1) && (addr >= 0xF800)) { //monitor ROM - always there IPB/IPC/800 SET_XACK(1); //set xack return EPROM_get_mbyte(addr - 0xF000, 0); //top half of EPROM } @@ -86,10 +87,16 @@ uint8 get_mbyte(uint16 addr) return RAM_get_mbyte(addr); } if (mem_map == 2) { //800 - if (((monitor_boot & 0x04) == 0) && (addr >= EPROM_unit[0].u3) && (addr <= (EPROM_unit[0].u3 + EPROM_unit[0].capac))) - return EPROM_get_mbyte(addr, 0); - else if ((addr >= EPROM_unit[1].u3) && (addr <= (EPROM_unit[1].u3 + EPROM_unit[1].capac))) + SET_XACK(1); //set xack + if ((addr >= EPROM_unit[0].u3) && (addr <= (EPROM_unit[0].u3 + EPROM_unit[0].capac))) { + if ((monitor_boot & 0x02) == 0) + return EPROM_get_mbyte(addr, 0); + else + return multibus_get_mbyte(addr); + } + if ((addr >= EPROM_unit[1].u3) && (addr <= (EPROM_unit[1].u3 + EPROM_unit[1].capac))) { return EPROM_get_mbyte(addr, 1); + } } if (mem_map == 3) { //isdk80 if ((addr >= EPROM_unit->u3) && ((uint16)addr <= (EPROM_unit->u3 + EPROM_unit->capac))) { @@ -133,14 +140,18 @@ uint16 get_mword(uint16 addr) void put_mbyte(uint16 addr, uint8 val) { - SET_XACK(0); /* set no XACK */ - if (addr >= 0xF800) { //monitor ROM - always there IPB/IPC/800 +/* put a byte to memory - handle RAM, ROM, I/O, and pcbus memory */ + SET_XACK(0); /* clear xack */ + if ((mem_map <= 1) && (addr >= 0xF800)) { //monitor ROM - always there IPB/IPC/800 + SET_XACK(1); //set xack return; //do nothing } if ((mem_map <= 1) && (addr < 0x1000) && ((ipc_cont_unit.u3 & 0x04) == 0)) { //startup IPB/IPC + SET_XACK(1); //set xack return; //do nothing } if ((mem_map <= 1) && (addr >= 0xE800) && (addr < 0xF000) && ((ipc_cont_unit.u3 & 0x10) == 0)) { //diagnostic ROM IPB/IPC + SET_XACK(1); //set xack return; //do nothing } if (mem_map == 1) { //IPC RAM @@ -186,7 +197,7 @@ void put_mbyte(uint16 addr, uint8 val) void put_mword(uint16 addr, uint16 val) { - put_mbyte(addr, val & 0xff); + put_mbyte(addr, val & BYTEMASK); put_mbyte(addr+1, val >> 8); } diff --git a/Intel-Systems/common/multibus.c b/Intel-Systems/common/multibus.c index b77626f6..fe022fba 100644 --- a/Intel-Systems/common/multibus.c +++ b/Intel-Systems/common/multibus.c @@ -34,7 +34,6 @@ #include "system_defs.h" -#define BASE_ADDR u3 #define multibus_NAME "Intel Multibus Interface" /* function prototypes */ @@ -81,8 +80,7 @@ DEBTAB multibus_debug[] = { { "FLOW", DEBUG_flow }, { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, + { "XACK", DEBUG_xack }, { NULL } }; @@ -122,7 +120,7 @@ DEVICE multibus_dev = { t_stat multibus_reset(DEVICE *dptr) { // if (SBC_reset(NULL) == 0) { - sim_printf(" Multibus: Reset\n"); +// sim_printf(" Multibus: Reset\n"); sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */ return SCPE_OK; // } else { @@ -145,15 +143,15 @@ uint8 multibus_get_mbyte(uint16 addr) { SET_XACK(0); /* set no XACK */ if ((isbc464_dev.flags & DEV_DIS) == 0) { //ROM is enabled - if (addr >= isbc464_dev.units->BASE_ADDR && - addr < (isbc464_dev.units->BASE_ADDR + isbc464_dev.units->capac)) { + if (addr >= isbc464_dev.units->u3 && + addr < (isbc464_dev.units->u3 + isbc464_dev.units->capac)) { SET_XACK(1); //set xack return(isbc464_get_mbyte(addr)); } } if ((isbc064_dev.flags & DEV_DIS) == 0) { //iSBC 064 is enabled - if (addr >= isbc064_dev.units->BASE_ADDR && - addr < (isbc064_dev.units->BASE_ADDR + isbc064_dev.units->capac)) { + if (addr >= isbc064_dev.units->u3 && + addr < (isbc064_dev.units->u3 + isbc064_dev.units->capac)) { SET_XACK(1); //set xack return (isbc064_get_mbyte(addr)); } @@ -165,8 +163,8 @@ void multibus_put_mbyte(uint16 addr, uint8 val) { SET_XACK(0); /* set no XACK */ if ((isbc064_dev.flags & DEV_DIS) == 0) { //device is enabled - if (addr >= isbc064_dev.units->BASE_ADDR && - addr < (isbc064_dev.units->BASE_ADDR + isbc064_dev.units->capac)) { + if (addr >= isbc064_dev.units->u3 && + addr < (isbc064_dev.units->u3 + isbc064_dev.units->capac)) { SET_XACK(1); //set xack isbc064_put_mbyte(addr, val); } diff --git a/Intel-Systems/common/port.c b/Intel-Systems/common/port.c index fa9bb8c6..939db106 100644 --- a/Intel-Systems/common/port.c +++ b/Intel-Systems/common/port.c @@ -74,8 +74,7 @@ DEBTAB port_debug[] = { { "FLOW", DEBUG_flow }, { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, + { "XACK", DEBUG_xack }, { NULL } }; @@ -115,7 +114,7 @@ DEVICE port_dev = { t_stat port_reset(DEVICE *dptr) { // if (SBC_reset(NULL) == 0) { - sim_printf(" Port: Reset\n"); +// sim_printf(" Port: Reset\n"); sim_activate (&port_unit, port_unit.wait); /* activate unit */ return SCPE_OK; // } else { diff --git a/Intel-Systems/common/sys.c b/Intel-Systems/common/sys.c index daf6fee0..79b394aa 100644 --- a/Intel-Systems/common/sys.c +++ b/Intel-Systems/common/sys.c @@ -76,6 +76,10 @@ #define SYS_80204 11 #define SYS_8024 12 #define SYS_8030 13 +#define SYS_8010_0 14 +#define SYS_8010_1 15 +#define SYS_8010_2 16 +#define SYS_8010_3 17 #define sys_name "Intel MDS Configuration Controller" @@ -107,6 +111,9 @@ extern t_stat EPROM_cfg(uint16 base, uint16 size, uint8 devnum); extern t_stat RAM_cfg(uint16 base, uint16 size, uint8 dummy); extern t_stat isbc064_cfg(uint16 base, uint16 size, uint8 dummy); extern t_stat isbc464_cfg(uint16 base, uint16 size, uint8 dummy); +extern t_stat isbc201_cfg(uint16 base, uint16 size, uint8 dummy); +extern t_stat isbc202_cfg(uint16 base, uint16 size, uint8 dummy); +extern t_stat isbc208_cfg(uint16 base, uint16 size, uint8 dummy); extern t_stat i3214_clr(void); extern t_stat i8251_clr(void); extern t_stat i8253_clr(void); @@ -118,12 +125,15 @@ extern t_stat EPROM_clr(void); extern t_stat RAM_clr(void); extern t_stat isbc064_clr(void); extern t_stat isbc464_clr(void); +extern t_stat isbc201_clr(void); +extern t_stat isbc202_clr(void); +extern t_stat isbc208_clr(void); extern void clr_dev(void); /* globals */ int model = -1; //force no model -int mem_map = 0; //memory model +int mem_map = 0; //memory model typedef struct device { int id; @@ -142,123 +152,154 @@ typedef struct system_model { SYS_DEV devices[30]; } SYS_MODEL; -#define SYS_NUM 15 +#define SYS_NUM 18 SYS_MODEL models[SYS_NUM+1] = { {MDS_210, "MDS-210 ", 9, // id name num arg routine routine1 val1 val2 val3 - {{ i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, - { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xF0 }, + {{ IOC_CONT, "IOC-CONT", 1, 1, ioc_cont_cfg, ioc_cont_clr, 0xC0 }, { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xF0 }, + { i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, { i8259, "I8259", 2, 1, i8259_cfg, i8259_clr, 0xFA, 0xFC }, - { IOC_CONT, "IOC-CONT", 1, 1, ioc_cont_cfg, ioc_cont_clr, 0xC0 }, { IPC_CONT, "IPC-CONT", 1, 1, ipc_cont_cfg, ipc_cont_clr, 0xFF }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x0FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x0000, 0x7FFF }, { SBC464, "SBC464", 1, 2, isbc464_cfg, isbc464_clr, 0xA800, 0x47FF }}, }, {MDS_220, "MDS-220 ", 8, - {{ i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, - { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xF0 }, + {{ IOC_CONT, "IOC-CONT", 1, 1, ioc_cont_cfg, ioc_cont_clr, 0xC0 }, { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xF0 }, + { i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, { i8259, "I8259", 2, 1, i8259_cfg, i8259_clr, 0xFA, 0xFC }, - { IOC_CONT, "IOC-CONT", 1, 1, ioc_cont_cfg, ioc_cont_clr, 0xC0 }, { IPC_CONT, "IPC-CONT", 1, 1, ipc_cont_cfg, ipc_cont_clr, 0xFF }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x0FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x0000, 0x7FFF }} }, {MDS_225, "MDS-225 ", 8, - {{ i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, - { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xF0 }, + {{ IOC_CONT, "IOC-CONT", 1, 1, ioc_cont_cfg, ioc_cont_clr, 0xC0 }, { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xF0 }, + { i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, { i8259, "I8259", 2, 1, i8259_cfg, i8259_clr, 0xFA, 0xFC }, - { IOC_CONT, "IOC-CONT", 1, 1, ioc_cont_cfg, ioc_cont_clr, 0xC0 }, { IPC_CONT, "IPC-CONT", 1, 1, ipc_cont_cfg, ipc_cont_clr, 0xFF }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x0FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x0000, 0xFFFF }}, }, {MDS_230, "MDS-230 ", 9, - {{ i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, - { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xF0 }, + {{ IOC_CONT, "IOC-CONT", 1, 1, ioc_cont_cfg, ioc_cont_clr, 0xC0 }, { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xF0 }, + { i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, { i8259, "I8259", 2, 1, i8259_cfg, i8259_clr, 0xFA, 0xFC }, - { IOC_CONT, "IOC-CONT", 1, 1, ioc_cont_cfg, ioc_cont_clr, 0xC0 }, { IPC_CONT, "IPC-CONT", 1, 1, ipc_cont_cfg, ipc_cont_clr, 0xFF }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x0FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x0000, 0x7FFF }, { SBC064, "SBC064", 1, 2, isbc064_cfg, isbc064_clr, 0x8000, 0x7FFF }}, }, {MDS_800, "MDS-800 ", 5, - {{ i3214, "I3214", 1, 1, i3214_cfg, i3214_clr, 0xFC }, - { i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, + {{ i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, + { i3214, "I3214", 1, 1, i3214_cfg, i3214_clr, 0xFC }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x00FF }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0xF800, 0x07FF }, - { SBC064, "SBC064", 1, 2, isbc064_cfg, isbc064_clr, 0x0000, 0x7FFF }}, + { SBC064, "SBC064", 1, 2, isbc064_cfg, isbc064_clr, 0x0000, 0xFFFF }}, }, {MDS_810, "MDS-810 ", 6, - {{ i3214, "I3214", 1, 1, i3214_cfg, i3214_clr, 0xFC }, - { i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, + {{ i8251, "I8251", 2, 1, i8251_cfg, i8251_clr, 0xF4, 0xF6 }, + { i3214, "I3214", 1, 1, i3214_cfg, i3214_clr, 0xFC }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x00FF }, { EPROM, "EPROM2", 1, 2, EPROM_cfg, EPROM_clr, 0xF800, 0x07FF }, { SBC064, "SBC064", 1, 2, isbc064_cfg, isbc064_clr, 0x0000, 0x7FFF }, { SBC464, "SBC464", 1, 2, isbc464_cfg, isbc464_clr, 0xA800, 0x47FF }}, }, {SDK_80, "SDK-80 ", 4, - {{ i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xFA }, - { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xF4, 0xEC }, + {{ i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xEC, 0xF4 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xFA }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x0FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x1000, 0x03FF }}, }, {SYS_8010, "SYS-80/10 ", 4, - {{ i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, - { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + {{ i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x0FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x3c00, 0x03FF }}, }, {SYS_8010A, "SYS-80/10A ", 4, - {{ i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, - { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + {{ i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x1FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x3c00, 0x03FF }}, }, {SYS_8010B, "SYS-80/10B ", 4, - {{ i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, - { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, - { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x3FFF }, + {{ i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, + { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x1FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x3c00, 0x03FF }}, }, {SYS_8020, "SYS-80/20 ", 6, - {{ i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, + {{ i8259, "I8259", 1, 1, i8259_cfg, i8259_clr, 0xDA }, { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xDC }, - { i8255, "I8255", 1, 1, i8255_cfg, i8255_clr, 0xE8 }, - { i8259, "I8259", 1, 1, i8259_cfg, i8259_clr, 0xDA }, + { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x1FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x3800, 0x07FF }}, }, - {SYS_8020-4, "SYS-80/20-4", 6, - {{ i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, + {SYS_80204, "SYS-80/20-4 ", 6, + {{ i8259, "I8259", 1, 1, i8259_cfg, i8259_clr, 0xDA }, { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xDC }, - { i8255, "I8255", 1, 1, i8255_cfg, i8255_clr, 0xE8 }, - { i8259, "I8259", 1, 1, i8259_cfg, i8259_clr, 0xDA }, + { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x1FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x3000, 0x0FFF }}, }, {SYS_8024, "SYS-80/24 ", 6, - {{ i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, + {{ i8259, "I8259", 1, 1, i8259_cfg, i8259_clr, 0xDA }, { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xDC }, - { i8255, "I8255", 1, 1, i8255_cfg, i8255_clr, 0xE8 }, - { i8259, "I8259", 1, 1, i8259_cfg, i8259_clr, 0xDA }, + { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE8 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x1FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x3c00, 0x03FF }}, }, {SYS_8030, "SYS-80/30 ", 6, - {{ i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, + {{ i8259, "I8259", 1, 1, i8259_cfg, i8259_clr, 0xDA }, { i8253, "I8253", 1, 1, i8253_cfg, i8253_clr, 0xDC }, - { i8255, "I8255", 1, 1, i8255_cfg, i8255_clr, 0xE8 }, - { i8259, "I8259", 1, 1, i8259_cfg, i8259_clr, 0xDA }, + { i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE8 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x1FFF }, { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x2000, 0x3FFF }}, }, + {SYS_8010_0, "SYS-80/10-0", 5, + {{ i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, + { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x0FFF }, + { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x3c00, 0x03FF }, + { SBC064, "SBC064", 1, 2, isbc064_cfg, isbc064_clr, 0x0000, 0xFFFF }}, + }, + {SYS_8010_1, "SYS-80/10-1", 6, + {{ i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, + { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x0FFF }, + { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x3c00, 0x03FF }, + { SBC064, "SBC064", 1, 2, isbc064_cfg, isbc064_clr, 0x0000, 0xFFFF }, + { SBC201, "SBC201", 1, 1, isbc201_cfg, isbc201_clr, 0x78 }}, + }, + {SYS_8010_2, "SYS-80/10-2", 6, + {{ i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, + { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x0FFF }, + { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x3c00, 0x03FF }, + { SBC064, "SBC064", 1, 2, isbc064_cfg, isbc064_clr, 0x0000, 0xFFFF }, + { SBC202, "SBC202", 1, 1, isbc202_cfg, isbc202_clr, 0x78 }}, + }, + {SYS_8010_3, "SYS-80/10-3 ", 6, + {{ i8255, "I8255", 2, 1, i8255_cfg, i8255_clr, 0xE4, 0xE8 }, + { i8251, "I8251", 1, 1, i8251_cfg, i8251_clr, 0xEC }, + { EPROM, "EPROM", 1, 2, EPROM_cfg, EPROM_clr, 0x0000, 0x0FFF }, + { RAM, "RAM", 1, 2, RAM_cfg, RAM_clr, 0x3c00, 0x03FF }, + { SBC064, "SBC064", 1, 2, isbc064_cfg, isbc064_clr, 0x0000, 0xFFFF }, + { SBC208, "SBC208", 1, 1, isbc208_cfg, isbc208_clr, 0x40 }}, + }, {0} }; @@ -282,8 +323,6 @@ DEBTAB sys_debug[] = { { "READ", DEBUG_read }, { "WRITE", DEBUG_write }, { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, { NULL } }; @@ -328,7 +367,7 @@ t_stat sys_cfg(uint16 base, uint16 devnum, uint8 dummy) DEVICE *dptr; if (model == (-1)) return SCPE_ARG; //no valid config - sim_printf("sys_cfg: Configure %s:\n", models[model].name); + sim_printf("sys_cfg: Configuring an %s:\n", models[model].name); switch (model) { //set memory map type case 0: //mds-210 mem_map = 0; //ipb @@ -372,6 +411,18 @@ t_stat sys_cfg(uint16 base, uint16 devnum, uint8 dummy) case 13: //sys-8030 mem_map = 4; //sys-8030 break; + case 14: //sys-8010-0 + mem_map = 4; //sys-8010-0 + break; + case 15: //sys-8010-1 + mem_map = 4; //sys-8010-1 + break; + case 16: //sys-8010-2 + mem_map = 4; //sys-8010-2 + break; + case 17: //sys-8010-3 + mem_map = 4; //sys-8010-3 + break; default: return SCPE_ARG; } @@ -391,13 +442,14 @@ t_stat sys_cfg(uint16 base, uint16 devnum, uint8 dummy) break; case 3: //three arguments models[model].devices[i].cfg_routine (models[model].devices[i].val[j], - models[model].devices[i].val[j+1], models[model].devices[i].val[j+1] & 0xff); + models[model].devices[i].val[j+1], models[model].devices[i].val[j+1] & BYTEMASK); break; default: return SCPE_ARG; } } } + //reset_all (0); return SCPE_OK; } @@ -428,7 +480,7 @@ t_stat sys_reset(DEVICE *dptr) { if (dptr == NULL) return SCPE_ARG; - sim_printf("SYS Reset\n"); +// sim_printf("SYS Reset\n"); sys_cfg(0, 0, 0); return SCPE_OK; } @@ -447,7 +499,7 @@ t_stat sys_set_model (UNIT *uptr, int32 val, CONST char *cptr, void *desc) if (!strncmp(cptr, models[i].name, strlen(cptr))) { //find the system model = models[i].id; strncpy(sim_name, models[i].name, 11); - printf("sys_set_model: Configuring %s\n", sim_name); + printf("sys_set_model: Configuring an %s\n", sim_name); switch (model) { //set memory map type case 0: //mds-210 mem_map = 0; //ipb @@ -491,6 +543,18 @@ t_stat sys_set_model (UNIT *uptr, int32 val, CONST char *cptr, void *desc) case 13: //sys-8030 mem_map = 4; //sys-8030 break; + case 14: //sys-8010-0 + mem_map = 4; //sys-8010-0 + break; + case 15: //sys-8010-1 + mem_map = 4; //sys-8010-1 + break; + case 16: //sys-8010-2 + mem_map = 4; //sys-8010-2 + break; + case 17: //sys-8010-3 + mem_map = 4; //sys-8010-3 + break; default: return SCPE_ARG; } @@ -510,13 +574,14 @@ t_stat sys_set_model (UNIT *uptr, int32 val, CONST char *cptr, void *desc) break; case 3: //three arguments models[model].devices[i].cfg_routine (models[model].devices[i].val[j], - models[model].devices[i].val[j+1], models[model].devices[i].val[j+1] & 0xff); + models[model].devices[i].val[j+1], models[model].devices[i].val[j+1] & BYTEMASK); break; default: return SCPE_ARG; } } } + reset_all (0); return SCPE_OK; } } @@ -530,12 +595,11 @@ t_stat sys_show_model (FILE *st, UNIT *uptr, int32 val, CONST void *desc) if (uptr == NULL) return SCPE_ARG; - return SCPE_OK; - fprintf(st, "%s: %d\n", models[model].name, models[model].num); + fprintf(st, "%s:%d devices\n", models[model].name, models[model].num); for (i=0; i> 4; uptr = zx200a_dev.units + fddnum; fbuf = (uint8 *) uptr->filebuf; + if (zx200a.verb) + sim_printf("\n zx200a: FDD %d - nr=%02XH ta=%02XH sa=%02XH IOPB=%04XH PCX=%04XH", + fddnum, nr, ta, sa, zx200a.iopb, PCX); //check for not ready switch(fddnum) { case 0: if ((zx200a.DDstat & RDY0) == 0) { zx200a.rtype = ROK; zx200a.rbyte0 = RB0NR; - zx200a.intff = 1; //set interrupt FF + zx200a.intff = 1; //set interrupt FF sim_printf("\n zx200a: Ready error on drive %d", fddnum); return; } @@ -711,7 +723,7 @@ void zx200a_diskio(void) if ((zx200a.DDstat & RDY1) == 0) { zx200a.rtype = ROK; zx200a.rbyte0 = RB0NR; - zx200a.intff = 1; //set interrupt FF + zx200a.intff = 1; //set interrupt FF sim_printf("\n zx200a: Ready error on drive %d", fddnum); return; } @@ -720,7 +732,7 @@ void zx200a_diskio(void) if ((zx200a.DDstat & RDY2) == 0) { zx200a.rtype = ROK; zx200a.rbyte0 = RB0NR; - zx200a.intff = 1; //set interrupt FF + zx200a.intff = 1; //set interrupt FF sim_printf("\n zx200a: Ready error on drive %d", fddnum); return; } @@ -729,7 +741,7 @@ void zx200a_diskio(void) if ((zx200a.DDstat & RDY3) == 0) { zx200a.rtype = ROK; zx200a.rbyte0 = RB0NR; - zx200a.intff = 1; //set interrupt FF + zx200a.intff = 1; //set interrupt FF sim_printf("\n zx200a: Ready error on drive %d", fddnum); return; } @@ -738,7 +750,7 @@ void zx200a_diskio(void) if ((zx200a.SDstat & RDY0) == 0) { zx200a.rtype = ROK; zx200a.rbyte0 = RB0NR; - zx200a.intff = 1; //set interrupt FF + zx200a.intff = 1; //set interrupt FF sim_printf("\n zx200a: Ready error on drive %d", fddnum); return; } @@ -747,7 +759,7 @@ void zx200a_diskio(void) if ((zx200a.SDstat & RDY1) == 0) { zx200a.rtype = ROK; zx200a.rbyte0 = RB0NR; - zx200a.intff = 1; //set interrupt FF + zx200a.intff = 1; //set interrupt FF sim_printf("\n zx200a: Ready error on drive %d", fddnum); return; } @@ -764,7 +776,7 @@ void zx200a_diskio(void) )) { zx200a.rtype = ROK; zx200a.rbyte0 = RB0ADR; - zx200a.intff = 1; //set interrupt FF + zx200a.intff = 1; //set interrupt FF sim_printf("\n ZX200A: FDD %d - Address error sa=%02X nr=%02X ta=%02X PCX=%04X", fddnum, sa, nr, ta, PCX); return; @@ -779,7 +791,7 @@ void zx200a_diskio(void) )) { zx200a.rtype = ROK; zx200a.rbyte0 = RB0ADR; - zx200a.intff = 1; //set interrupt FF + zx200a.intff = 1; //set interrupt FF sim_printf("\n ZX200A: FDD %d - Address error sa=%02X nr=%02X ta=%02X PCX=%04X", fddnum, sa, nr, ta, PCX); return; @@ -815,11 +827,11 @@ void zx200a_diskio(void) if(uptr->flags & UNIT_WPMODE) { zx200a.rtype = ROK; zx200a.rbyte0 = RB0WP; - zx200a.intff = 1; //set interrupt FF + zx200a.intff = 1; //set interrupt FF sim_printf("\n zx200a: Write protect error 1 on drive %d", fddnum); return; } - fmtb = get_mbyte(ba); //get the format byte + fmtb = get_mbyte(ba); //get the format byte if (zx200a.fdd[fddnum].dd == 1) { //calculate offset into DD disk image dskoff = ((ta * MAXSECDD) + (sa - 1)) * 128; diff --git a/Visual Studio Projects/Intel-MDS.vcproj b/Visual Studio Projects/Intel-MDS.vcproj index ea3e5354..aecf932d 100644 --- a/Visual Studio Projects/Intel-MDS.vcproj +++ b/Visual Studio Projects/Intel-MDS.vcproj @@ -95,6 +95,8 @@ />