From 5e9d8e0996a3da4bf05bf923c6b6b8a894dbb76b Mon Sep 17 00:00:00 2001 From: Bill Date: Tue, 11 Oct 2016 15:47:50 -0700 Subject: [PATCH] IBMPC: Remove unused files --- IBMPC-Systems/common/i8008.c | 2002 ---------------------------------- IBMPC-Systems/common/i8080.c | 1445 ------------------------ 2 files changed, 3447 deletions(-) delete mode 100644 IBMPC-Systems/common/i8008.c delete mode 100644 IBMPC-Systems/common/i8080.c diff --git a/IBMPC-Systems/common/i8008.c b/IBMPC-Systems/common/i8008.c deleted file mode 100644 index 48b30c86..00000000 --- a/IBMPC-Systems/common/i8008.c +++ /dev/null @@ -1,2002 +0,0 @@ -/* i8008.c: Intel 8008 CPU simulator - - Copyright (c) 2011, William A. Beech - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of William A. Beech shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from William A. Beech. - - cpu 8008 CPU - - The register state for the 8008 CPU is: - - A<0:7> Accumulator - B<0:7> B Register - C<0:7> C Register - D<0:7> D Register - E<0:7> E Register - H<0:7> H Register - L<0:7> L Register - PC<0:13> Program counter - - The 8008 is an 8-bit CPU, which uses 14-bit registers to address - up to 16KB of memory. - - The 57 basic instructions come in 1, 2, and 3-byte flavors. - - This routine is the instruction decode routine for the 8008. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HLT instruction - I/O error in I/O simulator - Invalid OP code (if ITRAP is set on CPU) - - 2. Interrupts. - There are 8 possible levels of interrupt, and in effect they - do a hardware CALL instruction to one of 8 possible low - memory addresses. - - 3. Non-existent memory. On the 8008, reads to non-existent memory - return 0FFh, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 4. Adding I/O devices. These modules must be modified: - - 15 Feb 15 - Original file. - -*/ - -#include "system_defs.h" - -#define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */ -#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) -#define UNIT_V_TRACE (UNIT_V_UF+1) /* Trace switch */ -#define UNIT_TRACE (1 << UNIT_V_TRACE) - -/* register masks */ -#define BYTE_R 0xFF -#define WORD_R14 0x3FFF - -/* storage for the rest of the registers */ -uint32 A = 0; /* accumulator */ -uint32 B = 0; /* B register */ -uint32 C = 0; /* C register */ -uint32 D = 0; /* D register */ -uint32 E = 0; /* E register */ -uint32 H = 0; /* H register */ -uint32 L = 0; /* L register */ -uint32 CF = 0; /* C - carry flag */ -uint32 PF = 0; /* P - parity flag */ -uint32 ZF = 0; /* Z - zero flag */ -uint32 SF = 0; /* S - sign flag */ -uint32 SP = 0; /* stack frame pointer */ -uint32 saved_PC = 0; /* program counter */ -uint32 int_req = 0; /* Interrupt request */ - -int32 PCX; /* External view of PC */ -int32 PC; -UNIT *uptr; - -/* function prototypes */ -void store_m(unit32 val); -unit32 fetch_m(void); -void set_cpuint(int32 int_num); -void dumpregs(void); -int32 fetch_byte(int32 flag); -int32 fetch_word(void); -uint16 pop_word(void); -void push_word(uint16 val); -void setflag4(int32 reg); -void setlogical(int32 reg); -void setinc(int32 reg); -int32 getreg(int32 reg); -void putreg(int32 reg, int32 val); -int32 getpair(int32 reg); -int32 getpush(int32 reg); -void putpush(int32 reg, int32 data); -void putpair(int32 reg, int32 val); -void parity(int32 reg); -int32 cond(int32 con); -t_stat i8008_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat i8008_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat i8008_reset (DEVICE *dptr); - -/* external function prototypes */ - -extern t_stat i8008_reset (DEVICE *dptr); -extern int32 get_mbyte(int32 addr); -extern int32 get_mword(int32 addr); -extern void put_mbyte(int32 addr, int32 val); -extern void put_mword(int32 addr, int32 val); -extern int32 sim_int_char; -extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - - -struct idev { - int32 (*routine)(); -}; - -/* This is the I/O configuration table. There are 256 possible -device addresses, if a device is plugged to a port it's routine -address is here, 'nulldev' means no device is available -*/ - -extern struct idev dev_table[]; - -/* CPU data structures - - i8008_dev CPU device descriptor - i8008_unit CPU unit descriptor - i8008_reg CPU register list - i8008_mod CPU modifiers list -*/ - -UNIT i8008_unit = { UDATA (NULL, 0, 65535) }; /* default 8008 */ - -REG i8008_reg[] = { - { HRDATA (PC, saved_PC, 16) }, /* must be first for sim_PC */ - { HRDATA (A, A, 8) }, - { HRDATA (B, B, 8) }, - { HRDATA (C, C, 8) }, - { HRDATA (D, D, 8) }, - { HRDATA (E, E, 8) }, - { HRDATA (H, H, 8) }, - { HRDATA (L, L, 8) }, - { HRDATA (CF, CF, 1) }, - { HRDATA (PF, PF, 1) }, - { HRDATA (ZF, SF, 1) }, - { HRDATA (SF, SF, 1) }, - { HRDATA (INTR, int_req, 32) }, - { HRDATA (WRU, sim_int_char, 8) }, - { NULL } -}; - -MTAB i8008_mod[] = { - { UNIT_OPSTOP, 0, "ITRAP", "ITRAP", NULL }, - { UNIT_OPSTOP, UNIT_OPSTOP, "NOITRAP", "NOITRAP", NULL }, - { UNIT_TRACE, 0, "NOTRACE", "NOTRACE", NULL }, - { UNIT_TRACE, UNIT_TRACE, "TRACE", "TRACE", NULL }, - { 0 } -}; - -DEBTAB i8008_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { "REG", DEBUG_reg }, - { "ASM", DEBUG_asm }, - { NULL } -}; - -DEVICE i8008_dev = { - "CPU", //name - &i8008_unit, //units - i8008_reg, //registers - i8008_mod, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - &i8008_ex, //examine - &i8008_dep, //deposit -// &i8008_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - i8008_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* tables for the disassembler */ -char *opcode[] = { -"*HLT", "*HLT", "RLC", "RFC", /* 0x00 */ -"ADI ", "RST 0", "LAI ,", "RET", -"INB", "DCB", "RRC", "RFZ", -"ACI ", "RST 1", "LBI ", "*RET", -"INC", "DCC", "RAL", "RFS", /* 0x10 */ -"SUI ", "RST 2", "LCI ", "*RET", -"IND", "DCD", "RAR", "RFP", -"SBI ", "RST 3", "LDI ", "*RET", -"INE", "DCE", "???", "RTC", /* 0x20 */ -"NDI ", "RST 4", "LEI ", "*RET", -"INH", "DCH", "???", "RTZ", -"XRI ", "RST 5", "LHI ", "*RET", -"INL", "DCL", "???", "RTS", /* 0x30 */ -"ORI ", "RST 6", "LLI ", "*RET", -"???", "???", "???", "RTP", -"CPI ", "RST 7", "LMI ", "*RET", -"JFC ", "INP ", "CFC ", "INP ", /* 0x40 */ -"JMP ", "INP ", "CAL ", "INP ", -"JFZ ", "INP ", "CFZ ", "INP ", -"*JMP ", "INP ", "*CAL ", "INP ", -"JFS", "OUT ", "CFS ", "OUT ", /* 0x50 */ -"*JMP ", "OUT ", "*CAL ", "OUT ", -"JFP ", "OUT ", "CFP ", "OUT ", -"*JMP ", "OUT ", "*CAL ", "OUT ", -"JTC ", "OUT ", "CTC ", "OUT ", /* 0x60 */ -"*JMP ", "OUT ", "*CAL ", "OUT ", -"JTZ ", "OUT ", "CTZ", "OUT ", -"*JMP ", "OUT ", "*CAL", "OUT ", -"JTS ", "OUT ", "CTS ", "OUT ", /* 0x70 */ -"*JMP ", "OUT ", "*CAL ", "OUT ", -"JTP ", "OUT ", "CTP", "OUT ", -"*JMP ", "OUT ", "*CAL ", "OUT ", -"ADA", "ADB", "ADC", "ADD", /* 0x80 */ -"ADE", "ADH", "ADL", "ADM", -"ACA", "ACB", "ACC", "ACD", -"ACE", "ACH", "ACL", "ACM", -"SUA", "SUB", "SUC", "SUD", /* 0x90 */ -"SUE", "SUH", "SUL", "SUM", -"SBA", "SBB", "SBC", "SBD", -"SBE", "SBH", "SBL", "SBM", -"NDA", "NDB", "NDC", "NDD", /* 0xA0 */ -"NDE", "NDH", "NDL", "NDM", -"XRA", "XRB", "XRC", "XRD", -"XRE", "XRH", "XRL", "XRM", -"ORA", "ORB", "ORC", "ORD", /* 0xB0 */ -"ORE", "ORH", "ORL", "ORM", -"CPA", "CPB", "CPC", "CPD", -"CPE", "CPH", "CPL", "CPM", -"NOP", "LAB", "LAC", "LAD", /* 0xC0 */ -"LAE", "LAH", "LAL", "LAM", -"LBA", "LBB", "LBC", "LBD", -"LBE", "LBH ", "LBL", "LBM", -"LCA", "LCB", "LCC", "LCD", /* 0xD0 */ -"LCE", "LCH", "LCL", "LCM", -"LDA", "LDB", "LDC", "LDD", -"LDE", "LDH", "LDL", "LDM", -"LEA", "LEB", "LEC", "LED", /* 0xE0 */ -"LEE", "LEH", "LEL", "LEM", -"LHA", "LHB", "LHC", "LHD", -"LHE", "LHH", "LHL", "LHM", -"LLA", "LLB", "LLC", "LLD", /* 0xF0 */ -"LLE", "LLH", "LLL", "LLM", -"LMA", "LMB", "LMC", "LMD", -"LME", "LMH", "LML", "HLT", - }; - -int32 oplen[256] = { -/* - 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, /* 0X */ - 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, /* 1X */ - 1, 1, 0, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, /* 2X */ - 1, 1, 0, 1, 2, 1, 2, 1, 0, 0, 0, 1, 2, 1, 2, 1, /* 3X */ - 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 4X */ - 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 5X */ - 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 6X */ - 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, /* 7X */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8X */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9X */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* AX */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* BX */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* CX */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* DX */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* EX */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* FX */ -}; - -uint16 stack_frame[7]; /* processor stack frame */ - -void set_cpuint(int32 int_num) -{ - int_req |= int_num; -} - -/* instruction simulator */ -int32 sim_instr (void) -{ - extern int32 sim_interval; - uint32 IR, OP, DAR, reason, hi, lo, i, adr, val; - - PC = saved_PC & WORD_R14; /* load local PC */ - reason = 0; - - uptr = i8008_dev.units; - - /* Main instruction fetch/decode loop */ - - while (reason == 0) { /* loop until halted */ - -// if (PC == 0x1000) { /* turn on debugging */ -// i8008_dev.dctrl = DEBUG_asm + DEBUG_reg; -// reason = STOP_HALT; -// } - if (i8008_dev.dctrl & DEBUG_reg) { - dumpregs(); - sim_printf("\n"); - } - - if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event()) - break; - } - sim_interval--; /* countdown clock */ - - if (int_req > 0) { /* interrupt? */ -// sim_printf("\ni8008: int_req=%04X", int_req); - ; - } else { /* 8008 */ - if (IE) { /* enabled? */ - push_word(PC); /* do an RST 7 */ - PC = 0x0038; - int_req &= ~INT_R; -// sim_printf("\ni8008: int_req=%04X", int_req); - } - } /* end interrupt */ - - if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - - PCX = PC; - - if (uptr->flags & UNIT_TRACE) { - dumpregs(); - sim_printf("\n"); - } - IR = OP = fetch_byte(0); /* instruction fetch */ - - if (OP == 0x00 || OP == 0x01 || OP == 0xFF) { /* HLT Instruction*/ - reason = STOP_HALT; - PC--; - continue; - } - - /* The Big Instruction Decode Switch */ - - switch (IR) { - - case 0x02: /* RLC */ - if (A & 0x80) - CF = 1; - else - CF = 0; - A = (A << 1) & 0xFF; - if (CF) - A |= 0x01; - A &= BYTE_R; - break; - - case 0x03: /* RFC */ - if (CF) - ; - else - PC = pop_word(); - break; - - case 0x04: /* ADI */ - A += fetch_byte(1); - setflag3(A); - A &= BYTE_R; - break; - - case 0x05: /* RST 0 */ - case 0x0D: /* RST 1 */ - case 0x15: /* RST 2 */ - case 0x1D: /* RST 3 */ - case 0x25: /* RST 4 */ - case 0x2D: /* RST 5 */ - case 0x35: /* RST 6 */ - case 0x3D: /* RST 7 */ - val = fetch_byte(); - push_word(PC); - PC = val << 3; - break; - - case 0x06: /* LAI */ - A = fetch_byte(1); - A &= BYTE_R; - break; - - case 0x07: /* RET */ - PC = pop_word(); - break; - - case 0x08: /* INB */ - B++; - setflag3(B); - B &= BYTE_R; - break; - - case 0x09: /* DCB */ - B--; - setflag3(B); - B &= BYTE_R; - break; - - case 0x0A: /* RRC */ - if (A & 0x01) - CF = 1; - else - CF = 0; - A = (A >> 1) & 0xFF; - if (CF) - A |= 0x80; - A &= BYTE_R; - break; - - case 0x0B: /* RFZ */ - if (ZF) - ; - else - PC = pop_word(); - break; - - case 0x0C: /* ACI */ - A += fetch_byte(1); - if (CF) - A++; - setflag3(A); - A &= BYTE_R; - break; - - case 0x0E: /* LBI */ - B = fetch_byte(1); - B &= BYTE_R; - break; - - case 0x0F: /* *RET */ - PC = pop_word(); - break; - - case 0x10: /* INC */ - C++; - setflag3(C); - C &= BYTE_R; - break; - - case 0x11: /* DCC */ - C--; - setflag3(C); - C &= BYTE_R; - break; - - case 0x12: /* RAL */ - if (A & 0x80) - CF = 1; - else - CF = 0; - A = (A << 1) & 0xFF; - if (CF) - A |= 0x01; - A &= BYTE_R; - break; - - case 0x13: /* RFS */ - if (SF) - ; - else - PC = pop_word(); - break; - - case 0x14: /* SUI */ - A -= fetch_byte(1); - setflag3(A); - A &= BYTE_R; - break; - - case 0x16: /* LCI */ - C = fetch_byte(1); - C &= BYTE_R; - break; - - case 0x17: /* *RET */ - PC = pop_word(); - break; - - case 0x18: /* IND */ - D++; - setflag3(D); - D &= BYTE_R; - break; - - case 0x19: /* DCD */ - D--; - setflag3(D); - D &= BYTE_R; - break; - - case 0x1A: /* RAR */ - if (A & 0x01) - CF = 1; - else - CF = 0; - A = (A >> 1) & 0xFF; - if (CF) - A |= 0x80; - A &= BYTE_R; - break; - - case 0x1B: /* RFP */ - if (PF) - ; - else - PC = pop_word(); - break; - - case 0x1C: /* SBI */ - A -= fetch_byte(1); - if (CF) - A--; - setflag3(A); - A &= BYTE_R; - break; - - case 0x1E: /* LDI */ - D = fetch_byte(1); - D &= BYTE_R; - break; - - case 0x1F: /* *RET */ - PC = pop_word(); - break; - - case 0x20: /* INE */ - E++; - setflag3(E); - E &= BYTE_R; - break; - - case 0x21: /* DCE */ - E--; - setflag3(E); - E &= BYTE_R; - break; - - case 0x23: /* RTC */ - if (CF) - PC = pop_word(); - break; - - case 0x24: /* NDI */ - A &= fetch_byte(1); - setflag3(A); - A &= BYTE_R; - break; - - case 0x26: /* LEI */ - E = fetch_byte(1); - E &= BYTE_R; - break; - - case 0x27: /* *RET */ - PC = pop_word(); - break; - - case 0x28: /* INH */ - H++; - setflag3(H); - H &= BYTE_R; - break; - - case 0x29: /* DCH */ - H--; - setflag3(H); - H &= BYTE_R; - break; - - case 0x2B: /* RTZ */ - if (ZF) - PC = pop_word(); - break; - - case 0x2C: /* XRI */ - A ^= fetch_byte(1); - setflag3(A); - break; - - case 0x2E: /* LHI */ - H = fetch_byte(1); - H &= BYTE_R; - break; - - case 0x2F: /* *RET */ - PC = pop_word(); - break; - - case 0x30: /* INL */ - L++; - setflag3(L); - L &= BYTE_R; - break; - - case 0x31: /* DCL */ - L--; - setflag3(L); - L &= BYTE_R; - break; - - case 0x33: /* RTS */ - if (SF) - PC = pop_word(); - break; - - case 0x34: /* ORI */ - A |= fetch_byte(1); - setflag3(A); - A &= BYTE_R; - break; - - case 0x36: /* LLI */ - L = fetch_byte(1); - L &= BYTE_R; - break; - - case 0x37: /* *RET */ - PC = pop_word(); - break; - - case 0x3B: /* RTP */ - if (PF) - PC = pop_word(); - break; - - case 0x3C: /* CPI */ - DAR = A; - DAR -= fetch_byte(1); - setflag3(DAR); - break; - - case 0x3E: /* LMI */ - val = fetch_byte(1); - store_m(val); - break; - - case 0x3F: /* *RET */ - PC = pop_word(); - break; - - case 0x40: /* JFC */ - DAR = fetch_word(); - if (CF) - ; - else - PC = DAR; - break; - - case 0x41: /* INP 0 */ - case 0x43: /* INP 1 */ - case 0x45: /* INP 2 */ - case 0x47: /* INP 3 */ - case 0x49: /* INP 4 */ - case 0x4B: /* INP 5 */ - case 0x4D: /* INP 6 */ - case 0x4F: /* INP 7 */ - /**** fix me! */ - break; - - case 0x42: /* CFC */ - adr = fetch_word(); - if (CF) - ; - else { - push_word(PC); - PC = adr; - } - break; - - case 0x44: /* JMP */ - PC = fetch_word(); - break; - - case 0x46: /* CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x48: /* JFZ */ - DAR = fetch_word(); - if (ZF) - ; - else - PC = DAR; - break; - - case 0x4A: /* CFZ */ - adr = fetch_word(); - if (ZF) - ; - else { - push_word(PC); - PC = adr; - } - break; - - case 0x4C: /* *JMP */ - PC = fetch_word(); - break; - - case 0x4E: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x50: /* JFS */ - DAR = fetch_word(); - if (SF) - ; - else - PC = DAR; - break; - - case 0x51: /* OUT 8 */ - case 0x53: /* OUT 9 */ - case 0x55: /* OUT 10 */ - case 0x57: /* OUT 11 */ - case 0x59: /* OUT 12 */ - case 0x5B: /* OUT 13 */ - case 0x5D: /* OUT 14 */ - case 0x5E: /* OUT 15 */ - case 0x61: /* OUT 16 */ - case 0x63: /* OUT 17 */ - case 0x65: /* OUT 18 */ - case 0x67: /* OUT 19 */ - case 0x69: /* OUT 20 */ - case 0x6B: /* OUT 21 */ - case 0x6D: /* OUT 22 */ - case 0x6E: /* OUT 23 */ - case 0x71: /* OUT 24 */ - case 0x73: /* OUT 25 */ - case 0x75: /* OUT 26 */ - case 0x77: /* OUT 27 */ - case 0x79: /* OUT 28 */ - case 0x7B: /* OUT 29 */ - case 0x7D: /* OUT 30 */ - case 0x7E: /* OUT 31 */ - /**** fix me! */ - break; - - case 0x52: /* CFS */ - adr = fetch_word(); - if (SF) - ; - else { - push_word(PC); - PC = adr; - } - break; - - case 0x54: /* *JMP */ - PC = fetch_word(); - break; - - case 0x56: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x58: /* JFP */ - DAR = fetch_word(); - if (PF) - ; - else - PC = DAR; - break; - - case 0x5A: /* CFP */ - adr = fetch_word(); - if (PF) - ; - else { - push_word(PC); - PC = adr; - } - break; - - case 0x5C: /* *JMP */ - PC = fetch_word(); - break; - - case 0x5E: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x60: /* JTC */ - DAR = fetch_word(); - if (CF) - PC = DAR; - break; - - case 0x62: /* CTC */ - adr = fetch_word(); - if (CF) { - push_word(PC); - PC = adr; - } - break; - - case 0x64: /* *JMP */ - PC = fetch_word(); - break; - - case 0x66: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x68: /* JTZ */ - DAR = fetch_word(); - if (ZF) - PC = DAR; - break; - - case 0x6A: /* CTZ */ - adr = fetch_word(); - if (ZF) { - push_word(PC); - PC = adr; - } - break; - - case 0x6C: /* *JMP */ - PC = fetch_word(); - break; - - case 0x6E: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x70: /* JTS */ - DAR = fetch_word(); - if (SF) - PC = DAR; - break; - - case 0x72: /* CTS */ - adr = fetch_word(); - if (SF) { - push_word(PC); - PC = adr; - } - break; - - case 0x74: /* *JMP */ - PC = fetch_word(); - break; - - case 0x76: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x78: /* JTP */ - DAR = fetch_word(); - if (PF) - PC = DAR; - break; - - case 0x7A: /* CTP */ - adr = fetch_word(); - if (PF) { - push_word(PC); - PC = adr; - } - break; - - case 0x7C: /* *JMP */ - PC = fetch_word(); - break; - - case 0x7E: /* *CAL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0x80: /* ADA */ - A += A; - setflag4(A); - A &= BYTE_R; - break; - - case 0x81: /* ADB */ - A += B; - setflag4(A); - A &= BYTE_R; - break; - - case 0x82: /* ADC */ - A += C; - setflag4(A); - A &= BYTE_R; - break; - - case 0x83: /* ADD */ - A += D; - setflag4(A); - A &= BYTE_R; - break; - - case 0x84: /* ADE */ - A += E; - setflag4(A); - A &= BYTE_R; - break; - - case 0x85: /* ADH */ - A += H; - setflag4(A); - A &= BYTE_R; - break; - - case 0x86: /* ADL */ - A += L; - setflag4(A); - A &= BYTE_R; - break; - - case 0x87: /* ADM */ - A += fetch_m(); - setflag4(A); - A &= BYTE_R; - break; - - case 0x88: /* ACA */ - A += A; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x89: /* ACB */ - A += B; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8A: /* ACC */ - A += C; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8B: /* ACD */ - A += D; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8C: /* ACE */ - A += E; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8D: /* ACH */ - A += H; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8E: /* ACL */ - A += L; - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x8F: /* ACM */ - A += fetch_m(); - if (CF) - A++; - setflag4(A); - A &= BYTE_R; - break; - - case 0x90: /* SUA */ - A -= A; - setflag4(A); - A &= BYTE_R; - break; - - case 0x91: /* SUB */ - A -= B; - setflag4(A); - A &= BYTE_R; - break; - - case 0x92: /* SUC */ - A -= C; - setflag4(A); - A &= BYTE_R; - break; - - case 0x93: /* SUD */ - A -= D; - setflag4(A); - A &= BYTE_R; - break; - - case 0x94: /* SUE */ - A -= E; - setflag4(A); - A &= BYTE_R; - break; - - case 0x95: /* SUH */ - A -= H; - setflag4(A); - A &= BYTE_R; - break; - - case 0x96: /* SUL */ - A -= L; - setflag4(A); - A &= BYTE_R; - break; - - case 0x97: /* SUM */ - A -= fetch_m(); - setflag4(A); - A &= BYTE_R; - break; - - case 0x98: /* SBA */ - A -= A; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x99: /* SBB */ - A -= B; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9A: /* SBC */ - A -= C; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9B: /* SBD */ - A -= D; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9C: /* SBE */ - A -= E; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9D: /* SBH */ - A -= H; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9E: /* SBL */ - A -= L; - if (CF) - A--; - setflag4(A); - A &= BYTE_R; - break; - - case 0x9F: /* SBM */ - A -= fetch_m(); - if (CF) - A - ; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA0: /* NDA */ - A &= A; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA1: /* NDB */ - A &= B; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA2: /* NDC */ - A &= C; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA3: /* NDD */ - A &= D; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA4: /* NDE */ - A &= E; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA5: /* NDH */ - A &= H; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA6: /* NDL */ - A &= L; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA7: /* NDM */ - A &= fetch_m(); - setflag4(A); - A &= BYTE_R; - break; - - case 0xA8: /* XRA */ - A ^= A; - setflag4(A); - A &= BYTE_R; - break; - - case 0xA9: /* XRB */ - A ^= B; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAA: /* XRC */ - A ^= C; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAB: /* XRD */ - A ^= D; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAC: /* XRE */ - A ^= E; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAD: /* XRH */ - A ^= H; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAE: /* XRL */ - A ^= L; - setflag4(A); - A &= BYTE_R; - break; - - case 0xAF: /* XRM */ - A |= fetch_m(); - setflag4(A); - A &= BYTE_R; - break; - - case 0xB0: /* ORA */ - A |= A; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB1: /* ORB */ - A |= B; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB2: /* ORC */ - A |= C; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB3: /* ORD */ - A |= D; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB4: /* ORE */ - A |= E; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB5: /* ORH */ - A |= H; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB6: /* ORL */ - A |= L; - setflag4(A); - A &= BYTE_R; - break; - - case 0xB7: /* ORM */ - A |= fetch_m(); - setflag4(A); - A &= BYTE_R; - break; - - case 0xB8: /* CPA */ - DAR -= A; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xB9: /* CPB */ - DAR -= B; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBA: /* CPC */ - DAR -= C; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBB: /* CPD */ - DAR -= D; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBC: /* CPE */ - DAR -= E; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBD: /* CPH */ - DAR -= H; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBE: /* CPL */ - DAR -= L; - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xBF: /* CPM */ - DAR -= fetch_m(); - setflag4(DAR); - A &= BYTE_R; - break; - - case 0xC0: /* NOP */ - break; - - case 0xC1: /* LAB */ - A = B; - A &= BYTE_R; - break; - - case 0xC2: /* LAC */ - A = C; - A &= BYTE_R; - break; - - case 0xC3: /* LAD */ - A = D; - A &= BYTE_R; - break; - - case 0xC4: /* LAE */ - A = E; - A &= BYTE_R; - break; - - case 0xC5: /* LAH */ - A = H; - A &= BYTE_R; - break; - - case 0xC6: /* LAL */ - A = L; - A &= BYTE_R; - break; - - case 0xC7: /* LAM */ - A = FETCH_M(); - A &= BYTE_R; - break; - - case 0xC8: /* LBA */ - B = A; - B &= BYTE_R; - break; - - case 0xC9: /* LBB */ - B = B; - B &= BYTE_R; - break; - - case 0xCA: /* LBC */ - B = C; - B &= BYTE_R; - break; - - case 0xCB: /* LBD */ - B = D; - B &= BYTE_R; - break; - - case 0xCC: /* LBE */ - B = E; - B &= BYTE_R; - break; - - case 0xCD: /* LBH */ - B = H; - B &= BYTE_R; - break; - - case 0xCE: /* LBL */ - B = L; - B &= BYTE_R; - break; - - case 0xCF: /* LBM */ - B = FETCH_M(); - B &= BYTE_R; - break; - - case 0xD0: /* LCA */ - C = A; - C &= BYTE_R; - break; - - case 0xD1: /* LCB */ - C = B; - C &= BYTE_R; - break; - - case 0xD2: /* LCC */ - C = C; - C &= BYTE_R; - break; - - case 0xD3: /* LCD */ - C = D; - C &= BYTE_R; - break; - - case 0xD4: /* LCE */ - C = E; - C &= BYTE_R; - break; - - case 0xD5: /* LCH */ - C = H; - C &= BYTE_R; - break; - - case 0xD6: /* LCL */ - C = L; - C &= BYTE_R; - break; - - case 0xD7: /* LCM */ - C = FETCH_M(); - C &= BYTE_R; - break; - - case 0xD8: /* LDA */ - D = A; - D &= BYTE_R; - break; - - case 0xD9: /* LDB */ - D = B; - D &= BYTE_R; - break; - - case 0xDA: /* LDC */ - D = C; - D &= BYTE_R; - break; - - case 0xDB: /* LDD */ - D = D; - D &= BYTE_R; - break; - - case 0xDC: /* LDE */ - D = E; - D &= BYTE_R; - break; - - case 0xDD: /* LDH */ - D = H; - D &= BYTE_R; - break; - - case 0xDE: /* LDL */ - D = L; - D &= BYTE_R; - break; - - case 0xDF: /* LDM */ - D = FETCH_M(); - D &= BYTE_R; - break; - - case 0xE0: /* LEA */ - E = A; - E &= BYTE_R; - break; - - case 0xE1: /* LEB */ - E = B; - E &= BYTE_R; - break; - - case 0xE2: /* LEC */ - E = C; - E &= BYTE_R; - break; - - case 0xE3: /* LED */ - E = D; - E &= BYTE_R; - break; - - case 0xE4: /* LEE */ - E = E; - E &= BYTE_R; - break; - - case 0xE5: /* LEH */ - E = H; - E &= BYTE_R; - break; - - case 0xE6: /* LEL */ - E = L; - E &= BYTE_R; - break; - - case 0xE7: /* LEM */ - E = FETCH_M(); - E &= BYTE_R; - break; - - case 0xE8: /* LHA */ - H = A; - H &= BYTE_R; - break; - - case 0xE9: /* LHB */ - H = B; - H &= BYTE_R; - break; - - case 0xEA: /* LHC */ - H = C; - H &= BYTE_R; - break; - - case 0xEB: /* LHD */ - H = D; - H &= BYTE_R; - break; - - case 0xEC: /* LHE */ - H = E; - H &= BYTE_R; - break; - - case 0xED: /* LHH */ - H = H; - H &= BYTE_R; - break; - - case 0xEE: /* LHL */ - H = L; - H &= BYTE_R; - break; - - case 0xEF: /* LHM */ - H = FETCH_M(); - H &= BYTE_R; - break; - - case 0xF0: /* LLA */ - L = A; - L &= BYTE_R; - break; - - case 0xF1: /* LLB */ - L = B; - L &= BYTE_R; - break; - - case 0xF2: /* LLC */ - L = C; - L &= BYTE_R; - break; - - case 0xF3: /* LLD */ - L = D; - L &= BYTE_R; - break; - - case 0xF4: /* LLE */ - L = E; - L &= BYTE_R; - break; - - case 0xF5: /* LLH */ - L = H; - L &= BYTE_R; - break; - - case 0xF6: /* LLL */ - L = L; - L &= BYTE_R; - break; - - case 0xF7: /* LLM */ - L = FETCH_M(); - L &= BYTE_R; - break; - - case 0xF8: /* LMA */ - store_m(A); - break; - - case 0xF9: /* LMB */ - store_m(B); - break; - - case 0xFA: /* LMC */ - store_m(C); - break; - - case 0xFB: /* LMD */ - store_m(D); - break; - - case 0xFC: /* LME */ - store_m(E); - break; - - case 0xFD: /* LMH */ - store_m(H); - break; - - case 0xFE: /* LML */ - store_m(L); - break; - - case 0xFF: /* LMM */ - val = FETCH_M(); - store_m(val); - break; - - default: /* undefined opcode */ - if (i8008_unit.flags & UNIT_OPSTOP) { - reason = STOP_OPCODE; - PC--; - } - break; - } - } - -/* Simulation halted */ - - saved_PC = PC; - return reason; -} - -/* store byte to (HL) */ -void store_m(uint32 val) -{ - DAR = (H << 8) + L; - DAR &= WORD_R14; - ret get_mword(DAR); -} - -/* get byte from (HL) */ -uint32 fetch_m(void) -{ - DAR = (H << 8) + L; - DAR &= WORD_R14; - put_mword(DAR, val); -} - -/* dump the registers */ -void dumpregs(void) -{ - sim_printf(" A=%02X B=%02X C=%02X D=%04X E=%02X H=%04X L=%02X\n", - A, B, C, D, E, H, L); - sim_printf(" CF=%d ZF=%d SF=%d PF=%d\n", - CF, ZF, SF, PF); -} - -/* fetch an instruction or byte */ -int32 fetch_byte(int32 flag) -{ - uint32 val; - - val = get_mbyte(PC) & 0xFF; /* fetch byte */ - if (i8008_dev.dctrl & DEBUG_asm || uptr->flags & UNIT_TRACE) { /* display source code */ - switch (flag) { - case 0: /* opcode fetch */ - sim_printf("OP=%02X %04X %s", val, PC, opcode[val]); - break; - case 1: /* byte operand fetch */ - sim_printf("0%02XH", val); - break; - } - } - PC = (PC + 1) & ADDRMASK; /* increment PC */ - val &= BYTE_R; - return val; -} - -/* fetch a word */ -int32 fetch_word(void) -{ - uint16 val; - - val = get_mbyte(PC) & BYTE_R; /* fetch low byte */ - val |= get_mbyte(PC + 1) << 8; /* fetch high byte */ - if (i8008_dev.dctrl & DEBUG_asm || uptr->flags & UNIT_TRACE) /* display source code */ - sim_printf("0%04XH", val); - PC = (PC + 2) & ADDRMASK; /* increment PC */ - val &= WORD_R14; - return val; -} - -/* push a word to the stack frame */ -void push_word(uint16 val) -{ - stack_frame[SP] = val; - SP++; - if (SP == 8) - SP = 0; -} - -/* pop a word from the stack frame */ -uint16 pop_word(void) -{ - SP--; - if (SP < 0) - SP = 7; - return stack_frame[SP]; -} - - -/* Set the arry, ign, ero and verflow flags following - an operation on 'reg'. -*/ - -void setflag4(int32 reg) -{ - if (reg & 0x100) - CF = 1; - else - CF = 0; - if (reg & 0x80) - SF = 0; - else - SF = 1; - if ((reg & BYTE_R) == 0) - ZF = 1; - else - ZF = 0; - parity(reg); -} - -/* Set the arry, ign and ero flags following - an operation on 'reg'. -*/ - -void setflag3(int32 reg) -{ - CF = 0; - if (reg & 0x80) - SF = 0; - else - SF = 1; - if ((reg & BYTE_R) == 0) - ZF = 1; - else - ZF = 0; - parity(reg); -} - -/* Set the Parity (PF) flag based on parity of 'reg', i.e., number -of bits on even: PF=1, else PF=0 -*/ - -void parity(int32 reg) -{ - int32 bc = 0; - - if (reg & 0x01) bc++; - if (reg & 0x02) bc++; - if (reg & 0x04) bc++; - if (reg & 0x08) bc++; - if (reg & 0x10) bc++; - if (reg & 0x20) bc++; - if (reg & 0x40) bc++; - if (reg & 0x80) bc++; - if (bc & 0x01) - PF = 0; - else - PF = 1; -} - - - -/* Reset routine */ - -t_stat i8008_reset (DEVICE *dptr) -{ - int i; - - CF = SF = ZF = PF = 0; - saved_PC = 0; - int_req = 0; - for (i = 0; i < 7; i++) - stack_frame[i] = 0; - sim_brk_types = sim_brk_dflt = SWMASK ('E'); - sim_printf(" 8008: Reset\n"); - return SCPE_OK; -} - -/* Memory examine */ - -t_stat i8008_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ - if (addr >= MEMSIZE) - return SCPE_NXM; - if (vptr != NULL) - *vptr = get_mbyte(addr); - return SCPE_OK; -} - -/* Memory deposit */ - -t_stat i8008_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ - if (addr >= MEMSIZE) - return SCPE_NXM; - put_mbyte(addr, val); - return SCPE_OK; -} - -/* This is the binary loader. The input file is considered to be - a string of literal bytes with no special format. The load - starts at the current value of the PC. -*/ - -int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ - int32 i, addr = 0, cnt = 0; - - if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; - addr = saved_PC; - while ((i = getc (fileref)) != EOF) { - put_mbyte(addr, i); - addr++; - cnt++; - } /* end while */ - sim_printf ("%d Bytes loaded.\n", cnt); - return (SCPE_OK); -} - -/* Symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ - int32 cflag, c1, c2, inst, adr; - - cflag = (uptr == NULL) || (uptr == &i8008_unit); - c1 = (val[0] >> 8) & 0x7F; - c2 = val[0] & 0x7F; - if (sw & SWMASK ('A')) { - fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2); - return SCPE_OK; - } - if (sw & SWMASK ('C')) { - fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); - fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2); - return SCPE_OK; - } - if (!(sw & SWMASK ('M'))) return SCPE_ARG; - inst = val[0]; - fprintf (of, "%s", opcode[inst]); - if (oplen[inst] == 2) { - if (strchr(opcode[inst], ' ') != NULL) - fprintf (of, ","); - else fprintf (of, " "); - fprintf (of, "%h", val[1]); - } - if (oplen[inst] == 3) { - adr = val[1] & 0xFF; - adr |= (val[2] << 8) & 0xff00; - if (strchr(opcode[inst], ' ') != NULL) - fprintf (of, ","); - else fprintf (of, " "); - fprintf (of, "%h", adr); - } - return -(oplen[inst] - 1); -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = error status -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ - int32 cflag, i = 0, j, r; - char gbuf[CBUFSIZE]; - - cflag = (uptr == NULL) || (uptr == &i8008_unit); - while (isspace (*cptr)) cptr++; /* absorb spaces */ - if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (uint32) cptr[0]; - return SCPE_OK; - } - if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((uint32) cptr[0] << 8) + (uint32) cptr[1]; - return SCPE_OK; - } - -/* An instruction: get opcode (all characters until null, comma, - or numeric (including spaces). -*/ - - while (1) { - if (*cptr == ',' || *cptr == '\0' || - isdigit(*cptr)) - break; - gbuf[i] = toupper(*cptr); - cptr++; - i++; - } - -/* Allow for RST which has numeric as part of opcode */ - - if (toupper(gbuf[0]) == 'R' && - toupper(gbuf[1]) == 'S' && - toupper(gbuf[2]) == 'T') { - gbuf[i] = toupper(*cptr); - cptr++; - i++; - } - -/* kill trailing spaces if any */ - gbuf[i] = '\0'; - for (j = i - 1; gbuf[j] == ' '; j--) { - gbuf[j] = '\0'; - } - -/* find opcode in table */ - for (j = 0; j < 256; j++) { - if (strcmp(gbuf, opcode[j]) == 0) - break; - } - if (j > 255) /* not found */ - return SCPE_ARG; - - val[0] = j; /* store opcode */ - if (oplen[j] < 2) /* if 1-byter we are done */ - return SCPE_OK; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); /* get address */ - sscanf(gbuf, "%o", &r); - if (oplen[j] == 2) { - val[1] = r & 0xFF; - return (-1); - } - val[1] = r & 0xFF; - val[2] = (r >> 8) & 0xFF; - return (-2); -} diff --git a/IBMPC-Systems/common/i8080.c b/IBMPC-Systems/common/i8080.c deleted file mode 100644 index 3d0f5ccc..00000000 --- a/IBMPC-Systems/common/i8080.c +++ /dev/null @@ -1,1445 +0,0 @@ -/* i8080.c: Intel 8080/8085 CPU simulator - - Copyright (c) 1997-2005, Charles E. Owen - - 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 - CHARLES E. OWEN 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 Charles E. Owen shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - This software was modified by Bill Beech, Nov 2010, to allow emulation of Intel - iSBC Single Board Computers. - - Copyright (c) 2011, William A. Beech - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of William A. Beech shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from William A. Beech. - - cpu 8080 CPU - - 08 Oct 02 RMS Tied off spurious compiler warnings - 23 Nov 10 WAB Modified for iSBC emulation - 04 Dec 12 WAB Added 8080 interrupts - 14 Dec 12 WAB Added 8085 interrupts - - The register state for the 8080 CPU is: - - A<0:7> Accumulator - BC<0:15> BC Register Pair - DE<0:15> DE Register Pair - HL<0:15> HL Register Pair - PSW<0:7> Program Status Word (Flags) - PC<0:15> Program counter - SP<0:15> Stack Pointer - - The 8080 is an 8-bit CPU, which uses 16-bit registers to address - up to 64KB of memory. - - The 78 basic instructions come in 1, 2, and 3-byte flavors. - - This routine is the instruction decode routine for the 8080. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until 'reason' is set non-zero. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - I/O error in I/O simulator - Invalid OP code (if ITRAP is set on CPU) - - 2. Interrupts. - There are 8 possible levels of interrupt, and in effect they - do a hardware CALL instruction to one of 8 possible low - memory addresses. - - 3. Non-existent memory. On the 8080, reads to non-existent memory - return 0FFh, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against actual memory size. - - 4. Adding I/O devices. These modules must be modified: - - altair_cpu.c add I/O service routines to dev_table - altair_sys.c add pointer to data structures in sim_devices - - ?? ??? 11 - Original file. - 16 Dec 12 - Modified to use isbc_80_10.cfg file to set base and size. - 20 Dec 12 - Modified for basic interrupt function. - 03 Mar 13 - Added trace function. - 04 Mar 13 - Modified all instructions to truncate the affected register - at the end of the routine. - 17 Mar 13 - Modified to enable/disable trace based on start and stop - addresses. - -*/ - -#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_8085 (UNIT_V_UF+1) /* 8080/8085 switch */ -#define UNIT_8085 (1 << UNIT_V_8085) -#define UNIT_V_TRACE (UNIT_V_UF+2) /* Trace switch */ -#define UNIT_TRACE (1 << UNIT_V_TRACE) - -/* Flag values to set proper positions in PSW */ -#define CF 0x01 -#define PF 0x04 -#define AF 0x10 -#define ZF 0x40 -#define SF 0x80 - -/* Macros to handle the flags in the PSW - 8080 has bit #1 always set. This is (not well) documented behavior. */ -#define PSW_ALWAYS_ON (0x02) /* for 8080 */ -#define PSW_MSK (CF|PF|AF|ZF|SF) -#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 COND_SET_FLAG(COND,FLAG) \ - if (COND) SET_FLAG(FLAG); else CLR_FLAG(FLAG) - -#define SET_XACK(VAL) (xack = VAL) -#define GET_XACK(FLAG) (xack &= FLAG) - -/* values for IM bits */ -#define ITRAP 0x100 -#define SID 0x80 -#define SOD 0x80 -#define SDE 0x40 -#define R75 0x10 -#define IE 0x08 -#define MSE 0x08 -#define M75 0x04 -#define M65 0x02 -#define M55 0x01 - -/* register masks */ -#define BYTE_R 0xFF -#define WORD_R 0xFFFF - -/* storage for the rest of the registers */ -uint32 PSW = 0; /* program status word */ -uint32 A = 0; /* accumulator */ -uint32 BC = 0; /* BC register pair */ -uint32 DE = 0; /* DE register pair */ -uint32 HL = 0; /* HL register pair */ -uint32 SP = 0; /* Stack pointer */ -uint32 saved_PC = 0; /* program counter */ -uint32 IM = 0; /* Interrupt Mask Register */ -uint8 xack = 0; /* XACK signal */ -uint32 int_req = 0; /* Interrupt request */ - -int32 PCX; /* External view of PC */ -int32 PC; -UNIT *uptr; - -/* function prototypes */ -void set_cpuint(int32 int_num); -void dumpregs(void); -int32 fetch_byte(int32 flag); -int32 fetch_word(void); -uint16 pop_word(void); -void push_word(uint16 val); -void setarith(int32 reg); -void setlogical(int32 reg); -void setinc(int32 reg); -int32 getreg(int32 reg); -void putreg(int32 reg, int32 val); -int32 getpair(int32 reg); -int32 getpush(int32 reg); -void putpush(int32 reg, int32 data); -void putpair(int32 reg, int32 val); -void parity(int32 reg); -int32 cond(int32 con); -t_stat i8080_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat i8080_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat i8080_reset (DEVICE *dptr); - -/* external function prototypes */ - -extern t_stat i8080_reset (DEVICE *dptr); -extern uint8 get_mbyte(uint16 addr); -extern uint16 get_mword(uint16 addr); -extern void put_mbyte(uint16 addr, uint8 val); -extern void put_mword(uint16 addr, uint16 val); -extern int32 sim_int_char; -extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - - -struct idev { - uint8 (*routine)(t_bool, uint8, uint8); - uint8 devnum; -}; - -/* This is the I/O configuration table. There are 256 possible -device addresses, if a device is plugged to a port it's routine -address is here, 'nulldev' means no device is available -*/ - -extern struct idev dev_table[]; - -/* CPU data structures - - i8080_dev CPU device descriptor - i8080_unit CPU unit descriptor - i8080_reg CPU register list - i8080_mod CPU modifiers list -*/ - -UNIT i8080_unit = { UDATA (NULL, 0, 65535) }; /* default 8080 */ - -REG i8080_reg[] = { - { HRDATA (PC, saved_PC, 16) }, /* must be first for sim_PC */ - { HRDATA (PSW, PSW, 8) }, - { HRDATA (A, A, 8) }, - { HRDATA (BC, BC, 16) }, - { HRDATA (DE, DE, 16) }, - { HRDATA (HL, HL, 16) }, - { HRDATA (SP, SP, 16) }, - { HRDATA (IM, IM, 8) }, - { HRDATA (XACK, xack, 8) }, - { HRDATA (INTR, int_req, 32) }, - { HRDATA (WRU, sim_int_char, 8) }, - { NULL } -}; - -MTAB i8080_mod[] = { - { UNIT_8085, 0, "8080", "8080", NULL }, - { UNIT_8085, UNIT_8085, "8085", "8085", NULL }, - { UNIT_OPSTOP, 0, "ITRAP", "ITRAP", NULL }, - { UNIT_OPSTOP, UNIT_OPSTOP, "NOITRAP", "NOITRAP", NULL }, - { UNIT_TRACE, 0, "NOTRACE", "NOTRACE", NULL }, - { UNIT_TRACE, UNIT_TRACE, "TRACE", "TRACE", NULL }, - { 0 } -}; - -DEBTAB i8080_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 i8080_dev = { - "CPU", //name - &i8080_unit, //units - i8080_reg, //registers - i8080_mod, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - &i8080_ex, //examine - &i8080_dep, //deposit -// &i8080_reset, //reset - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - i8080_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* tables for the disassembler */ -const char *opcode[] = { -"NOP", "LXI B,", "STAX B", "INX B", /* 0x00 */ -"INR B", "DCR B", "MVI B,", "RLC", -"???", "DAD B", "LDAX B", "DCX B", -"INR C", "DCR C", "MVI C,", "RRC", -"???", "LXI D,", "STAX D", "INX D", /* 0x10 */ -"INR D", "DCR D", "MVI D,", "RAL", -"???", "DAD D", "LDAX D", "DCX D", -"INR E", "DCR E", "MVI E,", "RAR", -"RIM", "LXI H,", "SHLD ", "INX H", /* 0x20 */ -"INR H", "DCR H", "MVI H,", "DAA", -"???", "DAD H", "LHLD ", "DCX H", -"INR L", "DCR L", "MVI L", "CMA", -"SIM", "LXI SP,", "STA ", "INX SP", /* 0x30 */ -"INR M", "DCR M", "MVI M,", "STC", -"???", "DAD SP", "LDA ", "DCX SP", -"INR A", "DCR A", "MVI A,", "CMC", -"MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", /* 0x40 */ -"MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", -"MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", -"MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", -"MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", /* 0x50 */ -"MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", -"MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", -"MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", -"MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", /* 0x60 */ -"MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", -"MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", -"MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", -"MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", /* 0x70 */ -"MOV M,H", "MOV M,L", "HLT", "MOV M,A", -"MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", -"MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", -"ADD B", "ADD C", "ADD D", "ADD E", /* 0x80 */ -"ADD H", "ADD L", "ADD M", "ADD A", -"ADC B", "ADC C", "ADC D", "ADC E", -"ADC H", "ADC L", "ADC M", "ADC A", -"SUB B", "SUB C", "SUB D", "SUB E", /* 0x90 */ -"SUB H", "SUB L", "SUB M", "SUB A", -"SBB B", "SBB C", "SBB D", "SBB E", -"SBB H", "SBB L", "SBB M", "SBB A", -"ANA B", "ANA C", "ANA D", "ANA E", /* 0xA0 */ -"ANA H", "ANA L", "ANA M", "ANA A", -"XRA B", "XRA C", "XRA D", "XRA E", -"XRA H", "XRA L", "XRA M", "XRA A", -"ORA B", "ORA C", "ORA D", "ORA E", /* 0xB0 */ -"ORA H", "ORA L", "ORA M", "ORA A", -"CMP B", "CMP C", "CMP D", "CMP E", -"CMP H", "CMP L", "CMP M", "CMP A", -"RNZ", "POP B", "JNZ ", "JMP ", /* 0xC0 */ -"CNZ ", "PUSH B", "ADI ", "RST 0", -"RZ", "RET", "JZ ", "???", -"CZ ", "CALL ", "ACI ", "RST 1", -"RNC", "POP D", "JNC ", "OUT ", /* 0xD0 */ -"CNC ", "PUSH D", "SUI ", "RST 2", -"RC", "???", "JC ", "IN ", -"CC ", "???", "SBI ", "RST 3", -"RPO", "POP H", "JPO ", "XTHL", /* 0xE0 */ -"CPO ", "PUSH H", "ANI ", "RST 4", -"RPE", "PCHL", "JPE ", "XCHG", -"CPE ", "???", "XRI ", "RST 5", -"RP", "POP PSW", "JP ", "DI", /* 0xF0 */ -"CP ", "PUSH PSW", "ORI ", "RST 6", -"RM", "SPHL", "JM ", "EI", -"CM ", "???", "CPI ", "RST 7", - }; - -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, -1,3,3,1,1,1,2,1,0,1,3,1,1,1,2,1, -1,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; -} - -//FILE *fpd; - -/* instruction simulator */ -int32 sim_instr (void) -{ - extern int32 sim_interval; - uint32 IR, OP, DAR, reason, adr; - - PC = saved_PC & WORD_R; /* load local PC */ - reason = 0; - - uptr = i8080_dev.units; - if (i8080_dev.dctrl & DEBUG_flow) { - if (uptr->flags & UNIT_8085) - sim_printf("CPU = 8085\n"); - else - sim_printf("CPU = 8080\n"); - } - /* Main instruction fetch/decode loop */ - - while (reason == 0) { /* loop until halted */ - - saved_PC = PC; - -// if (PC == 0x1000) { /* turn on debugging */ -// i8080_dev.dctrl = DEBUG_asm + DEBUG_reg; -// reason = STOP_HALT; -// } - if (i8080_dev.dctrl & DEBUG_reg) { - dumpregs(); - sim_printf("\n"); - } - - if (sim_interval <= 0) { /* check clock queue */ - if ((reason = sim_process_event())) - break; - } - sim_interval--; /* countdown clock */ - - if (int_req > 0) { /* interrupt? */ -// sim_printf("\ni8080: int_req=%04X IM=%04X", int_req, IM); - if (uptr->flags & UNIT_8085) { /* 8085 */ - if (int_req & ITRAP) { /* int */ - push_word(PC); - PC = 0x0024; - int_req &= ~ITRAP; - } else if (IM & IE) { - if (int_req & I75 && IM & M75) { /* int 7.5 */ - push_word(PC); - PC = 0x003C; - int_req &= ~I75; - } else if (int_req & I65 && IM & M65) { /* int 6.5 */ - push_word(PC); - PC = 0x0034; - int_req &= ~I65; - } else if (int_req & I55 && IM & M55) { /* int 5.5 */ - push_word(PC); - PC = 0x002C; - int_req &= ~I55; - } else if (int_req & INT_R) { /* intr */ - push_word(PC); /* do an RST 7 */ - PC = 0x0038; - int_req &= ~INT_R; - } - } - } else { /* 8080 */ - if (IM & IE) { /* enabled? */ - push_word(PC); /* do an RST 7 */ - PC = 0x0038; - int_req &= ~INT_R; -// sim_printf("\ni8080: int_req=%04X", int_req); - } - } - } /* end interrupt */ - - if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - - PCX = PC; - -// fprintf(fpd, "%04X\n", PC); -// fflush(fpd); - - if (uptr->flags & UNIT_TRACE) { - dumpregs(); - sim_printf("\n"); - } - IR = OP = fetch_byte(0); /* instruction fetch */ - - if (GET_XACK(1) == 0) { /* no XACK for instruction fetch */ - reason = STOP_XACK; - sim_printf("Stopped for XACK-1 PC=%04X\n", --PC); - continue; - } - - if (OP == 0x76) { /* HLT Instruction*/ - reason = STOP_HALT; - PC--; - continue; - } - - /* Handle below all operations which refer to registers or - register pairs. After that, a large switch statement - takes care of all other opcodes */ - - if ((OP & 0xC0) == 0x40) { /* MOV */ - DAR = getreg(OP & 0x07); - putreg((OP >> 3) & 0x07, DAR); - goto loop_end; - } - - if ((OP & 0xC7) == 0x06) { /* MVI */ - putreg((OP >> 3) & 0x07, fetch_byte(1)); - goto loop_end; - } - - if ((OP & 0xCF) == 0x01) { /* LXI */ - DAR = fetch_word(); - putpair((OP >> 4) & 0x03, DAR); - goto loop_end; - } - - if ((OP & 0xEF) == 0x0A) { /* LDAX */ - DAR = getpair((OP >> 4) & 0x03); - putreg(7, get_mbyte(DAR)); - goto loop_end; - } - - if ((OP & 0xEF) == 0x02) { /* STAX */ - DAR = getpair((OP >> 4) & 0x03); - put_mbyte(DAR, getreg(7)); - goto loop_end; - } - - if ((OP & 0xF8) == 0xB8) { /* CMP */ - DAR = A & 0xFF; - DAR -= getreg(OP & 0x07); - setarith(DAR); - DAR &= BYTE_R; - goto loop_end; - } - - if ((OP & 0xC7) == 0xC2) { /* JMP */ - adr = fetch_word(); - if (cond((OP >> 3) & 0x07)) - PC = adr; - goto loop_end; - } - - if ((OP & 0xC7) == 0xC4) { /* CALL */ - adr = fetch_word(); - if (cond((OP >> 3) & 0x07)) { - push_word(PC); - PC = adr; - } - goto loop_end; - } - - if ((OP & 0xC7) == 0xC0) { /* RET */ - if (cond((OP >> 3) & 0x07)) { - PC = pop_word(); - } - goto loop_end; - } - - if ((OP & 0xC7) == 0xC7) { /* RST */ - push_word(PC); - PC = OP & 0x38; - goto loop_end; - } - - if ((OP & 0xCF) == 0xC5) { /* PUSH */ - DAR = getpush((OP >> 4) & 0x03); - push_word(DAR); - goto loop_end; - } - - if ((OP & 0xCF) == 0xC1) { /* POP */ - DAR = pop_word(); - putpush((OP >> 4) & 0x03, DAR); - goto loop_end; - } - - if ((OP & 0xF8) == 0x80) { /* ADD */ - A += getreg(OP & 0x07); - setarith(A); - A &= BYTE_R; - goto loop_end; - } - - if ((OP & 0xF8) == 0x88) { /* ADC */ - A += getreg(OP & 0x07); - if (GET_FLAG(CF)) - A++; - setarith(A); - A &= BYTE_R; - goto loop_end; - } - - if ((OP & 0xF8) == 0x90) { /* SUB */ - A -= getreg(OP & 0x07); - setarith(A); - A &= BYTE_R; - goto loop_end; - } - - if ((OP & 0xF8) == 0x98) { /* SBB */ - A -= getreg(OP & 0x07); - if (GET_FLAG(CF)) - A--; - setarith(A); - A &= BYTE_R; - goto loop_end; - } - - if ((OP & 0xC7) == 0x04) { /* INR */ - DAR = getreg((OP >> 3) & 0x07); - DAR++; - setinc(DAR); -// DAR &= BYTE_R; - putreg((OP >> 3) & 0x07, DAR); - goto loop_end; - } - - if ((OP & 0xC7) == 0x05) { /* DCR */ - DAR = getreg((OP >> 3) & 0x07); - DAR--; - setinc(DAR); -// DAR &= BYTE_R; - putreg((OP >> 3) & 0x07, DAR); - goto loop_end; - } - - if ((OP & 0xCF) == 0x03) { /* INX */ - DAR = getpair((OP >> 4) & 0x03); - DAR++; -// DAR &= WORD_R; - putpair((OP >> 4) & 0x03, DAR); - goto loop_end; - } - - if ((OP & 0xCF) == 0x0B) { /* DCX */ - DAR = getpair((OP >> 4) & 0x03); - DAR--; -// DAR &= WORD_R; - putpair((OP >> 4) & 0x03, DAR); - goto loop_end; - } - - if ((OP & 0xCF) == 0x09) { /* DAD */ - HL += getpair((OP >> 4) & 0x03); - COND_SET_FLAG(HL & 0x10000, CF); - HL &= WORD_R; - goto loop_end; - } - - if ((OP & 0xF8) == 0xA0) { /* ANA */ - A &= getreg(OP & 0x07); - setlogical(A); - goto loop_end; - } - - if ((OP & 0xF8) == 0xA8) { /* XRA */ - A ^= getreg(OP & 0x07); - setlogical(A); - A &= BYTE_R; - goto loop_end; - } - - if ((OP & 0xF8) == 0xB0) { /* ORA */ - A |= getreg(OP & 0x07); - setlogical(A); - goto loop_end; - } - - /* The Big Instruction Decode Switch */ - - switch (IR) { - - /* 8085 instructions only */ - case 0x20: /* RIM */ - if (i8080_unit.flags & UNIT_8085) { /* 8085 */ - A = IM; - } else { /* 8080 */ - reason = STOP_OPCODE; - PC--; - } - break; - - case 0x30: /* SIM */ - if (i8080_unit.flags & UNIT_8085) { /* 8085 */ - if (A & MSE) { - IM &= 0xF8; - IM |= A & 0x07; - } - if (A & I75) { /* reset RST 7.5 FF */ - } - } else { /* 8080 */ - reason = STOP_OPCODE; - PC--; - } - break; - - /* Logical instructions */ - - case 0xFE: /* CPI */ - DAR = A; - DAR -= fetch_byte(1); -// DAR &= BYTE_R; - setarith(DAR); - break; - - case 0xE6: /* ANI */ - A &= fetch_byte(1); - setlogical(A); - break; - - case 0xEE: /* XRI */ - A ^= fetch_byte(1); -// DAR &= BYTE_R; - setlogical(A); - break; - - case 0xF6: /* ORI */ - A |= fetch_byte(1); - setlogical(A); - break; - - /* Jump instructions */ - - case 0xC3: /* JMP */ - PC = fetch_word(); - break; - - case 0xE9: /* PCHL */ - PC = HL; - break; - - case 0xCD: /* CALL */ - adr = fetch_word(); - push_word(PC); - PC = adr; - break; - - case 0xC9: /* RET */ - PC = pop_word(); - break; - - /* Data Transfer Group */ - - case 0x32: /* STA */ - DAR = fetch_word(); - DAR &= WORD_R; - put_mbyte(DAR, A); - break; - - case 0x3A: /* LDA */ - DAR = fetch_word(); - DAR &= WORD_R; - A = get_mbyte(DAR); - break; - - case 0x22: /* SHLD */ - DAR = fetch_word(); - DAR &= WORD_R; - put_mword(DAR, HL); - break; - - case 0x2A: /* LHLD */ - DAR = fetch_word(); - DAR &= WORD_R; - HL = get_mword(DAR); - break; - - case 0xEB: /* XCHG */ - DAR = HL; - HL = DE; - HL &= WORD_R; - DE = DAR; - DE &= WORD_R; - break; - - /* Arithmetic Group */ - - case 0xC6: /* ADI */ - A += fetch_byte(1); - setarith(A); - A &= BYTE_R; - break; - - case 0xCE: /* ACI */ - A += fetch_byte(1); - if (GET_FLAG(CF)) - A++; - setarith(A); - A &= BYTE_R; - break; - - case 0xD6: /* SUI */ - A -= fetch_byte(1); - setarith(A); - A &= BYTE_R; - break; - - case 0xDE: /* SBI */ - A -= fetch_byte(1); - if (GET_FLAG(CF)) - A--; - setarith(A); - A &= BYTE_R; - break; - - case 0x27: /* DAA */ - DAR = A & 0x0F; - if (DAR > 9 || GET_FLAG(AF)) { - DAR += 6; - A &= 0xF0; - A |= DAR & 0x0F; - COND_SET_FLAG(DAR & 0x10, AF); - } - DAR = (A >> 4) & 0x0F; - if (DAR > 9 || GET_FLAG(AF)) { - DAR += 6; - if (GET_FLAG(AF)) DAR++; - A &= 0x0F; - A |= (DAR << 4); - } - COND_SET_FLAG(DAR & 0x10, CF); - COND_SET_FLAG(A & 0x80, SF); - COND_SET_FLAG((A & 0xFF) == 0, ZF); - parity(A); - break; - - case 0x07: /* RLC */ - COND_SET_FLAG(A & 0x80, CF); - A = (A << 1) & 0xFF; - if (GET_FLAG(CF)) - A |= 0x01; - A &= BYTE_R; - break; - - case 0x0F: /* RRC */ - COND_SET_FLAG(A & 0x01, CF); - A = (A >> 1) & 0xFF; - if (GET_FLAG(CF)) - A |= 0x80; - A &= BYTE_R; - break; - - case 0x17: /* RAL */ - DAR = GET_FLAG(CF); - COND_SET_FLAG(A & 0x80, CF); - A = (A << 1) & 0xFF; - if (DAR) - A |= 0x01; - A &= BYTE_R; - break; - - case 0x1F: /* RAR */ - DAR = GET_FLAG(CF); - COND_SET_FLAG(A & 0x01, CF); - A = (A >> 1) & 0xFF; - if (DAR) - A |= 0x80; - A &= BYTE_R; - break; - - case 0x2F: /* CMA */ - A = ~A; - A &= BYTE_R; - break; - - case 0x3F: /* CMC */ - TOGGLE_FLAG(CF); - break; - - case 0x37: /* STC */ - SET_FLAG(CF); - break; - - /* Stack, I/O & Machine Control Group */ - - case 0x00: /* NOP */ - break; - - case 0xE3: /* XTHL */ - DAR = pop_word(); - push_word(HL); - HL = DAR; - HL &= WORD_R; - break; - - case 0xF9: /* SPHL */ - SP = HL; - break; - - case 0xFB: /* EI */ - IM |= IE; -// sim_printf("\nEI: pc=%04X", PC - 1); - break; - - case 0xF3: /* DI */ - IM &= ~IE; -// sim_printf("\nDI: pc=%04X", PC - 1); - break; - - case 0xDB: /* IN */ - DAR = fetch_byte(1); - A = dev_table[DAR].routine(0, 0, dev_table[DAR].devnum); - A &= BYTE_R; -// sim_printf("\n%04X\tIN\t%02X\t;devnum=%d", PC - 1, DAR, dev_table[DAR].devnum); - break; - - case 0xD3: /* OUT */ - DAR = fetch_byte(1); - dev_table[DAR].routine(1, A, dev_table[DAR].devnum); -// sim_printf("\n%04X\tOUT\t%02X\t;devnum=%d", PC - 1, DAR, dev_table[DAR].devnum); - break; - - default: /* undefined opcode */ - if (i8080_unit.flags & UNIT_OPSTOP) { - reason = STOP_OPCODE; - PC--; - } - break; - } -loop_end: - if (GET_XACK(1) == 0) { /* no XACK for instruction fetch */ - reason = STOP_XACK; - sim_printf("Stopped for XACK-2 PC=%04X\n", --PC); - continue; - } - - } - -/* Simulation halted */ - - saved_PC = PC; -// fclose(fpd); - return reason; -} - -/* dump the registers */ -void dumpregs(void) -{ - sim_printf(" A=%02X BC=%04X DE=%04X HL=%04X SP=%04X IM=%02X XACK=%d\n", - A, BC, DE, HL, SP, IM, xack); - sim_printf(" CF=%d ZF=%d AF=%d SF=%d PF=%d\n", - GET_FLAG(CF) ? 1 : 0, - GET_FLAG(ZF) ? 1 : 0, - GET_FLAG(AF) ? 1 : 0, - GET_FLAG(SF) ? 1 : 0, - GET_FLAG(PF) ? 1 : 0); -} -/* fetch an instruction or byte */ -int32 fetch_byte(int32 flag) -{ - uint32 val; - - val = get_mbyte(PC) & 0xFF; /* fetch byte */ - if (i8080_dev.dctrl & DEBUG_asm || uptr->flags & UNIT_TRACE) { /* display source code */ - switch (flag) { - case 0: /* opcode fetch */ - sim_printf("OP=%02X %04X %s", val, PC, opcode[val]); - break; - case 1: /* byte operand fetch */ - sim_printf("0%02XH", val); - break; - } - } - PC = (PC + 1) & ADDRMASK; /* increment PC */ - val &= BYTE_R; - return val; -} - -/* fetch a word */ -int32 fetch_word(void) -{ - uint16 val; - - val = get_mbyte(PC) & BYTE_R; /* fetch low byte */ - val |= get_mbyte(PC + 1) << 8; /* fetch high byte */ - if (i8080_dev.dctrl & DEBUG_asm || uptr->flags & UNIT_TRACE) /* display source code */ - sim_printf("0%04XH", val); - PC = (PC + 2) & ADDRMASK; /* increment PC */ - val &= WORD_R; - return val; -} - -/* push a word to the stack */ -void push_word(uint16 val) -{ - SP--; - put_mbyte(SP, (val >> 8)); - SP--; - put_mbyte(SP, val & 0xFF); -} - -/* pop a word from the stack */ -uint16 pop_word(void) -{ - register uint16 res; - - res = get_mbyte(SP); - SP++; - res |= get_mbyte(SP) << 8; - SP++; - return res; -} - -/* Test an 8080 flag condition and return 1 if true, 0 if false */ -int32 cond(int32 con) -{ - switch (con) { - case 0: /* NZ */ - if (GET_FLAG(ZF) == 0) return 1; - break; - case 1: /* Z */ - if (GET_FLAG(ZF)) return 1; - break; - case 2: /* NC */ - if (GET_FLAG(CF) == 0) return 1; - break; - case 3: /* C */ - if (GET_FLAG(CF)) return 1; - break; - case 4: /* PO */ - if (GET_FLAG(PF) == 0) return 1; - break; - case 5: /* PE */ - if (GET_FLAG(PF)) return 1; - break; - case 6: /* P */ - if (GET_FLAG(SF) == 0) return 1; - break; - case 7: /* M */ - if (GET_FLAG(SF)) return 1; - break; - default: - break; - } - return 0; -} - -/* Set the arry, ign, ero and

