From a3a1db40feb80e0e53cb1bd147353470b0e6620d Mon Sep 17 00:00:00 2001 From: Bill Beech Date: Mon, 13 Mar 2017 16:29:16 -0700 Subject: [PATCH] IBMPC: Minor cleanup and change to CRLF line endings --- IBMPC-Systems/common/i8088.c | 9621 ++++++++++++++------------- IBMPC-Systems/common/i8237.c | 1744 ++--- IBMPC-Systems/common/i8251.c | 636 +- IBMPC-Systems/common/i8253.c | 470 +- IBMPC-Systems/common/i8255.c | 578 +- IBMPC-Systems/common/i8259.c | 526 +- IBMPC-Systems/common/i8273.c | 504 +- IBMPC-Systems/common/i8274.c | 700 +- IBMPC-Systems/common/ipata.c | 412 +- IBMPC-Systems/common/pata.c | 386 +- IBMPC-Systems/common/pcbus.c | 931 +-- IBMPC-Systems/common/pceprom.c | 354 +- IBMPC-Systems/common/pcram8.c | 297 +- IBMPC-Systems/ibmpc/ibmpc.c | 406 +- IBMPC-Systems/ibmpc/system_defs.h | 222 +- IBMPC-Systems/ibmpcxt/ibmpcxt.c | 404 +- IBMPC-Systems/ibmpcxt/ibmpcxt_sys.c | 192 +- IBMPC-Systems/ibmpcxt/system_defs.h | 220 +- 18 files changed, 9359 insertions(+), 9244 deletions(-) diff --git a/IBMPC-Systems/common/i8088.c b/IBMPC-Systems/common/i8088.c index 4f71f6ee..2df1e7af 100644 --- a/IBMPC-Systems/common/i8088.c +++ b/IBMPC-Systems/common/i8088.c @@ -1,4750 +1,4871 @@ -/* i8088.c: Intel 8086/8088 CPU simulator - - Copyright (C) 1991 Jim Hudgens - - The file is part of GDE. - - GDE is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) - any later version. - - GDE is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GDE; see the file COPYING. If not, write to - the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - - This software was modified by Bill Beech, Mar 2011, from the software GDE - of Jim Hudgens as provided with the SIMH AltairZ80 emulation package. - - Copyright (c) 2011, William A. Beech - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of William A. Beech shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from William A. Beech. - - cpu 8088 CPU - - 17 Mar 11 WAB Original code - - The register state for the 8088 CPU is: - - AX<0:15> AH/AL Register Pair - BX<0:15> BH/BL Register Pair - CX<0:15> CH/CL Register Pair - DX<0:15> DH/DL Register Pair - SI<0:15> Source Index Register - DI<0:15> Destination Index Register - BP<0:15> Base Pointer - SP<0:15> Stack Pointer - CS<0:15> Code Segment Register - DS<0:15> Date Segment Register - SS<0:15> Stack Segment Register - ES<0:15> Extra Segment Register - IP<0:15> Program Counter - - PSW<0:15> Program Status Word - Contains the following flags: - - AF Auxillary Flag - CF Carry Flag - OF Overflow Flag - SF Sign Flag - PF Parity Flag - ZF Zero Flag - DF Direction Flag - IF Interrupt Enable Flag - TF Trap Flag - - in bit positions: - 15 8 7 0 - |--|--|--|--|OF|DF|IF|TF|SF|ZF|--|AF|--|PF|--|CF| - - The 8088 is an 8-bit CPU, which uses 16-bit offset and segment registers - in combination with a dedicated adder to address up to 1MB of memory directly. - The offset register is added to the segment register shifted left 4 places - to obtain the 20-bit address. - - The CPU utilizes two separate processing units - the Execution Unit (EU) and - the Bus Interface Unit (BIU). The EU executes instructions. The BIU fetches - instructions, reads operands and writes results. The two units can operate - independently of one another and are able, under most circumstances, to - extensively overlap instruction fetch with execution. - - The BIUs of the 8086 and 8088 are functionally identical, but are implemented - differently to match the structure and performance characteristics of their - respective buses. - - The almost 300 instructions come in 1, 2, 3, 4, 5, 6 and 7-byte flavors. - - This routine is the simulator for the 8088. It is called from the - simulator control program to execute instructions in simulated memory, - starting at the simulated IP. It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - I/O error in I/O simulator - Invalid OP code (if ITRAP is set on CPU) - - 2. Interrupts. - There are 256 possible levels of interrupt, and in effect they - do a hardware CALL instruction to one of 256 possible low - memory addresses. - - 3. Non-existent memory. On the 8088, reads to non-existent memory - return 0FFh, and writes are ignored. - - Some algorithms were pulled from the GDE Dos/IP Emulator by Jim Hudgens - -*/ -/* - This algorithm was pulled from the GDE Dos/IP Emulator by Jim Hudgens - -CARRY CHAIN CALCULATION. - This represents a somewhat expensive calculation which is - apparently required to emulate the setting of the OF and - AF flag. The latter is not so important, but the former is. - The overflow flag is the XOR of the top two bits of the - carry chain for an addition (similar for subtraction). - Since we do not want to simulate the addition in a bitwise - manner, we try to calculate the carry chain given the - two operands and the result. - - So, given the following table, which represents the - addition of two bits, we can derive a formula for - the carry chain. - - a b cin r cout - 0 0 0 0 0 - 0 0 1 1 0 - 0 1 0 1 0 - 0 1 1 0 1 - 1 0 0 1 0 - 1 0 1 0 1 - 1 1 0 0 1 - 1 1 1 1 1 - - Construction of table for cout: - - ab - r \ 00 01 11 10 - |------------------ - 0 | 0 1 1 1 - 1 | 0 0 1 0 - - By inspection, one gets: cc = ab + r'(a + b) - - That represents alot of operations, but NO CHOICE.... - -BORROW CHAIN CALCULATION. - The following table represents the - subtraction of two bits, from which we can derive a formula for - the borrow chain. - - a b bin r bout - 0 0 0 0 0 - 0 0 1 1 1 - 0 1 0 1 1 - 0 1 1 0 1 - 1 0 0 1 0 - 1 0 1 0 0 - 1 1 0 0 0 - 1 1 1 1 1 - - Construction of table for cout: - - ab - r \ 00 01 11 10 - |------------------ - 0 | 0 1 0 0 - 1 | 1 1 1 0 - - By inspection, one gets: bc = a'b + r(a' + b) - - Segment register selection and overrides are handled as follows: - If there is a segment override, the register number is stored - in seg_ovr. If there is no override, seg_ovr is zero. Seg_ovr - is set to zero after each instruction except segment override - instructions. - - Get_ea sets the value of seg_reg to the override if present - otherwise to the default value for the registers used in the - effective address calculation. - - The get/put_smword/byte routines use the register number in - seg_reg to obtain the segment value to calculate the absolute - memory address for the operation. - */ - -#include -#include "system_defs.h" - -#define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */ -#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) -#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8088 or 8086 */ -#define UNIT_CHIP (1 << UNIT_V_CHIP) - -/* Flag values to set proper positions in PSW */ -#define CF 0x0001 -#define PF 0x0004 -#define AF 0x0010 -#define ZF 0x0040 -#define SF 0x0080 -#define TF 0x0100 -#define IF 0x0200 -#define DF 0x0400 -#define OF 0x0800 - -/* Macros to handle the flags in the PSW - 8088 has top 4 bits of the flags set to 1 - also, bit#1 is set. This is (not well) documented behavior. */ -#define PSW_ALWAYS_ON (0xF002) /* for 8086 */ -#define PSW_MSK (CF|PF|AF|ZF|SF|TF|IF|DF|OF) -#define TOGGLE_FLAG(FLAG) (PSW ^= FLAG) -#define SET_FLAG(FLAG) (PSW |= FLAG) -#define CLR_FLAG(FLAG) (PSW &= ~FLAG) -#define GET_FLAG(FLAG) (PSW & FLAG) -#define CONDITIONAL_SET_FLAG(COND,FLAG) \ - if (COND) SET_FLAG(FLAG); else CLR_FLAG(FLAG) - -/* union of byte and word registers */ -union { - uint8 b[2]; /* two bytes */ - uint16 w; /* one word */ -} A, B, C, D; /* storage for AX, BX, CX and DX */ - -/* macros for byte registers */ -#define AH (A.b[1]) -#define AL (A.b[0]) -#define BH (B.b[1]) -#define BL (B.b[0]) -#define CH (C.b[1]) -#define CL (C.b[0]) -#define DH (D.b[1]) -#define DL (D.b[0]) - -/* macros for word registers */ -#define AX (A.w) -#define BX (B.w) -#define CX (C.w) -#define DX (D.w) - -/* macros for handling IP and SP */ -#define INC_IP1 (++IP & ADDRMASK16) /* increment IP one byte */ -#define INC_IP2 ((IP += 2) & ADDRMASK16) /* 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 0x01 = int, 0x02 = NMI*/ -uint16 port; //port called in dev_table[port] -int32 chip = 0; /* 0 = 8088 chip, 1 = 8086 chip */ -#define CHIP_8088 0 /* processor types */ -#define CHIP_8086 1 -#define CHIP_80188 2 -#define CHIP_80186 3 -#define CHIP_80286 4 - -int32 seg_ovr = 0; /* segment override register */ -int32 seg_reg = 0; /* segment register to use for EA */ -#define SEG_NONE 0 /* segmenr override register values */ -#define SEG_CS 8 -#define SEG_DS 9 -#define SEG_ES 10 -#define SEG_SS 11 - -int32 PCX; /* External view of IP */ - -/* handle prefix instructions */ -uint32 sysmode = 0; /* prefix flags */ -#define SYSMODE_SEG_DS_SS 0x01 -#define SYSMODE_SEGOVR_CS 0x02 -#define SYSMODE_SEGOVR_DS 0x04 -#define SYSMODE_SEGOVR_ES 0x08 -#define SYSMODE_SEGOVR_SS 0x10 -#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | SYSMODE_SEGOVR_CS | \ - SYSMODE_SEGOVR_DS | SYSMODE_SEGOVR_ES | SYSMODE_SEGOVR_SS) -#define SYSMODE_PREFIX_REPE 0x20 -#define SYSMODE_PREFIX_REPNE 0x40 - -/* function prototypes */ -int32 sign_ext(int32 val); -int32 fetch_byte(int32 flag); -int32 fetch_word(void); -int32 parity(int32 val); -void i86_intr_raise(uint8 num); -uint32 get_rbyte(uint32 reg); -uint32 get_rword(uint32 reg); -void put_rbyte(uint32 reg, uint32 val); -void put_rword(uint32 reg, uint32 val); -uint32 get_ea(uint32 mrr); -void set_segreg(uint32 reg); -void get_mrr_dec(uint32 mrr, uint32 *mod, uint32 *reg, uint32 *rm); - -/* emulator primitives function prototypes */ -uint8 aad_word(uint16 d); -uint16 aam_word(uint8 d); -uint8 adc_byte(uint8 d, uint8 s); -uint16 adc_word(uint16 d, uint16 s); -uint8 add_byte(uint8 d, uint8 s); -uint16 add_word(uint16 d, uint16 s); -uint8 and_byte(uint8 d, uint8 s); -uint16 cmp_word(uint16 d, uint16 s); -uint8 cmp_byte(uint8 d, uint8 s); -uint16 and_word(uint16 d, uint16 s); -uint8 dec_byte(uint8 d); -uint16 dec_word(uint16 d); -void div_byte(uint8 s); -void div_word(uint16 s); -void idiv_byte(uint8 s); -void idiv_word(uint16 s); -void imul_byte(uint8 s); -void imul_word(uint16 s); -uint8 inc_byte(uint8 d); -uint16 inc_word(uint16 d); -void mul_byte(uint8 s); -void mul_word(uint16 s); -uint8 neg_byte(uint8 s); -uint16 neg_word(uint16 s); -uint8 not_byte(uint8 s); -uint16 not_word(uint16 s); -uint8 or_byte(uint8 d, uint8 s); -uint16 or_word(uint16 d, uint16 s); -void push_word(uint16 val); -uint16 pop_word(void); -uint8 rcl_byte(uint8 d, uint8 s); -uint16 rcl_word(uint16 d, uint16 s); -uint8 rcr_byte(uint8 d, uint8 s); -uint16 rcr_word(uint16 d, uint16 s); -uint8 rol_byte(uint8 d, uint8 s); -uint16 rol_word(uint16 d, uint16 s); -uint8 ror_byte(uint8 d, uint8 s); -uint16 ror_word(uint16 d, uint16 s); -uint8 shl_byte(uint8 d, uint8 s); -uint16 shl_word(uint16 d, uint16 s); -uint8 shr_byte(uint8 d, uint8 s); -uint16 shr_word(uint16 d, uint16 s); -uint8 sar_byte(uint8 d, uint8 s); -uint16 sar_word(uint16 d, uint16 s); -uint8 sbb_byte(uint8 d, uint8 s); -uint16 sbb_word(uint16 d, uint16 s); -uint8 sub_byte(uint8 d, uint8 s); -uint16 sub_word(uint16 d, uint16 s); -void test_byte(uint8 d, uint8 s); -void test_word(uint16 d, uint16 s); -uint8 xor_byte(uint8 d, uint8 s); -uint16 xor_word(uint16 d, uint16 s); -int32 get_smbyte(int32 segreg, int32 addr); -int32 get_smword(int32 segreg, int32 addr); -void put_smbyte(int32 segreg, int32 addr, int32 val); -void put_smword(int32 segreg, int32 addr, int32 val); - -/* simulator routines */ -void set_cpuint(int32 int_num); -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 */ - -/* memory read and write absolute address routines */ -extern uint8 get_mbyte(uint32 addr); -extern uint16 get_mword(uint32 addr); -extern void put_mbyte(uint32 addr, uint8 val); -extern void put_mword(uint32 addr, uint16 val); - -extern int32 sim_int_char; -extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - -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_CHIP, UNIT_CHIP, "8086", "8086", NULL }, - { UNIT_CHIP, 0, "8088", "8088", NULL }, - { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL }, - { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL }, - { 0 } -}; - -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 = { - "8088", //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 -// DEBUG_reg+DEBUG_asm, //dctrl - DEBUG_asm, //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", -"60 ", "61 ", "62 ", "63 ", /* 0x60 */ -"64 ", "65 ", "66 ", "67 ", -"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", -"80 ", "81 ", "82 ", "83 ", /* 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," -"C0 ", "C1 ", "RET ", "RET ", /* 0xC0 */ -"LES ", "LDS ", "MOV ", "MOV ", -"C8 ", "C9 ", "RET ", "RET", -"INT 3", "INT ", "INTO", "IRET", -"SHL ", "D1 ", "SHR ", "D3 ", /* 0xD0 */ -"AAM", "AAD", "D6 ", "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", "F1 ", "REPNZ", "REPZ", /* 0xF0 */ -"HLT", "CMC", "F6 ", "F7 ", -"CLC", "STC", "CLI", "STI", -"CLD", "STD", "FE ", "FF " - }; - -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 -}; - -void set_cpuint(int32 int_num) -{ - int_req |= int_num; -} - - -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 (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 */ - - /* The Big Instruction Decode Switch */ - - switch (IR) { - - /* instructions in numerical order */ - - case 0x00: /* ADD byte - REG = REG + (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = add_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = add_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x01: /* ADD word - (EA) = (EA) + REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = add_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = add_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x02: /* ADD byte - REG = REG + (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = add_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = add_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x03: /* ADD word - (EA) = (EA) + REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = adc_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result *** */ - } else { /* RM is second register */ - VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x04: /* ADD byte - AL = AL + DATA */ - DATA = fetch_byte(1); - VAL = add_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x05: /* ADD word - (EA) = (EA) + REG */ - DATA = fetch_word(); - VAL = add_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x06: /* PUSH ES */ - push_word(ES); - break; - - case 0x07: /* POP ES */ - ES = pop_word(); - break; - - case 0x08: /* OR byte - REG = REG OR (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = or_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = or_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x09: /* OR word - (EA) = (EA) OR REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = or_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = or_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result */ - } - break; - - case 0x0A: /* OR byte - REG = REG OR (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = or_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = or_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x0B: /* OR word - (EA) = (EA) OR REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = or_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result *** */ - } else { /* RM is second register */ - VAL = or_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x0C: /* OR byte - AL = AL OR DATA */ - DATA = fetch_byte(1); - VAL = or_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x0D: /* OR word - (EA) = (EA) OR REG */ - DATA = fetch_word(); - VAL = or_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x0E: /* PUSH CS */ - push_word(CS); - break; - - /* 0x0F - Not implemented on 8086/8088 */ - - case 0x10: /* ADC byte - REG = REG + (EA) + CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = adc_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = adc_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x11: /* ADC word - (EA) = (EA) + REG + CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = adc_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x12: /* ADC byte - REG = REG + (EA) + CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = adc_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = adc_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x13: /* ADC word - (EA) = (EA) + REG + CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = adc_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result *** */ - } else { /* RM is second register */ - VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x14: /* ADC byte - AL = AL + DATA + CF */ - DATA = fetch_byte(1); - VAL = adc_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x15: /* ADC word - (EA) = (EA) + REG + CF */ - DATA = fetch_word(); - VAL = adc_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x16: /* PUSH SS */ - push_word(SS); - break; - - case 0x17: /* POP SS */ - SS = pop_word(); - break; - - case 0x18: /* SBB byte - REG = REG - (EA) - CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sbb_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sbb_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x19: /* SBB word - (EA) = (EA) - REG - CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sbb_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sbb_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x1A: /* SBB byte - REG = REG - (EA) - CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sbb_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sbb_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x1B: /* SBB word - (EA) = (EA) - REG - CF */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sbb_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result *** */ - } else { /* RM is second register */ - VAL = sbb_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x1C: /* SBB byte - AL = AL - DATA - CF */ - DATA = fetch_byte(1); - VAL = sbb_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x1D: /* SBB word - (EA) = (EA) - REG - CF */ - DATA = fetch_word(); - VAL = sbb_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x1E: /* PUSH DS */ - push_word(DS); - break; - - case 0x1F: /* POP DS */ - DS = pop_word(); - break; - - case 0x20: /* AND byte - REG = REG AND (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = and_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = and_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x21: /* AND word - (EA) = (EA) AND REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = and_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = and_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x22: /* AND byte - REG = REG AND (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = and_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = and_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x23: /* AND word - (EA) = (EA) AND REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = and_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result *** */ - } else { /* RM is second register */ - VAL = and_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x24: /* AND byte - AL = AL AND DATA */ - DATA = fetch_byte(1); - VAL = and_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x25: /* AND word - (EA) = (EA) AND REG */ - DATA = fetch_word(); - VAL = and_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x26: /* ES: - segment override prefix */ - seg_ovr = SEG_ES; - sysmode |= SYSMODE_SEGOVR_ES; - break; - - case 0x27: /* DAA */ - if (((AL & 0xF) > 9) || GET_FLAG(AF)) { - AL += 6; - SET_FLAG(AF); - } - if ((AL > 0x9F) || GET_FLAG(CF)) { - AL += 0x60; - SET_FLAG(CF); - } - break; - - case 0x28: /* SUB byte - REG = REG - (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sub_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sub_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x29: /* SUB word - (EA) = (EA) - REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sub_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sub_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x2A: /* SUB byte - REG = REG - (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sub_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = sub_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x2B: /* SUB word - (EA) = (EA) - REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = sub_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result *** */ - } else { /* RM is second register */ - VAL = sub_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x2C: /* SUB byte - AL = AL - DATA */ - DATA = fetch_byte(1); - VAL = sub_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x2D: /* SUB word - (EA) = (EA) - REG */ - DATA = fetch_word(); - VAL = sub_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x2E: /* DS: - segment override prefix */ - seg_ovr = SEG_DS; - sysmode |= SYSMODE_SEGOVR_DS; - break; - - case 0x2F: /* DAS */ - if (((AL & 0xF) > 9) || GET_FLAG(AF)) { - AL -= 6; - SET_FLAG(AF); - } - if ((AL > 0x9F) || GET_FLAG(CF)) { - AL -= 0x60; - SET_FLAG(CF); - } - break; - - case 0x30: /* XOR byte - REG = REG XOR (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x31: /* XOR word - (EA) = (EA) XOR REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x32: /* XOR byte - REG = REG XOR (EA) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x33: /* XOR word - (EA) = (EA) XOR REG */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result *** */ - } else { /* RM is second register */ - VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x34: /* XOR byte - AL = AL XOR DATA */ - DATA = fetch_byte(1); - VAL = xor_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x35: /* XOR word - (EA) = (EA) XOR REG */ - DATA = fetch_word(); - VAL = xor_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x36: /* SS: - segment override prefix */ - seg_ovr = SEG_SS; - sysmode |= SYSMODE_SEGOVR_SS; - break; - - case 0x37: /* AAA */ - if (((AL & 0xF) > 9) || GET_FLAG(AF)) { - AL += 6; - AH++; - SET_FLAG(AF); - } - CONDITIONAL_SET_FLAG(GET_FLAG(AF), CF); - AL &= 0xF; - break; - - case 0x38: /* CMP byte - CMP (REG, (EA)) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x39: /* CMP word - CMP ((EA), REG) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x3A: /* CMP byte - CMP (REG, (EA)) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } else { /* RM is second register */ - VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x3B: /* CMP word - CMP ((EA), REG) */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result *** */ - } else { /* RM is second register */ - VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ - put_rword(REG, VAL); /* store result *** */ - } - break; - - case 0x3C: /* CMP byte - CMP (AL, DATA) */ - DATA = fetch_byte(1); - VAL = xor_byte(AL, DATA); /* do operation */ - AL = VAL; /* store result */ - break; - - case 0x3D: /* CMP word - CMP ((EA), REG) */ - DATA = fetch_word(); - VAL = xor_word(AX, DATA); /* do operation */ - AX = VAL; /* store result */ - break; - - case 0x3E: /* DS: - segment override prefix */ - seg_ovr = SEG_DS; - sysmode |= SYSMODE_SEGOVR_DS; - break; - - case 0x3F: /* AAS */ - if (((AL & 0xF) > 9) || GET_FLAG(AF)) { - AL -= 6; - AH--; - SET_FLAG(AF); - } - CONDITIONAL_SET_FLAG(GET_FLAG(AF), CF); - AL &= 0xF; - break; - - case 0x40: /* INC AX */ - AX = inc_word(AX); - break; - - case 0x41: /* INC CX */ - CX = inc_word(CX); - break; - - case 0x42: /* INC DX */ - DX = inc_word(DX); - break; - - case 0x43: /* INC BX */ - BX = inc_word(BX); - break; - - case 0x44: /* INC SP */ - SP = inc_word(SP); - break; - - case 0x45: /* INC BP */ - BP = inc_word(BP); - break; - - case 0x46: /* INC SI */ - SI = inc_word(SI); - break; - - case 0x47: /* INC DI */ - DI = inc_word(DI); - break; - - case 0x48: /* DEC AX */ - AX = dec_word(AX); - break; - - case 0x49: /* DEC CX */ - CX = dec_word(CX); - break; - - case 0x4A: /* DEC DX */ - DX = dec_word(DX); - break; - - case 0x4B: /* DEC BX */ - BX = dec_word(BX); - break; - - case 0x4C: /* DEC SP */ - SP = dec_word(SP); - break; - - case 0x4D: /* DEC BP */ - BP = dec_word(BP); - break; - - case 0x4E: /* DEC SI */ - SI = dec_word(SI); - break; - - case 0x4F: /* DEC DI */ - DI = dec_word(DI); - break; - - case 0x50: /* PUSH AX */ - push_word(AX); - break; - - case 0x51: /* PUSH CX */ - push_word(CX); - break; - - case 0x52: /* PUSH DX */ - push_word(DX); - break; - - case 0x53: /* PUSH BX */ - push_word(BX); - break; - - case 0x54: /* PUSH SP */ - push_word(SP); - break; - - case 0x55: /* PUSH BP */ - push_word(BP); - break; - - case 0x56: /* PUSH SI */ - push_word(SI); - break; - - case 0x57: /* PUSH DI */ - push_word(DI); - break; - - case 0x58: /* POP AX */ - AX = pop_word(); - break; - - case 0x59: /* POP CX */ - CX = pop_word(); - break; - - case 0x5A: /* POP DX */ - DX = pop_word(); - break; - - case 0x5B: /* POP BX */ - BX = pop_word(); - break; - - case 0x5C: /* POP SP */ - SP = pop_word(); - break; - - case 0x5D: /* POP BP */ - BP = pop_word(); - break; - - case 0x5E: /* POP SI */ - SI = pop_word(); - break; - - case 0x5F: /* POP DI */ - DI = pop_word(); - break; - - /* 0x60 - 0x6F - Not implemented on 8086/8088 */ - - case 0x70: /* JO short label */ - /* jump to byte offset if overflow flag is set */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(OF)) - IP = EA; - break; - - case 0x71: /* JNO short label */ - /* jump to byte offset if overflow flag is clear */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!GET_FLAG(OF)) - IP = EA; - break; - - case 0x72: /* JB/JNAE/JC short label */ - /* jump to byte offset if carry flag is set. */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(CF)) - IP = EA; - break; - - case 0x73: /* JNB/JAE/JNC short label */ - /* jump to byte offset if carry flsg is clear */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!GET_FLAG(CF)) - IP = EA; - break; - - case 0x74: /* JE/JZ short label */ - /* jump to byte offset if zero flag is set */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(ZF)) - IP = EA; - break; - - case 0x75: /* JNE/JNZ short label */ - /* jump to byte offset if zero flag is clear */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!GET_FLAG(ZF)) - IP = EA; - break; - - case 0x76: /* JBE/JNA short label */ - /* jump to byte offset if carry flag is set or if the zero - flag is set. */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(CF) || GET_FLAG(ZF)) - IP = EA; - break; - - case 0x77: /* JNBE/JA short label */ - /* jump to byte offset if carry flag is clear and if the zero - flag is clear */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!(GET_FLAG(CF) || GET_FLAG(ZF))) - IP = EA; - break; - - case 0x78: /* JS short label */ - /* jump to byte offset if sign flag is set */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(SF)) - IP = EA; - break; - - case 0x79: /* JNS short label */ - /* jump to byte offset if sign flag is clear */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!GET_FLAG(SF)) - IP = EA; - break; - - case 0x7A: /* JP/JPE short label */ - /* jump to byte offset if parity flag is set (even) */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (GET_FLAG(PF)) - IP = EA; - break; - - case 0x7B: /* JNP/JPO short label */ - /* jump to byte offset if parity flsg is clear (odd) */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (!GET_FLAG(PF)) - IP = EA; - break; - - case 0x7C: /* JL/JNGE short label */ - /* jump to byte offset if sign flag not equal to overflow flag. */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if ((GET_FLAG(SF) != 0) ^ (GET_FLAG(OF) != 0)) - IP = EA; - break; - - case 0x7D: /* JNL/JGE short label */ - /* jump to byte offset if sign flag equal to overflow flag. */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if ((GET_FLAG(SF) != 0) == (GET_FLAG(OF) != 0)) - IP = EA; - break; - - case 0x7E: /* JLE/JNG short label */ - /* jump to byte offset if sign flag not equal to overflow flag - or the zero flag is set */ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (((GET_FLAG(SF) != 0) ^ (GET_FLAG(OF) != 0)) || GET_FLAG(ZF)) - IP = EA; - break; - - case 0x7F: /* JNLE/JG short label */ - /* jump to byte offset if sign flag equal to overflow flag. - and the zero flag is clear*/ - OFF = sign_ext(fetch_byte(1)); - EA = (IP + OFF) & ADDRMASK16; - if (((GET_FLAG(SF) != 0) == (GET_FLAG(OF) != 0)) || !GET_FLAG(ZF)) - IP = EA; - break; - - case 0x80: /* byte operands */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = fetch_byte(1); /* must be done after DISP is collected */ - switch(REG) { - case 0: - VAL = add_byte(get_smbyte(seg_reg, EA), DATA); /* ADD mem8, immed8 */ - break; - case 1: - VAL = or_byte(get_smbyte(seg_reg, EA), DATA); /* OR mem8, immed8 */ - break; - case 2: - VAL = adc_byte(get_smbyte(seg_reg, EA), DATA); /* ADC mem8, immed8 */ - break; - case 3: - VAL = sbb_byte(get_smbyte(seg_reg, EA), DATA); /* SBB mem8, immed8 */ - break; - case 4: - VAL = and_byte(get_smbyte(seg_reg, EA), DATA); /* AND mem8, immed8 */ - break; - case 5: - VAL = sub_byte(get_smbyte(seg_reg, EA), DATA); /* SUB mem8, immed8 */ - break; - case 6: - VAL = xor_byte(get_smbyte(seg_reg, EA), DATA); /* XOR mem8, immed8 */ - break; - case 7: - VAL = cmp_byte(get_smbyte(seg_reg, EA), DATA); /* CMP mem8, immed8 */ - break; - } - put_rbyte(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = add_byte(get_rbyte(RM), DATA); /* ADD REG8, immed8 */ - break; - case 1: - VAL = or_byte(get_rbyte(RM), DATA); /* OR REG8, immed8 */ - break; - case 2: - VAL = adc_byte(get_rbyte(RM), DATA); /* ADC REG8, immed8 */ - break; - case 3: - VAL = sbb_byte(get_rbyte(RM), DATA); /* SBB REG8, immed8 */ - break; - case 4: - VAL = and_byte(get_rbyte(RM), DATA); /* AND REG8, immed8 */ - break; - case 5: - VAL = sub_byte(get_rbyte(RM), DATA); /* SUB REG8, immed8 */ - break; - case 6: - VAL = xor_byte(get_rbyte(RM), DATA); /* XOR REG8, immed8 */ - break; - case 7: - VAL = cmp_byte(get_rbyte(RM), DATA); /* CMP REG8, immed8 */ - break; - } - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x81: /* word operands */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = fetch_byte(1) << 8; /* must be done after DISP is collected */ - DATA |= fetch_byte(1); - switch(REG) { - case 0: - VAL = add_word(get_smword(seg_reg, EA), DATA); /* ADD mem16, immed16 */ - break; - case 1: - VAL = or_word(get_smword(seg_reg, EA), DATA); /* OR mem16, immed16 */ - break; - case 2: - VAL = adc_word(get_smword(seg_reg, EA), DATA); /* ADC mem16, immed16 */ - break; - case 3: - VAL = sbb_word(get_smword(seg_reg, EA), DATA); /* SBB mem16, immed16 */ - break; - case 4: - VAL = and_word(get_smword(seg_reg, EA), DATA); /* AND mem16, immed16 */ - break; - case 5: - VAL = sub_word(get_smword(seg_reg, EA), DATA); /* SUB mem16, immed16 */ - break; - case 6: - VAL = xor_word(get_smword(seg_reg, EA), DATA); /* XOR mem16, immed16 */ - break; - case 7: - VAL = cmp_word(get_smword(seg_reg, EA), DATA); /* CMP mem16, immed16 */ - break; - } - put_rword(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = add_word(get_rword(RM), DATA); /* ADD reg16, immed16 */ - break; - case 1: - VAL = or_word(get_rword(RM), DATA); /* OR reg16, immed16 */ - break; - case 2: - VAL = adc_word(get_rword(RM), DATA); /* ADC reg16, immed16 */ - break; - case 3: - VAL = sbb_word(get_rword(RM), DATA); /* SBB reg16, immed16 */ - break; - case 4: - VAL = and_word(get_rword(RM), DATA); /* AND reg16, immed16 */ - break; - case 5: - VAL = sub_word(get_rword(RM), DATA); /* SUB reg16, immed16 */ - break; - case 6: - VAL = xor_word(get_rword(RM), DATA); /* XOR reg16, immed16 */ - break; - case 7: - VAL = cmp_word(get_rword(RM), DATA); /* CMP reg16, immed16 */ - break; - } - put_rword(RM, VAL); /* store result */ - } - break; - - case 0x82: /* byte operands */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = fetch_byte(1); /* must be done after DISP is collected */ - switch(REG) { - case 0: - VAL = add_byte(get_smbyte(seg_reg, EA), DATA); /* ADD mem8, immed8 */ - break; - case 2: - VAL = adc_byte(get_smbyte(seg_reg, EA), DATA); /* ADC mem8, immed8 */ - break; - case 3: - VAL = sbb_byte(get_smbyte(seg_reg, EA), DATA); /* SBB mem8, immed8 */ - break; - case 5: - VAL = sub_byte(get_smbyte(seg_reg, EA), DATA); /* SUB mem8, immed8 */ - break; - case 7: - VAL = cmp_byte(get_smbyte(seg_reg, EA), DATA); /* CMP mem8, immed8 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = add_byte(get_rbyte(RM), DATA); /* ADD reg8, immed8 */ - break; - case 2: - VAL = adc_byte(get_rbyte(RM), DATA); /* ADC reg8, immed8 */ - break; - case 3: - VAL = sbb_byte(get_rbyte(RM), DATA); /* SBB reg8, immed8 */ - break; - case 5: - VAL = sub_byte(get_rbyte(RM), DATA); /* SUB reg8, immed8 */ - break; - case 7: - VAL = cmp_byte(get_rbyte(RM), DATA); /* CMP reg8, immed8 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(REG, VAL); /* store result */ - } - break; - - case 0x83: /* word operands */ - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = fetch_byte(1) << 8; /* must be done after DISP is collected */ - if (DATA & 0x80) - DATA |= 0xFF00; - else - DATA &= 0xFF; - switch(REG) { - case 0: - VAL = add_word(get_smword(seg_reg, EA), DATA); /* ADD mem16, immed8-SX */ - break; - case 2: - VAL = adc_word(get_smword(seg_reg, EA), DATA); /* ADC mem16, immed8-SX */ - break; - case 3: - VAL = sbb_word(get_smword(seg_reg, EA), DATA); /* SBB mem16, immed8-SX */ - break; - case 5: - VAL = sub_word(get_smword(seg_reg, EA), DATA); /* SUB mem16, immed8-SX */ - break; - case 7: - VAL = cmp_word(get_smword(seg_reg, EA), DATA); /* CMP mem16, immed8-SX */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rword(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = add_word(get_rword(RM), DATA); /* ADD reg16, immed8-SX */ - break; - case 2: - VAL = adc_word(get_rword(RM), DATA); /* ADC reg16, immed8-SX */ - break; - case 3: - VAL = sbb_word(get_rword(RM), DATA); /* SBB reg16, immed8-SX */ - break; - case 5: - VAL = sub_word(get_rword(RM), DATA); /* CUB reg16, immed8-SX */ - break; - case 7: - VAL = cmp_word(get_rword(RM), DATA); /* CMP reg16, immed8-SX */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rword(RM, VAL); /* store result */ - } - break; - - case 0x84: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - test_byte(get_smbyte(seg_reg, EA),get_rbyte(REG)); /* TEST mem8, reg8 */ - } else { - test_byte(get_rbyte(REG),get_rbyte(RM)); /* TEST reg8, reg8 */ - } - break; - - case 0x85: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - test_word(get_smword(seg_reg, EA),get_rword(REG)); /* TEST mem16, reg16 */ - } else { - test_word(get_rword(REG),get_rword(RM)); /* TEST reg16, reg16 */ - } - break; - - case 0x86: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = get_rbyte(REG);/* XCHG mem8, reg8 */ - put_rbyte(REG, get_smbyte(seg_reg, EA)); - put_smbyte(seg_reg, EA, VAL); - } else { - VAL = get_rbyte(RM);/* XCHG reg8, reg8 */ - put_rbyte(RM, get_rbyte(REG)); - put_rbyte(REG, VAL); - } - break; - - case 0x87: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - VAL = get_rword(REG);/* XCHG mem16, reg16 */ - put_rword(REG, get_smword(seg_reg, EA)); - put_smword(seg_reg, EA, VAL); - } else { - VAL = get_rword(RM);/* XCHG reg16, reg16 */ - put_rword(RM, get_rword(REG)); - put_rword(REG, VAL); - } - break; - - case 0x88: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_smbyte(seg_reg, EA, get_rbyte(REG)); /* MOV mem8, reg8 */ - } else - put_rbyte(REG, get_rbyte(RM)); /* MOV reg8, reg8 */ - break; - - case 0x89: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_smword(seg_reg, EA, get_rword(REG)); /* MOV mem16, reg16 */ - } else - put_rword(REG, get_rword(RM)); /* MOV reg16, reg16 */ - break; - - case 0x8A: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_rbyte(REG, get_smbyte(seg_reg, EA)); /* MOV reg8, mem8 */ - } else - put_rbyte(REG, get_rbyte(RM)); /* MOV reg8, reg8 */ - break; - - case 0x8B: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_rword(REG, get_smword(seg_reg, EA)); /* MOV reg16, mem16 */ - } else - put_rword(REG, get_rword(RM)); /* MOV reg16, reg16 */ - break; - - case 0x8C: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* MOV mem16, ES */ - put_smword(seg_reg, EA, ES); - break; - case 1: /* MOV mem16, CS */ - put_smword(seg_reg, EA, CS); - break; - case 2: /* MOV mem16, SS */ - put_smword(seg_reg, EA, SS); - break; - case 3: /* MOV mem16, DS */ - put_smword(seg_reg, EA, DS); - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { - switch(REG) { - case 0: /* MOV reg16, ES */ - put_rword(RM, ES); - break; - case 1: /* MOV reg16, CS */ - put_rword(RM, CS); - break; - case 2: /* MOV reg16, SS */ - put_rword(RM, SS); - break; - case 3: /* MOV reg16, DS */ - put_rword(RM, DS); - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } - break; - - case 0x8D: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_rword(REG, EA); /* LEA reg16, mem16 */ - } else { - reason = STOP_OPCODE; - IP -= 2; - } - break; - - case 0x8E: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* MOV ES, mem16 */ - ES = get_smword(seg_reg, EA); - break; - case 1: /* MOV CS, mem16 */ - CS = get_smword(seg_reg, EA); - break; - case 2: /* MOV SS, mem16 */ - SS = get_smword(seg_reg, EA); - break; - case 3: /* MOV DS, mem16 */ - DS = get_smword(seg_reg, EA); - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { - switch(REG) { - case 0: /* MOV ES, reg16 */ - ES = get_rword(RM); - break; - case 1: /* MOV CS, reg16 */ - CS = get_rword(RM); - break; - case 2: /* MOV SS, reg16 */ - SS = get_rword(RM); - break; - case 3: /* MOV DS, reg16 */ - DS = get_rword(RM); - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } - break; - - case 0x8f: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_smword(seg_reg, EA, pop_word()); - } else { - reason = STOP_OPCODE; - IP -= 2; - } - break; - - case 0x90: /* NOP */ - break; - - case 0x91: /* XCHG AX, CX */ - VAL = AX; - AX = CX; - CX = VAL; - break; - - case 0x92: /* XCHG AX, DX */ - VAL = AX; - AX = DX; - DX = VAL; - break; - - case 0x93: /* XCHG AX, BX */ - VAL = AX; - AX = BX; - BX = VAL; - break; - - case 0x94: /* XCHG AX, SP */ - VAL = AX; - AX = SP; - SP = VAL; - break; - - case 0x95: /* XCHG AX, BP */ - VAL = AX; - AX = BP; - BP = VAL; - break; - - case 0x96: /* XCHG AX, SI */ - VAL = AX; - AX = SI; - SI = VAL; - break; - - case 0x97: /* XCHG AX, DI */ - VAL = AX; - AX = DI; - DI = VAL; - break; - - case 0x98: /* cbw */ - if (AL & 0x80) - AH = 0xFF; - else - AH = 0; - break; - - case 0x99: /* cbw */ - if (AX & 0x8000) - DX = 0xffff; - else - DX = 0x0; - break; - - case 0x9A: /* CALL FAR proc */ - OFF = fetch_word(); /* do operation */ - SEG = fetch_word(); - push_word(CS); - CS = SEG; - push_word(IP); - IP = OFF; - break; - - case 0x9B: /* WAIT */ - break; - - case 0x9C: /* PUSHF */ - VAL = PSW; - VAL &= PSW_MSK; - VAL |= PSW_ALWAYS_ON; - push_word(VAL); - break; - - case 0x9D: /* POPF */ - PSW = pop_word(); - break; - - case 0x9E: /* SAHF */ - PSW &= 0xFFFFFF00; - PSW |= AH; - break; - - case 0x9F: /* LAHF */ - AH = PSW & 0xFF; - AH |= 0x2; - break; - - case 0xA0: /* MOV AL, mem8 */ - OFF = fetch_word(); - set_segreg(SEG_DS); /* to allow segment override */ - AL = get_smbyte(seg_reg, OFF); - break; - - case 0xA1: /* MOV AX, mem16 */ - OFF = fetch_word(); - set_segreg(SEG_DS); /* to allow segment override */ - AX = get_smword(seg_reg, OFF); - break; - - case 0xA2: /* MOV mem8, AL */ - OFF = fetch_word(); - set_segreg(SEG_DS); /* to allow segment override */ - put_smbyte(seg_reg, OFF, AL); - break; - - case 0xA3: /* MOV mem16, AX */ - OFF = fetch_word(); - set_segreg(SEG_DS); /* to allow segment override */ - put_smword(seg_reg, OFF, AX); - break; - - case 0xA4: /* MOVS dest-str8, src-str8 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - while (CX != 0) { - VAL = get_smbyte(seg_reg, SI); - put_smbyte(ES, DI, VAL); - CX--; - SI += INC; - DI += INC; - } - break; - - case 0xA5: /* MOVS dest-str16, src-str16 */ - if (GET_FLAG(DF)) /* down */ - INC = -2; - else - INC = 2; - while (CX != 0) { - VAL = get_smword(seg_reg, SI); - put_smword(ES, DI, VAL); - CX--; - SI += INC; - DI += INC; - } - break; - - case 0xA6: /* CMPS dest-str8, src-str8 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - while (CX != 0) { - VAL = get_smbyte(seg_reg, SI); - VAL1 = get_smbyte(ES, DI); - cmp_byte(VAL, VAL1); - CX--; - SI += INC; - DI += INC; - if (GET_FLAG(ZF) == 0) - break; - } - break; - - case 0xA7: /* CMPS dest-str16, src-str16 */ - if (GET_FLAG(DF)) /* down */ - INC = -2; - else - INC = 2; - while (CX != 0) { - VAL = get_smword(seg_reg, SI); - VAL1 = get_smword(ES, DI); - cmp_word(VAL, VAL1); - CX--; - SI += INC; - DI += INC; - if (GET_FLAG(ZF) == 0) - break; - } - break; - - case 0xA8: /* TEST AL, immed8 */ - VAL = fetch_byte(1); - test_byte(AL, VAL); - break; - - case 0xA9: /* TEST AX, immed8 */ - VAL = fetch_word(); - test_word(AX, VAL); - break; - - case 0xAA: /* STOS dest-str8 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - put_smbyte(ES, DI, AL); - CX--; - DI += INC; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - put_smbyte(ES, DI, AL); - DI += INC; - } - break; - - case 0xAB: /* STOS dest-str16 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - put_smword(ES, DI, AX); - CX--; - DI += INC; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - put_smword(ES, DI, AL); - DI += INC; - } - break; - - case 0xAC: /* LODS dest-str8 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - set_segreg(SEG_DS); /* allow overrides */ - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - AL = get_smbyte(seg_reg, SI); - CX--; - SI += INC; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - AL = get_smbyte(seg_reg, SI); - SI += INC; - } - break; - - case 0xAD: /* LODS dest-str16 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - set_segreg(SEG_DS); /* allow overrides */ - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - AX = get_smword(seg_reg, SI); - CX--; - SI += INC; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - AX = get_smword(seg_reg, SI); - SI += INC; - } - break; - - case 0xAE: /* SCAS dest-str8 */ - if (GET_FLAG(DF)) /* down */ - INC = -1; - else - INC = 1; - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - VAL = get_smbyte(ES, DI); - cmp_byte(AL, VAL); - CX--; - DI += INC; - if (GET_FLAG(ZF) == 0) - break; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - VAL = get_smbyte(ES, DI); - cmp_byte(AL, VAL); - DI += INC; - } - break; - - case 0xAF: /* SCAS dest-str16 */ - if (GET_FLAG(DF)) /* down */ - INC = -2; - else - INC = 2; - if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { - while (CX != 0) { - VAL = get_smword(ES, DI); - cmp_word(AX, VAL); - CX--; - DI += INC; - if (GET_FLAG(ZF) == 0) - break; - } - sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } else { - VAL = get_smword(ES, DI); - cmp_byte(AL, VAL); - DI += INC; - } - break; - - case 0xB0: /* MOV AL,immed8 */ - AL = fetch_byte(1); - break; - - case 0xB1: /* MOV CL,immed8 */ - CL = fetch_byte(1); - break; - - case 0xB2: /* MOV DL,immed8 */ - DL = fetch_byte(1); - break; - - case 0xB3: /* MOV BL,immed8 */ - BL = fetch_byte(1); - break; - - case 0xB4: /* MOV AH,immed8 */ - AH = fetch_byte(1); - break; - - case 0xB5: /* MOV CH,immed8 */ - CH = fetch_byte(1); - break; - - case 0xB6: /* MOV DH,immed8 */ - DH = fetch_byte(1); - break; - - case 0xB7: /* MOV BH,immed8 */ - BH = fetch_byte(1); - break; - - case 0xB8: /* MOV AX,immed16 */ - AX = fetch_word(); - break; - - case 0xB9: /* MOV CX,immed16 */ - CX = fetch_word(); - break; - - case 0xBA: /* MOV DX,immed16 */ - DX = fetch_word(); - break; - - case 0xBB: /* MOV BX,immed16 */ - BX = fetch_word(); - break; - - case 0xBC: /* MOV SP,immed16 */ - SP = fetch_word(); - break; - - case 0xBD: /* MOV BP,immed16 */ - BP = fetch_word(); - break; - - case 0xBE: /* MOV SI,immed16 */ - SI = fetch_word(); - break; - - case 0xBF: /* MOV DI,immed16 */ - DI = fetch_word(); - break; - - /* 0xC0 - 0xC1 - Not implemented on 8086/8088 */ - - case 0xC2: /* RET immed16 (intrasegment) */ - OFF = fetch_word(); - IP = pop_word(); - SP += OFF; - break; - - case 0xC3: /* RET (intrasegment) */ - IP = pop_word(); - break; - - case 0xC4: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_rword(REG, get_smword(seg_reg, EA)); /* LES mem16 */ - ES = get_smword(seg_reg, EA + 2); - } else { -// put_rword(REG, get_rword(RM)); /* LES reg16 */ -// ES = get_rword(RM) + 2; - /* not defined for 8086 */ - reason = STOP_OPCODE; - IP -= 2; - } - break; - - case 0xC5: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - put_rword(REG, get_smword(seg_reg, EA)); /* LDS mem16 */ - DS = get_smword(seg_reg, EA + 2); - } else { -// put_rword(REG, get_rword(RM)); /* LDS reg16 */ -// DS = get_rword(RM) + 2; - /* not defined for 8086 */ - reason = STOP_OPCODE; - IP -= 2; - } - break; - - case 0xC6: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (REG) { /* has to be 0 */ - reason = STOP_OPCODE; - IP -= 2; - } - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = fetch_byte(1); /* has to be after DISP */ - put_smbyte(seg_reg, EA, DATA); /* MOV mem8, immed8 */ - } else { - put_rbyte(RM, DATA); /* MOV reg8, immed8 */ - } - break; - - case 0xC7: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (REG) { /* has to be 0 */ - reason = STOP_OPCODE; - IP -= 2; - } - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - DATA = get_mword(IP); /* has to be after DISP */ - put_smword(seg_reg, EA, DATA); /* MOV mem16, immed16 */ - } else { - put_rword(RM, DATA); /* MOV reg16, immed16 */ - } - break; - - /* 0xC8 - 0xC9 - Not implemented on 8086/8088 */ - - case 0xCA: /* RET immed16 (intersegment) */ - OFF = fetch_word(); - IP = pop_word(); - CS = pop_word(); - SP += OFF; - break; - - case 0xCB: /* RET (intersegment) */ - IP = pop_word(); - CS = pop_word(); - break; - - case 0xCC: /* INT 3 */ - push_word(PSW); - CLR_FLAG(IF); - CLR_FLAG(TF); - push_word(CS); - push_word(IP); - CS = get_mword(14); - IP = get_mword(12); - break; - - case 0xCD: /* INT immed8 */ - OFF = fetch_byte(1); - push_word(PSW); - CLR_FLAG(IF); - CLR_FLAG(TF); - push_word(CS); - push_word(IP); - CS = get_mword((OFF * 4) + 2); - IP = get_mword(OFF * 4); - break; - - case 0xCE: /* INT0 */ - push_word(PSW); - CLR_FLAG(IF); - CLR_FLAG(TF); - push_word(CS); - push_word(IP); - CS = get_mword(18); - IP = get_mword(16); - break; - - case 0xCF: /* IRET */ - IP = pop_word(); - CS = pop_word(); - PSW = pop_word(); - break; - - case 0xD0: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: - VAL = rol_byte(get_smbyte(seg_reg, EA), 1); /* ROL mem8, 1 */ - break; - case 1: - VAL = ror_byte(get_smbyte(seg_reg, EA), 1); /* ROR mem8, 1 */ - break; - case 2: - VAL = rcl_byte(get_smbyte(seg_reg, EA), 1); /* RCL mem8, 1 */ - break; - case 3: - VAL = rcr_byte(get_smbyte(seg_reg, EA), 1); /* RCR mem8, 1 */ - break; - case 4: - VAL = shl_byte(get_smbyte(seg_reg, EA), 1); /* SAL/SHL mem8, 1 */ - break; - case 5: - VAL = shr_byte(get_smbyte(seg_reg, EA), 1); /* SHR mem8, 1 */ - break; - case 7: - VAL = sar_byte(get_smbyte(seg_reg, EA), 1); /* SAR mem8, 1 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = rol_byte(get_rbyte(RM), 1); /* RCL reg8, 1 */ - break; - case 1: - VAL = ror_byte(get_rbyte(RM), 1); /* ROR reg8, 1 */ - break; - case 2: - VAL = rcl_byte(get_rbyte(RM), 1); /* RCL reg8, 1 */ - break; - case 3: - VAL = rcr_byte(get_rbyte(RM), 1); /* RCR reg8, 1 */ - break; - case 4: - VAL = shl_byte(get_rbyte(RM), 1); /* SHL/SAL reg8, 1*/ - break; - case 5: - VAL = shr_byte(get_rbyte(RM), 1); /* SHR reg8, 1 */ - break; - case 7: - VAL = sar_byte(get_rbyte(RM), 1); /* SAR reg8, 1 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xD1: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: - VAL = rol_word(get_smword(seg_reg, EA), 1); /* ROL mem16, 1 */ - break; - case 1: - VAL = ror_word(get_smword(seg_reg, EA), 1); /* ROR mem16, 1 */ - break; - case 2: - VAL = rcl_word(get_smword(seg_reg, EA), 1); /* RCL mem16, 1 */ - break; - case 3: - VAL = rcr_word(get_smword(seg_reg, EA), 1); /* RCR mem16, 1 */ - break; - case 4: - VAL = shl_word(get_smword(seg_reg, EA), 1); /* SAL/SHL mem16, 1 */ - break; - case 5: - VAL = shr_word(get_smword(seg_reg, EA), 1); /* SHR mem16, 1 */ - break; - case 7: - VAL = sar_word(get_smword(seg_reg, EA), 1); /* SAR mem16, 1 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rword(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = rol_word(get_rword(RM), 1); /* RCL reg16, 1 */ - break; - case 1: - VAL = ror_word(get_rword(RM), 1); /* ROR reg16, 1 */ - break; - case 2: - VAL = rcl_word(get_rword(RM), 1); /* RCL reg16, 1 */ - break; - case 3: - VAL = rcr_word(get_rword(RM), 1); /* RCR reg16, 1 */ - break; - case 4: - VAL = shl_word(get_rword(RM), 1); /* SHL/SAL reg16, 1 */ - break; - case 5: - VAL = shr_word(get_rword(RM), 1); /* SHR reg16, 1 */ - break; - case 7: - VAL = sar_word(get_rword(RM), 1); /* SAR reg16, 1 */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xD2: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: - VAL = rol_byte(get_smbyte(seg_reg, EA), CL); /* ROL mem8, CL */ - break; - case 1: - VAL = ror_byte(get_smbyte(seg_reg, EA), CL); /* ROR mem8, CL */ - break; - case 2: - VAL = rcl_byte(get_smbyte(seg_reg, EA), CL); /* RCL mem8, CL */ - break; - case 3: - VAL = rcr_byte(get_smbyte(seg_reg, EA), CL); /* RCR mem8, CL */ - break; - case 4: - VAL = shl_byte(get_smbyte(seg_reg, EA), CL); /* SAL/SHL mem8, CL */ - break; - case 5: - VAL = shr_byte(get_smbyte(seg_reg, EA), CL); /* SHR mem8, CL */ - break; - case 7: - VAL = sar_byte(get_smbyte(seg_reg, EA), CL); /* SAR mem8, CL */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = rol_byte(get_rbyte(RM), CL); /* RCL reg8, CL */ - break; - case 1: - VAL = ror_byte(get_rbyte(RM), CL); /* ROR reg8, CL */ - break; - case 2: - VAL = rcl_byte(get_rbyte(RM), CL); /* RCL reg8, CL */ - break; - case 3: - VAL = rcr_byte(get_rbyte(RM), CL); /* RCR reg8, CL */ - break; - case 4: - VAL = shl_byte(get_rbyte(RM), CL); /* SHL/SAL reg8, CL*/ - break; - case 5: - VAL = shr_byte(get_rbyte(RM), CL); /* SHR reg8, CL */ - break; - case 7: - VAL = sar_byte(get_rbyte(RM), CL); /* SAR reg8, CL */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xD3: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: - VAL = rol_word(get_smword(seg_reg, EA), CL); /* ROL mem16, CL */ - break; - case 1: - VAL = ror_word(get_smword(seg_reg, EA), CL); /* ROR mem16, CL */ - break; - case 2: - VAL = rcl_word(get_smword(seg_reg, EA), CL); /* RCL mem16, CL */ - break; - case 3: - VAL = rcr_word(get_smword(seg_reg, EA), CL); /* RCR mem16, CL */ - break; - case 4: - VAL = shl_word(get_smword(seg_reg, EA), CL); /* SAL/SHL mem16, CL */ - break; - case 5: - VAL = shr_word(get_smword(seg_reg, EA), CL); /* SHR mem16, CL */ - break; - case 7: - VAL = sar_word(get_smword(seg_reg, EA), CL); /* SAR mem16, CL */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rword(EA, VAL); /* store result */ - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = rol_word(get_rword(RM), CL); /* RCL reg16, CL */ - break; - case 1: - VAL = ror_word(get_rword(RM), CL); /* ROR reg16, CL */ - break; - case 2: - VAL = rcl_word(get_rword(RM), CL); /* RCL reg16, CL */ - break; - case 3: - VAL = rcr_word(get_rword(RM), CL); /* RCR reg16, CL */ - break; - case 4: - VAL = shl_word(get_rword(RM), CL); /* SHL/SAL reg16, CL */ - break; - case 5: - VAL = shr_word(get_rword(RM), CL); /* SHR reg16, CL */ - break; - case 7: - VAL = sar_word(get_rword(RM), CL); /* SAR reg16, CL */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xD4: /* AAM */ - VAL = fetch_word(); - if (VAL != 10) { - reason = STOP_OPCODE; - IP -= 2; - } - /* note the type change here --- returning AL and AH in AX. */ - AX = aam_word(AL); - break; - - case 0xD5: /* AAD */ - VAL = fetch_word(); - if (VAL != 10) { - reason = STOP_OPCODE; - IP -= 2; - } - AX = aad_word(AX); - break; - - /* 0xD6 - Not implemented on 8086/8088 */ - - case 0xD7: /* XLAT */ - OFF = BX + (uint8)AL; - AL = get_smbyte(SEG_CS, OFF); - break; - - case 0xD8: /* ESC */ - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: - /* for now, do nothing, NOP for 8088 */ - break; - - case 0xE0: /* LOOPNE label */ - OFF = fetch_byte(1); - OFF = sign_ext(OFF); - OFF += (int16)IP; - CX -= 1; - if (CX != 0 && !GET_FLAG(ZF)) /* CX != 0 and !ZF */ - IP = OFF; - break; - - case 0xE1: /* LOOPE label */ - OFF = fetch_byte(1); - OFF = sign_ext(OFF); - OFF += (int16)IP; - CX -= 1; - if (CX != 0 && GET_FLAG(ZF)) /* CX != 0 and ZF */ - IP = OFF; - break; - - case 0xE2: /* LOOP label */ - OFF = fetch_byte(1); - OFF = sign_ext(OFF); - OFF += (int16)IP; - CX -= 1; - if (CX != 0) /* CX != 0 */ - IP = OFF; - break; - - case 0xE3: /* JCXZ label */ - OFF = fetch_byte(1); - OFF = sign_ext(OFF); - OFF += (int16)IP; - if (CX == 0) /* CX != 0 */ - IP = OFF; - break; - - case 0xE4: /* IN AL, port8 */ - OFF = fetch_byte(1); - port = OFF; - AL = dev_table[OFF].routine(0, 0); - break; - - case 0xE5: /* IN AX, port8 */ - OFF = fetch_byte(1); - port = OFF; - AH = dev_table[OFF].routine(0, 0); - AL = dev_table[OFF+1].routine(0, 0); - break; - - case 0xE6: /* OUT AL, port8 */ - OFF = fetch_byte(1); - port = OFF; - dev_table[OFF].routine(1, AL); - //sim_printf("OUT AL: OFF=%04X\n", OFF); - break; - - case 0xE7: /* OUT AX, port8 */ - OFF = fetch_byte(1); - port = OFF; - 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 */ - port = DX; - AL = dev_table[DX].routine(0, 0); - break; - - case 0xED: /* IN AX,DX */ - port = DX; - AH = dev_table[DX].routine(0, 0); - AL = dev_table[DX+1].routine(0, 0); - break; - - case 0xEE: /* OUT AL,DX */ - port = DX; - dev_table[DX].routine(1, AL); - break; - - case 0xEF: /* OUT AX,DX */ - port = DX; - dev_table[DX].routine(1, AH); - dev_table[DX+1].routine(1, AL); - break; - - case 0xF0: /* LOCK */ - /* do nothing for now */ - break; - - /* 0xF1 - Not implemented on 8086/8088 */ - - case 0xF2: /* REPNE/REPNZ */ - sysmode |= SYSMODE_PREFIX_REPNE; - break; - - case 0xF3: /* REP/REPE/REPZ */ - sysmode |= SYSMODE_PREFIX_REPE; - break; - - case 0xF4: /* HLT */ - reason = STOP_HALT; - IP--; - break; - - case 0xF5: /* CMC */ - TOGGLE_FLAG(CF); - break; - - case 0xF6: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* TEST mem8, immed8 */ - DATA = fetch_byte(1); - test_byte(get_smbyte(seg_reg, EA), DATA); - break; - case 2: /* NOT mem8 */ - VAL = not_byte(get_smbyte(seg_reg, EA)); - put_smbyte(seg_reg, EA, VAL); /* store result */ - break; - case 3: /* NEG mem8 */ - VAL = neg_byte(get_smbyte(seg_reg, EA)); - put_smbyte(seg_reg, EA, VAL); /* store result */ - break; - case 4: /* MUL mem8 */ - mul_byte(get_smbyte(seg_reg, EA)); - break; - case 5: /* IMUL mem8 */ - imul_byte(get_smbyte(seg_reg, EA)); - break; - case 6: /* DIV mem8 */ - div_byte(get_smbyte(seg_reg, EA)); - break; - case 7: /* IDIV mem8 */ - idiv_byte(get_smbyte(seg_reg, EA)); - break; - default: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { /* RM is second register */ - switch(REG) { - case 0: /* TEST reg8, immed8 */ - DATA = fetch_byte(1); - test_byte(get_rbyte(RM), DATA); - break; - case 2: /* NOT reg8 */ - VAL = not_byte(get_rbyte(RM)); - put_rbyte(RM, VAL); /* store result */ - break; - case 3: /* NEG reg8 */ - VAL = neg_byte(get_rbyte(RM)); - put_rbyte(RM, VAL); /* store result */ - break; - case 4: /* MUL reg8 */ - mul_byte(get_rbyte(RM)); - break; - case 5: /* IMUL reg8 */ - imul_byte(get_rbyte(RM)); - break; - case 6: /* DIV reg8 */ - div_byte(get_rbyte(RM)); - break; - case 7: /* IDIV reg8 */ - idiv_byte(get_rbyte(RM)); - break; - default: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xF7: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* TEST mem16, immed16 */ - DATA = fetch_word(); - test_word(get_smword(seg_reg, EA), DATA); - break; - case 2: /* NOT mem16 */ - VAL = not_word(get_smword(seg_reg, EA)); - put_smword(seg_reg, EA, VAL); /* store result */ - break; - case 3: /* NEG mem16 */ - VAL = neg_word(get_smword(seg_reg, EA)); - put_smword(seg_reg, EA, VAL); /* store result */ - break; - case 4: /* MUL mem16 */ - mul_word(get_smword(seg_reg, EA)); - break; - case 5: /* IMUL mem16 */ - imul_word(get_smword(seg_reg, EA)); - break; - case 6: /* DIV mem16 */ - div_word(get_smword(seg_reg, EA)); - break; - case 7: /* IDIV mem16 */ - idiv_word(get_smword(seg_reg, EA)); - break; - default: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { /* RM is second register */ - switch(REG) { - case 0: /* TEST reg16, immed16 */ - DATA = fetch_word(); - test_word(get_rword(RM), DATA); - break; - case 2: /* NOT reg16 */ - VAL = not_word(get_rword(RM)); - put_rword(RM, VAL); /* store result */ - break; - case 3: /* NEG reg16 */ - VAL = neg_word(get_rword(RM)); - put_rword(RM, VAL); /* store result */ - break; - case 4: /* MUL reg16 */ - mul_word(get_rword(RM)); - break; - case 5: /* IMUL reg16 */ - imul_word(get_rword(RM)); - break; - case 6: /* DIV reg16 */ - div_word(get_rword(RM)); - break; - case 7: /* IDIV reg16 */ - idiv_word(get_rword(RM)); - break; - default: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xF8: /* CLC */ - CLR_FLAG(CF); - break; - - case 0xF9: /* STC */ - SET_FLAG(CF); - break; - - case 0xFA: /* CLI */ - CLR_FLAG(IF); - break; - - case 0xFB: /* STI */ - SET_FLAG(IF); - break; - - case 0xFC: /* CLD */ - CLR_FLAG(DF); - break; - - case 0xFD: /* STD */ - SET_FLAG(DF); - break; - - case 0xFE: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* INC mem16 */ - VAL = inc_byte(get_smbyte(seg_reg, EA)); /* do operation */ - put_smbyte(seg_reg, EA, VAL); /* store result */ - break; - case 1: /* DEC mem16 */ - VAL = dec_byte(get_smbyte(seg_reg, EA)); /* do operation */ - put_smbyte(seg_reg, EA, VAL); /* store result */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { /* RM is second register */ - switch(REG) { - case 0: - VAL = inc_byte(get_rbyte(RM)); /* do operation */ - put_rbyte(RM, VAL); /* store result */ - break; - case 1: - VAL = dec_byte(get_rbyte(RM)); /* do operation */ - put_rbyte(RM, VAL); /* store result */ - break; - default: /* bad opcodes */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - case 0xFF: - MRR = fetch_byte(1); - get_mrr_dec(MRR, &MOD, ®, &RM); - if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ - EA = get_ea(MRR); /* get effective address */ - switch(REG) { - case 0: /* INC mem16 */ - VAL = inc_word(get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - break; - case 1: /* DEC mem16 */ - VAL = dec_word(get_smword(seg_reg, EA)); /* do operation */ - put_smword(seg_reg, EA, VAL); /* store result */ - break; - case 2: /* CALL NEAR mem16 */ - OFF = get_smword(SEG_CS, EA); /* do operation */ - push_word(IP); - IP = OFF; - break; - case 3: /* CALL FAR mem16 */ - OFF = get_smword(SEG_CS, EA); /* do operation */ - SEG = get_smword(SEG_CS, EA + 2); - push_word(CS); - CS = SEG; - push_word(IP); - IP = OFF; - break; - case 4: /* JMP NEAR mem16 */ - OFF = get_smword(SEG_CS, EA); /* do operation */ - IP = OFF; - break; - case 5: /* JMP FAR mem16 */ - OFF = get_smword(SEG_CS, EA); /* do operation */ - SEG = get_smword(SEG_CS, EA + 2); - CS = SEG; - IP = OFF; - break; - case 6: /* PUSH mem16 */ - VAL = get_smword(seg_reg, EA); /* do operation */ - push_word(VAL); - break; - case 7: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - } else { /* RM is second register */ - switch(REG) { - case 2: /* CALL NEAR reg16 */ - OFF = get_rword(RM); /* do operation */ - push_word(IP); - IP = OFF; - break; - case 4: /* JMP NEAR reg16 */ - OFF = get_rword(RM); /* do operation */ - IP = OFF; - break; - default: /* bad opcode */ - reason = STOP_OPCODE; - IP -= 2; - break; - } - put_rbyte(RM, VAL); /* store result */ - } - break; - - - default: -// if (i8088_unit.flags & UNIT_OPSTOP) { - reason = STOP_OPCODE; - IP--; -// } - break; - } - /* not segment override */ - if ((IR == 0x26) || (IR == 0x2E) || (IR == 0x36) || (IR == 0x3E)) { - seg_ovr = SEG_NONE; /* clear segment override */ - sysmode &= 0x0000001E; /* clear flags */ - sysmode |= 0x00000001; - } - if (i8088_dev.dctrl & DEBUG_reg) { - sim_printf("\nRegs: AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X IP=%04X\n", - AX, BX, CX, DX, SP, BP, SI, DI, IP); - sim_printf("Segs: CS=%04X DS=%04X ES=%04X SS=%04X Flags: %04X\n", CS, DS, ES, SS, PSW); - } - } -/* Simulation halted */ - - 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 %02X", CS, IP, val); - if (i8088_dev.dctrl & DEBUG_asm) - sim_printf("%04X:%04X %s", CS, IP, opcode[val]); - break; - case 1: /* byte operand fetch */ - if (i8088_dev.dctrl & DEBUG_asm) - 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(" %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(SEG_SS, SP, val >> 8); - SP--; - put_smbyte(SEG_SS, SP, val & 0xFF); -} - -/* pop word primitive */ -uint16 pop_word(void) -{ - register uint16 res; - - //sim_printf("pop_word: entered SS=%04X SP=%04X\n", get_rword(SEG_SS), SP); - res = get_smbyte(SEG_SS, SP); - SP++; - //sim_printf("pop_word: first byte=%04X SS=%04X SP=%04X\n", res, get_rword(SEG_SS), SP); - res |= (get_smbyte(SEG_SS, SP) << 8); - SP++; - //sim_printf("pop_word: val=%04X SS=%04X SP=%04X\n", res, get_rword(SEG_SS), SP); - return res; -} - -/* rcl byte primitive */ -uint8 rcl_byte(uint8 d, uint8 s) -{ - register uint32 res, cnt, mask, cf; - - res = d; - if ((cnt = s % 9)) - { - cf = (d >> (8-cnt)) & 0x1; - res = (d << cnt) & 0xFF; - mask = (1<<(cnt-1)) - 1; - res |= (d >> (9-cnt)) & mask; - if (GET_FLAG(CF)) - res |= 1 << (cnt-1); - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[cf + ((res >> 6) & 0x2)], OF); - } - return res & 0xFF; -} - -/* rcl word primitive */ -uint16 rcl_word(uint16 d, uint16 s) -{ - register uint32 res, cnt, mask, cf; - - res = d; - if ((cnt = s % 17)) - { - cf = (d >> (16-cnt)) & 0x1; - res = (d << cnt) & 0xFFFF; - mask = (1<<(cnt-1)) - 1; - res |= (d >> (17-cnt)) & mask; - if (GET_FLAG(CF)) - res |= 1 << (cnt-1); - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[cf + ((res >> 14) & 0x2)], OF); - } - return res & 0xFFFF; -} - -/* rcr byte primitive */ -uint8 rcr_byte(uint8 d, uint8 s) -{ - uint8 res, cnt; - uint8 mask, cf, ocf = 0; - - res = d; - - if ((cnt = s % 9)) { - if (cnt == 1) { - cf = d & 0x1; - ocf = GET_FLAG(CF) != 0; - } else - cf = (d >> (cnt - 1)) & 0x1; - mask = (1 <<( 8 - cnt)) - 1; - res = (d >> cnt) & mask; - res |= (d << (9-cnt)); - if (GET_FLAG(CF)) - res |= 1 << (8 - cnt); - CONDITIONAL_SET_FLAG(cf, CF); - if (cnt == 1) - CONDITIONAL_SET_FLAG(xor_3_tab[ocf + ((d >> 6) & 0x2)], OF); - } - return res; -} - -/* rcr word primitive */ -uint16 rcr_word(uint16 d, uint16 s) -{ - uint16 res, cnt; - uint16 mask, cf, ocf = 0; - - res = d; - if ((cnt = s % 17)) { - if (cnt == 1) { - cf = d & 0x1; - ocf = GET_FLAG(CF) != 0; - } else - cf = (d >> (cnt-1)) & 0x1; - mask = (1 <<( 16 - cnt)) - 1; - res = (d >> cnt) & mask; - res |= (d << (17 - cnt)); - if (GET_FLAG(CF)) - res |= 1 << (16 - cnt); - CONDITIONAL_SET_FLAG(cf, CF); - if (cnt == 1) - CONDITIONAL_SET_FLAG(xor_3_tab[ocf + ((d >> 14) & 0x2)], OF); - } - return res; -} - -/* rol byte primitive */ -uint8 rol_byte(uint8 d, uint8 s) -{ - register uint32 res, cnt, mask; - - res =d; - - if ((cnt = s % 8)) { - res = (d << cnt); - mask = (1 << cnt) - 1; - res |= (d >> (8-cnt)) & mask; - CONDITIONAL_SET_FLAG(res & 0x1, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res & 0x1) + ((res >> 6) & 0x2)], OF); - } - return res & 0xFF; -} - -/* rol word primitive */ -uint16 rol_word(uint16 d, uint16 s) -{ - register uint32 res, cnt, mask; - - res = d; - if ((cnt = s % 16)) { - res = (d << cnt); - mask = (1 << cnt) - 1; - res |= (d >> (16 - cnt)) & mask; - CONDITIONAL_SET_FLAG(res & 0x1, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res & 0x1) + ((res >> 14) & 0x2)], OF); - } - return res&0xFFFF; -} - -/* ror byte primitive */ -uint8 ror_byte(uint8 d, uint8 s) -{ - register uint32 res, cnt, mask; - - res = d; - if ((cnt = s % 8)) { - res = (d << (8-cnt)); - mask = (1 << (8-cnt)) - 1; - res |= (d >> (cnt)) & mask; - CONDITIONAL_SET_FLAG(res & 0x80, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res >> 6) & 0x3], OF); - } - return res & 0xFF; -} - -/* ror word primitive */ -uint16 ror_word(uint16 d, uint16 s) -{ - register uint32 res, cnt, mask; - - res = d; - if ((cnt = s % 16)) { - res = (d << (16-cnt)); - mask = (1 << (16-cnt)) - 1; - res |= (d >> (cnt)) & mask; - CONDITIONAL_SET_FLAG(res & 0x8000, CF); - CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res >> 14) & 0x3], OF); - } - return res & 0xFFFF; -} - -/* shl byte primitive */ -uint8 shl_byte(uint8 d, uint8 s) -{ - uint32 cnt, res, cf; - - if (s < 8) { - cnt = s % 8; - if (cnt > 0) { - res = d << cnt; - cf = d & (1 << (8 - cnt)); - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG((res & 0xFF)==0, ZF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - } else - res = (uint8) d; - if (cnt == 1) - CONDITIONAL_SET_FLAG((((res & 0x80) == 0x80) ^ - (GET_FLAG( CF) != 0)), OF); - else - CLR_FLAG(OF); - } else { - res = 0; - CONDITIONAL_SET_FLAG((s == 8) && (d & 1), CF); - CLR_FLAG(OF); - CLR_FLAG(SF); - CLR_FLAG(PF); - SET_FLAG(ZF); - } - return res & 0xFF; -} - -/* shl word primitive */ -uint16 shl_word(uint16 d, uint16 s) -{ - uint32 cnt, res, cf; - - if (s < 16) { - cnt = s % 16; - if (cnt > 0) { - res = d << cnt; - cf = d & (1<<(16-cnt)); - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - } else - res = (uint16) d; - if (cnt == 1) - CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ - (GET_FLAG(CF) != 0)), OF); - else - CLR_FLAG(OF); - } else { - res = 0; - CONDITIONAL_SET_FLAG((s == 16) && (d & 1), CF); - CLR_FLAG(OF); - SET_FLAG(ZF); - CLR_FLAG(SF); - CLR_FLAG(PF); - } - return res & 0xFFFF; -} - -/* shr byte primitive */ -uint8 shr_byte(uint8 d, uint8 s) -{ - uint32 cnt, res, cf, mask; - - if (s < 8) { - cnt = s % 8; - if (cnt > 0) { - mask = (1 << (8 - cnt)) - 1; - cf = d & (1 << (cnt - 1)); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - } else - res = (uint8) d; - if (cnt == 1) - CONDITIONAL_SET_FLAG(xor_3_tab[(res >> 6) & 0x3], OF); - else - CLR_FLAG(OF); - } else { - res = 0; - CONDITIONAL_SET_FLAG((s == 8) && (d & 0x80), CF); - CLR_FLAG(OF); - SET_FLAG(ZF); - CLR_FLAG(SF); - CLR_FLAG(PF); - } - return res & 0xFF; -} - -/* shr word primitive */ -uint16 shr_word(uint16 d, uint16 s) -{ - uint32 cnt, res, cf, mask; - - res = d; - if (s < 16) { - cnt = s % 16; - if (cnt > 0) { - mask = (1 << (16 - cnt)) - 1; - cf = d & (1 << (cnt - 1)); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, CF); - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - } else - res = d; - if (cnt == 1) - CONDITIONAL_SET_FLAG(xor_3_tab[(res >> 14) & 0x3], OF); - else - CLR_FLAG(OF); - } else { - res = 0; - CONDITIONAL_SET_FLAG((s == 16) && (d & 0x8000), CF); - CLR_FLAG(OF); - SET_FLAG(ZF); - CLR_FLAG(SF); - CLR_FLAG(PF); - } - return res & 0xFFFF; -} - -/* sar byte primitive */ -uint8 sar_byte(uint8 d, uint8 s) -{ - uint32 cnt, res, cf, mask, sf; - - res = d; - sf = d & 0x80; - cnt = s % 8; - if (cnt > 0 && cnt < 8) { - mask = (1 << (8 - cnt)) - 1; - cf = d & (1 << (cnt -1 )); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, CF); - if (sf) - res |= ~mask; - CONDITIONAL_SET_FLAG((res & 0xFF)==0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - } else if (cnt >= 8) { - if (sf) { - res = 0xFF; - SET_FLAG(CF); - CLR_FLAG(ZF); - SET_FLAG(SF); - SET_FLAG(PF); - } else { - res = 0; - CLR_FLAG(CF); - SET_FLAG(ZF); - CLR_FLAG(SF); - CLR_FLAG(PF); - } - } - return res & 0xFF; -} - -/* sar word primitive */ -uint16 sar_word(uint16 d, uint16 s) -{ - uint32 cnt, res, cf, mask, sf; - - sf = d & 0x8000; - cnt = s % 16; - res = d; - if (cnt > 0 && cnt < 16) { - mask = (1 << (16 - cnt)) - 1; - cf = d & (1 << (cnt - 1)); - res = (d >> cnt) & mask; - CONDITIONAL_SET_FLAG(cf, CF); - if (sf) - res |= ~mask; - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - } else if (cnt >= 16) { - if (sf) { - res = 0xFFFF; - SET_FLAG(CF); - CLR_FLAG(ZF); - SET_FLAG(SF); - SET_FLAG(PF); - } else { - res = 0; - CLR_FLAG(CF); - SET_FLAG(ZF); - CLR_FLAG(SF); - CLR_FLAG(PF); - } - } - return res & 0xFFFF; -} - -/* sbb byte primitive */ -uint8 sbb_byte(uint8 d, uint8 s) -{ - register uint32 res; - register uint32 bc; - - if (GET_FLAG(CF)) - res = d - s - 1; - else - res = d - s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(bc & 0x80, CF); - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); -// return res & 0x0FF; - return (uint8) res; -} - -/* sbb word primitive */ -uint16 sbb_word(uint16 d, uint16 s) -{ - register uint32 res; - register uint32 bc; - - if (GET_FLAG(CF)) - res = d - s - 1; - else - res = d - s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(bc & 0x8000, CF); - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 14) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); -// return res & 0xFFFF; - return (uint16) res; -} - -/* sub byte primitive */ -uint8 sub_byte(uint8 d, uint8 s) -{ - register uint32 res; - register uint32 bc; - - res = d - s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(bc & 0x80, CF); - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); -// return res & 0xff; - return (uint8) res; -} - -/* sub word primitive */ -uint16 sub_word(uint16 d, uint16 s) -{ - register uint32 res; - register uint32 bc; - - res = d - s; - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res &0x8000, SF); - CONDITIONAL_SET_FLAG((res &0xFFFF) == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - /* set flags based on borrow chain */ - CONDITIONAL_SET_FLAG(bc & 0x8000, CF); - CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 14) & 0x3], OF); - CONDITIONAL_SET_FLAG(bc & 0x8, AF); -// return res & 0xffff; - return (uint16) res; -} - -/* test byte primitive */ -void test_byte(uint8 d, uint8 s) -{ - register uint32 res; - - res = d & s; - CLR_FLAG(OF); - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - /* AF == dont care*/ - CLR_FLAG(CF); -} - -/* test word primitive */ -void test_word(uint16 d, uint16 s) -{ - register uint32 res; - - res = d & s; - CLR_FLAG(OF); - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); - /* AF == dont care*/ - CLR_FLAG(CF); -} - -/* xor byte primitive */ -uint8 xor_byte(uint8 d, uint8 s) -{ - register uint8 res; - res = d ^ s; - - /* clear flags */ - CLR_FLAG(OF); - CLR_FLAG(CF); - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x80, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res), PF); - return res; -} - -/* xor word primitive */ -uint16 xor_word(uint16 d, uint16 s) -{ - register uint16 res; - - res = d ^ s; - /* clear flags */ - CLR_FLAG(OF); - CLR_FLAG(CF); - /* set the flags based on the result */ - CONDITIONAL_SET_FLAG(res & 0x8000, SF); - CONDITIONAL_SET_FLAG(res == 0, ZF); - CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); - return res; -} - -/* memory routines. These use the segment register (segreg) value and offset - (addr) to calculate the proper source or destination memory address */ - -/* get a byte from memory */ - -int32 get_smbyte(int32 segreg, int32 addr) -{ - int32 abs_addr, val; - - abs_addr = addr + (get_rword(segreg) << 4); - val = get_mbyte(abs_addr); - //sim_printf("get_smbyte: seg=%04X addr=%04X abs_addr=%05X val=%02X\n", - //get_rword(segreg), addr, abs_addr, val); - return val; -} - -/* get a word from memory using addr and segment register */ - -int32 get_smword(int32 segreg, int32 addr) -{ - int32 val; - - val = get_smbyte(segreg, addr); - val |= (get_smbyte(segreg, addr+1) << 8); - return val; -} - -/* put a byte to memory using addr and segment register */ - -void put_smbyte(int32 segreg, int32 addr, int32 val) -{ - int32 abs_addr; - - abs_addr = addr + (get_rword(segreg) << 4); - put_mbyte(abs_addr, val); - //sim_printf("put_smbyte: seg=%04X addr=%04X abs_addr=%08X val=%02X\n", - //get_rword(segreg), addr, abs_addr, val); -} - -/* put a word to memory using addr and segment register */ - -void put_smword(int32 segreg, int32 addr, int32 val) -{ - put_smbyte(segreg, addr, val); - put_smbyte(segreg, addr+1, val << 8); -} - -/* Reset routine using addr and segment register */ - -t_stat i8088_reset (DEVICE *dptr) -{ - PSW = 0; - CS = 0xFFFF; - DS = 0; - SS = 0; - ES = 0; - saved_PC = 0; - int_req = 0; - sim_brk_types = sim_brk_dflt = SWMASK ('E'); - sim_printf(" 8088 Reset\n"); - return SCPE_OK; -} - -/* Memory examine */ - -t_stat i8088_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ - 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. -*/ - -t_stat sim_load (FILE *fileref, const char *cptr, const 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 == &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 -*/ - -t_stat parse_sym (const char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ - int32 cflag, i = 0, j, r; - char gbuf[CBUFSIZE]; - - 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); -} - -/* end of i8088.c */ - +/* i8088.c: Intel 8086/8088 CPU simulator + + Copyright (C) 1991 Jim Hudgens + + The file is part of GDE. + + GDE is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + GDE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GDE; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + This software was modified by Bill Beech, Mar 2011, from the software GDE + of Jim Hudgens as provided with the SIMH AltairZ80 emulation package. + + Copyright (c) 2011, William A. Beech + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of William A. Beech shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from William A. Beech. + + cpu 8088 CPU + + 17 Mar 11 WAB Original code + + The register state for the 8088 CPU is: + + AX<0:15> AH/AL Register Pair + BX<0:15> BH/BL Register Pair + CX<0:15> CH/CL Register Pair + DX<0:15> DH/DL Register Pair + SI<0:15> Source Index Register + DI<0:15> Destination Index Register + BP<0:15> Base Pointer + SP<0:15> Stack Pointer + CS<0:15> Code Segment Register + DS<0:15> Date Segment Register + SS<0:15> Stack Segment Register + ES<0:15> Extra Segment Register + IP<0:15> Program Counter + + PSW<0:15> Program Status Word - Contains the following flags: + + AF Auxillary Flag + CF Carry Flag + OF Overflow Flag + SF Sign Flag + PF Parity Flag + ZF Zero Flag + DF Direction Flag + IF Interrupt Enable Flag + TF Trap Flag + + in bit positions: + 15 8 7 0 + |--|--|--|--|OF|DF|IF|TF|SF|ZF|--|AF|--|PF|--|CF| + + The 8088 is an 8-bit CPU, which uses 16-bit offset and segment registers + in combination with a dedicated adder to address up to 1MB of memory directly. + The offset register is added to the segment register shifted left 4 places + to obtain the 20-bit address. + + The CPU utilizes two separate processing units - the Execution Unit (EU) and + the Bus Interface Unit (BIU). The EU executes instructions. The BIU fetches + instructions, reads operands and writes results. The two units can operate + independently of one another and are able, under most circumstances, to + extensively overlap instruction fetch with execution. + + The BIUs of the 8086 and 8088 are functionally identical, but are implemented + differently to match the structure and performance characteristics of their + respective buses. + + The almost 300 instructions come in 1, 2, 3, 4, 5, 6 and 7-byte flavors. + + This routine is the simulator for the 8088. It is called from the + simulator control program to execute instructions in simulated memory, + starting at the simulated IP. It runs until 'reason' is set non-zero. + + General notes: + + 1. Reasons to stop. The simulator can be stopped by: + + HALT instruction + I/O error in I/O simulator + Invalid OP code (if ITRAP is set on CPU) + + 2. Interrupts. + There are 256 possible levels of interrupt, and in effect they + do a hardware CALL instruction to one of 256 possible low + memory addresses. + + 3. Non-existent memory. On the 8088, reads to non-existent memory + return 0FFh, and writes are ignored. + + Some algorithms were pulled from the GDE Dos/IP Emulator by Jim Hudgens + +*/ +/* + This algorithm was pulled from the GDE Dos/IP Emulator by Jim Hudgens + +CARRY CHAIN CALCULATION. + This represents a somewhat expensive calculation which is + apparently required to emulate the setting of the OF and + AF flag. The latter is not so important, but the former is. + The overflow flag is the XOR of the top two bits of the + carry chain for an addition (similar for subtraction). + Since we do not want to simulate the addition in a bitwise + manner, we try to calculate the carry chain given the + two operands and the result. + + So, given the following table, which represents the + addition of two bits, we can derive a formula for + the carry chain. + + a b cin r cout + 0 0 0 0 0 + 0 0 1 1 0 + 0 1 0 1 0 + 0 1 1 0 1 + 1 0 0 1 0 + 1 0 1 0 1 + 1 1 0 0 1 + 1 1 1 1 1 + + Construction of table for cout: + + ab + r \ 00 01 11 10 + |------------------ + 0 | 0 1 1 1 + 1 | 0 0 1 0 + + By inspection, one gets: cc = ab + r'(a + b) + + That represents alot of operations, but NO CHOICE.... + +BORROW CHAIN CALCULATION. + The following table represents the + subtraction of two bits, from which we can derive a formula for + the borrow chain. + + a b bin r bout + 0 0 0 0 0 + 0 0 1 1 1 + 0 1 0 1 1 + 0 1 1 0 1 + 1 0 0 1 0 + 1 0 1 0 0 + 1 1 0 0 0 + 1 1 1 1 1 + + Construction of table for cout: + + ab + r \ 00 01 11 10 + |------------------ + 0 | 0 1 0 0 + 1 | 1 1 1 0 + + By inspection, one gets: bc = a'b + r(a' + b) + + Segment register selection and overrides are handled as follows: + If there is a segment override, the register number is stored + in seg_ovr. If there is no override, seg_ovr is zero. Seg_ovr + is set to zero after each instruction except segment override + instructions. + + Get_ea sets the value of seg_reg to the override if present + otherwise to the default value for the registers used in the + effective address calculation. + + The get/put_smword/byte routines use the register number in + seg_reg to obtain the segment value to calculate the absolute + memory address for the operation. + */ + +#include +#include "system_defs.h" + +#define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */ +#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) +#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8088 or 8086 */ +#define UNIT_CHIP (1 << UNIT_V_CHIP) + +/* Flag values to set proper positions in PSW */ +#define CF 0x0001 +#define PF 0x0004 +#define AF 0x0010 +#define ZF 0x0040 +#define SF 0x0080 +#define TF 0x0100 +#define IF 0x0200 +#define DF 0x0400 +#define OF 0x0800 + +/* Macros to handle the flags in the PSW + 8088 has top 4 bits of the flags set to 1 + also, bit#1 is set. This is (not well) documented behavior. */ +#define PSW_ALWAYS_ON (0xF002) /* for 8086 */ +#define PSW_MSK (CF|PF|AF|ZF|SF|TF|IF|DF|OF) +#define TOGGLE_FLAG(FLAG) (PSW ^= FLAG) +#define SET_FLAG(FLAG) (PSW |= FLAG) +#define CLR_FLAG(FLAG) (PSW &= ~FLAG) +#define GET_FLAG(FLAG) (PSW & FLAG) +#define CONDITIONAL_SET_FLAG(COND,FLAG) \ + if (COND) SET_FLAG(FLAG); else CLR_FLAG(FLAG) + +/* union of byte and word registers */ +union { + uint8 b[2]; /* two bytes */ + uint16 w; /* one word */ +} A, B, C, D; /* storage for AX, BX, CX and DX */ + +/* macros for byte registers */ +#define AH (A.b[1]) +#define AL (A.b[0]) +#define BH (B.b[1]) +#define BL (B.b[0]) +#define CH (C.b[1]) +#define CL (C.b[0]) +#define DH (D.b[1]) +#define DL (D.b[0]) + +/* macros for word registers */ +#define AX (A.w) +#define BX (B.w) +#define CX (C.w) +#define DX (D.w) + +/* macros for handling IP and SP */ +#define INC_IP1 (++IP & ADDRMASK16) /* increment IP one byte */ +#define INC_IP2 ((IP += 2) & ADDRMASK16) /* 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 0x01 = int, 0x02 = NMI*/ +uint16 port; //port called in dev_table[port] +int32 chip = 0; /* 0 = 8088 chip, 1 = 8086 chip */ +#define CHIP_8088 0 /* processor types */ +#define CHIP_8086 1 +#define CHIP_80188 2 +#define CHIP_80186 3 +#define CHIP_80286 4 + +int32 seg_ovr = 0; /* segment override register */ +int32 seg_reg = 0; /* segment register to use for EA */ +#define SEG_NONE 0 /* segmenr override register values */ +#define SEG_CS 8 +#define SEG_DS 9 +#define SEG_ES 10 +#define SEG_SS 11 + +int32 PCX; /* External view of IP */ + +/* handle prefix instructions */ +uint32 sysmode = 0; /* prefix flags */ +#define SYSMODE_SEG_DS_SS 0x01 +#define SYSMODE_SEGOVR_CS 0x02 +#define SYSMODE_SEGOVR_DS 0x04 +#define SYSMODE_SEGOVR_ES 0x08 +#define SYSMODE_SEGOVR_SS 0x10 +#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | SYSMODE_SEGOVR_CS | \ + SYSMODE_SEGOVR_DS | SYSMODE_SEGOVR_ES | SYSMODE_SEGOVR_SS) +#define SYSMODE_PREFIX_REPE 0x20 +#define SYSMODE_PREFIX_REPNE 0x40 + +/* function prototypes */ +int32 sign_ext(int32 val); +int32 fetch_byte(int32 flag); +int32 fetch_word(void); +int32 parity(int32 val); +void i86_intr_raise(uint8 num); +uint32 get_rbyte(uint32 reg); +uint32 get_rword(uint32 reg); +void put_rbyte(uint32 reg, uint32 val); +void put_rword(uint32 reg, uint32 val); +uint32 get_ea(uint32 mrr); +void set_segreg(uint32 reg); +void get_mrr_dec(uint32 mrr, uint32 *mod, uint32 *reg, uint32 *rm); +void rm_byte_dec(uint32 rm); +void rm_word_dec(uint32 rm); +void rm_seg_dec(uint32 rm); + +/* emulator primitives function prototypes */ +uint8 aad_word(uint16 d); +uint16 aam_word(uint8 d); +uint8 adc_byte(uint8 d, uint8 s); +uint16 adc_word(uint16 d, uint16 s); +uint8 add_byte(uint8 d, uint8 s); +uint16 add_word(uint16 d, uint16 s); +uint8 and_byte(uint8 d, uint8 s); +uint16 cmp_word(uint16 d, uint16 s); +uint8 cmp_byte(uint8 d, uint8 s); +uint16 and_word(uint16 d, uint16 s); +uint8 dec_byte(uint8 d); +uint16 dec_word(uint16 d); +void div_byte(uint8 s); +void div_word(uint16 s); +void idiv_byte(uint8 s); +void idiv_word(uint16 s); +void imul_byte(uint8 s); +void imul_word(uint16 s); +uint8 inc_byte(uint8 d); +uint16 inc_word(uint16 d); +void mul_byte(uint8 s); +void mul_word(uint16 s); +uint8 neg_byte(uint8 s); +uint16 neg_word(uint16 s); +uint8 not_byte(uint8 s); +uint16 not_word(uint16 s); +uint8 or_byte(uint8 d, uint8 s); +uint16 or_word(uint16 d, uint16 s); +void push_word(uint16 val); +uint16 pop_word(void); +uint8 rcl_byte(uint8 d, uint8 s); +uint16 rcl_word(uint16 d, uint16 s); +uint8 rcr_byte(uint8 d, uint8 s); +uint16 rcr_word(uint16 d, uint16 s); +uint8 rol_byte(uint8 d, uint8 s); +uint16 rol_word(uint16 d, uint16 s); +uint8 ror_byte(uint8 d, uint8 s); +uint16 ror_word(uint16 d, uint16 s); +uint8 shl_byte(uint8 d, uint8 s); +uint16 shl_word(uint16 d, uint16 s); +uint8 shr_byte(uint8 d, uint8 s); +uint16 shr_word(uint16 d, uint16 s); +uint8 sar_byte(uint8 d, uint8 s); +uint16 sar_word(uint16 d, uint16 s); +uint8 sbb_byte(uint8 d, uint8 s); +uint16 sbb_word(uint16 d, uint16 s); +uint8 sub_byte(uint8 d, uint8 s); +uint16 sub_word(uint16 d, uint16 s); +void test_byte(uint8 d, uint8 s); +void test_word(uint16 d, uint16 s); +uint8 xor_byte(uint8 d, uint8 s); +uint16 xor_word(uint16 d, uint16 s); +int32 get_smbyte(int32 segreg, int32 addr); +int32 get_smword(int32 segreg, int32 addr); +void put_smbyte(int32 segreg, int32 addr, int32 val); +void put_smword(int32 segreg, int32 addr, int32 val); + +/* simulator routines */ +void set_cpuint(int32 int_num); +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 */ + +/* memory read and write absolute address routines */ +extern uint8 get_mbyte(uint32 addr); +extern uint16 get_mword(uint32 addr); +extern void put_mbyte(uint32 addr, uint8 val); +extern void put_mword(uint32 addr, uint16 val); + +extern int32 sim_int_char; +extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ + +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_CHIP, UNIT_CHIP, "8086", "8086", NULL }, + { UNIT_CHIP, 0, "8088", "8088", NULL }, + { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL }, + { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL }, + { 0 } +}; + +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 = { + "8088", //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 + DEBUG_asm+DEBUG_level1, //dctrl +// DEBUG_reg+DEBUG_asm+DEBUG_level1, //dctrl +// DEBUG_asm, //dctrl + i8088_debug, //debflags + NULL, //msize + NULL //lname +}; + +uint8 xor_3_tab[] = { 0, 1, 1, 0 }; + +int32 IP; + +static const char *opcode[] = { +"ADD\t", "ADD\t", "ADD\t", "ADD\t", /* 0x00 */ +"ADD\tAL,", "ADD\tAX,", "PUSH\tES", "POP\tES", +"OR\t", "OR\t", "OR\t", "OR\t", +"OR\tAL,", "OR\tAX,", "PUSH\tCS", "0F\t", +"ADC\t", "ADC\t", "ADC\t", "ADC\t", /* 0x10 */ +"ADC\tAL,", "ADC\tAX,", "PUSH\tSS", "POP\tSS", +"SBB\t", "SBB\t", "SBB\t", "SBB\t", +"SBB\tAL,", "SBB\tAX,", "PUSH\tDS", "POP\tDS", +"AND\t", "AND\t", "AND\t", "AND\t", /* 0x20 */ +"AND\tAL,", "AND\tAX,", "ES:", "DAA", +"SUB\t", "SUB\t", "SUB\t", "SUB\t", +"SUB\tAL,", "SUB\tAX,", "CS:", "DAS", +"XOR\t", "XOR\t", "XOR\t", "XOR\t", /* 0x30 */ +"XOR\tAL,", "XOR\tAX,", "SS:", "AAA", +"CMP\t", "CMP\t", "CMP\t", "CMP\t", +"CMP\tAL,", "CMP\tAX,", "DS:", "AAS", +"INC\tAX", "INC\tCX", "INC\tDX", "INC\tBX", /* 0x40 */ +"INC\tSP", "INC\tBP", "INC\tSI", "INC\tDI", +"DEC\tAX", "DEC\tCX", "DEC\tDX", "DEC\tBX", +"DEC\tSP", "DEC\tBP", "DEC\tSI", "DEC\tDI", +"PUSH\tAX", "PUSH\tCX", "PUSH\tDX", "PUSH\tBX", /* 0x50 */ +"PUSH\tSP", "PUSH\tBP", "PUSH\tSI", "PUSH\tDI", +"POP\tAX", "POP\tCX", "POP\tDX", "POP\tBX", +"POP\tSP", "POP\tBP", "POP\tSI", "POP\tDI", +"60\t", "61\t", "62\t", "63\t", /* 0x60 */ +"64\t", "65\t", "66\t", "67\t", +"68\t", "69\t", "6A\t", "6B\t", +"6C\t", "6D\t", "6E\t", "6F\t", +"JO\t", "JNO\t", "JC\t", "JNC\t", /* 0x70 */ +"JZ\t", "JNZ\t", "JNA\t", "JA\t", +"JS\t", "JNS\t", "JP\t", "JNP\t", +"JL\t", "JNL\t", "JLE\t", "JNLE\t", +"80\t", "81\t", "82\t", "83\t", /* 0x80 */ +"TEST\t", "TEST\t", "XCHG\t", "XCHG\t", +"MOV\t", "MOV\t", "MOV\t", "MOV\t", +"MOV\t", "LEA\t", "MOV\t", "POP\t", +"NOP", "XCHG\tAX,CX", "XCHG\tAX,DX", "XCHG\tAX,BX",/* 0x90 */ +"XCHG\tAX,SP", "XCHG\tAX,BP", "XCHG\tAX,SI", "XCHG\tAX,DI", +"CBW", "CWD", "CALL\t", "WAIT", +"PUSHF", "POPF", "SAHF", "LAHF", +"MOV\tAL,", "MOV\tAX,", "MOV\t", "MOV\t", /* 0xA0 */ +"MOVSB", "MOVSW", "CMPSB", "CMPSW", +"TEST\tAL,", "TEST\tAX,", "STOSB", "STOSW", +"LODSB", "LODSW", "SCASB", "SCASW", +"MOV\tAL,", "MOV\tCL,", "MOV\tDL,", "MOV\tBL,", /* 0xB0 */ +"MOV\tAH,", "MOV\tCH,", "MOV\tDH,", "MOV\tBH,", +"MOV\tAX,", "MOV\tCX,", "MOV\tDX,", "MOV\tBX,", +"MOV\tSP,", "MOV\tBP,", "MOV\tSI,", "MOV\tDI," +"C0\t", "C1\t", "RET ", "RET ", /* 0xC0 */ +"LES\t", "LDS\t", "MOV\t", "MOV\t", +"C8\t", "C9\t", "RET ", "RET", +"INT\t3", "INT\t", "INTO", "IRET", +"SHL\t", "D1\t", "SHR\t", "D3\t", /* 0xD0 */ +"AAM", "AAD", "D6\t", "XLATB", +"ESC\t", "ESC\t", "ESC\t", "ESC\t", +"ESC\t", "ESC\t", "ESC\t", "ESC\t", +"LOOPNZ\t", "LOOPZ\t", "LOOP\t", "JCXZ\t", /* 0xE0 */ +"IN\tAL,", "IN\tAX,", "OUT\t", "OUT\t", +"CALL\t", "JMP\t", "JMP\t", "JMP\t", +"IN\tAL,DX", "IN\tAX,DX", "OUT\tDX,AL", "OUT\tDX,AX", +"LOCK", "F1\t", "REPNZ", "REPZ", /* 0xF0 */ +"HLT", "CMC", "F6\t", "F7\t", +"CLC", "STC", "CLI", "STI", +"CLD", "STD", "FE\t", "FF\t" +}; + +/* +0 = 1 byte opcaode +1 = DATA8 +2 = DATA16 +3 = IP-INC8 +4 = IP-INC16 +20 = I haven't figured it out yet! +*/ + +int32 oplen[256] = { +20,20,20,20, 1, 2, 0, 0, 20,20,20,20, 1, 2, 0, 0, //0x00 +20,20,20,20, 1, 2, 0, 0, 20,20,20,20, 1, 2, 0, 0, //0x10 +20,20,20,20, 1, 2, 0, 0, 20,20,20,20, 1, 2, 0, 0, //0x20 +20,20,20,20, 1, 2, 0, 0, 20,20,20,20, 1, 2, 0, 0, //0x30 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x40 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x50 +20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20, //0x60 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, //0x70 +20,20,20,20,20,20,20,20, 20,20,20,20,20,20,20,20, //0x80 + 0, 0, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0, 0, 0, 0, //0x90 +20,20,20,20, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, //0xA0 + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, //0xB0 + 0, 0, 2, 0,20,20,20,20, 0, 0, 2, 0, 0, 1, 0, 0, //0xC0 +20,20,20,20, 0, 0, 0, 0, 20,20,20,20,20,20,20,20, //0xD0 + 3, 3, 3, 3, 1, 1, 1, 1, 4, 4,20, 3, 0, 0, 0, 0, //0xE0 + 0, 0, 0, 0, 0, 0,20,20, 0, 0, 0, 0, 0, 0,20,20, //0xF0 +}; + +void set_cpuint(int32 int_num) +{ + int_req |= int_num; +} + + +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 (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 */ + + /* The Big Instruction Decode Switch */ + + switch (IR) { + + /* instructions in numerical order */ + + case 0x00: /* ADD byte - REG = REG + (EA) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = add_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = add_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x01: /* ADD word - (EA) = (EA) + REG */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = add_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = add_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x02: /* ADD byte - REG = REG + (EA) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = add_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = add_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x03: /* ADD word - (EA) = (EA) + REG */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = adc_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x04: /* ADD byte - AL = AL + DATA */ + DATA = fetch_byte(1); + VAL = add_byte(AL, DATA); /* do operation */ + AL = VAL; /* store result */ + break; + + case 0x05: /* ADD word - (EA) = (EA) + REG */ + DATA = fetch_word(); + VAL = add_word(AX, DATA); /* do operation */ + AX = VAL; /* store result */ + break; + + case 0x06: /* PUSH ES */ + push_word(ES); + break; + + case 0x07: /* POP ES */ + ES = pop_word(); + break; + + case 0x08: /* OR byte - REG = REG OR (EA) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = or_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = or_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x09: /* OR word - (EA) = (EA) OR REG */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = or_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = or_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x0A: /* OR byte - REG = REG OR (EA) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = or_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = or_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x0B: /* OR word - (EA) = (EA) OR REG */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = or_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = or_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x0C: /* OR byte - AL = AL OR DATA */ + DATA = fetch_byte(1); + VAL = or_byte(AL, DATA); /* do operation */ + AL = VAL; /* store result */ + break; + + case 0x0D: /* OR word - (EA) = (EA) OR REG */ + DATA = fetch_word(); + VAL = or_word(AX, DATA); /* do operation */ + AX = VAL; /* store result */ + break; + + case 0x0E: /* PUSH CS */ + push_word(CS); + break; + + /* 0x0F - Not implemented on 8086/8088 */ + + case 0x10: /* ADC byte - REG = REG + (EA) + CF */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = adc_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = adc_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x11: /* ADC word - (EA) = (EA) + REG + CF */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = adc_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x12: /* ADC byte - REG = REG + (EA) + CF */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = adc_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = adc_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x13: /* ADC word - (EA) = (EA) + REG + CF */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = adc_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = adc_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x14: /* ADC byte - AL = AL + DATA + CF */ + DATA = fetch_byte(1); + VAL = adc_byte(AL, DATA); /* do operation */ + AL = VAL; /* store result */ + break; + + case 0x15: /* ADC word - (EA) = (EA) + REG + CF */ + DATA = fetch_word(); + VAL = adc_word(AX, DATA); /* do operation */ + AX = VAL; /* store result */ + break; + + case 0x16: /* PUSH SS */ + push_word(SS); + break; + + case 0x17: /* POP SS */ + SS = pop_word(); + break; + + case 0x18: /* SBB byte - REG = REG - (EA) - CF */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = sbb_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = sbb_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x19: /* SBB word - (EA) = (EA) - REG - CF */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = sbb_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = sbb_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x1A: /* SBB byte - REG = REG - (EA) - CF */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = sbb_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = sbb_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x1B: /* SBB word - (EA) = (EA) - REG - CF */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = sbb_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = sbb_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x1C: /* SBB byte - AL = AL - DATA - CF */ + DATA = fetch_byte(1); + VAL = sbb_byte(AL, DATA); /* do operation */ + AL = VAL; /* store result */ + break; + + case 0x1D: /* SBB word - (EA) = (EA) - REG - CF */ + DATA = fetch_word(); + VAL = sbb_word(AX, DATA); /* do operation */ + AX = VAL; /* store result */ + break; + + case 0x1E: /* PUSH DS */ + push_word(DS); + break; + + case 0x1F: /* POP DS */ + DS = pop_word(); + break; + + case 0x20: /* AND byte - REG = REG AND (EA) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = and_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = and_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x21: /* AND word - (EA) = (EA) AND REG */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = and_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = and_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x22: /* AND byte - REG = REG AND (EA) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = and_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = and_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x23: /* AND word - (EA) = (EA) AND REG */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = and_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = and_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x24: /* AND byte - AL = AL AND DATA */ + DATA = fetch_byte(1); + VAL = and_byte(AL, DATA); /* do operation */ + AL = VAL; /* store result */ + break; + + case 0x25: /* AND word - (EA) = (EA) AND REG */ + DATA = fetch_word(); + VAL = and_word(AX, DATA); /* do operation */ + AX = VAL; /* store result */ + break; + + case 0x26: /* ES: - segment override prefix */ + seg_ovr = SEG_ES; + sysmode |= SYSMODE_SEGOVR_ES; + break; + + case 0x27: /* DAA */ + if (((AL & 0xF) > 9) || GET_FLAG(AF)) { + AL += 6; + SET_FLAG(AF); + } + if ((AL > 0x9F) || GET_FLAG(CF)) { + AL += 0x60; + SET_FLAG(CF); + } + break; + + case 0x28: /* SUB byte - REG = REG - (EA) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = sub_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = sub_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x29: /* SUB word - (EA) = (EA) - REG */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = sub_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = sub_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x2A: /* SUB byte - REG = REG - (EA) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = sub_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = sub_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x2B: /* SUB word - (EA) = (EA) - REG */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = sub_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = sub_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x2C: /* SUB byte - AL = AL - DATA */ + DATA = fetch_byte(1); + VAL = sub_byte(AL, DATA); /* do operation */ + AL = VAL; /* store result */ + break; + + case 0x2D: /* SUB word - (EA) = (EA) - REG */ + DATA = fetch_word(); + VAL = sub_word(AX, DATA); /* do operation */ + AX = VAL; /* store result */ + break; + + case 0x2E: /* DS: - segment override prefix */ + seg_ovr = SEG_DS; + sysmode |= SYSMODE_SEGOVR_DS; + break; + + case 0x2F: /* DAS */ + if (((AL & 0xF) > 9) || GET_FLAG(AF)) { + AL -= 6; + SET_FLAG(AF); + } + if ((AL > 0x9F) || GET_FLAG(CF)) { + AL -= 0x60; + SET_FLAG(CF); + } + break; + + case 0x30: /* XOR byte - REG = REG XOR (EA) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x31: /* XOR word - (EA) = (EA) XOR REG */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x32: /* XOR byte - REG = REG XOR (EA) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x33: /* XOR word - (EA) = (EA) XOR REG */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x34: /* XOR byte - AL = AL XOR DATA */ + DATA = fetch_byte(1); + VAL = xor_byte(AL, DATA); /* do operation */ + AL = VAL; /* store result */ + break; + + case 0x35: /* XOR word - (EA) = (EA) XOR REG */ + DATA = fetch_word(); + VAL = xor_word(AX, DATA); /* do operation */ + AX = VAL; /* store result */ + break; + + case 0x36: /* SS: - segment override prefix */ + seg_ovr = SEG_SS; + sysmode |= SYSMODE_SEGOVR_SS; + break; + + case 0x37: /* AAA */ + if (((AL & 0xF) > 9) || GET_FLAG(AF)) { + AL += 6; + AH++; + SET_FLAG(AF); + } + CONDITIONAL_SET_FLAG(GET_FLAG(AF), CF); + AL &= 0xF; + break; + + case 0x38: /* CMP byte - CMP (REG, (EA)) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x39: /* CMP word - CMP ((EA), REG) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x3A: /* CMP byte - CMP (REG, (EA)) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = xor_byte(get_rbyte(REG), get_smbyte(seg_reg, EA)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } else { /* RM is second register */ + VAL = xor_byte(get_rbyte(REG), get_rbyte(RM)); /* do operation */ + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x3B: /* CMP word - CMP ((EA), REG) */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = xor_word(get_rword(REG), get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + } else { /* RM is second register */ + VAL = xor_word(get_rword(REG), get_rword(RM)); /* do operation */ + put_rword(REG, VAL); /* store result */ + } + break; + + case 0x3C: /* CMP byte - CMP (AL, DATA) */ + DATA = fetch_byte(1); + VAL = xor_byte(AL, DATA); /* do operation */ + AL = VAL; /* store result */ + break; + + case 0x3D: /* CMP word - CMP ((EA), REG) */ + DATA = fetch_word(); + VAL = xor_word(AX, DATA); /* do operation */ + AX = VAL; /* store result */ + break; + + case 0x3E: /* DS: - segment override prefix */ + seg_ovr = SEG_DS; + sysmode |= SYSMODE_SEGOVR_DS; + break; + + case 0x3F: /* AAS */ + if (((AL & 0xF) > 9) || GET_FLAG(AF)) { + AL -= 6; + AH--; + SET_FLAG(AF); + } + CONDITIONAL_SET_FLAG(GET_FLAG(AF), CF); + AL &= 0xF; + break; + + case 0x40: /* INC AX */ + AX = inc_word(AX); + break; + + case 0x41: /* INC CX */ + CX = inc_word(CX); + break; + + case 0x42: /* INC DX */ + DX = inc_word(DX); + break; + + case 0x43: /* INC BX */ + BX = inc_word(BX); + break; + + case 0x44: /* INC SP */ + SP = inc_word(SP); + break; + + case 0x45: /* INC BP */ + BP = inc_word(BP); + break; + + case 0x46: /* INC SI */ + SI = inc_word(SI); + break; + + case 0x47: /* INC DI */ + DI = inc_word(DI); + break; + + case 0x48: /* DEC AX */ + AX = dec_word(AX); + break; + + case 0x49: /* DEC CX */ + CX = dec_word(CX); + break; + + case 0x4A: /* DEC DX */ + DX = dec_word(DX); + break; + + case 0x4B: /* DEC BX */ + BX = dec_word(BX); + break; + + case 0x4C: /* DEC SP */ + SP = dec_word(SP); + break; + + case 0x4D: /* DEC BP */ + BP = dec_word(BP); + break; + + case 0x4E: /* DEC SI */ + SI = dec_word(SI); + break; + + case 0x4F: /* DEC DI */ + DI = dec_word(DI); + break; + + case 0x50: /* PUSH AX */ + push_word(AX); + break; + + case 0x51: /* PUSH CX */ + push_word(CX); + break; + + case 0x52: /* PUSH DX */ + push_word(DX); + break; + + case 0x53: /* PUSH BX */ + push_word(BX); + break; + + case 0x54: /* PUSH SP */ + push_word(SP); + break; + + case 0x55: /* PUSH BP */ + push_word(BP); + break; + + case 0x56: /* PUSH SI */ + push_word(SI); + break; + + case 0x57: /* PUSH DI */ + push_word(DI); + break; + + case 0x58: /* POP AX */ + AX = pop_word(); + break; + + case 0x59: /* POP CX */ + CX = pop_word(); + break; + + case 0x5A: /* POP DX */ + DX = pop_word(); + break; + + case 0x5B: /* POP BX */ + BX = pop_word(); + break; + + case 0x5C: /* POP SP */ + SP = pop_word(); + break; + + case 0x5D: /* POP BP */ + BP = pop_word(); + break; + + case 0x5E: /* POP SI */ + SI = pop_word(); + break; + + case 0x5F: /* POP DI */ + DI = pop_word(); + break; + + /* 0x60 - 0x6F - Not implemented on 8086/8088 */ + + case 0x70: /* JO short label */ + /* jump to byte offset if overflow flag is set */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (GET_FLAG(OF)) + IP = EA; + break; + + case 0x71: /* JNO short label */ + /* jump to byte offset if overflow flag is clear */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (!GET_FLAG(OF)) + IP = EA; + break; + + case 0x72: /* JB/JNAE/JC short label */ + /* jump to byte offset if carry flag is set. */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (GET_FLAG(CF)) + IP = EA; + break; + + case 0x73: /* JNB/JAE/JNC short label */ + /* jump to byte offset if carry flsg is clear */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (!GET_FLAG(CF)) + IP = EA; + break; + + case 0x74: /* JE/JZ short label */ + /* jump to byte offset if zero flag is set */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (GET_FLAG(ZF)) + IP = EA; + break; + + case 0x75: /* JNE/JNZ short label */ + /* jump to byte offset if zero flag is clear */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (!GET_FLAG(ZF)) + IP = EA; + break; + + case 0x76: /* JBE/JNA short label */ + /* jump to byte offset if carry flag is set or if the zero + flag is set. */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (GET_FLAG(CF) || GET_FLAG(ZF)) + IP = EA; + break; + + case 0x77: /* JNBE/JA short label */ + /* jump to byte offset if carry flag is clear and if the zero + flag is clear */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (!(GET_FLAG(CF) || GET_FLAG(ZF))) + IP = EA; + break; + + case 0x78: /* JS short label */ + /* jump to byte offset if sign flag is set */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (GET_FLAG(SF)) + IP = EA; + break; + + case 0x79: /* JNS short label */ + /* jump to byte offset if sign flag is clear */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (!GET_FLAG(SF)) + IP = EA; + break; + + case 0x7A: /* JP/JPE short label */ + /* jump to byte offset if parity flag is set (even) */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (GET_FLAG(PF)) + IP = EA; + break; + + case 0x7B: /* JNP/JPO short label */ + /* jump to byte offset if parity flsg is clear (odd) */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (!GET_FLAG(PF)) + IP = EA; + break; + + case 0x7C: /* JL/JNGE short label */ + /* jump to byte offset if sign flag not equal to overflow flag. */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if ((GET_FLAG(SF) != 0) ^ (GET_FLAG(OF) != 0)) + IP = EA; + break; + + case 0x7D: /* JNL/JGE short label */ + /* jump to byte offset if sign flag equal to overflow flag. */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if ((GET_FLAG(SF) != 0) == (GET_FLAG(OF) != 0)) + IP = EA; + break; + + case 0x7E: /* JLE/JNG short label */ + /* jump to byte offset if sign flag not equal to overflow flag + or the zero flag is set */ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (((GET_FLAG(SF) != 0) ^ (GET_FLAG(OF) != 0)) || GET_FLAG(ZF)) + IP = EA; + break; + + case 0x7F: /* JNLE/JG short label */ + /* jump to byte offset if sign flag equal to overflow flag. + and the zero flag is clear*/ + OFF = sign_ext(fetch_byte(1)); + EA = (IP + OFF) & ADDRMASK16; + if (((GET_FLAG(SF) != 0) == (GET_FLAG(OF) != 0)) || !GET_FLAG(ZF)) + IP = EA; + break; + + case 0x80: /* ADD/OR/ADC/SBB/AND/SUB/XOR/CMP byte operands */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + DATA = fetch_byte(1); /* must be done after DISP is collected */ + switch(REG) { + case 0: + VAL = add_byte(get_smbyte(seg_reg, EA), DATA); /* ADD mem8, immed8 */ + break; + case 1: + VAL = or_byte(get_smbyte(seg_reg, EA), DATA); /* OR mem8, immed8 */ + break; + case 2: + VAL = adc_byte(get_smbyte(seg_reg, EA), DATA); /* ADC mem8, immed8 */ + break; + case 3: + VAL = sbb_byte(get_smbyte(seg_reg, EA), DATA); /* SBB mem8, immed8 */ + break; + case 4: + VAL = and_byte(get_smbyte(seg_reg, EA), DATA); /* AND mem8, immed8 */ + break; + case 5: + VAL = sub_byte(get_smbyte(seg_reg, EA), DATA); /* SUB mem8, immed8 */ + break; + case 6: + VAL = xor_byte(get_smbyte(seg_reg, EA), DATA); /* XOR mem8, immed8 */ + break; + case 7: + VAL = cmp_byte(get_smbyte(seg_reg, EA), DATA); /* CMP mem8, immed8 */ + break; + } + put_rbyte(EA, VAL); /* store result */ + } else { /* RM is second register */ + switch(REG) { + case 0: + VAL = add_byte(get_rbyte(RM), DATA); /* ADD REG8, immed8 */ + break; + case 1: + VAL = or_byte(get_rbyte(RM), DATA); /* OR REG8, immed8 */ + break; + case 2: + VAL = adc_byte(get_rbyte(RM), DATA); /* ADC REG8, immed8 */ + break; + case 3: + VAL = sbb_byte(get_rbyte(RM), DATA); /* SBB REG8, immed8 */ + break; + case 4: + VAL = and_byte(get_rbyte(RM), DATA); /* AND REG8, immed8 */ + break; + case 5: + VAL = sub_byte(get_rbyte(RM), DATA); /* SUB REG8, immed8 */ + break; + case 6: + VAL = xor_byte(get_rbyte(RM), DATA); /* XOR REG8, immed8 */ + break; + case 7: + VAL = cmp_byte(get_rbyte(RM), DATA); /* CMP REG8, immed8 */ + break; + } + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x81: /* word operands */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + DATA = fetch_byte(1) << 8; /* must be done after DISP is collected */ + DATA |= fetch_byte(1); + switch(REG) { + case 0: + VAL = add_word(get_smword(seg_reg, EA), DATA); /* ADD mem16, immed16 */ + break; + case 1: + VAL = or_word(get_smword(seg_reg, EA), DATA); /* OR mem16, immed16 */ + break; + case 2: + VAL = adc_word(get_smword(seg_reg, EA), DATA); /* ADC mem16, immed16 */ + break; + case 3: + VAL = sbb_word(get_smword(seg_reg, EA), DATA); /* SBB mem16, immed16 */ + break; + case 4: + VAL = and_word(get_smword(seg_reg, EA), DATA); /* AND mem16, immed16 */ + break; + case 5: + VAL = sub_word(get_smword(seg_reg, EA), DATA); /* SUB mem16, immed16 */ + break; + case 6: + VAL = xor_word(get_smword(seg_reg, EA), DATA); /* XOR mem16, immed16 */ + break; + case 7: + VAL = cmp_word(get_smword(seg_reg, EA), DATA); /* CMP mem16, immed16 */ + break; + } + put_rword(EA, VAL); /* store result */ + } else { /* RM is second register */ + switch(REG) { + case 0: + VAL = add_word(get_rword(RM), DATA); /* ADD reg16, immed16 */ + break; + case 1: + VAL = or_word(get_rword(RM), DATA); /* OR reg16, immed16 */ + break; + case 2: + VAL = adc_word(get_rword(RM), DATA); /* ADC reg16, immed16 */ + break; + case 3: + VAL = sbb_word(get_rword(RM), DATA); /* SBB reg16, immed16 */ + break; + case 4: + VAL = and_word(get_rword(RM), DATA); /* AND reg16, immed16 */ + break; + case 5: + VAL = sub_word(get_rword(RM), DATA); /* SUB reg16, immed16 */ + break; + case 6: + VAL = xor_word(get_rword(RM), DATA); /* XOR reg16, immed16 */ + break; + case 7: + VAL = cmp_word(get_rword(RM), DATA); /* CMP reg16, immed16 */ + break; + } + put_rword(RM, VAL); /* store result */ + } + break; + + case 0x82: /* byte operands */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + DATA = fetch_byte(1); /* must be done after DISP is collected */ + switch(REG) { + case 0: + VAL = add_byte(get_smbyte(seg_reg, EA), DATA); /* ADD mem8, immed8 */ + break; + case 2: + VAL = adc_byte(get_smbyte(seg_reg, EA), DATA); /* ADC mem8, immed8 */ + break; + case 3: + VAL = sbb_byte(get_smbyte(seg_reg, EA), DATA); /* SBB mem8, immed8 */ + break; + case 5: + VAL = sub_byte(get_smbyte(seg_reg, EA), DATA); /* SUB mem8, immed8 */ + break; + case 7: + VAL = cmp_byte(get_smbyte(seg_reg, EA), DATA); /* CMP mem8, immed8 */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(EA, VAL); /* store result */ + } else { /* RM is second register */ + switch(REG) { + case 0: + VAL = add_byte(get_rbyte(RM), DATA); /* ADD reg8, immed8 */ + break; + case 2: + VAL = adc_byte(get_rbyte(RM), DATA); /* ADC reg8, immed8 */ + break; + case 3: + VAL = sbb_byte(get_rbyte(RM), DATA); /* SBB reg8, immed8 */ + break; + case 5: + VAL = sub_byte(get_rbyte(RM), DATA); /* SUB reg8, immed8 */ + break; + case 7: + VAL = cmp_byte(get_rbyte(RM), DATA); /* CMP reg8, immed8 */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(REG, VAL); /* store result */ + } + break; + + case 0x83: /* word operands */ + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + DATA = fetch_byte(1) << 8; /* must be done after DISP is collected */ + if (DATA & 0x80) + DATA |= 0xFF00; + else + DATA &= 0xFF; + switch(REG) { + case 0: + VAL = add_word(get_smword(seg_reg, EA), DATA); /* ADD mem16, immed8-SX */ + break; + case 2: + VAL = adc_word(get_smword(seg_reg, EA), DATA); /* ADC mem16, immed8-SX */ + break; + case 3: + VAL = sbb_word(get_smword(seg_reg, EA), DATA); /* SBB mem16, immed8-SX */ + break; + case 5: + VAL = sub_word(get_smword(seg_reg, EA), DATA); /* SUB mem16, immed8-SX */ + break; + case 7: + VAL = cmp_word(get_smword(seg_reg, EA), DATA); /* CMP mem16, immed8-SX */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rword(EA, VAL); /* store result */ + } else { /* RM is second register */ + switch(REG) { + case 0: + VAL = add_word(get_rword(RM), DATA); /* ADD reg16, immed8-SX */ + break; + case 2: + VAL = adc_word(get_rword(RM), DATA); /* ADC reg16, immed8-SX */ + break; + case 3: + VAL = sbb_word(get_rword(RM), DATA); /* SBB reg16, immed8-SX */ + break; + case 5: + VAL = sub_word(get_rword(RM), DATA); /* CUB reg16, immed8-SX */ + break; + case 7: + VAL = cmp_word(get_rword(RM), DATA); /* CMP reg16, immed8-SX */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rword(RM, VAL); /* store result */ + } + break; + + case 0x84: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + test_byte(get_smbyte(seg_reg, EA),get_rbyte(REG)); /* TEST mem8, reg8 */ + } else { + test_byte(get_rbyte(REG),get_rbyte(RM)); /* TEST reg8, reg8 */ + } + break; + + case 0x85: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + test_word(get_smword(seg_reg, EA),get_rword(REG)); /* TEST mem16, reg16 */ + } else { + test_word(get_rword(REG),get_rword(RM)); /* TEST reg16, reg16 */ + } + break; + + case 0x86: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = get_rbyte(REG);/* XCHG mem8, reg8 */ + put_rbyte(REG, get_smbyte(seg_reg, EA)); + put_smbyte(seg_reg, EA, VAL); + } else { + VAL = get_rbyte(RM);/* XCHG reg8, reg8 */ + put_rbyte(RM, get_rbyte(REG)); + put_rbyte(REG, VAL); + } + break; + + case 0x87: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + VAL = get_rword(REG);/* XCHG mem16, reg16 */ + put_rword(REG, get_smword(seg_reg, EA)); + put_smword(seg_reg, EA, VAL); + } else { + VAL = get_rword(RM);/* XCHG reg16, reg16 */ + put_rword(RM, get_rword(REG)); + put_rword(REG, VAL); + } + break; + + case 0x88: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + put_smbyte(seg_reg, EA, get_rbyte(REG)); /* MOV mem8, reg8 */ + } else + put_rbyte(REG, get_rbyte(RM)); /* MOV reg8, reg8 */ + break; + + case 0x89: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + put_smword(seg_reg, EA, get_rword(REG)); /* MOV mem16, reg16 */ + } else + put_rword(REG, get_rword(RM)); /* MOV reg16, reg16 */ + break; + + case 0x8A: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + put_rbyte(REG, get_smbyte(seg_reg, EA)); /* MOV reg8, mem8 */ + } else + put_rbyte(REG, get_rbyte(RM)); /* MOV reg8, reg8 */ + break; + + case 0x8B: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + put_rword(REG, get_smword(seg_reg, EA)); /* MOV reg16, mem16 */ + } else + put_rword(REG, get_rword(RM)); /* MOV reg16, reg16 */ + break; + + case 0x8C: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + switch(REG) { + case 0: /* MOV mem16, ES */ + put_smword(seg_reg, EA, ES); + break; + case 1: /* MOV mem16, CS */ + put_smword(seg_reg, EA, CS); + break; + case 2: /* MOV mem16, SS */ + put_smword(seg_reg, EA, SS); + break; + case 3: /* MOV mem16, DS */ + put_smword(seg_reg, EA, DS); + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + } else { + switch(REG) { + case 0: /* MOV reg16, ES */ + put_rword(RM, ES); + break; + case 1: /* MOV reg16, CS */ + put_rword(RM, CS); + break; + case 2: /* MOV reg16, SS */ + put_rword(RM, SS); + break; + case 3: /* MOV reg16, DS */ + put_rword(RM, DS); + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + } + break; + + case 0x8D: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + put_rword(REG, EA); /* LEA reg16, mem16 */ + } else { + reason = STOP_OPCODE; + IP -= 2; + } + break; + + case 0x8E: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + switch(REG) { + case 0: /* MOV ES, mem16 */ + ES = get_smword(seg_reg, EA); + break; + case 1: /* MOV CS, mem16 */ + CS = get_smword(seg_reg, EA); + break; + case 2: /* MOV SS, mem16 */ + SS = get_smword(seg_reg, EA); + break; + case 3: /* MOV DS, mem16 */ + DS = get_smword(seg_reg, EA); + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + } else { + switch(REG) { + case 0: /* MOV ES, reg16 */ + ES = get_rword(RM); + break; + case 1: /* MOV CS, reg16 */ + CS = get_rword(RM); + break; + case 2: /* MOV SS, reg16 */ + SS = get_rword(RM); + break; + case 3: /* MOV DS, reg16 */ + DS = get_rword(RM); + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + } + break; + + case 0x8f: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + put_smword(seg_reg, EA, pop_word()); + } else { + reason = STOP_OPCODE; + IP -= 2; + } + break; + + case 0x90: /* NOP */ + break; + + case 0x91: /* XCHG AX, CX */ + VAL = AX; + AX = CX; + CX = VAL; + break; + + case 0x92: /* XCHG AX, DX */ + VAL = AX; + AX = DX; + DX = VAL; + break; + + case 0x93: /* XCHG AX, BX */ + VAL = AX; + AX = BX; + BX = VAL; + break; + + case 0x94: /* XCHG AX, SP */ + VAL = AX; + AX = SP; + SP = VAL; + break; + + case 0x95: /* XCHG AX, BP */ + VAL = AX; + AX = BP; + BP = VAL; + break; + + case 0x96: /* XCHG AX, SI */ + VAL = AX; + AX = SI; + SI = VAL; + break; + + case 0x97: /* XCHG AX, DI */ + VAL = AX; + AX = DI; + DI = VAL; + break; + + case 0x98: /* cbw */ + if (AL & 0x80) + AH = 0xFF; + else + AH = 0; + break; + + case 0x99: /* cbw */ + if (AX & 0x8000) + DX = 0xffff; + else + DX = 0x0; + break; + + case 0x9A: /* CALL FAR proc */ + OFF = fetch_word(); /* do operation */ + SEG = fetch_word(); + push_word(CS); + CS = SEG; + push_word(IP); + IP = OFF; + break; + + case 0x9B: /* WAIT */ + break; + + case 0x9C: /* PUSHF */ + VAL = PSW; + VAL &= PSW_MSK; + VAL |= PSW_ALWAYS_ON; + push_word(VAL); + break; + + case 0x9D: /* POPF */ + PSW = pop_word(); + break; + + case 0x9E: /* SAHF */ + PSW &= 0xFFFFFF00; + PSW |= AH; + break; + + case 0x9F: /* LAHF */ + AH = PSW & 0xFF; + AH |= 0x2; + break; + + case 0xA0: /* MOV AL, mem8 */ + OFF = fetch_word(); + set_segreg(SEG_DS); /* to allow segment override */ + AL = get_smbyte(seg_reg, OFF); + break; + + case 0xA1: /* MOV AX, mem16 */ + OFF = fetch_word(); + set_segreg(SEG_DS); /* to allow segment override */ + AX = get_smword(seg_reg, OFF); + break; + + case 0xA2: /* MOV mem8, AL */ + OFF = fetch_word(); + set_segreg(SEG_DS); /* to allow segment override */ + put_smbyte(seg_reg, OFF, AL); + break; + + case 0xA3: /* MOV mem16, AX */ + OFF = fetch_word(); + set_segreg(SEG_DS); /* to allow segment override */ + put_smword(seg_reg, OFF, AX); + break; + + case 0xA4: /* MOVS dest-str8, src-str8 */ + if (GET_FLAG(DF)) /* down */ + INC = -1; + else + INC = 1; + while (CX != 0) { + VAL = get_smbyte(seg_reg, SI); + put_smbyte(ES, DI, VAL); + CX--; + SI += INC; + DI += INC; + } + break; + + case 0xA5: /* MOVS dest-str16, src-str16 */ + if (GET_FLAG(DF)) /* down */ + INC = -2; + else + INC = 2; + while (CX != 0) { + VAL = get_smword(seg_reg, SI); + put_smword(ES, DI, VAL); + CX--; + SI += INC; + DI += INC; + } + break; + + case 0xA6: /* CMPS dest-str8, src-str8 */ + if (GET_FLAG(DF)) /* down */ + INC = -1; + else + INC = 1; + while (CX != 0) { + VAL = get_smbyte(seg_reg, SI); + VAL1 = get_smbyte(ES, DI); + cmp_byte(VAL, VAL1); + CX--; + SI += INC; + DI += INC; + if (GET_FLAG(ZF) == 0) + break; + } + break; + + case 0xA7: /* CMPS dest-str16, src-str16 */ + if (GET_FLAG(DF)) /* down */ + INC = -2; + else + INC = 2; + while (CX != 0) { + VAL = get_smword(seg_reg, SI); + VAL1 = get_smword(ES, DI); + cmp_word(VAL, VAL1); + CX--; + SI += INC; + DI += INC; + if (GET_FLAG(ZF) == 0) + break; + } + break; + + case 0xA8: /* TEST AL, immed8 */ + VAL = fetch_byte(1); + test_byte(AL, VAL); + break; + + case 0xA9: /* TEST AX, immed8 */ + VAL = fetch_word(); + test_word(AX, VAL); + break; + + case 0xAA: /* STOS dest-str8 */ + if (GET_FLAG(DF)) /* down */ + INC = -1; + else + INC = 1; + if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + while (CX != 0) { + put_smbyte(ES, DI, AL); + CX--; + DI += INC; + } + sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } else { + put_smbyte(ES, DI, AL); + DI += INC; + } + break; + + case 0xAB: /* STOS dest-str16 */ + if (GET_FLAG(DF)) /* down */ + INC = -1; + else + INC = 1; + if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + while (CX != 0) { + put_smword(ES, DI, AX); + CX--; + DI += INC; + } + sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } else { + put_smword(ES, DI, AL); + DI += INC; + } + break; + + case 0xAC: /* LODS dest-str8 */ + if (GET_FLAG(DF)) /* down */ + INC = -1; + else + INC = 1; + set_segreg(SEG_DS); /* allow overrides */ + if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + while (CX != 0) { + AL = get_smbyte(seg_reg, SI); + CX--; + SI += INC; + } + sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } else { + AL = get_smbyte(seg_reg, SI); + SI += INC; + } + break; + + case 0xAD: /* LODS dest-str16 */ + if (GET_FLAG(DF)) /* down */ + INC = -1; + else + INC = 1; + set_segreg(SEG_DS); /* allow overrides */ + if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + while (CX != 0) { + AX = get_smword(seg_reg, SI); + CX--; + SI += INC; + } + sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } else { + AX = get_smword(seg_reg, SI); + SI += INC; + } + break; + + case 0xAE: /* SCAS dest-str8 */ + if (GET_FLAG(DF)) /* down */ + INC = -1; + else + INC = 1; + if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + while (CX != 0) { + VAL = get_smbyte(ES, DI); + cmp_byte(AL, VAL); + CX--; + DI += INC; + if (GET_FLAG(ZF) == 0) + break; + } + sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } else { + VAL = get_smbyte(ES, DI); + cmp_byte(AL, VAL); + DI += INC; + } + break; + + case 0xAF: /* SCAS dest-str16 */ + if (GET_FLAG(DF)) /* down */ + INC = -2; + else + INC = 2; + if (sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + while (CX != 0) { + VAL = get_smword(ES, DI); + cmp_word(AX, VAL); + CX--; + DI += INC; + if (GET_FLAG(ZF) == 0) + break; + } + sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } else { + VAL = get_smword(ES, DI); + cmp_byte(AL, VAL); + DI += INC; + } + break; + + case 0xB0: /* MOV AL,immed8 */ + AL = fetch_byte(1); + break; + + case 0xB1: /* MOV CL,immed8 */ + CL = fetch_byte(1); + break; + + case 0xB2: /* MOV DL,immed8 */ + DL = fetch_byte(1); + break; + + case 0xB3: /* MOV BL,immed8 */ + BL = fetch_byte(1); + break; + + case 0xB4: /* MOV AH,immed8 */ + AH = fetch_byte(1); + break; + + case 0xB5: /* MOV CH,immed8 */ + CH = fetch_byte(1); + break; + + case 0xB6: /* MOV DH,immed8 */ + DH = fetch_byte(1); + break; + + case 0xB7: /* MOV BH,immed8 */ + BH = fetch_byte(1); + break; + + case 0xB8: /* MOV AX,immed16 */ + AX = fetch_word(); + break; + + case 0xB9: /* MOV CX,immed16 */ + CX = fetch_word(); + break; + + case 0xBA: /* MOV DX,immed16 */ + DX = fetch_word(); + break; + + case 0xBB: /* MOV BX,immed16 */ + BX = fetch_word(); + break; + + case 0xBC: /* MOV SP,immed16 */ + SP = fetch_word(); + break; + + case 0xBD: /* MOV BP,immed16 */ + BP = fetch_word(); + break; + + case 0xBE: /* MOV SI,immed16 */ + SI = fetch_word(); + break; + + case 0xBF: /* MOV DI,immed16 */ + DI = fetch_word(); + break; + + /* 0xC0 - 0xC1 - Not implemented on 8086/8088 */ + + case 0xC2: /* RET immed16 (intrasegment) */ + OFF = fetch_word(); + IP = pop_word(); + SP += OFF; + break; + + case 0xC3: /* RET (intrasegment) */ + IP = pop_word(); + break; + + case 0xC4: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + put_rword(REG, get_smword(seg_reg, EA)); /* LES mem16 */ + ES = get_smword(seg_reg, EA + 2); + } else { +// put_rword(REG, get_rword(RM)); /* LES reg16 */ +// ES = get_rword(RM) + 2; + /* not defined for 8086 */ + reason = STOP_OPCODE; + IP -= 2; + } + break; + + case 0xC5: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + put_rword(REG, get_smword(seg_reg, EA)); /* LDS mem16 */ + DS = get_smword(seg_reg, EA + 2); + } else { +// put_rword(REG, get_rword(RM)); /* LDS reg16 */ +// DS = get_rword(RM) + 2; + /* not defined for 8086 */ + reason = STOP_OPCODE; + IP -= 2; + } + break; + + case 0xC6: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (REG) { /* has to be 0 */ + reason = STOP_OPCODE; + IP -= 2; + } + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + DATA = fetch_byte(1); /* has to be after DISP */ + put_smbyte(seg_reg, EA, DATA); /* MOV mem8, immed8 */ + } else { + put_rbyte(RM, DATA); /* MOV reg8, immed8 */ + } + break; + + case 0xC7: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (REG) { /* has to be 0 */ + reason = STOP_OPCODE; + IP -= 2; + } + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + DATA = get_mword(IP); /* has to be after DISP */ + put_smword(seg_reg, EA, DATA); /* MOV mem16, immed16 */ + } else { + put_rword(RM, DATA); /* MOV reg16, immed16 */ + } + break; + + /* 0xC8 - 0xC9 - Not implemented on 8086/8088 */ + + case 0xCA: /* RET immed16 (intersegment) */ + OFF = fetch_word(); + IP = pop_word(); + CS = pop_word(); + SP += OFF; + break; + + case 0xCB: /* RET (intersegment) */ + IP = pop_word(); + CS = pop_word(); + break; + + case 0xCC: /* INT 3 */ + push_word(PSW); + CLR_FLAG(IF); + CLR_FLAG(TF); + push_word(CS); + push_word(IP); + CS = get_mword(14); + IP = get_mword(12); + break; + + case 0xCD: /* INT immed8 */ + OFF = fetch_byte(1); + push_word(PSW); + CLR_FLAG(IF); + CLR_FLAG(TF); + push_word(CS); + push_word(IP); + CS = get_mword((OFF * 4) + 2); + IP = get_mword(OFF * 4); + break; + + case 0xCE: /* INT0 */ + push_word(PSW); + CLR_FLAG(IF); + CLR_FLAG(TF); + push_word(CS); + push_word(IP); + CS = get_mword(18); + IP = get_mword(16); + break; + + case 0xCF: /* IRET */ + IP = pop_word(); + CS = pop_word(); + PSW = pop_word(); + break; + + case 0xD0: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + switch(REG) { + case 0: + VAL = rol_byte(get_smbyte(seg_reg, EA), 1); /* ROL mem8, 1 */ + break; + case 1: + VAL = ror_byte(get_smbyte(seg_reg, EA), 1); /* ROR mem8, 1 */ + break; + case 2: + VAL = rcl_byte(get_smbyte(seg_reg, EA), 1); /* RCL mem8, 1 */ + break; + case 3: + VAL = rcr_byte(get_smbyte(seg_reg, EA), 1); /* RCR mem8, 1 */ + break; + case 4: + VAL = shl_byte(get_smbyte(seg_reg, EA), 1); /* SAL/SHL mem8, 1 */ + break; + case 5: + VAL = shr_byte(get_smbyte(seg_reg, EA), 1); /* SHR mem8, 1 */ + break; + case 7: + VAL = sar_byte(get_smbyte(seg_reg, EA), 1); /* SAR mem8, 1 */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(EA, VAL); /* store result */ + } else { /* RM is second register */ + switch(REG) { + case 0: + VAL = rol_byte(get_rbyte(RM), 1); /* RCL reg8, 1 */ + break; + case 1: + VAL = ror_byte(get_rbyte(RM), 1); /* ROR reg8, 1 */ + break; + case 2: + VAL = rcl_byte(get_rbyte(RM), 1); /* RCL reg8, 1 */ + break; + case 3: + VAL = rcr_byte(get_rbyte(RM), 1); /* RCR reg8, 1 */ + break; + case 4: + VAL = shl_byte(get_rbyte(RM), 1); /* SHL/SAL reg8, 1*/ + break; + case 5: + VAL = shr_byte(get_rbyte(RM), 1); /* SHR reg8, 1 */ + break; + case 7: + VAL = sar_byte(get_rbyte(RM), 1); /* SAR reg8, 1 */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(RM, VAL); /* store result */ + } + break; + + case 0xD1: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + switch(REG) { + case 0: + VAL = rol_word(get_smword(seg_reg, EA), 1); /* ROL mem16, 1 */ + break; + case 1: + VAL = ror_word(get_smword(seg_reg, EA), 1); /* ROR mem16, 1 */ + break; + case 2: + VAL = rcl_word(get_smword(seg_reg, EA), 1); /* RCL mem16, 1 */ + break; + case 3: + VAL = rcr_word(get_smword(seg_reg, EA), 1); /* RCR mem16, 1 */ + break; + case 4: + VAL = shl_word(get_smword(seg_reg, EA), 1); /* SAL/SHL mem16, 1 */ + break; + case 5: + VAL = shr_word(get_smword(seg_reg, EA), 1); /* SHR mem16, 1 */ + break; + case 7: + VAL = sar_word(get_smword(seg_reg, EA), 1); /* SAR mem16, 1 */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rword(EA, VAL); /* store result */ + } else { /* RM is second register */ + switch(REG) { + case 0: + VAL = rol_word(get_rword(RM), 1); /* RCL reg16, 1 */ + break; + case 1: + VAL = ror_word(get_rword(RM), 1); /* ROR reg16, 1 */ + break; + case 2: + VAL = rcl_word(get_rword(RM), 1); /* RCL reg16, 1 */ + break; + case 3: + VAL = rcr_word(get_rword(RM), 1); /* RCR reg16, 1 */ + break; + case 4: + VAL = shl_word(get_rword(RM), 1); /* SHL/SAL reg16, 1 */ + break; + case 5: + VAL = shr_word(get_rword(RM), 1); /* SHR reg16, 1 */ + break; + case 7: + VAL = sar_word(get_rword(RM), 1); /* SAR reg16, 1 */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(RM, VAL); /* store result */ + } + break; + + case 0xD2: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + switch(REG) { + case 0: + VAL = rol_byte(get_smbyte(seg_reg, EA), CL); /* ROL mem8, CL */ + break; + case 1: + VAL = ror_byte(get_smbyte(seg_reg, EA), CL); /* ROR mem8, CL */ + break; + case 2: + VAL = rcl_byte(get_smbyte(seg_reg, EA), CL); /* RCL mem8, CL */ + break; + case 3: + VAL = rcr_byte(get_smbyte(seg_reg, EA), CL); /* RCR mem8, CL */ + break; + case 4: + VAL = shl_byte(get_smbyte(seg_reg, EA), CL); /* SAL/SHL mem8, CL */ + break; + case 5: + VAL = shr_byte(get_smbyte(seg_reg, EA), CL); /* SHR mem8, CL */ + break; + case 7: + VAL = sar_byte(get_smbyte(seg_reg, EA), CL); /* SAR mem8, CL */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(EA, VAL); /* store result */ + } else { /* RM is second register */ + switch(REG) { + case 0: + VAL = rol_byte(get_rbyte(RM), CL); /* RCL reg8, CL */ + break; + case 1: + VAL = ror_byte(get_rbyte(RM), CL); /* ROR reg8, CL */ + break; + case 2: + VAL = rcl_byte(get_rbyte(RM), CL); /* RCL reg8, CL */ + break; + case 3: + VAL = rcr_byte(get_rbyte(RM), CL); /* RCR reg8, CL */ + break; + case 4: + VAL = shl_byte(get_rbyte(RM), CL); /* SHL/SAL reg8, CL*/ + break; + case 5: + VAL = shr_byte(get_rbyte(RM), CL); /* SHR reg8, CL */ + break; + case 7: + VAL = sar_byte(get_rbyte(RM), CL); /* SAR reg8, CL */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(RM, VAL); /* store result */ + } + break; + + case 0xD3: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + switch(REG) { + case 0: + VAL = rol_word(get_smword(seg_reg, EA), CL); /* ROL mem16, CL */ + break; + case 1: + VAL = ror_word(get_smword(seg_reg, EA), CL); /* ROR mem16, CL */ + break; + case 2: + VAL = rcl_word(get_smword(seg_reg, EA), CL); /* RCL mem16, CL */ + break; + case 3: + VAL = rcr_word(get_smword(seg_reg, EA), CL); /* RCR mem16, CL */ + break; + case 4: + VAL = shl_word(get_smword(seg_reg, EA), CL); /* SAL/SHL mem16, CL */ + break; + case 5: + VAL = shr_word(get_smword(seg_reg, EA), CL); /* SHR mem16, CL */ + break; + case 7: + VAL = sar_word(get_smword(seg_reg, EA), CL); /* SAR mem16, CL */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rword(EA, VAL); /* store result */ + } else { /* RM is second register */ + switch(REG) { + case 0: + VAL = rol_word(get_rword(RM), CL); /* RCL reg16, CL */ + break; + case 1: + VAL = ror_word(get_rword(RM), CL); /* ROR reg16, CL */ + break; + case 2: + VAL = rcl_word(get_rword(RM), CL); /* RCL reg16, CL */ + break; + case 3: + VAL = rcr_word(get_rword(RM), CL); /* RCR reg16, CL */ + break; + case 4: + VAL = shl_word(get_rword(RM), CL); /* SHL/SAL reg16, CL */ + break; + case 5: + VAL = shr_word(get_rword(RM), CL); /* SHR reg16, CL */ + break; + case 7: + VAL = sar_word(get_rword(RM), CL); /* SAR reg16, CL */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(RM, VAL); /* store result */ + } + break; + + case 0xD4: /* AAM */ + VAL = fetch_word(); + if (VAL != 10) { + reason = STOP_OPCODE; + IP -= 2; + } + /* note the type change here --- returning AL and AH in AX. */ + AX = aam_word(AL); + break; + + case 0xD5: /* AAD */ + VAL = fetch_word(); + if (VAL != 10) { + reason = STOP_OPCODE; + IP -= 2; + } + AX = aad_word(AX); + break; + + /* 0xD6 - Not implemented on 8086/8088 */ + + case 0xD7: /* XLAT */ + OFF = BX + (uint8)AL; + AL = get_smbyte(SEG_CS, OFF); + break; + + case 0xD8: /* ESC */ + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + /* for now, do nothing, NOP for 8088 */ + break; + + case 0xE0: /* LOOPNE label */ + OFF = fetch_byte(1); + OFF = sign_ext(OFF); + OFF += (int16)IP; + CX -= 1; + if (CX != 0 && !GET_FLAG(ZF)) /* CX != 0 and !ZF */ + IP = OFF; + break; + + case 0xE1: /* LOOPE label */ + OFF = fetch_byte(1); + OFF = sign_ext(OFF); + OFF += (int16)IP; + CX -= 1; + if (CX != 0 && GET_FLAG(ZF)) /* CX != 0 and ZF */ + IP = OFF; + break; + + case 0xE2: /* LOOP label */ + OFF = fetch_byte(1); + OFF = sign_ext(OFF); + OFF += (int16)IP; + CX -= 1; + if (CX != 0) /* CX != 0 */ + IP = OFF; + break; + + case 0xE3: /* JCXZ label */ + OFF = fetch_byte(1); + OFF = sign_ext(OFF); + OFF += (int16)IP; + if (CX == 0) /* CX != 0 */ + IP = OFF; + break; + + case 0xE4: /* IN AL, port8 */ + DATA = fetch_byte(1); + port = DATA; + AL = dev_table[DATA].routine(0, 0); + break; + + case 0xE5: /* IN AX, port16 */ + DATA = fetch_byte(1); + port = DATA; + AH = dev_table[DATA].routine(0, 0); + AL = dev_table[DATA+1].routine(0, 0); + break; + + case 0xE6: /* OUT AL, port8 */ + DATA = fetch_byte(1); + port = DATA; + dev_table[DATA].routine(1, AL); + //sim_printf("OUT AL: DATA=%04X\n", DATA); + break; + + case 0xE7: /* OUT AX, port16 */ + DATA = fetch_byte(1); + port = DATA; + dev_table[DATA].routine(1, AH); + dev_table[DATA+1].routine(1, AL); + break; + + case 0xE8: /* CALL NEAR proc */ + OFF = fetch_word(); + push_word(IP); + IP = (OFF + IP) & ADDRMASK16; + break; + + case 0xE9: /* JMP NEAR label */ + OFF = fetch_word(); + IP = (OFF + IP) & ADDRMASK16; + break; + + case 0xEA: /* JMP FAR label */ + OFF = fetch_word(); + SEG = fetch_word(); + CS = SEG; + IP = OFF; + break; + + case 0xEB: /* JMP short-label */ + OFF = fetch_byte(1); + if (OFF & 0x80) /* if negative, sign extend */ + OFF |= 0XFF00; + IP = (IP + OFF) & ADDRMASK16; + break; + + case 0xEC: /* IN AL,DX */ + port = DX; + AL = dev_table[DX].routine(0, 0); + break; + + case 0xED: /* IN AX,DX */ + port = DX; + AH = dev_table[DX].routine(0, 0); + AL = dev_table[DX+1].routine(0, 0); + break; + + case 0xEE: /* OUT AL,DX */ + port = DX; + dev_table[DX].routine(1, AL); + break; + + case 0xEF: /* OUT AX,DX */ + port = DX; + dev_table[DX].routine(1, AH); + dev_table[DX+1].routine(1, AL); + break; + + case 0xF0: /* LOCK */ + /* do nothing for now */ + break; + + /* 0xF1 - Not implemented on 8086/8088 */ + + case 0xF2: /* REPNE/REPNZ */ + sysmode |= SYSMODE_PREFIX_REPNE; + break; + + case 0xF3: /* REP/REPE/REPZ */ + sysmode |= SYSMODE_PREFIX_REPE; + break; + + case 0xF4: /* HLT */ + reason = STOP_HALT; + IP--; + break; + + case 0xF5: /* CMC */ + TOGGLE_FLAG(CF); + break; + + case 0xF6: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + switch(REG) { + case 0: /* TEST mem8, immed8 */ + DATA = fetch_byte(1); + test_byte(get_smbyte(seg_reg, EA), DATA); + break; + case 2: /* NOT mem8 */ + VAL = not_byte(get_smbyte(seg_reg, EA)); + put_smbyte(seg_reg, EA, VAL); /* store result */ + break; + case 3: /* NEG mem8 */ + VAL = neg_byte(get_smbyte(seg_reg, EA)); + put_smbyte(seg_reg, EA, VAL); /* store result */ + break; + case 4: /* MUL mem8 */ + mul_byte(get_smbyte(seg_reg, EA)); + break; + case 5: /* IMUL mem8 */ + imul_byte(get_smbyte(seg_reg, EA)); + break; + case 6: /* DIV mem8 */ + div_byte(get_smbyte(seg_reg, EA)); + break; + case 7: /* IDIV mem8 */ + idiv_byte(get_smbyte(seg_reg, EA)); + break; + default: /* bad opcode */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + } else { /* RM is second register */ + switch(REG) { + case 0: /* TEST reg8, immed8 */ + DATA = fetch_byte(1); + test_byte(get_rbyte(RM), DATA); + break; + case 2: /* NOT reg8 */ + VAL = not_byte(get_rbyte(RM)); + put_rbyte(RM, VAL); /* store result */ + break; + case 3: /* NEG reg8 */ + VAL = neg_byte(get_rbyte(RM)); + put_rbyte(RM, VAL); /* store result */ + break; + case 4: /* MUL reg8 */ + mul_byte(get_rbyte(RM)); + break; + case 5: /* IMUL reg8 */ + imul_byte(get_rbyte(RM)); + break; + case 6: /* DIV reg8 */ + div_byte(get_rbyte(RM)); + break; + case 7: /* IDIV reg8 */ + idiv_byte(get_rbyte(RM)); + break; + default: /* bad opcode */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(RM, VAL); /* store result */ + } + break; + + case 0xF7: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + switch(REG) { + case 0: /* TEST mem16, immed16 */ + DATA = fetch_word(); + test_word(get_smword(seg_reg, EA), DATA); + break; + case 2: /* NOT mem16 */ + VAL = not_word(get_smword(seg_reg, EA)); + put_smword(seg_reg, EA, VAL); /* store result */ + break; + case 3: /* NEG mem16 */ + VAL = neg_word(get_smword(seg_reg, EA)); + put_smword(seg_reg, EA, VAL); /* store result */ + break; + case 4: /* MUL mem16 */ + mul_word(get_smword(seg_reg, EA)); + break; + case 5: /* IMUL mem16 */ + imul_word(get_smword(seg_reg, EA)); + break; + case 6: /* DIV mem16 */ + div_word(get_smword(seg_reg, EA)); + break; + case 7: /* IDIV mem16 */ + idiv_word(get_smword(seg_reg, EA)); + break; + default: /* bad opcode */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + } else { /* RM is second register */ + switch(REG) { + case 0: /* TEST reg16, immed16 */ + DATA = fetch_word(); + test_word(get_rword(RM), DATA); + break; + case 2: /* NOT reg16 */ + VAL = not_word(get_rword(RM)); + put_rword(RM, VAL); /* store result */ + break; + case 3: /* NEG reg16 */ + VAL = neg_word(get_rword(RM)); + put_rword(RM, VAL); /* store result */ + break; + case 4: /* MUL reg16 */ + mul_word(get_rword(RM)); + break; + case 5: /* IMUL reg16 */ + imul_word(get_rword(RM)); + break; + case 6: /* DIV reg16 */ + div_word(get_rword(RM)); + break; + case 7: /* IDIV reg16 */ + idiv_word(get_rword(RM)); + break; + default: /* bad opcode */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(RM, VAL); /* store result */ + } + break; + + case 0xF8: /* CLC */ + CLR_FLAG(CF); + break; + + case 0xF9: /* STC */ + SET_FLAG(CF); + break; + + case 0xFA: /* CLI */ + CLR_FLAG(IF); + break; + + case 0xFB: /* STI */ + SET_FLAG(IF); + break; + + case 0xFC: /* CLD */ + CLR_FLAG(DF); + break; + + case 0xFD: /* STD */ + SET_FLAG(DF); + break; + + case 0xFE: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + switch(REG) { + case 0: /* INC mem16 */ + VAL = inc_byte(get_smbyte(seg_reg, EA)); /* do operation */ + put_smbyte(seg_reg, EA, VAL); /* store result */ + break; + case 1: /* DEC mem16 */ + VAL = dec_byte(get_smbyte(seg_reg, EA)); /* do operation */ + put_smbyte(seg_reg, EA, VAL); /* store result */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + } else { /* RM is second register */ + switch(REG) { + case 0: + VAL = inc_byte(get_rbyte(RM)); /* do operation */ + put_rbyte(RM, VAL); /* store result */ + break; + case 1: + VAL = dec_byte(get_rbyte(RM)); /* do operation */ + put_rbyte(RM, VAL); /* store result */ + break; + default: /* bad opcodes */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(RM, VAL); /* store result */ + } + break; + + case 0xFF: + MRR = fetch_byte(1); + get_mrr_dec(MRR, &MOD, ®, &RM); + if (MOD != 0x3) { /* based, indexed, or based indexed addressing */ + EA = get_ea(MRR); /* get effective address */ + switch(REG) { + case 0: /* INC mem16 */ + VAL = inc_word(get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + break; + case 1: /* DEC mem16 */ + VAL = dec_word(get_smword(seg_reg, EA)); /* do operation */ + put_smword(seg_reg, EA, VAL); /* store result */ + break; + case 2: /* CALL NEAR mem16 */ + OFF = get_smword(SEG_CS, EA); /* do operation */ + push_word(IP); + IP = OFF; + break; + case 3: /* CALL FAR mem16 */ + OFF = get_smword(SEG_CS, EA); /* do operation */ + SEG = get_smword(SEG_CS, EA + 2); + push_word(CS); + CS = SEG; + push_word(IP); + IP = OFF; + break; + case 4: /* JMP NEAR mem16 */ + OFF = get_smword(SEG_CS, EA); /* do operation */ + IP = OFF; + break; + case 5: /* JMP FAR mem16 */ + OFF = get_smword(SEG_CS, EA); /* do operation */ + SEG = get_smword(SEG_CS, EA + 2); + CS = SEG; + IP = OFF; + break; + case 6: /* PUSH mem16 */ + VAL = get_smword(seg_reg, EA); /* do operation */ + push_word(VAL); + break; + case 7: /* bad opcode */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + } else { /* RM is second register */ + switch(REG) { + case 2: /* CALL NEAR reg16 */ + OFF = get_rword(RM); /* do operation */ + push_word(IP); + IP = OFF; + break; + case 4: /* JMP NEAR reg16 */ + OFF = get_rword(RM); /* do operation */ + IP = OFF; + break; + default: /* bad opcode */ + reason = STOP_OPCODE; + IP -= 2; + break; + } + put_rbyte(RM, VAL); /* store result */ + } + break; + + + default: +// if (i8088_unit.flags & UNIT_OPSTOP) { + reason = STOP_OPCODE; + IP--; +// } + break; + } + /* not segment override */ + if ((IR == 0x26) || (IR == 0x2E) || (IR == 0x36) || (IR == 0x3E)) { + seg_ovr = SEG_NONE; /* clear segment override */ + sysmode &= 0x0000001E; /* clear flags */ + sysmode |= 0x00000001; + } + if (i8088_dev.dctrl & DEBUG_asm) { + sim_printf("%04X:%04X %s", CS, IP, opcode[IR]); + switch (oplen[IR]) { + case 0: //one byte opcode + break; + case 1: //IMMED8 + sim_printf(" 0%02XH", DATA); + break; + case 2: //IMMED16 + sim_printf(" 0%04XH", DATA); + break; + case 3: //IP-INC8 + sim_printf(" 0%02XH", EA); + break; + case 4: //IP-INC16 + sim_printf(" 0%04XH", EA); + break; + default: + break; + } + } + if (i8088_dev.dctrl & DEBUG_reg) { + sim_printf("\nRegs: AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X IP=%04X\n", + AX, BX, CX, DX, SP, BP, SI, DI, IP); + sim_printf("Segs: CS=%04X DS=%04X ES=%04X SS=%04X Flags: %04X\n", CS, DS, ES, SS, PSW); + } + } +/* Simulation halted */ + + saved_PC = IP; + return reason; +} + +/* emulation subfunctions */ + +int32 sign_ext(int32 val) +{ + int32 res; + + res = val; + if (val & 0x80) + res |= 0xFF00; + return res; +} + +int32 fetch_byte(int32 flag) +{ + uint8 val; + + val = get_smbyte(SEG_CS, IP) & 0xFF; /* fetch byte */ + if (i8088_dev.dctrl & DEBUG_asm) { /* display source code */ + switch (flag) { + case 0: /* opcode fetch */ +// if (i8088_dev.dctrl & DEBUG_asm) +// sim_printf("%04X:%04X %02X %s ", CS, IP, val, opcode[val]); + break; + case 1: /* byte operand fetch */ +// if (i8088_dev.dctrl & DEBUG_asm) +// sim_printf("0%02XH", val); + break; + } + } + IP = 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); + 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_reg = 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: DISP=%04X EA=%04X\n", +// DISP, EA); + return EA; +} +/* return mod, reg and rm field from mrr */ + +void get_mrr_dec(uint32 mrr, uint32 *mod, uint32 *reg, uint32 *rm) +{ + *mod = (mrr >> 6) & 0x3; + *reg = (mrr >> 3) & 0x7; + *rm = mrr & 0x7; +// if (i8088_dev.dctrl & DEBUG_level1) +// sim_printf("get_mrr_dec: MRR=%02X MOD=%02X REG=%02X R/M=%02X\n", +// mrr, *mod, *reg, *rm); +} + +/* decode byte register for disassembly */ + +void rm_byte_dec(uint32 rm) +{ + switch (rm) { + case 0: + sim_printf("AL"); + break; + case 1: + sim_printf("CL"); + break; + case 2: + sim_printf("DL"); + break; + case 3: + sim_printf("BL"); + break; + case 4: + sim_printf("AH"); + break; + case 5: + sim_printf("CH"); + break; + case 6: + sim_printf("DH"); + break; + case 7: + sim_printf("CH"); + break; + } +} +/* decode word register for disassembly */ + +void rm_word_dec(uint32 rm) +{ + switch (rm) { + case 0: + sim_printf("AX"); + break; + case 1: + sim_printf("CX"); + break; + case 2: + sim_printf("DX"); + break; + case 3: + sim_printf("BX"); + break; + case 4: + sim_printf("SP"); + break; + case 5: + sim_printf("BP"); + break; + case 6: + sim_printf("SI"); + break; + case 7: + sim_printf("DI"); + break; + } +} + +/* decode segment register for disassembly */ + +void rm_seg_dec(uint32 rm) +{ + switch (rm) { + case 0: + sim_printf("ES"); + break; + case 1: + sim_printf("CS"); + break; + case 2: + sim_printf("SS"); + break; + case 3: + sim_printf("DS"); + break; + } +} + +/* + Most of the primitive algorithms were pulled from the GDE Dos/IP Emulator by Jim Hudgens +*/ + +/* aad primitive */ +uint8 aad_word(uint16 d) +{ + uint16 VAL; + uint8 HI, LOW; + + HI = (d >> 8) & 0xFF; + LOW = d & 0xFF; + VAL = LOW + 10 * HI; + CONDITIONAL_SET_FLAG(VAL & 0x80, SF); + CONDITIONAL_SET_FLAG(VAL == 0, ZF); + CONDITIONAL_SET_FLAG(parity(VAL & 0xFF), PF); + return (uint8) VAL; +} + +/* aam primitive */ +uint16 aam_word(uint8 d) +{ + uint16 VAL, HI; + + HI = d / 10; + VAL = d % 10; + VAL |= (HI << 8); + CONDITIONAL_SET_FLAG(VAL & 0x80, SF); + CONDITIONAL_SET_FLAG(VAL == 0, ZF); + CONDITIONAL_SET_FLAG(parity(VAL & 0xFF), PF); + return VAL; +} + +/* add with carry byte primitive */ +uint8 adc_byte(uint8 d, uint8 s) +{ + register uint16 res; + register uint16 cc; + + if (GET_FLAG(CF)) + res = 1 + d + s; + else + res = d + s; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x0100, CF); + CONDITIONAL_SET_FLAG((res & 0xff) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); + /* calculate the carry chain SEE NOTE AT TOP.*/ + cc = (s & d) | ((~res) & (s | d)); + /* set the flags based on the carry chain */ + CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 6) & 0x3], OF); + CONDITIONAL_SET_FLAG(cc & 0x08, AF); + return (uint8) res; +} + +/* add with carry word primitive */ +uint16 adc_word(uint16 d, uint16 s) +{ + register uint32 res; + register uint32 cc; + + if (GET_FLAG(CF)) + res = 1 + d + s; + else + res = d + s; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x10000, CF); + CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + /* calculate the carry chain SEE NOTE AT TOP.*/ + cc = (s & d) | ((~res) & (s | d)); + /* set the flags based on the carry chain */ + CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 14) & 0x3], OF); + CONDITIONAL_SET_FLAG(cc & 0x08, AF); + return res; +} + +/* add byte primitive */ +uint8 add_byte(uint8 d, uint8 s) +{ + register uint16 res; + register uint16 cc; + + res = d + s; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x0100, CF); + CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + /* calculate the carry chain SEE NOTE AT TOP.*/ + cc = (s & d) | ((~res) & (s | d)); + /* set the flags based on the carry chain */ + CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 6) & 0x3], OF); + CONDITIONAL_SET_FLAG(cc & 0x08, AF); + return (uint8) res; +} + +/* add word primitive */ +uint16 add_word(uint16 d, uint16 s) +{ + register uint32 res; + register uint32 cc; + + res = d + s; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x10000, CF); + CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); + /* calculate the carry chain SEE NOTE AT TOP.*/ + cc = (s & d) | ((~res) & (s | d)); + /* set the flags based on the carry chain */ + CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 14) & 0x3], OF); + CONDITIONAL_SET_FLAG(cc & 0x08, AF); + return res; +} + +/* and byte primitive */ +uint8 and_byte(uint8 d, uint8 s) +{ + register uint8 res; + res = d & s; + + /* clear flags */ + CLR_FLAG(OF); + CLR_FLAG(CF); + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res), PF); + return res; +} + +/* and word primitive */ +uint16 and_word(uint16 d, uint16 s) +{ + register uint16 res; + res = d & s; + + /* clear flags */ + CLR_FLAG(OF); + CLR_FLAG(CF); + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + return res; +} + +/* cmp byte primitive */ +uint8 cmp_byte(uint8 d, uint8 s) +{ + register uint32 res; + register uint32 bc; + + res = d - s; + /* clear flags */ + CLR_FLAG(CF); + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG((res & 0xFF)==0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + /* calculate the borrow chain. See note at top */ + bc= (res&(~d|s))|(~d&s); + /* set flags based on borrow chain */ + CONDITIONAL_SET_FLAG(bc & 0x80, CF); + CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); + CONDITIONAL_SET_FLAG(bc & 0x8, AF); + return d; /* long story why this is needed. Look at opcode + 0x80 in ops.c, for an idea why this is necessary.*/ +} + +/* cmp word primitive */ +uint16 cmp_word(uint16 d, uint16 s) +{ + register uint32 res; + register uint32 bc; + + res = d - s; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + /* calculate the borrow chain. See note at top */ + bc = (res & (~d | s)) | (~d &s); + /* set flags based on borrow chain */ + CONDITIONAL_SET_FLAG(bc & 0x8000, CF); + CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 14) & 0x3], OF); + CONDITIONAL_SET_FLAG(bc & 0x8, AF); + return d; /* long story why this is needed. Look at opcode + 0x80 in ops.c, for an idea why this is necessary.*/ +} + +/* dec byte primitive */ +uint8 dec_byte(uint8 d) +{ + register uint32 res; + register uint32 bc; + + res = d - 1; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG((res & 0xff)==0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); + /* calculate the borrow chain. See note at top */ + /* based on sub_byte, uses s=1. */ + bc = (res & (~d | 1)) | (~d & 1); + /* carry flag unchanged */ + /* set flags based on borrow chain */ + CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); + CONDITIONAL_SET_FLAG(bc & 0x8, AF); + return res; +} + +/* dec word primitive */ +uint16 dec_word(uint16 d) +{ + register uint32 res; + register uint32 bc; + + res = d - 1; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); + /* calculate the borrow chain. See note at top */ + /* based on the sub_byte routine, with s==1 */ + bc = (res & (~d | 1)) | (~d & 1); + /* carry flag unchanged */ + /* set flags based on borrow chain */ + CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 14) & 0x3], OF); + CONDITIONAL_SET_FLAG(bc & 0x8, AF); + return res; +} + +/* div byte primitive */ +void div_byte(uint8 s) +{ + uint32 dvd, dvs, div, mod; + + dvs = s; + dvd = AX; + if (s == 0) { + i86_intr_raise(0); + return; + } + div = dvd / dvs; + mod = dvd % dvs; + if (abs(div) > 0xFF) { + i86_intr_raise(0); + return; + } + /* Undef --- Can't hurt */ + CLR_FLAG(SF); + CONDITIONAL_SET_FLAG(div == 0, ZF); + AL = (uint8)div; + AH = (uint8)mod; +} + +/* div word primitive */ +void div_word(uint16 s) +{ + uint32 dvd, dvs, div, mod; + + dvd = DX; + dvd = (dvd << 16) | AX; + dvs = s; + if (dvs == 0) { + i86_intr_raise(0); + return; + } + div = dvd / dvs; + mod = dvd % dvs; + if (abs(div) > 0xFFFF) { + i86_intr_raise(0); + return; + } + /* Undef --- Can't hurt */ + CLR_FLAG(SF); + CONDITIONAL_SET_FLAG(div == 0, ZF); + AX = div; + DX = mod; +} + +/* idiv byte primitive */ +void idiv_byte(uint8 s) +{ + int32 dvd, div, mod; + + dvd = (int16)AX; + if (s == 0) { + i86_intr_raise(0); + return; + } + div = dvd / (int8)s; + mod = dvd % (int8)s; + if (abs(div) > 0x7F) { + i86_intr_raise(0); + return; + } + /* Undef --- Can't hurt */ + CONDITIONAL_SET_FLAG(div & 0x80, SF); + CONDITIONAL_SET_FLAG(div == 0, ZF); + AL = (int8)div; + AH = (int8)mod; +} + +/* idiv word primitive */ +void idiv_word(uint16 s) +{ + int32 dvd, dvs, div, mod; + + dvd = DX; + dvd = (dvd << 16) | AX; + if (s == 0) { + i86_intr_raise(0); + return; + } + dvs = (int16)s; + div = dvd / dvs; + mod = dvd % dvs; + if (abs(div) > 0x7FFF) { + i86_intr_raise(0); + return; + } + /* Undef --- Can't hurt */ + CONDITIONAL_SET_FLAG(div & 0x8000, SF); + CONDITIONAL_SET_FLAG(div == 0, ZF); + AX = div; + DX = mod; +} + +/* imul byte primitive */ +void imul_byte(uint8 s) +{ + int16 res; + + res = (int8)AL * (int8)s; + AX = res; + /* Undef --- Can't hurt */ + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + if ( AH == 0 || AH == 0xFF) { + CLR_FLAG(CF); + CLR_FLAG(OF); + } else { + SET_FLAG(CF); + SET_FLAG(OF); + } +} + +/* imul word primitive */ +void imul_word(uint16 s) +{ + int32 res; + + res = (int16)AX * (int16)s; + AX = res & 0xFFFF; + DX = (res >> 16) & 0xFFFF; + /* Undef --- Can't hurt */ + CONDITIONAL_SET_FLAG(res & 0x80000000, SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + if (DX == 0 || DX == 0xFFFF) { + CLR_FLAG(CF); + CLR_FLAG(OF); + } else { + SET_FLAG(CF); + SET_FLAG(OF); + } +} + +/* inc byte primitive */ +uint8 inc_byte(uint8 d) +{ + register uint32 res; + register uint32 cc; + + res = d + 1; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + /* calculate the carry chain SEE NOTE AT TOP.*/ + cc = ((1 & d) | (~res)) & (1 | d); + /* set the flags based on the carry chain */ + CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 6) & 0x3], OF); + CONDITIONAL_SET_FLAG(cc & 0x8, AF); + return res; +} + +/* inc word primitive */ +uint16 inc_word(uint16 d) +{ + register uint32 res; + register uint32 cc; + + res = d + 1; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); + /* calculate the carry chain SEE NOTE AT TOP.*/ + cc = (1 & d) | ((~res) & (1 | d)); + /* set the flags based on the carry chain */ + CONDITIONAL_SET_FLAG(xor_3_tab[(cc >> 14) & 0x3], OF); + CONDITIONAL_SET_FLAG(cc & 0x8, AF); + return res ; +} + +/* mul byte primitive */ +void mul_byte(uint8 s) +{ + uint16 res; + + res = AL * s; + AX = res; + /* Undef --- Can't hurt */ + CLR_FLAG(SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + if (AH == 0) { + CLR_FLAG(CF); + CLR_FLAG(OF); + } else { + SET_FLAG(CF); + SET_FLAG(OF); + } +} + +/* mul word primitive */ +void mul_word(uint16 s) +{ + uint32 res; + + res = AX * s; + /* Undef --- Can't hurt */ + CLR_FLAG(SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + AX = res & 0xFFFF; + DX = (res >> 16) & 0xFFFF; + if (DX == 0) { + CLR_FLAG(CF); + CLR_FLAG(OF); + } else { + SET_FLAG(CF); + SET_FLAG(OF); + } +} + +/* neg byte primitive */ +uint8 neg_byte(uint8 s) +{ + register uint8 res; + register uint8 bc; + + CONDITIONAL_SET_FLAG(s != 0, CF); + res = -s; + CONDITIONAL_SET_FLAG((res & 0xff) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG(parity(res), PF); + /* calculate the borrow chain --- modified such that d=0. */ + bc= res | s; + CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); + CONDITIONAL_SET_FLAG(bc & 0x8, AF); + return res; +} + +/* neg word primitive */ +uint16 neg_word(uint16 s) +{ + register uint16 res; + register uint16 bc; + + CONDITIONAL_SET_FLAG(s != 0, CF); + res = -s; + CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + /* calculate the borrow chain --- modified such that d=0 */ + bc= res | s; + CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); + CONDITIONAL_SET_FLAG(bc & 0x8, AF); + return res; +} + +/* not byte primitive */ +uint8 not_byte(uint8 s) +{ + return ~s; +} + +/* not word primitive */ +uint16 not_word(uint16 s) +{ + return ~s; +} + +/* or byte primitive */ +uint8 or_byte(uint8 d, uint8 s) +{ + register uint8 res; + + res = d | s; + /* clear flags */ + CLR_FLAG(OF); + CLR_FLAG(CF); + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res), PF); + return res; +} + +/* or word primitive */ +uint16 or_word(uint16 d, uint16 s) +{ + register uint16 res; + + res = d | s; + /* clear flags */ + CLR_FLAG(OF); + CLR_FLAG(CF); + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + return res; +} + +/* push word primitive */ +void push_word(uint16 val) +{ + SP--; + put_smbyte(SEG_SS, SP, val >> 8); + SP--; + put_smbyte(SEG_SS, SP, val & 0xFF); +} + +/* pop word primitive */ +uint16 pop_word(void) +{ + register uint16 res; + + //sim_printf("pop_word: entered SS=%04X SP=%04X\n", get_rword(SEG_SS), SP); + res = get_smbyte(SEG_SS, SP); + SP++; + //sim_printf("pop_word: first byte=%04X SS=%04X SP=%04X\n", res, get_rword(SEG_SS), SP); + res |= (get_smbyte(SEG_SS, SP) << 8); + SP++; + //sim_printf("pop_word: val=%04X SS=%04X SP=%04X\n", res, get_rword(SEG_SS), SP); + return res; +} + +/* rcl byte primitive */ +uint8 rcl_byte(uint8 d, uint8 s) +{ + register uint32 res, cnt, mask, cf; + + res = d; + if ((cnt = s % 9)) + { + cf = (d >> (8-cnt)) & 0x1; + res = (d << cnt) & 0xFF; + mask = (1<<(cnt-1)) - 1; + res |= (d >> (9-cnt)) & mask; + if (GET_FLAG(CF)) + res |= 1 << (cnt-1); + CONDITIONAL_SET_FLAG(cf, CF); + CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[cf + ((res >> 6) & 0x2)], OF); + } + return res & 0xFF; +} + +/* rcl word primitive */ +uint16 rcl_word(uint16 d, uint16 s) +{ + register uint32 res, cnt, mask, cf; + + res = d; + if ((cnt = s % 17)) + { + cf = (d >> (16-cnt)) & 0x1; + res = (d << cnt) & 0xFFFF; + mask = (1<<(cnt-1)) - 1; + res |= (d >> (17-cnt)) & mask; + if (GET_FLAG(CF)) + res |= 1 << (cnt-1); + CONDITIONAL_SET_FLAG(cf, CF); + CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[cf + ((res >> 14) & 0x2)], OF); + } + return res & 0xFFFF; +} + +/* rcr byte primitive */ +uint8 rcr_byte(uint8 d, uint8 s) +{ + uint8 res, cnt; + uint8 mask, cf, ocf = 0; + + res = d; + + if ((cnt = s % 9)) { + if (cnt == 1) { + cf = d & 0x1; + ocf = GET_FLAG(CF) != 0; + } else + cf = (d >> (cnt - 1)) & 0x1; + mask = (1 <<( 8 - cnt)) - 1; + res = (d >> cnt) & mask; + res |= (d << (9-cnt)); + if (GET_FLAG(CF)) + res |= 1 << (8 - cnt); + CONDITIONAL_SET_FLAG(cf, CF); + if (cnt == 1) + CONDITIONAL_SET_FLAG(xor_3_tab[ocf + ((d >> 6) & 0x2)], OF); + } + return res; +} + +/* rcr word primitive */ +uint16 rcr_word(uint16 d, uint16 s) +{ + uint16 res, cnt; + uint16 mask, cf, ocf = 0; + + res = d; + if ((cnt = s % 17)) { + if (cnt == 1) { + cf = d & 0x1; + ocf = GET_FLAG(CF) != 0; + } else + cf = (d >> (cnt-1)) & 0x1; + mask = (1 <<( 16 - cnt)) - 1; + res = (d >> cnt) & mask; + res |= (d << (17 - cnt)); + if (GET_FLAG(CF)) + res |= 1 << (16 - cnt); + CONDITIONAL_SET_FLAG(cf, CF); + if (cnt == 1) + CONDITIONAL_SET_FLAG(xor_3_tab[ocf + ((d >> 14) & 0x2)], OF); + } + return res; +} + +/* rol byte primitive */ +uint8 rol_byte(uint8 d, uint8 s) +{ + register uint32 res, cnt, mask; + + res =d; + + if ((cnt = s % 8)) { + res = (d << cnt); + mask = (1 << cnt) - 1; + res |= (d >> (8-cnt)) & mask; + CONDITIONAL_SET_FLAG(res & 0x1, CF); + CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res & 0x1) + ((res >> 6) & 0x2)], OF); + } + return res & 0xFF; +} + +/* rol word primitive */ +uint16 rol_word(uint16 d, uint16 s) +{ + register uint32 res, cnt, mask; + + res = d; + if ((cnt = s % 16)) { + res = (d << cnt); + mask = (1 << cnt) - 1; + res |= (d >> (16 - cnt)) & mask; + CONDITIONAL_SET_FLAG(res & 0x1, CF); + CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res & 0x1) + ((res >> 14) & 0x2)], OF); + } + return res&0xFFFF; +} + +/* ror byte primitive */ +uint8 ror_byte(uint8 d, uint8 s) +{ + register uint32 res, cnt, mask; + + res = d; + if ((cnt = s % 8)) { + res = (d << (8-cnt)); + mask = (1 << (8-cnt)) - 1; + res |= (d >> (cnt)) & mask; + CONDITIONAL_SET_FLAG(res & 0x80, CF); + CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res >> 6) & 0x3], OF); + } + return res & 0xFF; +} + +/* ror word primitive */ +uint16 ror_word(uint16 d, uint16 s) +{ + register uint32 res, cnt, mask; + + res = d; + if ((cnt = s % 16)) { + res = (d << (16-cnt)); + mask = (1 << (16-cnt)) - 1; + res |= (d >> (cnt)) & mask; + CONDITIONAL_SET_FLAG(res & 0x8000, CF); + CONDITIONAL_SET_FLAG(cnt == 1 && xor_3_tab[(res >> 14) & 0x3], OF); + } + return res & 0xFFFF; +} + +/* shl byte primitive */ +uint8 shl_byte(uint8 d, uint8 s) +{ + uint32 cnt, res, cf; + + if (s < 8) { + cnt = s % 8; + if (cnt > 0) { + res = d << cnt; + cf = d & (1 << (8 - cnt)); + CONDITIONAL_SET_FLAG(cf, CF); + CONDITIONAL_SET_FLAG((res & 0xFF)==0, ZF); + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + } else + res = (uint8) d; + if (cnt == 1) + CONDITIONAL_SET_FLAG((((res & 0x80) == 0x80) ^ + (GET_FLAG( CF) != 0)), OF); + else + CLR_FLAG(OF); + } else { + res = 0; + CONDITIONAL_SET_FLAG((s == 8) && (d & 1), CF); + CLR_FLAG(OF); + CLR_FLAG(SF); + CLR_FLAG(PF); + SET_FLAG(ZF); + } + return res & 0xFF; +} + +/* shl word primitive */ +uint16 shl_word(uint16 d, uint16 s) +{ + uint32 cnt, res, cf; + + if (s < 16) { + cnt = s % 16; + if (cnt > 0) { + res = d << cnt; + cf = d & (1<<(16-cnt)); + CONDITIONAL_SET_FLAG(cf, CF); + CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + } else + res = (uint16) d; + if (cnt == 1) + CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ + (GET_FLAG(CF) != 0)), OF); + else + CLR_FLAG(OF); + } else { + res = 0; + CONDITIONAL_SET_FLAG((s == 16) && (d & 1), CF); + CLR_FLAG(OF); + SET_FLAG(ZF); + CLR_FLAG(SF); + CLR_FLAG(PF); + } + return res & 0xFFFF; +} + +/* shr byte primitive */ +uint8 shr_byte(uint8 d, uint8 s) +{ + uint32 cnt, res, cf, mask; + + if (s < 8) { + cnt = s % 8; + if (cnt > 0) { + mask = (1 << (8 - cnt)) - 1; + cf = d & (1 << (cnt - 1)); + res = (d >> cnt) & mask; + CONDITIONAL_SET_FLAG(cf, CF); + CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + } else + res = (uint8) d; + if (cnt == 1) + CONDITIONAL_SET_FLAG(xor_3_tab[(res >> 6) & 0x3], OF); + else + CLR_FLAG(OF); + } else { + res = 0; + CONDITIONAL_SET_FLAG((s == 8) && (d & 0x80), CF); + CLR_FLAG(OF); + SET_FLAG(ZF); + CLR_FLAG(SF); + CLR_FLAG(PF); + } + return res & 0xFF; +} + +/* shr word primitive */ +uint16 shr_word(uint16 d, uint16 s) +{ + uint32 cnt, res, cf, mask; + + res = d; + if (s < 16) { + cnt = s % 16; + if (cnt > 0) { + mask = (1 << (16 - cnt)) - 1; + cf = d & (1 << (cnt - 1)); + res = (d >> cnt) & mask; + CONDITIONAL_SET_FLAG(cf, CF); + CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + } else + res = d; + if (cnt == 1) + CONDITIONAL_SET_FLAG(xor_3_tab[(res >> 14) & 0x3], OF); + else + CLR_FLAG(OF); + } else { + res = 0; + CONDITIONAL_SET_FLAG((s == 16) && (d & 0x8000), CF); + CLR_FLAG(OF); + SET_FLAG(ZF); + CLR_FLAG(SF); + CLR_FLAG(PF); + } + return res & 0xFFFF; +} + +/* sar byte primitive */ +uint8 sar_byte(uint8 d, uint8 s) +{ + uint32 cnt, res, cf, mask, sf; + + res = d; + sf = d & 0x80; + cnt = s % 8; + if (cnt > 0 && cnt < 8) { + mask = (1 << (8 - cnt)) - 1; + cf = d & (1 << (cnt -1 )); + res = (d >> cnt) & mask; + CONDITIONAL_SET_FLAG(cf, CF); + if (sf) + res |= ~mask; + CONDITIONAL_SET_FLAG((res & 0xFF)==0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + CONDITIONAL_SET_FLAG(res & 0x80, SF); + } else if (cnt >= 8) { + if (sf) { + res = 0xFF; + SET_FLAG(CF); + CLR_FLAG(ZF); + SET_FLAG(SF); + SET_FLAG(PF); + } else { + res = 0; + CLR_FLAG(CF); + SET_FLAG(ZF); + CLR_FLAG(SF); + CLR_FLAG(PF); + } + } + return res & 0xFF; +} + +/* sar word primitive */ +uint16 sar_word(uint16 d, uint16 s) +{ + uint32 cnt, res, cf, mask, sf; + + sf = d & 0x8000; + cnt = s % 16; + res = d; + if (cnt > 0 && cnt < 16) { + mask = (1 << (16 - cnt)) - 1; + cf = d & (1 << (cnt - 1)); + res = (d >> cnt) & mask; + CONDITIONAL_SET_FLAG(cf, CF); + if (sf) + res |= ~mask; + CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + } else if (cnt >= 16) { + if (sf) { + res = 0xFFFF; + SET_FLAG(CF); + CLR_FLAG(ZF); + SET_FLAG(SF); + SET_FLAG(PF); + } else { + res = 0; + CLR_FLAG(CF); + SET_FLAG(ZF); + CLR_FLAG(SF); + CLR_FLAG(PF); + } + } + return res & 0xFFFF; +} + +/* sbb byte primitive */ +uint8 sbb_byte(uint8 d, uint8 s) +{ + register uint32 res; + register uint32 bc; + + if (GET_FLAG(CF)) + res = d - s - 1; + else + res = d - s; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + /* calculate the borrow chain. See note at top */ + bc= (res&(~d|s))|(~d&s); + /* set flags based on borrow chain */ + CONDITIONAL_SET_FLAG(bc & 0x80, CF); + CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); + CONDITIONAL_SET_FLAG(bc & 0x8, AF); +// return res & 0x0FF; + return (uint8) res; +} + +/* sbb word primitive */ +uint16 sbb_word(uint16 d, uint16 s) +{ + register uint32 res; + register uint32 bc; + + if (GET_FLAG(CF)) + res = d - s - 1; + else + res = d - s; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG((res & 0xFFFF) == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + /* calculate the borrow chain. See note at top */ + bc= (res&(~d|s))|(~d&s); + /* set flags based on borrow chain */ + CONDITIONAL_SET_FLAG(bc & 0x8000, CF); + CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 14) & 0x3], OF); + CONDITIONAL_SET_FLAG(bc & 0x8, AF); +// return res & 0xFFFF; + return (uint16) res; +} + +/* sub byte primitive */ +uint8 sub_byte(uint8 d, uint8 s) +{ + register uint32 res; + register uint32 bc; + + res = d - s; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG((res & 0xFF) == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + /* calculate the borrow chain. See note at top */ + bc= (res&(~d|s))|(~d&s); + /* set flags based on borrow chain */ + CONDITIONAL_SET_FLAG(bc & 0x80, CF); + CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 6) & 0x3], OF); + CONDITIONAL_SET_FLAG(bc & 0x8, AF); +// return res & 0xff; + return (uint8) res; +} + +/* sub word primitive */ +uint16 sub_word(uint16 d, uint16 s) +{ + register uint32 res; + register uint32 bc; + + res = d - s; + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res &0x8000, SF); + CONDITIONAL_SET_FLAG((res &0xFFFF) == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + /* calculate the borrow chain. See note at top */ + bc= (res&(~d|s))|(~d&s); + /* set flags based on borrow chain */ + CONDITIONAL_SET_FLAG(bc & 0x8000, CF); + CONDITIONAL_SET_FLAG(xor_3_tab[(bc >> 14) & 0x3], OF); + CONDITIONAL_SET_FLAG(bc & 0x8, AF); +// return res & 0xffff; + return (uint16) res; +} + +/* test byte primitive */ +void test_byte(uint8 d, uint8 s) +{ + register uint32 res; + + res = d & s; + CLR_FLAG(OF); + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + /* AF == dont care*/ + CLR_FLAG(CF); +} + +/* test word primitive */ +void test_word(uint16 d, uint16 s) +{ + register uint32 res; + + res = d & s; + CLR_FLAG(OF); + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xff), PF); + /* AF == dont care*/ + CLR_FLAG(CF); +} + +/* xor byte primitive */ +uint8 xor_byte(uint8 d, uint8 s) +{ + register uint8 res; + res = d ^ s; + + /* clear flags */ + CLR_FLAG(OF); + CLR_FLAG(CF); + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x80, SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res), PF); + return res; +} + +/* xor word primitive */ +uint16 xor_word(uint16 d, uint16 s) +{ + register uint16 res; + + res = d ^ s; + /* clear flags */ + CLR_FLAG(OF); + CLR_FLAG(CF); + /* set the flags based on the result */ + CONDITIONAL_SET_FLAG(res & 0x8000, SF); + CONDITIONAL_SET_FLAG(res == 0, ZF); + CONDITIONAL_SET_FLAG(parity(res & 0xFF), PF); + return res; +} + +/* memory routines. These use the segment register (segreg) value and offset + (addr) to calculate the proper source or destination memory address */ + +/* get a byte from memory */ + +int32 get_smbyte(int32 segreg, int32 addr) +{ + int32 abs_addr, val; + + abs_addr = addr + (get_rword(segreg) << 4); + val = get_mbyte(abs_addr); +// if (i8088_dev.dctrl & DEBUG_level1) +// sim_printf("get_smbyte: seg=%04X addr=%04X abs_addr=%05X val=%02X\n", +// get_rword(segreg), addr, abs_addr, val); + return val; +} + +/* get a word from memory using addr and segment register */ + +int32 get_smword(int32 segreg, int32 addr) +{ + int32 val; + + val = get_smbyte(segreg, addr); + val |= (get_smbyte(segreg, addr+1) << 8); + return val; +} + +/* put a byte to memory using addr and segment register */ + +void put_smbyte(int32 segreg, int32 addr, int32 val) +{ + int32 abs_addr; + + abs_addr = addr + (get_rword(segreg) << 4); + put_mbyte(abs_addr, val); +// if (i8088_dev.dctrl & DEBUG_level1) +// sim_printf("put_smbyte: seg=%04X addr=%04X abs_addr=%08X val=%02X\n", +// get_rword(segreg), addr, abs_addr, val); +} + +/* put a word to memory using addr and segment register */ + +void put_smword(int32 segreg, int32 addr, int32 val) +{ + put_smbyte(segreg, addr, val); + put_smbyte(segreg, addr+1, val << 8); +} + +/* Reset routine using addr and segment register */ + +t_stat i8088_reset (DEVICE *dptr) +{ + PSW = 0; + CS = 0xFFFF; + DS = 0; + SS = 0; + ES = 0; + saved_PC = 0; + int_req = 0; + sim_brk_types = sim_brk_dflt = SWMASK ('E'); + sim_printf(" 8088 Reset\n"); + return SCPE_OK; +} + +/* Memory examine */ + +t_stat i8088_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) +{ + 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. +*/ + +t_stat sim_load (FILE *fileref, const char *cptr, const 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 == &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 +*/ + +t_stat parse_sym (const char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) +{ + int32 cflag, i = 0, j, r; + char gbuf[CBUFSIZE]; + + 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); +} + +/* end of i8088.c */ + diff --git a/IBMPC-Systems/common/i8237.c b/IBMPC-Systems/common/i8237.c index 2db649c7..83fc2b37 100644 --- a/IBMPC-Systems/common/i8237.c +++ b/IBMPC-Systems/common/i8237.c @@ -1,872 +1,872 @@ -/* 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 - 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 - -/* internal function prototypes */ - -t_stat i8237_svc (UNIT *uptr); -t_stat i8237_reset (DEVICE *dptr, uint16 base); -void i8237_reset1 (void); -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; // 8237 ch 0 address register -uint16 i8237_r1; // 8237 ch 0 count register -uint16 i8237_r2; // 8237 ch 1 address register -uint16 i8237_r3; // 8237 ch 1 count register -uint16 i8237_r4; // 8237 ch 2 address register -uint16 i8237_r5; // 8237 ch 2 count register -uint16 i8237_r6; // 8237 ch 3 address register -uint16 i8237_r7; // 8237 ch 3 count register -uint8 i8237_r8; // 8237 status register -uint8 i8237_r9; // 8237 command register -uint8 i8237_rA; // 8237 mode register -uint8 i8237_rB; // 8237 mask register -uint8 i8237_rC; // 8237 request register -uint8 i8237_rD; // 8237 first/last ff -uint8 i8237_rE; // 8237 -uint8 i8237_rF; // 8237 - -/* i8237 physical register definitions */ - -uint16 i8237_sr; // isbc-208 segment register -uint8 i8237_i; // iSBC-208 interrupt register -uint8 i8237_a; // 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, 16) }, - { HRDATA (CH0CNT, i8237_r1, 16) }, - { HRDATA (CH1ADR, i8237_r2, 16) }, - { HRDATA (CH1CNT, i8237_r3, 16) }, - { HRDATA (CH2ADR, i8237_r4, 16) }, - { HRDATA (CH2CNT, i8237_r5, 16) }, - { HRDATA (CH3ADR, i8237_r6, 16) }, - { HRDATA (CH3CNT, i8237_r7, 16) }, - { HRDATA (STAT37, i8237_r8, 8) }, - { HRDATA (CMD37, i8237_r9, 8) }, - { HRDATA (MODE, i8237_rA, 8) }, - { HRDATA (MASK, i8237_rB, 8) }, - { HRDATA (REQ, i8237_rC, 8) }, - { HRDATA (FF, i8237_rD, 8) }, - { HRDATA (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 = { - "8237", //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; - } - 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++; - 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(void) -{ - int32 i; - UNIT *uptr; - static int flag = 1; - - for (i = 0; i < 1; i++) { /* handle all units */ - uptr = i8237_dev.units + i; - if (uptr->capac == 0) { /* if not configured */ -// sim_printf(" SBC208%d: Not configured\n", i); -// if (flag) { -// sim_printf(" ALL: \"set isbc208 en\"\n"); -// sim_printf(" EPROM: \"att isbc2080 \"\n"); -// flag = 0; -// } - uptr->capac = 0; /* initialize unit */ - uptr->u3 = 0; - uptr->u4 = 0; - uptr->u5 = 0; - uptr->u6 = i; /* unit number - only set here! */ - sim_activate (&i8237_unit[uptr->u6], i8237_unit[uptr->u6].wait); - } else { -// sim_printf(" SBC208%d: Configured, Attached to %s\n", i, uptr->filename); - } - } - i8237_r8 = 0; /* status */ - i8237_r9 = 0; /* command */ - i8237_rB = 0x0F; /* mask */ - i8237_rC = 0; /* request */ - i8237_rD = 0; /* first/last FF */ -} - - -/* i8237 set mode = 8- or 16-bit data bus */ -/* always 8-bit mode for current simulators */ - -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(H) read as %04X\n", i8237_r0); - return (i8237_r0 >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(L) read as %04X\n", i8237_r0); - return (i8237_r0 & 0xFF); - } - } else { /* write base & current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r0 |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(H) set to %04X\n", i8237_r0); - } else { /* low byte */ - i8237_rD++; - i8237_r0 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(L) set to %04X\n", i8237_r0); - } - 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(H) read as %04X\n", i8237_r1); - return (i8237_r1 >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(L) read as %04X\n", i8237_r1); - return (i8237_r1 & 0xFF); - } - } else { /* write base & current address CH 0 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r1 |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(H) set to %04X\n", i8237_r1); - } else { /* low byte */ - i8237_rD++; - i8237_r1 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(L) set to %04X\n", i8237_r1); - } - 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(H) read as %04X\n", i8237_r2); - return (i8237_r2 >> 8); - } else { /* low byte */ - i8237_rD++; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(L) read as %04X\n", i8237_r2); - return (i8237_r2 & 0xFF); - } - } else { /* write base & current address CH 1 */ - if (i8237_rD) { /* high byte */ - i8237_rD = 0; - i8237_r2 |= (data << 8); - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(H) set to %04X\n", i8237_r2); - } else { /* low byte */ - i8237_rD++; - i8237_r2 = data & 0xFF; - sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(L) set to %04X\n", i8237_r2); - } - 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 + 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 + +/* internal function prototypes */ + +t_stat i8237_svc (UNIT *uptr); +t_stat i8237_reset (DEVICE *dptr, uint16 base); +void i8237_reset1 (void); +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; // 8237 ch 0 address register +uint16 i8237_r1; // 8237 ch 0 count register +uint16 i8237_r2; // 8237 ch 1 address register +uint16 i8237_r3; // 8237 ch 1 count register +uint16 i8237_r4; // 8237 ch 2 address register +uint16 i8237_r5; // 8237 ch 2 count register +uint16 i8237_r6; // 8237 ch 3 address register +uint16 i8237_r7; // 8237 ch 3 count register +uint8 i8237_r8; // 8237 status register +uint8 i8237_r9; // 8237 command register +uint8 i8237_rA; // 8237 mode register +uint8 i8237_rB; // 8237 mask register +uint8 i8237_rC; // 8237 request register +uint8 i8237_rD; // 8237 first/last ff +uint8 i8237_rE; // 8237 +uint8 i8237_rF; // 8237 + +/* i8237 physical register definitions */ + +uint16 i8237_sr; // isbc-208 segment register +uint8 i8237_i; // iSBC-208 interrupt register +uint8 i8237_a; // 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, 16) }, + { HRDATA (CH0CNT, i8237_r1, 16) }, + { HRDATA (CH1ADR, i8237_r2, 16) }, + { HRDATA (CH1CNT, i8237_r3, 16) }, + { HRDATA (CH2ADR, i8237_r4, 16) }, + { HRDATA (CH2CNT, i8237_r5, 16) }, + { HRDATA (CH3ADR, i8237_r6, 16) }, + { HRDATA (CH3CNT, i8237_r7, 16) }, + { HRDATA (STAT37, i8237_r8, 8) }, + { HRDATA (CMD37, i8237_r9, 8) }, + { HRDATA (MODE, i8237_rA, 8) }, + { HRDATA (MASK, i8237_rB, 8) }, + { HRDATA (REQ, i8237_rC, 8) }, + { HRDATA (FF, i8237_rD, 8) }, + { HRDATA (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 = { + "8237", //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; + } + 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++; + 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(void) +{ + int32 i; + UNIT *uptr; + static int flag = 1; + + for (i = 0; i < 1; i++) { /* handle all units */ + uptr = i8237_dev.units + i; + if (uptr->capac == 0) { /* if not configured */ +// sim_printf(" SBC208%d: Not configured\n", i); +// if (flag) { +// sim_printf(" ALL: \"set isbc208 en\"\n"); +// sim_printf(" EPROM: \"att isbc2080 \"\n"); +// flag = 0; +// } + uptr->capac = 0; /* initialize unit */ + uptr->u3 = 0; + uptr->u4 = 0; + uptr->u5 = 0; + uptr->u6 = i; /* unit number - only set here! */ + sim_activate (&i8237_unit[uptr->u6], i8237_unit[uptr->u6].wait); + } else { +// sim_printf(" SBC208%d: Configured, Attached to %s\n", i, uptr->filename); + } + } + i8237_r8 = 0; /* status */ + i8237_r9 = 0; /* command */ + i8237_rB = 0x0F; /* mask */ + i8237_rC = 0; /* request */ + i8237_rD = 0; /* first/last FF */ +} + + +/* i8237 set mode = 8- or 16-bit data bus */ +/* always 8-bit mode for current simulators */ + +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(H) read as %04X\n", i8237_r0); + return (i8237_r0 >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(L) read as %04X\n", i8237_r0); + return (i8237_r0 & 0xFF); + } + } else { /* write base & current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r0 |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(H) set to %04X\n", i8237_r0); + } else { /* low byte */ + i8237_rD++; + i8237_r0 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r0(L) set to %04X\n", i8237_r0); + } + 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(H) read as %04X\n", i8237_r1); + return (i8237_r1 >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(L) read as %04X\n", i8237_r1); + return (i8237_r1 & 0xFF); + } + } else { /* write base & current address CH 0 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r1 |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(H) set to %04X\n", i8237_r1); + } else { /* low byte */ + i8237_rD++; + i8237_r1 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r1(L) set to %04X\n", i8237_r1); + } + 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(H) read as %04X\n", i8237_r2); + return (i8237_r2 >> 8); + } else { /* low byte */ + i8237_rD++; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(L) read as %04X\n", i8237_r2); + return (i8237_r2 & 0xFF); + } + } else { /* write base & current address CH 1 */ + if (i8237_rD) { /* high byte */ + i8237_rD = 0; + i8237_r2 |= (data << 8); + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(H) set to %04X\n", i8237_r2); + } else { /* low byte */ + i8237_rD++; + i8237_r2 = data & 0xFF; + sim_debug (DEBUG_reg, &i8237_dev, "i8237_r2(L) set to %04X\n", i8237_r2); + } + 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/IBMPC-Systems/common/i8251.c b/IBMPC-Systems/common/i8251.c index 4bf4a366..48207074 100644 --- a/IBMPC-Systems/common/i8251.c +++ b/IBMPC-Systems/common/i8251.c @@ -1,318 +1,318 @@ -/* i8251.c: Intel 8251 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 base 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" - -/* 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 i8251_svc (UNIT *uptr); -t_stat i8251_reset (DEVICE *dptr, uint16 base); -void i8251_reset1(uint8 devnum); -uint8 i8251_get_dn(void); -uint8 i8251s(t_bool io, uint8 data); -uint8 i8251d(t_bool io, uint8 data); - -/* globals */ - -int32 i8251_devnum = 0; //initially, no 8251 instances -uint16 i8251_port[4]; //base port assigned to each 8251 instance - -/* i8251 Standard I/O Data Structures */ -/* up to 1 i8251 devices */ - -UNIT i8251_unit = { - { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT } -}; - -REG i8251_reg[4] = { - { HRDATA (DATA0, i8251_unit[0].buf, 8) }, - { HRDATA (STAT0, i8251_unit[0].u3, 8) }, - { HRDATA (MODE0, i8251_unit[0].u4, 8) }, - { HRDATA (CMD0, i8251_unit[0].u5, 8) }, - { HRDATA (DATA1, i8251_unit[1].buf, 8) }, - { HRDATA (STAT1, i8251_unit[1].u3, 8) }, - { HRDATA (MODE1, i8251_unit[1].u4, 8) }, - { HRDATA (CMD1, i8251_unit[1].u5, 8) }, - { HRDATA (DATA2, i8251_unit[2].buf, 8) }, - { HRDATA (STAT2, i8251_unit[2].u3, 8) }, - { HRDATA (MODE2, i8251_unit[2].u4, 8) }, - { HRDATA (CMD2, i8251_unit[2].u5, 8) }, - { HRDATA (DATA3, i8251_unit[3].buf, 8) }, - { HRDATA (STAT3, i8251_unit[3].u3, 8) }, - { HRDATA (MOD3E, i8251_unit[3].u4, 8) }, - { HRDATA (CMD3, i8251_unit[3].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 = { - "8251", //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 base) -{ - if (i8251_devnum >= I8251_NUM) { - sim_printf("8251_reset: too many devices!\n"); - return 0; - } - i8251_port[i8251_devnum] = reg_dev(i8251d, base); - reg_dev(i8251s, base + 1); - i8251_reset1(i8251_devnum); - sim_printf(" 8251-%d: Registered at %04X\n", i8251_devnum, base); - sim_activate (&i8251_unit[i8251_devnum], i8251_unit[i8251_devnum].wait); /* activate unit */ - i8259_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: 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 %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 = i8259_get_dn()) != 0xFF) { - if (io == 0) { /* read status port */ - return i8251_unit[devnum].u3; - } else { /* write status port */ - if (i8251_unit[devnum].u6) { /* if mode, set cmd */ - i8251_unit[devnum].u5 = data; - sim_printf(" 8251-%d: Command Instruction=%02X\n", devnum, data); - if (data & SD) /* reset port! */ - i8251_reset1(devnum); - } else { /* set mode */ - i8251_unit[devnum].u4 = data; - sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); - i8251_unit[devnum].u6 = 1; /* set cmd received */ - } - } - } - return 0; -} - -uint8 i8251d(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8259_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - i8251_unit[devnum].u3 &= ~RXR; - return (i8251_unit[devnum].buf); - } else { /* write data port */ - sim_putchar(data); - } - } - return 0; -} - -/* end of i8251.c */ +/* i8251.c: Intel 8251 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 base 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" + +/* 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 i8251_svc (UNIT *uptr); +t_stat i8251_reset (DEVICE *dptr, uint16 base); +void i8251_reset1(uint8 devnum); +uint8 i8251_get_dn(void); +uint8 i8251s(t_bool io, uint8 data); +uint8 i8251d(t_bool io, uint8 data); + +/* globals */ + +int32 i8251_devnum = 0; //initially, no 8251 instances +uint16 i8251_port[4]; //base port assigned to each 8251 instance + +/* i8251 Standard I/O Data Structures */ +/* up to 1 i8251 devices */ + +UNIT i8251_unit = { + { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&i8251_svc, 0, 0), KBD_POLL_WAIT } +}; + +REG i8251_reg[4] = { + { HRDATA (DATA0, i8251_unit[0].buf, 8) }, + { HRDATA (STAT0, i8251_unit[0].u3, 8) }, + { HRDATA (MODE0, i8251_unit[0].u4, 8) }, + { HRDATA (CMD0, i8251_unit[0].u5, 8) }, + { HRDATA (DATA1, i8251_unit[1].buf, 8) }, + { HRDATA (STAT1, i8251_unit[1].u3, 8) }, + { HRDATA (MODE1, i8251_unit[1].u4, 8) }, + { HRDATA (CMD1, i8251_unit[1].u5, 8) }, + { HRDATA (DATA2, i8251_unit[2].buf, 8) }, + { HRDATA (STAT2, i8251_unit[2].u3, 8) }, + { HRDATA (MODE2, i8251_unit[2].u4, 8) }, + { HRDATA (CMD2, i8251_unit[2].u5, 8) }, + { HRDATA (DATA3, i8251_unit[3].buf, 8) }, + { HRDATA (STAT3, i8251_unit[3].u3, 8) }, + { HRDATA (MOD3E, i8251_unit[3].u4, 8) }, + { HRDATA (CMD3, i8251_unit[3].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 = { + "8251", //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 base) +{ + if (i8251_devnum >= I8251_NUM) { + sim_printf("8251_reset: too many devices!\n"); + return 0; + } + i8251_port[i8251_devnum] = reg_dev(i8251d, base); + reg_dev(i8251s, base + 1); + i8251_reset1(i8251_devnum); + sim_printf(" 8251-%d: Registered at %04X\n", i8251_devnum, base); + sim_activate (&i8251_unit[i8251_devnum], i8251_unit[i8251_devnum].wait); /* activate unit */ + i8259_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: 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 %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 = i8259_get_dn()) != 0xFF) { + if (io == 0) { /* read status port */ + return i8251_unit[devnum].u3; + } else { /* write status port */ + if (i8251_unit[devnum].u6) { /* if mode, set cmd */ + i8251_unit[devnum].u5 = data; + sim_printf(" 8251-%d: Command Instruction=%02X\n", devnum, data); + if (data & SD) /* reset port! */ + i8251_reset1(devnum); + } else { /* set mode */ + i8251_unit[devnum].u4 = data; + sim_printf(" 8251-%d: Mode Instruction=%02X\n", devnum, data); + i8251_unit[devnum].u6 = 1; /* set cmd received */ + } + } + } + return 0; +} + +uint8 i8251d(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8259_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + i8251_unit[devnum].u3 &= ~RXR; + return (i8251_unit[devnum].buf); + } else { /* write data port */ + sim_putchar(data); + } + } + return 0; +} + +/* end of i8251.c */ diff --git a/IBMPC-Systems/common/i8253.c b/IBMPC-Systems/common/i8253.c index 4ed10bd0..69130287 100644 --- a/IBMPC-Systems/common/i8253.c +++ b/IBMPC-Systems/common/i8253.c @@ -1,235 +1,235 @@ -/* 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 base and size. - 24 Apr 15 -- Modified to use simh_debug - - NOTES: - -*/ - -#include "system_defs.h" - -/* external function prototypes */ - -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); - -/* external globals */ - -extern uint16 port; //port called in dev_table[port] - -/* globals */ - -int32 i8253_devnum = 0; //actual number of 8253 instances + 1 -uint16 i8253_port[4]; //base port registered to each instance - -/* function prototypes */ - -t_stat i8253_svc (UNIT *uptr); -t_stat i8253_reset (DEVICE *dptr, uint16 base); -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 = { - "8251", //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) -{ - int32 temp; - - sim_activate (&i8253_unit[0], i8253_unit[0].wait); /* continue poll */ - return SCPE_OK; -} - -/* Reset routine */ - -t_stat i8253_reset (DEVICE *dptr, uint16 port) -{ - if (i8253_devnum > I8253_NUM) { - sim_printf("i8253_reset: too many devices!\n"); - return SCPE_MEM; - } - i8253_port[i8253_devnum] = reg_dev(i8253t0, port); - reg_dev(i8253t1, port + 1); - reg_dev(i8253t2, port + 2); - reg_dev(i8253c, port + 3); - 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_printf(" 8253-%d: Reset\n", i8253_devnum); - sim_printf(" 8253-%d: Registered at %03X\n", i8253_devnum, port); - 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 %03X 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 */ - i8253_unit[devnum].u3 = data; - return 0; - } else { /* write data port */ - return i8253_unit[devnum].u3; - } - } - return 0; -} - -uint8 i8253t1(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8253_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - i8253_unit[devnum].u4 = data; - return 0; - } else { /* write data port */ - return i8253_unit[devnum].u4; - } - } - return 0; -} - -uint8 i8253t2(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8253_get_dn()) != 0xFF) { - if (io == 0) { /* read data port */ - i8253_unit[devnum].u5 = data; - return 0; - } else { /* write data port */ - return i8253_unit[devnum].u5; - } - } - return 0; -} - -uint8 i8253c(t_bool io, uint8 data) -{ - uint8 devnum; - - if ((devnum = i8253_get_dn()) != 0xFF) { - if (io == 0) { /* read status port */ - i8253_unit[devnum].u6 = data; - return 0; - } else { /* write data port */ - return i8253_unit[devnum].u6; - } - } - 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 base and size. + 24 Apr 15 -- Modified to use simh_debug + + NOTES: + +*/ + +#include "system_defs.h" + +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + +/* globals */ + +int32 i8253_devnum = 0; //actual number of 8253 instances + 1 +uint16 i8253_port[4]; //base port registered to each instance + +/* function prototypes */ + +t_stat i8253_svc (UNIT *uptr); +t_stat i8253_reset (DEVICE *dptr, uint16 base); +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 = { + "8251", //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) +{ + int32 temp; + + sim_activate (&i8253_unit[0], i8253_unit[0].wait); /* continue poll */ + return SCPE_OK; +} + +/* Reset routine */ + +t_stat i8253_reset (DEVICE *dptr, uint16 port) +{ + if (i8253_devnum > I8253_NUM) { + sim_printf("i8253_reset: too many devices!\n"); + return SCPE_MEM; + } + i8253_port[i8253_devnum] = reg_dev(i8253t0, port); + reg_dev(i8253t1, port + 1); + reg_dev(i8253t2, port + 2); + reg_dev(i8253c, port + 3); + 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_printf(" 8253-%d: Reset\n", i8253_devnum); + sim_printf(" 8253-%d: Registered at %03X\n", i8253_devnum, port); + 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 %03X 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 */ + i8253_unit[devnum].u3 = data; + return 0; + } else { /* write data port */ + return i8253_unit[devnum].u3; + } + } + return 0; +} + +uint8 i8253t1(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8253_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + i8253_unit[devnum].u4 = data; + return 0; + } else { /* write data port */ + return i8253_unit[devnum].u4; + } + } + return 0; +} + +uint8 i8253t2(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8253_get_dn()) != 0xFF) { + if (io == 0) { /* read data port */ + i8253_unit[devnum].u5 = data; + return 0; + } else { /* write data port */ + return i8253_unit[devnum].u5; + } + } + return 0; +} + +uint8 i8253c(t_bool io, uint8 data) +{ + uint8 devnum; + + if ((devnum = i8253_get_dn()) != 0xFF) { + if (io == 0) { /* read status port */ + i8253_unit[devnum].u6 = data; + return 0; + } else { /* write data port */ + return i8253_unit[devnum].u6; + } + } + return 0; +} + +/* end of i8253.c */ diff --git a/IBMPC-Systems/common/i8255.c b/IBMPC-Systems/common/i8255.c index bb0851e9..c0326aef 100644 --- a/IBMPC-Systems/common/i8255.c +++ b/IBMPC-Systems/common/i8255.c @@ -1,289 +1,289 @@ -/* 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 (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. - - 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 */ - -/* 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 i8255s(t_bool io, uint8 data); -uint8 i8255a(t_bool io, uint8 data); -uint8 i8255b(t_bool io, uint8 data); -uint8 i8255c(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 = { - "8255", //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_reset, //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 i8255_unit[devnum].u3; - } else { /* write status port */ - if (data & 0x80) { /* mode instruction */ - i8255_unit[devnum].u3 = data; - 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; - 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; - 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; - 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 (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. + + 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 */ + +/* 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 i8255s(t_bool io, uint8 data); +uint8 i8255a(t_bool io, uint8 data); +uint8 i8255b(t_bool io, uint8 data); +uint8 i8255c(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 = { + "8255", //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_reset, //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 i8255_unit[devnum].u3; + } else { /* write status port */ + if (data & 0x80) { /* mode instruction */ + i8255_unit[devnum].u3 = data; + 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; + 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; + 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; + sim_printf(" 8255-%d: Port C = %02X\n", devnum, data); + } + } + return 0; +} + +/* end of i8255.c */ diff --git a/IBMPC-Systems/common/i8259.c b/IBMPC-Systems/common/i8259.c index 641f0f74..a2725432 100644 --- a/IBMPC-Systems/common/i8259.c +++ b/IBMPC-Systems/common/i8259.c @@ -1,263 +1,263 @@ -/* 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 Computer Systems. - - This program simulates up to 4 i8259 devices. - - u3 = IRR - u4 = ISR - u5 = IMR -*/ - -#include "system_defs.h" /* system header in system dir */ - -/* external globals */ - -extern uint16 port; //port called in dev_table[port] - -/* function prototypes */ - -void i8259_dump(uint8 devnum); -t_stat i8259_reset (DEVICE *dptr, uint16 base); -uint8 i8259_get_dn(void); -uint8 i8259a(t_bool io, uint8 data); -uint8 i8259b(t_bool io, uint8 data); - -/* external function prototypes */ - -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); - -/* globals */ - -int32 i8259_devnum = 0; //initially, no 8259 instances -uint16 i8259_port[4]; //base port assigned to each 8259 instance -uint8 i8259_ints[4]; //8 interrupt inputs for each 8259 instance - -uint8 i8259_icw1[4]; -uint8 i8259_icw2[4]; -uint8 i8259_icw3[4]; -uint8 i8259_icw4[4]; -uint8 i8259_ocw1[4]; -uint8 i8259_ocw2[4]; -uint8 i8259_ocw3[4]; -uint8 icw_num0 = 1, icw_num1 = 1; - -/* i8259 Standard I/O Data Structures */ -/* up to 4 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 0 */ - { HRDATA (ISR1, i8259_unit[1].u4, 8) }, - { HRDATA (IMR1, i8259_unit[1].u5, 8) }, - { HRDATA (IRR2, i8259_unit[2].u3, 8) }, /* i8259 2 */ - { HRDATA (ISR2, i8259_unit[2].u4, 8) }, - { HRDATA (IMR2, i8259_unit[2].u5, 8) }, - { HRDATA (IRR3, i8259_unit[3].u3, 8) }, /* i8259 3 */ - { HRDATA (ISR3, i8259_unit[3].u4, 8) }, - { HRDATA (IMR3, i8259_unit[3].u5, 8) }, - { NULL } -}; - -DEBTAB i8259_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 i8259_dev = { - "8259", //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 -}; - -void i8259_dump(uint8 devnum) -{ - sim_printf("Device %d\n", devnum); - sim_printf(" IRR = %02X\n", i8259_unit[devnum].u3); - sim_printf(" ISR = %02X\n", i8259_unit[devnum].u4); - sim_printf(" IMR = %02X\n", i8259_unit[devnum].u5); - sim_printf(" ICW1 = %02X\n", i8259_icw1[devnum]); - sim_printf(" ICW2 = %02X\n", i8259_icw2[devnum]); - sim_printf(" ICW3 = %02X\n", i8259_icw3[devnum]); - sim_printf(" ICW4 = %02X\n", i8259_icw4[devnum]); - sim_printf(" OCW1 = %02X\n", i8259_ocw1[devnum]); - sim_printf(" OCW2 = %02X\n", i8259_ocw2[devnum]); - sim_printf(" OCW3 = %02X\n", i8259_ocw3[devnum]); -} - -/* Reset routine */ - -t_stat i8259_reset (DEVICE *dptr, uint16 base) -{ - if (i8259_devnum > I8259_NUM) { - sim_printf("i8259_reset: too many devices!\n"); - return SCPE_MEM; - } - i8259_port[i8259_devnum] = reg_dev(i8259a, base); - reg_dev(i8259b, base + 1); - i8259_unit[i8259_devnum].u3 = 0x00; /* IRR */ - i8259_unit[i8259_devnum].u4 = 0x00; /* ISR */ - i8259_unit[i8259_devnum].u5 = 0x00; /* IMR */ - sim_printf(" 8259-%d: Reset\n", i8259_devnum); - sim_printf(" 8259-%d: Registered at %03X\n", i8259_devnum, base); - i8259_devnum++; - return SCPE_OK; -} - -uint8 i8259_get_dn(void) -{ - int i; - - for (i=0; i=i8259_port[i] && port <= i8259_port[i] + 2) - return i; - sim_printf("i8259_get_dn: port %03X not in 8259 device table\n", port); - return 0xFF; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. -*/ - - -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; - } - } - sim_printf("8259a-%d: 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; - } - } - sim_printf("8259b-%d: data = %02X\n", devnum, data); - icw_num1++; /* step ICW number */ - } - } - //i8259_dump(devnum); - return 0; -} - -/* 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 Computer Systems. + + This program simulates up to 4 i8259 devices. + + u3 = IRR + u4 = ISR + u5 = IMR +*/ + +#include "system_defs.h" /* system header in system dir */ + +/* external globals */ + +extern uint16 port; //port called in dev_table[port] + +/* function prototypes */ + +void i8259_dump(uint8 devnum); +t_stat i8259_reset (DEVICE *dptr, uint16 base); +uint8 i8259_get_dn(void); +uint8 i8259a(t_bool io, uint8 data); +uint8 i8259b(t_bool io, uint8 data); + +/* external function prototypes */ + +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); + +/* globals */ + +int32 i8259_devnum = 0; //initially, no 8259 instances +uint16 i8259_port[4]; //base port assigned to each 8259 instance +uint8 i8259_ints[4]; //8 interrupt inputs for each 8259 instance + +uint8 i8259_icw1[4]; +uint8 i8259_icw2[4]; +uint8 i8259_icw3[4]; +uint8 i8259_icw4[4]; +uint8 i8259_ocw1[4]; +uint8 i8259_ocw2[4]; +uint8 i8259_ocw3[4]; +uint8 icw_num0 = 1, icw_num1 = 1; + +/* i8259 Standard I/O Data Structures */ +/* up to 4 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 0 */ + { HRDATA (ISR1, i8259_unit[1].u4, 8) }, + { HRDATA (IMR1, i8259_unit[1].u5, 8) }, + { HRDATA (IRR2, i8259_unit[2].u3, 8) }, /* i8259 2 */ + { HRDATA (ISR2, i8259_unit[2].u4, 8) }, + { HRDATA (IMR2, i8259_unit[2].u5, 8) }, + { HRDATA (IRR3, i8259_unit[3].u3, 8) }, /* i8259 3 */ + { HRDATA (ISR3, i8259_unit[3].u4, 8) }, + { HRDATA (IMR3, i8259_unit[3].u5, 8) }, + { NULL } +}; + +DEBTAB i8259_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 i8259_dev = { + "8259", //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 +}; + +void i8259_dump(uint8 devnum) +{ + sim_printf("Device %d\n", devnum); + sim_printf(" IRR = %02X\n", i8259_unit[devnum].u3); + sim_printf(" ISR = %02X\n", i8259_unit[devnum].u4); + sim_printf(" IMR = %02X\n", i8259_unit[devnum].u5); + sim_printf(" ICW1 = %02X\n", i8259_icw1[devnum]); + sim_printf(" ICW2 = %02X\n", i8259_icw2[devnum]); + sim_printf(" ICW3 = %02X\n", i8259_icw3[devnum]); + sim_printf(" ICW4 = %02X\n", i8259_icw4[devnum]); + sim_printf(" OCW1 = %02X\n", i8259_ocw1[devnum]); + sim_printf(" OCW2 = %02X\n", i8259_ocw2[devnum]); + sim_printf(" OCW3 = %02X\n", i8259_ocw3[devnum]); +} + +/* Reset routine */ + +t_stat i8259_reset (DEVICE *dptr, uint16 base) +{ + if (i8259_devnum > I8259_NUM) { + sim_printf("i8259_reset: too many devices!\n"); + return SCPE_MEM; + } + i8259_port[i8259_devnum] = reg_dev(i8259a, base); + reg_dev(i8259b, base + 1); + i8259_unit[i8259_devnum].u3 = 0x00; /* IRR */ + i8259_unit[i8259_devnum].u4 = 0x00; /* ISR */ + i8259_unit[i8259_devnum].u5 = 0x00; /* IMR */ + sim_printf(" 8259-%d: Reset\n", i8259_devnum); + sim_printf(" 8259-%d: Registered at %03X\n", i8259_devnum, base); + i8259_devnum++; + return SCPE_OK; +} + +uint8 i8259_get_dn(void) +{ + int i; + + for (i=0; i=i8259_port[i] && port <= i8259_port[i] + 2) + return i; + sim_printf("i8259_get_dn: port %03X not in 8259 device table\n", port); + return 0xFF; +} + +/* I/O instruction handlers, called from the CPU module when an + IN or OUT instruction is issued. +*/ + + +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; + } + } + sim_printf("8259a-%d: 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; + } + } + sim_printf("8259b-%d: data = %02X\n", devnum, data); + icw_num1++; /* step ICW number */ + } + } + //i8259_dump(devnum); + return 0; +} + +/* end of i8259.c */ diff --git a/IBMPC-Systems/common/i8273.c b/IBMPC-Systems/common/i8273.c index aa91fcf4..674ab597 100644 --- a/IBMPC-Systems/common/i8273.c +++ b/IBMPC-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 = { - "8273", //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 = { + "8273", //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/IBMPC-Systems/common/i8274.c b/IBMPC-Systems/common/i8274.c index 357352f3..ef1dc406 100644 --- a/IBMPC-Systems/common/i8274.c +++ b/IBMPC-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 = { - "8274", //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 = { + "8274", //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/IBMPC-Systems/common/ipata.c b/IBMPC-Systems/common/ipata.c index 715f61f4..0a748bda 100644 --- a/IBMPC-Systems/common/ipata.c +++ b/IBMPC-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/IBMPC-Systems/common/pata.c b/IBMPC-Systems/common/pata.c index 0d68d4d9..4b08043d 100644 --- a/IBMPC-Systems/common/pata.c +++ b/IBMPC-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/IBMPC-Systems/common/pcbus.c b/IBMPC-Systems/common/pcbus.c index 0309d5ee..68c05dcb 100644 --- a/IBMPC-Systems/common/pcbus.c +++ b/IBMPC-Systems/common/pcbus.c @@ -1,465 +1,466 @@ -/* pcbus.c: PC bus 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. - - MODIFICATIONS: - - 11 Jul 16 - Original file. - - NOTES: - - This software was written by Bill Beech, Jul 2016, to allow emulation of PC XT - Computer Systems. - -*/ - -#include "system_defs.h" - -int32 mbirq = 0; /* set no interrupts */ - -/* function prototypes */ - -t_stat xtbus_svc(UNIT *uptr); -t_stat xtbus_reset(DEVICE *dptr); -void set_irq(int32 int_num); -void clr_irq(int32 int_num); -uint8 nulldev(t_bool io, uint8 data); -uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port); -void dump_dev_table(void); -t_stat xtbus_reset (DEVICE *dptr); -uint8 xtbus_get_mbyte(uint32 addr); -void xtbus_put_mbyte(uint32 addr, uint8 val); - -/* external function prototypes */ - -extern t_stat SBC_reset(DEVICE *dptr); /* reset the PC XT simulator */ -extern void set_cpuint(int32 int_num); - -/* external globals */ - -extern int32 int_req; /* i8088 INT signal */ -extern uint16 port; //port called in dev_table[port] - -/* Standard SIMH Device Data Structures */ - -UNIT xtbus_unit = { - UDATA (&xtbus_svc, 0, 0), 20 -}; - -REG xtbus_reg[] = { - { HRDATA (MBIRQ, mbirq, 32) }, -}; - -DEBTAB xtbus_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE xtbus_dev = { - "PCBUS", //name - &xtbus_unit, //units - xtbus_reg, //registers - NULL, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - &xtbus_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - xtbus_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Service routines to handle simulator functions */ - -/* service routine - actually does the simulated interrupts */ - -t_stat xtbus_svc(UNIT *uptr) -{ - switch (mbirq) { - case INT_1: - set_cpuint(INT_R); - sim_printf("xtbus_svc: mbirq=%04X int_req=%04X\n", mbirq, int_req); - break; - default: - //sim_printf("xtbus_svc: default mbirq=%04X\n", mbirq); - break; - } - sim_activate (&xtbus_unit, xtbus_unit.wait); /* continue poll */ - return SCPE_OK; -} - -/* Reset routine */ - -t_stat xtbus_reset(DEVICE *dptr) -{ - SBC_reset(NULL); - sim_printf(" Xtbus: Reset\n"); - sim_activate (&xtbus_unit, xtbus_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 1024 possible -device addresses, if a device is plugged to a port it's routine -address is here, 'nulldev' means no device has been registered. -The actual 808X can address 65,536 I/O ports but the IBM only uses -the first 1024. */ - -struct idev { - uint8 (*routine)(t_bool io, uint8 data); -}; - -struct idev dev_table[1024] = { -{&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 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 100H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 104H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 108H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 10CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 110H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 114H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 118H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 11CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 120H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 124H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 128H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 12CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 130H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 134H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 138H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 13CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 140H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 144H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 148H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 14CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 150H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 154H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 158H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 15CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 160H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 164H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 168H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 16CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 170H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 174H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 178H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 17CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 180H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 184H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 188H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 18CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 190H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 194H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 198H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 19CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1CCH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1D0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1D4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1D8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1DCH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1E0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1E4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1E8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1ECH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1F0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1F4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1F8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1FCH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 200H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 204H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 208H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 20CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 210H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 214H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 218H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 21CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 220H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 224H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 228H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 22CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 230H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 234H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 238H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 23CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 240H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 244H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 248H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 24CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 250H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 254H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 258H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 25CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 260H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 264H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 268H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 26CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 270H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 274H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 278H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 27CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 280H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 284H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 288H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 28CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 290H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 294H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 298H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 29CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2CCH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2D0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2D4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2D8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2DCH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2E0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2E4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2E8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2ECH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2F0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2F4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2F8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2FCH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 300H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 304H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 308H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 30CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 310H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 314H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 318H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 31CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 320H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 324H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 328H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 32CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 330H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 334H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 338H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 33CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 340H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 344H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 348H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 34CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 350H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 354H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 358H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 35CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 360H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 364H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 368H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 36CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 370H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 374H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 378H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 37CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 380H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 384H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 388H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 38CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 390H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 394H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 398H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 39CH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3CCH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3D0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3D4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3D8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3DCH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3E0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3E4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3E8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3ECH */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3F0H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3F4H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3F8H */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 3FCH */ -}; - -uint8 nulldev(t_bool flag, uint8 data) -{ - sim_printf("xtbus: I/O Port %03X is not assigned io=%d data=%02X\n", - port, flag, data); - if (flag == 0) /* if we got here, no valid I/O device */ - return 0xFF; -} - -uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port) -{ - if (dev_table[port].routine != &nulldev) { /* port already assigned */ - sim_printf("xtbus: I/O Port %03X is already assigned\n", port); - } else { - sim_printf("Port %03X is assigned\n", port); - dev_table[port].routine = routine; - } - //dump_dev_table(); - return port; -} - -void dump_dev_table(void) -{ - int i; - - for (i=0; i<1024; i++) { - if (dev_table[i].routine != &nulldev) { /* assigned port */ - sim_printf("Port %03X is assigned\n", i); - } - } -} - -/* get a byte from bus */ - -uint8 xtbus_get_mbyte(uint32 addr) -{ - return 0xFF; -} - -/* put a byte to bus */ - -void xtbus_put_mbyte(uint32 addr, uint8 val) -{ - ; -} - -/* end of pcbus.c */ - +/* pcbus.c: PC bus 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. + + MODIFICATIONS: + + 11 Jul 16 - Original file. + + NOTES: + + This software was written by Bill Beech, Jul 2016, to allow emulation of PC XT + Computer Systems. + +*/ + +#include "system_defs.h" + +int32 mbirq = 0; /* set no interrupts */ + +/* function prototypes */ + +t_stat xtbus_svc(UNIT *uptr); +t_stat xtbus_reset(DEVICE *dptr); +void set_irq(int32 int_num); +void clr_irq(int32 int_num); +uint8 nulldev(t_bool io, uint8 data); +uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port); +void dump_dev_table(void); +t_stat xtbus_reset (DEVICE *dptr); +uint8 xtbus_get_mbyte(uint32 addr); +void xtbus_put_mbyte(uint32 addr, uint8 val); + +/* external function prototypes */ +extern uint8 RAM_get_mbyte(uint32 addr); +extern void RAM_put_mbyte(uint32 addr, uint8 val); +extern t_stat SBC_reset(DEVICE *dptr); /* reset the PC XT simulator */ +extern void set_cpuint(int32 int_num); + +/* external globals */ + +extern int32 int_req; /* i8088 INT signal */ +extern uint16 port; //port called in dev_table[port] + +/* Standard SIMH Device Data Structures */ + +UNIT xtbus_unit = { + UDATA (&xtbus_svc, 0, 0), 20 +}; + +REG xtbus_reg[] = { + { HRDATA (MBIRQ, mbirq, 32) }, +}; + +DEBTAB xtbus_debug[] = { + { "ALL", DEBUG_all }, + { "FLOW", DEBUG_flow }, + { "READ", DEBUG_read }, + { "WRITE", DEBUG_write }, + { "LEV1", DEBUG_level1 }, + { "LEV2", DEBUG_level2 }, + { NULL } +}; + +DEVICE xtbus_dev = { + "PCBUS", //name + &xtbus_unit, //units + xtbus_reg, //registers + NULL, //modifiers + 1, //numunits + 16, //aradix + 16, //awidth + 1, //aincr + 16, //dradix + 8, //dwidth + NULL, //examine + NULL, //deposit + &xtbus_reset, //reset + NULL, //boot + NULL, //attach + NULL, //detach + NULL, //ctxt + DEV_DEBUG, //flags + 0, //dctrl + xtbus_debug, //debflags + NULL, //msize + NULL //lname +}; + +/* Service routines to handle simulator functions */ + +/* service routine - actually does the simulated interrupts */ + +t_stat xtbus_svc(UNIT *uptr) +{ + switch (mbirq) { + case INT_1: + set_cpuint(INT_R); + sim_printf("xtbus_svc: mbirq=%04X int_req=%04X\n", mbirq, int_req); + break; + default: + //sim_printf("xtbus_svc: default mbirq=%04X\n", mbirq); + break; + } + sim_activate (&xtbus_unit, xtbus_unit.wait); /* continue poll */ + return SCPE_OK; +} + +/* Reset routine */ + +t_stat xtbus_reset(DEVICE *dptr) +{ + SBC_reset(NULL); + sim_printf(" Xtbus: Reset\n"); + sim_activate (&xtbus_unit, xtbus_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 1024 possible +device addresses, if a device is plugged to a port it's routine +address is here, 'nulldev' means no device has been registered. +The actual 808X can address 65,536 I/O ports but the IBM only uses +the first 1024. */ + +struct idev { + uint8 (*routine)(t_bool io, uint8 data); +}; + +struct idev dev_table[1024] = { +{&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 */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 100H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 104H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 108H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 10CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 110H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 114H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 118H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 11CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 120H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 124H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 128H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 12CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 130H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 134H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 138H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 13CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 140H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 144H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 148H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 14CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 150H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 154H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 158H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 15CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 160H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 164H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 168H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 16CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 170H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 174H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 178H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 17CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 180H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 184H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 188H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 18CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 190H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 194H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 198H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 19CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1CCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1D0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1D4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1D8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1DCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1E0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1E4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1E8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1ECH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1F0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1F4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1F8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1FCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 200H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 204H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 208H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 20CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 210H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 214H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 218H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 21CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 220H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 224H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 228H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 22CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 230H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 234H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 238H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 23CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 240H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 244H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 248H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 24CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 250H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 254H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 258H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 25CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 260H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 264H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 268H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 26CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 270H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 274H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 278H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 27CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 280H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 284H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 288H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 28CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 290H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 294H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 298H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 29CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2CCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2D0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2D4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2D8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2DCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2E0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2E4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2E8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2ECH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2F0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2F4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2F8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2FCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 300H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 304H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 308H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 30CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 310H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 314H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 318H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 31CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 320H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 324H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 328H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 32CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 330H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 334H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 338H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 33CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 340H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 344H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 348H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 34CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 350H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 354H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 358H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 35CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 360H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 364H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 368H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 36CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 370H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 374H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 378H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 37CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 380H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 384H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 388H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 38CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 390H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 394H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 398H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 39CH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3A0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3B0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3CCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3D0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3D4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3D8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3DCH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3E0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3E4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3E8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3ECH */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3F0H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3F4H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3F8H */ +{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /* 3FCH */ +}; + +uint8 nulldev(t_bool flag, uint8 data) +{ + sim_printf("xtbus: I/O Port %03X is not assigned io=%d data=%02X\n", + port, flag, data); + if (flag == 0) /* if we got here, no valid I/O device */ + return 0xFF; +} + +uint16 reg_dev(uint8 (*routine)(t_bool io, uint8 data), uint16 port) +{ + if (dev_table[port].routine != &nulldev) { /* port already assigned */ + sim_printf("xtbus: I/O Port %03X is already assigned\n", port); + } else { + sim_printf("Port %03X is assigned\n", port); + dev_table[port].routine = routine; + } + //dump_dev_table(); + return port; +} + +void dump_dev_table(void) +{ + int i; + + for (i=0; i<1024; i++) { + if (dev_table[i].routine != &nulldev) { /* assigned port */ + sim_printf("Port %03X is assigned\n", i); + } + } +} + +/* get a byte from bus */ + +uint8 xtbus_get_mbyte(uint32 addr) +{ + return RAM_get_mbyte(addr); +} + +/* put a byte to bus */ + +void xtbus_put_mbyte(uint32 addr, uint8 val) +{ + RAM_put_mbyte(addr, val); +} + +/* end of pcbus.c */ + diff --git a/IBMPC-Systems/common/pceprom.c b/IBMPC-Systems/common/pceprom.c index cc02a4cd..2e6ab5d4 100644 --- a/IBMPC-Systems/common/pceprom.c +++ b/IBMPC-Systems/common/pceprom.c @@ -1,177 +1,177 @@ -/* pceprom.c: Intel EPROM simulator for 8-bit SBCs - - 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: - - These functions support a simulated ROM devices on aPC XT SBC. - This allows the attachment of the device to a binary file containing the EPROM - code image. Unit will support a single 2764, 27128, 27256, or 27512 type EPROM. -*/ - -#include "system_defs.h" - -/* function prototypes */ - -t_stat EPROM_attach (UNIT *uptr, CONST char *cptr); -t_stat EPROM_reset (DEVICE *dptr, uint32 base, uint32 size); -uint8 EPROM_get_mbyte(uint32 addr); - -/* external function prototypes */ - -/* 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 }, - { "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=%05X unit_capac=%05X\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, uint32 base, uint32 size) -{ - sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=%05X size=%05X\n", base, size); - if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */ - EPROM_unit.capac = size; /* set EPROM size */ - EPROM_unit.u3 = base; /* set EPROM base addr */ - sim_debug (DEBUG_flow, &EPROM_dev, "Done1\n"); - sim_printf(" EPROM: Available [%05X-%05XH]\n", - base, size); - return SCPE_OK; - } else - 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(uint32 addr) -{ - uint8 val; - uint32 romoff; - - romoff = addr - EPROM_unit.u3; - sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%05X romoff=%05X\n", addr, romoff); - if (romoff < EPROM_unit.capac) { - val = *((uint8 *)EPROM_unit.filebuf + romoff); - sim_debug (DEBUG_read, &EPROM_dev, " val=%02X\n", val); - return (val & 0xFF); - } - sim_debug (DEBUG_read, &EPROM_dev, " Out of range\n"); - return 0xFF; -} - -/* end of pceprom.c */ +/* pceprom.c: Intel EPROM simulator for 8-bit SBCs + + 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: + + These functions support a simulated ROM devices on aPC XT SBC. + This allows the attachment of the device to a binary file containing the EPROM + code image. Unit will support a single 2764, 27128, 27256, or 27512 type EPROM. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat EPROM_attach (UNIT *uptr, CONST char *cptr); +t_stat EPROM_reset (DEVICE *dptr, uint32 base, uint32 size); +uint8 EPROM_get_mbyte(uint32 addr); + +/* external function prototypes */ + +/* 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 }, + { "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=%05X unit_capac=%05X\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, uint32 base, uint32 size) +{ + sim_debug (DEBUG_flow, &EPROM_dev, " EPROM_reset: base=%05X size=%05X\n", base, size); + if ((EPROM_unit.flags & UNIT_ATT) == 0) { /* if unattached */ + EPROM_unit.capac = size; /* set EPROM size */ + EPROM_unit.u3 = base; /* set EPROM base addr */ + sim_debug (DEBUG_flow, &EPROM_dev, "Done1\n"); + sim_printf(" EPROM: Available [%05X-%05XH]\n", + base, size); + return SCPE_OK; + } else + 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(uint32 addr) +{ + uint8 val; + uint32 romoff; + + romoff = addr - EPROM_unit.u3; + sim_debug (DEBUG_read, &EPROM_dev, "EPROM_get_mbyte: addr=%05X romoff=%05X\n", addr, romoff); + if (romoff < EPROM_unit.capac) { + val = *((uint8 *)EPROM_unit.filebuf + romoff); + sim_debug (DEBUG_read, &EPROM_dev, " val=%02X\n", val); + return (val & 0xFF); + } + sim_debug (DEBUG_read, &EPROM_dev, " Out of range\n"); + return 0xFF; +} + +/* end of pceprom.c */ diff --git a/IBMPC-Systems/common/pcram8.c b/IBMPC-Systems/common/pcram8.c index 93c13be7..de97c555 100644 --- a/IBMPC-Systems/common/pcram8.c +++ b/IBMPC-Systems/common/pcram8.c @@ -1,152 +1,145 @@ -/* pcram8.c: Intel RAM simulator for 8-bit SBCs - - 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: - - These functions support a simulated RAM devices on a PC XT SBC. -*/ - -#include "system_defs.h" - -/* function prototypes */ - -t_stat RAM_svc (UNIT *uptr); -t_stat RAM_reset (DEVICE *dptr, uint32 base, uint32 size); -uint8 RAM_get_mbyte(uint32 addr); -void RAM_put_mbyte(uint32 addr, uint8 val); - -/* external function prototypes */ - -extern UNIT i8255_unit[]; - -/* 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 }, - { "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, uint32 base, uint32 size) -{ - sim_debug (DEBUG_flow, &RAM_dev, " RAM_reset: base=%05X size=%05X\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 [%05X-%05XH]\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(uint32 addr) -{ - uint8 val; - - if (i8255_unit[0].u5 & 0x02) { /* enable RAM */ - 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))) { - val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)); - sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val); - return (val & 0xFF); - } - sim_debug (DEBUG_read, &RAM_dev, " Out of range\n"); - return 0xFF; - } - sim_debug (DEBUG_read, &RAM_dev, " RAM disabled\n"); - return 0xFF; -} - -/* put a byte to memory */ - -void RAM_put_mbyte(uint32 addr, uint8 val) -{ - if (i8255_unit[0].u5 & 0x02) { /* enable RAM */ - 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)) { - *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF; - sim_debug (DEBUG_write, &RAM_dev, "\n"); - return; - } - sim_debug (DEBUG_write, &RAM_dev, " Out of range\n"); - return; - } - sim_debug (DEBUG_write, &RAM_dev, " RAM disabled\n"); -} - -/* end of pcram8.c */ +/* pcram8.c: Intel RAM simulator for 8-bit SBCs + + 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: + + These functions support a simulated RAM devices on a PC XT SBC. +*/ + +#include "system_defs.h" + +/* function prototypes */ + +t_stat RAM_svc (UNIT *uptr); +t_stat RAM_reset (DEVICE *dptr, uint32 base, uint32 size); +uint8 RAM_get_mbyte(uint32 addr); +void RAM_put_mbyte(uint32 addr, uint8 val); + +/* external function prototypes */ + +extern UNIT i8255_unit[]; + +/* 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 }, + { "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, uint32 base, uint32 size) +{ + sim_debug (DEBUG_flow, &RAM_dev, " RAM_reset: base=%05X size=%05X\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 [%05X-%05XH]\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(uint32 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))) { + val = *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)); + sim_debug (DEBUG_read, &RAM_dev, " val=%04X\n", val); + return (val & 0xFF); + } + sim_debug (DEBUG_read, &RAM_dev, " Out of range\n"); + return 0xFF; +} + +/* put a byte to memory */ + +void RAM_put_mbyte(uint32 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)) { + *((uint8 *)RAM_unit.filebuf + (addr - RAM_unit.u3)) = val & 0xFF; + sim_debug (DEBUG_write, &RAM_dev, "\n"); + return; + } + sim_debug (DEBUG_write, &RAM_dev, " Out of range\n"); + return; +} + +/* end of pcram8.c */ diff --git a/IBMPC-Systems/ibmpc/ibmpc.c b/IBMPC-Systems/ibmpc/ibmpc.c index 9beabe66..b8f298ab 100644 --- a/IBMPC-Systems/ibmpc/ibmpc.c +++ b/IBMPC-Systems/ibmpc/ibmpc.c @@ -1,203 +1,203 @@ -/* ibmpcxt.c: IBM PC Processor 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. - - MODIFICATIONS: - - 11 Jul 16 - Original file. - - NOTES: - - This software was written by Bill Beech, Jul 2016, to allow emulation of IBM PC - Computer Systems. -*/ - -#include "system_defs.h" - -int32 nmiflg = 0; //mask NMI off -uint8 dmapagreg0, dmapagreg1, dmapagreg2, dmapagreg3; -extern uint16 port; //port called in dev_table[port] - -/* function prototypes */ - -uint8 get_mbyte(uint32 addr); -uint16 get_mword(uint32 addr); -void put_mbyte(uint32 addr, uint8 val); -void put_mword(uint32 addr, uint16 val); -t_stat SBC_reset (DEVICE *dptr, uint16 base); -uint8 enbnmi(t_bool io, uint8 data); -uint8 dmapag(t_bool io, uint8 data); -uint8 dmapag0(t_bool io, uint8 data); -uint8 dmapag1(t_bool io, uint8 data); -uint8 dmapag2(t_bool io, uint8 data); -uint8 dmapag3(t_bool io, uint8 data); - -/* external function prototypes */ - -extern t_stat i8088_reset (DEVICE *dptr); /* reset the 8088 emulator */ -extern uint8 xtbus_get_mbyte(uint32 addr); -extern void xtbus_put_mbyte(uint32 addr, uint8 val); -extern uint8 EPROM_get_mbyte(uint32 addr); -extern uint8 RAM_get_mbyte(uint32 addr); -extern void RAM_put_mbyte(uint32 addr, uint8 val); -extern UNIT i8255_unit[]; -extern UNIT EPROM_unit; -extern UNIT RAM_unit; -extern t_stat i8237_reset (DEVICE *dptr, uint16 base); -extern t_stat i8253_reset (DEVICE *dptr, uint16 base); -extern t_stat i8255_reset (DEVICE *dptr, uint16 base); -extern t_stat i8259_reset (DEVICE *dptr, uint16 base); -extern t_stat EPROM_reset (DEVICE *dptr, uint32 base, uint32 size); -extern t_stat RAM_reset (DEVICE *dptr, uint32 base, uint32 size); -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); - -/* SBC reset routine */ - -t_stat SBC_reset (DEVICE *dptr, uint16 base) -{ - sim_printf("Initializing IBM PC:\n"); - i8088_reset (NULL); - i8237_reset (NULL, I8237_BASE_0); - i8253_reset (NULL, I8253_BASE_0); - i8255_reset (NULL, I8255_BASE_0); - i8259_reset (NULL, I8259_BASE_0); - EPROM_reset (NULL, ROM_BASE, ROM_SIZE); - RAM_reset (NULL, RAM_BASE, RAM_SIZE); - reg_dev(enbnmi, NMI_BASE); - reg_dev(dmapag0, DMAPAG_BASE_0); - reg_dev(dmapag1, DMAPAG_BASE_1); - reg_dev(dmapag2, DMAPAG_BASE_2); - reg_dev(dmapag3, DMAPAG_BASE_3); - return SCPE_OK; -} - -uint8 dmapag0(t_bool io, uint8 data) -{ - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - dmapagreg0 = data; - //sim_printf("dmapag0: dmapagreg0=%04X\n", data); - } -} - -uint8 dmapag1(t_bool io, uint8 data) -{ - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - dmapagreg1 = data; - //sim_printf("dmapag1: dmapagreg1=%04X\n", data); - } -} - -uint8 dmapag2(t_bool io, uint8 data) -{ - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - dmapagreg2 = data; - //sim_printf("dmapag2: dmapagreg2=%04X\n", data); - } -} - -uint8 dmapag3(t_bool io, uint8 data) -{ - //sim_printf("dmapag3: entered\n"); - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - dmapagreg3 = data; - //sim_printf("dmapag3: dmapagreg3=%04X\n", data); - } -} - -uint8 enbnmi(t_bool io, uint8 data) -{ - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - if (data & 0x80) { - nmiflg = 1; - //sim_printf("enbnmi: NMI enabled\n"); - } else { - nmiflg = 0; - //sim_printf("enbnmi: NMI disabled\n"); - } - } -} - -/* get a byte from memory - handle RAM, ROM, I/O, and pcbus memory */ - -uint8 get_mbyte(uint32 addr) -{ - /* if local EPROM handle it */ - if ((addr >= EPROM_unit.u3) && ((uint32)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { - sim_printf("Write to R/O memory address %05X - ignored\n", addr); - return EPROM_get_mbyte(addr); - } - /* if local RAM handle it */ - if ((addr >= RAM_unit.u3) && ((uint32)addr < (RAM_unit.u3 + RAM_unit.capac))) { - return RAM_get_mbyte(addr); - } - /* otherwise, try the pcbus */ - return xtbus_get_mbyte(addr); -} - -/* get a word from memory - handle RAM, ROM, I/O, and pcbus memory */ - -uint16 get_mword(uint32 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 pcbus memory */ - -void put_mbyte(uint32 addr, uint8 val) -{ - /* if local EPROM handle it */ - if ((addr >= EPROM_unit.u3) && ((uint32)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 ((i8255_unit[0].u5 & 0x02) && (addr >= RAM_unit.u3) && ((uint32)addr <= (RAM_unit.u3 + RAM_unit.capac))) { - RAM_put_mbyte(addr, val); - return; - } /* otherwise, try the pcbus */ - xtbus_put_mbyte(addr, val); -} - -/* put a word to memory - handle RAM, ROM, I/O, and pcbus memory */ - -void put_mword(uint32 addr, uint16 val) -{ - put_mbyte(addr, val & 0xff); - put_mbyte(addr+1, val >> 8); -} - -/* end of ibmpc.c */ +/* ibmpcxt.c: IBM PC Processor 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. + + MODIFICATIONS: + + 11 Jul 16 - Original file. + + NOTES: + + This software was written by Bill Beech, Jul 2016, to allow emulation of IBM PC + Computer Systems. +*/ + +#include "system_defs.h" + +int32 nmiflg = 0; //mask NMI off +uint8 dmapagreg0, dmapagreg1, dmapagreg2, dmapagreg3; +extern uint16 port; //port called in dev_table[port] + +/* function prototypes */ + +uint8 get_mbyte(uint32 addr); +uint16 get_mword(uint32 addr); +void put_mbyte(uint32 addr, uint8 val); +void put_mword(uint32 addr, uint16 val); +t_stat SBC_reset (DEVICE *dptr, uint16 base); +uint8 enbnmi(t_bool io, uint8 data); +uint8 dmapag(t_bool io, uint8 data); +uint8 dmapag0(t_bool io, uint8 data); +uint8 dmapag1(t_bool io, uint8 data); +uint8 dmapag2(t_bool io, uint8 data); +uint8 dmapag3(t_bool io, uint8 data); + +/* external function prototypes */ + +extern t_stat i8088_reset (DEVICE *dptr); /* reset the 8088 emulator */ +extern uint8 xtbus_get_mbyte(uint32 addr); +extern void xtbus_put_mbyte(uint32 addr, uint8 val); +extern uint8 EPROM_get_mbyte(uint32 addr); +extern uint8 RAM_get_mbyte(uint32 addr); +extern void RAM_put_mbyte(uint32 addr, uint8 val); +extern UNIT i8255_unit[]; +extern UNIT EPROM_unit; +extern UNIT RAM_unit; +extern t_stat i8237_reset (DEVICE *dptr, uint16 base); +extern t_stat i8253_reset (DEVICE *dptr, uint16 base); +extern t_stat i8255_reset (DEVICE *dptr, uint16 base); +extern t_stat i8259_reset (DEVICE *dptr, uint16 base); +extern t_stat EPROM_reset (DEVICE *dptr, uint32 base, uint32 size); +extern t_stat RAM_reset (DEVICE *dptr, uint32 base, uint32 size); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); + +/* SBC reset routine */ + +t_stat SBC_reset (DEVICE *dptr, uint16 base) +{ + sim_printf("Initializing IBM PC:\n"); + i8088_reset (NULL); + i8237_reset (NULL, I8237_BASE_0); + i8253_reset (NULL, I8253_BASE_0); + i8255_reset (NULL, I8255_BASE_0); + i8259_reset (NULL, I8259_BASE_0); + EPROM_reset (NULL, ROM_BASE, ROM_SIZE); + RAM_reset (NULL, RAM_BASE, RAM_SIZE); + reg_dev(enbnmi, NMI_BASE); + reg_dev(dmapag0, DMAPAG_BASE_0); + reg_dev(dmapag1, DMAPAG_BASE_1); + reg_dev(dmapag2, DMAPAG_BASE_2); + reg_dev(dmapag3, DMAPAG_BASE_3); + return SCPE_OK; +} + +uint8 dmapag0(t_bool io, uint8 data) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + dmapagreg0 = data; + //sim_printf("dmapag0: dmapagreg0=%04X\n", data); + } +} + +uint8 dmapag1(t_bool io, uint8 data) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + dmapagreg1 = data; + //sim_printf("dmapag1: dmapagreg1=%04X\n", data); + } +} + +uint8 dmapag2(t_bool io, uint8 data) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + dmapagreg2 = data; + //sim_printf("dmapag2: dmapagreg2=%04X\n", data); + } +} + +uint8 dmapag3(t_bool io, uint8 data) +{ + //sim_printf("dmapag3: entered\n"); + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + dmapagreg3 = data; + //sim_printf("dmapag3: dmapagreg3=%04X\n", data); + } +} + +uint8 enbnmi(t_bool io, uint8 data) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + if (data & 0x80) { + nmiflg = 1; + //sim_printf("enbnmi: NMI enabled\n"); + } else { + nmiflg = 0; + //sim_printf("enbnmi: NMI disabled\n"); + } + } +} + +/* get a byte from memory - handle RAM, ROM, I/O, and pcbus memory */ + +uint8 get_mbyte(uint32 addr) +{ + /* if local EPROM handle it */ + if ((addr >= EPROM_unit.u3) && ((uint32)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { +// sim_printf("Write to R/O memory address %05X - ignored\n", addr); + return EPROM_get_mbyte(addr); + } + /* if local RAM handle it */ + if ((addr >= RAM_unit.u3) && ((uint32)addr < (RAM_unit.u3 + RAM_unit.capac))) { + return RAM_get_mbyte(addr); + } + /* otherwise, try the pcbus */ + return xtbus_get_mbyte(addr); +} + +/* get a word from memory - handle RAM, ROM, I/O, and pcbus memory */ + +uint16 get_mword(uint32 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 pcbus memory */ + +void put_mbyte(uint32 addr, uint8 val) +{ + /* if local EPROM handle it */ + if ((addr >= EPROM_unit.u3) && ((uint32)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 ((addr >= RAM_unit.u3) && ((uint32)addr <= (RAM_unit.u3 + RAM_unit.capac))) { + RAM_put_mbyte(addr, val); + return; + } /* otherwise, try the pcbus */ + xtbus_put_mbyte(addr, val); +} + +/* put a word to memory - handle RAM, ROM, I/O, and pcbus memory */ + +void put_mword(uint32 addr, uint16 val) +{ + put_mbyte(addr, val & 0xff); + put_mbyte(addr+1, val >> 8); +} + +/* end of ibmpc.c */ diff --git a/IBMPC-Systems/ibmpc/system_defs.h b/IBMPC-Systems/ibmpc/system_defs.h index 8968cc26..7f5fd8cc 100644 --- a/IBMPC-Systems/ibmpc/system_defs.h +++ b/IBMPC-Systems/ibmpc/system_defs.h @@ -1,111 +1,111 @@ -/* system_defs.h: IBM PC 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. - - 11 Jul 16 - Original file. -*/ - -#include -#include -#include "sim_defs.h" /* simulator defns */ - -/* set the base I/O address and device count for the 8237 */ -#define I8237_BASE_0 0x000 -#define I8237_NUM 1 - -/* set the base I/O address and device count for the 8253 */ -#define I8253_BASE_0 0x040 -#define I8253_BASE_1 0x100 -#define I8253_NUM 2 - -/* set the base I/O address and device count for the 8255 */ -#define I8255_BASE_0 0x060 -#define I8255_NUM 1 - -/* set the base I/O address and device count for the 8259 */ -#define I8259_BASE_0 0x020 -#define I8259_NUM 1 - -/* set the base I/O address for the NMI mask */ -#define NMI_BASE 0x0A0 - -/* set the base I/O address and device count for the DMA page registers */ -#define DMAPAG_BASE_0 0x080 -#define DMAPAG_BASE_1 0x081 -#define DMAPAG_BASE_2 0x082 -#define DMAPAG_BASE_3 0x083 -#define DMAPAG_NUM 4 - -/* set the base and size for the EPROM on the IBM PC */ -#define ROM_BASE 0xFE000 -#define ROM_SIZE 0x02000 - -/* set the base and size for the RAM on the IBM PC */ -#define RAM_BASE 0x00000 -#define RAM_SIZE 0x40000 - -/* set INTR for CPU on the 8088 */ -#define INT_R INT_1 - -/* xtbus 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 - -/* Memory */ - -#define ADDRMASK16 0xFFFF -#define ADDRMASK20 0xFFFFF -#define MAXMEMSIZE20 0xFFFFF /* 8080 max memory size */ - -#define MEMSIZE (i8088_unit.capac) /* 8088 actual memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* 8088 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_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 */ - +/* system_defs.h: IBM PC 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. + + 11 Jul 16 - Original file. +*/ + +#include +#include +#include "sim_defs.h" /* simulator defns */ + +/* set the base I/O address and device count for the 8237 */ +#define I8237_BASE_0 0x000 +#define I8237_NUM 1 + +/* set the base I/O address and device count for the 8253 */ +#define I8253_BASE_0 0x040 +#define I8253_BASE_1 0x100 +#define I8253_NUM 2 + +/* set the base I/O address and device count for the 8255 */ +#define I8255_BASE_0 0x060 +#define I8255_NUM 1 + +/* set the base I/O address and device count for the 8259 */ +#define I8259_BASE_0 0x020 +#define I8259_NUM 1 + +/* set the base I/O address for the NMI mask */ +#define NMI_BASE 0x0A0 + +/* set the base I/O address and device count for the DMA page registers */ +#define DMAPAG_BASE_0 0x080 +#define DMAPAG_BASE_1 0x081 +#define DMAPAG_BASE_2 0x082 +#define DMAPAG_BASE_3 0x083 +#define DMAPAG_NUM 4 + +/* set the base and size for the EPROM on the IBM PC */ +#define ROM_BASE 0xFE000 +#define ROM_SIZE 0x02000 + +/* set the base and size for the RAM on the IBM PC */ +#define RAM_BASE 0x00000 +#define RAM_SIZE 0x40000 + +/* set INTR for CPU on the 8088 */ +#define INT_R INT_1 + +/* xtbus 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 + +/* Memory */ + +#define ADDRMASK16 0xFFFF +#define ADDRMASK20 0xFFFFF +#define MAXMEMSIZE20 0xFFFFF /* 8080 max memory size */ + +#define MEMSIZE (i8088_unit.capac) /* 8088 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8088 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_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 */ + diff --git a/IBMPC-Systems/ibmpcxt/ibmpcxt.c b/IBMPC-Systems/ibmpcxt/ibmpcxt.c index 40be0b76..469293a2 100644 --- a/IBMPC-Systems/ibmpcxt/ibmpcxt.c +++ b/IBMPC-Systems/ibmpcxt/ibmpcxt.c @@ -1,202 +1,202 @@ -/* ibmpcxt.c: IBM PC Processor 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. - - MODIFICATIONS: - - 11 Jul 16 - Original file. - - NOTES: - - This software was written by Bill Beech, Jul 2016, to allow emulation of IBM PC - Computer Systems. -*/ - -#include "system_defs.h" - -int32 nmiflg = 0; //mask NMI off -uint8 dmapagreg0, dmapagreg1, dmapagreg2, dmapagreg3; -extern uint16 port; //port called in dev_table[port] - -/* function prototypes */ - -uint8 get_mbyte(uint32 addr); -uint16 get_mword(uint32 addr); -void put_mbyte(uint32 addr, uint8 val); -void put_mword(uint32 addr, uint16 val); -t_stat SBC_reset (DEVICE *dptr); -uint8 enbnmi(t_bool io, uint8 data); -uint8 dmapag(t_bool io, uint8 data); -uint8 dmapag0(t_bool io, uint8 data); -uint8 dmapag1(t_bool io, uint8 data); -uint8 dmapag2(t_bool io, uint8 data); -uint8 dmapag3(t_bool io, uint8 data); - -/* external function prototypes */ - -extern t_stat i8088_reset (DEVICE *dptr); /* reset the 8088 emulator */ -extern uint8 xtbus_get_mbyte(uint32 addr); -extern void xtbus_put_mbyte(uint32 addr, uint8 val); -extern uint8 EPROM_get_mbyte(uint32 addr); -extern uint8 RAM_get_mbyte(uint32 addr); -extern void RAM_put_mbyte(uint32 addr, uint8 val); -extern UNIT i8255_unit[]; -extern UNIT EPROM_unit; -extern UNIT RAM_unit; -extern t_stat i8237_reset (DEVICE *dptr, uint16 base); -extern t_stat i8253_reset (DEVICE *dptr, uint16 base); -extern t_stat i8255_reset (DEVICE *dptr, uint16 base); -extern t_stat i8259_reset (DEVICE *dptr, uint16 base); -extern t_stat EPROM_reset (DEVICE *dptr, uint32 base, uint32 size); -extern t_stat RAM_reset (DEVICE *dptr, uint32 base, uint32 size); -extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); - -/* SBC reset routine */ - -t_stat SBC_reset (DEVICE *dptr) -{ - sim_printf("Initializing IBM PC XT:\n"); - i8088_reset (NULL); - i8237_reset (NULL, I8237_BASE_0); - i8253_reset (NULL, I8253_BASE_0); - i8255_reset (NULL, I8255_BASE_0); - i8259_reset (NULL, I8259_BASE_0); - EPROM_reset (NULL, ROM_BASE, ROM_SIZE); - RAM_reset (NULL, RAM_BASE, RAM_SIZE); - reg_dev(enbnmi, NMI_BASE); - reg_dev(dmapag0, DMAPAG_BASE_0); - reg_dev(dmapag1, DMAPAG_BASE_1); - reg_dev(dmapag2, DMAPAG_BASE_2); - reg_dev(dmapag3, DMAPAG_BASE_3); - return SCPE_OK; -} - -uint8 dmapag0(t_bool io, uint8 data) -{ - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - dmapagreg0 = data; - //sim_printf("dmapag0: dmapagreg0=%04X\n", data); - } -} - -uint8 dmapag1(t_bool io, uint8 data) -{ - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - dmapagreg1 = data; - //sim_printf("dmapag1: dmapagreg1=%04X\n", data); - } -} - -uint8 dmapag2(t_bool io, uint8 data) -{ - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - dmapagreg2 = data; - //sim_printf("dmapag2: dmapagreg2=%04X\n", data); - } -} - -uint8 dmapag3(t_bool io, uint8 data) -{ - //sim_printf("dmapag3: entered\n"); - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - dmapagreg3 = data; - //sim_printf("dmapag3: dmapagreg3=%04X\n", data); - } -} - -uint8 enbnmi(t_bool io, uint8 data) -{ - if (io == 0) { /* read data port */ - ; - } else { /* write data port */ - if (data & 0x80) { - nmiflg = 1; - //sim_printf("enbnmi: NMI enabled\n"); - } else { - nmiflg = 0; - //sim_printf("enbnmi: NMI disabled\n"); - } - } -} - -/* get a byte from memory - handle RAM, ROM, I/O, and Multibus memory */ - -uint8 get_mbyte(uint32 addr) -{ - /* if local EPROM handle it */ - if ((addr >= EPROM_unit.u3) && ((uint32)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { - return EPROM_get_mbyte(addr); - } - /* if local RAM handle it */ - if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { - return RAM_get_mbyte(addr); - } - /* otherwise, try the multibus */ - return xtbus_get_mbyte(addr); -} - -/* get a word from memory */ - -uint16 get_mword(uint32 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(uint32 addr, uint8 val) -{ - /* if local EPROM handle it */ - if ((addr >= EPROM_unit.u3) && ((uint32)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { - sim_printf("Write to R/O memory address %05X - ignored\n", addr); - return; - } /* if local RAM handle it */ - if ((i8255_unit[0].u5 & 0x02) && (addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { - RAM_put_mbyte(addr, val); - return; - } /* otherwise, try the multibus */ - xtbus_put_mbyte(addr, val); -} - -/* put a word to memory */ - -void put_mword(uint32 addr, uint16 val) -{ - put_mbyte(addr, val & 0xff); - put_mbyte(addr+1, val >> 8); -} - -/* end of ibmpcxt.c */ +/* ibmpcxt.c: IBM PC Processor 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. + + MODIFICATIONS: + + 11 Jul 16 - Original file. + + NOTES: + + This software was written by Bill Beech, Jul 2016, to allow emulation of IBM PC + Computer Systems. +*/ + +#include "system_defs.h" + +int32 nmiflg = 0; //mask NMI off +uint8 dmapagreg0, dmapagreg1, dmapagreg2, dmapagreg3; +extern uint16 port; //port called in dev_table[port] + +/* function prototypes */ + +uint8 get_mbyte(uint32 addr); +uint16 get_mword(uint32 addr); +void put_mbyte(uint32 addr, uint8 val); +void put_mword(uint32 addr, uint16 val); +t_stat SBC_reset (DEVICE *dptr); +uint8 enbnmi(t_bool io, uint8 data); +uint8 dmapag(t_bool io, uint8 data); +uint8 dmapag0(t_bool io, uint8 data); +uint8 dmapag1(t_bool io, uint8 data); +uint8 dmapag2(t_bool io, uint8 data); +uint8 dmapag3(t_bool io, uint8 data); + +/* external function prototypes */ + +extern t_stat i8088_reset (DEVICE *dptr); /* reset the 8088 emulator */ +extern uint8 xtbus_get_mbyte(uint32 addr); +extern void xtbus_put_mbyte(uint32 addr, uint8 val); +extern uint8 EPROM_get_mbyte(uint32 addr); +extern uint8 RAM_get_mbyte(uint32 addr); +extern void RAM_put_mbyte(uint32 addr, uint8 val); +extern UNIT i8255_unit[]; +extern UNIT EPROM_unit; +extern UNIT RAM_unit; +extern t_stat i8237_reset (DEVICE *dptr, uint16 base); +extern t_stat i8253_reset (DEVICE *dptr, uint16 base); +extern t_stat i8255_reset (DEVICE *dptr, uint16 base); +extern t_stat i8259_reset (DEVICE *dptr, uint16 base); +extern t_stat EPROM_reset (DEVICE *dptr, uint32 base, uint32 size); +extern t_stat RAM_reset (DEVICE *dptr, uint32 base, uint32 size); +extern uint16 reg_dev(uint8 (*routine)(t_bool, uint8), uint16); + +/* SBC reset routine */ + +t_stat SBC_reset (DEVICE *dptr) +{ + sim_printf("Initializing IBM PC XT:\n"); + i8088_reset (NULL); + i8237_reset (NULL, I8237_BASE_0); + i8253_reset (NULL, I8253_BASE_0); + i8255_reset (NULL, I8255_BASE_0); + i8259_reset (NULL, I8259_BASE_0); + EPROM_reset (NULL, ROM_BASE, ROM_SIZE); + RAM_reset (NULL, RAM_BASE, RAM_SIZE); + reg_dev(enbnmi, NMI_BASE); + reg_dev(dmapag0, DMAPAG_BASE_0); + reg_dev(dmapag1, DMAPAG_BASE_1); + reg_dev(dmapag2, DMAPAG_BASE_2); + reg_dev(dmapag3, DMAPAG_BASE_3); + return SCPE_OK; +} + +uint8 dmapag0(t_bool io, uint8 data) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + dmapagreg0 = data; + //sim_printf("dmapag0: dmapagreg0=%04X\n", data); + } +} + +uint8 dmapag1(t_bool io, uint8 data) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + dmapagreg1 = data; + //sim_printf("dmapag1: dmapagreg1=%04X\n", data); + } +} + +uint8 dmapag2(t_bool io, uint8 data) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + dmapagreg2 = data; + //sim_printf("dmapag2: dmapagreg2=%04X\n", data); + } +} + +uint8 dmapag3(t_bool io, uint8 data) +{ + //sim_printf("dmapag3: entered\n"); + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + dmapagreg3 = data; + //sim_printf("dmapag3: dmapagreg3=%04X\n", data); + } +} + +uint8 enbnmi(t_bool io, uint8 data) +{ + if (io == 0) { /* read data port */ + ; + } else { /* write data port */ + if (data & 0x80) { + nmiflg = 1; + //sim_printf("enbnmi: NMI enabled\n"); + } else { + nmiflg = 0; + //sim_printf("enbnmi: NMI disabled\n"); + } + } +} + +/* get a byte from memory - handle RAM, ROM, I/O, and Multibus memory */ + +uint8 get_mbyte(uint32 addr) +{ + /* if local EPROM handle it */ + if ((addr >= EPROM_unit.u3) && ((uint32)addr < (EPROM_unit.u3 + EPROM_unit.capac))) { + return EPROM_get_mbyte(addr); + } + /* if local RAM handle it */ + if ((addr >= RAM_unit.u3) && ((uint16)addr < (RAM_unit.u3 + RAM_unit.capac))) { + return RAM_get_mbyte(addr); + } + /* otherwise, try the multibus */ + return xtbus_get_mbyte(addr); +} + +/* get a word from memory */ + +uint16 get_mword(uint32 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(uint32 addr, uint8 val) +{ + /* if local EPROM handle it */ + if ((addr >= EPROM_unit.u3) && ((uint32)addr <= (EPROM_unit.u3 + EPROM_unit.capac))) { + sim_printf("Write to R/O memory address %05X - ignored\n", addr); + return; + } /* if local RAM handle it */ + if ((i8255_unit[0].u5 & 0x02) && (addr >= RAM_unit.u3) && ((uint16)addr <= (RAM_unit.u3 + RAM_unit.capac))) { + RAM_put_mbyte(addr, val); + return; + } /* otherwise, try the multibus */ + xtbus_put_mbyte(addr, val); +} + +/* put a word to memory */ + +void put_mword(uint32 addr, uint16 val) +{ + put_mbyte(addr, val & 0xff); + put_mbyte(addr+1, val >> 8); +} + +/* end of ibmpcxt.c */ diff --git a/IBMPC-Systems/ibmpcxt/ibmpcxt_sys.c b/IBMPC-Systems/ibmpcxt/ibmpcxt_sys.c index 11b7b6af..819dc83f 100644 --- a/IBMPC-Systems/ibmpcxt/ibmpcxt_sys.c +++ b/IBMPC-Systems/ibmpcxt/ibmpcxt_sys.c @@ -1,96 +1,96 @@ -/* 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 XT"; - -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", -}; - +/* 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 XT"; + +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", +}; + diff --git a/IBMPC-Systems/ibmpcxt/system_defs.h b/IBMPC-Systems/ibmpcxt/system_defs.h index ea7713a6..a9e0172b 100644 --- a/IBMPC-Systems/ibmpcxt/system_defs.h +++ b/IBMPC-Systems/ibmpcxt/system_defs.h @@ -1,110 +1,110 @@ -/* 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. - - 11 Jul 16 - Original file. -*/ - -#include -#include -#include "sim_defs.h" /* simulator defns */ - -/* set the base I/O address and device count for the 8237 */ -#define I8237_BASE_0 0x000 -#define I8237_NUM 1 - -/* set the base I/O address and device count for the 8253 */ -#define I8253_BASE_0 0x040 -#define I8253_NUM 1 - -/* set the base I/O address and device count for the 8255 */ -#define I8255_BASE_0 0x060 -#define I8255_NUM 1 - -/* set the base I/O address and device count for the 8259 */ -#define I8259_BASE_0 0x020 -#define I8259_NUM 1 - -/* set the base I/O address for the NMI mask */ -#define NMI_BASE 0x0A0 - -/* set the base I/O address and device count for the DMA page registers */ -#define DMAPAG_BASE_0 0x080 -#define DMAPAG_BASE_1 0x081 -#define DMAPAG_BASE_2 0x082 -#define DMAPAG_BASE_3 0x083 -#define DMAPAG_NUM 4 - -/* set the base and size for the EPROM on the IBM PC XT*/ -#define ROM_BASE 0xF0000 -#define ROM_SIZE 0x10000 - -/* set the base and size for the RAM on the IBM PC XT */ -#define RAM_BASE 0x00000 -#define RAM_SIZE 0x40000 - -/* set INTR for CPU on the IBM PC XT */ -#define INT_R INT_1 - -/* xtbus 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 - -/* Memory */ - -#define ADDRMASK16 0xFFFF -#define ADDRMASK20 0xFFFFF -#define MAXMEMSIZE20 0xFFFFF /* 8080 max memory size */ - -#define MEMSIZE (i8088_unit.capac) /* 8088 actual memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* 8088 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_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 */ - +/* 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. + + 11 Jul 16 - Original file. +*/ + +#include +#include +#include "sim_defs.h" /* simulator defns */ + +/* set the base I/O address and device count for the 8237 */ +#define I8237_BASE_0 0x000 +#define I8237_NUM 1 + +/* set the base I/O address and device count for the 8253 */ +#define I8253_BASE_0 0x040 +#define I8253_NUM 1 + +/* set the base I/O address and device count for the 8255 */ +#define I8255_BASE_0 0x060 +#define I8255_NUM 1 + +/* set the base I/O address and device count for the 8259 */ +#define I8259_BASE_0 0x020 +#define I8259_NUM 1 + +/* set the base I/O address for the NMI mask */ +#define NMI_BASE 0x0A0 + +/* set the base I/O address and device count for the DMA page registers */ +#define DMAPAG_BASE_0 0x080 +#define DMAPAG_BASE_1 0x081 +#define DMAPAG_BASE_2 0x082 +#define DMAPAG_BASE_3 0x083 +#define DMAPAG_NUM 4 + +/* set the base and size for the EPROM on the IBM PC XT*/ +#define ROM_BASE 0xF0000 +#define ROM_SIZE 0x10000 + +/* set the base and size for the RAM on the IBM PC XT */ +#define RAM_BASE 0x00000 +#define RAM_SIZE 0x40000 + +/* set INTR for CPU on the IBM PC XT */ +#define INT_R INT_1 + +/* xtbus 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 + +/* Memory */ + +#define ADDRMASK16 0xFFFF +#define ADDRMASK20 0xFFFFF +#define MAXMEMSIZE20 0xFFFFF /* 8080 max memory size */ + +#define MEMSIZE (i8088_unit.capac) /* 8088 actual memory size */ +#define ADDRMASK (MAXMEMSIZE - 1) /* 8088 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_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 */ +