diff --git a/IBMPC-Systems/ibmpc/ibmpc_sys.c b/IBMPC-Systems/ibmpc/ibmpc_sys.c index df51ce62..a5a1c1e1 100644 --- a/IBMPC-Systems/ibmpc/ibmpc_sys.c +++ b/IBMPC-Systems/ibmpc/ibmpc_sys.c @@ -1,97 +1,97 @@ -/* ibmpcxt_sys.c: IBM 5160 simulator - - Copyright (c) 2016, 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. - - 11 Jul 16 - Original file. -*/ - -#include "system_defs.h" - -extern DEVICE i8088_dev; -extern REG i8088_reg[]; -extern DEVICE i8237_dev; -extern DEVICE i8253_dev; -extern DEVICE i8255_dev; -extern DEVICE i8259_dev; -extern DEVICE EPROM_dev; -extern DEVICE RAM_dev; -extern DEVICE xtbus_dev; - -/* bit patterns to manipulate 8-bit ports */ - -#define i82XX_bit_0 0x01 //bit 0 of a port -#define i82XX_bit_1 0x02 //bit 1 of a port -#define i82XX_bit_2 0x04 //bit 2 of a port -#define i82XX_bit_3 0x08 //bit 3 of a port -#define i82XX_bit_4 0x10 //bit 4 of a port -#define i82XX_bit_5 0x20 //bit 5 of a port -#define i82XX_bit_6 0x40 //bit 6 of a port -#define i82XX_bit_7 0x80 //bit 7 of a port - -#define i82XX_nbit_0 ~i8255_bit_0 //bit 0 of a port -#define i82XX_nbit_1 ~i8255_bit_1 //bit 1 of a port -#define i82XX_nbit_2 ~i8255_bit_3 //bit 2 of a port -#define i82XX_nbit_3 ~i8255_bit_3 //bit 3 of a port -#define i82XX_nbit_4 ~i8255_bit_4 //bit 4 of a port -#define i82XX_nbit_5 ~i8255_bit_5 //bit 5 of a port -#define i82XX_nbit_6 ~i8255_bit_6 //bit 6 of a port -#define i82XX_nbit_7 ~i8255_bit_7 //bit 7 of a port - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages -*/ - -char sim_name[] = "IBM PC"; - -REG *sim_PC = &i8088_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &i8088_dev, - &EPROM_dev, - &RAM_dev, - &i8237_dev, - &i8253_dev, - &i8255_dev, - &i8259_dev, - &xtbus_dev, - NULL -}; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode", - "Invalid Memory", - "XACK Error" -}; - +/* ibmpcxt_sys.c: IBM 5160 simulator + + Copyright (c) 2016, 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. + + 11 Jul 16 - Original file. +*/ + +#include "system_defs.h" + +extern DEVICE i8088_dev; +extern REG i8088_reg[]; +extern DEVICE i8237_dev; +extern DEVICE i8253_dev; +extern DEVICE i8255_dev; +extern DEVICE i8259_dev; +extern DEVICE EPROM_dev; +extern DEVICE RAM_dev; +extern DEVICE xtbus_dev; + +/* bit patterns to manipulate 8-bit ports */ + +#define i82XX_bit_0 0x01 //bit 0 of a port +#define i82XX_bit_1 0x02 //bit 1 of a port +#define i82XX_bit_2 0x04 //bit 2 of a port +#define i82XX_bit_3 0x08 //bit 3 of a port +#define i82XX_bit_4 0x10 //bit 4 of a port +#define i82XX_bit_5 0x20 //bit 5 of a port +#define i82XX_bit_6 0x40 //bit 6 of a port +#define i82XX_bit_7 0x80 //bit 7 of a port + +#define i82XX_nbit_0 ~i8255_bit_0 //bit 0 of a port +#define i82XX_nbit_1 ~i8255_bit_1 //bit 1 of a port +#define i82XX_nbit_2 ~i8255_bit_3 //bit 2 of a port +#define i82XX_nbit_3 ~i8255_bit_3 //bit 3 of a port +#define i82XX_nbit_4 ~i8255_bit_4 //bit 4 of a port +#define i82XX_nbit_5 ~i8255_bit_5 //bit 5 of a port +#define i82XX_nbit_6 ~i8255_bit_6 //bit 6 of a port +#define i82XX_nbit_7 ~i8255_bit_7 //bit 7 of a port + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "IBM PC"; + +REG *sim_PC = &i8088_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8088_dev, + &EPROM_dev, + &RAM_dev, + &i8237_dev, + &i8253_dev, + &i8255_dev, + &i8259_dev, + &xtbus_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error" +}; + diff --git a/Intel-Systems/common/i8008.c b/Intel-Systems/common/i8008.c index 05a07727..461d77a5 100644 --- a/Intel-Systems/common/i8008.c +++ b/Intel-Systems/common/i8008.c @@ -1,2002 +1,2002 @@ -/* i8008.c: Intel 8008 CPU simulator - - 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 8008 CPU - - The register state for the 8008 CPU is: - - A<0:7> Accumulator - B<0:7> B Register - C<0:7> C Register - D<0:7> D Register - E<0:7> E Register - H<0:7> H Register - L<0:7> L Register - PC<0:13> Program counter - - The 8008 is an 8-bit CPU, which uses 14-bit registers to address - up to 16KB of memory. - - The 57 basic instructions come in 1, 2, and 3-byte flavors. - - This routine is the instruction decode routine for the 8008. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HLT instruction - I/O error in I/O simulator - Invalid OP code (if ITRAP is set on CPU) - - 2. Interrupts. - There are 8 possible levels of interrupt, and in effect they - do a hardware CALL instruction to one of 8 possible low - memory addresses. - - 3. Non-existent memory. On the 8008, reads to non-existent memory - return 0FFh, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 4. Adding I/O devices. These modules must be modified: - - 15 Feb 15 - Original file. - -*/ - -#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_TRACE (UNIT_V_UF+1) /* Trace switch */ -#define UNIT_TRACE (1 << UNIT_V_TRACE) - -/* register masks */ -#define BYTE_R 0xFF -#define WORD_R14 0x3FFF - -/* storage for the rest of the registers */ -uint32 A = 0; /* accumulator */ -uint32 B = 0; /* B register */ -uint32 C = 0; /* C register */ -uint32 D = 0; /* D register */ -uint32 E = 0; /* E register */ -uint32 H = 0; /* H register */ -uint32 L = 0; /* L register */ -uint32 CF = 0; /* C - carry flag */ -uint32 PF = 0; /* P - parity flag */ -uint32 ZF = 0; /* Z - zero flag */ -uint32 SF = 0; /* S - sign flag */ -uint32 SP = 0; /* stack frame pointer */ -uint32 saved_PC = 0; /* program counter */ -uint32 int_req = 0; /* Interrupt request */ - -int32 PCX; /* External view of PC */ -int32 PC; -UNIT *uptr; - -/* function prototypes */ -void store_m(unit32 val); -unit32 fetch_m(void); -void set_cpuint(int32 int_num); -void dumpregs(void); -int32 fetch_byte(int32 flag); -int32 fetch_word(void); -uint16 pop_word(void); -void push_word(uint16 val); -void setflag4(int32 reg); -void setlogical(int32 reg); -void setinc(int32 reg); -int32 getreg(int32 reg); -void putreg(int32 reg, int32 val); -int32 getpair(int32 reg); -int32 getpush(int32 reg); -void putpush(int32 reg, int32 data); -void putpair(int32 reg, int32 val); -void parity(int32 reg); -int32 cond(int32 con); -t_stat i8008_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat i8008_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat i8008_reset (DEVICE *dptr); - -/* external function prototypes */ - -extern t_stat i8008_reset (DEVICE *dptr); -extern int32 get_mbyte(int32 addr); -extern int32 get_mword(int32 addr); -extern void put_mbyte(int32 addr, int32 val); -extern void put_mword(int32 addr, int32 val); -extern int32 sim_int_char; -extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - - -struct idev { - int32 (*routine)(); -}; - -/* This is the I/O configuration table. There are 256 possible -device addresses, if a device is plugged to a port it's routine -address is here, 'nulldev' means no device is available -*/ - -extern struct idev dev_table[]; - -/* CPU data structures - - i8008_dev CPU device descriptor - i8008_unit CPU unit descriptor - i8008_reg CPU register list - i8008_mod CPU modifiers list -*/ - -UNIT i8008_unit = { UDATA (NULL, 0, 65535) }; /* default 8008 */ - -REG i8008_reg[] = { - { HRDATA (PC, saved_PC, 16) }, /* must be first for sim_PC */ - { HRDATA (A, A, 8) }, - { HRDATA (B, B, 8) }, - { HRDATA (C, C, 8) }, - { HRDATA (D, D, 8) }, - { HRDATA (E, E, 8) }, - { HRDATA (H, H, 8) }, - { HRDATA (L, L, 8) }, - { HRDATA (CF, CF, 1) }, - { HRDATA (PF, PF, 1) }, - { HRDATA (ZF, SF, 1) }, - { HRDATA (SF, SF, 1) }, - { HRDATA (INTR, int_req, 32) }, - { HRDATA (WRU, sim_int_char, 8) }, - { NULL } -}; - -MTAB i8008_mod[] = { - { 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 }, - { 0 } -}; - -DEBTAB i8008_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { "REG", DEBUG_reg }, - { "ASM", DEBUG_asm }, - { NULL } -}; - -DEVICE i8008_dev = { - "I8008", //name - &i8008_unit, //units - i8008_reg, //registers - i8008_mod, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - &i8008_ex, //examine - &i8008_dep, //deposit -// &i8008_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - i8008_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* tables for the disassembler */ -char *opcode[] = { -"*HLT", "*HLT", "RLC", "RFC", /* 0x00 */ -"ADI ", "RST 0", "LAI ,", "RET", -"INB", "DCB", "RRC", "RFZ", -"ACI ", "RST 1", "LBI ", "*RET", -"INC", "DCC", "RAL", "RFS", /* 0x10 */ -"SUI ", "RST 2", "LCI ", "*RET", -"IND", "DCD", "RAR", "RFP", -"SBI ", "RST 3", "LDI ", "*RET", -"INE", "DCE", "???", "RTC", /* 0x20 */ -"NDI ", "RST 4", "LEI ", "*RET", -"INH", "DCH", "???", "RTZ", -"XRI ", "RST 5", "LHI ", "*RET", -"INL", "DCL", "???", "RTS", /* 0x30 */ -"ORI ", "RST 6", "LLI ", "*RET", -"???", "???", "???", "RTP", -"CPI ", "RST 7", "LMI ", "*RET", -"JFC ", "INP ", "CFC ", "INP ", /* 0x40 */ -"JMP ", "INP ", "CAL ", "INP ", -"JFZ ", "INP ", "CFZ ", "INP ", -"*JMP ", "INP ", "*CAL ", "INP ", -"JFS", "OUT ", "CFS ", "OUT ", /* 0x50 */ -"*JMP ", "OUT ", "*CAL ", "OUT ", -"JFP ", "OUT ", "CFP ", "OUT ", -"*JMP ", "OUT ", "*CAL ", "OUT ", -"JTC ", "OUT ", "CTC ", "OUT ", /* 0x60 */ -"*JMP ", "OUT ", "*CAL ", "OUT ", -"JTZ ", "OUT ", "CTZ", "OUT ", -"*JMP ", "OUT ", "*CAL", "OUT ", -"JTS ", "OUT ", "CTS ", "OUT ", /* 0x70 */ -"*JMP ", "OUT ", "*CAL ", "OUT ", -"JTP ", "OUT ", "CTP", "OUT ", -"*JMP ", "OUT ", "*CAL ", "OUT ", -"ADA", "ADB", "ADC", "ADD", /* 0x80 */ -"ADE", "ADH", "ADL", "ADM", -"ACA", "ACB", "ACC", "ACD", -"ACE", "ACH", "ACL", "ACM", -"SUA", "SUB", "SUC", "SUD", /* 0x90 */ -"SUE", "SUH", "SUL", "SUM", -"SBA", "SBB", "SBC", "SBD", -"SBE", "SBH", "SBL", "SBM", -"NDA", "NDB", "NDC", "NDD", /* 0xA0 */ -"NDE", "NDH", "NDL", "NDM", -"XRA", "XRB", "XRC", "XRD", -"XRE", "XRH", "XRL", "XRM", -"ORA", "ORB", "ORC", "ORD", /* 0xB0 */ -"ORE", "ORH", "ORL", "ORM", -"CPA", "CPB", "CPC", "CPD", -"CPE", "CPH", "CPL", "CPM", -"NOP", "LAB", "LAC", "LAD", /* 0xC0 */ -"LAE", "LAH", "LAL", "LAM", -"LBA", "LBB", "LBC", "LBD", -"LBE", "LBH ", "LBL", "LBM", -"LCA", "LCB", "LCC", "LCD", /* 0xD0 */ -"LCE", "LCH", "LCL", "LCM", -"LDA", "LDB", "LDC", "LDD", -"LDE", "LDH", "LDL", "LDM", -"LEA", "LEB", "LEC", "LED", /* 0xE0 */ -"LEE", "LEH", "LEL", "LEM", -"LHA", "LHB", "LHC", "LHD", -"LHE", "LHH", "LHL", "LHM", -"LLA", "LLB", "LLC", "LLD", /* 0xF0 */ -"LLE", "LLH", "LLL", "LLM", -"LMA", "LMB", "LMC", "LMD", -"LME", "LMH", "LML", "HLT", - }; - -int32 oplen[256] = { -/* - 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, /* 0X */ - 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, /* 1X */ - 1, 1, 0, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, /* 2X */ - 1, 1, 0, 1, 2, 1, 2, 1, 0, 0, 0, 1, 2, 1, 2, 1, /* 3X */ - 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 4X */ - 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 5X */ - 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 6X */ - 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 7X */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8X */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9X */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* AX */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* BX */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* CX */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* DX */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* EX */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* FX */ -}; - -uint16 stack_frame[7]; /* processor stack frame */ - -void set_cpuint(int32 int_num) -{ - int_req |= int_num; -} - -/* instruction simulator */ -int32 sim_instr (void) -{ - extern int32 sim_interval; - uint32 IR, OP, DAR, reason, hi, lo, i, adr, val; - - PC = saved_PC & WORD_R14; /* load local PC */ - reason = 0; - - uptr = i8008_dev.units; - - /* Main instruction fetch/decode loop */ - - while (reason == 0) { /* loop until halted */ - -// if (PC == 0x1000) { /* turn on debugging */ -// i8008_dev.dctrl = DEBUG_asm + DEBUG_reg; -// reason = STOP_HALT; -// } - if (i8008_dev.dctrl & DEBUG_reg) { - dumpregs(); - sim_printf("\n"); - } - - if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event()) - break; - } - - if (int_req > 0) { /* interrupt? */ -// sim_printf("\ni8008: int_req=%04X", int_req); - ; - } else { /* 8008 */ - if (IE) { /* enabled? */ - push_word(PC); /* do an RST 7 */ - PC = 0x0038; - int_req &= ~INT_R; -// sim_printf("\ni8008: int_req=%04X", int_req); - } - } /* end interrupt */ - - if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - - sim_interval--; /* countdown clock */ - PCX = PC; - - if (uptr->flags & UNIT_TRACE) { - dumpregs(); - sim_printf("\n"); - } - IR = OP = fetch_byte(0); /* instruction fetch */ - - if (OP == 0x00 || OP == 0x01 || OP == 0xFF) { /* HLT Instruction*/ - reason = STOP_HALT; - PC--; - continue; - } - - /* The Big Instruction Decode Switch */ - - switch (IR) { - - case 0x02: /* RLC */ - if (A & 0x80) - CF = 1; - else - CF = 0; - A = (A << 1) & 0xFF; - if (CF) - A |= 0x01; - A &= BYTE_R; - break; - - case 0x03: /* RFC */ - if (CF) - ; - else - PC = pop_word(); - break; - - case 0x04: /* ADI */ - A += fetch_byte(1); - setflag3(A); - A &= BYTE_R; - break; - - case 0x05: /* RST 0 */ - case 0x0D: /* RST 1 */ - case 0x15: /* RST 2 */ - case 0x1D: /* RST 3 */ - case 0x25: /* RST 4 */ - case 0x2D: /* RST 5 */ - case 0x35: /* RST 6 */ - case 0x3D: /* RST 7 */ - val = fetch_byte(); - push_word(PC); - PC = val << 3; - break; - - case 0x06: /* LAI */ - A = fetch_byte(1); - A &= BYTE_R; - break; - - case 0x07: /* RET */ - PC = pop_word(); - break; - - case 0x08: /* INB */ - B++; - setflag3(B); - B &= BYTE_R; - break; - - case 0x09: /* DCB */ - B--; - setflag3(B); - B &= BYTE_R; - break; - - case 0x0A: /* RRC */ - if (A & 0x01) - CF = 1; - else - CF = 0; - A = (A >> 1) & 0xFF; - if (CF) - A |= 0x80; - A &= BYTE_R; - break; - - case 0x0B: /* RFZ */ - if (ZF) - ; - else - PC = pop_word(); - break; - - case 0x0C: /* ACI */ - A += fetch_byte(1); - if (CF) - A++; - setflag3(A); - A &= BYTE_R; - break; - - case 0x0E: /* LBI */ - B = fetch_byte(1); - B &= BYTE_R; - break; - - case 0x0F: /* *RET */ - PC = pop_word(); - break; - - case 0x10: /* INC */ - C++; - setflag3(C); - C &= BYTE_R; - break; - - case 0x11: /* DCC */ - C--; - setflag3(C); - C &= BYTE_R; - break; - - case 0x12: /* RAL */ - if (A & 0x80) - CF = 1; - else - CF = 0; - A = (A << 1) & 0xFF; - if (CF) - A |= 0x01; - A &= BYTE_R; - break; - - case 0x13: /* RFS */ - if (SF) - ; - else - PC = pop_word(); - break; - - case 0x14: /* SUI */ - A -= fetch_byte(1); - setflag3(A); - A &= BYTE_R; - break; - - case 0x16: /* LCI */ - C = fetch_byte(1); - C &= BYTE_R; - break; - - case 0x17: /* *RET */ - PC = pop_word(); - break; - - case 0x18: /* IND */ - D++; - setflag3(D); - D &= BYTE_R; - break; - - case 0x19: /* DCD */ - D--; - setflag3(D); - D &= BYTE_R; - break; - - case 0x1A: /* RAR */ - if (A & 0x01) - CF = 1; - else - CF = 0; - A = (A >> 1) & 0xFF; - if (CF) - A |= 0x80; - A &= BYTE_R; - break; - - case 0x1B: /* RFP */ - if (PF) - ; - else - PC = pop_word(); - break; - - case 0x1C: /* SBI */ - A -= fetch_byte(1); - if (CF) - A--; - setflag3(A); - A &= BYTE_R; - break; - - case 0x1E: /* LDI */ - D = fetch_byte(1); - D &= BYTE_R; - break; - - case 0x1F: /* *RET */ - PC = pop_word(); - break; - - case 0x20: /* INE */ - E++; - setflag3(E); - E &= BYTE_R; - break; - - case 0x21: /* DCE */ - E--; - setflag3(E); - E &= BYTE_R; - break; - - case 0x23: /* RTC */ - if (CF) - PC = pop_word(); - break; - - case 0x24: /* NDI */ - A &= fetch_byte(1); - setflag3(A); - A &= BYTE_R; - break; - - case 0x26: /* LEI */ - E = fetch_byte(1); - E &= BYTE_R; - break; - - case 0x27: /* *RET */ - PC = pop_word(); - break; - - case 0x28: /* INH */ - H++; - setflag3(H); - H &= BYTE_R; - break; - - case 0x29: /* DCH */ - H--; - setflag3(H); - H &= BYTE_R; - break; - - case 0x2B: /* RTZ */ - if (ZF) - PC = pop_word(); - break; - - case 0x2C: /* XRI */ - A ^= fetch_byte(1); - setflag3(A); - break; - - case 0x2E: /* LHI */ - H = fetch_byte(1); - H &= BYTE_R; - break; - - case 0x2F: /* *RET */ - PC = pop_word(); - break; - - case 0x30: /* INL */ - L++; - setflag3(L); - L &= BYTE_R; - break; - - case 0x31: /* DCL */ - L--; - setflag3(L); - L &= BYTE_R; - break; - - case 0x33: /* RTS */ - if (SF) - PC = pop_word(); - break; - - case 0x34: /* ORI */ - A |= fetch_byte(1); - setflag3(A); - A &= BYTE_R; - break; - - case 0x36: /* LLI */ - L = fetch_byte(1); - L &= BYTE_R; - break; - - case 0x37: /* *RET */ - PC = pop_word(); - break; - - case 0x3B: /* RTP */ - if (PF) - PC = pop_word(); - break; - - case 0x3C: /* CPI */ - DAR = A; - DAR -= fetch_byte(1); - setflag3(DAR); - break; - - case 0x3E: /* LMI */ - val = fetch_byte(1); - store_m(val); - break; - - case 0x3F: /* *RET */ - PC = pop_word(); - break; - - case 0x40: /* JFC */ - DAR = fetch_word(); - if (CF) - ; - else - PC = DAR; - break; - - case 0x41: /* INP 0 */ - case 0x43: /* INP 1 */ - case 0x45: /* INP 2 */ - case 0x47: /* INP 3 */ - case 0x49: /* INP 4 */ - case 0x4B: /* INP 5 */ - case 0x4D: /* INP 6 */ - case 0x4F: /* INP 7 */ - /**** fix me! */ - break; - - case 0x42: /* CFC */ - adr = fetch_word(); - if (CF) - ; - else { - push_word(PC); - PC = adr; - } - break; - - case 0x44: /* JMP */ - PC = fetch_word(); - break; - - case 0x46: /* CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x48: /* JFZ */ - DAR = fetch_word(); - if (ZF) - ; - else - PC = DAR; - break; - - case 0x4A: /* CFZ */ - adr = fetch_word(); - if (ZF) - ; - else { - push_word(PC); - PC = adr; - } - break; - - case 0x4C: /* *JMP */ - PC = fetch_word(); - break; - - case 0x4E: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x50: /* JFS */ - DAR = fetch_word(); - if (SF) - ; - else - PC = DAR; - break; - - case 0x51: /* OUT 8 */ - case 0x53: /* OUT 9 */ - case 0x55: /* OUT 10 */ - case 0x57: /* OUT 11 */ - case 0x59: /* OUT 12 */ - case 0x5B: /* OUT 13 */ - case 0x5D: /* OUT 14 */ - case 0x5E: /* OUT 15 */ - case 0x61: /* OUT 16 */ - case 0x63: /* OUT 17 */ - case 0x65: /* OUT 18 */ - case 0x67: /* OUT 19 */ - case 0x69: /* OUT 20 */ - case 0x6B: /* OUT 21 */ - case 0x6D: /* OUT 22 */ - case 0x6E: /* OUT 23 */ - case 0x71: /* OUT 24 */ - case 0x73: /* OUT 25 */ - case 0x75: /* OUT 26 */ - case 0x77: /* OUT 27 */ - case 0x79: /* OUT 28 */ - case 0x7B: /* OUT 29 */ - case 0x7D: /* OUT 30 */ - case 0x7E: /* OUT 31 */ - /**** fix me! */ - break; - - case 0x52: /* CFS */ - adr = fetch_word(); - if (SF) - ; - else { - push_word(PC); - PC = adr; - } - break; - - case 0x54: /* *JMP */ - PC = fetch_word(); - break; - - case 0x56: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x58: /* JFP */ - DAR = fetch_word(); - if (PF) - ; - else - PC = DAR; - break; - - case 0x5A: /* CFP */ - adr = fetch_word(); - if (PF) - ; - else { - push_word(PC); - PC = adr; - } - break; - - case 0x5C: /* *JMP */ - PC = fetch_word(); - break; - - case 0x5E: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x60: /* JTC */ - DAR = fetch_word(); - if (CF) - PC = DAR; - break; - - case 0x62: /* CTC */ - adr = fetch_word(); - if (CF) { - push_word(PC); - PC = adr; - } - break; - - case 0x64: /* *JMP */ - PC = fetch_word(); - break; - - case 0x66: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x68: /* JTZ */ - DAR = fetch_word(); - if (ZF) - PC = DAR; - break; - - case 0x6A: /* CTZ */ - adr = fetch_word(); - if (ZF) { - push_word(PC); - PC = adr; - } - break; - - case 0x6C: /* *JMP */ - PC = fetch_word(); - break; - - case 0x6E: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x70: /* JTS */ - DAR = fetch_word(); - if (SF) - PC = DAR; - break; - - case 0x72: /* CTS */ - adr = fetch_word(); - if (SF) { - push_word(PC); - PC = adr; - } - break; - - case 0x74: /* *JMP */ - PC = fetch_word(); - break; - - case 0x76: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x78: /* JTP */ - DAR = fetch_word(); - if (PF) - PC = DAR; - break; - - case 0x7A: /* CTP */ - adr = fetch_word(); - if (PF) { - push_word(PC); - PC = adr; - } - break; - - case 0x7C: /* *JMP */ - PC = fetch_word(); - break; - - case 0x7E: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x80: /* ADA */ - A += A; - setflag4(A); - A &= BYTE_R; - break; - - case 0x81: /* ADB */ - A += B; - setflag4(A); - A &= BYTE_R; - break; - - case 0x82: /* ADC */ - A += C; - setflag4(A); - A &= BYTE_R; - break; - - case 0x83: /* ADD */ - A += D; - setflag4(A); - A &= BYTE_R; - break; - - case 0x84: /* ADE */ - A += E; - setflag4(A); - A &= BYTE_R; - break; - - case 0x85: /* ADH */ - A += H; - setflag4(A); - A &= BYTE_R; - break; - - case 0x86: /* ADL */ - A += L; - setflag4(A); - A &= BYTE_R; - break; - - case 0x87: /* ADM */ - A += fetch_m(); - setflag4(A); - A &= BYTE_R; - break; - - case 0x88: /* ACA */ - A += A; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x89: /* ACB */ - A += B; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8A: /* ACC */ - A += C; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8B: /* ACD */ - A += D; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8C: /* ACE */ - A += E; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8D: /* ACH */ - A += H; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8E: /* ACL */ - A += L; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8F: /* ACM */ - A += fetch_m(); - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x90: /* SUA */ - A -= A; - setflag4(A); - A &= BYTE_R; - break; - - case 0x91: /* SUB */ - A -= B; - setflag4(A); - A &= BYTE_R; - break; - - case 0x92: /* SUC */ - A -= C; - setflag4(A); - A &= BYTE_R; - break; - - case 0x93: /* SUD */ - A -= D; - setflag4(A); - A &= BYTE_R; - break; - - case 0x94: /* SUE */ - A -= E; - setflag4(A); - A &= BYTE_R; - break; - - case 0x95: /* SUH */ - A -= H; - setflag4(A); - A &= BYTE_R; - break; - - case 0x96: /* SUL */ - A -= L; - setflag4(A); - A &= BYTE_R; - break; - - case 0x97: /* SUM */ - A -= fetch_m(); - setflag4(A); - A &= BYTE_R; - break; - - case 0x98: /* SBA */ - A -= A; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x99: /* SBB */ - A -= B; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9A: /* SBC */ - A -= C; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9B: /* SBD */ - A -= D; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9C: /* SBE */ - A -= E; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9D: /* SBH */ - A -= H; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9E: /* SBL */ - A -= L; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9F: /* SBM */ - A -= fetch_m(); - if (CF) - A - ; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA0: /* NDA */ - A &= A; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA1: /* NDB */ - A &= B; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA2: /* NDC */ - A &= C; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA3: /* NDD */ - A &= D; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA4: /* NDE */ - A &= E; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA5: /* NDH */ - A &= H; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA6: /* NDL */ - A &= L; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA7: /* NDM */ - A &= fetch_m(); - setflag4(A); - A &= BYTE_R; - break; - - case 0xA8: /* XRA */ - A ^= A; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA9: /* XRB */ - A ^= B; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAA: /* XRC */ - A ^= C; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAB: /* XRD */ - A ^= D; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAC: /* XRE */ - A ^= E; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAD: /* XRH */ - A ^= H; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAE: /* XRL */ - A ^= L; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAF: /* XRM */ - A |= fetch_m(); - setflag4(A); - A &= BYTE_R; - break; - - case 0xB0: /* ORA */ - A |= A; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB1: /* ORB */ - A |= B; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB2: /* ORC */ - A |= C; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB3: /* ORD */ - A |= D; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB4: /* ORE */ - A |= E; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB5: /* ORH */ - A |= H; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB6: /* ORL */ - A |= L; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB7: /* ORM */ - A |= fetch_m(); - setflag4(A); - A &= BYTE_R; - break; - - case 0xB8: /* CPA */ - DAR -= A; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xB9: /* CPB */ - DAR -= B; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBA: /* CPC */ - DAR -= C; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBB: /* CPD */ - DAR -= D; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBC: /* CPE */ - DAR -= E; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBD: /* CPH */ - DAR -= H; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBE: /* CPL */ - DAR -= L; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBF: /* CPM */ - DAR -= fetch_m(); - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xC0: /* NOP */ - break; - - case 0xC1: /* LAB */ - A = B; - A &= BYTE_R; - break; - - case 0xC2: /* LAC */ - A = C; - A &= BYTE_R; - break; - - case 0xC3: /* LAD */ - A = D; - A &= BYTE_R; - break; - - case 0xC4: /* LAE */ - A = E; - A &= BYTE_R; - break; - - case 0xC5: /* LAH */ - A = H; - A &= BYTE_R; - break; - - case 0xC6: /* LAL */ - A = L; - A &= BYTE_R; - break; - - case 0xC7: /* LAM */ - A = FETCH_M(); - A &= BYTE_R; - break; - - case 0xC8: /* LBA */ - B = A; - B &= BYTE_R; - break; - - case 0xC9: /* LBB */ - B = B; - B &= BYTE_R; - break; - - case 0xCA: /* LBC */ - B = C; - B &= BYTE_R; - break; - - case 0xCB: /* LBD */ - B = D; - B &= BYTE_R; - break; - - case 0xCC: /* LBE */ - B = E; - B &= BYTE_R; - break; - - case 0xCD: /* LBH */ - B = H; - B &= BYTE_R; - break; - - case 0xCE: /* LBL */ - B = L; - B &= BYTE_R; - break; - - case 0xCF: /* LBM */ - B = FETCH_M(); - B &= BYTE_R; - break; - - case 0xD0: /* LCA */ - C = A; - C &= BYTE_R; - break; - - case 0xD1: /* LCB */ - C = B; - C &= BYTE_R; - break; - - case 0xD2: /* LCC */ - C = C; - C &= BYTE_R; - break; - - case 0xD3: /* LCD */ - C = D; - C &= BYTE_R; - break; - - case 0xD4: /* LCE */ - C = E; - C &= BYTE_R; - break; - - case 0xD5: /* LCH */ - C = H; - C &= BYTE_R; - break; - - case 0xD6: /* LCL */ - C = L; - C &= BYTE_R; - break; - - case 0xD7: /* LCM */ - C = FETCH_M(); - C &= BYTE_R; - break; - - case 0xD8: /* LDA */ - D = A; - D &= BYTE_R; - break; - - case 0xD9: /* LDB */ - D = B; - D &= BYTE_R; - break; - - case 0xDA: /* LDC */ - D = C; - D &= BYTE_R; - break; - - case 0xDB: /* LDD */ - D = D; - D &= BYTE_R; - break; - - case 0xDC: /* LDE */ - D = E; - D &= BYTE_R; - break; - - case 0xDD: /* LDH */ - D = H; - D &= BYTE_R; - break; - - case 0xDE: /* LDL */ - D = L; - D &= BYTE_R; - break; - - case 0xDF: /* LDM */ - D = FETCH_M(); - D &= BYTE_R; - break; - - case 0xE0: /* LEA */ - E = A; - E &= BYTE_R; - break; - - case 0xE1: /* LEB */ - E = B; - E &= BYTE_R; - break; - - case 0xE2: /* LEC */ - E = C; - E &= BYTE_R; - break; - - case 0xE3: /* LED */ - E = D; - E &= BYTE_R; - break; - - case 0xE4: /* LEE */ - E = E; - E &= BYTE_R; - break; - - case 0xE5: /* LEH */ - E = H; - E &= BYTE_R; - break; - - case 0xE6: /* LEL */ - E = L; - E &= BYTE_R; - break; - - case 0xE7: /* LEM */ - E = FETCH_M(); - E &= BYTE_R; - break; - - case 0xE8: /* LHA */ - H = A; - H &= BYTE_R; - break; - - case 0xE9: /* LHB */ - H = B; - H &= BYTE_R; - break; - - case 0xEA: /* LHC */ - H = C; - H &= BYTE_R; - break; - - case 0xEB: /* LHD */ - H = D; - H &= BYTE_R; - break; - - case 0xEC: /* LHE */ - H = E; - H &= BYTE_R; - break; - - case 0xED: /* LHH */ - H = H; - H &= BYTE_R; - break; - - case 0xEE: /* LHL */ - H = L; - H &= BYTE_R; - break; - - case 0xEF: /* LHM */ - H = FETCH_M(); - H &= BYTE_R; - break; - - case 0xF0: /* LLA */ - L = A; - L &= BYTE_R; - break; - - case 0xF1: /* LLB */ - L = B; - L &= BYTE_R; - break; - - case 0xF2: /* LLC */ - L = C; - L &= BYTE_R; - break; - - case 0xF3: /* LLD */ - L = D; - L &= BYTE_R; - break; - - case 0xF4: /* LLE */ - L = E; - L &= BYTE_R; - break; - - case 0xF5: /* LLH */ - L = H; - L &= BYTE_R; - break; - - case 0xF6: /* LLL */ - L = L; - L &= BYTE_R; - break; - - case 0xF7: /* LLM */ - L = FETCH_M(); - L &= BYTE_R; - break; - - case 0xF8: /* LMA */ - store_m(A); - break; - - case 0xF9: /* LMB */ - store_m(B); - break; - - case 0xFA: /* LMC */ - store_m(C); - break; - - case 0xFB: /* LMD */ - store_m(D); - break; - - case 0xFC: /* LME */ - store_m(E); - break; - - case 0xFD: /* LMH */ - store_m(H); - break; - - case 0xFE: /* LML */ - store_m(L); - break; - - case 0xFF: /* LMM */ - val = FETCH_M(); - store_m(val); - break; - - default: /* undefined opcode */ - if (i8008_unit.flags & UNIT_OPSTOP) { - reason = STOP_OPCODE; - PC--; - } - break; - } - } - -/* Simulation halted */ - - saved_PC = PC; - return reason; -} - -/* store byte to (HL) */ -void store_m(uint32 val) -{ - DAR = (H << 8) + L; - DAR &= WORD_R14; - ret get_mword(DAR); -} - -/* get byte from (HL) */ -uint32 fetch_m(void) -{ - DAR = (H << 8) + L; - DAR &= WORD_R14; - put_mword(DAR, val); -} - -/* dump the registers */ -void dumpregs(void) -{ - sim_printf(" A=%02X B=%02X C=%02X D=%04X E=%02X H=%04X L=%02X\n", - A, B, C, D, E, H, L); - sim_printf(" CF=%d ZF=%d SF=%d PF=%d\n", - CF, ZF, SF, PF); -} - -/* fetch an instruction or byte */ -int32 fetch_byte(int32 flag) -{ - uint32 val; - - val = get_mbyte(PC) & 0xFF; /* fetch byte */ - if (i8008_dev.dctrl & DEBUG_asm || uptr->flags & UNIT_TRACE) { /* display source code */ - switch (flag) { - case 0: /* opcode fetch */ - sim_printf("OP=%02X %04X %s", val, PC, opcode[val]); - break; - case 1: /* byte operand fetch */ - sim_printf("0%02XH", val); - break; - } - } - PC = (PC + 1) & ADDRMASK; /* increment PC */ - val &= BYTE_R; - return val; -} - -/* fetch a word */ -int32 fetch_word(void) -{ - uint16 val; - - val = get_mbyte(PC) & BYTE_R; /* fetch low byte */ - val |= get_mbyte(PC + 1) << 8; /* fetch high byte */ - if (i8008_dev.dctrl & DEBUG_asm || uptr->flags & UNIT_TRACE) /* display source code */ - sim_printf("0%04XH", val); - PC = (PC + 2) & ADDRMASK; /* increment PC */ - val &= WORD_R14; - return val; -} - -/* push a word to the stack frame */ -void push_word(uint16 val) -{ - stack_frame[SP] = val; - SP++; - if (SP == 8) - SP = 0; -} - -/* pop a word from the stack frame */ -uint16 pop_word(void) -{ - SP--; - if (SP < 0) - SP = 7; - return stack_frame[SP]; -} - - -/* Set the arry, ign, ero and verflow flags following - an operation on 'reg'. -*/ - -void setflag4(int32 reg) -{ - if (reg & 0x100) - CF = 1; - else - CF = 0; - if (reg & 0x80) - SF = 0; - else - SF = 1; - if ((reg & BYTE_R) == 0) - ZF = 1; - else - ZF = 0; - parity(reg); -} - -/* Set the arry, ign and ero flags following - an operation on 'reg'. -*/ - -void setflag3(int32 reg) -{ - CF = 0; - if (reg & 0x80) - SF = 0; - else - SF = 1; - if ((reg & BYTE_R) == 0) - ZF = 1; - else - ZF = 0; - parity(reg); -} - -/* Set the Parity (PF) flag based on parity of 'reg', i.e., number -of bits on even: PF=1, else PF=0 -*/ - -void parity(int32 reg) -{ - int32 bc = 0; - - if (reg & 0x01) bc++; - if (reg & 0x02) bc++; - if (reg & 0x04) bc++; - if (reg & 0x08) bc++; - if (reg & 0x10) bc++; - if (reg & 0x20) bc++; - if (reg & 0x40) bc++; - if (reg & 0x80) bc++; - if (bc & 0x01) - PF = 0; - else - PF = 1; -} - - - -/* Reset routine */ - -t_stat i8008_reset (DEVICE *dptr) -{ - int i; - - CF = SF = ZF = PF = 0; - saved_PC = 0; - int_req = 0; - for (i = 0; i < 7; i++) - stack_frame[i] = 0; - sim_brk_types = sim_brk_dflt = SWMASK ('E'); - sim_printf(" 8008: Reset\n"); - return SCPE_OK; -} - -/* Memory examine */ - -t_stat i8008_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 i8008_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. -*/ - -int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ - int32 i, addr = 0, cnt = 0; - - if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; - addr = saved_PC; - while ((i = getc (fileref)) != EOF) { - put_mbyte(addr, i); - addr++; - cnt++; - } /* end while */ - sim_printf ("%d Bytes loaded.\n", cnt); - return (SCPE_OK); -} - -/* Symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -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 == &i8008_unit); - c1 = (val[0] >> 8) & 0x7F; - c2 = val[0] & 0x7F; - if (sw & SWMASK ('A')) { - fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2); - return SCPE_OK; - } - if (sw & SWMASK ('C')) { - fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); - fprintf (of, (c2 < 0x20)? "<%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, "%h", 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, "%h", adr); - } - return -(oplen[inst] - 1); -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ - int32 cflag, i = 0, j, r; - char gbuf[CBUFSIZE]; - - cflag = (uptr == NULL) || (uptr == &i8008_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 (1) { - 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++; - } - -/* 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); -} +/* i8008.c: Intel 8008 CPU simulator + + 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 8008 CPU + + The register state for the 8008 CPU is: + + A<0:7> Accumulator + B<0:7> B Register + C<0:7> C Register + D<0:7> D Register + E<0:7> E Register + H<0:7> H Register + L<0:7> L Register + PC<0:13> Program counter + + The 8008 is an 8-bit CPU, which uses 14-bit registers to address + up to 16KB of memory. + + The 57 basic instructions come in 1, 2, and 3-byte flavors. + + This routine is the instruction decode routine for the 8008. + It is called from the simulator control program to execute + instructions in simulated memory, starting at the simulated PC. + It runs until 'reason' is set non-zero. + + General notes: + + 1. Reasons to stop. The simulator can be stopped by: + + HLT instruction + I/O error in I/O simulator + Invalid OP code (if ITRAP is set on CPU) + + 2. Interrupts. + There are 8 possible levels of interrupt, and in effect they + do a hardware CALL instruction to one of 8 possible low + memory addresses. + + 3. Non-existent memory. On the 8008, reads to non-existent memory + return 0FFh, and writes are ignored. In the simulator, the + largest possible memory is instantiated and initialized to zero. + Thus, only writes need be checked against actual memory size. + + 4. Adding I/O devices. These modules must be modified: + + 15 Feb 15 - Original file. + +*/ + +#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_TRACE (UNIT_V_UF+1) /* Trace switch */ +#define UNIT_TRACE (1 << UNIT_V_TRACE) + +/* register masks */ +#define BYTE_R 0xFF +#define WORD_R14 0x3FFF + +/* storage for the rest of the registers */ +uint32 A = 0; /* accumulator */ +uint32 B = 0; /* B register */ +uint32 C = 0; /* C register */ +uint32 D = 0; /* D register */ +uint32 E = 0; /* E register */ +uint32 H = 0; /* H register */ +uint32 L = 0; /* L register */ +uint32 CF = 0; /* C - carry flag */ +uint32 PF = 0; /* P - parity flag */ +uint32 ZF = 0; /* Z - zero flag */ +uint32 SF = 0; /* S - sign flag */ +uint32 SP = 0; /* stack frame pointer */ +uint32 saved_PC = 0; /* program counter */ +uint32 int_req = 0; /* Interrupt request */ + +int32 PCX; /* External view of PC */ +int32 PC; +UNIT *uptr; + +/* function prototypes */ +void store_m(unit32 val); +unit32 fetch_m(void); +void set_cpuint(int32 int_num); +void dumpregs(void); +int32 fetch_byte(int32 flag); +int32 fetch_word(void); +uint16 pop_word(void); +void push_word(uint16 val); +void setflag4(int32 reg); +void setlogical(int32 reg); +void setinc(int32 reg); +int32 getreg(int32 reg); +void putreg(int32 reg, int32 val); +int32 getpair(int32 reg); +int32 getpush(int32 reg); +void putpush(int32 reg, int32 data); +void putpair(int32 reg, int32 val); +void parity(int32 reg); +int32 cond(int32 con); +t_stat i8008_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); +t_stat i8008_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); +t_stat i8008_reset (DEVICE *dptr); + +/* external function prototypes */ + +extern t_stat i8008_reset (DEVICE *dptr); +extern int32 get_mbyte(int32 addr); +extern int32 get_mword(int32 addr); +extern void put_mbyte(int32 addr, int32 val); +extern void put_mword(int32 addr, int32 val); +extern int32 sim_int_char; +extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ + + +struct idev { + int32 (*routine)(); +}; + +/* This is the I/O configuration table. There are 256 possible +device addresses, if a device is plugged to a port it's routine +address is here, 'nulldev' means no device is available +*/ + +extern struct idev dev_table[]; + +/* CPU data structures + + i8008_dev CPU device descriptor + i8008_unit CPU unit descriptor + i8008_reg CPU register list + i8008_mod CPU modifiers list +*/ + +UNIT i8008_unit = { UDATA (NULL, 0, 65535) }; /* default 8008 */ + +REG i8008_reg[] = { + { HRDATA (PC, saved_PC, 16) }, /* must be first for sim_PC */ + { HRDATA (A, A, 8) }, + { HRDATA (B, B, 8) }, + { HRDATA (C, C, 8) }, + { HRDATA (D, D, 8) }, + { HRDATA (E, E, 8) }, + { HRDATA (H, H, 8) }, + { HRDATA (L, L, 8) }, + { HRDATA (CF, CF, 1) }, + { HRDATA (PF, PF, 1) }, + { HRDATA (ZF, SF, 1) }, + { HRDATA (SF, SF, 1) }, + { HRDATA (INTR, int_req, 32) }, + { HRDATA (WRU, sim_int_char, 8) }, + { NULL } +}; + +MTAB i8008_mod[] = { + { 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 }, + { 0 } +}; + +DEBTAB i8008_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { "REG", DEBUG_reg }, + { "ASM", DEBUG_asm }, + { NULL } +}; + +DEVICE i8008_dev = { + "I8008", //name + &i8008_unit, //units + i8008_reg, //registers + i8008_mod, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + &i8008_ex, //examine + &i8008_dep, //deposit +// &i8008_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + i8008_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* tables for the disassembler */ +char *opcode[] = { +"*HLT", "*HLT", "RLC", "RFC", /* 0x00 */ +"ADI ", "RST 0", "LAI ,", "RET", +"INB", "DCB", "RRC", "RFZ", +"ACI ", "RST 1", "LBI ", "*RET", +"INC", "DCC", "RAL", "RFS", /* 0x10 */ +"SUI ", "RST 2", "LCI ", "*RET", +"IND", "DCD", "RAR", "RFP", +"SBI ", "RST 3", "LDI ", "*RET", +"INE", "DCE", "???", "RTC", /* 0x20 */ +"NDI ", "RST 4", "LEI ", "*RET", +"INH", "DCH", "???", "RTZ", +"XRI ", "RST 5", "LHI ", "*RET", +"INL", "DCL", "???", "RTS", /* 0x30 */ +"ORI ", "RST 6", "LLI ", "*RET", +"???", "???", "???", "RTP", +"CPI ", "RST 7", "LMI ", "*RET", +"JFC ", "INP ", "CFC ", "INP ", /* 0x40 */ +"JMP ", "INP ", "CAL ", "INP ", +"JFZ ", "INP ", "CFZ ", "INP ", +"*JMP ", "INP ", "*CAL ", "INP ", +"JFS", "OUT ", "CFS ", "OUT ", /* 0x50 */ +"*JMP ", "OUT ", "*CAL ", "OUT ", +"JFP ", "OUT ", "CFP ", "OUT ", +"*JMP ", "OUT ", "*CAL ", "OUT ", +"JTC ", "OUT ", "CTC ", "OUT ", /* 0x60 */ +"*JMP ", "OUT ", "*CAL ", "OUT ", +"JTZ ", "OUT ", "CTZ", "OUT ", +"*JMP ", "OUT ", "*CAL", "OUT ", +"JTS ", "OUT ", "CTS ", "OUT ", /* 0x70 */ +"*JMP ", "OUT ", "*CAL ", "OUT ", +"JTP ", "OUT ", "CTP", "OUT ", +"*JMP ", "OUT ", "*CAL ", "OUT ", +"ADA", "ADB", "ADC", "ADD", /* 0x80 */ +"ADE", "ADH", "ADL", "ADM", +"ACA", "ACB", "ACC", "ACD", +"ACE", "ACH", "ACL", "ACM", +"SUA", "SUB", "SUC", "SUD", /* 0x90 */ +"SUE", "SUH", "SUL", "SUM", +"SBA", "SBB", "SBC", "SBD", +"SBE", "SBH", "SBL", "SBM", +"NDA", "NDB", "NDC", "NDD", /* 0xA0 */ +"NDE", "NDH", "NDL", "NDM", +"XRA", "XRB", "XRC", "XRD", +"XRE", "XRH", "XRL", "XRM", +"ORA", "ORB", "ORC", "ORD", /* 0xB0 */ +"ORE", "ORH", "ORL", "ORM", +"CPA", "CPB", "CPC", "CPD", +"CPE", "CPH", "CPL", "CPM", +"NOP", "LAB", "LAC", "LAD", /* 0xC0 */ +"LAE", "LAH", "LAL", "LAM", +"LBA", "LBB", "LBC", "LBD", +"LBE", "LBH ", "LBL", "LBM", +"LCA", "LCB", "LCC", "LCD", /* 0xD0 */ +"LCE", "LCH", "LCL", "LCM", +"LDA", "LDB", "LDC", "LDD", +"LDE", "LDH", "LDL", "LDM", +"LEA", "LEB", "LEC", "LED", /* 0xE0 */ +"LEE", "LEH", "LEL", "LEM", +"LHA", "LHB", "LHC", "LHD", +"LHE", "LHH", "LHL", "LHM", +"LLA", "LLB", "LLC", "LLD", /* 0xF0 */ +"LLE", "LLH", "LLL", "LLM", +"LMA", "LMB", "LMC", "LMD", +"LME", "LMH", "LML", "HLT", + }; + +int32 oplen[256] = { +/* + 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, /* 0X */ + 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, /* 1X */ + 1, 1, 0, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, /* 2X */ + 1, 1, 0, 1, 2, 1, 2, 1, 0, 0, 0, 1, 2, 1, 2, 1, /* 3X */ + 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 4X */ + 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 5X */ + 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 6X */ + 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 7X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9X */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* AX */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* BX */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* CX */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* DX */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* EX */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* FX */ +}; + +uint16 stack_frame[7]; /* processor stack frame */ + +void set_cpuint(int32 int_num) +{ + int_req |= int_num; +} + +/* instruction simulator */ +int32 sim_instr (void) +{ + extern int32 sim_interval; + uint32 IR, OP, DAR, reason, hi, lo, i, adr, val; + + PC = saved_PC & WORD_R14; /* load local PC */ + reason = 0; + + uptr = i8008_dev.units; + + /* Main instruction fetch/decode loop */ + + while (reason == 0) { /* loop until halted */ + +// if (PC == 0x1000) { /* turn on debugging */ +// i8008_dev.dctrl = DEBUG_asm + DEBUG_reg; +// reason = STOP_HALT; +// } + if (i8008_dev.dctrl & DEBUG_reg) { + dumpregs(); + sim_printf("\n"); + } + + if (sim_interval <= 0) { /* check clock queue */ + if (reason = sim_process_event()) + break; + } + + if (int_req > 0) { /* interrupt? */ +// sim_printf("\ni8008: int_req=%04X", int_req); + ; + } else { /* 8008 */ + if (IE) { /* enabled? */ + push_word(PC); /* do an RST 7 */ + PC = 0x0038; + int_req &= ~INT_R; +// sim_printf("\ni8008: int_req=%04X", int_req); + } + } /* end interrupt */ + + if (sim_brk_summ && + sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ + reason = STOP_IBKPT; /* stop simulation */ + break; + } + + sim_interval--; /* countdown clock */ + PCX = PC; + + if (uptr->flags & UNIT_TRACE) { + dumpregs(); + sim_printf("\n"); + } + IR = OP = fetch_byte(0); /* instruction fetch */ + + if (OP == 0x00 || OP == 0x01 || OP == 0xFF) { /* HLT Instruction*/ + reason = STOP_HALT; + PC--; + continue; + } + + /* The Big Instruction Decode Switch */ + + switch (IR) { + + case 0x02: /* RLC */ + if (A & 0x80) + CF = 1; + else + CF = 0; + A = (A << 1) & 0xFF; + if (CF) + A |= 0x01; + A &= BYTE_R; + break; + + case 0x03: /* RFC */ + if (CF) + ; + else + PC = pop_word(); + break; + + case 0x04: /* ADI */ + A += fetch_byte(1); + setflag3(A); + A &= BYTE_R; + break; + + case 0x05: /* RST 0 */ + case 0x0D: /* RST 1 */ + case 0x15: /* RST 2 */ + case 0x1D: /* RST 3 */ + case 0x25: /* RST 4 */ + case 0x2D: /* RST 5 */ + case 0x35: /* RST 6 */ + case 0x3D: /* RST 7 */ + val = fetch_byte(); + push_word(PC); + PC = val << 3; + break; + + case 0x06: /* LAI */ + A = fetch_byte(1); + A &= BYTE_R; + break; + + case 0x07: /* RET */ + PC = pop_word(); + break; + + case 0x08: /* INB */ + B++; + setflag3(B); + B &= BYTE_R; + break; + + case 0x09: /* DCB */ + B--; + setflag3(B); + B &= BYTE_R; + break; + + case 0x0A: /* RRC */ + if (A & 0x01) + CF = 1; + else + CF = 0; + A = (A >> 1) & 0xFF; + if (CF) + A |= 0x80; + A &= BYTE_R; + break; + + case 0x0B: /* RFZ */ + if (ZF) + ; + else + PC = pop_word(); + break; + + case 0x0C: /* ACI */ + A += fetch_byte(1); + if (CF) + A++; + setflag3(A); + A &= BYTE_R; + break; + + case 0x0E: /* LBI */ + B = fetch_byte(1); + B &= BYTE_R; + break; + + case 0x0F: /* *RET */ + PC = pop_word(); + break; + + case 0x10: /* INC */ + C++; + setflag3(C); + C &= BYTE_R; + break; + + case 0x11: /* DCC */ + C--; + setflag3(C); + C &= BYTE_R; + break; + + case 0x12: /* RAL */ + if (A & 0x80) + CF = 1; + else + CF = 0; + A = (A << 1) & 0xFF; + if (CF) + A |= 0x01; + A &= BYTE_R; + break; + + case 0x13: /* RFS */ + if (SF) + ; + else + PC = pop_word(); + break; + + case 0x14: /* SUI */ + A -= fetch_byte(1); + setflag3(A); + A &= BYTE_R; + break; + + case 0x16: /* LCI */ + C = fetch_byte(1); + C &= BYTE_R; + break; + + case 0x17: /* *RET */ + PC = pop_word(); + break; + + case 0x18: /* IND */ + D++; + setflag3(D); + D &= BYTE_R; + break; + + case 0x19: /* DCD */ + D--; + setflag3(D); + D &= BYTE_R; + break; + + case 0x1A: /* RAR */ + if (A & 0x01) + CF = 1; + else + CF = 0; + A = (A >> 1) & 0xFF; + if (CF) + A |= 0x80; + A &= BYTE_R; + break; + + case 0x1B: /* RFP */ + if (PF) + ; + else + PC = pop_word(); + break; + + case 0x1C: /* SBI */ + A -= fetch_byte(1); + if (CF) + A--; + setflag3(A); + A &= BYTE_R; + break; + + case 0x1E: /* LDI */ + D = fetch_byte(1); + D &= BYTE_R; + break; + + case 0x1F: /* *RET */ + PC = pop_word(); + break; + + case 0x20: /* INE */ + E++; + setflag3(E); + E &= BYTE_R; + break; + + case 0x21: /* DCE */ + E--; + setflag3(E); + E &= BYTE_R; + break; + + case 0x23: /* RTC */ + if (CF) + PC = pop_word(); + break; + + case 0x24: /* NDI */ + A &= fetch_byte(1); + setflag3(A); + A &= BYTE_R; + break; + + case 0x26: /* LEI */ + E = fetch_byte(1); + E &= BYTE_R; + break; + + case 0x27: /* *RET */ + PC = pop_word(); + break; + + case 0x28: /* INH */ + H++; + setflag3(H); + H &= BYTE_R; + break; + + case 0x29: /* DCH */ + H--; + setflag3(H); + H &= BYTE_R; + break; + + case 0x2B: /* RTZ */ + if (ZF) + PC = pop_word(); + break; + + case 0x2C: /* XRI */ + A ^= fetch_byte(1); + setflag3(A); + break; + + case 0x2E: /* LHI */ + H = fetch_byte(1); + H &= BYTE_R; + break; + + case 0x2F: /* *RET */ + PC = pop_word(); + break; + + case 0x30: /* INL */ + L++; + setflag3(L); + L &= BYTE_R; + break; + + case 0x31: /* DCL */ + L--; + setflag3(L); + L &= BYTE_R; + break; + + case 0x33: /* RTS */ + if (SF) + PC = pop_word(); + break; + + case 0x34: /* ORI */ + A |= fetch_byte(1); + setflag3(A); + A &= BYTE_R; + break; + + case 0x36: /* LLI */ + L = fetch_byte(1); + L &= BYTE_R; + break; + + case 0x37: /* *RET */ + PC = pop_word(); + break; + + case 0x3B: /* RTP */ + if (PF) + PC = pop_word(); + break; + + case 0x3C: /* CPI */ + DAR = A; + DAR -= fetch_byte(1); + setflag3(DAR); + break; + + case 0x3E: /* LMI */ + val = fetch_byte(1); + store_m(val); + break; + + case 0x3F: /* *RET */ + PC = pop_word(); + break; + + case 0x40: /* JFC */ + DAR = fetch_word(); + if (CF) + ; + else + PC = DAR; + break; + + case 0x41: /* INP 0 */ + case 0x43: /* INP 1 */ + case 0x45: /* INP 2 */ + case 0x47: /* INP 3 */ + case 0x49: /* INP 4 */ + case 0x4B: /* INP 5 */ + case 0x4D: /* INP 6 */ + case 0x4F: /* INP 7 */ + /**** fix me! */ + break; + + case 0x42: /* CFC */ + adr = fetch_word(); + if (CF) + ; + else { + push_word(PC); + PC = adr; + } + break; + + case 0x44: /* JMP */ + PC = fetch_word(); + break; + + case 0x46: /* CAL */ + adr = fetch_word(); + push_word(PC); + PC = adr; + break; + + case 0x48: /* JFZ */ + DAR = fetch_word(); + if (ZF) + ; + else + PC = DAR; + break; + + case 0x4A: /* CFZ */ + adr = fetch_word(); + if (ZF) + ; + else { + push_word(PC); + PC = adr; + } + break; + + case 0x4C: /* *JMP */ + PC = fetch_word(); + break; + + case 0x4E: /* *CAL */ + adr = fetch_word(); + push_word(PC); + PC = adr; + break; + + case 0x50: /* JFS */ + DAR = fetch_word(); + if (SF) + ; + else + PC = DAR; + break; + + case 0x51: /* OUT 8 */ + case 0x53: /* OUT 9 */ + case 0x55: /* OUT 10 */ + case 0x57: /* OUT 11 */ + case 0x59: /* OUT 12 */ + case 0x5B: /* OUT 13 */ + case 0x5D: /* OUT 14 */ + case 0x5E: /* OUT 15 */ + case 0x61: /* OUT 16 */ + case 0x63: /* OUT 17 */ + case 0x65: /* OUT 18 */ + case 0x67: /* OUT 19 */ + case 0x69: /* OUT 20 */ + case 0x6B: /* OUT 21 */ + case 0x6D: /* OUT 22 */ + case 0x6E: /* OUT 23 */ + case 0x71: /* OUT 24 */ + case 0x73: /* OUT 25 */ + case 0x75: /* OUT 26 */ + case 0x77: /* OUT 27 */ + case 0x79: /* OUT 28 */ + case 0x7B: /* OUT 29 */ + case 0x7D: /* OUT 30 */ + case 0x7E: /* OUT 31 */ + /**** fix me! */ + break; + + case 0x52: /* CFS */ + adr = fetch_word(); + if (SF) + ; + else { + push_word(PC); + PC = adr; + } + break; + + case 0x54: /* *JMP */ + PC = fetch_word(); + break; + + case 0x56: /* *CAL */ + adr = fetch_word(); + push_word(PC); + PC = adr; + break; + + case 0x58: /* JFP */ + DAR = fetch_word(); + if (PF) + ; + else + PC = DAR; + break; + + case 0x5A: /* CFP */ + adr = fetch_word(); + if (PF) + ; + else { + push_word(PC); + PC = adr; + } + break; + + case 0x5C: /* *JMP */ + PC = fetch_word(); + break; + + case 0x5E: /* *CAL */ + adr = fetch_word(); + push_word(PC); + PC = adr; + break; + + case 0x60: /* JTC */ + DAR = fetch_word(); + if (CF) + PC = DAR; + break; + + case 0x62: /* CTC */ + adr = fetch_word(); + if (CF) { + push_word(PC); + PC = adr; + } + break; + + case 0x64: /* *JMP */ + PC = fetch_word(); + break; + + case 0x66: /* *CAL */ + adr = fetch_word(); + push_word(PC); + PC = adr; + break; + + case 0x68: /* JTZ */ + DAR = fetch_word(); + if (ZF) + PC = DAR; + break; + + case 0x6A: /* CTZ */ + adr = fetch_word(); + if (ZF) { + push_word(PC); + PC = adr; + } + break; + + case 0x6C: /* *JMP */ + PC = fetch_word(); + break; + + case 0x6E: /* *CAL */ + adr = fetch_word(); + push_word(PC); + PC = adr; + break; + + case 0x70: /* JTS */ + DAR = fetch_word(); + if (SF) + PC = DAR; + break; + + case 0x72: /* CTS */ + adr = fetch_word(); + if (SF) { + push_word(PC); + PC = adr; + } + break; + + case 0x74: /* *JMP */ + PC = fetch_word(); + break; + + case 0x76: /* *CAL */ + adr = fetch_word(); + push_word(PC); + PC = adr; + break; + + case 0x78: /* JTP */ + DAR = fetch_word(); + if (PF) + PC = DAR; + break; + + case 0x7A: /* CTP */ + adr = fetch_word(); + if (PF) { + push_word(PC); + PC = adr; + } + break; + + case 0x7C: /* *JMP */ + PC = fetch_word(); + break; + + case 0x7E: /* *CAL */ + adr = fetch_word(); + push_word(PC); + PC = adr; + break; + + case 0x80: /* ADA */ + A += A; + setflag4(A); + A &= BYTE_R; + break; + + case 0x81: /* ADB */ + A += B; + setflag4(A); + A &= BYTE_R; + break; + + case 0x82: /* ADC */ + A += C; + setflag4(A); + A &= BYTE_R; + break; + + case 0x83: /* ADD */ + A += D; + setflag4(A); + A &= BYTE_R; + break; + + case 0x84: /* ADE */ + A += E; + setflag4(A); + A &= BYTE_R; + break; + + case 0x85: /* ADH */ + A += H; + setflag4(A); + A &= BYTE_R; + break; + + case 0x86: /* ADL */ + A += L; + setflag4(A); + A &= BYTE_R; + break; + + case 0x87: /* ADM */ + A += fetch_m(); + setflag4(A); + A &= BYTE_R; + break; + + case 0x88: /* ACA */ + A += A; + if (CF) + A++; + setflag4(A); + A &= BYTE_R; + break; + + case 0x89: /* ACB */ + A += B; + if (CF) + A++; + setflag4(A); + A &= BYTE_R; + break; + + case 0x8A: /* ACC */ + A += C; + if (CF) + A++; + setflag4(A); + A &= BYTE_R; + break; + + case 0x8B: /* ACD */ + A += D; + if (CF) + A++; + setflag4(A); + A &= BYTE_R; + break; + + case 0x8C: /* ACE */ + A += E; + if (CF) + A++; + setflag4(A); + A &= BYTE_R; + break; + + case 0x8D: /* ACH */ + A += H; + if (CF) + A++; + setflag4(A); + A &= BYTE_R; + break; + + case 0x8E: /* ACL */ + A += L; + if (CF) + A++; + setflag4(A); + A &= BYTE_R; + break; + + case 0x8F: /* ACM */ + A += fetch_m(); + if (CF) + A++; + setflag4(A); + A &= BYTE_R; + break; + + case 0x90: /* SUA */ + A -= A; + setflag4(A); + A &= BYTE_R; + break; + + case 0x91: /* SUB */ + A -= B; + setflag4(A); + A &= BYTE_R; + break; + + case 0x92: /* SUC */ + A -= C; + setflag4(A); + A &= BYTE_R; + break; + + case 0x93: /* SUD */ + A -= D; + setflag4(A); + A &= BYTE_R; + break; + + case 0x94: /* SUE */ + A -= E; + setflag4(A); + A &= BYTE_R; + break; + + case 0x95: /* SUH */ + A -= H; + setflag4(A); + A &= BYTE_R; + break; + + case 0x96: /* SUL */ + A -= L; + setflag4(A); + A &= BYTE_R; + break; + + case 0x97: /* SUM */ + A -= fetch_m(); + setflag4(A); + A &= BYTE_R; + break; + + case 0x98: /* SBA */ + A -= A; + if (CF) + A--; + setflag4(A); + A &= BYTE_R; + break; + + case 0x99: /* SBB */ + A -= B; + if (CF) + A--; + setflag4(A); + A &= BYTE_R; + break; + + case 0x9A: /* SBC */ + A -= C; + if (CF) + A--; + setflag4(A); + A &= BYTE_R; + break; + + case 0x9B: /* SBD */ + A -= D; + if (CF) + A--; + setflag4(A); + A &= BYTE_R; + break; + + case 0x9C: /* SBE */ + A -= E; + if (CF) + A--; + setflag4(A); + A &= BYTE_R; + break; + + case 0x9D: /* SBH */ + A -= H; + if (CF) + A--; + setflag4(A); + A &= BYTE_R; + break; + + case 0x9E: /* SBL */ + A -= L; + if (CF) + A--; + setflag4(A); + A &= BYTE_R; + break; + + case 0x9F: /* SBM */ + A -= fetch_m(); + if (CF) + A - ; + setflag4(A); + A &= BYTE_R; + break; + + case 0xA0: /* NDA */ + A &= A; + setflag4(A); + A &= BYTE_R; + break; + + case 0xA1: /* NDB */ + A &= B; + setflag4(A); + A &= BYTE_R; + break; + + case 0xA2: /* NDC */ + A &= C; + setflag4(A); + A &= BYTE_R; + break; + + case 0xA3: /* NDD */ + A &= D; + setflag4(A); + A &= BYTE_R; + break; + + case 0xA4: /* NDE */ + A &= E; + setflag4(A); + A &= BYTE_R; + break; + + case 0xA5: /* NDH */ + A &= H; + setflag4(A); + A &= BYTE_R; + break; + + case 0xA6: /* NDL */ + A &= L; + setflag4(A); + A &= BYTE_R; + break; + + case 0xA7: /* NDM */ + A &= fetch_m(); + setflag4(A); + A &= BYTE_R; + break; + + case 0xA8: /* XRA */ + A ^= A; + setflag4(A); + A &= BYTE_R; + break; + + case 0xA9: /* XRB */ + A ^= B; + setflag4(A); + A &= BYTE_R; + break; + + case 0xAA: /* XRC */ + A ^= C; + setflag4(A); + A &= BYTE_R; + break; + + case 0xAB: /* XRD */ + A ^= D; + setflag4(A); + A &= BYTE_R; + break; + + case 0xAC: /* XRE */ + A ^= E; + setflag4(A); + A &= BYTE_R; + break; + + case 0xAD: /* XRH */ + A ^= H; + setflag4(A); + A &= BYTE_R; + break; + + case 0xAE: /* XRL */ + A ^= L; + setflag4(A); + A &= BYTE_R; + break; + + case 0xAF: /* XRM */ + A |= fetch_m(); + setflag4(A); + A &= BYTE_R; + break; + + case 0xB0: /* ORA */ + A |= A; + setflag4(A); + A &= BYTE_R; + break; + + case 0xB1: /* ORB */ + A |= B; + setflag4(A); + A &= BYTE_R; + break; + + case 0xB2: /* ORC */ + A |= C; + setflag4(A); + A &= BYTE_R; + break; + + case 0xB3: /* ORD */ + A |= D; + setflag4(A); + A &= BYTE_R; + break; + + case 0xB4: /* ORE */ + A |= E; + setflag4(A); + A &= BYTE_R; + break; + + case 0xB5: /* ORH */ + A |= H; + setflag4(A); + A &= BYTE_R; + break; + + case 0xB6: /* ORL */ + A |= L; + setflag4(A); + A &= BYTE_R; + break; + + case 0xB7: /* ORM */ + A |= fetch_m(); + setflag4(A); + A &= BYTE_R; + break; + + case 0xB8: /* CPA */ + DAR -= A; + setflag4(DAR); + A &= BYTE_R; + break; + + case 0xB9: /* CPB */ + DAR -= B; + setflag4(DAR); + A &= BYTE_R; + break; + + case 0xBA: /* CPC */ + DAR -= C; + setflag4(DAR); + A &= BYTE_R; + break; + + case 0xBB: /* CPD */ + DAR -= D; + setflag4(DAR); + A &= BYTE_R; + break; + + case 0xBC: /* CPE */ + DAR -= E; + setflag4(DAR); + A &= BYTE_R; + break; + + case 0xBD: /* CPH */ + DAR -= H; + setflag4(DAR); + A &= BYTE_R; + break; + + case 0xBE: /* CPL */ + DAR -= L; + setflag4(DAR); + A &= BYTE_R; + break; + + case 0xBF: /* CPM */ + DAR -= fetch_m(); + setflag4(DAR); + A &= BYTE_R; + break; + + case 0xC0: /* NOP */ + break; + + case 0xC1: /* LAB */ + A = B; + A &= BYTE_R; + break; + + case 0xC2: /* LAC */ + A = C; + A &= BYTE_R; + break; + + case 0xC3: /* LAD */ + A = D; + A &= BYTE_R; + break; + + case 0xC4: /* LAE */ + A = E; + A &= BYTE_R; + break; + + case 0xC5: /* LAH */ + A = H; + A &= BYTE_R; + break; + + case 0xC6: /* LAL */ + A = L; + A &= BYTE_R; + break; + + case 0xC7: /* LAM */ + A = FETCH_M(); + A &= BYTE_R; + break; + + case 0xC8: /* LBA */ + B = A; + B &= BYTE_R; + break; + + case 0xC9: /* LBB */ + B = B; + B &= BYTE_R; + break; + + case 0xCA: /* LBC */ + B = C; + B &= BYTE_R; + break; + + case 0xCB: /* LBD */ + B = D; + B &= BYTE_R; + break; + + case 0xCC: /* LBE */ + B = E; + B &= BYTE_R; + break; + + case 0xCD: /* LBH */ + B = H; + B &= BYTE_R; + break; + + case 0xCE: /* LBL */ + B = L; + B &= BYTE_R; + break; + + case 0xCF: /* LBM */ + B = FETCH_M(); + B &= BYTE_R; + break; + + case 0xD0: /* LCA */ + C = A; + C &= BYTE_R; + break; + + case 0xD1: /* LCB */ + C = B; + C &= BYTE_R; + break; + + case 0xD2: /* LCC */ + C = C; + C &= BYTE_R; + break; + + case 0xD3: /* LCD */ + C = D; + C &= BYTE_R; + break; + + case 0xD4: /* LCE */ + C = E; + C &= BYTE_R; + break; + + case 0xD5: /* LCH */ + C = H; + C &= BYTE_R; + break; + + case 0xD6: /* LCL */ + C = L; + C &= BYTE_R; + break; + + case 0xD7: /* LCM */ + C = FETCH_M(); + C &= BYTE_R; + break; + + case 0xD8: /* LDA */ + D = A; + D &= BYTE_R; + break; + + case 0xD9: /* LDB */ + D = B; + D &= BYTE_R; + break; + + case 0xDA: /* LDC */ + D = C; + D &= BYTE_R; + break; + + case 0xDB: /* LDD */ + D = D; + D &= BYTE_R; + break; + + case 0xDC: /* LDE */ + D = E; + D &= BYTE_R; + break; + + case 0xDD: /* LDH */ + D = H; + D &= BYTE_R; + break; + + case 0xDE: /* LDL */ + D = L; + D &= BYTE_R; + break; + + case 0xDF: /* LDM */ + D = FETCH_M(); + D &= BYTE_R; + break; + + case 0xE0: /* LEA */ + E = A; + E &= BYTE_R; + break; + + case 0xE1: /* LEB */ + E = B; + E &= BYTE_R; + break; + + case 0xE2: /* LEC */ + E = C; + E &= BYTE_R; + break; + + case 0xE3: /* LED */ + E = D; + E &= BYTE_R; + break; + + case 0xE4: /* LEE */ + E = E; + E &= BYTE_R; + break; + + case 0xE5: /* LEH */ + E = H; + E &= BYTE_R; + break; + + case 0xE6: /* LEL */ + E = L; + E &= BYTE_R; + break; + + case 0xE7: /* LEM */ + E = FETCH_M(); + E &= BYTE_R; + break; + + case 0xE8: /* LHA */ + H = A; + H &= BYTE_R; + break; + + case 0xE9: /* LHB */ + H = B; + H &= BYTE_R; + break; + + case 0xEA: /* LHC */ + H = C; + H &= BYTE_R; + break; + + case 0xEB: /* LHD */ + H = D; + H &= BYTE_R; + break; + + case 0xEC: /* LHE */ + H = E; + H &= BYTE_R; + break; + + case 0xED: /* LHH */ + H = H; + H &= BYTE_R; + break; + + case 0xEE: /* LHL */ + H = L; + H &= BYTE_R; + break; + + case 0xEF: /* LHM */ + H = FETCH_M(); + H &= BYTE_R; + break; + + case 0xF0: /* LLA */ + L = A; + L &= BYTE_R; + break; + + case 0xF1: /* LLB */ + L = B; + L &= BYTE_R; + break; + + case 0xF2: /* LLC */ + L = C; + L &= BYTE_R; + break; + + case 0xF3: /* LLD */ + L = D; + L &= BYTE_R; + break; + + case 0xF4: /* LLE */ + L = E; + L &= BYTE_R; + break; + + case 0xF5: /* LLH */ + L = H; + L &= BYTE_R; + break; + + case 0xF6: /* LLL */ + L = L; + L &= BYTE_R; + break; + + case 0xF7: /* LLM */ + L = FETCH_M(); + L &= BYTE_R; + break; + + case 0xF8: /* LMA */ + store_m(A); + break; + + case 0xF9: /* LMB */ + store_m(B); + break; + + case 0xFA: /* LMC */ + store_m(C); + break; + + case 0xFB: /* LMD */ + store_m(D); + break; + + case 0xFC: /* LME */ + store_m(E); + break; + + case 0xFD: /* LMH */ + store_m(H); + break; + + case 0xFE: /* LML */ + store_m(L); + break; + + case 0xFF: /* LMM */ + val = FETCH_M(); + store_m(val); + break; + + default: /* undefined opcode */ + if (i8008_unit.flags & UNIT_OPSTOP) { + reason = STOP_OPCODE; + PC--; + } + break; + } + } + +/* Simulation halted */ + + saved_PC = PC; + return reason; +} + +/* store byte to (HL) */ +void store_m(uint32 val) +{ + DAR = (H << 8) + L; + DAR &= WORD_R14; + ret get_mword(DAR); +} + +/* get byte from (HL) */ +uint32 fetch_m(void) +{ + DAR = (H << 8) + L; + DAR &= WORD_R14; + put_mword(DAR, val); +} + +/* dump the registers */ +void dumpregs(void) +{ + sim_printf(" A=%02X B=%02X C=%02X D=%04X E=%02X H=%04X L=%02X\n", + A, B, C, D, E, H, L); + sim_printf(" CF=%d ZF=%d SF=%d PF=%d\n", + CF, ZF, SF, PF); +} + +/* fetch an instruction or byte */ +int32 fetch_byte(int32 flag) +{ + uint32 val; + + val = get_mbyte(PC) & 0xFF; /* fetch byte */ + if (i8008_dev.dctrl & DEBUG_asm || uptr->flags & UNIT_TRACE) { /* display source code */ + switch (flag) { + case 0: /* opcode fetch */ + sim_printf("OP=%02X %04X %s", val, PC, opcode[val]); + break; + case 1: /* byte operand fetch */ + sim_printf("0%02XH", val); + break; + } + } + PC = (PC + 1) & ADDRMASK; /* increment PC */ + val &= BYTE_R; + return val; +} + +/* fetch a word */ +int32 fetch_word(void) +{ + uint16 val; + + val = get_mbyte(PC) & BYTE_R; /* fetch low byte */ + val |= get_mbyte(PC + 1) << 8; /* fetch high byte */ + if (i8008_dev.dctrl & DEBUG_asm || uptr->flags & UNIT_TRACE) /* display source code */ + sim_printf("0%04XH", val); + PC = (PC + 2) & ADDRMASK; /* increment PC */ + val &= WORD_R14; + return val; +} + +/* push a word to the stack frame */ +void push_word(uint16 val) +{ + stack_frame[SP] = val; + SP++; + if (SP == 8) + SP = 0; +} + +/* pop a word from the stack frame */ +uint16 pop_word(void) +{ + SP--; + if (SP < 0) + SP = 7; + return stack_frame[SP]; +} + + +/* Set the arry, ign, ero and verflow flags following + an operation on 'reg'. +*/ + +void setflag4(int32 reg) +{ + if (reg & 0x100) + CF = 1; + else + CF = 0; + if (reg & 0x80) + SF = 0; + else + SF = 1; + if ((reg & BYTE_R) == 0) + ZF = 1; + else + ZF = 0; + parity(reg); +} + +/* Set the arry, ign and ero flags following + an operation on 'reg'. +*/ + +void setflag3(int32 reg) +{ + CF = 0; + if (reg & 0x80) + SF = 0; + else + SF = 1; + if ((reg & BYTE_R) == 0) + ZF = 1; + else + ZF = 0; + parity(reg); +} + +/* Set the Parity (PF) flag based on parity of 'reg', i.e., number +of bits on even: PF=1, else PF=0 +*/ + +void parity(int32 reg) +{ + int32 bc = 0; + + if (reg & 0x01) bc++; + if (reg & 0x02) bc++; + if (reg & 0x04) bc++; + if (reg & 0x08) bc++; + if (reg & 0x10) bc++; + if (reg & 0x20) bc++; + if (reg & 0x40) bc++; + if (reg & 0x80) bc++; + if (bc & 0x01) + PF = 0; + else + PF = 1; +} + + + +/* Reset routine */ + +t_stat i8008_reset (DEVICE *dptr) +{ + int i; + + CF = SF = ZF = PF = 0; + saved_PC = 0; + int_req = 0; + for (i = 0; i < 7; i++) + stack_frame[i] = 0; + sim_brk_types = sim_brk_dflt = SWMASK ('E'); + sim_printf(" 8008: Reset\n"); + return SCPE_OK; +} + +/* Memory examine */ + +t_stat i8008_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 i8008_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. +*/ + +int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag) +{ + int32 i, addr = 0, cnt = 0; + + if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; + addr = saved_PC; + while ((i = getc (fileref)) != EOF) { + put_mbyte(addr, i); + addr++; + cnt++; + } /* end while */ + sim_printf ("%d Bytes loaded.\n", cnt); + return (SCPE_OK); +} + +/* Symbolic output + + Inputs: + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches + Outputs: + status = error code +*/ + +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 == &i8008_unit); + c1 = (val[0] >> 8) & 0x7F; + c2 = val[0] & 0x7F; + if (sw & SWMASK ('A')) { + fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2); + return SCPE_OK; + } + if (sw & SWMASK ('C')) { + fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); + fprintf (of, (c2 < 0x20)? "<%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, "%h", 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, "%h", adr); + } + return -(oplen[inst] - 1); +} + +/* Symbolic input + + Inputs: + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches + Outputs: + status = error status +*/ + +t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) +{ + int32 cflag, i = 0, j, r; + char gbuf[CBUFSIZE]; + + cflag = (uptr == NULL) || (uptr == &i8008_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 (1) { + 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++; + } + +/* 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); +} diff --git a/Intel-Systems/common/i8088.c b/Intel-Systems/common/i8088.c index 0349ad77..c971cba1 100644 --- a/Intel-Systems/common/i8088.c +++ b/Intel-Systems/common/i8088.c @@ -1,4742 +1,4742 @@ -/* 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. - I modified it to allow emulation of Intel iSBC Single Board Computers. - - 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 "multibus_defs.h" - -#define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */ -#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) -#define UNIT_V_8088 (UNIT_V_UF+1) /* 8088 or 8086 */ -#define UNIT_8088 (1 << UNIT_V_8088) - -/* 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) - -/* macros for handling IP and SP */ -#define INC_IP1 (++IP & ADDRMASK20) /* increment IP one byte */ -#define INC_IP2 ((IP += 2) & ADDRMASK20) /* increment IP two bytes */ - -/* 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 */ -int32 IP; /* Program Counter */ -int32 PSW; /* Program Status Word (Flags) */ -int32 saved_PC = 0; /* saved program counter */ -int32 int_req = 0; /* Interrupt request */ -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); - -/* emulator primitives */ -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); - -/* simulator routines */ -int32 sim_instr(void); -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 */ -//extern t_stat i8088_reset (DEVICE *dptr); - -/* Multibus memory read and write absolute address routines */ -extern int32 get_mbyte(int32 addr); -extern int32 get_mword(int32 addr); -extern void put_mbyte(int32 addr, int32 val); -extern void put_mword(int32 addr, int32 val); - -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - -/* This is the I/O configuration table. There are 65536 possible -device addresses, if a device is plugged to a port it's routine -address is here, 'nulldev' means no device is available -*/ - -struct idev { - int32 (*routine)(); -}; -extern struct idev dev_table[]; - -/* 8088 CPU data structures - - i8088_dev CPU device descriptor - i8088_unit CPU unit descriptor - i8088_reg CPU register list - i8088_mod CPU modifiers list -*/ - -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_8088, UNIT_8088, "8086", "8086", NULL }, - { UNIT_8088, 0, "8088", "8088", NULL }, - { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL }, - { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL }, - { 0 } -}; - -DEBTAB i8088_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { "REG", DEBUG_reg }, - { "ASM", DEBUG_asm }, - { NULL } -}; - -DEVICE i8088_dev = { - "I8088", //name - &i8088_unit, //units - i8088_reg, //registers - i8088_mod, //modifiers - 1, //numunits - 16, //aradix - 20, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - &i8088_ex, //examine - &i8088_dep, //deposit - &i8088_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - i8088_debug, //debflags - NULL, //msize - NULL //lname -}; - -uint8 xor_3_tab[] = { 0, 1, 1, 0 }; - -int32 IP; - -static const char *opcode[] = { -"ADD ", "ADD ", "ADD ", "ADD ", /* 0x00 */ -"ADD AL,", "ADD AX,", "PUSH ES", "POP ES", -"OR ", "OR ", "OR ", "OR ", -"OR AL,", "OR AX,", "PUSH CS", "???", -"ADC ", "ADC ", "ADC ", "ADC ", /* 0x10 */ -"ADC AL,", "ADC AX,", "PUSH SS", "RPOP SS", -"SBB ", "SBB ", "SBB ", "SBB ", -"SBB AL,", "SBB AX,", "PUSH DS", "POP DS", -"AND ", "AND ", "AND ", "AND ", /* 0x20 */ -"AND AL,", "AND AX,", "ES:", "DAA", -"SUB ", "SUB ", "SUB ", "SUB ", -"SUB AL,", "SUB AX,", "CS:", "DAS", -"XOR ", "XOR ", "XOR ", "XOR ", /* 0x30 */ -"XOR AL,", "XOR AX,", "SS:", "AAA", -"CMP ", "CMP ", "CMP ", "CMP ", -"CMP AL,", "CMP AX,", "DS:", "AAS", -"INC AX", "INC CX", "INC DX", "INC BX", /* 0x40 */ -"INC SP", "INC BP", "INC SI", "INC DI", -"DEC AX", "DEC CX", "DEC DX", "DEC BX", -"DEC SP", "DEC BP", "DEC SI", "DEC DI", -"PUSH AX", "PUSH CX", "PUSH DX", "PUSH BX", /* 0x50 */ -"PUSH SP", "PUSH BP", "PUSH SI", "PUSH DI", -"POP AX", "POP CX", "POP DX", "POP BX", -"POP SP", "POP BP", "POP SI", "POP DI", -"???", "???", "???", "???", /* 0x60 */ -"???", "???", "???", "???", -"PUSH ", "IMUL ", "PUSH ", "IMUL ", -"INSB", "INSW", "OUTSB", "OUTSW", -"JO ", "JNO ", "JC ", "JNC", /* 0x70 */ -"JZ ", "JNZ ", "JNA ", "JA", -"JS ", "JNS ", "JP ", "JNP ", -"JL ", "JNL ", "JLE ", "JNLE", -"???", "???", "???", "???", /* 0x80 */ -"TEST ", "TEST ", "XCHG ", "XCHG ", -"MOV ", "MOV ", "MOV ", "MOV ", -"MOV ", "LEA ", "MOV ", "POP ", -"NOP", "XCHG AX,CX", "XCHG AX,DX", "XCHG AX,BX",/* 0x90 */ -"XCHG AX,SP", "XCHG AX,BP", "XCHG AX,SI", "XCHG AX,DI", -"CBW", "CWD", "CALL ", "WAIT", -"PUSHF", "POPF", "SAHF", "LAHF", -"MOV AL,", "MOV AX,", "MOV ", "MOV ", /* 0xA0 */ -"MOVSB", "MOVSW", "CMPSB", "CMPSW", -"TEST AL,", "TEST AX,", "STOSB", "STOSW", -"LODSB", "LODSW", "SCASB", "SCASW", -"MOV AL,", "MOV CL,", "MOV DL,", "MOV BL,", /* 0xB0 */ -"MOV AH,", "MOV CH,", "MOV DH,", "MOV BH,", -"MOV AX,", "MOV CX,", "MOV DX,", "MOV BX,", -"MOV SP,", "MOV BP,", "MOV SI,", "MOV DI," -" ", " ", "RET ", "RET ", /* 0xC0 */ -"LES ", "LDS ", "MOV ", "MOV ", -"???", "???", "RET ", "RET", -"INT 3", "INT ", "INTO", "IRET", -" ", " ", " ", " ", /* 0xD0 */ -"AAM", "AAD", "???", "XLATB", -"ESC ", "ESC ", "ESC ", "ESC ", -"ESC ", "ESC ", "ESC ", "ESC ", -"LOOPNZ ", "LOOPZ ", "LOOP", "JCXZ", /* 0xE0 */ -"IN AL,", "IN AX,", "OUT ", "OUT ", -"CALL ", "JMP ", "JMP ", "JMP ", -"IN AL,DX", "IN AX,DX", "OUT DX,AL", "OUT DX,AX", -"LOCK", "???", "REPNZ", "REPZ", /* 0xF0 */ -"HLT", "CMC", " ", " ", -"CLC", "STC", "CLI", "STI", -"CLD", "STD", "???", "???" - }; - -int32 oplen[256] = { -1,3,1,1,1,1,2,1,0,1,1,1,1,1,2,1, -0,3,1,1,1,1,2,1,0,1,1,1,1,1,2,1, -0,3,3,1,1,1,2,1,0,1,3,1,1,1,2,1, -0,3,3,1,1,1,2,1,0,1,3,1,1,1,2,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,3,3,3,1,2,1,1,1,3,0,3,3,2,1, -1,1,3,2,3,1,2,1,1,0,3,2,3,0,2,1, -1,1,3,1,3,1,2,1,1,1,3,1,3,0,2,1, -1,1,3,1,3,1,2,1,1,1,3,1,3,0,2,1 -}; - -int32 sim_instr (void) -{ - extern int32 sim_interval; - int32 IR, OP, DAR, reason, hi, lo, carry, i, adr; - int32 MRR, REG, EA, MOD, RM, DISP, VAL, DATA, OFF, SEG, INC, VAL1; - - IP = saved_PC & ADDRMASK16; /* load local IP */ - 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 (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 ", CS, DS, ES, SS); - sim_printf("Flags: %04X\n", PSW); - } - - if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - } - - if (int_req > 0) { /* interrupt? */ - - /* 8088 interrupts not implemented yet. */ - - } /* end interrupt */ - - if (sim_brk_summ && - sim_brk_test (IP, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - - sim_interval--; /* countdown clock */ - PCX = IP; - IR = OP = fetch_byte(0); /* fetch instruction */ - - /* Handle below all operations which refer to registers or - register pairs. After that, a large switch statement - takes care of all other opcodes */ - - /* data transfer instructions */ - - /* arithmetic instructions */ - - /* bit manipulation instructions */ - /* string manipulation instructions */ - /* control transfer instructions */ - /* processor control instructions */ - /* The Big Instruction Decode Switch */ - - switch (IR) { - - /* data transfer instructions */ - /* arithmetic instructions */ - - 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_smbyte(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = or_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sbb_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = and_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sub_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rbyte(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: /* 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: /* INTO */ - 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 += (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 += (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 += (int16)IP; - CX -= 1; - if (CX != 0) /* CX != 0 */ - IP = OFF; - break; - - case 0xE3: /* JCXZ label */ - OFF = fetch_byte(1); - OFF += (int16)IP; - if (CX == 0) /* CX != 0 */ - IP = OFF; - break; - - case 0xE4: /* IN AL,immed8 */ - OFF = fetch_byte(1); - AL = dev_table[OFF].routine(0, 0); - break; - - case 0xE5: /* IN AX,immed8 */ - OFF = fetch_byte(1); - AH = dev_table[OFF].routine(0, 0); - AL = dev_table[OFF+1].routine(0, 0); - break; - - case 0xE6: /* OUT AL,immed8 */ - OFF = fetch_byte(1); - dev_table[OFF].routine(1, AL); - break; - - case 0xE7: /* OUT AX,immed8 */ - OFF = fetch_byte(1); - dev_table[OFF].routine(1, AH); - dev_table[OFF+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 */ - AL = dev_table[DX].routine(0, 0); - break; - - case 0xED: /* IN AX,DX */ - AH = dev_table[DX].routine(0, 0); - AL = dev_table[DX+1].routine(0, 0); - break; - - case 0xEE: /* OUT AL,DX */ - dev_table[DX].routine(1, AL); - break; - - case 0xEF: /* OUT AX,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; - } - } - - /* Simulation halted */ - 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 */ -// sim_printf("%04X:%04X %s", CS, IP, opcode[val]); - sim_printf("%04X:%04X %02X", CS, IP, val); - break; - case 1: /* byte operand fetch */ - sim_printf(" %02X", val); - break; - } - } - IP = INC_IP1; /* increment IP */ - 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); - sim_printf(" %04X", val); - IP = INC_IP2; /* increment IP */ - 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; - - 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; - - 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_ovr = reg; -} - -/* return effective address from mrr - also set seg_reg */ - -uint32 get_ea(uint32 mrr) -{ - uint32 MOD, REG, RM, DISP, EA; - - 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: MRR=%02X MOD=%02X REG=%02X R/M=%02X DISP=%04X EA=%04X\n", - mrr, MOD, REG, RM, 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; -} - -/* - 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(SS, SP, val >> 8); - SP--; - put_smbyte(SS, SP, val & 0xFF); -} - -/* pop word primitive */ -uint16 pop_word(void) -{ - register uint16 res; - - res = get_smbyte(SS, SP); - SP++; - res |= (get_smbyte(SS, SP) << 8); - 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); -// sim_printf("get_smbyte: seg=%04X addr=%04X abs_addr=%08X get_mbyte=%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); -} - -/* 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) -{ - if (addr >= MAXMEMSIZE20) - return SCPE_NXM; - if (vptr != NULL) - *vptr = get_mbyte(addr); - return SCPE_OK; -} - -/* Memory deposit */ - -t_stat i8088_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ - if (addr >= MAXMEMSIZE20) - 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. -*/ - -int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ - int32 i, addr = 0, cnt = 0; - - if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; - addr = saved_PC; - while ((i = getc (fileref)) != EOF) { - put_mbyte(addr, i); - addr++; - cnt++; - } /* end while */ - sim_printf ("%d Bytes loaded.\n", cnt); - return (SCPE_OK); -} - -/* Symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -int32 fprint_sym (FILE *of, int32 addr, uint32 *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, "%h", 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, "%h", adr); - } - return -(oplen[inst] - 1); -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw) -{ - int32 cflag, i = 0, j, r; - char gbuf[CBUFSIZE]; - - 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 (1) { - 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); -} +/* 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. + I modified it to allow emulation of Intel iSBC Single Board Computers. + + 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 "multibus_defs.h" + +#define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */ +#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) +#define UNIT_V_8088 (UNIT_V_UF+1) /* 8088 or 8086 */ +#define UNIT_8088 (1 << UNIT_V_8088) + +/* 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) + +/* macros for handling IP and SP */ +#define INC_IP1 (++IP & ADDRMASK20) /* increment IP one byte */ +#define INC_IP2 ((IP += 2) & ADDRMASK20) /* increment IP two bytes */ + +/* 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 */ +int32 IP; /* Program Counter */ +int32 PSW; /* Program Status Word (Flags) */ +int32 saved_PC = 0; /* saved program counter */ +int32 int_req = 0; /* Interrupt request */ +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); + +/* emulator primitives */ +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); + +/* simulator routines */ +int32 sim_instr(void); +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 */ +//extern t_stat i8088_reset (DEVICE *dptr); + +/* Multibus memory read and write absolute address routines */ +extern int32 get_mbyte(int32 addr); +extern int32 get_mword(int32 addr); +extern void put_mbyte(int32 addr, int32 val); +extern void put_mword(int32 addr, int32 val); + +extern int32 sim_int_char; +extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ + +/* This is the I/O configuration table. There are 65536 possible +device addresses, if a device is plugged to a port it's routine +address is here, 'nulldev' means no device is available +*/ + +struct idev { + int32 (*routine)(); +}; +extern struct idev dev_table[]; + +/* 8088 CPU data structures + + i8088_dev CPU device descriptor + i8088_unit CPU unit descriptor + i8088_reg CPU register list + i8088_mod CPU modifiers list +*/ + +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_8088, UNIT_8088, "8086", "8086", NULL }, + { UNIT_8088, 0, "8088", "8088", NULL }, + { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL }, + { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL }, + { 0 } +}; + +DEBTAB i8088_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { "REG", DEBUG_reg }, + { "ASM", DEBUG_asm }, + { NULL } +}; + +DEVICE i8088_dev = { + "I8088", //name + &i8088_unit, //units + i8088_reg, //registers + i8088_mod, //modifiers + 1, //numunits + 16, //aradix + 20, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + &i8088_ex, //examine + &i8088_dep, //deposit + &i8088_reset, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + i8088_debug, //debflags + NULL, //msize + NULL //lname +}; + +uint8 xor_3_tab[] = { 0, 1, 1, 0 }; + +int32 IP; + +static const char *opcode[] = { +"ADD ", "ADD ", "ADD ", "ADD ", /* 0x00 */ +"ADD AL,", "ADD AX,", "PUSH ES", "POP ES", +"OR ", "OR ", "OR ", "OR ", +"OR AL,", "OR AX,", "PUSH CS", "???", +"ADC ", "ADC ", "ADC ", "ADC ", /* 0x10 */ +"ADC AL,", "ADC AX,", "PUSH SS", "RPOP SS", +"SBB ", "SBB ", "SBB ", "SBB ", +"SBB AL,", "SBB AX,", "PUSH DS", "POP DS", +"AND ", "AND ", "AND ", "AND ", /* 0x20 */ +"AND AL,", "AND AX,", "ES:", "DAA", +"SUB ", "SUB ", "SUB ", "SUB ", +"SUB AL,", "SUB AX,", "CS:", "DAS", +"XOR ", "XOR ", "XOR ", "XOR ", /* 0x30 */ +"XOR AL,", "XOR AX,", "SS:", "AAA", +"CMP ", "CMP ", "CMP ", "CMP ", +"CMP AL,", "CMP AX,", "DS:", "AAS", +"INC AX", "INC CX", "INC DX", "INC BX", /* 0x40 */ +"INC SP", "INC BP", "INC SI", "INC DI", +"DEC AX", "DEC CX", "DEC DX", "DEC BX", +"DEC SP", "DEC BP", "DEC SI", "DEC DI", +"PUSH AX", "PUSH CX", "PUSH DX", "PUSH BX", /* 0x50 */ +"PUSH SP", "PUSH BP", "PUSH SI", "PUSH DI", +"POP AX", "POP CX", "POP DX", "POP BX", +"POP SP", "POP BP", "POP SI", "POP DI", +"???", "???", "???", "???", /* 0x60 */ +"???", "???", "???", "???", +"PUSH ", "IMUL ", "PUSH ", "IMUL ", +"INSB", "INSW", "OUTSB", "OUTSW", +"JO ", "JNO ", "JC ", "JNC", /* 0x70 */ +"JZ ", "JNZ ", "JNA ", "JA", +"JS ", "JNS ", "JP ", "JNP ", +"JL ", "JNL ", "JLE ", "JNLE", +"???", "???", "???", "???", /* 0x80 */ +"TEST ", "TEST ", "XCHG ", "XCHG ", +"MOV ", "MOV ", "MOV ", "MOV ", +"MOV ", "LEA ", "MOV ", "POP ", +"NOP", "XCHG AX,CX", "XCHG AX,DX", "XCHG AX,BX",/* 0x90 */ +"XCHG AX,SP", "XCHG AX,BP", "XCHG AX,SI", "XCHG AX,DI", +"CBW", "CWD", "CALL ", "WAIT", +"PUSHF", "POPF", "SAHF", "LAHF", +"MOV AL,", "MOV AX,", "MOV ", "MOV ", /* 0xA0 */ +"MOVSB", "MOVSW", "CMPSB", "CMPSW", +"TEST AL,", "TEST AX,", "STOSB", "STOSW", +"LODSB", "LODSW", "SCASB", "SCASW", +"MOV AL,", "MOV CL,", "MOV DL,", "MOV BL,", /* 0xB0 */ +"MOV AH,", "MOV CH,", "MOV DH,", "MOV BH,", +"MOV AX,", "MOV CX,", "MOV DX,", "MOV BX,", +"MOV SP,", "MOV BP,", "MOV SI,", "MOV DI," +" ", " ", "RET ", "RET ", /* 0xC0 */ +"LES ", "LDS ", "MOV ", "MOV ", +"???", "???", "RET ", "RET", +"INT 3", "INT ", "INTO", "IRET", +" ", " ", " ", " ", /* 0xD0 */ +"AAM", "AAD", "???", "XLATB", +"ESC ", "ESC ", "ESC ", "ESC ", +"ESC ", "ESC ", "ESC ", "ESC ", +"LOOPNZ ", "LOOPZ ", "LOOP", "JCXZ", /* 0xE0 */ +"IN AL,", "IN AX,", "OUT ", "OUT ", +"CALL ", "JMP ", "JMP ", "JMP ", +"IN AL,DX", "IN AX,DX", "OUT DX,AL", "OUT DX,AX", +"LOCK", "???", "REPNZ", "REPZ", /* 0xF0 */ +"HLT", "CMC", " ", " ", +"CLC", "STC", "CLI", "STI", +"CLD", "STD", "???", "???" + }; + +int32 oplen[256] = { +1,3,1,1,1,1,2,1,0,1,1,1,1,1,2,1, +0,3,1,1,1,1,2,1,0,1,1,1,1,1,2,1, +0,3,3,1,1,1,2,1,0,1,3,1,1,1,2,1, +0,3,3,1,1,1,2,1,0,1,3,1,1,1,2,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,3,3,3,1,2,1,1,1,3,0,3,3,2,1, +1,1,3,2,3,1,2,1,1,0,3,2,3,0,2,1, +1,1,3,1,3,1,2,1,1,1,3,1,3,0,2,1, +1,1,3,1,3,1,2,1,1,1,3,1,3,0,2,1 +}; + +int32 sim_instr (void) +{ + extern int32 sim_interval; + int32 IR, OP, DAR, reason, hi, lo, carry, i, adr; + int32 MRR, REG, EA, MOD, RM, DISP, VAL, DATA, OFF, SEG, INC, VAL1; + + IP = saved_PC & ADDRMASK16; /* load local IP */ + 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 (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 ", CS, DS, ES, SS); + sim_printf("Flags: %04X\n", PSW); + } + + if (sim_interval <= 0) { /* check clock queue */ + if (reason = sim_process_event ()) break; + } + + if (int_req > 0) { /* interrupt? */ + + /* 8088 interrupts not implemented yet. */ + + } /* end interrupt */ + + if (sim_brk_summ && + sim_brk_test (IP, SWMASK ('E'))) { /* breakpoint? */ + reason = STOP_IBKPT; /* stop simulation */ + break; + } + + sim_interval--; /* countdown clock */ + PCX = IP; + IR = OP = fetch_byte(0); /* fetch instruction */ + + /* Handle below all operations which refer to registers or + register pairs. After that, a large switch statement + takes care of all other opcodes */ + + /* data transfer instructions */ + + /* arithmetic instructions */ + + /* bit manipulation instructions */ + /* string manipulation instructions */ + /* control transfer instructions */ + /* processor control instructions */ + /* The Big Instruction Decode Switch */ + + switch (IR) { + + /* data transfer instructions */ + /* arithmetic instructions */ + + 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_smbyte(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = or_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = sbb_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = and_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = sub_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rbyte(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_rbyte(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_smbyte(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rbyte(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: /* 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: /* INTO */ + 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 += (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 += (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 += (int16)IP; + CX -= 1; + if (CX != 0) /* CX != 0 */ + IP = OFF; + break; + + case 0xE3: /* JCXZ label */ + OFF = fetch_byte(1); + OFF += (int16)IP; + if (CX == 0) /* CX != 0 */ + IP = OFF; + break; + + case 0xE4: /* IN AL,immed8 */ + OFF = fetch_byte(1); + AL = dev_table[OFF].routine(0, 0); + break; + + case 0xE5: /* IN AX,immed8 */ + OFF = fetch_byte(1); + AH = dev_table[OFF].routine(0, 0); + AL = dev_table[OFF+1].routine(0, 0); + break; + + case 0xE6: /* OUT AL,immed8 */ + OFF = fetch_byte(1); + dev_table[OFF].routine(1, AL); + break; + + case 0xE7: /* OUT AX,immed8 */ + OFF = fetch_byte(1); + dev_table[OFF].routine(1, AH); + dev_table[OFF+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 */ + AL = dev_table[DX].routine(0, 0); + break; + + case 0xED: /* IN AX,DX */ + AH = dev_table[DX].routine(0, 0); + AL = dev_table[DX+1].routine(0, 0); + break; + + case 0xEE: /* OUT AL,DX */ + dev_table[DX].routine(1, AL); + break; + + case 0xEF: /* OUT AX,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; + } + } + + /* Simulation halted */ + 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 */ +// sim_printf("%04X:%04X %s", CS, IP, opcode[val]); + sim_printf("%04X:%04X %02X", CS, IP, val); + break; + case 1: /* byte operand fetch */ + sim_printf(" %02X", val); + break; + } + } + IP = INC_IP1; /* increment IP */ + 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); + sim_printf(" %04X", val); + IP = INC_IP2; /* increment IP */ + 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; + + 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; + + 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_ovr = reg; +} + +/* return effective address from mrr - also set seg_reg */ + +uint32 get_ea(uint32 mrr) +{ + uint32 MOD, REG, RM, DISP, EA; + + 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: MRR=%02X MOD=%02X REG=%02X R/M=%02X DISP=%04X EA=%04X\n", + mrr, MOD, REG, RM, 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; +} + +/* + 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(SS, SP, val >> 8); + SP--; + put_smbyte(SS, SP, val & 0xFF); +} + +/* pop word primitive */ +uint16 pop_word(void) +{ + register uint16 res; + + res = get_smbyte(SS, SP); + SP++; + res |= (get_smbyte(SS, SP) << 8); + 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); +// sim_printf("get_smbyte: seg=%04X addr=%04X abs_addr=%08X get_mbyte=%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); +} + +/* 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) +{ + if (addr >= MAXMEMSIZE20) + return SCPE_NXM; + if (vptr != NULL) + *vptr = get_mbyte(addr); + return SCPE_OK; +} + +/* Memory deposit */ + +t_stat i8088_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) +{ + if (addr >= MAXMEMSIZE20) + 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. +*/ + +int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag) +{ + int32 i, addr = 0, cnt = 0; + + if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; + addr = saved_PC; + while ((i = getc (fileref)) != EOF) { + put_mbyte(addr, i); + addr++; + cnt++; + } /* end while */ + sim_printf ("%d Bytes loaded.\n", cnt); + return (SCPE_OK); +} + +/* Symbolic output + + Inputs: + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches + Outputs: + status = error code +*/ + +int32 fprint_sym (FILE *of, int32 addr, uint32 *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, "%h", 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, "%h", adr); + } + return -(oplen[inst] - 1); +} + +/* Symbolic input + + Inputs: + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches + Outputs: + status = error status +*/ + +int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw) +{ + int32 cflag, i = 0, j, r; + char gbuf[CBUFSIZE]; + + 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 (1) { + 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); +} diff --git a/Intel-Systems/common/i8237.c b/Intel-Systems/common/i8237.c index fbbcaffb..5c5f8831 100644 --- a/Intel-Systems/common/i8237.c +++ b/Intel-Systems/common/i8237.c @@ -1,867 +1,867 @@ -/* i8237.c: Intel 8237 DMA adapter - - Copyright (c) 2016, 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 Jul 16 - Original file. - - NOTES: - - - 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 - 02 Write Load DMAC Channel 1 Base and Current Address Regsiters - Read Read DMAC Channel 1 Current Address Register - 03 Write Load DMAC Channel 1 Base and Current Word Count Registers - Read Read DMAC Channel 1 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 - 0A Write Set/Reset DMAC Mask Register - 0B Write Load DMAC Mode Register - 0C Write Clear DMAC First/Last Flip-Flop - 0D Write DMAC Master Clear - 0F Write Load DMAC Mask Register - - Register usage is defined in the following paragraphs. - - Read/Write DMAC Address Registers - - Used to simultaneously load a channel's current-address register and base-address - register with the memory address of the first byte to be transferred. (The Channel - 0 current/base 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/base 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 base 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 - -*/ - -#include "system_defs.h" - -/* external globals */ - -extern uint16 port; //port called in dev_table[port] - -/* globals */ - -int32 i8237_devnum = 0; //actual number of 8253 instances + 1 -uint16 i8237_port[4]; //base port registered to each instance - -/* function prototypes */ - -t_stat i8237_svc(UNIT *uptr); -t_stat i8237_reset(DEVICE *dptr, uint16 base); -void i8237_reset1(int32 devnum); -t_stat i8237_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -uint8 i8237_r0x(t_bool io, uint8 data); -uint8 i8237_r1x(t_bool io, uint8 data); -uint8 i8237_r2x(t_bool io, uint8 data); -uint8 i8237_r3x(t_bool io, uint8 data); -uint8 i8237_r4x(t_bool io, uint8 data); -uint8 i8237_r5x(t_bool io, uint8 data); -uint8 i8237_r6x(t_bool io, uint8 data); -uint8 i8237_r7x(t_bool io, uint8 data); -uint8 i8237_r8x(t_bool io, uint8 data); -uint8 i8237_r9x(t_bool io, uint8 data); -uint8 i8237_rAx(t_bool io, uint8 data); -uint8 i8237_rBx(t_bool io, uint8 data); -uint8 i8237_rCx(t_bool io, uint8 data); -uint8 i8237_rDx(t_bool io, uint8 data); -uint8 i8237_rEx(t_bool io, uint8 data); -uint8 i8237_rFx(t_bool io, uint8 data); - -/* external function prototypes */ - -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); - -/* 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 - -/* i8237 physical register definitions */ - -uint16 i8237_sr[4]; // isbc-208 segment register -uint8 i8237_i[4]; // iSBC-208 interrupt register -uint8 i8237_a[4]; // iSBC-208 auxillary port register - -/* 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 */ -}; - - -REG i8237_reg[] = { - { HRDATA (CH0ADR, i8237_r0[devnum], 16) }, - { HRDATA (CH0CNT, i8237_r1[devnum], 16) }, - { HRDATA (CH1ADR, i8237_r2[devnum], 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 (SEGREG, i8237_sr, 8) }, - { HRDATA (AUX, i8237_a, 8) }, - { HRDATA (INT, i8237_i, 8) }, - { NULL } -}; - -MTAB i8237_mod[] = { - { 0 } -}; - -DEBTAB i8237_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { "REG", DEBUG_reg }, - { NULL } -}; - -DEVICE i8237_dev = { - "I8237", //name - i8237_unit, //units - i8237_reg, //registers - i8237_mod, //modifiers - 1, //numunits - 16, //aradix - 32, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &i8237_reset, //deposit - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags - 0, //dctrl -// DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl - i8237_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Service routines to handle simulator functions */ - -/* service routine - actually does the simulated DMA */ - -t_stat i8237_svc(UNIT *uptr) -{ - sim_printf("uptr=%08X\n", uptr); - sim_activate (&i8237_unit[uptr->u6], i8237_unit[uptr->u6].wait); - return SCPE_OK; -} - -/* Reset routine */ - -t_stat i8237_reset(DEVICE *dptr, uint16 base) -{ - if (i8237_devnum > I8237_NUM) { - sim_printf("i8237_reset: too many devices!\n"); - return SCPE_MEM; - } - sim_printf(" 8237 Reset\n"); - sim_printf(" 8237: Registered at %03X\n", base); - i8237_port[i8237_devnum] = reg_dev(i8237_r0x, base); - reg_dev(i8237_r1x, base + 1); - reg_dev(i8237_r2x, base + 2); - reg_dev(i8237_r3x, base + 3); - reg_dev(i8237_r4x, base + 4); - reg_dev(i8237_r5x, base + 5); - reg_dev(i8237_r6x, base + 6); - reg_dev(i8237_r7x, base + 7); - reg_dev(i8237_r8x, base + 8); - reg_dev(i8237_r9x, base + 9); - reg_dev(i8237_rAx, base + 10); - reg_dev(i8237_rBx, base + 11); - reg_dev(i8237_rCx, base + 12); - reg_dev(i8237_rDx, base + 13); - reg_dev(i8237_rEx, base + 14); - reg_dev(i8237_rFx, base + 15); - sim_printf(" 8237 Reset\n"); - sim_printf(" 8237: Registered at %03X\n", base); - sim_activate (&i8237_unit[i8237_devnum], i8237_unit[i8237_devnum].wait); /* activate unit */ - if ((i8237_dev.flags & DEV_DIS) == 0) - i8237_reset1(i8237_devnum); - i8237_devnum++; - return SCPE_OK; -} - -uint8 i8237_get_dn(void) -{ - int i; - - for (i=0; i=i8237_port[i] && port <= i8237_port[i] + 16) - return i; - sim_printf("i8237_get_dn: port %03X not in 8237 device table\n", port); - return 0xFF; -} - -void i8237_reset1(int32 devnum) -{ - int32 i; - UNIT *uptr; - - uptr = i8237_dev[devnum].units; - if (uptr->capac == 0) { /* if not configured */ - 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[devnum], i8237_unit[devnum].wait); - } - 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 set mode = 8- or 16-bit data bus */ -/* always 8-bit mode for current simulators */ - -t_stat i8237_set_mode(UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - sim_debug (DEBUG_flow, &i8237_dev, " i8237_set_mode: Entered with val=%08XH uptr->flags=%08X\n", val, uptr->flags); - sim_debug (DEBUG_flow, &i8237_dev, " i8237_set_mode: Done\n"); - return SCPE_OK; -} - -/* 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 i8237_r0x(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { /* read current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](H) read as %04X\n", devnum, i8237_r0[devnum]); - return (i8237_r0[devnum] >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](L) read as %04X\n", devnum, i8237_r0[devnum]); - return (i8237_r0[devnum] & 0xFF); - } - } else { /* write base & current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r0[devnum] |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](H) set to %04X\n", devnum, i8237_r0[devnum]); - } else { /* low byte */ - i8237_rD++; - i8237_r0[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](L) set to %04X\n"devnum, , i8237_r0[devnum]); - } - return 0; - } - } -} - -uint8 i8237_r1x(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { /* read current word count CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](H) read as %04X\n", devnum, i8237_r1[devnum]); - return (i8237_r1[devnum][devnum] >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](L) read as %04X\n", devnum, i8237_r1[devnum]); - return (i8237_r1[devnum] & 0xFF); - } - } else { /* write base & current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r1[devnum] |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](H) set to %04X\n", devnum, i8237_r1[devnum]); - } else { /* low byte */ - i8237_rD++; - i8237_r1[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](L) set to %04X\n", devnum, i8237_r1[devnum]); - } - return 0; - } - } -} - -uint8 i8237_r2x(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { /* read current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](H) read as %04X\n", devnum, i8237_r2[devnum]); - return (i8237_r2[devnum] >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](L) read as %04X\n", devnum, i8237_r2[devnum]); - return (i8237_r2[devnum] & 0xFF); - } - } else { /* write base & current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r2[devnum] |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](H) set to %04X\n", devnum, i8237_r2[devnum]); - } else { /* low byte */ - i8237_rD++; - i8237_r2[devnum] = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](L) set to %04X\n", devnum, i8237_r2[devnum]); - } - return 0; - } - } -} - -uint8 i8237_r3x(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { /* read current word count CH 1 */ - 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++; - 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) { /* 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++; - i8237_r3 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(L) set to %04X\n", i8237_r3); - } - return 0; - } - } -} - -uint8 i8237_r4x(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { /* read current address CH 2 */ - 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++; - 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) { /* 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++; - i8237_r4 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(L) set to %04X\n", i8237_r4); - } - return 0; - } - } -} - -uint8 i8237_r5x(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { /* read current word count CH 2 */ - 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++; - 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) { /* 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++; - i8237_r5 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(L) set to %04X\n", i8237_r5); - } - return 0; - } - } -} - -uint8 i8237_r6x(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { /* read current address CH 3 */ - 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++; - 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) { /* 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++; - i8237_r6 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(L) set to %04X\n", i8237_r6); - } - return 0; - } - } -} - -uint8 i8237_r7x(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { /* read current word count CH 3 */ - 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++; - 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) { /* 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++; - i8237_r7 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(L) set to %04X\n", i8237_r7); - } - return 0; - } - } -} - -uint8 i8237_r8x(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { /* read status register */ - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r8 (status) read as %02X\n", i8237_r8); - return (i8237_r8); - } else { /* write command register */ - i8237_r9 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r9 (command) set to %02X\n", i8237_r9); - return 0; - } - } -} - -uint8 i8237_r9x(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_r9\n"); - return 0; - } else { /* write request register */ - i8237_rC = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rC (request) set to %02X\n", i8237_rC); - return 0; - } - } -} - -uint8 i8237_rAx(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { - 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 |= 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; - } - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); - return 0; - } - } -} - -uint8 i8237_rBx(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rB\n"); - return 0; - } else { /* write mode register */ - i8237_rA = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rA (mode) set to %02X\n", i8237_rA); - return 0; - } - } -} - -uint8 i8237_rCx(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rC\n"); - return 0; - } else { /* clear byte pointer FF */ - i8237_rD = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rD (FF) cleared\n"); - return 0; - } - } -} - -uint8 i8237_rDx(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { /* read temporary register */ - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rD\n"); - return 0; - } else { /* master clear */ - i8237_reset1(); - sim_debug (DEBUG_reg, &i8237_dev, "i8237 master clear\n"); - return 0; - } - } -} - -uint8 i8237_rEx(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rE\n"); - return 0; - } else { /* clear mask register */ - i8237_rB = 0; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) cleared\n"); - return 0; - } - } -} - -uint8 i8237_rFx(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8237_get_dn()) != 0xFF) { - if (io == 0) { - sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rF\n"); - return 0; - } else { /* write all mask register bits */ - i8237_rB = data & 0x0F; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); - return 0; - } - } -} - -/* end of i8237.c */ +/* i8237.c: Intel 8237 DMA adapter + + Copyright (c) 2016, 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 Jul 16 - Original file. + + NOTES: + + + 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 + 02 Write Load DMAC Channel 1 Base and Current Address Regsiters + Read Read DMAC Channel 1 Current Address Register + 03 Write Load DMAC Channel 1 Base and Current Word Count Registers + Read Read DMAC Channel 1 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 + 0A Write Set/Reset DMAC Mask Register + 0B Write Load DMAC Mode Register + 0C Write Clear DMAC First/Last Flip-Flop + 0D Write DMAC Master Clear + 0F Write Load DMAC Mask Register + + Register usage is defined in the following paragraphs. + + Read/Write DMAC Address Registers + + Used to simultaneously load a channel's current-address register and base-address + register with the memory address of the first byte to be transferred. (The Channel + 0 current/base 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/base 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 base 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 + +*/ + +#include "system_defs.h" + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + +/* globals */ + +int32 i8237_devnum = 0; //actual number of 8253 instances + 1 +uint16 i8237_port[4]; //base port registered to each instance + +/* function prototypes */ + +t_stat i8237_svc(UNIT *uptr); +t_stat i8237_reset(DEVICE *dptr, uint16 base); +void i8237_reset1(int32 devnum); +t_stat i8237_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +uint8 i8237_r0x(t_bool io, uint8 data); +uint8 i8237_r1x(t_bool io, uint8 data); +uint8 i8237_r2x(t_bool io, uint8 data); +uint8 i8237_r3x(t_bool io, uint8 data); +uint8 i8237_r4x(t_bool io, uint8 data); +uint8 i8237_r5x(t_bool io, uint8 data); +uint8 i8237_r6x(t_bool io, uint8 data); +uint8 i8237_r7x(t_bool io, uint8 data); +uint8 i8237_r8x(t_bool io, uint8 data); +uint8 i8237_r9x(t_bool io, uint8 data); +uint8 i8237_rAx(t_bool io, uint8 data); +uint8 i8237_rBx(t_bool io, uint8 data); +uint8 i8237_rCx(t_bool io, uint8 data); +uint8 i8237_rDx(t_bool io, uint8 data); +uint8 i8237_rEx(t_bool io, uint8 data); +uint8 i8237_rFx(t_bool io, uint8 data); + +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); + +/* 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 + +/* i8237 physical register definitions */ + +uint16 i8237_sr[4]; // isbc-208 segment register +uint8 i8237_i[4]; // iSBC-208 interrupt register +uint8 i8237_a[4]; // iSBC-208 auxillary port register + +/* 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 */ +}; + + +REG i8237_reg[] = { + { HRDATA (CH0ADR, i8237_r0[devnum], 16) }, + { HRDATA (CH0CNT, i8237_r1[devnum], 16) }, + { HRDATA (CH1ADR, i8237_r2[devnum], 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 (SEGREG, i8237_sr, 8) }, + { HRDATA (AUX, i8237_a, 8) }, + { HRDATA (INT, i8237_i, 8) }, + { NULL } +}; + +MTAB i8237_mod[] = { + { 0 } +}; + +DEBTAB i8237_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { "REG", DEBUG_reg }, + { NULL } +}; + +DEVICE i8237_dev = { + "I8237", //name + i8237_unit, //units + i8237_reg, //registers + i8237_mod, //modifiers + 1, //numunits + 16, //aradix + 32, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &i8237_reset, //deposit + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags + 0, //dctrl +// DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl + i8237_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +/* service routine - actually does the simulated DMA */ + +t_stat i8237_svc(UNIT *uptr) +{ + sim_printf("uptr=%08X\n", uptr); + sim_activate (&i8237_unit[uptr->u6], i8237_unit[uptr->u6].wait); + return SCPE_OK; +} + +/* Reset routine */ + +t_stat i8237_reset(DEVICE *dptr, uint16 base) +{ + if (i8237_devnum > I8237_NUM) { + sim_printf("i8237_reset: too many devices!\n"); + return SCPE_MEM; + } + sim_printf(" 8237 Reset\n"); + sim_printf(" 8237: Registered at %03X\n", base); + i8237_port[i8237_devnum] = reg_dev(i8237_r0x, base); + reg_dev(i8237_r1x, base + 1); + reg_dev(i8237_r2x, base + 2); + reg_dev(i8237_r3x, base + 3); + reg_dev(i8237_r4x, base + 4); + reg_dev(i8237_r5x, base + 5); + reg_dev(i8237_r6x, base + 6); + reg_dev(i8237_r7x, base + 7); + reg_dev(i8237_r8x, base + 8); + reg_dev(i8237_r9x, base + 9); + reg_dev(i8237_rAx, base + 10); + reg_dev(i8237_rBx, base + 11); + reg_dev(i8237_rCx, base + 12); + reg_dev(i8237_rDx, base + 13); + reg_dev(i8237_rEx, base + 14); + reg_dev(i8237_rFx, base + 15); + sim_printf(" 8237 Reset\n"); + sim_printf(" 8237: Registered at %03X\n", base); + sim_activate (&i8237_unit[i8237_devnum], i8237_unit[i8237_devnum].wait); /* activate unit */ + if ((i8237_dev.flags & DEV_DIS) == 0) + i8237_reset1(i8237_devnum); + i8237_devnum++; + return SCPE_OK; +} + +uint8 i8237_get_dn(void) +{ + int i; + + for (i=0; i=i8237_port[i] && port <= i8237_port[i] + 16) + return i; + sim_printf("i8237_get_dn: port %03X not in 8237 device table\n", port); + return 0xFF; +} + +void i8237_reset1(int32 devnum) +{ + int32 i; + UNIT *uptr; + + uptr = i8237_dev[devnum].units; + if (uptr->capac == 0) { /* if not configured */ + 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[devnum], i8237_unit[devnum].wait); + } + 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 set mode = 8- or 16-bit data bus */ +/* always 8-bit mode for current simulators */ + +t_stat i8237_set_mode(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + sim_debug (DEBUG_flow, &i8237_dev, " i8237_set_mode: Entered with val=%08XH uptr->flags=%08X\n", val, uptr->flags); + sim_debug (DEBUG_flow, &i8237_dev, " i8237_set_mode: Done\n"); + return SCPE_OK; +} + +/* 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 i8237_r0x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](H) read as %04X\n", devnum, i8237_r0[devnum]); + return (i8237_r0[devnum] >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](L) read as %04X\n", devnum, i8237_r0[devnum]); + return (i8237_r0[devnum] & 0xFF); + } + } else { /* write base & current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r0[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](H) set to %04X\n", devnum, i8237_r0[devnum]); + } else { /* low byte */ + i8237_rD++; + i8237_r0[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0[%d](L) set to %04X\n"devnum, , i8237_r0[devnum]); + } + return 0; + } + } +} + +uint8 i8237_r1x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current word count CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](H) read as %04X\n", devnum, i8237_r1[devnum]); + return (i8237_r1[devnum][devnum] >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](L) read as %04X\n", devnum, i8237_r1[devnum]); + return (i8237_r1[devnum] & 0xFF); + } + } else { /* write base & current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r1[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](H) set to %04X\n", devnum, i8237_r1[devnum]); + } else { /* low byte */ + i8237_rD++; + i8237_r1[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1[%d](L) set to %04X\n", devnum, i8237_r1[devnum]); + } + return 0; + } + } +} + +uint8 i8237_r2x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current address CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](H) read as %04X\n", devnum, i8237_r2[devnum]); + return (i8237_r2[devnum] >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](L) read as %04X\n", devnum, i8237_r2[devnum]); + return (i8237_r2[devnum] & 0xFF); + } + } else { /* write base & current address CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r2[devnum] |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](H) set to %04X\n", devnum, i8237_r2[devnum]); + } else { /* low byte */ + i8237_rD++; + i8237_r2[devnum] = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2[%d](L) set to %04X\n", devnum, i8237_r2[devnum]); + } + return 0; + } + } +} + +uint8 i8237_r3x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current word count CH 1 */ + 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++; + 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) { /* 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++; + i8237_r3 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r3(L) set to %04X\n", i8237_r3); + } + return 0; + } + } +} + +uint8 i8237_r4x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current address CH 2 */ + 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++; + 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) { /* 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++; + i8237_r4 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r4(L) set to %04X\n", i8237_r4); + } + return 0; + } + } +} + +uint8 i8237_r5x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current word count CH 2 */ + 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++; + 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) { /* 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++; + i8237_r5 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r5(L) set to %04X\n", i8237_r5); + } + return 0; + } + } +} + +uint8 i8237_r6x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current address CH 3 */ + 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++; + 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) { /* 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++; + i8237_r6 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r6(L) set to %04X\n", i8237_r6); + } + return 0; + } + } +} + +uint8 i8237_r7x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read current word count CH 3 */ + 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++; + 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) { /* 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++; + i8237_r7 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r7(L) set to %04X\n", i8237_r7); + } + return 0; + } + } +} + +uint8 i8237_r8x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read status register */ + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r8 (status) read as %02X\n", i8237_r8); + return (i8237_r8); + } else { /* write command register */ + i8237_r9 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r9 (command) set to %02X\n", i8237_r9); + return 0; + } + } +} + +uint8 i8237_r9x(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_r9\n"); + return 0; + } else { /* write request register */ + i8237_rC = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rC (request) set to %02X\n", i8237_rC); + return 0; + } + } +} + +uint8 i8237_rAx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + 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 |= 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; + } + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); + return 0; + } + } +} + +uint8 i8237_rBx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rB\n"); + return 0; + } else { /* write mode register */ + i8237_rA = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rA (mode) set to %02X\n", i8237_rA); + return 0; + } + } +} + +uint8 i8237_rCx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rC\n"); + return 0; + } else { /* clear byte pointer FF */ + i8237_rD = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rD (FF) cleared\n"); + return 0; + } + } +} + +uint8 i8237_rDx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { /* read temporary register */ + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rD\n"); + return 0; + } else { /* master clear */ + i8237_reset1(); + sim_debug (DEBUG_reg, &i8237_dev, "i8237 master clear\n"); + return 0; + } + } +} + +uint8 i8237_rEx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rE\n"); + return 0; + } else { /* clear mask register */ + i8237_rB = 0; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) cleared\n"); + return 0; + } + } +} + +uint8 i8237_rFx(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8237_get_dn()) != 0xFF) { + if (io == 0) { + sim_debug (DEBUG_reg, &i8237_dev, "Illegal read of i8237_rF\n"); + return 0; + } else { /* write all mask register bits */ + i8237_rB = data & 0x0F; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_rB (mask) set to %02X\n", i8237_rB); + return 0; + } + } +} + +/* end of i8237.c */ diff --git a/Intel-Systems/common/i8251.c b/Intel-Systems/common/i8251.c index 1260d65b..828a3194 100644 --- a/Intel-Systems/common/i8251.c +++ b/Intel-Systems/common/i8251.c @@ -1,312 +1,312 @@ -/* i8251.c: Intel i8251 UART adapter - - Copyright (c) 2010, 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: - - ?? ??? 10 - 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 i8251 interface device on an iSBC. - The device had one physical I/O port which could be connected - to any serial I/O device that would connect to a current loop, - RS232, or TTY interface. Available baud rates were jumper - selectable for each port from 110 to 9600. - - All I/O is via programmed I/O. The i8251 has a status port - and a data port. - - The simulated device does not support synchronous mode. The simulated device - supports a select from I/O space and one address line. The data port is at the - lower address and the status/command port is at the higher. - - A write to the status port can select some options for the device: - - Asynchronous Mode Instruction - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | S2 S1 EP PEN L2 L1 B2 B1| - +---+---+---+---+---+---+---+---+ - - Baud Rate Factor - B2 0 1 0 1 - B1 0 0 1 1 - sync 1X 16X 64X - mode - - Character Length - L2 0 1 0 1 - L1 0 0 1 1 - 5 6 7 8 - bits bits bits bits - - EP - A 1 in this bit position selects even parity. - PEN - A 1 in this bit position enables parity. - - Number of Stop Bits - S2 0 1 0 1 - S1 0 0 1 1 - invalid 1 1.5 2 - bit bits bits - - Command Instruction Format - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - | EH IR RTS ER SBRK RxE DTR TxE| - +---+---+---+---+---+---+---+---+ - - TxE - A 1 in this bit position enables transmit. - DTR - A 1 in this bit position forces *DTR to zero. - RxE - A 1 in this bit position enables receive. - SBRK - A 1 in this bit position forces TxD to zero. - ER - A 1 in this bit position resets the error bits - RTS - A 1 in this bit position forces *RTS to zero. - IR - A 1 in this bit position returns the 8251 to Mode Instruction Format. - EH - A 1 in this bit position enables search for sync characters. - - A read of the status port gets the port status: - - Status Read Format - 7 6 5 4 3 2 1 0 - +---+---+---+---+---+---+---+---+ - |DSR SD FE OE PE TxE RxR TxR| - +---+---+---+---+---+---+---+---+ - - TxR - A 1 in this bit position signals transmit ready to receive a character. - RxR - A 1 in this bit position signals receiver has a character. - TxE - A 1 in this bit position signals transmitter has no more characters to transmit. - PE - A 1 in this bit signals a parity error. - OE - A 1 in this bit signals an transmit overrun error. - FE - A 1 in this bit signals a framing error. - SD - A 1 in this bit position returns the 8251 to Mode Instruction Format. - DSR - A 1 in this bit position signals *DSR is at zero. - - A read from the data port gets the typed character, a write - to the data port writes the character to the device. -*/ - -#include "system_defs.h" - -#define DEBUG 0 - -/* external globals */ - -extern uint16 port; //port called in dev_table[port] - -#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ -#define UNIT_ANSI (1 << UNIT_V_ANSI) - -#define TXR 0x01 -#define RXR 0x02 -#define TXE 0x04 -#define SD 0x40 - -/* external function prototypes */ - -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); - -/* globals */ - -int32 i8251_devnum = 0; //actual number of 8251 instances + 1 -uint16 i8251_port[4]; //baseport port registered to each instance - -/* function prototypes */ - -t_stat i8251_svc (UNIT *uptr); -t_stat i8251_reset (DEVICE *dptr, uint16 baseport); -uint8 i8251_get_dn(void); -uint8 i8251s(t_bool io, uint8 data); -uint8 i8251d(t_bool io, uint8 data); -void i8251_reset1(uint8 devnum); - -/* i8251 Standard I/O Data Structures */ -/* up to 1 i8251 devices */ - -UNIT i8251_unit = { - UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT -}; - -REG i8251_reg[] = { - { HRDATA (DATA, i8251_unit.buf, 8) }, - { HRDATA (STAT, i8251_unit.u3, 8) }, - { HRDATA (MODE, i8251_unit.u4, 8) }, - { HRDATA (CMD, i8251_unit.u5, 8) }, - { NULL } -}; - -DEBTAB i8251_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -MTAB i8251_mod[] = { - { UNIT_ANSI, 0, "TTY", "TTY", NULL }, - { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, - { 0 } -}; - -/* address width is set to 16 bits to use devices in 8086/8088 implementations */ - -DEVICE i8251_dev = { - "I8251", //name - &i8251_unit, //units - i8251_reg, //registers - i8251_mod, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &i8251_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - 0, //flags - 0, //dctrl - i8251_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Service routines to handle simulator functions */ - -/* i8251_svc - actually gets char & places in buffer */ - -t_stat i8251_svc (UNIT *uptr) -{ - int32 temp; - - sim_activate (&i8251_unit, i8251_unit.wait); /* continue poll */ - if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) - return temp; /* no char or error? */ - i8251_unit.buf = temp & 0xFF; /* Save char */ - i8251_unit.u3 |= RXR; /* Set status */ - - /* Do any special character handling here */ - - i8251_unit.pos++; - return SCPE_OK; -} - -/* Reset routine */ - -t_stat i8251_reset (DEVICE *dptr, uint16 baseport) -{ - if (i8251_devnum >= I8251_NUM) { - sim_printf("i8251_reset: too many devices!\n"); - return SCPE_MEM; - } - sim_printf(" 8251-%d: Hardware Reset\n", i8251_devnum); - sim_printf(" 8251-%d: Registered at %04X\n", i8251_devnum, baseport); - i8251_port[i8251_devnum] = baseport; - reg_dev(i8251d, baseport, i8251_devnum); - reg_dev(i8251s, baseport + 1, i8251_devnum); - i8251_reset1(i8251_devnum); - sim_activate (&i8251_unit, i8251_unit.wait); /* activate unit */ - i8251_devnum++; - return SCPE_OK; -} - -void i8251_reset1(uint8 devnum) -{ - i8251_unit.u3 = TXR + TXE; /* status */ - i8251_unit.u4 = 0; /* mode instruction */ - i8251_unit.u5 = 0; /* command instruction */ - i8251_unit.u6 = 0; - i8251_unit.buf = 0; - i8251_unit.pos = 0; - sim_printf(" 8251-%d: Software Reset\n", devnum); -} - -uint8 i8251_get_dn(void) -{ - int i; - - for (i=0; i= i8251_port[i] && port <= i8251_port[i] + 1) - return i; - sim_printf("i8251_get_dn: port %04X not in 8251 device table\n", port); - return 0xFF; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. -*/ - -uint8 i8251s(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8251_get_dn()) != 0xFF) { - // sim_printf("\nio=%d data=%04X\n", io, data); - if (io == 0) { /* read status port */ - return i8251_unit.u3; - } else { /* write status port */ - if (i8251_unit.u6) { /* if mode, set cmd */ - i8251_unit.u5 = data; - if (DEBUG) - sim_printf(" 8251-%d: Command Instruction=%02X\n", devnum, data); - if (data & SD) /* reset port! */ - i8251_reset1(devnum); - } else { /* set mode */ - i8251_unit.u4 = data; - if (DEBUG) - sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); - i8251_unit.u6 = 1; /* set cmd received */ - } - } - } - return 0; -} - -uint8 i8251d(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8251_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - i8251_unit.u3 &= ~RXR; - return (i8251_unit.buf); - } else { /* write data port */ - sim_putchar(data); - } - } - return 0; -} - -/* end of i8251.c */ +/* i8251.c: Intel i8251 UART adapter + + Copyright (c) 2010, 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: + + ?? ??? 10 - 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 i8251 interface device on an iSBC. + The device had one physical I/O port which could be connected + to any serial I/O device that would connect to a current loop, + RS232, or TTY interface. Available baud rates were jumper + selectable for each port from 110 to 9600. + + All I/O is via programmed I/O. The i8251 has a status port + and a data port. + + The simulated device does not support synchronous mode. The simulated device + supports a select from I/O space and one address line. The data port is at the + lower address and the status/command port is at the higher. + + A write to the status port can select some options for the device: + + Asynchronous Mode Instruction + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | S2 S1 EP PEN L2 L1 B2 B1| + +---+---+---+---+---+---+---+---+ + + Baud Rate Factor + B2 0 1 0 1 + B1 0 0 1 1 + sync 1X 16X 64X + mode + + Character Length + L2 0 1 0 1 + L1 0 0 1 1 + 5 6 7 8 + bits bits bits bits + + EP - A 1 in this bit position selects even parity. + PEN - A 1 in this bit position enables parity. + + Number of Stop Bits + S2 0 1 0 1 + S1 0 0 1 1 + invalid 1 1.5 2 + bit bits bits + + Command Instruction Format + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + | EH IR RTS ER SBRK RxE DTR TxE| + +---+---+---+---+---+---+---+---+ + + TxE - A 1 in this bit position enables transmit. + DTR - A 1 in this bit position forces *DTR to zero. + RxE - A 1 in this bit position enables receive. + SBRK - A 1 in this bit position forces TxD to zero. + ER - A 1 in this bit position resets the error bits + RTS - A 1 in this bit position forces *RTS to zero. + IR - A 1 in this bit position returns the 8251 to Mode Instruction Format. + EH - A 1 in this bit position enables search for sync characters. + + A read of the status port gets the port status: + + Status Read Format + 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+ + |DSR SD FE OE PE TxE RxR TxR| + +---+---+---+---+---+---+---+---+ + + TxR - A 1 in this bit position signals transmit ready to receive a character. + RxR - A 1 in this bit position signals receiver has a character. + TxE - A 1 in this bit position signals transmitter has no more characters to transmit. + PE - A 1 in this bit signals a parity error. + OE - A 1 in this bit signals an transmit overrun error. + FE - A 1 in this bit signals a framing error. + SD - A 1 in this bit position returns the 8251 to Mode Instruction Format. + DSR - A 1 in this bit position signals *DSR is at zero. + + A read from the data port gets the typed character, a write + to the data port writes the character to the device. +*/ + +#include "system_defs.h" + +#define DEBUG 0 + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + +#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ +#define UNIT_ANSI (1 << UNIT_V_ANSI) + +#define TXR 0x01 +#define RXR 0x02 +#define TXE 0x04 +#define SD 0x40 + +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); + +/* globals */ + +int32 i8251_devnum = 0; //actual number of 8251 instances + 1 +uint16 i8251_port[4]; //baseport port registered to each instance + +/* function prototypes */ + +t_stat i8251_svc (UNIT *uptr); +t_stat i8251_reset (DEVICE *dptr, uint16 baseport); +uint8 i8251_get_dn(void); +uint8 i8251s(t_bool io, uint8 data); +uint8 i8251d(t_bool io, uint8 data); +void i8251_reset1(uint8 devnum); + +/* i8251 Standard I/O Data Structures */ +/* up to 1 i8251 devices */ + +UNIT i8251_unit = { + UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT +}; + +REG i8251_reg[] = { + { HRDATA (DATA, i8251_unit.buf, 8) }, + { HRDATA (STAT, i8251_unit.u3, 8) }, + { HRDATA (MODE, i8251_unit.u4, 8) }, + { HRDATA (CMD, i8251_unit.u5, 8) }, + { NULL } +}; + +DEBTAB i8251_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +MTAB i8251_mod[] = { + { UNIT_ANSI, 0, "TTY", "TTY", NULL }, + { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, + { 0 } +}; + +/* address width is set to 16 bits to use devices in 8086/8088 implementations */ + +DEVICE i8251_dev = { + "I8251", //name + &i8251_unit, //units + i8251_reg, //registers + i8251_mod, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &i8251_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + i8251_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +/* i8251_svc - actually gets char & places in buffer */ + +t_stat i8251_svc (UNIT *uptr) +{ + int32 temp; + + sim_activate (&i8251_unit, i8251_unit.wait); /* continue poll */ + if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) + return temp; /* no char or error? */ + i8251_unit.buf = temp & 0xFF; /* Save char */ + i8251_unit.u3 |= RXR; /* Set status */ + + /* Do any special character handling here */ + + i8251_unit.pos++; + return SCPE_OK; +} + +/* Reset routine */ + +t_stat i8251_reset (DEVICE *dptr, uint16 baseport) +{ + if (i8251_devnum >= I8251_NUM) { + sim_printf("i8251_reset: too many devices!\n"); + return SCPE_MEM; + } + sim_printf(" 8251-%d: Hardware Reset\n", i8251_devnum); + sim_printf(" 8251-%d: Registered at %04X\n", i8251_devnum, baseport); + i8251_port[i8251_devnum] = baseport; + reg_dev(i8251d, baseport, i8251_devnum); + reg_dev(i8251s, baseport + 1, i8251_devnum); + i8251_reset1(i8251_devnum); + sim_activate (&i8251_unit, i8251_unit.wait); /* activate unit */ + i8251_devnum++; + return SCPE_OK; +} + +void i8251_reset1(uint8 devnum) +{ + i8251_unit.u3 = TXR + TXE; /* status */ + i8251_unit.u4 = 0; /* mode instruction */ + i8251_unit.u5 = 0; /* command instruction */ + i8251_unit.u6 = 0; + i8251_unit.buf = 0; + i8251_unit.pos = 0; + sim_printf(" 8251-%d: Software Reset\n", devnum); +} + +uint8 i8251_get_dn(void) +{ + int i; + + for (i=0; i= i8251_port[i] && port <= i8251_port[i] + 1) + return i; + sim_printf("i8251_get_dn: port %04X not in 8251 device table\n", port); + return 0xFF; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +uint8 i8251s(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8251_get_dn()) != 0xFF) { + // sim_printf("\nio=%d data=%04X\n", io, data); + if (io == 0) { /* read status port */ + return i8251_unit.u3; + } else { /* write status port */ + if (i8251_unit.u6) { /* if mode, set cmd */ + i8251_unit.u5 = data; + if (DEBUG) + sim_printf(" 8251-%d: Command Instruction=%02X\n", devnum, data); + if (data & SD) /* reset port! */ + i8251_reset1(devnum); + } else { /* set mode */ + i8251_unit.u4 = data; + if (DEBUG) + sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); + i8251_unit.u6 = 1; /* set cmd received */ + } + } + } + return 0; +} + +uint8 i8251d(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8251_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + i8251_unit.u3 &= ~RXR; + return (i8251_unit.buf); + } else { /* write data port */ + sim_putchar(data); + } + } + return 0; +} + +/* end of i8251.c */ diff --git a/Intel-Systems/common/i8253.c b/Intel-Systems/common/i8253.c index ed6ac9ad..26c5fb47 100644 --- a/Intel-Systems/common/i8253.c +++ b/Intel-Systems/common/i8253.c @@ -1,248 +1,248 @@ -/* i8253.c: Intel i8253 PIT adapter - - Copyright (c) 2010, 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: - - ?? ??? 10 - 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: - -*/ - -#include "system_defs.h" - -#define DEBUG 0 - -/* external globals */ - -extern uint16 port; //port called in dev_table[port] - -/* external function prototypes */ - -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); - -/* globals */ - -int32 i8253_devnum = 0; //actual number of 8253 instances + 1 -uint16 i8253_port[4]; //baseport port registered to each instance - -/* function prototypes */ - -t_stat i8253_svc (UNIT *uptr); -t_stat i8253_reset (DEVICE *dptr, uint16 baseport); -uint8 i8253_get_dn(void); -uint8 i8253t0(t_bool io, uint8 data); -uint8 i8253t1(t_bool io, uint8 data); -uint8 i8253t2(t_bool io, uint8 data); -uint8 i8253c(t_bool io, uint8 data); - -/* i8253 Standard I/O Data Structures */ -/* up to 4 i8253 devices */ - -UNIT i8253_unit[] = { - { UDATA (&i8253_svc, 0, 0), 20 }, - { UDATA (&i8253_svc, 0, 0), 20 }, - { UDATA (&i8253_svc, 0, 0), 20 }, - { UDATA (&i8253_svc, 0, 0), 20 } -}; - -REG i8253_reg[] = { - { HRDATA (T0, i8253_unit[0].u3, 8) }, - { HRDATA (T1, i8253_unit[0].u4, 8) }, - { HRDATA (T2, i8253_unit[0].u5, 8) }, - { HRDATA (CMD, i8253_unit[0].u6, 8) }, - { HRDATA (T0, i8253_unit[1].u3, 8) }, - { HRDATA (T1, i8253_unit[1].u4, 8) }, - { HRDATA (T2, i8253_unit[1].u5, 8) }, - { HRDATA (CMD, i8253_unit[1].u6, 8) }, - { NULL } -}; - -DEBTAB i8253_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -MTAB i8253_mod[] = { - { 0 } -}; - -/* address width is set to 16 bits to use devices in 8086/8088 implementations */ - -DEVICE i8253_dev = { - "I8251", //name - i8253_unit, //units - i8253_reg, //registers - i8253_mod, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &i8253_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - 0, //flags - 0, //dctrl - i8253_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Service routines to handle simulator functions */ - -/* i8253_svc - actually gets char & places in buffer */ - -t_stat i8253_svc (UNIT *uptr) -{ - sim_activate (&i8253_unit[0], i8253_unit[0].wait); /* continue poll */ - return SCPE_OK; -} - -/* Reset routine */ - -t_stat i8253_reset (DEVICE *dptr, uint16 baseport) -{ - if (i8253_devnum > I8253_NUM) { - sim_printf("i8253_reset: too many devices!\n"); - return SCPE_MEM; - } - sim_printf(" 8253-%d: Reset\n", i8253_devnum); - sim_printf(" 8253-%d: Registered at %04X\n", i8253_devnum, baseport); - i8253_port[i8253_devnum] = baseport; - reg_dev(i8253t0, baseport, i8253_devnum); - reg_dev(i8253t1, baseport + 1, i8253_devnum); - reg_dev(i8253t2, baseport + 2, i8253_devnum); - reg_dev(i8253c, baseport + 3, i8253_devnum); - i8253_unit[i8253_devnum].u3 = 0; /* status */ - i8253_unit[i8253_devnum].u4 = 0; /* mode instruction */ - i8253_unit[i8253_devnum].u5 = 0; /* command instruction */ - i8253_unit[i8253_devnum].u6 = 0; -// sim_activate (&i8253_unit[i8253_devnum], i8253_unit[i8253_devnum].wait); /* activate unit */ - i8253_devnum++; - return SCPE_OK; -} - -uint8 i8253_get_dn(void) -{ - int i; - - for (i=0; i= i8253_port[i] && port <= i8253_port[i] + 3) - return i; - sim_printf("i8253_get_dn: port %04X not in 8253 device table\n", port); - return 0xFF; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. -*/ - -uint8 i8253t0(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8253_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - return i8253_unit[devnum].u3; - } else { /* write data port */ - if (DEBUG) - sim_printf(" 8253-%d: Timer 0=%02X\n", devnum, data); - i8253_unit[devnum].u3 = data; - //sim_activate_after (&i8253_unit[devnum], ); - return 0; - } - } - return 0; -} - -//read routine: -//sim_activate_time(&i8253_unit[devnum])/sim_inst_per_second() - -uint8 i8253t1(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8253_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - return i8253_unit[devnum].u4; - } else { /* write data port */ - if (DEBUG) - sim_printf(" 8253-%d: Timer 1=%02X\n", devnum, data); - i8253_unit[devnum].u4 = data; - return 0; - } - } - return 0; -} - -uint8 i8253t2(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8253_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - return i8253_unit[devnum].u5; - } else { /* write data port */ - if (DEBUG) - sim_printf(" 8253-%d: Timer 2=%02X\n", devnum, data); - i8253_unit[devnum].u5 = data; - return 0; - } - } - return 0; -} - -uint8 i8253c(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8253_get_dn()) != 0xFF) { - if (io == 0) { /* read status port */ - return i8253_unit[devnum].u6; - } else { /* write data port */ - i8253_unit[devnum].u6 = data; - if (DEBUG) - sim_printf(" 8253-%d: Mode Instruction=%02X\n", devnum, data); - return 0; - } - } - return 0; -} - -/* end of i8253.c */ +/* i8253.c: Intel i8253 PIT adapter + + Copyright (c) 2010, 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: + + ?? ??? 10 - 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: + +*/ + +#include "system_defs.h" + +#define DEBUG 0 + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); + +/* globals */ + +int32 i8253_devnum = 0; //actual number of 8253 instances + 1 +uint16 i8253_port[4]; //baseport port registered to each instance + +/* function prototypes */ + +t_stat i8253_svc (UNIT *uptr); +t_stat i8253_reset (DEVICE *dptr, uint16 baseport); +uint8 i8253_get_dn(void); +uint8 i8253t0(t_bool io, uint8 data); +uint8 i8253t1(t_bool io, uint8 data); +uint8 i8253t2(t_bool io, uint8 data); +uint8 i8253c(t_bool io, uint8 data); + +/* i8253 Standard I/O Data Structures */ +/* up to 4 i8253 devices */ + +UNIT i8253_unit[] = { + { UDATA (&i8253_svc, 0, 0), 20 }, + { UDATA (&i8253_svc, 0, 0), 20 }, + { UDATA (&i8253_svc, 0, 0), 20 }, + { UDATA (&i8253_svc, 0, 0), 20 } +}; + +REG i8253_reg[] = { + { HRDATA (T0, i8253_unit[0].u3, 8) }, + { HRDATA (T1, i8253_unit[0].u4, 8) }, + { HRDATA (T2, i8253_unit[0].u5, 8) }, + { HRDATA (CMD, i8253_unit[0].u6, 8) }, + { HRDATA (T0, i8253_unit[1].u3, 8) }, + { HRDATA (T1, i8253_unit[1].u4, 8) }, + { HRDATA (T2, i8253_unit[1].u5, 8) }, + { HRDATA (CMD, i8253_unit[1].u6, 8) }, + { NULL } +}; + +DEBTAB i8253_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +MTAB i8253_mod[] = { + { 0 } +}; + +/* address width is set to 16 bits to use devices in 8086/8088 implementations */ + +DEVICE i8253_dev = { + "I8251", //name + i8253_unit, //units + i8253_reg, //registers + i8253_mod, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &i8253_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + i8253_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +/* i8253_svc - actually gets char & places in buffer */ + +t_stat i8253_svc (UNIT *uptr) +{ + sim_activate (&i8253_unit[0], i8253_unit[0].wait); /* continue poll */ + return SCPE_OK; +} + +/* Reset routine */ + +t_stat i8253_reset (DEVICE *dptr, uint16 baseport) +{ + if (i8253_devnum > I8253_NUM) { + sim_printf("i8253_reset: too many devices!\n"); + return SCPE_MEM; + } + sim_printf(" 8253-%d: Reset\n", i8253_devnum); + sim_printf(" 8253-%d: Registered at %04X\n", i8253_devnum, baseport); + i8253_port[i8253_devnum] = baseport; + reg_dev(i8253t0, baseport, i8253_devnum); + reg_dev(i8253t1, baseport + 1, i8253_devnum); + reg_dev(i8253t2, baseport + 2, i8253_devnum); + reg_dev(i8253c, baseport + 3, i8253_devnum); + i8253_unit[i8253_devnum].u3 = 0; /* status */ + i8253_unit[i8253_devnum].u4 = 0; /* mode instruction */ + i8253_unit[i8253_devnum].u5 = 0; /* command instruction */ + i8253_unit[i8253_devnum].u6 = 0; +// sim_activate (&i8253_unit[i8253_devnum], i8253_unit[i8253_devnum].wait); /* activate unit */ + i8253_devnum++; + return SCPE_OK; +} + +uint8 i8253_get_dn(void) +{ + int i; + + for (i=0; i= i8253_port[i] && port <= i8253_port[i] + 3) + return i; + sim_printf("i8253_get_dn: port %04X not in 8253 device table\n", port); + return 0xFF; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +uint8 i8253t0(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8253_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + return i8253_unit[devnum].u3; + } else { /* write data port */ + if (DEBUG) + sim_printf(" 8253-%d: Timer 0=%02X\n", devnum, data); + i8253_unit[devnum].u3 = data; + //sim_activate_after (&i8253_unit[devnum], ); + return 0; + } + } + return 0; +} + +//read routine: +//sim_activate_time(&i8253_unit[devnum])/sim_inst_per_second() + +uint8 i8253t1(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8253_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + return i8253_unit[devnum].u4; + } else { /* write data port */ + if (DEBUG) + sim_printf(" 8253-%d: Timer 1=%02X\n", devnum, data); + i8253_unit[devnum].u4 = data; + return 0; + } + } + return 0; +} + +uint8 i8253t2(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8253_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + return i8253_unit[devnum].u5; + } else { /* write data port */ + if (DEBUG) + sim_printf(" 8253-%d: Timer 2=%02X\n", devnum, data); + i8253_unit[devnum].u5 = data; + return 0; + } + } + return 0; +} + +uint8 i8253c(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8253_get_dn()) != 0xFF) { + if (io == 0) { /* read status port */ + return i8253_unit[devnum].u6; + } else { /* write data port */ + i8253_unit[devnum].u6 = data; + if (DEBUG) + sim_printf(" 8253-%d: Mode Instruction=%02X\n", devnum, data); + return 0; + } + } + return 0; +} + +/* end of i8253.c */ diff --git a/Intel-Systems/common/i8255.c b/Intel-Systems/common/i8255.c index f4dd5637..d0b07846 100644 --- a/Intel-Systems/common/i8255.c +++ b/Intel-Systems/common/i8255.c @@ -1,295 +1,295 @@ -/* i8255.c: Intel i8255 PIO adapter - - Copyright (c) 2010, 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: - - ?? ??? 10 - 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 i8255 interface device on an iSBC. - The device has threee physical 8-bit I/O ports which could be connected - to any parallel I/O device. - - All I/O is via programmed I/O. The i8255 has a control port (i8255s) - and three data ports (i8255a, i8255b, and i8255c). - - The simulated device supports a select from I/O space and two address lines. - The data ports are at the lower addresses and the control port is at - the highest. - - A write to the control port can configure the device: - - Control Word - +---+---+---+---+---+---+---+---+ - | D7 D6 D5 D4 D3 D2 D1 D0| - +---+---+---+---+---+---+---+---+ - - Group B - D0 Port C (lower) 1-Input, 0-Output - D1 Port B 1-Input, 0-Output - D2 Mode Selection 0-Mode 0, 1-Mode 1 - - Group A - D3 Port C (upper) 1-Input, 0-Output - D4 Port A 1-Input, 0-Output - D5-6 Mode Selection 00-Mode 0, 01-Mode 1, 1X-Mode 2 - - D7 Mode Set Flag 1=Active, 0=Bit Set - - Mode 0 - Basic Input/Output - Mode 1 - Strobed Input/Output - Mode 2 - Bidirectional Bus - - Bit Set - D7=0, D3:1 select port C bit, D0 1=set, 0=reset - - A read to the data ports gets the current port value, a write - to the data ports writes the character to the device. - - This program simulates up to 4 i8255 devices. It handles 2 i8255 - devices on the iSBC 80/10 SBC. Other devices could be on other - multibus boards in the simulated system. -*/ - -#include "system_defs.h" /* system header in system dir */ - -#define DEBUG 0 - -/* external globals */ - -extern uint16 port; //port called in dev_table[port] - -/* function prototypes */ - -t_stat i8255_reset (DEVICE *dptr, uint16 baseport); -uint8 i8255_get_dn(void); -uint8 i8255a(t_bool io, uint8 data); -uint8 i8255b(t_bool io, uint8 data); -uint8 i8255c(t_bool io, uint8 data); -uint8 i8255s(t_bool io, uint8 data); - -/* external function prototypes */ - -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); - -/* globals */ - -int32 i8255_devnum = 0; //actual number of 8255 instances + 1 -uint16 i8255_port[4]; //baseport port registered to each instance - -/* these bytes represent the input and output to/from a port instance */ - -uint8 i8255_A[4]; //port A byte I/O -uint8 i8255_B[4]; //port B byte I/O -uint8 i8255_C[4]; //port C byte I/O - -/* i8255 Standard I/O Data Structures */ -/* up to 4 i8255 devices */ - -UNIT i8255_unit[] = { - { UDATA (0, 0, 0) }, /* i8255 0 */ - { UDATA (0, 0, 0) }, /* i8255 1 */ - { UDATA (0, 0, 0) }, /* i8255 2 */ - { UDATA (0, 0, 0) } /* i8255 3 */ -}; - -REG i8255_reg[] = { - { HRDATA (CS0, i8255_unit[0].u3, 8) }, /* i8255 0 */ - { HRDATA (A0, i8255_A[0], 8) }, - { HRDATA (B0, i8255_B[0], 8) }, - { HRDATA (C0, i8255_C[0], 8) }, - { HRDATA (CS1, i8255_unit[1].u3, 8) }, /* i8255 1 */ - { HRDATA (A1, i8255_A[1], 8) }, - { HRDATA (B1, i8255_B[1], 8) }, - { HRDATA (C1, i8255_C[1], 8) }, - { HRDATA (CS2, i8255_unit[2].u3, 8) }, /* i8255 2 */ - { HRDATA (A2, i8255_A[2], 8) }, - { HRDATA (B2, i8255_B[2], 8) }, - { HRDATA (C2, i8255_C[2], 8) }, - { HRDATA (CS3, i8255_unit[3].u3, 8) }, /* i8255 3 */ - { HRDATA (A3, i8255_A[3], 8) }, - { HRDATA (B3, i8255_B[3], 8) }, - { HRDATA (C3, i8255_C[3], 8) }, - { NULL } -}; - -DEBTAB i8255_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -/* address width is set to 16 bits to use devices in 8086/8088 implementations */ - -DEVICE i8255_dev = { - "I8255", //name - i8255_unit, //units - i8255_reg, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// i8255_reset2(), //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - 0, //flags - 0, //dctrl - i8255_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Reset routine */ - -t_stat i8255_reset (DEVICE *dptr, uint16 baseport) -{ - if (i8255_devnum > I8255_NUM) { - sim_printf("i8255_reset: too many devices!\n"); - return SCPE_MEM; - } - sim_printf(" 8255-%d: Reset\n", i8255_devnum); - sim_printf(" 8255-%d: Registered at %04X\n", i8255_devnum, baseport); - i8255_port[i8255_devnum] = baseport; - reg_dev(i8255a, baseport, i8255_devnum); - reg_dev(i8255b, baseport + 1, i8255_devnum); - reg_dev(i8255c, baseport + 2, i8255_devnum); - reg_dev(i8255s, baseport + 3, i8255_devnum); - i8255_unit[i8255_devnum].u3 = 0x9B; /* control */ - i8255_A[i8255_devnum] = 0xFF; /* Port A */ - i8255_B[i8255_devnum] = 0xFF; /* Port B */ - i8255_C[i8255_devnum] = 0xFF; /* Port C */ - i8255_devnum++; - return SCPE_OK; -} - -uint8 i8255_get_dn(void) -{ - int i; - - for (i=0; i=i8255_port[i] && port <= i8255_port[i] + 3) - return i; - sim_printf("i8255_get_dn: port %04X not in 8255 device table\n", port); - return 0xFF; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. -*/ - -/* i8255 functions */ - -uint8 i8255s(t_bool io, uint8 data) -{ - uint8 bit; - uint8 devnum; - - if ((devnum = i8255_get_dn()) != 0xFF) { - if (io == 0) { /* read status port */ - return 0xFF; //undefined - } else { /* write status port */ - if (data & 0x80) { /* mode instruction */ - i8255_unit[devnum].u3 = data; - if (DEBUG) - sim_printf(" 8255-%d: Mode Instruction=%02X\n", devnum, data); - if (data & 0x64) - sim_printf(" Mode 1 and 2 not yet implemented\n"); - } else { /* bit set */ - bit = (data & 0x0E) >> 1; /* get bit number */ - if (data & 0x01) { /* set bit */ - i8255_C[devnum] |= (0x01 << bit); - } else { /* reset bit */ - i8255_C[devnum] &= ~(0x01 << bit); - } - } - } - } - return 0; -} - -uint8 i8255a(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8255_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - //return (i8255_unit[devnum].u4); - return (i8255_A[devnum]); - } else { /* write data port */ - i8255_A[devnum] = data; - if (DEBUG) - sim_printf(" 8255-%d: Port A = %02X\n", devnum, data); - } - } - return 0; -} - -uint8 i8255b(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8255_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - return (i8255_B[devnum]); - } else { /* write data port */ - i8255_B[devnum] = data; - if (DEBUG) - sim_printf(" 8255-%d: Port B = %02X\n", devnum, data); - } - } - return 0; -} - -uint8 i8255c(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8255_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - return (i8255_C[devnum]); - } else { /* write data port */ - i8255_C[devnum] = data; - if (DEBUG) - sim_printf(" 8255-%d: Port C = %02X\n", devnum, data); - } - } - return 0; -} - -/* end of i8255.c */ +/* i8255.c: Intel i8255 PIO adapter + + Copyright (c) 2010, 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: + + ?? ??? 10 - 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 i8255 interface device on an iSBC. + The device has threee physical 8-bit I/O ports which could be connected + to any parallel I/O device. + + All I/O is via programmed I/O. The i8255 has a control port (i8255s) + and three data ports (i8255a, i8255b, and i8255c). + + The simulated device supports a select from I/O space and two address lines. + The data ports are at the lower addresses and the control port is at + the highest. + + A write to the control port can configure the device: + + Control Word + +---+---+---+---+---+---+---+---+ + | D7 D6 D5 D4 D3 D2 D1 D0| + +---+---+---+---+---+---+---+---+ + + Group B + D0 Port C (lower) 1-Input, 0-Output + D1 Port B 1-Input, 0-Output + D2 Mode Selection 0-Mode 0, 1-Mode 1 + + Group A + D3 Port C (upper) 1-Input, 0-Output + D4 Port A 1-Input, 0-Output + D5-6 Mode Selection 00-Mode 0, 01-Mode 1, 1X-Mode 2 + + D7 Mode Set Flag 1=Active, 0=Bit Set + + Mode 0 - Basic Input/Output + Mode 1 - Strobed Input/Output + Mode 2 - Bidirectional Bus + + Bit Set - D7=0, D3:1 select port C bit, D0 1=set, 0=reset + + A read to the data ports gets the current port value, a write + to the data ports writes the character to the device. + + This program simulates up to 4 i8255 devices. It handles 2 i8255 + devices on the iSBC 80/10 SBC. Other devices could be on other + multibus boards in the simulated system. +*/ + +#include "system_defs.h" /* system header in system dir */ + +#define DEBUG 0 + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + +/* function prototypes */ + +t_stat i8255_reset (DEVICE *dptr, uint16 baseport); +uint8 i8255_get_dn(void); +uint8 i8255a(t_bool io, uint8 data); +uint8 i8255b(t_bool io, uint8 data); +uint8 i8255c(t_bool io, uint8 data); +uint8 i8255s(t_bool io, uint8 data); + +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); + +/* globals */ + +int32 i8255_devnum = 0; //actual number of 8255 instances + 1 +uint16 i8255_port[4]; //baseport port registered to each instance + +/* these bytes represent the input and output to/from a port instance */ + +uint8 i8255_A[4]; //port A byte I/O +uint8 i8255_B[4]; //port B byte I/O +uint8 i8255_C[4]; //port C byte I/O + +/* i8255 Standard I/O Data Structures */ +/* up to 4 i8255 devices */ + +UNIT i8255_unit[] = { + { UDATA (0, 0, 0) }, /* i8255 0 */ + { UDATA (0, 0, 0) }, /* i8255 1 */ + { UDATA (0, 0, 0) }, /* i8255 2 */ + { UDATA (0, 0, 0) } /* i8255 3 */ +}; + +REG i8255_reg[] = { + { HRDATA (CS0, i8255_unit[0].u3, 8) }, /* i8255 0 */ + { HRDATA (A0, i8255_A[0], 8) }, + { HRDATA (B0, i8255_B[0], 8) }, + { HRDATA (C0, i8255_C[0], 8) }, + { HRDATA (CS1, i8255_unit[1].u3, 8) }, /* i8255 1 */ + { HRDATA (A1, i8255_A[1], 8) }, + { HRDATA (B1, i8255_B[1], 8) }, + { HRDATA (C1, i8255_C[1], 8) }, + { HRDATA (CS2, i8255_unit[2].u3, 8) }, /* i8255 2 */ + { HRDATA (A2, i8255_A[2], 8) }, + { HRDATA (B2, i8255_B[2], 8) }, + { HRDATA (C2, i8255_C[2], 8) }, + { HRDATA (CS3, i8255_unit[3].u3, 8) }, /* i8255 3 */ + { HRDATA (A3, i8255_A[3], 8) }, + { HRDATA (B3, i8255_B[3], 8) }, + { HRDATA (C3, i8255_C[3], 8) }, + { NULL } +}; + +DEBTAB i8255_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +/* address width is set to 16 bits to use devices in 8086/8088 implementations */ + +DEVICE i8255_dev = { + "I8255", //name + i8255_unit, //units + i8255_reg, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// i8255_reset2(), //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + i8255_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Reset routine */ + +t_stat i8255_reset (DEVICE *dptr, uint16 baseport) +{ + if (i8255_devnum > I8255_NUM) { + sim_printf("i8255_reset: too many devices!\n"); + return SCPE_MEM; + } + sim_printf(" 8255-%d: Reset\n", i8255_devnum); + sim_printf(" 8255-%d: Registered at %04X\n", i8255_devnum, baseport); + i8255_port[i8255_devnum] = baseport; + reg_dev(i8255a, baseport, i8255_devnum); + reg_dev(i8255b, baseport + 1, i8255_devnum); + reg_dev(i8255c, baseport + 2, i8255_devnum); + reg_dev(i8255s, baseport + 3, i8255_devnum); + i8255_unit[i8255_devnum].u3 = 0x9B; /* control */ + i8255_A[i8255_devnum] = 0xFF; /* Port A */ + i8255_B[i8255_devnum] = 0xFF; /* Port B */ + i8255_C[i8255_devnum] = 0xFF; /* Port C */ + i8255_devnum++; + return SCPE_OK; +} + +uint8 i8255_get_dn(void) +{ + int i; + + for (i=0; i=i8255_port[i] && port <= i8255_port[i] + 3) + return i; + sim_printf("i8255_get_dn: port %04X not in 8255 device table\n", port); + return 0xFF; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +/* i8255 functions */ + +uint8 i8255s(t_bool io, uint8 data) +{ + uint8 bit; + uint8 devnum; + + if ((devnum = i8255_get_dn()) != 0xFF) { + if (io == 0) { /* read status port */ + return 0xFF; //undefined + } else { /* write status port */ + if (data & 0x80) { /* mode instruction */ + i8255_unit[devnum].u3 = data; + if (DEBUG) + sim_printf(" 8255-%d: Mode Instruction=%02X\n", devnum, data); + if (data & 0x64) + sim_printf(" Mode 1 and 2 not yet implemented\n"); + } else { /* bit set */ + bit = (data & 0x0E) >> 1; /* get bit number */ + if (data & 0x01) { /* set bit */ + i8255_C[devnum] |= (0x01 << bit); + } else { /* reset bit */ + i8255_C[devnum] &= ~(0x01 << bit); + } + } + } + } + return 0; +} + +uint8 i8255a(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8255_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + //return (i8255_unit[devnum].u4); + return (i8255_A[devnum]); + } else { /* write data port */ + i8255_A[devnum] = data; + if (DEBUG) + sim_printf(" 8255-%d: Port A = %02X\n", devnum, data); + } + } + return 0; +} + +uint8 i8255b(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8255_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + return (i8255_B[devnum]); + } else { /* write data port */ + i8255_B[devnum] = data; + if (DEBUG) + sim_printf(" 8255-%d: Port B = %02X\n", devnum, data); + } + } + return 0; +} + +uint8 i8255c(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8255_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + return (i8255_C[devnum]); + } else { /* write data port */ + i8255_C[devnum] = data; + if (DEBUG) + sim_printf(" 8255-%d: Port C = %02X\n", devnum, data); + } + } + return 0; +} + +/* end of i8255.c */ diff --git a/Intel-Systems/common/i8259.c b/Intel-Systems/common/i8259.c index 1a0faef3..3a9cec17 100644 --- a/Intel-Systems/common/i8259.c +++ b/Intel-Systems/common/i8259.c @@ -1,268 +1,268 @@ -/* i8259.c: Intel i8259 PIC adapter - - Copyright (c) 2010, 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. - - NOTES: - - This software was written by Bill Beech, 24 Jan 13, to allow emulation of - more complex Multibus Computer Systems. - - This program simulates up to 2 i8259 devices. It handles 1 i8259 - device on the iSBC 80/20 and iSBC 80/30 SBCs. Other devices could be on - other multibus boards in the simulated system. -*/ - -#include "system_defs.h" /* system header in system dir */ - -#define DEBUG 0 - -/* function prototypes */ - -uint8 i8259a(t_bool io, uint8 data); -uint8 i8259b(t_bool io, uint8 data); -void i8259_dump(uint8 devnum); -t_stat i8259_reset (DEVICE *dptr, uint16 baseport); -uint8 i8259_get_dn(void); - -/* external globals */ - -extern uint16 port; //port called in dev_table[port] - -/* external function prototypes */ - -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); - -/* globals */ - -int32 i8259_devnum = 0; //actual number of 8259 instances + 1 -uint16 i8259_port[4]; //baseport port registered to each instance - -uint8 i8259_base[I8259_NUM]; -uint8 i8259_icw1[I8259_NUM]; -uint8 i8259_icw2[I8259_NUM]; -uint8 i8259_icw3[I8259_NUM]; -uint8 i8259_icw4[I8259_NUM]; -uint8 i8259_ocw1[I8259_NUM]; -uint8 i8259_ocw2[I8259_NUM]; -uint8 i8259_ocw3[I8259_NUM]; -uint8 icw_num0 = 1, icw_num1 = 1; - -/* i8259 Standard I/O Data Structures */ -/* up to 2 i8259 devices */ - -UNIT i8259_unit[] = { - { UDATA (0, 0, 0) }, /* i8259 0 */ - { UDATA (0, 0, 0) }, /* i8259 1 */ - { UDATA (0, 0, 0) }, /* i8259 2 */ - { UDATA (0, 0, 0) } /* i8259 3 */ -}; - -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) }, - { NULL } -}; - -DEBTAB i8259_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -/* address width is set to 16 bits to use devices in 8086/8088 implementations */ - -DEVICE i8259_dev = { - "I8259", //name - i8259_unit, //units - i8259_reg, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &i8259_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - 0, //flags - 0, //dctrl - i8259_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. -*/ - -/* Reset routine */ - -t_stat i8259_reset (DEVICE *dptr, uint16 baseport) -{ - if (i8259_devnum >= I8259_NUM) { - sim_printf("i8255_reset: too many devices!\n"); - return SCPE_MEM; - } - sim_printf(" 8259-%d: Reset\n", i8259_devnum); - sim_printf(" 8259-%d: Registered at %04X\n", i8259_devnum, baseport); - i8259_port[i8259_devnum] = baseport; - reg_dev(i8259a, baseport, i8259_devnum); - reg_dev(i8259b, baseport + 1, i8259_devnum); - i8259_unit[i8259_devnum].u3 = 0x00; /* IRR */ - i8259_unit[i8259_devnum].u4 = 0x00; /* ISR */ - i8259_unit[i8259_devnum].u5 = 0x00; /* IMR */ - i8259_devnum++; - return SCPE_OK; -} - -uint8 i8259_get_dn(void) -{ - int i; - - for (i=0; i= i8259_port[i] && port <= i8259_port[i] + 1) - return i; - sim_printf("i8259_get_dn: port %04X not in 8259 device table\n", port); - return 0xFF; -} - -/* i8259 functions */ - -uint8 i8259a(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8259_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - if ((i8259_ocw3[devnum] & 0x03) == 0x02) - return (i8259_unit[devnum].u3); /* IRR */ - if ((i8259_ocw3[devnum] & 0x03) == 0x03) - return (i8259_unit[devnum].u4); /* ISR */ - } else { /* write data port */ - if (data & 0x10) { - icw_num0 = 1; - } - if (icw_num0 == 1) { - i8259_icw1[devnum] = data; /* ICW1 */ - i8259_unit[devnum].u5 = 0x00; /* clear IMR */ - i8259_ocw3[devnum] = 0x02; /* clear OCW3, Sel IRR */ - } else { - switch (data & 0x18) { - case 0: /* OCW2 */ - i8259_ocw2[devnum] = data; - break; - case 8: /* OCW3 */ - i8259_ocw3[devnum] = data; - break; - default: - sim_printf("8259a-%d: OCW Error %02X\n", devnum, data); - break; - } - } - if (DEBUG) - sim_printf(" 8259-%d: A data = %02X\n", devnum, data); - icw_num0++; /* step ICW number */ - } -// i8259_dump(devnum); - } - return 0; -} - -uint8 i8259b(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8259_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - if ((i8259_ocw3[devnum] & 0x03) == 0x02) - return (i8259_unit[devnum].u3); /* IRR */ - if ((i8259_ocw3[devnum] & 0x03) == 0x03) - return (i8259_unit[devnum].u4); /* ISR */ - } else { /* write data port */ - if (data & 0x10) { - icw_num1 = 1; - } - if (icw_num1 == 1) { - i8259_icw1[devnum] = data; /* ICW1 */ - i8259_unit[devnum].u5 = 0x00; /* clear IMR */ - i8259_ocw3[devnum] = 0x02; /* clear OCW3, Sel IRR */ - } else { - switch (data & 0x18) { - case 0: /* OCW2 */ - i8259_ocw2[devnum] = data; - break; - case 8: /* OCW3 */ - i8259_ocw3[devnum] = data; - break; - default: - sim_printf("8259b-%d: OCW Error %02X\n", devnum, data); - break; - } - } - if (DEBUG) - sim_printf(" 8259-%d: B data = %02X\n", devnum, data); - icw_num1++; /* step ICW number */ - } -// i8259_dump(devnum); - } - return 0; -} - -void i8259_dump(uint8 devnum) -{ - sim_printf("Device %d", devnum); - sim_printf(" IRR=%02X", i8259_unit[devnum].u3); - sim_printf(" ISR=%02X", i8259_unit[devnum].u4); - sim_printf(" IMR=%02X", i8259_unit[devnum].u5); - sim_printf(" ICW1=%02X", i8259_icw1[devnum]); - sim_printf(" ICW2=%02X", i8259_icw2[devnum]); - sim_printf(" ICW3=%02X", i8259_icw3[devnum]); - sim_printf(" ICW4=%02X", i8259_icw4[devnum]); - sim_printf(" OCW1=%02X", i8259_ocw1[devnum]); - sim_printf(" OCW2=%02X", i8259_ocw2[devnum]); - sim_printf(" OCW3=%02X\n", i8259_ocw3[devnum]); -} - -/* end of i8259.c */ +/* i8259.c: Intel i8259 PIC adapter + + Copyright (c) 2010, 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. + + NOTES: + + This software was written by Bill Beech, 24 Jan 13, to allow emulation of + more complex Multibus Computer Systems. + + This program simulates up to 2 i8259 devices. It handles 1 i8259 + device on the iSBC 80/20 and iSBC 80/30 SBCs. Other devices could be on + other multibus boards in the simulated system. +*/ + +#include "system_defs.h" /* system header in system dir */ + +#define DEBUG 0 + +/* function prototypes */ + +uint8 i8259a(t_bool io, uint8 data); +uint8 i8259b(t_bool io, uint8 data); +void i8259_dump(uint8 devnum); +t_stat i8259_reset (DEVICE *dptr, uint16 baseport); +uint8 i8259_get_dn(void); + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); + +/* globals */ + +int32 i8259_devnum = 0; //actual number of 8259 instances + 1 +uint16 i8259_port[4]; //baseport port registered to each instance + +uint8 i8259_base[I8259_NUM]; +uint8 i8259_icw1[I8259_NUM]; +uint8 i8259_icw2[I8259_NUM]; +uint8 i8259_icw3[I8259_NUM]; +uint8 i8259_icw4[I8259_NUM]; +uint8 i8259_ocw1[I8259_NUM]; +uint8 i8259_ocw2[I8259_NUM]; +uint8 i8259_ocw3[I8259_NUM]; +uint8 icw_num0 = 1, icw_num1 = 1; + +/* i8259 Standard I/O Data Structures */ +/* up to 2 i8259 devices */ + +UNIT i8259_unit[] = { + { UDATA (0, 0, 0) }, /* i8259 0 */ + { UDATA (0, 0, 0) }, /* i8259 1 */ + { UDATA (0, 0, 0) }, /* i8259 2 */ + { UDATA (0, 0, 0) } /* i8259 3 */ +}; + +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) }, + { NULL } +}; + +DEBTAB i8259_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +/* address width is set to 16 bits to use devices in 8086/8088 implementations */ + +DEVICE i8259_dev = { + "I8259", //name + i8259_unit, //units + i8259_reg, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &i8259_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + i8259_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +/* Reset routine */ + +t_stat i8259_reset (DEVICE *dptr, uint16 baseport) +{ + if (i8259_devnum >= I8259_NUM) { + sim_printf("i8255_reset: too many devices!\n"); + return SCPE_MEM; + } + sim_printf(" 8259-%d: Reset\n", i8259_devnum); + sim_printf(" 8259-%d: Registered at %04X\n", i8259_devnum, baseport); + i8259_port[i8259_devnum] = baseport; + reg_dev(i8259a, baseport, i8259_devnum); + reg_dev(i8259b, baseport + 1, i8259_devnum); + i8259_unit[i8259_devnum].u3 = 0x00; /* IRR */ + i8259_unit[i8259_devnum].u4 = 0x00; /* ISR */ + i8259_unit[i8259_devnum].u5 = 0x00; /* IMR */ + i8259_devnum++; + return SCPE_OK; +} + +uint8 i8259_get_dn(void) +{ + int i; + + for (i=0; i= i8259_port[i] && port <= i8259_port[i] + 1) + return i; + sim_printf("i8259_get_dn: port %04X not in 8259 device table\n", port); + return 0xFF; +} + +/* i8259 functions */ + +uint8 i8259a(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8259_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + if ((i8259_ocw3[devnum] & 0x03) == 0x02) + return (i8259_unit[devnum].u3); /* IRR */ + if ((i8259_ocw3[devnum] & 0x03) == 0x03) + return (i8259_unit[devnum].u4); /* ISR */ + } else { /* write data port */ + if (data & 0x10) { + icw_num0 = 1; + } + if (icw_num0 == 1) { + i8259_icw1[devnum] = data; /* ICW1 */ + i8259_unit[devnum].u5 = 0x00; /* clear IMR */ + i8259_ocw3[devnum] = 0x02; /* clear OCW3, Sel IRR */ + } else { + switch (data & 0x18) { + case 0: /* OCW2 */ + i8259_ocw2[devnum] = data; + break; + case 8: /* OCW3 */ + i8259_ocw3[devnum] = data; + break; + default: + sim_printf("8259a-%d: OCW Error %02X\n", devnum, data); + break; + } + } + if (DEBUG) + sim_printf(" 8259-%d: A data = %02X\n", devnum, data); + icw_num0++; /* step ICW number */ + } +// i8259_dump(devnum); + } + return 0; +} + +uint8 i8259b(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8259_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + if ((i8259_ocw3[devnum] & 0x03) == 0x02) + return (i8259_unit[devnum].u3); /* IRR */ + if ((i8259_ocw3[devnum] & 0x03) == 0x03) + return (i8259_unit[devnum].u4); /* ISR */ + } else { /* write data port */ + if (data & 0x10) { + icw_num1 = 1; + } + if (icw_num1 == 1) { + i8259_icw1[devnum] = data; /* ICW1 */ + i8259_unit[devnum].u5 = 0x00; /* clear IMR */ + i8259_ocw3[devnum] = 0x02; /* clear OCW3, Sel IRR */ + } else { + switch (data & 0x18) { + case 0: /* OCW2 */ + i8259_ocw2[devnum] = data; + break; + case 8: /* OCW3 */ + i8259_ocw3[devnum] = data; + break; + default: + sim_printf("8259b-%d: OCW Error %02X\n", devnum, data); + break; + } + } + if (DEBUG) + sim_printf(" 8259-%d: B data = %02X\n", devnum, data); + icw_num1++; /* step ICW number */ + } +// i8259_dump(devnum); + } + return 0; +} + +void i8259_dump(uint8 devnum) +{ + sim_printf("Device %d", devnum); + sim_printf(" IRR=%02X", i8259_unit[devnum].u3); + sim_printf(" ISR=%02X", i8259_unit[devnum].u4); + sim_printf(" IMR=%02X", i8259_unit[devnum].u5); + sim_printf(" ICW1=%02X", i8259_icw1[devnum]); + sim_printf(" ICW2=%02X", i8259_icw2[devnum]); + sim_printf(" ICW3=%02X", i8259_icw3[devnum]); + sim_printf(" ICW4=%02X", i8259_icw4[devnum]); + sim_printf(" OCW1=%02X", i8259_ocw1[devnum]); + sim_printf(" OCW2=%02X", i8259_ocw2[devnum]); + sim_printf(" OCW3=%02X\n", i8259_ocw3[devnum]); +} + +/* end of i8259.c */ diff --git a/Intel-Systems/common/i8272.c b/Intel-Systems/common/i8272.c index 984cb3ab..22efa496 100644 --- a/Intel-Systems/common/i8272.c +++ b/Intel-Systems/common/i8272.c @@ -1,228 +1,228 @@ -/* i8272.c: Intel 8272 FDC adapter - - Copyright (c) 2010, 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: - - ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. - 24 Apr 15 -- Modified to use simh_debug - - NOTES: - - u6 - unit number/device number -*/ - -#include "system_defs.h" - -/* external globals */ - -extern uint16 port; - -#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ -#define UNIT_ANSI (1 << UNIT_V_ANSI) - -#define TXR 0x01 -#define RXR 0x02 -#define TXE 0x04 -#define SD 0x40 - -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); - -/* function prototypes */ - -t_stat i8272_svc (UNIT *uptr); -t_stat i8272_reset (DEVICE *dptr, uint16 base); -void i8272_reset1(uint8 devnum); -uint8 i8272_get_dn(void); -uint8 i8251s(t_bool io, uint8 data); -uint8 i8251d(t_bool io, uint8 data); - -/* globals */ - -int32 i8272_devnum = 0; //initially, no 8272 instances -uint16 i8272_port[4]; //base port assigned to each 8272 instance - -/* i8272 Standard I/O Data Structures */ -/* up to 4 i8282 devices */ - -UNIT i8272_unit[4] = { - { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT } -}; - -REG i8272_reg[4] = { - { HRDATA (DATA, i8272_unit[0].buf, 8) }, - { HRDATA (STAT, i8272_unit[0].u3, 8) }, - { HRDATA (MODE, i8272_unit[0].u4, 8) }, - { HRDATA (CMD, i8272_unit[0].u5, 8) } -}; - -DEBTAB i8272_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -MTAB i8272_mod[] = { - { UNIT_ANSI, 0, "TTY", "TTY", NULL }, - { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, - { 0 } -}; - -/* address width is set to 16 bits to use devices in 8086/8088 implementations */ - -DEVICE i8272_dev = { - "I8272", //name - i8272_unit, //units - i8272_reg, //registers - i8272_mod, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &i8272_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - 0, //flags - 0, //dctrl - i8272_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Service routines to handle simulator functions */ - -/* i8272_svc - actually does FDD read and write */ - -t_stat i8272_svc(UNIT *uptr) -{ - int32 temp; - - sim_activate(&i8272_unit[uptr->u6], i8272_unit[uptr->u6].wait); /* continue poll */ - if (uptr->u6 >= i8272_devnum) return SCPE_OK; - if ((temp = sim_poll_kbd()) < SCPE_KFLAG) - return temp; /* no char or error? */ - //sim_printf("i8272_svc: received character temp=%04X devnum=%d\n", temp, uptr->u6); - i8272_unit[uptr->u6].buf = temp & 0xFF; /* Save char */ - i8272_unit[uptr->u6].u3 |= RXR; /* Set status */ - return SCPE_OK; -} - -/* Reset routine */ - -t_stat i8272_reset(DEVICE *dptr, uint16 base) -{ - if (i8272_devnum >= i8272_NUM) { - sim_printf("8251_reset: too many devices!\n"); - return 0; - } - i8272_reset1(i8272_devnum); - sim_printf(" 8251-%d: Registered at %03X\n", i8272_devnum, base); - i8272_port[i8272_devnum] = reg_dev(i8251d, base); - reg_dev(i8251s, base + 1); - i8272_unit[i8272_devnum].u6 = i8272_devnum; - sim_activate(&i8272_unit[i8272_devnum], i8272_unit[i8272_devnum].wait); /* activate unit */ - i8272_devnum++; - return SCPE_OK; -} - -void i8272_reset1(uint8 devnum) -{ - i8272_unit[devnum].u3 = TXR + TXE; /* status */ - i8272_unit[devnum].u4 = 0; /* mode instruction */ - i8272_unit[devnum].u5 = 0; /* command instruction */ - i8272_unit[devnum].buf = 0; - i8272_unit[devnum].pos = 0; - sim_printf(" 8251-%d: Reset\n", devnum); -} - -uint8 i8272_get_dn(void) -{ - int i; - - for (i=0; i=i8272_port[i] && port <= i8272_port[i] + 1) - return i; - sim_printf("i8272_get_dn: port %03X not in 8251 device table\n", port); - return 0xFF; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. -*/ - -uint8 i8251s(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8272_get_dn()) != 0xFF) { - if (io == 0) { /* read status port */ - return i8272_unit[devnum].u3; - } else { /* write status port */ - if (i8272_unit[devnum].u6) { /* if mode, set cmd */ - i8272_unit[devnum].u5 = data; - sim_printf(" 8251-%d: Command Instruction=%02X\n", devnum, data); - if (data & SD) /* reset port! */ - i8272_reset1(devnum); - } else { /* set mode */ - i8272_unit[devnum].u4 = data; - sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); - i8272_unit[devnum].u6 = 1; /* set cmd received */ - } - } - } - return 0; -} - -uint8 i8251d(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8272_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - i8272_unit[devnum].u3 &= ~RXR; - return (i8272_unit[devnum].buf); - } else { /* write data port */ - sim_putchar(data); - } - } - return 0; -} - -/* end of i8272.c */ +/* i8272.c: Intel 8272 FDC adapter + + Copyright (c) 2010, 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: + + ?? ??? 10 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + u6 - unit number/device number +*/ + +#include "system_defs.h" + +/* external globals */ + +extern uint16 port; + +#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ +#define UNIT_ANSI (1 << UNIT_V_ANSI) + +#define TXR 0x01 +#define RXR 0x02 +#define TXE 0x04 +#define SD 0x40 + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); + +/* function prototypes */ + +t_stat i8272_svc (UNIT *uptr); +t_stat i8272_reset (DEVICE *dptr, uint16 base); +void i8272_reset1(uint8 devnum); +uint8 i8272_get_dn(void); +uint8 i8251s(t_bool io, uint8 data); +uint8 i8251d(t_bool io, uint8 data); + +/* globals */ + +int32 i8272_devnum = 0; //initially, no 8272 instances +uint16 i8272_port[4]; //base port assigned to each 8272 instance + +/* i8272 Standard I/O Data Structures */ +/* up to 4 i8282 devices */ + +UNIT i8272_unit[4] = { + { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8272_svc, 0, 0), KBD_POLL_WAIT } +}; + +REG i8272_reg[4] = { + { HRDATA (DATA, i8272_unit[0].buf, 8) }, + { HRDATA (STAT, i8272_unit[0].u3, 8) }, + { HRDATA (MODE, i8272_unit[0].u4, 8) }, + { HRDATA (CMD, i8272_unit[0].u5, 8) } +}; + +DEBTAB i8272_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +MTAB i8272_mod[] = { + { UNIT_ANSI, 0, "TTY", "TTY", NULL }, + { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, + { 0 } +}; + +/* address width is set to 16 bits to use devices in 8086/8088 implementations */ + +DEVICE i8272_dev = { + "I8272", //name + i8272_unit, //units + i8272_reg, //registers + i8272_mod, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &i8272_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + i8272_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +/* i8272_svc - actually does FDD read and write */ + +t_stat i8272_svc(UNIT *uptr) +{ + int32 temp; + + sim_activate(&i8272_unit[uptr->u6], i8272_unit[uptr->u6].wait); /* continue poll */ + if (uptr->u6 >= i8272_devnum) return SCPE_OK; + if ((temp = sim_poll_kbd()) < SCPE_KFLAG) + return temp; /* no char or error? */ + //sim_printf("i8272_svc: received character temp=%04X devnum=%d\n", temp, uptr->u6); + i8272_unit[uptr->u6].buf = temp & 0xFF; /* Save char */ + i8272_unit[uptr->u6].u3 |= RXR; /* Set status */ + return SCPE_OK; +} + +/* Reset routine */ + +t_stat i8272_reset(DEVICE *dptr, uint16 base) +{ + if (i8272_devnum >= i8272_NUM) { + sim_printf("8251_reset: too many devices!\n"); + return 0; + } + i8272_reset1(i8272_devnum); + sim_printf(" 8251-%d: Registered at %03X\n", i8272_devnum, base); + i8272_port[i8272_devnum] = reg_dev(i8251d, base); + reg_dev(i8251s, base + 1); + i8272_unit[i8272_devnum].u6 = i8272_devnum; + sim_activate(&i8272_unit[i8272_devnum], i8272_unit[i8272_devnum].wait); /* activate unit */ + i8272_devnum++; + return SCPE_OK; +} + +void i8272_reset1(uint8 devnum) +{ + i8272_unit[devnum].u3 = TXR + TXE; /* status */ + i8272_unit[devnum].u4 = 0; /* mode instruction */ + i8272_unit[devnum].u5 = 0; /* command instruction */ + i8272_unit[devnum].buf = 0; + i8272_unit[devnum].pos = 0; + sim_printf(" 8251-%d: Reset\n", devnum); +} + +uint8 i8272_get_dn(void) +{ + int i; + + for (i=0; i=i8272_port[i] && port <= i8272_port[i] + 1) + return i; + sim_printf("i8272_get_dn: port %03X not in 8251 device table\n", port); + return 0xFF; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +uint8 i8251s(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8272_get_dn()) != 0xFF) { + if (io == 0) { /* read status port */ + return i8272_unit[devnum].u3; + } else { /* write status port */ + if (i8272_unit[devnum].u6) { /* if mode, set cmd */ + i8272_unit[devnum].u5 = data; + sim_printf(" 8251-%d: Command Instruction=%02X\n", devnum, data); + if (data & SD) /* reset port! */ + i8272_reset1(devnum); + } else { /* set mode */ + i8272_unit[devnum].u4 = data; + sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); + i8272_unit[devnum].u6 = 1; /* set cmd received */ + } + } + } + return 0; +} + +uint8 i8251d(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8272_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + i8272_unit[devnum].u3 &= ~RXR; + return (i8272_unit[devnum].buf); + } else { /* write data port */ + sim_putchar(data); + } + } + return 0; +} + +/* end of i8272.c */ diff --git a/Intel-Systems/common/i8273.c b/Intel-Systems/common/i8273.c index 421e0ebd..47b8967b 100644 --- a/Intel-Systems/common/i8273.c +++ b/Intel-Systems/common/i8273.c @@ -1,252 +1,252 @@ -/* i8273.c: Intel i8273 UART adapter - - 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. - - These functions support a simulated i8273 interface device on an iSBC. - The device had one physical I/O port which could be connected - to any serial I/O device that would connect to a current loop, - RS232, or TTY interface. Available baud rates were jumper - selectable for each port from 110 to 9600. - - All I/O is via programmed I/O. The i8273 has a status port - and a data port. - - The simulated device does not support synchronous mode. The simulated device - supports a select from I/O space and one address line. The data port is at the - lower address and the status/command port is at the higher. - - A write to the status port can select some options for the device: - - Asynchronous Mode Instruction - +---+---+---+---+---+---+---+---+ - | S2 S1 EP PEN L2 L1 B2 B1| - +---+---+---+---+---+---+---+---+ - - Baud Rate Factor - B2 0 1 0 1 - B1 0 0 1 1 - sync 1X 16X 64X - mode - - Character Length - L2 0 1 0 1 - L1 0 0 1 1 - 5 6 7 8 - bits bits bits bits - - EP - A 1 in this bit position selects even parity. - PEN - A 1 in this bit position enables parity. - - Number of Stop Bits - S2 0 1 0 1 - S1 0 0 1 1 - invalid 1 1.5 2 - bit bits bits - - Command Instruction Format - +---+---+---+---+---+---+---+---+ - | EH IR RTS ER SBRK RxE DTR TxE| - +---+---+---+---+---+---+---+---+ - - TxE - A 1 in this bit position enables transmit. - DTR - A 1 in this bit position forces *DTR to zero. - RxE - A 1 in this bit position enables receive. - SBRK - A 1 in this bit position forces TxD to zero. - ER - A 1 in this bit position resets the error bits - RTS - A 1 in this bit position forces *RTS to zero. - IR - A 1 in this bit position returns the 8251 to Mode Instruction Format. - EH - A 1 in this bit position enables search for sync characters. - - A read of the status port gets the port status: - - Status Read Format - +---+---+---+---+---+---+---+---+ - |DSR SD FE OE PE TxE RxR TxR| - +---+---+---+---+---+---+---+---+ - - TxR - A 1 in this bit position signals transmit ready to receive a character. - RxR - A 1 in this bit position signals receiver has a character. - TxE - A 1 in this bit position signals transmitter has no more characters to transmit. - PE - A 1 in this bit signals a parity error. - OE - A 1 in this bit signals an transmit overrun error. - FE - A 1 in this bit signals a framing error. - SD - A 1 in this bit position returns the 8251 to Mode Instruction Format. - DSR - A 1 in this bit position signals *DSR is at zero. - - A read to the data port gets the buffered character, a write - to the data port writes the character to the device. - -*/ - -#include - -#include "multibus_defs.h" - -#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ -#define UNIT_ANSI (1 << UNIT_V_ANSI) - -uint8 - wr0 = 0, /* command register */ - wr1 = 0, /* enable register */ - wr2 = 0, /* CH A mode register */ - /* CH B interrups vector */ - wr3 = 0, /* configuration register 1 */ - wr4 = 0, /* configuration register 2 */ - wr5 = 0, /* configuration register 3 */ - wr6 = 0, /* sync low byte */ - wr7 = 0, /* sync high byte */ - rr0 = 0, /* status register */ - rr1 = 0, /* error register */ - rr2 = 0; /* read interrupt vector */ - -/* function prototypes */ - -t_stat i8273_reset (DEVICE *dptr); - -/* i8273 Standard I/O Data Structures */ - -UNIT i8273_unit = { UDATA (NULL, 0, 0), KBD_POLL_WAIT }; - -REG i8273_reg[] = { - { HRDATA (WR0, wr0, 8) }, - { HRDATA (WR1, wr1, 8) }, - { HRDATA (WR2, wr2, 8) }, - { HRDATA (WR3, wr3, 8) }, - { HRDATA (WR4, wr4, 8) }, - { HRDATA (WR5, wr5, 8) }, - { HRDATA (WR6, wr6, 8) }, - { HRDATA (WR7, wr7, 8) }, - { HRDATA (RR0, rr0, 8) }, - { HRDATA (RR0, rr1, 8) }, - { HRDATA (RR0, rr2, 8) }, - { NULL } -}; -MTAB i8273_mod[] = { - { UNIT_ANSI, 0, "TTY", "TTY", NULL }, - { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, - { 0 } -}; - -DEBTAB i8273_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE i8273_dev = { - "I8273", //name - &i8273_unit, //units - i8273_reg, //registers - i8273_mod, //modifiers - 1, //numunits - 16, //aradix - 32, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - i8273_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - i8273_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Service routines to handle simulator functions */ - -/* Reset routine */ - -t_stat i8273_reset (DEVICE *dptr) -{ - wr0 = 0; /* command register */ - wr1 = 0; /* enable register */ - wr2 = 0; /* CH A mode register */ - /* CH B interrups vector */ - wr3 = 0; /* configuration register 1 */ - wr4 = 0; /* configuration register 2 */ - wr5 = 0; /* configuration register 3 */ - wr6 = 0; /* sync low byte */ - wr7 = 0; /* sync high byte */ - rr0 = 0; /* status register */ - rr1 = 0; /* error register */ - rr2 = 0; /* read interrupt vector */ - sim_printf(" 8273 Reset\n"); - return SCPE_OK; -} - -/* 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. -*/ - -int32 i8273s(int32 io, int32 data) -{ - if (io == 0) { /* read status port */ - return i8273_unit.u3; - } else { /* write status port */ - if (data == 0x40) { /* reset port! */ - i8273_unit.u3 = 0x05; /* status */ - i8273_unit.u4 = 0; /* mode instruction */ - i8273_unit.u5 = 0; /* command instruction */ - i8273_unit.u6 = 0; - i8273_unit.buf = 0; - i8273_unit.pos = 0; - sim_printf("8273 Reset\n"); - } else if (i8273_unit.u6) { - i8273_unit.u5 = data; - sim_printf("8273 Command Instruction=%02X\n", data); - } else { - i8273_unit.u4 = data; - sim_printf("8273 Mode Instruction=%02X\n", data); - i8273_unit.u6++; - } - return (0); - } -} - -int32 i8273d(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - i8273_unit.u3 &= 0xFD; - return (i8273_unit.buf); - } else { /* write data port */ - sim_putchar(data); - } - return 0; -} - +/* i8273.c: Intel i8273 UART adapter + + 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. + + These functions support a simulated i8273 interface device on an iSBC. + The device had one physical I/O port which could be connected + to any serial I/O device that would connect to a current loop, + RS232, or TTY interface. Available baud rates were jumper + selectable for each port from 110 to 9600. + + All I/O is via programmed I/O. The i8273 has a status port + and a data port. + + The simulated device does not support synchronous mode. The simulated device + supports a select from I/O space and one address line. The data port is at the + lower address and the status/command port is at the higher. + + A write to the status port can select some options for the device: + + Asynchronous Mode Instruction + +---+---+---+---+---+---+---+---+ + | S2 S1 EP PEN L2 L1 B2 B1| + +---+---+---+---+---+---+---+---+ + + Baud Rate Factor + B2 0 1 0 1 + B1 0 0 1 1 + sync 1X 16X 64X + mode + + Character Length + L2 0 1 0 1 + L1 0 0 1 1 + 5 6 7 8 + bits bits bits bits + + EP - A 1 in this bit position selects even parity. + PEN - A 1 in this bit position enables parity. + + Number of Stop Bits + S2 0 1 0 1 + S1 0 0 1 1 + invalid 1 1.5 2 + bit bits bits + + Command Instruction Format + +---+---+---+---+---+---+---+---+ + | EH IR RTS ER SBRK RxE DTR TxE| + +---+---+---+---+---+---+---+---+ + + TxE - A 1 in this bit position enables transmit. + DTR - A 1 in this bit position forces *DTR to zero. + RxE - A 1 in this bit position enables receive. + SBRK - A 1 in this bit position forces TxD to zero. + ER - A 1 in this bit position resets the error bits + RTS - A 1 in this bit position forces *RTS to zero. + IR - A 1 in this bit position returns the 8251 to Mode Instruction Format. + EH - A 1 in this bit position enables search for sync characters. + + A read of the status port gets the port status: + + Status Read Format + +---+---+---+---+---+---+---+---+ + |DSR SD FE OE PE TxE RxR TxR| + +---+---+---+---+---+---+---+---+ + + TxR - A 1 in this bit position signals transmit ready to receive a character. + RxR - A 1 in this bit position signals receiver has a character. + TxE - A 1 in this bit position signals transmitter has no more characters to transmit. + PE - A 1 in this bit signals a parity error. + OE - A 1 in this bit signals an transmit overrun error. + FE - A 1 in this bit signals a framing error. + SD - A 1 in this bit position returns the 8251 to Mode Instruction Format. + DSR - A 1 in this bit position signals *DSR is at zero. + + A read to the data port gets the buffered character, a write + to the data port writes the character to the device. + +*/ + +#include + +#include "multibus_defs.h" + +#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ +#define UNIT_ANSI (1 << UNIT_V_ANSI) + +uint8 + wr0 = 0, /* command register */ + wr1 = 0, /* enable register */ + wr2 = 0, /* CH A mode register */ + /* CH B interrups vector */ + wr3 = 0, /* configuration register 1 */ + wr4 = 0, /* configuration register 2 */ + wr5 = 0, /* configuration register 3 */ + wr6 = 0, /* sync low byte */ + wr7 = 0, /* sync high byte */ + rr0 = 0, /* status register */ + rr1 = 0, /* error register */ + rr2 = 0; /* read interrupt vector */ + +/* function prototypes */ + +t_stat i8273_reset (DEVICE *dptr); + +/* i8273 Standard I/O Data Structures */ + +UNIT i8273_unit = { UDATA (NULL, 0, 0), KBD_POLL_WAIT }; + +REG i8273_reg[] = { + { HRDATA (WR0, wr0, 8) }, + { HRDATA (WR1, wr1, 8) }, + { HRDATA (WR2, wr2, 8) }, + { HRDATA (WR3, wr3, 8) }, + { HRDATA (WR4, wr4, 8) }, + { HRDATA (WR5, wr5, 8) }, + { HRDATA (WR6, wr6, 8) }, + { HRDATA (WR7, wr7, 8) }, + { HRDATA (RR0, rr0, 8) }, + { HRDATA (RR0, rr1, 8) }, + { HRDATA (RR0, rr2, 8) }, + { NULL } +}; +MTAB i8273_mod[] = { + { UNIT_ANSI, 0, "TTY", "TTY", NULL }, + { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, + { 0 } +}; + +DEBTAB i8273_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE i8273_dev = { + "I8273", //name + &i8273_unit, //units + i8273_reg, //registers + i8273_mod, //modifiers + 1, //numunits + 16, //aradix + 32, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + i8273_reset, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + i8273_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +/* Reset routine */ + +t_stat i8273_reset (DEVICE *dptr) +{ + wr0 = 0; /* command register */ + wr1 = 0; /* enable register */ + wr2 = 0; /* CH A mode register */ + /* CH B interrups vector */ + wr3 = 0; /* configuration register 1 */ + wr4 = 0; /* configuration register 2 */ + wr5 = 0; /* configuration register 3 */ + wr6 = 0; /* sync low byte */ + wr7 = 0; /* sync high byte */ + rr0 = 0; /* status register */ + rr1 = 0; /* error register */ + rr2 = 0; /* read interrupt vector */ + sim_printf(" 8273 Reset\n"); + return SCPE_OK; +} + +/* 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. +*/ + +int32 i8273s(int32 io, int32 data) +{ + if (io == 0) { /* read status port */ + return i8273_unit.u3; + } else { /* write status port */ + if (data == 0x40) { /* reset port! */ + i8273_unit.u3 = 0x05; /* status */ + i8273_unit.u4 = 0; /* mode instruction */ + i8273_unit.u5 = 0; /* command instruction */ + i8273_unit.u6 = 0; + i8273_unit.buf = 0; + i8273_unit.pos = 0; + sim_printf("8273 Reset\n"); + } else if (i8273_unit.u6) { + i8273_unit.u5 = data; + sim_printf("8273 Command Instruction=%02X\n", data); + } else { + i8273_unit.u4 = data; + sim_printf("8273 Mode Instruction=%02X\n", data); + i8273_unit.u6++; + } + return (0); + } +} + +int32 i8273d(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + i8273_unit.u3 &= 0xFD; + return (i8273_unit.buf); + } else { /* write data port */ + sim_putchar(data); + } + return 0; +} + diff --git a/Intel-Systems/common/i8274.c b/Intel-Systems/common/i8274.c index 930a165c..6eb8742b 100644 --- a/Intel-Systems/common/i8274.c +++ b/Intel-Systems/common/i8274.c @@ -1,351 +1,351 @@ -/* i8274.c: Intel i8274 MPSC adapter - - 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. - - These functions support a simulated i8274 interface device on an iSBC. - The device had two physical I/O ports which could be connected - to any serial I/O device that would connect to an RS232 interface. - - All I/O is via programmed I/O. The i8274 has a status port - and a data port. - - The simulated device does not support synchronous mode. The simulated device - supports a select from I/O space and two address lines. The data port is at the - lower address and the status/command port is at the higher address for each - channel. - - Minimum simulation is provided for this device. Channel A is used as a - console port for the iSBC-88/45 - - A write to the status port can select some options for the device: - - Asynchronous Mode Instruction - +---+---+---+---+---+---+---+---+ - | S2 S1 EP PEN L2 L1 B2 B1| - +---+---+---+---+---+---+---+---+ - - Baud Rate Factor - B2 0 1 0 1 - B1 0 0 1 1 - sync 1X 16X 64X - mode - - Character Length - L2 0 1 0 1 - L1 0 0 1 1 - 5 6 7 8 - bits bits bits bits - - EP - A 1 in this bit position selects even parity. - PEN - A 1 in this bit position enables parity. - - Number of Stop Bits - S2 0 1 0 1 - S1 0 0 1 1 - invalid 1 1.5 2 - bit bits bits - - Command Instruction Format - +---+---+---+---+---+---+---+---+ - | EH IR RTS ER SBRK RxE DTR TxE| - +---+---+---+---+---+---+---+---+ - - TxE - A 1 in this bit position enables transmit. - DTR - A 1 in this bit position forces *DTR to zero. - RxE - A 1 in this bit position enables receive. - SBRK - A 1 in this bit position forces TxD to zero. - ER - A 1 in this bit position resets the error bits - RTS - A 1 in this bit position forces *RTS to zero. - IR - A 1 in this bit position returns the 8251 to Mode Instruction Format. - EH - A 1 in this bit position enables search for sync characters. - - A read of the status port gets the port status: - - Status Read Format - +---+---+---+---+---+---+---+---+ - |DSR SD FE OE PE TxE RxR TxR| - +---+---+---+---+---+---+---+---+ - - TxR - A 1 in this bit position signals transmit ready to receive a character. - RxR - A 1 in this bit position signals receiver has a character. - TxE - A 1 in this bit position signals transmitter has no more characters to transmit. - PE - A 1 in this bit signals a parity error. - OE - A 1 in this bit signals an transmit overrun error. - FE - A 1 in this bit signals a framing error. - SD - A 1 in this bit position returns the 8251 to Mode Instruction Format. - DSR - A 1 in this bit position signals *DSR is at zero. - - A read to the data port gets the buffered character, a write - to the data port writes the character to the device. - -*/ - -#include - -#include "multibus_defs.h" - -#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ -#define UNIT_ANSI (1 << UNIT_V_ANSI) - -/* register definitions */ -/* channel A */ -uint8 wr0a = 0, /* command register */ - wr1a = 0, /* enable register */ - wr2a = 0, /* mode register */ - wr3a = 0, /* configuration register 1 */ - wr4a = 0, /* configuration register 2 */ - wr5a = 0, /* configuration register 3 */ - wr6a = 0, /* sync low byte */ - wr7a = 0, /* sync high byte */ - rr0a = 0, /* status register */ - rr1a = 0, /* error register */ - rr2a = 0; /* read interrupt vector */ -/* channel B */ -uint8 wr0b = 0, /* command register */ - wr1b = 0, /* enable register */ - wr2b = 0, /* CH B interrups vector */ - wr3b = 0, /* configuration register 1 */ - wr4b = 0, /* configuration register 2 */ - wr5b = 0, /* configuration register 3 */ - wr6b = 0, /* sync low byte */ - wr7b = 0, /* sync high byte */ - rr0b = 0, /* status register */ - rr1b = 0, /* error register */ - rr2b = 0; /* read interrupt vector */ - -/* function prototypes */ - -t_stat i8274_svc (UNIT *uptr); -t_stat i8274_reset (DEVICE *dptr); -int32 i8274As(int32 io, int32 data); -int32 i8274Ad(int32 io, int32 data); -int32 i8274Bs(int32 io, int32 data); -int32 i8274Bd(int32 io, int32 data); - -/* i8274 Standard I/O Data Structures */ - -UNIT i8274_unit = { UDATA (NULL, 0, 0), KBD_POLL_WAIT }; - -REG i8274_reg[] = { - { HRDATA (WR0A, wr0a, 8) }, - { HRDATA (WR1A, wr1a, 8) }, - { HRDATA (WR2A, wr2a, 8) }, - { HRDATA (WR3A, wr3a, 8) }, - { HRDATA (WR4A, wr4a, 8) }, - { HRDATA (WR5A, wr5a, 8) }, - { HRDATA (WR6A, wr6a, 8) }, - { HRDATA (WR7A, wr7a, 8) }, - { HRDATA (RR0A, rr0a, 8) }, - { HRDATA (RR0A, rr1a, 8) }, - { HRDATA (RR0A, rr2a, 8) }, - { HRDATA (WR0B, wr0b, 8) }, - { HRDATA (WR1B, wr1b, 8) }, - { HRDATA (WR2B, wr2b, 8) }, - { HRDATA (WR3B, wr3b, 8) }, - { HRDATA (WR4B, wr4b, 8) }, - { HRDATA (WR5B, wr5b, 8) }, - { HRDATA (WR6B, wr6b, 8) }, - { HRDATA (WR7B, wr7b, 8) }, - { HRDATA (RR0B, rr0b, 8) }, - { HRDATA (RR0B, rr1b, 8) }, - { HRDATA (RR0B, rr2b, 8) }, - { NULL } -}; -MTAB i8274_mod[] = { - { UNIT_ANSI, 0, "TTY", "TTY", NULL }, - { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, - { 0 } -}; - -DEBTAB i8274_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE i8274_dev = { - "I8274", //name - &i8274_unit, //units - i8274_reg, //registers - i8274_mod, //modifiers - 1, //numunits - 16, //aradix - 32, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - i8274_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - i8274_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Service routines to handle simulator functions */ - -/* service routine - actually gets char & places in buffer in CH A*/ - -t_stat i8274_svc (UNIT *uptr) -{ - int32 temp; - - sim_activate (&i8274_unit, i8274_unit.wait); /* continue poll */ - if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) - return temp; /* no char or error? */ - i8274_unit.buf = temp & 0xFF; /* Save char */ - rr0a |= 0x01; /* Set rx char ready */ - - /* Do any special character handling here */ - - i8274_unit.pos++; - return SCPE_OK; -} - -/* Reset routine */ - -t_stat i8274_reset (DEVICE *dptr) -{ - wr0a = wr1a = wr2a = wr3a = wr4a = wr5a = wr6a = wr7a = rr0a = rr1a = rr2a = 0; - wr0b = wr1b = wr2b = wr3b = wr4b = wr5b = wr6b = wr7b = rr0b = rr1b = rr2b = 0; - sim_printf(" 8274 Reset\n"); - return SCPE_OK; -} - -/* 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. - - The 8274 contains 2 separate channels, A and B. -*/ - -/* channel A command/status */ -int32 i8274As(int32 io, int32 data) -{ - if (io == 0) { /* read status port */ - switch(wr0a & 0x7) { - case 0: /* rr0a */ - return rr0a; - case 1: /* rr1a */ - return rr1a; - case 2: /* rr1a */ - return rr2a; - } - return 0; /* bad register select */ - } else { /* write status port */ - switch(wr0a & 0x7) { - case 0: /* wr0a */ - wr0a = data; - if ((wr0a & 0x38) == 0x18) { /* channel reset */ - wr0a = wr1a = wr2a = wr3a = wr4a = wr5a = 0; - wr6a = wr7a = rr0a = rr1a = rr2a = 0; - sim_printf("8274 Channel A reset\n"); - } - break; - case 1: /* wr1a */ - wr1a = data; - break; - case 2: /* wr2a */ - wr2a = data; - break; - case 3: /* wr3a */ - wr3a = data; - break; - case 4: /* wr4a */ - wr4a = data; - break; - case 5: /* wr5a */ - wr5a = data; - break; - case 6: /* wr6a */ - wr6a = data; - break; - case 7: /* wr7a */ - wr7a = data; - break; - } - sim_printf("8274 Command WR%dA=%02X\n", wr0a & 0x7, data); - return 0; - } -} - -/* channel A data */ -int32 i8274Ad(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - rr0a &= 0xFE; - return (i8274_unit.buf); - } else { /* write data port */ - sim_putchar(data); - } - return 0; -} - -/* channel B command/status */ -int32 i8274Bs(int32 io, int32 data) -{ - if (io == 0) { /* read status port */ - return i8274_unit.u3; - } else { /* write status port */ - if (data == 0x40) { /* reset port! */ - sim_printf("8274 Reset\n"); - } else if (i8274_unit.u6) { - i8274_unit.u5 = data; - sim_printf("8274 Command Instruction=%02X\n", data); - } else { - i8274_unit.u4 = data; - sim_printf("8274 Mode Instruction=%02X\n", data); - i8274_unit.u6++; - } - return (0); - } -} - -/* channel B data */ -int32 i8274Bd(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - i8274_unit.u3 &= 0xFD; - return (i8274_unit.buf); - } else { /* write data port */ - sim_putchar(data); - } - return 0; -} - +/* i8274.c: Intel i8274 MPSC adapter + + 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. + + These functions support a simulated i8274 interface device on an iSBC. + The device had two physical I/O ports which could be connected + to any serial I/O device that would connect to an RS232 interface. + + All I/O is via programmed I/O. The i8274 has a status port + and a data port. + + The simulated device does not support synchronous mode. The simulated device + supports a select from I/O space and two address lines. The data port is at the + lower address and the status/command port is at the higher address for each + channel. + + Minimum simulation is provided for this device. Channel A is used as a + console port for the iSBC-88/45 + + A write to the status port can select some options for the device: + + Asynchronous Mode Instruction + +---+---+---+---+---+---+---+---+ + | S2 S1 EP PEN L2 L1 B2 B1| + +---+---+---+---+---+---+---+---+ + + Baud Rate Factor + B2 0 1 0 1 + B1 0 0 1 1 + sync 1X 16X 64X + mode + + Character Length + L2 0 1 0 1 + L1 0 0 1 1 + 5 6 7 8 + bits bits bits bits + + EP - A 1 in this bit position selects even parity. + PEN - A 1 in this bit position enables parity. + + Number of Stop Bits + S2 0 1 0 1 + S1 0 0 1 1 + invalid 1 1.5 2 + bit bits bits + + Command Instruction Format + +---+---+---+---+---+---+---+---+ + | EH IR RTS ER SBRK RxE DTR TxE| + +---+---+---+---+---+---+---+---+ + + TxE - A 1 in this bit position enables transmit. + DTR - A 1 in this bit position forces *DTR to zero. + RxE - A 1 in this bit position enables receive. + SBRK - A 1 in this bit position forces TxD to zero. + ER - A 1 in this bit position resets the error bits + RTS - A 1 in this bit position forces *RTS to zero. + IR - A 1 in this bit position returns the 8251 to Mode Instruction Format. + EH - A 1 in this bit position enables search for sync characters. + + A read of the status port gets the port status: + + Status Read Format + +---+---+---+---+---+---+---+---+ + |DSR SD FE OE PE TxE RxR TxR| + +---+---+---+---+---+---+---+---+ + + TxR - A 1 in this bit position signals transmit ready to receive a character. + RxR - A 1 in this bit position signals receiver has a character. + TxE - A 1 in this bit position signals transmitter has no more characters to transmit. + PE - A 1 in this bit signals a parity error. + OE - A 1 in this bit signals an transmit overrun error. + FE - A 1 in this bit signals a framing error. + SD - A 1 in this bit position returns the 8251 to Mode Instruction Format. + DSR - A 1 in this bit position signals *DSR is at zero. + + A read to the data port gets the buffered character, a write + to the data port writes the character to the device. + +*/ + +#include + +#include "multibus_defs.h" + +#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ +#define UNIT_ANSI (1 << UNIT_V_ANSI) + +/* register definitions */ +/* channel A */ +uint8 wr0a = 0, /* command register */ + wr1a = 0, /* enable register */ + wr2a = 0, /* mode register */ + wr3a = 0, /* configuration register 1 */ + wr4a = 0, /* configuration register 2 */ + wr5a = 0, /* configuration register 3 */ + wr6a = 0, /* sync low byte */ + wr7a = 0, /* sync high byte */ + rr0a = 0, /* status register */ + rr1a = 0, /* error register */ + rr2a = 0; /* read interrupt vector */ +/* channel B */ +uint8 wr0b = 0, /* command register */ + wr1b = 0, /* enable register */ + wr2b = 0, /* CH B interrups vector */ + wr3b = 0, /* configuration register 1 */ + wr4b = 0, /* configuration register 2 */ + wr5b = 0, /* configuration register 3 */ + wr6b = 0, /* sync low byte */ + wr7b = 0, /* sync high byte */ + rr0b = 0, /* status register */ + rr1b = 0, /* error register */ + rr2b = 0; /* read interrupt vector */ + +/* function prototypes */ + +t_stat i8274_svc (UNIT *uptr); +t_stat i8274_reset (DEVICE *dptr); +int32 i8274As(int32 io, int32 data); +int32 i8274Ad(int32 io, int32 data); +int32 i8274Bs(int32 io, int32 data); +int32 i8274Bd(int32 io, int32 data); + +/* i8274 Standard I/O Data Structures */ + +UNIT i8274_unit = { UDATA (NULL, 0, 0), KBD_POLL_WAIT }; + +REG i8274_reg[] = { + { HRDATA (WR0A, wr0a, 8) }, + { HRDATA (WR1A, wr1a, 8) }, + { HRDATA (WR2A, wr2a, 8) }, + { HRDATA (WR3A, wr3a, 8) }, + { HRDATA (WR4A, wr4a, 8) }, + { HRDATA (WR5A, wr5a, 8) }, + { HRDATA (WR6A, wr6a, 8) }, + { HRDATA (WR7A, wr7a, 8) }, + { HRDATA (RR0A, rr0a, 8) }, + { HRDATA (RR0A, rr1a, 8) }, + { HRDATA (RR0A, rr2a, 8) }, + { HRDATA (WR0B, wr0b, 8) }, + { HRDATA (WR1B, wr1b, 8) }, + { HRDATA (WR2B, wr2b, 8) }, + { HRDATA (WR3B, wr3b, 8) }, + { HRDATA (WR4B, wr4b, 8) }, + { HRDATA (WR5B, wr5b, 8) }, + { HRDATA (WR6B, wr6b, 8) }, + { HRDATA (WR7B, wr7b, 8) }, + { HRDATA (RR0B, rr0b, 8) }, + { HRDATA (RR0B, rr1b, 8) }, + { HRDATA (RR0B, rr2b, 8) }, + { NULL } +}; +MTAB i8274_mod[] = { + { UNIT_ANSI, 0, "TTY", "TTY", NULL }, + { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, + { 0 } +}; + +DEBTAB i8274_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE i8274_dev = { + "I8274", //name + &i8274_unit, //units + i8274_reg, //registers + i8274_mod, //modifiers + 1, //numunits + 16, //aradix + 32, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + i8274_reset, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + i8274_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +/* service routine - actually gets char & places in buffer in CH A*/ + +t_stat i8274_svc (UNIT *uptr) +{ + int32 temp; + + sim_activate (&i8274_unit, i8274_unit.wait); /* continue poll */ + if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) + return temp; /* no char or error? */ + i8274_unit.buf = temp & 0xFF; /* Save char */ + rr0a |= 0x01; /* Set rx char ready */ + + /* Do any special character handling here */ + + i8274_unit.pos++; + return SCPE_OK; +} + +/* Reset routine */ + +t_stat i8274_reset (DEVICE *dptr) +{ + wr0a = wr1a = wr2a = wr3a = wr4a = wr5a = wr6a = wr7a = rr0a = rr1a = rr2a = 0; + wr0b = wr1b = wr2b = wr3b = wr4b = wr5b = wr6b = wr7b = rr0b = rr1b = rr2b = 0; + sim_printf(" 8274 Reset\n"); + return SCPE_OK; +} + +/* 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. + + The 8274 contains 2 separate channels, A and B. +*/ + +/* channel A command/status */ +int32 i8274As(int32 io, int32 data) +{ + if (io == 0) { /* read status port */ + switch(wr0a & 0x7) { + case 0: /* rr0a */ + return rr0a; + case 1: /* rr1a */ + return rr1a; + case 2: /* rr1a */ + return rr2a; + } + return 0; /* bad register select */ + } else { /* write status port */ + switch(wr0a & 0x7) { + case 0: /* wr0a */ + wr0a = data; + if ((wr0a & 0x38) == 0x18) { /* channel reset */ + wr0a = wr1a = wr2a = wr3a = wr4a = wr5a = 0; + wr6a = wr7a = rr0a = rr1a = rr2a = 0; + sim_printf("8274 Channel A reset\n"); + } + break; + case 1: /* wr1a */ + wr1a = data; + break; + case 2: /* wr2a */ + wr2a = data; + break; + case 3: /* wr3a */ + wr3a = data; + break; + case 4: /* wr4a */ + wr4a = data; + break; + case 5: /* wr5a */ + wr5a = data; + break; + case 6: /* wr6a */ + wr6a = data; + break; + case 7: /* wr7a */ + wr7a = data; + break; + } + sim_printf("8274 Command WR%dA=%02X\n", wr0a & 0x7, data); + return 0; + } +} + +/* channel A data */ +int32 i8274Ad(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + rr0a &= 0xFE; + return (i8274_unit.buf); + } else { /* write data port */ + sim_putchar(data); + } + return 0; +} + +/* channel B command/status */ +int32 i8274Bs(int32 io, int32 data) +{ + if (io == 0) { /* read status port */ + return i8274_unit.u3; + } else { /* write status port */ + if (data == 0x40) { /* reset port! */ + sim_printf("8274 Reset\n"); + } else if (i8274_unit.u6) { + i8274_unit.u5 = data; + sim_printf("8274 Command Instruction=%02X\n", data); + } else { + i8274_unit.u4 = data; + sim_printf("8274 Mode Instruction=%02X\n", data); + i8274_unit.u6++; + } + return (0); + } +} + +/* channel B data */ +int32 i8274Bd(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + i8274_unit.u3 &= 0xFD; + return (i8274_unit.buf); + } else { /* write data port */ + sim_putchar(data); + } + return 0; +} + /* end of i8274.c */ \ No newline at end of file diff --git a/Intel-Systems/common/ieprom.c b/Intel-Systems/common/ieprom.c index f3658deb..36f19ab4 100644 --- a/Intel-Systems/common/ieprom.c +++ b/Intel-Systems/common/ieprom.c @@ -1,186 +1,186 @@ -/* iEPROM.c: Intel EPROM simulator for 8-bit SBCs - - Copyright (c) 2010, 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: - - ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. - 24 Apr 15 -- Modified to use simh_debug - - NOTES: - - These functions support a simulated ROM devices on an iSBC-80/XX SBCs. - This allows the attachment of the device to a binary file containing the EPROM - code image. Unit will support a single 2708, 2716, 2732, or 2764 type EPROM. - These functions also support bit 1 of 8255 number 1, port B, to enable/ - disable the onboard ROM. -*/ - -#include "system_defs.h" - -/* function prototypes */ - -t_stat EPROM_attach (UNIT *uptr, CONST char *cptr); -t_stat EPROM_reset (DEVICE *dptr, uint16 size); -uint8 EPROM_get_mbyte(uint16 addr); - -/* external function prototypes */ - -extern uint8 i8255_C[4]; //port c byte I/O -extern uint8 xack; /* XACK signal */ - -/* SIMH EPROM Standard I/O Data Structures */ - -UNIT EPROM_unit = { - UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0), 0 -}; - -DEBTAB EPROM_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE EPROM_dev = { - "EPROM", //name - &EPROM_unit, //units - NULL, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &EPROM_reset, //reset - NULL, //reset - NULL, //boot - &EPROM_attach, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl -// 0, //dctrl - EPROM_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* global variables */ - -/* EPROM functions */ - -/* EPROM attach */ - -t_stat EPROM_attach (UNIT *uptr, CONST char *cptr) -{ - uint16 j; - int c; - FILE *fp; - t_stat r; - - sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: cptr=%s\n", cptr); - if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { - sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Error\n"); - return r; - } - sim_debug (DEBUG_read, &EPROM_dev, "\tAllocate buffer\n"); - if (EPROM_unit.filebuf == NULL) { /* no buffer allocated */ - EPROM_unit.filebuf = malloc(EPROM_unit.capac); /* allocate EPROM buffer */ - if (EPROM_unit.filebuf == NULL) { - sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Malloc error\n"); - return SCPE_MEM; - } - } - sim_debug (DEBUG_read, &EPROM_dev, "\tOpen file %s\n", EPROM_unit.filename); - fp = fopen(EPROM_unit.filename, "rb"); /* open EPROM file */ - if (fp == NULL) { - sim_printf("EPROM: Unable to open ROM file %s\n", EPROM_unit.filename); - sim_printf("\tNo ROM image loaded!!!\n"); - return SCPE_OK; - } - sim_debug (DEBUG_read, &EPROM_dev, "\tRead file\n"); - j = 0; /* load EPROM file */ - c = fgetc(fp); - while (c != EOF) { - *((uint8 *)EPROM_unit.filebuf + j++) = c & 0xFF; - c = fgetc(fp); - if (j >= EPROM_unit.capac) { - sim_printf("\tImage is too large - Load truncated!!!\n"); - break; - } - } - sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n"); - fclose(fp); - sim_printf(" EPROM: Configured %d bytes, Attached to %s\n", - EPROM_unit.capac, EPROM_unit.filename); - sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Done\n"); - return SCPE_OK; -} - -/* EPROM reset */ - -t_stat EPROM_reset (DEVICE *dptr, uint16 size) -{ - sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=0000 size=%04X\n", size); - if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */ - EPROM_unit.capac = size; /* set EPROM size to 0 */ - sim_printf(" EPROM: Configured, Not attached\n"); - sim_debug (DEBUG_flow, &EPROM_dev, "Done1\n"); - } else { - sim_printf(" EPROM: Configured %d bytes, Attached to %s\n", - EPROM_unit.capac, EPROM_unit.filename); - } - sim_debug (DEBUG_flow, &EPROM_dev, "Done2\n"); - return SCPE_OK; -} - -/* get a byte from memory */ - -uint8 EPROM_get_mbyte(uint16 addr) -{ - uint8 val; - - sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%04X\n", addr); - if (addr < EPROM_unit.capac) { - SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_xack, &EPROM_dev, "EPROM_get_mbyte: Set XACK for %04X\n", addr); - val = *((uint8 *)EPROM_unit.filebuf + addr); - sim_debug (DEBUG_read, &EPROM_dev, " val=%04X\n", val); - return (val & 0xFF); - } else { - sim_debug (DEBUG_read, &EPROM_dev, " Out of range\n"); - return 0; - } -} - -/* end of iEPROM.c */ +/* iEPROM.c: Intel EPROM simulator for 8-bit SBCs + + Copyright (c) 2010, 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: + + ?? ??? 10 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + These functions support a simulated ROM devices on an iSBC-80/XX SBCs. + This allows the attachment of the device to a binary file containing the EPROM + code image. Unit will support a single 2708, 2716, 2732, or 2764 type EPROM. + These functions also support bit 1 of 8255 number 1, port B, to enable/ + disable the onboard ROM. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat EPROM_attach (UNIT *uptr, CONST char *cptr); +t_stat EPROM_reset (DEVICE *dptr, uint16 size); +uint8 EPROM_get_mbyte(uint16 addr); + +/* external function prototypes */ + +extern uint8 i8255_C[4]; //port c byte I/O +extern uint8 xack; /* XACK signal */ + +/* SIMH EPROM Standard I/O Data Structures */ + +UNIT EPROM_unit = { + UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0), 0 +}; + +DEBTAB EPROM_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE EPROM_dev = { + "EPROM", //name + &EPROM_unit, //units + NULL, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &EPROM_reset, //reset + NULL, //reset + NULL, //boot + &EPROM_attach, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + DEBUG_flow + DEBUG_read + DEBUG_write, //dctrl +// 0, //dctrl + EPROM_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* global variables */ + +/* EPROM functions */ + +/* EPROM attach */ + +t_stat EPROM_attach (UNIT *uptr, CONST char *cptr) +{ + uint16 j; + int c; + FILE *fp; + t_stat r; + + sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: cptr=%s\n", cptr); + if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { + sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Error\n"); + return r; + } + sim_debug (DEBUG_read, &EPROM_dev, "\tAllocate buffer\n"); + if (EPROM_unit.filebuf == NULL) { /* no buffer allocated */ + EPROM_unit.filebuf = malloc(EPROM_unit.capac); /* allocate EPROM buffer */ + if (EPROM_unit.filebuf == NULL) { + sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Malloc error\n"); + return SCPE_MEM; + } + } + sim_debug (DEBUG_read, &EPROM_dev, "\tOpen file %s\n", EPROM_unit.filename); + fp = fopen(EPROM_unit.filename, "rb"); /* open EPROM file */ + if (fp == NULL) { + sim_printf("EPROM: Unable to open ROM file %s\n", EPROM_unit.filename); + sim_printf("\tNo ROM image loaded!!!\n"); + return SCPE_OK; + } + sim_debug (DEBUG_read, &EPROM_dev, "\tRead file\n"); + j = 0; /* load EPROM file */ + c = fgetc(fp); + while (c != EOF) { + *((uint8 *)EPROM_unit.filebuf + j++) = c & 0xFF; + c = fgetc(fp); + if (j >= EPROM_unit.capac) { + sim_printf("\tImage is too large - Load truncated!!!\n"); + break; + } + } + sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n"); + fclose(fp); + sim_printf(" EPROM: Configured %d bytes, Attached to %s\n", + EPROM_unit.capac, EPROM_unit.filename); + sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Done\n"); + return SCPE_OK; +} + +/* EPROM reset */ + +t_stat EPROM_reset (DEVICE *dptr, uint16 size) +{ + sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=0000 size=%04X\n", size); + if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */ + EPROM_unit.capac = size; /* set EPROM size to 0 */ + sim_printf(" EPROM: Configured, Not attached\n"); + sim_debug (DEBUG_flow, &EPROM_dev, "Done1\n"); + } else { + sim_printf(" EPROM: Configured %d bytes, Attached to %s\n", + EPROM_unit.capac, EPROM_unit.filename); + } + sim_debug (DEBUG_flow, &EPROM_dev, "Done2\n"); + return SCPE_OK; +} + +/* get a byte from memory */ + +uint8 EPROM_get_mbyte(uint16 addr) +{ + uint8 val; + + sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%04X\n", addr); + if (addr < EPROM_unit.capac) { + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &EPROM_dev, "EPROM_get_mbyte: Set XACK for %04X\n", addr); + val = *((uint8 *)EPROM_unit.filebuf + addr); + sim_debug (DEBUG_read, &EPROM_dev, " val=%04X\n", val); + return (val & 0xFF); + } else { + sim_debug (DEBUG_read, &EPROM_dev, " Out of range\n"); + return 0; + } +} + +/* end of iEPROM.c */ diff --git a/Intel-Systems/common/ijedec.c b/Intel-Systems/common/ijedec.c index f5c63212..70a6fd87 100644 --- a/Intel-Systems/common/ijedec.c +++ b/Intel-Systems/common/ijedec.c @@ -1,486 +1,486 @@ -/* iJEDEC.c: Intel JEDEC Universal Site simulator for SBCs - - 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. - - These functions support a simulated i2732 JEDEC device on an iSBC. This - allows the attachment of the device to a binary file containing the JEDEC - code. - - Unit will support 8, 16 and 32 KB EPROMs as well as 8 and 16 KB static - RAMs in the JEDEC sockets. Units must be configured for 8KB for 8KB - SRAM and 32KB for 32KB SRAM. If configured for 16KB, SRAM cannot be - configured. Size is set by configuring the top JEDEC site for an EPROM. - Size and spacing for the other JEDEC units is derived from the top JEDEC - site configuration. Changing the top JEDEC site will clear the - configuration of all other JEDEC sites. The JEDEC driver can be set for - either 8- or 16bit data access. - - The top JEDEC site can only be configured to contain an EPROM. - It contains the reset address for the 8088, 8086, 80188, 80186, - and 80286. - - For illustration 8-bit mode - 4 Sites - configured for 8KB chips - - +--------+ 0xFFFFF - | | - | jedec3 | Only ROM - | | - +--------+ 0xFE000 - - +--------+ 0xFDFFF - | | - | jedec2 | RAM/ROM - | | - +--------+ 0xFC000 - - +--------+ 0xFBFFF - | | - | jedec1 | RAM/ROM - | | - +--------+ 0xFA000 - - +--------+ 0xF9FFF - | | - | jedec0 | RAM/ROM - | | - +--------+ 0xF8000 - - For illustration 16-bit mode - 4 Sites - configured for 8KB chips - - Odd data byte Even data byte - High data byte Low data byte - +--------+ 0xFFFFF +--------+ 0xFFFFE - | | | | - | jedec3 | Only ROM | jedec2 | Only ROM - | | | | - +--------+ 0xFC001 +--------+ 0xFC000 - - +--------+ 0xFBFFF +--------+ 0xFBFFE - | | | | - | jedec3 | RAM/ROM | jedec2 | RAM/ROM - | | | | - +--------+ 0xF8001 +--------+ 0xF8000 - - uptr->filename - ROM image file attached to unit - uptr->capac - unit capacity in bytes - uptr->u3 - unit base address - uptr->u4 - unit device type {none|8krom|16krom|32krom|8kram|32kram} - uptr->u5 - unit flags - ROM or RAM, 8 or 16BIT (top unit only) - uptr->u6 - unit number -*/ - -#include - -#include "multibus_defs.h" - -#define JEDEC_NUM 4 - -#define UNIT_V_DMODE (UNIT_V_UF) /* data bus mode */ -#define UNIT_DMODE (1 << UNIT_V_DMODE) -#define UNIT_V_MSIZE (UNIT_V_UF+1) /* Memory Size */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) -#define UNIT_NONE 0 /* No device */ -#define UNIT_8KROM 1 /* 8KB ROM */ -#define UNIT_16KROM 2 /* 16KB ROM */ -#define UNIT_32KROM 3 /* 32KB ROM */ -#define UNIT_8KRAM 4 /* 8KB RAM */ -#define UNIT_32KRAM 5 /* 32KB RAM */ - -#define RAM 0x00000001 -#define D16BIT 0x00000002 - -/* function prototypes */ - -t_stat JEDEC_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat JEDEC_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat JEDEC_attach (UNIT *uptr, char *cptr); -t_stat JEDEC_reset (DEVICE *dptr); -int32 JEDEC_get_mbyte(int32 addr); -void JEDEC_put_mbyte(int32 addr, int32 val); - -/* SIMH JEDEC Standard I/O Data Structures */ - -UNIT JEDEC_unit[] = { - { UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0),0 }, - { UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0),0 }, - { UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0),0 }, - { UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0),0 } -}; - -MTAB JEDEC_mod[] = { - { UNIT_DMODE, 0, "8-Bit", "8B", &JEDEC_set_mode }, - { UNIT_DMODE, UNIT_DMODE, "16-Bit", "16B", &JEDEC_set_mode }, - { UNIT_MSIZE, UNIT_NONE, "Not configured", "NONE", &JEDEC_set_size }, - { UNIT_MSIZE, UNIT_8KROM, "8KB ROM", "8KROM", &JEDEC_set_size }, - { UNIT_MSIZE, UNIT_16KROM, "16KB ROM", "16KROM", &JEDEC_set_size }, - { UNIT_MSIZE, UNIT_32KROM, "32KB ROM", "32KROM", &JEDEC_set_size }, - { UNIT_MSIZE, UNIT_8KRAM, "8KB RAM", "8KRAM", &JEDEC_set_size }, - { UNIT_MSIZE, UNIT_32KRAM, "32KB RAM", "32KRAM", &JEDEC_set_size }, - { 0 } -}; - -DEBTAB JEDEC_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE JEDEC_dev = { - "JEDEC", //name - JEDEC_unit, //units - NULL, //registers - JEDEC_mod, //modifiers - JEDEC_NUM, //numunits - 16, //aradix - 32, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - &JEDEC_reset, //reset - NULL, //boot - &JEDEC_attach, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - JEDEC_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* global variables */ - -uint8 *JEDEC_buf[JEDEC_NUM] = { /* JEDEC buffer pointers */ - NULL, - NULL, - NULL, - NULL -}; - -/* JEDEC functions */ - -/* JEDEC attach - force JEDEC reset at completion */ - -t_stat JEDEC_attach (UNIT *uptr, char *cptr) -{ - t_stat r; - - if (JEDEC_dev.dctrl & DEBUG_flow) - sim_printf("\tJEDEC_attach: Entered with cptr=%s\n", cptr); - if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { - if (JEDEC_dev.dctrl & DEBUG_flow) - sim_printf("\tJEDEC_attach: Error\n"); - return r; - } - if (JEDEC_dev.dctrl & DEBUG_flow) - sim_printf("\tJEDEC_attach: Done\n"); - return (JEDEC_reset (NULL)); -} - -/* JEDEC set mode = 8- or 16-bit data bus */ - -t_stat JEDEC_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ - UNIT *uptr1; - - if (JEDEC_dev.dctrl & DEBUG_flow) - sim_printf("\tJEDEC_set_mode: Entered with val=%08XH, unit=%d\n", val, uptr->u6); - uptr1 = JEDEC_dev.units + JEDEC_NUM - 1; /* top unit holds this configuration */ - if (val) { /* 16-bit mode */ - uptr1->u5 |= D16BIT; - } else { /* 8-bit mode */ - uptr1->u5 &= ~D16BIT; - } - if (JEDEC_dev.dctrl & DEBUG_flow) - sim_printf("JEDEC%d->u5=%08XH\n", JEDEC_NUM - 1, uptr1->u5); - sim_printf("\tJEDEC_set_mode: Done\n"); -} - -/* JEDEC set type = none, 8krom, 16krom, 32krom, 8kram or 32kram */ - -t_stat JEDEC_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ - uint32 i, basadr; - UNIT *uptr1; - - if (JEDEC_dev.dctrl & DEBUG_flow) - sim_printf("\tJEDEC_set_size: Entered with val=%d, unit=%d\n", val, uptr->u6); - uptr1 = JEDEC_dev.units + JEDEC_NUM - 1; /* top unit holds u5 configuration */ - uptr->u4 = val; - switch(val) { - case UNIT_NONE: - uptr->capac = 0; - uptr->u5 &= ~RAM; /* ROM */ - if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ - uptr->u3 = 0; /* base address */ - sim_printf("JEDEC site size set to 8KB\n"); - for (i = 0; i < JEDEC_NUM-1; i++) { /* clear all units but last unit */ - uptr1 = JEDEC_dev.units + i; - uptr1->capac = 0; - } - } - break; - case UNIT_8KROM: - uptr->capac = 0x2000; - uptr1->u5 &= ~RAM; /* ROM */ - basadr = 0x100000 - (uptr->capac * JEDEC_NUM); - sim_printf("JEDEC site base address = %06XH\n", basadr); - if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ - uptr->u3 = basadr + (uptr->capac * uptr->u6); /* base address */ - sim_printf("JEDEC site size set to 8KB\n"); - for (i = 0; i < JEDEC_NUM-1; i++) { /* clear all units but last unit */ - uptr1 = JEDEC_dev.units + i; - uptr1->capac = 0; - } - } else { - if (uptr1->capac != uptr->capac) { - uptr->capac = 0; - sim_printf("JEDEC site size precludes use of this device\n"); - } - } - break; - case UNIT_16KROM: - uptr->capac = 0x4000; - uptr1->u5 &= ~RAM; /* ROM */ - basadr = 0x100000 - (uptr->capac * JEDEC_NUM); - sim_printf("JEDEC site base address = %06XH\n", basadr); - if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ - uptr->u3 = basadr + (uptr->capac * uptr->u6); /* base address */ - sim_printf("JEDEC site size set to 16KB\n"); - for (i = 0; i < JEDEC_NUM-1; i++) { /* clear all units but last unit */ - uptr1 = JEDEC_dev.units + i; - uptr1->capac = 0; - } - } else { - if (uptr1->capac != uptr->capac) { - uptr->capac = 0; - sim_printf("JEDEC site size precludes use of this device\n"); - } - } - break; - case UNIT_32KROM: - uptr->capac = 0x8000; - uptr1->u5 &= ~RAM; /* ROM */ - basadr = 0x100000 - (uptr->capac * JEDEC_NUM); - sim_printf("JEDEC site base address = %06XH\n", basadr); - if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ - uptr->u3 = basadr + (uptr->capac * uptr->u6); /* base address */ - sim_printf("JEDEC site size set to 32KB\n"); - for (i = 0; i < JEDEC_NUM-1; i++) { /* clear all units but last unit */ - uptr1 = JEDEC_dev.units + i; - uptr1->capac = 0; - } - } else { - if (uptr1->capac != uptr->capac) { - uptr->capac = 0; - sim_printf("JEDEC site size precludes use of this device\n"); - } - } - break; - case UNIT_8KRAM: - uptr->capac = 0x2000; - if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ - sim_printf("JEDEC%d cannot be SRAM\n", uptr->u6); - } else { - if (uptr1->capac != uptr->capac) { - uptr->capac = 0; - sim_printf("JEDEC site size precludes use of this device\n"); - } else { - uptr->u5 |= RAM; /* RAM */ - } - } - break; - case UNIT_32KRAM: - uptr->capac = 0x8000; - if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ - sim_printf("JEDEC%d cannot be SRAM\n", uptr->u6); - } else { - if (uptr1->capac != uptr->capac) { - uptr->capac = 0; - sim_printf("JEDEC site size precludes use of this device\n"); - } else { - uptr->u5 |= RAM; /* RAM */ - } - } - break; - default: - if (JEDEC_dev.dctrl & DEBUG_flow) - sim_printf("\tJEDEC_set_size: Error\n"); - return SCPE_ARG; - } - if (JEDEC_buf[uptr->u6]) { /* any change requires a new buffer */ - free (JEDEC_buf[uptr->u6]); - JEDEC_buf[uptr->u6] = NULL; - } - if (JEDEC_dev.dctrl & DEBUG_flow) { - sim_printf("\tJEDEC%d->capac=%04XH\n", uptr->u6, uptr->capac); - sim_printf("\tJEDEC%d->u3[Base addr]=%06XH\n", uptr->u6, uptr->u3); - sim_printf("\tJEDEC%d->u4[val]=%06XH\n", uptr->u6, uptr->u4); - sim_printf("\tJEDEC%d->u5[Flags]=%06XH\n", uptr->u6, uptr->u5); - sim_printf("\tJEDEC%d->u6[unit #]=%06XH\n", uptr->u6, uptr->u6); - uptr1 = JEDEC_dev.units + JEDEC_NUM - 1; /* top unit holds u5 configuration */ - sim_printf("\tJEDEC%d->u5[Flags]=%06XH\n", JEDEC_NUM - 1, uptr1->u5); - sim_printf("\tJEDEC_set_size: Done\n"); - } - return SCPE_OK; -} - -/* JEDEC reset */ - -t_stat JEDEC_reset (DEVICE *dptr) -{ - int32 i, j, c; - FILE *fp; - t_stat r; - UNIT *uptr; - static int flag = 1; - - if (JEDEC_dev.dctrl & DEBUG_flow) - sim_printf("\tJEDEC_reset: Entered\n"); - for (i = 0; i < JEDEC_NUM; i++) { /* handle all umits */ - uptr = JEDEC_dev.units + i; - if (uptr->capac == 0) { /* if not configured */ - sim_printf(" JEDEC%d: Not configured\n", i); - if (flag) { - sim_printf(" ALL: \"set JEDEC3 None | 8krom | 16krom | 32krom | 8kram | 32kram\"\n"); - sim_printf(" EPROM: \"att JEDEC3 \"\n"); - flag = 0; - } - uptr->capac = 0; - /* assume 8KB in base address calculation */ - uptr->u3 = 0xF8000 + (0x2000 * i); /* base address */ - uptr->u4 = 0; /* None */ - uptr->u5 = 0; /* RO */ - uptr->u6 = i; /* unit number - only set here! */ - } - if (uptr->capac) { /* if configured */ - sim_printf(" JEDEC%d: Initializing %2XKB %s [%04X-%04XH]\n", - i, - uptr->capac / 0x400, - uptr->u5 ? "Ram" : "Rom", - uptr->u3, - uptr->u3 + uptr->capac - 1); - if (JEDEC_buf[uptr->u6] == NULL) {/* no buffer allocated */ - JEDEC_buf[uptr->u6] = malloc(uptr->capac); - if (JEDEC_buf[uptr->u6] == NULL) { - if (JEDEC_dev.dctrl & DEBUG_flow) - sim_printf("\tJEDEC_reset: Malloc error\n"); - return SCPE_MEM; - } - } - if ((uptr->u5 & 0x0001) == 0) { /* ROM - load file */ - fp = fopen(uptr->filename, "rb"); - if (fp == NULL) { - sim_printf("\tUnable to open ROM file %s\n", uptr->filename); - sim_printf("\tNo ROM image loaded!!!\n"); - } else { - j = 0; - c = fgetc(fp); - while (c != EOF) { - *(JEDEC_buf[uptr->u6] + j++) = c & 0xFF; - c = fgetc(fp); - if (j >= JEDEC_unit[uptr->u6].capac) { - sim_printf("\tImage is too large - Load truncated!!!\n"); - break; - } - } - fclose(fp); - sim_printf("\t%d bytes of ROM image %s loaded\n", j, uptr->filename); - } - } - } - } - if (JEDEC_dev.dctrl & DEBUG_flow) - sim_printf("\tJEDEC_reset: Done\n"); - return SCPE_OK; -} - -/* I/O instruction handlers, called from the CPU module when an - JEDEC memory read or write is issued. - - Need to fix for hi/low memory operations -*/ - -/* get a byte from memory */ - -int32 JEDEC_get_mbyte(int32 addr) -{ - int32 i, val, org, len; - UNIT *uptr; - - if (JEDEC_dev.dctrl & DEBUG_read) - sim_printf("\tJEDEC_get_mbyte: Entered\n"); - for (i = 0; i < JEDEC_NUM; i++) { /* test all umits for address */ - uptr = JEDEC_dev.units + i; - org = uptr->u3; - len = uptr->capac - 1; - if ((addr >= org) && (addr <= org + len)) { - if (JEDEC_dev.dctrl & DEBUG_read) - sim_printf("\tJEDEC%d Addr=%06XH Org=%06XH Len=%06XH\n", i, addr, org, len); - val = *(JEDEC_buf[uptr->u6] + (addr - org)); - if (JEDEC_dev.dctrl & DEBUG_read) - sim_printf("\tJEDEC_get_mbyte: Exit with [%0XH]\n", val & 0xFF); - return (val & 0xFF); - } - } - if (JEDEC_dev.dctrl & DEBUG_read) - sim_printf("\tJEDEC_get_mbyte: Exit - Out of range\n", addr); - return 0xFF; -} - -/* put a byte into memory */ - -void JEDEC_put_mbyte(int32 addr, int32 val) -{ - int32 i, org, len, type; - UNIT *uptr; - - if (JEDEC_dev.dctrl & DEBUG_write) - sim_printf("\tJEDEC_put_mbyte: Entered\n"); - for (i = 0; i < JEDEC_NUM; i++) { /* test all umits for address */ - uptr = JEDEC_dev.units + i; - org = uptr->u3; - len = uptr->capac - 1; - if ((addr >= org) && (addr < org + len)) { - if (JEDEC_dev.dctrl & DEBUG_write) - sim_printf("\tJEDEC%d Org=%06XH Len=%06XH\n", i, org, len); - if (uptr->u5 & RAM) { /* can't write to ROM */ - *(JEDEC_buf[uptr->u6] + (addr - org)) = val & 0xFF; - if (JEDEC_dev.dctrl & DEBUG_write) - sim_printf("\tJEDEC_put_mbyte: Exit with [%06XH]=%02XH\n", addr, val); - } else - sim_printf("\tJEDEC_put_mbyte: Write to ROM ignored\n"); - } - } - if (JEDEC_dev.dctrl & DEBUG_write) - sim_printf("\tJEDEC_put_mbyte: Exit - Out of range\n"); -} - -/* end of iJEDEC.c */ +/* iJEDEC.c: Intel JEDEC Universal Site simulator for SBCs + + 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. + + These functions support a simulated i2732 JEDEC device on an iSBC. This + allows the attachment of the device to a binary file containing the JEDEC + code. + + Unit will support 8, 16 and 32 KB EPROMs as well as 8 and 16 KB static + RAMs in the JEDEC sockets. Units must be configured for 8KB for 8KB + SRAM and 32KB for 32KB SRAM. If configured for 16KB, SRAM cannot be + configured. Size is set by configuring the top JEDEC site for an EPROM. + Size and spacing for the other JEDEC units is derived from the top JEDEC + site configuration. Changing the top JEDEC site will clear the + configuration of all other JEDEC sites. The JEDEC driver can be set for + either 8- or 16bit data access. + + The top JEDEC site can only be configured to contain an EPROM. + It contains the reset address for the 8088, 8086, 80188, 80186, + and 80286. + + For illustration 8-bit mode - 4 Sites - configured for 8KB chips + + +--------+ 0xFFFFF + | | + | jedec3 | Only ROM + | | + +--------+ 0xFE000 + + +--------+ 0xFDFFF + | | + | jedec2 | RAM/ROM + | | + +--------+ 0xFC000 + + +--------+ 0xFBFFF + | | + | jedec1 | RAM/ROM + | | + +--------+ 0xFA000 + + +--------+ 0xF9FFF + | | + | jedec0 | RAM/ROM + | | + +--------+ 0xF8000 + + For illustration 16-bit mode - 4 Sites - configured for 8KB chips + + Odd data byte Even data byte + High data byte Low data byte + +--------+ 0xFFFFF +--------+ 0xFFFFE + | | | | + | jedec3 | Only ROM | jedec2 | Only ROM + | | | | + +--------+ 0xFC001 +--------+ 0xFC000 + + +--------+ 0xFBFFF +--------+ 0xFBFFE + | | | | + | jedec3 | RAM/ROM | jedec2 | RAM/ROM + | | | | + +--------+ 0xF8001 +--------+ 0xF8000 + + uptr->filename - ROM image file attached to unit + uptr->capac - unit capacity in bytes + uptr->u3 - unit base address + uptr->u4 - unit device type {none|8krom|16krom|32krom|8kram|32kram} + uptr->u5 - unit flags - ROM or RAM, 8 or 16BIT (top unit only) + uptr->u6 - unit number +*/ + +#include + +#include "multibus_defs.h" + +#define JEDEC_NUM 4 + +#define UNIT_V_DMODE (UNIT_V_UF) /* data bus mode */ +#define UNIT_DMODE (1 << UNIT_V_DMODE) +#define UNIT_V_MSIZE (UNIT_V_UF+1) /* Memory Size */ +#define UNIT_MSIZE (1 << UNIT_V_MSIZE) +#define UNIT_NONE 0 /* No device */ +#define UNIT_8KROM 1 /* 8KB ROM */ +#define UNIT_16KROM 2 /* 16KB ROM */ +#define UNIT_32KROM 3 /* 32KB ROM */ +#define UNIT_8KRAM 4 /* 8KB RAM */ +#define UNIT_32KRAM 5 /* 32KB RAM */ + +#define RAM 0x00000001 +#define D16BIT 0x00000002 + +/* function prototypes */ + +t_stat JEDEC_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat JEDEC_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat JEDEC_attach (UNIT *uptr, char *cptr); +t_stat JEDEC_reset (DEVICE *dptr); +int32 JEDEC_get_mbyte(int32 addr); +void JEDEC_put_mbyte(int32 addr, int32 val); + +/* SIMH JEDEC Standard I/O Data Structures */ + +UNIT JEDEC_unit[] = { + { UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0),0 }, + { UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0),0 }, + { UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0),0 }, + { UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0),0 } +}; + +MTAB JEDEC_mod[] = { + { UNIT_DMODE, 0, "8-Bit", "8B", &JEDEC_set_mode }, + { UNIT_DMODE, UNIT_DMODE, "16-Bit", "16B", &JEDEC_set_mode }, + { UNIT_MSIZE, UNIT_NONE, "Not configured", "NONE", &JEDEC_set_size }, + { UNIT_MSIZE, UNIT_8KROM, "8KB ROM", "8KROM", &JEDEC_set_size }, + { UNIT_MSIZE, UNIT_16KROM, "16KB ROM", "16KROM", &JEDEC_set_size }, + { UNIT_MSIZE, UNIT_32KROM, "32KB ROM", "32KROM", &JEDEC_set_size }, + { UNIT_MSIZE, UNIT_8KRAM, "8KB RAM", "8KRAM", &JEDEC_set_size }, + { UNIT_MSIZE, UNIT_32KRAM, "32KB RAM", "32KRAM", &JEDEC_set_size }, + { 0 } +}; + +DEBTAB JEDEC_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE JEDEC_dev = { + "JEDEC", //name + JEDEC_unit, //units + NULL, //registers + JEDEC_mod, //modifiers + JEDEC_NUM, //numunits + 16, //aradix + 32, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + &JEDEC_reset, //reset + NULL, //boot + &JEDEC_attach, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + JEDEC_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* global variables */ + +uint8 *JEDEC_buf[JEDEC_NUM] = { /* JEDEC buffer pointers */ + NULL, + NULL, + NULL, + NULL +}; + +/* JEDEC functions */ + +/* JEDEC attach - force JEDEC reset at completion */ + +t_stat JEDEC_attach (UNIT *uptr, char *cptr) +{ + t_stat r; + + if (JEDEC_dev.dctrl & DEBUG_flow) + sim_printf("\tJEDEC_attach: Entered with cptr=%s\n", cptr); + if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { + if (JEDEC_dev.dctrl & DEBUG_flow) + sim_printf("\tJEDEC_attach: Error\n"); + return r; + } + if (JEDEC_dev.dctrl & DEBUG_flow) + sim_printf("\tJEDEC_attach: Done\n"); + return (JEDEC_reset (NULL)); +} + +/* JEDEC set mode = 8- or 16-bit data bus */ + +t_stat JEDEC_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) +{ + UNIT *uptr1; + + if (JEDEC_dev.dctrl & DEBUG_flow) + sim_printf("\tJEDEC_set_mode: Entered with val=%08XH, unit=%d\n", val, uptr->u6); + uptr1 = JEDEC_dev.units + JEDEC_NUM - 1; /* top unit holds this configuration */ + if (val) { /* 16-bit mode */ + uptr1->u5 |= D16BIT; + } else { /* 8-bit mode */ + uptr1->u5 &= ~D16BIT; + } + if (JEDEC_dev.dctrl & DEBUG_flow) + sim_printf("JEDEC%d->u5=%08XH\n", JEDEC_NUM - 1, uptr1->u5); + sim_printf("\tJEDEC_set_mode: Done\n"); +} + +/* JEDEC set type = none, 8krom, 16krom, 32krom, 8kram or 32kram */ + +t_stat JEDEC_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) +{ + uint32 i, basadr; + UNIT *uptr1; + + if (JEDEC_dev.dctrl & DEBUG_flow) + sim_printf("\tJEDEC_set_size: Entered with val=%d, unit=%d\n", val, uptr->u6); + uptr1 = JEDEC_dev.units + JEDEC_NUM - 1; /* top unit holds u5 configuration */ + uptr->u4 = val; + switch(val) { + case UNIT_NONE: + uptr->capac = 0; + uptr->u5 &= ~RAM; /* ROM */ + if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ + uptr->u3 = 0; /* base address */ + sim_printf("JEDEC site size set to 8KB\n"); + for (i = 0; i < JEDEC_NUM-1; i++) { /* clear all units but last unit */ + uptr1 = JEDEC_dev.units + i; + uptr1->capac = 0; + } + } + break; + case UNIT_8KROM: + uptr->capac = 0x2000; + uptr1->u5 &= ~RAM; /* ROM */ + basadr = 0x100000 - (uptr->capac * JEDEC_NUM); + sim_printf("JEDEC site base address = %06XH\n", basadr); + if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ + uptr->u3 = basadr + (uptr->capac * uptr->u6); /* base address */ + sim_printf("JEDEC site size set to 8KB\n"); + for (i = 0; i < JEDEC_NUM-1; i++) { /* clear all units but last unit */ + uptr1 = JEDEC_dev.units + i; + uptr1->capac = 0; + } + } else { + if (uptr1->capac != uptr->capac) { + uptr->capac = 0; + sim_printf("JEDEC site size precludes use of this device\n"); + } + } + break; + case UNIT_16KROM: + uptr->capac = 0x4000; + uptr1->u5 &= ~RAM; /* ROM */ + basadr = 0x100000 - (uptr->capac * JEDEC_NUM); + sim_printf("JEDEC site base address = %06XH\n", basadr); + if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ + uptr->u3 = basadr + (uptr->capac * uptr->u6); /* base address */ + sim_printf("JEDEC site size set to 16KB\n"); + for (i = 0; i < JEDEC_NUM-1; i++) { /* clear all units but last unit */ + uptr1 = JEDEC_dev.units + i; + uptr1->capac = 0; + } + } else { + if (uptr1->capac != uptr->capac) { + uptr->capac = 0; + sim_printf("JEDEC site size precludes use of this device\n"); + } + } + break; + case UNIT_32KROM: + uptr->capac = 0x8000; + uptr1->u5 &= ~RAM; /* ROM */ + basadr = 0x100000 - (uptr->capac * JEDEC_NUM); + sim_printf("JEDEC site base address = %06XH\n", basadr); + if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ + uptr->u3 = basadr + (uptr->capac * uptr->u6); /* base address */ + sim_printf("JEDEC site size set to 32KB\n"); + for (i = 0; i < JEDEC_NUM-1; i++) { /* clear all units but last unit */ + uptr1 = JEDEC_dev.units + i; + uptr1->capac = 0; + } + } else { + if (uptr1->capac != uptr->capac) { + uptr->capac = 0; + sim_printf("JEDEC site size precludes use of this device\n"); + } + } + break; + case UNIT_8KRAM: + uptr->capac = 0x2000; + if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ + sim_printf("JEDEC%d cannot be SRAM\n", uptr->u6); + } else { + if (uptr1->capac != uptr->capac) { + uptr->capac = 0; + sim_printf("JEDEC site size precludes use of this device\n"); + } else { + uptr->u5 |= RAM; /* RAM */ + } + } + break; + case UNIT_32KRAM: + uptr->capac = 0x8000; + if (uptr->u6 == JEDEC_NUM - 1) {/* top unit ? */ + sim_printf("JEDEC%d cannot be SRAM\n", uptr->u6); + } else { + if (uptr1->capac != uptr->capac) { + uptr->capac = 0; + sim_printf("JEDEC site size precludes use of this device\n"); + } else { + uptr->u5 |= RAM; /* RAM */ + } + } + break; + default: + if (JEDEC_dev.dctrl & DEBUG_flow) + sim_printf("\tJEDEC_set_size: Error\n"); + return SCPE_ARG; + } + if (JEDEC_buf[uptr->u6]) { /* any change requires a new buffer */ + free (JEDEC_buf[uptr->u6]); + JEDEC_buf[uptr->u6] = NULL; + } + if (JEDEC_dev.dctrl & DEBUG_flow) { + sim_printf("\tJEDEC%d->capac=%04XH\n", uptr->u6, uptr->capac); + sim_printf("\tJEDEC%d->u3[Base addr]=%06XH\n", uptr->u6, uptr->u3); + sim_printf("\tJEDEC%d->u4[val]=%06XH\n", uptr->u6, uptr->u4); + sim_printf("\tJEDEC%d->u5[Flags]=%06XH\n", uptr->u6, uptr->u5); + sim_printf("\tJEDEC%d->u6[unit #]=%06XH\n", uptr->u6, uptr->u6); + uptr1 = JEDEC_dev.units + JEDEC_NUM - 1; /* top unit holds u5 configuration */ + sim_printf("\tJEDEC%d->u5[Flags]=%06XH\n", JEDEC_NUM - 1, uptr1->u5); + sim_printf("\tJEDEC_set_size: Done\n"); + } + return SCPE_OK; +} + +/* JEDEC reset */ + +t_stat JEDEC_reset (DEVICE *dptr) +{ + int32 i, j, c; + FILE *fp; + t_stat r; + UNIT *uptr; + static int flag = 1; + + if (JEDEC_dev.dctrl & DEBUG_flow) + sim_printf("\tJEDEC_reset: Entered\n"); + for (i = 0; i < JEDEC_NUM; i++) { /* handle all umits */ + uptr = JEDEC_dev.units + i; + if (uptr->capac == 0) { /* if not configured */ + sim_printf(" JEDEC%d: Not configured\n", i); + if (flag) { + sim_printf(" ALL: \"set JEDEC3 None | 8krom | 16krom | 32krom | 8kram | 32kram\"\n"); + sim_printf(" EPROM: \"att JEDEC3 \"\n"); + flag = 0; + } + uptr->capac = 0; + /* assume 8KB in base address calculation */ + uptr->u3 = 0xF8000 + (0x2000 * i); /* base address */ + uptr->u4 = 0; /* None */ + uptr->u5 = 0; /* RO */ + uptr->u6 = i; /* unit number - only set here! */ + } + if (uptr->capac) { /* if configured */ + sim_printf(" JEDEC%d: Initializing %2XKB %s [%04X-%04XH]\n", + i, + uptr->capac / 0x400, + uptr->u5 ? "Ram" : "Rom", + uptr->u3, + uptr->u3 + uptr->capac - 1); + if (JEDEC_buf[uptr->u6] == NULL) {/* no buffer allocated */ + JEDEC_buf[uptr->u6] = malloc(uptr->capac); + if (JEDEC_buf[uptr->u6] == NULL) { + if (JEDEC_dev.dctrl & DEBUG_flow) + sim_printf("\tJEDEC_reset: Malloc error\n"); + return SCPE_MEM; + } + } + if ((uptr->u5 & 0x0001) == 0) { /* ROM - load file */ + fp = fopen(uptr->filename, "rb"); + if (fp == NULL) { + sim_printf("\tUnable to open ROM file %s\n", uptr->filename); + sim_printf("\tNo ROM image loaded!!!\n"); + } else { + j = 0; + c = fgetc(fp); + while (c != EOF) { + *(JEDEC_buf[uptr->u6] + j++) = c & 0xFF; + c = fgetc(fp); + if (j >= JEDEC_unit[uptr->u6].capac) { + sim_printf("\tImage is too large - Load truncated!!!\n"); + break; + } + } + fclose(fp); + sim_printf("\t%d bytes of ROM image %s loaded\n", j, uptr->filename); + } + } + } + } + if (JEDEC_dev.dctrl & DEBUG_flow) + sim_printf("\tJEDEC_reset: Done\n"); + return SCPE_OK; +} + +/* I/O instruction handlers, called from the CPU module when an + JEDEC memory read or write is issued. + + Need to fix for hi/low memory operations +*/ + +/* get a byte from memory */ + +int32 JEDEC_get_mbyte(int32 addr) +{ + int32 i, val, org, len; + UNIT *uptr; + + if (JEDEC_dev.dctrl & DEBUG_read) + sim_printf("\tJEDEC_get_mbyte: Entered\n"); + for (i = 0; i < JEDEC_NUM; i++) { /* test all umits for address */ + uptr = JEDEC_dev.units + i; + org = uptr->u3; + len = uptr->capac - 1; + if ((addr >= org) && (addr <= org + len)) { + if (JEDEC_dev.dctrl & DEBUG_read) + sim_printf("\tJEDEC%d Addr=%06XH Org=%06XH Len=%06XH\n", i, addr, org, len); + val = *(JEDEC_buf[uptr->u6] + (addr - org)); + if (JEDEC_dev.dctrl & DEBUG_read) + sim_printf("\tJEDEC_get_mbyte: Exit with [%0XH]\n", val & 0xFF); + return (val & 0xFF); + } + } + if (JEDEC_dev.dctrl & DEBUG_read) + sim_printf("\tJEDEC_get_mbyte: Exit - Out of range\n", addr); + return 0xFF; +} + +/* put a byte into memory */ + +void JEDEC_put_mbyte(int32 addr, int32 val) +{ + int32 i, org, len, type; + UNIT *uptr; + + if (JEDEC_dev.dctrl & DEBUG_write) + sim_printf("\tJEDEC_put_mbyte: Entered\n"); + for (i = 0; i < JEDEC_NUM; i++) { /* test all umits for address */ + uptr = JEDEC_dev.units + i; + org = uptr->u3; + len = uptr->capac - 1; + if ((addr >= org) && (addr < org + len)) { + if (JEDEC_dev.dctrl & DEBUG_write) + sim_printf("\tJEDEC%d Org=%06XH Len=%06XH\n", i, org, len); + if (uptr->u5 & RAM) { /* can't write to ROM */ + *(JEDEC_buf[uptr->u6] + (addr - org)) = val & 0xFF; + if (JEDEC_dev.dctrl & DEBUG_write) + sim_printf("\tJEDEC_put_mbyte: Exit with [%06XH]=%02XH\n", addr, val); + } else + sim_printf("\tJEDEC_put_mbyte: Write to ROM ignored\n"); + } + } + if (JEDEC_dev.dctrl & DEBUG_write) + sim_printf("\tJEDEC_put_mbyte: Exit - Out of range\n"); +} + +/* end of iJEDEC.c */ diff --git a/Intel-Systems/common/ipata.c b/Intel-Systems/common/ipata.c index 715f61f4..0a748bda 100644 --- a/Intel-Systems/common/ipata.c +++ b/Intel-Systems/common/ipata.c @@ -1,206 +1,206 @@ -/* iPATA.c: Intel i8255 PIO adapter for PATA HD - - Copyright (c) 2015, 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. - - NOTES: - - These functions support a simulated i8255 interface device on an iSBC. - The device has threee physical 8-bit I/O ports which could be connected - to any parallel I/O device. This is an extension of the i8255.c file to support - an emulated PATA IDE Hard Disk Drive. - - All I/O is via programmed I/O. The i8255 has a control port (PIOS) - and three data ports (PIOA, PIOB, and PIOC). - - The simulated device supports a select from I/O space and two address lines. - The data ports are at the lower addresses and the control port is at - the highest. - - A write to the control port can configure the device: - - Control Word - +---+---+---+---+---+---+---+---+ - | D7 D6 D5 D4 D3 D2 D1 D0| - +---+---+---+---+---+---+---+---+ - - Group B - D0 Port C (lower) 1-Input, 0-Output - D1 Port B 1-Input, 0-Output - D2 Mode Selection 0-Mode 0, 1-Mode 1 - - Group A - D3 Port C (upper) 1-Input, 0-Output - D4 Port A 1-Input, 0-Output - D5-6 Mode Selection 00-Mode 0, 01-Mode 1, 1X-Mode 2 - - D7 Mode Set Flag 1=Active, 0=Bit Set - - Mode 0 - Basic Input/Output - Mode 1 - Strobed Input/Output - Mode 2 - Bidirectional Bus - - Bit Set - D7=0, D3:1 select port C bit, D0 1=set, 0=reset - - A read to the data ports gets the current port value, a write - to the data ports writes the character to the device. - - The Second 8255 on the iSBC 80/10 is used to connect to the IDE PATA - Hard Disk Drive. Pins are defined as shown below: - - PA[0..7] High data byte - PB[0..7] Low data byte - PC[0..2] Register select - PC[3..4] CSFX select - PC[5] Read register - PC[6] Write register -*/ - -#include "system_defs.h" - -extern int32 reg_dev(int32 (*routine)(), int32 port); - -/* function prototypes */ - -t_stat pata_reset (DEVICE *dptr, int32 base); - -/* i8255 Standard I/O Data Structures */ - -UNIT pata_unit[] = { - { UDATA (0, 0, 0) } -}; - -REG pata_reg[] = { - { HRDATA (CONTROL0, pata_unit[0].u3, 8) }, - { HRDATA (PORTA0, pata_unit[0].u4, 8) }, - { HRDATA (PORTB0, pata_unit[0].u5, 8) }, - { HRDATA (PORTC0, pata_unit[0].u6, 8) }, - { NULL } -}; - -DEVICE pata_dev = { - "PATA", //name - pata_unit, //units - pata_reg, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 32, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &pata_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - 0, //flags - 0, //dctrl - NULL, //debflags - NULL, //msize - NULL //lname -}; - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. -*/ - -int32 patas(int32 io, int32 data) -{ - int32 bit; - - if (io == 0) { /* read status port */ - return pata_unit[0].u3; - } else { /* write status port */ - if (data & 0x80) { /* mode instruction */ - pata_unit[0].u3 = data; - sim_printf("PATA: 8255 Mode Instruction=%02X\n", data); - if (data & 0x64) - sim_printf(" Mode 1 and 2 not yet implemented\n"); - } else { /* bit set */ - bit = (data & 0x0E) >> 1; /* get bit number */ - if (data & 0x01) { /* set bit */ - pata_unit[0].u6 |= (0x01 << bit); - } else { /* reset bit */ - pata_unit[0].u6 &= ~(0x01 << bit); - } - } - } - return 0; -} - -int32 pataa(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - sim_printf("PATA: 8255 Read Port A = %02X\n", pata_unit[0].u4); - return (pata_unit[0].u4); - } else { /* write data port */ - pata_unit[0].u4 = data; - sim_printf("PATA: 8255 Write Port A = %02X\n", data); - } - return 0; -} - -int32 patab(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - sim_printf("PATA: 8255 Read Port B = %02X\n", pata_unit[0].u5); - return (pata_unit[0].u5); - } else { /* write data port */ - pata_unit[0].u5 = data; - sim_printf("PATA: 8255 Write Port B = %02X\n", data); - } - return 0; -} - -int32 patac(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - sim_printf("PATA: 8255 Read Port C = %02X\n", pata_unit[0].u6); - return (pata_unit[0].u6); - } else { /* write data port */ - pata_unit[0].u6 = data; - sim_printf("PATA: 8255 Write Port C = %02X\n", data); - } - return 0; -} - -/* Reset routine */ - -t_stat pata_reset (DEVICE *dptr, int32 base) -{ - pata_unit[0].u3 = 0x9B; /* control */ - pata_unit[0].u4 = 0xFF; /* Port A */ - pata_unit[0].u5 = 0xFF; /* Port B */ - pata_unit[0].u6 = 0xFF; /* Port C */ - reg_dev(pataa, base); - reg_dev(patab, base + 1); - reg_dev(patac, base + 2); - reg_dev(patas, base + 3); - sim_printf(" PATA: Reset\n"); - return SCPE_OK; -} - +/* iPATA.c: Intel i8255 PIO adapter for PATA HD + + Copyright (c) 2015, 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. + + NOTES: + + These functions support a simulated i8255 interface device on an iSBC. + The device has threee physical 8-bit I/O ports which could be connected + to any parallel I/O device. This is an extension of the i8255.c file to support + an emulated PATA IDE Hard Disk Drive. + + All I/O is via programmed I/O. The i8255 has a control port (PIOS) + and three data ports (PIOA, PIOB, and PIOC). + + The simulated device supports a select from I/O space and two address lines. + The data ports are at the lower addresses and the control port is at + the highest. + + A write to the control port can configure the device: + + Control Word + +---+---+---+---+---+---+---+---+ + | D7 D6 D5 D4 D3 D2 D1 D0| + +---+---+---+---+---+---+---+---+ + + Group B + D0 Port C (lower) 1-Input, 0-Output + D1 Port B 1-Input, 0-Output + D2 Mode Selection 0-Mode 0, 1-Mode 1 + + Group A + D3 Port C (upper) 1-Input, 0-Output + D4 Port A 1-Input, 0-Output + D5-6 Mode Selection 00-Mode 0, 01-Mode 1, 1X-Mode 2 + + D7 Mode Set Flag 1=Active, 0=Bit Set + + Mode 0 - Basic Input/Output + Mode 1 - Strobed Input/Output + Mode 2 - Bidirectional Bus + + Bit Set - D7=0, D3:1 select port C bit, D0 1=set, 0=reset + + A read to the data ports gets the current port value, a write + to the data ports writes the character to the device. + + The Second 8255 on the iSBC 80/10 is used to connect to the IDE PATA + Hard Disk Drive. Pins are defined as shown below: + + PA[0..7] High data byte + PB[0..7] Low data byte + PC[0..2] Register select + PC[3..4] CSFX select + PC[5] Read register + PC[6] Write register +*/ + +#include "system_defs.h" + +extern int32 reg_dev(int32 (*routine)(), int32 port); + +/* function prototypes */ + +t_stat pata_reset (DEVICE *dptr, int32 base); + +/* i8255 Standard I/O Data Structures */ + +UNIT pata_unit[] = { + { UDATA (0, 0, 0) } +}; + +REG pata_reg[] = { + { HRDATA (CONTROL0, pata_unit[0].u3, 8) }, + { HRDATA (PORTA0, pata_unit[0].u4, 8) }, + { HRDATA (PORTB0, pata_unit[0].u5, 8) }, + { HRDATA (PORTC0, pata_unit[0].u6, 8) }, + { NULL } +}; + +DEVICE pata_dev = { + "PATA", //name + pata_unit, //units + pata_reg, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 32, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &pata_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + NULL, //debflags + NULL, //msize + NULL //lname +}; + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +int32 patas(int32 io, int32 data) +{ + int32 bit; + + if (io == 0) { /* read status port */ + return pata_unit[0].u3; + } else { /* write status port */ + if (data & 0x80) { /* mode instruction */ + pata_unit[0].u3 = data; + sim_printf("PATA: 8255 Mode Instruction=%02X\n", data); + if (data & 0x64) + sim_printf(" Mode 1 and 2 not yet implemented\n"); + } else { /* bit set */ + bit = (data & 0x0E) >> 1; /* get bit number */ + if (data & 0x01) { /* set bit */ + pata_unit[0].u6 |= (0x01 << bit); + } else { /* reset bit */ + pata_unit[0].u6 &= ~(0x01 << bit); + } + } + } + return 0; +} + +int32 pataa(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + sim_printf("PATA: 8255 Read Port A = %02X\n", pata_unit[0].u4); + return (pata_unit[0].u4); + } else { /* write data port */ + pata_unit[0].u4 = data; + sim_printf("PATA: 8255 Write Port A = %02X\n", data); + } + return 0; +} + +int32 patab(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + sim_printf("PATA: 8255 Read Port B = %02X\n", pata_unit[0].u5); + return (pata_unit[0].u5); + } else { /* write data port */ + pata_unit[0].u5 = data; + sim_printf("PATA: 8255 Write Port B = %02X\n", data); + } + return 0; +} + +int32 patac(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + sim_printf("PATA: 8255 Read Port C = %02X\n", pata_unit[0].u6); + return (pata_unit[0].u6); + } else { /* write data port */ + pata_unit[0].u6 = data; + sim_printf("PATA: 8255 Write Port C = %02X\n", data); + } + return 0; +} + +/* Reset routine */ + +t_stat pata_reset (DEVICE *dptr, int32 base) +{ + pata_unit[0].u3 = 0x9B; /* control */ + pata_unit[0].u4 = 0xFF; /* Port A */ + pata_unit[0].u5 = 0xFF; /* Port B */ + pata_unit[0].u6 = 0xFF; /* Port C */ + reg_dev(pataa, base); + reg_dev(patab, base + 1); + reg_dev(patac, base + 2); + reg_dev(patas, base + 3); + sim_printf(" PATA: Reset\n"); + return SCPE_OK; +} + diff --git a/Intel-Systems/common/ipc-cont.c b/Intel-Systems/common/ipc-cont.c index 1601b350..f467a2a8 100644 --- a/Intel-Systems/common/ipc-cont.c +++ b/Intel-Systems/common/ipc-cont.c @@ -1,160 +1,160 @@ -/* ipc-cont.c: Intel IPC control port PIO adapter - - Copyright (c) 2010, 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: - - 07 Jun 16 - Original file. - - NOTES: - -*/ - -#include "system_defs.h" /* system header in system dir */ - -/* function prototypes */ - -uint8 ipc_cont(t_bool io, uint8 data); /* ipc_cont*/ -t_stat ipc_cont_reset (DEVICE *dptr, uint16 baseport); - -/* external function prototypes */ - -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); - -/* globals */ - -UNIT ipc_cont_unit[] = { - { UDATA (0, 0, 0) }, /* ipc_cont*/ -}; - -REG ipc_cont_reg[] = { - { HRDATA (CONTROL0, ipc_cont_unit[0].u3, 8) }, /* ipc_cont */ - { NULL } -}; - -DEBTAB ipc_cont_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -/* address width is set to 16 bits to use devices in 8086/8088 implementations */ - -DEVICE ipc_cont_dev = { - "IPC-CONT", //name - ipc_cont_unit, //units - ipc_cont_reg, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &ipc_cont_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - 0, //flags - 0, //dctrl - ipc_cont_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Reset routine */ - -t_stat ipc_cont_reset(DEVICE *dptr, uint16 baseport) -{ - sim_printf(" ipc_cont[%d]: Reset\n", 0); - sim_printf(" ipc_cont[%d]: Registered at %04X\n", 0, baseport); - reg_dev(ipc_cont, baseport, 0); - ipc_cont_unit[0].u3 = 0x00; /* ipc reset */ - return SCPE_OK; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. -*/ - -/* IPC control port functions */ - -uint8 ipc_cont(t_bool io, uint8 data) -{ - if (io == 0) { /* read status port */ - sim_printf(" ipc_cont: read data=%02X ipc_cont_unit[%d].u3=%02X\n", - ipc_cont_unit[0].u3, 0, ipc_cont_unit[0].u3); - return ipc_cont_unit[0].u3; - } else { /* write control port */ - //this simulates an 74LS259 register - //d0-d2 address the reg(in reverse order!), d3 is the data to be latched (inverted) - switch(data & 0x07) { - case 5: //interrupt enable 8085 INTR - if(data & 0x08) //bit low - ipc_cont_unit[0].u3 &= 0xBF; - else //bit high - ipc_cont_unit[0].u3 |= 0x20; - break; - case 4: //*selboot ROM @ 0E800h - if(data & 0x08) //bit low - ipc_cont_unit[0].u3 &= 0xEF; - else //bit high - ipc_cont_unit[0].u3 |= 0x10; - break; - case 2: //*startup ROM @ 00000h - if(data & 0x08) //bit low - ipc_cont_unit[0].u3 &= 0xFB; - else //bit high - ipc_cont_unit[0].u3 |= 0x04; - break; - case 1: //override inhibit other multibus users - if(data & 0x08) //bit low - ipc_cont_unit[0].u3 &= 0xFD; - else //bit high - ipc_cont_unit[0].u3 |= 0x02; - break; - case 0: //aux prom enable - if(data & 0x08) //bit low - ipc_cont_unit[0].u3 &= 0xFE; - else //bit high - ipc_cont_unit[0].u3 |= 0x01; - break; - default: - break; - } - sim_printf(" ipc_cont: write data=%02X ipc_cont_unit[%d].u3=%02X\n", data, 0, ipc_cont_unit[0].u3); - } - return 0; -} - -/* end of ipc-cont.c */ +/* ipc-cont.c: Intel IPC control port PIO adapter + + Copyright (c) 2010, 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: + + 07 Jun 16 - Original file. + + NOTES: + +*/ + +#include "system_defs.h" /* system header in system dir */ + +/* function prototypes */ + +uint8 ipc_cont(t_bool io, uint8 data); /* ipc_cont*/ +t_stat ipc_cont_reset (DEVICE *dptr, uint16 baseport); + +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); + +/* globals */ + +UNIT ipc_cont_unit[] = { + { UDATA (0, 0, 0) }, /* ipc_cont*/ +}; + +REG ipc_cont_reg[] = { + { HRDATA (CONTROL0, ipc_cont_unit[0].u3, 8) }, /* ipc_cont */ + { NULL } +}; + +DEBTAB ipc_cont_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +/* address width is set to 16 bits to use devices in 8086/8088 implementations */ + +DEVICE ipc_cont_dev = { + "IPC-CONT", //name + ipc_cont_unit, //units + ipc_cont_reg, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &ipc_cont_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + ipc_cont_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Reset routine */ + +t_stat ipc_cont_reset(DEVICE *dptr, uint16 baseport) +{ + sim_printf(" ipc_cont[%d]: Reset\n", 0); + sim_printf(" ipc_cont[%d]: Registered at %04X\n", 0, baseport); + reg_dev(ipc_cont, baseport, 0); + ipc_cont_unit[0].u3 = 0x00; /* ipc reset */ + return SCPE_OK; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +/* IPC control port functions */ + +uint8 ipc_cont(t_bool io, uint8 data) +{ + if (io == 0) { /* read status port */ + sim_printf(" ipc_cont: read data=%02X ipc_cont_unit[%d].u3=%02X\n", + ipc_cont_unit[0].u3, 0, ipc_cont_unit[0].u3); + return ipc_cont_unit[0].u3; + } else { /* write control port */ + //this simulates an 74LS259 register + //d0-d2 address the reg(in reverse order!), d3 is the data to be latched (inverted) + switch(data & 0x07) { + case 5: //interrupt enable 8085 INTR + if(data & 0x08) //bit low + ipc_cont_unit[0].u3 &= 0xBF; + else //bit high + ipc_cont_unit[0].u3 |= 0x20; + break; + case 4: //*selboot ROM @ 0E800h + if(data & 0x08) //bit low + ipc_cont_unit[0].u3 &= 0xEF; + else //bit high + ipc_cont_unit[0].u3 |= 0x10; + break; + case 2: //*startup ROM @ 00000h + if(data & 0x08) //bit low + ipc_cont_unit[0].u3 &= 0xFB; + else //bit high + ipc_cont_unit[0].u3 |= 0x04; + break; + case 1: //override inhibit other multibus users + if(data & 0x08) //bit low + ipc_cont_unit[0].u3 &= 0xFD; + else //bit high + ipc_cont_unit[0].u3 |= 0x02; + break; + case 0: //aux prom enable + if(data & 0x08) //bit low + ipc_cont_unit[0].u3 &= 0xFE; + else //bit high + ipc_cont_unit[0].u3 |= 0x01; + break; + default: + break; + } + sim_printf(" ipc_cont: write data=%02X ipc_cont_unit[%d].u3=%02X\n", data, 0, ipc_cont_unit[0].u3); + } + return 0; +} + +/* end of ipc-cont.c */ diff --git a/Intel-Systems/common/ipceprom.c b/Intel-Systems/common/ipceprom.c index f997a249..7aab9159 100644 --- a/Intel-Systems/common/ipceprom.c +++ b/Intel-Systems/common/ipceprom.c @@ -1,186 +1,186 @@ -/* ipcEPROM.c: Intel EPROM simulator for 8-bit SBCs - - Copyright (c) 2010, 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: - - ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. - 24 Apr 15 -- Modified to use simh_debug - - NOTES: - - These functions support a simulated ROM devices on an iSBC-80/XX SBCs. - This allows the attachment of the device to a binary file containing the EPROM - code image. Unit will support a single 2708, 2716, 2732, or 2764 type EPROM. - These functions also support bit 1 of 8255 number 1, port B, to enable/ - disable the onboard ROM. -*/ - -#include "system_defs.h" - -/* function prototypes */ - -t_stat EPROM_attach (UNIT *uptr, CONST char *cptr); -t_stat EPROM_reset (DEVICE *dptr, uint16 size); -uint8 EPROM_get_mbyte(uint16 addr); - -/* external function prototypes */ - -extern uint8 xack; /* XACK signal */ -extern UNIT ipc_cont_unit[]; - -/* SIMH EPROM Standard I/O Data Structures */ - -UNIT EPROM_unit = { - UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0), 0 -}; - -DEBTAB EPROM_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE EPROM_dev = { - "EPROM", //name - &EPROM_unit, //units - NULL, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &EPROM_reset, //reset - NULL, //reset - NULL, //boot - &EPROM_attach, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - EPROM_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* global variables */ - -/* EPROM functions */ - -/* EPROM attach */ - -t_stat EPROM_attach (UNIT *uptr, CONST char *cptr) -{ - uint16 j; - int c; - FILE *fp; - t_stat r; - - sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: cptr=%s\n", cptr); - if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { - sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Error\n"); - return r; - } - sim_debug (DEBUG_read, &EPROM_dev, "\tAllocate buffer\n"); - if (EPROM_unit.filebuf == NULL) { /* no buffer allocated */ - EPROM_unit.filebuf = malloc(EPROM_unit.capac); /* allocate EPROM buffer */ - if (EPROM_unit.filebuf == NULL) { - sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Malloc error\n"); - return SCPE_MEM; - } - } - sim_debug (DEBUG_read, &EPROM_dev, "\tOpen file %s\n", EPROM_unit.filename); - fp = fopen(EPROM_unit.filename, "rb"); /* open EPROM file */ - if (fp == NULL) { - sim_printf("EPROM: Unable to open ROM file %s\n", EPROM_unit.filename); - sim_printf("\tNo ROM image loaded!!!\n"); - return SCPE_OK; - } - sim_debug (DEBUG_read, &EPROM_dev, "\tRead file\n"); - j = 0; /* load EPROM file */ - c = fgetc(fp); - while (c != EOF) { - *((uint8 *)EPROM_unit.filebuf + j++) = c & 0xFF; - c = fgetc(fp); - if (j > EPROM_unit.capac) { - sim_printf("\tImage is too large - Load truncated!!!\n"); - break; - } - } - sim_printf("\tImage size=%04X unit_capac=%04X\n", j, EPROM_unit.capac); - sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n"); - fclose(fp); - sim_printf("EPROM: %d bytes of ROM image %s loaded\n", j, EPROM_unit.filename); - sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Done\n"); - return SCPE_OK; -} - -/* EPROM reset */ - -t_stat EPROM_reset (DEVICE *dptr, uint16 size) -{ -// sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=0000 size=%04X\n", size); - if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */ - EPROM_unit.capac = size; /* set EPROM size to 0 */ - sim_debug (DEBUG_flow, &EPROM_dev, "Done1\n"); -// sim_printf(" EPROM: Available [%04X-%04XH]\n", -// 0, EPROM_unit.capac - 1); - return SCPE_OK; - } - if ((EPROM_unit.flags & UNIT_ATT) == 0) { - sim_printf("EPROM: No file attached\n"); - } - sim_debug (DEBUG_flow, &EPROM_dev, "Done2\n"); - return SCPE_OK; -} - -/* get a byte from memory */ - -uint8 EPROM_get_mbyte(uint16 addr) -{ - uint8 val; - - sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%04X\n", addr); - if (addr < EPROM_unit.capac) { - SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_xack, &EPROM_dev, "EPROM_get_mbyte: Set XACK for %04X\n", addr); - val = *((uint8 *)EPROM_unit.filebuf + addr); - sim_debug (DEBUG_read, &EPROM_dev, " val=%04X\n", val); - return (val & 0xFF); - } - sim_debug (DEBUG_read, &EPROM_dev, " Out of range\n"); - return 0xFF; -} - -/* end of ipcEPROM.c */ +/* ipcEPROM.c: Intel EPROM simulator for 8-bit SBCs + + Copyright (c) 2010, 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: + + ?? ??? 10 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + These functions support a simulated ROM devices on an iSBC-80/XX SBCs. + This allows the attachment of the device to a binary file containing the EPROM + code image. Unit will support a single 2708, 2716, 2732, or 2764 type EPROM. + These functions also support bit 1 of 8255 number 1, port B, to enable/ + disable the onboard ROM. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat EPROM_attach (UNIT *uptr, CONST char *cptr); +t_stat EPROM_reset (DEVICE *dptr, uint16 size); +uint8 EPROM_get_mbyte(uint16 addr); + +/* external function prototypes */ + +extern uint8 xack; /* XACK signal */ +extern UNIT ipc_cont_unit[]; + +/* SIMH EPROM Standard I/O Data Structures */ + +UNIT EPROM_unit = { + UDATA (NULL, UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0), 0 +}; + +DEBTAB EPROM_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE EPROM_dev = { + "EPROM", //name + &EPROM_unit, //units + NULL, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &EPROM_reset, //reset + NULL, //reset + NULL, //boot + &EPROM_attach, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + EPROM_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* global variables */ + +/* EPROM functions */ + +/* EPROM attach */ + +t_stat EPROM_attach (UNIT *uptr, CONST char *cptr) +{ + uint16 j; + int c; + FILE *fp; + t_stat r; + + sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: cptr=%s\n", cptr); + if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { + sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Error\n"); + return r; + } + sim_debug (DEBUG_read, &EPROM_dev, "\tAllocate buffer\n"); + if (EPROM_unit.filebuf == NULL) { /* no buffer allocated */ + EPROM_unit.filebuf = malloc(EPROM_unit.capac); /* allocate EPROM buffer */ + if (EPROM_unit.filebuf == NULL) { + sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Malloc error\n"); + return SCPE_MEM; + } + } + sim_debug (DEBUG_read, &EPROM_dev, "\tOpen file %s\n", EPROM_unit.filename); + fp = fopen(EPROM_unit.filename, "rb"); /* open EPROM file */ + if (fp == NULL) { + sim_printf("EPROM: Unable to open ROM file %s\n", EPROM_unit.filename); + sim_printf("\tNo ROM image loaded!!!\n"); + return SCPE_OK; + } + sim_debug (DEBUG_read, &EPROM_dev, "\tRead file\n"); + j = 0; /* load EPROM file */ + c = fgetc(fp); + while (c != EOF) { + *((uint8 *)EPROM_unit.filebuf + j++) = c & 0xFF; + c = fgetc(fp); + if (j > EPROM_unit.capac) { + sim_printf("\tImage is too large - Load truncated!!!\n"); + break; + } + } + sim_printf("\tImage size=%04X unit_capac=%04X\n", j, EPROM_unit.capac); + sim_debug (DEBUG_read, &EPROM_dev, "\tClose file\n"); + fclose(fp); + sim_printf("EPROM: %d bytes of ROM image %s loaded\n", j, EPROM_unit.filename); + sim_debug (DEBUG_flow, &EPROM_dev, "EPROM_attach: Done\n"); + return SCPE_OK; +} + +/* EPROM reset */ + +t_stat EPROM_reset (DEVICE *dptr, uint16 size) +{ +// sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=0000 size=%04X\n", size); + if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */ + EPROM_unit.capac = size; /* set EPROM size to 0 */ + sim_debug (DEBUG_flow, &EPROM_dev, "Done1\n"); +// sim_printf(" EPROM: Available [%04X-%04XH]\n", +// 0, EPROM_unit.capac - 1); + return SCPE_OK; + } + if ((EPROM_unit.flags & UNIT_ATT) == 0) { + sim_printf("EPROM: No file attached\n"); + } + sim_debug (DEBUG_flow, &EPROM_dev, "Done2\n"); + return SCPE_OK; +} + +/* get a byte from memory */ + +uint8 EPROM_get_mbyte(uint16 addr) +{ + uint8 val; + + sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%04X\n", addr); + if (addr < EPROM_unit.capac) { + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &EPROM_dev, "EPROM_get_mbyte: Set XACK for %04X\n", addr); + val = *((uint8 *)EPROM_unit.filebuf + addr); + sim_debug (DEBUG_read, &EPROM_dev, " val=%04X\n", val); + return (val & 0xFF); + } + sim_debug (DEBUG_read, &EPROM_dev, " Out of range\n"); + return 0xFF; +} + +/* end of ipcEPROM.c */ diff --git a/Intel-Systems/common/ipcmultibus.c b/Intel-Systems/common/ipcmultibus.c index 3f5e06e2..e3a25939 100644 --- a/Intel-Systems/common/ipcmultibus.c +++ b/Intel-Systems/common/ipcmultibus.c @@ -1,309 +1,309 @@ -/* ipcmultibus.c: Multibus I simulator - - Copyright (c) 2010, 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: - - ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. - 24 Apr 15 -- Modified to use simh_debug - - NOTES: - - This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus - Computer Systems. - -*/ - -#include "system_defs.h" - -#define SET_XACK(VAL) (xack = VAL) - -int32 mbirq = 0; /* set no multibus interrupts */ - -/* function prototypes */ - -t_stat multibus_svc(UNIT *uptr); -t_stat multibus_reset(DEVICE *dptr); -void set_irq(int32 int_num); -void clr_irq(int32 int_num); -uint8 nulldev(t_bool io, uint8 data); -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); -t_stat multibus_reset (DEVICE *dptr); -uint8 multibus_get_mbyte(uint16 addr); -uint16 multibus_get_mword(uint16 addr); -void multibus_put_mbyte(uint16 addr, uint8 val); -void multibus_put_mword(uint16 addr, uint16 val); - -/* external function prototypes */ - -extern t_stat SBC_reset(DEVICE *dptr); /* reset the IPC simulator */ -extern void set_cpuint(int32 int_num); -extern UNIT zx200a_unit; -extern t_stat zx200a_reset(DEVICE *dptr, uint16 base); -extern t_stat isbc201_reset (DEVICE *dptr, uint16); -extern t_stat isbc202_reset (DEVICE *dptr, uint16); -extern uint8 RAM_get_mbyte(uint16 addr); -extern void RAM_put_mbyte(uint16 addr, uint8 val); - -/* external globals */ - -extern uint8 xack; /* XACK signal */ -extern int32 int_req; /* i8080 INT signal */ -extern int32 isbc201_fdcnum; -extern int32 isbc202_fdcnum; -extern int32 zx200a_fdcnum; - -/* multibus Standard SIMH Device Data Structures */ - -UNIT multibus_unit = { - UDATA (&multibus_svc, 0, 0), 20 -}; - -REG multibus_reg[] = { - { HRDATA (MBIRQ, mbirq, 32) }, - { HRDATA (XACK, xack, 8) } -}; - -DEBTAB multibus_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE multibus_dev = { - "MBIRQ", //name - &multibus_unit, //units - multibus_reg, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - &multibus_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - multibus_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Service routines to handle simulator functions */ - -/* service routine - actually does the simulated interrupts */ - -t_stat multibus_svc(UNIT *uptr) -{ - switch (mbirq) { - case INT_1: - set_cpuint(INT_R); -#if NIPC - clr_irq(SBC202_INT); /***** bad, bad, bad! */ -#endif -// sim_printf("multibus_svc: mbirq=%04X int_req=%04X\n", mbirq, int_req); - break; - default: -// sim_printf("multibus_svc: default mbirq=%04X\n", mbirq); - break; - } - sim_activate (&multibus_unit, multibus_unit.wait); /* continue poll */ - return SCPE_OK; -} - -/* Reset routine */ - -t_stat multibus_reset(DEVICE *dptr) -{ - SBC_reset(NULL); - sim_printf(" Multibus: Reset\n"); - zx200a_fdcnum = 0; - zx200a_reset(NULL, ZX200A_BASE_DD); -// zx200a_reset(NULL, ZX200A_BASE_SD); - isbc201_fdcnum = 0; - isbc201_reset(NULL, SBC201_BASE); - isbc202_fdcnum = 0; - isbc202_reset(NULL, SBC202_BASE); - sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */ - return SCPE_OK; -} - -void set_irq(int32 int_num) -{ - mbirq |= int_num; -// sim_printf("set_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq); -} - -void clr_irq(int32 int_num) -{ - mbirq &= ~int_num; -// sim_printf("clr_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq); -} - -/* This is the I/O configuration table. There are 256 possible -device addresses, if a device is plugged to a port it's routine -address is here, 'nulldev' means no device has been registered. -*/ -struct idev { - uint8 (*routine)(t_bool io, uint8 data); - uint8 devnum; -}; - -struct idev dev_table[256] = { -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 000H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 004H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 008H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 00CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 010H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 014H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 018H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 01CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 020H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 024H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 028H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 02CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 030H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 034H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 038H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 03CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 040H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 044H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 048H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 04CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 050H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 054H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 058H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 05CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 060H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 064H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 068H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 06CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 070H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 074H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 078H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 07CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 080H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 084H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 088H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 08CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 090H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 094H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 098H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 09CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0CCH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0DCH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0ECH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 0FCH */ -}; - -uint8 nulldev(t_bool flag, uint8 data) -{ - SET_XACK(0); /* set no XACK */ -// return 0xFF; - return 0; -} - -uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port, uint8 devnum) -{ - if (dev_table[port].routine != &nulldev) { /* port already assigned */ - sim_printf("Multibus: I/O Port %04X is already assigned\n", port); - } else { - sim_printf("Port %04X is assigned\n", port); - dev_table[port].routine = routine; - dev_table[port].devnum = devnum; - } - return 0; -} - -/* get a byte from memory */ - -uint8 multibus_get_mbyte(uint16 addr) -{ - SET_XACK(0); /* set no XACK */ -// sim_printf("multibus_get_mbyte: Cleared XACK for %04X\n", addr); - return RAM_get_mbyte(addr); -} - -/* get a word from memory */ - -uint16 multibus_get_mword(uint16 addr) -{ - uint16 val; - - val = multibus_get_mbyte(addr); - val |= (multibus_get_mbyte(addr+1) << 8); - return val; -} - -/* put a byte to memory */ - -void multibus_put_mbyte(uint16 addr, uint8 val) -{ - SET_XACK(0); /* set no XACK */ -// sim_printf("multibus_put_mbyte: Cleared XACK for %04X\n", addr); - RAM_put_mbyte(addr, val); -// sim_printf("multibus_put_mbyte: Done XACK=%dX\n", XACK); -} - -/* put a word to memory */ - -void multibus_put_mword(uint16 addr, uint16 val) -{ - multibus_put_mbyte(addr, val & 0xff); - multibus_put_mbyte(addr+1, val >> 8); -} - -/* end of ipcmultibus.c */ - +/* ipcmultibus.c: Multibus I simulator + + Copyright (c) 2010, 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: + + ?? ??? 10 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. + +*/ + +#include "system_defs.h" + +#define SET_XACK(VAL) (xack = VAL) + +int32 mbirq = 0; /* set no multibus interrupts */ + +/* function prototypes */ + +t_stat multibus_svc(UNIT *uptr); +t_stat multibus_reset(DEVICE *dptr); +void set_irq(int32 int_num); +void clr_irq(int32 int_num); +uint8 nulldev(t_bool io, uint8 data); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16, uint8); +t_stat multibus_reset (DEVICE *dptr); +uint8 multibus_get_mbyte(uint16 addr); +uint16 multibus_get_mword(uint16 addr); +void multibus_put_mbyte(uint16 addr, uint8 val); +void multibus_put_mword(uint16 addr, uint16 val); + +/* external function prototypes */ + +extern t_stat SBC_reset(DEVICE *dptr); /* reset the IPC simulator */ +extern void set_cpuint(int32 int_num); +extern UNIT zx200a_unit; +extern t_stat zx200a_reset(DEVICE *dptr, uint16 base); +extern t_stat isbc201_reset (DEVICE *dptr, uint16); +extern t_stat isbc202_reset (DEVICE *dptr, uint16); +extern uint8 RAM_get_mbyte(uint16 addr); +extern void RAM_put_mbyte(uint16 addr, uint8 val); + +/* external globals */ + +extern uint8 xack; /* XACK signal */ +extern int32 int_req; /* i8080 INT signal */ +extern int32 isbc201_fdcnum; +extern int32 isbc202_fdcnum; +extern int32 zx200a_fdcnum; + +/* multibus Standard SIMH Device Data Structures */ + +UNIT multibus_unit = { + UDATA (&multibus_svc, 0, 0), 20 +}; + +REG multibus_reg[] = { + { HRDATA (MBIRQ, mbirq, 32) }, + { HRDATA (XACK, xack, 8) } +}; + +DEBTAB multibus_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE multibus_dev = { + "MBIRQ", //name + &multibus_unit, //units + multibus_reg, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + &multibus_reset, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + multibus_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +/* service routine - actually does the simulated interrupts */ + +t_stat multibus_svc(UNIT *uptr) +{ + switch (mbirq) { + case INT_1: + set_cpuint(INT_R); +#if NIPC + clr_irq(SBC202_INT); /***** bad, bad, bad! */ +#endif +// sim_printf("multibus_svc: mbirq=%04X int_req=%04X\n", mbirq, int_req); + break; + default: +// sim_printf("multibus_svc: default mbirq=%04X\n", mbirq); + break; + } + sim_activate (&multibus_unit, multibus_unit.wait); /* continue poll */ + return SCPE_OK; +} + +/* Reset routine */ + +t_stat multibus_reset(DEVICE *dptr) +{ + SBC_reset(NULL); + sim_printf(" Multibus: Reset\n"); + zx200a_fdcnum = 0; + zx200a_reset(NULL, ZX200A_BASE_DD); +// zx200a_reset(NULL, ZX200A_BASE_SD); + isbc201_fdcnum = 0; + isbc201_reset(NULL, SBC201_BASE); + isbc202_fdcnum = 0; + isbc202_reset(NULL, SBC202_BASE); + sim_activate (&multibus_unit, multibus_unit.wait); /* activate unit */ + return SCPE_OK; +} + +void set_irq(int32 int_num) +{ + mbirq |= int_num; +// sim_printf("set_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq); +} + +void clr_irq(int32 int_num) +{ + mbirq &= ~int_num; +// sim_printf("clr_irq: int_num=%04X mbirq=%04X\n", int_num, mbirq); +} + +/* This is the I/O configuration table. There are 256 possible +device addresses, if a device is plugged to a port it's routine +address is here, 'nulldev' means no device has been registered. +*/ +struct idev { + uint8 (*routine)(t_bool io, uint8 data); + uint8 devnum; +}; + +struct idev dev_table[256] = { +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 000H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 004H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 008H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 00CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 010H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 014H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 018H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 01CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 020H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 024H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 028H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 02CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 030H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 034H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 038H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 03CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 040H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 044H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 048H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 04CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 050H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 054H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 058H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 05CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 060H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 064H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 068H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 06CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 070H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 074H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 078H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 07CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 080H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 084H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 088H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 08CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 090H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 094H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 098H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 09CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0CCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0D8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0DCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0E8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0ECH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0F8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 0FCH */ +}; + +uint8 nulldev(t_bool flag, uint8 data) +{ + SET_XACK(0); /* set no XACK */ +// return 0xFF; + return 0; +} + +uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port, uint8 devnum) +{ + if (dev_table[port].routine != &nulldev) { /* port already assigned */ + sim_printf("Multibus: I/O Port %04X is already assigned\n", port); + } else { + sim_printf("Port %04X is assigned\n", port); + dev_table[port].routine = routine; + dev_table[port].devnum = devnum; + } + return 0; +} + +/* get a byte from memory */ + +uint8 multibus_get_mbyte(uint16 addr) +{ + SET_XACK(0); /* set no XACK */ +// sim_printf("multibus_get_mbyte: Cleared XACK for %04X\n", addr); + return RAM_get_mbyte(addr); +} + +/* get a word from memory */ + +uint16 multibus_get_mword(uint16 addr) +{ + uint16 val; + + val = multibus_get_mbyte(addr); + val |= (multibus_get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory */ + +void multibus_put_mbyte(uint16 addr, uint8 val) +{ + SET_XACK(0); /* set no XACK */ +// sim_printf("multibus_put_mbyte: Cleared XACK for %04X\n", addr); + RAM_put_mbyte(addr, val); +// sim_printf("multibus_put_mbyte: Done XACK=%dX\n", XACK); +} + +/* put a word to memory */ + +void multibus_put_mword(uint16 addr, uint16 val) +{ + multibus_put_mbyte(addr, val & 0xff); + multibus_put_mbyte(addr+1, val >> 8); +} + +/* end of ipcmultibus.c */ + diff --git a/Intel-Systems/common/ipcram8.c b/Intel-Systems/common/ipcram8.c index 57c55fa8..b2697ef2 100644 --- a/Intel-Systems/common/ipcram8.c +++ b/Intel-Systems/common/ipcram8.c @@ -1,145 +1,145 @@ -/* ipcRAM8.c: Intel RAM simulator for 8-bit SBCs - - 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 base and size. - 24 Apr 15 -- Modified to use simh_debug - - NOTES: - - These functions support a simulated RAM devices on an iSBC-80/XX SBCs. - These functions also support bit 2 of 8255 number 1, port B, to enable/ - disable the onboard RAM. -*/ - -#include "system_defs.h" - -/* function prototypes */ - -t_stat RAM_svc (UNIT *uptr); -t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); -uint8 RAM_get_mbyte(uint16 addr); -void RAM_put_mbyte(uint16 addr, uint8 val); - -/* external function prototypes */ - -extern uint8 xack; /* XACK signal */ - -/* SIMH RAM Standard I/O Data Structures */ - -UNIT RAM_unit = { UDATA (NULL, UNIT_BINK, 0), KBD_POLL_WAIT }; - -DEBTAB RAM_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE RAM_dev = { - "RAM", //name - &RAM_unit, //units - NULL, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &RAM_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - RAM_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* global variables */ - -/* RAM functions */ - -/* RAM reset */ - -t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size) -{ - sim_debug (DEBUG_flow, &RAM_dev, " RAM_reset: base=%04X size=%04X\n", base, size-1); - if (RAM_unit.capac == 0) { /* if undefined */ - RAM_unit.capac = size; - RAM_unit.u3 = base; - } - if (RAM_unit.filebuf == NULL) { /* no buffer allocated */ - RAM_unit.filebuf = malloc(RAM_unit.capac); - if (RAM_unit.filebuf == NULL) { - sim_debug (DEBUG_flow, &RAM_dev, "RAM_set_size: Malloc error\n"); - return SCPE_MEM; - } - } -// sim_printf(" RAM: Available [%04X-%04XH]\n", -// RAM_unit.u3, -// RAM_unit.u3 + RAM_unit.capac - 1); - sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n"); - return SCPE_OK; -} - -/* get a byte from memory */ - -uint8 RAM_get_mbyte(uint16 addr) -{ - uint8 val; - - sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr); - SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr); - val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)); - sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val); - return (val & 0xFF); -} - -/* put a byte to memory */ - -void RAM_put_mbyte(uint16 addr, uint8 val) -{ - sim_debug (DEBUG_write, &RAM_dev, "RAM_put_mbyte: addr=%04X, val=%02X\n", addr, val); - SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr); - *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF; - sim_debug (DEBUG_write, &RAM_dev, "\n"); -} - -/* end of ipcRAM8.c */ +/* ipcRAM8.c: Intel RAM simulator for 8-bit SBCs + + 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 base and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + These functions support a simulated RAM devices on an iSBC-80/XX SBCs. + These functions also support bit 2 of 8255 number 1, port B, to enable/ + disable the onboard RAM. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat RAM_svc (UNIT *uptr); +t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); +uint8 RAM_get_mbyte(uint16 addr); +void RAM_put_mbyte(uint16 addr, uint8 val); + +/* external function prototypes */ + +extern uint8 xack; /* XACK signal */ + +/* SIMH RAM Standard I/O Data Structures */ + +UNIT RAM_unit = { UDATA (NULL, UNIT_BINK, 0), KBD_POLL_WAIT }; + +DEBTAB RAM_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE RAM_dev = { + "RAM", //name + &RAM_unit, //units + NULL, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &RAM_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + RAM_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* global variables */ + +/* RAM functions */ + +/* RAM reset */ + +t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size) +{ + sim_debug (DEBUG_flow, &RAM_dev, " RAM_reset: base=%04X size=%04X\n", base, size-1); + if (RAM_unit.capac == 0) { /* if undefined */ + RAM_unit.capac = size; + RAM_unit.u3 = base; + } + if (RAM_unit.filebuf == NULL) { /* no buffer allocated */ + RAM_unit.filebuf = malloc(RAM_unit.capac); + if (RAM_unit.filebuf == NULL) { + sim_debug (DEBUG_flow, &RAM_dev, "RAM_set_size: Malloc error\n"); + return SCPE_MEM; + } + } +// sim_printf(" RAM: Available [%04X-%04XH]\n", +// RAM_unit.u3, +// RAM_unit.u3 + RAM_unit.capac - 1); + sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n"); + return SCPE_OK; +} + +/* get a byte from memory */ + +uint8 RAM_get_mbyte(uint16 addr) +{ + uint8 val; + + sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr); + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr); + val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)); + sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val); + return (val & 0xFF); +} + +/* put a byte to memory */ + +void RAM_put_mbyte(uint16 addr, uint8 val) +{ + sim_debug (DEBUG_write, &RAM_dev, "RAM_put_mbyte: addr=%04X, val=%02X\n", addr, val); + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr); + *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF; + sim_debug (DEBUG_write, &RAM_dev, "\n"); +} + +/* end of ipcRAM8.c */ diff --git a/Intel-Systems/common/iram16.c b/Intel-Systems/common/iram16.c index 0732c6c8..2a890552 100644 --- a/Intel-Systems/common/iram16.c +++ b/Intel-Systems/common/iram16.c @@ -1,203 +1,203 @@ -/* iram.c: Intel RAM simulator for 16-bit SBCs - - 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. - - These functions support a simulated RAM device in low memory on an iSBC. These - SBCs do not have the capability to switch off this RAM. In most cases a portion - of the RAM is dual-ported so it also appears in the multibus memory map at - a configurable location. - - Unit will support 16K SRAM sizes. - -*/ - -#include - -#include "multibus_defs.h" - -#define UNIT_V_RSIZE (UNIT_V_UF) /* RAM Size */ -#define UNIT_RSIZE (0x1 << UNIT_V_RSIZE) -#define UNIT_NONE (0) /* No unit */ -#define UNIT_16K (1) /* 16KB */ - -/* function prototypes */ - -t_stat RAM_svc (UNIT *uptr); -t_stat RAM_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat RAM_reset (DEVICE *dptr); -int32 RAM_get_mbyte(int32 addr); -void RAM_put_mbyte(int32 addr, int32 val); - -/* SIMH RAM Standard I/O Data Structures */ - -UNIT RAM_unit = { UDATA (NULL, UNIT_BINK, 0), KBD_POLL_WAIT }; - -MTAB RAM_mod[] = { - { UNIT_RSIZE, UNIT_NONE, "None", "none", &RAM_set_size }, - { UNIT_RSIZE, UNIT_16K, "16KB", "16KB", &RAM_set_size }, - { 0 } -}; - -DEBTAB RAM_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE RAM_dev = { - "RAM", //name - &RAM_unit, //units - NULL, //registers - RAM_mod, //modifiers - 1, //numunits - 16, //aradix - 32, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - &RAM_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - RAM_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* global variables */ - -uint8 *RAM_buf = NULL; /* RAM buffer pointer */ - -/* RAM functions */ - -/* RAM set size = none or 16KB */ - -t_stat RAM_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ - if (RAM_dev.dctrl & DEBUG_flow) - sim_printf("RAM_set_size: val=%d\n", val); - if ((val < UNIT_NONE) || (val > UNIT_16K)) { - if (RAM_dev.dctrl & DEBUG_flow) - sim_printf("RAM_set_size: Size error\n"); - return SCPE_ARG; - } - RAM_unit.capac = 0x4000 * val; /* set size */ - RAM_unit.u3 = 0x0000; /* base is 0 */ - RAM_unit.u4 = val; /* save val */ - if (RAM_buf) { /* if changed, allocate new buffer */ - free (RAM_buf); - RAM_buf = NULL; - } - if (RAM_dev.dctrl & DEBUG_flow) - sim_printf("RAM_set_size: Done\n"); - return (RAM_reset (NULL)); /* force reset after reconfig */ -} - -/* RAM reset */ - -t_stat RAM_reset (DEVICE *dptr) -{ - int j; - FILE *fp; - - if (RAM_dev.dctrl & DEBUG_flow) - sim_printf("RAM_reset: \n"); - if (RAM_unit.capac == 0) { /* if undefined */ - sim_printf(" RAM: defaulted for 16KB\n"); - sim_printf(" \"set RAM 16KB\"\n"); - RAM_unit.capac = 0x4000; - RAM_unit.u3 = 0; - RAM_unit.u4 = 1; - } - sim_printf(" RAM: Initializing [%04X-%04XH]\n", - RAM_unit.u3, - RAM_unit.u3 + RAM_unit.capac - 1); - if (RAM_buf == NULL) { /* no buffer allocated */ - RAM_buf = malloc(RAM_unit.capac); - if (RAM_buf == NULL) { - if (RAM_dev.dctrl & DEBUG_flow) - sim_printf("RAM_reset: Malloc error\n"); - return SCPE_MEM; - } - } - if (RAM_dev.dctrl & DEBUG_flow) - sim_printf("RAM_reset: Done\n"); - return SCPE_OK; -} - -/* I/O instruction handlers, called from the CPU module when an - RAM memory read or write is issued. -*/ - -/* get a byte from memory */ - -int32 RAM_get_mbyte(int32 addr) -{ - int32 val, org, len; - - org = RAM_unit.u3; - len = RAM_unit.capac - 1; - if (RAM_dev.dctrl & DEBUG_read) - sim_printf("RAM_get_mbyte: addr=%04X", addr); - if ((addr >= org) && (addr <= org + len)) { - val = *(RAM_buf + (addr - org)); - if (RAM_dev.dctrl & DEBUG_read) - sim_printf(" val=%04X\n", val); - return (val & 0xFF); - } - if (RAM_dev.dctrl & DEBUG_read) - sim_printf(" Out of range\n", addr); - return 0xFF; -} - -/* put a byte to memory */ - -void RAM_put_mbyte(int32 addr, int32 val) -{ - int32 org, len; - - org = RAM_unit.u3; - len = RAM_unit.capac - 1; - if (RAM_dev.dctrl & DEBUG_write) - sim_printf("RAM_put_mbyte: addr=%04X, val=%02X", addr, val); - if ((addr >= org) && (addr < org + len)) { - *(RAM_buf + (addr - org)) = val & 0xFF; - if (RAM_dev.dctrl & DEBUG_write) - sim_printf("\n"); - return; - } - if (RAM_dev.dctrl & DEBUG_write) - sim_printf(" Out of range\n", val); -} - -/* end of iram.c */ +/* iram.c: Intel RAM simulator for 16-bit SBCs + + 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. + + These functions support a simulated RAM device in low memory on an iSBC. These + SBCs do not have the capability to switch off this RAM. In most cases a portion + of the RAM is dual-ported so it also appears in the multibus memory map at + a configurable location. + + Unit will support 16K SRAM sizes. + +*/ + +#include + +#include "multibus_defs.h" + +#define UNIT_V_RSIZE (UNIT_V_UF) /* RAM Size */ +#define UNIT_RSIZE (0x1 << UNIT_V_RSIZE) +#define UNIT_NONE (0) /* No unit */ +#define UNIT_16K (1) /* 16KB */ + +/* function prototypes */ + +t_stat RAM_svc (UNIT *uptr); +t_stat RAM_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat RAM_reset (DEVICE *dptr); +int32 RAM_get_mbyte(int32 addr); +void RAM_put_mbyte(int32 addr, int32 val); + +/* SIMH RAM Standard I/O Data Structures */ + +UNIT RAM_unit = { UDATA (NULL, UNIT_BINK, 0), KBD_POLL_WAIT }; + +MTAB RAM_mod[] = { + { UNIT_RSIZE, UNIT_NONE, "None", "none", &RAM_set_size }, + { UNIT_RSIZE, UNIT_16K, "16KB", "16KB", &RAM_set_size }, + { 0 } +}; + +DEBTAB RAM_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE RAM_dev = { + "RAM", //name + &RAM_unit, //units + NULL, //registers + RAM_mod, //modifiers + 1, //numunits + 16, //aradix + 32, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + &RAM_reset, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + RAM_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* global variables */ + +uint8 *RAM_buf = NULL; /* RAM buffer pointer */ + +/* RAM functions */ + +/* RAM set size = none or 16KB */ + +t_stat RAM_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) +{ + if (RAM_dev.dctrl & DEBUG_flow) + sim_printf("RAM_set_size: val=%d\n", val); + if ((val < UNIT_NONE) || (val > UNIT_16K)) { + if (RAM_dev.dctrl & DEBUG_flow) + sim_printf("RAM_set_size: Size error\n"); + return SCPE_ARG; + } + RAM_unit.capac = 0x4000 * val; /* set size */ + RAM_unit.u3 = 0x0000; /* base is 0 */ + RAM_unit.u4 = val; /* save val */ + if (RAM_buf) { /* if changed, allocate new buffer */ + free (RAM_buf); + RAM_buf = NULL; + } + if (RAM_dev.dctrl & DEBUG_flow) + sim_printf("RAM_set_size: Done\n"); + return (RAM_reset (NULL)); /* force reset after reconfig */ +} + +/* RAM reset */ + +t_stat RAM_reset (DEVICE *dptr) +{ + int j; + FILE *fp; + + if (RAM_dev.dctrl & DEBUG_flow) + sim_printf("RAM_reset: \n"); + if (RAM_unit.capac == 0) { /* if undefined */ + sim_printf(" RAM: defaulted for 16KB\n"); + sim_printf(" \"set RAM 16KB\"\n"); + RAM_unit.capac = 0x4000; + RAM_unit.u3 = 0; + RAM_unit.u4 = 1; + } + sim_printf(" RAM: Initializing [%04X-%04XH]\n", + RAM_unit.u3, + RAM_unit.u3 + RAM_unit.capac - 1); + if (RAM_buf == NULL) { /* no buffer allocated */ + RAM_buf = malloc(RAM_unit.capac); + if (RAM_buf == NULL) { + if (RAM_dev.dctrl & DEBUG_flow) + sim_printf("RAM_reset: Malloc error\n"); + return SCPE_MEM; + } + } + if (RAM_dev.dctrl & DEBUG_flow) + sim_printf("RAM_reset: Done\n"); + return SCPE_OK; +} + +/* I/O instruction handlers, called from the CPU module when an + RAM memory read or write is issued. +*/ + +/* get a byte from memory */ + +int32 RAM_get_mbyte(int32 addr) +{ + int32 val, org, len; + + org = RAM_unit.u3; + len = RAM_unit.capac - 1; + if (RAM_dev.dctrl & DEBUG_read) + sim_printf("RAM_get_mbyte: addr=%04X", addr); + if ((addr >= org) && (addr <= org + len)) { + val = *(RAM_buf + (addr - org)); + if (RAM_dev.dctrl & DEBUG_read) + sim_printf(" val=%04X\n", val); + return (val & 0xFF); + } + if (RAM_dev.dctrl & DEBUG_read) + sim_printf(" Out of range\n", addr); + return 0xFF; +} + +/* put a byte to memory */ + +void RAM_put_mbyte(int32 addr, int32 val) +{ + int32 org, len; + + org = RAM_unit.u3; + len = RAM_unit.capac - 1; + if (RAM_dev.dctrl & DEBUG_write) + sim_printf("RAM_put_mbyte: addr=%04X, val=%02X", addr, val); + if ((addr >= org) && (addr < org + len)) { + *(RAM_buf + (addr - org)) = val & 0xFF; + if (RAM_dev.dctrl & DEBUG_write) + sim_printf("\n"); + return; + } + if (RAM_dev.dctrl & DEBUG_write) + sim_printf(" Out of range\n", val); +} + +/* end of iram.c */ diff --git a/Intel-Systems/common/iram8.c b/Intel-Systems/common/iram8.c index 0a69be8a..edb7bb38 100644 --- a/Intel-Systems/common/iram8.c +++ b/Intel-Systems/common/iram8.c @@ -1,154 +1,154 @@ -/* iRAM8.c: Intel RAM simulator for 8-bit SBCs - - 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 base and size. - 24 Apr 15 -- Modified to use simh_debug - - NOTES: - - These functions support a simulated RAM devices on an iSBC-80/XX SBCs. - These functions also support bit 2 of 8255 number 1, port B, to enable/ - disable the onboard RAM. -*/ - -#include "system_defs.h" - -/* function prototypes */ - -t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); -uint8 RAM_get_mbyte(uint16 addr); -void RAM_put_mbyte(uint16 addr, uint8 val); - -/* external function prototypes */ - -extern uint8 i8255_B[4]; //port B byte I/O -extern uint8 xack; /* XACK signal */ - -/* SIMH RAM Standard I/O Data Structures */ - -UNIT RAM_unit = { UDATA (NULL, UNIT_BINK, 0), KBD_POLL_WAIT }; - -DEBTAB RAM_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE RAM_dev = { - "RAM", //name - &RAM_unit, //units - NULL, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &RAM_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - RAM_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* RAM functions */ - -/* RAM reset */ - -t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size) -{ - sim_debug (DEBUG_flow, &RAM_dev, " RAM_reset: base=%04X size=%04X\n", base, size-1); - if (RAM_unit.capac == 0) { /* if undefined */ - RAM_unit.capac = size; - RAM_unit.u3 = base; - } - if (RAM_unit.filebuf == NULL) { /* no buffer allocated */ - RAM_unit.filebuf = malloc(RAM_unit.capac); - if (RAM_unit.filebuf == NULL) { - sim_debug (DEBUG_flow, &RAM_dev, "RAM_set_size: Malloc error\n"); - return SCPE_MEM; - } - } - sim_printf(" RAM: Available [%04X-%04XH]\n", - RAM_unit.u3, - RAM_unit.u3 + RAM_unit.capac - 1); - sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n"); - return SCPE_OK; -} - -/* get a byte from memory */ - -uint8 RAM_get_mbyte(uint16 addr) -{ - uint8 val; - - sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr); - if ((addr >= RAM_unit.u3) && ((uint32) addr < (RAM_unit.u3 + RAM_unit.capac))) { - SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr); - val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)); - sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val); - return (val & 0xFF); - } else { - sim_debug (DEBUG_read, &RAM_dev, " Out of range\n"); - return 0xFF; - } -} - -/* put a byte to memory */ - -void RAM_put_mbyte(uint16 addr, uint8 val) -{ - sim_debug (DEBUG_write, &RAM_dev, "RAM_put_mbyte: addr=%04X, val=%02X\n", addr, val); - if ((addr >= RAM_unit.u3) && ((uint32)addr < RAM_unit.u3 + RAM_unit.capac)) { - SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr); - *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF; - sim_debug (DEBUG_write, &RAM_dev, "\n"); - return; - } else { - sim_debug (DEBUG_write, &RAM_dev, " Out of range\n"); - return; - } -} - -/* end of iRAM8.c */ +/* iRAM8.c: Intel RAM simulator for 8-bit SBCs + + 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 base and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + These functions support a simulated RAM devices on an iSBC-80/XX SBCs. + These functions also support bit 2 of 8255 number 1, port B, to enable/ + disable the onboard RAM. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); +uint8 RAM_get_mbyte(uint16 addr); +void RAM_put_mbyte(uint16 addr, uint8 val); + +/* external function prototypes */ + +extern uint8 i8255_B[4]; //port B byte I/O +extern uint8 xack; /* XACK signal */ + +/* SIMH RAM Standard I/O Data Structures */ + +UNIT RAM_unit = { UDATA (NULL, UNIT_BINK, 0), KBD_POLL_WAIT }; + +DEBTAB RAM_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE RAM_dev = { + "RAM", //name + &RAM_unit, //units + NULL, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &RAM_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + RAM_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* RAM functions */ + +/* RAM reset */ + +t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size) +{ + sim_debug (DEBUG_flow, &RAM_dev, " RAM_reset: base=%04X size=%04X\n", base, size-1); + if (RAM_unit.capac == 0) { /* if undefined */ + RAM_unit.capac = size; + RAM_unit.u3 = base; + } + if (RAM_unit.filebuf == NULL) { /* no buffer allocated */ + RAM_unit.filebuf = malloc(RAM_unit.capac); + if (RAM_unit.filebuf == NULL) { + sim_debug (DEBUG_flow, &RAM_dev, "RAM_set_size: Malloc error\n"); + return SCPE_MEM; + } + } + sim_printf(" RAM: Available [%04X-%04XH]\n", + RAM_unit.u3, + RAM_unit.u3 + RAM_unit.capac - 1); + sim_debug (DEBUG_flow, &RAM_dev, "RAM_reset: Done\n"); + return SCPE_OK; +} + +/* get a byte from memory */ + +uint8 RAM_get_mbyte(uint16 addr) +{ + uint8 val; + + sim_debug (DEBUG_read, &RAM_dev, "RAM_get_mbyte: addr=%04X\n", addr); + if ((addr >= RAM_unit.u3) && ((uint32) addr < (RAM_unit.u3 + RAM_unit.capac))) { + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &RAM_dev, "RAM_get_mbyte: Set XACK for %04X\n", addr); + val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)); + sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val); + return (val & 0xFF); + } else { + sim_debug (DEBUG_read, &RAM_dev, " Out of range\n"); + return 0xFF; + } +} + +/* put a byte to memory */ + +void RAM_put_mbyte(uint16 addr, uint8 val) +{ + sim_debug (DEBUG_write, &RAM_dev, "RAM_put_mbyte: addr=%04X, val=%02X\n", addr, val); + if ((addr >= RAM_unit.u3) && ((uint32)addr < RAM_unit.u3 + RAM_unit.capac)) { + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &RAM_dev, "RAM_put_mbyte: Set XACK for %04X\n", addr); + *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF; + sim_debug (DEBUG_write, &RAM_dev, "\n"); + return; + } else { + sim_debug (DEBUG_write, &RAM_dev, " Out of range\n"); + return; + } +} + +/* end of iRAM8.c */ diff --git a/Intel-Systems/common/isbc064.c b/Intel-Systems/common/isbc064.c index 77959f5d..87ea71e5 100644 --- a/Intel-Systems/common/isbc064.c +++ b/Intel-Systems/common/isbc064.c @@ -1,174 +1,174 @@ -/* isbc064.c: Intel iSBC064 64K Byte Memory Card - - 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 base and size. - 24 Apr 15 -- Modified to use simh_debug - - NOTES: - - These functions support a simulated isbc016, isbc032, isbc048 and isbc064 - memory card on an Intel multibus system. -*/ - -#include "system_defs.h" - -#define SET_XACK(VAL) (xack = VAL) - -/* prototypes */ - -t_stat isbc064_reset (DEVICE *dptr); -uint8 isbc064_get_mbyte(uint16 addr); -void isbc064_put_mbyte(uint16 addr, uint8 val); - -extern uint8 xack; /* XACK signal */ - -/* isbc064 Standard I/O Data Structures */ - -UNIT isbc064_unit = { - UDATA (NULL, UNIT_FIX+UNIT_DISABLE+UNIT_BINK, 65536), KBD_POLL_WAIT -}; - -DEBTAB isbc064_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "XACK", DEBUG_xack }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE isbc064_dev = { - "SBC064", //name - &isbc064_unit, //units - NULL, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposite -// &isbc064_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags - 0, //dctrl - isbc064_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* iSBC064 globals */ - -/* Reset routine */ - -t_stat isbc064_reset (DEVICE *dptr) -{ - sim_debug (DEBUG_flow, &isbc064_dev, "isbc064_reset: "); - if ((isbc064_dev.flags & DEV_DIS) == 0) { - isbc064_unit.capac = SBC064_SIZE; - isbc064_unit.u3 = SBC064_BASE; - sim_printf("Initializing iSBC-064 RAM Board\n"); - sim_printf(" Available[%04X-%04XH]\n", - isbc064_unit.u3, - isbc064_unit.u3 + isbc064_unit.capac - 1); - } - if (isbc064_unit.filebuf == NULL) { - isbc064_unit.filebuf = (uint8 *)malloc(isbc064_unit.capac); - if (isbc064_unit.filebuf == NULL) { - sim_debug (DEBUG_flow, &isbc064_dev, "isbc064_reset: Malloc error\n"); - return SCPE_MEM; - } - } - sim_debug (DEBUG_flow, &isbc064_dev, "isbc064_reset: Done\n"); - return SCPE_OK; -} - -/* get a byte from memory */ - -uint8 isbc064_get_mbyte(uint16 addr) -{ - uint32 val, org, len; - - if ((isbc064_dev.flags & DEV_DIS) == 0) { - org = isbc064_unit.u3; - len = isbc064_unit.capac; - sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: addr=%04X", addr); - sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: org=%04X, len=%04X\n", org, len); - if ((addr >= org) && (addr < (org + len))) { - SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_xack, &isbc064_dev, "isbc064_get_mbyte: Set XACK for %04X\n", addr); - val = *((uint8 *)isbc064_unit.filebuf + (addr - org)); - sim_debug (DEBUG_read, &isbc064_dev, " val=%04X\n", val); -// sim_printf ("isbc064_get_mbyte: addr=%04X, val=%02X\n", addr, val); - return (val & 0xFF); - } else { - sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: Out of range\n"); - return 0; /* multibus has active high pullups and inversion */ - } - } - sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: Disabled\n"); -// sim_printf ("isbc064_get_mbyte: Disabled\n"); - return 0; /* multibus has active high pullups and inversion */ -} - -/* put a byte into memory */ - -void isbc064_put_mbyte(uint16 addr, uint8 val) -{ - uint32 org, len; - - if ((isbc064_dev.flags & DEV_DIS) == 0) { - org = isbc064_unit.u3; - len = isbc064_unit.capac; -// sim_printf ("isbc064_put_mbyte: addr=%04X, val=%02X\n", addr, val); - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: addr=%04X, val=%02X\n", addr, val); - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: org=%04X, len=%04X\n", org, len); - if ((addr >= org) && (addr < (org + len))) { - SET_XACK(1); /* good memory address */ - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Set XACK for %04X\n", addr); - *((uint8 *)isbc064_unit.filebuf + (addr - org)) = val & 0xFF; - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Return\n"); - return; - } else { - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Out of range\n"); - return; - } - } - sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Disabled\n"); -// sim_printf ("isbc064_put_mbyte: Disabled\n"); -} - -/* end of isbc064.c */ +/* isbc064.c: Intel iSBC064 64K Byte Memory Card + + 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 base and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + These functions support a simulated isbc016, isbc032, isbc048 and isbc064 + memory card on an Intel multibus system. +*/ + +#include "system_defs.h" + +#define SET_XACK(VAL) (xack = VAL) + +/* prototypes */ + +t_stat isbc064_reset (DEVICE *dptr); +uint8 isbc064_get_mbyte(uint16 addr); +void isbc064_put_mbyte(uint16 addr, uint8 val); + +extern uint8 xack; /* XACK signal */ + +/* isbc064 Standard I/O Data Structures */ + +UNIT isbc064_unit = { + UDATA (NULL, UNIT_FIX+UNIT_DISABLE+UNIT_BINK, 65536), KBD_POLL_WAIT +}; + +DEBTAB isbc064_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "XACK", DEBUG_xack }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE isbc064_dev = { + "SBC064", //name + &isbc064_unit, //units + NULL, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposite +// &isbc064_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG+DEV_DISABLE+DEV_DIS, //flags + 0, //dctrl + isbc064_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* iSBC064 globals */ + +/* Reset routine */ + +t_stat isbc064_reset (DEVICE *dptr) +{ + sim_debug (DEBUG_flow, &isbc064_dev, "isbc064_reset: "); + if ((isbc064_dev.flags & DEV_DIS) == 0) { + isbc064_unit.capac = SBC064_SIZE; + isbc064_unit.u3 = SBC064_BASE; + sim_printf("Initializing iSBC-064 RAM Board\n"); + sim_printf(" Available[%04X-%04XH]\n", + isbc064_unit.u3, + isbc064_unit.u3 + isbc064_unit.capac - 1); + } + if (isbc064_unit.filebuf == NULL) { + isbc064_unit.filebuf = (uint8 *)malloc(isbc064_unit.capac); + if (isbc064_unit.filebuf == NULL) { + sim_debug (DEBUG_flow, &isbc064_dev, "isbc064_reset: Malloc error\n"); + return SCPE_MEM; + } + } + sim_debug (DEBUG_flow, &isbc064_dev, "isbc064_reset: Done\n"); + return SCPE_OK; +} + +/* get a byte from memory */ + +uint8 isbc064_get_mbyte(uint16 addr) +{ + uint32 val, org, len; + + if ((isbc064_dev.flags & DEV_DIS) == 0) { + org = isbc064_unit.u3; + len = isbc064_unit.capac; + sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: addr=%04X", addr); + sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: org=%04X, len=%04X\n", org, len); + if ((addr >= org) && (addr < (org + len))) { + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_xack, &isbc064_dev, "isbc064_get_mbyte: Set XACK for %04X\n", addr); + val = *((uint8 *)isbc064_unit.filebuf + (addr - org)); + sim_debug (DEBUG_read, &isbc064_dev, " val=%04X\n", val); +// sim_printf ("isbc064_get_mbyte: addr=%04X, val=%02X\n", addr, val); + return (val & 0xFF); + } else { + sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: Out of range\n"); + return 0; /* multibus has active high pullups and inversion */ + } + } + sim_debug (DEBUG_read, &isbc064_dev, "isbc064_get_mbyte: Disabled\n"); +// sim_printf ("isbc064_get_mbyte: Disabled\n"); + return 0; /* multibus has active high pullups and inversion */ +} + +/* put a byte into memory */ + +void isbc064_put_mbyte(uint16 addr, uint8 val) +{ + uint32 org, len; + + if ((isbc064_dev.flags & DEV_DIS) == 0) { + org = isbc064_unit.u3; + len = isbc064_unit.capac; +// sim_printf ("isbc064_put_mbyte: addr=%04X, val=%02X\n", addr, val); + sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: addr=%04X, val=%02X\n", addr, val); + sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: org=%04X, len=%04X\n", org, len); + if ((addr >= org) && (addr < (org + len))) { + SET_XACK(1); /* good memory address */ + sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Set XACK for %04X\n", addr); + *((uint8 *)isbc064_unit.filebuf + (addr - org)) = val & 0xFF; + sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Return\n"); + return; + } else { + sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Out of range\n"); + return; + } + } + sim_debug (DEBUG_write, &isbc064_dev, "isbc064_put_mbyte: Disabled\n"); +// sim_printf ("isbc064_put_mbyte: Disabled\n"); +} + +/* end of isbc064.c */ diff --git a/Intel-Systems/common/isbc201.c b/Intel-Systems/common/isbc201.c index ddda85d0..afab5b05 100644 --- a/Intel-Systems/common/isbc201.c +++ b/Intel-Systems/common/isbc201.c @@ -185,8 +185,8 @@ /* external globals */ -extern uint16 port; //port called in dev_table[port] -extern int32 PCX; +extern uint16 port; //port called in dev_table[port] +extern int32 PCX; /* external function prototypes */ @@ -472,7 +472,7 @@ uint8 isbc2010(t_bool io, uint8 data) if (io == 0) { /* read ststus*/ if (DEBUG) sim_printf("\n isbc201-%d: 0x78 returned status=%02X PCX=%04X", - fdcnum, fdc201[fdcnum].stat, PCX); + fdcnum, fdc201[fdcnum].stat, PCX); return fdc201[fdcnum].stat; } } @@ -495,7 +495,7 @@ uint8 isbc2011(t_bool io, uint8 data) fdc201[fdcnum].iopb = data; if (DEBUG) sim_printf("\n isbc201-%d: 0x79 IOPB low=%02X PCX=%04X", - fdcnum, data, PCX); + fdcnum, data, PCX); } } return 0; @@ -527,12 +527,12 @@ uint8 isbc2013(t_bool io, uint8 data) if ((fdcnum = isbc201_get_dn()) != 0xFF) { if (io == 0) { /* read data port */ - if (fdc201[fdcnum].rtype == 0) { + if (fdc201[fdcnum].rtype == 0) { if (DEBUG) sim_printf("\n isbc201-%d: 0x7B returned rbyte0=%02X PCX=%04X", fdcnum, fdc201[fdcnum].rbyte0, PCX); return fdc201[fdcnum].rbyte0; - } else { + } else { if (fdc201[fdcnum].rdychg) { if (DEBUG) sim_printf("\n isbc201-%d: 0x7B returned rbyte1=%02X PCX=%04X", diff --git a/Intel-Systems/common/isbc202.c b/Intel-Systems/common/isbc202.c index 1602348a..8d183840 100644 --- a/Intel-Systems/common/isbc202.c +++ b/Intel-Systems/common/isbc202.c @@ -495,7 +495,7 @@ uint8 isbc2020(t_bool io, uint8 data) if (io == 0) { /* read ststus*/ if (DEBUG) sim_printf("\n isbc202-%d: 0x78 returned status=%02X PCX=%04X", - fdcnum, fdc202[fdcnum].stat, PCX); + fdcnum, fdc202[fdcnum].stat, PCX); return fdc202[fdcnum].stat; } } @@ -535,7 +535,7 @@ uint8 isbc2022(t_bool io, uint8 data) fdc202[fdcnum].iopb |= (data << 8); if (DEBUG) sim_printf("\n isbc202-%d: 0x7A IOPB=%04X PCX=%04X", - fdcnum, fdc202[fdcnum].iopb, PCX); + fdcnum, fdc202[fdcnum].iopb, PCX); isbc202_diskio(fdcnum); if (fdc202[fdcnum].intff) fdc202[fdcnum].stat |= FDCINT; @@ -550,12 +550,12 @@ uint8 isbc2023(t_bool io, uint8 data) if ((fdcnum = isbc202_get_dn()) != 0xFF) { if (io == 0) { /* read data port */ - if (fdc202[fdcnum].rtype == 0) { + if (fdc202[fdcnum].rtype == 0) { if (DEBUG) sim_printf("\n isbc202-%d: 0x7B returned rbyte0=%02X PCX=%04X", fdcnum, fdc202[fdcnum].rbyte0, PCX); return fdc202[fdcnum].rbyte0; - } else { + } else { if (fdc202[fdcnum].rdychg) { if (DEBUG) sim_printf("\n isbc202-%d: 0x7B returned rbyte1=%02X PCX=%04X", @@ -567,7 +567,7 @@ uint8 isbc2023(t_bool io, uint8 data) fdcnum, 0, PCX); return 0; } - } + } } else { /* write data port */ ; //stop diskette operation } diff --git a/Intel-Systems/common/pata.c b/Intel-Systems/common/pata.c index 0d68d4d9..4b08043d 100644 --- a/Intel-Systems/common/pata.c +++ b/Intel-Systems/common/pata.c @@ -1,193 +1,193 @@ -/* i8255.c: Intel i8255 PIO adapter - - Copyright (c) 2010, 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. - - These functions support a simulated i8255 interface device on an iSBC. - The device has threee physical 8-bit I/O ports which could be connected - to any parallel I/O device. - - All I/O is via programmed I/O. The i8255 has a control port (PIOS) - and three data ports (PIOA, PIOB, and PIOC). - - The simulated device supports a select from I/O space and two address lines. - The data ports are at the lower addresses and the control port is at - the highest. - - A write to the control port can configure the device: - - Control Word - +---+---+---+---+---+---+---+---+ - | D7 D6 D5 D4 D3 D2 D1 D0| - +---+---+---+---+---+---+---+---+ - - Group B - D0 Port C (lower) 1-Input, 0-Output - D1 Port B 1-Input, 0-Output - D2 Mode Selection 0-Mode 0, 1-Mode 1 - - Group A - D3 Port C (upper) 1-Input, 0-Output - D4 Port A 1-Input, 0-Output - D5-6 Mode Selection 00-Mode 0, 01-Mode 1, 1X-Mode 2 - - D7 Mode Set Flag 1=Active, 0=Bit Set - - Mode 0 - Basic Input/Output - Mode 1 - Strobed Input/Output - Mode 2 - Bidirectional Bus - - Bit Set - D7=0, D3:1 select port C bit, D0 1=set, 0=reset - - A read to the data ports gets the current port value, a write - to the data ports writes the character to the device. - - ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. -*/ - -#include "system_defs.h" - -extern int32 reg_dev(int32 (*routine)(int32, int32), int32 port); - -/* function prototypes */ - -t_stat pata_reset (DEVICE *dptr, int32 base); - -/* i8255 Standard I/O Data Structures */ - -UNIT pata_unit[] = { - { UDATA (0, 0, 0) } -}; - -REG pata_reg[] = { - { HRDATA (CONTROL0, pata_unit[0].u3, 8) }, - { HRDATA (PORTA0, pata_unit[0].u4, 8) }, - { HRDATA (PORTB0, pata_unit[0].u5, 8) }, - { HRDATA (PORTC0, pata_unit[0].u6, 8) }, - { NULL } -}; - -DEVICE pata_dev = { - "PATA", //name - pata_unit, //units - pata_reg, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 32, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit -// &pata_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - 0, //flags - 0, //dctrl - NULL, //debflags - NULL, //msize - NULL //lname -}; - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. -*/ - -int32 patas(int32 io, int32 data) -{ - int32 bit; - - if (io == 0) { /* read status port */ - return pata_unit[0].u3; - } else { /* write status port */ - if (data & 0x80) { /* mode instruction */ - pata_unit[0].u3 = data; - sim_printf("PATA: 8255 Mode Instruction=%02X\n", data); - if (data & 0x64) - sim_printf(" Mode 1 and 2 not yet implemented\n"); - } else { /* bit set */ - bit = (data & 0x0E) >> 1; /* get bit number */ - if (data & 0x01) { /* set bit */ - pata_unit[0].u6 |= (0x01 << bit); - } else { /* reset bit */ - pata_unit[0].u6 &= ~(0x01 << bit); - } - } - } - return 0; -} - -int32 pataa(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (pata_unit[0].u4); - } else { /* write data port */ - pata_unit[0].u4 = data; - sim_printf("PATA: 8255 Port A = %02X\n", data); - } - return 0; -} - -int32 patab(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (pata_unit[0].u5); - } else { /* write data port */ - pata_unit[0].u5 = data; - sim_printf("PATA: 8255 Port B = %02X\n", data); - } - return 0; -} - -int32 patac(int32 io, int32 data) -{ - if (io == 0) { /* read data port */ - return (pata_unit[0].u6); - } else { /* write data port */ - pata_unit[0].u6 = data; - sim_printf("PATA: 8255 Port C = %02X\n", data); - } - return 0; -} - -/* Reset routine */ - -t_stat pata_reset (DEVICE *dptr, int32 base) -{ - pata_unit[0].u3 = 0x9B; /* control */ - pata_unit[0].u4 = 0xFF; /* Port A */ - pata_unit[0].u5 = 0xFF; /* Port B */ - pata_unit[0].u6 = 0xFF; /* Port C */ - reg_dev(pataa, base); - reg_dev(patab, base + 1); - reg_dev(patac, base + 2); - reg_dev(patas, base + 3); - sim_printf(" PATA: Reset\n"); - return SCPE_OK; -} - +/* i8255.c: Intel i8255 PIO adapter + + Copyright (c) 2010, 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. + + These functions support a simulated i8255 interface device on an iSBC. + The device has threee physical 8-bit I/O ports which could be connected + to any parallel I/O device. + + All I/O is via programmed I/O. The i8255 has a control port (PIOS) + and three data ports (PIOA, PIOB, and PIOC). + + The simulated device supports a select from I/O space and two address lines. + The data ports are at the lower addresses and the control port is at + the highest. + + A write to the control port can configure the device: + + Control Word + +---+---+---+---+---+---+---+---+ + | D7 D6 D5 D4 D3 D2 D1 D0| + +---+---+---+---+---+---+---+---+ + + Group B + D0 Port C (lower) 1-Input, 0-Output + D1 Port B 1-Input, 0-Output + D2 Mode Selection 0-Mode 0, 1-Mode 1 + + Group A + D3 Port C (upper) 1-Input, 0-Output + D4 Port A 1-Input, 0-Output + D5-6 Mode Selection 00-Mode 0, 01-Mode 1, 1X-Mode 2 + + D7 Mode Set Flag 1=Active, 0=Bit Set + + Mode 0 - Basic Input/Output + Mode 1 - Strobed Input/Output + Mode 2 - Bidirectional Bus + + Bit Set - D7=0, D3:1 select port C bit, D0 1=set, 0=reset + + A read to the data ports gets the current port value, a write + to the data ports writes the character to the device. + + ?? ??? 10 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. +*/ + +#include "system_defs.h" + +extern int32 reg_dev(int32 (*routine)(int32, int32), int32 port); + +/* function prototypes */ + +t_stat pata_reset (DEVICE *dptr, int32 base); + +/* i8255 Standard I/O Data Structures */ + +UNIT pata_unit[] = { + { UDATA (0, 0, 0) } +}; + +REG pata_reg[] = { + { HRDATA (CONTROL0, pata_unit[0].u3, 8) }, + { HRDATA (PORTA0, pata_unit[0].u4, 8) }, + { HRDATA (PORTB0, pata_unit[0].u5, 8) }, + { HRDATA (PORTC0, pata_unit[0].u6, 8) }, + { NULL } +}; + +DEVICE pata_dev = { + "PATA", //name + pata_unit, //units + pata_reg, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 32, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit +// &pata_reset, //reset + NULL, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + 0, //flags + 0, //dctrl + NULL, //debflags + NULL, //msize + NULL //lname +}; + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + +int32 patas(int32 io, int32 data) +{ + int32 bit; + + if (io == 0) { /* read status port */ + return pata_unit[0].u3; + } else { /* write status port */ + if (data & 0x80) { /* mode instruction */ + pata_unit[0].u3 = data; + sim_printf("PATA: 8255 Mode Instruction=%02X\n", data); + if (data & 0x64) + sim_printf(" Mode 1 and 2 not yet implemented\n"); + } else { /* bit set */ + bit = (data & 0x0E) >> 1; /* get bit number */ + if (data & 0x01) { /* set bit */ + pata_unit[0].u6 |= (0x01 << bit); + } else { /* reset bit */ + pata_unit[0].u6 &= ~(0x01 << bit); + } + } + } + return 0; +} + +int32 pataa(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + return (pata_unit[0].u4); + } else { /* write data port */ + pata_unit[0].u4 = data; + sim_printf("PATA: 8255 Port A = %02X\n", data); + } + return 0; +} + +int32 patab(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + return (pata_unit[0].u5); + } else { /* write data port */ + pata_unit[0].u5 = data; + sim_printf("PATA: 8255 Port B = %02X\n", data); + } + return 0; +} + +int32 patac(int32 io, int32 data) +{ + if (io == 0) { /* read data port */ + return (pata_unit[0].u6); + } else { /* write data port */ + pata_unit[0].u6 = data; + sim_printf("PATA: 8255 Port C = %02X\n", data); + } + return 0; +} + +/* Reset routine */ + +t_stat pata_reset (DEVICE *dptr, int32 base) +{ + pata_unit[0].u3 = 0x9B; /* control */ + pata_unit[0].u4 = 0xFF; /* Port A */ + pata_unit[0].u5 = 0xFF; /* Port B */ + pata_unit[0].u6 = 0xFF; /* Port C */ + reg_dev(pataa, base); + reg_dev(patab, base + 1); + reg_dev(patac, base + 2); + reg_dev(patas, base + 3); + sim_printf(" PATA: Reset\n"); + return SCPE_OK; +} + diff --git a/Intel-Systems/common/zx200a.c b/Intel-Systems/common/zx200a.c index e9043913..cfaa131d 100644 --- a/Intel-Systems/common/zx200a.c +++ b/Intel-Systems/common/zx200a.c @@ -520,7 +520,7 @@ uint8 zx200a0(t_bool io, uint8 data) if (io == 0) { /* read ststus*/ if (DEBUG) sim_printf("\n zx-200a0-%d: 0x78/88 returned status=%02X PCX=%04X", - fdcnum, zx200a[fdcnum].stat, PCX); + fdcnum, zx200a[fdcnum].stat, PCX); return zx200a[fdcnum].stat; } } @@ -560,7 +560,7 @@ uint8 zx200a2(t_bool io, uint8 data) zx200a[fdcnum].iopb |= (data << 8); if (DEBUG) sim_printf("\n zx-200a2-%d: 0x7A/8A IOPB=%04X PCX=%04X", - fdcnum, zx200a[fdcnum].iopb, PCX); + fdcnum, zx200a[fdcnum].iopb, PCX); zx200a_diskio(fdcnum); if (zx200a[fdcnum].intff) zx200a[fdcnum].stat |= FDCINT; @@ -575,12 +575,12 @@ uint8 zx200a3(t_bool io, uint8 data) if ((fdcnum = zx200_get_dn()) != 0xFF) { if (io == 0) { /* read data port */ - if (zx200a[fdcnum].rtype == 0) { + if (zx200a[fdcnum].rtype == 0) { if (DEBUG) sim_printf("\n zx200a3-%d: 0x7B/8B returned rbyte0=%02X PCX=%04X", fdcnum, zx200a[fdcnum].rbyte0, PCX); return zx200a[fdcnum].rbyte0; - } else { + } else { if (zx200a[fdcnum].rdychg) { if (DEBUG) sim_printf("\n zx200a3-%d: 0x7B/8B returned rbyte1=%02X PCX=%04X", @@ -592,7 +592,7 @@ uint8 zx200a3(t_bool io, uint8 data) fdcnum, 0, PCX); return 0; } - } + } } else { /* write data port */ ; //stop diskette operation } diff --git a/Intel-Systems/imds-225/imds-225_sys.c b/Intel-Systems/imds-225/imds-225_sys.c index b12fdfa6..6a77f530 100644 --- a/Intel-Systems/imds-225/imds-225_sys.c +++ b/Intel-Systems/imds-225/imds-225_sys.c @@ -1,85 +1,85 @@ -/* mds225_sys.c: multibus system interface - - Copyright (c) 2010, 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. - - 07 Jun 16 - Original file. -*/ - -#include "system_defs.h" - -extern DEVICE i8080_dev; -extern REG i8080_reg[]; -extern DEVICE i8251_dev; -extern DEVICE i8253_dev; -extern DEVICE i8255_dev; -extern DEVICE i8259_dev; -extern DEVICE EPROM_dev; -extern DEVICE RAM_dev; -extern DEVICE ipc_cont_dev; -extern DEVICE multibus_dev; -extern DEVICE isbc201_dev; -extern DEVICE isbc202_dev; -extern DEVICE zx200a_dev; - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages -*/ - -char sim_name[] = "Intel MDS-225"; - -REG *sim_PC = &i8080_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &i8080_dev, - &EPROM_dev, - &RAM_dev, - &i8251_dev, - &i8253_dev, - &i8255_dev, - &i8259_dev, - &ipc_cont_dev, - &multibus_dev, - &isbc201_dev, - &isbc202_dev, - &zx200a_dev, - NULL -}; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode", - "Invalid Memory", - "XACK Error" -}; - +/* mds225_sys.c: multibus system interface + + Copyright (c) 2010, 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. + + 07 Jun 16 - Original file. +*/ + +#include "system_defs.h" + +extern DEVICE i8080_dev; +extern REG i8080_reg[]; +extern DEVICE i8251_dev; +extern DEVICE i8253_dev; +extern DEVICE i8255_dev; +extern DEVICE i8259_dev; +extern DEVICE EPROM_dev; +extern DEVICE RAM_dev; +extern DEVICE ipc_cont_dev; +extern DEVICE multibus_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE zx200a_dev; + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "Intel MDS-225"; + +REG *sim_PC = &i8080_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8080_dev, + &EPROM_dev, + &RAM_dev, + &i8251_dev, + &i8253_dev, + &i8255_dev, + &i8259_dev, + &ipc_cont_dev, + &multibus_dev, + &isbc201_dev, + &isbc202_dev, + &zx200a_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error" +}; + diff --git a/Intel-Systems/imds-225/ipc.c b/Intel-Systems/imds-225/ipc.c index dd12363f..b20a1b3e 100644 --- a/Intel-Systems/imds-225/ipc.c +++ b/Intel-Systems/imds-225/ipc.c @@ -1,148 +1,148 @@ -/* ipc.c: Intel IPC Processor simulator - - Copyright (c) 2010, 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. - - This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus - Computer Systems. - - 07 Jun 16 - Original file. -*/ - -#include "system_defs.h" - -/* function prototypes */ - -uint8 get_mbyte(uint16 addr); -uint16 get_mword(uint16 addr); -void put_mbyte(uint16 addr, uint8 val); -void put_mword(uint16 addr, uint16 val); -t_stat SBC_reset (DEVICE *dptr); - -/* external function prototypes */ - -extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -//extern uint8 multibus_get_mbyte(uint16 addr); -//extern void multibus_put_mbyte(uint16 addr, uint8 val); -extern uint8 EPROM_get_mbyte(uint16 addr); -extern uint8 RAM_get_mbyte(uint16 addr); -extern void RAM_put_mbyte(uint16 addr, uint8 val); -extern UNIT i8255_unit; -extern UNIT EPROM_unit; -extern UNIT RAM_unit; -extern UNIT ipc_cont_unit; -extern UNIT ioc_cont_unit; -extern int32 i8251_devnum; -extern t_stat i8251_reset(DEVICE *dptr, uint16 base); -extern int32 i8253_devnum; -extern t_stat i8253_reset(DEVICE *dptr, uint16 base); -extern int32 i8255_devnum; -extern t_stat i8255_reset(DEVICE *dptr, uint16 base); -extern int32 i8259_devnum; -extern t_stat i8259_reset(DEVICE *dptr, uint16 base); -extern t_stat EPROM_reset(DEVICE *dptr, uint16 size); -extern t_stat RAM_reset(DEVICE *dptr, uint16 base, uint16 size); -extern t_stat ipc_cont_reset(DEVICE *dptr, uint16 base); -extern t_stat ioc_cont_reset(DEVICE *dptr, uint16 base); -extern uint32 PCX; /* program counter */ - -/* CPU reset routine - put here to cause a reset of the entire IPC system */ - -t_stat SBC_reset (DEVICE *dptr) -{ - sim_printf("Initializing MDS-225\n Onboard Devices:\n"); - i8080_reset(NULL); - i8251_devnum = 0; - i8251_reset(NULL, I8251_BASE_0); - i8251_reset(NULL, I8251_BASE_1); - i8253_devnum = 0; - i8253_reset(NULL, I8253_BASE); - i8255_devnum = 0; - i8255_reset(NULL, I8255_BASE_0); - i8255_reset(NULL, I8255_BASE_1); - i8259_devnum = 0; - i8259_reset(NULL, I8259_BASE_0); - i8259_reset(NULL, I8259_BASE_1); - EPROM_reset(NULL, ROM_SIZE); - RAM_reset(NULL, RAM_BASE, RAM_SIZE); - ipc_cont_reset(NULL, ICONT_BASE); - ioc_cont_reset(NULL, DBB_BASE); - return SCPE_OK; -} - -/* get a byte from memory - handle RAM, ROM and Multibus memory */ - -uint8 get_mbyte(uint16 addr) -{ - if (addr >= 0xF800) { //monitor ROM - always there - return EPROM_get_mbyte(addr - 0xF000); //top half of EPROM - } - if ((addr < 0x1000) && ((ipc_cont_unit.u3 & 0x04) == 0)) { //startup - return EPROM_get_mbyte(addr); - } - if ((addr >= 0xE800) && (addr < 0xF000) && ((ipc_cont_unit.u3 & 0x10) == 0)) { //diagnostic ROM - return EPROM_get_mbyte(addr - 0xE800); - } - return RAM_get_mbyte(addr); -} - -/* get a word from memory */ - -uint16 get_mword(uint16 addr) -{ - uint16 val; - - val = get_mbyte(addr); - val |= (get_mbyte(addr+1) << 8); - return val; -} - -/* put a byte to memory - handle RAM, ROM and Multibus memory */ - -void put_mbyte(uint16 addr, uint8 val) -{ - if (addr >= 0xF800) { //monitor ROM - always there - sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX); - return; - } - if ((addr < 0x1000) && ((ipc_cont_unit.u3 & 0x04) == 0)) { //startup - sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX); - return; - } - if ((addr >= 0xE800) && (addr < 0xF000) && ((ipc_cont_unit.u3 & 0x10) == 0)) { //diagnostic ROM - sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX); - return; - } - RAM_put_mbyte(addr, val); -} - -/* put a word to memory */ - -void put_mword(uint16 addr, uint16 val) -{ - put_mbyte(addr, val & 0xff); - put_mbyte(addr+1, val >> 8); -} - -/* end of ipc.c */ +/* ipc.c: Intel IPC Processor simulator + + Copyright (c) 2010, 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. + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. + + 07 Jun 16 - Original file. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +uint8 get_mbyte(uint16 addr); +uint16 get_mword(uint16 addr); +void put_mbyte(uint16 addr, uint8 val); +void put_mword(uint16 addr, uint16 val); +t_stat SBC_reset (DEVICE *dptr); + +/* external function prototypes */ + +extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ +//extern uint8 multibus_get_mbyte(uint16 addr); +//extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern uint8 EPROM_get_mbyte(uint16 addr); +extern uint8 RAM_get_mbyte(uint16 addr); +extern void RAM_put_mbyte(uint16 addr, uint8 val); +extern UNIT i8255_unit; +extern UNIT EPROM_unit; +extern UNIT RAM_unit; +extern UNIT ipc_cont_unit; +extern UNIT ioc_cont_unit; +extern int32 i8251_devnum; +extern t_stat i8251_reset(DEVICE *dptr, uint16 base); +extern int32 i8253_devnum; +extern t_stat i8253_reset(DEVICE *dptr, uint16 base); +extern int32 i8255_devnum; +extern t_stat i8255_reset(DEVICE *dptr, uint16 base); +extern int32 i8259_devnum; +extern t_stat i8259_reset(DEVICE *dptr, uint16 base); +extern t_stat EPROM_reset(DEVICE *dptr, uint16 size); +extern t_stat RAM_reset(DEVICE *dptr, uint16 base, uint16 size); +extern t_stat ipc_cont_reset(DEVICE *dptr, uint16 base); +extern t_stat ioc_cont_reset(DEVICE *dptr, uint16 base); +extern uint32 PCX; /* program counter */ + +/* CPU reset routine + put here to cause a reset of the entire IPC system */ + +t_stat SBC_reset (DEVICE *dptr) +{ + sim_printf("Initializing MDS-225\n Onboard Devices:\n"); + i8080_reset(NULL); + i8251_devnum = 0; + i8251_reset(NULL, I8251_BASE_0); + i8251_reset(NULL, I8251_BASE_1); + i8253_devnum = 0; + i8253_reset(NULL, I8253_BASE); + i8255_devnum = 0; + i8255_reset(NULL, I8255_BASE_0); + i8255_reset(NULL, I8255_BASE_1); + i8259_devnum = 0; + i8259_reset(NULL, I8259_BASE_0); + i8259_reset(NULL, I8259_BASE_1); + EPROM_reset(NULL, ROM_SIZE); + RAM_reset(NULL, RAM_BASE, RAM_SIZE); + ipc_cont_reset(NULL, ICONT_BASE); + ioc_cont_reset(NULL, DBB_BASE); + return SCPE_OK; +} + +/* get a byte from memory - handle RAM, ROM and Multibus memory */ + +uint8 get_mbyte(uint16 addr) +{ + if (addr >= 0xF800) { //monitor ROM - always there + return EPROM_get_mbyte(addr - 0xF000); //top half of EPROM + } + if ((addr < 0x1000) && ((ipc_cont_unit.u3 & 0x04) == 0)) { //startup + return EPROM_get_mbyte(addr); + } + if ((addr >= 0xE800) && (addr < 0xF000) && ((ipc_cont_unit.u3 & 0x10) == 0)) { //diagnostic ROM + return EPROM_get_mbyte(addr - 0xE800); + } + return RAM_get_mbyte(addr); +} + +/* get a word from memory */ + +uint16 get_mword(uint16 addr) +{ + uint16 val; + + val = get_mbyte(addr); + val |= (get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory - handle RAM, ROM and Multibus memory */ + +void put_mbyte(uint16 addr, uint8 val) +{ + if (addr >= 0xF800) { //monitor ROM - always there + sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX); + return; + } + if ((addr < 0x1000) && ((ipc_cont_unit.u3 & 0x04) == 0)) { //startup + sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX); + return; + } + if ((addr >= 0xE800) && (addr < 0xF000) && ((ipc_cont_unit.u3 & 0x10) == 0)) { //diagnostic ROM + sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX); + return; + } + RAM_put_mbyte(addr, val); +} + +/* put a word to memory */ + +void put_mword(uint16 addr, uint16 val) +{ + put_mbyte(addr, val & 0xff); + put_mbyte(addr+1, val >> 8); +} + +/* end of ipc.c */ diff --git a/Intel-Systems/imds-225/system_defs.h b/Intel-Systems/imds-225/system_defs.h index 0e50e0d8..4ca3cf22 100644 --- a/Intel-Systems/imds-225/system_defs.h +++ b/Intel-Systems/imds-225/system_defs.h @@ -1,140 +1,140 @@ -/* system_defs.h: Intel iSBC simulator definitions - - Copyright (c) 2010, 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. - - ?? ??? 10 - Original file. -*/ - -#include -#include -#include "sim_defs.h" /* simulator defns */ - -#define IPC 0 -#define SET_XACK(VAL) (xack = VAL) - -/* set the base for the DBB ports */ -#define DBB_BASE 0xC0 - -/* set the base I/O address for the 8255 */ -#define I8255_BASE_0 0xE4 -#define I8255_BASE_1 0xE8 -#define I8255_NUM 2 - -/* set the base I/O address for the 8253 */ -#define I8253_BASE 0xF0 -#define I8253_NUM 1 - -/* set the base I/O address for the 8251 */ -#define I8251_BASE_0 0xF4 -#define I8251_BASE_1 0xF6 -#define I8251_NUM 2 - -/* set the base I/O address for the 8259 */ -#define I8259_BASE_0 0xFA -#define I8259_BASE_1 0xFC -#define I8259_NUM 2 - -/* set the base I/O address for the IPC control port */ -#define ICONT_BASE 0xFF - -/* set the base and size for the EPROM on the MDS 225 */ -#define ROM_BASE 0x0000 -#define ROM_SIZE 0x1000 -#define ROM_DISABLE 1 - -/* set the base and size for the RAM on the MDS 225 */ -#define RAM_BASE 0x0000 -#define RAM_SIZE 0xF800 - -//board definitions for the multibus -/* set the base I/O address for the iSBC 201 */ -#define SBC201_BASE 0x88 -#define SBC201_INT INT_1 -#define SBC201_NUM 0 - -/* set the base I/O address for the iSBC 202 */ -#define SBC202_BASE 0x78 -#define SBC202_INT INT_1 -#define SBC202_NUM 1 - -/* set the base I/O address for the iSBC 208 */ -#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_DD 0x78 -#define ZX200A_BASE_SD 0x88 -#define ZX200A_NUM 0 - -/* set INTR for CPU */ -#define INTR INT_1 - -/* multibus interrupt definitions */ - -#define INT_0 0x01 -#define INT_1 0x02 -#define INT_2 0x04 -#define INT_3 0x08 -#define INT_4 0x10 -#define INT_5 0x20 -#define INT_6 0x40 -#define INT_7 0x80 - -/* CPU interrupts definitions */ - -#define INT_R 0x200 -#define I75 0x40 -#define I65 0x20 -#define I55 0x10 - -/* Memory */ - -#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ -#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* debug definitions */ - -#define DEBUG_flow 0x0001 -#define DEBUG_read 0x0002 -#define DEBUG_write 0x0004 -#define DEBUG_level1 0x0008 -#define DEBUG_level2 0x0010 -#define DEBUG_reg 0x0020 -#define DEBUG_asm 0x0040 -#define DEBUG_xack 0x0080 -#define DEBUG_all 0xFFFF - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_OPCODE 4 /* Invalid Opcode */ -#define STOP_IO 5 /* I/O error */ -#define STOP_MEM 6 /* Memory error */ -#define STOP_XACK 7 /* XACK error */ - +/* system_defs.h: Intel iSBC simulator definitions + + Copyright (c) 2010, 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. + + ?? ??? 10 - Original file. +*/ + +#include +#include +#include "sim_defs.h" /* simulator defns */ + +#define IPC 0 +#define SET_XACK(VAL) (xack = VAL) + +/* set the base for the DBB ports */ +#define DBB_BASE 0xC0 + +/* set the base I/O address for the 8255 */ +#define I8255_BASE_0 0xE4 +#define I8255_BASE_1 0xE8 +#define I8255_NUM 2 + +/* set the base I/O address for the 8253 */ +#define I8253_BASE 0xF0 +#define I8253_NUM 1 + +/* set the base I/O address for the 8251 */ +#define I8251_BASE_0 0xF4 +#define I8251_BASE_1 0xF6 +#define I8251_NUM 2 + +/* set the base I/O address for the 8259 */ +#define I8259_BASE_0 0xFA +#define I8259_BASE_1 0xFC +#define I8259_NUM 2 + +/* set the base I/O address for the IPC control port */ +#define ICONT_BASE 0xFF + +/* set the base and size for the EPROM on the MDS 225 */ +#define ROM_BASE 0x0000 +#define ROM_SIZE 0x1000 +#define ROM_DISABLE 1 + +/* set the base and size for the RAM on the MDS 225 */ +#define RAM_BASE 0x0000 +#define RAM_SIZE 0xF800 + +//board definitions for the multibus +/* set the base I/O address for the iSBC 201 */ +#define SBC201_BASE 0x88 +#define SBC201_INT INT_1 +#define SBC201_NUM 0 + +/* set the base I/O address for the iSBC 202 */ +#define SBC202_BASE 0x78 +#define SBC202_INT INT_1 +#define SBC202_NUM 1 + +/* set the base I/O address for the iSBC 208 */ +#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_DD 0x78 +#define ZX200A_BASE_SD 0x88 +#define ZX200A_NUM 0 + +/* set INTR for CPU */ +#define INTR INT_1 + +/* multibus interrupt definitions */ + +#define INT_0 0x01 +#define INT_1 0x02 +#define INT_2 0x04 +#define INT_3 0x08 +#define INT_4 0x10 +#define INT_5 0x20 +#define INT_6 0x40 +#define INT_7 0x80 + +/* CPU interrupts definitions */ + +#define INT_R 0x200 +#define I75 0x40 +#define I65 0x20 +#define I55 0x10 + +/* Memory */ + +#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ +#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ +#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) + +/* debug definitions */ + +#define DEBUG_flow 0x0001 +#define DEBUG_read 0x0002 +#define DEBUG_write 0x0004 +#define DEBUG_level1 0x0008 +#define DEBUG_level2 0x0010 +#define DEBUG_reg 0x0020 +#define DEBUG_asm 0x0040 +#define DEBUG_xack 0x0080 +#define DEBUG_all 0xFFFF + +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_OPCODE 4 /* Invalid Opcode */ +#define STOP_IO 5 /* I/O error */ +#define STOP_MEM 6 /* Memory error */ +#define STOP_XACK 7 /* XACK error */ + diff --git a/Intel-Systems/isys8010/isbc8010.c b/Intel-Systems/isys8010/isbc8010.c index 189c2b6f..78f04246 100644 --- a/Intel-Systems/isys8010/isbc8010.c +++ b/Intel-Systems/isys8010/isbc8010.c @@ -1,141 +1,141 @@ -/* iSBC80-10.c: Intel iSBC 80/10 Processor simulator - - Copyright (c) 2010, 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: - - ?? ??? 10 - Original file. - 24 Apr 15 -- Modified to use simh_debug - - NOTES: - - This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus - Computer Systems. -*/ - -#include "system_defs.h" - -/* function prototypes */ - -uint8 get_mbyte(uint16 addr); -uint16 get_mword(uint16 addr); -void put_mbyte(uint16 addr, uint8 val); -void put_mword(uint16 addr, uint16 val); -t_stat SBC_reset (DEVICE *dptr); - -/* external globals */ - -extern uint8 i8255_C[4]; //port C byte I/O - -/* external function prototypes */ - -extern uint8 multibus_get_mbyte(uint16 addr); -extern void multibus_put_mbyte(uint16 addr, uint8 val); -extern uint8 EPROM_get_mbyte(uint16 addr); -extern uint8 RAM_get_mbyte(uint16 addr); -extern void RAM_put_mbyte(uint16 addr, uint8 val); -extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -extern int32 i8251_devnum; -extern t_stat i8251_reset (DEVICE *dptr, uint16 base); -extern int32 i8255_devnum; -extern t_stat i8255_reset (DEVICE *dptr, uint16 base); -extern UNIT EPROM_unit; -extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); -extern UNIT RAM_unit; -extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); - -/* SBC reset routine */ - -t_stat SBC_reset (DEVICE *dptr) -{ - sim_printf("Initializing iSBC-80/10 SBC\n Onboard Devices:\n"); - i8080_reset (NULL); - i8251_devnum = 0; - i8251_reset (NULL, I8251_BASE); - i8255_devnum = 0; - i8255_reset (NULL, I8255_BASE_0); - i8255_reset (NULL, I8255_BASE_1); - EPROM_reset (NULL, ROM_SIZE); - RAM_reset (NULL, RAM_BASE, RAM_SIZE); - return SCPE_OK; -} - -/* get a byte from memory - handle RAM, ROM, I/O, and Multibus memory */ - -uint8 get_mbyte(uint16 addr) -{ - /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ - if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { - return EPROM_get_mbyte(addr); - } - } /* if local RAM handle it */ - if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ - if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { - return RAM_get_mbyte(addr); - } - } /* otherwise, try the multibus */ - return multibus_get_mbyte(addr); -} - -/* get a word from memory */ - -uint16 get_mword(uint16 addr) -{ - uint16 val; - - val = get_mbyte(addr); - val |= (get_mbyte(addr+1) << 8); - return val; -} - -/* put a byte to memory - handle RAM, ROM, I/O, and Multibus memory */ - -void put_mbyte(uint16 addr, uint8 val) -{ - /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ - if ((addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { - sim_printf("Write to R/O memory address %04X - ignored\n", addr); - return; - } - } /* if local RAM handle it */ - if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ - if ((addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { - RAM_put_mbyte(addr, val); - return; - } - } /* otherwise, try the multibus */ - multibus_put_mbyte(addr, val); -} - -/* put a word to memory */ - -void put_mword(uint16 addr, uint16 val) -{ - put_mbyte(addr, val & 0xff); - put_mbyte(addr+1, val >> 8); -} - -/* end of iSBC80-10.c */ +/* iSBC80-10.c: Intel iSBC 80/10 Processor simulator + + Copyright (c) 2010, 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: + + ?? ??? 10 - Original file. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +uint8 get_mbyte(uint16 addr); +uint16 get_mword(uint16 addr); +void put_mbyte(uint16 addr, uint8 val); +void put_mword(uint16 addr, uint16 val); +t_stat SBC_reset (DEVICE *dptr); + +/* external globals */ + +extern uint8 i8255_C[4]; //port C byte I/O + +/* external function prototypes */ + +extern uint8 multibus_get_mbyte(uint16 addr); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern uint8 EPROM_get_mbyte(uint16 addr); +extern uint8 RAM_get_mbyte(uint16 addr); +extern void RAM_put_mbyte(uint16 addr, uint8 val); +extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ +extern int32 i8251_devnum; +extern t_stat i8251_reset (DEVICE *dptr, uint16 base); +extern int32 i8255_devnum; +extern t_stat i8255_reset (DEVICE *dptr, uint16 base); +extern UNIT EPROM_unit; +extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); +extern UNIT RAM_unit; +extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); + +/* SBC reset routine */ + +t_stat SBC_reset (DEVICE *dptr) +{ + sim_printf("Initializing iSBC-80/10 SBC\n Onboard Devices:\n"); + i8080_reset (NULL); + i8251_devnum = 0; + i8251_reset (NULL, I8251_BASE); + i8255_devnum = 0; + i8255_reset (NULL, I8255_BASE_0); + i8255_reset (NULL, I8255_BASE_1); + EPROM_reset (NULL, ROM_SIZE); + RAM_reset (NULL, RAM_BASE, RAM_SIZE); + return SCPE_OK; +} + +/* get a byte from memory - handle RAM, ROM, I/O, and Multibus memory */ + +uint8 get_mbyte(uint16 addr) +{ + /* if local EPROM handle it */ + if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { + return EPROM_get_mbyte(addr); + } + } /* if local RAM handle it */ + if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { + return RAM_get_mbyte(addr); + } + } /* otherwise, try the multibus */ + return multibus_get_mbyte(addr); +} + +/* get a word from memory */ + +uint16 get_mword(uint16 addr) +{ + uint16 val; + + val = get_mbyte(addr); + val |= (get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory - handle RAM, ROM, I/O, and Multibus memory */ + +void put_mbyte(uint16 addr, uint8 val) +{ + /* if local EPROM handle it */ + if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { + sim_printf("Write to R/O memory address %04X - ignored\n", addr); + return; + } + } /* if local RAM handle it */ + if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { + RAM_put_mbyte(addr, val); + return; + } + } /* otherwise, try the multibus */ + multibus_put_mbyte(addr, val); +} + +/* put a word to memory */ + +void put_mword(uint16 addr, uint16 val) +{ + put_mbyte(addr, val & 0xff); + put_mbyte(addr+1, val >> 8); +} + +/* end of iSBC80-10.c */ diff --git a/Intel-Systems/isys8010/isys8010_sys.c b/Intel-Systems/isys8010/isys8010_sys.c index a33e1f19..6d5247ee 100644 --- a/Intel-Systems/isys8010/isys8010_sys.c +++ b/Intel-Systems/isys8010/isys8010_sys.c @@ -1,82 +1,82 @@ -/* sys-8010_sys.c: multibus system interface - - Copyright (c) 2010, 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. - - ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. -*/ - -#include "system_defs.h" - -extern DEVICE i8080_dev; -extern REG i8080_reg[]; -extern DEVICE i8251_dev; -extern DEVICE i8255_dev; -extern DEVICE EPROM_dev; -extern DEVICE RAM_dev; -extern DEVICE multibus_dev; -extern DEVICE isbc201_dev; -extern DEVICE isbc202_dev; -extern DEVICE zx200a_dev; -extern DEVICE isbc064_dev; - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages -*/ - -char sim_name[] = "Intel System 80/10"; - -REG *sim_PC = &i8080_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &i8080_dev, - &EPROM_dev, - &RAM_dev, - &i8251_dev, - &i8255_dev, - &multibus_dev, - &isbc064_dev, - &isbc201_dev, - &isbc202_dev, - &zx200a_dev, - NULL -}; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode", - "Invalid Memory", - "XACK Error" -}; - +/* sys-8010_sys.c: multibus system interface + + Copyright (c) 2010, 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. + + ?? ??? 10 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. +*/ + +#include "system_defs.h" + +extern DEVICE i8080_dev; +extern REG i8080_reg[]; +extern DEVICE i8251_dev; +extern DEVICE i8255_dev; +extern DEVICE EPROM_dev; +extern DEVICE RAM_dev; +extern DEVICE multibus_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE zx200a_dev; +extern DEVICE isbc064_dev; + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "Intel System 80/10"; + +REG *sim_PC = &i8080_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8080_dev, + &EPROM_dev, + &RAM_dev, + &i8251_dev, + &i8255_dev, + &multibus_dev, + &isbc064_dev, + &isbc201_dev, + &isbc202_dev, + &zx200a_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error" +}; + diff --git a/Intel-Systems/isys8010/system_defs.h b/Intel-Systems/isys8010/system_defs.h index 5a4a4ae4..c143e10d 100644 --- a/Intel-Systems/isys8010/system_defs.h +++ b/Intel-Systems/isys8010/system_defs.h @@ -28,7 +28,7 @@ #include #include -#include "sim_defs.h" /* simulator defns */ +#include "sim_defs.h" /* simulator defns */ #define SET_XACK(VAL) (xack = VAL) @@ -57,17 +57,17 @@ //board definitions for the multibus /* set the base I/O address for the iSBC 201 */ -#define SBC201_BASE 0x88 +#define SBC201_BASE 0x88 #define SBC201_INT INT_1 #define SBC201_NUM 1 /* set the base I/O address for the iSBC 202 */ -#define SBC202_BASE 0x78 +#define SBC202_BASE 0x78 #define SBC202_INT INT_1 #define SBC202_NUM 1 /* set the base I/O address for the iSBC 208 */ -#define SBC208_BASE 0x40 +#define SBC208_BASE 0x40 #define SBC208_INT INT_1 #define SBC208_NUM 0 @@ -101,10 +101,10 @@ /* Memory */ -#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ -#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) +#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ +#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ +#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) /* debug definitions */ @@ -120,11 +120,11 @@ /* Simulator stop codes */ -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_OPCODE 4 /* Invalid Opcode */ -#define STOP_IO 5 /* I/O error */ -#define STOP_MEM 6 /* Memory error */ -#define STOP_XACK 7 /* XACK error */ +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_OPCODE 4 /* Invalid Opcode */ +#define STOP_IO 5 /* I/O error */ +#define STOP_MEM 6 /* Memory error */ +#define STOP_XACK 7 /* XACK error */ diff --git a/Intel-Systems/isys8020/isbc8020.c b/Intel-Systems/isys8020/isbc8020.c index 72372305..1dd917eb 100644 --- a/Intel-Systems/isys8020/isbc8020.c +++ b/Intel-Systems/isys8020/isbc8020.c @@ -1,136 +1,136 @@ -/* iSBC80-20.c: Intel iSBC 80/20 Processor simulator - - Copyright (c) 2010, 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. - - This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus - Computer Systems. - - ?? ??? 10 - Original file. -*/ - -#include "system_defs.h" - -/* function prototypes */ - -uint8 get_mbyte(uint16 addr); -uint16 get_mword(uint16 addr); -void put_mbyte(uint16 addr, uint8 val); -void put_mword(uint16 addr, uint16 val); -t_stat SBC_reset (DEVICE *dptr); - -/* external globals */ - -extern uint8 i8255_C[4]; //port C byte I/O - -/* external function prototypes */ - -extern uint8 multibus_get_mbyte(uint16 addr); -extern void multibus_put_mbyte(uint16 addr, uint8 val); -extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -extern int32 i8251_devnum; -extern t_stat i8251_reset (DEVICE *dptr, uint16 base); -extern int32 i8255_devnum; -extern t_stat i8255_reset (DEVICE *dptr, uint16 base); -extern int32 i8259_devnum; -extern t_stat i8259_reset (DEVICE *dptr, uint16 base); -extern uint8 EPROM_get_mbyte(uint16 addr); -extern UNIT EPROM_unit; -extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); -extern uint8 RAM_get_mbyte(uint16 addr); -extern void RAM_put_mbyte(uint16 addr, uint8 val); -extern UNIT RAM_unit; -extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); - -/* CPU reset routine - put here to cause a reset of the entire iSBC system */ - -t_stat SBC_reset (DEVICE *dptr) -{ - sim_printf("Initializing iSBC-80/20\n"); - i8080_reset(NULL); - i8251_reset(NULL, I8251_BASE); - i8255_reset(NULL, I8255_BASE_0); - i8255_reset(NULL, I8255_BASE_1); - i8259_reset(NULL, I8259_BASE); - EPROM_reset(NULL, ROM_SIZE); - RAM_reset(NULL, RAM_BASE, RAM_SIZE); - return SCPE_OK; -} - -/* get a byte from memory - handle RAM, ROM and Multibus memory */ - -uint8 get_mbyte(uint16 addr) -{ - /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ - if ((addr >= EPROM_unit.u3) && (addr < (EPROM_unit.u3 + EPROM_unit.capac))) - return EPROM_get_mbyte(addr); - } /* if local RAM handle it */ - if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ - if ((addr >= RAM_unit.u3) && (addr < (RAM_unit.u3 + RAM_unit.capac))) - return RAM_get_mbyte(addr); - } /* otherwise, try the multibus */ - return multibus_get_mbyte(addr); -} - -/* get a word from memory */ - -uint16 get_mword(uint16 addr) -{ - uint16 val; - - val = get_mbyte(addr); - val |= (get_mbyte(addr+1) << 8); - return val; -} - -/* put a byte to memory - handle RAM, ROM and Multibus memory */ - -void put_mbyte(uint16 addr, uint8 val) -{ - /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ - if ((addr >= EPROM_unit.u3) && (addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { - sim_printf("Write to R/O memory address %04X - ignored\n", addr); - return; - } - } /* if local RAM handle it */ - if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ - if ((addr >= RAM_unit.u3) && (addr <= (RAM_unit.u3 + RAM_unit.capac))) { - RAM_put_mbyte(addr, val); - return; - } - } /* otherwise, try the multibus */ - multibus_put_mbyte(addr, val); -} - -/* put a word to memory */ - -void put_mword(uint16 addr, uint16 val) -{ - put_mbyte(addr, val & 0xff); - put_mbyte(addr+1, val >> 8); -} - -/* end of iSBC80-20.c */ +/* iSBC80-20.c: Intel iSBC 80/20 Processor simulator + + Copyright (c) 2010, 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. + + This software was written by Bill Beech, Dec 2010, to allow emulation of Multibus + Computer Systems. + + ?? ??? 10 - Original file. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +uint8 get_mbyte(uint16 addr); +uint16 get_mword(uint16 addr); +void put_mbyte(uint16 addr, uint8 val); +void put_mword(uint16 addr, uint16 val); +t_stat SBC_reset (DEVICE *dptr); + +/* external globals */ + +extern uint8 i8255_C[4]; //port C byte I/O + +/* external function prototypes */ + +extern uint8 multibus_get_mbyte(uint16 addr); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ +extern int32 i8251_devnum; +extern t_stat i8251_reset (DEVICE *dptr, uint16 base); +extern int32 i8255_devnum; +extern t_stat i8255_reset (DEVICE *dptr, uint16 base); +extern int32 i8259_devnum; +extern t_stat i8259_reset (DEVICE *dptr, uint16 base); +extern uint8 EPROM_get_mbyte(uint16 addr); +extern UNIT EPROM_unit; +extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); +extern uint8 RAM_get_mbyte(uint16 addr); +extern void RAM_put_mbyte(uint16 addr, uint8 val); +extern UNIT RAM_unit; +extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); + +/* CPU reset routine + put here to cause a reset of the entire iSBC system */ + +t_stat SBC_reset (DEVICE *dptr) +{ + sim_printf("Initializing iSBC-80/20\n"); + i8080_reset(NULL); + i8251_reset(NULL, I8251_BASE); + i8255_reset(NULL, I8255_BASE_0); + i8255_reset(NULL, I8255_BASE_1); + i8259_reset(NULL, I8259_BASE); + EPROM_reset(NULL, ROM_SIZE); + RAM_reset(NULL, RAM_BASE, RAM_SIZE); + return SCPE_OK; +} + +/* get a byte from memory - handle RAM, ROM and Multibus memory */ + +uint8 get_mbyte(uint16 addr) +{ + /* if local EPROM handle it */ + if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((addr >= EPROM_unit.u3) && (addr < (EPROM_unit.u3 + EPROM_unit.capac))) + return EPROM_get_mbyte(addr); + } /* if local RAM handle it */ + if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((addr >= RAM_unit.u3) && (addr < (RAM_unit.u3 + RAM_unit.capac))) + return RAM_get_mbyte(addr); + } /* otherwise, try the multibus */ + return multibus_get_mbyte(addr); +} + +/* get a word from memory */ + +uint16 get_mword(uint16 addr) +{ + uint16 val; + + val = get_mbyte(addr); + val |= (get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory - handle RAM, ROM and Multibus memory */ + +void put_mbyte(uint16 addr, uint8 val) +{ + /* if local EPROM handle it */ + if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((addr >= EPROM_unit.u3) && (addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { + sim_printf("Write to R/O memory address %04X - ignored\n", addr); + return; + } + } /* if local RAM handle it */ + if ((RAM_DISABLE && (i8255_C[0] & 0x20)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((addr >= RAM_unit.u3) && (addr <= (RAM_unit.u3 + RAM_unit.capac))) { + RAM_put_mbyte(addr, val); + return; + } + } /* otherwise, try the multibus */ + multibus_put_mbyte(addr, val); +} + +/* put a word to memory */ + +void put_mword(uint16 addr, uint16 val) +{ + put_mbyte(addr, val & 0xff); + put_mbyte(addr+1, val >> 8); +} + +/* end of iSBC80-20.c */ diff --git a/Intel-Systems/isys8020/isys8020_sys.c b/Intel-Systems/isys8020/isys8020_sys.c index a539d225..7e24718c 100644 --- a/Intel-Systems/isys8020/isys8020_sys.c +++ b/Intel-Systems/isys8020/isys8020_sys.c @@ -1,82 +1,82 @@ -/* sys-8020_sys.c: multibus system interface - - Copyright (c) 2010, 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. - - ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. -*/ - -#include "system_defs.h" - -extern DEVICE i8080_dev; -extern REG i8080_reg[]; -extern DEVICE i8259_dev; -extern DEVICE i8251_dev; -extern DEVICE i8255_dev; -extern DEVICE EPROM_dev; -extern DEVICE RAM_dev; -extern DEVICE multibus_dev; -extern DEVICE isbc201_dev; -extern DEVICE isbc202_dev; -extern DEVICE isbc064_dev; - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages -*/ - -char sim_name[] = "Intel System 80/20"; - -REG *sim_PC = &i8080_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &i8080_dev, - &EPROM_dev, - &RAM_dev, - &i8259_dev, - &i8251_dev, - &i8255_dev, - &multibus_dev, - &isbc064_dev, - &isbc201_dev, - &isbc202_dev, - NULL -}; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode", - "Invalid Memory", - "XACK Error" -}; - +/* sys-8020_sys.c: multibus system interface + + Copyright (c) 2010, 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. + + ?? ??? 10 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. +*/ + +#include "system_defs.h" + +extern DEVICE i8080_dev; +extern REG i8080_reg[]; +extern DEVICE i8259_dev; +extern DEVICE i8251_dev; +extern DEVICE i8255_dev; +extern DEVICE EPROM_dev; +extern DEVICE RAM_dev; +extern DEVICE multibus_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE isbc064_dev; + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "Intel System 80/20"; + +REG *sim_PC = &i8080_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8080_dev, + &EPROM_dev, + &RAM_dev, + &i8259_dev, + &i8251_dev, + &i8255_dev, + &multibus_dev, + &isbc064_dev, + &isbc201_dev, + &isbc202_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error" +}; + diff --git a/Intel-Systems/isys8020/system_defs.h b/Intel-Systems/isys8020/system_defs.h index db0c9780..e1943944 100644 --- a/Intel-Systems/isys8020/system_defs.h +++ b/Intel-Systems/isys8020/system_defs.h @@ -28,7 +28,7 @@ #include #include -#include "sim_defs.h" /* simulator defns */ +#include "sim_defs.h" /* simulator defns */ #define SET_XACK(VAL) (xack = VAL) @@ -61,17 +61,17 @@ //board definitions for the multibus /* set the base I/O address for the iSBC 201 */ -#define SBC201_BASE 0x78 +#define SBC201_BASE 0x78 #define SBC201_INT INT_1 #define SBC201_NUM 0 /* set the base I/O address for the iSBC 202 */ -#define SBC202_BASE 0x78 +#define SBC202_BASE 0x78 #define SBC202_INT INT_1 #define SBC202_NUM 1 /* set the base I/O address for the iSBC 208 */ -#define SBC208_BASE 0x40 +#define SBC208_BASE 0x40 #define SBC208_INT INT_1 #define SBC208_NUM 0 @@ -105,10 +105,10 @@ /* Memory */ -#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ -#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) +#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ +#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ +#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) /* debug definitions */ @@ -124,11 +124,11 @@ /* Simulator stop codes */ -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_OPCODE 4 /* Invalid Opcode */ -#define STOP_IO 5 /* I/O error */ -#define STOP_MEM 6 /* Memory error */ -#define STOP_XACK 7 /* XACK error */ +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_OPCODE 4 /* Invalid Opcode */ +#define STOP_IO 5 /* I/O error */ +#define STOP_MEM 6 /* Memory error */ +#define STOP_XACK 7 /* XACK error */ diff --git a/Intel-Systems/isys8024/isbc8024.c b/Intel-Systems/isys8024/isbc8024.c index 84a185c2..fb7c63cf 100644 --- a/Intel-Systems/isys8024/isbc8024.c +++ b/Intel-Systems/isys8024/isbc8024.c @@ -1,149 +1,149 @@ -/* iSBC80-24.c: Intel iSBC 80/24 Processor simulator - - Copyright (c) 2010, 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: - - 04 Nov 16 - Original file. - - NOTES: - - This software was written by Bill Beech, Nov 2016, to allow emulation of Multibus - Computer Systems. -*/ - -#include "system_defs.h" - -/* function prototypes */ - -uint8 get_mbyte(uint16 addr); -uint16 get_mword(uint16 addr); -void put_mbyte(uint16 addr, uint8 val); -void put_mword(uint16 addr, uint16 val); -t_stat SBC_reset (DEVICE *dptr); - -/* external globals */ - -extern uint8 i8255_C[4]; //port C byte I/O -extern int32 PCX; /* External view of PC */ - -/* external function prototypes */ - -extern uint8 multibus_get_mbyte(uint16 addr); -extern void multibus_put_mbyte(uint16 addr, uint8 val); -extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -extern int32 i8251_devnum; -extern t_stat i8251_reset (DEVICE *dptr, uint16 base); -extern int32 i8253_devnum; -extern t_stat i8253_reset (DEVICE *dptr, uint16 base); -extern int32 i8255_devnum; -extern t_stat i8255_reset (DEVICE *dptr, uint16 base); -extern int32 i8259_devnum; -extern t_stat i8259_reset (DEVICE *dptr, uint16 base); -extern uint8 EPROM_get_mbyte(uint16 addr); -extern UNIT EPROM_unit; -extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); -extern uint8 RAM_get_mbyte(uint16 addr); -extern void RAM_put_mbyte(uint16 addr, uint8 val); -extern UNIT RAM_unit; -extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); - -/* SBC reset routine */ - -t_stat SBC_reset (DEVICE *dptr) -{ - sim_printf("Initializing iSBC-80/24 SBC\n Onboard Devices:\n"); - i8080_reset (NULL); - i8251_devnum = 0; - i8251_reset (NULL, I8251_BASE); - i8253_devnum = 0; - i8253_reset (NULL, I8253_BASE); - i8255_devnum = 0; - i8255_reset (NULL, I8255_BASE_0); - i8255_reset (NULL, I8255_BASE_1); - i8259_devnum = 0; - i8259_reset (NULL, I8259_BASE); - EPROM_reset (NULL, ROM_SIZE); - RAM_reset (NULL, RAM_BASE, RAM_SIZE); - return SCPE_OK; -} - -/* get a byte from memory - handle RAM, ROM, I/O, and Multibus memory */ - -uint8 get_mbyte(uint16 addr) -{ - /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ - if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { - return EPROM_get_mbyte(addr); - } - } /* if local RAM handle it */ - if ((RAM_DISABLE && (i8255_C[0] & 0x10)) || (RAM_DISABLE == 0)) { /* RAM enabled */ - if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { - return RAM_get_mbyte(addr); - } - } /* otherwise, try the multibus */ - return multibus_get_mbyte(addr); -} - -/* get a word from memory */ - -uint16 get_mword(uint16 addr) -{ - uint16 val; - - val = get_mbyte(addr); - val |= (get_mbyte(addr+1) << 8); - return val; -} - -/* put a byte to memory - handle RAM, ROM, I/O, and Multibus memory */ - -void put_mbyte(uint16 addr, uint8 val) -{ - /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ - if ((addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { - sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX); - return; - } - } /* if local RAM handle it */ - if ((RAM_DISABLE && (i8255_C[0] & 0x10)) || (RAM_DISABLE == 0)) { /* RAM enabled */ - if ((addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { - RAM_put_mbyte(addr, val); - return; - } - } /* otherwise, try the multibus */ - multibus_put_mbyte(addr, val); -} - -/* put a word to memory */ - -void put_mword(uint16 addr, uint16 val) -{ - put_mbyte(addr, val & 0xff); - put_mbyte(addr+1, val >> 8); -} - -/* end of iSBC80-24.c */ +/* iSBC80-24.c: Intel iSBC 80/24 Processor simulator + + Copyright (c) 2010, 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: + + 04 Nov 16 - Original file. + + NOTES: + + This software was written by Bill Beech, Nov 2016, to allow emulation of Multibus + Computer Systems. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +uint8 get_mbyte(uint16 addr); +uint16 get_mword(uint16 addr); +void put_mbyte(uint16 addr, uint8 val); +void put_mword(uint16 addr, uint16 val); +t_stat SBC_reset (DEVICE *dptr); + +/* external globals */ + +extern uint8 i8255_C[4]; //port C byte I/O +extern int32 PCX; /* External view of PC */ + +/* external function prototypes */ + +extern uint8 multibus_get_mbyte(uint16 addr); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ +extern int32 i8251_devnum; +extern t_stat i8251_reset (DEVICE *dptr, uint16 base); +extern int32 i8253_devnum; +extern t_stat i8253_reset (DEVICE *dptr, uint16 base); +extern int32 i8255_devnum; +extern t_stat i8255_reset (DEVICE *dptr, uint16 base); +extern int32 i8259_devnum; +extern t_stat i8259_reset (DEVICE *dptr, uint16 base); +extern uint8 EPROM_get_mbyte(uint16 addr); +extern UNIT EPROM_unit; +extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); +extern uint8 RAM_get_mbyte(uint16 addr); +extern void RAM_put_mbyte(uint16 addr, uint8 val); +extern UNIT RAM_unit; +extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); + +/* SBC reset routine */ + +t_stat SBC_reset (DEVICE *dptr) +{ + sim_printf("Initializing iSBC-80/24 SBC\n Onboard Devices:\n"); + i8080_reset (NULL); + i8251_devnum = 0; + i8251_reset (NULL, I8251_BASE); + i8253_devnum = 0; + i8253_reset (NULL, I8253_BASE); + i8255_devnum = 0; + i8255_reset (NULL, I8255_BASE_0); + i8255_reset (NULL, I8255_BASE_1); + i8259_devnum = 0; + i8259_reset (NULL, I8259_BASE); + EPROM_reset (NULL, ROM_SIZE); + RAM_reset (NULL, RAM_BASE, RAM_SIZE); + return SCPE_OK; +} + +/* get a byte from memory - handle RAM, ROM, I/O, and Multibus memory */ + +uint8 get_mbyte(uint16 addr) +{ + /* if local EPROM handle it */ + if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { + return EPROM_get_mbyte(addr); + } + } /* if local RAM handle it */ + if ((RAM_DISABLE && (i8255_C[0] & 0x10)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { + return RAM_get_mbyte(addr); + } + } /* otherwise, try the multibus */ + return multibus_get_mbyte(addr); +} + +/* get a word from memory */ + +uint16 get_mword(uint16 addr) +{ + uint16 val; + + val = get_mbyte(addr); + val |= (get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory - handle RAM, ROM, I/O, and Multibus memory */ + +void put_mbyte(uint16 addr, uint8 val) +{ + /* if local EPROM handle it */ + if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { + sim_printf("Write to R/O memory address %04X from PC=%04X - ignored\n", addr, PCX); + return; + } + } /* if local RAM handle it */ + if ((RAM_DISABLE && (i8255_C[0] & 0x10)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { + RAM_put_mbyte(addr, val); + return; + } + } /* otherwise, try the multibus */ + multibus_put_mbyte(addr, val); +} + +/* put a word to memory */ + +void put_mword(uint16 addr, uint16 val) +{ + put_mbyte(addr, val & 0xff); + put_mbyte(addr+1, val >> 8); +} + +/* end of iSBC80-24.c */ diff --git a/Intel-Systems/isys8024/isys8024_sys.c b/Intel-Systems/isys8024/isys8024_sys.c index 6a6c8333..51f72e94 100644 --- a/Intel-Systems/isys8024/isys8024_sys.c +++ b/Intel-Systems/isys8024/isys8024_sys.c @@ -1,84 +1,84 @@ -/* sys-8010_sys.c: multibus system interface - - Copyright (c) 2010, 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. - - ?? ??? 10 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. -*/ - -#include "system_defs.h" - -extern DEVICE i8080_dev; -extern REG i8080_reg[]; -extern DEVICE i8251_dev; -extern DEVICE i8253_dev; -extern DEVICE i8255_dev; -extern DEVICE i8259_dev; -extern DEVICE EPROM_dev; -extern DEVICE RAM_dev; -extern DEVICE multibus_dev; -extern DEVICE isbc201_dev; -extern DEVICE isbc202_dev; -extern DEVICE isbc064_dev; - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages -*/ - -char sim_name[] = "Intel System 80/24"; - -REG *sim_PC = &i8080_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &i8080_dev, - &i8251_dev, - &i8253_dev, - &i8255_dev, - &i8259_dev, - &EPROM_dev, - &RAM_dev, - &multibus_dev, - &isbc064_dev, - &isbc201_dev, - &isbc202_dev, - NULL -}; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode", - "Invalid Memory", - "XACK Error" -}; - +/* sys-8010_sys.c: multibus system interface + + Copyright (c) 2010, 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. + + ?? ??? 10 - Original file. + 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. +*/ + +#include "system_defs.h" + +extern DEVICE i8080_dev; +extern REG i8080_reg[]; +extern DEVICE i8251_dev; +extern DEVICE i8253_dev; +extern DEVICE i8255_dev; +extern DEVICE i8259_dev; +extern DEVICE EPROM_dev; +extern DEVICE RAM_dev; +extern DEVICE multibus_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE isbc064_dev; + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "Intel System 80/24"; + +REG *sim_PC = &i8080_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8080_dev, + &i8251_dev, + &i8253_dev, + &i8255_dev, + &i8259_dev, + &EPROM_dev, + &RAM_dev, + &multibus_dev, + &isbc064_dev, + &isbc201_dev, + &isbc202_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error" +}; + diff --git a/Intel-Systems/isys8024/system_defs.h b/Intel-Systems/isys8024/system_defs.h index ce59c90d..9e76a858 100644 --- a/Intel-Systems/isys8024/system_defs.h +++ b/Intel-Systems/isys8024/system_defs.h @@ -28,7 +28,7 @@ #include #include -#include "sim_defs.h" /* simulator defns */ +#include "sim_defs.h" /* simulator defns */ #define SET_XACK(VAL) (xack = VAL) @@ -65,12 +65,12 @@ //board definitions for the multibus /* set the base I/O address for the iSBC 201 */ -#define SBC201_BASE 0x78 +#define SBC201_BASE 0x78 #define SBC201_INT INT_1 #define SBC201_NUM 0 /* set the base I/O address for the iSBC 202 */ -#define SBC202_BASE 0x78 +#define SBC202_BASE 0x78 #define SBC202_INT INT_1 #define SBC202_NUM 1 @@ -80,7 +80,7 @@ #define ZX200A_NUM 0 /* set the base I/O address for the iSBC 208 */ -#define SBC208_BASE 0x40 +#define SBC208_BASE 0x40 #define SBC208_INT INT_1 #define SBC208_NUM 0 @@ -109,10 +109,10 @@ /* Memory */ -#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ -#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) +#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ +#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ +#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) /* debug definitions */ @@ -128,11 +128,11 @@ /* Simulator stop codes */ -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_OPCODE 4 /* Invalid Opcode */ -#define STOP_IO 5 /* I/O error */ -#define STOP_MEM 6 /* Memory error */ -#define STOP_XACK 7 /* XACK error */ +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_OPCODE 4 /* Invalid Opcode */ +#define STOP_IO 5 /* I/O error */ +#define STOP_MEM 6 /* Memory error */ +#define STOP_XACK 7 /* XACK error */ diff --git a/Intel-Systems/isys8030/isbc8030.c b/Intel-Systems/isys8030/isbc8030.c index e68c468f..32421b7a 100644 --- a/Intel-Systems/isys8030/isbc8030.c +++ b/Intel-Systems/isys8030/isbc8030.c @@ -1,147 +1,147 @@ -/* iSBC8030.c: Intel iSBC 80/30 SBC simulator - - Copyright (c) 2010, 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: - - 04 Nov 16 - Original file. - - NOTES: - - This software was written by Bill Beech, Nov 2016, to allow emulation of Multibus - Computer Systems. -*/ - -#include "system_defs.h" - -/* function prototypes */ - -uint8 get_mbyte(uint16 addr); -uint16 get_mword(uint16 addr); -void put_mbyte(uint16 addr, uint8 val); -void put_mword(uint16 addr, uint16 val); -t_stat SBC_reset (DEVICE *dptr); - -/* external globals */ - -extern uint8 i8255_C[4]; //port C byte I/O - -/* external function prototypes */ - -extern uint8 multibus_get_mbyte(uint16 addr); -extern void multibus_put_mbyte(uint16 addr, uint8 val); -extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ -extern int32 i8251_devnum; -extern t_stat i8251_reset (DEVICE *dptr, uint16 base); -extern int32 i8253_devnum; -extern t_stat i8253_reset (DEVICE *dptr, uint16 base); -extern int32 i8255_devnum; -extern t_stat i8255_reset (DEVICE *dptr, uint16 base); -extern int32 i8259_devnum; -extern t_stat i8259_reset (DEVICE *dptr, uint16 base); -extern uint8 EPROM_get_mbyte(uint16 addr); -extern UNIT EPROM_unit; -extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); -extern uint8 RAM_get_mbyte(uint16 addr); -extern void RAM_put_mbyte(uint16 addr, uint8 val); -extern UNIT RAM_unit; -extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); - -/* SBC reset routine */ - -t_stat SBC_reset (DEVICE *dptr) -{ - sim_printf("Initializing iSBC-80/24:\n"); - i8080_reset (NULL); - i8251_devnum = 0; - i8251_reset (NULL, I8251_BASE); - i8253_devnum = 0; - i8253_reset (NULL, I8253_BASE); - i8255_devnum = 0; - i8255_reset (NULL, I8255_BASE); - i8259_devnum = 0; - i8259_reset (NULL, I8259_BASE); - EPROM_reset (NULL, ROM_SIZE); - RAM_reset (NULL, RAM_BASE, RAM_SIZE); - return SCPE_OK; -} - -/* get a byte from memory - handle RAM, ROM, I/O, and Multibus memory */ - -uint8 get_mbyte(uint16 addr) -{ - /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ - if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { - return EPROM_get_mbyte(addr); - } - } /* if local RAM handle it */ - if ((RAM_DISABLE && (i8255_C[0] & 0x10)) || (RAM_DISABLE == 0)) { /* RAM enabled */ - if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { - return RAM_get_mbyte(addr); - } - } /* otherwise, try the multibus */ - return multibus_get_mbyte(addr); -} - -/* get a word from memory */ - -uint16 get_mword(uint16 addr) -{ - uint16 val; - - val = get_mbyte(addr); - val |= (get_mbyte(addr+1) << 8); - return val; -} - -/* put a byte to memory - handle RAM, ROM, I/O, and Multibus memory */ - -void put_mbyte(uint16 addr, uint8 val) -{ - /* if local EPROM handle it */ - if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ - if ((addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { - sim_printf("Write to R/O memory address %04X - ignored\n", addr); - return; - } - } /* if local RAM handle it */ - if ((RAM_DISABLE && (i8255_C[0] & 0x10)) || (RAM_DISABLE == 0)) { /* RAM enabled */ - if ((addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { - RAM_put_mbyte(addr, val); - return; - } - } /* otherwise, try the multibus */ - multibus_put_mbyte(addr, val); -} - -/* put a word to memory */ - -void put_mword(uint16 addr, uint16 val) -{ - put_mbyte(addr, val & 0xff); - put_mbyte(addr+1, val >> 8); -} - -/* end of iSBC8030.c */ +/* iSBC8030.c: Intel iSBC 80/30 SBC simulator + + Copyright (c) 2010, 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: + + 04 Nov 16 - Original file. + + NOTES: + + This software was written by Bill Beech, Nov 2016, to allow emulation of Multibus + Computer Systems. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +uint8 get_mbyte(uint16 addr); +uint16 get_mword(uint16 addr); +void put_mbyte(uint16 addr, uint8 val); +void put_mword(uint16 addr, uint16 val); +t_stat SBC_reset (DEVICE *dptr); + +/* external globals */ + +extern uint8 i8255_C[4]; //port C byte I/O + +/* external function prototypes */ + +extern uint8 multibus_get_mbyte(uint16 addr); +extern void multibus_put_mbyte(uint16 addr, uint8 val); +extern t_stat i8080_reset (DEVICE *dptr); /* reset the 8080 emulator */ +extern int32 i8251_devnum; +extern t_stat i8251_reset (DEVICE *dptr, uint16 base); +extern int32 i8253_devnum; +extern t_stat i8253_reset (DEVICE *dptr, uint16 base); +extern int32 i8255_devnum; +extern t_stat i8255_reset (DEVICE *dptr, uint16 base); +extern int32 i8259_devnum; +extern t_stat i8259_reset (DEVICE *dptr, uint16 base); +extern uint8 EPROM_get_mbyte(uint16 addr); +extern UNIT EPROM_unit; +extern t_stat EPROM_reset (DEVICE *dptr, uint16 size); +extern uint8 RAM_get_mbyte(uint16 addr); +extern void RAM_put_mbyte(uint16 addr, uint8 val); +extern UNIT RAM_unit; +extern t_stat RAM_reset (DEVICE *dptr, uint16 base, uint16 size); + +/* SBC reset routine */ + +t_stat SBC_reset (DEVICE *dptr) +{ + sim_printf("Initializing iSBC-80/24:\n"); + i8080_reset (NULL); + i8251_devnum = 0; + i8251_reset (NULL, I8251_BASE); + i8253_devnum = 0; + i8253_reset (NULL, I8253_BASE); + i8255_devnum = 0; + i8255_reset (NULL, I8255_BASE); + i8259_devnum = 0; + i8259_reset (NULL, I8259_BASE); + EPROM_reset (NULL, ROM_SIZE); + RAM_reset (NULL, RAM_BASE, RAM_SIZE); + return SCPE_OK; +} + +/* get a byte from memory - handle RAM, ROM, I/O, and Multibus memory */ + +uint8 get_mbyte(uint16 addr) +{ + /* if local EPROM handle it */ + if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((addr >= EPROM_unit.u3) && ((uint16)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { + return EPROM_get_mbyte(addr); + } + } /* if local RAM handle it */ + if ((RAM_DISABLE && (i8255_C[0] & 0x10)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { + return RAM_get_mbyte(addr); + } + } /* otherwise, try the multibus */ + return multibus_get_mbyte(addr); +} + +/* get a word from memory */ + +uint16 get_mword(uint16 addr) +{ + uint16 val; + + val = get_mbyte(addr); + val |= (get_mbyte(addr+1) << 8); + return val; +} + +/* put a byte to memory - handle RAM, ROM, I/O, and Multibus memory */ + +void put_mbyte(uint16 addr, uint8 val) +{ + /* if local EPROM handle it */ + if ((ROM_DISABLE && (i8255_C[0] & 0x20)) || (ROM_DISABLE == 0)) { /* EPROM enabled */ + if ((addr >= EPROM_unit.u3) && ((uint16)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { + sim_printf("Write to R/O memory address %04X - ignored\n", addr); + return; + } + } /* if local RAM handle it */ + if ((RAM_DISABLE && (i8255_C[0] & 0x10)) || (RAM_DISABLE == 0)) { /* RAM enabled */ + if ((addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { + RAM_put_mbyte(addr, val); + return; + } + } /* otherwise, try the multibus */ + multibus_put_mbyte(addr, val); +} + +/* put a word to memory */ + +void put_mword(uint16 addr, uint16 val) +{ + put_mbyte(addr, val & 0xff); + put_mbyte(addr+1, val >> 8); +} + +/* end of iSBC8030.c */ diff --git a/Intel-Systems/isys8030/isys8030_sys.c b/Intel-Systems/isys8030/isys8030_sys.c index 9d58a311..9ad98802 100644 --- a/Intel-Systems/isys8030/isys8030_sys.c +++ b/Intel-Systems/isys8030/isys8030_sys.c @@ -1,85 +1,85 @@ -/* sys-8030_sys.c: multibus system interface - - Copyright (c) 2010, 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. - - ?? ??? 10 - Original file. -*/ - -#include "system_defs.h" - -extern DEVICE i8080_dev; -extern REG i8080_reg[]; -extern DEVICE i8251_dev; -extern DEVICE i8253_dev; -extern DEVICE i8255_dev; -extern DEVICE i8259_dev; -extern DEVICE EPROM_dev; -extern DEVICE RAM_dev; -extern DEVICE multibus_dev; -extern DEVICE isbc201_dev; -extern DEVICE isbc202_dev; -extern DEVICE zx200a_dev; -extern DEVICE isbc064_dev; - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages -*/ - -char sim_name[] = "Intel System 80/10"; - -REG *sim_PC = &i8080_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &i8080_dev, - &i8251_dev, - &i8253_dev, - &i8255_dev, - &i8259_dev, - &EPROM_dev, - &RAM_dev, - &multibus_dev, - &isbc064_dev, - &isbc201_dev, - &isbc202_dev, - &zx200a_dev, - NULL -}; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode", - "Invalid Memory", - "XACK Error" -}; - +/* sys-8030_sys.c: multibus system interface + + Copyright (c) 2010, 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. + + ?? ??? 10 - Original file. +*/ + +#include "system_defs.h" + +extern DEVICE i8080_dev; +extern REG i8080_reg[]; +extern DEVICE i8251_dev; +extern DEVICE i8253_dev; +extern DEVICE i8255_dev; +extern DEVICE i8259_dev; +extern DEVICE EPROM_dev; +extern DEVICE RAM_dev; +extern DEVICE multibus_dev; +extern DEVICE isbc201_dev; +extern DEVICE isbc202_dev; +extern DEVICE zx200a_dev; +extern DEVICE isbc064_dev; + +/* SCP data structures + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words needed for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages +*/ + +char sim_name[] = "Intel System 80/10"; + +REG *sim_PC = &i8080_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &i8080_dev, + &i8251_dev, + &i8253_dev, + &i8255_dev, + &i8259_dev, + &EPROM_dev, + &RAM_dev, + &multibus_dev, + &isbc064_dev, + &isbc201_dev, + &isbc202_dev, + &zx200a_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unknown I/O Instruction", + "HALT instruction", + "Breakpoint", + "Invalid Opcode", + "Invalid Memory", + "XACK Error" +}; + diff --git a/Intel-Systems/isys8030/system_defs.h b/Intel-Systems/isys8030/system_defs.h index c6256ac5..957edc4a 100644 --- a/Intel-Systems/isys8030/system_defs.h +++ b/Intel-Systems/isys8030/system_defs.h @@ -28,7 +28,7 @@ #include #include -#include "sim_defs.h" /* simulator defns */ +#include "sim_defs.h" /* simulator defns */ #define SET_XACK(VAL) (xack = VAL) @@ -68,12 +68,12 @@ //board definitions for the multibus /* set the base I/O address for the iSBC 201 */ -#define SBC201_BASE 0x78 +#define SBC201_BASE 0x78 #define SBC201_INT INT_1 #define SBC201_NUM 0 /* set the base I/O address for the iSBC 202 */ -#define SBC202_BASE 0x78 +#define SBC202_BASE 0x78 #define SBC202_INT INT_1 #define SBC202_NUM 1 @@ -83,7 +83,7 @@ #define ZX200A_NUM 0 /* set the base I/O address for the iSBC 208 */ -#define SBC208_BASE 0x40 +#define SBC208_BASE 0x40 #define SBC208_INT INT_1 #define SBC208_NUM 0 @@ -112,10 +112,10 @@ /* Memory */ -#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ -#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) +#define MAXMEMSIZE 0x10000 /* 8080 max memory size */ +#define MEMSIZE (i8080_unit.capac) /* 8080 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8080 address mask */ +#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) /* debug definitions */ @@ -131,11 +131,11 @@ /* Simulator stop codes */ -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_OPCODE 4 /* Invalid Opcode */ -#define STOP_IO 5 /* I/O error */ -#define STOP_MEM 6 /* Memory error */ -#define STOP_XACK 7 /* XACK error */ +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_OPCODE 4 /* Invalid Opcode */ +#define STOP_IO 5 /* I/O error */ +#define STOP_MEM 6 /* Memory error */ +#define STOP_XACK 7 /* XACK error */