arity flags following - an arithmetic operation on 'reg'. -*/ - -void setarith(int32 reg) -{ - COND_SET_FLAG(reg & 0x100, CF); - COND_SET_FLAG(reg & 0x80, SF); - COND_SET_FLAG((reg & BYTE_R) == 0, ZF); - CLR_FLAG(AF); - parity(reg); -} - -/* Set the arry, ign, ero amd

arity flags following - a logical (bitwise) operation on 'reg'. -*/ - -void setlogical(int32 reg) -{ - CLR_FLAG(CF); - COND_SET_FLAG(reg & 0x80, SF); - COND_SET_FLAG((reg & BYTE_R) == 0, ZF); - CLR_FLAG(AF); - parity(reg); -} - -/* Set the Parity (P) flag based on parity of 'reg', i.e., number - of bits on even: P=0200000, else P=0 -*/ - -void parity(int32 reg) -{ - int32 bc = 0; - - if (reg & 0x01) bc++; - if (reg & 0x02) bc++; - if (reg & 0x04) bc++; - if (reg & 0x08) bc++; - if (reg & 0x10) bc++; - if (reg & 0x20) bc++; - if (reg & 0x40) bc++; - if (reg & 0x80) bc++; - if (bc & 0x01) - CLR_FLAG(PF); - else - SET_FLAG(PF); -} - -/* Set the ign, ero amd

arity flags following - an INR/DCR operation on 'reg'. -*/ - -void setinc(int32 reg) -{ - COND_SET_FLAG(reg & 0x80, SF); - COND_SET_FLAG((reg & BYTE_R) == 0, ZF); - parity(reg); -} - -/* Get an 8080 register and return it */ -int32 getreg(int32 reg) -{ - switch (reg) { - case 0: /* reg B */ -// sim_printf("reg=%04X BC=%04X ret=%04X\n", -// reg, BC, (BC >>8) & 0xff); - return ((BC >>8) & BYTE_R); - case 1: /* reg C */ - return (BC & BYTE_R); - case 2: /* reg D */ - return ((DE >>8) & BYTE_R); - case 3: /* reg E */ - return (DE & BYTE_R); - case 4: /* reg H */ - return ((HL >>8) & BYTE_R); - case 5: /* reg L */ - return (HL & BYTE_R); - case 6: /* reg M */ - return (get_mbyte(HL)); - case 7: /* reg A */ - return (A); - default: - break; - } - return 0; -} - -/* Put a value into an 8-bit 8080 register from memory */ -void putreg(int32 reg, int32 val) -{ - switch (reg) { - case 0: /* reg B */ -// sim_printf("reg=%04X val=%04X\n", reg, val); - BC = BC & BYTE_R; -// sim_printf("BC&0x00ff=%04X val<<8=%04X\n", BC, val<<8); - BC = BC | (val <<8); - break; - case 1: /* reg C */ - BC = BC & 0xFF00; - BC = BC | val; - break; - case 2: /* reg D */ - DE = DE & BYTE_R; - DE = DE | (val <<8); - break; - case 3: /* reg E */ - DE = DE & 0xFF00; - DE = DE | val; - break; - case 4: /* reg H */ - HL = HL & BYTE_R; - HL = HL | (val <<8); - break; - case 5: /* reg L */ - HL = HL & 0xFF00; - HL = HL | val; - break; - case 6: /* reg M */ - put_mbyte(HL, val); - break; - case 7: /* reg A */ - A = val & BYTE_R; - default: - break; - } -} - -/* Return the value of a selected register pair */ -int32 getpair(int32 reg) -{ - switch (reg) { - case 0: /* reg BC */ - return (BC); - case 1: /* reg DE */ - return (DE); - case 2: /* reg HL */ - return (HL); - case 3: /* reg SP */ - return (SP); - default: - break; - } - return 0; -} - -/* Return the value of a selected register pair, in PUSH - format where 3 means A & flags, not SP */ -int32 getpush(int32 reg) -{ - int32 stat; - - switch (reg) { - case 0: /* reg BC */ - return (BC); - case 1: /* reg DE */ - return (DE); - case 2: /* reg HL */ - return (HL); - case 3: /* reg (A << 8) | PSW */ - stat = A << 8 | PSW; - return (stat); - default: - break; - } - return 0; -} - - -/* Place data into the indicated register pair, in PUSH - format where 3 means A& flags, not SP */ -void putpush(int32 reg, int32 data) -{ - switch (reg) { - case 0: /* reg BC */ - BC = data; - break; - case 1: /* reg DE */ - DE = data; - break; - case 2: /* reg HL */ - HL = data; - break; - case 3: /* reg (A << 8) | PSW */ - A = (data >> 8) & BYTE_R; - PSW = data & BYTE_R; - break; - default: - break; - } -} - - -/* Put a value into an 8080 register pair */ -void putpair(int32 reg, int32 val) -{ - switch (reg) { - case 0: /* reg BC */ - BC = val; - break; - case 1: /* reg DE */ - DE = val; - break; - case 2: /* reg HL */ - HL = val; - break; - case 3: /* reg SP */ - SP = val; - break; - default: - break; - } -} - -/* Reset routine */ - -t_stat i8080_reset (DEVICE *dptr) -{ - PSW = PSW_ALWAYS_ON; - CLR_FLAG(CF); - CLR_FLAG(ZF); - saved_PC = 0; - int_req = 0; - IM = 0; - sim_brk_types = sim_brk_dflt = SWMASK ('E'); - sim_printf(" 8080: Reset\n"); -// fpd = fopen("trace.txt", "w"); - return SCPE_OK; -} - -/* Memory examine */ - -t_stat i8080_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ - if (addr >= MEMSIZE) - return SCPE_NXM; - if (vptr != NULL) - *vptr = get_mbyte(addr); - return SCPE_OK; -} - -/* Memory deposit */ - -t_stat i8080_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ - if (addr >= MEMSIZE) - return SCPE_NXM; - put_mbyte(addr, val); - return SCPE_OK; -} - -/* This is the binary loader. The input file is considered to be - a string of literal bytes with no special format. The load - starts at the current value of the PC. -*/ - -int32 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 == &i8080_unit); - c1 = (val[0] >> 8) & 0x7F; - c2 = val[0] & 0x7F; - if (sw & SWMASK ('A')) { - fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2); - return SCPE_OK; - } - if (sw & SWMASK ('C')) { - fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); - fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2); - return SCPE_OK; - } - if (!(sw & SWMASK ('M'))) return SCPE_ARG; - inst = val[0]; - fprintf (of, "%s", opcode[inst]); - if (oplen[inst] == 2) { - if (strchr(opcode[inst], ' ') != NULL) - fprintf (of, ","); - else fprintf (of, " "); - fprintf (of, "%02X", 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, "%04X", 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 == &i8080_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 i8080.c */