diff --git a/AltairZ80/altairz80_cpu.c b/AltairZ80/altairz80_cpu.c deleted file mode 100644 index 9d7c6580..00000000 --- a/AltairZ80/altairz80_cpu.c +++ /dev/null @@ -1,6952 +0,0 @@ -/* altairz80_cpu.c: MITS Altair CPU (8080 and Z80) - - Copyright (c) 2002-2012, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license) -*/ - -#include "altairz80_defs.h" -#include -#define SWITCHCPU_DEFAULT 0xfd - -/* Debug flags */ -#define IN_MSG (1 << 0) -#define OUT_MSG (1 << 1) - -#if defined (_WIN32) -#include -#else -#include -#endif - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_SIZE_LOG2 6 /* log2 of PCQ_SIZE */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY(PC) if (pcq[pcq_p] != (PC)) { pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = (PC); } - -#define FLAG_C 1 -#define FLAG_N 2 -#define FLAG_P 4 -#define FLAG_H 16 -#define FLAG_Z 64 -#define FLAG_S 128 - -#define SETFLAG(f,c) AF = (c) ? AF | FLAG_ ## f : AF & ~FLAG_ ## f -#define TSTFLAG(f) ((AF & FLAG_ ## f) != 0) - -#define LOW_DIGIT(x) ((x) & 0xf) -#define HIGH_DIGIT(x) (((x) >> 4) & 0xf) -#define LOW_REGISTER(x) ((x) & 0xff) -#define HIGH_REGISTER(x) (((x) >> 8) & 0xff) - -#define SET_LOW_REGISTER(x, v) x = (((x) & 0xff00) | ((v) & 0xff)) -#define SET_HIGH_REGISTER(x, v) x = (((x) & 0xff) | (((v) & 0xff) << 8)) - -#define PARITY(x) parityTable[(x) & 0xff] -/* SET_PV and SET_PV2 are used to provide correct PARITY flag semantics for the 8080 in cases - where the Z80 uses the overflow flag -*/ -#define SET_PVS(s) ((chiptype == CHIP_TYPE_Z80) ? (((cbits >> 6) ^ (cbits >> 5)) & 4) : (PARITY(s))) -#define SET_PV (SET_PVS(sum)) -#define SET_PV2(x) ((chiptype == CHIP_TYPE_Z80) ? (((temp == (x)) << 2)) : (PARITY(temp))) - -/* CHECK_CPU_8080 must be invoked whenever a Z80 only instruction is executed - In case a Z80 instruction is executed on an 8080 the following two cases exist: - 1) Trapping is enabled: execution stops - 2) Trapping is not enabled: decoding continues with the next byte, i.e. interpret as NOP - Note: in some cases different instructions need to be chosen on 8080 -*/ -#define CHECK_CPU_8080 \ - if (chiptype == CHIP_TYPE_8080) { \ - if (cpu_unit.flags & UNIT_CPU_OPSTOP) { \ - reason = STOP_OPCODE; \ - goto end_decode; \ - } \ - else { \ - sim_brk_pend[0] = FALSE; \ - continue; \ - } \ - } - -/* CHECK_CPU_Z80 must be invoked whenever a non Z80 instruction is executed */ -#define CHECK_CPU_Z80 \ - if (cpu_unit.flags & UNIT_CPU_OPSTOP) { \ - reason = STOP_OPCODE; \ - goto end_decode; \ - } - -#define POP(x) { \ - register uint32 y = RAM_PP(SP); \ - x = y + (RAM_PP(SP) << 8); \ -} - -#define JPC(cond) { \ - tStates += 10; \ - if (cond) { \ - PCQ_ENTRY(PCX); \ - PC = GET_WORD(PC); \ - } \ - else { \ - PC += 2; \ - } \ -} - -#define CALLC(cond) { \ - if (cond) { \ - register uint32 adrr = GET_WORD(PC); \ - CHECK_BREAK_WORD(SP - 2); \ - PUSH(PC + 2); \ - PCQ_ENTRY(PCX); \ - PC = adrr; \ - tStates += 17; \ - } \ - else { \ - sim_brk_pend[0] = FALSE; \ - PC += 2; \ - tStates += (chiptype == CHIP_TYPE_8080 ? 11 : 10); \ - } \ -} - -extern int32 sim_int_char; -extern int32 sio0s (const int32 port, const int32 io, const int32 data); -extern int32 sio0d (const int32 port, const int32 io, const int32 data); -extern int32 sio1s (const int32 port, const int32 io, const int32 data); -extern int32 sio1d (const int32 port, const int32 io, const int32 data); -extern int32 dsk10 (const int32 port, const int32 io, const int32 data); -extern int32 dsk11 (const int32 port, const int32 io, const int32 data); -extern int32 dsk12 (const int32 port, const int32 io, const int32 data); -extern int32 netStatus (const int32 port, const int32 io, const int32 data); -extern int32 netData (const int32 port, const int32 io, const int32 data); -extern int32 nulldev (const int32 port, const int32 io, const int32 data); -extern int32 hdsk_io (const int32 port, const int32 io, const int32 data); -extern int32 simh_dev (const int32 port, const int32 io, const int32 data); -extern int32 sr_dev (const int32 port, const int32 io, const int32 data); -extern void install_ALTAIRbootROM(void); -extern void do_SIMH_sleep(void); -extern void prepareMemoryAccessMessage(const t_addr loc); -extern void prepareInstructionMessage(const t_addr loc, const uint32 op); - -extern FILE *sim_deb; - -extern t_stat sim_instr_nommu(void); -extern uint8 MOPT[MAXBANKSIZE]; -extern t_stat sim_instr_8086(void); -extern void cpu8086reset(void); - -/* function prototypes */ -static t_stat cpu_set_switcher (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_reset_switcher(UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_show_switcher (FILE *st, UNIT *uptr, int32 val, void *desc); -static int32 switchcpu_io (const int32 port, const int32 io, const int32 data); - -static t_stat cpu_set_altairrom (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_noaltairrom (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_nommu (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_banked (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_nonbanked (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_ramtype (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_chiptype (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_memory (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_clear_command (UNIT *uptr, int32 value, char *cptr, void *desc); -static void cpu_clear(void); -static t_stat cpu_show (FILE *st, UNIT *uptr, int32 val, void *desc); -static t_stat chip_show (FILE *st, UNIT *uptr, int32 val, void *desc); -static t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -static t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw); -static t_stat cpu_reset(DEVICE *dptr); -static t_stat sim_instr_mmu(void); -static uint32 GetBYTE(register uint32 Addr); -static void PutWORD(register uint32 Addr, const register uint32 Value); -static void PutBYTE(register uint32 Addr, const register uint32 Value); -void out(const uint32 Port, const uint32 Value); -uint32 in(const uint32 Port); -void altairz80_init(void); -t_stat sim_instr(void); -t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM); -uint8 GetBYTEWrapper(const uint32 Addr); -void PutBYTEWrapper(const uint32 Addr, const uint32 Value); -uint8 GetByteDMA(const uint32 Addr); -void PutByteDMA(const uint32 Addr, const uint32 Value); -int32 getBankSelect(void); -void setBankSelect(const int32 b); -uint32 getClockFrequency(void); -void setClockFrequency(const uint32 Value); -uint32 getCommon(void); -t_stat sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag); -uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); - -void PutBYTEExtended(register uint32 Addr, const register uint32 Value); -uint32 GetBYTEExtended(register uint32 Addr); -void cpu_raise_interrupt(uint32 irq); - -/* CPU data structures - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list -*/ - -UNIT cpu_unit = { - UDATA (NULL, UNIT_FIX | UNIT_BINK | UNIT_CPU_ALTAIRROM | - UNIT_CPU_STOPONHALT | UNIT_CPU_MMU, MAXBANKSIZE) -}; - - uint32 PCX = 0; /* external view of PC */ - int32 AF_S; /* AF register */ - int32 BC_S; /* BC register */ - int32 DE_S; /* DE register */ - int32 HL_S; /* HL register */ - int32 IX_S; /* IX register */ - int32 IY_S; /* IY register */ - int32 PC_S = 0; /* 8080 / Z80 program counter */ - int32 PCX_S = 0xFFFF0; /* 8086 program counter */ - int32 SP_S; /* SP register */ - int32 AF1_S; /* alternate AF register */ - int32 BC1_S; /* alternate BC register */ - int32 DE1_S; /* alternate DE register */ - int32 HL1_S; /* alternate HL register */ - int32 IFF_S; /* Interrupt Flip Flop */ - int32 IR_S; /* Interrupt (upper) / Refresh (lower) register */ - int32 AX_S; /* AX register (8086) */ - int32 BX_S; /* BX register (8086) */ - int32 CX_S; /* CX register (8086) */ - int32 DX_S; /* DX register (8086) */ - int32 CS_S; /* CS register (8086) */ - int32 DS_S; /* DS register (8086) */ - int32 ES_S; /* ES register (8086) */ - int32 SS_S; /* SS register (8086) */ - int32 DI_S; /* DI register (8086) */ - int32 SI_S; /* SI register (8086) */ - int32 BP_S; /* BP register (8086) */ - int32 SPX_S; /* SP register (8086) */ - int32 IP_S; /* IP register (8086) */ - int32 FLAGS_S; /* flags register (8086) */ - int32 SR = 0; /* switch register */ -static int32 bankSelect = 0; /* determines selected memory bank */ -static uint32 common = 0xc000; /* addresses >= 'common' are in common memory */ -static uint32 previousCapacity = MAXBANKSIZE; /* safe for previous memory capacity */ -static uint32 clockFrequency = 0; /* in kHz, 0 means as fast as possible */ -static uint32 sliceLength = 10; /* length of time-slice for CPU speed */ - /* adjustment in milliseconds */ -static uint32 executedTStates = 0; /* executed t-states */ -static uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -static int32 pcq_p = 0; /* PC queue ptr */ -static REG *pcq_r = NULL; /* PC queue reg ptr */ - -/* data structure for IN/OUT instructions */ -struct idev { - int32 (*routine)(const int32, const int32, const int32); -}; - -static int32 switcherPort = SWITCHCPU_DEFAULT; -static struct idev oldSwitcherDevice = { NULL }; - -REG cpu_reg[] = { - { HRDATA (AF, AF_S, 16) }, - { HRDATA (BC, BC_S, 16) }, - { HRDATA (DE, DE_S, 16) }, - { HRDATA (HL, HL_S, 16) }, - { HRDATA (IX, IX_S, 16) }, - { HRDATA (IY, IY_S, 16) }, - { HRDATA (PC, PC_S, 16 + MAXBANKSLOG2) }, /* 8080 / Z80 PC [6] */ - { HRDATA (PCX, PCX_S, 16 + MAXBANKSLOG2) }, /* 8086 PC [7] */ - { HRDATA (SP, SP_S, 16) }, - { HRDATA (AF1, AF1_S, 16) }, - { HRDATA (BC1, BC1_S, 16) }, - { HRDATA (DE1, DE1_S, 16) }, - { HRDATA (HL1, HL1_S, 16) }, - { GRDATA (IFF, IFF_S, 2, 2, 0) }, - { FLDATA (IR, IR_S, 8) }, - { HRDATA (AX, AX_S, 16) }, /* 8086 */ - { GRDATA (AL, AX_S, 16, 8, 0) }, /* 8086, low 8 bits of AX */ - { GRDATA (AH, AX_S, 16, 8, 8) }, /* 8086, high 8 bits of AX */ - { HRDATA (BX, BX_S, 16) }, /* 8086 */ - { GRDATA (BL, BX_S, 16, 8, 0) }, /* 8086, low 8 bits of BX */ - { GRDATA (BH, BX_S, 16, 8, 8) }, /* 8086, high 8 bits of BX */ - { HRDATA (CX, CX_S, 16) }, /* 8086 */ - { GRDATA (CL, CX_S, 16, 8, 0) }, /* 8086, low 8 bits of CX */ - { GRDATA (CH, CX_S, 16, 8, 8) }, /* 8086, high 8 bits of CX */ - { HRDATA (DX, DX_S, 16) }, /* 8086 */ - { GRDATA (DL, DX_S, 16, 8, 0) }, /* 8086, low 8 bits of DX */ - { GRDATA (DH, DX_S, 16, 8, 8) }, /* 8086, high 8 bits of DX */ - { HRDATA (SPX, SPX_S, 16) }, /* 8086 */ - { HRDATA (BP, BP_S, 16) }, /* 8086, Base Pointer */ - { HRDATA (SI, SI_S, 16) }, /* 8086, Source Index */ - { HRDATA (DI, DI_S, 16) }, /* 8086, Destination Index */ - { HRDATA (CS, CS_S, 16) }, /* 8086, Code Segment */ - { HRDATA (DS, DS_S, 16) }, /* 8086, Data Segment */ - { HRDATA (ES, ES_S, 16) }, /* 8086, Extra Segment */ - { HRDATA (SS, SS_S, 16) }, /* 8086, Stack Segment */ - { HRDATA (FLAGS, FLAGS_S, 16) }, /* 8086, FLAGS */ - { HRDATA (IP, IP_S, 16), REG_RO }, /* 8086, set via PC */ - { FLDATA (OPSTOP, cpu_unit.flags, UNIT_CPU_V_OPSTOP), REG_HRO }, - { HRDATA (SR, SR, 8) }, - { HRDATA (BANK, bankSelect, MAXBANKSLOG2) }, - { HRDATA (COMMON, common, 32) }, - { HRDATA (SWITCHERPORT, switcherPort, 8), }, - { DRDATA (CLOCK, clockFrequency, 32) }, - { DRDATA (SLICE, sliceLength, 16) }, - { DRDATA (TSTATES, executedTStates, 32), REG_RO }, - { HRDATA (CAPACITY, cpu_unit.capac, 32), REG_RO }, - { HRDATA (PREVCAP, previousCapacity, 32), REG_RO }, - { BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO + REG_CIRC }, - { DRDATA (PCQP, pcq_p, PCQ_SIZE_LOG2), REG_HRO }, - { HRDATA (WRU, sim_int_char, 8) }, - { NULL } -}; - -static MTAB cpu_mod[] = { - { MTAB_XTD | MTAB_VDV, CHIP_TYPE_8080, NULL, "8080", &cpu_set_chiptype }, - { MTAB_XTD | MTAB_VDV, CHIP_TYPE_Z80, NULL, "Z80", &cpu_set_chiptype }, - { MTAB_XTD | MTAB_VDV, CHIP_TYPE_8086, NULL, "8086", &cpu_set_chiptype }, - { UNIT_CPU_OPSTOP, UNIT_CPU_OPSTOP, "ITRAP", "ITRAP", NULL, &chip_show }, - { UNIT_CPU_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL, &chip_show }, - { UNIT_CPU_STOPONHALT, UNIT_CPU_STOPONHALT,"STOPONHALT", "STOPONHALT", NULL }, - { UNIT_CPU_STOPONHALT, 0, "LOOPONHALT", "LOOPONHALT", NULL }, - { UNIT_CPU_BANKED, UNIT_CPU_BANKED, "BANKED", "BANKED", &cpu_set_banked }, - { UNIT_CPU_BANKED, 0, "NONBANKED", "NONBANKED", &cpu_set_nonbanked }, - { UNIT_CPU_ALTAIRROM, UNIT_CPU_ALTAIRROM, "ALTAIRROM", "ALTAIRROM", &cpu_set_altairrom }, - { UNIT_CPU_ALTAIRROM, 0, "NOALTAIRROM", "NOALTAIRROM", &cpu_set_noaltairrom}, - { UNIT_CPU_VERBOSE, UNIT_CPU_VERBOSE, "VERBOSE", "VERBOSE", NULL, &cpu_show }, - { UNIT_CPU_VERBOSE, 0, "QUIET", "QUIET", NULL }, - { MTAB_VDV, 0, NULL, "CLEARMEMORY", &cpu_clear_command }, - { UNIT_CPU_MMU, UNIT_CPU_MMU, "MMU", "MMU", NULL }, - { UNIT_CPU_MMU, 0, "NOMMU", "NOMMU", &cpu_set_nommu }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "MEMORY", &cpu_set_memory }, - { UNIT_CPU_SWITCHER, UNIT_CPU_SWITCHER, "SWITCHER", "SWITCHER", &cpu_set_switcher, &cpu_show_switcher }, - { UNIT_CPU_SWITCHER, 0, "NOSWITCHER", "NOSWITCHER", &cpu_reset_switcher, &cpu_show_switcher }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "AZ80", &cpu_set_ramtype }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "HRAM", &cpu_set_ramtype }, - { MTAB_XTD | MTAB_VDV, 2, NULL, "VRAM", &cpu_set_ramtype }, - { MTAB_XTD | MTAB_VDV, 3, NULL, "CRAM", &cpu_set_ramtype }, - { MTAB_VDV, 4, NULL, "4KB", &cpu_set_size }, - { MTAB_VDV, 8, NULL, "8KB", &cpu_set_size }, - { MTAB_VDV, 12, NULL, "12KB", &cpu_set_size }, - { MTAB_VDV, 16, NULL, "16KB", &cpu_set_size }, - { MTAB_VDV, 20, NULL, "20KB", &cpu_set_size }, - { MTAB_VDV, 24, NULL, "24KB", &cpu_set_size }, - { MTAB_VDV, 28, NULL, "28KB", &cpu_set_size }, - { MTAB_VDV, 32, NULL, "32KB", &cpu_set_size }, - { MTAB_VDV, 36, NULL, "36KB", &cpu_set_size }, - { MTAB_VDV, 40, NULL, "40KB", &cpu_set_size }, - { MTAB_VDV, 44, NULL, "44KB", &cpu_set_size }, - { MTAB_VDV, 48, NULL, "48KB", &cpu_set_size }, - { MTAB_VDV, 52, NULL, "52KB", &cpu_set_size }, - { MTAB_VDV, 56, NULL, "56KB", &cpu_set_size }, - { MTAB_VDV, 60, NULL, "60KB", &cpu_set_size }, - { MTAB_VDV, 64, NULL, "64KB", &cpu_set_size }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB cpu_dt[] = { - { "LOG_IN", IN_MSG }, - { "LOG_OUT", OUT_MSG }, - { NULL, 0 } -}; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 16, 1, 16, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, - NULL, DEV_DEBUG, 0, - cpu_dt, NULL, NULL -}; - -/* This is the I/O configuration table. There are 255 possible - device addresses, if a device is plugged to a port it's routine - address is here, 'nulldev' means no device is available -*/ -static struct idev dev_table[256] = { - {&nulldev}, {&nulldev}, {&sio0d}, {&sio0s}, /* 00 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 04 */ - {&dsk10}, {&dsk11}, {&dsk12}, {&nulldev}, /* 08 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C */ - {&sio0s}, {&sio0d}, {&sio1s}, {&sio1d}, /* 10 */ - {&sio0s}, {&sio0d}, {&sio0s}, {&sio0d}, /* 14 */ - {&sio0s}, {&sio0d}, {&nulldev}, {&nulldev}, /* 18 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 20 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 24 */ - {&netStatus},{&netData},{&netStatus},{&netData}, /* 28 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C */ - {&nulldev}, {&nulldev}, {&netStatus},{&netData}, /* 30 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 34 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 38 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 40 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 44 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 48 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 4C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 50 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 54 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 58 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 5C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 60 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 64 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 68 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 6C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 70 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 74 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 78 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 7C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 80 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 84 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 88 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 8C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 90 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 94 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 98 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 9C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* AC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* BC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* CC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* DC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* EC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F8 */ - {&nulldev}, {&hdsk_io}, {&simh_dev}, {&sr_dev} /* FC */ -}; - -static int32 ramtype = 0; -#define MAX_RAM_TYPE 3 - -int32 chiptype = CHIP_TYPE_8080; - -void out(const uint32 Port, const uint32 Value) { - if ((cpu_dev.dctrl & OUT_MSG) && sim_deb) { - fprintf(sim_deb, "CPU: " ADDRESS_FORMAT - " OUT(port=0x%04x [%5d], value=0x%04x [%5d])\n", PCX, Port, Port, Value, Value); - fflush(sim_deb); - } - dev_table[Port & 0xff].routine(Port, 1, Value); - if ((cpu_dev.dctrl & OUT_MSG) && sim_deb) { - fprintf(sim_deb, "CPU: " ADDRESS_FORMAT - " OUT(port=0x%04x [%5d], value=0x%04x [%5d]) done\n", PCX, Port, Port, Value, Value); - fflush(sim_deb); - } -} - -uint32 in(const uint32 Port) { - uint32 result; - if ((cpu_dev.dctrl & IN_MSG) && sim_deb) { - fprintf(sim_deb, "CPU: " ADDRESS_FORMAT - " IN(port=0x%04x [%5d])\n", PCX, Port, Port); - fflush(sim_deb); - } - result = dev_table[Port & 0xff].routine(Port, 0, 0); - if ((cpu_dev.dctrl & IN_MSG) && sim_deb) { - fprintf(sim_deb, "CPU: " ADDRESS_FORMAT - " IN(port=0x%04x [%5d]) = 0x%04x [%5d]\n", PCX, Port, Port, result, result); - fflush(sim_deb); - } - return result; -} - -/* the following tables precompute some common subexpressions - parityTable[i] 0..255 (number of 1's in i is odd) ? 0 : 4 - incTable[i] 0..256! (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0) << 4) - decTable[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0xf) << 4) | 2 - cbitsTable[i] 0..511 (i & 0x10) | ((i >> 8) & 1) - cbitsDup8Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | ((i & 0xff) << 8) | (i & 0xa8) | - (((i & 0xff) == 0) << 6) - cbitsDup16Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | (i & 0x28) - cbits2Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | 2 - rrcaTable[i] 0..255 ((i & 1) << 15) | ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1) - rraTable[i] 0..255 ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1) - addTable[i] 0..511 ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) - subTable[i] 0..255 ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | 2 - andTable[i] 0..255 (i << 8) | (i & 0xa8) | ((i == 0) << 6) | 0x10 | parityTable[i] - xororTable[i] 0..255 (i << 8) | (i & 0xa8) | ((i == 0) << 6) | parityTable[i] - rotateShiftTable[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i & 0xff] - incZ80Table[i] 0..256! (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0) << 4) | ((i == 0x80) << 2) - decZ80Table[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0xf) << 4) | ((i == 0x7f) << 2) | 2 - cbitsZ80Table[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) - cbitsZ80DupTable[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | - ((i >> 8) & 1) | (i & 0xa8) - cbits2Z80Table[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 - cbits2Z80DupTable[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 | - (i & 0xa8) - negTable[i] 0..255 (((i & 0x0f) != 0) << 4) | ((i == 0x80) << 2) | 2 | (i != 0) - rrdrldTable[i] 0..255 (i << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i] - cpTable[i] 0..255 (i & 0x80) | (((i & 0xff) == 0) << 6) -*/ - -/* parityTable[i] = (number of 1's in i is odd) ? 0 : 4, i = 0..255 */ -static const uint8 parityTable[256] = { - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, -}; - -/* incTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0) << 4), i = 0..256 */ -static const uint8 incTable[257] = { - 80, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 80 -}; - -/* decTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0xf) << 4) | 2, i = 0..255 */ -static const uint8 decTable[256] = { - 66, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, -}; - -/* cbitsTable[i] = (i & 0x10) | ((i >> 8) & 1), i = 0..511 */ -static const uint8 cbitsTable[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, -}; - -/* cbitsDup8Table[i] = (i & 0x10) | ((i >> 8) & 1) | ((i & 0xff) << 8) | (i & 0xa8) | - (((i & 0xff) == 0) << 6), i = 0..511 */ -static const uint16 cbitsDup8Table[512] = { - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710, - 0x1818,0x1918,0x1a18,0x1b18,0x1c18,0x1d18,0x1e18,0x1f18, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,0x3630,0x3730, - 0x3838,0x3938,0x3a38,0x3b38,0x3c38,0x3d38,0x3e38,0x3f38, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710, - 0x5818,0x5918,0x5a18,0x5b18,0x5c18,0x5d18,0x5e18,0x5f18, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7030,0x7130,0x7230,0x7330,0x7430,0x7530,0x7630,0x7730, - 0x7838,0x7938,0x7a38,0x7b38,0x7c38,0x7d38,0x7e38,0x7f38, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9090,0x9190,0x9290,0x9390,0x9490,0x9590,0x9690,0x9790, - 0x9898,0x9998,0x9a98,0x9b98,0x9c98,0x9d98,0x9e98,0x9f98, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0b0,0xb1b0,0xb2b0,0xb3b0,0xb4b0,0xb5b0,0xb6b0,0xb7b0, - 0xb8b8,0xb9b8,0xbab8,0xbbb8,0xbcb8,0xbdb8,0xbeb8,0xbfb8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd090,0xd190,0xd290,0xd390,0xd490,0xd590,0xd690,0xd790, - 0xd898,0xd998,0xda98,0xdb98,0xdc98,0xdd98,0xde98,0xdf98, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0b0,0xf1b0,0xf2b0,0xf3b0,0xf4b0,0xf5b0,0xf6b0,0xf7b0, - 0xf8b8,0xf9b8,0xfab8,0xfbb8,0xfcb8,0xfdb8,0xfeb8,0xffb8, - 0x0041,0x0101,0x0201,0x0301,0x0401,0x0501,0x0601,0x0701, - 0x0809,0x0909,0x0a09,0x0b09,0x0c09,0x0d09,0x0e09,0x0f09, - 0x1011,0x1111,0x1211,0x1311,0x1411,0x1511,0x1611,0x1711, - 0x1819,0x1919,0x1a19,0x1b19,0x1c19,0x1d19,0x1e19,0x1f19, - 0x2021,0x2121,0x2221,0x2321,0x2421,0x2521,0x2621,0x2721, - 0x2829,0x2929,0x2a29,0x2b29,0x2c29,0x2d29,0x2e29,0x2f29, - 0x3031,0x3131,0x3231,0x3331,0x3431,0x3531,0x3631,0x3731, - 0x3839,0x3939,0x3a39,0x3b39,0x3c39,0x3d39,0x3e39,0x3f39, - 0x4001,0x4101,0x4201,0x4301,0x4401,0x4501,0x4601,0x4701, - 0x4809,0x4909,0x4a09,0x4b09,0x4c09,0x4d09,0x4e09,0x4f09, - 0x5011,0x5111,0x5211,0x5311,0x5411,0x5511,0x5611,0x5711, - 0x5819,0x5919,0x5a19,0x5b19,0x5c19,0x5d19,0x5e19,0x5f19, - 0x6021,0x6121,0x6221,0x6321,0x6421,0x6521,0x6621,0x6721, - 0x6829,0x6929,0x6a29,0x6b29,0x6c29,0x6d29,0x6e29,0x6f29, - 0x7031,0x7131,0x7231,0x7331,0x7431,0x7531,0x7631,0x7731, - 0x7839,0x7939,0x7a39,0x7b39,0x7c39,0x7d39,0x7e39,0x7f39, - 0x8081,0x8181,0x8281,0x8381,0x8481,0x8581,0x8681,0x8781, - 0x8889,0x8989,0x8a89,0x8b89,0x8c89,0x8d89,0x8e89,0x8f89, - 0x9091,0x9191,0x9291,0x9391,0x9491,0x9591,0x9691,0x9791, - 0x9899,0x9999,0x9a99,0x9b99,0x9c99,0x9d99,0x9e99,0x9f99, - 0xa0a1,0xa1a1,0xa2a1,0xa3a1,0xa4a1,0xa5a1,0xa6a1,0xa7a1, - 0xa8a9,0xa9a9,0xaaa9,0xaba9,0xaca9,0xada9,0xaea9,0xafa9, - 0xb0b1,0xb1b1,0xb2b1,0xb3b1,0xb4b1,0xb5b1,0xb6b1,0xb7b1, - 0xb8b9,0xb9b9,0xbab9,0xbbb9,0xbcb9,0xbdb9,0xbeb9,0xbfb9, - 0xc081,0xc181,0xc281,0xc381,0xc481,0xc581,0xc681,0xc781, - 0xc889,0xc989,0xca89,0xcb89,0xcc89,0xcd89,0xce89,0xcf89, - 0xd091,0xd191,0xd291,0xd391,0xd491,0xd591,0xd691,0xd791, - 0xd899,0xd999,0xda99,0xdb99,0xdc99,0xdd99,0xde99,0xdf99, - 0xe0a1,0xe1a1,0xe2a1,0xe3a1,0xe4a1,0xe5a1,0xe6a1,0xe7a1, - 0xe8a9,0xe9a9,0xeaa9,0xeba9,0xeca9,0xeda9,0xeea9,0xefa9, - 0xf0b1,0xf1b1,0xf2b1,0xf3b1,0xf4b1,0xf5b1,0xf6b1,0xf7b1, - 0xf8b9,0xf9b9,0xfab9,0xfbb9,0xfcb9,0xfdb9,0xfeb9,0xffb9, -}; - -/* cbitsDup16Table[i] = (i & 0x10) | ((i >> 8) & 1) | (i & 0x28), i = 0..511 */ -static const uint8 cbitsDup16Table[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, -}; - -/* cbits2Table[i] = (i & 0x10) | ((i >> 8) & 1) | 2, i = 0..511 */ -static const uint8 cbits2Table[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* rrcaTable[i] = ((i & 1) << 15) | ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1), i = 0..255 */ -static const uint16 rrcaTable[256] = { - 0x0000,0x8001,0x0100,0x8101,0x0200,0x8201,0x0300,0x8301, - 0x0400,0x8401,0x0500,0x8501,0x0600,0x8601,0x0700,0x8701, - 0x0808,0x8809,0x0908,0x8909,0x0a08,0x8a09,0x0b08,0x8b09, - 0x0c08,0x8c09,0x0d08,0x8d09,0x0e08,0x8e09,0x0f08,0x8f09, - 0x1000,0x9001,0x1100,0x9101,0x1200,0x9201,0x1300,0x9301, - 0x1400,0x9401,0x1500,0x9501,0x1600,0x9601,0x1700,0x9701, - 0x1808,0x9809,0x1908,0x9909,0x1a08,0x9a09,0x1b08,0x9b09, - 0x1c08,0x9c09,0x1d08,0x9d09,0x1e08,0x9e09,0x1f08,0x9f09, - 0x2020,0xa021,0x2120,0xa121,0x2220,0xa221,0x2320,0xa321, - 0x2420,0xa421,0x2520,0xa521,0x2620,0xa621,0x2720,0xa721, - 0x2828,0xa829,0x2928,0xa929,0x2a28,0xaa29,0x2b28,0xab29, - 0x2c28,0xac29,0x2d28,0xad29,0x2e28,0xae29,0x2f28,0xaf29, - 0x3020,0xb021,0x3120,0xb121,0x3220,0xb221,0x3320,0xb321, - 0x3420,0xb421,0x3520,0xb521,0x3620,0xb621,0x3720,0xb721, - 0x3828,0xb829,0x3928,0xb929,0x3a28,0xba29,0x3b28,0xbb29, - 0x3c28,0xbc29,0x3d28,0xbd29,0x3e28,0xbe29,0x3f28,0xbf29, - 0x4000,0xc001,0x4100,0xc101,0x4200,0xc201,0x4300,0xc301, - 0x4400,0xc401,0x4500,0xc501,0x4600,0xc601,0x4700,0xc701, - 0x4808,0xc809,0x4908,0xc909,0x4a08,0xca09,0x4b08,0xcb09, - 0x4c08,0xcc09,0x4d08,0xcd09,0x4e08,0xce09,0x4f08,0xcf09, - 0x5000,0xd001,0x5100,0xd101,0x5200,0xd201,0x5300,0xd301, - 0x5400,0xd401,0x5500,0xd501,0x5600,0xd601,0x5700,0xd701, - 0x5808,0xd809,0x5908,0xd909,0x5a08,0xda09,0x5b08,0xdb09, - 0x5c08,0xdc09,0x5d08,0xdd09,0x5e08,0xde09,0x5f08,0xdf09, - 0x6020,0xe021,0x6120,0xe121,0x6220,0xe221,0x6320,0xe321, - 0x6420,0xe421,0x6520,0xe521,0x6620,0xe621,0x6720,0xe721, - 0x6828,0xe829,0x6928,0xe929,0x6a28,0xea29,0x6b28,0xeb29, - 0x6c28,0xec29,0x6d28,0xed29,0x6e28,0xee29,0x6f28,0xef29, - 0x7020,0xf021,0x7120,0xf121,0x7220,0xf221,0x7320,0xf321, - 0x7420,0xf421,0x7520,0xf521,0x7620,0xf621,0x7720,0xf721, - 0x7828,0xf829,0x7928,0xf929,0x7a28,0xfa29,0x7b28,0xfb29, - 0x7c28,0xfc29,0x7d28,0xfd29,0x7e28,0xfe29,0x7f28,0xff29, -}; - -/* rraTable[i] = ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1), i = 0..255 */ -static const uint16 rraTable[256] = { - 0x0000,0x0001,0x0100,0x0101,0x0200,0x0201,0x0300,0x0301, - 0x0400,0x0401,0x0500,0x0501,0x0600,0x0601,0x0700,0x0701, - 0x0808,0x0809,0x0908,0x0909,0x0a08,0x0a09,0x0b08,0x0b09, - 0x0c08,0x0c09,0x0d08,0x0d09,0x0e08,0x0e09,0x0f08,0x0f09, - 0x1000,0x1001,0x1100,0x1101,0x1200,0x1201,0x1300,0x1301, - 0x1400,0x1401,0x1500,0x1501,0x1600,0x1601,0x1700,0x1701, - 0x1808,0x1809,0x1908,0x1909,0x1a08,0x1a09,0x1b08,0x1b09, - 0x1c08,0x1c09,0x1d08,0x1d09,0x1e08,0x1e09,0x1f08,0x1f09, - 0x2020,0x2021,0x2120,0x2121,0x2220,0x2221,0x2320,0x2321, - 0x2420,0x2421,0x2520,0x2521,0x2620,0x2621,0x2720,0x2721, - 0x2828,0x2829,0x2928,0x2929,0x2a28,0x2a29,0x2b28,0x2b29, - 0x2c28,0x2c29,0x2d28,0x2d29,0x2e28,0x2e29,0x2f28,0x2f29, - 0x3020,0x3021,0x3120,0x3121,0x3220,0x3221,0x3320,0x3321, - 0x3420,0x3421,0x3520,0x3521,0x3620,0x3621,0x3720,0x3721, - 0x3828,0x3829,0x3928,0x3929,0x3a28,0x3a29,0x3b28,0x3b29, - 0x3c28,0x3c29,0x3d28,0x3d29,0x3e28,0x3e29,0x3f28,0x3f29, - 0x4000,0x4001,0x4100,0x4101,0x4200,0x4201,0x4300,0x4301, - 0x4400,0x4401,0x4500,0x4501,0x4600,0x4601,0x4700,0x4701, - 0x4808,0x4809,0x4908,0x4909,0x4a08,0x4a09,0x4b08,0x4b09, - 0x4c08,0x4c09,0x4d08,0x4d09,0x4e08,0x4e09,0x4f08,0x4f09, - 0x5000,0x5001,0x5100,0x5101,0x5200,0x5201,0x5300,0x5301, - 0x5400,0x5401,0x5500,0x5501,0x5600,0x5601,0x5700,0x5701, - 0x5808,0x5809,0x5908,0x5909,0x5a08,0x5a09,0x5b08,0x5b09, - 0x5c08,0x5c09,0x5d08,0x5d09,0x5e08,0x5e09,0x5f08,0x5f09, - 0x6020,0x6021,0x6120,0x6121,0x6220,0x6221,0x6320,0x6321, - 0x6420,0x6421,0x6520,0x6521,0x6620,0x6621,0x6720,0x6721, - 0x6828,0x6829,0x6928,0x6929,0x6a28,0x6a29,0x6b28,0x6b29, - 0x6c28,0x6c29,0x6d28,0x6d29,0x6e28,0x6e29,0x6f28,0x6f29, - 0x7020,0x7021,0x7120,0x7121,0x7220,0x7221,0x7320,0x7321, - 0x7420,0x7421,0x7520,0x7521,0x7620,0x7621,0x7720,0x7721, - 0x7828,0x7829,0x7928,0x7929,0x7a28,0x7a29,0x7b28,0x7b29, - 0x7c28,0x7c29,0x7d28,0x7d29,0x7e28,0x7e29,0x7f28,0x7f29, -}; - -/* addTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6), i = 0..511 */ -static const uint16 addTable[512] = { - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, - 0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720, - 0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, - 0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720, - 0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780, - 0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0, - 0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780, - 0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0, - 0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8, - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, - 0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720, - 0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, - 0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720, - 0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780, - 0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0, - 0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780, - 0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0, - 0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8, -}; - -/* subTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | 2, i = 0..255 */ -static const uint16 subTable[256] = { - 0x0042,0x0102,0x0202,0x0302,0x0402,0x0502,0x0602,0x0702, - 0x080a,0x090a,0x0a0a,0x0b0a,0x0c0a,0x0d0a,0x0e0a,0x0f0a, - 0x1002,0x1102,0x1202,0x1302,0x1402,0x1502,0x1602,0x1702, - 0x180a,0x190a,0x1a0a,0x1b0a,0x1c0a,0x1d0a,0x1e0a,0x1f0a, - 0x2022,0x2122,0x2222,0x2322,0x2422,0x2522,0x2622,0x2722, - 0x282a,0x292a,0x2a2a,0x2b2a,0x2c2a,0x2d2a,0x2e2a,0x2f2a, - 0x3022,0x3122,0x3222,0x3322,0x3422,0x3522,0x3622,0x3722, - 0x382a,0x392a,0x3a2a,0x3b2a,0x3c2a,0x3d2a,0x3e2a,0x3f2a, - 0x4002,0x4102,0x4202,0x4302,0x4402,0x4502,0x4602,0x4702, - 0x480a,0x490a,0x4a0a,0x4b0a,0x4c0a,0x4d0a,0x4e0a,0x4f0a, - 0x5002,0x5102,0x5202,0x5302,0x5402,0x5502,0x5602,0x5702, - 0x580a,0x590a,0x5a0a,0x5b0a,0x5c0a,0x5d0a,0x5e0a,0x5f0a, - 0x6022,0x6122,0x6222,0x6322,0x6422,0x6522,0x6622,0x6722, - 0x682a,0x692a,0x6a2a,0x6b2a,0x6c2a,0x6d2a,0x6e2a,0x6f2a, - 0x7022,0x7122,0x7222,0x7322,0x7422,0x7522,0x7622,0x7722, - 0x782a,0x792a,0x7a2a,0x7b2a,0x7c2a,0x7d2a,0x7e2a,0x7f2a, - 0x8082,0x8182,0x8282,0x8382,0x8482,0x8582,0x8682,0x8782, - 0x888a,0x898a,0x8a8a,0x8b8a,0x8c8a,0x8d8a,0x8e8a,0x8f8a, - 0x9082,0x9182,0x9282,0x9382,0x9482,0x9582,0x9682,0x9782, - 0x988a,0x998a,0x9a8a,0x9b8a,0x9c8a,0x9d8a,0x9e8a,0x9f8a, - 0xa0a2,0xa1a2,0xa2a2,0xa3a2,0xa4a2,0xa5a2,0xa6a2,0xa7a2, - 0xa8aa,0xa9aa,0xaaaa,0xabaa,0xacaa,0xadaa,0xaeaa,0xafaa, - 0xb0a2,0xb1a2,0xb2a2,0xb3a2,0xb4a2,0xb5a2,0xb6a2,0xb7a2, - 0xb8aa,0xb9aa,0xbaaa,0xbbaa,0xbcaa,0xbdaa,0xbeaa,0xbfaa, - 0xc082,0xc182,0xc282,0xc382,0xc482,0xc582,0xc682,0xc782, - 0xc88a,0xc98a,0xca8a,0xcb8a,0xcc8a,0xcd8a,0xce8a,0xcf8a, - 0xd082,0xd182,0xd282,0xd382,0xd482,0xd582,0xd682,0xd782, - 0xd88a,0xd98a,0xda8a,0xdb8a,0xdc8a,0xdd8a,0xde8a,0xdf8a, - 0xe0a2,0xe1a2,0xe2a2,0xe3a2,0xe4a2,0xe5a2,0xe6a2,0xe7a2, - 0xe8aa,0xe9aa,0xeaaa,0xebaa,0xecaa,0xedaa,0xeeaa,0xefaa, - 0xf0a2,0xf1a2,0xf2a2,0xf3a2,0xf4a2,0xf5a2,0xf6a2,0xf7a2, - 0xf8aa,0xf9aa,0xfaaa,0xfbaa,0xfcaa,0xfdaa,0xfeaa,0xffaa, -}; - -/* andTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | 0x10 | parityTable[i], i = 0..255 */ -static const uint16 andTable[256] = { - 0x0054,0x0110,0x0210,0x0314,0x0410,0x0514,0x0614,0x0710, - 0x0818,0x091c,0x0a1c,0x0b18,0x0c1c,0x0d18,0x0e18,0x0f1c, - 0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,0x1610,0x1714, - 0x181c,0x1918,0x1a18,0x1b1c,0x1c18,0x1d1c,0x1e1c,0x1f18, - 0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,0x2630,0x2734, - 0x283c,0x2938,0x2a38,0x2b3c,0x2c38,0x2d3c,0x2e3c,0x2f38, - 0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,0x3634,0x3730, - 0x3838,0x393c,0x3a3c,0x3b38,0x3c3c,0x3d38,0x3e38,0x3f3c, - 0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,0x4610,0x4714, - 0x481c,0x4918,0x4a18,0x4b1c,0x4c18,0x4d1c,0x4e1c,0x4f18, - 0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,0x5614,0x5710, - 0x5818,0x591c,0x5a1c,0x5b18,0x5c1c,0x5d18,0x5e18,0x5f1c, - 0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,0x6634,0x6730, - 0x6838,0x693c,0x6a3c,0x6b38,0x6c3c,0x6d38,0x6e38,0x6f3c, - 0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,0x7630,0x7734, - 0x783c,0x7938,0x7a38,0x7b3c,0x7c38,0x7d3c,0x7e3c,0x7f38, - 0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,0x8690,0x8794, - 0x889c,0x8998,0x8a98,0x8b9c,0x8c98,0x8d9c,0x8e9c,0x8f98, - 0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,0x9694,0x9790, - 0x9898,0x999c,0x9a9c,0x9b98,0x9c9c,0x9d98,0x9e98,0x9f9c, - 0xa0b4,0xa1b0,0xa2b0,0xa3b4,0xa4b0,0xa5b4,0xa6b4,0xa7b0, - 0xa8b8,0xa9bc,0xaabc,0xabb8,0xacbc,0xadb8,0xaeb8,0xafbc, - 0xb0b0,0xb1b4,0xb2b4,0xb3b0,0xb4b4,0xb5b0,0xb6b0,0xb7b4, - 0xb8bc,0xb9b8,0xbab8,0xbbbc,0xbcb8,0xbdbc,0xbebc,0xbfb8, - 0xc094,0xc190,0xc290,0xc394,0xc490,0xc594,0xc694,0xc790, - 0xc898,0xc99c,0xca9c,0xcb98,0xcc9c,0xcd98,0xce98,0xcf9c, - 0xd090,0xd194,0xd294,0xd390,0xd494,0xd590,0xd690,0xd794, - 0xd89c,0xd998,0xda98,0xdb9c,0xdc98,0xdd9c,0xde9c,0xdf98, - 0xe0b0,0xe1b4,0xe2b4,0xe3b0,0xe4b4,0xe5b0,0xe6b0,0xe7b4, - 0xe8bc,0xe9b8,0xeab8,0xebbc,0xecb8,0xedbc,0xeebc,0xefb8, - 0xf0b4,0xf1b0,0xf2b0,0xf3b4,0xf4b0,0xf5b4,0xf6b4,0xf7b0, - 0xf8b8,0xf9bc,0xfabc,0xfbb8,0xfcbc,0xfdb8,0xfeb8,0xffbc, -}; - -/* xororTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | parityTable[i], i = 0..255 */ -static const uint16 xororTable[256] = { - 0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700, - 0x0808,0x090c,0x0a0c,0x0b08,0x0c0c,0x0d08,0x0e08,0x0f0c, - 0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704, - 0x180c,0x1908,0x1a08,0x1b0c,0x1c08,0x1d0c,0x1e0c,0x1f08, - 0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724, - 0x282c,0x2928,0x2a28,0x2b2c,0x2c28,0x2d2c,0x2e2c,0x2f28, - 0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720, - 0x3828,0x392c,0x3a2c,0x3b28,0x3c2c,0x3d28,0x3e28,0x3f2c, - 0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704, - 0x480c,0x4908,0x4a08,0x4b0c,0x4c08,0x4d0c,0x4e0c,0x4f08, - 0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700, - 0x5808,0x590c,0x5a0c,0x5b08,0x5c0c,0x5d08,0x5e08,0x5f0c, - 0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720, - 0x6828,0x692c,0x6a2c,0x6b28,0x6c2c,0x6d28,0x6e28,0x6f2c, - 0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724, - 0x782c,0x7928,0x7a28,0x7b2c,0x7c28,0x7d2c,0x7e2c,0x7f28, - 0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784, - 0x888c,0x8988,0x8a88,0x8b8c,0x8c88,0x8d8c,0x8e8c,0x8f88, - 0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780, - 0x9888,0x998c,0x9a8c,0x9b88,0x9c8c,0x9d88,0x9e88,0x9f8c, - 0xa0a4,0xa1a0,0xa2a0,0xa3a4,0xa4a0,0xa5a4,0xa6a4,0xa7a0, - 0xa8a8,0xa9ac,0xaaac,0xaba8,0xacac,0xada8,0xaea8,0xafac, - 0xb0a0,0xb1a4,0xb2a4,0xb3a0,0xb4a4,0xb5a0,0xb6a0,0xb7a4, - 0xb8ac,0xb9a8,0xbaa8,0xbbac,0xbca8,0xbdac,0xbeac,0xbfa8, - 0xc084,0xc180,0xc280,0xc384,0xc480,0xc584,0xc684,0xc780, - 0xc888,0xc98c,0xca8c,0xcb88,0xcc8c,0xcd88,0xce88,0xcf8c, - 0xd080,0xd184,0xd284,0xd380,0xd484,0xd580,0xd680,0xd784, - 0xd88c,0xd988,0xda88,0xdb8c,0xdc88,0xdd8c,0xde8c,0xdf88, - 0xe0a0,0xe1a4,0xe2a4,0xe3a0,0xe4a4,0xe5a0,0xe6a0,0xe7a4, - 0xe8ac,0xe9a8,0xeaa8,0xebac,0xeca8,0xedac,0xeeac,0xefa8, - 0xf0a4,0xf1a0,0xf2a0,0xf3a4,0xf4a0,0xf5a4,0xf6a4,0xf7a0, - 0xf8a8,0xf9ac,0xfaac,0xfba8,0xfcac,0xfda8,0xfea8,0xffac, -}; - -/* rotateShiftTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i & 0xff], i = 0..255 */ -static const uint8 rotateShiftTable[256] = { - 68, 0, 0, 4, 0, 4, 4, 0, 8, 12, 12, 8, 12, 8, 8, 12, - 0, 4, 4, 0, 4, 0, 0, 4, 12, 8, 8, 12, 8, 12, 12, 8, - 32, 36, 36, 32, 36, 32, 32, 36, 44, 40, 40, 44, 40, 44, 44, 40, - 36, 32, 32, 36, 32, 36, 36, 32, 40, 44, 44, 40, 44, 40, 40, 44, - 0, 4, 4, 0, 4, 0, 0, 4, 12, 8, 8, 12, 8, 12, 12, 8, - 4, 0, 0, 4, 0, 4, 4, 0, 8, 12, 12, 8, 12, 8, 8, 12, - 36, 32, 32, 36, 32, 36, 36, 32, 40, 44, 44, 40, 44, 40, 40, 44, - 32, 36, 36, 32, 36, 32, 32, 36, 44, 40, 40, 44, 40, 44, 44, 40, - 128,132,132,128,132,128,128,132,140,136,136,140,136,140,140,136, - 132,128,128,132,128,132,132,128,136,140,140,136,140,136,136,140, - 164,160,160,164,160,164,164,160,168,172,172,168,172,168,168,172, - 160,164,164,160,164,160,160,164,172,168,168,172,168,172,172,168, - 132,128,128,132,128,132,132,128,136,140,140,136,140,136,136,140, - 128,132,132,128,132,128,128,132,140,136,136,140,136,140,140,136, - 160,164,164,160,164,160,160,164,172,168,168,172,168,172,172,168, - 164,160,160,164,160,164,164,160,168,172,172,168,172,168,168,172, -}; - -/* incZ80Table[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0) << 4) | ((i == 0x80) << 2), i = 0..256 */ -static const uint8 incZ80Table[257] = { - 80, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 148,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 80, -}; - -/* decZ80Table[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0xf) << 4) | ((i == 0x7f) << 2) | 2, i = 0..255 */ -static const uint8 decZ80Table[256] = { - 66, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 62, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, -}; - -/* cbitsZ80Table[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1), i = 0..511 */ -static const uint8 cbitsZ80Table[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, -}; - -/* cbitsZ80DupTable[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | - ((i >> 8) & 1) | (i & 0xa8), i = 0..511 */ -static const uint8 cbitsZ80DupTable[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, - 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, - 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56, - 132,132,132,132,132,132,132,132,140,140,140,140,140,140,140,140, - 148,148,148,148,148,148,148,148,156,156,156,156,156,156,156,156, - 164,164,164,164,164,164,164,164,172,172,172,172,172,172,172,172, - 180,180,180,180,180,180,180,180,188,188,188,188,188,188,188,188, - 132,132,132,132,132,132,132,132,140,140,140,140,140,140,140,140, - 148,148,148,148,148,148,148,148,156,156,156,156,156,156,156,156, - 164,164,164,164,164,164,164,164,172,172,172,172,172,172,172,172, - 180,180,180,180,180,180,180,180,188,188,188,188,188,188,188,188, - 5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 13, 13, 13, 13, 13, 13, - 21, 21, 21, 21, 21, 21, 21, 21, 29, 29, 29, 29, 29, 29, 29, 29, - 37, 37, 37, 37, 37, 37, 37, 37, 45, 45, 45, 45, 45, 45, 45, 45, - 53, 53, 53, 53, 53, 53, 53, 53, 61, 61, 61, 61, 61, 61, 61, 61, - 5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 13, 13, 13, 13, 13, 13, - 21, 21, 21, 21, 21, 21, 21, 21, 29, 29, 29, 29, 29, 29, 29, 29, - 37, 37, 37, 37, 37, 37, 37, 37, 45, 45, 45, 45, 45, 45, 45, 45, - 53, 53, 53, 53, 53, 53, 53, 53, 61, 61, 61, 61, 61, 61, 61, 61, - 129,129,129,129,129,129,129,129,137,137,137,137,137,137,137,137, - 145,145,145,145,145,145,145,145,153,153,153,153,153,153,153,153, - 161,161,161,161,161,161,161,161,169,169,169,169,169,169,169,169, - 177,177,177,177,177,177,177,177,185,185,185,185,185,185,185,185, - 129,129,129,129,129,129,129,129,137,137,137,137,137,137,137,137, - 145,145,145,145,145,145,145,145,153,153,153,153,153,153,153,153, - 161,161,161,161,161,161,161,161,169,169,169,169,169,169,169,169, - 177,177,177,177,177,177,177,177,185,185,185,185,185,185,185,185, -}; - -/* cbits2Z80Table[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2, i = 0..511 */ -static const uint8 cbits2Z80Table[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* cbits2Z80DupTable[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 | - (i & 0xa8), i = 0..511 */ -static const uint8 cbits2Z80DupTable[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, - 18, 18, 18, 18, 18, 18, 18, 18, 26, 26, 26, 26, 26, 26, 26, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42, - 50, 50, 50, 50, 50, 50, 50, 50, 58, 58, 58, 58, 58, 58, 58, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, - 18, 18, 18, 18, 18, 18, 18, 18, 26, 26, 26, 26, 26, 26, 26, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42, - 50, 50, 50, 50, 50, 50, 50, 50, 58, 58, 58, 58, 58, 58, 58, 58, - 134,134,134,134,134,134,134,134,142,142,142,142,142,142,142,142, - 150,150,150,150,150,150,150,150,158,158,158,158,158,158,158,158, - 166,166,166,166,166,166,166,166,174,174,174,174,174,174,174,174, - 182,182,182,182,182,182,182,182,190,190,190,190,190,190,190,190, - 134,134,134,134,134,134,134,134,142,142,142,142,142,142,142,142, - 150,150,150,150,150,150,150,150,158,158,158,158,158,158,158,158, - 166,166,166,166,166,166,166,166,174,174,174,174,174,174,174,174, - 182,182,182,182,182,182,182,182,190,190,190,190,190,190,190,190, - 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15, - 23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, - 39, 39, 39, 39, 39, 39, 39, 39, 47, 47, 47, 47, 47, 47, 47, 47, - 55, 55, 55, 55, 55, 55, 55, 55, 63, 63, 63, 63, 63, 63, 63, 63, - 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15, - 23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, - 39, 39, 39, 39, 39, 39, 39, 39, 47, 47, 47, 47, 47, 47, 47, 47, - 55, 55, 55, 55, 55, 55, 55, 55, 63, 63, 63, 63, 63, 63, 63, 63, - 131,131,131,131,131,131,131,131,139,139,139,139,139,139,139,139, - 147,147,147,147,147,147,147,147,155,155,155,155,155,155,155,155, - 163,163,163,163,163,163,163,163,171,171,171,171,171,171,171,171, - 179,179,179,179,179,179,179,179,187,187,187,187,187,187,187,187, - 131,131,131,131,131,131,131,131,139,139,139,139,139,139,139,139, - 147,147,147,147,147,147,147,147,155,155,155,155,155,155,155,155, - 163,163,163,163,163,163,163,163,171,171,171,171,171,171,171,171, - 179,179,179,179,179,179,179,179,187,187,187,187,187,187,187,187, -}; - -/* negTable[i] = (((i & 0x0f) != 0) << 4) | ((i == 0x80) << 2) | 2 | (i != 0), i = 0..255 */ -static const uint8 negTable[256] = { - 2,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 7,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* rrdrldTable[i] = (i << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i], i = 0..255 */ -static const uint16 rrdrldTable[256] = { - 0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700, - 0x0808,0x090c,0x0a0c,0x0b08,0x0c0c,0x0d08,0x0e08,0x0f0c, - 0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704, - 0x180c,0x1908,0x1a08,0x1b0c,0x1c08,0x1d0c,0x1e0c,0x1f08, - 0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724, - 0x282c,0x2928,0x2a28,0x2b2c,0x2c28,0x2d2c,0x2e2c,0x2f28, - 0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720, - 0x3828,0x392c,0x3a2c,0x3b28,0x3c2c,0x3d28,0x3e28,0x3f2c, - 0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704, - 0x480c,0x4908,0x4a08,0x4b0c,0x4c08,0x4d0c,0x4e0c,0x4f08, - 0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700, - 0x5808,0x590c,0x5a0c,0x5b08,0x5c0c,0x5d08,0x5e08,0x5f0c, - 0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720, - 0x6828,0x692c,0x6a2c,0x6b28,0x6c2c,0x6d28,0x6e28,0x6f2c, - 0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724, - 0x782c,0x7928,0x7a28,0x7b2c,0x7c28,0x7d2c,0x7e2c,0x7f28, - 0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784, - 0x888c,0x8988,0x8a88,0x8b8c,0x8c88,0x8d8c,0x8e8c,0x8f88, - 0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780, - 0x9888,0x998c,0x9a8c,0x9b88,0x9c8c,0x9d88,0x9e88,0x9f8c, - 0xa0a4,0xa1a0,0xa2a0,0xa3a4,0xa4a0,0xa5a4,0xa6a4,0xa7a0, - 0xa8a8,0xa9ac,0xaaac,0xaba8,0xacac,0xada8,0xaea8,0xafac, - 0xb0a0,0xb1a4,0xb2a4,0xb3a0,0xb4a4,0xb5a0,0xb6a0,0xb7a4, - 0xb8ac,0xb9a8,0xbaa8,0xbbac,0xbca8,0xbdac,0xbeac,0xbfa8, - 0xc084,0xc180,0xc280,0xc384,0xc480,0xc584,0xc684,0xc780, - 0xc888,0xc98c,0xca8c,0xcb88,0xcc8c,0xcd88,0xce88,0xcf8c, - 0xd080,0xd184,0xd284,0xd380,0xd484,0xd580,0xd680,0xd784, - 0xd88c,0xd988,0xda88,0xdb8c,0xdc88,0xdd8c,0xde8c,0xdf88, - 0xe0a0,0xe1a4,0xe2a4,0xe3a0,0xe4a4,0xe5a0,0xe6a0,0xe7a4, - 0xe8ac,0xe9a8,0xeaa8,0xebac,0xeca8,0xedac,0xeeac,0xefa8, - 0xf0a4,0xf1a0,0xf2a0,0xf3a4,0xf4a0,0xf5a4,0xf6a4,0xf7a0, - 0xf8a8,0xf9ac,0xfaac,0xfba8,0xfcac,0xfda8,0xfea8,0xffac, -}; - -/* cpTable[i] = (i & 0x80) | (((i & 0xff) == 0) << 6), i = 0..255 */ -static const uint8 cpTable[256] = { - 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, -}; - -/* remove comments to generate table contents and add a call to - altairz80_print_tables in the altairz80_init -static void altairz80_print_tables(void) { -*/ -/* parityTable */ -/* - uint32 i, v; - for (i = 0; i < 256; i++) { - v = ((i & 1) + ((i & 2) >> 1) + ((i & 4) >> 2) + ((i & 8) >> 3) + - ((i & 16) >> 4) + ((i & 32) >> 5) + ((i & 64) >> 6) + ((i & 128) >> 7)) % 2 ? 0 : 4; - printf("%1d,", v); - if ( ((i+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* incTable */ -/* - uint32 temp, v; - for (temp = 0; temp <= 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | (((temp & 0xf) == 0) << 4); - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* decTable */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | (((temp & 0xf) == 0xf) << 4) | 2; - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsTable */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsDup8Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1) | ((cbits & 0xff) << 8) | (cbits & 0xa8) | (((cbits & 0xff) == 0) << 6); - printf("0x%04x,", v); - if ( ((cbits+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* cbitsDup16Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1) | (cbits & 0x28); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbits2Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1) | 2; - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* rrcaTable */ -/* - uint32 temp, sum, v; - for (temp = 0; temp < 256; temp++) { - sum = temp >> 1; - v = ((temp & 1) << 15) | (sum << 8) | (sum & 0x28) | (temp & 1); - printf("0x%04x,", v); - if ( ((temp+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* rraTable */ -/* - uint32 temp, sum, v; - for (temp = 0; temp < 256; temp++) { - sum = temp >> 1; - v = (sum << 8) | (sum & 0x28) | (temp & 1); - printf("0x%04x,", v); - if ( ((temp+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* addTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 512; sum++) { - v = ((sum & 0xff) << 8) | (sum & 0xa8) | (((sum & 0xff) == 0) << 6); - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* subTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = ((sum & 0xff) << 8) | (sum & 0xa8) | (((sum & 0xff) == 0) << 6) | 2; - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* andTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | 0x10 | parityTable[sum]; - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* xororTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | parityTable[sum]; - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* rotateShiftTable */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | PARITY(temp); - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* incZ80Table */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | - (((temp & 0xf) == 0) << 4) | ((temp == 0x80) << 2); - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* decZ80Table */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | - (((temp & 0xf) == 0xf) << 4) | ((temp == 0x7f) << 2) | 2; - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsZ80Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | (((cbits >> 6) ^ (cbits >> 5)) & 4) | - ((cbits >> 8) & 1); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsZ80DupTable */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | (((cbits >> 6) ^ (cbits >> 5)) & 4) | - ((cbits >> 8) & 1) | (cbits & 0xa8); - printf("%3d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbits2Z80Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (((cbits >> 6) ^ (cbits >> 5)) & 4) | (cbits & 0x10) | 2 | ((cbits >> 8) & 1); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbits2Z80DupTable */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (((cbits >> 6) ^ (cbits >> 5)) & 4) | (cbits & 0x10) | 2 | ((cbits >> 8) & 1) | - (cbits & 0xa8); - printf("%3d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* negTable */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (((temp & 0x0f) != 0) << 4) | ((temp == 0x80) << 2) | 2 | (temp != 0); - printf("%2d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* rrdrldTable */ -/* - uint32 acu, v; - for (acu = 0; acu < 256; acu++) { - v = (acu << 8) | (acu & 0xa8) | (((acu & 0xff) == 0) << 6) | parityTable[acu]; - printf("0x%04x,", v); - if ( ((acu+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* cpTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = (sum & 0x80) | (((sum & 0xff) == 0) << 6); - printf("%3d,", v); - if ( ((sum+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* remove comments to generate table contents -} -*/ - -/* Memory management */ - -#define LOG2PAGESIZE 8 -#define PAGESIZE (1 << LOG2PAGESIZE) - -static uint8 M[MAXMEMORY]; /* RAM which is present */ - -struct mdev { /* Structure to describe a 2^LOG2PAGESIZE byte page of address space */ - /* There are four cases - isRAM isEmpty routine code - TRUE FALSE NULL W page is random access memory (RAM) - FALSE TRUE NULL U no memory at this location - FALSE FALSE NULL R page is read only memory (ROM) - FALSE FALSE not NULL M page is mapped to memory mapped I/O routine - other combinations are undefined! - */ - uint32 isRAM; - uint32 isEmpty; - int32 (*routine)(const int32, const int32, const int32); -}; - -typedef struct mdev MDEV; - -static MDEV ROM_PAGE = {FALSE, FALSE, NULL}; /* this makes a page ROM */ -static MDEV RAM_PAGE = {TRUE, FALSE, NULL}; /* this makes a page RAM */ -static MDEV EMPTY_PAGE = {FALSE, TRUE, NULL}; /* this is non-existing memory */ -static MDEV mmu_table[MAXMEMORY >> LOG2PAGESIZE]; - -/* Memory and I/O Resource Mapping and Unmapping routine. */ -uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap) { - uint32 page, i, addr; - if (resource_type == RESOURCE_TYPE_MEMORY) { - for (i = 0; i < (size >> LOG2PAGESIZE); i++) { - addr = (baseaddr & 0xfff00) + (i << LOG2PAGESIZE); - if ((cpu_unit.flags & UNIT_CPU_BANKED) && (addr < common)) - addr |= bankSelect << MAXBANKSIZELOG2; - page = addr >> LOG2PAGESIZE; - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("%s memory 0x%05x, handler=%p\n", unmap ? "Unmapping" : " Mapping", - addr, routine); - if (unmap) { - if (mmu_table[page].routine == routine) { /* unmap only if it was mapped */ - if (MEMORYSIZE < MAXBANKSIZE) - if (addr < MEMORYSIZE) - mmu_table[page] = RAM_PAGE; - else - mmu_table[page] = EMPTY_PAGE; - else - mmu_table[page] = RAM_PAGE; - } - } - else { - mmu_table[page] = ROM_PAGE; - mmu_table[page].routine = routine; - } - } - } else if (resource_type == RESOURCE_TYPE_IO) { - for (i = baseaddr; i < baseaddr + size; i++) - if (unmap) { - if (dev_table[i & 0xff].routine == routine) { - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("Unmapping IO %04x, handler=%p\n", i, routine); - dev_table[i & 0xff].routine = &nulldev; - } - } - else { - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf(" Mapping IO %04x, handler=%p\n", i, routine); - dev_table[i & 0xff].routine = routine; - } - } else { - printf("%s: cannot map unknown resource type %d\n", __FUNCTION__, resource_type); - return -1; - } - return 0; -} - -static void PutBYTE(register uint32 Addr, const register uint32 Value) { - MDEV m; - - Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - if ((cpu_unit.flags & UNIT_CPU_BANKED) && (Addr < common)) - Addr |= bankSelect << MAXBANKSIZELOG2; - m = mmu_table[Addr >> LOG2PAGESIZE]; - - if (m.isRAM) - M[Addr] = Value; - else if (m.routine) - m.routine(Addr, 1, Value); - else if (cpu_unit.flags & UNIT_CPU_VERBOSE) { - if (m.isEmpty) - printf("CPU: " ADDRESS_FORMAT " Attempt to write to non existing memory " ADDRESS_FORMAT "." NLP, PCX, Addr); - else - printf("CPU: " ADDRESS_FORMAT " Attempt to write to ROM " ADDRESS_FORMAT "." NLP, PCX, Addr); - } -} - -void PutBYTEExtended(register uint32 Addr, const register uint32 Value) { - MDEV m; - - Addr &= ADDRMASKEXTENDED; - m = mmu_table[Addr >> LOG2PAGESIZE]; - - if (m.isRAM) - M[Addr] = Value; - else if (m.routine) - m.routine(Addr, 1, Value); - else if (cpu_unit.flags & UNIT_CPU_VERBOSE) { - if (m.isEmpty) - printf("CPU: " ADDRESS_FORMAT " Attempt to write to non existing memory " ADDRESS_FORMAT "." NLP, PCX, Addr); - else - printf("CPU: " ADDRESS_FORMAT " Attempt to write to ROM " ADDRESS_FORMAT "." NLP, PCX, Addr); - } -} - -static void PutWORD(register uint32 Addr, const register uint32 Value) { - PutBYTE(Addr, Value); - PutBYTE(Addr + 1, Value >> 8); -} - -static uint32 GetBYTE(register uint32 Addr) { - MDEV m; - - Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - if ((cpu_unit.flags & UNIT_CPU_BANKED) && (Addr < common)) - Addr |= bankSelect << MAXBANKSIZELOG2; - m = mmu_table[Addr >> LOG2PAGESIZE]; - - if (m.isRAM) - return M[Addr]; /* RAM */ - if (m.routine) - return m.routine(Addr, 0, 0); /* memory mapped I/O */ - if (m.isEmpty) { - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("CPU: " ADDRESS_FORMAT " Attempt to read from non existing memory " ADDRESS_FORMAT "." NLP, PCX, Addr); - return 0xff; - } - return M[Addr]; /* ROM */ -} - -uint32 GetBYTEExtended(register uint32 Addr) { - MDEV m; - - Addr &= ADDRMASKEXTENDED; - m = mmu_table[Addr >> LOG2PAGESIZE]; - - if (m.isRAM) - return M[Addr]; - if (m.routine) - return m.routine(Addr, 0, 0); - if (m.isEmpty) { - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("CPU: " ADDRESS_FORMAT " Attempt to read from non existing memory " ADDRESS_FORMAT "." NLP, PCX, Addr); - return 0xff; - } - return M[Addr]; -} - -int32 getBankSelect(void) { - return bankSelect; -} - -void setBankSelect(const int32 b) { - bankSelect = b; -} - -uint32 getCommon(void) { - return common; -} - -/* memory access during a simulation */ -uint8 GetBYTEWrapper(const uint32 Addr) { - if (chiptype == CHIP_TYPE_8086) - return GetBYTEExtended(Addr); - else if (cpu_unit.flags & UNIT_CPU_MMU) - return GetBYTE(Addr); - else - return MOPT[Addr & ADDRMASK]; -} - -/* memory access during a simulation */ -void PutBYTEWrapper(const uint32 Addr, const uint32 Value) { - if (chiptype == CHIP_TYPE_8086) - PutBYTEExtended(Addr, Value); - else if (cpu_unit.flags & UNIT_CPU_MMU) - PutBYTE(Addr, Value); - else - MOPT[Addr & ADDRMASK] = Value & 0xff; -} - -/* DMA memory access during a simulation, suggested by Tony Nicholson */ -uint8 GetByteDMA(const uint32 Addr) { - if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU)) - return GetBYTEExtended(Addr); - else - return MOPT[Addr & ADDRMASK]; -} - -void PutByteDMA(const uint32 Addr, const uint32 Value) { - if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU)) - PutBYTEExtended(Addr, Value); - else - MOPT[Addr & ADDRMASK] = Value & 0xff; -} - -#define RAM_PP(Addr) GetBYTE(Addr++) -#define RAM_MM(Addr) GetBYTE(Addr--) -#define GET_WORD(Addr) (GetBYTE(Addr) | (GetBYTE(Addr + 1) << 8)) -#define PUT_BYTE_PP(a,v) PutBYTE(a++, v) -#define PUT_BYTE_MM(a,v) PutBYTE(a--, v) -#define MM_PUT_BYTE(a,v) PutBYTE(--a, v) - -#define MASK_BRK (TRUE + 1) - -/* this is a modified version of sim_brk_test with two differences: - 1) is does not set sim_brk_pend to FALSE (this is left to the instruction decode) - 2) it returns MASK_BRK if a breakpoint is found but should be ignored -*/ -static int32 sim_brk_lookup (const t_addr loc, const int32 btyp) { - extern t_bool sim_brk_pend[SIM_BKPT_N_SPC]; - extern t_addr sim_brk_ploc[SIM_BKPT_N_SPC]; - extern char *sim_brk_act; - BRKTAB *bp; - if ((bp = sim_brk_fnd (loc)) && /* entry in table? */ - (btyp & bp->typ) && /* type match? */ - (!sim_brk_pend[0] || (loc != sim_brk_ploc[0])) && /* new location? */ - (--(bp->cnt) <= 0)) { /* count reach 0? */ - bp->cnt = 0; /* reset count */ - sim_brk_ploc[0] = loc; /* save location */ - sim_brk_act = bp->act; /* set up actions */ - sim_brk_pend[0] = TRUE; /* don't do twice */ - return TRUE; - } - return (sim_brk_pend[0] && (loc == sim_brk_ploc[0])) ? MASK_BRK : FALSE; -} - -#define PUSH(x) { \ - MM_PUT_BYTE(SP, (x) >> 8); \ - MM_PUT_BYTE(SP, x); \ -} - -#define CHECK_BREAK_BYTE(a) \ - if (sim_brk_summ) { \ - if (sim_brk_test((a) & 0xffff, SWMASK('M'))) { \ - reason = STOP_MEM; \ - prepareMemoryAccessMessage((a) & 0xffff); \ - goto end_decode; \ - } \ - sim_brk_pend[0] = FALSE; \ - } - -#define CHECK_BREAK_TWO_BYTES_EXTENDED(a1, a2, iCode) \ - if (sim_brk_summ) { \ - int32 brl = sim_brk_lookup((a1) & 0xffff, SWMASK('M')); \ - if ((brl == TRUE) || (brl == FALSE) && (sim_brk_lookup((a2) \ - & 0xffff, SWMASK('M')) == TRUE)) { \ - reason = STOP_MEM; \ - prepareMemoryAccessMessage((brl ? (a1):(a2)) & 0xffff); \ - iCode; \ - goto end_decode; \ - } \ - sim_brk_pend[0] = FALSE; \ - } - -#define CHECK_BREAK_TWO_BYTES(a1, a2) CHECK_BREAK_TWO_BYTES_EXTENDED(a1, a2,;) - -#define CHECK_BREAK_WORD(a) CHECK_BREAK_TWO_BYTES(a, (a + 1)) - -#define HALTINSTRUCTION 0x76 - -/* Macros for the IN/OUT instructions INI/INIR/IND/INDR/OUTI/OTIR/OUTD/OTDR - - Pre condition - temp == value of register B at entry of the instruction - acu == value of transferred byte (IN or OUT) - Post condition - F is set correctly - - Use INOUTFLAGS_ZERO(x) for INIR/INDR/OTIR/OTDR where - x == (C + 1) & 0xff for INIR - x == L for OTIR and OTDR - x == (C - 1) & 0xff for INDR - Use INOUTFLAGS_NONZERO(x) for INI/IND/OUTI/OUTD where - x == (C + 1) & 0xff for INI - x == L for OUTI and OUTD - x == (C - 1) & 0xff for IND -*/ -#define INOUTFLAGS(syxz, x) \ - AF = (AF & 0xff00) | (syxz) | /* SF, YF, XF, ZF */ \ - ((acu & 0x80) >> 6) | /* NF */ \ - ((acu + (x)) > 0xff ? (FLAG_C | FLAG_H) : 0) | /* CF, HF */ \ - parityTable[((acu + (x)) & 7) ^ temp] /* PF */ - -#define INOUTFLAGS_ZERO(x) INOUTFLAGS(FLAG_Z, x) -#define INOUTFLAGS_NONZERO(x) \ - INOUTFLAGS((HIGH_REGISTER(BC) & 0xa8) | ((HIGH_REGISTER(BC) == 0) << 6), x) - -int32 switch_cpu_now = TRUE; /* hharte */ - -t_stat sim_instr (void) { - uint32 i; - t_stat result; - if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU)) - do { - result = (chiptype == CHIP_TYPE_8086) ? sim_instr_8086() : sim_instr_mmu(); - } while (switch_cpu_now == FALSE); - else { - for (i = 0; i < MAXBANKSIZE; i++) - MOPT[i] = M[i]; - result = sim_instr_nommu(); - for (i = 0; i < MAXBANKSIZE; i++) - M[i] = MOPT[i]; - } - return result; -} - -static int32 clockHasChanged = FALSE; - -uint32 getClockFrequency(void) { - return clockFrequency; -} - -void setClockFrequency(const uint32 Value) { - clockFrequency = Value; - clockHasChanged = TRUE; -} - -static t_stat sim_instr_mmu (void) { - extern int32 sim_interval; - extern t_bool sim_brk_pend[SIM_BKPT_N_SPC]; - extern int32 timerInterrupt; - extern int32 timerInterruptHandler; - extern int32 keyboardInterrupt; - extern uint32 keyboardInterruptHandler; - extern uint32 sim_os_msec(void); - extern const t_bool rtc_avail; - extern uint32 sim_brk_summ; - int32 reason = SCPE_OK; - register uint32 specialProcessing; - register uint32 AF; - register uint32 BC; - register uint32 DE; - register uint32 HL; - register uint32 PC; - register uint32 SP; - register uint32 IX; - register uint32 IY; - register uint32 temp = 0; - register uint32 acu = 0; - register uint32 sum; - register uint32 cbits; - register uint32 op; - register uint32 adr; - /* tStates contains the number of t-states executed. One t-state is executed - in one microsecond on a 1MHz CPU. tStates is used for real-time simulations. */ - register uint32 tStates; - uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */ - uint32 startTime, now; - int32 tStateModifier = FALSE; - - switch_cpu_now = TRUE; /* hharte */ - - AF = AF_S; - BC = BC_S; - DE = DE_S; - HL = HL_S; - PC = PC_S & ADDRMASK; - SP = SP_S; - IX = IX_S; - IY = IY_S; - specialProcessing = clockFrequency | timerInterrupt | keyboardInterrupt | sim_brk_summ; - tStates = 0; - if (rtc_avail) { - startTime = sim_os_msec(); - tStatesInSlice = sliceLength*clockFrequency; - } - else /* make sure that sim_os_msec() is not called later */ - clockFrequency = startTime = tStatesInSlice = 0; - - /* main instruction fetch/decode loop */ - while (switch_cpu_now == TRUE) { /* loop until halted */ - if (sim_interval <= 0) { /* check clock queue */ -#if !UNIX_PLATFORM - if ((reason = sim_os_poll_kbd()) == SCPE_STOP) /* poll on platforms without reliable signalling */ - break; -#endif - if ((reason = sim_process_event())) - break; - if (clockHasChanged) { - clockHasChanged = FALSE; - tStates = 0; - if (rtc_avail) { - startTime = sim_os_msec(); - tStatesInSlice = sliceLength*clockFrequency; - } - else /* make sure that sim_os_msec() is not called later */ - clockFrequency = startTime = tStatesInSlice = 0; - } - specialProcessing = clockFrequency | timerInterrupt | keyboardInterrupt | sim_brk_summ; - } - - if (specialProcessing) { /* quick check for special processing */ - if (clockFrequency && (tStates >= tStatesInSlice)) { - /* clockFrequency != 0 implies that real time clock is available */ - startTime += sliceLength; - tStates -= tStatesInSlice; - if (startTime > (now = sim_os_msec())) { -#if defined (_WIN32) - Sleep(startTime - now); -#else - usleep(1000 * (startTime - now)); -#endif - } - } - - if (timerInterrupt && (IFF_S & 1)) { - timerInterrupt = FALSE; - specialProcessing = clockFrequency | sim_brk_summ; - IFF_S = 0; /* disable interrupts */ - CHECK_BREAK_TWO_BYTES_EXTENDED(SP - 2, SP - 1, (timerInterrupt = TRUE, IFF_S |= 1)); - if ((GetBYTE(PC) == HALTINSTRUCTION) && ((cpu_unit.flags & UNIT_CPU_STOPONHALT) == 0)) { - PUSH(PC + 1); - PCQ_ENTRY(PC); - } - else { - PUSH(PC); - PCQ_ENTRY(PC - 1); - } - PC = timerInterruptHandler & ADDRMASK; - } - - if (keyboardInterrupt && (IFF_S & 1)) { - keyboardInterrupt = FALSE; - specialProcessing = clockFrequency | sim_brk_summ; - IFF_S = 0; /* disable interrupts */ - CHECK_BREAK_TWO_BYTES_EXTENDED(SP - 2, SP - 1, (keyboardInterrupt = TRUE, IFF_S |= 1)); - if ((GetBYTE(PC) == HALTINSTRUCTION) && ((cpu_unit.flags & UNIT_CPU_STOPONHALT) == 0)) { - PUSH(PC + 1); - PCQ_ENTRY(PC); - } - else { - PUSH(PC); - PCQ_ENTRY(PC - 1); - } - PC = keyboardInterruptHandler & ADDRMASK; - } - - if (sim_brk_summ) { - if (sim_brk_test(PC, (2u << SIM_BKPT_V_SPC) | SWMASK('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - if (sim_brk_test(GetBYTE(PC), (1u << SIM_BKPT_V_SPC) | SWMASK('I'))) { /* instruction breakpoint? */ - reason = STOP_INSTR; /* stop simulation */ - prepareInstructionMessage(PC, GetBYTE(PC)); - break; - } - } - } - - PCX = PC; - sim_interval--; - - /* make sure that each instructions properly sets sim_brk_pend: - 1) Either directly to FALSE if no memory access takes place or - 2) through a call to a Check... routine - */ - switch(RAM_PP(PC)) { - - case 0x00: /* NOP */ - tStates += 4; /* NOP 4 */ - sim_brk_pend[0] = FALSE; - break; - - case 0x01: /* LD BC,nnnn */ - tStates += 10; /* LXI B,nnnn 10 */ - sim_brk_pend[0] = FALSE; - BC = GET_WORD(PC); - PC += 2; - break; - - case 0x02: /* LD (BC),A */ - tStates += 7; /* STAX B 7 */ - CHECK_BREAK_BYTE(BC) - PutBYTE(BC, HIGH_REGISTER(AF)); - break; - - case 0x03: /* INC BC */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 6); /* INX B 5 */ - sim_brk_pend[0] = FALSE; - ++BC; - break; - - case 0x04: /* INC B */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* INR B 5 */ - sim_brk_pend[0] = FALSE; - BC += 0x100; - temp = HIGH_REGISTER(BC); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); /* SET_PV2 uses temp */ - break; - - case 0x05: /* DEC B */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* DCR B 5 */ - sim_brk_pend[0] = FALSE; - BC -= 0x100; - temp = HIGH_REGISTER(BC); - AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ - break; - - case 0x06: /* LD B,nn */ - tStates += 7; /* MVI B,nn 7 */ - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(BC, RAM_PP(PC)); - break; - - case 0x07: /* RLCA */ - tStates += 4; /* RLC 4 */ - sim_brk_pend[0] = FALSE; - AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) | - (AF & 0xc4) | ((AF >> 15) & 1); - break; - - case 0x08: /* EX AF,AF' */ - tStates += 4; /* NOP 4 */ - sim_brk_pend[0] = FALSE; - CHECK_CPU_8080; - temp = AF; - AF = AF1_S; - AF1_S = temp; - break; - - case 0x09: /* ADD HL,BC */ - tStates += (chiptype == CHIP_TYPE_8080 ? 10 : 11); /* DAD B 10 */ - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ BC ^ sum) >> 8]; - HL = sum; - break; - - case 0x0a: /* LD A,(BC) */ - tStates += 7; /* LDAX B 7 */ - CHECK_BREAK_BYTE(BC) - SET_HIGH_REGISTER(AF, GetBYTE(BC)); - break; - - case 0x0b: /* DEC BC */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 6); /* DCX B 5 */ - sim_brk_pend[0] = FALSE; - --BC; - break; - - case 0x0c: /* INC C */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* INR C 5 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(BC) + 1; - SET_LOW_REGISTER(BC, temp); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); - break; - - case 0x0d: /* DEC C */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* DCR C 5 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(BC) - 1; - SET_LOW_REGISTER(BC, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); - break; - - case 0x0e: /* LD C,nn */ - tStates += 7; /* MVI C,nn 7 */ - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(BC, RAM_PP(PC)); - break; - - case 0x0f: /* RRCA */ - tStates += 4; /* RRC 4 */ - sim_brk_pend[0] = FALSE; - AF = (AF & 0xc4) | rrcaTable[HIGH_REGISTER(AF)]; - break; - - case 0x10: /* DJNZ dd */ - sim_brk_pend[0] = FALSE; - if (chiptype == CHIP_TYPE_8080) - tStates += 4; /* NOP 4 */ - CHECK_CPU_8080; - if ((BC -= 0x100) & 0xff00) { - PCQ_ENTRY(PCX); - PC += (int8) GetBYTE(PC) + 1; - tStates += 13; - } - else { - PC++; - tStates += 8; - } - break; - - case 0x11: /* LD DE,nnnn */ - tStates += 10; /* LXI D,nnnn 10 */ - sim_brk_pend[0] = FALSE; - DE = GET_WORD(PC); - PC += 2; - break; - - case 0x12: /* LD (DE),A */ - tStates += 7; /* STAX D 7 */ - CHECK_BREAK_BYTE(DE) - PutBYTE(DE, HIGH_REGISTER(AF)); - break; - - case 0x13: /* INC DE */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 6); /* INX D 5 */ - sim_brk_pend[0] = FALSE; - ++DE; - break; - - case 0x14: /* INC D */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* INR D 5 */ - sim_brk_pend[0] = FALSE; - DE += 0x100; - temp = HIGH_REGISTER(DE); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); /* SET_PV2 uses temp */ - break; - - case 0x15: /* DEC D */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* DCR D 5 */ - sim_brk_pend[0] = FALSE; - DE -= 0x100; - temp = HIGH_REGISTER(DE); - AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ - break; - - case 0x16: /* LD D,nn */ - tStates += 7; /* MVI D,nn 7 */ - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(DE, RAM_PP(PC)); - break; - - case 0x17: /* RLA */ - tStates += 4; /* RAL 4 */ - sim_brk_pend[0] = FALSE; - AF = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) | - (AF & 0xc4) | ((AF >> 15) & 1); - break; - - case 0x18: /* JR dd */ - tStates += (chiptype == CHIP_TYPE_8080 ? 4 : 12); /* NOP 4 */ - sim_brk_pend[0] = FALSE; - CHECK_CPU_8080; - PCQ_ENTRY(PCX); - PC += (int8) GetBYTE(PC) + 1; - break; - - case 0x19: /* ADD HL,DE */ - tStates += (chiptype == CHIP_TYPE_8080 ? 10 : 11); /* DAD D 10 */ - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ DE ^ sum) >> 8]; - HL = sum; - break; - - case 0x1a: /* LD A,(DE) */ - tStates += 7; /* LDAX D 7 */ - CHECK_BREAK_BYTE(DE) - SET_HIGH_REGISTER(AF, GetBYTE(DE)); - break; - - case 0x1b: /* DEC DE */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 6); /* DCX D 5 */ - sim_brk_pend[0] = FALSE; - --DE; - break; - - case 0x1c: /* INC E */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* INR E 5 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(DE) + 1; - SET_LOW_REGISTER(DE, temp); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); - break; - - case 0x1d: /* DEC E */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* DCR E 5 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(DE) - 1; - SET_LOW_REGISTER(DE, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); - break; - - case 0x1e: /* LD E,nn */ - tStates += 7; /* MVI E 7 */ - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(DE, RAM_PP(PC)); - break; - - case 0x1f: /* RRA */ - tStates += 4; /* RAR 4 */ - sim_brk_pend[0] = FALSE; - AF = ((AF & 1) << 15) | (AF & 0xc4) | rraTable[HIGH_REGISTER(AF)]; - break; - - case 0x20: /* JR NZ,dd */ - if (chiptype == CHIP_TYPE_8080) - tStates += 4; /* NOP 4 */ - sim_brk_pend[0] = FALSE; - CHECK_CPU_8080; - if (TSTFLAG(Z)) { - PC++; - tStates += 7; - } - else { - PCQ_ENTRY(PCX); - PC += (int8) GetBYTE(PC) + 1; - tStates += 12; - } - break; - - case 0x21: /* LD HL,nnnn */ - tStates += 10; /* LXI H,nnnn 10 */ - sim_brk_pend[0] = FALSE; - HL = GET_WORD(PC); - PC += 2; - break; - - case 0x22: /* LD (nnnn),HL */ - tStates += 16; /* SHLD 16 */ - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - PutWORD(temp, HL); - PC += 2; - break; - - case 0x23: /* INC HL */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 6); /* INX H 5 */ - sim_brk_pend[0] = FALSE; - ++HL; - break; - - case 0x24: /* INC H */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* INR H 5 */ - sim_brk_pend[0] = FALSE; - HL += 0x100; - temp = HIGH_REGISTER(HL); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); /* SET_PV2 uses temp */ - break; - - case 0x25: /* DEC H */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* DCR H 5 */ - sim_brk_pend[0] = FALSE; - HL -= 0x100; - temp = HIGH_REGISTER(HL); - AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ - break; - - case 0x26: /* LD H,nn */ - tStates += 7; /* MVI H,nn 7 */ - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(HL, RAM_PP(PC)); - break; - - case 0x27: /* DAA */ - tStates += 4; /* DAA 4 */ - sim_brk_pend[0] = FALSE; - acu = HIGH_REGISTER(AF); - temp = LOW_DIGIT(acu); - cbits = TSTFLAG(C); - if (TSTFLAG(N)) { /* last operation was a subtract */ - int hd = cbits || acu > 0x99; - if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */ - if (temp > 5) { - SETFLAG(H, 0); - } - acu -= 6; - acu &= 0xff; - } - if (hd) - acu -= 0x160; /* adjust high digit */ - } - else { /* last operation was an add */ - if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */ - SETFLAG(H, (temp > 9)); - acu += 6; - } - if (cbits || ((acu & 0x1f0) > 0x90)) - acu += 0x60; /* adjust high digit */ - } - AF = (AF & 0x12) | rrdrldTable[acu & 0xff] | ((acu >> 8) & 1) | cbits; - break; - - case 0x28: /* JR Z,dd */ - if (chiptype == CHIP_TYPE_8080) - tStates += 4; /* NOP 4 */ - sim_brk_pend[0] = FALSE; - CHECK_CPU_8080; - if (TSTFLAG(Z)) { - PCQ_ENTRY(PCX); - PC += (int8) GetBYTE(PC) + 1; - tStates += 12; - } - else { - PC++; - tStates += 7; - } - break; - - case 0x29: /* ADD HL,HL */ - tStates += (chiptype == CHIP_TYPE_8080 ? 10 : 11); /* DAD H 10 */ - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - sum = HL + HL; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - HL = sum; - break; - - case 0x2a: /* LD HL,(nnnn) */ - tStates += 16; /* LHLD nnnn 16 */ - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - HL = GET_WORD(temp); - PC += 2; - break; - - case 0x2b: /* DEC HL */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 6); /* DCX H 5 */ - sim_brk_pend[0] = FALSE; - --HL; - break; - - case 0x2c: /* INC L */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* INR L 5 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(HL) + 1; - SET_LOW_REGISTER(HL, temp); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); - break; - - case 0x2d: /* DEC L */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* DCR L 5 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(HL) - 1; - SET_LOW_REGISTER(HL, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); - break; - - case 0x2e: /* LD L,nn */ - tStates += 7; /* MVI L,nn 7 */ - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(HL, RAM_PP(PC)); - break; - - case 0x2f: /* CPL */ - tStates += 4; /* CMA 4 */ - sim_brk_pend[0] = FALSE; - AF = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12; - break; - - case 0x30: /* JR NC,dd */ - if (chiptype == CHIP_TYPE_8080) - tStates += 4; /* NOP 4 */ - sim_brk_pend[0] = FALSE; - CHECK_CPU_8080; - if (TSTFLAG(C)) { - PC++; - tStates += 7; - } - else { - PCQ_ENTRY(PCX); - PC += (int8) GetBYTE(PC) + 1; - tStates += 12; - } - break; - - case 0x31: /* LD SP,nnnn */ - tStates += 10; /* LXI SP,nnnn 10 */ - sim_brk_pend[0] = FALSE; - SP = GET_WORD(PC); - PC += 2; - break; - - case 0x32: /* LD (nnnn),A */ - tStates += 13; /* STA nnnn 13 */ - temp = GET_WORD(PC); - CHECK_BREAK_BYTE(temp); - PutBYTE(temp, HIGH_REGISTER(AF)); - PC += 2; - break; - - case 0x33: /* INC SP */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 6); /* INX SP 5 */ - sim_brk_pend[0] = FALSE; - ++SP; - break; - - case 0x34: /* INC (HL) */ - tStates += (chiptype == CHIP_TYPE_8080 ? 10 : 11); /* INR M 10 */ - CHECK_BREAK_BYTE(HL); - temp = GetBYTE(HL) + 1; - PutBYTE(HL, temp); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); - break; - - case 0x35: /* DEC (HL) */ - tStates += (chiptype == CHIP_TYPE_8080 ? 10 : 11); /* DCR M 10 */ - CHECK_BREAK_BYTE(HL); - temp = GetBYTE(HL) - 1; - PutBYTE(HL, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); - break; - - case 0x36: /* LD (HL),nn */ - tStates += 10; /* MVI M 10 */ - CHECK_BREAK_BYTE(HL); - PutBYTE(HL, RAM_PP(PC)); - break; - - case 0x37: /* SCF */ - tStates += 4; /* STC 4 */ - sim_brk_pend[0] = FALSE; - AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | 1; - break; - - case 0x38: /* JR C,dd */ - if (chiptype == CHIP_TYPE_8080) - tStates += 4; /* NOP 4 */ - sim_brk_pend[0] = FALSE; - CHECK_CPU_8080; - if (TSTFLAG(C)) { - PCQ_ENTRY(PCX); - PC += (int8) GetBYTE(PC) + 1; - tStates += 12; - } - else { - PC++; - tStates += 7; - } - break; - - case 0x39: /* ADD HL,SP */ - tStates += (chiptype == CHIP_TYPE_8080 ? 10 : 11); /* DAD SP 10 */ - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ SP ^ sum) >> 8]; - HL = sum; - break; - - case 0x3a: /* LD A,(nnnn) */ - tStates += 13; /* LDA nnnn 13 */ - temp = GET_WORD(PC); - CHECK_BREAK_BYTE(temp); - SET_HIGH_REGISTER(AF, GetBYTE(temp)); - PC += 2; - break; - - case 0x3b: /* DEC SP */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 6); /* DCX SP 5 */ - sim_brk_pend[0] = FALSE; - --SP; - break; - - case 0x3c: /* INC A */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* INR A 5 */ - sim_brk_pend[0] = FALSE; - AF += 0x100; - temp = HIGH_REGISTER(AF); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); /* SET_PV2 uses temp */ - break; - - case 0x3d: /* DEC A */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* DCR A 5 */ - sim_brk_pend[0] = FALSE; - AF -= 0x100; - temp = HIGH_REGISTER(AF); - AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ - break; - - case 0x3e: /* LD A,nn */ - tStates += 7; /* MVI A,nn 7 */ - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(AF, RAM_PP(PC)); - break; - - case 0x3f: /* CCF */ - tStates += 4; /* CMC 4 */ - sim_brk_pend[0] = FALSE; - AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | ((AF & 1) << 4) | (~AF & 1); - break; - - case 0x40: /* LD B,B */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV B,B 5 */ - sim_brk_pend[0] = FALSE; /* nop */ - break; - - case 0x41: /* LD B,C */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV B,C 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & 0xff) | ((BC & 0xff) << 8); - break; - - case 0x42: /* LD B,D */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV B,D 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & 0xff) | (DE & ~0xff); - break; - - case 0x43: /* LD B,E */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV B,E 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & 0xff) | ((DE & 0xff) << 8); - break; - - case 0x44: /* LD B,H */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV B,H 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & 0xff) | (HL & ~0xff); - break; - - case 0x45: /* LD B,L */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV B,L 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & 0xff) | ((HL & 0xff) << 8); - break; - - case 0x46: /* LD B,(HL) */ - tStates += 7; /* MOV B,M 7 */ - CHECK_BREAK_BYTE(HL); - SET_HIGH_REGISTER(BC, GetBYTE(HL)); - break; - - case 0x47: /* LD B,A */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV B,A 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & 0xff) | (AF & ~0xff); - break; - - case 0x48: /* LD C,B */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV C,B 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & ~0xff) | ((BC >> 8) & 0xff); - break; - - case 0x49: /* LD C,C */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV C,C 5 */ - sim_brk_pend[0] = FALSE; /* nop */ - break; - - case 0x4a: /* LD C,D */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV C,D 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & ~0xff) | ((DE >> 8) & 0xff); - break; - - case 0x4b: /* LD C,E */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV C,E 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & ~0xff) | (DE & 0xff); - break; - - case 0x4c: /* LD C,H */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV C,H 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & ~0xff) | ((HL >> 8) & 0xff); - break; - - case 0x4d: /* LD C,L */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV C,L 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & ~0xff) | (HL & 0xff); - break; - - case 0x4e: /* LD C,(HL) */ - tStates += 7; /* MOV C,M 7 */ - CHECK_BREAK_BYTE(HL); - SET_LOW_REGISTER(BC, GetBYTE(HL)); - break; - - case 0x4f: /* LD C,A */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV C,A 5 */ - sim_brk_pend[0] = FALSE; - BC = (BC & ~0xff) | ((AF >> 8) & 0xff); - break; - - case 0x50: /* LD D,B */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV D,B 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & 0xff) | (BC & ~0xff); - break; - - case 0x51: /* LD D,C */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV D,C 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & 0xff) | ((BC & 0xff) << 8); - break; - - case 0x52: /* LD D,D */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV D,D 5 */ - sim_brk_pend[0] = FALSE; /* nop */ - break; - - case 0x53: /* LD D,E */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV D,E 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & 0xff) | ((DE & 0xff) << 8); - break; - - case 0x54: /* LD D,H */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV D,H 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & 0xff) | (HL & ~0xff); - break; - - case 0x55: /* LD D,L */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV D,L 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & 0xff) | ((HL & 0xff) << 8); - break; - - case 0x56: /* LD D,(HL) */ - tStates += 7; /* MOV D,M 7 */ - CHECK_BREAK_BYTE(HL); - SET_HIGH_REGISTER(DE, GetBYTE(HL)); - break; - - case 0x57: /* LD D,A */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV D,A 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & 0xff) | (AF & ~0xff); - break; - - case 0x58: /* LD E,B */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV E,B 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & ~0xff) | ((BC >> 8) & 0xff); - break; - - case 0x59: /* LD E,C */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV E,C 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & ~0xff) | (BC & 0xff); - break; - - case 0x5a: /* LD E,D */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV E,D 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & ~0xff) | ((DE >> 8) & 0xff); - break; - - case 0x5b: /* LD E,E */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV E,E 5 */ - sim_brk_pend[0] = FALSE; /* nop */ - break; - - case 0x5c: /* LD E,H */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV E,H 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & ~0xff) | ((HL >> 8) & 0xff); - break; - - case 0x5d: /* LD E,L */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV E,L 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & ~0xff) | (HL & 0xff); - break; - - case 0x5e: /* LD E,(HL) */ - tStates += 7; /* MOV E,M 7 */ - CHECK_BREAK_BYTE(HL); - SET_LOW_REGISTER(DE, GetBYTE(HL)); - break; - - case 0x5f: /* LD E,A */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV E,A 5 */ - sim_brk_pend[0] = FALSE; - DE = (DE & ~0xff) | ((AF >> 8) & 0xff); - break; - - case 0x60: /* LD H,B */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV H,B 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & 0xff) | (BC & ~0xff); - break; - - case 0x61: /* LD H,C */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV H,C 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & 0xff) | ((BC & 0xff) << 8); - break; - - case 0x62: /* LD H,D */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV H,D 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & 0xff) | (DE & ~0xff); - break; - - case 0x63: /* LD H,E */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV H,E 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & 0xff) | ((DE & 0xff) << 8); - break; - - case 0x64: /* LD H,H */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV H,H 5 */ - sim_brk_pend[0] = FALSE; /* nop */ - break; - - case 0x65: /* LD H,L */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV H,L 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & 0xff) | ((HL & 0xff) << 8); - break; - - case 0x66: /* LD H,(HL) */ - tStates += 7; /* MOV H,M 7 */ - CHECK_BREAK_BYTE(HL); - SET_HIGH_REGISTER(HL, GetBYTE(HL)); - break; - - case 0x67: /* LD H,A */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV H,A 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & 0xff) | (AF & ~0xff); - break; - - case 0x68: /* LD L,B */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV L,B 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & ~0xff) | ((BC >> 8) & 0xff); - break; - - case 0x69: /* LD L,C */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV L,C 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & ~0xff) | (BC & 0xff); - break; - - case 0x6a: /* LD L,D */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV L,D 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & ~0xff) | ((DE >> 8) & 0xff); - break; - - case 0x6b: /* LD L,E */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV L,E 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & ~0xff) | (DE & 0xff); - break; - - case 0x6c: /* LD L,H */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV L,H 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & ~0xff) | ((HL >> 8) & 0xff); - break; - - case 0x6d: /* LD L,L */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV L,L 5 */ - sim_brk_pend[0] = FALSE; /* nop */ - break; - - case 0x6e: /* LD L,(HL) */ - tStates += 7; /* MOV L,M 7 */ - CHECK_BREAK_BYTE(HL); - SET_LOW_REGISTER(HL, GetBYTE(HL)); - break; - - case 0x6f: /* LD L,A */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV L,A 5 */ - sim_brk_pend[0] = FALSE; - HL = (HL & ~0xff) | ((AF >> 8) & 0xff); - break; - - case 0x70: /* LD (HL),B */ - tStates += 7; /* MOV M,B 7 */ - CHECK_BREAK_BYTE(HL); - PutBYTE(HL, HIGH_REGISTER(BC)); - break; - - case 0x71: /* LD (HL),C */ - tStates += 7; /* MOV M,C 7 */ - CHECK_BREAK_BYTE(HL); - PutBYTE(HL, LOW_REGISTER(BC)); - break; - - case 0x72: /* LD (HL),D */ - tStates += 7; /* MOV M,D 7 */ - CHECK_BREAK_BYTE(HL); - PutBYTE(HL, HIGH_REGISTER(DE)); - break; - - case 0x73: /* LD (HL),E */ - tStates += 7; /* MOV M,E 7 */ - CHECK_BREAK_BYTE(HL); - PutBYTE(HL, LOW_REGISTER(DE)); - break; - - case 0x74: /* LD (HL),H */ - tStates += 7; /* MOV M,H 7 */ - CHECK_BREAK_BYTE(HL); - PutBYTE(HL, HIGH_REGISTER(HL)); - break; - - case 0x75: /* LD (HL),L */ - tStates += 7; /* MOV M,L 7 */ - CHECK_BREAK_BYTE(HL); - PutBYTE(HL, LOW_REGISTER(HL)); - break; - - case HALTINSTRUCTION: /* HALT */ - tStates += (chiptype == CHIP_TYPE_8080 ? 7 : 4); /* HLT 7 */ - sim_brk_pend[0] = FALSE; - PC--; - if (cpu_unit.flags & UNIT_CPU_STOPONHALT) { - reason = STOP_HALT; - goto end_decode; - } - sim_interval = 0; - do_SIMH_sleep(); /* reduce CPU load in busy wait */ - break; - - case 0x77: /* LD (HL),A */ - tStates += 7; /* MOV M,A 7 */ - CHECK_BREAK_BYTE(HL); - PutBYTE(HL, HIGH_REGISTER(AF)); - break; - - case 0x78: /* LD A,B */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV A,B 5 */ - sim_brk_pend[0] = FALSE; - AF = (AF & 0xff) | (BC & ~0xff); - break; - - case 0x79: /* LD A,C */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV A,C 5 */ - sim_brk_pend[0] = FALSE; - AF = (AF & 0xff) | ((BC & 0xff) << 8); - break; - - case 0x7a: /* LD A,D */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV A,D 5 */ - sim_brk_pend[0] = FALSE; - AF = (AF & 0xff) | (DE & ~0xff); - break; - - case 0x7b: /* LD A,E */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV A,E 5 */ - sim_brk_pend[0] = FALSE; - AF = (AF & 0xff) | ((DE & 0xff) << 8); - break; - - case 0x7c: /* LD A,H */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV A,H 5 */ - sim_brk_pend[0] = FALSE; - AF = (AF & 0xff) | (HL & ~0xff); - break; - - case 0x7d: /* LD A,L */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV A,L 5 */ - sim_brk_pend[0] = FALSE; - AF = (AF & 0xff) | ((HL & 0xff) << 8); - break; - - case 0x7e: /* LD A,(HL) */ - tStates += 7; /* MOV A,M 7 */ - CHECK_BREAK_BYTE(HL); - SET_HIGH_REGISTER(AF, GetBYTE(HL)); - break; - - case 0x7f: /* LD A,A */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* MOV A,A 5 */ - sim_brk_pend[0] = FALSE; /* nop */ - break; - - case 0x80: /* ADD A,B */ - tStates += 4; /* ADD B 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x81: /* ADD A,C */ - tStates += 4; /* ADD C 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x82: /* ADD A,D */ - tStates += 4; /* ADD D 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x83: /* ADD A,E */ - tStates += 4; /* ADD E 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x84: /* ADD A,H */ - tStates += 4; /* ADD H 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x85: /* ADD A,L */ - tStates += 4; /* ADD L 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x86: /* ADD A,(HL) */ - tStates += 7; /* ADD M 7 */ - CHECK_BREAK_BYTE(HL); - temp = GetBYTE(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x87: /* ADD A,A */ - tStates += 4; /* ADD A 4 */ - sim_brk_pend[0] = FALSE; - cbits = 2 * HIGH_REGISTER(AF); - AF = cbitsDup8Table[cbits] | (SET_PVS(cbits)); - break; - - case 0x88: /* ADC A,B */ - tStates += 4; /* ADC B 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x89: /* ADC A,C */ - tStates += 4; /* ADC C 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8a: /* ADC A,D */ - tStates += 4; /* ADC D 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8b: /* ADC A,E */ - tStates += 4; /* ADC E 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8c: /* ADC A,H */ - tStates += 4; /* ADC H 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8d: /* ADC A,L */ - tStates += 4; /* ADC L 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8e: /* ADC A,(HL) */ - tStates += 7; /* ADC M 7 */ - CHECK_BREAK_BYTE(HL); - temp = GetBYTE(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8f: /* ADC A,A */ - tStates += 4; /* ADC A 4 */ - sim_brk_pend[0] = FALSE; - cbits = 2 * HIGH_REGISTER(AF) + TSTFLAG(C); - AF = cbitsDup8Table[cbits] | (SET_PVS(cbits)); - break; - - case 0x90: /* SUB B */ - tStates += 4; /* SUB B 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x91: /* SUB C */ - tStates += 4; /* SUB C 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x92: /* SUB D */ - tStates += 4; /* SUB D 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x93: /* SUB E */ - tStates += 4; /* SUB E 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x94: /* SUB H */ - tStates += 4; /* SUB H 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x95: /* SUB L */ - tStates += 4; /* SUB L 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x96: /* SUB (HL) */ - tStates += 7; /* SUB M 7 */ - CHECK_BREAK_BYTE(HL); - temp = GetBYTE(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x97: /* SUB A */ - tStates += 4; /* SUB A 4 */ - sim_brk_pend[0] = FALSE; - AF = (chiptype == CHIP_TYPE_Z80) ? 0x42 : 0x46; - break; - - case 0x98: /* SBC A,B */ - tStates += 4; /* SBB B 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x99: /* SBC A,C */ - tStates += 4; /* SBB C 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9a: /* SBC A,D */ - tStates += 4; /* SBB D 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9b: /* SBC A,E */ - tStates += 4; /* SBB E 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9c: /* SBC A,H */ - tStates += 4; /* SBB H 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9d: /* SBC A,L */ - tStates += 4; /* SBB L 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9e: /* SBC A,(HL) */ - tStates += 7; /* SBB M 7 */ - CHECK_BREAK_BYTE(HL); - temp = GetBYTE(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9f: /* SBC A,A */ - tStates += 4; /* SBB A 4 */ - sim_brk_pend[0] = FALSE; - cbits = -TSTFLAG(C); - AF = subTable[cbits & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PVS(cbits)); - break; - - case 0xa0: /* AND B */ - tStates += 4; /* ANA B 4 */ - sim_brk_pend[0] = FALSE; - AF = andTable[((AF & BC) >> 8) & 0xff]; - break; - - case 0xa1: /* AND C */ - tStates += 4; /* ANA C 4 */ - sim_brk_pend[0] = FALSE; - AF = andTable[((AF >> 8) & BC) & 0xff]; - break; - - case 0xa2: /* AND D */ - tStates += 4; /* ANA D 4 */ - sim_brk_pend[0] = FALSE; - AF = andTable[((AF & DE) >> 8) & 0xff]; - break; - - case 0xa3: /* AND E */ - tStates += 4; /* ANA E 4 */ - sim_brk_pend[0] = FALSE; - AF = andTable[((AF >> 8) & DE) & 0xff]; - break; - - case 0xa4: /* AND H */ - tStates += 4; /* ANA H 4 */ - sim_brk_pend[0] = FALSE; - AF = andTable[((AF & HL) >> 8) & 0xff]; - break; - - case 0xa5: /* AND L */ - tStates += 4; /* ANA L 4 */ - sim_brk_pend[0] = FALSE; - AF = andTable[((AF >> 8) & HL) & 0xff]; - break; - - case 0xa6: /* AND (HL) */ - tStates += 7; /* ANA M 7 */ - CHECK_BREAK_BYTE(HL); - AF = andTable[((AF >> 8) & GetBYTE(HL)) & 0xff]; - break; - - case 0xa7: /* AND A */ - tStates += 4; /* ANA A 4 */ - sim_brk_pend[0] = FALSE; - AF = andTable[(AF >> 8) & 0xff]; - break; - - case 0xa8: /* XOR B */ - tStates += 4; /* XRA B 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF ^ BC) >> 8) & 0xff]; - break; - - case 0xa9: /* XOR C */ - tStates += 4; /* XRA C 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) ^ BC) & 0xff]; - break; - - case 0xaa: /* XOR D */ - tStates += 4; /* XRA D 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF ^ DE) >> 8) & 0xff]; - break; - - case 0xab: /* XOR E */ - tStates += 4; /* XRA E 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) ^ DE) & 0xff]; - break; - - case 0xac: /* XOR H */ - tStates += 4; /* XRA H 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF ^ HL) >> 8) & 0xff]; - break; - - case 0xad: /* XOR L */ - tStates += 4; /* XRA L 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) ^ HL) & 0xff]; - break; - - case 0xae: /* XOR (HL) */ - tStates += 7; /* XRA M 7 */ - CHECK_BREAK_BYTE(HL); - AF = xororTable[((AF >> 8) ^ GetBYTE(HL)) & 0xff]; - break; - - case 0xaf: /* XOR A */ - tStates += 4; /* XRA A 4 */ - sim_brk_pend[0] = FALSE; - AF = 0x44; - break; - - case 0xb0: /* OR B */ - tStates += 4; /* ORA B 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF | BC) >> 8) & 0xff]; - break; - - case 0xb1: /* OR C */ - tStates += 4; /* ORA C 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) | BC) & 0xff]; - break; - - case 0xb2: /* OR D */ - tStates += 4; /* ORA D 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF | DE) >> 8) & 0xff]; - break; - - case 0xb3: /* OR E */ - tStates += 4; /* ORA E 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) | DE) & 0xff]; - break; - - case 0xb4: /* OR H */ - tStates += 4; /* ORA H 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF | HL) >> 8) & 0xff]; - break; - - case 0xb5: /* OR L */ - tStates += 4; /* ORA L 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) | HL) & 0xff]; - break; - - case 0xb6: /* OR (HL) */ - tStates += 7; /* ORA M 7 */ - CHECK_BREAK_BYTE(HL); - AF = xororTable[((AF >> 8) | GetBYTE(HL)) & 0xff]; - break; - - case 0xb7: /* OR A */ - tStates += 4; /* ORA A 4 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[(AF >> 8) & 0xff]; - break; - - case 0xb8: /* CP B */ - tStates += 4; /* CMP B 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(BC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xb9: /* CP C */ - tStates += 4; /* CMP C 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(BC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xba: /* CP D */ - tStates += 4; /* CMP D 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(DE); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xbb: /* CP E */ - tStates += 4; /* CMP E 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(DE); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xbc: /* CP H */ - tStates += 4; /* CMP H 4 */ - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xbd: /* CP L */ - tStates += 4; /* CMP L 4 */ - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xbe: /* CP (HL) */ - tStates += 7; /* CMP M 7 */ - CHECK_BREAK_BYTE(HL); - temp = GetBYTE(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xbf: /* CP A */ - tStates += 4; /* CMP A 4 */ - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(AF, (HIGH_REGISTER(AF) & 0x28) | (chiptype == CHIP_TYPE_Z80 ? 0x42 : 0x46)); - break; - - case 0xc0: /* RET NZ */ - if (TSTFLAG(Z)) { - sim_brk_pend[0] = FALSE; - tStates += 5; /* RNZ 5 */ - } - else { - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - tStates += 11; /* RNZ 11 */ - } - break; - - case 0xc1: /* POP BC */ - tStates += 10; /* POP B 10 */ - CHECK_BREAK_WORD(SP); - POP(BC); - break; - - case 0xc2: /* JP NZ,nnnn */ - sim_brk_pend[0] = FALSE; - JPC(!TSTFLAG(Z)); /* also updates tStates, Z80 and 8080 are equal */ - break; - - case 0xc3: /* JP nnnn */ - sim_brk_pend[0] = FALSE; - JPC(1); /* also updates tStates, Z80 and 8080 are equal */ - break; - - case 0xc4: /* CALL NZ,nnnn */ - CALLC(!TSTFLAG(Z)); /* also updates tStates */ - break; - - case 0xc5: /* PUSH BC */ - tStates += 11; /* PUSH B 11 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(BC); - break; - - case 0xc6: /* ADD A,nn */ - tStates += 7; /* ADI nn 7 */ - sim_brk_pend[0] = FALSE; - temp = RAM_PP(PC); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0xc7: /* RST 0 */ - tStates += 11; /* RST 0 11 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(PC); - PCQ_ENTRY(PCX); - PC = 0; - break; - - case 0xc8: /* RET Z */ - if (TSTFLAG(Z)) { - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - tStates += 11; /* RZ 11 */ - } - else { - sim_brk_pend[0] = FALSE; - tStates += 5; /* RZ 5 */ - } - break; - - case 0xc9: /* RET */ - tStates += 10; /* RET 10 */ - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - break; - - case 0xca: /* JP Z,nnnn */ - sim_brk_pend[0] = FALSE; - JPC(TSTFLAG(Z)); /* also updates tStates */ - break; - - case 0xcb: /* CB prefix */ - if (chiptype == CHIP_TYPE_8080) { - if (cpu_unit.flags & UNIT_CPU_OPSTOP) { - reason = STOP_OPCODE; - goto end_decode; - } - else { - sim_brk_pend[0] = FALSE; - JPC(1); - break; - } - } - adr = HL; - switch ((op = GetBYTE(PC)) & 7) { - - case 0: - sim_brk_pend[0] = tStateModifier = FALSE; - ++PC; - acu = HIGH_REGISTER(BC); - tStates += 8; - break; - - case 1: - sim_brk_pend[0] = tStateModifier = FALSE; - ++PC; - acu = LOW_REGISTER(BC); - tStates += 8; - break; - - case 2: - sim_brk_pend[0] = tStateModifier = FALSE; - ++PC; - acu = HIGH_REGISTER(DE); - tStates += 8; - break; - - case 3: - sim_brk_pend[0] = tStateModifier = FALSE; - ++PC; - acu = LOW_REGISTER(DE); - tStates += 8; - break; - - case 4: - sim_brk_pend[0] = tStateModifier = FALSE; - ++PC; - acu = HIGH_REGISTER(HL); - tStates += 8; - break; - - case 5: - sim_brk_pend[0] = tStateModifier = FALSE; - ++PC; - acu = LOW_REGISTER(HL); - tStates += 8; - break; - - case 6: - CHECK_BREAK_BYTE(adr); - ++PC; - acu = GetBYTE(adr); - tStateModifier = TRUE; - tStates += 15; - break; - - case 7: - sim_brk_pend[0] = tStateModifier = FALSE; - ++PC; - acu = HIGH_REGISTER(AF); - tStates += 8; - break; - } - switch (op & 0xc0) { - - case 0x00: /* shift/rotate */ - switch (op & 0x38) { - - case 0x00: /* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg1; - - case 0x08: /* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg1; - - case 0x10: /* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg1; - - case 0x18: /* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg1; - - case 0x20: /* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg1; - - case 0x28: /* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg1; - - case 0x30: /* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg1; - - case 0x38: /* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg1: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - /* !!cbits == 0 if cbits == 0 !!cbits == 1 if cbits > 0 */ - } - break; - - case 0x40: /* BIT */ - if (tStateModifier) - tStates -= 3; - if (acu & (1 << ((op >> 3) & 7))) - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - else - AF = (AF & ~0xfe) | 0x54; - if ((op & 7) != 6) - AF |= (acu & 0x28); - temp = acu; - break; - - case 0x80: /* RES */ - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - - case 0xc0: /* SET */ - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - - switch (op & 7) { - - case 0: - SET_HIGH_REGISTER(BC, temp); - break; - - case 1: - SET_LOW_REGISTER(BC, temp); - break; - - case 2: - SET_HIGH_REGISTER(DE, temp); - break; - - case 3: - SET_LOW_REGISTER(DE, temp); - break; - - case 4: - SET_HIGH_REGISTER(HL, temp); - break; - - case 5: - SET_LOW_REGISTER(HL, temp); - break; - - case 6: - PutBYTE(adr, temp); - break; - - case 7: - SET_HIGH_REGISTER(AF, temp); - break; - } - break; - - case 0xcc: /* CALL Z,nnnn */ - CALLC(TSTFLAG(Z)); /* also updates tStates */ - break; - - case 0xcd: /* CALL nnnn */ - CALLC(1); /* also updates tStates */ - break; - - case 0xce: /* ADC A,nn */ - tStates += 7; /* ACI nn 7 */ - sim_brk_pend[0] = FALSE; - temp = RAM_PP(PC); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0xcf: /* RST 8 */ - tStates += 11; /* RST 1 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(PC); - PCQ_ENTRY(PCX); - PC = 8; - break; - - case 0xd0: /* RET NC */ - if (TSTFLAG(C)) { - sim_brk_pend[0] = FALSE; - tStates += 5; /* RNC 5 */ - } - else { - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - tStates += 11; /* RNC 11 */ - } - break; - - case 0xd1: /* POP DE */ - tStates += 10; /* POP D 10 */ - CHECK_BREAK_WORD(SP); - POP(DE); - break; - - case 0xd2: /* JP NC,nnnn */ - sim_brk_pend[0] = FALSE; - JPC(!TSTFLAG(C)); /* also updates tStates */ - break; - - case 0xd3: /* OUT (nn),A */ - tStates += (chiptype == CHIP_TYPE_8080 ? 10 :11); /* OUT nn 10 */ - sim_brk_pend[0] = FALSE; - out(RAM_PP(PC), HIGH_REGISTER(AF)); - break; - - case 0xd4: /* CALL NC,nnnn */ - CALLC(!TSTFLAG(C)); /* also updates tStates */ - break; - - case 0xd5: /* PUSH DE */ - tStates += 11; /* PUSH D 11 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(DE); - break; - - case 0xd6: /* SUB nn */ - tStates += 7; /* SUI nn 7 */ - sim_brk_pend[0] = FALSE; - temp = RAM_PP(PC); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0xd7: /* RST 10H */ - tStates += 11; /* RST 2 11 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(PC); - PCQ_ENTRY(PCX); - PC = 0x10; - break; - - case 0xd8: /* RET C */ - if (TSTFLAG(C)) { - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - tStates += 11; /* RC 11 */ - } - else { - sim_brk_pend[0] = FALSE; - tStates += 5; /* RC 5 */ - } - break; - - case 0xd9: /* EXX */ - if (chiptype == CHIP_TYPE_8080) { - if (cpu_unit.flags & UNIT_CPU_OPSTOP) { - reason = STOP_OPCODE; - goto end_decode; - } - else { - tStates += 10; /* RET 10 */ - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - break; - } - } - tStates += 4; - sim_brk_pend[0] = FALSE; - temp = BC; - BC = BC1_S; - BC1_S = temp; - temp = DE; - DE = DE1_S; - DE1_S = temp; - temp = HL; - HL = HL1_S; - HL1_S = temp; - break; - - case 0xda: /* JP C,nnnn */ - sim_brk_pend[0] = FALSE; - JPC(TSTFLAG(C)); /* also updates tStates */ - break; - - case 0xdb: /* IN A,(nn) */ - tStates += (chiptype == CHIP_TYPE_8080 ? 10 : 11); /* IN nn 10 */ - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(AF, in(RAM_PP(PC))); - break; - - case 0xdc: /* CALL C,nnnn */ - CALLC(TSTFLAG(C)); /* also updates tStates */ - break; - - case 0xdd: /* DD prefix */ - if (chiptype == CHIP_TYPE_8080) { - if (cpu_unit.flags & UNIT_CPU_OPSTOP) { - reason = STOP_OPCODE; - goto end_decode; - } - else { - CALLC(1); /* also updates tStates */ - break; - } - } - switch (RAM_PP(PC)) { - - case 0x09: /* ADD IX,BC */ - tStates += 15; - sim_brk_pend[0] = FALSE; - IX &= ADDRMASK; - BC &= ADDRMASK; - sum = IX + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ BC ^ sum) >> 8]; - IX = sum; - break; - - case 0x19: /* ADD IX,DE */ - tStates += 15; - sim_brk_pend[0] = FALSE; - IX &= ADDRMASK; - DE &= ADDRMASK; - sum = IX + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ DE ^ sum) >> 8]; - IX = sum; - break; - - case 0x21: /* LD IX,nnnn */ - tStates += 14; - sim_brk_pend[0] = FALSE; - IX = GET_WORD(PC); - PC += 2; - break; - - case 0x22: /* LD (nnnn),IX */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - PutWORD(temp, IX); - PC += 2; - break; - - case 0x23: /* INC IX */ - tStates += 10; - sim_brk_pend[0] = FALSE; - ++IX; - break; - - case 0x24: /* INC IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - IX += 0x100; - AF = (AF & ~0xfe) | incZ80Table[HIGH_REGISTER(IX)]; - break; - - case 0x25: /* DEC IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - IX -= 0x100; - AF = (AF & ~0xfe) | decZ80Table[HIGH_REGISTER(IX)]; - break; - - case 0x26: /* LD IXH,nn */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IX, RAM_PP(PC)); - break; - - case 0x29: /* ADD IX,IX */ - tStates += 15; - sim_brk_pend[0] = FALSE; - IX &= ADDRMASK; - sum = IX + IX; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - IX = sum; - break; - - case 0x2a: /* LD IX,(nnnn) */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - IX = GET_WORD(temp); - PC += 2; - break; - - case 0x2b: /* DEC IX */ - tStates += 10; - sim_brk_pend[0] = FALSE; - --IX; - break; - - case 0x2c: /* INC IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IX) + 1; - SET_LOW_REGISTER(IX, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - - case 0x2d: /* DEC IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IX) - 1; - SET_LOW_REGISTER(IX, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - - case 0x2e: /* LD IXL,nn */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IX, RAM_PP(PC)); - break; - - case 0x34: /* INC (IX+dd) */ - tStates += 23; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr) + 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - - case 0x35: /* DEC (IX+dd) */ - tStates += 23; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr) - 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - - case 0x36: /* LD (IX+dd),nn */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, RAM_PP(PC)); - break; - - case 0x39: /* ADD IX,SP */ - tStates += 15; - sim_brk_pend[0] = FALSE; - IX &= ADDRMASK; - SP &= ADDRMASK; - sum = IX + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ SP ^ sum) >> 8]; - IX = sum; - break; - - case 0x44: /* LD B,IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(BC, HIGH_REGISTER(IX)); - break; - - case 0x45: /* LD B,IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(BC, LOW_REGISTER(IX)); - break; - - case 0x46: /* LD B,(IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_HIGH_REGISTER(BC, GetBYTE(adr)); - break; - - case 0x4c: /* LD C,IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(BC, HIGH_REGISTER(IX)); - break; - - case 0x4d: /* LD C,IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(BC, LOW_REGISTER(IX)); - break; - - case 0x4e: /* LD C,(IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_LOW_REGISTER(BC, GetBYTE(adr)); - break; - - case 0x54: /* LD D,IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(DE, HIGH_REGISTER(IX)); - break; - - case 0x55: /* LD D,IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(DE, LOW_REGISTER(IX)); - break; - - case 0x56: /* LD D,(IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_HIGH_REGISTER(DE, GetBYTE(adr)); - break; - - case 0x5c: /* LD E,IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(DE, HIGH_REGISTER(IX)); - break; - - case 0x5d: /* LD E,IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(DE, LOW_REGISTER(IX)); - break; - - case 0x5e: /* LD E,(IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_LOW_REGISTER(DE, GetBYTE(adr)); - break; - - case 0x60: /* LD IXH,B */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IX, HIGH_REGISTER(BC)); - break; - - case 0x61: /* LD IXH,C */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IX, LOW_REGISTER(BC)); - break; - - case 0x62: /* LD IXH,D */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IX, HIGH_REGISTER(DE)); - break; - - case 0x63: /* LD IXH,E */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IX, LOW_REGISTER(DE)); - break; - - case 0x64: /* LD IXH,IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; /* nop */ - break; - - case 0x65: /* LD IXH,IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IX, LOW_REGISTER(IX)); - break; - - case 0x66: /* LD H,(IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_HIGH_REGISTER(HL, GetBYTE(adr)); - break; - - case 0x67: /* LD IXH,A */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IX, HIGH_REGISTER(AF)); - break; - - case 0x68: /* LD IXL,B */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IX, HIGH_REGISTER(BC)); - break; - - case 0x69: /* LD IXL,C */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IX, LOW_REGISTER(BC)); - break; - - case 0x6a: /* LD IXL,D */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IX, HIGH_REGISTER(DE)); - break; - - case 0x6b: /* LD IXL,E */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IX, LOW_REGISTER(DE)); - break; - - case 0x6c: /* LD IXL,IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IX, HIGH_REGISTER(IX)); - break; - - case 0x6d: /* LD IXL,IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; /* nop */ - break; - - case 0x6e: /* LD L,(IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_LOW_REGISTER(HL, GetBYTE(adr)); - break; - - case 0x6f: /* LD IXL,A */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IX, HIGH_REGISTER(AF)); - break; - - case 0x70: /* LD (IX+dd),B */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, HIGH_REGISTER(BC)); - break; - - case 0x71: /* LD (IX+dd),C */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, LOW_REGISTER(BC)); - break; - - case 0x72: /* LD (IX+dd),D */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, HIGH_REGISTER(DE)); - break; - - case 0x73: /* LD (IX+dd),E */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, LOW_REGISTER(DE)); - break; - - case 0x74: /* LD (IX+dd),H */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, HIGH_REGISTER(HL)); - break; - - case 0x75: /* LD (IX+dd),L */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, LOW_REGISTER(HL)); - break; - - case 0x77: /* LD (IX+dd),A */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, HIGH_REGISTER(AF)); - break; - - case 0x7c: /* LD A,IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(AF, HIGH_REGISTER(IX)); - break; - - case 0x7d: /* LD A,IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(AF, LOW_REGISTER(IX)); - break; - - case 0x7e: /* LD A,(IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_HIGH_REGISTER(AF, GetBYTE(adr)); - break; - - case 0x84: /* ADD A,IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x85: /* ADD A,IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x86: /* ADD A,(IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8c: /* ADC A,IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8d: /* ADC A,IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8e: /* ADC A,(IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x96: /* SUB (IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x94: /* SUB IXH */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - - case 0x9c: /* SBC A,IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x95: /* SUB IXL */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - - case 0x9d: /* SBC A,IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x9e: /* SBC A,(IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xa4: /* AND IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = andTable[((AF & IX) >> 8) & 0xff]; - break; - - case 0xa5: /* AND IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = andTable[((AF >> 8) & IX) & 0xff]; - break; - - case 0xa6: /* AND (IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - AF = andTable[((AF >> 8) & GetBYTE(adr)) & 0xff]; - break; - - case 0xac: /* XOR IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF ^ IX) >> 8) & 0xff]; - break; - - case 0xad: /* XOR IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) ^ IX) & 0xff]; - break; - - case 0xae: /* XOR (IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - AF = xororTable[((AF >> 8) ^ GetBYTE(adr)) & 0xff]; - break; - - case 0xb4: /* OR IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF | IX) >> 8) & 0xff]; - break; - - case 0xb5: /* OR IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) | IX) & 0xff]; - break; - - case 0xb6: /* OR (IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - AF = xororTable[((AF >> 8) | GetBYTE(adr)) & 0xff]; - break; - - case 0xbc: /* CP IXH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(IX); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xbd: /* CP IXL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IX); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xbe: /* CP (IX+dd) */ - tStates += 19; - adr = IX + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xcb: /* CB prefix */ - adr = IX + (int8) RAM_PP(PC); - switch ((op = GetBYTE(PC)) & 7) { - - case 0: - sim_brk_pend[0] = FALSE; - ++PC; - acu = HIGH_REGISTER(BC); - break; - - case 1: - sim_brk_pend[0] = FALSE; - ++PC; - acu = LOW_REGISTER(BC); - break; - - case 2: - sim_brk_pend[0] = FALSE; - ++PC; - acu = HIGH_REGISTER(DE); - break; - - case 3: - sim_brk_pend[0] = FALSE; - ++PC; - acu = LOW_REGISTER(DE); - break; - - case 4: - sim_brk_pend[0] = FALSE; - ++PC; - acu = HIGH_REGISTER(HL); - break; - - case 5: - sim_brk_pend[0] = FALSE; - ++PC; - acu = LOW_REGISTER(HL); - break; - - case 6: - CHECK_BREAK_BYTE(adr); - ++PC; - acu = GetBYTE(adr); - break; - - case 7: - sim_brk_pend[0] = FALSE; - ++PC; - acu = HIGH_REGISTER(AF); - break; - } - switch (op & 0xc0) { - - case 0x00: /* shift/rotate */ - tStates += 23; - switch (op & 0x38) { - - case 0x00: /* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg2; - - case 0x08: /* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg2; - - case 0x10: /* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg2; - - case 0x18: /* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg2; - - case 0x20: /* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg2; - - case 0x28: /* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg2; - - case 0x30: /* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg2; - - case 0x38: /* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg2: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - /* !!cbits == 0 if cbits == 0 !!cbits == 1 if cbits > 0 */ - } - break; - - case 0x40: /* BIT */ - tStates += 20; - if (acu & (1 << ((op >> 3) & 7))) - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - else - AF = (AF & ~0xfe) | 0x54; - if ((op & 7) != 6) - AF |= (acu & 0x28); - temp = acu; - break; - - case 0x80: /* RES */ - tStates += 23; - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - - case 0xc0: /* SET */ - tStates += 23; - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - switch (op & 7) { - - case 0: - SET_HIGH_REGISTER(BC, temp); - break; - - case 1: - SET_LOW_REGISTER(BC, temp); - break; - - case 2: - SET_HIGH_REGISTER(DE, temp); - break; - - case 3: - SET_LOW_REGISTER(DE, temp); - break; - - case 4: - SET_HIGH_REGISTER(HL, temp); - break; - - case 5: - SET_LOW_REGISTER(HL, temp); - break; - - case 6: - PutBYTE(adr, temp); - break; - - case 7: - SET_HIGH_REGISTER(AF, temp); - break; - } - break; - - case 0xe1: /* POP IX */ - tStates += 14; - CHECK_BREAK_WORD(SP); - POP(IX); - break; - - case 0xe3: /* EX (SP),IX */ - tStates += 23; - CHECK_BREAK_WORD(SP); - temp = IX; - POP(IX); - PUSH(temp); - break; - - case 0xe5: /* PUSH IX */ - tStates += 15; - CHECK_BREAK_WORD(SP - 2); - PUSH(IX); - break; - - case 0xe9: /* JP (IX) */ - tStates += 8; - sim_brk_pend[0] = FALSE; - PCQ_ENTRY(PCX); - PC = IX; - break; - - case 0xf9: /* LD SP,IX */ - tStates += 10; - sim_brk_pend[0] = FALSE; - SP = IX; - break; - - default: /* ignore DD */ - sim_brk_pend[0] = FALSE; - CHECK_CPU_Z80; - PC--; - } - break; - - case 0xde: /* SBC A,nn */ - tStates += 7; /* SBI nn 7 */ - sim_brk_pend[0] = FALSE; - temp = RAM_PP(PC); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0xdf: /* RST 18H */ - tStates += 11; /* RST 3 11 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(PC); - PCQ_ENTRY(PCX); - PC = 0x18; - break; - - case 0xe0: /* RET PO */ - if (TSTFLAG(P)) { - sim_brk_pend[0] = FALSE; - tStates += 5; /* RPO 5 */ - } - else { - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - tStates += 11; /* RPO 11 */ - } - break; - - case 0xe1: /* POP HL */ - tStates += 10; /* POP H 10 */ - CHECK_BREAK_WORD(SP); - POP(HL); - break; - - case 0xe2: /* JP PO,nnnn */ - sim_brk_pend[0] = FALSE; - JPC(!TSTFLAG(P)); /* also updates tStates */ - break; - - case 0xe3: /* EX (SP),HL */ - tStates += (chiptype == CHIP_TYPE_8080 ? 18 : 19); /* XTHL 18 */ - CHECK_BREAK_WORD(SP); - temp = HL; - POP(HL); - PUSH(temp); - break; - - case 0xe4: /* CALL PO,nnnn */ - CALLC(!TSTFLAG(P)); /* also updates tStates */ - break; - - case 0xe5: /* PUSH HL */ - tStates += 11; /* PUSH H 11 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(HL); - break; - - case 0xe6: /* AND nn */ - tStates += 7; /* ANI nn 7 */ - sim_brk_pend[0] = FALSE; - AF = andTable[((AF >> 8) & RAM_PP(PC)) & 0xff]; - break; - - case 0xe7: /* RST 20H */ - tStates += 11; /* RST 4 11 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(PC); - PCQ_ENTRY(PCX); - PC = 0x20; - break; - - case 0xe8: /* RET PE */ - if (TSTFLAG(P)) { - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - tStates += 11; /* RPE 11 */ - } - else { - sim_brk_pend[0] = FALSE; - tStates += 5; /* RPE 5 */ - } - break; - - case 0xe9: /* JP (HL) */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* PCHL 5 */ - sim_brk_pend[0] = FALSE; - PCQ_ENTRY(PCX); - PC = HL; - break; - - case 0xea: /* JP PE,nnnn */ - sim_brk_pend[0] = FALSE; - JPC(TSTFLAG(P)); /* also updates tStates */ - break; - - case 0xeb: /* EX DE,HL */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 4); /* XCHG 5 */ - sim_brk_pend[0] = FALSE; - temp = HL; - HL = DE; - DE = temp; - break; - - case 0xec: /* CALL PE,nnnn */ - CALLC(TSTFLAG(P)); /* also updates tStates */ - break; - - case 0xed: /* ED prefix */ - if (chiptype == CHIP_TYPE_8080) { - if (cpu_unit.flags & UNIT_CPU_OPSTOP) { - reason = STOP_OPCODE; - goto end_decode; - } - else { - CALLC(1); /* also updates tStates */ - break; - } - } - switch (RAM_PP(PC)) { - - case 0x40: /* IN B,(C) */ - tStates += 12; - sim_brk_pend[0] = FALSE; - temp = in(LOW_REGISTER(BC)); - SET_HIGH_REGISTER(BC, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x41: /* OUT (C),B */ - tStates += 12; - sim_brk_pend[0] = FALSE; - out(LOW_REGISTER(BC), HIGH_REGISTER(BC)); - break; - - case 0x42: /* SBC HL,BC */ - tStates += 15; - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL - BC - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ BC ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - - case 0x43: /* LD (nnnn),BC */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - PutWORD(temp, BC); - PC += 2; - break; - - case 0x44: /* NEG */ - - case 0x4C: /* NEG, unofficial */ - - case 0x54: /* NEG, unofficial */ - - case 0x5C: /* NEG, unofficial */ - - case 0x64: /* NEG, unofficial */ - - case 0x6C: /* NEG, unofficial */ - - case 0x74: /* NEG, unofficial */ - - case 0x7C: /* NEG, unofficial */ - tStates += 8; - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(AF); - AF = ((~(AF & 0xff00) + 1) & 0xff00); /* AF = (-(AF & 0xff00) & 0xff00); */ - AF |= ((AF >> 8) & 0xa8) | (((AF & 0xff00) == 0) << 6) | negTable[temp]; - break; - - case 0x45: /* RETN */ - - case 0x55: /* RETN, unofficial */ - - case 0x5D: /* RETN, unofficial */ - - case 0x65: /* RETN, unofficial */ - - case 0x6D: /* RETN, unofficial */ - - case 0x75: /* RETN, unofficial */ - - case 0x7D: /* RETN, unofficial */ - tStates += 14; - IFF_S |= IFF_S >> 1; - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - break; - - case 0x46: /* IM 0 */ - tStates += 8; - sim_brk_pend[0] = FALSE; - /* interrupt mode 0 */ - break; - - case 0x47: /* LD I,A */ - tStates += 9; - sim_brk_pend[0] = FALSE; - IR_S = (IR_S & 0xff) | (AF & ~0xff); - break; - - case 0x48: /* IN C,(C) */ - tStates += 12; - sim_brk_pend[0] = FALSE; - temp = in(LOW_REGISTER(BC)); - SET_LOW_REGISTER(BC, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x49: /* OUT (C),C */ - tStates += 12; - sim_brk_pend[0] = FALSE; - out(LOW_REGISTER(BC), LOW_REGISTER(BC)); - break; - - case 0x4a: /* ADC HL,BC */ - tStates += 15; - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL + BC + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ BC ^ sum) >> 8]; - HL = sum; - break; - - case 0x4b: /* LD BC,(nnnn) */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - BC = GET_WORD(temp); - PC += 2; - break; - - case 0x4d: /* RETI */ - tStates += 14; - IFF_S |= IFF_S >> 1; - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - break; - - case 0x4f: /* LD R,A */ - tStates += 9; - sim_brk_pend[0] = FALSE; - IR_S = (IR_S & ~0xff) | ((AF >> 8) & 0xff); - break; - - case 0x50: /* IN D,(C) */ - tStates += 12; - sim_brk_pend[0] = FALSE; - temp = in(LOW_REGISTER(BC)); - SET_HIGH_REGISTER(DE, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x51: /* OUT (C),D */ - tStates += 12; - sim_brk_pend[0] = FALSE; - out(LOW_REGISTER(BC), HIGH_REGISTER(DE)); - break; - - case 0x52: /* SBC HL,DE */ - tStates += 15; - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL - DE - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ DE ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - - case 0x53: /* LD (nnnn),DE */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - PutWORD(temp, DE); - PC += 2; - break; - - case 0x56: /* IM 1 */ - tStates += 8; - sim_brk_pend[0] = FALSE; - /* interrupt mode 1 */ - break; - - case 0x57: /* LD A,I */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = (AF & 0x29) | (IR_S & ~0xff) | ((IR_S >> 8) & 0x80) | (((IR_S & ~0xff) == 0) << 6) | ((IFF_S & 2) << 1); - break; - - case 0x58: /* IN E,(C) */ - tStates += 12; - sim_brk_pend[0] = FALSE; - temp = in(LOW_REGISTER(BC)); - SET_LOW_REGISTER(DE, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x59: /* OUT (C),E */ - tStates += 12; - sim_brk_pend[0] = FALSE; - out(LOW_REGISTER(BC), LOW_REGISTER(DE)); - break; - - case 0x5a: /* ADC HL,DE */ - tStates += 15; - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL + DE + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ DE ^ sum) >> 8]; - HL = sum; - break; - - case 0x5b: /* LD DE,(nnnn) */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - DE = GET_WORD(temp); - PC += 2; - break; - - case 0x5e: /* IM 2 */ - tStates += 8; - sim_brk_pend[0] = FALSE; - /* interrupt mode 2 */ - break; - - case 0x5f: /* LD A,R */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = (AF & 0x29) | ((IR_S & 0xff) << 8) | (IR_S & 0x80) | - (((IR_S & 0xff) == 0) << 6) | ((IFF_S & 2) << 1); - break; - - case 0x60: /* IN H,(C) */ - tStates += 12; - sim_brk_pend[0] = FALSE; - temp = in(LOW_REGISTER(BC)); - SET_HIGH_REGISTER(HL, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x61: /* OUT (C),H */ - tStates += 12; - sim_brk_pend[0] = FALSE; - out(LOW_REGISTER(BC), HIGH_REGISTER(HL)); - break; - - case 0x62: /* SBC HL,HL */ - tStates += 15; - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - sum = HL - HL - TSTFLAG(C); - AF = (AF & ~0xff) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80DupTable[(sum >> 8) & 0x1ff]; - HL = sum; - break; - - case 0x63: /* LD (nnnn),HL */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - PutWORD(temp, HL); - PC += 2; - break; - - case 0x67: /* RRD */ - tStates += 18; - sim_brk_pend[0] = FALSE; - temp = GetBYTE(HL); - acu = HIGH_REGISTER(AF); - PutBYTE(HL, HIGH_DIGIT(temp) | (LOW_DIGIT(acu) << 4)); - AF = rrdrldTable[(acu & 0xf0) | LOW_DIGIT(temp)] | (AF & 1); - break; - - case 0x68: /* IN L,(C) */ - tStates += 12; - sim_brk_pend[0] = FALSE; - temp = in(LOW_REGISTER(BC)); - SET_LOW_REGISTER(HL, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x69: /* OUT (C),L */ - tStates += 12; - sim_brk_pend[0] = FALSE; - out(LOW_REGISTER(BC), LOW_REGISTER(HL)); - break; - - case 0x6a: /* ADC HL,HL */ - tStates += 15; - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - sum = HL + HL + TSTFLAG(C); - AF = (AF & ~0xff) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80DupTable[sum >> 8]; - HL = sum; - break; - - case 0x6b: /* LD HL,(nnnn) */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - HL = GET_WORD(temp); - PC += 2; - break; - - case 0x6f: /* RLD */ - tStates += 18; - sim_brk_pend[0] = FALSE; - temp = GetBYTE(HL); - acu = HIGH_REGISTER(AF); - PutBYTE(HL, (LOW_DIGIT(temp) << 4) | LOW_DIGIT(acu)); - AF = rrdrldTable[(acu & 0xf0) | HIGH_DIGIT(temp)] | (AF & 1); - break; - - case 0x70: /* IN (C) */ - tStates += 12; - sim_brk_pend[0] = FALSE; - temp = in(LOW_REGISTER(BC)); - SET_LOW_REGISTER(temp, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x71: /* OUT (C),0 */ - tStates += 12; - sim_brk_pend[0] = FALSE; - out(LOW_REGISTER(BC), 0); - break; - - case 0x72: /* SBC HL,SP */ - tStates += 15; - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL - SP - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ SP ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - - case 0x73: /* LD (nnnn),SP */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - PutWORD(temp, SP); - PC += 2; - break; - - case 0x78: /* IN A,(C) */ - tStates += 12; - sim_brk_pend[0] = FALSE; - temp = in(LOW_REGISTER(BC)); - SET_HIGH_REGISTER(AF, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x79: /* OUT (C),A */ - tStates += 12; - sim_brk_pend[0] = FALSE; - out(LOW_REGISTER(BC), HIGH_REGISTER(AF)); - break; - - case 0x7a: /* ADC HL,SP */ - tStates += 15; - sim_brk_pend[0] = FALSE; - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL + SP + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ SP ^ sum) >> 8]; - HL = sum; - break; - - case 0x7b: /* LD SP,(nnnn) */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - SP = GET_WORD(temp); - PC += 2; - break; - - case 0xa0: /* LDI */ - tStates += 16; - CHECK_BREAK_TWO_BYTES(HL, DE); - acu = RAM_PP(HL); - PUT_BYTE_PP(DE, acu); - acu += HIGH_REGISTER(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) | - (((--BC & ADDRMASK) != 0) << 2); - break; - - case 0xa1: /* CPI */ - tStates += 16; - CHECK_BREAK_BYTE(HL); - acu = HIGH_REGISTER(AF); - temp = RAM_PP(HL); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | (cbits & 16) | - ((sum - ((cbits >> 4) & 1)) & 8) | - ((--BC & ADDRMASK) != 0) << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) - AF &= ~8; - break; - -/* SF, ZF, YF, XF flags are affected by decreasing register B, as in DEC B. - NF flag A is copy of bit 7 of the value read from or written to an I/O port. - INI/INIR/IND/INDR use the C flag in stead of the L register. There is a - catch though, because not the value of C is used, but C + 1 if it's INI/INIR or - C - 1 if it's IND/INDR. So, first of all INI/INIR: - HF and CF Both set if ((HL) + ((C + 1) & 255) > 255) - PF The parity of (((HL) + ((C + 1) & 255)) & 7) xor B) */ - case 0xa2: /* INI */ - tStates += 16; - CHECK_BREAK_BYTE(HL); - acu = in(LOW_REGISTER(BC)); - PutBYTE(HL, acu); - ++HL; - temp = HIGH_REGISTER(BC); - BC -= 0x100; - INOUTFLAGS_NONZERO((LOW_REGISTER(BC) + 1) & 0xff); - break; - -/* SF, ZF, YF, XF flags are affected by decreasing register B, as in DEC B. - NF flag A is copy of bit 7 of the value read from or written to an I/O port. - And now the for OUTI/OTIR/OUTD/OTDR instructions. Take state of the L - after the increment or decrement of HL; add the value written to the I/O port - to; call that k for now. If k > 255, then the CF and HF flags are set. The PF - flags is set like the parity of k bitwise and'ed with 7, bitwise xor'ed with B. - HF and CF Both set if ((HL) + L > 255) - PF The parity of ((((HL) + L) & 7) xor B) */ - case 0xa3: /* OUTI */ - tStates += 16; - CHECK_BREAK_BYTE(HL); - acu = GetBYTE(HL); - out(LOW_REGISTER(BC), acu); - ++HL; - temp = HIGH_REGISTER(BC); - BC -= 0x100; - INOUTFLAGS_NONZERO(LOW_REGISTER(HL)); - break; - - case 0xa8: /* LDD */ - tStates += 16; - CHECK_BREAK_TWO_BYTES(HL, DE); - acu = RAM_MM(HL); - PUT_BYTE_MM(DE, acu); - acu += HIGH_REGISTER(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) | - (((--BC & ADDRMASK) != 0) << 2); - break; - - case 0xa9: /* CPD */ - tStates += 16; - CHECK_BREAK_BYTE(HL); - acu = HIGH_REGISTER(AF); - temp = RAM_MM(HL); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | (cbits & 16) | - ((sum - ((cbits >> 4) & 1)) & 8) | - ((--BC & ADDRMASK) != 0) << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) - AF &= ~8; - break; - -/* SF, ZF, YF, XF flags are affected by decreasing register B, as in DEC B. - NF flag A is copy of bit 7 of the value read from or written to an I/O port. - INI/INIR/IND/INDR use the C flag in stead of the L register. There is a - catch though, because not the value of C is used, but C + 1 if it's INI/INIR or - C - 1 if it's IND/INDR. And last IND/INDR: - HF and CF Both set if ((HL) + ((C - 1) & 255) > 255) - PF The parity of (((HL) + ((C - 1) & 255)) & 7) xor B) */ - case 0xaa: /* IND */ - tStates += 16; - CHECK_BREAK_BYTE(HL); - acu = in(LOW_REGISTER(BC)); - PutBYTE(HL, acu); - --HL; - temp = HIGH_REGISTER(BC); - BC -= 0x100; - INOUTFLAGS_NONZERO((LOW_REGISTER(BC) - 1) & 0xff); - break; - - case 0xab: /* OUTD */ - tStates += 16; - CHECK_BREAK_BYTE(HL); - acu = GetBYTE(HL); - out(LOW_REGISTER(BC), acu); - --HL; - temp = HIGH_REGISTER(BC); - BC -= 0x100; - INOUTFLAGS_NONZERO(LOW_REGISTER(HL)); - break; - - case 0xb0: /* LDIR */ - tStates -= 5; - BC &= ADDRMASK; - if (BC == 0) - BC = 0x10000; - do { - tStates += 21; - CHECK_BREAK_TWO_BYTES(HL, DE); - acu = RAM_PP(HL); - PUT_BYTE_PP(DE, acu); - } while (--BC); - acu += HIGH_REGISTER(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4); - break; - - case 0xb1: /* CPIR */ - tStates -= 5; - acu = HIGH_REGISTER(AF); - BC &= ADDRMASK; - if (BC == 0) - BC = 0x10000; - do { - tStates += 21; - CHECK_BREAK_BYTE(HL); - temp = RAM_PP(HL); - op = --BC != 0; - sum = acu - temp; - } while (op && sum != 0); - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | - (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) | - op << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) - AF &= ~8; - break; - - case 0xb2: /* INIR */ - tStates -= 5; - temp = HIGH_REGISTER(BC); - if (temp == 0) - temp = 0x100; - do { - tStates += 21; - CHECK_BREAK_BYTE(HL); - acu = in(LOW_REGISTER(BC)); - PutBYTE(HL, acu); - ++HL; - } while (--temp); - temp = HIGH_REGISTER(BC); - SET_HIGH_REGISTER(BC, 0); - INOUTFLAGS_ZERO((LOW_REGISTER(BC) + 1) & 0xff); - break; - - case 0xb3: /* OTIR */ - tStates -= 5; - temp = HIGH_REGISTER(BC); - if (temp == 0) - temp = 0x100; - do { - tStates += 21; - CHECK_BREAK_BYTE(HL); - acu = GetBYTE(HL); - out(LOW_REGISTER(BC), acu); - ++HL; - } while (--temp); - temp = HIGH_REGISTER(BC); - SET_HIGH_REGISTER(BC, 0); - INOUTFLAGS_ZERO(LOW_REGISTER(HL)); - break; - - case 0xb8: /* LDDR */ - tStates -= 5; - BC &= ADDRMASK; - if (BC == 0) - BC = 0x10000; - do { - tStates += 21; - CHECK_BREAK_TWO_BYTES(HL, DE); - acu = RAM_MM(HL); - PUT_BYTE_MM(DE, acu); - } while (--BC); - acu += HIGH_REGISTER(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4); - break; - - case 0xb9: /* CPDR */ - tStates -= 5; - acu = HIGH_REGISTER(AF); - BC &= ADDRMASK; - if (BC == 0) - BC = 0x10000; - do { - tStates += 21; - CHECK_BREAK_BYTE(HL); - temp = RAM_MM(HL); - op = --BC != 0; - sum = acu - temp; - } while (op && sum != 0); - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | - (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) | - op << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) - AF &= ~8; - break; - - case 0xba: /* INDR */ - tStates -= 5; - temp = HIGH_REGISTER(BC); - if (temp == 0) - temp = 0x100; - do { - tStates += 21; - CHECK_BREAK_BYTE(HL); - acu = in(LOW_REGISTER(BC)); - PutBYTE(HL, acu); - --HL; - } while (--temp); - temp = HIGH_REGISTER(BC); - SET_HIGH_REGISTER(BC, 0); - INOUTFLAGS_ZERO((LOW_REGISTER(BC) - 1) & 0xff); - break; - - case 0xbb: /* OTDR */ - tStates -= 5; - temp = HIGH_REGISTER(BC); - if (temp == 0) - temp = 0x100; - do { - tStates += 21; - CHECK_BREAK_BYTE(HL); - acu = GetBYTE(HL); - out(LOW_REGISTER(BC), acu); - --HL; - } while (--temp); - temp = HIGH_REGISTER(BC); - SET_HIGH_REGISTER(BC, 0); - INOUTFLAGS_ZERO(LOW_REGISTER(HL)); - break; - - default: /* ignore ED and following byte */ - sim_brk_pend[0] = FALSE; - CHECK_CPU_Z80; - } - break; - - case 0xee: /* XOR nn */ - tStates += 7; /* XRI nn 7 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) ^ RAM_PP(PC)) & 0xff]; - break; - - case 0xef: /* RST 28H */ - tStates += 11; /* RST 5 11 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(PC); - PCQ_ENTRY(PCX); - PC = 0x28; - break; - - case 0xf0: /* RET P */ - if (TSTFLAG(S)) { - sim_brk_pend[0] = FALSE; - tStates += 5; /* RP 5 */ - } - else { - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - tStates += 11; /* RP 11 */ - } - break; - - case 0xf1: /* POP AF */ - tStates += 10; /* POP PSW 10 */ - CHECK_BREAK_WORD(SP); - POP(AF); - break; - - case 0xf2: /* JP P,nnnn */ - sim_brk_pend[0] = FALSE; - JPC(!TSTFLAG(S)); /* also updates tStates */ - break; - - case 0xf3: /* DI */ - tStates += 4; /* DI 4 */ - sim_brk_pend[0] = FALSE; - IFF_S = 0; - break; - - case 0xf4: /* CALL P,nnnn */ - CALLC(!TSTFLAG(S)); /* also updates tStates */ - break; - - case 0xf5: /* PUSH AF */ - tStates += 11; /* PUSH PSW 11 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(AF); - break; - - case 0xf6: /* OR nn */ - tStates += 7; /* ORI nn 7 */ - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) | RAM_PP(PC)) & 0xff]; - break; - - case 0xf7: /* RST 30H */ - tStates += 11; /* RST 6 11 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(PC); - PCQ_ENTRY(PCX); - PC = 0x30; - break; - - case 0xf8: /* RET M */ - if (TSTFLAG(S)) { - CHECK_BREAK_WORD(SP); - PCQ_ENTRY(PCX); - POP(PC); - tStates += 11; /* RM 11 */ - } - else { - sim_brk_pend[0] = FALSE; - tStates += 5; /* RM 5 */ - } - break; - - case 0xf9: /* LD SP,HL */ - tStates += (chiptype == CHIP_TYPE_8080 ? 5 : 6); /* SPHL 5 */ - sim_brk_pend[0] = FALSE; - SP = HL; - break; - - case 0xfa: /* JP M,nnnn */ - sim_brk_pend[0] = FALSE; - JPC(TSTFLAG(S)); /* also updates tStates */ - break; - - case 0xfb: /* EI */ - tStates += 4; /* EI 4 */ - sim_brk_pend[0] = FALSE; - IFF_S = 3; - break; - - case 0xfc: /* CALL M,nnnn */ - CALLC(TSTFLAG(S)); /* also updates tStates */ - break; - - case 0xfd: /* FD prefix */ - if (chiptype == CHIP_TYPE_8080) { - if (cpu_unit.flags & UNIT_CPU_OPSTOP) { - reason = STOP_OPCODE; - goto end_decode; - } - else { - CALLC(1); /* also updates tStates */ - break; - } - } - switch (RAM_PP(PC)) { - - case 0x09: /* ADD IY,BC */ - tStates += 15; - sim_brk_pend[0] = FALSE; - IY &= ADDRMASK; - BC &= ADDRMASK; - sum = IY + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ BC ^ sum) >> 8]; - IY = sum; - break; - - case 0x19: /* ADD IY,DE */ - tStates += 15; - sim_brk_pend[0] = FALSE; - IY &= ADDRMASK; - DE &= ADDRMASK; - sum = IY + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ DE ^ sum) >> 8]; - IY = sum; - break; - - case 0x21: /* LD IY,nnnn */ - tStates += 14; - sim_brk_pend[0] = FALSE; - IY = GET_WORD(PC); - PC += 2; - break; - - case 0x22: /* LD (nnnn),IY */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - PutWORD(temp, IY); - PC += 2; - break; - - case 0x23: /* INC IY */ - tStates += 10; - sim_brk_pend[0] = FALSE; - ++IY; - break; - - case 0x24: /* INC IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - IY += 0x100; - AF = (AF & ~0xfe) | incZ80Table[HIGH_REGISTER(IY)]; - break; - - case 0x25: /* DEC IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - IY -= 0x100; - AF = (AF & ~0xfe) | decZ80Table[HIGH_REGISTER(IY)]; - break; - - case 0x26: /* LD IYH,nn */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IY, RAM_PP(PC)); - break; - - case 0x29: /* ADD IY,IY */ - tStates += 15; - sim_brk_pend[0] = FALSE; - IY &= ADDRMASK; - sum = IY + IY; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - IY = sum; - break; - - case 0x2a: /* LD IY,(nnnn) */ - tStates += 20; - temp = GET_WORD(PC); - CHECK_BREAK_WORD(temp); - IY = GET_WORD(temp); - PC += 2; - break; - - case 0x2b: /* DEC IY */ - tStates += 10; - sim_brk_pend[0] = FALSE; - --IY; - break; - - case 0x2c: /* INC IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IY) + 1; - SET_LOW_REGISTER(IY, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - - case 0x2d: /* DEC IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IY) - 1; - SET_LOW_REGISTER(IY, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - - case 0x2e: /* LD IYL,nn */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IY, RAM_PP(PC)); - break; - - case 0x34: /* INC (IY+dd) */ - tStates += 23; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr) + 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - - case 0x35: /* DEC (IY+dd) */ - tStates += 23; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr) - 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - - case 0x36: /* LD (IY+dd),nn */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, RAM_PP(PC)); - break; - - case 0x39: /* ADD IY,SP */ - tStates += 15; - sim_brk_pend[0] = FALSE; - IY &= ADDRMASK; - SP &= ADDRMASK; - sum = IY + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ SP ^ sum) >> 8]; - IY = sum; - break; - - case 0x44: /* LD B,IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(BC, HIGH_REGISTER(IY)); - break; - - case 0x45: /* LD B,IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(BC, LOW_REGISTER(IY)); - break; - - case 0x46: /* LD B,(IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_HIGH_REGISTER(BC, GetBYTE(adr)); - break; - - case 0x4c: /* LD C,IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(BC, HIGH_REGISTER(IY)); - break; - - case 0x4d: /* LD C,IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(BC, LOW_REGISTER(IY)); - break; - - case 0x4e: /* LD C,(IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_LOW_REGISTER(BC, GetBYTE(adr)); - break; - - case 0x54: /* LD D,IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(DE, HIGH_REGISTER(IY)); - break; - - case 0x55: /* LD D,IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(DE, LOW_REGISTER(IY)); - break; - - case 0x56: /* LD D,(IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_HIGH_REGISTER(DE, GetBYTE(adr)); - break; - - case 0x5c: /* LD E,IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(DE, HIGH_REGISTER(IY)); - break; - - case 0x5d: /* LD E,IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(DE, LOW_REGISTER(IY)); - break; - - case 0x5e: /* LD E,(IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_LOW_REGISTER(DE, GetBYTE(adr)); - break; - - case 0x60: /* LD IYH,B */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IY, HIGH_REGISTER(BC)); - break; - - case 0x61: /* LD IYH,C */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IY, LOW_REGISTER(BC)); - break; - - case 0x62: /* LD IYH,D */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IY, HIGH_REGISTER(DE)); - break; - - case 0x63: /* LD IYH,E */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IY, LOW_REGISTER(DE)); - break; - - case 0x64: /* LD IYH,IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; /* nop */ - break; - - case 0x65: /* LD IYH,IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IY, LOW_REGISTER(IY)); - break; - - case 0x66: /* LD H,(IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_HIGH_REGISTER(HL, GetBYTE(adr)); - break; - - case 0x67: /* LD IYH,A */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(IY, HIGH_REGISTER(AF)); - break; - - case 0x68: /* LD IYL,B */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IY, HIGH_REGISTER(BC)); - break; - - case 0x69: /* LD IYL,C */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IY, LOW_REGISTER(BC)); - break; - - case 0x6a: /* LD IYL,D */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IY, HIGH_REGISTER(DE)); - break; - - case 0x6b: /* LD IYL,E */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IY, LOW_REGISTER(DE)); - break; - - case 0x6c: /* LD IYL,IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IY, HIGH_REGISTER(IY)); - break; - - case 0x6d: /* LD IYL,IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; /* nop */ - break; - - case 0x6e: /* LD L,(IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_LOW_REGISTER(HL, GetBYTE(adr)); - break; - - case 0x6f: /* LD IYL,A */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_LOW_REGISTER(IY, HIGH_REGISTER(AF)); - break; - - case 0x70: /* LD (IY+dd),B */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, HIGH_REGISTER(BC)); - break; - - case 0x71: /* LD (IY+dd),C */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, LOW_REGISTER(BC)); - break; - - case 0x72: /* LD (IY+dd),D */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, HIGH_REGISTER(DE)); - break; - - case 0x73: /* LD (IY+dd),E */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, LOW_REGISTER(DE)); - break; - - case 0x74: /* LD (IY+dd),H */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, HIGH_REGISTER(HL)); - break; - - case 0x75: /* LD (IY+dd),L */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, LOW_REGISTER(HL)); - break; - - case 0x77: /* LD (IY+dd),A */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - PutBYTE(adr, HIGH_REGISTER(AF)); - break; - - case 0x7c: /* LD A,IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(AF, HIGH_REGISTER(IY)); - break; - - case 0x7d: /* LD A,IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - SET_HIGH_REGISTER(AF, LOW_REGISTER(IY)); - break; - - case 0x7e: /* LD A,(IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - SET_HIGH_REGISTER(AF, GetBYTE(adr)); - break; - - case 0x84: /* ADD A,IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x85: /* ADD A,IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x86: /* ADD A,(IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8c: /* ADC A,IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8d: /* ADC A,IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8e: /* ADC A,(IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x96: /* SUB (IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x94: /* SUB IYH */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - - case 0x9c: /* SBC A,IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x95: /* SUB IYL */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - - case 0x9d: /* SBC A,IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x9e: /* SBC A,(IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xa4: /* AND IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = andTable[((AF & IY) >> 8) & 0xff]; - break; - - case 0xa5: /* AND IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = andTable[((AF >> 8) & IY) & 0xff]; - break; - - case 0xa6: /* AND (IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - AF = andTable[((AF >> 8) & GetBYTE(adr)) & 0xff]; - break; - - case 0xac: /* XOR IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF ^ IY) >> 8) & 0xff]; - break; - - case 0xad: /* XOR IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) ^ IY) & 0xff]; - break; - - case 0xae: /* XOR (IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - AF = xororTable[((AF >> 8) ^ GetBYTE(adr)) & 0xff]; - break; - - case 0xb4: /* OR IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF | IY) >> 8) & 0xff]; - break; - - case 0xb5: /* OR IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - AF = xororTable[((AF >> 8) | IY) & 0xff]; - break; - - case 0xb6: /* OR (IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - AF = xororTable[((AF >> 8) | GetBYTE(adr)) & 0xff]; - break; - - case 0xbc: /* CP IYH */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = HIGH_REGISTER(IY); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xbd: /* CP IYL */ - tStates += 9; - sim_brk_pend[0] = FALSE; - temp = LOW_REGISTER(IY); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xbe: /* CP (IY+dd) */ - tStates += 19; - adr = IY + (int8) RAM_PP(PC); - CHECK_BREAK_BYTE(adr); - temp = GetBYTE(adr); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xcb: /* CB prefix */ - adr = IY + (int8) RAM_PP(PC); - switch ((op = GetBYTE(PC)) & 7) { - - case 0: - sim_brk_pend[0] = FALSE; - ++PC; - acu = HIGH_REGISTER(BC); - break; - - case 1: - sim_brk_pend[0] = FALSE; - ++PC; - acu = LOW_REGISTER(BC); - break; - - case 2: - sim_brk_pend[0] = FALSE; - ++PC; - acu = HIGH_REGISTER(DE); - break; - - case 3: - sim_brk_pend[0] = FALSE; - ++PC; - acu = LOW_REGISTER(DE); - break; - - case 4: - sim_brk_pend[0] = FALSE; - ++PC; - acu = HIGH_REGISTER(HL); - break; - - case 5: - sim_brk_pend[0] = FALSE; - ++PC; - acu = LOW_REGISTER(HL); - break; - - case 6: - CHECK_BREAK_BYTE(adr); - ++PC; - acu = GetBYTE(adr); - break; - - case 7: - sim_brk_pend[0] = FALSE; - ++PC; - acu = HIGH_REGISTER(AF); - break; - } - switch (op & 0xc0) { - - case 0x00: /* shift/rotate */ - tStates += 23; - switch (op & 0x38) { - - case 0x00: /* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg3; - - case 0x08: /* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg3; - - case 0x10: /* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg3; - - case 0x18: /* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg3; - - case 0x20: /* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg3; - - case 0x28: /* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg3; - - case 0x30: /* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg3; - - case 0x38: /* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg3: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - /* !!cbits == 0 if cbits == 0 !!cbits == 1 if cbits > 0 */ - } - break; - - case 0x40: /* BIT */ - tStates += 20; - if (acu & (1 << ((op >> 3) & 7))) - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - else - AF = (AF & ~0xfe) | 0x54; - if ((op & 7) != 6) - AF |= (acu & 0x28); - temp = acu; - break; - - case 0x80: /* RES */ - tStates += 23; - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - - case 0xc0: /* SET */ - tStates += 23; - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - switch (op & 7) { - - case 0: - SET_HIGH_REGISTER(BC, temp); - break; - - case 1: - SET_LOW_REGISTER(BC, temp); - break; - - case 2: - SET_HIGH_REGISTER(DE, temp); - break; - - case 3: - SET_LOW_REGISTER(DE, temp); - break; - - case 4: - SET_HIGH_REGISTER(HL, temp); - break; - - case 5: - SET_LOW_REGISTER(HL, temp); - break; - - case 6: - PutBYTE(adr, temp); - break; - - case 7: - SET_HIGH_REGISTER(AF, temp); - break; - } - break; - - case 0xe1: /* POP IY */ - tStates += 14; - CHECK_BREAK_WORD(SP); - POP(IY); - break; - - case 0xe3: /* EX (SP),IY */ - tStates += 23; - CHECK_BREAK_WORD(SP); - temp = IY; - POP(IY); - PUSH(temp); - break; - - case 0xe5: /* PUSH IY */ - tStates += 15; - CHECK_BREAK_WORD(SP - 2); - PUSH(IY); - break; - - case 0xe9: /* JP (IY) */ - tStates += 8; - sim_brk_pend[0] = FALSE; - PCQ_ENTRY(PCX); - PC = IY; - break; - - case 0xf9: /* LD SP,IY */ - tStates += 10; - sim_brk_pend[0] = FALSE; - SP = IY; - break; - - default: /* ignore FD */ - sim_brk_pend[0] = FALSE; - CHECK_CPU_Z80; - PC--; - } - break; - - case 0xfe: /* CP nn */ - tStates += 7; /* CPI nn 7 */ - sim_brk_pend[0] = FALSE; - temp = RAM_PP(PC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xff: /* RST 38H */ - tStates += 11; /* RST 7 11 */ - CHECK_BREAK_WORD(SP - 2); - PUSH(PC); - PCQ_ENTRY(PCX); - PC = 0x38; - } - } - - /* It we stopped processing instructions because of a switch to the other - * CPU, then fixup the reason code. - */ - if (switch_cpu_now == FALSE) { - reason = SCPE_OK; - } - - end_decode: - - /* simulation halted */ - PC_S = ((reason == STOP_OPCODE) || (reason == STOP_MEM)) ? PCX : (PC & ADDRMASK); - pcq_r->qptr = pcq_p; /* update pc q ptr */ - AF_S = AF; - BC_S = BC; - DE_S = DE; - HL_S = HL; - IX_S = IX; - IY_S = IY; - SP_S = SP; - executedTStates = tStates; - return reason; -} - -/* reset routine */ - -static t_stat cpu_reset(DEVICE *dptr) { - extern uint32 sim_brk_types, sim_brk_dflt; /* breakpoint info */ - int32 i; - AF_S = AF1_S = 0; - BC_S = DE_S = HL_S = 0; - BC1_S = DE1_S = HL1_S = 0; - IR_S = IX_S = IY_S = SP_S = 0; - IFF_S = 3; - setBankSelect(0); - cpu8086reset(); - sim_brk_types = (SWMASK('E') | SWMASK('I') | SWMASK('M')); - sim_brk_dflt = SWMASK('E'); - for (i = 0; i < PCQ_SIZE; i++) - pcq[i] = 0; - pcq_p = 0; - pcq_r = find_reg("PCQ", NULL, dptr); - if (pcq_r) - pcq_r->qptr = 0; - else - return SCPE_IERR; - return SCPE_OK; -} - -t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM) { - int32 i; - if (addr & (PAGESIZE - 1)) - return SCPE_IERR; - for (i = 0; i < size; i++) { - if (makeROM && ((i & (PAGESIZE - 1)) == 0)) - mmu_table[(i + addr) >> LOG2PAGESIZE] = ROM_PAGE; - M[i + addr] = bootrom[i] & 0xff; - } - return SCPE_OK; -} - -/* memory examine */ -static t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { - int32 oldBankSelect; - if (chiptype == CHIP_TYPE_8086) - *vptr = GetBYTEExtended(addr); - else { - oldBankSelect = getBankSelect(); - setBankSelect((addr >> MAXBANKSIZELOG2) & BANKMASK); - *vptr = GetBYTE(addr & ADDRMASK); - setBankSelect(oldBankSelect); - } - return SCPE_OK; -} - -/* memory deposit */ -static t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) { - int32 oldBankSelect; - if (chiptype == CHIP_TYPE_8086) - PutBYTEExtended(addr, val); - else { - oldBankSelect = getBankSelect(); - setBankSelect((addr >> MAXBANKSIZELOG2) & BANKMASK); - PutBYTE(addr & ADDRMASK, val); - setBankSelect(oldBankSelect); - } - return SCPE_OK; -} - -struct cpuflag { - int32 mask; /* bit mask within CPU status register */ - char name; /* character to print if flag is set */ -}; -typedef struct cpuflag CPUFLAG; - -static CPUFLAG cpuflags8086[] = { - {1 << 11, 'O'}, - {1 << 10, 'D'}, - {1 << 9, 'I'}, - {1 << 8, 'T'}, - {1 << 7, 'S'}, - {1 << 6, 'Z'}, - {1 << 4, 'A'}, - {1 << 2, 'P'}, - {1 << 0, 'C'}, - {0, 0} /* last mask must be 0 */ -}; - -static CPUFLAG cpuflags8080[] = { - {1 << 7, 'S'}, - {1 << 6, 'Z'}, - {1 << 4, 'A'}, - {1 << 3, 'P'}, - {1 << 1, 'N'}, - {1 << 0, 'C'}, - {0, 0} /* last mask must be 0 */ -}; - -static CPUFLAG cpuflagsZ80[] = { - {1 << 7, 'S'}, - {1 << 6, 'Z'}, - {1 << 4, 'A'}, - {1 << 3, 'V'}, - {1 << 1, 'N'}, - {1 << 0, 'C'}, - {0, 0} /* last mask must be 0 */ -}; - -/* needs to be set for each chiptype <= MAX_CHIP_TYPE */ -static char *chipTypeToString[] = { "8080", "Z80", "8086" }; -static int32 *flagregister[] = { &AF_S, &AF_S, &FLAGS_S }; -static CPUFLAG *cpuflags[] = { cpuflags8080, cpuflagsZ80, cpuflags8086 }; - -/* needs to be set for each ramtype <= MAX_RAM_TYPE */ -static char *ramTypeToString[] = { "AZ80", "HRAM", "VRAM", "CRAM" }; - -static t_stat chip_show(FILE *st, UNIT *uptr, int32 val, void *desc) { - fprintf(st, cpu_unit.flags & UNIT_CPU_OPSTOP ? "ITRAP, " : "NOITRAP, "); - if (chiptype <= MAX_CHIP_TYPE) - fprintf(st, "%s", chipTypeToString[chiptype]); - fprintf(st, ", "); - if (ramtype <= MAX_RAM_TYPE) - fprintf(st, "%s", ramTypeToString[ramtype]); - return SCPE_OK; -} - -static t_stat cpu_show(FILE *st, UNIT *uptr, int32 val, void *desc) { - uint32 i, maxBanks, first = TRUE; - MDEV m; - maxBanks = ((cpu_unit.flags & UNIT_CPU_BANKED) || - (chiptype == CHIP_TYPE_8086)) ? MAXBANKS : 1; - fprintf(st, "VERBOSE,\n "); - for (i = 0; i < 4; i++) - fprintf(st, "0123456789ABCDEF"); - fprintf(st, " [16k]"); - for (i = 0; i < (maxBanks * (MAXBANKSIZE >> LOG2PAGESIZE)); i++) { - if ((i & 0x3f) == 0) - fprintf(st, "\n%05X: ", (i << LOG2PAGESIZE)); - m = mmu_table[i]; - if (m.isRAM) - fprintf(st, "W"); - else if (m.isEmpty) - fprintf(st, "U"); - else if (m.routine) - fprintf(st, "M"); - else - fprintf(st, "R"); - } - fprintf(st, ",\n0x["); - /* show which ports are assigned */ - for (i = 0; i < 256; i++) - if (dev_table[i].routine != &nulldev) { - if (first) - first = FALSE; - else - fprintf(st, " "); - fprintf(st, "%02X", i); - } - fprintf(st, "]"); - if (chiptype <= MAX_CHIP_TYPE) { - first = TRUE; - /* show verbose CPU flags */ - for (i = 0; cpuflags[chiptype][i].mask; i++) - if (*flagregister[chiptype] & cpuflags[chiptype][i].mask) { - if (first) { - first = FALSE; - fprintf(st, " "); - } - fprintf(st, "%c", cpuflags[chiptype][i].name); - } - } - return SCPE_OK; -} - -static void cpu_clear(void) { - uint32 i; - for (i = 0; i < MAXMEMORY; i++) M[i] = 0; - for (i = 0; i < (MAXMEMORY >> LOG2PAGESIZE); i++) - mmu_table[i] = RAM_PAGE; - for (i = (MEMORYSIZE >> LOG2PAGESIZE); i < (MAXMEMORY >> LOG2PAGESIZE); i++) - mmu_table[i] = EMPTY_PAGE; - if (cpu_unit.flags & UNIT_CPU_ALTAIRROM) - install_ALTAIRbootROM(); - clockHasChanged = FALSE; -} - -static t_stat cpu_clear_command(UNIT *uptr, int32 value, char *cptr, void *desc) { - cpu_clear(); - return SCPE_OK; -} - -static t_stat cpu_set_altairrom(UNIT *uptr, int32 value, char *cptr, void *desc) { - install_ALTAIRbootROM(); - return SCPE_OK; -} - -static t_stat cpu_set_noaltairrom(UNIT *uptr, int32 value, char *cptr, void *desc) { - mmu_table[ALTAIR_ROM_LOW >> LOG2PAGESIZE] = MEMORYSIZE < MAXBANKSIZE ? - EMPTY_PAGE : RAM_PAGE; - return SCPE_OK; -} - -static t_stat cpu_set_nommu(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (chiptype == CHIP_TYPE_8086) { - printf("Cannot switch off MMU for 8086 CPU.\n"); - return SCPE_ARG; - } - if (cpu_unit.flags & UNIT_CPU_BANKED) { - printf("Cannot switch off MMU for banked memory.\n"); - return SCPE_ARG; - } - if (((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) && - (MEMORYSIZE < MAXBANKSIZE)) { - printf("Cannot switch off MMU when memory is %iKB < %iKB.\n", - MEMORYSIZE >> KBLOG2, MAXBANKSIZE >> KBLOG2); - return SCPE_ARG; - } - return SCPE_OK; -} - -static t_stat cpu_set_banked(UNIT *uptr, int32 value, char *cptr, void *desc) { - if ((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) { - if (MEMORYSIZE <= MAXBANKSIZE) - previousCapacity = MEMORYSIZE; - MEMORYSIZE = MAXMEMORY; - cpu_dev.awidth = MAXBANKSIZELOG2 + MAXBANKSLOG2; - cpu_clear(); - } - else if (chiptype == CHIP_TYPE_8086) { - printf("Cannot use banked memory for 8086 CPU.\n"); - return SCPE_ARG; - } - return SCPE_OK; -} - -static t_stat cpu_set_nonbanked(UNIT *uptr, int32 value, char *cptr, void *desc) { - if ((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) { - MEMORYSIZE = previousCapacity; - cpu_dev.awidth = MAXBANKSIZELOG2; - cpu_clear(); - } - return SCPE_OK; -} - -static int32 bankseldev(const int32 port, const int32 io, const int32 data) { - if (io) { - switch(ramtype) { - case 1: - if (data & 0x40) { - printf("HRAM: Parity %s" NLP, data & 1 ? "ON" : "OFF"); - } else { - printf("HRAM BANKSEL=%02x" NLP, data); - } - break; - case 2: -/* printf("VRAM BANKSEL=%02x" NLP, data);*/ - switch(data & 0xFF) { - case 0x01: -/* case 0x41: // OASIS uses this for some reason? */ - setBankSelect(0); - break; - case 0x02: -/* case 0x42: // OASIS uses this for some reason? */ - setBankSelect(1); - break; - case 0x04: - setBankSelect(2); - break; - case 0x08: - setBankSelect(3); - break; - case 0x10: - setBankSelect(4); - break; - case 0x20: - setBankSelect(5); - break; - case 0x40: - setBankSelect(6); - break; - case 0x80: - setBankSelect(7); - break; - default: -/* printf("Invalid bank select 0x%02x for VRAM" NLP, data);*/ - break; - } - break; - case 3: -/* printf(ADDRESS_FORMAT " CRAM BANKSEL=%02x" NLP, PCX, data); */ - switch(data & 0x7F) { - case 0x01: - setBankSelect(0); - break; - case 0x02: - setBankSelect(1); - break; - case 0x04: - setBankSelect(2); - break; - case 0x08: - setBankSelect(3); - break; - case 0x10: - setBankSelect(4); - break; - case 0x20: - setBankSelect(5); - break; - case 0x40: - setBankSelect(6); - break; -/* case 0x80: */ -/* setBankSelect(7); */ -/* break; */ - default: - printf("Invalid bank select 0x%02x for CRAM" NLP, data); - break; - } - - break; - case 0: - default: - break; - } - return 0; - } else { - return(0xFF); - } -} - -static void cpu_set_chiptype_short(int32 value, uint32 need_cpu_clear) { - extern REG *sim_PC; - if ((chiptype == value) || (chiptype > MAX_CHIP_TYPE)) - return; /* nothing to do */ - if (((chiptype == CHIP_TYPE_8080) && (value == CHIP_TYPE_Z80)) || - ((chiptype == CHIP_TYPE_Z80) && (value == CHIP_TYPE_8080))) { - chiptype = value; - return; - } - chiptype = value; - if (chiptype == CHIP_TYPE_8086) { - if (MEMORYSIZE <= MAXBANKSIZE) - previousCapacity = MEMORYSIZE; - MEMORYSIZE = MAXMEMORY; - cpu_unit.flags &= ~(UNIT_CPU_BANKED | UNIT_CPU_ALTAIRROM); - cpu_unit.flags |= UNIT_CPU_MMU; - cpu_dev.awidth = MAXBANKSIZELOG2 + MAXBANKSLOG2; - if (need_cpu_clear) - cpu_clear(); - sim_PC = &cpu_reg[7]; - } - else if ((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) { - MEMORYSIZE = previousCapacity; - cpu_dev.awidth = MAXBANKSIZELOG2; - if (need_cpu_clear) - cpu_clear(); - sim_PC = &cpu_reg[6]; - } -} - -static t_stat cpu_set_chiptype(UNIT *uptr, int32 value, char *cptr, void *desc) { - cpu_set_chiptype_short(value, TRUE); - return SCPE_OK; -} - -static int32 switchcpu_io(const int32 port, const int32 io, const int32 data) { - int32 new_chiptype = 0; - if (io == 0) { /* Read, switch CPU */ - switch(chiptype) { - case CHIP_TYPE_8080: - case CHIP_TYPE_Z80: - if (cpu_unit.flags & UNIT_CPU_VERBOSE) { - printf("CPU: " ADDRESS_FORMAT " SWITCH(port=%02x) to 8086" NLP, PCX, port); - } - new_chiptype = CHIP_TYPE_8086; - switch_cpu_now = FALSE; /* hharte */ - break; - case CHIP_TYPE_8086: - if (cpu_unit.flags & UNIT_CPU_VERBOSE) { - printf("CPU: " ADDRESS_FORMAT " SWITCH(port=%02x) to 8085/Z80" NLP, PCX, port); - } - new_chiptype = CHIP_TYPE_Z80; - switch_cpu_now = FALSE; /* hharte */ - break; - default: - printf("%s: invalid chiptype: %d\n", __FUNCTION__, chiptype); - break; - } - - cpu_set_chiptype_short(new_chiptype, FALSE); - return(0xFF); /* Return High-Z Data */ - } else { - printf("%s: Set EXT_ADDR=%02x\n", __FUNCTION__, data); - } - return 0; -} - -static t_stat cpu_show_switcher(FILE *st, UNIT *uptr, int32 val, void *desc) { - if ((cpu_unit.flags & UNIT_CPU_SWITCHER) && (switcherPort >= 0)) - fprintf(st, "SWITCHER=0x%02x", switcherPort); - else - fprintf(st, "NOSWITCHER"); - return SCPE_OK; -} - -static t_stat cpu_set_switcher(UNIT *uptr, int32 value, char *cptr, void *desc) { - struct idev safe; - switcherPort &= 0xff; - safe = dev_table[switcherPort]; - if (sim_map_resource(switcherPort, 1, RESOURCE_TYPE_IO, &switchcpu_io, FALSE)) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, switcherPort); - return SCPE_ARG; - } - oldSwitcherDevice = safe; - return SCPE_OK; -} - -static t_stat cpu_reset_switcher(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (sim_map_resource(switcherPort, 1, RESOURCE_TYPE_IO, oldSwitcherDevice.routine, FALSE)) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, switcherPort); - return SCPE_ARG; - } - return SCPE_OK; -} - -static t_stat cpu_set_ramtype(UNIT *uptr, int32 value, char *cptr, void *desc) { - - if (value == ramtype) { - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("RAM Selection unchanged\n"); - return SCPE_OK; - } - - switch(ramtype) { - case 1: - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("Unmapping NorthStar HRAM\n"); - sim_map_resource(0xC0, 1, RESOURCE_TYPE_IO, &bankseldev, TRUE); - break; - case 2: - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("Unmapping Vector RAM\n"); - sim_map_resource(0x40, 1, RESOURCE_TYPE_IO, &bankseldev, TRUE); - break; - case 3: - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("Unmapping Cromemco RAM\n"); - sim_map_resource(0x40, 1, RESOURCE_TYPE_IO, &bankseldev, TRUE); - break; - case 0: - default: - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("Unmapping AltairZ80 RAM\n"); - break; - } - - switch(value) { - case 1: - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("NorthStar HRAM Selected\n"); - sim_map_resource(0xC0, 1, RESOURCE_TYPE_IO, &bankseldev, FALSE); - break; - case 2: - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("Vector RAM Selected\n"); - sim_map_resource(0x40, 1, RESOURCE_TYPE_IO, &bankseldev, FALSE); - break; - case 3: - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("Cromemco RAM Selected\n"); - sim_map_resource(0x40, 1, RESOURCE_TYPE_IO, &bankseldev, FALSE); - break; - case 0: - default: - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("AltairZ80 RAM Selected\n"); - break; - } - - ramtype = value; - return SCPE_OK; -} - -/* set memory to 'size' kilo byte */ -static t_stat set_size(uint32 size) { - uint32 maxsize = (((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) && - ((cpu_unit.flags & UNIT_CPU_BANKED) == 0)) ? MAXBANKSIZE : MAXMEMORY; - size <<= KBLOG2; - if (cpu_unit.flags & UNIT_CPU_BANKED) - size &= ~ADDRMASK; - cpu_unit.flags |= UNIT_CPU_MMU; - if (size < KB) - MEMORYSIZE = KB; - else if (size > maxsize) - MEMORYSIZE = maxsize; - else - MEMORYSIZE = size; - cpu_dev.awidth = MAXBANKSIZELOG2; - if (size > MAXBANKSIZE) - cpu_dev.awidth += MAXBANKSLOG2; - cpu_clear(); - return SCPE_OK; -} - -static t_stat cpu_set_size(UNIT *uptr, int32 value, char *cptr, void *desc) { - return set_size(value); -} - -static t_stat cpu_set_memory(UNIT *uptr, int32 value, char *cptr, void *desc) { - uint32 size, result, i; - if (cptr == NULL) - return SCPE_ARG; - result = sscanf(cptr, "%i%n", &size, &i); - if ((result == 1) && (cptr[i] == 'K') && ((cptr[i + 1] == 0) || - ((cptr[i + 1] == 'B') && (cptr[i + 2] == 0)))) - return set_size(size); - return SCPE_ARG; -} - -/* AltairZ80 Simulator initialization */ -void altairz80_init(void) { - cpu_clear(); -/* altairz80_print_tables(); */ -} - -void (*sim_vm_init) (void) = &altairz80_init; - -/* 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 if no start address is given. If the input string ends with ROM - (not case sensitive) the memory area is made read only. - ALTAIRROM/NOALTAIRROM settings are ignored. -*/ - -#define PLURAL(x) (x), (x) == 1 ? "" : "s" - -t_stat sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag) { - int32 i; - uint32 addr, cnt = 0, org, pagesModified = 0, makeROM = FALSE; - t_addr j, lo, hi; - char *result; - MDEV m; - char gbuf[CBUFSIZE]; - if (flag) { - result = get_range(NULL, cptr, &lo, &hi, 16, ADDRMASKEXTENDED, 0); - if (result == NULL) - return SCPE_ARG; - for (j = lo; j <= hi; j++) { - if (putc(GetBYTEExtended(j), fileref) == EOF) - return SCPE_IOERR; - } - printf("%d byte%s dumped [%x - %x].\n", PLURAL(hi + 1 - lo), lo, hi); - } - else { - if (*cptr == 0) - addr = (chiptype == CHIP_TYPE_8086) ? PCX_S : PC_S; - else { - get_glyph(cptr, gbuf, 0); - if (strcmp(gbuf, "ROM") == 0) { - addr = (chiptype == CHIP_TYPE_8086) ? PCX_S : PC_S; - makeROM = TRUE; - } - else { - addr = strtotv(cptr, &result, 16) & ADDRMASKEXTENDED; - if (cptr == result) - return SCPE_ARG; - while (isspace(*result)) result++; - get_glyph(result, gbuf, 0); - if (strcmp(gbuf, "ROM") == 0) - makeROM = TRUE; - } - } - /* addr is start address to load to, makeROM == TRUE iff memory should become ROM */ - org = addr; - while ((addr < MAXMEMORY) && ((i = getc(fileref)) != EOF)) { - m = mmu_table[addr >> LOG2PAGESIZE]; - if (!m.isRAM && m.isEmpty) { - mmu_table[addr >> LOG2PAGESIZE] = RAM_PAGE; - pagesModified++; - m = RAM_PAGE; - } - if (makeROM) { - mmu_table[addr >> LOG2PAGESIZE] = ROM_PAGE; - m = ROM_PAGE; - } - if (!m.isRAM && m.routine) - m.routine(addr, 1, i); - else - M[addr] = i; - addr++; - cnt++; - } /* end while */ - printf("%d byte%s [%d page%s] loaded at %x%s.\n", PLURAL(cnt), - PLURAL((cnt + 0xff) >> 8), org, makeROM ? " [ROM]" : ""); - if (pagesModified) - printf("Warning: %d page%s modified.\n", PLURAL(pagesModified)); - } - return SCPE_OK; -} - -void cpu_raise_interrupt(uint32 irq) { - extern void cpu8086_intr(uint8 intrnum); - - if (chiptype == CHIP_TYPE_8086) { - cpu8086_intr(irq); - } else if (cpu_unit.flags & UNIT_CPU_VERBOSE) { - printf("Interrupts not fully supported for chiptype: %s\n", - (chiptype <= MAX_CHIP_TYPE) ? chipTypeToString[chiptype] : "????"); - } -} diff --git a/AltairZ80/altairz80_cpu_nommu.c b/AltairZ80/altairz80_cpu_nommu.c deleted file mode 100644 index dbd38f27..00000000 --- a/AltairZ80/altairz80_cpu_nommu.c +++ /dev/null @@ -1,4215 +0,0 @@ -/* altairz80_cpu_opt.c: MITS Altair CPU (8080 and Z80) - - Copyright (c) 2002-2012, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license) -*/ - -#include "altairz80_defs.h" - -#define FLAG_C 1 -#define FLAG_N 2 -#define FLAG_P 4 -#define FLAG_H 16 -#define FLAG_Z 64 -#define FLAG_S 128 - -#define SETFLAG(f,c) AF = (c) ? AF | FLAG_ ## f : AF & ~FLAG_ ## f -#define TSTFLAG(f) ((AF & FLAG_ ## f) != 0) - -#define LOW_DIGIT(x) ((x) & 0xf) -#define HIGH_DIGIT(x) (((x) >> 4) & 0xf) -#define LOW_REGISTER(x) ((x) & 0xff) -#define HIGH_REGISTER(x) (((x) >> 8) & 0xff) - -#define SET_LOW_REGISTER(x, v) x = (((x) & 0xff00) | ((v) & 0xff)) -#define SET_HIGH_REGISTER(x, v) x = (((x) & 0xff) | (((v) & 0xff) << 8)) - -#define PARITY(x) parityTable[(x) & 0xff] -/* SET_PV and SET_PV2 are used to provide correct PARITY flag semantics for the 8080 in cases - where the Z80 uses the overflow flag -*/ -#define SET_PVS(s) ((chiptype == CHIP_TYPE_Z80) ? (((cbits >> 6) ^ (cbits >> 5)) & 4) : (PARITY(s))) -#define SET_PV (SET_PVS(sum)) -#define SET_PV2(x) ((chiptype == CHIP_TYPE_Z80) ? (((temp == (x)) << 2)) : (PARITY(temp))) - -/* CHECK_CPU_8080 must be invoked whenever a Z80 only instruction is executed - In case a Z80 instruction is executed on an 8080 the following two cases exist: - 1) Trapping is enabled: execution stops - 2) Trapping is not enabled: decoding continues with the next byte -*/ -#define CHECK_CPU_8080 \ - if (chiptype == CHIP_TYPE_8080) { \ - if (cpu_unit.flags & UNIT_CPU_OPSTOP) { \ - reason = STOP_OPCODE; \ - goto end_decode; \ - } \ - else continue; \ - } - -/* CHECK_CPU_Z80 must be invoked whenever a non Z80 instruction is executed */ -#define CHECK_CPU_Z80 \ - if (cpu_unit.flags & UNIT_CPU_OPSTOP) { \ - reason = STOP_OPCODE; \ - goto end_decode; \ - } - -#define POP(x) { \ - register uint32 y = RAM_PP(SP); \ - x = y + (RAM_PP(SP) << 8); \ -} - -#define JPC(cond) { \ - if (cond) { \ - PC = GET_WORD(PC); \ - } \ - else { \ - PC += 2; \ - } \ -} - -#define CALLC(cond) { \ - if (cond) { \ - register uint32 adrr = GET_WORD(PC); \ - PUSH(PC + 2); \ - PC = adrr; \ - } \ - else { \ - PC += 2; \ - } \ -} - -/* function prototypes */ -t_stat sim_instr_nommu(void); - -extern void out(const uint32 Port, const uint32 Value); -extern uint32 in(const uint32 Port); -extern UNIT cpu_unit; -extern uint32 PCX; /* external view of PC */ -extern int32 AF_S; /* AF register */ -extern int32 BC_S; /* BC register */ -extern int32 DE_S; /* DE register */ -extern int32 HL_S; /* HL register */ -extern int32 IX_S; /* IX register */ -extern int32 IY_S; /* IY register */ -extern int32 PC_S; /* program counter */ -extern int32 SP_S; /* SP register */ -extern int32 AF1_S; /* alternate AF register */ -extern int32 BC1_S; /* alternate BC register */ -extern int32 DE1_S; /* alternate DE register */ -extern int32 HL1_S; /* alternate HL register */ -extern int32 IFF_S; /* Interrupt Flip Flop */ -extern int32 IR_S; /* Interrupt (upper) / Refresh (lower) register */ -extern int32 chiptype; - -/* the following tables precompute some common subexpressions - parityTable[i] 0..255 (number of 1's in i is odd) ? 0 : 4 - incTable[i] 0..256! (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0) << 4) - decTable[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0xf) << 4) | 2 - cbitsTable[i] 0..511 (i & 0x10) | ((i >> 8) & 1) - cbitsDup8Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | ((i & 0xff) << 8) | (i & 0xa8) | - (((i & 0xff) == 0) << 6) - cbitsDup16Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | (i & 0x28) - cbits2Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | 2 - rrcaTable[i] 0..255 ((i & 1) << 15) | ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1) - rraTable[i] 0..255 ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1) - addTable[i] 0..511 ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) - subTable[i] 0..255 ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | 2 - andTable[i] 0..255 (i << 8) | (i & 0xa8) | ((i == 0) << 6) | 0x10 | parityTable[i] - xororTable[i] 0..255 (i << 8) | (i & 0xa8) | ((i == 0) << 6) | parityTable[i] - rotateShiftTable[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i & 0xff] - incZ80Table[i] 0..256! (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0) << 4) | ((i == 0x80) << 2) - decZ80Table[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0xf) << 4) | ((i == 0x7f) << 2) | 2 - cbitsZ80Table[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) - cbitsZ80DupTable[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | - ((i >> 8) & 1) | (i & 0xa8) - cbits2Z80Table[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 - cbits2Z80DupTable[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 | - (i & 0xa8) - negTable[i] 0..255 (((i & 0x0f) != 0) << 4) | ((i == 0x80) << 2) | 2 | (i != 0) - rrdrldTable[i] 0..255 (i << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i] - cpTable[i] 0..255 (i & 0x80) | (((i & 0xff) == 0) << 6) -*/ - -/* parityTable[i] = (number of 1's in i is odd) ? 0 : 4, i = 0..255 */ -static const uint8 parityTable[256] = { - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, -}; - -/* incTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0) << 4), i = 0..256 */ -static const uint8 incTable[257] = { - 80, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 80 -}; - -/* decTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0xf) << 4) | 2, i = 0..255 */ -static const uint8 decTable[256] = { - 66, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, -}; - -/* cbitsTable[i] = (i & 0x10) | ((i >> 8) & 1), i = 0..511 */ -static const uint8 cbitsTable[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, -}; - -/* cbitsDup8Table[i] = (i & 0x10) | ((i >> 8) & 1) | ((i & 0xff) << 8) | (i & 0xa8) | - (((i & 0xff) == 0) << 6), i = 0..511 */ -static const uint16 cbitsDup8Table[512] = { - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710, - 0x1818,0x1918,0x1a18,0x1b18,0x1c18,0x1d18,0x1e18,0x1f18, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,0x3630,0x3730, - 0x3838,0x3938,0x3a38,0x3b38,0x3c38,0x3d38,0x3e38,0x3f38, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710, - 0x5818,0x5918,0x5a18,0x5b18,0x5c18,0x5d18,0x5e18,0x5f18, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7030,0x7130,0x7230,0x7330,0x7430,0x7530,0x7630,0x7730, - 0x7838,0x7938,0x7a38,0x7b38,0x7c38,0x7d38,0x7e38,0x7f38, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9090,0x9190,0x9290,0x9390,0x9490,0x9590,0x9690,0x9790, - 0x9898,0x9998,0x9a98,0x9b98,0x9c98,0x9d98,0x9e98,0x9f98, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0b0,0xb1b0,0xb2b0,0xb3b0,0xb4b0,0xb5b0,0xb6b0,0xb7b0, - 0xb8b8,0xb9b8,0xbab8,0xbbb8,0xbcb8,0xbdb8,0xbeb8,0xbfb8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd090,0xd190,0xd290,0xd390,0xd490,0xd590,0xd690,0xd790, - 0xd898,0xd998,0xda98,0xdb98,0xdc98,0xdd98,0xde98,0xdf98, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0b0,0xf1b0,0xf2b0,0xf3b0,0xf4b0,0xf5b0,0xf6b0,0xf7b0, - 0xf8b8,0xf9b8,0xfab8,0xfbb8,0xfcb8,0xfdb8,0xfeb8,0xffb8, - 0x0041,0x0101,0x0201,0x0301,0x0401,0x0501,0x0601,0x0701, - 0x0809,0x0909,0x0a09,0x0b09,0x0c09,0x0d09,0x0e09,0x0f09, - 0x1011,0x1111,0x1211,0x1311,0x1411,0x1511,0x1611,0x1711, - 0x1819,0x1919,0x1a19,0x1b19,0x1c19,0x1d19,0x1e19,0x1f19, - 0x2021,0x2121,0x2221,0x2321,0x2421,0x2521,0x2621,0x2721, - 0x2829,0x2929,0x2a29,0x2b29,0x2c29,0x2d29,0x2e29,0x2f29, - 0x3031,0x3131,0x3231,0x3331,0x3431,0x3531,0x3631,0x3731, - 0x3839,0x3939,0x3a39,0x3b39,0x3c39,0x3d39,0x3e39,0x3f39, - 0x4001,0x4101,0x4201,0x4301,0x4401,0x4501,0x4601,0x4701, - 0x4809,0x4909,0x4a09,0x4b09,0x4c09,0x4d09,0x4e09,0x4f09, - 0x5011,0x5111,0x5211,0x5311,0x5411,0x5511,0x5611,0x5711, - 0x5819,0x5919,0x5a19,0x5b19,0x5c19,0x5d19,0x5e19,0x5f19, - 0x6021,0x6121,0x6221,0x6321,0x6421,0x6521,0x6621,0x6721, - 0x6829,0x6929,0x6a29,0x6b29,0x6c29,0x6d29,0x6e29,0x6f29, - 0x7031,0x7131,0x7231,0x7331,0x7431,0x7531,0x7631,0x7731, - 0x7839,0x7939,0x7a39,0x7b39,0x7c39,0x7d39,0x7e39,0x7f39, - 0x8081,0x8181,0x8281,0x8381,0x8481,0x8581,0x8681,0x8781, - 0x8889,0x8989,0x8a89,0x8b89,0x8c89,0x8d89,0x8e89,0x8f89, - 0x9091,0x9191,0x9291,0x9391,0x9491,0x9591,0x9691,0x9791, - 0x9899,0x9999,0x9a99,0x9b99,0x9c99,0x9d99,0x9e99,0x9f99, - 0xa0a1,0xa1a1,0xa2a1,0xa3a1,0xa4a1,0xa5a1,0xa6a1,0xa7a1, - 0xa8a9,0xa9a9,0xaaa9,0xaba9,0xaca9,0xada9,0xaea9,0xafa9, - 0xb0b1,0xb1b1,0xb2b1,0xb3b1,0xb4b1,0xb5b1,0xb6b1,0xb7b1, - 0xb8b9,0xb9b9,0xbab9,0xbbb9,0xbcb9,0xbdb9,0xbeb9,0xbfb9, - 0xc081,0xc181,0xc281,0xc381,0xc481,0xc581,0xc681,0xc781, - 0xc889,0xc989,0xca89,0xcb89,0xcc89,0xcd89,0xce89,0xcf89, - 0xd091,0xd191,0xd291,0xd391,0xd491,0xd591,0xd691,0xd791, - 0xd899,0xd999,0xda99,0xdb99,0xdc99,0xdd99,0xde99,0xdf99, - 0xe0a1,0xe1a1,0xe2a1,0xe3a1,0xe4a1,0xe5a1,0xe6a1,0xe7a1, - 0xe8a9,0xe9a9,0xeaa9,0xeba9,0xeca9,0xeda9,0xeea9,0xefa9, - 0xf0b1,0xf1b1,0xf2b1,0xf3b1,0xf4b1,0xf5b1,0xf6b1,0xf7b1, - 0xf8b9,0xf9b9,0xfab9,0xfbb9,0xfcb9,0xfdb9,0xfeb9,0xffb9, -}; - -/* cbitsDup16Table[i] = (i & 0x10) | ((i >> 8) & 1) | (i & 0x28), i = 0..511 */ -static const uint8 cbitsDup16Table[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, -}; - -/* cbits2Table[i] = (i & 0x10) | ((i >> 8) & 1) | 2, i = 0..511 */ -static const uint8 cbits2Table[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* rrcaTable[i] = ((i & 1) << 15) | ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1), i = 0..255 */ -static const uint16 rrcaTable[256] = { - 0x0000,0x8001,0x0100,0x8101,0x0200,0x8201,0x0300,0x8301, - 0x0400,0x8401,0x0500,0x8501,0x0600,0x8601,0x0700,0x8701, - 0x0808,0x8809,0x0908,0x8909,0x0a08,0x8a09,0x0b08,0x8b09, - 0x0c08,0x8c09,0x0d08,0x8d09,0x0e08,0x8e09,0x0f08,0x8f09, - 0x1000,0x9001,0x1100,0x9101,0x1200,0x9201,0x1300,0x9301, - 0x1400,0x9401,0x1500,0x9501,0x1600,0x9601,0x1700,0x9701, - 0x1808,0x9809,0x1908,0x9909,0x1a08,0x9a09,0x1b08,0x9b09, - 0x1c08,0x9c09,0x1d08,0x9d09,0x1e08,0x9e09,0x1f08,0x9f09, - 0x2020,0xa021,0x2120,0xa121,0x2220,0xa221,0x2320,0xa321, - 0x2420,0xa421,0x2520,0xa521,0x2620,0xa621,0x2720,0xa721, - 0x2828,0xa829,0x2928,0xa929,0x2a28,0xaa29,0x2b28,0xab29, - 0x2c28,0xac29,0x2d28,0xad29,0x2e28,0xae29,0x2f28,0xaf29, - 0x3020,0xb021,0x3120,0xb121,0x3220,0xb221,0x3320,0xb321, - 0x3420,0xb421,0x3520,0xb521,0x3620,0xb621,0x3720,0xb721, - 0x3828,0xb829,0x3928,0xb929,0x3a28,0xba29,0x3b28,0xbb29, - 0x3c28,0xbc29,0x3d28,0xbd29,0x3e28,0xbe29,0x3f28,0xbf29, - 0x4000,0xc001,0x4100,0xc101,0x4200,0xc201,0x4300,0xc301, - 0x4400,0xc401,0x4500,0xc501,0x4600,0xc601,0x4700,0xc701, - 0x4808,0xc809,0x4908,0xc909,0x4a08,0xca09,0x4b08,0xcb09, - 0x4c08,0xcc09,0x4d08,0xcd09,0x4e08,0xce09,0x4f08,0xcf09, - 0x5000,0xd001,0x5100,0xd101,0x5200,0xd201,0x5300,0xd301, - 0x5400,0xd401,0x5500,0xd501,0x5600,0xd601,0x5700,0xd701, - 0x5808,0xd809,0x5908,0xd909,0x5a08,0xda09,0x5b08,0xdb09, - 0x5c08,0xdc09,0x5d08,0xdd09,0x5e08,0xde09,0x5f08,0xdf09, - 0x6020,0xe021,0x6120,0xe121,0x6220,0xe221,0x6320,0xe321, - 0x6420,0xe421,0x6520,0xe521,0x6620,0xe621,0x6720,0xe721, - 0x6828,0xe829,0x6928,0xe929,0x6a28,0xea29,0x6b28,0xeb29, - 0x6c28,0xec29,0x6d28,0xed29,0x6e28,0xee29,0x6f28,0xef29, - 0x7020,0xf021,0x7120,0xf121,0x7220,0xf221,0x7320,0xf321, - 0x7420,0xf421,0x7520,0xf521,0x7620,0xf621,0x7720,0xf721, - 0x7828,0xf829,0x7928,0xf929,0x7a28,0xfa29,0x7b28,0xfb29, - 0x7c28,0xfc29,0x7d28,0xfd29,0x7e28,0xfe29,0x7f28,0xff29, -}; - -/* rraTable[i] = ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1), i = 0..255 */ -static const uint16 rraTable[256] = { - 0x0000,0x0001,0x0100,0x0101,0x0200,0x0201,0x0300,0x0301, - 0x0400,0x0401,0x0500,0x0501,0x0600,0x0601,0x0700,0x0701, - 0x0808,0x0809,0x0908,0x0909,0x0a08,0x0a09,0x0b08,0x0b09, - 0x0c08,0x0c09,0x0d08,0x0d09,0x0e08,0x0e09,0x0f08,0x0f09, - 0x1000,0x1001,0x1100,0x1101,0x1200,0x1201,0x1300,0x1301, - 0x1400,0x1401,0x1500,0x1501,0x1600,0x1601,0x1700,0x1701, - 0x1808,0x1809,0x1908,0x1909,0x1a08,0x1a09,0x1b08,0x1b09, - 0x1c08,0x1c09,0x1d08,0x1d09,0x1e08,0x1e09,0x1f08,0x1f09, - 0x2020,0x2021,0x2120,0x2121,0x2220,0x2221,0x2320,0x2321, - 0x2420,0x2421,0x2520,0x2521,0x2620,0x2621,0x2720,0x2721, - 0x2828,0x2829,0x2928,0x2929,0x2a28,0x2a29,0x2b28,0x2b29, - 0x2c28,0x2c29,0x2d28,0x2d29,0x2e28,0x2e29,0x2f28,0x2f29, - 0x3020,0x3021,0x3120,0x3121,0x3220,0x3221,0x3320,0x3321, - 0x3420,0x3421,0x3520,0x3521,0x3620,0x3621,0x3720,0x3721, - 0x3828,0x3829,0x3928,0x3929,0x3a28,0x3a29,0x3b28,0x3b29, - 0x3c28,0x3c29,0x3d28,0x3d29,0x3e28,0x3e29,0x3f28,0x3f29, - 0x4000,0x4001,0x4100,0x4101,0x4200,0x4201,0x4300,0x4301, - 0x4400,0x4401,0x4500,0x4501,0x4600,0x4601,0x4700,0x4701, - 0x4808,0x4809,0x4908,0x4909,0x4a08,0x4a09,0x4b08,0x4b09, - 0x4c08,0x4c09,0x4d08,0x4d09,0x4e08,0x4e09,0x4f08,0x4f09, - 0x5000,0x5001,0x5100,0x5101,0x5200,0x5201,0x5300,0x5301, - 0x5400,0x5401,0x5500,0x5501,0x5600,0x5601,0x5700,0x5701, - 0x5808,0x5809,0x5908,0x5909,0x5a08,0x5a09,0x5b08,0x5b09, - 0x5c08,0x5c09,0x5d08,0x5d09,0x5e08,0x5e09,0x5f08,0x5f09, - 0x6020,0x6021,0x6120,0x6121,0x6220,0x6221,0x6320,0x6321, - 0x6420,0x6421,0x6520,0x6521,0x6620,0x6621,0x6720,0x6721, - 0x6828,0x6829,0x6928,0x6929,0x6a28,0x6a29,0x6b28,0x6b29, - 0x6c28,0x6c29,0x6d28,0x6d29,0x6e28,0x6e29,0x6f28,0x6f29, - 0x7020,0x7021,0x7120,0x7121,0x7220,0x7221,0x7320,0x7321, - 0x7420,0x7421,0x7520,0x7521,0x7620,0x7621,0x7720,0x7721, - 0x7828,0x7829,0x7928,0x7929,0x7a28,0x7a29,0x7b28,0x7b29, - 0x7c28,0x7c29,0x7d28,0x7d29,0x7e28,0x7e29,0x7f28,0x7f29, -}; - -/* addTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6), i = 0..511 */ -static const uint16 addTable[512] = { - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, - 0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720, - 0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, - 0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720, - 0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780, - 0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0, - 0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780, - 0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0, - 0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8, - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, - 0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720, - 0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, - 0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720, - 0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780, - 0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0, - 0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780, - 0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0, - 0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8, -}; - -/* subTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | 2, i = 0..255 */ -static const uint16 subTable[256] = { - 0x0042,0x0102,0x0202,0x0302,0x0402,0x0502,0x0602,0x0702, - 0x080a,0x090a,0x0a0a,0x0b0a,0x0c0a,0x0d0a,0x0e0a,0x0f0a, - 0x1002,0x1102,0x1202,0x1302,0x1402,0x1502,0x1602,0x1702, - 0x180a,0x190a,0x1a0a,0x1b0a,0x1c0a,0x1d0a,0x1e0a,0x1f0a, - 0x2022,0x2122,0x2222,0x2322,0x2422,0x2522,0x2622,0x2722, - 0x282a,0x292a,0x2a2a,0x2b2a,0x2c2a,0x2d2a,0x2e2a,0x2f2a, - 0x3022,0x3122,0x3222,0x3322,0x3422,0x3522,0x3622,0x3722, - 0x382a,0x392a,0x3a2a,0x3b2a,0x3c2a,0x3d2a,0x3e2a,0x3f2a, - 0x4002,0x4102,0x4202,0x4302,0x4402,0x4502,0x4602,0x4702, - 0x480a,0x490a,0x4a0a,0x4b0a,0x4c0a,0x4d0a,0x4e0a,0x4f0a, - 0x5002,0x5102,0x5202,0x5302,0x5402,0x5502,0x5602,0x5702, - 0x580a,0x590a,0x5a0a,0x5b0a,0x5c0a,0x5d0a,0x5e0a,0x5f0a, - 0x6022,0x6122,0x6222,0x6322,0x6422,0x6522,0x6622,0x6722, - 0x682a,0x692a,0x6a2a,0x6b2a,0x6c2a,0x6d2a,0x6e2a,0x6f2a, - 0x7022,0x7122,0x7222,0x7322,0x7422,0x7522,0x7622,0x7722, - 0x782a,0x792a,0x7a2a,0x7b2a,0x7c2a,0x7d2a,0x7e2a,0x7f2a, - 0x8082,0x8182,0x8282,0x8382,0x8482,0x8582,0x8682,0x8782, - 0x888a,0x898a,0x8a8a,0x8b8a,0x8c8a,0x8d8a,0x8e8a,0x8f8a, - 0x9082,0x9182,0x9282,0x9382,0x9482,0x9582,0x9682,0x9782, - 0x988a,0x998a,0x9a8a,0x9b8a,0x9c8a,0x9d8a,0x9e8a,0x9f8a, - 0xa0a2,0xa1a2,0xa2a2,0xa3a2,0xa4a2,0xa5a2,0xa6a2,0xa7a2, - 0xa8aa,0xa9aa,0xaaaa,0xabaa,0xacaa,0xadaa,0xaeaa,0xafaa, - 0xb0a2,0xb1a2,0xb2a2,0xb3a2,0xb4a2,0xb5a2,0xb6a2,0xb7a2, - 0xb8aa,0xb9aa,0xbaaa,0xbbaa,0xbcaa,0xbdaa,0xbeaa,0xbfaa, - 0xc082,0xc182,0xc282,0xc382,0xc482,0xc582,0xc682,0xc782, - 0xc88a,0xc98a,0xca8a,0xcb8a,0xcc8a,0xcd8a,0xce8a,0xcf8a, - 0xd082,0xd182,0xd282,0xd382,0xd482,0xd582,0xd682,0xd782, - 0xd88a,0xd98a,0xda8a,0xdb8a,0xdc8a,0xdd8a,0xde8a,0xdf8a, - 0xe0a2,0xe1a2,0xe2a2,0xe3a2,0xe4a2,0xe5a2,0xe6a2,0xe7a2, - 0xe8aa,0xe9aa,0xeaaa,0xebaa,0xecaa,0xedaa,0xeeaa,0xefaa, - 0xf0a2,0xf1a2,0xf2a2,0xf3a2,0xf4a2,0xf5a2,0xf6a2,0xf7a2, - 0xf8aa,0xf9aa,0xfaaa,0xfbaa,0xfcaa,0xfdaa,0xfeaa,0xffaa, -}; - -/* andTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | 0x10 | parityTable[i], i = 0..255 */ -static const uint16 andTable[256] = { - 0x0054,0x0110,0x0210,0x0314,0x0410,0x0514,0x0614,0x0710, - 0x0818,0x091c,0x0a1c,0x0b18,0x0c1c,0x0d18,0x0e18,0x0f1c, - 0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,0x1610,0x1714, - 0x181c,0x1918,0x1a18,0x1b1c,0x1c18,0x1d1c,0x1e1c,0x1f18, - 0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,0x2630,0x2734, - 0x283c,0x2938,0x2a38,0x2b3c,0x2c38,0x2d3c,0x2e3c,0x2f38, - 0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,0x3634,0x3730, - 0x3838,0x393c,0x3a3c,0x3b38,0x3c3c,0x3d38,0x3e38,0x3f3c, - 0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,0x4610,0x4714, - 0x481c,0x4918,0x4a18,0x4b1c,0x4c18,0x4d1c,0x4e1c,0x4f18, - 0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,0x5614,0x5710, - 0x5818,0x591c,0x5a1c,0x5b18,0x5c1c,0x5d18,0x5e18,0x5f1c, - 0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,0x6634,0x6730, - 0x6838,0x693c,0x6a3c,0x6b38,0x6c3c,0x6d38,0x6e38,0x6f3c, - 0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,0x7630,0x7734, - 0x783c,0x7938,0x7a38,0x7b3c,0x7c38,0x7d3c,0x7e3c,0x7f38, - 0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,0x8690,0x8794, - 0x889c,0x8998,0x8a98,0x8b9c,0x8c98,0x8d9c,0x8e9c,0x8f98, - 0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,0x9694,0x9790, - 0x9898,0x999c,0x9a9c,0x9b98,0x9c9c,0x9d98,0x9e98,0x9f9c, - 0xa0b4,0xa1b0,0xa2b0,0xa3b4,0xa4b0,0xa5b4,0xa6b4,0xa7b0, - 0xa8b8,0xa9bc,0xaabc,0xabb8,0xacbc,0xadb8,0xaeb8,0xafbc, - 0xb0b0,0xb1b4,0xb2b4,0xb3b0,0xb4b4,0xb5b0,0xb6b0,0xb7b4, - 0xb8bc,0xb9b8,0xbab8,0xbbbc,0xbcb8,0xbdbc,0xbebc,0xbfb8, - 0xc094,0xc190,0xc290,0xc394,0xc490,0xc594,0xc694,0xc790, - 0xc898,0xc99c,0xca9c,0xcb98,0xcc9c,0xcd98,0xce98,0xcf9c, - 0xd090,0xd194,0xd294,0xd390,0xd494,0xd590,0xd690,0xd794, - 0xd89c,0xd998,0xda98,0xdb9c,0xdc98,0xdd9c,0xde9c,0xdf98, - 0xe0b0,0xe1b4,0xe2b4,0xe3b0,0xe4b4,0xe5b0,0xe6b0,0xe7b4, - 0xe8bc,0xe9b8,0xeab8,0xebbc,0xecb8,0xedbc,0xeebc,0xefb8, - 0xf0b4,0xf1b0,0xf2b0,0xf3b4,0xf4b0,0xf5b4,0xf6b4,0xf7b0, - 0xf8b8,0xf9bc,0xfabc,0xfbb8,0xfcbc,0xfdb8,0xfeb8,0xffbc, -}; - -/* xororTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | parityTable[i], i = 0..255 */ -static const uint16 xororTable[256] = { - 0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700, - 0x0808,0x090c,0x0a0c,0x0b08,0x0c0c,0x0d08,0x0e08,0x0f0c, - 0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704, - 0x180c,0x1908,0x1a08,0x1b0c,0x1c08,0x1d0c,0x1e0c,0x1f08, - 0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724, - 0x282c,0x2928,0x2a28,0x2b2c,0x2c28,0x2d2c,0x2e2c,0x2f28, - 0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720, - 0x3828,0x392c,0x3a2c,0x3b28,0x3c2c,0x3d28,0x3e28,0x3f2c, - 0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704, - 0x480c,0x4908,0x4a08,0x4b0c,0x4c08,0x4d0c,0x4e0c,0x4f08, - 0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700, - 0x5808,0x590c,0x5a0c,0x5b08,0x5c0c,0x5d08,0x5e08,0x5f0c, - 0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720, - 0x6828,0x692c,0x6a2c,0x6b28,0x6c2c,0x6d28,0x6e28,0x6f2c, - 0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724, - 0x782c,0x7928,0x7a28,0x7b2c,0x7c28,0x7d2c,0x7e2c,0x7f28, - 0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784, - 0x888c,0x8988,0x8a88,0x8b8c,0x8c88,0x8d8c,0x8e8c,0x8f88, - 0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780, - 0x9888,0x998c,0x9a8c,0x9b88,0x9c8c,0x9d88,0x9e88,0x9f8c, - 0xa0a4,0xa1a0,0xa2a0,0xa3a4,0xa4a0,0xa5a4,0xa6a4,0xa7a0, - 0xa8a8,0xa9ac,0xaaac,0xaba8,0xacac,0xada8,0xaea8,0xafac, - 0xb0a0,0xb1a4,0xb2a4,0xb3a0,0xb4a4,0xb5a0,0xb6a0,0xb7a4, - 0xb8ac,0xb9a8,0xbaa8,0xbbac,0xbca8,0xbdac,0xbeac,0xbfa8, - 0xc084,0xc180,0xc280,0xc384,0xc480,0xc584,0xc684,0xc780, - 0xc888,0xc98c,0xca8c,0xcb88,0xcc8c,0xcd88,0xce88,0xcf8c, - 0xd080,0xd184,0xd284,0xd380,0xd484,0xd580,0xd680,0xd784, - 0xd88c,0xd988,0xda88,0xdb8c,0xdc88,0xdd8c,0xde8c,0xdf88, - 0xe0a0,0xe1a4,0xe2a4,0xe3a0,0xe4a4,0xe5a0,0xe6a0,0xe7a4, - 0xe8ac,0xe9a8,0xeaa8,0xebac,0xeca8,0xedac,0xeeac,0xefa8, - 0xf0a4,0xf1a0,0xf2a0,0xf3a4,0xf4a0,0xf5a4,0xf6a4,0xf7a0, - 0xf8a8,0xf9ac,0xfaac,0xfba8,0xfcac,0xfda8,0xfea8,0xffac, -}; - -/* rotateShiftTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i & 0xff], i = 0..255 */ -static const uint8 rotateShiftTable[256] = { - 68, 0, 0, 4, 0, 4, 4, 0, 8, 12, 12, 8, 12, 8, 8, 12, - 0, 4, 4, 0, 4, 0, 0, 4, 12, 8, 8, 12, 8, 12, 12, 8, - 32, 36, 36, 32, 36, 32, 32, 36, 44, 40, 40, 44, 40, 44, 44, 40, - 36, 32, 32, 36, 32, 36, 36, 32, 40, 44, 44, 40, 44, 40, 40, 44, - 0, 4, 4, 0, 4, 0, 0, 4, 12, 8, 8, 12, 8, 12, 12, 8, - 4, 0, 0, 4, 0, 4, 4, 0, 8, 12, 12, 8, 12, 8, 8, 12, - 36, 32, 32, 36, 32, 36, 36, 32, 40, 44, 44, 40, 44, 40, 40, 44, - 32, 36, 36, 32, 36, 32, 32, 36, 44, 40, 40, 44, 40, 44, 44, 40, - 128,132,132,128,132,128,128,132,140,136,136,140,136,140,140,136, - 132,128,128,132,128,132,132,128,136,140,140,136,140,136,136,140, - 164,160,160,164,160,164,164,160,168,172,172,168,172,168,168,172, - 160,164,164,160,164,160,160,164,172,168,168,172,168,172,172,168, - 132,128,128,132,128,132,132,128,136,140,140,136,140,136,136,140, - 128,132,132,128,132,128,128,132,140,136,136,140,136,140,140,136, - 160,164,164,160,164,160,160,164,172,168,168,172,168,172,172,168, - 164,160,160,164,160,164,164,160,168,172,172,168,172,168,168,172, -}; - -/* incZ80Table[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0) << 4) | ((i == 0x80) << 2), i = 0..256 */ -static const uint8 incZ80Table[257] = { - 80, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 148,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 80, -}; - -/* decZ80Table[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0xf) << 4) | ((i == 0x7f) << 2) | 2, i = 0..255 */ -static const uint8 decZ80Table[256] = { - 66, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 62, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, -}; - -/* cbitsZ80Table[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1), i = 0..511 */ -static const uint8 cbitsZ80Table[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, -}; - -/* cbitsZ80DupTable[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | - ((i >> 8) & 1) | (i & 0xa8), i = 0..511 */ -static const uint8 cbitsZ80DupTable[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, - 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, - 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56, - 132,132,132,132,132,132,132,132,140,140,140,140,140,140,140,140, - 148,148,148,148,148,148,148,148,156,156,156,156,156,156,156,156, - 164,164,164,164,164,164,164,164,172,172,172,172,172,172,172,172, - 180,180,180,180,180,180,180,180,188,188,188,188,188,188,188,188, - 132,132,132,132,132,132,132,132,140,140,140,140,140,140,140,140, - 148,148,148,148,148,148,148,148,156,156,156,156,156,156,156,156, - 164,164,164,164,164,164,164,164,172,172,172,172,172,172,172,172, - 180,180,180,180,180,180,180,180,188,188,188,188,188,188,188,188, - 5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 13, 13, 13, 13, 13, 13, - 21, 21, 21, 21, 21, 21, 21, 21, 29, 29, 29, 29, 29, 29, 29, 29, - 37, 37, 37, 37, 37, 37, 37, 37, 45, 45, 45, 45, 45, 45, 45, 45, - 53, 53, 53, 53, 53, 53, 53, 53, 61, 61, 61, 61, 61, 61, 61, 61, - 5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 13, 13, 13, 13, 13, 13, - 21, 21, 21, 21, 21, 21, 21, 21, 29, 29, 29, 29, 29, 29, 29, 29, - 37, 37, 37, 37, 37, 37, 37, 37, 45, 45, 45, 45, 45, 45, 45, 45, - 53, 53, 53, 53, 53, 53, 53, 53, 61, 61, 61, 61, 61, 61, 61, 61, - 129,129,129,129,129,129,129,129,137,137,137,137,137,137,137,137, - 145,145,145,145,145,145,145,145,153,153,153,153,153,153,153,153, - 161,161,161,161,161,161,161,161,169,169,169,169,169,169,169,169, - 177,177,177,177,177,177,177,177,185,185,185,185,185,185,185,185, - 129,129,129,129,129,129,129,129,137,137,137,137,137,137,137,137, - 145,145,145,145,145,145,145,145,153,153,153,153,153,153,153,153, - 161,161,161,161,161,161,161,161,169,169,169,169,169,169,169,169, - 177,177,177,177,177,177,177,177,185,185,185,185,185,185,185,185, -}; - -/* cbits2Z80Table[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2, i = 0..511 */ -static const uint8 cbits2Z80Table[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* cbits2Z80DupTable[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 | - (i & 0xa8), i = 0..511 */ -static const uint8 cbits2Z80DupTable[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, - 18, 18, 18, 18, 18, 18, 18, 18, 26, 26, 26, 26, 26, 26, 26, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42, - 50, 50, 50, 50, 50, 50, 50, 50, 58, 58, 58, 58, 58, 58, 58, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, - 18, 18, 18, 18, 18, 18, 18, 18, 26, 26, 26, 26, 26, 26, 26, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42, - 50, 50, 50, 50, 50, 50, 50, 50, 58, 58, 58, 58, 58, 58, 58, 58, - 134,134,134,134,134,134,134,134,142,142,142,142,142,142,142,142, - 150,150,150,150,150,150,150,150,158,158,158,158,158,158,158,158, - 166,166,166,166,166,166,166,166,174,174,174,174,174,174,174,174, - 182,182,182,182,182,182,182,182,190,190,190,190,190,190,190,190, - 134,134,134,134,134,134,134,134,142,142,142,142,142,142,142,142, - 150,150,150,150,150,150,150,150,158,158,158,158,158,158,158,158, - 166,166,166,166,166,166,166,166,174,174,174,174,174,174,174,174, - 182,182,182,182,182,182,182,182,190,190,190,190,190,190,190,190, - 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15, - 23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, - 39, 39, 39, 39, 39, 39, 39, 39, 47, 47, 47, 47, 47, 47, 47, 47, - 55, 55, 55, 55, 55, 55, 55, 55, 63, 63, 63, 63, 63, 63, 63, 63, - 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15, - 23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, - 39, 39, 39, 39, 39, 39, 39, 39, 47, 47, 47, 47, 47, 47, 47, 47, - 55, 55, 55, 55, 55, 55, 55, 55, 63, 63, 63, 63, 63, 63, 63, 63, - 131,131,131,131,131,131,131,131,139,139,139,139,139,139,139,139, - 147,147,147,147,147,147,147,147,155,155,155,155,155,155,155,155, - 163,163,163,163,163,163,163,163,171,171,171,171,171,171,171,171, - 179,179,179,179,179,179,179,179,187,187,187,187,187,187,187,187, - 131,131,131,131,131,131,131,131,139,139,139,139,139,139,139,139, - 147,147,147,147,147,147,147,147,155,155,155,155,155,155,155,155, - 163,163,163,163,163,163,163,163,171,171,171,171,171,171,171,171, - 179,179,179,179,179,179,179,179,187,187,187,187,187,187,187,187, -}; - -/* negTable[i] = (((i & 0x0f) != 0) << 4) | ((i == 0x80) << 2) | 2 | (i != 0), i = 0..255 */ -static const uint8 negTable[256] = { - 2,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 7,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* rrdrldTable[i] = (i << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i], i = 0..255 */ -static const uint16 rrdrldTable[256] = { - 0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700, - 0x0808,0x090c,0x0a0c,0x0b08,0x0c0c,0x0d08,0x0e08,0x0f0c, - 0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704, - 0x180c,0x1908,0x1a08,0x1b0c,0x1c08,0x1d0c,0x1e0c,0x1f08, - 0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724, - 0x282c,0x2928,0x2a28,0x2b2c,0x2c28,0x2d2c,0x2e2c,0x2f28, - 0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720, - 0x3828,0x392c,0x3a2c,0x3b28,0x3c2c,0x3d28,0x3e28,0x3f2c, - 0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704, - 0x480c,0x4908,0x4a08,0x4b0c,0x4c08,0x4d0c,0x4e0c,0x4f08, - 0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700, - 0x5808,0x590c,0x5a0c,0x5b08,0x5c0c,0x5d08,0x5e08,0x5f0c, - 0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720, - 0x6828,0x692c,0x6a2c,0x6b28,0x6c2c,0x6d28,0x6e28,0x6f2c, - 0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724, - 0x782c,0x7928,0x7a28,0x7b2c,0x7c28,0x7d2c,0x7e2c,0x7f28, - 0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784, - 0x888c,0x8988,0x8a88,0x8b8c,0x8c88,0x8d8c,0x8e8c,0x8f88, - 0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780, - 0x9888,0x998c,0x9a8c,0x9b88,0x9c8c,0x9d88,0x9e88,0x9f8c, - 0xa0a4,0xa1a0,0xa2a0,0xa3a4,0xa4a0,0xa5a4,0xa6a4,0xa7a0, - 0xa8a8,0xa9ac,0xaaac,0xaba8,0xacac,0xada8,0xaea8,0xafac, - 0xb0a0,0xb1a4,0xb2a4,0xb3a0,0xb4a4,0xb5a0,0xb6a0,0xb7a4, - 0xb8ac,0xb9a8,0xbaa8,0xbbac,0xbca8,0xbdac,0xbeac,0xbfa8, - 0xc084,0xc180,0xc280,0xc384,0xc480,0xc584,0xc684,0xc780, - 0xc888,0xc98c,0xca8c,0xcb88,0xcc8c,0xcd88,0xce88,0xcf8c, - 0xd080,0xd184,0xd284,0xd380,0xd484,0xd580,0xd680,0xd784, - 0xd88c,0xd988,0xda88,0xdb8c,0xdc88,0xdd8c,0xde8c,0xdf88, - 0xe0a0,0xe1a4,0xe2a4,0xe3a0,0xe4a4,0xe5a0,0xe6a0,0xe7a4, - 0xe8ac,0xe9a8,0xeaa8,0xebac,0xeca8,0xedac,0xeeac,0xefa8, - 0xf0a4,0xf1a0,0xf2a0,0xf3a4,0xf4a0,0xf5a4,0xf6a4,0xf7a0, - 0xf8a8,0xf9ac,0xfaac,0xfba8,0xfcac,0xfda8,0xfea8,0xffac, -}; - -/* cpTable[i] = (i & 0x80) | (((i & 0xff) == 0) << 6), i = 0..255 */ -static const uint8 cpTable[256] = { - 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, -}; - -/* Memory management */ - -uint8 MOPT[MAXBANKSIZE]; /* RAM which is present */ - -static uint8 GET_BYTE(register uint32 Addr) { - return MOPT[Addr & ADDRMASK]; -} - -static void PUT_BYTE(register uint32 Addr, register uint32 Value) { - MOPT[Addr & ADDRMASK] = Value; -} - -static void PUT_WORD(register uint32 Addr, register uint32 Value) { - MOPT[Addr & ADDRMASK] = Value; - MOPT[(Addr + 1) & ADDRMASK] = Value >> 8; -} - -static uint16 GET_WORD(register uint32 a) { - return GET_BYTE(a) | (GET_BYTE(a + 1) << 8); -} - -#define RAM_MM(a) GET_BYTE(a--) -#define RAM_PP(a) GET_BYTE(a++) - -#define PUT_BYTE_PP(a,v) PUT_BYTE(a++, v) -#define PUT_BYTE_MM(a,v) PUT_BYTE(a--, v) -#define MM_PUT_BYTE(a,v) PUT_BYTE(--a, v) - -#define PUSH(x) do { \ - MM_PUT_BYTE(SP, (x) >> 8); \ - MM_PUT_BYTE(SP, x); \ -} while (0) - -/* Macros for the IN/OUT instructions INI/INIR/IND/INDR/OUTI/OTIR/OUTD/OTDR - - Pre condition - temp == value of register B at entry of the instruction - acu == value of transferred byte (IN or OUT) - Post condition - F is set correctly - - Use INOUTFLAGS_ZERO(x) for INIR/INDR/OTIR/OTDR where - x == (C + 1) & 0xff for INIR - x == L for OTIR and OTDR - x == (C - 1) & 0xff for INDR - Use INOUTFLAGS_NONZERO(x) for INI/IND/OUTI/OUTD where - x == (C + 1) & 0xff for INI - x == L for OUTI and OUTD - x == (C - 1) & 0xff for IND -*/ -#define INOUTFLAGS(syxz, x) \ - AF = (AF & 0xff00) | (syxz) | /* SF, YF, XF, ZF */ \ - ((acu & 0x80) >> 6) | /* NF */ \ - ((acu + (x)) > 0xff ? (FLAG_C | FLAG_H) : 0) | /* CF, HF */ \ - parityTable[((acu + (x)) & 7) ^ temp] /* PF */ - -#define INOUTFLAGS_ZERO(x) INOUTFLAGS(FLAG_Z, x) -#define INOUTFLAGS_NONZERO(x) \ - INOUTFLAGS((HIGH_REGISTER(BC) & 0xa8) | ((HIGH_REGISTER(BC) == 0) << 6), x) - -t_stat sim_instr_nommu(void) { - extern int32 sim_interval; - extern uint32 sim_brk_summ; - int32 reason = SCPE_OK; - register uint32 AF; - register uint32 BC; - register uint32 DE; - register uint32 HL; - register uint32 PC; - register uint32 SP; - register uint32 IX; - register uint32 IY; - register uint32 temp = 0; - register uint32 acu = 0; - register uint32 sum; - register uint32 cbits; - register uint32 op; - register uint32 adr; - register int32 l_sim_brk_summ; - - AF = AF_S; - BC = BC_S; - DE = DE_S; - HL = HL_S; - PC = PC_S & ADDRMASK; - SP = SP_S; - IX = IX_S; - IY = IY_S; - l_sim_brk_summ = sim_brk_summ; - - /* main instruction fetch/decode loop */ - while (TRUE) { /* loop until halted */ - if (sim_interval <= 0) { /* check clock queue */ -#if !UNIX_PLATFORM - if ((reason = sim_poll_kbd()) == SCPE_STOP) - break; /* poll on platforms without reliable signalling */ -#endif - if ((reason = sim_process_event())) - break; - } - - if (l_sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) {/* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - - PCX = PC; - sim_interval--; - - switch(RAM_PP(PC)) { - - case 0x00: /* NOP */ - break; - - case 0x01: /* LD BC,nnnn */ - BC = GET_WORD(PC); - PC += 2; - break; - - case 0x02: /* LD (BC),A */ - PUT_BYTE(BC, HIGH_REGISTER(AF)); - break; - - case 0x03: /* INC BC */ - ++BC; - break; - - case 0x04: /* INC B */ - BC += 0x100; - temp = HIGH_REGISTER(BC); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); /* SET_PV2 uses temp */ - break; - - case 0x05: /* DEC B */ - BC -= 0x100; - temp = HIGH_REGISTER(BC); - AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ - break; - - case 0x06: /* LD B,nn */ - SET_HIGH_REGISTER(BC, RAM_PP(PC)); - break; - - case 0x07: /* RLCA */ - AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) | - (AF & 0xc4) | ((AF >> 15) & 1); - break; - - case 0x08: /* EX AF,AF' */ - CHECK_CPU_8080; - temp = AF; - AF = AF1_S; - AF1_S = temp; - break; - - case 0x09: /* ADD HL,BC */ - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ BC ^ sum) >> 8]; - HL = sum; - break; - - case 0x0a: /* LD A,(BC) */ - SET_HIGH_REGISTER(AF, GET_BYTE(BC)); - break; - - case 0x0b: /* DEC BC */ - --BC; - break; - - case 0x0c: /* INC C */ - temp = LOW_REGISTER(BC) + 1; - SET_LOW_REGISTER(BC, temp); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); - break; - - case 0x0d: /* DEC C */ - temp = LOW_REGISTER(BC) - 1; - SET_LOW_REGISTER(BC, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); - break; - - case 0x0e: /* LD C,nn */ - SET_LOW_REGISTER(BC, RAM_PP(PC)); - break; - - case 0x0f: /* RRCA */ - AF = (AF & 0xc4) | rrcaTable[HIGH_REGISTER(AF)]; - break; - - case 0x10: /* DJNZ dd */ - CHECK_CPU_8080; - if ((BC -= 0x100) & 0xff00) - PC += (int8) GET_BYTE(PC) + 1; - else - PC++; - break; - - case 0x11: /* LD DE,nnnn */ - DE = GET_WORD(PC); - PC += 2; - break; - - case 0x12: /* LD (DE),A */ - PUT_BYTE(DE, HIGH_REGISTER(AF)); - break; - - case 0x13: /* INC DE */ - ++DE; - break; - - case 0x14: /* INC D */ - DE += 0x100; - temp = HIGH_REGISTER(DE); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); /* SET_PV2 uses temp */ - break; - - case 0x15: /* DEC D */ - DE -= 0x100; - temp = HIGH_REGISTER(DE); - AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ - break; - - case 0x16: /* LD D,nn */ - SET_HIGH_REGISTER(DE, RAM_PP(PC)); - break; - - case 0x17: /* RLA */ - AF = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) | - (AF & 0xc4) | ((AF >> 15) & 1); - break; - - case 0x18: /* JR dd */ - CHECK_CPU_8080; - PC += (int8) GET_BYTE(PC) + 1; - break; - - case 0x19: /* ADD HL,DE */ - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ DE ^ sum) >> 8]; - HL = sum; - break; - - case 0x1a: /* LD A,(DE) */ - SET_HIGH_REGISTER(AF, GET_BYTE(DE)); - break; - - case 0x1b: /* DEC DE */ - --DE; - break; - - case 0x1c: /* INC E */ - temp = LOW_REGISTER(DE) + 1; - SET_LOW_REGISTER(DE, temp); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); - break; - - case 0x1d: /* DEC E */ - temp = LOW_REGISTER(DE) - 1; - SET_LOW_REGISTER(DE, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); - break; - - case 0x1e: /* LD E,nn */ - SET_LOW_REGISTER(DE, RAM_PP(PC)); - break; - - case 0x1f: /* RRA */ - AF = ((AF & 1) << 15) | (AF & 0xc4) | rraTable[HIGH_REGISTER(AF)]; - break; - - case 0x20: /* JR NZ,dd */ - CHECK_CPU_8080; - if (TSTFLAG(Z)) - PC++; - else - PC += (int8) GET_BYTE(PC) + 1; - break; - - case 0x21: /* LD HL,nnnn */ - HL = GET_WORD(PC); - PC += 2; - break; - - case 0x22: /* LD (nnnn),HL */ - temp = GET_WORD(PC); - PUT_WORD(temp, HL); - PC += 2; - break; - - case 0x23: /* INC HL */ - ++HL; - break; - - case 0x24: /* INC H */ - HL += 0x100; - temp = HIGH_REGISTER(HL); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); /* SET_PV2 uses temp */ - break; - - case 0x25: /* DEC H */ - HL -= 0x100; - temp = HIGH_REGISTER(HL); - AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ - break; - - case 0x26: /* LD H,nn */ - SET_HIGH_REGISTER(HL, RAM_PP(PC)); - break; - - case 0x27: /* DAA */ - acu = HIGH_REGISTER(AF); - temp = LOW_DIGIT(acu); - cbits = TSTFLAG(C); - if (TSTFLAG(N)) { /* last operation was a subtract */ - int hd = cbits || acu > 0x99; - if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */ - if (temp > 5) - SETFLAG(H, 0); - acu -= 6; - acu &= 0xff; - } - if (hd) - acu -= 0x160; /* adjust high digit */ - } - else { /* last operation was an add */ - if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */ - SETFLAG(H, (temp > 9)); - acu += 6; - } - if (cbits || ((acu & 0x1f0) > 0x90)) - acu += 0x60; /* adjust high digit */ - } - AF = (AF & 0x12) | rrdrldTable[acu & 0xff] | ((acu >> 8) & 1) | cbits; - break; - - case 0x28: /* JR Z,dd */ - CHECK_CPU_8080; - if (TSTFLAG(Z)) - PC += (int8) GET_BYTE(PC) + 1; - else - PC++; - break; - - case 0x29: /* ADD HL,HL */ - HL &= ADDRMASK; - sum = HL + HL; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - HL = sum; - break; - - case 0x2a: /* LD HL,(nnnn) */ - temp = GET_WORD(PC); - HL = GET_WORD(temp); - PC += 2; - break; - - case 0x2b: /* DEC HL */ - --HL; - break; - - case 0x2c: /* INC L */ - temp = LOW_REGISTER(HL) + 1; - SET_LOW_REGISTER(HL, temp); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); - break; - - case 0x2d: /* DEC L */ - temp = LOW_REGISTER(HL) - 1; - SET_LOW_REGISTER(HL, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); - break; - - case 0x2e: /* LD L,nn */ - SET_LOW_REGISTER(HL, RAM_PP(PC)); - break; - - case 0x2f: /* CPL */ - AF = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12; - break; - - case 0x30: /* JR NC,dd */ - CHECK_CPU_8080; - if (TSTFLAG(C)) - PC++; - else - PC += (int8) GET_BYTE(PC) + 1; - break; - - case 0x31: /* LD SP,nnnn */ - SP = GET_WORD(PC); - PC += 2; - break; - - case 0x32: /* LD (nnnn),A */ - temp = GET_WORD(PC); - PUT_BYTE(temp, HIGH_REGISTER(AF)); - PC += 2; - break; - - case 0x33: /* INC SP */ - ++SP; - break; - - case 0x34: /* INC (HL) */ - temp = GET_BYTE(HL) + 1; - PUT_BYTE(HL, temp); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); - break; - - case 0x35: /* DEC (HL) */ - temp = GET_BYTE(HL) - 1; - PUT_BYTE(HL, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SET_PV2(0x7f); - break; - - case 0x36: /* LD (HL),nn */ - PUT_BYTE(HL, RAM_PP(PC)); - break; - - case 0x37: /* SCF */ - AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | 1; - break; - - case 0x38: /* JR C,dd */ - CHECK_CPU_8080; - if (TSTFLAG(C)) - PC += (int8) GET_BYTE(PC) + 1; - else - PC++; - break; - - case 0x39: /* ADD HL,SP */ - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ SP ^ sum) >> 8]; - HL = sum; - break; - - case 0x3a: /* LD A,(nnnn) */ - temp = GET_WORD(PC); - SET_HIGH_REGISTER(AF, GET_BYTE(temp)); - PC += 2; - break; - - case 0x3b: /* DEC SP */ - --SP; - break; - - case 0x3c: /* INC A */ - AF += 0x100; - temp = HIGH_REGISTER(AF); - AF = (AF & ~0xfe) | incTable[temp] | SET_PV2(0x80); /* SET_PV2 uses temp */ - break; - - case 0x3d: /* DEC A */ - AF -= 0x100; - temp = HIGH_REGISTER(AF); - AF = (AF & ~0xfe) | decTable[temp] | SET_PV2(0x7f); /* SET_PV2 uses temp */ - break; - - case 0x3e: /* LD A,nn */ - SET_HIGH_REGISTER(AF, RAM_PP(PC)); - break; - - case 0x3f: /* CCF */ - AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | ((AF & 1) << 4) | (~AF & 1); - break; - - case 0x40: /* LD B,B */ - break; - - case 0x41: /* LD B,C */ - BC = (BC & 0xff) | ((BC & 0xff) << 8); - break; - - case 0x42: /* LD B,D */ - BC = (BC & 0xff) | (DE & ~0xff); - break; - - case 0x43: /* LD B,E */ - BC = (BC & 0xff) | ((DE & 0xff) << 8); - break; - - case 0x44: /* LD B,H */ - BC = (BC & 0xff) | (HL & ~0xff); - break; - - case 0x45: /* LD B,L */ - BC = (BC & 0xff) | ((HL & 0xff) << 8); - break; - - case 0x46: /* LD B,(HL) */ - SET_HIGH_REGISTER(BC, GET_BYTE(HL)); - break; - - case 0x47: /* LD B,A */ - BC = (BC & 0xff) | (AF & ~0xff); - break; - - case 0x48: /* LD C,B */ - BC = (BC & ~0xff) | ((BC >> 8) & 0xff); - break; - - case 0x49: /* LD C,C */ - break; - - case 0x4a: /* LD C,D */ - BC = (BC & ~0xff) | ((DE >> 8) & 0xff); - break; - - case 0x4b: /* LD C,E */ - BC = (BC & ~0xff) | (DE & 0xff); - break; - - case 0x4c: /* LD C,H */ - BC = (BC & ~0xff) | ((HL >> 8) & 0xff); - break; - - case 0x4d: /* LD C,L */ - BC = (BC & ~0xff) | (HL & 0xff); - break; - - case 0x4e: /* LD C,(HL) */ - SET_LOW_REGISTER(BC, GET_BYTE(HL)); - break; - - case 0x4f: /* LD C,A */ - BC = (BC & ~0xff) | ((AF >> 8) & 0xff); - break; - - case 0x50: /* LD D,B */ - DE = (DE & 0xff) | (BC & ~0xff); - break; - - case 0x51: /* LD D,C */ - DE = (DE & 0xff) | ((BC & 0xff) << 8); - break; - - case 0x52: /* LD D,D */ - break; - - case 0x53: /* LD D,E */ - DE = (DE & 0xff) | ((DE & 0xff) << 8); - break; - - case 0x54: /* LD D,H */ - DE = (DE & 0xff) | (HL & ~0xff); - break; - - case 0x55: /* LD D,L */ - DE = (DE & 0xff) | ((HL & 0xff) << 8); - break; - - case 0x56: /* LD D,(HL) */ - SET_HIGH_REGISTER(DE, GET_BYTE(HL)); - break; - - case 0x57: /* LD D,A */ - DE = (DE & 0xff) | (AF & ~0xff); - break; - - case 0x58: /* LD E,B */ - DE = (DE & ~0xff) | ((BC >> 8) & 0xff); - break; - - case 0x59: /* LD E,C */ - DE = (DE & ~0xff) | (BC & 0xff); - break; - - case 0x5a: /* LD E,D */ - DE = (DE & ~0xff) | ((DE >> 8) & 0xff); - break; - - case 0x5b: /* LD E,E */ - break; - - case 0x5c: /* LD E,H */ - DE = (DE & ~0xff) | ((HL >> 8) & 0xff); - break; - - case 0x5d: /* LD E,L */ - DE = (DE & ~0xff) | (HL & 0xff); - break; - - case 0x5e: /* LD E,(HL) */ - SET_LOW_REGISTER(DE, GET_BYTE(HL)); - break; - - case 0x5f: /* LD E,A */ - DE = (DE & ~0xff) | ((AF >> 8) & 0xff); - break; - - case 0x60: /* LD H,B */ - HL = (HL & 0xff) | (BC & ~0xff); - break; - - case 0x61: /* LD H,C */ - HL = (HL & 0xff) | ((BC & 0xff) << 8); - break; - - case 0x62: /* LD H,D */ - HL = (HL & 0xff) | (DE & ~0xff); - break; - - case 0x63: /* LD H,E */ - HL = (HL & 0xff) | ((DE & 0xff) << 8); - break; - - case 0x64: /* LD H,H */ - break; - - case 0x65: /* LD H,L */ - HL = (HL & 0xff) | ((HL & 0xff) << 8); - break; - - case 0x66: /* LD H,(HL) */ - SET_HIGH_REGISTER(HL, GET_BYTE(HL)); - break; - - case 0x67: /* LD H,A */ - HL = (HL & 0xff) | (AF & ~0xff); - break; - - case 0x68: /* LD L,B */ - HL = (HL & ~0xff) | ((BC >> 8) & 0xff); - break; - - case 0x69: /* LD L,C */ - HL = (HL & ~0xff) | (BC & 0xff); - break; - - case 0x6a: /* LD L,D */ - HL = (HL & ~0xff) | ((DE >> 8) & 0xff); - break; - - case 0x6b: /* LD L,E */ - HL = (HL & ~0xff) | (DE & 0xff); - break; - - case 0x6c: /* LD L,H */ - HL = (HL & ~0xff) | ((HL >> 8) & 0xff); - break; - - case 0x6d: /* LD L,L */ - break; - - case 0x6e: /* LD L,(HL) */ - SET_LOW_REGISTER(HL, GET_BYTE(HL)); - break; - - case 0x6f: /* LD L,A */ - HL = (HL & ~0xff) | ((AF >> 8) & 0xff); - break; - - case 0x70: /* LD (HL),B */ - PUT_BYTE(HL, HIGH_REGISTER(BC)); - break; - - case 0x71: /* LD (HL),C */ - PUT_BYTE(HL, LOW_REGISTER(BC)); - break; - - case 0x72: /* LD (HL),D */ - PUT_BYTE(HL, HIGH_REGISTER(DE)); - break; - - case 0x73: /* LD (HL),E */ - PUT_BYTE(HL, LOW_REGISTER(DE)); - break; - - case 0x74: /* LD (HL),H */ - PUT_BYTE(HL, HIGH_REGISTER(HL)); - break; - - case 0x75: /* LD (HL),L */ - PUT_BYTE(HL, LOW_REGISTER(HL)); - break; - - case 0x76: /* HALT */ - PC--; - if (cpu_unit.flags & UNIT_CPU_STOPONHALT) { - reason = STOP_HALT; - goto end_decode; - } - sim_interval = 0; - break; - - case 0x77: /* LD (HL),A */ - PUT_BYTE(HL, HIGH_REGISTER(AF)); - break; - - case 0x78: /* LD A,B */ - AF = (AF & 0xff) | (BC & ~0xff); - break; - - case 0x79: /* LD A,C */ - AF = (AF & 0xff) | ((BC & 0xff) << 8); - break; - - case 0x7a: /* LD A,D */ - AF = (AF & 0xff) | (DE & ~0xff); - break; - - case 0x7b: /* LD A,E */ - AF = (AF & 0xff) | ((DE & 0xff) << 8); - break; - - case 0x7c: /* LD A,H */ - AF = (AF & 0xff) | (HL & ~0xff); - break; - - case 0x7d: /* LD A,L */ - AF = (AF & 0xff) | ((HL & 0xff) << 8); - break; - - case 0x7e: /* LD A,(HL) */ - SET_HIGH_REGISTER(AF, GET_BYTE(HL)); - break; - - case 0x7f: /* LD A,A */ - break; - - case 0x80: /* ADD A,B */ - temp = HIGH_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x81: /* ADD A,C */ - temp = LOW_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x82: /* ADD A,D */ - temp = HIGH_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x83: /* ADD A,E */ - temp = LOW_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x84: /* ADD A,H */ - temp = HIGH_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x85: /* ADD A,L */ - temp = LOW_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x86: /* ADD A,(HL) */ - temp = GET_BYTE(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x87: /* ADD A,A */ - cbits = 2 * HIGH_REGISTER(AF); - AF = cbitsDup8Table[cbits] | (SET_PVS(cbits)); - break; - - case 0x88: /* ADC A,B */ - temp = HIGH_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x89: /* ADC A,C */ - temp = LOW_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8a: /* ADC A,D */ - temp = HIGH_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8b: /* ADC A,E */ - temp = LOW_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8c: /* ADC A,H */ - temp = HIGH_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8d: /* ADC A,L */ - temp = LOW_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8e: /* ADC A,(HL) */ - temp = GET_BYTE(HL); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0x8f: /* ADC A,A */ - cbits = 2 * HIGH_REGISTER(AF) + TSTFLAG(C); - AF = cbitsDup8Table[cbits] | (SET_PVS(cbits)); - break; - - case 0x90: /* SUB B */ - temp = HIGH_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x91: /* SUB C */ - temp = LOW_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x92: /* SUB D */ - temp = HIGH_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x93: /* SUB E */ - temp = LOW_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x94: /* SUB H */ - temp = HIGH_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x95: /* SUB L */ - temp = LOW_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x96: /* SUB (HL) */ - temp = GET_BYTE(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x97: /* SUB A */ - AF = (chiptype == CHIP_TYPE_Z80) ? 0x42 : 0x46; - break; - - case 0x98: /* SBC A,B */ - temp = HIGH_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x99: /* SBC A,C */ - temp = LOW_REGISTER(BC); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9a: /* SBC A,D */ - temp = HIGH_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9b: /* SBC A,E */ - temp = LOW_REGISTER(DE); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9c: /* SBC A,H */ - temp = HIGH_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9d: /* SBC A,L */ - temp = LOW_REGISTER(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9e: /* SBC A,(HL) */ - temp = GET_BYTE(HL); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0x9f: /* SBC A,A */ - cbits = -TSTFLAG(C); - AF = subTable[cbits & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PVS(cbits)); - break; - - case 0xa0: /* AND B */ - AF = andTable[((AF & BC) >> 8) & 0xff]; - break; - - case 0xa1: /* AND C */ - AF = andTable[((AF >> 8) & BC) & 0xff]; - break; - - case 0xa2: /* AND D */ - AF = andTable[((AF & DE) >> 8) & 0xff]; - break; - - case 0xa3: /* AND E */ - AF = andTable[((AF >> 8) & DE) & 0xff]; - break; - - case 0xa4: /* AND H */ - AF = andTable[((AF & HL) >> 8) & 0xff]; - break; - - case 0xa5: /* AND L */ - AF = andTable[((AF >> 8) & HL) & 0xff]; - break; - - case 0xa6: /* AND (HL) */ - AF = andTable[((AF >> 8) & GET_BYTE(HL)) & 0xff]; - break; - - case 0xa7: /* AND A */ - AF = andTable[(AF >> 8) & 0xff]; - break; - - case 0xa8: /* XOR B */ - AF = xororTable[((AF ^ BC) >> 8) & 0xff]; - break; - - case 0xa9: /* XOR C */ - AF = xororTable[((AF >> 8) ^ BC) & 0xff]; - break; - - case 0xaa: /* XOR D */ - AF = xororTable[((AF ^ DE) >> 8) & 0xff]; - break; - - case 0xab: /* XOR E */ - AF = xororTable[((AF >> 8) ^ DE) & 0xff]; - break; - - case 0xac: /* XOR H */ - AF = xororTable[((AF ^ HL) >> 8) & 0xff]; - break; - - case 0xad: /* XOR L */ - AF = xororTable[((AF >> 8) ^ HL) & 0xff]; - break; - - case 0xae: /* XOR (HL) */ - AF = xororTable[((AF >> 8) ^ GET_BYTE(HL)) & 0xff]; - break; - - case 0xaf: /* XOR A */ - AF = 0x44; - break; - - case 0xb0: /* OR B */ - AF = xororTable[((AF | BC) >> 8) & 0xff]; - break; - - case 0xb1: /* OR C */ - AF = xororTable[((AF >> 8) | BC) & 0xff]; - break; - - case 0xb2: /* OR D */ - AF = xororTable[((AF | DE) >> 8) & 0xff]; - break; - - case 0xb3: /* OR E */ - AF = xororTable[((AF >> 8) | DE) & 0xff]; - break; - - case 0xb4: /* OR H */ - AF = xororTable[((AF | HL) >> 8) & 0xff]; - break; - - case 0xb5: /* OR L */ - AF = xororTable[((AF >> 8) | HL) & 0xff]; - break; - - case 0xb6: /* OR (HL) */ - AF = xororTable[((AF >> 8) | GET_BYTE(HL)) & 0xff]; - break; - - case 0xb7: /* OR A */ - AF = xororTable[(AF >> 8) & 0xff]; - break; - - case 0xb8: /* CP B */ - temp = HIGH_REGISTER(BC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xb9: /* CP C */ - temp = LOW_REGISTER(BC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xba: /* CP D */ - temp = HIGH_REGISTER(DE); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xbb: /* CP E */ - temp = LOW_REGISTER(DE); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xbc: /* CP H */ - temp = HIGH_REGISTER(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xbd: /* CP L */ - temp = LOW_REGISTER(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xbe: /* CP (HL) */ - temp = GET_BYTE(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xbf: /* CP A */ - SET_LOW_REGISTER(AF, (HIGH_REGISTER(AF) & 0x28) | (chiptype == CHIP_TYPE_Z80 ? 0x42 : 0x46)); - break; - - case 0xc0: /* RET NZ */ - if (!(TSTFLAG(Z))) - POP(PC); - break; - - case 0xc1: /* POP BC */ - POP(BC); - break; - - case 0xc2: /* JP NZ,nnnn */ - JPC(!TSTFLAG(Z)); - break; - - case 0xc3: /* JP nnnn */ - JPC(1); - break; - - case 0xc4: /* CALL NZ,nnnn */ - CALLC(!TSTFLAG(Z)); - break; - - case 0xc5: /* PUSH BC */ - PUSH(BC); - break; - - case 0xc6: /* ADD A,nn */ - temp = RAM_PP(PC); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0xc7: /* RST 0 */ - PUSH(PC); - PC = 0; - break; - - case 0xc8: /* RET Z */ - if (TSTFLAG(Z)) - POP(PC); - break; - - case 0xc9: /* RET */ - POP(PC); - break; - - case 0xca: /* JP Z,nnnn */ - JPC(TSTFLAG(Z)); - break; - - case 0xcb: /* CB prefix */ - CHECK_CPU_8080; - adr = HL; - switch ((op = GET_BYTE(PC)) & 7) { - - case 0: - ++PC; - acu = HIGH_REGISTER(BC); - break; - - case 1: - ++PC; - acu = LOW_REGISTER(BC); - break; - - case 2: - ++PC; - acu = HIGH_REGISTER(DE); - break; - - case 3: - ++PC; - acu = LOW_REGISTER(DE); - break; - - case 4: - ++PC; - acu = HIGH_REGISTER(HL); - break; - - case 5: - ++PC; - acu = LOW_REGISTER(HL); - break; - - case 6: - ++PC; - acu = GET_BYTE(adr); - break; - - case 7: - ++PC; - acu = HIGH_REGISTER(AF); - break; - } - switch (op & 0xc0) { - - case 0x00: /* shift/rotate */ - switch (op & 0x38) { - - case 0x00:/* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg1; - - case 0x08:/* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg1; - - case 0x10:/* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg1; - - case 0x18:/* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg1; - - case 0x20:/* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg1; - - case 0x28:/* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg1; - - case 0x30:/* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg1; - - case 0x38:/* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg1: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - } - break; - - case 0x40: /* BIT */ - if (acu & (1 << ((op >> 3) & 7))) - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - else - AF = (AF & ~0xfe) | 0x54; - if ((op & 7) != 6) - AF |= (acu & 0x28); - temp = acu; - break; - - case 0x80: /* RES */ - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - - case 0xc0: /* SET */ - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - switch (op & 7) { - - case 0: - SET_HIGH_REGISTER(BC, temp); - break; - - case 1: - SET_LOW_REGISTER(BC, temp); - break; - - case 2: - SET_HIGH_REGISTER(DE, temp); - break; - - case 3: - SET_LOW_REGISTER(DE, temp); - break; - - case 4: - SET_HIGH_REGISTER(HL, temp); - break; - - case 5: - SET_LOW_REGISTER(HL, temp); - break; - - case 6: - PUT_BYTE(adr, temp); - break; - - case 7: - SET_HIGH_REGISTER(AF, temp); - break; - } - break; - - case 0xcc: /* CALL Z,nnnn */ - CALLC(TSTFLAG(Z)); - break; - - case 0xcd: /* CALL nnnn */ - CALLC(1); - break; - - case 0xce: /* ADC A,nn */ - temp = RAM_PP(PC); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SET_PV); - break; - - case 0xcf: /* RST 8 */ - PUSH(PC); - PC = 8; - break; - - case 0xd0: /* RET NC */ - if (!(TSTFLAG(C))) - POP(PC); - break; - - case 0xd1: /* POP DE */ - POP(DE); - break; - - case 0xd2: /* JP NC,nnnn */ - JPC(!TSTFLAG(C)); - break; - - case 0xd3: /* OUT (nn),A */ - out(RAM_PP(PC), HIGH_REGISTER(AF)); - break; - - case 0xd4: /* CALL NC,nnnn */ - CALLC(!TSTFLAG(C)); - break; - - case 0xd5: /* PUSH DE */ - PUSH(DE); - break; - - case 0xd6: /* SUB nn */ - temp = RAM_PP(PC); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0xd7: /* RST 10H */ - PUSH(PC); - PC = 0x10; - break; - - case 0xd8: /* RET C */ - if (TSTFLAG(C)) - POP(PC); - break; - - case 0xd9: /* EXX */ - CHECK_CPU_8080; - temp = BC; - BC = BC1_S; - BC1_S = temp; - temp = DE; - DE = DE1_S; - DE1_S = temp; - temp = HL; - HL = HL1_S; - HL1_S = temp; - break; - - case 0xda: /* JP C,nnnn */ - JPC(TSTFLAG(C)); - break; - - case 0xdb: /* IN A,(nn) */ - SET_HIGH_REGISTER(AF, in(RAM_PP(PC))); - break; - - case 0xdc: /* CALL C,nnnn */ - CALLC(TSTFLAG(C)); - break; - - case 0xdd: /* DD prefix */ - CHECK_CPU_8080; - switch (RAM_PP(PC)) { - - case 0x09: /* ADD IX,BC */ - IX &= ADDRMASK; - BC &= ADDRMASK; - sum = IX + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ BC ^ sum) >> 8]; - IX = sum; - break; - - case 0x19: /* ADD IX,DE */ - IX &= ADDRMASK; - DE &= ADDRMASK; - sum = IX + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ DE ^ sum) >> 8]; - IX = sum; - break; - - case 0x21: /* LD IX,nnnn */ - IX = GET_WORD(PC); - PC += 2; - break; - - case 0x22: /* LD (nnnn),IX */ - temp = GET_WORD(PC); - PUT_WORD(temp, IX); - PC += 2; - break; - - case 0x23: /* INC IX */ - ++IX; - break; - - case 0x24: /* INC IXH */ - IX += 0x100; - AF = (AF & ~0xfe) | incZ80Table[HIGH_REGISTER(IX)]; - break; - - case 0x25: /* DEC IXH */ - IX -= 0x100; - AF = (AF & ~0xfe) | decZ80Table[HIGH_REGISTER(IX)]; - break; - - case 0x26: /* LD IXH,nn */ - SET_HIGH_REGISTER(IX, RAM_PP(PC)); - break; - - case 0x29: /* ADD IX,IX */ - IX &= ADDRMASK; - sum = IX + IX; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - IX = sum; - break; - - case 0x2a: /* LD IX,(nnnn) */ - temp = GET_WORD(PC); - IX = GET_WORD(temp); - PC += 2; - break; - - case 0x2b: /* DEC IX */ - --IX; - break; - - case 0x2c: /* INC IXL */ - temp = LOW_REGISTER(IX) + 1; - SET_LOW_REGISTER(IX, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - - case 0x2d: /* DEC IXL */ - temp = LOW_REGISTER(IX) - 1; - SET_LOW_REGISTER(IX, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - - case 0x2e: /* LD IXL,nn */ - SET_LOW_REGISTER(IX, RAM_PP(PC)); - break; - - case 0x34: /* INC (IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - temp = GET_BYTE(adr) + 1; - PUT_BYTE(adr, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - - case 0x35: /* DEC (IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - temp = GET_BYTE(adr) - 1; - PUT_BYTE(adr, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - - case 0x36: /* LD (IX+dd),nn */ - adr = IX + (int8) RAM_PP(PC); - PUT_BYTE(adr, RAM_PP(PC)); - break; - - case 0x39: /* ADD IX,SP */ - IX &= ADDRMASK; - SP &= ADDRMASK; - sum = IX + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ SP ^ sum) >> 8]; - IX = sum; - break; - - case 0x44: /* LD B,IXH */ - SET_HIGH_REGISTER(BC, HIGH_REGISTER(IX)); - break; - - case 0x45: /* LD B,IXL */ - SET_HIGH_REGISTER(BC, LOW_REGISTER(IX)); - break; - - case 0x46: /* LD B,(IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - SET_HIGH_REGISTER(BC, GET_BYTE(adr)); - break; - - case 0x4c: /* LD C,IXH */ - SET_LOW_REGISTER(BC, HIGH_REGISTER(IX)); - break; - - case 0x4d: /* LD C,IXL */ - SET_LOW_REGISTER(BC, LOW_REGISTER(IX)); - break; - - case 0x4e: /* LD C,(IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - SET_LOW_REGISTER(BC, GET_BYTE(adr)); - break; - - case 0x54: /* LD D,IXH */ - SET_HIGH_REGISTER(DE, HIGH_REGISTER(IX)); - break; - - case 0x55: /* LD D,IXL */ - SET_HIGH_REGISTER(DE, LOW_REGISTER(IX)); - break; - - case 0x56: /* LD D,(IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - SET_HIGH_REGISTER(DE, GET_BYTE(adr)); - break; - - case 0x5c: /* LD E,IXH */ - SET_LOW_REGISTER(DE, HIGH_REGISTER(IX)); - break; - - case 0x5d: /* LD E,IXL */ - SET_LOW_REGISTER(DE, LOW_REGISTER(IX)); - break; - - case 0x5e: /* LD E,(IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - SET_LOW_REGISTER(DE, GET_BYTE(adr)); - break; - - case 0x60: /* LD IXH,B */ - SET_HIGH_REGISTER(IX, HIGH_REGISTER(BC)); - break; - - case 0x61: /* LD IXH,C */ - SET_HIGH_REGISTER(IX, LOW_REGISTER(BC)); - break; - - case 0x62: /* LD IXH,D */ - SET_HIGH_REGISTER(IX, HIGH_REGISTER(DE)); - break; - - case 0x63: /* LD IXH,E */ - SET_HIGH_REGISTER(IX, LOW_REGISTER(DE)); - break; - - case 0x64: /* LD IXH,IXH */ - break; - - case 0x65: /* LD IXH,IXL */ - SET_HIGH_REGISTER(IX, LOW_REGISTER(IX)); - break; - - case 0x66: /* LD H,(IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - SET_HIGH_REGISTER(HL, GET_BYTE(adr)); - break; - - case 0x67: /* LD IXH,A */ - SET_HIGH_REGISTER(IX, HIGH_REGISTER(AF)); - break; - - case 0x68: /* LD IXL,B */ - SET_LOW_REGISTER(IX, HIGH_REGISTER(BC)); - break; - - case 0x69: /* LD IXL,C */ - SET_LOW_REGISTER(IX, LOW_REGISTER(BC)); - break; - - case 0x6a: /* LD IXL,D */ - SET_LOW_REGISTER(IX, HIGH_REGISTER(DE)); - break; - - case 0x6b: /* LD IXL,E */ - SET_LOW_REGISTER(IX, LOW_REGISTER(DE)); - break; - - case 0x6c: /* LD IXL,IXH */ - SET_LOW_REGISTER(IX, HIGH_REGISTER(IX)); - break; - - case 0x6d: /* LD IXL,IXL */ - break; - - case 0x6e: /* LD L,(IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - SET_LOW_REGISTER(HL, GET_BYTE(adr)); - break; - - case 0x6f: /* LD IXL,A */ - SET_LOW_REGISTER(IX, HIGH_REGISTER(AF)); - break; - - case 0x70: /* LD (IX+dd),B */ - adr = IX + (int8) RAM_PP(PC); - PUT_BYTE(adr, HIGH_REGISTER(BC)); - break; - - case 0x71: /* LD (IX+dd),C */ - adr = IX + (int8) RAM_PP(PC); - PUT_BYTE(adr, LOW_REGISTER(BC)); - break; - - case 0x72: /* LD (IX+dd),D */ - adr = IX + (int8) RAM_PP(PC); - PUT_BYTE(adr, HIGH_REGISTER(DE)); - break; - - case 0x73: /* LD (IX+dd),E */ - adr = IX + (int8) RAM_PP(PC); - PUT_BYTE(adr, LOW_REGISTER(DE)); - break; - - case 0x74: /* LD (IX+dd),H */ - adr = IX + (int8) RAM_PP(PC); - PUT_BYTE(adr, HIGH_REGISTER(HL)); - break; - - case 0x75: /* LD (IX+dd),L */ - adr = IX + (int8) RAM_PP(PC); - PUT_BYTE(adr, LOW_REGISTER(HL)); - break; - - case 0x77: /* LD (IX+dd),A */ - adr = IX + (int8) RAM_PP(PC); - PUT_BYTE(adr, HIGH_REGISTER(AF)); - break; - - case 0x7c: /* LD A,IXH */ - SET_HIGH_REGISTER(AF, HIGH_REGISTER(IX)); - break; - - case 0x7d: /* LD A,IXL */ - SET_HIGH_REGISTER(AF, LOW_REGISTER(IX)); - break; - - case 0x7e: /* LD A,(IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - SET_HIGH_REGISTER(AF, GET_BYTE(adr)); - break; - - case 0x84: /* ADD A,IXH */ - temp = HIGH_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x85: /* ADD A,IXL */ - temp = LOW_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x86: /* ADD A,(IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - temp = GET_BYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8c: /* ADC A,IXH */ - temp = HIGH_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8d: /* ADC A,IXL */ - temp = LOW_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8e: /* ADC A,(IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - temp = GET_BYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x96: /* SUB (IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - temp = GET_BYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x94: /* SUB IXH */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - - case 0x9c: /* SBC A,IXH */ - temp = HIGH_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x95: /* SUB IXL */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - - case 0x9d: /* SBC A,IXL */ - temp = LOW_REGISTER(IX); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x9e: /* SBC A,(IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - temp = GET_BYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xa4: /* AND IXH */ - AF = andTable[((AF & IX) >> 8) & 0xff]; - break; - - case 0xa5: /* AND IXL */ - AF = andTable[((AF >> 8) & IX) & 0xff]; - break; - - case 0xa6: /* AND (IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - AF = andTable[((AF >> 8) & GET_BYTE(adr)) & 0xff]; - break; - - case 0xac: /* XOR IXH */ - AF = xororTable[((AF ^ IX) >> 8) & 0xff]; - break; - - case 0xad: /* XOR IXL */ - AF = xororTable[((AF >> 8) ^ IX) & 0xff]; - break; - - case 0xae: /* XOR (IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - AF = xororTable[((AF >> 8) ^ GET_BYTE(adr)) & 0xff]; - break; - - case 0xb4: /* OR IXH */ - AF = xororTable[((AF | IX) >> 8) & 0xff]; - break; - - case 0xb5: /* OR IXL */ - AF = xororTable[((AF >> 8) | IX) & 0xff]; - break; - - case 0xb6: /* OR (IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - AF = xororTable[((AF >> 8) | GET_BYTE(adr)) & 0xff]; - break; - - case 0xbc: /* CP IXH */ - temp = HIGH_REGISTER(IX); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xbd: /* CP IXL */ - temp = LOW_REGISTER(IX); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xbe: /* CP (IX+dd) */ - adr = IX + (int8) RAM_PP(PC); - temp = GET_BYTE(adr); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xcb: /* CB prefix */ - adr = IX + (int8) RAM_PP(PC); - switch ((op = GET_BYTE(PC)) & 7) { - - case 0: - ++PC; - acu = HIGH_REGISTER(BC); - break; - - case 1: - ++PC; - acu = LOW_REGISTER(BC); - break; - - case 2: - ++PC; - acu = HIGH_REGISTER(DE); - break; - - case 3: - ++PC; - acu = LOW_REGISTER(DE); - break; - - case 4: - ++PC; - acu = HIGH_REGISTER(HL); - break; - - case 5: - ++PC; - acu = LOW_REGISTER(HL); - break; - - case 6: - ++PC; - acu = GET_BYTE(adr); - break; - - case 7: - ++PC; - acu = HIGH_REGISTER(AF); - break; - } - switch (op & 0xc0) { - - case 0x00: /* shift/rotate */ - switch (op & 0x38) { - - case 0x00:/* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg2; - - case 0x08:/* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg2; - - case 0x10:/* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg2; - - case 0x18:/* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg2; - - case 0x20:/* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg2; - - case 0x28:/* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg2; - - case 0x30:/* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg2; - - case 0x38:/* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg2: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - } - break; - - case 0x40: /* BIT */ - if (acu & (1 << ((op >> 3) & 7))) - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - else - AF = (AF & ~0xfe) | 0x54; - if ((op & 7) != 6) - AF |= (acu & 0x28); - temp = acu; - break; - - case 0x80: /* RES */ - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - - case 0xc0: /* SET */ - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - switch (op & 7) { - - case 0: - SET_HIGH_REGISTER(BC, temp); - break; - - case 1: - SET_LOW_REGISTER(BC, temp); - break; - - case 2: - SET_HIGH_REGISTER(DE, temp); - break; - - case 3: - SET_LOW_REGISTER(DE, temp); - break; - - case 4: - SET_HIGH_REGISTER(HL, temp); - break; - - case 5: - SET_LOW_REGISTER(HL, temp); - break; - - case 6: - PUT_BYTE(adr, temp); - break; - - case 7: - SET_HIGH_REGISTER(AF, temp); - break; - } - break; - - case 0xe1: /* POP IX */ - POP(IX); - break; - - case 0xe3: /* EX (SP),IX */ - temp = IX; - POP(IX); - PUSH(temp); - break; - - case 0xe5: /* PUSH IX */ - PUSH(IX); - break; - - case 0xe9: /* JP (IX) */ - PC = IX; - break; - - case 0xf9: /* LD SP,IX */ - SP = IX; - break; - - default: /* ignore DD */ - CHECK_CPU_Z80; - PC--; - } - break; - - case 0xde: /* SBC A,nn */ - temp = RAM_PP(PC); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SET_PV); - break; - - case 0xdf: /* RST 18H */ - PUSH(PC); - PC = 0x18; - break; - - case 0xe0: /* RET PO */ - if (!(TSTFLAG(P))) - POP(PC); - break; - - case 0xe1: /* POP HL */ - POP(HL); - break; - - case 0xe2: /* JP PO,nnnn */ - JPC(!TSTFLAG(P)); - break; - - case 0xe3: /* EX (SP),HL */ - temp = HL; - POP(HL); - PUSH(temp); - break; - - case 0xe4: /* CALL PO,nnnn */ - CALLC(!TSTFLAG(P)); - break; - - case 0xe5: /* PUSH HL */ - PUSH(HL); - break; - - case 0xe6: /* AND nn */ - AF = andTable[((AF >> 8) & RAM_PP(PC)) & 0xff]; - break; - - case 0xe7: /* RST 20H */ - PUSH(PC); - PC = 0x20; - break; - - case 0xe8: /* RET PE */ - if (TSTFLAG(P)) - POP(PC); - break; - - case 0xe9: /* JP (HL) */ - PC = HL; - break; - - case 0xea: /* JP PE,nnnn */ - JPC(TSTFLAG(P)); - break; - - case 0xeb: /* EX DE,HL */ - temp = HL; - HL = DE; - DE = temp; - break; - - case 0xec: /* CALL PE,nnnn */ - CALLC(TSTFLAG(P)); - break; - - case 0xed: /* ED prefix */ - CHECK_CPU_8080; - switch (RAM_PP(PC)) { - - case 0x40: /* IN B,(C) */ - temp = in(LOW_REGISTER(BC)); - SET_HIGH_REGISTER(BC, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x41: /* OUT (C),B */ - out(LOW_REGISTER(BC), HIGH_REGISTER(BC)); - break; - - case 0x42: /* SBC HL,BC */ - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL - BC - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ BC ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - - case 0x43: /* LD (nnnn),BC */ - temp = GET_WORD(PC); - PUT_WORD(temp, BC); - PC += 2; - break; - - case 0x44: /* NEG */ - - case 0x4C: /* NEG, unofficial */ - - case 0x54: /* NEG, unofficial */ - - case 0x5C: /* NEG, unofficial */ - - case 0x64: /* NEG, unofficial */ - - case 0x6C: /* NEG, unofficial */ - - case 0x74: /* NEG, unofficial */ - - case 0x7C: /* NEG, unofficial */ - temp = HIGH_REGISTER(AF); - AF = ((~(AF & 0xff00) + 1) & 0xff00); /* AF = (-(AF & 0xff00) & 0xff00); */ - AF |= ((AF >> 8) & 0xa8) | (((AF & 0xff00) == 0) << 6) | negTable[temp]; - break; - - case 0x45: /* RETN */ - - case 0x55: /* RETN, unofficial */ - - case 0x5D: /* RETN, unofficial */ - - case 0x65: /* RETN, unofficial */ - - case 0x6D: /* RETN, unofficial */ - - case 0x75: /* RETN, unofficial */ - - case 0x7D: /* RETN, unofficial */ - IFF_S |= IFF_S >> 1; - POP(PC); - break; - - case 0x46: /* IM 0 */ - /* interrupt mode 0 */ - break; - - case 0x47: /* LD I,A */ - IR_S = (IR_S & 0xff) | (AF & ~0xff); - break; - - case 0x48: /* IN C,(C) */ - temp = in(LOW_REGISTER(BC)); - SET_LOW_REGISTER(BC, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x49: /* OUT (C),C */ - out(LOW_REGISTER(BC), LOW_REGISTER(BC)); - break; - - case 0x4a: /* ADC HL,BC */ - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL + BC + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ BC ^ sum) >> 8]; - HL = sum; - break; - - case 0x4b: /* LD BC,(nnnn) */ - temp = GET_WORD(PC); - BC = GET_WORD(temp); - PC += 2; - break; - - case 0x4d: /* RETI */ - IFF_S |= IFF_S >> 1; - POP(PC); - break; - - case 0x4f: /* LD R,A */ - IR_S = (IR_S & ~0xff) | ((AF >> 8) & 0xff); - break; - - case 0x50: /* IN D,(C) */ - temp = in(LOW_REGISTER(BC)); - SET_HIGH_REGISTER(DE, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x51: /* OUT (C),D */ - out(LOW_REGISTER(BC), HIGH_REGISTER(DE)); - break; - - case 0x52: /* SBC HL,DE */ - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL - DE - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ DE ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - - case 0x53: /* LD (nnnn),DE */ - temp = GET_WORD(PC); - PUT_WORD(temp, DE); - PC += 2; - break; - - case 0x56: /* IM 1 */ - /* interrupt mode 1 */ - break; - - case 0x57: /* LD A,I */ - AF = (AF & 0x29) | (IR_S & ~0xff) | ((IR_S >> 8) & 0x80) | (((IR_S & ~0xff) == 0) << 6) | ((IFF_S & 2) << 1); - break; - - case 0x58: /* IN E,(C) */ - temp = in(LOW_REGISTER(BC)); - SET_LOW_REGISTER(DE, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x59: /* OUT (C),E */ - out(LOW_REGISTER(BC), LOW_REGISTER(DE)); - break; - - case 0x5a: /* ADC HL,DE */ - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL + DE + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ DE ^ sum) >> 8]; - HL = sum; - break; - - case 0x5b: /* LD DE,(nnnn) */ - temp = GET_WORD(PC); - DE = GET_WORD(temp); - PC += 2; - break; - - case 0x5e: /* IM 2 */ - /* interrupt mode 2 */ - break; - - case 0x5f: /* LD A,R */ - AF = (AF & 0x29) | ((IR_S & 0xff) << 8) | (IR_S & 0x80) | - (((IR_S & 0xff) == 0) << 6) | ((IFF_S & 2) << 1); - break; - - case 0x60: /* IN H,(C) */ - temp = in(LOW_REGISTER(BC)); - SET_HIGH_REGISTER(HL, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x61: /* OUT (C),H */ - out(LOW_REGISTER(BC), HIGH_REGISTER(HL)); - break; - - case 0x62: /* SBC HL,HL */ - HL &= ADDRMASK; - sum = HL - HL - TSTFLAG(C); - AF = (AF & ~0xff) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80DupTable[(sum >> 8) & 0x1ff]; - HL = sum; - break; - - case 0x63: /* LD (nnnn),HL */ - temp = GET_WORD(PC); - PUT_WORD(temp, HL); - PC += 2; - break; - - case 0x67: /* RRD */ - temp = GET_BYTE(HL); - acu = HIGH_REGISTER(AF); - PUT_BYTE(HL, HIGH_DIGIT(temp) | (LOW_DIGIT(acu) << 4)); - AF = rrdrldTable[(acu & 0xf0) | LOW_DIGIT(temp)] | (AF & 1); - break; - - case 0x68: /* IN L,(C) */ - temp = in(LOW_REGISTER(BC)); - SET_LOW_REGISTER(HL, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x69: /* OUT (C),L */ - out(LOW_REGISTER(BC), LOW_REGISTER(HL)); - break; - - case 0x6a: /* ADC HL,HL */ - HL &= ADDRMASK; - sum = HL + HL + TSTFLAG(C); - AF = (AF & ~0xff) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80DupTable[sum >> 8]; - HL = sum; - break; - - case 0x6b: /* LD HL,(nnnn) */ - temp = GET_WORD(PC); - HL = GET_WORD(temp); - PC += 2; - break; - - case 0x6f: /* RLD */ - temp = GET_BYTE(HL); - acu = HIGH_REGISTER(AF); - PUT_BYTE(HL, (LOW_DIGIT(temp) << 4) | LOW_DIGIT(acu)); - AF = rrdrldTable[(acu & 0xf0) | HIGH_DIGIT(temp)] | (AF & 1); - break; - - case 0x70: /* IN (C) */ - temp = in(LOW_REGISTER(BC)); - SET_LOW_REGISTER(temp, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x71: /* OUT (C),0 */ - out(LOW_REGISTER(BC), 0); - break; - - case 0x72: /* SBC HL,SP */ - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL - SP - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ SP ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - - case 0x73: /* LD (nnnn),SP */ - temp = GET_WORD(PC); - PUT_WORD(temp, SP); - PC += 2; - break; - - case 0x78: /* IN A,(C) */ - temp = in(LOW_REGISTER(BC)); - SET_HIGH_REGISTER(AF, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - - case 0x79: /* OUT (C),A */ - out(LOW_REGISTER(BC), HIGH_REGISTER(AF)); - break; - - case 0x7a: /* ADC HL,SP */ - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL + SP + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ SP ^ sum) >> 8]; - HL = sum; - break; - - case 0x7b: /* LD SP,(nnnn) */ - temp = GET_WORD(PC); - SP = GET_WORD(temp); - PC += 2; - break; - - case 0xa0: /* LDI */ - acu = RAM_PP(HL); - PUT_BYTE_PP(DE, acu); - acu += HIGH_REGISTER(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) | - (((--BC & ADDRMASK) != 0) << 2); - break; - - case 0xa1: /* CPI */ - acu = HIGH_REGISTER(AF); - temp = RAM_PP(HL); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | (cbits & 16) | - ((sum - ((cbits >> 4) & 1)) & 8) | - ((--BC & ADDRMASK) != 0) << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) - AF &= ~8; - break; - -/* SF, ZF, YF, XF flags are affected by decreasing register B, as in DEC B. - NF flag A is copy of bit 7 of the value read from or written to an I/O port. - INI/INIR/IND/INDR use the C flag in stead of the L register. There is a - catch though, because not the value of C is used, but C + 1 if it's INI/INIR or - C - 1 if it's IND/INDR. So, first of all INI/INIR: - HF and CF Both set if ((HL) + ((C + 1) & 255) > 255) - PF The parity of (((HL) + ((C + 1) & 255)) & 7) xor B) */ - case 0xa2: /* INI */ - acu = in(LOW_REGISTER(BC)); - PUT_BYTE(HL, acu); - ++HL; - temp = HIGH_REGISTER(BC); - BC -= 0x100; - INOUTFLAGS_NONZERO((LOW_REGISTER(BC) + 1) & 0xff); - break; - -/* SF, ZF, YF, XF flags are affected by decreasing register B, as in DEC B. - NF flag A is copy of bit 7 of the value read from or written to an I/O port. - And now the for OUTI/OTIR/OUTD/OTDR instructions. Take state of the L - after the increment or decrement of HL; add the value written to the I/O port - to; call that k for now. If k > 255, then the CF and HF flags are set. The PF - flags is set like the parity of k bitwise and'ed with 7, bitwise xor'ed with B. - HF and CF Both set if ((HL) + L > 255) - PF The parity of ((((HL) + L) & 7) xor B) */ - case 0xa3: /* OUTI */ - acu = GET_BYTE(HL); - out(LOW_REGISTER(BC), acu); - ++HL; - temp = HIGH_REGISTER(BC); - BC -= 0x100; - INOUTFLAGS_NONZERO(LOW_REGISTER(HL)); - break; - - case 0xa8: /* LDD */ - acu = RAM_MM(HL); - PUT_BYTE_MM(DE, acu); - acu += HIGH_REGISTER(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) | - (((--BC & ADDRMASK) != 0) << 2); - break; - - case 0xa9: /* CPD */ - acu = HIGH_REGISTER(AF); - temp = RAM_MM(HL); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | (cbits & 16) | - ((sum - ((cbits >> 4) & 1)) & 8) | - ((--BC & ADDRMASK) != 0) << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) - AF &= ~8; - break; - -/* SF, ZF, YF, XF flags are affected by decreasing register B, as in DEC B. - NF flag A is copy of bit 7 of the value read from or written to an I/O port. - INI/INIR/IND/INDR use the C flag in stead of the L register. There is a - catch though, because not the value of C is used, but C + 1 if it's INI/INIR or - C - 1 if it's IND/INDR. And last IND/INDR: - HF and CF Both set if ((HL) + ((C - 1) & 255) > 255) - PF The parity of (((HL) + ((C - 1) & 255)) & 7) xor B) */ - case 0xaa: /* IND */ - acu = in(LOW_REGISTER(BC)); - PUT_BYTE(HL, acu); - --HL; - temp = HIGH_REGISTER(BC); - BC -= 0x100; - INOUTFLAGS_NONZERO((LOW_REGISTER(BC) - 1) & 0xff); - break; - - case 0xab: /* OUTD */ - acu = GET_BYTE(HL); - out(LOW_REGISTER(BC), acu); - --HL; - temp = HIGH_REGISTER(BC); - BC -= 0x100; - INOUTFLAGS_NONZERO(LOW_REGISTER(HL)); - break; - - case 0xb0: /* LDIR */ - BC &= ADDRMASK; - if (BC == 0) - BC = 0x10000; - do { - acu = RAM_PP(HL); - PUT_BYTE_PP(DE, acu); - } while (--BC); - acu += HIGH_REGISTER(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4); - break; - - case 0xb1: /* CPIR */ - acu = HIGH_REGISTER(AF); - BC &= ADDRMASK; - if (BC == 0) - BC = 0x10000; - do { - temp = RAM_PP(HL); - op = --BC != 0; - sum = acu - temp; - } while (op && sum != 0); - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | - (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) | - op << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) - AF &= ~8; - break; - - case 0xb2: /* INIR */ - temp = HIGH_REGISTER(BC); - if (temp == 0) - temp = 0x100; - do { - acu = in(LOW_REGISTER(BC)); - PUT_BYTE(HL, acu); - ++HL; - } while (--temp); - temp = HIGH_REGISTER(BC); - SET_HIGH_REGISTER(BC, 0); - INOUTFLAGS_ZERO((LOW_REGISTER(BC) + 1) & 0xff); - break; - - case 0xb3: /* OTIR */ - temp = HIGH_REGISTER(BC); - if (temp == 0) - temp = 0x100; - do { - acu = GET_BYTE(HL); - out(LOW_REGISTER(BC), acu); - ++HL; - } while (--temp); - temp = HIGH_REGISTER(BC); - SET_HIGH_REGISTER(BC, 0); - INOUTFLAGS_ZERO(LOW_REGISTER(HL)); - break; - - case 0xb8: /* LDDR */ - BC &= ADDRMASK; - if (BC == 0) - BC = 0x10000; - do { - acu = RAM_MM(HL); - PUT_BYTE_MM(DE, acu); - } while (--BC); - acu += HIGH_REGISTER(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4); - break; - - case 0xb9: /* CPDR */ - acu = HIGH_REGISTER(AF); - BC &= ADDRMASK; - if (BC == 0) - BC = 0x10000; - do { - temp = RAM_MM(HL); - op = --BC != 0; - sum = acu - temp; - } while (op && sum != 0); - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | - (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) | - op << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) - AF &= ~8; - break; - - case 0xba: /* INDR */ - temp = HIGH_REGISTER(BC); - if (temp == 0) - temp = 0x100; - do { - acu = in(LOW_REGISTER(BC)); - PUT_BYTE(HL, acu); - --HL; - } while (--temp); - temp = HIGH_REGISTER(BC); - SET_HIGH_REGISTER(BC, 0); - INOUTFLAGS_ZERO((LOW_REGISTER(BC) - 1) & 0xff); - break; - - case 0xbb: /* OTDR */ - temp = HIGH_REGISTER(BC); - if (temp == 0) - temp = 0x100; - do { - acu = GET_BYTE(HL); - out(LOW_REGISTER(BC), acu); - --HL; - } while (--temp); - temp = HIGH_REGISTER(BC); - SET_HIGH_REGISTER(BC, 0); - INOUTFLAGS_ZERO(LOW_REGISTER(HL)); - break; - - default: /* ignore ED and following byte */ - CHECK_CPU_Z80; - } - break; - - case 0xee: /* XOR nn */ - AF = xororTable[((AF >> 8) ^ RAM_PP(PC)) & 0xff]; - break; - - case 0xef: /* RST 28H */ - PUSH(PC); - PC = 0x28; - break; - - case 0xf0: /* RET P */ - if (!(TSTFLAG(S))) - POP(PC); - break; - - case 0xf1: /* POP AF */ - POP(AF); - break; - - case 0xf2: /* JP P,nnnn */ - JPC(!TSTFLAG(S)); - break; - - case 0xf3: /* DI */ - IFF_S = 0; - break; - - case 0xf4: /* CALL P,nnnn */ - CALLC(!TSTFLAG(S)); - break; - - case 0xf5: /* PUSH AF */ - PUSH(AF); - break; - - case 0xf6: /* OR nn */ - AF = xororTable[((AF >> 8) | RAM_PP(PC)) & 0xff]; - break; - - case 0xf7: /* RST 30H */ - PUSH(PC); - PC = 0x30; - break; - - case 0xf8: /* RET M */ - if (TSTFLAG(S)) - POP(PC); - break; - - case 0xf9: /* LD SP,HL */ - SP = HL; - break; - - case 0xfa: /* JP M,nnnn */ - JPC(TSTFLAG(S)); - break; - - case 0xfb: /* EI */ - IFF_S = 3; - break; - - case 0xfc: /* CALL M,nnnn */ - CALLC(TSTFLAG(S)); - break; - - case 0xfd: /* FD prefix */ - CHECK_CPU_8080; - switch (RAM_PP(PC)) { - - case 0x09: /* ADD IY,BC */ - IY &= ADDRMASK; - BC &= ADDRMASK; - sum = IY + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ BC ^ sum) >> 8]; - IY = sum; - break; - - case 0x19: /* ADD IY,DE */ - IY &= ADDRMASK; - DE &= ADDRMASK; - sum = IY + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ DE ^ sum) >> 8]; - IY = sum; - break; - - case 0x21: /* LD IY,nnnn */ - IY = GET_WORD(PC); - PC += 2; - break; - - case 0x22: /* LD (nnnn),IY */ - temp = GET_WORD(PC); - PUT_WORD(temp, IY); - PC += 2; - break; - - case 0x23: /* INC IY */ - ++IY; - break; - - case 0x24: /* INC IYH */ - IY += 0x100; - AF = (AF & ~0xfe) | incZ80Table[HIGH_REGISTER(IY)]; - break; - - case 0x25: /* DEC IYH */ - IY -= 0x100; - AF = (AF & ~0xfe) | decZ80Table[HIGH_REGISTER(IY)]; - break; - - case 0x26: /* LD IYH,nn */ - SET_HIGH_REGISTER(IY, RAM_PP(PC)); - break; - - case 0x29: /* ADD IY,IY */ - IY &= ADDRMASK; - sum = IY + IY; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - IY = sum; - break; - - case 0x2a: /* LD IY,(nnnn) */ - temp = GET_WORD(PC); - IY = GET_WORD(temp); - PC += 2; - break; - - case 0x2b: /* DEC IY */ - --IY; - break; - - case 0x2c: /* INC IYL */ - temp = LOW_REGISTER(IY) + 1; - SET_LOW_REGISTER(IY, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - - case 0x2d: /* DEC IYL */ - temp = LOW_REGISTER(IY) - 1; - SET_LOW_REGISTER(IY, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - - case 0x2e: /* LD IYL,nn */ - SET_LOW_REGISTER(IY, RAM_PP(PC)); - break; - - case 0x34: /* INC (IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - temp = GET_BYTE(adr) + 1; - PUT_BYTE(adr, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - - case 0x35: /* DEC (IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - temp = GET_BYTE(adr) - 1; - PUT_BYTE(adr, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - - case 0x36: /* LD (IY+dd),nn */ - adr = IY + (int8) RAM_PP(PC); - PUT_BYTE(adr, RAM_PP(PC)); - break; - - case 0x39: /* ADD IY,SP */ - IY &= ADDRMASK; - SP &= ADDRMASK; - sum = IY + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ SP ^ sum) >> 8]; - IY = sum; - break; - - case 0x44: /* LD B,IYH */ - SET_HIGH_REGISTER(BC, HIGH_REGISTER(IY)); - break; - - case 0x45: /* LD B,IYL */ - SET_HIGH_REGISTER(BC, LOW_REGISTER(IY)); - break; - - case 0x46: /* LD B,(IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - SET_HIGH_REGISTER(BC, GET_BYTE(adr)); - break; - - case 0x4c: /* LD C,IYH */ - SET_LOW_REGISTER(BC, HIGH_REGISTER(IY)); - break; - - case 0x4d: /* LD C,IYL */ - SET_LOW_REGISTER(BC, LOW_REGISTER(IY)); - break; - - case 0x4e: /* LD C,(IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - SET_LOW_REGISTER(BC, GET_BYTE(adr)); - break; - - case 0x54: /* LD D,IYH */ - SET_HIGH_REGISTER(DE, HIGH_REGISTER(IY)); - break; - - case 0x55: /* LD D,IYL */ - SET_HIGH_REGISTER(DE, LOW_REGISTER(IY)); - break; - - case 0x56: /* LD D,(IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - SET_HIGH_REGISTER(DE, GET_BYTE(adr)); - break; - - case 0x5c: /* LD E,IYH */ - SET_LOW_REGISTER(DE, HIGH_REGISTER(IY)); - break; - - case 0x5d: /* LD E,IYL */ - SET_LOW_REGISTER(DE, LOW_REGISTER(IY)); - break; - - case 0x5e: /* LD E,(IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - SET_LOW_REGISTER(DE, GET_BYTE(adr)); - break; - - case 0x60: /* LD IYH,B */ - SET_HIGH_REGISTER(IY, HIGH_REGISTER(BC)); - break; - - case 0x61: /* LD IYH,C */ - SET_HIGH_REGISTER(IY, LOW_REGISTER(BC)); - break; - - case 0x62: /* LD IYH,D */ - SET_HIGH_REGISTER(IY, HIGH_REGISTER(DE)); - break; - - case 0x63: /* LD IYH,E */ - SET_HIGH_REGISTER(IY, LOW_REGISTER(DE)); - break; - - case 0x64: /* LD IYH,IYH */ - break; - - case 0x65: /* LD IYH,IYL */ - SET_HIGH_REGISTER(IY, LOW_REGISTER(IY)); - break; - - case 0x66: /* LD H,(IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - SET_HIGH_REGISTER(HL, GET_BYTE(adr)); - break; - - case 0x67: /* LD IYH,A */ - SET_HIGH_REGISTER(IY, HIGH_REGISTER(AF)); - break; - - case 0x68: /* LD IYL,B */ - SET_LOW_REGISTER(IY, HIGH_REGISTER(BC)); - break; - - case 0x69: /* LD IYL,C */ - SET_LOW_REGISTER(IY, LOW_REGISTER(BC)); - break; - - case 0x6a: /* LD IYL,D */ - SET_LOW_REGISTER(IY, HIGH_REGISTER(DE)); - break; - - case 0x6b: /* LD IYL,E */ - SET_LOW_REGISTER(IY, LOW_REGISTER(DE)); - break; - - case 0x6c: /* LD IYL,IYH */ - SET_LOW_REGISTER(IY, HIGH_REGISTER(IY)); - break; - - case 0x6d: /* LD IYL,IYL */ - break; - - case 0x6e: /* LD L,(IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - SET_LOW_REGISTER(HL, GET_BYTE(adr)); - break; - - case 0x6f: /* LD IYL,A */ - SET_LOW_REGISTER(IY, HIGH_REGISTER(AF)); - break; - - case 0x70: /* LD (IY+dd),B */ - adr = IY + (int8) RAM_PP(PC); - PUT_BYTE(adr, HIGH_REGISTER(BC)); - break; - - case 0x71: /* LD (IY+dd),C */ - adr = IY + (int8) RAM_PP(PC); - PUT_BYTE(adr, LOW_REGISTER(BC)); - break; - - case 0x72: /* LD (IY+dd),D */ - adr = IY + (int8) RAM_PP(PC); - PUT_BYTE(adr, HIGH_REGISTER(DE)); - break; - - case 0x73: /* LD (IY+dd),E */ - adr = IY + (int8) RAM_PP(PC); - PUT_BYTE(adr, LOW_REGISTER(DE)); - break; - - case 0x74: /* LD (IY+dd),H */ - adr = IY + (int8) RAM_PP(PC); - PUT_BYTE(adr, HIGH_REGISTER(HL)); - break; - - case 0x75: /* LD (IY+dd),L */ - adr = IY + (int8) RAM_PP(PC); - PUT_BYTE(adr, LOW_REGISTER(HL)); - break; - - case 0x77: /* LD (IY+dd),A */ - adr = IY + (int8) RAM_PP(PC); - PUT_BYTE(adr, HIGH_REGISTER(AF)); - break; - - case 0x7c: /* LD A,IYH */ - SET_HIGH_REGISTER(AF, HIGH_REGISTER(IY)); - break; - - case 0x7d: /* LD A,IYL */ - SET_HIGH_REGISTER(AF, LOW_REGISTER(IY)); - break; - - case 0x7e: /* LD A,(IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - SET_HIGH_REGISTER(AF, GET_BYTE(adr)); - break; - - case 0x84: /* ADD A,IYH */ - temp = HIGH_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x85: /* ADD A,IYL */ - temp = LOW_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x86: /* ADD A,(IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - temp = GET_BYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8c: /* ADC A,IYH */ - temp = HIGH_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8d: /* ADC A,IYL */ - temp = LOW_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x8e: /* ADC A,(IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - temp = GET_BYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - - case 0x96: /* SUB (IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - temp = GET_BYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x94: /* SUB IYH */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - - case 0x9c: /* SBC A,IYH */ - temp = HIGH_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x95: /* SUB IYL */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - - case 0x9d: /* SBC A,IYL */ - temp = LOW_REGISTER(IY); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0x9e: /* SBC A,(IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - temp = GET_BYTE(adr); - acu = HIGH_REGISTER(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xa4: /* AND IYH */ - AF = andTable[((AF & IY) >> 8) & 0xff]; - break; - - case 0xa5: /* AND IYL */ - AF = andTable[((AF >> 8) & IY) & 0xff]; - break; - - case 0xa6: /* AND (IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - AF = andTable[((AF >> 8) & GET_BYTE(adr)) & 0xff]; - break; - - case 0xac: /* XOR IYH */ - AF = xororTable[((AF ^ IY) >> 8) & 0xff]; - break; - - case 0xad: /* XOR IYL */ - AF = xororTable[((AF >> 8) ^ IY) & 0xff]; - break; - - case 0xae: /* XOR (IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - AF = xororTable[((AF >> 8) ^ GET_BYTE(adr)) & 0xff]; - break; - - case 0xb4: /* OR IYH */ - AF = xororTable[((AF | IY) >> 8) & 0xff]; - break; - - case 0xb5: /* OR IYL */ - AF = xororTable[((AF >> 8) | IY) & 0xff]; - break; - - case 0xb6: /* OR (IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - AF = xororTable[((AF >> 8) | GET_BYTE(adr)) & 0xff]; - break; - - case 0xbc: /* CP IYH */ - temp = HIGH_REGISTER(IY); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xbd: /* CP IYL */ - temp = LOW_REGISTER(IY); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xbe: /* CP (IY+dd) */ - adr = IY + (int8) RAM_PP(PC); - temp = GET_BYTE(adr); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - - case 0xcb: /* CB prefix */ - adr = IY + (int8) RAM_PP(PC); - switch ((op = GET_BYTE(PC)) & 7) { - - case 0: - ++PC; - acu = HIGH_REGISTER(BC); - break; - - case 1: - ++PC; - acu = LOW_REGISTER(BC); - break; - - case 2: - ++PC; - acu = HIGH_REGISTER(DE); - break; - - case 3: - ++PC; - acu = LOW_REGISTER(DE); - break; - - case 4: - ++PC; - acu = HIGH_REGISTER(HL); - break; - - case 5: - ++PC; - acu = LOW_REGISTER(HL); - break; - - case 6: - ++PC; - acu = GET_BYTE(adr); - break; - - case 7: - ++PC; - acu = HIGH_REGISTER(AF); - break; - } - switch (op & 0xc0) { - - case 0x00: /* shift/rotate */ - switch (op & 0x38) { - - case 0x00:/* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg3; - - case 0x08:/* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg3; - - case 0x10:/* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg3; - - case 0x18:/* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg3; - - case 0x20:/* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg3; - - case 0x28:/* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg3; - - case 0x30:/* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg3; - - case 0x38:/* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg3: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - } - break; - - case 0x40: /* BIT */ - if (acu & (1 << ((op >> 3) & 7))) - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - else - AF = (AF & ~0xfe) | 0x54; - if ((op & 7) != 6) - AF |= (acu & 0x28); - temp = acu; - break; - - case 0x80: /* RES */ - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - - case 0xc0: /* SET */ - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - switch (op & 7) { - - case 0: - SET_HIGH_REGISTER(BC, temp); - break; - - case 1: - SET_LOW_REGISTER(BC, temp); - break; - - case 2: - SET_HIGH_REGISTER(DE, temp); - break; - - case 3: - SET_LOW_REGISTER(DE, temp); - break; - - case 4: - SET_HIGH_REGISTER(HL, temp); - break; - - case 5: - SET_LOW_REGISTER(HL, temp); - break; - - case 6: - PUT_BYTE(adr, temp); - break; - - case 7: - SET_HIGH_REGISTER(AF, temp); - break; - } - break; - - case 0xe1: /* POP IY */ - POP(IY); - break; - - case 0xe3: /* EX (SP),IY */ - temp = IY; - POP(IY); - PUSH(temp); - break; - - case 0xe5: /* PUSH IY */ - PUSH(IY); - break; - - case 0xe9: /* JP (IY) */ - PC = IY; - break; - - case 0xf9: /* LD SP,IY */ - SP = IY; - break; - - default: /* ignore FD */ - CHECK_CPU_Z80; - PC--; - } - break; - - case 0xfe: /* CP nn */ - temp = RAM_PP(PC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = HIGH_REGISTER(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SET_PV) | cbits2Table[cbits & 0x1ff]; - break; - - case 0xff: /* RST 38H */ - PUSH(PC); - PC = 0x38; - } - } - end_decode: - - /* simulation halted */ - PC_S = (reason == STOP_OPCODE) ? PCX : PC; - AF_S = AF; - BC_S = BC; - DE_S = DE; - HL_S = HL; - IX_S = IX; - IY_S = IY; - SP_S = SP; - return reason; -} diff --git a/AltairZ80/altairz80_defs.h b/AltairZ80/altairz80_defs.h deleted file mode 100644 index 75341d49..00000000 --- a/AltairZ80/altairz80_defs.h +++ /dev/null @@ -1,102 +0,0 @@ -/* altairz80_defs.h: MITS Altair simulator definitions - - Copyright (c) 2002-2012, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 -*/ - -#include "sim_defs.h" /* simulator definitions */ - -#define MAXBANKSIZE 65536 /* maximum memory size, a power of 2 */ -#define MAXBANKSIZELOG2 16 /* log2 of MAXBANKSIZE */ -#define MAXBANKS 16 /* max number of memory banks, a power of 2 */ -#define MAXBANKSLOG2 4 /* log2 of MAXBANKS */ -#define MAXMEMORY (MAXBANKS * MAXBANKSIZE) /* maximum, total memory size */ -#define ADDRMASK (MAXBANKSIZE - 1) /* address mask */ -#define ADDRMASKEXTENDED (MAXMEMORY - 1) /* extended address mask */ -#define BANKMASK (MAXBANKS - 1) /* bank mask */ -#define MEMORYSIZE (cpu_unit.capac) /* actual memory size */ -#define KB 1024 /* kilo byte */ -#define KBLOG2 10 /* log2 of KB */ -#define ALTAIR_ROM_LOW 0xff00 /* start address of regular Altair ROM */ -#define RESOURCE_TYPE_MEMORY 1 -#define RESOURCE_TYPE_IO 2 - -#define NUM_OF_DSK 16 /* NUM_OF_DSK must be power of two */ -#define LDA_INSTRUCTION 0x3e /* op-code for LD A,<8-bit value> instruction */ -#define UNIT_NO_OFFSET_1 0x37 /* LD A, */ -#define UNIT_NO_OFFSET_2 0xb4 /* LD a,80h | */ - -#define CHIP_TYPE_8080 0 -#define CHIP_TYPE_Z80 1 -#define CHIP_TYPE_8086 2 -#define MAX_CHIP_TYPE CHIP_TYPE_8086 - -/* simulator stop codes */ -#define STOP_HALT 0 /* HALT */ -#define STOP_IBKPT 1 /* breakpoint (program counter) */ -#define STOP_MEM 2 /* breakpoint (memory access) */ -#define STOP_INSTR 3 /* breakpoint (instruction access) */ -#define STOP_OPCODE 4 /* invalid operation encountered (8080, Z80, 8086) */ - -#define UNIT_CPU_V_OPSTOP (UNIT_V_UF+0) /* stop on invalid operation */ -#define UNIT_CPU_OPSTOP (1 << UNIT_CPU_V_OPSTOP) -#define UNIT_CPU_V_BANKED (UNIT_V_UF+1) /* banked memory is used */ -#define UNIT_CPU_BANKED (1 << UNIT_CPU_V_BANKED) -#define UNIT_CPU_V_ALTAIRROM (UNIT_V_UF+2) /* ALTAIR ROM exists */ -#define UNIT_CPU_ALTAIRROM (1 << UNIT_CPU_V_ALTAIRROM) -#define UNIT_CPU_V_VERBOSE (UNIT_V_UF+3) /* warn if ROM is written to */ -#define UNIT_CPU_VERBOSE (1 << UNIT_CPU_V_VERBOSE) -#define UNIT_CPU_V_MMU (UNIT_V_UF+4) /* use MMU and slower CPU */ -#define UNIT_CPU_MMU (1 << UNIT_CPU_V_MMU) -#define UNIT_CPU_V_STOPONHALT (UNIT_V_UF+5) /* stop simulation on HALT */ -#define UNIT_CPU_STOPONHALT (1 << UNIT_CPU_V_STOPONHALT) -#define UNIT_CPU_V_SWITCHER (UNIT_V_UF+6) /* switcher 8086 <--> 8080/Z80 enabled */ -#define UNIT_CPU_SWITCHER (1 << UNIT_CPU_V_SWITCHER) - -#if defined (__linux) || defined(__NetBSD__) || defined (__OpenBSD__) || defined (__FreeBSD__) || defined (__APPLE__) -#define UNIX_PLATFORM 1 -#else -#define UNIX_PLATFORM 0 -#endif - -#define ADDRESS_FORMAT "[0x%05x]" - -/* use NLP for new line printing while the simulation is running */ -#if UNIX_PLATFORM -#define NLP "\r\n" -#else -#define NLP "\n" -#endif - -#if (defined (__MWERKS__) && defined (macintosh)) || defined(__DECC) -#define __FUNCTION__ __FILE__ -#endif - -typedef struct { - uint32 mem_base; /* Memory Base Address */ - uint32 mem_size; /* Memory Address space requirement */ - uint32 io_base; /* I/O Base Address */ - uint32 io_size; /* I/O Address Space requirement */ -} PNP_INFO; diff --git a/AltairZ80/altairz80_dsk.c b/AltairZ80/altairz80_dsk.c deleted file mode 100644 index 4dcca246..00000000 --- a/AltairZ80/altairz80_dsk.c +++ /dev/null @@ -1,595 +0,0 @@ -/* altairz80_dsk.c: MITS Altair 88-DISK Simulator - - Copyright (c) 2002-2012, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - - The 88_DISK is a 8-inch floppy controller which can control up - to 16 daisy-chained Pertec FD-400 hard-sectored floppy drives. - Each diskette has physically 77 tracks of 32 137-byte sectors - each. - - The controller is interfaced to the CPU by use of 3 I/O addresses, - standardly, these are device numbers 10, 11, and 12 (octal). - - Address Mode Function - ------- ---- -------- - - 10 Out Selects and enables Controller and Drive - 10 In Indicates status of Drive and Controller - 11 Out Controls Disk Function - 11 In Indicates current sector position of disk - 12 Out Write data - 12 In Read data - - Drive Select Out (Device 10 OUT): - - +---+---+---+---+---+---+---+---+ - | C | X | X | X | Device | - +---+---+---+---+---+---+---+---+ - - C = If this bit is 1, the disk controller selected by 'device' is - cleared. If the bit is zero, 'device' is selected as the - device being controlled by subsequent I/O operations. - X = not used - Device = value zero thru 15, selects drive to be controlled. - - Drive Status In (Device 10 IN): - - +---+---+---+---+---+---+---+---+ - | R | Z | I | X | X | H | M | W | - +---+---+---+---+---+---+---+---+ - - W - When 0, write circuit ready to write another byte. - M - When 0, head movement is allowed - H - When 0, indicates head is loaded for read/write - X - not used (will be 0) - I - When 0, indicates interrupts enabled (not used by this simulator) - Z - When 0, indicates head is on track 0 - R - When 0, indicates that read circuit has new byte to read - - Drive Control (Device 11 OUT): - - +---+---+---+---+---+---+---+---+ - | W | C | D | E | U | H | O | I | - +---+---+---+---+---+---+---+---+ - - I - When 1, steps head IN one track - O - When 1, steps head OUT one track - H - When 1, loads head to drive surface - U - When 1, unloads head - E - Enables interrupts (ignored by this simulator) - D - Disables interrupts (ignored by this simulator) - C - When 1 lowers head current (ignored by this simulator) - W - When 1, starts Write Enable sequence: W bit on device 10 - (see above) will go 1 and data will be read from port 12 - until 137 bytes have been read by the controller from - that port. The W bit will go off then, and the sector data - will be written to disk. Before you do this, you must have - stepped the track to the desired number, and waited until - the right sector number is presented on device 11 IN, then - set this bit. - - Sector Position (Device 11 IN): - - As the sectors pass by the read head, they are counted and the - number of the current one is available in this register. - - +---+---+---+---+---+---+---+---+ - | X | X | Sector Number | T | - +---+---+---+---+---+---+---+---+ - - X = Not used - Sector number = binary of the sector number currently under the - head, 0-31. - T = Sector True, is a 1 when the sector is positioned to read or - write. - -*/ - -#include "altairz80_defs.h" -#include - -/* Debug flags */ -#define IN_MSG (1 << 0) -#define OUT_MSG (1 << 1) -#define READ_MSG (1 << 2) -#define WRITE_MSG (1 << 3) -#define SECTOR_STUCK_MSG (1 << 4) -#define TRACK_STUCK_MSG (1 << 5) -#define VERBOSE_MSG (1 << 6) - -#define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK) -#define DSK_SECTSIZE 137 /* size of sector */ -#define DSK_SECT 32 /* sectors per track */ -#define MAX_TRACKS 254 /* number of tracks, - original Altair has 77 tracks only */ -#define DSK_TRACSIZE (DSK_SECTSIZE * DSK_SECT) -#define MAX_DSK_SIZE (DSK_TRACSIZE * MAX_TRACKS) -#define NUM_OF_DSK_MASK (NUM_OF_DSK - 1) -#define BOOTROM_SIZE_DSK 256 /* size of boot rom */ - - -int32 dsk10(const int32 port, const int32 io, const int32 data); -int32 dsk11(const int32 port, const int32 io, const int32 data); -int32 dsk12(const int32 port, const int32 io, const int32 data); -static t_stat dsk_boot(int32 unitno, DEVICE *dptr); -static t_stat dsk_reset(DEVICE *dptr); - -extern REG *sim_PC; -extern UNIT cpu_unit; -extern uint32 PCX; - -extern t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -void install_ALTAIRbootROM(void); - -/* global data on status */ - -/* currently selected drive (values are 0 .. NUM_OF_DSK) - current_disk < NUM_OF_DSK implies that the corresponding disk is attached to a file */ -static int32 current_disk = NUM_OF_DSK; -static int32 current_track [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static int32 current_sector [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static int32 current_byte [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static int32 current_flag [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static uint8 tracks [NUM_OF_DSK] = { MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, - MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, - MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, - MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS }; -static int32 in9_count = 0; -static int32 in9_message = FALSE; -static int32 dirty = FALSE; /* TRUE when buffer has unwritten data in it */ -static int32 warnLevelDSK = 3; -static int32 warnLock [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static int32 warnAttached [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static int32 warnDSK10 = 0; -static int32 warnDSK11 = 0; -static int32 warnDSK12 = 0; -static int8 dskbuf[DSK_SECTSIZE]; /* data Buffer */ - -/* Altair MITS modified BOOT EPROM, fits in upper 256 byte of memory */ -int32 bootrom_dsk[BOOTROM_SIZE_DSK] = { - 0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* ff00-ff07 */ - 0xc2, 0x05, 0xff, 0x3e, 0x16, 0xd3, 0xfe, 0x3e, /* ff08-ff0f */ - 0x12, 0xd3, 0xfe, 0xdb, 0xfe, 0xb7, 0xca, 0x20, /* ff10-ff17 */ - 0xff, 0x3e, 0x0c, 0xd3, 0xfe, 0xaf, 0xd3, 0xfe, /* ff18-ff1f */ - 0x21, 0x00, 0x5c, 0x11, 0x33, 0xff, 0x0e, 0x88, /* ff20-ff27 */ - 0x1a, 0x77, 0x13, 0x23, 0x0d, 0xc2, 0x28, 0xff, /* ff28-ff2f */ - 0xc3, 0x00, 0x5c, 0x31, 0x21, 0x5d, 0x3e, 0x00, /* ff30-ff37 */ - 0xd3, 0x08, 0x3e, 0x04, 0xd3, 0x09, 0xc3, 0x19, /* ff38-ff3f */ - 0x5c, 0xdb, 0x08, 0xe6, 0x02, 0xc2, 0x0e, 0x5c, /* ff40-ff47 */ - 0x3e, 0x02, 0xd3, 0x09, 0xdb, 0x08, 0xe6, 0x40, /* ff48-ff4f */ - 0xc2, 0x0e, 0x5c, 0x11, 0x00, 0x00, 0x06, 0x08, /* ff50-ff57 */ - 0xc5, 0xd5, 0x11, 0x86, 0x80, 0x21, 0x88, 0x5c, /* ff58-ff5f */ - 0xdb, 0x09, 0x1f, 0xda, 0x2d, 0x5c, 0xe6, 0x1f, /* ff60-ff67 */ - 0xb8, 0xc2, 0x2d, 0x5c, 0xdb, 0x08, 0xb7, 0xfa, /* ff68-ff6f */ - 0x39, 0x5c, 0xdb, 0x0a, 0x77, 0x23, 0x1d, 0xc2, /* ff70-ff77 */ - 0x39, 0x5c, 0xd1, 0x21, 0x8b, 0x5c, 0x06, 0x80, /* ff78-ff7f */ - 0x7e, 0x12, 0x23, 0x13, 0x05, 0xc2, 0x4d, 0x5c, /* ff80-ff87 */ - 0xc1, 0x21, 0x00, 0x5c, 0x7a, 0xbc, 0xc2, 0x60, /* ff88-ff8f */ - 0x5c, 0x7b, 0xbd, 0xd2, 0x80, 0x5c, 0x04, 0x04, /* ff90-ff97 */ - 0x78, 0xfe, 0x20, 0xda, 0x25, 0x5c, 0x06, 0x01, /* ff98-ff9f */ - 0xca, 0x25, 0x5c, 0xdb, 0x08, 0xe6, 0x02, 0xc2, /* ffa0-ffa7 */ - 0x70, 0x5c, 0x3e, 0x01, 0xd3, 0x09, 0x06, 0x00, /* ffa8-ffaf */ - 0xc3, 0x25, 0x5c, 0x3e, 0x80, 0xd3, 0x08, 0xfb, /* ffb0-ffb7 */ - 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffb8-ffbf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffc0-ffc7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffc8-ffcf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffd0-ffd7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffd8-ffdf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffe0-ffe7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffe8-ffef */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* fff0-fff7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* fff8-ffff */ -}; - -/* 88DSK Standard I/O Data Structures */ - -static UNIT dsk_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, -}; - -static REG dsk_reg[] = { - { DRDATA (DISK, current_disk, 4) }, - { BRDATA (CURTRACK, current_track, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (CURSECTOR, current_sector, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (CURBYTE, current_byte, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (CURFLAG, current_flag, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (TRACKS, tracks, 10, 8, NUM_OF_DSK), REG_CIRC }, - { DRDATA (IN9COUNT, in9_count, 4), REG_RO }, - { DRDATA (IN9MESSAGE, in9_message, 4), REG_RO }, - { DRDATA (DIRTY, dirty, 4), REG_RO }, - { DRDATA (DSKWL, warnLevelDSK, 32) }, - { BRDATA (WARNLOCK, warnLock, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (WARNATTACHED, warnAttached, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { DRDATA (WARNDSK10, warnDSK10, 4), REG_RO }, - { DRDATA (WARNDSK11, warnDSK11, 4), REG_RO }, - { DRDATA (WARNDSK12, warnDSK12, 4), REG_RO }, - { BRDATA (DISKBUFFER, dskbuf, 10, 8, DSK_SECTSIZE), REG_CIRC + REG_RO }, - { NULL } -}; - -static MTAB dsk_mod[] = { - { UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_DSK_WLK, UNIT_DSK_WLK, "WRTLCK", "WRTLCK", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB dsk_dt[] = { - { "IN", IN_MSG }, - { "OUT", OUT_MSG }, - { "READ", READ_MSG }, - { "WRITE", WRITE_MSG }, - { "SECTOR_STUCK", SECTOR_STUCK_MSG }, - { "TRACK_STUCK", TRACK_STUCK_MSG }, - { "VERBOSE", VERBOSE_MSG }, - { NULL, 0 } -}; - -DEVICE dsk_dev = { - "DSK", dsk_unit, dsk_reg, dsk_mod, - NUM_OF_DSK, 10, 31, 1, 8, 8, - NULL, NULL, &dsk_reset, - &dsk_boot, NULL, NULL, - NULL, (DEV_DISABLE | DEV_DEBUG), 0, - dsk_dt, NULL, "Altair Floppy Disk DSK" -}; - -static char* selectInOut(const int32 io) { - return io == 0 ? "IN" : "OUT"; -} - -/* service routines to handle simulator functions */ -/* reset routine */ - -static t_stat dsk_reset(DEVICE *dptr) { - int32 i; - for (i = 0; i < NUM_OF_DSK; i++) { - warnLock[i] = 0; - warnAttached[i] = 0; - current_track[i] = 0; - current_sector[i] = 0; - current_byte[i] = 0; - current_flag[i] = 0; - tracks[i] = MAX_TRACKS; - } - warnDSK10 = 0; - warnDSK11 = 0; - warnDSK12 = 0; - current_disk = NUM_OF_DSK; - in9_count = 0; - in9_message = FALSE; - sim_map_resource(0x08, 1, RESOURCE_TYPE_IO, &dsk10, dptr->flags & DEV_DIS); - sim_map_resource(0x09, 1, RESOURCE_TYPE_IO, &dsk11, dptr->flags & DEV_DIS); - sim_map_resource(0x0A, 1, RESOURCE_TYPE_IO, &dsk12, dptr->flags & DEV_DIS); - return SCPE_OK; -} - -void install_ALTAIRbootROM(void) { - assert(install_bootrom(bootrom_dsk, BOOTROM_SIZE_DSK, ALTAIR_ROM_LOW, TRUE) == SCPE_OK); -} - -/* The boot routine modifies the boot ROM in such a way that subsequently - the specified disk is used for boot purposes. -*/ -static t_stat dsk_boot(int32 unitno, DEVICE *dptr) { - if (cpu_unit.flags & (UNIT_CPU_ALTAIRROM | UNIT_CPU_BANKED)) { - /* check whether we are really modifying an LD A,<> instruction */ - if ((bootrom_dsk[UNIT_NO_OFFSET_1 - 1] == LDA_INSTRUCTION) && (bootrom_dsk[UNIT_NO_OFFSET_2 - 1] == LDA_INSTRUCTION)) { - bootrom_dsk[UNIT_NO_OFFSET_1] = unitno & 0xff; /* LD A, */ - bootrom_dsk[UNIT_NO_OFFSET_2] = 0x80 | (unitno & 0xff); /* LD a,80h | */ - } - else { /* Attempt to modify non LD A,<> instructions is refused. */ - printf("Incorrect boot ROM offsets detected.\n"); - return SCPE_IERR; - } - install_ALTAIRbootROM(); /* install modified ROM */ - } - *((int32 *) sim_PC->loc) = ALTAIR_ROM_LOW; - return SCPE_OK; -} - -static int32 dskseek(const UNIT *xptr) { - return sim_fseek(xptr->fileref, DSK_TRACSIZE * current_track[current_disk] + - DSK_SECTSIZE * current_sector[current_disk], SEEK_SET); -} - -/* precondition: current_disk < NUM_OF_DSK */ -static void writebuf(void) { - int32 i, rtn; - UNIT *uptr; - i = current_byte[current_disk]; /* null-fill rest of sector if any */ - while (i < DSK_SECTSIZE) - dskbuf[i++] = 0; - uptr = dsk_dev.units + current_disk; - if (((uptr->flags) & UNIT_DSK_WLK) == 0) { /* write enabled */ - sim_debug(WRITE_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT " OUT 0x0a (WRITE) D%d T%d S%d\n", - current_disk, PCX, current_disk, - current_track[current_disk], current_sector[current_disk]); - if (dskseek(uptr)) { - sim_debug(VERBOSE_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT " fseek failed D%d T%d S%d\n", - current_disk, PCX, current_disk, - current_track[current_disk], current_sector[current_disk]); - } - rtn = sim_fwrite(dskbuf, 1, DSK_SECTSIZE, uptr->fileref); - if (rtn != DSK_SECTSIZE) { - sim_debug(VERBOSE_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT " sim_fwrite failed T%d S%d Return=%d\n", - current_disk, PCX, current_track[current_disk], - current_sector[current_disk], rtn); - } - } - else if ( (dsk_dev.dctrl & VERBOSE_MSG) && (warnLock[current_disk] < warnLevelDSK) ) { - /* write locked - print warning message if required */ - warnLock[current_disk]++; - sim_debug(VERBOSE_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT " Attempt to write to locked DSK%d - ignored.\n", - current_disk, PCX, current_disk); - } - current_flag[current_disk] &= 0xfe; /* ENWD off */ - current_byte[current_disk] = 0xff; - dirty = FALSE; -} - -/* 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. -*/ - -/* Disk Controller Status/Select */ - -/* IMPORTANT: The status flags read by port 8 IN instruction are - INVERTED, that is, 0 is true and 1 is false. To handle this, the - simulator keeps it's own status flags as 0=false, 1=true; and - returns the COMPLEMENT of the status flags when read. This makes - setting/testing of the flag bits more logical, yet meets the - simulation requirement that they are reversed in hardware. -*/ - -int32 dsk10(const int32 port, const int32 io, const int32 data) { - int32 current_disk_flags; - in9_count = 0; - if (io == 0) { /* IN: return flags */ - if (current_disk >= NUM_OF_DSK) { - if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK10 < warnLevelDSK)) { - warnDSK10++; - sim_debug(VERBOSE_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT - " Attempt of IN 0x08 on unattached disk - ignored.\n", - current_disk, PCX); - } - return 0xff; /* no drive selected - can do nothing */ - } - return (~current_flag[current_disk]) & 0xff; /* return the COMPLEMENT! */ - } - - /* OUT: Controller set/reset/enable/disable */ - if (dirty) /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - sim_debug(OUT_MSG, &dsk_dev, "DSK%i: " ADDRESS_FORMAT " OUT 0x08: %x\n", current_disk, PCX, data); - current_disk = data & NUM_OF_DSK_MASK; /* 0 <= current_disk < NUM_OF_DSK */ - current_disk_flags = (dsk_dev.units + current_disk)->flags; - if ((current_disk_flags & UNIT_ATT) == 0) { /* nothing attached? */ - if ( (dsk_dev.dctrl & VERBOSE_MSG) && (warnAttached[current_disk] < warnLevelDSK) ) { - warnAttached[current_disk]++; - sim_debug(VERBOSE_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT - " Attempt to select unattached DSK%d - ignored.\n", - current_disk, PCX, current_disk); - } - current_disk = NUM_OF_DSK; - } - else { - current_sector[current_disk] = 0xff; /* reset internal counters */ - current_byte[current_disk] = 0xff; - current_flag[current_disk] = data & 0x80 ? 0 /* disable drive */ : - (current_track[current_disk] == 0 ? 0x5a /* enable: head move true, track 0 if there */ : - 0x1a); /* enable: head move true */ - } - return 0; /* ignored since OUT */ -} - -/* Disk Drive Status/Functions */ - -int32 dsk11(const int32 port, const int32 io, const int32 data) { - if (current_disk >= NUM_OF_DSK) { - if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK11 < warnLevelDSK)) { - warnDSK11++; - sim_debug(VERBOSE_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT - " Attempt of %s 0x09 on unattached disk - ignored.\n", - current_disk, PCX, selectInOut(io)); - } - return 0; /* no drive selected - can do nothing */ - } - - /* now current_disk < NUM_OF_DSK */ - if (io == 0) { /* read sector position */ - in9_count++; - if ((dsk_dev.dctrl & SECTOR_STUCK_MSG) && (in9_count > 2 * DSK_SECT) && (!in9_message)) { - in9_message = TRUE; - sim_debug(SECTOR_STUCK_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT " Looping on sector find.\n", - current_disk, PCX); - } - sim_debug(IN_MSG, &dsk_dev, "DSK%i: " ADDRESS_FORMAT " IN 0x09\n", current_disk, PCX); - if (dirty) /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - if (current_flag[current_disk] & 0x04) { /* head loaded? */ - current_sector[current_disk]++; - if (current_sector[current_disk] >= DSK_SECT) - current_sector[current_disk] = 0; - current_byte[current_disk] = 0xff; - return (((current_sector[current_disk] << 1) & 0x3e) /* return 'sector true' bit = 0 (true) */ - | 0xc0); /* set on 'unused' bits */ - } else - return 0; /* head not loaded - return 0 */ - } - - in9_count = 0; - /* drive functions */ - - sim_debug(OUT_MSG, &dsk_dev, "DSK%i: " ADDRESS_FORMAT " OUT 0x09: %x\n", current_disk, PCX, data); - if (data & 0x01) { /* step head in */ - if (current_track[current_disk] == (tracks[current_disk] - 1)) - sim_debug(TRACK_STUCK_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT " Unnecessary step in.\n", - current_disk, PCX); - current_track[current_disk]++; - current_flag[current_disk] &= 0xbf; /* mwd 1/29/13: track zero now false */ - if (current_track[current_disk] > (tracks[current_disk] - 1)) - current_track[current_disk] = (tracks[current_disk] - 1); - if (dirty) /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - current_sector[current_disk] = 0xff; - current_byte[current_disk] = 0xff; - } - - if (data & 0x02) { /* step head out */ - if (current_track[current_disk] == 0) - sim_debug(TRACK_STUCK_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT " Unnecessary step out.\n", - current_disk, PCX); - current_track[current_disk]--; - if (current_track[current_disk] < 0) { - current_track[current_disk] = 0; - current_flag[current_disk] |= 0x40; /* track 0 if there */ - } - if (dirty) /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - current_sector[current_disk] = 0xff; - current_byte[current_disk] = 0xff; - } - - if (dirty) /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - - if (data & 0x04) { /* head load */ - current_flag[current_disk] |= 0x04; /* turn on head loaded bit */ - current_flag[current_disk] |= 0x80; /* turn on 'read data available' */ - } - - if (data & 0x08) { /* head unload */ - current_flag[current_disk] &= 0xfb; /* turn off 'head loaded' bit */ - current_flag[current_disk] &= 0x7f; /* turn off 'read data available' */ - current_sector[current_disk] = 0xff; - current_byte[current_disk] = 0xff; - } - - /* interrupts & head current are ignored */ - - if (data & 0x80) { /* write sequence start */ - current_byte[current_disk] = 0; - current_flag[current_disk] |= 0x01; /* enter new write data on */ - } - return 0; /* ignored since OUT */ -} - -/* Disk Data In/Out */ - -int32 dsk12(const int32 port, const int32 io, const int32 data) { - int32 i, rtn; - UNIT *uptr; - - if (current_disk >= NUM_OF_DSK) { - if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK12 < warnLevelDSK)) { - warnDSK12++; - sim_debug(VERBOSE_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT - " Attempt of %s 0x0a on unattached disk - ignored.\n", - current_disk, PCX, selectInOut(io)); - } - return 0; - } - - /* now current_disk < NUM_OF_DSK */ - in9_count = 0; - uptr = dsk_dev.units + current_disk; - if (io == 0) { - if (current_byte[current_disk] >= DSK_SECTSIZE) { - /* physically read the sector */ - sim_debug(READ_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT " IN 0x0a (READ) D%d T%d S%d\n", - current_disk, PCX, current_disk, - current_track[current_disk], current_sector[current_disk]); - for (i = 0; i < DSK_SECTSIZE; i++) - dskbuf[i] = 0; - if (dskseek(uptr)) { - if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK12 < warnLevelDSK)) { - warnDSK12++; - sim_debug(VERBOSE_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT " fseek error D%d T%d S%d\n", - current_disk, PCX, current_disk, - current_track[current_disk], current_sector[current_disk]); - } - } - rtn = sim_fread(dskbuf, 1, DSK_SECTSIZE, uptr->fileref); - if (rtn != DSK_SECTSIZE) { - if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK12 < warnLevelDSK)) { - warnDSK12++; - sim_debug(VERBOSE_MSG, &dsk_dev, - "DSK%i: " ADDRESS_FORMAT " sim_fread error D%d T%d S%d\n", - current_disk, PCX, current_disk, - current_track[current_disk], current_sector[current_disk]); - } - } - current_byte[current_disk] = 0; - } - return dskbuf[current_byte[current_disk]++] & 0xff; - } - else { - if (current_byte[current_disk] >= DSK_SECTSIZE) - writebuf(); /* from above we have that current_disk < NUM_OF_DSK */ - else { - dirty = TRUE; /* this guarantees for the next call to writebuf that current_disk < NUM_OF_DSK */ - dskbuf[current_byte[current_disk]++] = data & 0xff; - } - return 0; /* ignored since OUT */ - } -} diff --git a/AltairZ80/altairz80_hdsk.c b/AltairZ80/altairz80_hdsk.c deleted file mode 100644 index fb277571..00000000 --- a/AltairZ80/altairz80_hdsk.c +++ /dev/null @@ -1,957 +0,0 @@ -/* altairz80_hdsk.c: simulated hard disk device to increase capacity - - Copyright (c) 2002-2012, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Contains code from Howard M. Harte for defining and changing disk geometry. -*/ - -#include "altairz80_defs.h" -#include -#include "sim_imd.h" - -/* Debug flags */ -#define READ_MSG (1 << 0) -#define WRITE_MSG (1 << 1) -#define VERBOSE_MSG (1 << 2) - -/* The following routines are based on work from Howard M. Harte */ -static t_stat set_geom(UNIT *uptr, int32 val, char *cptr, void *desc); -static t_stat show_geom(FILE *st, UNIT *uptr, int32 val, void *desc); -static t_stat set_format(UNIT *uptr, int32 val, char *cptr, void *desc); -static t_stat show_format(FILE *st, UNIT *uptr, int32 val, void *desc); - -static t_stat hdsk_reset(DEVICE *dptr); -static t_stat hdsk_attach(UNIT *uptr, char *cptr); -static t_stat hdsk_detach(UNIT *uptr); -static uint32 is_imd(const UNIT *uptr); -static void assignFormat(UNIT *uptr); -static void verifyDiskInfo(const DISK_INFO info, const char unitChar); - -#define UNIT_V_HDSK_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_HDSK_WLK (1 << UNIT_V_HDSK_WLK) -#define HDSK_MAX_SECTOR_SIZE 1024 /* maximum size of a sector */ -#define HDSK_SECTOR_SIZE u5 /* size of sector */ -#define HDSK_SECTORS_PER_TRACK u4 /* sectors per track */ -#define HDSK_NUMBER_OF_TRACKS u3 /* number of tracks */ -#define HDSK_FORMAT_TYPE u6 /* Disk Format Type */ -#define HDSK_CAPACITY (2048*32*128) /* Default Altair HDSK Capacity */ -#define HDSK_NUMBER 8 /* number of hard disks */ -#define CPM_OK 0 /* indicates to CP/M everything ok */ -#define CPM_ERROR 1 /* indicates to CP/M an error condition */ -#define CPM_EMPTY 0xe5 /* default value for non-existing bytes */ -#define HDSK_NONE 0 -#define HDSK_RESET 1 -#define HDSK_READ 2 -#define HDSK_WRITE 3 -#define HDSK_PARAM 4 -#define HDSK_BOOT_ADDRESS 0x5c00 -#define DPB_NAME_LENGTH 15 -#define BOOTROM_SIZE_HDSK 256 - -extern uint32 PCX; -extern REG *sim_PC; -extern UNIT cpu_unit; -extern FILE *sim_deb; - -extern void install_ALTAIRbootROM(void); -extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); -extern uint8 GetBYTEWrapper(const uint32 Addr); -extern t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM); -extern int32 bootrom_dsk[]; -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern int32 find_unit_index(UNIT *uptr); - -static t_stat hdsk_boot(int32 unitno, DEVICE *dptr); -int32 hdsk_io(const int32 port, const int32 io, const int32 data); - -static int32 hdskLastCommand = HDSK_NONE; -static int32 hdskCommandPosition = 0; -static int32 parameterCount = 0; -static int32 selectedDisk; -static int32 selectedSector; -static int32 selectedTrack; -static int32 selectedDMA; - -typedef struct { - char name[DPB_NAME_LENGTH + 1]; /* name of CP/M disk parameter block */ - t_addr capac; /* capacity */ - uint16 spt; /* sectors per track */ - uint8 bsh; /* data allocation block shift factor */ - uint8 blm; /* data allocation block mask */ - uint8 exm; /* extent mask */ - uint16 dsm; /* maximum data block number */ - uint16 drm; /* total number of directory entries */ - uint8 al0; /* determine reserved directory blocks */ - uint8 al1; /* determine reserved directory blocks */ - uint16 cks; /* size of directory check vector */ - uint16 off; /* number of reserved tracks */ - uint8 psh; /* physical record shift factor, CP/M 3 */ - uint8 phm; /* physical record mask, CP/M 3 */ - int32 physicalSectorSize; /* 0 for 128 << psh, > 0 for special */ - int32 offset; /* offset in physical sector where logical sector starts */ - int32 *skew; /* pointer to skew table or NULL */ -} DPB; - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ -} HDSK_INFO; - -#define SPT16 16 -#define SPT32 32 -#define SPT26 26 -#define SPT52 52 - -static HDSK_INFO hdsk_info_data = { { 0x0000, 0, 0xFD, 1 } }; - -static int32 standard8[SPT26] = { 0, 6, 12, 18, 24, 4, 10, 16, - 22, 2, 8, 14, 20, 1, 7, 13, - 19, 25, 5, 11, 17, 23, 3, 9, - 15, 21 }; - -static int32 apple_ii_DOS[SPT16] = { 0, 6, 12, 3, 9, 15, 14, 5, - 11, 2, 8, 7, 13, 4, 10, 1 }; - -static int32 apple_ii_DOS2[SPT32] = { 0, 1, 12, 13, 24, 25, 6, 7, - 18, 19, 30, 31, 28, 29, 10, 11, - 22, 23, 4, 5, 16, 17, 14, 15, - 26, 27, 8, 9, 20, 21, 2, 3 }; - -static int32 apple_ii_PRODOS[SPT16] = { 0, 9, 3, 12, 6, 15, 1, 10, - 4, 13, 7, 8, 2, 11, 5, 14 }; - -static int32 apple_ii_PRODOS2[SPT32] = { 0, 1, 18, 19, 6, 7, 24, 25, - 12, 13, 30, 31, 2, 3, 20, 21, - 8, 9, 26, 27, 14, 15, 16, 17, - 4, 5, 22, 23, 10, 11, 28, 29 }; - -static int32 mits[SPT32] = { 0, 17, 2, 19, 4, 21, 6, 23, - 8, 25, 10, 27, 12, 29, 14, 31, - 16, 1, 18, 3, 20, 5, 22, 7, - 24, 9, 26, 11, 28, 13, 30, 15 }; - -/* Note in the following CKS = 0 for fixed media which are not supposed to be - changed while CP/M is executing. Also note that spt (sectors per track) is - measured in CP/M sectors of size 128 bytes. Standard format "HDSK" must be - first as index 0 is used as default in some cases. - */ -static DPB dpb[] = { -/* name capac spt bsh blm exm dsm drm - al0 al1 cks off psh phm ss off skew */ - { "HDSK", HDSK_CAPACITY, 32, 0x05, 0x1F, 0x01, 0x07f9, 0x03FF, - 0xFF, 0x00, 0x0000, 0x0006, 0x00, 0x00, 0, 0, NULL }, /* AZ80 HDSK */ - - { "EZ80FL", 131072, 32, 0x03, 0x07, 0x00, 127, 0x003E, - 0xC0, 0x00, 0x0000, 0x0000, 0x02, 0x03, 0, 0, NULL }, /* 128K FLASH */ - - { "P112", 1474560, 72, 0x04, 0x0F, 0x00, 710, 0x00FE, - 0xF0, 0x00, 0x0000, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* 1.44M P112 */ - - { "SU720", 737280, 36, 0x04, 0x0F, 0x00, 354, 0x007E, - 0xC0, 0x00, 0x0020, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* 720K Super I/O */ - - { "OSB1", 102400, 20, 0x04, 0x0F, 0x01, 45, 0x003F, - 0x80, 0x00, 0x0000, 0x0003, 0x02, 0x03, 0, 0, NULL }, /* Osborne1 5.25" SS SD */ - - { "OSB2", 204800, 40, 0x03, 0x07, 0x00, 184, 0x003F, - 0xC0, 0x00, 0x0000, 0x0003, 0x02, 0x03, 0, 0, NULL }, /* Osborne1 5.25" SS DD */ - - { "NSSS1", 179200, 40, 0x03, 0x07, 0x00, 0xA4, 0x003F, - 0xC0, 0x00, 0x0010, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Northstar SSDD Format 1 */ - - { "NSSS2", 179200, 40, 0x04, 0x0F, 0x01, 0x51, 0x003F, - 0x80, 0x00, 0x0010, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Northstar SSDD Format 2 */ - - { "NSDS2", 358400, 40, 0x04, 0x0F, 0x01, 0xA9, 0x003F, - 0x80, 0x00, 0x0010, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Northstar DSDD Format 2 */ - - { "VGSS", 315392, 32, 0x04, 0x0F, 0x00, 149, 0x007F, - 0xC0, 0x00, 0x0020, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Vector SS SD */ - - { "VGDS", 630784, 32, 0x04, 0x0F, 0x00, 299, 0x007F, - 0xC0, 0x00, 0x0020, 0x0004, 0x02, 0x03, 0, 0, NULL }, /* Vector DS SD */ - - { "DISK1A", 630784, 64, 0x04, 0x0F, 0x00, 299, 0x007F, - 0xC0, 0x00, 0x0020, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* CompuPro Disk1A 8" SS SD */ - - { "SSSD8", 256256, SPT26, 0x03, 0x07, 0x00, 242, 0x003F, - 0xC0, 0x00, 0x0000, 0x0002, 0x00, 0x00, 0, 0, NULL }, /* Standard 8" SS SD */ - - { "SSSD8S", 256256, SPT26, 0x03, 0x07, 0x00, 242, 0x003F, - 0xC0, 0x00, 0x0000, 0x0002, 0x00, 0x00, 0, 0, standard8 }, /* Standard 8" SS SD with skew */ - - { "SSDD8", 512512, SPT52, 0x04, 0x0F, 0x01, 242, 0x007F, - 0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, NULL }, /* Standard 8" SS DD */ - - { "SSDD8S", 512512, SPT52, 0x04, 0x0F, 0x01, 242, 0x007F, - 0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, standard8 }, /* Standard 8" SS DD with skew */ - - { "DSDD8", 1025024, SPT52, 0x04, 0x0F, 0x00, 493, 0x007F, - 0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, NULL }, /* Standard 8" DS DD */ - - { "DSDD8S", 1025024, SPT52, 0x04, 0x0F, 0x00, 493, 0x007F, - 0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, NULL }, /* Standard 8" DS DD with skew */ - - {"512SSDD8",591360, 60, 0x04, 0x0F, 0x00, 280, 0x007F, - 0xC0, 0x00, 0x0000, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Standard 8" SS DD with 512 byte sectors */ - - {"512DSDD8",1182720, 60, 0x04, 0x0F, 0x00, 569, 0x007F, - 0xC0, 0x00, 0x0000, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Standard 8" DS DD with 512 byte sectors */ - -#if 0 - /* CP/M 3 BIOS currently does not support physical sector size 1024 */ - {"1024SSDD8",630784, 64, 0x04, 0x0F, 0x00, 299, 0x007F, - 0xC0, 0x00, 0x0000, 0x0002, 0x03, 0x07, 0, 0, NULL }, /* Standard 8" SS DD with 1024 byte sectors */ - - {"1024DSDD8",1261568, 64, 0x04, 0x0F, 0x00, 607, 0x007F, - 0xC0, 0x00, 0x0000, 0x0002, 0x03, 0x07, 0, 0, NULL }, /* Standard 8" DS DD with 1024 byte sectors */ -#endif - - { "APPLE-DO",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F, - 0xC0, 0x00, 0x0000, 0x0003, 0x01, 0x01, 0, 0, apple_ii_DOS }, /* Apple II DOS 3.3 */ - - { "APPLE-PO",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F, - 0xC0, 0x00, 0x0000, 0x0003, 0x01, 0x01, 0, 0, apple_ii_PRODOS }, /* Apple II PRODOS */ - - { "APPLE-D2",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F, - 0xC0, 0x00, 0x0000, 0x0003, 0x00, 0x00, 0, 0, apple_ii_DOS2 }, /* Apple II DOS 3.3, deblocked */ - - { "APPLE-P2",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F, - 0xC0, 0x00, 0x0000, 0x0003, 0x00, 0x00, 0, 0, apple_ii_PRODOS2 }, /* Apple II PRODOS, deblocked */ - - { "MITS", 337568, SPT32, 0x03, 0x07, 0x00, 254, 0x00FF, - 0xFF, 0x00, 0x0000, 0x0006, 0x00, 0x00, 137, 3, mits }, /* MITS Altair original */ - - { "MITS2", 1113536, SPT32, 0x04, 0x0F, 0x00, 0x1EF, 0x00FF, - 0xF0, 0x00, 0x0000, 0x0006, 0x00, 0x00, 137, 3, mits }, /* MITS Altair original, extra */ - - /* - dw 40 ;#128 byte records/track - db 4,0fh ;block shift mask (2K) - db 1 ;extent mask - dw 194 ;maximun block number - dw 127 ;max number of dir entry - 1 - db 0C0H,00h ;alloc vector for directory - dw 0020h ;checksum size - dw 2 ;offset for sys tracks - db 2,3 ;physical sector shift (512 sector) - */ - { "V1050", 409600, 40, 0x04, 0x0F, 0x01, 194, 0x007F, - 0xC0, 0x00, 0x0000, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Visual Technology Visual 1050, http://www.metabarn.com/v1050/index.html */ - - { "", 0 } -}; - -static UNIT hdsk_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) } -}; -static DISK_INFO* hdsk_imd[HDSK_NUMBER]; - -static REG hdsk_reg[] = { - { DRDATA (HDCMD, hdskLastCommand, 32), REG_RO }, - { DRDATA (HDPOS, hdskCommandPosition, 32), REG_RO }, - { DRDATA (HDDSK, selectedDisk, 32), REG_RO }, - { DRDATA (HDSEC, selectedSector, 32), REG_RO }, - { DRDATA (HDTRK, selectedTrack, 32), REG_RO }, - { DRDATA (HDDMA, selectedDMA, 32), REG_RO }, - { NULL } -}; - -static MTAB hdsk_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", &set_format, &show_format, NULL }, - { UNIT_HDSK_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_HDSK_WLK, UNIT_HDSK_WLK, "WRTLCK", "WRTLCK", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "GEOM", "GEOM", &set_geom, &show_geom, NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB hdsk_dt[] = { - { "READ", READ_MSG }, - { "WRITE", WRITE_MSG }, - { "VERBOSE", VERBOSE_MSG }, - { NULL, 0 } -}; - -DEVICE hdsk_dev = { - "HDSK", hdsk_unit, hdsk_reg, hdsk_mod, - 8, 10, 31, 1, 8, 8, - NULL, NULL, &hdsk_reset, - &hdsk_boot, &hdsk_attach, &hdsk_detach, - &hdsk_info_data, (DEV_DISABLE | DEV_DEBUG), 0, - hdsk_dt, NULL, "Hard Disk HDSK" -}; - -/* Reset routine */ -static t_stat hdsk_reset(DEVICE *dptr) { - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - if (dptr->flags & DEV_DIS) - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &hdsk_io, TRUE); - else { - /* Connect HDSK at base address */ - if (sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &hdsk_io, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->mem_base); - dptr->flags |= DEV_DIS; - return SCPE_ARG; - } - } - return SCPE_OK; -} - -#ifdef _WIN32 -#define strcasecmp _stricmp -#endif -static uint32 is_imd(const UNIT *uptr) { - return ((uptr != NULL) && (uptr->filename != NULL) && (strlen(uptr->filename) > 3) && - (strcasecmp(".IMD", uptr->filename + strlen(uptr->filename) - 4) == 0)); -} - -static void assignFormat(UNIT *uptr) { - uint32 i; - uptr->HDSK_FORMAT_TYPE = -1; /* default to unknown format type */ - for (i = 0; dpb[i].capac != 0; i++) { /* find disk parameter block */ - if (dpb[i].capac == uptr->capac) { /* found if correct capacity */ - uptr->HDSK_FORMAT_TYPE = i; - break; - } - } -} - -static void verifyDiskInfo(const DISK_INFO info, const char unitChar) { - uint32 track, head; - if (info.ntracks < 1) - printf("HDSK%c (IMD): WARNING: Number of tracks is 0.\n", unitChar); - if (info.nsides < 1) { - printf("HDSK%c (IMD): WARNING: Number of sides is 0.\n", unitChar); - return; - } - for (track = 0; track < info.ntracks / info.nsides; track++) - for (head = 0; head < info.nsides; head++) { - if (info.track[track][head].nsects != info.track[1][0].nsects) - printf("HDSK%c (IMD): WARNING: For track %i and head %i expected number of sectors " - "%i but got %i.\n", unitChar, track, head, - info.track[1][0].nsects, info.track[track][head].nsects); - if (info.track[track][head].sectsize != info.track[1][0].sectsize) - printf("HDSK%c (IMD): WARNING: For track %i and head %i expected sector size " - "%i but got %i.\n", unitChar, track, head, - info.track[1][0].sectsize, info.track[track][head].sectsize); - if (info.track[track][head].start_sector != info.track[1][0].start_sector) - printf("HDSK%c (IMD): WARNING: For track %i and head %i expected start sector " - "%i but got %i.\n", unitChar, track, head, - info.track[1][0].start_sector, info.track[track][head].start_sector); - } -} - -/* Attach routine */ -static t_stat hdsk_attach(UNIT *uptr, char *cptr) { - int32 thisUnitIndex; - char unitChar; - const t_stat r = attach_unit(uptr, cptr); /* attach unit */ - if (r != SCPE_OK) /* error? */ - return r; - - assert(uptr != NULL); - thisUnitIndex = find_unit_index(uptr); - unitChar = '0' + thisUnitIndex; - assert((0 <= thisUnitIndex) && (thisUnitIndex < HDSK_NUMBER)); - - if (is_imd(uptr)) { - if ((sim_fsize(uptr->fileref) == 0) && - (diskCreate(uptr->fileref, "$Id: SIMH hdsk.c $") != SCPE_OK)) { - printf("HDSK%c (IMD): Failed to create IMD disk.\n", unitChar); - detach_unit(uptr); - return SCPE_OPENERR; - } - hdsk_imd[thisUnitIndex] = diskOpen(uptr->fileref, sim_deb && (hdsk_dev.dctrl & VERBOSE_MSG)); - if (hdsk_imd[thisUnitIndex] == NULL) - return SCPE_IOERR; - verifyDiskInfo(*hdsk_imd[thisUnitIndex], '0' + thisUnitIndex); - uptr->HDSK_NUMBER_OF_TRACKS = hdsk_imd[thisUnitIndex]->ntracks; - uptr->HDSK_SECTORS_PER_TRACK = hdsk_imd[thisUnitIndex]->track[1][0].nsects; - uptr->HDSK_SECTOR_SIZE = hdsk_imd[thisUnitIndex]->track[1][0].sectsize; - uptr->capac = ((uptr->HDSK_NUMBER_OF_TRACKS) * - (uptr->HDSK_SECTORS_PER_TRACK) * - (uptr->HDSK_SECTOR_SIZE)); - assignFormat(uptr); - if (uptr->HDSK_FORMAT_TYPE == -1) { /* Case 1: no disk parameter block found*/ - uptr->HDSK_FORMAT_TYPE = 0; - printf("HDSK%c (IMD): WARNING: Unsupported disk capacity, assuming HDSK type " - "with capacity %iKB.\n", unitChar, uptr->capac / 1000); - uptr->flags |= UNIT_HDSK_WLK; - printf("HDSK%c (IMD): WARNING: Forcing WRTLCK.\n", unitChar); - } - return SCPE_OK; - } - - /* Step 1: Determine capacity of this disk */ - uptr->capac = sim_fsize(uptr->fileref); /* the file length is a good indication */ - if (uptr->capac == 0) { /* file does not exist or has length 0 */ - uptr->capac = (uptr->HDSK_NUMBER_OF_TRACKS * - uptr->HDSK_SECTORS_PER_TRACK * uptr->HDSK_SECTOR_SIZE); - if (uptr->capac == 0) - uptr->capac = HDSK_CAPACITY; - } /* post condition: uptr->capac > 0 */ - assert(uptr->capac); - - /* Step 2: Determine format based on disk capacity */ - assignFormat(uptr); - - /* Step 3: Set number of sectors per track and sector size */ - if (uptr->HDSK_FORMAT_TYPE == -1) { /* Case 1: no disk parameter block found*/ - uptr->HDSK_FORMAT_TYPE = 0; - printf("HDSK%c: WARNING: Unsupported disk capacity, assuming HDSK type with capacity %iKB.\n", - unitChar, uptr->capac / 1000); - uptr->flags |= UNIT_HDSK_WLK; - printf("HDSK%c: WARNING: Forcing WRTLCK.\n", unitChar); - /* check whether capacity corresponds to setting of tracks, sectors per track and sector size */ - if (uptr->capac != (uint32)(uptr->HDSK_NUMBER_OF_TRACKS * - uptr->HDSK_SECTORS_PER_TRACK * uptr->HDSK_SECTOR_SIZE)) { - printf("HDSK%c: WARNING: Fixing geometry.\n", unitChar); - if (uptr->HDSK_SECTORS_PER_TRACK == 0) - uptr->HDSK_SECTORS_PER_TRACK = 32; - if (uptr->HDSK_SECTOR_SIZE == 0) - uptr->HDSK_SECTOR_SIZE = 128; - } - } - else { /* Case 2: disk parameter block found */ - uptr->HDSK_SECTORS_PER_TRACK = dpb[uptr->HDSK_FORMAT_TYPE].spt >> dpb[uptr->HDSK_FORMAT_TYPE].psh; - uptr->HDSK_SECTOR_SIZE = (128 << dpb[uptr->HDSK_FORMAT_TYPE].psh); - } - assert((uptr->HDSK_SECTORS_PER_TRACK) && (uptr->HDSK_SECTOR_SIZE) && (uptr->HDSK_FORMAT_TYPE >= 0)); - - /* Step 4: Number of tracks is smallest number to accomodate capacity */ - uptr->HDSK_NUMBER_OF_TRACKS = (uptr->capac + uptr->HDSK_SECTORS_PER_TRACK * - uptr->HDSK_SECTOR_SIZE - 1) / (uptr->HDSK_SECTORS_PER_TRACK * uptr->HDSK_SECTOR_SIZE); - assert( ( (t_addr) ((uptr->HDSK_NUMBER_OF_TRACKS - 1) * uptr->HDSK_SECTORS_PER_TRACK * - uptr->HDSK_SECTOR_SIZE) < uptr->capac) && - (uptr->capac <= (t_addr) (uptr->HDSK_NUMBER_OF_TRACKS * - uptr->HDSK_SECTORS_PER_TRACK * uptr->HDSK_SECTOR_SIZE) ) ); - - return SCPE_OK; -} - -static t_stat hdsk_detach(UNIT *uptr) { - t_stat result; - int32 unitIndex; - if (uptr == NULL) - return SCPE_IERR; - if (is_imd(uptr)) { - unitIndex = find_unit_index(uptr); - if (unitIndex == -1) - return SCPE_IERR; - assert((0 <= unitIndex) && (unitIndex < HDSK_NUMBER)); - diskClose(&hdsk_imd[unitIndex]); - } - result = detach_unit(uptr); - uptr->capac = HDSK_CAPACITY; - uptr->HDSK_FORMAT_TYPE = 0; - uptr->HDSK_SECTOR_SIZE = 0; - uptr->HDSK_SECTORS_PER_TRACK = 0; - uptr->HDSK_NUMBER_OF_TRACKS = 0; - return result; -} - -/* Set disk geometry routine */ -static t_stat set_geom(UNIT *uptr, int32 val, char *cptr, void *desc) { - uint32 numberOfTracks, numberOfSectors, sectorSize; - int result, n; - - if (cptr == NULL) - return SCPE_ARG; - if (uptr == NULL) - return SCPE_IERR; - if (((uptr->flags) & UNIT_ATT) == 0) { - printf("Cannot set geometry for not attached unit %i.\n", find_unit_index(uptr)); - return SCPE_ARG; - } - result = sscanf(cptr, "%d/%d/%d%n", &numberOfTracks, &numberOfSectors, §orSize, &n); - if ((result != 3) || (result == EOF) || (cptr[n] != 0)) { - result = sscanf(cptr, "T:%d/N:%d/S:%d%n", &numberOfTracks, &numberOfSectors, §orSize, &n); - if ((result != 3) || (result == EOF) || (cptr[n] != 0)) - return SCPE_ARG; - } - uptr->HDSK_NUMBER_OF_TRACKS = numberOfTracks; - uptr->HDSK_SECTORS_PER_TRACK = numberOfSectors; - uptr->HDSK_SECTOR_SIZE = sectorSize; - uptr->capac = numberOfTracks * numberOfSectors * sectorSize; - return SCPE_OK; -} - -/* Show disk geometry routine */ -static t_stat show_geom(FILE *st, UNIT *uptr, int32 val, void *desc) { - if (uptr == NULL) - return SCPE_IERR; - fprintf(st, "T:%d/N:%d/S:%d", uptr->HDSK_NUMBER_OF_TRACKS, - uptr->HDSK_SECTORS_PER_TRACK, uptr->HDSK_SECTOR_SIZE); - return SCPE_OK; -} - -#define QUOTE1(text) #text -#define QUOTE2(text) QUOTE1(text) -/* Set disk format routine */ -static t_stat set_format(UNIT *uptr, int32 val, char *cptr, void *desc) { - char fmtname[DPB_NAME_LENGTH + 1]; - int32 i; - - if (cptr == NULL) - return SCPE_ARG; - if (uptr == NULL) - return SCPE_IERR; - if (sscanf(cptr, "%" QUOTE2(DPB_NAME_LENGTH) "s", fmtname) == 0) - return SCPE_ARG; - if (((uptr->flags) & UNIT_ATT) == 0) { - printf("Cannot set format for not attached unit %i.\n", find_unit_index(uptr)); - return SCPE_ARG; - } - for (i = 0; dpb[i].capac != 0; i++) { - if (strncmp(fmtname, dpb[i].name, strlen(fmtname)) == 0) { - uptr->HDSK_FORMAT_TYPE = i; - uptr->capac = dpb[i].capac; /* Set capacity */ - - /* Configure physical disk geometry */ - uptr->HDSK_SECTOR_SIZE = (128 << dpb[uptr->HDSK_FORMAT_TYPE].psh); - uptr->HDSK_SECTORS_PER_TRACK = dpb[uptr->HDSK_FORMAT_TYPE].spt >> dpb[uptr->HDSK_FORMAT_TYPE].psh; - uptr->HDSK_NUMBER_OF_TRACKS = (uptr->capac + - uptr->HDSK_SECTORS_PER_TRACK * uptr->HDSK_SECTOR_SIZE - 1) / - (uptr->HDSK_SECTORS_PER_TRACK * uptr->HDSK_SECTOR_SIZE); - - return SCPE_OK; - } - } - return SCPE_ARG; -} - -/* Show disk format routine */ -static t_stat show_format(FILE *st, UNIT *uptr, int32 val, void *desc) { - if (uptr == NULL) - return SCPE_IERR; - fprintf(st, "%s", dpb[uptr->HDSK_FORMAT_TYPE].name); - return SCPE_OK; -} - -static int32 bootrom_hdsk[BOOTROM_SIZE_HDSK] = { - 0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* 5c00-5c07 */ - 0xc2, 0x05, 0x5c, 0x3e, 0x16, 0xd3, 0xfe, 0x3e, /* 5c08-5c0f */ - 0x12, 0xd3, 0xfe, 0xdb, 0xfe, 0xb7, 0xca, 0x20, /* 5c10-5c17 */ - 0x5c, 0x3e, 0x0c, 0xd3, 0xfe, 0xaf, 0xd3, 0xfe, /* 5c18-5c1f */ - 0x06, 0x20, 0x3e, 0x01, 0xd3, 0xfd, 0x05, 0xc2, /* 5c20-5c27 */ - 0x24, 0x5c, 0x11, 0x08, 0x00, 0x21, 0x00, 0x00, /* 5c28-5c2f */ - 0x0e, 0xb8, 0x3e, 0x02, 0xd3, 0xfd, 0x3a, 0x37, /* 5c30-5c37 */ - 0xff, 0xd6, 0x08, 0xd3, 0xfd, 0x7b, 0xd3, 0xfd, /* 5c38-5c3f */ - 0x7a, 0xd3, 0xfd, 0xaf, 0xd3, 0xfd, 0x7d, 0xd3, /* 5c40-5c47 */ - 0xfd, 0x7c, 0xd3, 0xfd, 0xdb, 0xfd, 0xb7, 0xca, /* 5c48-5c4f */ - 0x53, 0x5c, 0x76, 0x79, 0x0e, 0x80, 0x09, 0x4f, /* 5c50-5c57 */ - 0x0d, 0xc2, 0x60, 0x5c, 0xfb, 0xc3, 0x00, 0x00, /* 5c58-5c5f */ - 0x1c, 0x1c, 0x7b, 0xfe, 0x20, 0xca, 0x73, 0x5c, /* 5c60-5c67 */ - 0xfe, 0x21, 0xc2, 0x32, 0x5c, 0x1e, 0x00, 0x14, /* 5c68-5c6f */ - 0xc3, 0x32, 0x5c, 0x1e, 0x01, 0xc3, 0x32, 0x5c, /* 5c70-5c77 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c78-5c7f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c80-5c87 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c88-5c8f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c90-5c97 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c98-5c9f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ca0-5ca7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ca8-5caf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cb0-5cb7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cb8-5cbf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cc0-5cc7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cc8-5ccf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cd0-5cd7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cd8-5cdf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ce0-5ce7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ce8-5cef */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cf0-5cf7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cf8-5cff */ -}; - -static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) { - if (MEMORYSIZE < 24*KB) { - printf("Need at least 24KB RAM to boot from hard disk.\n"); - return SCPE_ARG; - } - if (cpu_unit.flags & (UNIT_CPU_ALTAIRROM | UNIT_CPU_BANKED)) { - /* check whether we are really modifying an LD A,<> instruction */ - if (bootrom_dsk[UNIT_NO_OFFSET_1 - 1] == LDA_INSTRUCTION) - bootrom_dsk[UNIT_NO_OFFSET_1] = (unitno + NUM_OF_DSK) & 0xff; /* LD A, */ - else { /* Attempt to modify non LD A,<> instructions is refused. */ - printf("Incorrect boot ROM offset detected.\n"); - return SCPE_IERR; - } - install_ALTAIRbootROM(); /* install modified ROM */ - } - assert(install_bootrom(bootrom_hdsk, BOOTROM_SIZE_HDSK, HDSK_BOOT_ADDRESS, FALSE) == SCPE_OK); - *((int32 *) sim_PC->loc) = HDSK_BOOT_ADDRESS; - return SCPE_OK; -} - -/* The hard disk port is 0xfd. It understands the following commands. - - 1. Reset - ld b,32 - ld a,HDSK_RESET - l: out (0fdh),a - dec b - jp nz,l - - 2. Read / write - ; parameter block - cmd: db HDSK_READ or HDSK_WRITE - hd: db 0 ; 0 .. 7, defines hard disk to be used - sector: db 0 ; 0 .. 31, defines sector - track: dw 0 ; 0 .. 2047, defines track - dma: dw 0 ; defines where result is placed in memory - - ; routine to execute - ld b,7 ; size of parameter block - ld hl,cmd ; start address of parameter block - l: ld a,(hl) ; get byte of parameter block - out (0fdh),a ; send it to port - inc hl ; point to next byte - dec b ; decrement counter - jp nz,l ; again, if not done - in a,(0fdh) ; get result code - - 3. Retrieve Disk Parameters from controller (Howard M. Harte) - Reads a 19-byte parameter block from the disk controller. - This parameter block is in CP/M DPB format for the first 17 bytes, - and the last two bytes are the lsb/msb of the disk's physical - sector size. - - ; routine to execute - ld a,hdskParam ; hdskParam = 4 - out (hdskPort),a ; Send 'get parameters' command, hdskPort = 0fdh - ld a,(diskno) - out (hdskPort),a ; Send selected HDSK number - ld b,17 - 1: in a,(hdskPort) ; Read 17-bytes of DPB - ld (hl), a - inc hl - djnz 1 - in a,(hdskPort) ; Read LSB of disk's physical sector size. - ld (hsecsiz), a - in a,(hdskPort) ; Read MSB of disk's physical sector size. - ld (hsecsiz+1), a - -*/ - -/* check the parameters and return TRUE iff parameters are correct or have been repaired */ -static int32 checkParameters(void) { - UNIT *uptr; - if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) { - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT - " Disk %i does not exist, will use HDSK0 instead.\n", - selectedDisk, PCX, selectedDisk); - selectedDisk = 0; - } - uptr = &hdsk_dev.units[selectedDisk]; - if ((hdsk_dev.units[selectedDisk].flags & UNIT_ATT) == 0) { - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT - " Disk %i is not attached.\n", selectedDisk, PCX, selectedDisk); - return FALSE; /* cannot read or write */ - } - if ((selectedSector < 0) || (selectedSector >= uptr->HDSK_SECTORS_PER_TRACK)) { - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT - " Constraint violation 0 <= Sector=%02d < %d, will use sector 0 instead.\n", - selectedDisk, PCX, selectedSector, uptr->HDSK_SECTORS_PER_TRACK); - selectedSector = 0; - } - if ((selectedTrack < 0) || (selectedTrack >= uptr->HDSK_NUMBER_OF_TRACKS)) { - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT - " Constraint violation 0 <= Track=%04d < %04d, will use track 0 instead.\n", - selectedDisk, PCX, selectedTrack, uptr->HDSK_NUMBER_OF_TRACKS); - selectedTrack = 0; - } - selectedDMA &= ADDRMASK; - if (hdskLastCommand == HDSK_READ) - sim_debug(READ_MSG, &hdsk_dev, "HDSK%d " ADDRESS_FORMAT - " Read Track=%04d Sector=%02d Len=%04d DMA=%04x\n", - selectedDisk, PCX, selectedTrack, selectedSector, uptr->HDSK_SECTOR_SIZE, selectedDMA); - if (hdskLastCommand == HDSK_WRITE) - sim_debug(WRITE_MSG, &hdsk_dev, "HDSK%d " ADDRESS_FORMAT - " Write Track=%04d Sector=%02d Len=%04d DMA=%04x\n", - selectedDisk, PCX, selectedTrack, selectedSector, uptr->HDSK_SECTOR_SIZE, selectedDMA); - return TRUE; -} - -/* pre-condition: checkParameters has been executed to repair any faulty parameters */ -static int32 doSeek(void) { - UNIT *uptr = &hdsk_dev.units[selectedDisk]; - int32 hostSector = (dpb[uptr->HDSK_FORMAT_TYPE].skew == NULL) ? - selectedSector : dpb[uptr->HDSK_FORMAT_TYPE].skew[selectedSector]; - int32 sectorSize = (dpb[uptr->HDSK_FORMAT_TYPE].physicalSectorSize == 0) ? - uptr->HDSK_SECTOR_SIZE : dpb[uptr->HDSK_FORMAT_TYPE].physicalSectorSize; - if (sim_fseek(uptr->fileref, - sectorSize * (uptr->HDSK_SECTORS_PER_TRACK * selectedTrack + hostSector) + - dpb[uptr->HDSK_FORMAT_TYPE].offset, SEEK_SET)) { - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT - " Could not access Sector=%02d[=%02d] Track=%04d.\n", - selectedDisk, PCX, selectedSector, hostSector, selectedTrack); - return CPM_ERROR; - } - return CPM_OK; -} - -static uint8 hdskbuf[HDSK_MAX_SECTOR_SIZE] = { 0 }; /* data buffer */ - -/* pre-condition: checkParameters has been executed to repair any faulty parameters */ -static int32 doRead(void) { - int32 i; - t_stat result; - DISK_INFO *thisDisk; - int32 hostSector; - int32 sectorSize; - uint32 flags; - uint32 readlen; - uint32 cylinder; - uint32 head; - UNIT *uptr = &hdsk_dev.units[selectedDisk]; - if (is_imd(uptr)) { - thisDisk = hdsk_imd[selectedDisk]; - hostSector = ((dpb[uptr->HDSK_FORMAT_TYPE].skew == NULL) ? - selectedSector : dpb[uptr->HDSK_FORMAT_TYPE].skew[selectedSector]) + thisDisk->track[1][0].start_sector; - sectorSize = ((dpb[uptr->HDSK_FORMAT_TYPE].physicalSectorSize == 0) ? - uptr->HDSK_SECTOR_SIZE : - dpb[uptr->HDSK_FORMAT_TYPE].physicalSectorSize); - flags = 0; - readlen = 0; - cylinder = selectedTrack; - head = 0; - if (cylinder >= thisDisk->ntracks / thisDisk->nsides) { - head = 1; - cylinder -= thisDisk->ntracks / thisDisk->nsides; - } - result = sectRead(thisDisk, cylinder, head, hostSector, hdskbuf, sectorSize, - &flags, &readlen); - if (result != SCPE_OK) { - for (i = 0; i < uptr->HDSK_SECTOR_SIZE; i++) - hdskbuf[i] = CPM_EMPTY; - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d (IMD): " ADDRESS_FORMAT - " . Could not read Sector=%02d Track=%04d.\n", - selectedDisk, PCX, selectedSector, selectedTrack); - return CPM_ERROR; - } - } else { - if (doSeek()) - return CPM_ERROR; - - if (sim_fread(hdskbuf, 1, uptr->HDSK_SECTOR_SIZE, uptr->fileref) != (size_t)(uptr->HDSK_SECTOR_SIZE)) { - for (i = 0; i < uptr->HDSK_SECTOR_SIZE; i++) - hdskbuf[i] = CPM_EMPTY; - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT - " Could not read Sector=%02d Track=%04d.\n", - selectedDisk, PCX, selectedSector, selectedTrack); - return CPM_OK; /* allows the creation of empty hard disks */ - } - } - for (i = 0; i < uptr->HDSK_SECTOR_SIZE; i++) - PutBYTEWrapper(selectedDMA + i, hdskbuf[i]); - return CPM_OK; -} - -/* pre-condition: checkParameters has been executed to repair any faulty parameters */ -static int32 doWrite(void) { - int32 i; - t_stat result; - DISK_INFO *thisDisk; - int32 hostSector; - int32 sectorSize; - uint32 flags; - uint32 writelen; - uint32 cylinder; - uint32 head; - size_t rtn; - UNIT *uptr = &hdsk_dev.units[selectedDisk]; - if (((uptr->flags) & UNIT_HDSK_WLK) == 0) { /* write enabled */ - if (is_imd(uptr)) { - for (i = 0; i < uptr->HDSK_SECTOR_SIZE; i++) - hdskbuf[i] = GetBYTEWrapper(selectedDMA + i); - thisDisk = hdsk_imd[selectedDisk]; - hostSector = ((dpb[uptr->HDSK_FORMAT_TYPE].skew == NULL) ? - selectedSector : dpb[uptr->HDSK_FORMAT_TYPE].skew[selectedSector]) + thisDisk->track[1][0].start_sector; - sectorSize = ((dpb[uptr->HDSK_FORMAT_TYPE].physicalSectorSize == 0) ? - uptr->HDSK_SECTOR_SIZE : - dpb[uptr->HDSK_FORMAT_TYPE].physicalSectorSize); - flags = 0; - writelen = 0; - cylinder = selectedTrack; - head = 0; - if (cylinder >= thisDisk->ntracks / thisDisk->nsides) { - head = 1; - cylinder -= thisDisk->ntracks / thisDisk->nsides; - } - result = sectWrite(thisDisk, cylinder, head, hostSector, hdskbuf, - sectorSize, &flags, &writelen); - if (result != SCPE_OK) { - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d (IMD): " ADDRESS_FORMAT - " . Could not write Sector=%02d Track=%04d.\n", - selectedDisk, PCX, selectedSector, selectedTrack); - return CPM_ERROR; - } - } else { - if (doSeek()) - return CPM_ERROR; - for (i = 0; i < uptr->HDSK_SECTOR_SIZE; i++) - hdskbuf[i] = GetBYTEWrapper(selectedDMA + i); - rtn = sim_fwrite(hdskbuf, 1, uptr->HDSK_SECTOR_SIZE, uptr->fileref); - if (rtn != (size_t)(uptr->HDSK_SECTOR_SIZE)) { - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT - " Could not write Sector=%02d Track=%04d Result=%zd.\n", - selectedDisk, PCX, selectedSector, selectedTrack, rtn); - return CPM_ERROR; - } - } - } - else { - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT - " Could not write to locked disk Sector=%02d Track=%04d.\n", - selectedDisk, PCX, selectedSector, selectedTrack); - return CPM_ERROR; - } - return CPM_OK; -} - -#define PARAMETER_BLOCK_SIZE 19 -static uint8 parameterBlock[PARAMETER_BLOCK_SIZE]; - -static int32 hdsk_in(const int32 port) { - if ((hdskCommandPosition == 6) && ((hdskLastCommand == HDSK_READ) || (hdskLastCommand == HDSK_WRITE))) { - int32 result = checkParameters() ? ((hdskLastCommand == HDSK_READ) ? doRead() : doWrite()) : CPM_ERROR; - hdskLastCommand = HDSK_NONE; - hdskCommandPosition = 0; - return result; - } - if (hdskLastCommand == HDSK_PARAM) { - if (++parameterCount >= PARAMETER_BLOCK_SIZE) - hdskLastCommand = HDSK_NONE; - return parameterBlock[parameterCount - 1]; - } - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT - " Illegal IN command detected (port=%03xh, cmd=%d, pos=%d).\n", - selectedDisk, PCX, port, hdskLastCommand, hdskCommandPosition); - return CPM_OK; -} - -static int32 hdsk_out(const int32 port, const int32 data) { - int32 thisDisk; - UNIT *uptr; - DPB current; - - switch(hdskLastCommand) { - - case HDSK_PARAM: - parameterCount = 0; - thisDisk = (0 <= data) && (data < HDSK_NUMBER) ? data : 0; - uptr = &hdsk_dev.units[thisDisk]; - if ((uptr->flags) & UNIT_ATT) { - current = dpb[uptr->HDSK_FORMAT_TYPE]; - parameterBlock[17] = uptr->HDSK_SECTOR_SIZE & 0xff; - parameterBlock[18] = (uptr->HDSK_SECTOR_SIZE >> 8) & 0xff; - } - else { - current = dpb[0]; - parameterBlock[17] = 128; - parameterBlock[18] = 0; - } - parameterBlock[ 0] = current.spt & 0xff; parameterBlock[ 1] = (current.spt >> 8) & 0xff; - parameterBlock[ 2] = current.bsh; - parameterBlock[ 3] = current.blm; - parameterBlock[ 4] = current.exm; - parameterBlock[ 5] = current.dsm & 0xff; parameterBlock[ 6] = (current.dsm >> 8) & 0xff; - parameterBlock[ 7] = current.drm & 0xff; parameterBlock[ 8] = (current.drm >> 8) & 0xff; - parameterBlock[ 9] = current.al0; - parameterBlock[10] = current.al1; - parameterBlock[11] = current.cks & 0xff; parameterBlock[12] = (current.cks >> 8) & 0xff; - parameterBlock[13] = current.off & 0xff; parameterBlock[14] = (current.off >> 8) & 0xff; - parameterBlock[15] = current.psh; - parameterBlock[16] = current.phm; - break; - - case HDSK_READ: - - case HDSK_WRITE: - switch(hdskCommandPosition) { - - case 0: - selectedDisk = data; - hdskCommandPosition++; - break; - - case 1: - selectedSector = data; - hdskCommandPosition++; - break; - - case 2: - selectedTrack = data; - hdskCommandPosition++; - break; - - case 3: - selectedTrack += (data << 8); - hdskCommandPosition++; - break; - - case 4: - selectedDMA = data; - hdskCommandPosition++; - break; - - case 5: - selectedDMA += (data << 8); - hdskCommandPosition++; - break; - - default: - hdskLastCommand = HDSK_NONE; - hdskCommandPosition = 0; - } - break; - - default: - if ((HDSK_RESET <= data) && (data <= HDSK_PARAM)) - hdskLastCommand = data; - else { - sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT - " Illegal OUT command detected (port=%03xh, cmd=%d).\n", - selectedDisk, PCX, port, data); - hdskLastCommand = HDSK_RESET; - } - hdskCommandPosition = 0; - } - return 0; /* ignored, since OUT */ -} - -int32 hdsk_io(const int32 port, const int32 io, const int32 data) { - return io == 0 ? hdsk_in(port) : hdsk_out(port, data); -} diff --git a/AltairZ80/altairz80_net.c b/AltairZ80/altairz80_net.c deleted file mode 100644 index ea2bf276..00000000 --- a/AltairZ80/altairz80_net.c +++ /dev/null @@ -1,321 +0,0 @@ -/* altairz80_net.c: networking capability - - Copyright (c) 2002-2012, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. -*/ - -#include "altairz80_defs.h" -#include "sim_sock.h" - -/* Debug flags */ -#define ACCEPT_MSG (1 << 0) -#define DROP_MSG (1 << 1) -#define IN_MSG (1 << 2) -#define OUT_MSG (1 << 3) - -extern uint32 PCX; - -#define UNIT_V_SERVER (UNIT_V_UF + 0) /* define machine as a server */ -#define UNIT_SERVER (1 << UNIT_V_SERVER) -#define NET_INIT_POLL_SERVER 16000 -#define NET_INIT_POLL_CLIENT 15000 - -static t_stat net_attach (UNIT *uptr, char *cptr); -static t_stat net_detach (UNIT *uptr); -static t_stat net_reset (DEVICE *dptr); -static t_stat net_svc (UNIT *uptr); -static t_stat set_net (UNIT *uptr, int32 value, char *cptr, void *desc); -int32 netStatus (const int32 port, const int32 io, const int32 data); -int32 netData (const int32 port, const int32 io, const int32 data); - -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); - -#define MAX_CONNECTIONS 2 /* maximal number of server connections */ -#define BUFFER_LENGTH 512 /* length of input and output buffer */ - -static struct { - int32 Z80StatusPort; /* Z80 status port associated with this ioSocket, read only */ - int32 Z80DataPort; /* Z80 data port associated with this ioSocket, read only */ - SOCKET masterSocket; /* server master socket, only defined at [1] */ - SOCKET ioSocket; /* accepted server socket or connected client socket, 0 iff free */ - char inputBuffer[BUFFER_LENGTH]; /* buffer for input characters read from ioSocket */ - int32 inputPosRead; /* position of next character to read from buffer */ - int32 inputPosWrite; /* position of next character to append to input buffer from ioSocket */ - int32 inputSize; /* number of characters in circular input buffer */ - char outputBuffer[BUFFER_LENGTH];/* buffer for output characters to be written to ioSocket */ - int32 outputPosRead; /* position of next character to write to ioSocket */ - int32 outputPosWrite; /* position of next character to append to output buffer */ - int32 outputSize; /* number of characters in circular output buffer */ -} serviceDescriptor[MAX_CONNECTIONS + 1] = { /* serviceDescriptor[0] holds the information for a client */ -/* stat dat ms ios in inPR inPW inS out outPR outPW outS */ - {0x32, 0x33, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* client Z80 port 50 and 51 */ - {0x28, 0x29, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* server Z80 port 40 and 41 */ - {0x2a, 0x2b, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0} /* server Z80 port 42 and 43 */ -}; - -static UNIT net_unit = { - UDATA (&net_svc, UNIT_ATTABLE, 0), - 0, /* wait, set in attach */ - 0, /* u3 = Port */ - 0, /* u4 = IP of host */ - 0, /* u5, unused */ - 0, /* u6, unused */ -}; - -static REG net_reg[] = { - { DRDATA (POLL, net_unit.wait, 32) }, - { HRDATA (IPHOST, net_unit.u4, 32), REG_RO }, - { DRDATA (PORT, net_unit.u3, 32), REG_RO }, - { NULL } -}; - -static MTAB net_mod[] = { - { UNIT_SERVER, 0, "CLIENT", "CLIENT", &set_net}, /* machine is a client */ - { UNIT_SERVER, UNIT_SERVER, "SERVER", "SERVER", &set_net}, /* machine is a server */ - { 0 } -}; - -/* Debug Flags */ -static DEBTAB net_dt[] = { - { "ACCEPT", ACCEPT_MSG }, - { "DROP", DROP_MSG }, - { "IN", IN_MSG }, - { "OUT", OUT_MSG }, - { NULL, 0 } -}; - -DEVICE net_dev = { - "NET", &net_unit, net_reg, net_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &net_reset, - NULL, &net_attach, &net_detach, - NULL, (DEV_DISABLE | DEV_DEBUG), 0, - net_dt, NULL, "Network NET" -}; - -static t_stat set_net(UNIT *uptr, int32 value, char *cptr, void *desc) { - char temp[CBUFSIZE]; - if ((net_unit.flags & UNIT_ATT) && ((net_unit.flags & UNIT_SERVER) != (uint32)value)) { - strncpy(temp, net_unit.filename, CBUFSIZE); /* save name for later attach */ - net_detach(&net_unit); - net_unit.flags ^= UNIT_SERVER; /* now switch from client to server and vice versa */ - net_attach(uptr, temp); - return SCPE_OK; - } - return SCPE_OK; -} - -static void serviceDescriptor_reset(const uint32 i) { - serviceDescriptor[i].inputPosRead = 0; - serviceDescriptor[i].inputPosWrite = 0; - serviceDescriptor[i].inputSize = 0; - serviceDescriptor[i].outputPosRead = 0; - serviceDescriptor[i].outputPosWrite = 0; - serviceDescriptor[i].outputSize = 0; -} - -static t_stat net_reset(DEVICE *dptr) { - uint32 i; - if (net_unit.flags & UNIT_ATT) - sim_activate(&net_unit, net_unit.wait); /* start poll */ - for (i = 0; i <= MAX_CONNECTIONS; i++) { - serviceDescriptor_reset(i); - sim_map_resource(serviceDescriptor[i].Z80StatusPort, 1, - RESOURCE_TYPE_IO, &netStatus, dptr->flags & DEV_DIS); - sim_map_resource(serviceDescriptor[i].Z80DataPort, 1, - RESOURCE_TYPE_IO, &netData, dptr->flags & DEV_DIS); - } - return SCPE_OK; -} - -static t_stat net_attach(UNIT *uptr, char *cptr) { - uint32 i, ipa, ipp; - t_stat r = get_ipaddr(cptr, &ipa, &ipp); - if (r != SCPE_OK) - return SCPE_ARG; - if (ipa == 0) - ipa = 0x7F000001; /* localhost = 127.0.0.1 */ - if (ipp == 0) - ipp = 3000; - net_unit.u3 = ipp; - net_unit.u4 = ipa; - net_reset(&net_dev); - for (i = 0; i <= MAX_CONNECTIONS; i++) - serviceDescriptor[i].ioSocket = 0; - if (net_unit.flags & UNIT_SERVER) { - net_unit.wait = NET_INIT_POLL_SERVER; - serviceDescriptor[1].masterSocket = sim_master_sock(ipp); - if (serviceDescriptor[1].masterSocket == INVALID_SOCKET) - return SCPE_IOERR; - } - else { - net_unit.wait = NET_INIT_POLL_CLIENT; - serviceDescriptor[0].ioSocket = sim_connect_sock(ipa, ipp); - if (serviceDescriptor[0].ioSocket == INVALID_SOCKET) - return SCPE_IOERR; - } - net_unit.flags |= UNIT_ATT; - net_unit.filename = (char *) calloc(CBUFSIZE, sizeof (char)); /* alloc name buf */ - if (net_unit.filename == NULL) - return SCPE_MEM; - strncpy(net_unit.filename, cptr, CBUFSIZE); /* save name */ - return SCPE_OK; -} - -static t_stat net_detach(UNIT *uptr) { - uint32 i; - if (!(net_unit.flags & UNIT_ATT)) - return SCPE_OK; /* if not attached simply return */ - if (net_unit.flags & UNIT_SERVER) - sim_close_sock(serviceDescriptor[1].masterSocket, TRUE); - for (i = 0; i <= MAX_CONNECTIONS; i++) - if (serviceDescriptor[i].ioSocket) - sim_close_sock(serviceDescriptor[i].ioSocket, FALSE); - free(net_unit.filename); /* free port string */ - net_unit.filename = NULL; - net_unit.flags &= ~UNIT_ATT; /* not attached */ - return SCPE_OK; -} - -/* cannot use sim_check_conn to check whether read will return an error */ -static t_stat net_svc(UNIT *uptr) { - int32 i, j, k, r; - SOCKET s; - static char svcBuffer[BUFFER_LENGTH]; - if (net_unit.flags & UNIT_ATT) { /* cannot remove due to following else */ - sim_activate(&net_unit, net_unit.wait); /* continue poll */ - if (net_unit.flags & UNIT_SERVER) { - for (i = 1; i <= MAX_CONNECTIONS; i++) - if (serviceDescriptor[i].ioSocket == 0) { - s = sim_accept_conn(serviceDescriptor[1].masterSocket, NULL); - if (s != INVALID_SOCKET) { - serviceDescriptor[i].ioSocket = s; - sim_debug(ACCEPT_MSG, &net_dev, "NET: " ADDRESS_FORMAT " Accepted connection %i with socket %i.\n", PCX, i, s); - } - } - } - else if (serviceDescriptor[0].ioSocket == 0) { - serviceDescriptor[0].ioSocket = sim_connect_sock(net_unit.u4, net_unit.u3); - if (serviceDescriptor[0].ioSocket == INVALID_SOCKET) - return SCPE_IOERR; - printf("\rWaiting for server ... Type g (possibly twice) when ready" NLP); - return SCPE_STOP; - } - for (i = 0; i <= MAX_CONNECTIONS; i++) - if (serviceDescriptor[i].ioSocket) { - if (serviceDescriptor[i].inputSize < BUFFER_LENGTH) { /* there is space left in inputBuffer */ - r = sim_read_sock(serviceDescriptor[i].ioSocket, svcBuffer, - BUFFER_LENGTH - serviceDescriptor[i].inputSize); - if (r == -1) { - sim_debug(DROP_MSG, &net_dev, "NET: " ADDRESS_FORMAT " Drop connection %i with socket %i.\n", PCX, i, serviceDescriptor[i].ioSocket); - sim_close_sock(serviceDescriptor[i].ioSocket, FALSE); - serviceDescriptor[i].ioSocket = 0; - serviceDescriptor_reset(i); - continue; - } - else { - for (j = 0; j < r; j++) { - serviceDescriptor[i].inputBuffer[serviceDescriptor[i].inputPosWrite++] = svcBuffer[j]; - if (serviceDescriptor[i].inputPosWrite == BUFFER_LENGTH) - serviceDescriptor[i].inputPosWrite = 0; - } - serviceDescriptor[i].inputSize += r; - } - } - if (serviceDescriptor[i].outputSize > 0) { /* there is something to write in outputBuffer */ - k = serviceDescriptor[i].outputPosRead; - for (j = 0; j < serviceDescriptor[i].outputSize; j++) { - svcBuffer[j] = serviceDescriptor[i].outputBuffer[k++]; - if (k == BUFFER_LENGTH) - k = 0; - } - r = sim_write_sock(serviceDescriptor[i].ioSocket, svcBuffer, serviceDescriptor[i].outputSize); - if (r >= 0) { - serviceDescriptor[i].outputSize -= r; - serviceDescriptor[i].outputPosRead += r; - if (serviceDescriptor[i].outputPosRead >= BUFFER_LENGTH) - serviceDescriptor[i].outputPosRead -= BUFFER_LENGTH; - } - else - printf("write %i" NLP, r); - } - } - } - return SCPE_OK; -} - -int32 netStatus(const int32 port, const int32 io, const int32 data) { - uint32 i; - if ((net_unit.flags & UNIT_ATT) == 0) - return 0; - net_svc(&net_unit); - if (io == 0) /* IN */ - for (i = 0; i <= MAX_CONNECTIONS; i++) - if (serviceDescriptor[i].Z80StatusPort == port) - return (serviceDescriptor[i].inputSize > 0 ? 1 : 0) | - (serviceDescriptor[i].outputSize < BUFFER_LENGTH ? 2 : 0); - return 0; -} - -int32 netData(const int32 port, const int32 io, const int32 data) { - uint32 i; - char result; - if ((net_unit.flags & UNIT_ATT) == 0) - return 0; - net_svc(&net_unit); - for (i = 0; i <= MAX_CONNECTIONS; i++) - if (serviceDescriptor[i].Z80DataPort == port) { - if (io == 0) { /* IN */ - if (serviceDescriptor[i].inputSize == 0) { - printf("re-read from %i" NLP, port); - result = serviceDescriptor[i].inputBuffer[serviceDescriptor[i].inputPosRead > 0 ? - serviceDescriptor[i].inputPosRead - 1 : BUFFER_LENGTH - 1]; - } - else { - result = serviceDescriptor[i].inputBuffer[serviceDescriptor[i].inputPosRead++]; - if (serviceDescriptor[i].inputPosRead == BUFFER_LENGTH) - serviceDescriptor[i].inputPosRead = 0; - serviceDescriptor[i].inputSize--; - } - sim_debug(IN_MSG, &net_dev, "NET: " ADDRESS_FORMAT " IN(%i)=%03xh (%c)\n", PCX, port, (result & 0xff), (32 <= (result & 0xff)) && ((result & 0xff) <= 127) ? (result & 0xff) : '?'); - return result; - } - else { /* OUT */ - if (serviceDescriptor[i].outputSize == BUFFER_LENGTH) { - printf("over-write %i to %i" NLP, data, port); - serviceDescriptor[i].outputBuffer[serviceDescriptor[i].outputPosWrite > 0 ? - serviceDescriptor[i].outputPosWrite - 1 : BUFFER_LENGTH - 1] = data; - } - else { - serviceDescriptor[i].outputBuffer[serviceDescriptor[i].outputPosWrite++] = data; - if (serviceDescriptor[i].outputPosWrite== BUFFER_LENGTH) - serviceDescriptor[i].outputPosWrite = 0; - serviceDescriptor[i].outputSize++; - } - sim_debug(OUT_MSG, &net_dev, "NET: " ADDRESS_FORMAT " OUT(%i)=%03xh (%c)\n", PCX, port, data, (32 <= data) && (data <= 127) ? data : '?'); - return 0; - } - } - return 0; -} diff --git a/AltairZ80/altairz80_sio.c b/AltairZ80/altairz80_sio.c deleted file mode 100644 index 984f8772..00000000 --- a/AltairZ80/altairz80_sio.c +++ /dev/null @@ -1,1880 +0,0 @@ -/* altairz80_sio.c: MITS Altair serial I/O card - - Copyright (c) 2002-2012, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - - These functions support a simulated MITS 2SIO interface card. - The card had two physical I/O ports 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. Each device has a status port - and a data port. A write to the status port can select - some options for the device (0x03 will reset the port). - A read of the status port gets the port status: - - +---+---+---+---+---+---+---+---+ - | X | X | X | X | X | X | O | I | - +---+---+---+---+---+---+---+---+ - - I - A 1 in this bit position means a character has been received - on the data port and is ready to be read. - O - A 1 in this bit means the port is ready to receive a character - on the data port and transmit it out over the serial line. - - A read to the data port gets the buffered character, a write - to the data port writes the character to the device. -*/ - -#include - -#include "altairz80_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include -#include -#if UNIX_PLATFORM -#include -#elif defined (_WIN32) -#include -#endif - -uint8 *URLContents(const char *URL, uint32 *length); -#ifndef URL_READER_SUPPORT -#define RESULT_BUFFER_LENGTH 1024 -#define RESULT_LEAD_IN "URL is not supported on this platform. START URL \"" -#define RESULT_LEAD_OUT "\" URL END." -uint8 *URLContents(const char *URL, uint32 *length) { - char str[RESULT_BUFFER_LENGTH] = RESULT_LEAD_IN; - char *result; - strncat(str, URL, RESULT_BUFFER_LENGTH - strlen(RESULT_LEAD_IN) - strlen(RESULT_LEAD_OUT) - 1); - strcat(str, RESULT_LEAD_OUT); - result = malloc(strlen(str)); - strcpy(result, str); - *length = strlen(str); - return (uint8*)result; -} -#endif - -/* Debug flags */ -#define IN_MSG (1 << 0) -#define OUT_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define VERBOSE_MSG (1 << 3) -#define BUFFER_EMPTY_MSG (1 << 4) - -#define UNIT_V_SIO_ANSI (UNIT_V_UF + 0) /* ANSI mode, strip bit 8 on output */ -#define UNIT_SIO_ANSI (1 << UNIT_V_SIO_ANSI) -#define UNIT_V_SIO_UPPER (UNIT_V_UF + 1) /* upper case mode */ -#define UNIT_SIO_UPPER (1 << UNIT_V_SIO_UPPER) -#define UNIT_V_SIO_BS (UNIT_V_UF + 2) /* map delete to backspace */ -#define UNIT_SIO_BS (1 << UNIT_V_SIO_BS) -#define UNIT_V_SIO_VERBOSE (UNIT_V_UF + 3) /* verbose mode, i.e. show error messages */ -#define UNIT_SIO_VERBOSE (1 << UNIT_V_SIO_VERBOSE) -#define UNIT_V_SIO_MAP (UNIT_V_UF + 4) /* mapping mode on */ -#define UNIT_SIO_MAP (1 << UNIT_V_SIO_MAP) -#define UNIT_V_SIO_BELL (UNIT_V_UF + 5) /* ^G (bell character) rings bell */ -#define UNIT_SIO_BELL (1 << UNIT_V_SIO_BELL) -#define UNIT_V_SIO_INTERRUPT (UNIT_V_UF + 6) /* create keyboard interrupts */ -#define UNIT_SIO_INTERRUPT (1 << UNIT_V_SIO_INTERRUPT) -#define UNIT_V_SIO_SLEEP (UNIT_V_UF + 7) /* sleep after keyboard status check */ -#define UNIT_SIO_SLEEP (1 << UNIT_V_SIO_SLEEP) - -#define UNIT_V_SIMH_TIMERON (UNIT_V_UF + 1) /* SIMH pseudo device timer generate interrupts */ -#define UNIT_SIMH_TIMERON (1 << UNIT_V_SIMH_TIMERON) - -#define TERMINALS 33 /* lines per mux (increased to 33 for IF3 board)*/ -#define SIO_CAN_READ 0x01 /* bit 0 is set iff character available */ -#define SIO_CAN_WRITE 0x02 /* bit 1 is set iff character can be sent */ -#define SIO_RESET 0x03 /* Command to reset SIO */ -#define VGSIO_CAN_READ 0x02 /* bit 1 is set iff character available */ -#define VGSIO_CAN_WRITE 0x01 /* bit 0 is set iff character can be sent */ -#define KBD_HAS_CHAR 0x40 /* bit 6 is set iff character available */ -#define KBD_HAS_NO_CHAR 0x01 /* bit 0 is set iff no character is available */ - -#define BACKSPACE_CHAR 0x08 /* backspace character */ -#define DELETE_CHAR 0x7f /* delete character */ -#define CONTROLC_CHAR 0x03 /* control C character */ -#define CONTROLG_CHAR 0x07 /* control G char., rings bell when displayed */ -#define CONTROLZ_CHAR 0x1a /* control Z character */ - -#define PORT_TABLE_SIZE 256 /* size of port mapping table */ -#define SLEEP_ALLOWED_START_DEFAULT 100 /* default initial value for sleepAllowedCounter*/ -#define DEFAULT_TIMER_DELTA 100 /* default value for timer delta in ms */ - -static t_stat simh_dev_set_timeron (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat simh_dev_set_timeroff (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat sio_reset(DEVICE *dptr); -static t_stat sio_attach(UNIT *uptr, char *cptr); -static t_stat sio_detach(UNIT *uptr); -static t_stat ptr_reset(DEVICE *dptr); -static t_stat ptp_reset(DEVICE *dptr); -static t_stat toBool(char tf, int32 *result); -static t_stat sio_dev_set_port(UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat sio_dev_show_port(FILE *st, UNIT *uptr, int32 val, void *desc); -static t_stat sio_dev_set_interrupton(UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat sio_dev_set_interruptoff(UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat sio_svc(UNIT *uptr); -static t_stat simh_dev_reset(DEVICE *dptr); -static t_stat simh_svc(UNIT *uptr); -static void mapAltairPorts(void); -int32 nulldev (const int32 port, const int32 io, const int32 data); -int32 sr_dev (const int32 port, const int32 io, const int32 data); -int32 simh_dev (const int32 port, const int32 io, const int32 data); -int32 sio0d (const int32 port, const int32 io, const int32 data); -int32 sio0s (const int32 port, const int32 io, const int32 data); -int32 sio1d (const int32 port, const int32 io, const int32 data); -int32 sio1s (const int32 port, const int32 io, const int32 data); -void do_SIMH_sleep(void); -static void pollConnection(void); -static int32 mapCharacter(int32 ch); -static void checkSleep(void); -static void voidSleep(void); - -extern int32 getBankSelect(void); -extern void setBankSelect(const int32 b); -extern uint32 getCommon(void); -extern uint8 GetBYTEWrapper(const uint32 Addr); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern uint32 getClockFrequency(void); -extern void setClockFrequency(const uint32 Value); - -extern int32 chiptype; -extern const t_bool rtc_avail; -extern uint32 PCX; -extern int32 sim_switches; -extern int32 sim_quiet; -extern int32 SR; -extern UNIT cpu_unit; -extern volatile int32 stop_cpu; -extern int32 sim_interval; -extern const char *scp_error_messages[]; - -/* Debug Flags */ -static DEBTAB generic_dt[] = { - { "IN", IN_MSG }, - { "OUT", OUT_MSG }, - { "CMD", CMD_MSG }, - { "VERBOSE", VERBOSE_MSG }, - { "BUFFEREMPTY", BUFFER_EMPTY_MSG }, - { NULL, 0 } -}; - -/* SIMH pseudo device status registers */ -/* ZSDOS clock definitions */ -static time_t ClockZSDOSDelta = 0; /* delta between real clock and Altair clock */ -static int32 setClockZSDOSPos = 0; /* determines state for receiving address of parameter block */ -static int32 setClockZSDOSAdr = 0; /* address in M of 6 byte parameter block for setting time */ -static int32 getClockZSDOSPos = 0; /* determines state for sending clock information */ - -/* CPM3 clock definitions */ -static time_t ClockCPM3Delta = 0; /* delta between real clock and Altair clock */ -static int32 setClockCPM3Pos = 0; /* determines state for receiving address of parameter block */ -static int32 setClockCPM3Adr = 0; /* address in M of 5 byte parameter block for setting time */ -static int32 getClockCPM3Pos = 0; /* determines state for sending clock information */ -static int32 daysCPM3SinceOrg = 0; /* days since 1 Jan 1978 */ - -/* timer interrupt related */ -static uint32 timeOfNextInterrupt; /* time when next interrupt is scheduled */ - int32 timerInterrupt = FALSE; /* timer interrupt pending */ - int32 timerInterruptHandler = 0x0fc00; /* default address of interrupt handling routine */ -static int32 setTimerInterruptAdrPos= 0; /* determines state for receiving timerInterruptHandler */ -static int32 timerDelta = DEFAULT_TIMER_DELTA; /* interrupt every 100 ms */ -static int32 setTimerDeltaPos = 0; /* determines state for receiving timerDelta */ - -/* stop watch and timer related */ -static uint32 stopWatchDelta = 0; /* stores elapsed time of stop watch */ -static int32 getStopWatchDeltaPos = 0; /* determines the state for receiving stopWatchDelta */ -static uint32 stopWatchNow = 0; /* stores starting time of stop watch */ -static int32 markTimeSP = 0; /* stack pointer for timer stack */ - - /* default time in microseconds to sleep for SIMHSleepCmd */ -#if defined (_WIN32) -static uint32 SIMHSleep = 1000; /* Sleep uses milliseconds */ -#elif defined (__MWERKS__) && defined (macintosh) -static uint32 SIMHSleep = 0; /* no sleep on Macintosh OS9 */ -#else -static uint32 SIMHSleep = 100; /* on other platforms 100 micro seconds is good enough */ -#endif -static uint32 sleepAllowedCounter = 0; /* only sleep on no character available when == 0 */ -static uint32 sleepAllowedStart = SLEEP_ALLOWED_START_DEFAULT; /* default start for above counter */ - -/* miscellaneous */ -static int32 versionPos = 0; /* determines state for sending device identifier */ -static int32 lastCPMStatus = 0; /* result of last attachCPM command */ -static int32 lastCommand = 0; /* most recent command processed on port 0xfeh */ -static int32 getCommonPos = 0; /* determines state for sending the 'common' register */ - -/* CPU Clock Frequency related */ -static uint32 newClockFrequency; -static int32 setClockFrequencyPos = 0; /* determines state for sending the clock frequency */ -static int32 getClockFrequencyPos = 0; /* determines state for receiving the clock frequency */ - -/* support for wild card expansion */ -#if UNIX_PLATFORM -static glob_t globS; -static uint32 globPosNameList = 0; -static int32 globPosName = 0; -static int32 globValid = FALSE; -static int32 globError = 0; -#elif defined (_WIN32) -static WIN32_FIND_DATA FindFileData; -static HANDLE hFind = INVALID_HANDLE_VALUE; -static int32 globFinished = FALSE; -static int32 globValid = FALSE; -static int32 globPosName = 0; -static int32 lastPathSeparator = 0; -static int32 firstPathCharacter = 0; -#endif - -/* SIO status registers */ -static int32 warnLevelSIO = 3; /* display at most 'warnLevelSIO' times the same warning */ -static int32 warnUnattachedPTP = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE and output to PTP without an attached file */ -static int32 warnUnattachedPTR = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE and attempt to read from PTR without an attached file */ -static int32 warnPTREOF = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE and attempt to read from PTR past EOF */ -static int32 warnUnassignedPort = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE and attempt to perform IN or OUT on an unassigned PORT */ - - int32 keyboardInterrupt = FALSE; /* keyboard interrupt pending */ - uint32 keyboardInterruptHandler = 0x0038;/* address of keyboard interrupt handler */ - -static TMLN TerminalLines[TERMINALS] = { /* four terminals */ - { 0 } -}; - -static TMXR altairTMXR = { /* mux descriptor */ - TERMINALS, 0, 0, TerminalLines -}; - -static UNIT sio_unit = { - UDATA (&sio_svc, UNIT_ATTABLE | UNIT_SIO_MAP | UNIT_SIO_SLEEP, 0), - 100000, /* wait */ - FALSE, /* u3 = FALSE, no character available in buffer */ - FALSE, /* u4 = FALSE, terminal input is not attached to a file */ - 0, /* u5 = 0, not used */ - 0 /* u6 = 0, not used */ -}; - -static REG sio_reg[] = { - { DRDATA (SIOWLEV, warnLevelSIO, 32) }, - { DRDATA (WRNUPTP, warnUnattachedPTP, 32) }, - { DRDATA (WRNUPTR, warnUnattachedPTR, 32) }, - { DRDATA (WRNPTRE, warnPTREOF, 32) }, - { DRDATA (WRUPORT, warnUnassignedPort, 32) }, - { HRDATA (FILEATT, sio_unit.u4, 8), REG_RO }, /* TRUE iff terminal input is attached to a file */ - { HRDATA (TSTATUS, sio_unit.u3, 8) }, /* TRUE iff a character available in sio_unit.buf */ - { DRDATA (TBUFFER, sio_unit.buf, 8) }, /* input buffer for one character */ - { DRDATA (KEYBDI, keyboardInterrupt, 3), REG_RO }, - { HRDATA (KEYBDH, keyboardInterruptHandler, 16) }, - { NULL } -}; - -static MTAB sio_mod[] = { - { UNIT_SIO_ANSI, 0, "TTY", "TTY", NULL }, /* keep bit 8 as is for output */ - { UNIT_SIO_ANSI, UNIT_SIO_ANSI, "ANSI", "ANSI", NULL }, /* set bit 8 to 0 before output */ - { UNIT_SIO_UPPER, 0, "ALL", "ALL", NULL }, /* do not change case of input characters */ - { UNIT_SIO_UPPER, UNIT_SIO_UPPER, "UPPER", "UPPER", NULL }, /* change input characters to upper case */ - { UNIT_SIO_BS, 0, "BS", "BS", NULL }, /* map delete to backspace */ - { UNIT_SIO_BS, UNIT_SIO_BS, "DEL", "DEL", NULL }, /* map backspace to delete */ - { UNIT_SIO_VERBOSE, 0, "QUIET", "QUIET", NULL }, /* quiet, no error messages */ - { UNIT_SIO_VERBOSE, UNIT_SIO_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - /* verbose, display warning messages */ - { UNIT_SIO_MAP, 0, "NOMAP", "NOMAP", NULL }, /* disable character mapping */ - { UNIT_SIO_MAP, UNIT_SIO_MAP, "MAP", "MAP", NULL }, /* enable all character mapping */ - { UNIT_SIO_BELL, 0, "BELL", "BELL", NULL }, /* enable bell character */ - { UNIT_SIO_BELL, UNIT_SIO_BELL, "NOBELL", "NOBELL", NULL }, /* suppress ringing the bell */ - { UNIT_SIO_SLEEP, 0, "NOSLEEP", "NOSLEEP", NULL }, /* no sleep after keyboard status check */ - { UNIT_SIO_SLEEP, UNIT_SIO_SLEEP, "SLEEP", "SLEEP", NULL }, /* sleep after keyboard status check */ - /* no keyboard interrupts */ - { UNIT_SIO_INTERRUPT, 0, "NOINTERRUPT","NOINTERRUPT",&sio_dev_set_interruptoff }, - /* create keyboard interrupts */ - { UNIT_SIO_INTERRUPT, UNIT_SIO_INTERRUPT, "INTERRUPT","INTERRUPT",&sio_dev_set_interrupton }, - { MTAB_XTD|MTAB_VDV, 0, "PORT", "PORT", &sio_dev_set_port, &sio_dev_show_port }, - { 0 } -}; - -DEVICE sio_dev = { - "SIO", &sio_unit, sio_reg, sio_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &sio_reset, - NULL, &sio_attach, &sio_detach, - NULL, DEV_DEBUG, 0, - generic_dt, NULL, "Serial Input Output SIO" -}; - -static MTAB ptpptr_mod[] = { - { 0 } -}; - -static UNIT ptr_unit = { - UDATA (NULL, UNIT_ATTABLE | UNIT_ROABLE, 0) -}; - -static REG ptr_reg[] = { - { HRDATA (STAT, ptr_unit.u3, 8) }, - { NULL } -}; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, ptpptr_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - NULL, NULL, NULL, - NULL, (DEV_DISABLE | DEV_DEBUG), 0, - generic_dt, NULL, "Paper Tape Reader PTR" -}; - -static UNIT ptp_unit = { - UDATA (NULL, UNIT_ATTABLE, 0) -}; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, NULL, ptpptr_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL, - NULL, (DEV_DISABLE | DEV_DEBUG), 0, - generic_dt, NULL, "Paper Tape Puncher PTP" -}; - -/* Synthetic device SIMH for communication - between Altair and SIMH environment using port 0xfe */ -static UNIT simh_unit = { - UDATA (&simh_svc, 0, 0), KBD_POLL_WAIT -}; - -static REG simh_reg[] = { - { DRDATA (CZD, ClockZSDOSDelta, 32) }, - { DRDATA (SCZP, setClockZSDOSPos, 8), REG_RO }, - { HRDATA (SCZA, setClockZSDOSAdr, 16), REG_RO }, - { DRDATA (GCZP, getClockZSDOSPos, 8), REG_RO }, - - { DRDATA (CC3D, ClockCPM3Delta, 32) }, - { DRDATA (SC3DP, setClockCPM3Pos, 8), REG_RO }, - { HRDATA (SC3DA, setClockCPM3Adr, 16), REG_RO }, - { DRDATA (GC3DP, getClockCPM3Pos, 8), REG_RO }, - { DRDATA (D3DO, daysCPM3SinceOrg, 32), REG_RO }, - - { DRDATA (TOFNI, timeOfNextInterrupt, 32), REG_RO }, - { DRDATA (TIMI, timerInterrupt, 3) }, - { HRDATA (TIMH, timerInterruptHandler, 16) }, - { DRDATA (STIAP, setTimerInterruptAdrPos,8), REG_RO }, - { DRDATA (TIMD, timerDelta, 32) }, - { DRDATA (STDP, setTimerDeltaPos, 8), REG_RO }, - { DRDATA (SLEEP, SIMHSleep, 32) }, - { DRDATA (VOSLP, sleepAllowedStart, 32) }, - - { DRDATA (STPDT, stopWatchDelta, 32), REG_RO }, - { DRDATA (STPOS, getStopWatchDeltaPos, 8), REG_RO }, - { DRDATA (STPNW, stopWatchNow, 32), REG_RO }, - { DRDATA (MTSP, markTimeSP, 8), REG_RO }, - - { DRDATA (VPOS, versionPos, 8), REG_RO }, - { DRDATA (LCPMS, lastCPMStatus, 8), REG_RO }, - { DRDATA (LCMD, lastCommand, 8), REG_RO }, - { DRDATA (CPOS, getCommonPos, 8), REG_RO }, - { NULL } -}; - -static MTAB simh_mod[] = { - /* timer generated interrupts are off */ - { UNIT_SIMH_TIMERON, 0, "TIMEROFF", "TIMEROFF", &simh_dev_set_timeroff }, - /* timer generated interrupts are on */ - { UNIT_SIMH_TIMERON, UNIT_SIMH_TIMERON, "TIMERON", "TIMERON", &simh_dev_set_timeron }, - { 0 } -}; - -DEVICE simh_device = { - "SIMH", &simh_unit, simh_reg, simh_mod, - 1, 10, 31, 1, 16, 4, - NULL, NULL, &simh_dev_reset, - NULL, NULL, NULL, - NULL, (DEV_DISABLE | DEV_DEBUG), 0, - generic_dt, NULL, "Pseudo Device SIMH" -}; - -static void resetSIOWarningFlags(void) { - warnUnattachedPTP = warnUnattachedPTR = warnPTREOF = warnUnassignedPort = 0; -} - -static t_stat sio_attach(UNIT *uptr, char *cptr) { - t_stat r = SCPE_IERR; - sio_unit.u3 = FALSE; /* no character in terminal input buffer */ - get_uint(cptr, 10, 65535, &r); /* attempt to get port, discard result */ - if (r == SCPE_OK) { /* string can be interpreted as port number */ - sio_unit.u4 = FALSE; /* terminal input is not attached to a file */ - return tmxr_attach(&altairTMXR, uptr, cptr); /* attach mux */ - } - sio_unit.u4 = TRUE; /* terminal input is attached to a file */ - return attach_unit(uptr, cptr); -} - -static t_stat sio_detach(UNIT *uptr) { - sio_unit.u3 = FALSE; /* no character in terminal input buffer */ - if (sio_unit.u4) { /* is terminal input attached to a file? */ - sio_unit.u4 = FALSE; /* not anymore, detach */ - return detach_unit(uptr); - } - return tmxr_detach(&altairTMXR, uptr); -} - -static void pollConnection(void) { - if (sio_unit.flags & UNIT_ATT) { - int32 temp = tmxr_poll_conn(&altairTMXR); /* poll connection */ - if (temp >= 0) - TerminalLines[temp].rcve = 1; /* enable receive */ - tmxr_poll_rx(&altairTMXR); /* poll input */ - tmxr_poll_tx(&altairTMXR); /* poll output */ - } -} - -/* reset routines */ -static t_stat sio_reset(DEVICE *dptr) { - int32 i; - sim_debug(VERBOSE_MSG, &sio_dev, "SIO: " ADDRESS_FORMAT " Reset\n", PCX); - sio_unit.u3 = FALSE; /* no character in terminal input buffer */ - sio_unit.buf = 0; - resetSIOWarningFlags(); - if (sio_unit.u4) /* is terminal input attached to a file? */ - rewind(sio_unit.fileref); /* yes, rewind input */ - else if (sio_unit.flags & UNIT_ATT) - for (i = 0; i < TERMINALS; i++) - if (TerminalLines[i].conn) - tmxr_reset_ln(&TerminalLines[i]); - mapAltairPorts(); - return SCPE_OK; -} - -static t_stat ptr_reset(DEVICE *dptr) { - sim_debug(VERBOSE_MSG, &ptr_dev, "PTR: " ADDRESS_FORMAT " Reset\n", PCX); - resetSIOWarningFlags(); - ptr_unit.u3 = FALSE; /* End Of File not yet reached */ - ptr_unit.buf = 0; - if (ptr_unit.flags & UNIT_ATT) /* attached? */ - rewind(ptr_unit.fileref); - sim_map_resource(0x12, 1, RESOURCE_TYPE_IO, &sio1s, dptr->flags & DEV_DIS); - sim_map_resource(0x13, 1, RESOURCE_TYPE_IO, &sio1d, dptr->flags & DEV_DIS); - return SCPE_OK; -} - -static t_stat ptp_reset(DEVICE *dptr) { - sim_debug(VERBOSE_MSG, &ptp_dev, "PTP: " ADDRESS_FORMAT " Reset\n", PCX); - resetSIOWarningFlags(); - sim_map_resource(0x12, 1, RESOURCE_TYPE_IO, &sio1s, dptr->flags & DEV_DIS); - sim_map_resource(0x13, 1, RESOURCE_TYPE_IO, &sio1d, dptr->flags & DEV_DIS); - return SCPE_OK; -} - -static int32 mapCharacter(int32 ch) { - ch &= 0xff; - if (sio_unit.flags & UNIT_SIO_MAP) { - if (sio_unit.flags & UNIT_SIO_BS) { - if (ch == BACKSPACE_CHAR) - return DELETE_CHAR; - } - else if (ch == DELETE_CHAR) - return BACKSPACE_CHAR; - if (sio_unit.flags & UNIT_SIO_UPPER) - return toupper(ch); - } - return ch; -} - -/* 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. - - Port 1 controls console I/O. We distinguish three cases: - 1) SIO attached to a file (i.e. input taken from a file ) - 2) SIO attached to a port (i.e. Telnet console I/O ) - 3) SIO not attached to a port (i.e. "regular" console I/O ) -*/ - -typedef struct { - int32 port; /* this information belongs to port number 'port' */ - int32 terminalLine; /* map to this 'terminalLine' */ - int32 sio_can_read; /* bit mask to indicate that one can read from this port */ - int32 sio_cannot_read; /* bit mask to indicate that one cannot read from this port */ - int32 sio_can_write; /* bit mask to indicate that one can write to this port */ - int32 hasReset; /* TRUE iff SIO has reset command */ - int32 sio_reset; /* reset command */ - int32 hasOUT; /* TRUE iff port supports OUT command */ - int32 isBuiltin; /* TRUE iff mapping is built in */ -} SIO_PORT_INFO; - -static SIO_PORT_INFO port_table[PORT_TABLE_SIZE] = { - {0x00, 0, KBD_HAS_CHAR, KBD_HAS_NO_CHAR, SIO_CAN_WRITE, FALSE, 0, FALSE, TRUE }, - {0x01, 0, 0, 0, 0, FALSE, 0, FALSE, TRUE }, - {0x02, 0, VGSIO_CAN_READ, 0, VGSIO_CAN_WRITE, FALSE, 0, TRUE, TRUE }, - {0x03, 0, VGSIO_CAN_READ, 0, VGSIO_CAN_WRITE, FALSE, 0, FALSE, TRUE }, - {0x10, 0, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, - {0x11, 0, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, - {0x14, 1, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, - {0x15, 1, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, - {0x16, 2, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, - {0x17, 2, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, - {0x18, 3, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, FALSE, TRUE }, - {0x19, 3, SIO_CAN_READ, 0, SIO_CAN_WRITE, TRUE, SIO_RESET, TRUE, TRUE }, - - /* CompuPro System Support 1 Board */ - {0x5c, 0, 0x0, 0, 0, FALSE,0, TRUE, TRUE }, - {0x5d, 0, 0xC2, 0, 0xC5, FALSE,0, FALSE, TRUE }, - - /* CompuPro Interfacer 3 (IF3) Board 0 */ - {0x300, 1, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x301, 1, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x302, 2, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x303, 2, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x304, 3, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x305, 3, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x306, 4, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x307, 4, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x308, 5, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x309, 5, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x30a, 6, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x30b, 6, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x30c, 7, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x30d, 7, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x30e, 8, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x30f, 8, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - /* CompuPro Interfacer 3 (IF3) Board 1 */ - {0x310, 9, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x311, 9, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x312, 10, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x313, 10, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x314, 11, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x315, 11, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x316, 12, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x317, 12, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x318, 13, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x319, 13, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x31a, 14, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x31b, 14, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x31c, 15, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x31d, 15, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x31e, 16, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x31f, 16, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - /* CompuPro Interfacer 3 (IF3) Board 2 */ - {0x320, 17, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x321, 17, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x322, 18, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x323, 18, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x324, 19, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x325, 19, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x326, 20, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x327, 20, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x328, 21, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x329, 21, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x32a, 22, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x32b, 22, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x32c, 23, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x32d, 23, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x32e, 24, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x32f, 24, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - /* CompuPro Interfacer 3 (IF3) Board 3 */ - {0x330, 25, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x331, 25, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x332, 26, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x333, 26, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x334, 27, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x335, 27, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x336, 28, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x337, 28, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x338, 29, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x339, 29, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x33a, 30, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x33b, 30, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x33c, 31, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x33d, 31, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {0x33e, 32, 0x0, 0, 0, TRUE, SIO_RESET, TRUE, TRUE }, - {0x33f, 32, 0xC2, 0, 0xC5, TRUE, SIO_RESET, FALSE, TRUE }, - {-1, 0, 0, 0, 0, 0, 0, 0, 0} /* must be last */ -}; - -static SIO_PORT_INFO lookupPortInfo(const int32 port, int32 *position) { - int32 i = 0; - while ((port_table[i].port != -1) && (port_table[i].port != port)) - i++; - *position = i; - return port_table[i]; -} - -/* keyboard idle detection: sleep when feature enabled, no character available - (duty of caller) and operation not voided (e.g. when output is available) */ -static void checkSleep(void) { - if (sio_unit.flags & UNIT_SIO_SLEEP) { - if (sleepAllowedCounter) - sleepAllowedCounter--; - else - do_SIMH_sleep(); - } -} - -/* void sleep for next 'sleepAllowedStart' tests */ -static void voidSleep(void) { - sleepAllowedCounter = sleepAllowedStart; -} - -/* generic status port for keyboard input / terminal output */ -static int32 sio0sCore(const int32 port, const int32 io, const int32 data) { - int32 ch, result; - const SIO_PORT_INFO spi = lookupPortInfo(port, &ch); - assert(spi.port == port); - pollConnection(); - if (io == 0) { /* IN */ - if (sio_unit.u4) { /* attached to a file? */ - if (sio_unit.u3) /* character available? */ - return spi.sio_can_read | spi.sio_can_write; - ch = getc(sio_unit.fileref); - if (ch == EOF) { - sio_detach(&sio_unit); /* detach file and switch to keyboard input */ - return spi.sio_cannot_read | spi.sio_can_write; - } - else { - sio_unit.u3 = TRUE; /* indicate character available */ - sio_unit.buf = ch; /* store character in buffer */ - return spi.sio_can_read | spi.sio_can_write; - } - } - if (sio_unit.flags & UNIT_ATT) { /* attached to a port? */ - if (tmxr_rqln(&TerminalLines[spi.terminalLine])) - result = spi.sio_can_read; - else { - result = spi.sio_cannot_read; - checkSleep(); - } - return result | /* read possible if character available */ - (TerminalLines[spi.terminalLine].conn && TerminalLines[spi.terminalLine].xmte ? spi.sio_can_write : 0x00); - /* write possible if connected and transmit - enabled */ - } - if (sio_unit.u3) /* character available? */ - return spi.sio_can_read | spi.sio_can_write; - ch = sim_poll_kbd(); /* no, try to get a character */ - if (ch) { /* character available? */ - if (ch == SCPE_STOP) { /* stop CPU in case ^E (default) was typed */ - stop_cpu = TRUE; - sim_interval = 0; /* detect stop condition as soon as possible*/ - return spi.sio_cannot_read | spi.sio_can_write; /* do not consume stop character */ - } - sio_unit.u3 = TRUE; /* indicate character available */ - sio_unit.buf = ch; /* store character in buffer */ - return spi.sio_can_read | spi.sio_can_write; - } - checkSleep(); - return spi.sio_cannot_read | spi.sio_can_write; - } /* OUT follows, no fall-through from IN */ - if (spi.hasReset && (data == spi.sio_reset)) { /* reset command */ - if (!sio_unit.u4) /* only reset for regular console I/O */ - sio_unit.u3 = FALSE; /* indicate that no character is available */ - sim_debug(CMD_MSG, &sio_dev, "\tSIO_S: " ADDRESS_FORMAT - " Command OUT(0x%03x) = 0x%02x\n", PCX, port, data); - } - return 0x00; /* ignored since OUT */ -} - -int32 sio0s(const int32 port, const int32 io, const int32 data) { - const int32 result = sio0sCore(port, io, data); - if (io == 0) - sim_debug(IN_MSG, &sio_dev, "\tSIO_S: " ADDRESS_FORMAT - " IN(0x%03x) = 0x%02x\n", PCX, port, result); - else if (io) - sim_debug(OUT_MSG, &sio_dev, "\tSIO_S: " ADDRESS_FORMAT - " OUT(0x%03x) = 0x%02x\n", PCX, port, data); - return result; -} - -/* generic data port for keyboard input / terminal output */ -static int32 sio0dCore(const int32 port, const int32 io, const int32 data) { - int32 ch; - const SIO_PORT_INFO spi = lookupPortInfo(port, &ch); - assert(spi.port == port); - pollConnection(); - if (io == 0) { /* IN */ - if ((sio_unit.flags & UNIT_ATT) && (!sio_unit.u4)) - return mapCharacter(tmxr_getc_ln(&TerminalLines[spi.terminalLine])); - if (!sio_unit.u3) - sim_debug(BUFFER_EMPTY_MSG, &sio_dev, "\tSIO_D: " ADDRESS_FORMAT - " IN(0x%03x) for empty character buffer\n", PCX, port); - sio_unit.u3 = FALSE; /* no character is available any more */ - return mapCharacter(sio_unit.buf); /* return previous character */ - } /* OUT follows, no fall-through from IN */ - if (spi.hasOUT) { - ch = sio_unit.flags & UNIT_SIO_ANSI ? data & 0x7f : data; /* clear highest bit in ANSI mode */ - if ((ch != CONTROLG_CHAR) || !(sio_unit.flags & UNIT_SIO_BELL)) { - voidSleep(); - if ((sio_unit.flags & UNIT_ATT) && (!sio_unit.u4)) /* attached to a port and not to a file */ - tmxr_putc_ln(&TerminalLines[spi.terminalLine], ch); /* status ignored */ - else - sim_putchar(ch); - } - } - return 0x00; /* ignored since OUT */ -} - -static char* printable(char* result, int32 data, const int32 isIn) { - result[0] = 0; - data &= 0x7f; - if ((0x20 <= data) && (data < 0x7f)) - sprintf(result, isIn ? " <-\"%c\"" : " ->\"%c\"", data); - return result; -} - -int32 sio0d(const int32 port, const int32 io, const int32 data) { - char buffer[8]; - const int32 result = sio0dCore(port, io, data); - if (io == 0) - sim_debug(IN_MSG, &sio_dev, "\tSIO_D: " ADDRESS_FORMAT - " IN(0x%03x) = 0x%02x%s\n", PCX, port, result, printable(buffer, result, TRUE)); - else if (io) - sim_debug(OUT_MSG, &sio_dev, "\tSIO_D: " ADDRESS_FORMAT - " OUT(0x%03x) = 0x%02x%s\n", PCX, port, data, printable(buffer, data, FALSE)); - return result; -} - -/* PTR/PTP status port */ -static int32 sio1sCore(const int32 port, const int32 io, const int32 data) { - if (io == 0) { /* IN */ - /* reset I bit iff PTR unit not attached or - no more data available. O bit is always - set since write always possible. */ - if ((ptr_unit.flags & UNIT_ATT) == 0) { /* PTR is not attached */ - if ((ptr_dev.dctrl & VERBOSE_MSG) && (warnUnattachedPTR < warnLevelSIO)) { - warnUnattachedPTR++; -/*06*/ sim_debug(VERBOSE_MSG, &ptr_dev, "PTR: " ADDRESS_FORMAT - " Attempt to test status of unattached PTR[0x%02x]. 0x02 returned.\n", PCX, port); - } - return SIO_CAN_WRITE; - } - /* if EOF then SIO_CAN_WRITE else - (SIO_CAN_WRITE and SIO_CAN_READ) */ - return ptr_unit.u3 ? SIO_CAN_WRITE : (SIO_CAN_READ | SIO_CAN_WRITE); - } /* OUT follows */ - if (data == SIO_RESET) { - ptr_unit.u3 = FALSE; /* reset EOF indicator */ - sim_debug(CMD_MSG, &ptr_dev, "PTR: " ADDRESS_FORMAT - " Command OUT(0x%03x) = 0x%02x\n", PCX, port, data); - } - return 0x00; /* ignored since OUT */ -} - -int32 sio1s(const int32 port, const int32 io, const int32 data) { - const int32 result = sio1sCore(port, io, data); - if (io == 0) { - sim_debug(IN_MSG, &ptr_dev, "PTR_S: " ADDRESS_FORMAT - " IN(0x%02x) = 0x%02x\n", PCX, port, result); - sim_debug(IN_MSG, &ptp_dev, "PTP_S: " ADDRESS_FORMAT - " IN(0x%02x) = 0x%02x\n", PCX, port, result); - } - else if (io) { - sim_debug(OUT_MSG, &ptr_dev, "PTR_S: " ADDRESS_FORMAT - " OUT(0x%02x) = 0x%02x\n", PCX, port, data); - sim_debug(OUT_MSG, &ptp_dev, "PTP_S: " ADDRESS_FORMAT - " OUT(0x%02x) = 0x%02x\n", PCX, port, data); - } - return result; -} - -/* PTR/PTP data port */ -static int32 sio1dCore(const int32 port, const int32 io, const int32 data) { - int32 ch; - if (io == 0) { /* IN */ - if (ptr_unit.u3) { /* EOF reached, no more data available */ - if ((ptr_dev.dctrl & VERBOSE_MSG) && (warnPTREOF < warnLevelSIO)) { - warnPTREOF++; -/*07*/ sim_debug(VERBOSE_MSG, &ptr_dev, "PTR: " ADDRESS_FORMAT - " PTR[0x%02x] attempted to read past EOF. 0x00 returned.\n", PCX, port); - } - return 0x00; - } - if ((ptr_unit.flags & UNIT_ATT) == 0) { /* not attached */ - if ((ptr_dev.dctrl & VERBOSE_MSG) && (warnUnattachedPTR < warnLevelSIO)) { - warnUnattachedPTR++; -/*08*/ sim_debug(VERBOSE_MSG, &ptr_dev, "PTR: " ADDRESS_FORMAT - " Attempt to read from unattached PTR[0x%02x]. 0x00 returned.\n", PCX, port); - } - return 0x00; - } - if ((ch = getc(ptr_unit.fileref)) == EOF) { /* end of file? */ - ptr_unit.u3 = TRUE; /* remember EOF reached */ - return CONTROLZ_CHAR; /* ^Z denotes end of text file in CP/M */ - } - return ch & 0xff; - } /* OUT follows */ - if (ptp_unit.flags & UNIT_ATT) /* unit must be attached */ - putc(data, ptp_unit.fileref); - /* else ignore data */ - else if ((ptp_dev.dctrl & VERBOSE_MSG) && (warnUnattachedPTP < warnLevelSIO)) { - warnUnattachedPTP++; -/*09*/ sim_debug(VERBOSE_MSG, &ptp_dev, "PTP: " ADDRESS_FORMAT - " Attempt to output '0x%02x' to unattached PTP[0x%02x] - ignored.\n", PCX, data, port); - } - return 0x00; /* ignored since OUT */ -} - -int32 sio1d(const int32 port, const int32 io, const int32 data) { - const int32 result = sio1dCore(port, io, data); - if (io == 0) { - sim_debug(IN_MSG, &ptr_dev, "PTR_D: " ADDRESS_FORMAT - " IN(0x%02x) = 0x%02x\n", PCX, port, result); - sim_debug(IN_MSG, &ptp_dev, "PTP_D: " ADDRESS_FORMAT - " IN(0x%02x) = 0x%02x\n", PCX, port, result); - } - else if (io) { - sim_debug(OUT_MSG, &ptr_dev, "PTR_D: " ADDRESS_FORMAT - " OUT(0x%02x) = 0x%02x\n", PCX, port, data); - sim_debug(OUT_MSG, &ptp_dev, "PTP_D: " ADDRESS_FORMAT - " OUT(0x%02x) = 0x%02x\n", PCX, port, data); - } - return result; -} - -static t_stat toBool(char tf, int32 *result) { - if (tf == 'T') { - *result = TRUE; - return SCPE_OK; - } - if (tf == 'F') { - *result = FALSE; - return SCPE_OK; - } - return SCPE_ARG; -} - -static void show_sio_port_info(FILE *st, SIO_PORT_INFO sip) { - if (sio_unit.flags & UNIT_SIO_VERBOSE) - fprintf(st, "(Port=%02x/Terminal=%1i/Read=0x%02x/NotRead=0x%02x/" - "Write=0x%02x/Reset?=%s/Reset=0x%02x/Data?=%s)", - sip.port, sip.terminalLine, sip.sio_can_read, sip.sio_cannot_read, - sip.sio_can_write, sip.hasReset ? "True" : "False", sip.sio_reset, - sip.hasOUT ? "True" : "False"); - else - fprintf(st, "(%02x/%1i/%02x/%02x/%02x/%s/%02x/%s)", - sip.port, sip.terminalLine, sip.sio_can_read, sip.sio_cannot_read, - sip.sio_can_write, sip.hasReset ? "T" : "F", sip.sio_reset, - sip.hasOUT ? "T" : "F"); -} - -static uint32 equalSIP(SIO_PORT_INFO x, SIO_PORT_INFO y) { - /* isBuiltin is not relevant for equality, only for display */ - return (x.port == y.port) && (x.terminalLine == y.terminalLine) && - (x.sio_can_read == y.sio_can_read) && (x.sio_cannot_read == y.sio_cannot_read) && - (x.sio_can_write == y.sio_can_write) && (x.hasReset == y.hasReset) && - (x.sio_reset == y.sio_reset) && (x.hasOUT == y.hasOUT); -} - -static t_stat sio_dev_set_port(UNIT *uptr, int32 value, char *cptr, void *desc) { - int32 result, n, position; - SIO_PORT_INFO sip = { 0 }, old; - char hasReset, hasOUT; - if (cptr == NULL) - return SCPE_ARG; - result = sscanf(cptr, "%x%n", &sip.port, &n); - if ((result == 1) && (cptr[n] == 0)) { - old = lookupPortInfo(sip.port, &position); - if (old.port == -1) { - printf("No mapping for port 0x%02x exists - cannot remove.\n", sip.port); - return SCPE_ARG; - } - do { - port_table[position] = port_table[position + 1]; - position++; - } while (port_table[position].port != -1); - sim_map_resource(sip.port, 1, RESOURCE_TYPE_IO, &nulldev, FALSE); - if (sio_unit.flags & UNIT_SIO_VERBOSE) { - printf("Removing mapping for port 0x%02x.\n\t", sip.port); - show_sio_port_info(stdout, old); - } - return SCPE_OK; - } - result = sscanf(cptr, "%x/%d/%x/%x/%x/%1c/%x/%1c%n", &sip.port, - &sip.terminalLine, &sip.sio_can_read, &sip.sio_cannot_read, - &sip.sio_can_write, &hasReset, &sip.sio_reset, &hasOUT, &n); - if ((result != 8) || (result == EOF) || (cptr[n] != 0)) - return SCPE_ARG; - result = toBool(hasReset, &sip.hasReset); - if (result != SCPE_OK) - return result; - result = toBool(hasOUT, &sip.hasOUT); - if (result != SCPE_OK) - return result; - if (sip.port != (sip.port & 0xff)) { - printf("Truncating port 0x%x to 0x%02x.\n", sip.port, sip.port & 0xff); - sip.port &= 0xff; - } - old = lookupPortInfo(sip.port, &position); - if (old.port == sip.port) { - if (sio_unit.flags & UNIT_SIO_VERBOSE) { - printf("Replacing mapping for port 0x%02x.\n\t", sip.port); - show_sio_port_info(stdout, old); - printf("-> "); - show_sio_port_info(stdout, sip); - if (equalSIP(sip, old)) - printf("[identical]"); - } - } - else { - port_table[position + 1] = old; - if (sio_unit.flags & UNIT_SIO_VERBOSE) { - printf("Adding mapping for port 0x%02x.\n\t", sip.port); - show_sio_port_info(stdout, sip); - } - } - if (sio_unit.flags & UNIT_SIO_VERBOSE) - printf("\n"); - port_table[position] = sip; - sim_map_resource(sip.port, 1, RESOURCE_TYPE_IO, (sip.hasOUT || - ((sip.sio_can_read == 0) && (sip.sio_cannot_read == 0) && - (sip.sio_can_write == 0))) ? &sio0d : &sio0s, FALSE); - return SCPE_OK; -} - -static t_stat sio_dev_show_port(FILE *st, UNIT *uptr, int32 val, void *desc) { - int32 i, first = TRUE; - for (i = 0; port_table[i].port != -1; i++) - if (!port_table[i].isBuiltin) { - if (first) - first = FALSE; - else - fprintf(st, " "); - show_sio_port_info(st, port_table[i]); - } - if (first) - fprintf(st, "no extra port"); - return SCPE_OK; -} - -static t_stat sio_dev_set_interrupton(UNIT *uptr, int32 value, char *cptr, void *desc) { - keyboardInterrupt = FALSE; - return sim_activate(&sio_unit, sio_unit.wait); /* activate unit */ -} - -static t_stat sio_dev_set_interruptoff(UNIT *uptr, int32 value, char *cptr, void *desc) { - keyboardInterrupt = FALSE; - sim_cancel(&sio_unit); - return SCPE_OK; -} - -static t_stat sio_svc(UNIT *uptr) { - if (sio0s(0, 0, 0) & KBD_HAS_CHAR) - keyboardInterrupt = TRUE; - if (sio_unit.flags & UNIT_SIO_INTERRUPT) - sim_activate(&sio_unit, sio_unit.wait); /* activate unit */ - return SCPE_OK; -} - -static void mapAltairPorts(void) { - int32 i = 0; - SIO_PORT_INFO spi; - do { - spi = port_table[i++]; - if ((0x02 <= spi.port) && (spi.port <= 0x19)) - sim_map_resource(spi.port, 1, RESOURCE_TYPE_IO, spi.hasOUT ? &sio0d : &sio0s, FALSE); - } while (spi.port >= 0); -} - -int32 nulldev(const int32 port, const int32 io, const int32 data) { - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnassignedPort < warnLevelSIO)) { - warnUnassignedPort++; - if (io == 0) - sim_debug(VERBOSE_MSG, &sio_dev, "SIO: " ADDRESS_FORMAT - " Attempt to input from unassigned port 0x%04x - ignored.\n", - PCX, port); - else - sim_debug(VERBOSE_MSG, &sio_dev, "SIO: " ADDRESS_FORMAT - " Attempt to output 0x%02x to unassigned port 0x%04x - ignored.\n", - PCX, data, port); - } - return io == 0 ? 0xff : 0; -} - -int32 sr_dev(const int32 port, const int32 io, const int32 data) { - return io == 0 ? SR : 0; -} - -static int32 toBCD(const int32 x) { - return (x / 10) * 16 + (x % 10); -} - -static int32 fromBCD(const int32 x) { - return 10 * ((0xf0 & x) >> 4) + (0x0f & x); -} - -/* Z80 or 8080 programs communicate with the SIMH pseudo device via port 0xfe. - The following principles apply: - - 1) For commands that do not require parameters and do not return results - ld a, - out (0feh),a - Special case is the reset command which needs to be send 128 times to make - sure that the internal state is properly reset. - - 2) For commands that require parameters and do not return results - ld a, - out (0feh),a - ld a, - out (0feh),a - ld a, - out (0feh),a - ... - Note: The calling program must send all parameter bytes. Otherwise - the pseudo device is left in an undefined state. - - 3) For commands that do not require parameters and return results - ld a, - out (0feh),a - in a,(0feh) ; contains first byte of result - in a,(0feh) ; contains second byte of result - ... - Note: The calling program must request all bytes of the result. Otherwise - the pseudo device is left in an undefined state. - - 4) For commands that do require parameters and return results - ld a, - out (0feh),a - ld a, - out (0feh),a - ld a, - out (0feh),a - ... ; send all parameters - in a,(0feh) ; contains first byte of result - in a,(0feh) ; contains second byte of result - ... - -*/ - -enum simhPseudoDeviceCommands { /* do not change order or remove commands, add only at the end */ - printTimeCmd, /* 0 print the current time in milliseconds */ - startTimerCmd, /* 1 start a new timer on the top of the timer stack */ - stopTimerCmd, /* 2 stop timer on top of timer stack and show time difference */ - resetPTRCmd, /* 3 reset the PTR device */ - attachPTRCmd, /* 4 attach the PTR device */ - detachPTRCmd, /* 5 detach the PTR device */ - getSIMHVersionCmd, /* 6 get the current version of the SIMH pseudo device */ - getClockZSDOSCmd, /* 7 get the current time in ZSDOS format */ - setClockZSDOSCmd, /* 8 set the current time in ZSDOS format */ - getClockCPM3Cmd, /* 9 get the current time in CP/M 3 format */ - setClockCPM3Cmd, /* 10 set the current time in CP/M 3 format */ - getBankSelectCmd, /* 11 get the selected bank */ - setBankSelectCmd, /* 12 set the selected bank */ - getCommonCmd, /* 13 get the base address of the common memory segment */ - resetSIMHInterfaceCmd, /* 14 reset the SIMH pseudo device */ - showTimerCmd, /* 15 show time difference to timer on top of stack */ - attachPTPCmd, /* 16 attach PTP to the file with name at beginning of CP/M command line*/ - detachPTPCmd, /* 17 detach PTP */ - hasBankedMemoryCmd, /* 18 determines whether machine has banked memory */ - setZ80CPUCmd, /* 19 set the CPU to a Z80 */ - set8080CPUCmd, /* 20 set the CPU to an 8080 */ - startTimerInterruptsCmd, /* 21 start timer interrupts */ - stopTimerInterruptsCmd, /* 22 stop timer interrupts */ - setTimerDeltaCmd, /* 23 set the timer interval in which interrupts occur */ - setTimerInterruptAdrCmd, /* 24 set the address to call by timer interrupts */ - resetStopWatchCmd, /* 25 reset the millisecond stop watch */ - readStopWatchCmd, /* 26 read the millisecond stop watch */ - SIMHSleepCmd, /* 27 let SIMH sleep for SIMHSleep microseconds */ - getHostOSPathSeparatorCmd, /* 28 obtain the file path separator of the OS under which SIMH runs */ - getHostFilenamesCmd, /* 29 perform wildcard expansion and obtain list of file names */ - readURLCmd, /* 30 read the contents of an URL */ - getCPUClockFrequency, /* 31 get the clock frequency of the CPU */ - setCPUClockFrequency, /* 32 set the clock frequency of the CPU */ - kSimhPseudoDeviceCommands -}; - -static char *cmdNames[kSimhPseudoDeviceCommands] = { - "printTime", - "startTimer", - "stopTimer", - "resetPTR", - "attachPTR", - "detachPTR", - "getSIMHVersion", - "getClockZSDOS", - "setClockZSDOS", - "getClockCPM3", - "setClockCPM3", - "getBankSelect", - "setBankSelect", - "getCommon", - "resetSIMHInterface", - "showTimer", - "attachPTP", - "detachPTP", - "hasBankedMemory", - "setZ80CPU", - "set8080CPU", - "startTimerInterrupts", - "stopTimerInterrupts", - "setTimerDelta", - "setTimerInterruptAdr", - "resetStopWatch", - "readStopWatch", - "SIMHSleep", - "getHostOSPathSeparator", - "getHostFilenames", - "readURL", - "getCPUClockFrequency", - "setCPUClockFrequency", -}; - -#define CPM_COMMAND_LINE_LENGTH 128 -#define TIMER_STACK_LIMIT 10 /* stack depth of timer stack */ -static uint32 markTime[TIMER_STACK_LIMIT]; /* timer stack */ -static struct tm currentTime; -static int32 currentTimeValid = FALSE; -static char version[] = "SIMH004"; - -#define URL_MAX_LENGTH 1024 -static uint32 urlPointer; -static char urlStore[URL_MAX_LENGTH]; -static uint8 *urlResult = NULL; -static uint32 resultLength; -static uint32 resultPointer; -static int32 showAvailability; -static int32 isInReadPhase; - -static t_stat simh_dev_reset(DEVICE *dptr) { - sim_map_resource(0xfe, 1, RESOURCE_TYPE_IO, &simh_dev, dptr->flags & DEV_DIS); - currentTimeValid = FALSE; - ClockZSDOSDelta = 0; - setClockZSDOSPos = 0; - getClockZSDOSPos = 0; - ClockCPM3Delta = 0; - setClockCPM3Pos = 0; - getClockCPM3Pos = 0; - getStopWatchDeltaPos = 0; - getCommonPos = 0; - setTimerDeltaPos = 0; - setTimerInterruptAdrPos = 0; - markTimeSP = 0; - versionPos = 0; - lastCommand = 0; - lastCPMStatus = SCPE_OK; - timerInterrupt = FALSE; - urlPointer = 0; - getClockFrequencyPos = 0; - setClockFrequencyPos = 0; - if (urlResult != NULL) { - free(urlResult); - urlResult = NULL; - } - if (simh_unit.flags & UNIT_SIMH_TIMERON) - simh_dev_set_timeron(NULL, 0, NULL, NULL); - return SCPE_OK; -} - -static void warnNoRealTimeClock(void) { - sim_debug(VERBOSE_MSG, &simh_device, "SIMH: " ADDRESS_FORMAT - " Sorry - no real time clock available.\n", PCX); -} - -static t_stat simh_dev_set_timeron(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (rtc_avail) { - timeOfNextInterrupt = sim_os_msec() + timerDelta; - return sim_activate(&simh_unit, simh_unit.wait); /* activate unit */ - } - warnNoRealTimeClock(); - return SCPE_ARG; -} - -static t_stat simh_dev_set_timeroff(UNIT *uptr, int32 value, char *cptr, void *desc) { - timerInterrupt = FALSE; - if (rtc_avail) - sim_cancel(&simh_unit); - return SCPE_OK; -} - -static t_stat simh_svc(UNIT *uptr) { - uint32 now = sim_os_msec(); - if (now >= timeOfNextInterrupt) { - timerInterrupt = TRUE; - if (timerDelta == 0) - timeOfNextInterrupt = now + DEFAULT_TIMER_DELTA; - else { - uint32 newTimeOfNextInterrupt = now + timerDelta - (now - timeOfNextInterrupt) % timerDelta; - if (newTimeOfNextInterrupt != timeOfNextInterrupt + timerDelta) { - sim_debug(VERBOSE_MSG, &simh_device, "SIMH: " ADDRESS_FORMAT - " Timer interrupts skipped %i. Delta %i. Expect %i. Got %i.\n", - PCX, (newTimeOfNextInterrupt - timeOfNextInterrupt) / timerDelta - 1, - timerDelta, timeOfNextInterrupt + timerDelta - now, - newTimeOfNextInterrupt - now); - } - timeOfNextInterrupt = newTimeOfNextInterrupt; - } - } - /* post condition: now < timeOfNextInterrupt */ - if (simh_unit.flags & UNIT_SIMH_TIMERON) - sim_activate(&simh_unit, simh_unit.wait); /* activate unit */ - return SCPE_OK; -} - -static char cpmCommandLine[CPM_COMMAND_LINE_LENGTH]; -static void createCPMCommandLine(void) { - int32 i, len = (GetBYTEWrapper(0x80) & 0x7f); /* 0x80 contains length of command line, discard first char */ - for (i = 0; i < len - 1; i++) - cpmCommandLine[i] = (char)GetBYTEWrapper(0x82 + i); /* the first char, typically ' ', is discarded */ - cpmCommandLine[i] = 0; /* make C string */ -} - -#if defined (_WIN32) -static void setLastPathSeparator(void) { - int32 i = 0; - while (cpmCommandLine[i]) - i++; - while ((i >= 0) && (cpmCommandLine[i] != '\\')) - i--; - lastPathSeparator = i; - firstPathCharacter = 0; -} -#endif - -/* The CP/M command line is used as the name of a file and UNIT* uptr is attached to it. */ -static void attachCPM(UNIT *uptr) { - createCPMCommandLine(); - if (uptr == &ptr_unit) - sim_switches = SWMASK('R') | SWMASK('Q'); - else if (uptr == &ptp_unit) - sim_switches = SWMASK('W') | SWMASK('C') | SWMASK('Q'); - /* 'C' option makes sure that file is properly truncated if it had existed before */ - sim_quiet = sim_switches & SWMASK ('Q'); /* -q means quiet */ - lastCPMStatus = attach_unit(uptr, cpmCommandLine); - if (lastCPMStatus != SCPE_OK) - sim_debug(VERBOSE_MSG, &simh_device, "SIMH: " ADDRESS_FORMAT - " Cannot open '%s' (%s).\n", PCX, cpmCommandLine, - scp_error_messages[lastCPMStatus - SCPE_BASE]); -} - -/* setClockZSDOSAdr points to 6 byte block in M: YY MM DD HH MM SS in BCD notation */ -static void setClockZSDOS(void) { - struct tm newTime; - int32 year = fromBCD(GetBYTEWrapper(setClockZSDOSAdr)); - newTime.tm_year = year < 50 ? year + 100 : year; - newTime.tm_mon = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 1)) - 1; - newTime.tm_mday = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 2)); - newTime.tm_hour = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 3)); - newTime.tm_min = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 4)); - newTime.tm_sec = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 5)); - ClockZSDOSDelta = mktime(&newTime) - time(NULL); -} - -#define SECONDS_PER_MINUTE 60 -#define SECONDS_PER_HOUR (60 * SECONDS_PER_MINUTE) -#define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR) -static time_t mkCPM3Origin(void) { - struct tm date; - date.tm_year = 77; - date.tm_mon = 11; - date.tm_mday = 31; - date.tm_hour = 0; - date.tm_min = 0; - date.tm_sec = 0; - return mktime(&date); -} - -/* setClockCPM3Adr points to 5 byte block in M: - 0 - 1 int16: days since 31 Dec 77 - 2 BCD byte: HH - 3 BCD byte: MM - 4 BCD byte: SS */ -static void setClockCPM3(void) { - ClockCPM3Delta = mkCPM3Origin() + - (GetBYTEWrapper(setClockCPM3Adr) + GetBYTEWrapper(setClockCPM3Adr + 1) * 256) * SECONDS_PER_DAY + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 2)) * SECONDS_PER_HOUR + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 3)) * SECONDS_PER_MINUTE + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 4)) - time(NULL); -} - -static int32 simh_in(const int32 port) { - int32 result = 0; - switch(lastCommand) { - case readURLCmd: - if (isInReadPhase) { - if (showAvailability) { - if (resultPointer < resultLength) - result = 1; - else { - if (urlResult != NULL) - free(urlResult); - urlResult = NULL; - lastCommand = 0; - } - } - else if (resultPointer < resultLength) - result = urlResult[resultPointer++]; - showAvailability = 1 - showAvailability; - } - else - lastCommand = 0; - break; - - case getHostFilenamesCmd: -#if UNIX_PLATFORM - if (globValid) { - if (globPosNameList < globS.gl_pathc) { - if (!(result = globS.gl_pathv[globPosNameList][globPosName++])) { - globPosNameList++; - globPosName = 0; - } - } - else { - globValid = FALSE; - lastCommand = 0; - globfree(&globS); - } - } -#elif defined (_WIN32) - if (globValid) - if (globFinished) - globValid = FALSE; - else if (firstPathCharacter <= lastPathSeparator) - result = cpmCommandLine[firstPathCharacter++]; - else if (!(result = FindFileData.cFileName[globPosName++])) { - globPosName = firstPathCharacter = 0; - if (!FindNextFile(hFind, &FindFileData)) { - globFinished = TRUE; - FindClose(hFind); - hFind = INVALID_HANDLE_VALUE; - } - } -#else - lastCommand = 0; -#endif - break; - - case attachPTRCmd: - - case attachPTPCmd: - result = lastCPMStatus; - lastCommand = 0; - break; - - case getClockZSDOSCmd: - if (currentTimeValid) - switch(getClockZSDOSPos) { - - case 0: - result = toBCD(currentTime.tm_year > 99 ? - currentTime.tm_year - 100 : currentTime.tm_year); - getClockZSDOSPos = 1; - break; - - case 1: - result = toBCD(currentTime.tm_mon + 1); - getClockZSDOSPos = 2; - break; - - case 2: - result = toBCD(currentTime.tm_mday); - getClockZSDOSPos = 3; - break; - - case 3: - result = toBCD(currentTime.tm_hour); - getClockZSDOSPos = 4; - break; - - case 4: - result = toBCD(currentTime.tm_min); - getClockZSDOSPos = 5; - break; - - case 5: - result = toBCD(currentTime.tm_sec); - getClockZSDOSPos = lastCommand = 0; - break; - } - else - result = getClockZSDOSPos = lastCommand = 0; - break; - - case getClockCPM3Cmd: - if (currentTimeValid) - switch(getClockCPM3Pos) { - case 0: - result = daysCPM3SinceOrg & 0xff; - getClockCPM3Pos = 1; - break; - - case 1: - result = (daysCPM3SinceOrg >> 8) & 0xff; - getClockCPM3Pos = 2; - break; - - case 2: - result = toBCD(currentTime.tm_hour); - getClockCPM3Pos = 3; - break; - - case 3: - result = toBCD(currentTime.tm_min); - getClockCPM3Pos = 4; - break; - - case 4: - result = toBCD(currentTime.tm_sec); - getClockCPM3Pos = lastCommand = 0; - break; - } - else - result = getClockCPM3Pos = lastCommand = 0; - break; - - case getSIMHVersionCmd: - result = version[versionPos++]; - if (result == 0) - versionPos = lastCommand = 0; - break; - - case getBankSelectCmd: - if (cpu_unit.flags & UNIT_CPU_BANKED) - result = getBankSelect(); - else { - result = 0; - sim_debug(VERBOSE_MSG, &simh_device, "SIMH: " ADDRESS_FORMAT - " Get selected bank ignored for non-banked memory.\n", PCX); - } - lastCommand = 0; - break; - - case getCommonCmd: - if (getCommonPos == 0) { - result = getCommon() & 0xff; - getCommonPos = 1; - } - else { - result = (getCommon() >> 8) & 0xff; - getCommonPos = lastCommand = 0; - } - break; - - case getCPUClockFrequency: - if (getClockFrequencyPos == 0) { - result = getClockFrequency() & 0xff; - getClockFrequencyPos = 1; - } - else { - result = (getClockFrequency() >> 8) & 0xff; - getClockFrequencyPos = lastCommand = 0; - } - break; - - case hasBankedMemoryCmd: - result = cpu_unit.flags & UNIT_CPU_BANKED ? MAXBANKS : 0; - lastCommand = 0; - break; - - case readStopWatchCmd: - if (getStopWatchDeltaPos == 0) { - result = stopWatchDelta & 0xff; - getStopWatchDeltaPos = 1; - } - else { - result = (stopWatchDelta >> 8) & 0xff; - getStopWatchDeltaPos = lastCommand = 0; - } - break; - - case getHostOSPathSeparatorCmd: -#if defined (__MWERKS__) && defined (macintosh) - result = ':'; /* colon on Macintosh OS 9 */ -#elif defined (_WIN32) - result = '\\'; /* back slash in Windows */ -#else - result = '/'; /* slash in UNIX */ -#endif - break; - - default: - sim_debug(VERBOSE_MSG, &simh_device, "SIMH: " ADDRESS_FORMAT - " Undefined IN from SIMH pseudo device on port %03xh ignored.\n", - PCX, port); - result = lastCommand = 0; - } - return result; -} - -void do_SIMH_sleep(void) { - /* Do not sleep when timer interrupts are pending or are about to be created. - Otherwise there is the possibility that such interrupts are skipped. */ - if ((simh_unit.flags & UNIT_SIMH_TIMERON) && rtc_avail && (sim_os_msec() + 1 >= timeOfNextInterrupt)) - return; -#if defined (_WIN32) - if ((SIMHSleep / 1000) && !sio_unit.u4) /* time to sleep and SIO not attached to a file */ - Sleep(SIMHSleep / 1000); -#else - if (SIMHSleep && !sio_unit.u4) /* time to sleep and SIO not attached to a file */ - usleep(SIMHSleep); -#endif -} - -static int32 simh_out(const int32 port, const int32 data) { - time_t now; - switch(lastCommand) { - case readURLCmd: - if (isInReadPhase) - lastCommand = 0; - else { - if (data) { - if (urlPointer < URL_MAX_LENGTH - 1) - urlStore[urlPointer++] = data & 0xff; - } - else { - if (urlResult != NULL) - free(urlResult); - urlStore[urlPointer] = 0; - urlResult = URLContents(urlStore, &resultLength); - urlPointer = resultPointer = 0; - showAvailability = 1; - isInReadPhase = TRUE; - } - } - break; - - case setClockZSDOSCmd: - if (setClockZSDOSPos == 0) { - setClockZSDOSAdr = data; - setClockZSDOSPos = 1; - } - else { - setClockZSDOSAdr |= (data << 8); - setClockZSDOS(); - setClockZSDOSPos = lastCommand = 0; - } - break; - - case setClockCPM3Cmd: - if (setClockCPM3Pos == 0) { - setClockCPM3Adr = data; - setClockCPM3Pos = 1; - } - else { - setClockCPM3Adr |= (data << 8); - setClockCPM3(); - setClockCPM3Pos = lastCommand = 0; - } - break; - - case setCPUClockFrequency: - if (setClockFrequencyPos == 0) { - newClockFrequency = data; - setClockFrequencyPos = 1; - } - else { - setClockFrequency((data << 8) | newClockFrequency); - setClockFrequencyPos = lastCommand = 0; - } - break; - - case setBankSelectCmd: - if (cpu_unit.flags & UNIT_CPU_BANKED) - setBankSelect(data & BANKMASK); - else - sim_debug(VERBOSE_MSG, &simh_device, "SIMH: " ADDRESS_FORMAT - " Set selected bank to %i ignored for non-banked memory.\n", - PCX, data & 3); - lastCommand = 0; - break; - - case setTimerDeltaCmd: - if (setTimerDeltaPos == 0) { - timerDelta = data; - setTimerDeltaPos = 1; - } - else { - timerDelta |= (data << 8); - setTimerDeltaPos = lastCommand = 0; - if (timerDelta == 0) { - timerDelta = DEFAULT_TIMER_DELTA; - sim_debug(VERBOSE_MSG, &simh_device, "SIMH: " ADDRESS_FORMAT - " Timer delta set to 0 ms ignored. Using %i ms instead.\n", - PCX, DEFAULT_TIMER_DELTA); - } - } - break; - - case setTimerInterruptAdrCmd: - if (setTimerInterruptAdrPos == 0) { - timerInterruptHandler = data; - setTimerInterruptAdrPos = 1; - } - else { - timerInterruptHandler |= (data << 8); - setTimerInterruptAdrPos = lastCommand = 0; - } - break; - - default: /* lastCommand not yet set */ - sim_debug(CMD_MSG, &simh_device, "SIMH: " ADDRESS_FORMAT - " CMD(0x%02x) <- %i (0x%02x, '%s')\n", - PCX, port, data, data, - (0 <= data) && (data < kSimhPseudoDeviceCommands) ? - cmdNames[data] : "Unknown command"); - - lastCommand = data; - switch(data) { - case readURLCmd: - urlPointer = 0; - isInReadPhase = FALSE; - break; - - case getHostFilenamesCmd: -#if UNIX_PLATFORM - if (!globValid) { - globValid = TRUE; - globPosNameList = globPosName = 0; - createCPMCommandLine(); - globError = glob(cpmCommandLine, GLOB_ERR, NULL, &globS); - if (globError) { - sim_debug(VERBOSE_MSG, &simh_device, - "SIMH: " ADDRESS_FORMAT - " Cannot expand '%s'. Error is %i.\n", - PCX, cpmCommandLine, globError); - globfree(&globS); - globValid = FALSE; - } - } -#elif defined (_WIN32) - if (!globValid) { - globValid = TRUE; - globPosName = 0; - globFinished = FALSE; - createCPMCommandLine(); - setLastPathSeparator(); - hFind = FindFirstFile(cpmCommandLine, &FindFileData); - if (hFind == INVALID_HANDLE_VALUE) { - sim_debug(VERBOSE_MSG, &simh_device, - "SIMH: " ADDRESS_FORMAT - " Cannot expand '%s'. Error is %lu.\n", - PCX, cpmCommandLine, GetLastError()); - globValid = FALSE; - } - } -#endif - break; - - case SIMHSleepCmd: - do_SIMH_sleep(); - break; - - case printTimeCmd: /* print time */ - if (rtc_avail) - printf("SIMH: " ADDRESS_FORMAT " Current time in milliseconds = %d." NLP, PCX, sim_os_msec()); - else - warnNoRealTimeClock(); - break; - - case startTimerCmd: /* create a new timer on top of stack */ - if (rtc_avail) - if (markTimeSP < TIMER_STACK_LIMIT) - markTime[markTimeSP++] = sim_os_msec(); - else - printf("SIMH: " ADDRESS_FORMAT " Timer stack overflow." NLP, PCX); - else - warnNoRealTimeClock(); - break; - - case stopTimerCmd: /* stop timer on top of stack and show time difference */ - if (rtc_avail) - if (markTimeSP > 0) { - uint32 delta = sim_os_msec() - markTime[--markTimeSP]; - printf("SIMH: " ADDRESS_FORMAT " Timer stopped. Elapsed time in milliseconds = %d." NLP, PCX, delta); - } - else - printf("SIMH: " ADDRESS_FORMAT " No timer active." NLP, PCX); - else - warnNoRealTimeClock(); - break; - - case resetPTRCmd: /* reset ptr device */ - ptr_reset(&ptr_dev); - break; - - case attachPTRCmd: /* attach ptr to the file with name at beginning of CP/M command line */ - attachCPM(&ptr_unit); - break; - - case detachPTRCmd: /* detach ptr */ - detach_unit(&ptr_unit); - break; - - case getSIMHVersionCmd: - versionPos = 0; - break; - - case getClockZSDOSCmd: - time(&now); - now += ClockZSDOSDelta; - currentTime = *localtime(&now); - currentTimeValid = TRUE; - getClockZSDOSPos = 0; - break; - - case setClockZSDOSCmd: - setClockZSDOSPos = 0; - break; - - case getClockCPM3Cmd: - time(&now); - now += ClockCPM3Delta; - currentTime = *localtime(&now); - currentTimeValid = TRUE; - daysCPM3SinceOrg = (int32) ((now - mkCPM3Origin()) / SECONDS_PER_DAY); - getClockCPM3Pos = 0; - break; - - case setClockCPM3Cmd: - setClockCPM3Pos = 0; - break; - - case getCommonCmd: - getCommonPos = 0; - break; - - case getCPUClockFrequency: - getClockFrequencyPos = 0; - break; - - case setCPUClockFrequency: - setClockFrequencyPos = 0; - break; - - case getBankSelectCmd: - case setBankSelectCmd: - case hasBankedMemoryCmd: - case getHostOSPathSeparatorCmd: - break; - - case resetSIMHInterfaceCmd: - markTimeSP = 0; - lastCommand = 0; -#if UNIX_PLATFORM - if (globValid) { - globValid = FALSE; - globfree(&globS); - } -#elif defined (_WIN32) - if (globValid) { - globValid = FALSE; - if (hFind != INVALID_HANDLE_VALUE) { - FindClose(hFind); - } - } -#endif - break; - - case showTimerCmd: /* show time difference to timer on top of stack */ - if (rtc_avail) - if (markTimeSP > 0) { - uint32 delta = sim_os_msec() - markTime[markTimeSP - 1]; - printf("SIMH: " ADDRESS_FORMAT " Timer running. Elapsed in milliseconds = %d." NLP, PCX, delta); - } - else - printf("SIMH: " ADDRESS_FORMAT " No timer active." NLP, PCX); - else - warnNoRealTimeClock(); - break; - - case attachPTPCmd: /* attach ptp to the file with name at beginning of CP/M command line */ - attachCPM(&ptp_unit); - break; - - case detachPTPCmd: /* detach ptp */ - detach_unit(&ptp_unit); - break; - - case setZ80CPUCmd: - chiptype = CHIP_TYPE_Z80; - break; - - case set8080CPUCmd: - chiptype = CHIP_TYPE_8080; - break; - - case startTimerInterruptsCmd: - if (simh_dev_set_timeron(NULL, 0, NULL, NULL) == SCPE_OK) { - timerInterrupt = FALSE; - simh_unit.flags |= UNIT_SIMH_TIMERON; - } - break; - - case stopTimerInterruptsCmd: - simh_unit.flags &= ~UNIT_SIMH_TIMERON; - simh_dev_set_timeroff(NULL, 0, NULL, NULL); - break; - - case setTimerDeltaCmd: - setTimerDeltaPos = 0; - break; - - case setTimerInterruptAdrCmd: - setTimerInterruptAdrPos = 0; - break; - - case resetStopWatchCmd: - stopWatchNow = rtc_avail ? sim_os_msec() : 0; - break; - - case readStopWatchCmd: - getStopWatchDeltaPos = 0; - stopWatchDelta = rtc_avail ? sim_os_msec() - stopWatchNow : 0; - break; - - default: - sim_debug(CMD_MSG, &simh_device, "SIMH: " ADDRESS_FORMAT - " Unknown command (%i) to SIMH pseudo device on port %03xh ignored.\n", - PCX, data, port); - } - } - return 0x00; /* ignored, since OUT */ -} - -/* port 0xfe is a device for communication SIMH <--> Altair machine */ -int32 simh_dev(const int32 port, const int32 io, const int32 data) { - int32 result = 0; - if (io == 0) { - result = simh_in(port); - sim_debug(IN_MSG, &simh_device, "SIMH: " ADDRESS_FORMAT - " IN(0x%02x) -> %i (0x%02x, '%c')\n", PCX, - port, result, result, - (32 <= (result & 0xff)) && ((result & 0xff) <= 127) ? (result & 0xff) : '?'); - - } - else { - sim_debug(OUT_MSG, &simh_device, "SIMH: " ADDRESS_FORMAT - " OUT(0x%02x) <- %i (0x%02x, '%c')\n", PCX, - port, data, data, - (32 <= (data & 0xff)) && ((data & 0xff) <= 127) ? (data & 0xff) : '?'); - simh_out(port, data); - } - return result; -} diff --git a/AltairZ80/altairz80_sys.c b/AltairZ80/altairz80_sys.c deleted file mode 100644 index c1285ead..00000000 --- a/AltairZ80/altairz80_sys.c +++ /dev/null @@ -1,889 +0,0 @@ -/* altairz80_sys.c: MITS Altair system interface - - Copyright (c) 2002-2012, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - Disassembler from Marat Fayzullin ((c) 1995, 1996, 1997 - Commercial use prohibited) -*/ - -#include -#include "altairz80_defs.h" - -#define SIM_EMAX 6 - -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern DEVICE cpu_dev; -extern DEVICE sio_dev; -extern DEVICE simh_device; -extern DEVICE ptr_dev; -extern DEVICE ptp_dev; -extern DEVICE dsk_dev; -extern DEVICE hdsk_dev; -extern DEVICE net_dev; - -extern DEVICE mfdc_dev; -extern DEVICE fw2_dev; -extern DEVICE fif_dev; -extern DEVICE vfdhd_dev; -extern DEVICE mdsad_dev; -extern DEVICE nsfpb_dev; -extern DEVICE disk1a_dev; -extern DEVICE disk2_dev; -extern DEVICE disk3_dev; -extern DEVICE selchan_dev; -extern DEVICE ss1_dev; -extern DEVICE if3_dev; -extern DEVICE i8272_dev; -extern DEVICE mdriveh_dev; -extern DEVICE switchcpu_dev; - -extern DEVICE adcs6_dev; -extern DEVICE hdc1001_dev; - -extern DEVICE cromfdc_dev; -extern DEVICE wd179x_dev; -extern DEVICE n8vem_dev; -extern DEVICE wdi2_dev; - -extern DEVICE scp300f_dev; - -#ifdef USE_FPC -extern DEVICE fpc_dev; -#endif /* USE_FPC */ - -extern int32 chiptype; -extern long disasm (unsigned char *data, char *output, int segsize, long offset); - -void prepareMemoryAccessMessage(const t_addr loc); -void prepareInstructionMessage(const t_addr loc, const uint32 op); -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw); -t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw); - -t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); - -/* 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[] = "Altair 8800 (Z80)"; -REG *sim_PC = &cpu_reg[6]; -int32 sim_emax = SIM_EMAX; -DEVICE *sim_devices[] = { - /* AltairZ80 Devices */ - &cpu_dev, &sio_dev, &simh_device, &ptr_dev, &ptp_dev, &dsk_dev, - &hdsk_dev, &net_dev, - /* Advanced Digital (ADC) Devices */ - &adcs6_dev, - &hdc1001_dev, - /* Compupro Devices */ - &disk1a_dev, &disk2_dev, &disk3_dev, &ss1_dev, &mdriveh_dev, &selchan_dev, &if3_dev, - /* Cromemco Devices */ - &cromfdc_dev, - /* IMSAI Devices */ - &fif_dev, - /* Micropolis Devices */ - &mfdc_dev, - /* North Star Devices */ - &mdsad_dev, - /* Seattle Computer Products Devices */ - &scp300f_dev, - /* Vector Graphic Devices */ - &fw2_dev, &vfdhd_dev, - /* Single-Board Computers */ - &n8vem_dev, - /* Floppy Controller Cores */ - &i8272_dev, &wd179x_dev, - NULL -}; - -static char memoryAccessMessage[256]; -static char instructionMessage[256]; -const char *sim_stop_messages[] = { - "HALT instruction", - "Breakpoint", - memoryAccessMessage, - instructionMessage, - "Invalid Opcode" -}; - -static char *const Mnemonics8080[] = { -/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LXI B,#h", "STAX B", "INX B", "INR B", "DCR B", "MVI B,*h", "RLC", /* 00-07 */ - "_NOP", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,*h", "RRC", /* 08-0f */ - "_NOP", "LXI D,#h", "STAX D", "INX D", "INR D", "DCR D", "MVI D,*h", "RAL", /* 10-17 */ - "_NOP", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,*h", "RAR", /* 18-1f */ - "_NOP", "LXI H,#h", "SHLD #h", "INX H", "INR H", "DCR H", "MVI H,*h", "DAA", /* 20-27 */ - "_NOP", "DAD H", "LHLD #h", "DCX H", "INR L", "DCR L", "MVI L,*h", "CMA", /* 28-2f */ - "_NOP", "LXI SP,#h", "STA #h", "INX SP", "INR M", "DCR M", "MVI M,*h", "STC", /* 30-37 */ - "_NOP", "DAD SP", "LDA #h", "DCX SP", "INR A", "DCR A", "MVI A,*h", "CMC", /* 38-3f */ - "MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", "MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", /* 40-47 */ - "MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", "MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", /* 48-4f */ - "MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", "MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", /* 50-57 */ - "MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", "MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", /* 58-5f */ - "MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", "MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", /* 60-67 */ - "MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", "MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", /* 68-6f */ - "MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", "MOV M,H", "MOV M,L", "HLT", "MOV M,A", /* 70-77 */ - "MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", "MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", /* 78-7f */ - "ADD B", "ADD C", "ADD D", "ADD E", "ADD H", "ADD L", "ADD M", "ADD A", /* 80-87 */ - "ADC B", "ADC C", "ADC D", "ADC E", "ADC H", "ADC L", "ADC M", "ADC A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB M", "SUB A", /* 90-97 */ - "SBB B", "SBB C", "SBB D", "SBB E", "SBB H", "SBB L", "SBB M", "SBB A", /* 98-9f */ - "ANA B", "ANA C", "ANA D", "ANA E", "ANA H", "ANA L", "ANA M", "ANA A", /* a0-a7 */ - "XRA B", "XRA C", "XRA D", "XRA E", "XRA H", "XRA L", "XRA M", "XRA A", /* a8-af */ - "ORA B", "ORA C", "ORA D", "ORA E", "ORA H", "ORA L", "ORA M", "ORA A", /* b0-b7 */ - "CMP B", "CMP C", "CMP D", "CMP E", "CMP H", "CMP L", "CMP M", "CMP A", /* b8-bf */ - "RNZ", "POP B", "JNZ #h", "JMP #h", "CNZ #h", "PUSH B", "ADI *h", "RST 0", /* c0-c7 */ - "RZ", "RET", "JZ #h", "_JMP #h", "CZ #h", "CALL #h", "ACI *h", "RST 1", /* c8-cf */ - "RNC", "POP D", "JNC #h", "OUT *h", "CNC #h", "PUSH D", "SUI *h", "RST 2", /* d0-d7 */ - "RC", "_RET", "JC #h", "IN *h", "CC #h", "_CALL #h", "SBI *h", "RST 3", /* d8-df */ - "RPO", "POP H", "JPO #h", "XTHL", "CPO #h", "PUSH H", "ANI *h", "RST 4", /* e0-e7 */ - "RPE", "PCHL", "JPE #h", "XCHG", "CPE #h", "_CALL #h", "XRI *h", "RST 5", /* e8-ef */ - "RP", "POP PSW", "JP #h", "DI", "CP #h", "PUSH PSW", "ORI *h", "RST 6", /* f0-f7 */ - "RM", "SPHL", "JM #h", "EI", "CM #h", "_CALL #h", "CPI *h", "RST 7" /* f8-ff */ -}; - -static char *const MnemonicsZ80[256] = { -/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */ - "EX AF,AF'", "ADD HL,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */ - "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */ - "JR $h", "ADD HL,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */ - "JR NZ,$h", "LD HL,#h", "LD (#h),HL", "INC HL", "INC H", "DEC H", "LD H,*h", "DAA", /* 20-27 */ - "JR Z,$h", "ADD HL,HL", "LD HL,(#h)", "DEC HL", "INC L", "DEC L", "LD L,*h", "CPL", /* 28-2f */ - "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (HL)", "DEC (HL)", "LD (HL),*h", "SCF", /* 30-37 */ - "JR C,$h", "ADD HL,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */ - "LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,H", "LD B,L", "LD B,(HL)", "LD B,A", /* 40-47 */ - "LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,H", "LD C,L", "LD C,(HL)", "LD C,A", /* 48-4f */ - "LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,H", "LD D,L", "LD D,(HL)", "LD D,A", /* 50-57 */ - "LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,H", "LD E,L", "LD E,(HL)", "LD E,A", /* 58-5f */ - "LD H,B", "LD H,C", "LD H,D", "LD H,E", "LD H,H", "LD H,L", "LD H,(HL)", "LD H,A", /* 60-67 */ - "LD L,B", "LD L,C", "LD L,D", "LD L,E", "LD L,H", "LD L,L", "LD L,(HL)", "LD L,A", /* 68-6f */ - "LD (HL),B", "LD (HL),C", "LD (HL),D", "LD (HL),E", "LD (HL),H", "LD (HL),L", "HALT", "LD (HL),A", /* 70-77 */ - "LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,H", "LD A,L", "LD A,(HL)", "LD A,A", /* 78-7f */ - "ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,H", "ADD A,L", "ADD A,(HL)", "ADD A,A", /* 80-87 */ - "ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,H", "ADC A,L", "ADC A,(HL)", "ADC A,A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB (HL)", "SUB A", /* 90-97 */ - "SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,H", "SBC A,L", "SBC A,(HL)", "SBC A,A", /* 98-9f */ - "AND B", "AND C", "AND D", "AND E", "AND H", "AND L", "AND (HL)", "AND A", /* a0-a7 */ - "XOR B", "XOR C", "XOR D", "XOR E", "XOR H", "XOR L", "XOR (HL)", "XOR A", /* a8-af */ - "OR B", "OR C", "OR D", "OR E", "OR H", "OR L", "OR (HL)", "OR A", /* b0-b7 */ - "CP B", "CP C", "CP D", "CP E", "CP H", "CP L", "CP (HL)", "CP A", /* b8-bf */ - "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c0-c7 */ - "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */ - "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */ - "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */ - "RET PO", "POP HL", "JP PO,#h", "EX (SP),HL", "CALL PO,#h", "PUSH HL", "AND *h", "RST 20h", /* e0-e7 */ - "RET PE", "LD PC,HL", "JP PE,#h", "EX DE,HL", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */ - "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */ - "RET M", "LD SP,HL", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */ -}; - -static char *const MnemonicsCB[256] = { -/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A", /* 00-07 */ - "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A", /* 08-0f */ - "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (HL)", "RL A", /* 10-17 */ - "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (HL)", "RR A", /* 18-1f */ - "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (HL)", "SLA A", /* 20-27 */ - "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (HL)", "SRA A", /* 28-2f */ - "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (HL)", "SLL A", /* 30-37 */ - "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (HL)", "SRL A", /* 38-3f */ - "BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(HL)", "BIT 0,A", /* 40-47 */ - "BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(HL)", "BIT 1,A", /* 48-4f */ - "BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(HL)", "BIT 2,A", /* 50-57 */ - "BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(HL)", "BIT 3,A", /* 58-5f */ - "BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(HL)", "BIT 4,A", /* 60-67 */ - "BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(HL)", "BIT 5,A", /* 68-6f */ - "BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(HL)", "BIT 6,A", /* 70-77 */ - "BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(HL)", "BIT 7,A", /* 78-7f */ - "RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(HL)", "RES 0,A", /* 80-87 */ - "RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(HL)", "RES 1,A", /* 88-8f */ - "RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(HL)", "RES 2,A", /* 90-97 */ - "RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(HL)", "RES 3,A", /* 98-9f */ - "RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(HL)", "RES 4,A", /* a0-a7 */ - "RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(HL)", "RES 5,A", /* a8-af */ - "RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(HL)", "RES 6,A", /* b0-b7 */ - "RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(HL)", "RES 7,A", /* b8-bf */ - "SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(HL)", "SET 0,A", /* c0-c7 */ - "SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(HL)", "SET 1,A", /* c8-cf */ - "SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(HL)", "SET 2,A", /* d0-d7 */ - "SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(HL)", "SET 3,A", /* d8-df */ - "SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(HL)", "SET 4,A", /* e0-e7 */ - "SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(HL)", "SET 5,A", /* e8-ef */ - "SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(HL)", "SET 6,A", /* f0-f7 */ - "SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(HL)", "SET 7,A" /* f8-ff */ -}; - -static char *const MnemonicsED[256] = { -/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "DB EDh,00h", "DB EDh,01h", "DB EDh,02h", "DB EDh,03h", "DB EDh,04h", "DB EDh,05h", "DB EDh,06h", "DB EDh,07h", /* 00-07 */ - "DB EDh,08h", "DB EDh,09h", "DB EDh,0Ah", "DB EDh,0Bh", "DB EDh,0Ch", "DB EDh,0Dh", "DB EDh,0Eh", "DB EDh,0Fh", /* 08-0f */ - "DB EDh,10h", "DB EDh,11h", "DB EDh,12h", "DB EDh,13h", "DB EDh,14h", "DB EDh,15h", "DB EDh,16h", "DB EDh,17h", /* 10-17 */ - "DB EDh,18h", "DB EDh,19h", "DB EDh,1Ah", "DB EDh,1Bh", "DB EDh,1Ch", "DB EDh,1Dh", "DB EDh,1Eh", "DB EDh,1Fh", /* 18-1f */ - "DB EDh,20h", "DB EDh,21h", "DB EDh,22h", "DB EDh,23h", "DB EDh,24h", "DB EDh,25h", "DB EDh,26h", "DB EDh,27h", /* 20-27 */ - "DB EDh,28h", "DB EDh,29h", "DB EDh,2Ah", "DB EDh,2Bh", "DB EDh,2Ch", "DB EDh,2Dh", "DB EDh,2Eh", "DB EDh,2Fh", /* 28-2f */ - "DB EDh,30h", "DB EDh,31h", "DB EDh,32h", "DB EDh,33h", "DB EDh,34h", "DB EDh,35h", "DB EDh,36h", "DB EDh,37h", /* 30-37 */ - "DB EDh,38h", "DB EDh,39h", "DB EDh,3Ah", "DB EDh,3Bh", "DB EDh,3Ch", "DB EDh,3Dh", "DB EDh,3Eh", "DB EDh,3Fh", /* 38-3f */ - "IN B,(C)", "OUT (C),B", "SBC HL,BC", "LD (#h),BC", "NEG", "RETN", "IM 0", "LD I,A", /* 40-47 */ - "IN C,(C)", "OUT (C),C", "ADC HL,BC", "LD BC,(#h)", "DB EDh,4Ch", "RETI", "DB EDh,4Eh", "LD R,A", /* 48-4f */ - "IN D,(C)", "OUT (C),D", "SBC HL,DE", "LD (#h),DE", "DB EDh,54h", "DB EDh,55h", "IM 1", "LD A,I", /* 50-57 */ - "IN E,(C)", "OUT (C),E", "ADC HL,DE", "LD DE,(#h)", "DB EDh,5Ch", "DB EDh,5Dh", "IM 2", "LD A,R", /* 58-5f */ - "IN H,(C)", "OUT (C),H", "SBC HL,HL", "LD (#h),HL", "DB EDh,64h", "DB EDh,65h", "DB EDh,66h", "RRD", /* 60-67 */ - "IN L,(C)", "OUT (C),L", "ADC HL,HL", "LD HL,(#h)", "DB EDh,6Ch", "DB EDh,6Dh", "DB EDh,6Eh", "RLD", /* 68-6f */ - "IN F,(C)", "DB EDh,71h", "SBC HL,SP", "LD (#h),SP", "DB EDh,74h", "DB EDh,75h", "DB EDh,76h", "DB EDh,77h", /* 70-77 */ - "IN A,(C)", "OUT (C),A", "ADC HL,SP", "LD SP,(#h)", "DB EDh,7Ch", "DB EDh,7Dh", "DB EDh,7Eh", "DB EDh,7Fh", /* 78-7f */ - "DB EDh,80h", "DB EDh,81h", "DB EDh,82h", "DB EDh,83h", "DB EDh,84h", "DB EDh,85h", "DB EDh,86h", "DB EDh,87h", /* 80-87 */ - "DB EDh,88h", "DB EDh,89h", "DB EDh,8Ah", "DB EDh,8Bh", "DB EDh,8Ch", "DB EDh,8Dh", "DB EDh,8Eh", "DB EDh,8Fh", /* 88-8f */ - "DB EDh,90h", "DB EDh,91h", "DB EDh,92h", "DB EDh,93h", "DB EDh,94h", "DB EDh,95h", "DB EDh,96h", "DB EDh,97h", /* 90-97 */ - "DB EDh,98h", "DB EDh,99h", "DB EDh,9Ah", "DB EDh,9Bh", "DB EDh,9Ch", "DB EDh,9Dh", "DB EDh,9Eh", "DB EDh,9Fh", /* 98-9f */ - "LDI", "CPI", "INI", "OUTI", "DB EDh,A4h", "DB EDh,A5h", "DB EDh,A6h", "DB EDh,A7h", /* a0-a7 */ - "LDD", "CPD", "IND", "OUTD", "DB EDh,ACh", "DB EDh,ADh", "DB EDh,AEh", "DB EDh,AFh", /* a8-af */ - "LDIR", "CPIR", "INIR", "OTIR", "DB EDh,B4h", "DB EDh,B5h", "DB EDh,B6h", "DB EDh,B7h", /* b0-b7 */ - "LDDR", "CPDR", "INDR", "OTDR", "DB EDh,BCh", "DB EDh,BDh", "DB EDh,BEh", "DB EDh,BFh", /* b8-bf */ - "DB EDh,C0h", "DB EDh,C1h", "DB EDh,C2h", "DB EDh,C3h", "DB EDh,C4h", "DB EDh,C5h", "DB EDh,C6h", "DB EDh,C7h", /* c0-c7 */ - "DB EDh,C8h", "DB EDh,C9h", "DB EDh,CAh", "DB EDh,CBh", "DB EDh,CCh", "DB EDh,CDh", "DB EDh,CEh", "DB EDh,CFh", /* c8-cf */ - "DB EDh,D0h", "DB EDh,D1h", "DB EDh,D2h", "DB EDh,D3h", "DB EDh,D4h", "DB EDh,D5h", "DB EDh,D6h", "DB EDh,D7h", /* d0-d7 */ - "DB EDh,D8h", "DB EDh,D9h", "DB EDh,DAh", "DB EDh,DBh", "DB EDh,DCh", "DB EDh,DDh", "DB EDh,DEh", "DB EDh,DFh", /* d8-df */ - "DB EDh,E0h", "DB EDh,E1h", "DB EDh,E2h", "DB EDh,E3h", "DB EDh,E4h", "DB EDh,E5h", "DB EDh,E6h", "DB EDh,E7h", /* e0-e7 */ - "DB EDh,E8h", "DB EDh,E9h", "DB EDh,EAh", "DB EDh,EBh", "DB EDh,ECh", "DB EDh,EDh", "DB EDh,EEh", "DB EDh,EFh", /* e8-ef */ - "DB EDh,F0h", "DB EDh,F1h", "DB EDh,F2h", "DB EDh,F3h", "DB EDh,F4h", "DB EDh,F5h", "DB EDh,F6h", "DB EDh,F7h", /* f0-f7 */ - "DB EDh,F8h", "DB EDh,F9h", "DB EDh,FAh", "DB EDh,FBh", "DB EDh,FCh", "DB EDh,FDh", "DB EDh,FEh", "DB EDh,FFh" /* f8-ff */ -}; - -static char *const MnemonicsXX[256] = { -/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */ - "EX AF,AF'", "ADD I%,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */ - "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */ - "JR $h", "ADD I%,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */ - "JR NZ,$h", "LD I%,#h", "LD (#h),I%", "INC I%", "INC I%H", "DEC I%H", "LD I%H,*h", "DAA", /* 20-27 */ - "JR Z,$h", "ADD I%,I%", "LD I%,(#h)", "DEC I%", "INC I%L", "DEC I%L", "LD I%L,*h", "CPL", /* 28-2f */ - "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (I%+^h)", "DEC (I%+^h)", "LD (I%+^h),*h","SCF", /* 30-37 */ - "JR C,$h", "ADD I%,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */ - "LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,I%H", "LD B,I%L", "LD B,(I%+^h)", "LD B,A", /* 40-47 */ - "LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,I%H", "LD C,I%L", "LD C,(I%+^h)", "LD C,A", /* 48-4f */ - "LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,I%H", "LD D,I%L", "LD D,(I%+^h)", "LD D,A", /* 50-57 */ - "LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,I%H", "LD E,I%L", "LD E,(I%+^h)", "LD E,A", /* 58-5f */ - "LD I%H,B", "LD I%H,C", "LD I%H,D", "LD I%H,E", "LD I%H,I%H", "LD I%H,I%L", "LD H,(I%+^h)", "LD I%H,A", /* 60-67 */ - "LD I%L,B", "LD I%L,C", "LD I%L,D", "LD I%L,E", "LD I%L,I%H", "LD I%L,I%L", "LD L,(I%+^h)", "LD I%L,A", /* 68-6f */ - "LD (I%+^h),B", "LD (I%+^h),C", "LD (I%+^h),D", "LD (I%+^h),E", "LD (I%+^h),H", "LD (I%+^h),L", "HALT", "LD (I%+^h),A", /* 70-77 */ - "LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,I%H", "LD A,I%L", "LD A,(I%+^h)", "LD A,A", /* 78-7f */ - "ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,I%H", "ADD A,I%L", "ADD A,(I%+^h)","ADD A,A", /* 80-87 */ - "ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,I%H", "ADC A,I%L", "ADC A,(I%+^h)","ADC A,A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB I%H", "SUB I%L", "SUB (I%+^h)", "SUB A", /* 90-97 */ - "SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,I%H", "SBC A,I%L", "SBC A,(I%+^h)","SBC A,A", /* 98-9f */ - "AND B", "AND C", "AND D", "AND E", "AND I%H", "AND I%L", "AND (I%+^h)", "AND A", /* a0-a7 */ - "XOR B", "XOR C", "XOR D", "XOR E", "XOR I%H", "XOR I%L", "XOR (I%+^h)", "XOR A", /* a8-af */ - "OR B", "OR C", "OR D", "OR E", "OR I%H", "OR I%L", "OR (I%+^h)", "OR A", /* b0-b7 */ - "CP B", "CP C", "CP D", "CP E", "CP I%H", "CP I%L", "CP (I%+^h)", "CP A", /* b8-bf */ - "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c8-cf */ - "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */ - "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */ - "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */ - "RET PO", "POP I%", "JP PO,#h", "EX (SP),I%", "CALL PO,#h", "PUSH I%", "AND *h", "RST 20h", /* e0-e7 */ - "RET PE", "LD PC,I%", "JP PE,#h", "EX DE,I%", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */ - "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */ - "RET M", "LD SP,I%", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */ -}; - -static char *const MnemonicsXCB[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (I%@h)", "RLC A", /* 00-07 */ - "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (I%@h)", "RRC A", /* 08-0f */ - "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (I%@h)", "RL A", /* 10-17 */ - "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (I%@h)", "RR A", /* 18-1f */ - "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (I%@h)", "SLA A", /* 20-27 */ - "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (I%@h)", "SRA A", /* 28-2f */ - "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (I%@h)", "SLL A", /* 30-37 */ - "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (I%@h)", "SRL A", /* 38-3f */ - "BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(I%@h)", "BIT 0,A", /* 40-47 */ - "BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(I%@h)", "BIT 1,A", /* 48-4f */ - "BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(I%@h)", "BIT 2,A", /* 50-57 */ - "BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(I%@h)", "BIT 3,A", /* 58-5f */ - "BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(I%@h)", "BIT 4,A", /* 60-67 */ - "BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(I%@h)", "BIT 5,A", /* 68-6f */ - "BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(I%@h)", "BIT 6,A", /* 70-77 */ - "BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(I%@h)", "BIT 7,A", /* 78-7f */ - "RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(I%@h)", "RES 0,A", /* 80-87 */ - "RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(I%@h)", "RES 1,A", /* 88-8f */ - "RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(I%@h)", "RES 2,A", /* 90-97 */ - "RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(I%@h)", "RES 3,A", /* 98-9f */ - "RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(I%@h)", "RES 4,A", /* a0-a7 */ - "RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(I%@h)", "RES 5,A", /* a8-af */ - "RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(I%@h)", "RES 6,A", /* b0-b7 */ - "RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(I%@h)", "RES 7,A", /* b8-bf */ - "SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(I%@h)", "SET 0,A", /* c0-c7 */ - "SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(I%@h)", "SET 1,A", /* c8-cf */ - "SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(I%@h)", "SET 2,A", /* d0-d7 */ - "SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(I%@h)", "SET 3,A", /* d8-df */ - "SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(I%@h)", "SET 4,A", /* e0-e7 */ - "SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(I%@h)", "SET 5,A", /* e8-ef */ - "SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(I%@h)", "SET 6,A", /* f0-f7 */ - "SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(I%@h)", "SET 7,A" /* f8-ff */ -}; - -void prepareMemoryAccessMessage(const t_addr loc) { - sprintf(memoryAccessMessage, "Memory access breakpoint [%05xh]", loc); -} - -void prepareInstructionMessage(const t_addr loc, const uint32 op) { - sprintf(instructionMessage, "Instruction \"%s\" breakpoint [%05xh]", chiptype == CHIP_TYPE_8080 ? Mnemonics8080[op & 0xff] : - (chiptype == CHIP_TYPE_Z80 ? MnemonicsZ80[op & 0xff] : "???"), loc); -} - -/* Symbolic disassembler - - Inputs: - *val = instructions to disassemble - useZ80Mnemonics = > 0 iff Z80 mnemonics are to be used - addr = current PC - Outputs: - *S = output text - - DAsm is Copyright (C) Marat Fayzullin 1995,1996,1997 - You are not allowed to distribute this software - commercially. - -*/ - -static int32 DAsm(char *S, const uint32 *val, const int32 useZ80Mnemonics, const int32 addr) { - char R[128], H[10], C = '\0', *T, *P; - uint8 J = 0, Offset = 0; - uint16 B = 0; - - if (useZ80Mnemonics) - switch(val[B]) { - - case 0xcb: - B++; - T = MnemonicsCB[val[B++]]; - break; - - case 0xed: - B++; - T = MnemonicsED[val[B++]]; - break; - - case 0xdd: - - case 0xfd: - C = (val[B++] == 0xdd) ? 'X' : 'Y'; - if (val[B] == 0xcb) { - B++; - Offset = val[B++]; - J = 1; - T = MnemonicsXCB[val[B++]]; - } - else - T = MnemonicsXX[val[B++]]; - break; - - default: - T = MnemonicsZ80[val[B++]]; - } - else - T = Mnemonics8080[val[B++]]; - - if ( (P = strchr(T, '^')) ) { - strncpy(R, T, P - T); - R[P - T] = '\0'; - sprintf(H, "%02X", val[B++]); - strcat(R, H); - strcat(R, P + 1); - } - else - strcpy(R, T); - if ( (P = strchr(R, '%')) ) { - *P = C; - if ( (P = strchr(P + 1, '%')) ) - *P = C; - } - - if ( (P = strchr(R, '*')) ) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - sprintf(H, "%02X", val[B++]); - strcat(S, H); - strcat(S, P + 1); - } - else if ( (P = strchr(R, '@')) ) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - if (!J) - Offset = val[B++]; - strcat(S, Offset & 0x80 ? "-" : "+"); - J = Offset & 0x80 ? 256 - Offset : Offset; - sprintf(H, "%02X", J); - strcat(S, H); - strcat(S, P + 1); - } - else if ( (P = strchr(R, '$')) ) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - Offset = val[B++]; - sprintf(H, "%04X", (addr + 2 + (Offset & 0x80 ? (Offset - 256) : Offset)) & 0xFFFF); - strcat(S, H); - strcat(S, P + 1); - } - else if ( (P = strchr(R, '#')) ) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - sprintf(H, "%04X", val[B] + 256 * val[B + 1]); - strcat(S, H); - strcat(S, P + 1); - B += 2; - } - else - strcpy(S, R); - return(B); -} - -/* 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) { - char disasm_result[128]; - int32 ch = val[0] & 0x7f; - long r; - unsigned char vals[SIM_EMAX]; - int32 i; - if (sw & (SWMASK('A') | SWMASK('C'))) { - fprintf(of, ((0x20 <= ch) && (ch < 0x7f)) ? "'%c'" : "%02x", ch); - return SCPE_OK; - } - if (!(sw & SWMASK('M'))) - return SCPE_ARG; - if (chiptype == CHIP_TYPE_8086) { - for (i = 0; i < SIM_EMAX; i++) - vals[i] = val[i] & 0xff; - r = disasm(vals, disasm_result, 16, addr); - } - else - r = DAsm(disasm_result, val, chiptype == CHIP_TYPE_Z80, addr); - fprintf(of, "%s", disasm_result); - return 1 - r; -} - -/* checkbase determines the base of the number (ch, *numString) - and returns FALSE if the number is bad */ -static int32 checkbase(char ch, const char *numString) { - int32 decimal = (ch <= '9'); - if (toupper(ch) == 'H') - return FALSE; - while (isxdigit(ch = *numString++)) - if (ch > '9') - decimal = FALSE; - return toupper(ch) == 'H' ? 16 : (decimal ? 10 : FALSE); -} - -static int32 numok(char ch, const char **numString, const int32 minvalue, - const int32 maxvalue, const int32 requireSign, int32 *result) { - int32 sign = 1, value = 0, base; - if (requireSign) { - if (ch == '+') - ch = *(*numString)++; - else if (ch == '-') { - sign = -1; - ch = *(*numString)++; - } - else - return FALSE; - } - if (!(base = checkbase(ch, *numString))) - return FALSE; - while (isxdigit(ch)) { - value = base * value + ((ch <= '9') ? (ch - '0') : (toupper(ch) - 'A' + 10)); - ch = *(*numString)++; - } - if (toupper(ch) != 'H') - (*numString)--; - *result = value * sign; - return (minvalue <= value) && (value <= maxvalue); -} - -static int32 match(const char *pattern, const char *input, char *xyFirst, char *xy, int32 *number, int32 *star, - int32 *at, int32 *hat, int32 *dollar) { - char pat = *pattern++; - char inp = *input++; - while ((pat) && (inp)) { - switch(pat) { - - case '_': /* patterns containing '_' should never match */ - return FALSE; - - case ',': - if (inp == ' ') { - inp = *input++; - continue; - } /* otherwise fall through */ - - case ' ': - if (inp != pat) - return FALSE; - pat = *pattern++; - inp = *input++; - while (inp == ' ') - inp = *input++; - continue; - - case '%': - inp = toupper(inp); - if ((inp == 'X') || (inp == 'Y')) - if (*xyFirst) /* make sure that second '%' corresponds to first */ - if (*xyFirst == inp) - *xy = inp; - else - return FALSE; - else { /* take note of first '%' for later */ - *xyFirst = inp; - *xy = inp; - } - else - return FALSE; - break; - - case '#': - if (numok(inp, &input, 0, 65535, FALSE, number)) - pattern++; /* skip h */ - else - return FALSE; - break; - - case '*': - if (numok(inp, &input, 0, 255, FALSE, star)) - pattern++; /* skip h */ - else - return FALSE; - break; - - case '@': - if (numok(inp, &input, -128, 65535, TRUE, at)) - pattern++; /* skip h */ - else - return FALSE; - break; - - case '$': - if (numok(inp, &input, 0, 65535, FALSE, dollar)) - pattern++; /* skip h */ - else - return FALSE; - break; - - case '^': - if (numok(inp, &input, 0, 255, FALSE, hat)) - pattern++; /* skip h */ - else - return FALSE; - break; - - default: - if (toupper(pat) != toupper(inp)) - return FALSE; - } - pat = *pattern++; - inp = *input++; - } - while (inp == ' ') - inp = *input++; - return (pat == 0) && (inp == 0); -} - -static int32 checkXY(const char xy) { - return xy == 'X' ? 0xdd : 0xfd; /* else is 'Y' */ -} - -static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *const Mnemonics[]) { - char xyFirst = 0, xy; - int32 op, number, star, at, hat, dollar; - for (op = 0; op < 256; op++) { - number = star = at = dollar = -129; - if (match(Mnemonics[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = op; - if (number >= 0) { - val[1] = (0xff) & number; - val[2] = (0xff) & (number >> 8); - return -2; /* two additional bytes returned */ - } - else if (star >= 0) { - val[1] = (0xff) & star; - return -1; /* one additional byte returned */ - } - else if (at > -129) - if ((-128 <= at) && (at <= 127)) { - val[1] = (int8)(at); - return -1; /* one additional byte returned */ - } - else - return SCPE_ARG; - else if (dollar >= 0) { - dollar -= addr + 2; /* relative translation */ - if ((-128 <= dollar) && (dollar <= 127)) { - val[1] = (int8)(dollar); - return -1; /* one additional byte returned */ - } - else - return SCPE_ARG; - } - else - return SCPE_OK; - } - } - if (Mnemonics == Mnemonics8080) - return SCPE_ARG; - - for (op = 0; op < 256; op++) - if (match(MnemonicsCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = 0xcb; - val[1] = op; - return -1; /* one additional byte returned */ - } - - for (op = 0; op < 256; op++) { - number = -1; - if (match(MnemonicsED[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = 0xed; - val[1] = op; - if (number >= 0) { - val[2] = (0xff) & number; - val[3] = (0xff) & (number >> 8); - return -3; /* three additional bytes returned */ - } - else - return -1; /* one additional byte returned */ - } - } - - for (op = 0; op < 256; op++) { - number = star = hat = -1; - xy = 0; - if (match(MnemonicsXX[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - /* all matches must have contained a '%' character */ - if (!(val[0] = checkXY(xy))) - return SCPE_ARG; - val[1] = op; - if (number >= 0) { - val[2] = (0xff) & number; - val[3] = (0xff) & (number >> 8); - return -3; /* three additional bytes returned */ - } - else if ((star >= 0) && (hat >= 0)) { - val[2] = (0xff) & hat; - val[3] = (0xff) & star; - return -3; /* three additional bytes returned */ - } - else if (star >= 0) { - val[2] = (0xff) & star; - return -2; /* two additional bytes returned */ - } - else if (hat >= 0) { - val[2] = (0xff) & hat; - return -2; /* two additional bytes returned */ - } - else - return -1; /* one additional byte returned */ - } - } - - for (op = 0; op < 256; op++) { - at = -129; - xy = 0; - if (match(MnemonicsXCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - /* all matches must have contained a '%' character */ - if (!(val[0] = checkXY(xy))) - return SCPE_ARG; - val[1] = 0xcb; - if (at > -129) - val[2] = (int8) (at); - else { - printf("Offset expected.\n"); - return SCPE_ARG; - } - val[3] = op; - return -3; /* three additional bytes returned */ - } - } - return SCPE_ARG; -} - - -/* 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) { - while (isspace(*cptr)) - cptr++; /* absorb spaces */ - if ((sw & (SWMASK('A') | SWMASK('C'))) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) - return SCPE_ARG; /* must have one char */ - val[0] = (uint32) cptr[0]; - return SCPE_OK; - } - return parse_X80(cptr, addr, val, chiptype == CHIP_TYPE_Z80 ? MnemonicsZ80 : Mnemonics8080); -} - -/* Set Memory Base Address routine */ -t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc) -{ - DEVICE *dptr; - PNP_INFO *pnp; - uint32 newba; - t_stat r; - - if (cptr == NULL) - return SCPE_ARG; - if (uptr == NULL) - return SCPE_IERR; - dptr = find_dev_from_unit (uptr); - if (dptr == NULL) - return SCPE_IERR; - pnp = (PNP_INFO *) dptr->ctxt; - if (pnp == NULL) - return SCPE_IERR; - - newba = get_uint (cptr, 16, 0xFFFF, &r); - if (r != SCPE_OK) - return r; - - if ((newba > 0xFFFF) || (newba % pnp->mem_size)) - return SCPE_ARG; - - if (dptr->flags & DEV_DIS) { - printf("device not enabled yet.\n"); - pnp->mem_base = newba & ~(pnp->mem_size-1); - } else { - dptr->flags |= DEV_DIS; - dptr->reset(dptr); - pnp->mem_base = newba & ~(pnp->mem_size-1); - dptr->flags &= ~DEV_DIS; - dptr->reset(dptr); - } - - return SCPE_OK; -} - -/* Show Base Address routine */ -t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc) -{ - DEVICE *dptr; - PNP_INFO *pnp; - - if (uptr == NULL) - return SCPE_IERR; - dptr = find_dev_from_unit (uptr); - if (dptr == NULL) - return SCPE_IERR; - pnp = (PNP_INFO *) dptr->ctxt; - if (pnp == NULL) - return SCPE_IERR; - - fprintf(st, "MEM=0x%04X-0x%04X", pnp->mem_base, pnp->mem_base+pnp->mem_size-1); - return SCPE_OK; -} - -/* Set Memory Base Address routine */ -t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc) -{ - DEVICE *dptr; - PNP_INFO *pnp; - uint32 newba; - t_stat r; - - if (cptr == NULL) - return SCPE_ARG; - if (uptr == NULL) - return SCPE_IERR; - dptr = find_dev_from_unit (uptr); - if (dptr == NULL) - return SCPE_IERR; - pnp = (PNP_INFO *) dptr->ctxt; - if (pnp == NULL) - return SCPE_IERR; - - newba = get_uint (cptr, 16, 0xFF, &r); - if (r != SCPE_OK) - return r; - - if ((newba > 0xFF) || - (newba % pnp->io_size)) - return SCPE_ARG; - - if (dptr->flags & DEV_DIS) { - printf("device not enabled yet.\n"); - pnp->io_base = newba & ~(pnp->io_size-1); - } else { - dptr->flags |= DEV_DIS; - dptr->reset(dptr); - pnp->io_base = newba & ~(pnp->io_size-1); - dptr->flags &= ~DEV_DIS; - dptr->reset(dptr); - } - - return SCPE_OK; -} - -/* Show I/O Base Address routine */ -t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc) -{ - DEVICE *dptr; - PNP_INFO *pnp; - - if (uptr == NULL) - return SCPE_IERR; - dptr = find_dev_from_unit (uptr); - if (dptr == NULL) - return SCPE_IERR; - pnp = (PNP_INFO *) dptr->ctxt; - if (pnp == NULL) - return SCPE_IERR; - - fprintf(st, "I/O=0x%02X-0x%02X", pnp->io_base, pnp->io_base+pnp->io_size-1); - return SCPE_OK; -} - diff --git a/AltairZ80/disasm.c b/AltairZ80/disasm.c deleted file mode 100644 index 9b6059f5..00000000 --- a/AltairZ80/disasm.c +++ /dev/null @@ -1,1426 +0,0 @@ -/* disasm.c where all the _work_ gets done in the Netwide Disassembler - * - * The Netwide Assembler is copyright (C) 1996 Simon Tatham and - * Julian Hall. All rights reserved. The software is - * redistributable under the licence given in the file "Licence" - * distributed in the NASM archive. - * - * initial version 27/iii/95 by Simon Tatham - */ - -#include -#include - -#include "nasm.h" -#include "insns.h" - -/* names.c included source file defining instruction and register - * names for the Netwide [Dis]Assembler - * - * The Netwide Assembler is copyright (C) 1996 Simon Tatham and - * Julian Hall. All rights reserved. The software is - * redistributable under the licence given in the file "Licence" - * distributed in the NASM archive. - */ - -static const char *conditions[] = { /* condition code names */ - "a", "ae", "b", "be", "c", "e", "g", "ge", "l", "le", "na", "nae", - "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no", "np", - "ns", "nz", "o", "p", "pe", "po", "s", "z" -}; - -/* Register names automatically generated from regs.dat */ -/* automatically generated from ./regs.dat - do not edit */ -static const char *reg_names[] = { - "ah", - "al", - "ax", - "bh", - "bl", - "bp", - "bx", - "ch", - "cl", - "cr0", - "cr1", - "cr2", - "cr3", - "cr4", - "cr5", - "cr6", - "cr7", - "cs", - "cx", - "dh", - "di", - "dl", - "dr0", - "dr1", - "dr2", - "dr3", - "dr4", - "dr5", - "dr6", - "dr7", - "ds", - "dx", - "eax", - "ebp", - "ebx", - "ecx", - "edi", - "edx", - "es", - "esi", - "esp", - "fs", - "gs", - "mm0", - "mm1", - "mm2", - "mm3", - "mm4", - "mm5", - "mm6", - "mm7", - "segr6", - "segr7", - "si", - "sp", - "ss", - "st0", - "st1", - "st2", - "st3", - "st4", - "st5", - "st6", - "st7", - "tr0", - "tr1", - "tr2", - "tr3", - "tr4", - "tr5", - "tr6", - "tr7", - "xmm0", - "xmm1", - "xmm2", - "xmm3", - "xmm4", - "xmm5", - "xmm6", - "xmm7" -}; - -/* Instruction names automatically generated from insns.dat */ -/* This file is auto-generated from insns.dat by insns.pl - don't edit it */ -/* This file in included by names.c */ -static const char *insn_names[] = { - "aaa", - "aad", - "aam", - "aas", - "adc", - "add", - "addpd", - "addps", - "addsd", - "addss", - "addsubpd", - "addsubps", - "and", - "andnpd", - "andnps", - "andpd", - "andps", - "arpl", - "bound", - "bsf", - "bsr", - "bswap", - "bt", - "btc", - "btr", - "bts", - "call", - "cbw", - "cdq", - "clc", - "cld", - "clflush", - "cli", - "clts", - "cmc", - "cmp", - "cmpeqpd", - "cmpeqps", - "cmpeqsd", - "cmpeqss", - "cmplepd", - "cmpleps", - "cmplesd", - "cmpless", - "cmpltpd", - "cmpltps", - "cmpltsd", - "cmpltss", - "cmpneqpd", - "cmpneqps", - "cmpneqsd", - "cmpneqss", - "cmpnlepd", - "cmpnleps", - "cmpnlesd", - "cmpnless", - "cmpnltpd", - "cmpnltps", - "cmpnltsd", - "cmpnltss", - "cmpordpd", - "cmpordps", - "cmpordsd", - "cmpordss", - "cmppd", - "cmpps", - "cmpsb", - "cmpsd", - "cmpss", - "cmpsw", - "cmpunordpd", - "cmpunordps", - "cmpunordsd", - "cmpunordss", - "cmpxchg", - "cmpxchg486", - "cmpxchg8b", - "comisd", - "comiss", - "cpuid", - "cvtdq2pd", - "cvtdq2ps", - "cvtpd2dq", - "cvtpd2pi", - "cvtpd2ps", - "cvtpi2pd", - "cvtpi2ps", - "cvtps2dq", - "cvtps2pd", - "cvtps2pi", - "cvtsd2si", - "cvtsd2ss", - "cvtsi2sd", - "cvtsi2ss", - "cvtss2sd", - "cvtss2si", - "cvttpd2dq", - "cvttpd2pi", - "cvttps2dq", - "cvttps2pi", - "cvttsd2si", - "cvttss2si", - "cwd", - "cwde", - "daa", - "das", - "db", - "dd", - "dec", - "div", - "divpd", - "divps", - "divsd", - "divss", - "dq", - "dt", - "dw", - "emms", - "enter", - "equ", - "f2xm1", - "fabs", - "fadd", - "faddp", - "fbld", - "fbstp", - "fchs", - "fclex", - "fcmovb", - "fcmovbe", - "fcmove", - "fcmovnb", - "fcmovnbe", - "fcmovne", - "fcmovnu", - "fcmovu", - "fcom", - "fcomi", - "fcomip", - "fcomp", - "fcompp", - "fcos", - "fdecstp", - "fdisi", - "fdiv", - "fdivp", - "fdivr", - "fdivrp", - "femms", - "feni", - "ffree", - "ffreep", - "fiadd", - "ficom", - "ficomp", - "fidiv", - "fidivr", - "fild", - "fimul", - "fincstp", - "finit", - "fist", - "fistp", - "fisttp", - "fisub", - "fisubr", - "fld", - "fld1", - "fldcw", - "fldenv", - "fldl2e", - "fldl2t", - "fldlg2", - "fldln2", - "fldpi", - "fldz", - "fmul", - "fmulp", - "fnclex", - "fndisi", - "fneni", - "fninit", - "fnop", - "fnsave", - "fnstcw", - "fnstenv", - "fnstsw", - "fpatan", - "fprem", - "fprem1", - "fptan", - "frndint", - "frstor", - "fsave", - "fscale", - "fsetpm", - "fsin", - "fsincos", - "fsqrt", - "fst", - "fstcw", - "fstenv", - "fstp", - "fstsw", - "fsub", - "fsubp", - "fsubr", - "fsubrp", - "ftst", - "fucom", - "fucomi", - "fucomip", - "fucomp", - "fucompp", - "fwait", - "fxam", - "fxch", - "fxrstor", - "fxsave", - "fxtract", - "fyl2x", - "fyl2xp1", - "haddpd", - "haddps", - "hlt", - "hsubpd", - "hsubps", - "ibts", - "icebp", - "idiv", - "imul", - "in", - "inc", - "incbin", - "insb", - "insd", - "insw", - "int", - "int01", - "int03", - "int1", - "int3", - "into", - "invd", - "invlpg", - "iret", - "iretd", - "iretw", - "jcxz", - "jecxz", - "jmp", - "jmpe", - "lahf", - "lar", - "lddqu", - "ldmxcsr", - "lds", - "lea", - "leave", - "les", - "lfence", - "lfs", - "lgdt", - "lgs", - "lidt", - "lldt", - "lmsw", - "loadall", - "loadall286", - "lodsb", - "lodsd", - "lodsw", - "loop", - "loope", - "loopne", - "loopnz", - "loopz", - "lsl", - "lss", - "ltr", - "maskmovdqu", - "maskmovq", - "maxpd", - "maxps", - "maxsd", - "maxss", - "mfence", - "minpd", - "minps", - "minsd", - "minss", - "monitor", - "mov", - "movapd", - "movaps", - "movd", - "movddup", - "movdq2q", - "movdqa", - "movdqu", - "movhlps", - "movhpd", - "movhps", - "movlhps", - "movlpd", - "movlps", - "movmskpd", - "movmskps", - "movntdq", - "movnti", - "movntpd", - "movntps", - "movntq", - "movq", - "movq2dq", - "movsb", - "movsd", - "movshdup", - "movsldup", - "movss", - "movsw", - "movsx", - "movupd", - "movups", - "movzx", - "mul", - "mulpd", - "mulps", - "mulsd", - "mulss", - "mwait", - "neg", - "nop", - "not", - "or", - "orpd", - "orps", - "out", - "outsb", - "outsd", - "outsw", - "packssdw", - "packsswb", - "packuswb", - "paddb", - "paddd", - "paddq", - "paddsb", - "paddsiw", - "paddsw", - "paddusb", - "paddusw", - "paddw", - "pand", - "pandn", - "pause", - "paveb", - "pavgb", - "pavgusb", - "pavgw", - "pcmpeqb", - "pcmpeqd", - "pcmpeqw", - "pcmpgtb", - "pcmpgtd", - "pcmpgtw", - "pdistib", - "pextrw", - "pf2id", - "pf2iw", - "pfacc", - "pfadd", - "pfcmpeq", - "pfcmpge", - "pfcmpgt", - "pfmax", - "pfmin", - "pfmul", - "pfnacc", - "pfpnacc", - "pfrcp", - "pfrcpit1", - "pfrcpit2", - "pfrsqit1", - "pfrsqrt", - "pfsub", - "pfsubr", - "pi2fd", - "pi2fw", - "pinsrw", - "pmachriw", - "pmaddwd", - "pmagw", - "pmaxsw", - "pmaxub", - "pminsw", - "pminub", - "pmovmskb", - "pmulhriw", - "pmulhrwa", - "pmulhrwc", - "pmulhuw", - "pmulhw", - "pmullw", - "pmuludq", - "pmvgezb", - "pmvlzb", - "pmvnzb", - "pmvzb", - "pop", - "popa", - "popad", - "popaw", - "popf", - "popfd", - "popfw", - "por", - "prefetch", - "prefetchnta", - "prefetcht0", - "prefetcht1", - "prefetcht2", - "prefetchw", - "psadbw", - "pshufd", - "pshufhw", - "pshuflw", - "pshufw", - "pslld", - "pslldq", - "psllq", - "psllw", - "psrad", - "psraw", - "psrld", - "psrldq", - "psrlq", - "psrlw", - "psubb", - "psubd", - "psubq", - "psubsb", - "psubsiw", - "psubsw", - "psubusb", - "psubusw", - "psubw", - "pswapd", - "punpckhbw", - "punpckhdq", - "punpckhqdq", - "punpckhwd", - "punpcklbw", - "punpckldq", - "punpcklqdq", - "punpcklwd", - "push", - "pusha", - "pushad", - "pushaw", - "pushf", - "pushfd", - "pushfw", - "pxor", - "rcl", - "rcpps", - "rcpss", - "rcr", - "rdmsr", - "rdpmc", - "rdshr", - "rdtsc", - "resb", - "resd", - "resq", - "rest", - "resw", - "ret", - "retf", - "retn", - "rol", - "ror", - "rsdc", - "rsldt", - "rsm", - "rsqrtps", - "rsqrtss", - "rsts", - "sahf", - "sal", - "salc", - "sar", - "sbb", - "scasb", - "scasd", - "scasw", - "sfence", - "sgdt", - "shl", - "shld", - "shr", - "shrd", - "shufpd", - "shufps", - "sidt", - "sldt", - "smi", - "smint", - "smintold", - "smsw", - "sqrtpd", - "sqrtps", - "sqrtsd", - "sqrtss", - "stc", - "std", - "sti", - "stmxcsr", - "stosb", - "stosd", - "stosw", - "str", - "sub", - "subpd", - "subps", - "subsd", - "subss", - "svdc", - "svldt", - "svts", - "syscall", - "sysenter", - "sysexit", - "sysret", - "test", - "ucomisd", - "ucomiss", - "ud0", - "ud1", - "ud2", - "umov", - "unpckhpd", - "unpckhps", - "unpcklpd", - "unpcklps", - "verr", - "verw", - "wait", - "wbinvd", - "wrmsr", - "wrshr", - "xadd", - "xbts", - "xchg", - "xlat", - "xlatb", - "xor", - "xorpd", - "xorps", - "xstore" -}; - -/* Conditional instructions */ -static const char *icn[] = { - "cmov", - "j", - "set" -}; - -/* and the corresponding opcodes */ -static int ico[] = { - I_CMOVcc, - I_Jcc, - I_SETcc -}; - -#define INSN_MAX 32 /* one instruction can't be longer than this */ -long disasm (unsigned char *data, char *output, int segsize, long offset); -extern struct itemplate **itable[]; - -/* - * Flags that go into the `segment' field of `insn' structures - * during disassembly. - */ -#define SEG_RELATIVE 1 -#define SEG_32BIT 2 -#define SEG_RMREG 4 -#define SEG_DISP8 8 -#define SEG_DISP16 16 -#define SEG_DISP32 32 -#define SEG_NODISP 64 -#define SEG_SIGNED 128 - -static int whichreg(long regflags, int regval) -{ - /* automatically generated from ./regs.dat - do not edit */ - static const int creg [] = {R_CR0,R_CR1,R_CR2,R_CR3,R_CR4,R_CR5,R_CR6,R_CR7}; - static const int dreg [] = {R_DR0,R_DR1,R_DR2,R_DR3,R_DR4,R_DR5,R_DR6,R_DR7}; - static const int fpureg [] = {R_ST0,R_ST1,R_ST2,R_ST3,R_ST4,R_ST5,R_ST6,R_ST7}; - static const int mmxreg [] = {R_MM0,R_MM1,R_MM2,R_MM3,R_MM4,R_MM5,R_MM6,R_MM7}; - static const int reg16 [] = {R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI}; - static const int reg32 [] = {R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI}; - static const int reg8 [] = {R_AL,R_CL,R_DL,R_BL,R_AH,R_CH,R_DH,R_BH}; - static const int sreg [] = {R_ES,R_CS,R_SS,R_DS,R_FS,R_GS,R_SEGR6,R_SEGR7}; - static const int treg [] = {R_TR0,R_TR1,R_TR2,R_TR3,R_TR4,R_TR5,R_TR6,R_TR7}; - static const int xmmreg [] = {R_XMM0,R_XMM1,R_XMM2,R_XMM3,R_XMM4,R_XMM5,R_XMM6,R_XMM7}; - - if (!(REG_AL & ~regflags)) - return R_AL; - if (!(REG_AX & ~regflags)) - return R_AX; - if (!(REG_EAX & ~regflags)) - return R_EAX; - if (!(REG_DL & ~regflags)) - return R_DL; - if (!(REG_DX & ~regflags)) - return R_DX; - if (!(REG_EDX & ~regflags)) - return R_EDX; - if (!(REG_CL & ~regflags)) - return R_CL; - if (!(REG_CX & ~regflags)) - return R_CX; - if (!(REG_ECX & ~regflags)) - return R_ECX; - if (!(FPU0 & ~regflags)) - return R_ST0; - if (!(REG_CS & ~regflags)) - return (regval == 1) ? R_CS : 0; - if (!(REG_DESS & ~regflags)) - return (regval == 0 || regval == 2 || regval == 3 ? sreg[regval] : 0); - if (!(REG_FSGS & ~regflags)) - return (regval == 4 || regval == 5 ? sreg[regval] : 0); - if (!(REG_SEG67 & ~regflags)) - return (regval == 6 || regval == 7 ? sreg[regval] : 0); - - /* All the entries below look up regval in an 8-entry array */ - if (regval < 0 || regval > 7) - return 0; - - if (!((REGMEM|BITS8) & ~regflags)) - return reg8[regval]; - if (!((REGMEM|BITS16) & ~regflags)) - return reg16[regval]; - if (!((REGMEM|BITS32) & ~regflags)) - return reg32[regval]; - if (!(REG_SREG & ~regflags)) - return sreg[regval]; - if (!(REG_CREG & ~regflags)) - return creg[regval]; - if (!(REG_DREG & ~regflags)) - return dreg[regval]; - if (!(REG_TREG & ~regflags)) - return treg[regval]; - if (!(FPUREG & ~regflags)) - return fpureg[regval]; - if (!(MMXREG & ~regflags)) - return mmxreg[regval]; - if (!(XMMREG & ~regflags)) - return xmmreg[regval]; - - return 0; -} - -static const char *whichcond(int condval) -{ - static int conds[] = { - C_O, C_NO, C_C, C_NC, C_Z, C_NZ, C_NA, C_A, - C_S, C_NS, C_PE, C_PO, C_L, C_NL, C_NG, C_G - }; - return conditions[conds[condval]]; -} - -/* - * Process an effective address (ModRM) specification. - */ -static unsigned char *do_ea (unsigned char *data, int modrm, int asize, - int segsize, operand *op) -{ - int mod, rm, scale, index, base; - - mod = (modrm >> 6) & 03; - rm = modrm & 07; - - if (mod == 3) { /* pure register version */ - op->basereg = rm; - op->segment |= SEG_RMREG; - return data; - } - - op->addr_size = 0; - - if (asize == 16) { - /* - * specifies the displacement size (none, byte or - * word), and specifies the register combination. - * Exception: mod=0,rm=6 does not specify [BP] as one might - * expect, but instead specifies [disp16]. - */ - op->indexreg = op->basereg = -1; - op->scale = 1; /* always, in 16 bits */ - switch (rm) { - case 0: op->basereg = R_BX; op->indexreg = R_SI; break; - case 1: op->basereg = R_BX; op->indexreg = R_DI; break; - case 2: op->basereg = R_BP; op->indexreg = R_SI; break; - case 3: op->basereg = R_BP; op->indexreg = R_DI; break; - case 4: op->basereg = R_SI; break; - case 5: op->basereg = R_DI; break; - case 6: op->basereg = R_BP; break; - case 7: op->basereg = R_BX; break; - } - if (rm == 6 && mod == 0) { /* special case */ - op->basereg = -1; - if (segsize != 16) - op->addr_size = 16; - mod = 2; /* fake disp16 */ - } - switch (mod) { - case 0: - op->segment |= SEG_NODISP; - break; - case 1: - op->segment |= SEG_DISP8; - op->offset = (signed char) *data++; - break; - case 2: - op->segment |= SEG_DISP16; - op->offset = *data++; - op->offset |= ((unsigned) *data++) << 8; - break; - } - return data; - } else { - /* - * Once again, specifies displacement size (this time - * none, byte or *dword*), while specifies the base - * register. Again, [EBP] is missing, replaced by a pure - * disp32 (this time that's mod=0,rm=*5*). However, rm=4 - * indicates not a single base register, but instead the - * presence of a SIB byte... - */ - op->indexreg = -1; - switch (rm) { - case 0: op->basereg = R_EAX; break; - case 1: op->basereg = R_ECX; break; - case 2: op->basereg = R_EDX; break; - case 3: op->basereg = R_EBX; break; - case 5: op->basereg = R_EBP; break; - case 6: op->basereg = R_ESI; break; - case 7: op->basereg = R_EDI; break; - } - if (rm == 5 && mod == 0) { - op->basereg = -1; - if (segsize != 32) - op->addr_size = 32; - mod = 2; /* fake disp32 */ - } - if (rm == 4) { /* process SIB */ - scale = (*data >> 6) & 03; - index = (*data >> 3) & 07; - base = *data & 07; - data++; - - op->scale = 1 << scale; - switch (index) { - case 0: op->indexreg = R_EAX; break; - case 1: op->indexreg = R_ECX; break; - case 2: op->indexreg = R_EDX; break; - case 3: op->indexreg = R_EBX; break; - case 4: op->indexreg = -1; break; - case 5: op->indexreg = R_EBP; break; - case 6: op->indexreg = R_ESI; break; - case 7: op->indexreg = R_EDI; break; - } - - switch (base) { - case 0: op->basereg = R_EAX; break; - case 1: op->basereg = R_ECX; break; - case 2: op->basereg = R_EDX; break; - case 3: op->basereg = R_EBX; break; - case 4: op->basereg = R_ESP; break; - case 6: op->basereg = R_ESI; break; - case 7: op->basereg = R_EDI; break; - case 5: - if (mod == 0) { - mod = 2; - op->basereg = -1; - } else - op->basereg = R_EBP; - break; - } - } - switch (mod) { - case 0: - op->segment |= SEG_NODISP; - break; - case 1: - op->segment |= SEG_DISP8; - op->offset = (signed char) *data++; - break; - case 2: - op->segment |= SEG_DISP32; - op->offset = *data++; - op->offset |= ((unsigned) *data++) << 8; - op->offset |= ((long) *data++) << 16; - op->offset |= ((long) *data++) << 24; - break; - } - return data; - } -} - -/* - * Determine whether the instruction template in t corresponds to the data - * stream in data. Return the number of bytes matched if so. - */ -static int matches (struct itemplate *t, unsigned char *data, int asize, - int osize, int segsize, int rep, insn *ins) -{ - unsigned char * r = (unsigned char *)(t->code); - unsigned char * origdata = data; - int a_used = FALSE, o_used = FALSE; - int drep = 0; - - if ( rep == 0xF2 ) - drep = P_REPNE; - else if ( rep == 0xF3 ) - drep = P_REP; - - while (*r) - { - int c = *r++; - if (c >= 01 && c <= 03) { - while (c--) - if (*r++ != *data++) - return FALSE; - } - if (c == 04) { - switch (*data++) { - case 0x07: ins->oprs[0].basereg = 0; break; - case 0x17: ins->oprs[0].basereg = 2; break; - case 0x1F: ins->oprs[0].basereg = 3; break; - default: return FALSE; - } - } - if (c == 05) { - switch (*data++) { - case 0xA1: ins->oprs[0].basereg = 4; break; - case 0xA9: ins->oprs[0].basereg = 5; break; - default: return FALSE; - } - } - if (c == 06) { - switch (*data++) { - case 0x06: ins->oprs[0].basereg = 0; break; - case 0x0E: ins->oprs[0].basereg = 1; break; - case 0x16: ins->oprs[0].basereg = 2; break; - case 0x1E: ins->oprs[0].basereg = 3; break; - default: return FALSE; - } - } - if (c == 07) { - switch (*data++) { - case 0xA0: ins->oprs[0].basereg = 4; break; - case 0xA8: ins->oprs[0].basereg = 5; break; - default: return FALSE; - } - } - if (c >= 010 && c <= 012) { - int t = *r++, d = *data++; - if (d < t || d > t+7) - return FALSE; - else { - ins->oprs[c-010].basereg = d-t; - ins->oprs[c-010].segment |= SEG_RMREG; - } - } - if (c == 017) - if (*data++) - return FALSE; - if (c >= 014 && c <= 016) { - ins->oprs[c-014].offset = (signed char) *data++; - ins->oprs[c-014].segment |= SEG_SIGNED; - } - if (c >= 020 && c <= 022) - ins->oprs[c-020].offset = *data++; - if (c >= 024 && c <= 026) - ins->oprs[c-024].offset = *data++; - if (c >= 030 && c <= 032) { - ins->oprs[c-030].offset = *data++; - ins->oprs[c-030].offset |= (((unsigned) *data++) << 8); - } - if (c >= 034 && c <= 036) { - ins->oprs[c-034].offset = *data++; - ins->oprs[c-034].offset |= (((unsigned) *data++) << 8); - if (osize == 32) { - ins->oprs[c-034].offset |= (((long) *data++) << 16); - ins->oprs[c-034].offset |= (((long) *data++) << 24); - } - if (segsize != asize) - ins->oprs[c-034].addr_size = asize; - } - if (c >= 040 && c <= 042) { - ins->oprs[c-040].offset = *data++; - ins->oprs[c-040].offset |= (((unsigned) *data++) << 8); - ins->oprs[c-040].offset |= (((long) *data++) << 16); - ins->oprs[c-040].offset |= (((long) *data++) << 24); - } - if (c >= 044 && c <= 046) { - ins->oprs[c-044].offset = *data++; - ins->oprs[c-044].offset |= (((unsigned) *data++) << 8); - if (asize == 32) { - ins->oprs[c-044].offset |= (((long) *data++) << 16); - ins->oprs[c-044].offset |= (((long) *data++) << 24); - } - if (segsize != asize) - ins->oprs[c-044].addr_size = asize; - } - if (c >= 050 && c <= 052) { - ins->oprs[c-050].offset = (signed char) *data++; - ins->oprs[c-050].segment |= SEG_RELATIVE; - } - if (c >= 060 && c <= 062) { - ins->oprs[c-060].offset = *data++; - ins->oprs[c-060].offset |= (((unsigned) *data++) << 8); - ins->oprs[c-060].segment |= SEG_RELATIVE; - ins->oprs[c-060].segment &= ~SEG_32BIT; - } - if (c >= 064 && c <= 066) { - ins->oprs[c-064].offset = *data++; - ins->oprs[c-064].offset |= (((unsigned) *data++) << 8); - if (osize == 32) { - ins->oprs[c-064].offset |= (((long) *data++) << 16); - ins->oprs[c-064].offset |= (((long) *data++) << 24); - ins->oprs[c-064].segment |= SEG_32BIT; - } else - ins->oprs[c-064].segment &= ~SEG_32BIT; - ins->oprs[c-064].segment |= SEG_RELATIVE; - if (segsize != osize) { - ins->oprs[c-064].type = - (ins->oprs[c-064].type & NON_SIZE) - | ((osize == 16) ? BITS16 : BITS32); - } - } - if (c >= 070 && c <= 072) { - ins->oprs[c-070].offset = *data++; - ins->oprs[c-070].offset |= (((unsigned) *data++) << 8); - ins->oprs[c-070].offset |= (((long) *data++) << 16); - ins->oprs[c-070].offset |= (((long) *data++) << 24); - ins->oprs[c-070].segment |= SEG_32BIT | SEG_RELATIVE; - } - if (c >= 0100 && c < 0130) { - int modrm = *data++; - ins->oprs[c & 07].basereg = (modrm >> 3) & 07; - ins->oprs[c & 07].segment |= SEG_RMREG; - data = do_ea (data, modrm, asize, segsize, - &ins->oprs[(c >> 3) & 07]); - } - if (c >= 0130 && c <= 0132) { - ins->oprs[c-0130].offset = *data++; - ins->oprs[c-0130].offset |= (((unsigned) *data++) << 8); - } - if (c >= 0140 && c <= 0142) { - ins->oprs[c-0140].offset = *data++; - ins->oprs[c-0140].offset |= (((unsigned) *data++) << 8); - ins->oprs[c-0140].offset |= (((long) *data++) << 16); - ins->oprs[c-0140].offset |= (((long) *data++) << 24); - } - if (c >= 0200 && c <= 0277) { - int modrm = *data++; - if (((modrm >> 3) & 07) != (c & 07)) - return FALSE; /* spare field doesn't match up */ - data = do_ea (data, modrm, asize, segsize, - &ins->oprs[(c >> 3) & 07]); - } - if (c >= 0300 && c <= 0302) { - if (asize) - ins->oprs[c-0300].segment |= SEG_32BIT; - else - ins->oprs[c-0300].segment &= ~SEG_32BIT; - a_used = TRUE; - } - if (c == 0310) { - if (asize == 32) - return FALSE; - else - a_used = TRUE; - } - if (c == 0311) { - if (asize == 16) - return FALSE; - else - a_used = TRUE; - } - if (c == 0312) { - if (asize != segsize) - return FALSE; - else - a_used = TRUE; - } - if (c == 0320) { - if (osize == 32) - return FALSE; - else - o_used = TRUE; - } - if (c == 0321) { - if (osize == 16) - return FALSE; - else - o_used = TRUE; - } - if (c == 0322) { - if (osize != segsize) - return FALSE; - else - o_used = TRUE; - } - if (c == 0330) { - int t = *r++, d = *data++; - if (d < t || d > t+15) - return FALSE; - else - ins->condition = d - t; - } - if (c == 0331) { - if ( rep ) - return FALSE; - } - if (c == 0332) { - if (drep == P_REP) - drep = P_REPE; - } - if (c == 0333) { - if ( rep != 0xF3 ) - return FALSE; - drep = 0; - } - } - - /* - * Check for unused rep or a/o prefixes. - */ - ins->nprefix = 0; - if (drep) - ins->prefixes[ins->nprefix++] = drep; - if (!a_used && asize != segsize) - ins->prefixes[ins->nprefix++] = (asize == 16 ? P_A16 : P_A32); - if (!o_used && osize != segsize) - ins->prefixes[ins->nprefix++] = (osize == 16 ? P_O16 : P_O32); - - return data - origdata; -} - -long disasm (unsigned char *data, char *output, int segsize, long offset) -{ - struct itemplate **p, **best_p; - int length, best_length = 0; - char *segover; - int rep, lock, asize, osize, i, slen, colon; - unsigned char *origdata; - int works; - insn tmp_ins, ins; - unsigned long goodness, best; - - /* - * Scan for prefixes. - */ - asize = osize = segsize; - segover = NULL; - ins.condition = ins.nprefix = rep = lock = 0; - origdata = data; - for (;;) { - if (*data == 0xF3 || *data == 0xF2) - rep = *data++; - else if (*data == 0xF0) - lock = *data++; - else if (*data == 0x2E || *data == 0x36 || *data == 0x3E || - *data == 0x26 || *data == 0x64 || *data == 0x65) { - switch (*data++) { - case 0x2E: segover = "cs"; break; - case 0x36: segover = "ss"; break; - case 0x3E: segover = "ds"; break; - case 0x26: segover = "es"; break; - case 0x64: segover = "fs"; break; - case 0x65: segover = "gs"; break; - } - } else if (*data == 0x66) - osize = 48 - segsize, data++; - else if (*data == 0x67) - asize = 48 - segsize, data++; - else - break; - } - - tmp_ins.oprs[0].segment = tmp_ins.oprs[1].segment = - tmp_ins.oprs[2].segment = - tmp_ins.oprs[0].addr_size = tmp_ins.oprs[1].addr_size = - tmp_ins.oprs[2].addr_size = (segsize == 16 ? 0 : SEG_32BIT); - tmp_ins.condition = -1; - best = ~0UL; /* Worst possible */ - best_p = NULL; - for (p = itable[*data]; *p; p++) { - if ( (length = matches(*p, data, asize, osize, - segsize, rep, &tmp_ins)) ) { - works = TRUE; - /* - * Final check to make sure the types of r/m match up. - */ - for (i = 0; i < (*p)->operands; i++) { - if ( - /* If it's a mem-only EA but we have a register, die. */ - ((tmp_ins.oprs[i].segment & SEG_RMREG) && - !(MEMORY & ~(*p)->opd[i])) || - - /* If it's a reg-only EA but we have a memory ref, die. */ - (!(tmp_ins.oprs[i].segment & SEG_RMREG) && - !(REGNORM & ~(*p)->opd[i]) && - !((*p)->opd[i] & REG_SMASK)) || - - /* Register type mismatch (eg FS vs REG_DESS): die. */ - ((((*p)->opd[i] & (REGISTER | FPUREG)) || - (tmp_ins.oprs[i].segment & SEG_RMREG)) && - !whichreg ((*p)->opd[i], tmp_ins.oprs[i].basereg))) { - works = FALSE; - break; - } - } - - if (works) { - goodness = (*p)->flags & IF_PFMASK; - if ( goodness < best ) { - /* This is the best one found so far */ - best = goodness; - best_p = p; - best_length = length; - ins = tmp_ins; - } - } - } - } - - if (!best_p) { /* no instruction was matched */ - sprintf(output, "db 0%02xh", data[0]); - return 1; - } - - /* Pick the best match */ - p = best_p; - length = best_length; - - slen = 0; - - if (lock) - slen += sprintf(output+slen, "lock "); - for (i = 0; i < ins.nprefix; i++) - switch (ins.prefixes[i]) { - case P_REP: slen += sprintf(output+slen, "rep "); break; - case P_REPE: slen += sprintf(output+slen, "repe "); break; - case P_REPNE: slen += sprintf(output+slen, "repne "); break; - case P_A16: slen += sprintf(output+slen, "a16 "); break; - case P_A32: slen += sprintf(output+slen, "a32 "); break; - case P_O16: slen += sprintf(output+slen, "o16 "); break; - case P_O32: slen += sprintf(output+slen, "o32 "); break; - } - - for (i = 0; i < (int)elements(ico); i++) - if ((*p)->opcode == ico[i]) { - slen += sprintf(output+slen, "%s%s", icn[i], - whichcond(ins.condition)); - break; - } - if (i >= (int)elements(ico)) - slen += sprintf(output+slen, "%s", insn_names[(*p)->opcode]); - colon = FALSE; - length += data - origdata; /* fix up for prefixes */ - for (i=0; i<(*p)->operands; i++) { - output[slen++] = (colon ? ':' : i==0 ? ' ' : ','); - - if (ins.oprs[i].segment & SEG_RELATIVE) { - ins.oprs[i].offset += offset + length; - /* - * sort out wraparound - */ - if (!(ins.oprs[i].segment & SEG_32BIT)) - ins.oprs[i].offset &= 0xFFFF; - } - - if ((*p)->opd[i] & COLON) - colon = TRUE; - else - colon = FALSE; - - if (((*p)->opd[i] & (REGISTER | FPUREG)) || - (ins.oprs[i].segment & SEG_RMREG)) - { - ins.oprs[i].basereg = whichreg ((*p)->opd[i], - ins.oprs[i].basereg); - if ( (*p)->opd[i] & TO ) - slen += sprintf(output+slen, "to "); - slen += sprintf(output+slen, "%s", - reg_names[ins.oprs[i].basereg-EXPR_REG_START]); - } else if (!(UNITY & ~(*p)->opd[i])) { - output[slen++] = '1'; - } else if ( (*p)->opd[i] & IMMEDIATE ) { - if ( (*p)->opd[i] & BITS8 ) { - slen += sprintf(output+slen, "byte "); - if (ins.oprs[i].segment & SEG_SIGNED) { - if (ins.oprs[i].offset < 0) { - ins.oprs[i].offset *= -1; - output[slen++] = '-'; - } else - output[slen++] = '+'; - } - } else if ( (*p)->opd[i] & BITS16 ) { - slen += sprintf(output+slen, "word "); - } else if ( (*p)->opd[i] & BITS32 ) { - slen += sprintf(output+slen, "dword "); - } else if ( (*p)->opd[i] & NEAR ) { - slen += sprintf(output+slen, "near "); - } else if ( (*p)->opd[i] & SHORT ) { - slen += sprintf(output+slen, "short "); - } - slen += sprintf(output+slen, "0x%lx", ins.oprs[i].offset); - } else if ( !(MEM_OFFS & ~(*p)->opd[i]) ) { - slen += sprintf(output+slen, "[%s%s%s0x%lx]", - (segover ? segover : ""), - (segover ? ":" : ""), - (ins.oprs[i].addr_size == 32 ? "dword " : - ins.oprs[i].addr_size == 16 ? "word " : ""), - ins.oprs[i].offset); - segover = NULL; - } else if ( !(REGMEM & ~(*p)->opd[i]) ) { - int started = FALSE; - if ( (*p)->opd[i] & BITS8 ) - slen += sprintf(output+slen, "byte "); - if ( (*p)->opd[i] & BITS16 ) - slen += sprintf(output+slen, "word "); - if ( (*p)->opd[i] & BITS32 ) - slen += sprintf(output+slen, "dword "); - if ( (*p)->opd[i] & BITS64 ) - slen += sprintf(output+slen, "qword "); - if ( (*p)->opd[i] & BITS80 ) - slen += sprintf(output+slen, "tword "); - if ( (*p)->opd[i] & FAR ) - slen += sprintf(output+slen, "far "); - if ( (*p)->opd[i] & NEAR ) - slen += sprintf(output+slen, "near "); - output[slen++] = '['; - if (ins.oprs[i].addr_size) - slen += sprintf(output+slen, "%s", - (ins.oprs[i].addr_size == 32 ? "dword " : - ins.oprs[i].addr_size == 16 ? "word " : "")); - if (segover) { - slen += sprintf(output+slen, "%s:", segover); - segover = NULL; - } - if (ins.oprs[i].basereg != -1) { - slen += sprintf(output+slen, "%s", - reg_names[(ins.oprs[i].basereg - - EXPR_REG_START)]); - started = TRUE; - } - if (ins.oprs[i].indexreg != -1) { - if (started) - output[slen++] = '+'; - slen += sprintf(output+slen, "%s", - reg_names[(ins.oprs[i].indexreg - - EXPR_REG_START)]); - if (ins.oprs[i].scale > 1) - slen += sprintf(output+slen, "*%d", ins.oprs[i].scale); - started = TRUE; - } - if (ins.oprs[i].segment & SEG_DISP8) { - int sign = '+'; - if (ins.oprs[i].offset & 0x80) { - ins.oprs[i].offset = - (signed char) ins.oprs[i].offset; - sign = '-'; - } - slen += sprintf(output+slen, "%c0x%lx", sign, - ins.oprs[i].offset); - } else if (ins.oprs[i].segment & SEG_DISP16) { - if (started) - output[slen++] = '+'; - slen += sprintf(output+slen, "0x%lx", ins.oprs[i].offset); - } else if (ins.oprs[i].segment & SEG_DISP32) { - if (started) - output[slen++] = '+'; - slen += sprintf(output+slen, "0x%lx", ins.oprs[i].offset); - } - output[slen++] = ']'; - } else { - slen += sprintf(output+slen, "", i); - } - } - output[slen] = '\0'; - if (segover) { /* unused segment override */ - char *p = output; - int count = slen+1; - while (count--) - p[count+3] = p[count]; - strncpy (output, segover, 2); - output[2] = ' '; - } - return length; -} diff --git a/AltairZ80/flashwriter2.c b/AltairZ80/flashwriter2.c deleted file mode 100644 index ba11478f..00000000 --- a/AltairZ80/flashwriter2.c +++ /dev/null @@ -1,315 +0,0 @@ -/************************************************************************* - * * - * $Id: flashwriter2.c 1941 2008-06-13 05:31:03Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Vector Graphic, Inc. FlashWriter II module for SIMH * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/*#define DBG_MSG*/ - -#include "altairz80_defs.h" - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -extern int32 sio0s(const int32 port, const int32 io, const int32 data); -extern int32 sio0d(const int32 port, const int32 io, const int32 data); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); - -static char ansibuf[10]; - -#define FW2_MAX_BOARDS 4 -#define UNIT_V_FW2_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_FW2_VERBOSE (1 << UNIT_V_FW2_VERBOSE) -#define FW2_CAPACITY (2048) /* FlashWriter II Memory Size */ - -typedef struct { - UNIT *uptr; /* UNIT pointer */ - uint8 cur_FL_Row; /* Current Flashwriter Row */ - uint8 cur_FL_Col; /* Current Flashwriter Column */ - uint8 FL_Row; - uint8 FL_Col; - uint8 reversevideo; /* Flag set if reverse video is currently on */ - uint8 M[FW2_CAPACITY]; /* FlashWriter 2K Video Memory */ -} FW2_INFO; - -static FW2_INFO *fw2_info[FW2_MAX_BOARDS]; -static uint8 port_map[FW2_MAX_BOARDS] = { 0x11, 0x15, 0x17, 0x19 }; - -static int32 fw2dev(const int32 Addr, const int32 rw, const int32 data); -static t_stat fw2_attach(UNIT *uptr, char *cptr); -static t_stat fw2_detach(UNIT *uptr); -static uint8 FW2_Read(const uint32 Addr); -static uint8 FW2_Write(const uint32 Addr, uint8 cData); -static t_stat get_base_address(char *cptr, uint32 *baseaddr); - -static UNIT fw2_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) } -}; - -static MTAB fw2_mod[] = { - /* quiet, no warning messages */ - { UNIT_FW2_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_FW2_VERBOSE, UNIT_FW2_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -DEVICE fw2_dev = { - "FWII", fw2_unit, NULL, fw2_mod, - FW2_MAX_BOARDS, 10, 31, 1, FW2_MAX_BOARDS, FW2_MAX_BOARDS, - NULL, NULL, NULL, - NULL, &fw2_attach, &fw2_detach, - NULL, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, "Vector Graphic Flashwriter 2 FWII" -}; - -/* Attach routine */ -static t_stat fw2_attach(UNIT *uptr, char *cptr) -{ - t_stat r; - unsigned int i = 0; - uint32 baseaddr; - char *tptr; - - r = get_base_address(cptr, &baseaddr); - if(r != SCPE_OK) /* error? */ - return r; - - DBG_PRINT(("%s\n", __FUNCTION__)); - - for(i = 0; i < FW2_MAX_BOARDS; i++) { - if(&fw2_dev.units[i] == uptr) { - if(uptr->flags & UNIT_FW2_VERBOSE) { - printf("Attaching unit %d at %04x\n", i, baseaddr); - } - break; - } - } - - fw2_info[i] = calloc(1, sizeof(FW2_INFO)); - fw2_info[i]->uptr = uptr; - fw2_info[i]->uptr->u3 = baseaddr; - - if(sim_map_resource(baseaddr, FW2_CAPACITY, RESOURCE_TYPE_MEMORY, &fw2dev, FALSE) != 0) { - printf("%s: error mapping MEM resource at 0x%04x\n", __FUNCTION__, baseaddr); - return SCPE_ARG; - } - - if(sim_map_resource(0x00, 1, RESOURCE_TYPE_IO, &sio0s, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, 0x00); - return SCPE_ARG; - } - - if(sim_map_resource(0x01, 1, RESOURCE_TYPE_IO, &sio0d, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, 0x01); - return SCPE_ARG; - } - - tptr = (char *) malloc (strlen (cptr) + 3); /* get string buf */ - if (tptr == NULL) - return SCPE_MEM; /* no more mem? */ - sprintf(tptr, "0x%04x", baseaddr); /* copy base address */ - uptr->filename = tptr; /* save */ - uptr->flags = uptr->flags | UNIT_ATT; - return SCPE_OK; -} - - -/* Detach routine */ -static t_stat fw2_detach(UNIT *uptr) -{ - uint8 i; - - DBG_PRINT(("%s\n", __FUNCTION__)); - - for(i = 0; i < FW2_MAX_BOARDS; i++) { - if(&fw2_dev.units[i] == uptr) { - break; - } - } - - if (i >= FW2_MAX_BOARDS) - return SCPE_ARG; - - /* Disconnect FlashWriter2: unmap memory and I/O resources */ - sim_map_resource(fw2_info[i]->uptr->u3, FW2_CAPACITY, RESOURCE_TYPE_MEMORY, &fw2dev, TRUE); - sim_map_resource(0x00, 1, RESOURCE_TYPE_IO, &sio0s, TRUE); - sim_map_resource(0x01, 1, RESOURCE_TYPE_IO, &sio0d, TRUE); - - if(fw2_info[i]) { - free(fw2_info[i]); - } - - free (uptr->filename); /* free base address string */ - uptr->filename = NULL; - uptr->flags = uptr->flags & ~UNIT_ATT; /* not attached */ - return SCPE_OK; -} - -static t_stat get_base_address(char *cptr, uint32 *baseaddr) -{ - uint32 b; - sscanf(cptr, "%x", &b); - if(b & (FW2_CAPACITY-1)) { - printf("FWII must be on a %d-byte boundary.\n", FW2_CAPACITY); - return SCPE_ARG; - } - *baseaddr = b & ~(FW2_CAPACITY-1); - return SCPE_OK; -} - -extern int32 getBankSelect(void); - -/* This is the main entry point into the Flashwriter2 emulation. */ -static int32 fw2dev(const int32 Addr, const int32 rw, const int32 data) -{ - int32 bank = getBankSelect(); - if(bank == 0) { - if(rw == 0) { /* Read */ - return(FW2_Read(Addr)); - } else { /* Write */ - return(FW2_Write(Addr, data)); - } - } else - return 0xff; -} - - -static uint8 FW2_Write(const uint32 Addr, uint8 Value) -{ - FW2_INFO *fw2 = NULL; - uint8 FL_Row; - uint8 FL_Col; - uint32 baseaddr = 0; - uint8 i; - uint8 outchar; - uint8 port; - - for(i = 0; i < FW2_MAX_BOARDS; i++) { - if(fw2_info[i] != NULL) { - baseaddr = fw2_info[i]->uptr->u3; - if((Addr >= baseaddr) && (Addr < (baseaddr + FW2_CAPACITY))) { - break; - } - } - } - - if(i == FW2_MAX_BOARDS) { - return 0; - } - - fw2 = fw2_info[i]; - port = port_map[i]; - - fw2->M[Addr - baseaddr] = Value; - - /* Only print if it is in the visible part of the Flashwriter memory */ - if((Addr >= baseaddr) && (Addr < (baseaddr + (80 * 24)))) { - FL_Col = ((Addr-baseaddr) % 80) + 1; - FL_Row = ((Addr-baseaddr) / 80) + 1; - - if(Value & 0x80) { /* reverse video */ - if(fw2->reversevideo == 0) { - fw2->reversevideo = 1; - sprintf(ansibuf, "\x1b[07m"); - for(i=0;ireversevideo == 1) { - fw2->reversevideo = 0; - sprintf(ansibuf, "\x1b[00m"); - for(i=0;icur_FL_Row == FL_Row) && (FL_Col == fw2->cur_FL_Col + 1)) { - sio0d(port, 1, outchar); - } else { - /* ESC[#;#H */ - sprintf(ansibuf, "\x1b[%d;%dH%c", FL_Row, FL_Col, outchar); - for(i=0;icur_FL_Col = FL_Col; - fw2->cur_FL_Row = FL_Row; - } - - return(1); -} - - -static uint8 FW2_Read(const uint32 Addr) -{ - uint32 baseaddr = 0; - uint8 i; - - for(i = 0; i < FW2_MAX_BOARDS; i++) { - if(fw2_info[i] != NULL) { - baseaddr = fw2_info[i]->uptr->u3; - if((Addr >= baseaddr) && (Addr < (baseaddr + FW2_CAPACITY))) { - break; - } - } - } - - if(i == FW2_MAX_BOARDS) { - return 0xFF; - } - - return(fw2_info[i]->M[Addr - baseaddr]); -} diff --git a/AltairZ80/i8272.c b/AltairZ80/i8272.c deleted file mode 100644 index bf7451da..00000000 --- a/AltairZ80/i8272.c +++ /dev/null @@ -1,972 +0,0 @@ -/************************************************************************* - * * - * $Id: i8272.c 1999 2008-07-22 04:25:28Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Generic Intel 8272 Disk Controller module for SIMH. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/* Change log: - - 19-Apr-2008, Tony Nicholson, added other .IMD formats - - 06-Aug-2008, Tony Nicholson, READID should use HDS bit and add support - for logical Head and Cylinder maps in the .IMD image file (AGN) -*/ - -/*#define DBG_MSG */ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#include "sim_imd.h" -#include "i8272.h" - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define STATUS_MSG (1 << 5) -#define FMT_MSG (1 << 6) -#define VERBOSE_MSG (1 << 7) -#define IRQ_MSG (1 << 8) - -#define I8272_MAX_DRIVES 4 -#define I8272_MAX_SECTOR 26 -#define I8272_SECTOR_LEN 8192 -/* 2^(7 + I8272_MAX_N) == I8272_SECTOR_LEN */ -#define I8272_MAX_N 6 - -#define CMD_PHASE 0 -#define EXEC_PHASE 1 -#define DATA_PHASE 2 - -typedef union { - uint8 raw[I8272_SECTOR_LEN]; -} SECTOR_FORMAT; - -typedef struct { - UNIT *uptr; - DISK_INFO *imd; - uint8 ntracks; /* number of tracks */ - uint8 nheads; /* number of heads */ - uint32 sectsize; /* sector size, not including pre/postamble */ - uint8 track; /* Current Track */ - uint8 ready; /* Is drive ready? */ -} I8272_DRIVE_INFO; - -typedef struct { - PNP_INFO pnp; /* Plug-n-Play Information */ - uint32 fdc_dma_addr;/* DMA Transfer Address */ - uint8 fdc_msr; /* 8272 Main Status Register */ - uint8 fdc_phase; /* Phase that the 8272 is currently in */ - uint8 fdc_srt; /* Step Rate in ms */ - uint8 fdc_hut; /* Head Unload Time in ms */ - uint8 fdc_hlt; /* Head Load Time in ms */ - uint8 fdc_nd; /* Non-DMA Mode 1=Non-DMA, 0=DMA */ - uint8 fdc_head; /* H Head Number */ - uint8 fdc_sector; /* R Record (Sector) */ - uint8 fdc_sec_len; /* N Sector Length, in bytes: 2^(7 + fdc_sec_len), fdc_sec_len <= I8272_MAX_N */ - uint8 fdc_eot; /* EOT End of Track (Final sector number of cyl) */ - uint8 fdc_gpl; /* GPL Gap3 Length */ - uint8 fdc_dtl; /* DTL Data Length */ - uint8 fdc_mt; /* Multiple sectors */ - uint8 fdc_mfm; /* MFM mode */ - uint8 fdc_sk; /* Skip Deleted Data */ - uint8 fdc_hds; /* Head Select */ - uint8 fdc_fillbyte; /* Fill-byte used for FORMAT TRACK */ - uint8 fdc_sc; /* Sector count for FORMAT TRACK */ - uint8 fdc_sectorcount; /* Current sector being formatted by FORMAT TRACK */ - uint8 fdc_sectormap[I8272_MAX_SECTOR]; /* Physical to logical sector map for FORMAT TRACK */ - uint8 fdc_status[3];/* Status Register Bytes */ - uint8 fdc_seek_end; /* Seek was executed successfully */ - uint8 cmd_index; /* Index of command byte */ - uint8 cmd[10]; /* Storage for current command */ - uint8 cmd_len; /* FDC Command Length */ - uint8 result_index; /* Index of result byte */ - uint8 result[10]; /* Result data */ - uint8 result_len; /* FDC Result Length */ - uint8 sel_drive; /* Currently selected drive */ - I8272_DRIVE_INFO drive[I8272_MAX_DRIVES]; -} I8272_INFO; - -static SECTOR_FORMAT sdata; -extern uint32 PCX; -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); - -/* These are needed for DMA. PIO Mode has not been implemented yet. */ -extern void PutByteDMA(const uint32 Addr, const uint32 Value); -extern uint8 GetByteDMA(const uint32 Addr); - -#define UNIT_V_I8272_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_I8272_WLK (1 << UNIT_V_I8272_WLK) -#define UNIT_V_I8272_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_I8272_VERBOSE (1 << UNIT_V_I8272_VERBOSE) -#define I8272_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ -#define I8272_CAPACITY_SSSD (77*1*26*128) /* Single-sided Single Density IBM Diskette1 */ - -/* Intel 8272 Commands */ -#define I8272_READ_TRACK 0x02 -#define I8272_SPECIFY 0x03 -#define I8272_SENSE_DRIVE_STATUS 0x04 -#define I8272_WRITE_DATA 0x05 -#define I8272_READ_DATA 0x06 -#define I8272_RECALIBRATE 0x07 -#define I8272_SENSE_INTR_STATUS 0x08 -#define I8272_WRITE_DELETED_DATA 0x09 -#define I8272_READ_ID 0x0A -#define I8272_READ_DELETED_DATA 0x0C -#define I8272_FORMAT_TRACK 0x0D -#define I8272_SEEK 0x0F -#define I8272_SCAN_EQUAL 0x11 -#define I8272_SCAN_LOW_EQUAL 0x19 -#define I8272_SCAN_HIGH_EQUAL 0x1D - -/* SENSE DRIVE STATUS bit definitions */ -#define DRIVE_STATUS_TWO_SIDED 0x08 -#define DRIVE_STATUS_TRACK0 0x10 -#define DRIVE_STATUS_READY 0x20 -#define DRIVE_STATUS_WP 0x40 -#define DRIVE_STATUS_FAULT 0x80 - -static void raise_i8272_interrupt(void); -static int32 i8272dev(const int32 port, const int32 io, const int32 data); -static t_stat i8272_reset(DEVICE *dptr); -int32 find_unit_index (UNIT *uptr); - -I8272_INFO i8272_info_data = { { 0x0, 0, 0xC0, 2 } }; -I8272_INFO *i8272_info = &i8272_info_data; - -uint8 i8272_irq = 1; - -static UNIT i8272_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, I8272_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, I8272_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, I8272_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, I8272_CAPACITY) } -}; - -static MTAB i8272_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_I8272_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_I8272_WLK, UNIT_I8272_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_I8272_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_I8272_VERBOSE, UNIT_I8272_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB i8272_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "CMD", CMD_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "STATUS", STATUS_MSG }, - { "FMT", FMT_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { "IRQ", IRQ_MSG }, - { NULL, 0 } -}; - -DEVICE i8272_dev = { - "I8272", i8272_unit, NULL, i8272_mod, - I8272_MAX_DRIVES, 10, 31, 1, I8272_MAX_DRIVES, I8272_MAX_DRIVES, - NULL, NULL, &i8272_reset, - NULL, &i8272_attach, &i8272_detach, - &i8272_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - i8272_dt, NULL, "Intel/NEC(765) FDC Core I8272" -}; - -static uint8 I8272_Setup_Cmd(uint8 fdc_cmd); - - -/* Reset routine */ -static t_stat i8272_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &i8272dev, TRUE); - } else { - /* Connect I/O Ports at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &i8272dev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - return SCPE_OK; -} - - -/* find_unit_index find index of a unit - - Inputs: - uptr = pointer to unit - Outputs: - result = index of device -*/ -int32 find_unit_index (UNIT *uptr) -{ - DEVICE *dptr; - uint32 i; - - if (uptr == NULL) - return (-1); - dptr = find_dev_from_unit(uptr); - for(i=0; inumunits; i++) { - if(dptr->units + i == uptr) { - break; - } - } - if(i == dptr->numunits) { - return (-1); - } - return (i); -} - -/* Attach routine */ -t_stat i8272_attach(UNIT *uptr, char *cptr) -{ - char header[4]; - t_stat r; - int32 i = 0; - - r = attach_unit(uptr, cptr); /* attach unit */ - if ( r != SCPE_OK) /* error? */ - return r; - - /* Determine length of this disk */ - uptr->capac = sim_fsize(uptr->fileref); - - i = find_unit_index(uptr); - - if (i == -1) { - return (SCPE_IERR); - } - - DBG_PRINT(("Attach I8272%d\n", i)); - i8272_info->drive[i].uptr = uptr; - - /* Default to drive not ready */ - i8272_info->drive[i].ready = 0; - - if(uptr->capac > 0) { - char *rtn = fgets(header, 4, uptr->fileref); - if((rtn != NULL) && strncmp(header, "IMD", 3)) { - printf("I8272: Only IMD disk images are supported\n"); - i8272_info->drive[i].uptr = NULL; - return SCPE_OPENERR; - } - } else { - /* create a disk image file in IMD format. */ - if (diskCreate(uptr->fileref, "$Id: i8272.c 1999 2008-07-22 04:25:28Z hharte $") != SCPE_OK) { - printf("I8272: Failed to create IMD disk.\n"); - i8272_info->drive[i].uptr = NULL; - return SCPE_OPENERR; - } - uptr->capac = sim_fsize(uptr->fileref); - } - - uptr->u3 = IMAGE_TYPE_IMD; - - if (uptr->flags & UNIT_I8272_VERBOSE) { - printf("I8272%d: attached to '%s', type=%s, len=%d\n", i, cptr, - uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", - uptr->capac); - } - - if(uptr->u3 == IMAGE_TYPE_IMD) { - if (uptr->flags & UNIT_I8272_VERBOSE) - printf("--------------------------------------------------------\n"); - i8272_info->drive[i].imd = diskOpen(uptr->fileref, uptr->flags & UNIT_I8272_VERBOSE); - if (uptr->flags & UNIT_I8272_VERBOSE) - printf("\n"); - if (i8272_info->drive[i].imd == NULL) { - printf("I8272: IMD disk corrupt.\n"); - i8272_info->drive[i].uptr = NULL; - return SCPE_OPENERR; - } - i8272_info->drive[i].ready = 1; - } else { - i8272_info->drive[i].imd = NULL; - } - - return SCPE_OK; -} - - -/* Detach routine */ -t_stat i8272_detach(UNIT *uptr) -{ - t_stat r; - int8 i; - - i = find_unit_index(uptr); - - if (i == -1) { - return (SCPE_IERR); - } - - DBG_PRINT(("Detach I8272%d\n", i)); - r = diskClose(&i8272_info->drive[i].imd); - i8272_info->drive[i].ready = 0; - if (r != SCPE_OK) - return r; - - r = detach_unit(uptr); /* detach unit */ - if (r != SCPE_OK) - return r; - - return SCPE_OK; -} - - -static int32 i8272dev(const int32 port, const int32 io, const int32 data) -{ - DBG_PRINT(("I8272: " ADDRESS_FORMAT " %s, Port 0x%02x Data 0x%02x" NLP, - PCX, io ? "OUT" : " IN", port, data)); - if(io) { - I8272_Write(port, data); - return 0; - } else { - return(I8272_Read(port)); - } -} - -uint8 I8272_Set_DMA(const uint32 dma_addr) -{ - i8272_info->fdc_dma_addr = dma_addr & 0xFFFFFF; - - return 0; -} - -extern uint8 floorlog2(unsigned int n); - -#define I8272_MSR_RQM (1 << 7) -#define I8272_MSR_DATA_OUT (1 << 6) -#define I8272_MSR_NON_DMA (1 << 5) -#define I8272_MSR_FDC_BUSY (1 << 4) - -uint8 I8272_Read(const uint32 Addr) -{ - uint8 cData; - I8272_DRIVE_INFO *pDrive; - - pDrive = &i8272_info->drive[i8272_info->sel_drive]; - - if(pDrive->uptr == NULL) { - return 0xFF; - } - - /* the switch statement ensures that cData is set in all cases! */ - switch(Addr & 0x3) { - case I8272_FDC_MSR: - cData = i8272_info->fdc_msr | I8272_MSR_RQM; - if(i8272_info->fdc_phase == CMD_PHASE) { - cData &= ~I8272_MSR_DATA_OUT; - } else { - cData |= I8272_MSR_DATA_OUT; - } -#if 0 - if(i8272_info->fdc_phase == EXEC_PHASE) { - cData |= I8272_MSR_FDC_BUSY; - } else { - cData |= ~I8272_MSR_FDC_BUSY; - } -#endif /* 0 hharte */ - sim_debug(STATUS_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " RD FDC MSR = 0x%02x\n", PCX, cData); - break; - case I8272_FDC_DATA: - if(i8272_info->fdc_phase == DATA_PHASE) { - cData = i8272_info->result[i8272_info->result_index]; - sim_debug(VERBOSE_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " RD Data, phase=%d, [%d]=0x%02x\n", - PCX, i8272_info->fdc_phase, i8272_info->result_index, cData); - i8272_irq = 0; - i8272_info->result_index ++; - if(i8272_info->result_index == i8272_info->result_len) { - sim_debug(VERBOSE_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " result phase complete.\n", PCX); - i8272_info->fdc_phase = CMD_PHASE; - } - } else { - cData = i8272_info->result[0]; /* hack, in theory any value should be ok but this makes "format" work */ - sim_debug(VERBOSE_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " error, reading data register when not in data phase. " - "Returning 0x%02x\n", PCX, cData); - } - break; - default: - sim_debug(VERBOSE_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Cannot read register %x\n", PCX, Addr); - cData = 0xFF; - } - - return (cData); -} - -static char *messages[0x20] = { -/* 0 1 2 3 */ - "Undefined Command 0x0","Undefined Command 0x1","Read Track", "Specify", -/* 4 5 6 7 */ - "Sense Drive Status", "Write Data", "Read Data", "Recalibrate", -/* 8 9 A B */ - "Sense Interrupt Status", "Write Deleted Data", "Read ID", "Undefined Command 0xB", -/* C D E F */ - "Read Deleted Data", "Format Track", "Undefined Command 0xE","Seek", -/* 10 11 12 13 */ - "Undefined Command 0x10","Scan Equal", "Undefined Command 0x12","Undefined Command 0x13", -/* 14 15 16 17 */ - "Undefined Command 0x14","Undefined Command 0x15","Undefined Command 0x16","Undefined Command 0x17", -/* 18 19 1A 1B */ - "Undefined Command 0x18","Scan Low Equal", "Undefined Command 0x1A","Undefined Command 0x1B", -/* 1C 1D 1E 1F */ - "Undefined Command 0x1C","Scan High Equal", "Undefined Command 0x1E","Undefined Command 0x1F" -}; - -uint8 I8272_Write(const uint32 Addr, uint8 cData) -{ - I8272_DRIVE_INFO *pDrive; - uint32 flags = 0; - uint32 readlen; - uint8 disk_read = 0; - int32 i; - - pDrive = &i8272_info->drive[i8272_info->sel_drive]; - - if(pDrive->uptr == NULL) { - return 0xFF; - } - - switch(Addr & 0x3) { - case I8272_FDC_MSR: - sim_debug(WR_DATA_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " WR Drive Select Reg=%02x\n", PCX, cData); - break; - case I8272_FDC_DATA: - i8272_info->fdc_msr &= 0xF0; - sim_debug(VERBOSE_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " WR Data, phase=%d, index=%d\n", - PCX, i8272_info->fdc_phase, i8272_info->cmd_index); - if(i8272_info->fdc_phase == CMD_PHASE) { - i8272_info->cmd[i8272_info->cmd_index] = cData; - - if(i8272_info->cmd_index == 0) { - sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " CMD=0x%02x[%s]\n", PCX, cData & 0x1F, messages[cData & 0x1F]); - I8272_Setup_Cmd(cData & 0x1F); - } - i8272_info->cmd_index ++; - - if(i8272_info->cmd_len == i8272_info->cmd_index) { - i8272_info->cmd_index = 0; - i8272_info->fdc_phase = EXEC_PHASE; - } - } - - if(i8272_info->fdc_phase == EXEC_PHASE) { - switch(i8272_info->cmd[0] & 0x1F) { - case I8272_READ_DATA: - case I8272_WRITE_DATA: - case I8272_READ_DELETED_DATA: - case I8272_WRITE_DELETED_DATA: - case I8272_READ_TRACK: - case I8272_SCAN_LOW_EQUAL: - case I8272_SCAN_HIGH_EQUAL: - case I8272_SCAN_EQUAL: - i8272_info->fdc_mt = (i8272_info->cmd[0] & 0x80) >> 7; - i8272_info->fdc_mfm = (i8272_info->cmd[0] & 0x40) >> 6; - i8272_info->fdc_sk = (i8272_info->cmd[0] & 0x20) >> 5; - i8272_info->fdc_hds = (i8272_info->cmd[1] & 0x04) >> 2; - i8272_info->sel_drive = (i8272_info->cmd[1] & 0x03); - pDrive = &i8272_info->drive[i8272_info->sel_drive]; - if(pDrive->uptr == NULL) { - return 0xFF; - } - - if(pDrive->track != i8272_info->cmd[2]) { - i8272_info->fdc_seek_end = 1; - } else { - i8272_info->fdc_seek_end = 0; - } - if(pDrive->track != i8272_info->cmd[2]) { - sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " ERROR: CMD=0x%02x[%s]: Drive: %d, Command wants track %d, " - "but positioner is on track %d.\n", - PCX, i8272_info->cmd[0] & 0x1F, - messages[i8272_info->cmd[0] & 0x1F], - i8272_info->sel_drive, i8272_info->cmd[2], pDrive->track); - } - - pDrive->track = i8272_info->cmd[2]; - i8272_info->fdc_head = i8272_info->cmd[3] & 1; /* AGN mask to head 0 or 1 */ - i8272_info->fdc_sector = i8272_info->cmd[4]; - i8272_info->fdc_sec_len = i8272_info->cmd[5]; - if(i8272_info->fdc_sec_len > I8272_MAX_N) { - sim_debug(ERROR_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Illegal sector size %d [N=%d]. Reset to %d [N=%d].\n", - PCX, 128 << i8272_info->fdc_sec_len, - i8272_info->fdc_sec_len, 128 << I8272_MAX_N, I8272_MAX_N); - i8272_info->fdc_sec_len = I8272_MAX_N; - } - i8272_info->fdc_eot = i8272_info->cmd[6]; - i8272_info->fdc_gpl = i8272_info->cmd[7]; - i8272_info->fdc_dtl = i8272_info->cmd[8]; - - sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " CMD=0x%02x[%s]: Drive: %d, %s %s, C=%d. H=%d. S=%d, N=%d, " - "EOT=%02x, GPL=%02x, DTL=%02x\n", PCX, - i8272_info->cmd[0] & 0x1F, - messages[i8272_info->cmd[0] & 0x1F], - i8272_info->sel_drive, - i8272_info->fdc_mt ? "Multi" : "Single", - i8272_info->fdc_mfm ? "MFM" : "FM", - pDrive->track, - i8272_info->fdc_head, - i8272_info->fdc_sector, - i8272_info->fdc_sec_len, - i8272_info->fdc_eot, - i8272_info->fdc_gpl, - i8272_info->fdc_dtl); - - i8272_info->fdc_status[0] = (i8272_info->fdc_hds & 1) << 2; - i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 0x03); - i8272_info->fdc_status[0] |= 0x40; - - i8272_info->fdc_status[1] = 0; - i8272_info->fdc_status[2] = 0; - - i8272_info->result[0] = i8272_info->fdc_status[0]; - i8272_info->result[1] = i8272_info->fdc_status[1]; - i8272_info->result[2] = i8272_info->fdc_status[2]; - i8272_info->result[3] = pDrive->imd->track[pDrive->track][i8272_info->fdc_head].logicalCyl[i8272_info->fdc_sector]; /* AGN logicalCyl */ - i8272_info->result[4] = pDrive->imd->track[pDrive->track][i8272_info->fdc_head].logicalHead[i8272_info->fdc_sector]; /* AGN logicalHead */ - i8272_info->result[5] = i8272_info->fdc_sector; - i8272_info->result[6] = i8272_info->fdc_sec_len; - break; - case I8272_READ_ID: /* READ ID */ - i8272_info->fdc_mfm = (i8272_info->cmd[0] & 0x40) >> 6; - i8272_info->fdc_hds = (i8272_info->cmd[1] & 0x04) >> 2; - i8272_info->sel_drive = (i8272_info->cmd[1] & 0x03); - pDrive = &i8272_info->drive[i8272_info->sel_drive]; - if(pDrive->uptr == NULL) { - return 0xFF; - } - /* Compute the i8272 "N" value from the sectorsize of this */ - /* disk's current track - i.e. N = log2(sectsize) - log2(128) */ - /* The calculation also works for non-standard format disk images with */ - /* sectorsizes of 2048, 4096 and 8192 bytes */ - i8272_info->fdc_sec_len = floorlog2( - pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].sectsize) - 7; /* AGN fix to use fdc_hds (was fdc_head)*/ - /* For now always return the starting sector number */ - /* but could return (say) a valid sector number based */ - /* on elapsed time for a more "realistic" simulation. */ - /* This would allow disk analysis programs that use */ - /* READID to detect non-standard disk formats. */ - i8272_info->fdc_sector = pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].start_sector; - if((i8272_info->fdc_sec_len == 0xF8) || (i8272_info->fdc_sec_len > I8272_MAX_N)) { /* Error calculating N or N too large */ - sim_debug(ERROR_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Illegal sector size N=%d. Reset to 0.\n", - PCX, i8272_info->fdc_sec_len); - i8272_info->fdc_sec_len = 0; - return 0xFF; - } - i8272_info->fdc_status[0] = (i8272_info->fdc_hds & 1) << 2; - i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 0x03); - - i8272_info->fdc_status[1] = 0; - i8272_info->fdc_status[2] = 0; - - i8272_info->result[0] = i8272_info->fdc_status[0]; - i8272_info->result[1] = i8272_info->fdc_status[1]; - i8272_info->result[2] = i8272_info->fdc_status[2]; - i8272_info->result[3] = pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].logicalCyl[i8272_info->fdc_sector]; /* AGN logicalCyl */ - i8272_info->result[4] = pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].logicalHead[i8272_info->fdc_sector]; /* AGN logicalHead */ - i8272_info->result[5] = i8272_info->fdc_sector; - i8272_info->result[6] = i8272_info->fdc_sec_len; - break; - case I8272_RECALIBRATE: /* RECALIBRATE */ - i8272_info->sel_drive = i8272_info->cmd[1] & 0x03; - pDrive = &i8272_info->drive[i8272_info->sel_drive]; - if(pDrive->uptr == NULL) { - return 0xFF; - } - - pDrive->track = 0; - i8272_info->fdc_phase = CMD_PHASE; /* No result phase */ - i8272_info->fdc_seek_end = 1; - sim_debug(SEEK_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Recalibrate: Drive 0x%02x\n", - PCX, i8272_info->sel_drive); - break; - case I8272_FORMAT_TRACK: /* FORMAT A TRACK */ - i8272_info->fdc_mfm = (i8272_info->cmd[0] & 0x40) >> 6; - i8272_info->fdc_hds = (i8272_info->cmd[1] & 0x04) >> 2; - i8272_info->fdc_head = i8272_info->fdc_hds; - i8272_info->sel_drive = (i8272_info->cmd[1] & 0x03); - pDrive = &i8272_info->drive[i8272_info->sel_drive]; - if(pDrive->uptr == NULL) { - return 0xFF; - } - - if(pDrive->track != i8272_info->cmd[2]) { - i8272_info->fdc_seek_end = 1; - } else { - i8272_info->fdc_seek_end = 0; - } - i8272_info->fdc_sec_len = i8272_info->cmd[2]; - if(i8272_info->fdc_sec_len > I8272_MAX_N) { - sim_debug(ERROR_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Illegal sector size %d [N=%d]. Reset to %d [N=%d].\n", - PCX, 128 << i8272_info->fdc_sec_len, - i8272_info->fdc_sec_len, 128 << I8272_MAX_N, I8272_MAX_N); - i8272_info->fdc_sec_len = I8272_MAX_N; - } - i8272_info->fdc_sc = i8272_info->cmd[3]; - i8272_info->fdc_gpl = i8272_info->cmd[4]; - i8272_info->fdc_fillbyte = i8272_info->cmd[5]; - - sim_debug(FMT_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Format Drive: %d, %s, C=%d. H=%d. N=%d, SC=%d, GPL=%02x, FILL=%02x\n", - PCX, - i8272_info->sel_drive, - i8272_info->fdc_mfm ? "MFM" : "FM", - pDrive->track, - i8272_info->fdc_head, - i8272_info->fdc_sec_len, - i8272_info->fdc_sc, - i8272_info->fdc_gpl, - i8272_info->fdc_fillbyte); - - i8272_info->fdc_status[0] = (i8272_info->fdc_hds & 1) << 2; - i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 0x03); - - i8272_info->fdc_status[1] = 0; - i8272_info->fdc_status[2] = 0; - i8272_info->fdc_sectorcount = 0; - - i8272_info->result[0] = i8272_info->fdc_status[0]; - i8272_info->result[1] = i8272_info->fdc_status[1]; - i8272_info->result[2] = i8272_info->fdc_status[2]; - i8272_info->result[3] = pDrive->track; - i8272_info->result[4] = i8272_info->fdc_head; /* AGN for now we cannot format with logicalHead */ - i8272_info->result[5] = i8272_info->fdc_sector; /* AGN ditto for logicalCyl */ - i8272_info->result[6] = i8272_info->fdc_sec_len; - break; - case I8272_SENSE_INTR_STATUS: /* SENSE INTERRUPT STATUS */ - sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Sense Interrupt Status\n", PCX); - i8272_info->result[0] = i8272_info->fdc_seek_end ? 0x20 : 0x00; /* SEEK_END */ - i8272_info->result[0] |= i8272_info->sel_drive; - i8272_info->result[1] = pDrive->track; - i8272_irq = 0; - break; - case I8272_SPECIFY: /* SPECIFY */ - i8272_info->fdc_srt = 16 - ((i8272_info->cmd[1] & 0xF0) >> 4); - i8272_info->fdc_hut = (i8272_info->cmd[1] & 0x0F) * 16; - i8272_info->fdc_hlt = ((i8272_info->cmd[2] & 0xFE) >> 1) * 2; - i8272_info->fdc_nd = (i8272_info->cmd[2] & 0x01); - i8272_info->fdc_phase = CMD_PHASE; /* No result phase */ - sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Specify: SRT=%d, HUT=%d, HLT=%d, ND=%s\n", - PCX, i8272_info->fdc_srt, - i8272_info->fdc_hut, - i8272_info->fdc_hlt, - i8272_info->fdc_nd ? "NON-DMA" : "DMA"); - break; - case I8272_SENSE_DRIVE_STATUS: /* Setup Status3 Byte */ - i8272_info->fdc_hds = (i8272_info->cmd[1] & 0x04) >> 2; - i8272_info->sel_drive = (i8272_info->cmd[1] & 0x03); - pDrive = &i8272_info->drive[i8272_info->sel_drive]; - if(pDrive->uptr == NULL) { - return 0xFF; - } - - i8272_info->result[0] = (pDrive->ready) ? DRIVE_STATUS_READY : 0; /* Drive Ready */ - if(imdGetSides(pDrive->imd) == 2) { - i8272_info->result[0] |= DRIVE_STATUS_TWO_SIDED; /* Two-sided? */ - } - if(imdIsWriteLocked(pDrive->imd)) { - i8272_info->result[0] |= DRIVE_STATUS_WP; /* Write Protected? */ - } - i8272_info->result[0] |= (i8272_info->fdc_hds & 1) << 2; - i8272_info->result[0] |= (i8272_info->sel_drive & 0x03); - i8272_info->result[0] |= (pDrive->track == 0) ? DRIVE_STATUS_TRACK0 : 0x00; /* Track 0 */ - sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Sense Drive Status = 0x%02x\n", PCX, i8272_info->result[0]); - break; - case I8272_SEEK: /* SEEK */ - i8272_info->fdc_mt = (i8272_info->cmd[0] & 0x80) >> 7; - i8272_info->fdc_mfm = (i8272_info->cmd[0] & 0x40) >> 6; - i8272_info->fdc_sk = (i8272_info->cmd[0] & 0x20) >> 5; - i8272_info->fdc_hds = (i8272_info->cmd[1] & 0x04) >> 2; - i8272_info->sel_drive = (i8272_info->cmd[1] & 0x03); - pDrive = &i8272_info->drive[i8272_info->sel_drive]; - if(pDrive->uptr == NULL) { - return 0xFF; - } - - pDrive->track = i8272_info->cmd[2]; - i8272_info->fdc_head = i8272_info->fdc_hds; /*AGN seek should save the head */ - i8272_info->fdc_seek_end = 1; - sim_debug(SEEK_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Seek Drive: %d, %s %s, C=%d. Skip Deleted Data=%s Head Select=%s\n", - PCX, - i8272_info->sel_drive, - i8272_info->fdc_mt ? "Multi" : "Single", - i8272_info->fdc_mfm ? "MFM" : "FM", - i8272_info->cmd[2], - i8272_info->fdc_sk ? "True" : "False", - i8272_info->fdc_hds ? "True" : "False"); - break; - default: /* INVALID */ - break; - } - - if(i8272_info->fdc_phase == EXEC_PHASE) { - switch(i8272_info->cmd[0] & 0x1F) { - case I8272_READ_TRACK: - printf("I8272: " ADDRESS_FORMAT " Read a track (untested.)" NLP, PCX); - i8272_info->fdc_sector = 1; /* Read entire track from sector 1...eot */ - case I8272_READ_DATA: - case I8272_READ_DELETED_DATA: - disk_read = 1; - case I8272_WRITE_DATA: - case I8272_WRITE_DELETED_DATA: - for(;i8272_info->fdc_sector<=i8272_info->fdc_eot;i8272_info->fdc_sector++) { - sim_debug(RD_DATA_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " %s Data, sector: %d sector len=%d\n", - PCX, disk_read ? "RD" : "WR", - i8272_info->fdc_sector, - 128 << i8272_info->fdc_sec_len); - - if(pDrive->imd == NULL) { - printf(".imd is NULL!" NLP); - } - if(disk_read) { /* Read sector */ - sectRead(pDrive->imd, - pDrive->track, - i8272_info->fdc_head, - i8272_info->fdc_sector, - sdata.raw, - 128 << i8272_info->fdc_sec_len, - &flags, - &readlen); - - for(i=0;i<(128 << i8272_info->fdc_sec_len);i++) { - PutByteDMA(i8272_info->fdc_dma_addr, sdata.raw[i]); - i8272_info->fdc_dma_addr++; - } - sim_debug(RD_DATA_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " T:%d/H:%d/S:%d/L:%4d: Data transferred to RAM at 0x%06x\n", - PCX, pDrive->track, - i8272_info->fdc_head, - i8272_info->fdc_sector, - 128 << i8272_info->fdc_sec_len, - i8272_info->fdc_dma_addr - i); - } else { /* Write */ - for(i=0;i<(128 << i8272_info->fdc_sec_len);i++) { - sdata.raw[i] = GetByteDMA(i8272_info->fdc_dma_addr); - i8272_info->fdc_dma_addr++; - } - sim_debug(WR_DATA_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Data transferred from RAM at 0x%06x\n", - PCX, i8272_info->fdc_dma_addr); - sectWrite(pDrive->imd, - pDrive->track, - i8272_info->fdc_head, - i8272_info->fdc_sector, - sdata.raw, - 128 << i8272_info->fdc_sec_len, - &flags, - &readlen); - } - - i8272_info->result[5] = i8272_info->fdc_sector; - i8272_info->result[1] = 0x80; - } - break; - case I8272_FORMAT_TRACK: /* FORMAT A TRACK */ - for(i8272_info->fdc_sector = 1;i8272_info->fdc_sector<=i8272_info->fdc_sc;i8272_info->fdc_sector++) { - sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Format Track %d, Sector=%d, len=%d\n", PCX, pDrive->track, i8272_info->fdc_sector, 128 << i8272_info->fdc_sec_len); - - if(i8272_info->fdc_sectorcount >= I8272_MAX_SECTOR) { - sim_debug(ERROR_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Illegal sector count\n", PCX); - i8272_info->fdc_sectorcount = 0; - } - i8272_info->fdc_sectormap[i8272_info->fdc_sectorcount] = i8272_info->fdc_sector; - i8272_info->fdc_sectorcount++; - if(i8272_info->fdc_sectorcount == i8272_info->fdc_sc) { - trackWrite(pDrive->imd, - pDrive->track, - i8272_info->fdc_head, - i8272_info->fdc_sc, - 128 << i8272_info->fdc_sec_len, - i8272_info->fdc_sectormap, - i8272_info->fdc_mfm ? 3 : 0, - i8272_info->fdc_fillbyte, - &flags); - - /* Recalculate disk size */ - pDrive->uptr->capac = sim_fsize(pDrive->uptr->fileref); - - } - } - break; - - case I8272_SCAN_LOW_EQUAL: /* SCAN LOW OR EQUAL */ - case I8272_SCAN_HIGH_EQUAL: /* SCAN HIGH OR EQUAL */ - case I8272_SCAN_EQUAL: /* SCAN EQUAL */ - sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " Scan Data\n", PCX); - sim_debug(ERROR_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " ERROR: Scan not implemented.\n", PCX); - break; - case I8272_READ_ID: /* READ ID */ - sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT - " READ ID Drive %d result ST0=%02x ST1=%02x ST2=%02x " - "C=%d H=%d R=%02x N=%d\n", PCX, - i8272_info->sel_drive, - i8272_info->result[0], i8272_info->result[1], - i8272_info->result[2], i8272_info->result[3], - i8272_info->result[4], i8272_info->result[5], - i8272_info->result[6]); - break; - - default: - break; - } - } - - if(i8272_info->result_len != 0) { - i8272_info->fdc_phase ++; - } else { - i8272_info->fdc_phase = CMD_PHASE; - } - - i8272_info->result_index = 0; - if((i8272_info->cmd[0] & 0x1F) != I8272_SENSE_INTR_STATUS) { - raise_i8272_interrupt(); - } - } - - break; - } - - cData = 0x00; - - return (cData); -} - -static uint8 I8272_Setup_Cmd(uint8 fdc_cmd) -{ - uint8 result = 0; - - switch(fdc_cmd) { - case I8272_READ_DATA: - case I8272_WRITE_DATA: - case I8272_READ_DELETED_DATA: - case I8272_WRITE_DELETED_DATA: - case I8272_READ_TRACK: - case I8272_SCAN_LOW_EQUAL: - case I8272_SCAN_HIGH_EQUAL: - case I8272_SCAN_EQUAL: - i8272_info->cmd_len = 9; - i8272_info->result_len = 7; - break; - case I8272_READ_ID: /* READ ID */ - i8272_info->cmd_len = 2; - i8272_info->result_len = 7; - break; - case I8272_RECALIBRATE: /* RECALIBRATE */ - i8272_info->cmd_len = 2; - i8272_info->result_len = 0; - break; - case I8272_FORMAT_TRACK: /* FORMAT A TRACK */ - i8272_info->cmd_len = 6; - i8272_info->result_len = 7; - break; - case I8272_SENSE_INTR_STATUS: /* SENSE INTERRUPT STATUS */ - i8272_info->cmd_len = 1; - i8272_info->result_len = 2; - break; - case I8272_SPECIFY: /* SPECIFY */ - i8272_info->cmd_len = 3; - i8272_info->result_len = 0; - break; - case I8272_SENSE_DRIVE_STATUS: /* SENSE DRIVE STATUS */ - i8272_info->cmd_len = 2; - i8272_info->result_len = 1; - break; - case I8272_SEEK: /* SEEK */ - i8272_info->cmd_len = 3; - i8272_info->result_len = 0; - break; - default: /* INVALID */ - i8272_info->cmd_len = 1; - i8272_info->result_len = 1; - result = -1; - break; - } - return (result); -} - -extern void raise_disk1a_interrupt(void); - -static void raise_i8272_interrupt(void) -{ - sim_debug(IRQ_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT " FDC Interrupt\n", PCX); - i8272_irq = 1; - raise_disk1a_interrupt(); -} diff --git a/AltairZ80/i8272.h b/AltairZ80/i8272.h deleted file mode 100644 index 3182301e..00000000 --- a/AltairZ80/i8272.h +++ /dev/null @@ -1,49 +0,0 @@ -/************************************************************************* - * * - * $Id: i8272.h 1903 2008-05-18 02:21:23Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Generic Intel 8272 Disk Controller module for SIMH. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -extern t_stat i8272_attach(UNIT *uptr, char *cptr); -extern t_stat i8272_detach(UNIT *uptr); -extern uint8 I8272_Set_DMA(const uint32 dma_addr); -extern uint8 I8272_Read(const uint32 Addr); -extern uint8 I8272_Write(const uint32 Addr, uint8 cData); - -#define I8272_FDC_MSR 0 /* R=FDC Main Status Register, W=Drive Select Register */ -#define I8272_FDC_DATA 1 /* R/W FDC Data Register */ diff --git a/AltairZ80/i86.h b/AltairZ80/i86.h deleted file mode 100644 index 06e4c8e3..00000000 --- a/AltairZ80/i86.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Dos/PC Emulator - * 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. - * - */ - -/* 8086 support structs and definitions */ -/* definition of the registers */ - -/* general EAX,EBX,ECX, EDX type registers. - Note that for portability, and speed, the issue of byte - swapping is not addressed in the registers. All registers - are stored in the default format available on the - host machine. The only critical issue is that the - registers should line up EXACTLY in the same manner as - they do in the 386. That is: - - EAX & 0xff === AL - EAX & 0xffff == AX - - etc. The result is that alot of the calculations can then be - done using the native instruction set fully. -*/ - -/* Endian Logic -Priority 1: If LOWFIRST is defined, use it. LOWFIRST must be 1 if the - lower part of a 16 bit quantity comes first in memory, otherwise - LOWFIRST must be 0 -Priority 2: If __BIG_ENDIAN__ is defined, use it to define LOWFIRST accordingly -Priority 3: OS 9 on Macintosh needs LOWFIRST 0 -Priority 4: Use LOWFIRST 1 as default -*/ - -#ifndef LOWFIRST -#ifdef __BIG_ENDIAN__ -#if __BIG_ENDIAN__ -#define LOWFIRST 0 -#else -#define LOWFIRST 1 -#endif -#elif defined (__MWERKS__) && defined (macintosh) -#define LOWFIRST 0 -#else -#define LOWFIRST 1 -#endif -#endif - -#if LOWFIRST -typedef struct { uint16 x_reg; } I16_reg_t; -typedef struct { uint8 l_reg, h_reg; } I8_reg_t; -#else -typedef struct { uint16 x_reg; } I16_reg_t; -typedef struct { uint8 h_reg, l_reg; } I8_reg_t; -#endif - -typedef union -{ - I16_reg_t I16_reg; - I8_reg_t I8_reg; -} i386_general_register; - -struct i386_general_regs -{ - i386_general_register A, B, C, D; -}; - -typedef struct i386_general_regs Gen_reg_t; - -struct i386_special_regs -{ - i386_general_register SP, BP, SI, DI, IP; - uint32 FLAGS; -}; - -/* - * segment registers here represent the 16 bit quantities - * CS, DS, ES, SS - * - * segment pointers --- used to speed up the expressions: - * q = m->R_CSP + m->R_IP; - * fetched = *q; - * m->R_IP += 1; - * compared to: - * fetched = GetBYTEExtended(((uint32)m->R_CS << 4) + (m->R_IP++)); - * Save at least one shift, more if doing two byte moves. - */ -struct i386_segment_regs -{ - uint16 CS, DS, SS, ES, FS, GS; -}; - -/* 8 bit registers */ -#define R_AH Gn_regs.A.I8_reg.h_reg -#define R_AL Gn_regs.A.I8_reg.l_reg -#define R_BH Gn_regs.B.I8_reg.h_reg -#define R_BL Gn_regs.B.I8_reg.l_reg -#define R_CH Gn_regs.C.I8_reg.h_reg -#define R_CL Gn_regs.C.I8_reg.l_reg -#define R_DH Gn_regs.D.I8_reg.h_reg -#define R_DL Gn_regs.D.I8_reg.l_reg - -/* 16 bit registers */ -#define R_AX Gn_regs.A.I16_reg.x_reg -#define R_BX Gn_regs.B.I16_reg.x_reg -#define R_CX Gn_regs.C.I16_reg.x_reg -#define R_DX Gn_regs.D.I16_reg.x_reg - -/* special registers */ -#define R_SP Sp_regs.SP.I16_reg.x_reg -#define R_BP Sp_regs.BP.I16_reg.x_reg -#define R_SI Sp_regs.SI.I16_reg.x_reg -#define R_DI Sp_regs.DI.I16_reg.x_reg -#define R_IP Sp_regs.IP.I16_reg.x_reg -#define R_FLG Sp_regs.FLAGS - -/* segment registers */ -#define R_CS Sg_regs.CS -#define R_DS Sg_regs.DS -#define R_SS Sg_regs.SS -#define R_ES Sg_regs.ES - -/* 8088 has top 4 bits of the flags set to 1 */ -/* Also, bit#1 is set. This is (not well) documented behavior. */ -/* see note in userman.tex about the subtleties of dealing with */ -/* code which attempts to detect the host processor. */ -/* This is def'd as F_ALWAYS_ON */ -#define F_ALWAYS_ON (0xf002) /* flag bits always on */ - -/* following bits masked in to a 16bit quantity */ -#define F_CF 0x1 /* CARRY flag */ -#define F_PF 0x4 /* PARITY flag */ -#define F_AF 0x10 /* AUX flag */ -#define F_ZF 0x40 /* ZERO flag */ -#define F_SF 0x80 /* SIGN flag */ -#define F_TF 0x100 /* TRAP flag */ -#define F_IF 0x200 /* INTERRUPT ENABLE flag */ -#define F_DF 0x400 /* DIR flag */ -#define F_OF 0x800 /* OVERFLOW flag */ - -/* - * DEFINE A MASK FOR ONLY THOSE FLAG BITS WE WILL EVER PASS BACK - * (via PUSHF) - */ -#define F_MSK (F_CF|F_PF|F_AF|F_ZF|F_SF|F_TF|F_IF|F_DF|F_OF) - -#define TOGGLE_FLAG(M,FLAG) (M)->R_FLG ^= FLAG -#define SET_FLAG(M,FLAG) (M)->R_FLG |= FLAG -#define CLEAR_FLAG(M, FLAG) (M)->R_FLG &= ~FLAG -#define ACCESS_FLAG(M,FLAG) ((M)->R_FLG & (FLAG)) - -#define CONDITIONAL_SET_FLAG(COND,M,FLAG) \ - if (COND) SET_FLAG(M,FLAG); else CLEAR_FLAG(M,FLAG) - -/* emulator machine state. */ -/* segment usage control */ -#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 - -#define INTR_SYNCH 0x1 -#define INTR_HALTED 0x4 -#define INTR_ILLEGAL_OPCODE 0x8 - -/* INSTRUCTION DECODING STUFF */ -#define FETCH_DECODE_MODRM(m,mod,rh,rl) fetch_decode_modrm(m,&mod,&rh,&rl) -#define DECODE_RM_BYTE_REGISTER(m,r) decode_rm_byte_register(m,r) -#define DECODE_RM_WORD_REGISTER(m,r) decode_rm_word_register(m,r) -#define DECODE_CLEAR_SEGOVR(m) m->sysmode &= ~(SYSMODE_SEGMASK) - -typedef struct pc_env PC_ENV; -struct pc_env -{ - /* The registers!! */ - struct i386_general_regs Gn_regs; - struct i386_special_regs Sp_regs; - struct i386_segment_regs Sg_regs; - /* our flags structrure. This contains information on - REPE prefix 2 bits repe,repne - SEGMENT overrides 5 bits normal,DS,SS,CS,ES - Delayed flag set 3 bits (zero, signed, parity) - reserved 6 bits - interrupt # 8 bits instruction raised interrupt - BIOS video segregs 4 bits - Interrupt Pending 1 bits - Extern interrupt 1 bits - Halted 1 bits - */ - long sysmode; - uint8 intno; -}; - -/* GLOBAL */ -volatile int intr; - -void halt_sys (PC_ENV *sys); -void fetch_decode_modrm (PC_ENV *m, uint16 *mod, uint16 *regh, uint16 *regl); -uint8 *decode_rm_byte_register (PC_ENV *m, int reg); -uint16 *decode_rm_word_register (PC_ENV *m, int reg); -uint16 *decode_rm_seg_register (PC_ENV *m, int reg); -uint8 fetch_byte_imm (PC_ENV *m); -uint16 fetch_word_imm (PC_ENV *m); -uint16 decode_rm00_address (PC_ENV *m, int rm); -uint16 decode_rm01_address (PC_ENV *m, int rm); -uint16 decode_rm10_address (PC_ENV *m, int rm); -uint8 fetch_data_byte (PC_ENV *m, uint16 offset); -uint8 fetch_data_byte_abs (PC_ENV *m, uint16 segment, uint16 offset); -uint16 fetch_data_word (PC_ENV *m, uint16 offset); -uint16 fetch_data_word_abs (PC_ENV *m, uint16 segment, uint16 offset); -void store_data_byte (PC_ENV *m, uint16 offset, uint8 val); -void store_data_byte_abs (PC_ENV *m, uint16 segment, uint16 offset, uint8 val); -void store_data_word (PC_ENV *m, uint16 offset, uint16 val); -void store_data_word_abs (PC_ENV *m, uint16 segment, uint16 offset, uint16 val); - -typedef void (*OP)(PC_ENV *m); -extern OP i86_optab[256]; - -/* PRIMITIVE OPERATIONS */ - -uint8 aad_word (PC_ENV *m, uint16 d); -uint16 aam_word (PC_ENV *m, uint8 d); -uint8 adc_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 adc_word (PC_ENV *m, uint16 d, uint16 s); -uint8 add_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 add_word (PC_ENV *m, uint16 d, uint16 s); -uint8 and_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 and_word (PC_ENV *m, uint16 d, uint16 s); -uint8 cmp_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 cmp_word (PC_ENV *m, uint16 d, uint16 s); -uint8 dec_byte (PC_ENV *m, uint8 d); -uint16 dec_word (PC_ENV *m, uint16 d); -uint8 inc_byte (PC_ENV *m, uint8 d); -uint16 inc_word (PC_ENV *m, uint16 d); -uint8 or_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 or_word (PC_ENV *m, uint16 d, uint16 s); -uint8 neg_byte (PC_ENV *m, uint8 s); -uint16 neg_word (PC_ENV *m, uint16 s); -uint8 not_byte (PC_ENV *m, uint8 s); -uint16 not_word (PC_ENV *m, uint16 s); -uint16 mem_access_word (PC_ENV *m, int addr); -void push_word (PC_ENV *m, uint16 w); -uint16 pop_word (PC_ENV *m); -uint8 rcl_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 rcl_word (PC_ENV *m, uint16 d, uint16 s); -uint8 rcr_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 rcr_word (PC_ENV *m, uint16 d, uint16 s); -uint8 rol_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 rol_word (PC_ENV *m, uint16 d, uint16 s); -uint8 ror_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 ror_word (PC_ENV *m, uint16 d, uint16 s); -uint8 shl_byte (PC_ENV *m, uint8 d, uint8 s) ; -uint16 shl_word (PC_ENV *m, uint16 d, uint16 s); -uint8 shr_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 shr_word (PC_ENV *m, uint16 d, uint16 s); -uint8 sar_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 sar_word (PC_ENV *m, uint16 d, uint16 s); -uint8 sbb_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 sbb_word (PC_ENV *m, uint16 d, uint16 s); -uint8 sub_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 sub_word (PC_ENV *m, uint16 d, uint16 s); -void test_byte (PC_ENV *m, uint8 d, uint8 s); -void test_word (PC_ENV *m, uint16 d, uint16 s); -uint8 xor_byte (PC_ENV *m, uint8 d, uint8 s); -uint16 xor_word (PC_ENV *m, uint16 d, uint16 s); -void imul_byte (PC_ENV *m, uint8 s); -void imul_word (PC_ENV *m, uint16 s); -void mul_byte (PC_ENV *m, uint8 s); -void mul_word (PC_ENV *m, uint16 s); -void idiv_byte (PC_ENV *m, uint8 s); -void idiv_word (PC_ENV *m, uint16 s); -void div_byte (PC_ENV *m, uint8 s); -void div_word (PC_ENV *m, uint16 s); diff --git a/AltairZ80/i86_decode.c b/AltairZ80/i86_decode.c deleted file mode 100644 index 2b15e27f..00000000 --- a/AltairZ80/i86_decode.c +++ /dev/null @@ -1,958 +0,0 @@ -/* - * Dos/PC Emulator - * 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. - * - */ - -#include "altairz80_defs.h" -#include "i86.h" - -extern uint32 GetBYTEExtended(register uint32 Addr); -extern void PutBYTEExtended(register uint32 Addr, const register uint32 Value); -extern int32 AX_S; /* AX register (8086) */ -extern int32 BX_S; /* BX register (8086) */ -extern int32 CX_S; /* CX register (8086) */ -extern int32 DX_S; /* DX register (8086) */ -extern int32 CS_S; /* CS register (8086) */ -extern int32 DS_S; /* DS register (8086) */ -extern int32 ES_S; /* ES register (8086) */ -extern int32 SS_S; /* SS register (8086) */ -extern int32 DI_S; /* DI register (8086) */ -extern int32 SI_S; /* SI register (8086) */ -extern int32 BP_S; /* BP register (8086) */ -extern int32 SPX_S; /* SP register (8086) */ -extern int32 IP_S; /* IP register (8086) */ -extern int32 FLAGS_S; /* flags register (8086) */ -extern int32 PCX_S; /* PC register (8086), 20 bit */ -extern int32 sim_interval; -extern uint32 PCX; /* external view of PC */ -extern uint32 sim_brk_summ; -extern UNIT cpu_unit; - -void i86_intr_raise(PC_ENV *m,uint8 intrnum); -void cpu8086reset(void); -t_stat sim_instr_8086(void); -void cpu8086_intr(uint8 intrnum); - -/* $Log: $ - * Revision 0.05 1992/04/12 23:16:42 hudgens - * Many changes. Added support for the QUICK_FETCH option, - * so that memory accesses are faster. Now compiles with gcc -Wall - * and gcc -traditional and Sun cc. - * - * Revision 0.04 1991/07/30 01:59:56 hudgens - * added copyright. - * - * Revision 0.03 1991/06/03 01:02:09 hudgens - * fixed minor problems due to unsigned to signed short integer - * promotions. - * - * Revision 0.02 1991/03/31 01:29:39 hudgens - * Fixed segment handling (overrides, default segment accessed) in - * routines decode_rmXX_address and the {fetch,store}_data_{byte,word}. - * - * Revision 0.01 1991/03/30 21:59:49 hudgens - * Initial checkin. - * - * - */ - -/* this file includes subroutines which do: - stuff involving decoding instruction formats. - stuff involving accessess of immediate data via IP. - etc. -*/ - -static void i86_intr_handle(PC_ENV *m) -{ uint16 tmp; - uint8 intno; - if (intr & INTR_SYNCH) /* raised by something */ - { - intno = m->intno; - { - tmp = m->R_FLG; - push_word(m, tmp); - CLEAR_FLAG(m, F_IF); - CLEAR_FLAG(m, F_TF); - /* [JCE] If we're interrupting between a segment override (or REP override) - * and the following instruction, decrease IP to get back to the prefix */ - if (m->sysmode & (SYSMODE_SEGMASK | SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) - { - --m->R_IP; - } - /* [JCE] CS and IP were the wrong way round... */ - push_word(m, m->R_CS); - push_word(m, m->R_IP); - tmp = mem_access_word(m, intno * 4); - m->R_IP = tmp; - tmp = mem_access_word(m, intno * 4 + 2); - m->R_CS = tmp; - } - intr &= ~INTR_SYNCH; /* [JCE] Dealt with, reset flag */ - } - /* The interrupt code can't pick up the segment override status. */ - DECODE_CLEAR_SEGOVR(m); -} - -void i86_intr_raise(PC_ENV *m,uint8 intrnum) -{ - m->intno = intrnum; - intr |= INTR_SYNCH; -} - -static PC_ENV cpu8086; - -void cpu8086_intr(uint8 intrnum) -{ - i86_intr_raise(&cpu8086, intrnum); -} - -static void setViewRegisters(void) { - FLAGS_S = cpu8086.R_FLG; - AX_S = cpu8086.R_AX; - BX_S = cpu8086.R_BX; - CX_S = cpu8086.R_CX; - DX_S = cpu8086.R_DX; - SPX_S = cpu8086.R_SP; - BP_S = cpu8086.R_BP; - SI_S = cpu8086.R_SI; - DI_S = cpu8086.R_DI; - ES_S = cpu8086.R_ES; - CS_S = cpu8086.R_CS; - SS_S = cpu8086.R_SS; - DS_S = cpu8086.R_DS; - IP_S = cpu8086.R_IP; -} - -static void setCPURegisters(void) { - cpu8086.R_FLG = FLAGS_S; - cpu8086.R_AX = AX_S; - cpu8086.R_BX = BX_S; - cpu8086.R_CX = CX_S; - cpu8086.R_DX = DX_S; - cpu8086.R_SP = SPX_S; - cpu8086.R_BP = BP_S; - cpu8086.R_SI = SI_S; - cpu8086.R_DI = DI_S; - cpu8086.R_ES = ES_S; - cpu8086.R_CS = CS_S; - cpu8086.R_SS = SS_S; - cpu8086.R_DS = DS_S; - cpu8086.R_IP = IP_S; -} - -void cpu8086reset(void) { - cpu8086.R_AX = 0x1961; - if ((cpu8086.R_AH != 0x19) || (cpu8086.R_AL != 0x61)) { - printf("Fatal endian error - make sure to compile with '#define LOWFIRST %i'\n", 1 - LOWFIRST); - exit(1); - } - /* 16 bit registers */ - cpu8086.R_AX = 0; - cpu8086.R_BX = 0; - cpu8086.R_CX = 0; - cpu8086.R_DX = 0; - /* special registers */ - cpu8086.R_SP = 0; - cpu8086.R_BP = 0; - cpu8086.R_SI = 0; - cpu8086.R_DI = 0; - cpu8086.R_IP = 0; - cpu8086.R_FLG = F_ALWAYS_ON; - /* segment registers */ - cpu8086.R_CS = 0; - cpu8086.R_DS = 0; - cpu8086.R_SS = 0; - cpu8086.R_ES = 0; - setViewRegisters(); -} - -static uint32 getFullPC(void) { - return cpu8086.R_IP + (cpu8086.R_CS << 4); -} - -extern int32 switch_cpu_now; /* hharte */ - -t_stat sim_instr_8086(void) { - t_stat reason = SCPE_OK; - uint8 op1; - int32 newIP; - setCPURegisters(); - intr = 0; - newIP = PCX_S - 16 * CS_S; - switch_cpu_now = TRUE; /* hharte */ - if ((0 <= newIP) && (newIP <= 0xffff)) - cpu8086.R_IP = newIP; - else { - if (CS_S != ((PCX_S & 0xf0000) >> 4)) { - cpu8086.R_CS = (PCX_S & 0xf0000) >> 4; - if (cpu_unit.flags & UNIT_CPU_VERBOSE) - printf("CPU: " ADDRESS_FORMAT " Segment register CS set to %04x" NLP, PCX, cpu8086.R_CS); - } - cpu8086.R_IP = PCX_S & 0xffff; - } - while (switch_cpu_now == TRUE) { /* loop until halted */ - if (sim_interval <= 0) { /* check clock queue */ -#if !UNIX_PLATFORM - if ((reason = sim_os_poll_kbd()) == SCPE_STOP) /* poll on platforms without reliable signalling */ - break; -#endif - if ( (reason = sim_process_event()) ) - break; - } - if (sim_brk_summ && sim_brk_test(getFullPC(), SWMASK('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - PCX = getFullPC(); - op1 = GetBYTEExtended((((uint32)cpu8086.R_CS<<4) + cpu8086.R_IP) & 0xFFFFF); - if (sim_brk_summ && sim_brk_test(op1, (1u << SIM_BKPT_V_SPC) | SWMASK('I'))) { /* instruction breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - sim_interval--; - cpu8086.R_IP++; - (*(i86_optab[op1]))(&cpu8086); - if (intr & INTR_HALTED) { - reason = STOP_HALT; - intr &= ~INTR_HALTED; - break; - } - if (intr & INTR_ILLEGAL_OPCODE) { - intr &= ~INTR_ILLEGAL_OPCODE; - if (cpu_unit.flags & UNIT_CPU_OPSTOP) { - reason = STOP_OPCODE; - break; - } - } - if (((intr & INTR_SYNCH) && (cpu8086.intno == 0 || cpu8086.intno == 2)) || - (ACCESS_FLAG(&cpu8086, F_IF))) { - /* [JCE] Reversed the sense of this ACCESS_FLAG; it's set for interrupts - enabled, not interrupts blocked i.e. either not blockable (intr 0 or 2) - or the IF flag not set so interrupts not blocked */ - /* hharte: if a segment override exists, then treat that as "atomic" and do not handle - * an interrupt until the override is cleared. - * Not sure if this is the way an 8086 really works, need to find out for sure. - * Also, what about the REPE prefix? - */ - if ((cpu8086.sysmode & SYSMODE_SEGMASK) == 0) { - i86_intr_handle(&cpu8086); - } - } - } - /* It we stopped processing instructions because of a switch to the other - * CPU, then fixup the reason code. - */ - if (switch_cpu_now == FALSE) { - reason = SCPE_OK; - PCX += 2; - PCX_S = PCX; - } else { - PCX_S = (reason == STOP_HALT) | (reason == STOP_OPCODE) ? PCX : getFullPC(); - } - - setViewRegisters(); - return reason; -} - -void halt_sys(PC_ENV *m) -{ - intr |= INTR_HALTED; -} - -/* once the instruction is fetched, an optional byte follows which - has 3 fields encoded in it. This routine fetches the byte - and breaks into the three fields. - This has been changed, in an attempt to reduce the amount of - executed code for this frequently executed subroutine. If this - works, then it may pay to somehow inline it. - */ - -#ifdef NOTDEF -/* this code generated the following table */ -main() -{ int i; - printf("\n\nstruct modrm{ uint8 mod,rh,rl;} modrmtab[] = {\n"); - for (i=0; i<256; i++) - { - printf("{%d,%d,%d}, ",((i&0xc0)>>6),((i&0x38)>>3),(i&0x07)); - if (i%4==3) - printf("/* %d to %d */\n",i&0xfc,i); - } - printf("};\n\n"); -} -#endif - -struct modrm { uint16 mod, rh, rl; }; -static struct modrm modrmtab[] = { - {0,0,0}, {0,0,1}, {0,0,2}, {0,0,3}, /* 0 to 3 */ - {0,0,4}, {0,0,5}, {0,0,6}, {0,0,7}, /* 4 to 7 */ - {0,1,0}, {0,1,1}, {0,1,2}, {0,1,3}, /* 8 to 11 */ - {0,1,4}, {0,1,5}, {0,1,6}, {0,1,7}, /* 12 to 15 */ - {0,2,0}, {0,2,1}, {0,2,2}, {0,2,3}, /* 16 to 19 */ - {0,2,4}, {0,2,5}, {0,2,6}, {0,2,7}, /* 20 to 23 */ - {0,3,0}, {0,3,1}, {0,3,2}, {0,3,3}, /* 24 to 27 */ - {0,3,4}, {0,3,5}, {0,3,6}, {0,3,7}, /* 28 to 31 */ - {0,4,0}, {0,4,1}, {0,4,2}, {0,4,3}, /* 32 to 35 */ - {0,4,4}, {0,4,5}, {0,4,6}, {0,4,7}, /* 36 to 39 */ - {0,5,0}, {0,5,1}, {0,5,2}, {0,5,3}, /* 40 to 43 */ - {0,5,4}, {0,5,5}, {0,5,6}, {0,5,7}, /* 44 to 47 */ - {0,6,0}, {0,6,1}, {0,6,2}, {0,6,3}, /* 48 to 51 */ - {0,6,4}, {0,6,5}, {0,6,6}, {0,6,7}, /* 52 to 55 */ - {0,7,0}, {0,7,1}, {0,7,2}, {0,7,3}, /* 56 to 59 */ - {0,7,4}, {0,7,5}, {0,7,6}, {0,7,7}, /* 60 to 63 */ - {1,0,0}, {1,0,1}, {1,0,2}, {1,0,3}, /* 64 to 67 */ - {1,0,4}, {1,0,5}, {1,0,6}, {1,0,7}, /* 68 to 71 */ - {1,1,0}, {1,1,1}, {1,1,2}, {1,1,3}, /* 72 to 75 */ - {1,1,4}, {1,1,5}, {1,1,6}, {1,1,7}, /* 76 to 79 */ - {1,2,0}, {1,2,1}, {1,2,2}, {1,2,3}, /* 80 to 83 */ - {1,2,4}, {1,2,5}, {1,2,6}, {1,2,7}, /* 84 to 87 */ - {1,3,0}, {1,3,1}, {1,3,2}, {1,3,3}, /* 88 to 91 */ - {1,3,4}, {1,3,5}, {1,3,6}, {1,3,7}, /* 92 to 95 */ - {1,4,0}, {1,4,1}, {1,4,2}, {1,4,3}, /* 96 to 99 */ - {1,4,4}, {1,4,5}, {1,4,6}, {1,4,7}, /* 100 to 103 */ - {1,5,0}, {1,5,1}, {1,5,2}, {1,5,3}, /* 104 to 107 */ - {1,5,4}, {1,5,5}, {1,5,6}, {1,5,7}, /* 108 to 111 */ - {1,6,0}, {1,6,1}, {1,6,2}, {1,6,3}, /* 112 to 115 */ - {1,6,4}, {1,6,5}, {1,6,6}, {1,6,7}, /* 116 to 119 */ - {1,7,0}, {1,7,1}, {1,7,2}, {1,7,3}, /* 120 to 123 */ - {1,7,4}, {1,7,5}, {1,7,6}, {1,7,7}, /* 124 to 127 */ - {2,0,0}, {2,0,1}, {2,0,2}, {2,0,3}, /* 128 to 131 */ - {2,0,4}, {2,0,5}, {2,0,6}, {2,0,7}, /* 132 to 135 */ - {2,1,0}, {2,1,1}, {2,1,2}, {2,1,3}, /* 136 to 139 */ - {2,1,4}, {2,1,5}, {2,1,6}, {2,1,7}, /* 140 to 143 */ - {2,2,0}, {2,2,1}, {2,2,2}, {2,2,3}, /* 144 to 147 */ - {2,2,4}, {2,2,5}, {2,2,6}, {2,2,7}, /* 148 to 151 */ - {2,3,0}, {2,3,1}, {2,3,2}, {2,3,3}, /* 152 to 155 */ - {2,3,4}, {2,3,5}, {2,3,6}, {2,3,7}, /* 156 to 159 */ - {2,4,0}, {2,4,1}, {2,4,2}, {2,4,3}, /* 160 to 163 */ - {2,4,4}, {2,4,5}, {2,4,6}, {2,4,7}, /* 164 to 167 */ - {2,5,0}, {2,5,1}, {2,5,2}, {2,5,3}, /* 168 to 171 */ - {2,5,4}, {2,5,5}, {2,5,6}, {2,5,7}, /* 172 to 175 */ - {2,6,0}, {2,6,1}, {2,6,2}, {2,6,3}, /* 176 to 179 */ - {2,6,4}, {2,6,5}, {2,6,6}, {2,6,7}, /* 180 to 183 */ - {2,7,0}, {2,7,1}, {2,7,2}, {2,7,3}, /* 184 to 187 */ - {2,7,4}, {2,7,5}, {2,7,6}, {2,7,7}, /* 188 to 191 */ - {3,0,0}, {3,0,1}, {3,0,2}, {3,0,3}, /* 192 to 195 */ - {3,0,4}, {3,0,5}, {3,0,6}, {3,0,7}, /* 196 to 199 */ - {3,1,0}, {3,1,1}, {3,1,2}, {3,1,3}, /* 200 to 203 */ - {3,1,4}, {3,1,5}, {3,1,6}, {3,1,7}, /* 204 to 207 */ - {3,2,0}, {3,2,1}, {3,2,2}, {3,2,3}, /* 208 to 211 */ - {3,2,4}, {3,2,5}, {3,2,6}, {3,2,7}, /* 212 to 215 */ - {3,3,0}, {3,3,1}, {3,3,2}, {3,3,3}, /* 216 to 219 */ - {3,3,4}, {3,3,5}, {3,3,6}, {3,3,7}, /* 220 to 223 */ - {3,4,0}, {3,4,1}, {3,4,2}, {3,4,3}, /* 224 to 227 */ - {3,4,4}, {3,4,5}, {3,4,6}, {3,4,7}, /* 228 to 231 */ - {3,5,0}, {3,5,1}, {3,5,2}, {3,5,3}, /* 232 to 235 */ - {3,5,4}, {3,5,5}, {3,5,6}, {3,5,7}, /* 236 to 239 */ - {3,6,0}, {3,6,1}, {3,6,2}, {3,6,3}, /* 240 to 243 */ - {3,6,4}, {3,6,5}, {3,6,6}, {3,6,7}, /* 244 to 247 */ - {3,7,0}, {3,7,1}, {3,7,2}, {3,7,3}, /* 248 to 251 */ - {3,7,4}, {3,7,5}, {3,7,6}, {3,7,7}, /* 252 to 255 */ -}; - -void fetch_decode_modrm(PC_ENV *m, uint16 *mod, uint16 *regh, uint16 *regl) -{ uint8 fetched; - register struct modrm *p; - /* do the fetch in real mode. Shift the CS segment register - over by 4 bits, and add in the IP register. Index into - the system memory. - */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - fetched = GetBYTEExtended(((m->R_CS << 4) + (m->R_IP++)) & 0xFFFFF); - -#ifdef NOTDEF - *mod = ((fetched&0xc0)>>6); - *regh= ((fetched&0x38)>>3); - *regl= (fetched&0x7); -#else - p = modrmtab + fetched; - *mod = p->mod; - *regh= p->rh; - *regl= p->rl; -#endif - -} - -/* - return a pointer to the register given by the R/RM field of - the modrm byte, for byte operands. - Also enables the decoding of instructions. -*/ -uint8 *decode_rm_byte_register(PC_ENV *m, int reg) -{ - switch(reg) - { - case 0: - return &m->R_AL; - break; - case 1: - return &m->R_CL; - break; - case 2: - return &m->R_DL; - break; - case 3: - return &m->R_BL; - break; - case 4: - return &m->R_AH; - break; - case 5: - return &m->R_CH; - break; - case 6: - return &m->R_DH; - break; - case 7: - return &m->R_BH; - break; - } - halt_sys(m); - return NULL; /* NOT REACHED OR REACHED ON ERROR */ -} - -/* - return a pointer to the register given by the R/RM field of - the modrm byte, for word operands. - Also enables the decoding of instructions. -*/ -uint16 *decode_rm_word_register(PC_ENV *m, int reg) -{ - switch(reg) - { - case 0: - return &m->R_AX; - break; - case 1: - return &m->R_CX; - break; - case 2: - return &m->R_DX; - break; - case 3: - return &m->R_BX; - break; - case 4: - return &m->R_SP; - break; - case 5: - return &m->R_BP; - break; - case 6: - return &m->R_SI; - break; - case 7: - return &m->R_DI; - break; - } - halt_sys(m); - return NULL; /* NOTREACHED OR REACHED ON ERROR*/ -} - -/* - return a pointer to the register given by the R/RM field of - the modrm byte, for word operands, modified from above - for the weirdo special case of segreg operands. - Also enables the decoding of instructions. -*/ -uint16 *decode_rm_seg_register(PC_ENV *m, int reg) -{ - switch(reg) - { - case 0: - return &m->R_ES; - break; - case 1: - return &m->R_CS; - break; - case 2: - return &m->R_SS; - break; - case 3: - return &m->R_DS; - break; - case 4: - case 5: - case 6: - case 7: - break; - } - halt_sys(m); - return NULL; /* NOT REACHED OR REACHED ON ERROR */ -} - -/* once the instruction is fetched, an optional byte follows which - has 3 fields encoded in it. This routine fetches the byte - and breaks into the three fields. -*/ -uint8 fetch_byte_imm(PC_ENV *m) -{ - uint8 fetched; - /* do the fetch in real mode. Shift the CS segment register - over by 4 bits, and add in the IP register. Index into - the system memory. - */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - fetched = GetBYTEExtended((((uint32)m->R_CS << 4) + (m->R_IP++)) & 0xFFFFF); - return fetched; -} - -uint16 fetch_word_imm(PC_ENV *m) -{ - uint16 fetched; - /* do the fetch in real mode. Shift the CS segment register - over by 4 bits, and add in the IP register. Index into - the system PC_ENVory. - */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - fetched = GetBYTEExtended((((uint32)m->R_CS << 4) + (m->R_IP++)) & 0xFFFFF); - fetched |= (GetBYTEExtended((((uint32)m->R_CS << 4) + (m->R_IP++)) & 0xFFFFF) << 8); - return fetched; -} - -/* - return the offset given by mod=00 addressing. - Also enables the decoding of instructions. -*/ -uint16 decode_rm00_address(PC_ENV *m, int rm) -{ - uint16 offset; - /* note the code which specifies the corresponding segment (ds vs ss) - below in the case of [BP+..]. The assumption here is that at the - point that this subroutine is called, the bit corresponding to - SYSMODE_SEG_DS_SS will be zero. After every instruction - except the segment override instructions, this bit (as well - as any bits indicating segment overrides) will be clear. So - if a SS access is needed, set this bit. Otherwise, DS access - occurs (unless any of the segment override bits are set). - */ - switch(rm) - { - case 0: - return (int16)m->R_BX + (int16)m->R_SI; - break; - case 1: - return (int16)m->R_BX + (int16)m->R_DI; - break; - case 2: - m->sysmode |= SYSMODE_SEG_DS_SS; - return (int16)m->R_BP + (int16)m->R_SI; - break; - case 3: - m->sysmode |= SYSMODE_SEG_DS_SS; - return (int16)m->R_BP + (int16)m->R_DI; - break; - case 4: - return m->R_SI; - break; - case 5: - return m->R_DI; - break; - case 6: - offset = (int16)fetch_word_imm(m); - return offset; - break; - case 7: - return m->R_BX; - } - halt_sys(m); - return 0; -} - -/* - return the offset given by mod=01 addressing. - Also enables the decoding of instructions. -*/ -uint16 decode_rm01_address(PC_ENV *m, int rm) -{ - int8 displacement; - /* note comment on decode_rm00_address above */ - displacement = (int8)fetch_byte_imm(m); /* !!!! Check this */ - switch(rm) - { - case 0: - return (int16)m->R_BX + (int16)m->R_SI + displacement; - break; - case 1: - return (int16)m->R_BX + (int16)m->R_DI + displacement; - break; - case 2: - m->sysmode |= SYSMODE_SEG_DS_SS; - return (int16)m->R_BP + (int16)m->R_SI + displacement; - break; - case 3: - m->sysmode |= SYSMODE_SEG_DS_SS; - return (int16)m->R_BP + (int16)m->R_DI + displacement; - break; - case 4: - return (int16)m->R_SI + displacement; - break; - case 5: - return (int16)m->R_DI + displacement; - break; - case 6: - m->sysmode |= SYSMODE_SEG_DS_SS; - return (int16)m->R_BP + displacement; - break; - case 7: - return (int16)m->R_BX + displacement; - break; - } - halt_sys(m); - return 0; /* SHOULD NOT HAPPEN */ -} - -/* - return the offset given by mod=01 addressing. - Also enables the decoding of instructions. -*/ -uint16 decode_rm10_address(PC_ENV *m, int rm) -{ - int16 displacement; - /* note comment on decode_rm00_address above */ - displacement = (int16)fetch_word_imm(m); - switch(rm) - { - case 0: - return (int16)m->R_BX + (int16)m->R_SI + displacement; - break; - case 1: - return (int16)m->R_BX + (int16)m->R_DI + displacement; - break; - case 2: - m->sysmode |= SYSMODE_SEG_DS_SS; - return (int16)m->R_BP + (int16)m->R_SI + displacement; - break; - case 3: - m->sysmode |= SYSMODE_SEG_DS_SS; - return (int16)m->R_BP + (int16)m->R_DI + displacement; - break; - case 4: - return (int16)m->R_SI + displacement; - break; - case 5: - return (int16)m->R_DI + displacement; - break; - case 6: - m->sysmode |= SYSMODE_SEG_DS_SS; - return (int16)m->R_BP + displacement; - break; - case 7: - return (int16)m->R_BX + displacement; - break; - } - halt_sys(m); - return 0; - /*NOTREACHED */ -} - -/* fetch a byte of data, given an offset, the current register set, - and a descriptor for memory. -*/ -uint8 fetch_data_byte(PC_ENV *m, uint16 offset) -{ - register uint8 value; - /* this code originally completely broken, and never showed - up since the DS segments === SS segment in all test cases. - It had been originally assumed, that all access to data would - involve the DS register unless there was a segment override. - Not so. Address modes such as -3[BP] or 10[BP+SI] all - refer to addresses relative to the SS. So, at the minimum, - all decodings of addressing modes would have to set/clear - a bit describing whether the access is relative to DS or SS. - That is the function of the cpu-state-varible m->sysmode. - There are several potential states: - repe prefix seen (handled elsewhere) - repne prefix seen (ditto) - cs segment override - ds segment override - es segment override - ss segment override - ds/ss select (in absense of override) - Each of the above 7 items are handled with a bit in the sysmode - field. - The latter 5 can be implemented as a simple state machine: - */ - switch(m->sysmode & SYSMODE_SEGMASK) - { - case 0: - /* default case: use ds register */ - value = GetBYTEExtended(((uint32)m->R_DS<<4) + offset); - break; - case SYSMODE_SEG_DS_SS: - /* non-overridden, use ss register */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - value = GetBYTEExtended((((uint32)m->R_SS << 4) + offset) & 0xFFFFF); - break; - case SYSMODE_SEGOVR_CS: - /* ds overridden */ - case SYSMODE_SEGOVR_CS|SYSMODE_SEG_DS_SS: - /* ss overridden, use cs register */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - value = GetBYTEExtended((((uint32)m->R_CS << 4) + offset) & 0xFFFFF); - break; - case SYSMODE_SEGOVR_DS: - /* ds overridden --- shouldn't happen, but hey. */ - case SYSMODE_SEGOVR_DS|SYSMODE_SEG_DS_SS: - /* ss overridden, use ds register */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - value = GetBYTEExtended((((uint32)m->R_DS << 4) + offset) & 0xFFFFF); - break; - case SYSMODE_SEGOVR_ES: - /* ds overridden */ - case SYSMODE_SEGOVR_ES|SYSMODE_SEG_DS_SS: - /* ss overridden, use es register */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - value = GetBYTEExtended((((uint32)m->R_ES << 4) + offset) & 0xFFFFF); - break; - case SYSMODE_SEGOVR_SS: - /* ds overridden */ - case SYSMODE_SEGOVR_SS|SYSMODE_SEG_DS_SS: - /* ss overridden, use ss register === should not happen */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - value = GetBYTEExtended((((uint32)m->R_SS << 4) + offset) & 0xFFFFF); - break; - default: - printf("error: should not happen: multiple overrides. " NLP); - value = 0; - halt_sys(m); - } - return value; -} - -/* fetch a byte of data, given an offset, the current register set, - and a descriptor for memory. -*/ -uint8 fetch_data_byte_abs(PC_ENV *m, uint16 segment, uint16 offset) -{ - register uint8 value; - uint32 addr; - /* note, cannot change this, since we do not know the ID of the segment. */ -/* [JCE] Simulate wrap at top of memory (the A20 gate) */ -/* addr = (segment << 4) + offset; */ - addr = ((segment << 4) + offset) & 0xFFFFF; - value = GetBYTEExtended(addr); - return value; -} - -/* fetch a byte of data, given an offset, the current register set, - and a descriptor for memory. -*/ -uint16 fetch_data_word(PC_ENV *m, uint16 offset) -{ - uint16 value; - /* See note above in fetch_data_byte. */ - switch(m->sysmode & SYSMODE_SEGMASK) - { - case 0: - /* default case: use ds register */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - value = GetBYTEExtended((((uint32)m->R_DS << 4) + offset) & 0xFFFFF) - | (GetBYTEExtended((((uint32)m->R_DS << 4) + - (uint16)(offset + 1)) & 0xFFFFF) << 8); - break; - case SYSMODE_SEG_DS_SS: - /* non-overridden, use ss register */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - value = GetBYTEExtended((((uint32)m->R_SS << 4) + offset) & 0xFFFFF) - | (GetBYTEExtended((((uint32)m->R_SS << 4) - + (uint16)(offset + 1)) & 0xFFFFF) << 8); - break; - case SYSMODE_SEGOVR_CS: - /* ds overridden */ - case SYSMODE_SEGOVR_CS|SYSMODE_SEG_DS_SS: - /* ss overridden, use cs register */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - value = GetBYTEExtended((((uint32)m->R_CS << 4) + offset) & 0xFFFFF) - | (GetBYTEExtended((((uint32)m->R_CS << 4) - + (uint16)(offset + 1)) & 0xFFFFF) << 8); - break; - case SYSMODE_SEGOVR_DS: - /* ds overridden --- shouldn't happen, but hey. */ - case SYSMODE_SEGOVR_DS|SYSMODE_SEG_DS_SS: - /* ss overridden, use ds register */ - /* [JCE] Wrap at 1Mb (the A20 gate) */ - value = GetBYTEExtended((((uint32)m->R_DS << 4) + offset) & 0xFFFFF) - | (GetBYTEExtended((((uint32)m->R_DS << 4) - + (uint16)(offset + 1)) & 0xFFFFF) << 8); - break; - case SYSMODE_SEGOVR_ES: - /* ds overridden */ - case SYSMODE_SEGOVR_ES|SYSMODE_SEG_DS_SS: - /* ss overridden, use es register */ - value = GetBYTEExtended((((uint32)m->R_ES << 4) + offset) & 0xFFFFF) - | (GetBYTEExtended((((uint32)m->R_ES << 4) + - (uint16)(offset + 1)) & 0xFFFFF) << 8); - break; - case SYSMODE_SEGOVR_SS: - /* ds overridden */ - case SYSMODE_SEGOVR_SS|SYSMODE_SEG_DS_SS: - /* ss overridden, use ss register === should not happen */ - value = GetBYTEExtended((((uint32)m->R_SS << 4) + offset) & 0xFFFFF) - | (GetBYTEExtended((((uint32)m->R_SS << 4) - + (uint16)(offset + 1)) & 0xFFFFF) << 8); - break; - default: - printf("error: should not happen: multiple overrides. " NLP); - value = 0; - halt_sys(m); - } - return value; -} - -/* fetch a byte of data, given an offset, the current register set, - and a descriptor for memory. -*/ -uint16 fetch_data_word_abs(PC_ENV *m, uint16 segment, uint16 offset) -{ - uint16 value; - uint32 addr; -/* [JCE] Simulate wrap at top of memory (the A20 gate) */ -/* addr = (segment << 4) + offset; */ - addr = ((segment << 4) + offset) & 0xFFFFF; - value = GetBYTEExtended(addr) | (GetBYTEExtended(addr + 1) << 8); - return value; -} - -/* Store a byte of data, given an offset, the current register set, - and a descriptor for memory. -*/ -void store_data_byte(PC_ENV *m, uint16 offset, uint8 val) -{ - /* See note above in fetch_data_byte. */ - uint32 addr; - register uint16 segment; - switch(m->sysmode & SYSMODE_SEGMASK) - { - case 0: - /* default case: use ds register */ - segment = m->R_DS; - break; - case SYSMODE_SEG_DS_SS: - /* non-overridden, use ss register */ - segment = m->R_SS; - break; - case SYSMODE_SEGOVR_CS: - /* ds overridden */ - case SYSMODE_SEGOVR_CS|SYSMODE_SEG_DS_SS: - /* ss overridden, use cs register */ - segment = m->R_CS; - break; - case SYSMODE_SEGOVR_DS: - /* ds overridden --- shouldn't happen, but hey. */ - case SYSMODE_SEGOVR_DS|SYSMODE_SEG_DS_SS: - /* ss overridden, use ds register */ - segment = m->R_DS; - break; - case SYSMODE_SEGOVR_ES: - /* ds overridden */ - case SYSMODE_SEGOVR_ES|SYSMODE_SEG_DS_SS: - /* ss overridden, use es register */ - segment = m->R_ES; - break; - case SYSMODE_SEGOVR_SS: - /* ds overridden */ - case SYSMODE_SEGOVR_SS|SYSMODE_SEG_DS_SS: - /* ss overridden, use ss register === should not happen */ - segment = m->R_SS; - break; - default: - printf("error: should not happen: multiple overrides. " NLP); - segment = 0; - halt_sys(m); - } -/* [JCE] Simulate wrap at top of memory (the A20 gate) */ -/* addr = (segment << 4) + offset; */ - addr = (((uint32)segment << 4) + offset) & 0xFFFFF; - PutBYTEExtended(addr, val); -} - -void store_data_byte_abs(PC_ENV *m, uint16 segment, uint16 offset, uint8 val) -{ - register uint32 addr; -/* [JCE] Simulate wrap at top of memory (the A20 gate) */ -/* addr = (segment << 4) + offset; */ - addr = (((uint32)segment << 4) + offset) & 0xFFFFF; - PutBYTEExtended(addr, val); -} - -/* Store a word of data, given an offset, the current register set, - and a descriptor for memory. -*/ -void store_data_word(PC_ENV *m, uint16 offset, uint16 val) -{ - register uint32 addr; - register uint16 segment; - /* See note above in fetch_data_byte. */ - switch(m->sysmode & SYSMODE_SEGMASK) - { - case 0: - /* default case: use ds register */ - segment = m->R_DS; - break; - case SYSMODE_SEG_DS_SS: - /* non-overridden, use ss register */ - segment = m->R_SS; - break; - case SYSMODE_SEGOVR_CS: - /* ds overridden */ - case SYSMODE_SEGOVR_CS|SYSMODE_SEG_DS_SS: - /* ss overridden, use cs register */ - segment = m->R_CS; - break; - case SYSMODE_SEGOVR_DS: - /* ds overridden --- shouldn't happen, but hey. */ - case SYSMODE_SEGOVR_DS|SYSMODE_SEG_DS_SS: - /* ss overridden, use ds register */ - segment = m->R_DS; - break; - case SYSMODE_SEGOVR_ES: - /* ds overridden */ - case SYSMODE_SEGOVR_ES|SYSMODE_SEG_DS_SS: - /* ss overridden, use es register */ - segment = m->R_ES; - break; - case SYSMODE_SEGOVR_SS: - /* ds overridden */ - case SYSMODE_SEGOVR_SS|SYSMODE_SEG_DS_SS: - /* ss overridden, use ss register === should not happen */ - segment = m->R_SS; - break; - default: - printf("error: should not happen: multiple overrides." NLP); - segment = 0; - halt_sys(m); - } -/* [JCE] Simulate wrap at top of memory (the A20 gate) */ -/* addr = (segment << 4) + offset; */ - addr = (((uint32)segment << 4) + offset) & 0xFFFFF; - PutBYTEExtended(addr, val & 0xff); - PutBYTEExtended(addr + 1, val >> 8); -} - -void store_data_word_abs(PC_ENV *m, uint16 segment, uint16 offset, uint16 val) -{ - register uint32 addr; - /* [JCE] Wrap at top of memory */ - addr = ((segment << 4) + offset) & 0xFFFFF; - PutBYTEExtended(addr, val & 0xff); - PutBYTEExtended(addr + 1, val >> 8); -} diff --git a/AltairZ80/i86_ops.c b/AltairZ80/i86_ops.c deleted file mode 100644 index cb60407e..00000000 --- a/AltairZ80/i86_ops.c +++ /dev/null @@ -1,5488 +0,0 @@ -/* - * Dos/PC Emulator - * 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. - * - */ - -#include "altairz80_defs.h" -#include "i86.h" - -extern void out(const uint32 Port, const uint32 Value); -extern uint32 in(const uint32 Port); - -/* $Log: i86_ops.c,v $ - * Revision 0.11 1991/07/30 02:02:04 hudgens - * added copyright. - * - * Revision 0.10 1991/07/21 18:22:08 hudgens - * Fixed problem with scans, which was the result of the loop break - * condition being incorrect when used in conjunction with the repe - * or repne prefixes. Eureka. pkzip/pkunzip now compress/decompress - * correctly. - * - * Revision 0.9 1991/07/21 03:33:18 hudgens - * fixed popf so that it appears to be the same as an 8088 popf, and always - * sets the high 4 bits of the flags. - * - * Revision 0.8 1991/07/21 01:44:11 hudgens - * fixed aad and aam instructions. - * - * Revision 0.7 1991/07/21 00:31:24 hudgens - * Fixed iret so that it works correctly. - * - * Revision 0.6 1991/07/20 16:54:50 hudgens - * removed the 8087 coprocessor operations. Moved to i87_ops.c - * - * Revision 0.5 1991/07/17 03:50:10 hudgens - * Minor modifications. - * - * Revision 0.4 1991/06/18 02:48:41 hudgens - * Fixed a problem with scasb and scasw. - * - * Revision 0.3 1991/06/03 01:01:10 hudgens - * fixed minor problems due to unsigned to signed short integer - * promotions. - * - * Revision 0.2 1991/03/31 01:32:10 hudgens - * fixed segment handling. Added calls to DECODE_CLEAR_SEGOVR in - * many places in the code. Should work much better now. - * - * Revision 0.1 1991/03/30 21:15:48 hudgens - * Initial checkin to RCS. - * - * - */ - -/* 2/23/91 fixed decode for operand x87. */ - -/* partially mechanically generated file....(based on the optable) */ -/* - There are approximately 250 subroutines in here, which correspond - to the 256 byte-"opcodes" found on the 8086. The table which - dispatches this is found in the files optab.[ch]. - - Each opcode proc has a comment preceeding it which gives it's table - address. Several opcodes are missing (undefined) in the table. - - Each proc includes information for decoding (DECODE_PRINTF and - and misc functions ( - Many of the procedures are *VERY* similar in coding. This has - allowed for a very large amount of code to be generated in a fairly - short amount of time (i.e. cut, paste, and modify). - The result is that much of the code below could - have been folded into subroutines for a large reduction in size of - this file. The downside would be that there would be a penalty in - execution speed. The file could also have been *MUCH* larger by - inlining certain functions which were called. This could have - resulted even faster execution. The prime directive I used to decide - whether to inline the code or to modularize it, was basically: 1) no - unnecessary subroutine calls, 2) no routines more than about 200 lines - in size, and 3) modularize any code that I might not get right the first - time. The fetch_* subroutines fall into the latter category. The - The decode_* fall into the second category. The coding of the - "switch(mod){ .... }" in many of the subroutines below falls into the - first category. Especially, the coding of {add,and,or,sub,...}_{byte,word} - subroutines are an especially glaring case of the third guideline. - Since so much of the code is cloned from other modules (compare - opcode #00 to opcode #01), making the basic operations subroutine calls - is especially important; otherwise mistakes in coding an "add" - would represent a nightmare in maintenance. - - So, without further ado, ... -*/ - -extern uint8 parity_tab[]; - -static void i86op_illegal_op(PC_ENV *m) -{ - intr |= INTR_ILLEGAL_OPCODE; -} - -/*opcode=0x00*/ -static void i86op_add_byte_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 destoffset; - uint8 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = add_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = add_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = add_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - *destreg = add_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x01*/ -static void i86op_add_word_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - uint16 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = add_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = add_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = add_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - *destreg = add_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x02*/ -static void i86op_add_byte_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 srcoffset; - uint8 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = add_byte(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = add_byte(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = add_byte(m, * destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcreg = DECODE_RM_BYTE_REGISTER(m,rl); - *destreg = add_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x03*/ -static void i86op_add_word_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 srcoffset; - uint16 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = add_word(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = add_word(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = add_word(m, *destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcreg = DECODE_RM_WORD_REGISTER(m,rl); - *destreg = add_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x04*/ -static void i86op_add_byte_AL_IMM(PC_ENV *m) -{ - uint8 srcval; - srcval = fetch_byte_imm(m); - m->R_AL = add_byte(m, m->R_AL, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x05*/ -static void i86op_add_word_AX_IMM(PC_ENV *m) -{ - uint16 srcval; - srcval = fetch_word_imm(m); - m->R_AX = add_word(m, m->R_AX, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x06*/ -static void i86op_push_ES(PC_ENV *m) -{ - push_word(m,m->R_ES); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x07*/ -static void i86op_pop_ES(PC_ENV *m) -{ - m->R_ES = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x08*/ -static void i86op_or_byte_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 destoffset; - uint8 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = or_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = or_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = or_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - *destreg = or_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x09*/ -static void i86op_or_word_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - uint16 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = or_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = or_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = or_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - *destreg = or_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x0a*/ -static void i86op_or_byte_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 srcoffset; - uint8 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = or_byte(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = or_byte(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = or_byte(m, * destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcreg = DECODE_RM_BYTE_REGISTER(m,rl); - *destreg = or_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x0b*/ -static void i86op_or_word_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 srcoffset; - uint16 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = or_word(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = or_word(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = or_word(m, *destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcreg = DECODE_RM_WORD_REGISTER(m,rl); - *destreg = or_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x0c*/ -static void i86op_or_byte_AL_IMM(PC_ENV *m) -{ - uint8 srcval; - srcval = fetch_byte_imm(m); - m->R_AL = or_byte(m, m->R_AL, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x0d*/ -static void i86op_or_word_AX_IMM(PC_ENV *m) -{ - uint16 srcval; - srcval = fetch_word_imm(m); - m->R_AX = or_word(m, m->R_AX, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x0e*/ -static void i86op_push_CS(PC_ENV *m) -{ - push_word(m,m->R_CS); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x0f === ILLEGAL OP*/ - -/*opcode=0x10*/ -static void i86op_adc_byte_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 destoffset; - uint8 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = adc_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = adc_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = adc_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - *destreg = adc_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x11*/ -static void i86op_adc_word_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - uint16 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = adc_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = adc_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = adc_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - *destreg = adc_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x12*/ -static void i86op_adc_byte_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 srcoffset; - uint8 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = adc_byte(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = adc_byte(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = adc_byte(m, * destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcreg = DECODE_RM_BYTE_REGISTER(m,rl); - *destreg = adc_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x13*/ -static void i86op_adc_word_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 srcoffset; - uint16 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = adc_word(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = adc_word(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = adc_word(m, *destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcreg = DECODE_RM_WORD_REGISTER(m,rl); - *destreg = adc_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x14*/ -static void i86op_adc_byte_AL_IMM(PC_ENV *m) -{ - uint8 srcval; - srcval = fetch_byte_imm(m); - m->R_AL = adc_byte(m, m->R_AL, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x15*/ -static void i86op_adc_word_AX_IMM(PC_ENV *m) -{ - uint16 srcval; - srcval = fetch_word_imm(m); - m->R_AX = adc_word(m, m->R_AX, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x16*/ -static void i86op_push_SS(PC_ENV *m) -{ - push_word(m,m->R_SS); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x17*/ -static void i86op_pop_SS(PC_ENV *m) -{ - m->R_SS = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x18*/ -static void i86op_sbb_byte_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 destoffset; - uint8 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = sbb_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = sbb_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = sbb_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - *destreg = sbb_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x19*/ -static void i86op_sbb_word_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - uint16 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = sbb_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = sbb_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = sbb_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - *destreg = sbb_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x1a*/ -static void i86op_sbb_byte_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 srcoffset; - uint8 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = sbb_byte(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = sbb_byte(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = sbb_byte(m, * destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcreg = DECODE_RM_BYTE_REGISTER(m,rl); - *destreg = sbb_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x1b*/ -static void i86op_sbb_word_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 srcoffset; - uint16 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = sbb_word(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = sbb_word(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = sbb_word(m, *destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcreg = DECODE_RM_WORD_REGISTER(m,rl); - *destreg = sbb_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x1c*/ -static void i86op_sbb_byte_AL_IMM(PC_ENV *m) -{ - uint8 srcval; - srcval = fetch_byte_imm(m); - m->R_AL = sbb_byte(m, m->R_AL, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x1d*/ -static void i86op_sbb_word_AX_IMM(PC_ENV *m) -{ - uint16 srcval; - srcval = fetch_word_imm(m); - m->R_AX = sbb_word(m, m->R_AX, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x1e*/ -static void i86op_push_DS(PC_ENV *m) -{ - push_word(m,m->R_DS); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x1f*/ -static void i86op_pop_DS(PC_ENV *m) -{ - m->R_DS = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x20*/ -static void i86op_and_byte_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 destoffset; - uint8 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = and_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = and_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = and_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - *destreg = and_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x21*/ -static void i86op_and_word_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - uint16 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = and_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = and_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = and_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - *destreg = and_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x22*/ -static void i86op_and_byte_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 srcoffset; - uint8 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = and_byte(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = and_byte(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = and_byte(m, * destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcreg = DECODE_RM_BYTE_REGISTER(m,rl); - *destreg = and_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x23*/ -static void i86op_and_word_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 srcoffset; - uint16 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = and_word(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = and_word(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = and_word(m, *destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcreg = DECODE_RM_WORD_REGISTER(m,rl); - *destreg = and_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x24*/ -static void i86op_and_byte_AL_IMM(PC_ENV *m) -{ - uint8 srcval; - srcval = fetch_byte_imm(m); - m->R_AL = and_byte(m, m->R_AL, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x25*/ -static void i86op_and_word_AX_IMM(PC_ENV *m) -{ - uint16 srcval; - srcval = fetch_word_imm(m); - m->R_AX = and_word(m, m->R_AX, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x26*/ -static void i86op_segovr_ES(PC_ENV *m) -{ - m->sysmode |= SYSMODE_SEGOVR_ES; - /* note the lack of DECODE_CLEAR_SEGOVR(r) - since, here is one of 4 opcode subroutines we do not - want to do this. - */ -} - -/*opcode=0x27*/ -static void i86op_daa(PC_ENV *m) -{ - uint16 dbyte; - dbyte = m->R_AL; - if (ACCESS_FLAG(m,F_AF)|| (dbyte&0xf) > 9) - { - dbyte += 6; - if (dbyte&0x100) - SET_FLAG(m, F_CF); - SET_FLAG(m, F_AF); - } - else - CLEAR_FLAG(m, F_AF); - if (ACCESS_FLAG(m,F_CF) || (dbyte&0xf0) > 0x90) - { - dbyte += 0x60; - SET_FLAG(m, F_CF); - } - else - CLEAR_FLAG(m, F_CF); - m->R_AL = (uint8) dbyte; - CONDITIONAL_SET_FLAG((m->R_AL & 0x80),m,F_SF); - CONDITIONAL_SET_FLAG((m->R_AL == 0), m,F_ZF); - CONDITIONAL_SET_FLAG((parity_tab[m->R_AL]),m,F_PF); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x28*/ -static void i86op_sub_byte_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 destoffset; - uint8 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = sub_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = sub_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = sub_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - *destreg = sub_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x29*/ -static void i86op_sub_word_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - uint16 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = sub_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = sub_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = sub_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - *destreg = sub_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x2a*/ -static void i86op_sub_byte_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 srcoffset; - uint8 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = sub_byte(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = sub_byte(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = sub_byte(m, * destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcreg = DECODE_RM_BYTE_REGISTER(m,rl); - *destreg = sub_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x2b*/ -static void i86op_sub_word_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 srcoffset; - uint16 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = sub_word(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = sub_word(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = sub_word(m, *destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcreg = DECODE_RM_WORD_REGISTER(m,rl); - *destreg = sub_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x2c*/ -static void i86op_sub_byte_AL_IMM(PC_ENV *m) -{ - uint8 srcval; - srcval = fetch_byte_imm(m); - m->R_AL = sub_byte(m, m->R_AL, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x2d*/ -static void i86op_sub_word_AX_IMM(PC_ENV *m) -{ - uint16 srcval; - srcval = fetch_word_imm(m); - m->R_AX = sub_word(m, m->R_AX, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x2e*/ -static void i86op_segovr_CS(PC_ENV *m) -{ - m->sysmode |= SYSMODE_SEGOVR_CS; - /* note no DECODE_CLEAR_SEGOVER here. */ -} - -/*opcode=0x2f*/ -static void i86op_das(PC_ENV *m) -{ - uint16 dbyte; - dbyte = m->R_AL; - if ( ACCESS_FLAG(m,F_AF) || (dbyte&0xf) > 9) - { - dbyte -= 6; - if (dbyte&0x100) /* XXXXX --- this is WRONG */ - SET_FLAG(m, F_CF); - SET_FLAG(m, F_AF); - } - else - CLEAR_FLAG(m, F_AF); - if (ACCESS_FLAG(m,F_CF) || (dbyte&0xf0) > 0x90) - { - dbyte -= 0x60; - SET_FLAG(m, F_CF); - } - else - CLEAR_FLAG(m, F_CF); - m->R_AL = (uint8) dbyte; - CONDITIONAL_SET_FLAG(m->R_AL & 0x80,m,F_SF); - CONDITIONAL_SET_FLAG(m->R_AL == 0,m,F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[m->R_AL],m,F_PF); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x30*/ -static void i86op_xor_byte_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 destoffset; - uint8 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = xor_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = xor_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - destval = xor_byte(m, destval, *srcreg); - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - *destreg = xor_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x31*/ -static void i86op_xor_word_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - uint16 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = xor_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = xor_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destval = xor_word(m, destval, *srcreg); - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - *destreg = xor_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x32*/ -static void i86op_xor_byte_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 srcoffset; - uint8 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = xor_byte(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = xor_byte(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = xor_byte(m, *destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcreg = DECODE_RM_BYTE_REGISTER(m,rl); - *destreg = xor_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x33*/ -static void i86op_xor_word_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 srcoffset; - uint16 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = xor_word(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = xor_word(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = xor_word(m, *destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcreg = DECODE_RM_WORD_REGISTER(m,rl); - *destreg = xor_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x34*/ -static void i86op_xor_byte_AL_IMM(PC_ENV *m) -{ - uint8 srcval; - srcval = fetch_byte_imm(m); - m->R_AL = xor_byte(m, m->R_AL, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x35*/ -static void i86op_xor_word_AX_IMM(PC_ENV *m) -{ - uint16 srcval; - srcval = fetch_word_imm(m); - m->R_AX = xor_word(m, m->R_AX, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x36*/ -static void i86op_segovr_SS(PC_ENV *m) -{ - m->sysmode |= SYSMODE_SEGOVR_SS; - /* no DECODE_CLEAR_SEGOVER ! */ -} - -/*opcode=0x37*/ -static void i86op_aaa(PC_ENV *m) -{ - if ( (m->R_AL & 0xf) > 0x9 || ACCESS_FLAG(m,F_AF)) - { - m->R_AL += 0x6; - m->R_AH += 1; - SET_FLAG(m, F_AF); - SET_FLAG(m, F_CF); - } - else - { - CLEAR_FLAG(m, F_CF); - CLEAR_FLAG(m, F_AF); - } - m->R_AL &= 0xf; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x38*/ -static void i86op_cmp_byte_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 destoffset; - uint8 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - cmp_byte(m, destval, *srcreg); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - cmp_byte(m, destval, *srcreg); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - cmp_byte(m, destval, *srcreg); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - cmp_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x39*/ -static void i86op_cmp_word_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - uint16 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - cmp_word(m, destval, *srcreg); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - cmp_word(m, destval, *srcreg); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - cmp_word(m, destval, *srcreg); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - cmp_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x3a*/ -static void i86op_cmp_byte_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 srcoffset; - uint8 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - cmp_byte(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - cmp_byte(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - cmp_byte(m, * destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcreg = DECODE_RM_BYTE_REGISTER(m,rl); - cmp_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x3b*/ -static void i86op_cmp_word_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 srcoffset; - uint16 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - cmp_word(m, *destreg, srcval); - break; - case 1: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - cmp_word(m, *destreg, srcval); - break; - case 2: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - cmp_word(m, *destreg, srcval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcreg = DECODE_RM_WORD_REGISTER(m,rl); - cmp_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x3c*/ -static void i86op_cmp_byte_AL_IMM(PC_ENV *m) -{ - uint8 srcval; - srcval = fetch_byte_imm(m); - cmp_byte(m, m->R_AL, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x3d*/ -static void i86op_cmp_word_AX_IMM(PC_ENV *m) -{ - uint16 srcval; - srcval = fetch_word_imm(m); - cmp_word(m, m->R_AX, srcval); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x3e*/ -static void i86op_segovr_DS(PC_ENV *m) -{ - m->sysmode |= SYSMODE_SEGOVR_DS; - /* NO DECODE_CLEAR_SEGOVR! */ -} - -/*opcode=0x3f*/ -static void i86op_aas(PC_ENV *m) -{ - /* ???? Check out the subtraction here. Will this ?ever? cause - the contents of R_AL or R_AH to be affected incorrectly since - they are being subtracted from *and* are unsigned. - Should put an assertion in here. - */ - if ( (m->R_AL & 0xf) > 0x9 || ACCESS_FLAG(m,F_AF)) - { - m->R_AL -= 0x6; - m->R_AH -= 1; - SET_FLAG(m, F_AF); - SET_FLAG(m, F_CF); - } - else - { - CLEAR_FLAG(m, F_CF); - CLEAR_FLAG(m, F_AF); - } - m->R_AL &= 0xf; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x40*/ -static void i86op_inc_AX(PC_ENV *m) -{ - m->R_AX = inc_word(m,m->R_AX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x41*/ -static void i86op_inc_CX(PC_ENV *m) -{ - m->R_CX = inc_word(m,m->R_CX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x42*/ -static void i86op_inc_DX(PC_ENV *m) -{ - m->R_DX = inc_word(m,m->R_DX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x43*/ -static void i86op_inc_BX(PC_ENV *m) -{ - m->R_BX = inc_word(m,m->R_BX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x44*/ -static void i86op_inc_SP(PC_ENV *m) -{ - m->R_SP = inc_word(m,m->R_SP); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x45*/ -static void i86op_inc_BP(PC_ENV *m) -{ - m->R_BP = inc_word(m,m->R_BP); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x46*/ -static void i86op_inc_SI(PC_ENV *m) -{ - m->R_SI = inc_word(m,m->R_SI); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x47*/ -static void i86op_inc_DI(PC_ENV *m) -{ - m->R_DI = inc_word(m,m->R_DI); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x48*/ -static void i86op_dec_AX(PC_ENV *m) -{ - m->R_AX = dec_word(m,m->R_AX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x49*/ -static void i86op_dec_CX(PC_ENV *m) -{ - m->R_CX = dec_word(m,m->R_CX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x4a*/ -static void i86op_dec_DX(PC_ENV *m) -{ - m->R_DX = dec_word(m,m->R_DX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x4b*/ -static void i86op_dec_BX(PC_ENV *m) -{ - m->R_BX = dec_word(m,m->R_BX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x4c*/ -static void i86op_dec_SP(PC_ENV *m) -{ - m->R_SP = dec_word(m,m->R_SP); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x4d*/ -static void i86op_dec_BP(PC_ENV *m) -{ - m->R_BP = dec_word(m,m->R_BP); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x4e*/ -static void i86op_dec_SI(PC_ENV *m) -{ - m->R_SI = dec_word(m,m->R_SI); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x4f*/ -static void i86op_dec_DI(PC_ENV *m) -{ - m->R_DI = dec_word(m,m->R_DI); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x50*/ -static void i86op_push_AX(PC_ENV *m) -{ - push_word(m,m->R_AX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x51*/ -static void i86op_push_CX(PC_ENV *m) -{ - push_word(m,m->R_CX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x52*/ -static void i86op_push_DX(PC_ENV *m) -{ - push_word(m,m->R_DX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x53*/ -static void i86op_push_BX(PC_ENV *m) -{ - push_word(m,m->R_BX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x54*/ -static void i86op_push_SP(PC_ENV *m) -{ - /* .... Note this weirdness: One book I have access to - claims that the value pushed here is actually sp-2. I.e. - it decrements the stackpointer, and then pushes it. The 286 - I have does it this way. Changing this causes many problems.*/ - /* changed to push SP-2, since this *IS* how a 8088 does this */ - push_word(m,m->R_SP-2); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x55*/ -static void i86op_push_BP(PC_ENV *m) -{ - push_word(m,m->R_BP); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x56*/ -static void i86op_push_SI(PC_ENV *m) -{ - push_word(m,m->R_SI); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x57*/ -static void i86op_push_DI(PC_ENV *m) -{ - push_word(m,m->R_DI); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x58*/ -static void i86op_pop_AX(PC_ENV *m) -{ - m->R_AX = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x59*/ -static void i86op_pop_CX(PC_ENV *m) -{ - m->R_CX = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x5a*/ -static void i86op_pop_DX(PC_ENV *m) -{ - m->R_DX = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x5b*/ -static void i86op_pop_BX(PC_ENV *m) -{ - m->R_BX = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x5c*/ -static void i86op_pop_SP(PC_ENV *m) -{ - m->R_SP = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x5d*/ -static void i86op_pop_BP(PC_ENV *m) -{ - m->R_BP = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x5e*/ -static void i86op_pop_SI(PC_ENV *m) -{ - m->R_SI = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x5f*/ -static void i86op_pop_DI(PC_ENV *m) -{ - m->R_DI = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x60 ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x61 ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x62 ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x63 ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x64 ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x65 ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x66 ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x67 ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x68 ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x69 ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x6a ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x6b ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x6c ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x6d ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x6e ILLEGAL OP, calls i86op_illegal_op() */ -/*opcode=0x6f ILLEGAL OP, calls i86op_illegal_op() */ - -/*opcode=0x70*/ -static void i86op_jump_near_O(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if overflow flag is set */ - offset = (int8) fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - if (ACCESS_FLAG(m,F_OF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x71*/ -static void i86op_jump_near_NO(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if overflow is not set */ - offset = (int8) fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - if (!ACCESS_FLAG(m,F_OF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x72*/ -static void i86op_jump_near_B(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if carry flag is set. */ - offset = (int8)fetch_byte_imm(m); /* sign extended ??? */ - target = (int16)(m->R_IP) + offset; - if (ACCESS_FLAG(m, F_CF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x73*/ -static void i86op_jump_near_NB(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if carry flag is clear. */ - offset = (int8)fetch_byte_imm(m); /* sign extended ??? */ - target = (int16)(m->R_IP) + offset; - if (!ACCESS_FLAG(m,F_CF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x74*/ -static void i86op_jump_near_Z(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if zero flag is set. */ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - if (ACCESS_FLAG(m, F_ZF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x75*/ -static void i86op_jump_near_NZ(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if zero flag is clear. */ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - if (!ACCESS_FLAG(m, F_ZF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x76*/ -static void i86op_jump_near_BE(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if carry flag is set or if the zero - flag is set. */ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - if (ACCESS_FLAG(m,F_CF) || ACCESS_FLAG(m,F_ZF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x77*/ -static void i86op_jump_near_NBE(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if carry flag is clear and if the zero - flag is clear */ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - if (!(ACCESS_FLAG(m,F_CF)||ACCESS_FLAG(m,F_ZF))) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x78*/ -static void i86op_jump_near_S(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if sign flag is set */ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - if (ACCESS_FLAG(m,F_SF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x79*/ -static void i86op_jump_near_NS(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if sign flag is clear */ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - if (!ACCESS_FLAG(m,F_SF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x7a*/ -static void i86op_jump_near_P(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if parity flag is set (even parity) */ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - if (ACCESS_FLAG(m, F_PF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x7b*/ -static void i86op_jump_near_NP(PC_ENV *m) -{ - int8 offset; - uint16 target; - /* jump to byte offset if parity flag is clear (odd parity) */ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - if (!ACCESS_FLAG(m, F_PF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/* JHH fixed till here... */ - -/*opcode=0x7c*/ -static void i86op_jump_near_L(PC_ENV *m) -{ - int8 offset; - uint16 target; - int sf,of; - /* jump to byte offset if sign flag not equal to overflow flag. */ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - /* note: - * this is the simplest expression i could think of which - * expresses SF != OF. m->R_FLG&F_SF either equals x80 or x00. - * Similarly m->R_FLG&F_OF either equals x800 or x000. - * The former shifted right by 7 puts a 1 or 0 in bit 0. - * The latter shifter right by 11 puts a 1 or 0 in bit 0. - * if the two expressions are the same, i.e. equal, then - * a zero results from the xor. If they are not equal, - * then a 1 results, and the jump is taken. - */ - sf = ACCESS_FLAG(m,F_SF) != 0; - of = ACCESS_FLAG(m,F_OF) != 0; - /* was: if ( ((m->R_FLG & F_SF)>>7) ^ ((m->R_FLG & F_OF) >> 11))*/ - if (sf ^ of) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x7d*/ -static void i86op_jump_near_NL(PC_ENV *m) -{ - int8 offset; - uint16 target; - int sf,of; - /* jump to byte offset if sign flag not equal to overflow flag. */ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - sf = ACCESS_FLAG(m,F_SF) != 0; - of = ACCESS_FLAG(m,F_OF) != 0; - /* note: inverse of above, but using == instead of xor. */ - /* was: if (((m->R_FLG & F_SF)>>7) == ((m->R_FLG & F_OF) >> 11))*/ - if (sf == of) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x7e*/ -static void i86op_jump_near_LE(PC_ENV *m) -{ - int8 offset; - uint16 target; - int sf,of; - /* jump to byte offset if sign flag not equal to overflow flag - or the zero flag is set */ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - sf = ACCESS_FLAG(m,F_SF) != 0; - of = ACCESS_FLAG(m,F_OF) != 0; - /* note: modification of JL */ - /* sf != of */ - /* was: if ((((m->R_FLG & F_SF)>>7) ^ ((m->R_FLG & F_OF) >> 11)) - || (m->R_FLG & F_ZF) ) */ - if ( (sf ^ of) || ACCESS_FLAG(m,F_ZF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x7f*/ -static void i86op_jump_near_NLE(PC_ENV *m) -{ - int8 offset; - uint16 target; - int sf,of; - /* jump to byte offset if sign flag equal to overflow flag. - and the zero flag is clear*/ - offset = (int8)fetch_byte_imm(m); - target = (int16)(m->R_IP) + offset; - sf = ACCESS_FLAG(m,F_SF) != 0; - of = ACCESS_FLAG(m,F_OF) != 0; - -/* if (((m->R_FLG & F_SF)>>7) == ((m->R_FLG & F_OF) >> 11) - && (!(m->R_FLG & F_ZF))) */ - if ( ( sf == of ) && !ACCESS_FLAG(m,F_ZF)) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -static uint8 (*opc80_byte_operation[])(PC_ENV *m,uint8 d,uint8 s) = -{ - add_byte,/*00*/ - or_byte, /*01*/ - adc_byte,/*02*/ - sbb_byte,/*03*/ - and_byte,/*04*/ - sub_byte,/*05*/ - xor_byte,/*06*/ - cmp_byte,/*07*/ -}; - -/*opcode=0x80*/ -static void i86op_opc80_byte_RM_IMM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg; - uint16 destoffset; - uint8 imm; - uint8 destval; - /* weirdo special case instruction format. Part of the - opcode held below in "RH". Doubly nested case would - result, except that the decoded instruction - */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - /* know operation, decode the mod byte to find the addressing - mode. */ - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - imm = fetch_byte_imm(m); - destval = (*opc80_byte_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - imm = fetch_byte_imm(m); - destval = (*opc80_byte_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - imm = fetch_byte_imm(m); - destval = (*opc80_byte_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - imm = fetch_byte_imm(m); - destval = (*opc80_byte_operation[rh])(m, *destreg, imm); - if (rh != 7) - *destreg = destval; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -static uint16 (*opc81_word_operation[])(PC_ENV *m,uint16 d,uint16 s) = -{ add_word,/*00*/ - or_word, /*01*/ - adc_word,/*02*/ - sbb_word,/*03*/ - and_word,/*04*/ - sub_word,/*05*/ - xor_word,/*06*/ - cmp_word,/*07*/ -}; - -/*opcode=0x81*/ -static void i86op_opc81_word_RM_IMM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg; - uint16 destoffset; - uint16 imm; - uint16 destval; - /* weirdo special case instruction format. Part of the - opcode held below in "RH". Doubly nested case would - result, except that the decoded instruction - */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - /* know operation, decode the mod byte to find the addressing - mode. */ - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - imm = fetch_word_imm(m); - destval = (*opc81_word_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - imm = fetch_word_imm(m); - destval = (*opc81_word_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - imm = fetch_word_imm(m); - destval = (*opc81_word_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - imm = fetch_word_imm(m); - destval = (*opc81_word_operation[rh])(m, *destreg, imm); - if (rh != 7) - *destreg = destval; - break; - } - DECODE_CLEAR_SEGOVR(m); - } - -static uint8 (*opc82_byte_operation[])(PC_ENV *m,uint8 s,uint8 d) = -{ - add_byte,/*00*/ - or_byte, /*01*/ /*YYY UNUSED ????*/ - adc_byte,/*02*/ - sbb_byte,/*03*/ - and_byte,/*04*/ /*YYY UNUSED ????*/ - sub_byte,/*05*/ - xor_byte,/*06*/ /*YYY UNUSED ????*/ - cmp_byte,/*07*/ -}; - -/*opcode=0x82*/ -static void i86op_opc82_byte_RM_IMM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg; - uint16 destoffset; - uint8 imm; - uint8 destval; - /* weirdo special case instruction format. Part of the - opcode held below in "RH". Doubly nested case would - result, except that the decoded instruction - Similar to opcode 81, except that the immediate byte - is sign extended to a word length. - */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - /* know operation, decode the mod byte to find the addressing - mode. */ - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - imm = fetch_byte_imm(m); - destval = (*opc82_byte_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - imm = fetch_byte_imm(m); - destval = (*opc82_byte_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - imm = fetch_byte_imm(m); - destval = (*opc82_byte_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - imm = fetch_byte_imm(m); - destval = (*opc82_byte_operation[rh])(m, *destreg, imm); - if (rh != 7) - *destreg = destval; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -static uint16 (*opc83_word_operation[])(PC_ENV *m,uint16 s,uint16 d) = -{ - add_word,/*00*/ - or_word, /*01*/ /*YYY UNUSED ????*/ - adc_word,/*02*/ - sbb_word,/*03*/ - and_word,/*04*/ /*YYY UNUSED ????*/ - sub_word,/*05*/ - xor_word,/*06*/ /*YYY UNUSED ????*/ - cmp_word,/*07*/ -}; - -/*opcode=0x83*/ -static void i86op_opc83_word_RM_IMM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg; - uint16 destoffset; - uint16 imm; - uint16 destval; - /* weirdo special case instruction format. Part of the - opcode held below in "RH". Doubly nested case would - result, except that the decoded instruction - Similar to opcode 81, except that the immediate byte - is sign extended to a word length. - */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - /* know operation, decode the mod byte to find the addressing - mode. */ - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - imm = (int8)fetch_byte_imm(m); - destval = (*opc83_word_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - imm = (int8)fetch_byte_imm(m); - destval = (*opc83_word_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - imm = (int8) fetch_byte_imm(m); - destval = (*opc83_word_operation[rh])(m, destval, imm); - if (rh != 7) - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - imm = (int8) fetch_byte_imm(m); - destval = (*opc83_word_operation[rh])(m, *destreg, imm); - if (rh != 7) - *destreg = destval; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x84*/ -static void i86op_test_byte_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 destoffset; - uint8 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - test_byte(m, destval, *srcreg); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - test_byte(m, destval, *srcreg); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - test_byte(m, destval, *srcreg); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - test_byte(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); - } - -/*opcode=0x85*/ -static void i86op_test_word_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - uint16 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - test_word(m, destval, *srcreg); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - test_word(m, destval, *srcreg); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - test_word(m, destval, *srcreg); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - test_word(m, *destreg, *srcreg); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x86*/ -static void i86op_xchg_byte_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 destoffset; - uint8 destval; - uint8 tmp; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - tmp = *srcreg; - *srcreg = destval; - destval = tmp; - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - tmp = *srcreg; - *srcreg = destval; - destval = tmp; - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - tmp = *srcreg; - *srcreg = destval; - destval = tmp; - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - tmp = *srcreg; - *srcreg = *destreg; - *destreg = tmp; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x87*/ -static void i86op_xchg_word_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - uint16 destval; - uint16 tmp; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - tmp = *srcreg; - *srcreg = destval; - destval = tmp; - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - tmp = *srcreg; - *srcreg = destval; - destval = tmp; - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - tmp = *srcreg; - *srcreg = destval; - destval = tmp; - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - tmp = *srcreg; - *srcreg = *destreg; - *destreg = tmp; - break; - } - DECODE_CLEAR_SEGOVR(m); - } - -/*opcode=0x88*/ -static void i86op_mov_byte_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 destoffset; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - store_data_byte(m,destoffset,*srcreg); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - store_data_byte(m,destoffset,*srcreg); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - store_data_byte(m,destoffset,*srcreg); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - srcreg = DECODE_RM_BYTE_REGISTER(m,rh); - *destreg = *srcreg; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x89*/ -static void i86op_mov_word_RM_R(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - store_data_word(m,destoffset,*srcreg); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - store_data_word(m,destoffset,*srcreg); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - store_data_word(m,destoffset,*srcreg); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - *destreg = *srcreg; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x8a*/ -static void i86op_mov_byte_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg,*srcreg; - uint16 srcoffset; - uint8 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = srcval; - break; - case 1: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = srcval; - break; - case 2: - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_byte(m,srcoffset); - *destreg = srcval; - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rh); - srcreg = DECODE_RM_BYTE_REGISTER(m,rl); - *destreg = *srcreg; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - - /*opcode=0x8b*/ -static void i86op_mov_word_R_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 srcoffset; - uint16 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = srcval; - break; - case 1: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = srcval; - break; - case 2: - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = srcval; - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rh); - srcreg = DECODE_RM_WORD_REGISTER(m,rl); - *destreg = *srcreg; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x8c*/ -static void i86op_mov_word_RM_SR(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 destoffset; - uint16 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - srcreg = decode_rm_seg_register(m,rh); - destval = *srcreg; - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - srcreg = decode_rm_seg_register(m,rh); - destval = *srcreg; - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - srcreg = decode_rm_seg_register(m,rh); - destval = *srcreg; - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - srcreg = decode_rm_seg_register(m,rh); - *destreg = *srcreg; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x8d*/ -static void i86op_lea_word_R_M(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *srcreg; - uint16 destoffset; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destoffset=decode_rm00_address(m,rl); - *srcreg = destoffset; - break; - case 1: - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destoffset=decode_rm01_address(m,rl); - *srcreg = destoffset; - break; - case 2: - srcreg = DECODE_RM_WORD_REGISTER(m,rh); - destoffset=decode_rm10_address(m,rl); - *srcreg = destoffset; - break; - case 3: /* register to register */ - /* undefined. Do nothing. */ - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x8e*/ -static void i86op_mov_word_SR_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg,*srcreg; - uint16 srcoffset; - uint16 srcval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destreg = decode_rm_seg_register(m,rh); - srcoffset=decode_rm00_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = srcval; - break; - case 1: - destreg = decode_rm_seg_register(m,rh); - srcoffset=decode_rm01_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = srcval; - break; - case 2: - destreg = decode_rm_seg_register(m,rh); - srcoffset = decode_rm10_address(m,rl); - srcval = fetch_data_word(m,srcoffset); - *destreg = srcval; - break; - case 3: /* register to register */ - destreg = decode_rm_seg_register(m,rh); - srcreg = DECODE_RM_WORD_REGISTER(m,rl); - *destreg = *srcreg; - break; - } - /*\ - * clean up, and reset all the R_xSP pointers to the correct - * locations. This is about 3x too much overhead (doing all the - * segreg ptrs when only one is needed, but this instruction - * *cannot* be that common, and this isn't too much work anyway. - \*/ - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x8f*/ -static void i86op_pop_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg; - uint16 destoffset; - uint16 destval; - FETCH_DECODE_MODRM(m,mod,rh,rl); - if (rh != 0) - { - halt_sys(m); - } - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = pop_word( m); - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = pop_word(m); - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = pop_word(m); - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - *destreg = pop_word(m); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x90*/ -static void i86op_nop(PC_ENV *m) -{ - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x91*/ -static void i86op_xchg_word_AX_CX(PC_ENV *m) -{ - uint16 tmp; - tmp = m->R_AX; - m->R_AX = m->R_CX; - m->R_CX = tmp; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x92*/ -static void i86op_xchg_word_AX_DX(PC_ENV *m) -{ - uint16 tmp; - tmp = m->R_AX; - m->R_AX = m->R_DX; - m->R_DX = tmp; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x93*/ -static void i86op_xchg_word_AX_BX(PC_ENV *m) -{ - uint16 tmp; - tmp = m->R_AX; - m->R_AX = m->R_BX; - m->R_BX = tmp; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x94*/ -static void i86op_xchg_word_AX_SP(PC_ENV *m) -{ - uint16 tmp; - tmp = m->R_AX; - m->R_AX = m->R_SP; - m->R_SP = tmp; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x95*/ -static void i86op_xchg_word_AX_BP(PC_ENV *m) -{ - uint16 tmp; - tmp = m->R_AX; - m->R_AX = m->R_BP; - m->R_BP = tmp; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x96*/ -static void i86op_xchg_word_AX_SI(PC_ENV *m) -{ - uint16 tmp; - tmp = m->R_AX; - m->R_AX = m->R_SI; - m->R_SI = tmp; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x97*/ -static void i86op_xchg_word_AX_DI(PC_ENV *m) -{ - uint16 tmp; - tmp = m->R_AX; - m->R_AX = m->R_DI; - m->R_DI = tmp; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x98*/ -static void i86op_cbw(PC_ENV *m) -{ - if (m->R_AL & 0x80) - { - m->R_AH = 0xff; - } - else - { - m->R_AH = 0x0; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x99*/ -static void i86op_cwd(PC_ENV *m) -{ - if (m->R_AX & 0x8000) - { - m->R_DX = 0xffff; - } - else - { - m->R_DX = 0x0; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x9a*/ -static void i86op_call_far_IMM(PC_ENV *m) -{ - uint16 farseg,faroff; - faroff = fetch_word_imm(m); - farseg = fetch_word_imm(m); - /* XXX - HOOKED INTERRUPT VECTORS CALLING INTO OUR "BIOS" - WILL CAUSE PROBLEMS UNLESS ALL INTERSEGMENT STUFF IS - CHECKED FOR BIOS ACCESS. CHECK NEEDED HERE. - FOR MOMENT, LET IT ALONE. - */ - push_word(m,m->R_CS); - m->R_CS = farseg; - push_word(m,m->R_IP); - m->R_IP = faroff; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x9b*/ -static void i86op_wait(PC_ENV *m) -{ - /* NADA. */ - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x9c*/ -static void i86op_pushf_word(PC_ENV *m) -{ - uint16 flags; - flags = m->R_FLG; - /* clear out *all* bits not representing flags */ - flags &= F_MSK; - /* TURN ON CHARACTERISTIC BITS OF FLAG FOR 8088 */ - flags |= F_ALWAYS_ON; - push_word(m,flags); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x9d*/ -static void i86op_popf_word(PC_ENV *m) -{ - m->R_FLG = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x9e*/ -static void i86op_sahf(PC_ENV *m) -{ - /* clear the lower bits of the flag register */ - m->R_FLG &= 0xffffff00; - /* or in the AH register into the flags register */ - m->R_FLG |= m->R_AH; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0x9f*/ -static void i86op_lahf(PC_ENV *m) -{ - m->R_AH = m->R_FLG & 0xff; - /*undocumented TC++ behavior??? Nope. It's documented, but - you have too look real hard to notice it. */ - m->R_AH |= 0x2; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xa0*/ -static void i86op_mov_AL_M_IMM(PC_ENV *m) -{ - uint16 offset; - uint8 destval; - offset = fetch_word_imm(m); - destval = fetch_data_byte(m,offset); - m->R_AL = destval; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xa1*/ -static void i86op_mov_AX_M_IMM(PC_ENV *m) -{ - uint16 offset; - uint16 destval; - offset = fetch_word_imm(m); - destval = fetch_data_word(m,offset); - m->R_AX = destval; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xa2*/ -static void i86op_mov_M_AL_IMM(PC_ENV *m) -{ - uint16 offset; - offset = fetch_word_imm(m); - store_data_byte(m,offset,m->R_AL); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xa3*/ -static void i86op_mov_M_AX_IMM(PC_ENV *m) -{ - uint16 offset; - offset = fetch_word_imm(m); - store_data_word(m,offset,m->R_AX); - DECODE_CLEAR_SEGOVR(m); -} - -/* JHH CLEANED */ - -/*opcode=0xa4*/ -static void i86op_movs_byte(PC_ENV *m) -{ - uint8 val; - int inc; - if (ACCESS_FLAG(m,F_DF)) /* down */ - inc = -1; - else - inc = 1; - if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) - { - /* dont care whether REPE or REPNE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - val = fetch_data_byte(m,m->R_SI); - store_data_byte_abs(m,m->R_ES,m->R_DI,val); - m->R_CX -= 1; - m->R_SI += inc; - m->R_DI += inc; - } - m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } - else - { - val = fetch_data_byte(m,m->R_SI); - store_data_byte_abs(m,m->R_ES,m->R_DI,val); - m->R_SI += inc; - m->R_DI += inc; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xa5*/ -static void i86op_movs_word(PC_ENV *m) -{ - int16 val; - int inc; - if (ACCESS_FLAG(m, F_DF)) /* down */ - inc = -2; - else - inc = 2; - if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) - { - /* dont care whether REPE or REPNE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - val = fetch_data_word(m,m->R_SI); - store_data_word_abs(m,m->R_ES,m->R_DI,val); - m->R_CX -= 1; - m->R_SI += inc; - m->R_DI += inc; - } - m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } - else - { - val = fetch_data_word(m,m->R_SI); - store_data_word_abs(m,m->R_ES,m->R_DI,val); - m->R_SI += inc; - m->R_DI += inc; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xa6*/ -static void i86op_cmps_byte(PC_ENV *m) -{ - int8 val1,val2; - int inc; - if (ACCESS_FLAG(m,F_DF)) /* down */ - inc = -1; - else - inc = 1; - if (m->sysmode & SYSMODE_PREFIX_REPE) - { - /* REPE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - val1 = fetch_data_byte(m,m->R_SI); - val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI); - cmp_byte(m, val1,val2); - m->R_CX -= 1; - m->R_SI += inc; - m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)==0) - break; - } - m->sysmode &= ~SYSMODE_PREFIX_REPE; - } - else if (m->sysmode & SYSMODE_PREFIX_REPNE) - { - /* REPNE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - val1 = fetch_data_byte(m,m->R_SI); - val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI); - cmp_byte(m, val1,val2); - m->R_CX -= 1; - m->R_SI += inc; - m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)) - break; /* zero flag set means equal */ - } - m->sysmode &= ~SYSMODE_PREFIX_REPNE; - } - else - { - val1 = fetch_data_byte(m,m->R_SI); - val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI); - cmp_byte(m, val1,val2); - m->R_SI += inc; - m->R_DI += inc; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xa7*/ -static void i86op_cmps_word(PC_ENV *m) -{ - int16 val1,val2; - int inc; - if (ACCESS_FLAG(m,F_DF)) /* down */ - inc = -2; - else - inc = 2; - if (m->sysmode & SYSMODE_PREFIX_REPE) - { - /* REPE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - val1 = fetch_data_word(m,m->R_SI); - val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI); - cmp_word(m, val1,val2); - m->R_CX -= 1; - m->R_SI += inc; - m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)==0) - break; - } - m->sysmode &= ~SYSMODE_PREFIX_REPE; - } - else if (m->sysmode & SYSMODE_PREFIX_REPNE) - { - /* REPNE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - val1 = fetch_data_word(m,m->R_SI); - val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI); - cmp_word(m, val1,val2); - m->R_CX -= 1; - m->R_SI += inc; - m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)) - break; /* zero flag set means equal */ - } - m->sysmode &= ~SYSMODE_PREFIX_REPNE; - } - else - { - val1 = fetch_data_word(m,m->R_SI); - val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI); - cmp_word(m, val1,val2); - m->R_SI += inc; - m->R_DI += inc; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xa8*/ -static void i86op_test_AL_IMM(PC_ENV *m) -{ - int imm; - imm = fetch_byte_imm(m); - test_byte(m, m->R_AL, imm); - DECODE_CLEAR_SEGOVR(m); - } - -/*opcode=0xa9*/ -static void i86op_test_AX_IMM(PC_ENV *m) -{ - int imm; - imm = fetch_word_imm(m); - test_word(m, m->R_AX, imm); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xaa*/ -static void i86op_stos_byte(PC_ENV *m) -{ - int inc; - if (ACCESS_FLAG(m, F_DF)) /* down */ - inc = -1; - else - inc = 1; - if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) - { - /* dont care whether REPE or REPNE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - store_data_byte_abs(m,m->R_ES,m->R_DI,m->R_AL); - m->R_CX -= 1; - m->R_DI += inc; - } - m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } - else - { - store_data_byte_abs(m,m->R_ES,m->R_DI,m->R_AL); - m->R_DI += inc; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xab*/ -static void i86op_stos_word(PC_ENV *m) -{ - int inc; - if (ACCESS_FLAG(m, F_DF)) /* down */ - inc = -2; - else - inc = 2; - if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) - { - /* dont care whether REPE or REPNE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - store_data_word_abs(m,m->R_ES,m->R_DI,m->R_AX); - m->R_CX -= 1; - m->R_DI += inc; - } - m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } - else - { - store_data_word_abs(m,m->R_ES,m->R_DI,m->R_AX); - m->R_DI += inc; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xac*/ -static void i86op_lods_byte(PC_ENV *m) -{ - int inc; - if (ACCESS_FLAG(m,F_DF)) /* down */ - inc = -1; - else - inc = 1; - if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) - { - /* dont care whether REPE or REPNE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - m->R_AL = fetch_data_byte(m,m->R_SI); - m->R_CX -= 1; - m->R_SI += inc; - } - m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } - else - { - m->R_AL = fetch_data_byte(m,m->R_SI); - m->R_SI += inc; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xad*/ -static void i86op_lods_word(PC_ENV *m) -{ - int inc; - if (ACCESS_FLAG(m,F_DF)) /* down */ - inc = -2; - else - inc = 2; - if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) - { - /* dont care whether REPE or REPNE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - m->R_AX = fetch_data_word(m,m->R_SI); - m->R_CX -= 1; - m->R_SI += inc; - } - m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); - } - else - { - m->R_AX = fetch_data_word(m,m->R_SI); - m->R_SI += inc; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xae*/ -static void i86op_scas_byte(PC_ENV *m) -{ - int8 val2; - int inc; - if (ACCESS_FLAG(m,F_DF)) /* down */ - inc = -1; - else - inc = 1; - if (m->sysmode & SYSMODE_PREFIX_REPE) - { - /* REPE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI); - cmp_byte(m, m->R_AL,val2); - m->R_CX -= 1; - m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)==0) - break; - } - m->sysmode &= ~SYSMODE_PREFIX_REPE; - } - else if (m->sysmode & SYSMODE_PREFIX_REPNE) - { - /* REPNE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI); - cmp_byte(m, m->R_AL,val2); - m->R_CX -= 1; - m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)) - break; /* zero flag set means equal */ - } - m->sysmode &= ~SYSMODE_PREFIX_REPNE; - } - else - { - val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI); - cmp_byte(m, m->R_AL,val2); - m->R_DI += inc; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xaf*/ -static void i86op_scas_word(PC_ENV *m) -{ - int16 val2; - int inc; - if (ACCESS_FLAG(m, F_DF)) /* down */ - inc = -2; - else - inc = 2; - if (m->sysmode & SYSMODE_PREFIX_REPE) - { - /* REPE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI); - cmp_word(m,m->R_AX,val2); - m->R_CX -= 1; - m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)==0) - break; - } - m->sysmode &= ~SYSMODE_PREFIX_REPE; - } - else if (m->sysmode & SYSMODE_PREFIX_REPNE) - { - /* REPNE */ - /* move them until CX is ZERO. */ - while (m->R_CX != 0) - { - val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI); - cmp_word(m, m->R_AX,val2); - m->R_CX -= 1; - m->R_DI += inc; - if (ACCESS_FLAG(m,F_ZF)) - break; /* zero flag set means equal */ - } - m->sysmode &= ~SYSMODE_PREFIX_REPNE; - } - else - { - val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI); - cmp_word(m, m->R_AX,val2); - m->R_DI += inc; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xb0*/ -static void i86op_mov_byte_AL_IMM(PC_ENV *m) -{ - uint8 imm; - imm = fetch_byte_imm(m); - m->R_AL = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xb1*/ -static void i86op_mov_byte_CL_IMM(PC_ENV *m) -{ - uint8 imm; - imm = fetch_byte_imm(m); - m->R_CL = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xb2*/ -static void i86op_mov_byte_DL_IMM(PC_ENV *m) -{ - uint8 imm; - imm = fetch_byte_imm(m); - m->R_DL = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xb3*/ -static void i86op_mov_byte_BL_IMM(PC_ENV *m) -{ - uint8 imm; - imm = fetch_byte_imm(m); - m->R_BL = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xb4*/ -static void i86op_mov_byte_AH_IMM(PC_ENV *m) -{ - uint8 imm; - imm = fetch_byte_imm(m); - m->R_AH = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xb5*/ -static void i86op_mov_byte_CH_IMM(PC_ENV *m) -{ - uint8 imm; - imm = fetch_byte_imm(m); - m->R_CH = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xb6*/ -static void i86op_mov_byte_DH_IMM(PC_ENV *m) -{ - uint8 imm; - imm = fetch_byte_imm(m); - m->R_DH = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xb7*/ -static void i86op_mov_byte_BH_IMM(PC_ENV *m) -{ - uint8 imm; - imm = fetch_byte_imm(m); - m->R_BH = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xb8*/ -static void i86op_mov_word_AX_IMM(PC_ENV *m) -{ - uint16 imm; - imm = fetch_word_imm(m); - m->R_AX = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xb9*/ -static void i86op_mov_word_CX_IMM(PC_ENV *m) -{ - uint16 imm; - imm = fetch_word_imm(m); - m->R_CX = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xba*/ -static void i86op_mov_word_DX_IMM(PC_ENV *m) -{ - uint16 imm; - imm = fetch_word_imm(m); - m->R_DX = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xbb*/ -static void i86op_mov_word_BX_IMM(PC_ENV *m) -{ - uint16 imm; - imm = fetch_word_imm(m); - m->R_BX = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xbc*/ -static void i86op_mov_word_SP_IMM(PC_ENV *m) -{ - uint16 imm; - imm = fetch_word_imm(m); - m->R_SP = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xbd*/ -static void i86op_mov_word_BP_IMM(PC_ENV *m) -{ - uint16 imm; - imm = fetch_word_imm(m); - m->R_BP = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xbe*/ -static void i86op_mov_word_SI_IMM(PC_ENV *m) -{ - uint16 imm; - imm = fetch_word_imm(m); - m->R_SI = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xbf*/ -static void i86op_mov_word_DI_IMM(PC_ENV *m) -{ - uint16 imm; - imm = fetch_word_imm(m); - m->R_DI = imm; - DECODE_CLEAR_SEGOVR(m); -} - -/* c0 === ILLEGAL OPERAND */ -/* c1 === ILLEGAL OPERAND */ - -/*opcode=0xc2*/ -static void i86op_ret_near_IMM(PC_ENV *m) -{ - uint16 imm; - imm = fetch_word_imm(m); - m->R_IP = pop_word(m); - m->R_SP += imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xc3*/ -static void i86op_ret_near(PC_ENV *m) -{ - m->R_IP = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xc4*/ -static void i86op_les_R_IMM(PC_ENV *m) -{ - uint16 mod,rh,rl; - uint16 *dstreg; - uint16 srcoffset; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - dstreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - *dstreg = fetch_data_word(m,srcoffset); - m->R_ES = fetch_data_word(m,srcoffset+2); - break; - case 1: - dstreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - *dstreg = fetch_data_word(m,srcoffset); - m->R_ES = fetch_data_word(m,srcoffset+2); - break; - case 2: - dstreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - *dstreg = fetch_data_word(m,srcoffset); - m->R_ES = fetch_data_word(m,srcoffset+2); - break; - case 3: /* register to register */ - /* UNDEFINED! */ - ; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xc5*/ -static void i86op_lds_R_IMM(PC_ENV *m) -{ - uint16 mod,rh,rl; - uint16 *dstreg; - uint16 srcoffset; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - dstreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm00_address(m,rl); - *dstreg = fetch_data_word(m,srcoffset); - m->R_DS = fetch_data_word(m,srcoffset+2); - break; - case 1: - dstreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm01_address(m,rl); - *dstreg = fetch_data_word(m,srcoffset); - m->R_DS = fetch_data_word(m,srcoffset+2); - break; - case 2: - dstreg = DECODE_RM_WORD_REGISTER(m,rh); - srcoffset=decode_rm10_address(m,rl); - *dstreg = fetch_data_word(m,srcoffset); - m->R_DS = fetch_data_word(m,srcoffset+2); - break; - case 3: /* register to register */ - /* UNDEFINED! */ - ; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xc6*/ -static void i86op_mov_byte_RM_IMM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg; - uint16 destoffset; - uint8 imm; - FETCH_DECODE_MODRM(m,mod,rh,rl); - if (rh != 0) - { - halt_sys(m); - } - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - imm = fetch_byte_imm(m); - store_data_byte(m,destoffset,imm); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - imm = fetch_byte_imm(m); - store_data_byte(m,destoffset,imm); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - imm = fetch_byte_imm(m); - store_data_byte(m,destoffset,imm); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - imm = fetch_byte_imm(m); - *destreg = imm; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xc7*/ -static void i86op_mov_word_RM_IMM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg; - uint16 destoffset; - uint16 imm; - FETCH_DECODE_MODRM(m,mod,rh,rl); - if (rh != 0) - { - halt_sys(m); - } - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - imm = fetch_word_imm(m); - store_data_word(m,destoffset,imm); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - imm = fetch_word_imm(m); - store_data_word(m,destoffset,imm); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - imm = fetch_word_imm(m); - store_data_word(m,destoffset,imm); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - imm = fetch_word_imm(m); - *destreg = imm; - break; - } - DECODE_CLEAR_SEGOVR(m); - } - -/*opcode=0xc8 ILLEGAL OP*/ -/*opcode=0xc9 ILLEGAL OP*/ - -/*opcode=0xca*/ -static void i86op_ret_far_IMM(PC_ENV *m) -{ - uint16 imm; - imm = fetch_word_imm(m); - m->R_IP = pop_word(m); - m->R_CS = pop_word(m); - m->R_SP += imm; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xcb*/ -static void i86op_ret_far(PC_ENV *m) -{ - m->R_IP = pop_word(m); - m->R_CS = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xcc*/ -static void i86op_int3(PC_ENV *m) -{ - uint16 tmp; - /* access the segment register */ - { - tmp = m->R_FLG; - push_word(m, tmp); - CLEAR_FLAG(m, F_IF); - CLEAR_FLAG(m, F_TF); -/* [JCE] If we're interrupting between a segment override (or REP override) - * and the following instruction, decrease IP to get back to the prefix */ - if (m->sysmode & (SYSMODE_SEGMASK | - SYSMODE_PREFIX_REPE | - SYSMODE_PREFIX_REPNE)) - { - --m->R_IP; - } - push_word(m, m->R_CS); - push_word(m, m->R_IP); -/* [JCE] CS and IP were the wrong way round... */ - tmp = mem_access_word(m, 3 * 4); - m->R_IP = tmp; - tmp = mem_access_word(m, 3 * 4 + 2); - m->R_CS = tmp; - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xcd*/ -static void i86op_int_IMM(PC_ENV *m) -{ - uint16 tmp; - uint8 intnum; - intnum = fetch_byte_imm(m); - { - tmp = m->R_FLG; - push_word(m, tmp); - CLEAR_FLAG(m, F_IF); - CLEAR_FLAG(m, F_TF); -/* [JCE] If we're interrupting between a segment override (or REP override) - * and the following instruction, decrease IP to get back to the prefix */ - if (m->sysmode & (SYSMODE_SEGMASK | - SYSMODE_PREFIX_REPE | - SYSMODE_PREFIX_REPNE)) - { - --m->R_IP; - } - push_word(m, m->R_CS); - push_word(m, m->R_IP); -/* [JCE] CS and IP were the wrong way round... */ - tmp = mem_access_word(m, intnum * 4); - m->R_IP = tmp; - tmp = mem_access_word(m, intnum * 4 + 2); - m->R_CS = tmp; - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xce*/ -static void i86op_into(PC_ENV *m) -{ - uint16 tmp; - if (ACCESS_FLAG(m,F_OF)) - { - { - tmp = m->R_FLG; - push_word(m, tmp); - CLEAR_FLAG(m, F_IF); - CLEAR_FLAG(m, F_TF); -/* [JCE] If we're interrupting between a segment override (or REP override) - * and the following instruction, decrease IP to get back to the prefix */ - if (m->sysmode & (SYSMODE_SEGMASK | - SYSMODE_PREFIX_REPE | - SYSMODE_PREFIX_REPNE)) - { - --m->R_IP; - } - push_word(m, m->R_CS); - push_word(m, m->R_IP); -/* [JCE] CS and IP were the wrong way round... */ - tmp = mem_access_word(m, 4 * 4); - m->R_IP = tmp; - tmp = mem_access_word(m, 4 * 4 + 2); - m->R_CS = tmp; - } - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xcf*/ -static void i86op_iret(PC_ENV *m) -{ - m->R_IP = pop_word(m); - m->R_CS = pop_word(m); - m->R_FLG = pop_word(m); - DECODE_CLEAR_SEGOVR(m); -} - -static uint8 (*opcD0_byte_operation[])(PC_ENV *m,uint8 d, uint8 s) = - /* used by opcodes d0 and d2. */ -{ - rol_byte, - ror_byte, - rcl_byte, - rcr_byte, - shl_byte, - shr_byte, - shl_byte, /* sal_byte === shl_byte by definition */ - sar_byte, -}; - -/* opcode=0xd0*/ -static void i86op_opcD0_byte_RM_1(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg; - uint16 destoffset; - uint8 destval; - /* Yet another weirdo special case instruction format. Part of the - opcode held below in "RH". Doubly nested case would - result, except that the decoded instruction - */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - /* know operation, decode the mod byte to find the addressing - mode. */ - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = (*opcD0_byte_operation[rh])(m, destval,1); - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = (*opcD0_byte_operation[rh])(m, destval, 1); - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = (*opcD0_byte_operation[rh])(m, destval, 1); - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - destval = (*opcD0_byte_operation[rh])(m, *destreg, 1); - *destreg = destval; - break; - } - DECODE_CLEAR_SEGOVR(m); - } - -static uint16 (*opcD1_word_operation[])(PC_ENV *m,uint16 s,uint16 d) = - /* used by opcodes d1 and d3. */ -{ rol_word, - ror_word, - rcl_word, - rcr_word, - shl_word, - shr_word, - shl_word, /* sal_byte === shl_byte by definition */ - sar_word, -}; - -/* opcode=0xd1*/ -static void i86op_opcD1_word_RM_1(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg; - uint16 destoffset; - uint16 destval; - /* Yet another weirdo special case instruction format. Part of the - opcode held below in "RH". Doubly nested case would - result, except that the decoded instruction - */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - /* know operation, decode the mod byte to find the addressing - mode. */ - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = (*opcD1_word_operation[rh])(m, destval,1); - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = (*opcD1_word_operation[rh])(m, destval, 1); - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = (*opcD1_word_operation[rh])(m, destval, 1); - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - destval = (*opcD1_word_operation[rh])(m, *destreg, 1); - *destreg = destval; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xd2*/ -static void i86op_opcD2_byte_RM_CL(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg; - uint16 destoffset; - uint8 destval; - uint8 amt; - /* Yet another weirdo special case instruction format. Part of the - opcode held below in "RH". Doubly nested case would - result, except that the decoded instruction - */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - amt = m->R_CL; - /* know operation, decode the mod byte to find the addressing - mode. */ - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = (*opcD0_byte_operation[rh])(m, destval,amt); - store_data_byte(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = (*opcD0_byte_operation[rh])(m, destval, amt); - store_data_byte(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = (*opcD0_byte_operation[rh])(m, destval, amt); - store_data_byte(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - destval = (*opcD0_byte_operation[rh])(m, *destreg, amt); - *destreg = destval; - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xd3*/ -static void i86op_opcD3_word_RM_CL(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg; - uint16 destoffset; - uint16 destval; - uint8 amt; - /* Yet another weirdo special case instruction format. Part of the - opcode held below in "RH". Doubly nested case would - result, except that the decoded instruction - */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - amt = m->R_CL; - /* know operation, decode the mod byte to find the addressing - mode. */ - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = (*opcD1_word_operation[rh])(m, destval, amt); - store_data_word(m,destoffset,destval); - break; - case 1: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = (*opcD1_word_operation[rh])(m, destval, amt); - store_data_word(m,destoffset,destval); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = (*opcD1_word_operation[rh])(m, destval, amt); - store_data_word(m,destoffset,destval); - break; - case 3: /* register to register */ - destreg = DECODE_RM_WORD_REGISTER(m,rl); - *destreg = (*opcD1_word_operation[rh])(m, *destreg, amt); - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -static void sys_fatal(int error, char *fmt, ...) -{ - va_list p; - va_start(p, fmt); - fprintf(stderr, "Fatal error: "); - if (error != 0) - { - fprintf(stderr, "<%d>",error); - fprintf(stderr,"%s",strerror(error)); - } - vfprintf(stderr, fmt, p); - va_end(p); - fprintf(stderr, NLP "Exiting..." NLP); - exit(1); -} - -/* opcode=0xd4*/ -static void i86op_aam(PC_ENV *m) -{ uint8 a; - a = fetch_byte_imm(m); /* this is a stupid encoding. */ - if (a != 10) - sys_fatal(0,"error decoding aam" NLP); - /* note the type change here --- returning AL and AH in AX. */ - m->R_AX = aam_word(m,m->R_AL); - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xd5*/ -static void i86op_aad(PC_ENV *m) -{ - m->R_AX = aad_word(m,m->R_AX); - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xd6 ILLEGAL OPCODE */ - -/* opcode=0xd7 */ -static void i86op_xlat(PC_ENV *m) -{ - uint16 addr; - addr = m->R_BX + (uint8)m->R_AL; - m->R_AL = fetch_data_byte(m,addr); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xe0*/ -static void i86op_loopne(PC_ENV *m) -{ - int16 ip; - ip = (int8)fetch_byte_imm(m); - ip += (int16)m->R_IP; - m->R_CX -= 1; - if (m->R_CX != 0 && !ACCESS_FLAG(m,F_ZF)) /* CX != 0 and !ZF */ - m->R_IP = ip; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xe1*/ -static void i86op_loope(PC_ENV *m) -{ - int16 ip; - ip = (int8)fetch_byte_imm(m); - ip += (int16)m->R_IP; - m->R_CX -= 1; - if (m->R_CX != 0 && ACCESS_FLAG(m,F_ZF)) /* CX != 0 and ZF */ - m->R_IP = ip; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xe2*/ -static void i86op_loop(PC_ENV *m) -{ - int16 ip; - ip = (int8)fetch_byte_imm(m); - ip += (int16)m->R_IP; - m->R_CX -= 1; - if (m->R_CX != 0) - m->R_IP = ip; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xe3*/ -static void i86op_jcxz(PC_ENV *m) -{ - int16 offset,target; - /* jump to byte offset if overflow flag is set */ - offset = (int8)fetch_byte_imm(m); /* sign extended ??? */ - target = (int16)m->R_IP + offset; - if (m->R_CX == 0) - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xe4*/ -static void i86op_in_byte_AL_IMM(PC_ENV *m) -{ - uint8 port; - port = (uint8)fetch_byte_imm(m); - m->R_AL = in(port); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xe5*/ -static void i86op_in_word_AX_IMM(PC_ENV *m) -{ - uint8 port; - port = (uint8)fetch_byte_imm(m); - m->R_AX = in(port); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xe6*/ -static void i86op_out_byte_IMM_AL(PC_ENV *m) -{ - uint8 port; - port = (uint8)fetch_byte_imm(m); - out(port, m->R_AL); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xe7*/ -static void i86op_out_word_IMM_AX(PC_ENV *m) -{ - uint8 port; - port = (uint8)fetch_byte_imm(m); - out(port, m->R_AX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xe8*/ -static void i86op_call_near_IMM(PC_ENV *m) -{ - int16 ip; - /* weird. Thought this was a signed disp! */ - ip = (int16)fetch_word_imm(m); - ip += (int16)m->R_IP; /* CHECK SIGN */ - push_word(m,m->R_IP); - m->R_IP = ip; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xe9*/ -static void i86op_jump_near_IMM(PC_ENV *m) -{ - int ip; - /* weird. Thought this was a signed disp too! */ - ip = (int16)fetch_word_imm(m); - ip += (int16)m->R_IP; /* CHECK SIGN */ - m->R_IP = ip; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xea*/ -static void i86op_jump_far_IMM(PC_ENV *m) -{ - uint16 cs,ip; - ip = fetch_word_imm(m); - cs = fetch_word_imm(m); - m->R_IP = ip; - m->R_CS = cs; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xeb*/ -static void i86op_jump_byte_IMM(PC_ENV *m) -{ - int8 offset; - uint16 target; - offset = (int8) fetch_byte_imm(m); /* CHECK */ -/* printf("jump byte imm offset=%d\n",offset);*/ - target = (int16) m->R_IP + offset; - m->R_IP = target; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xec*/ -static void i86op_in_byte_AL_DX(PC_ENV *m) -{ - m->R_AL = in(m->R_DX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xed*/ -static void i86op_in_word_AX_DX(PC_ENV *m) -{ - m->R_AX = in(m->R_DX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xee*/ -static void i86op_out_byte_DX_AL(PC_ENV *m) -{ - out(m->R_DX, m->R_AL); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xef*/ -static void i86op_out_word_DX_AX(PC_ENV *m) -{ - out(m->R_DX, m->R_AX); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xf0*/ -static void i86op_lock(PC_ENV *m) -{ - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xf1 ILLEGAL OPERATION*/ - -/*opcode=0xf2*/ -static void i86op_repne(PC_ENV *m) -{ - m->sysmode |= SYSMODE_PREFIX_REPNE; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xf3*/ -static void i86op_repe(PC_ENV *m) -{ - m->sysmode |= SYSMODE_PREFIX_REPE; - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xf4*/ -static void i86op_halt(PC_ENV *m) -{ - halt_sys(m); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xf5*/ -static void i86op_cmc(PC_ENV *m) -{ - /* complement the carry flag. */ - TOGGLE_FLAG(m,F_CF); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xf6*/ -static void i86op_opcF6_byte_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint8 *destreg; - uint16 destoffset; - uint8 destval,srcval; - /* long, drawn out code follows. Double switch for a total - of 32 cases. */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: /* mod=00 */ - switch(rh) - { - case 0: /* test byte imm */ - destoffset=decode_rm00_address(m,rl); - srcval = fetch_byte_imm(m); - destval = fetch_data_byte(m,destoffset); - test_byte(m, destval, srcval); - break; - case 1: - halt_sys(m); - break; - case 2: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = not_byte(m, destval); - store_data_byte(m,destoffset,destval); - break; - case 3: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = neg_byte(m, destval); - store_data_byte(m,destoffset,destval); - break; - case 4: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - mul_byte(m, destval); - break; - case 5: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - imul_byte(m, destval); - break; - case 6: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - div_byte(m, destval); - break; - case 7: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_byte(m,destoffset); - idiv_byte(m, destval); - break; - } - break; /* end mod==00 */ - case 1: /* mod=01 */ - switch(rh) - { - case 0: /* test byte imm */ - destoffset=decode_rm01_address(m,rl); - srcval = fetch_byte_imm(m); - destval = fetch_data_byte(m,destoffset); - test_byte(m, destval, srcval); - break; - case 1: - halt_sys(m); - break; - case 2: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = not_byte(m, destval); - store_data_byte(m,destoffset,destval); - break; - case 3: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = neg_byte(m, destval); - store_data_byte(m,destoffset,destval); - break; - case 4: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - mul_byte(m, destval); - break; - case 5: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - imul_byte(m, destval); - break; - case 6: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - div_byte(m, destval); - break; - case 7: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_byte(m,destoffset); - idiv_byte(m, destval); - break; - } - break; /* end mod==01 */ - case 2: /* mod=10 */ - switch(rh) - { - case 0: /* test byte imm */ - destoffset=decode_rm10_address(m,rl); - srcval = fetch_byte_imm(m); - destval = fetch_data_byte(m,destoffset); - test_byte(m, destval, srcval); - break; - case 1: - halt_sys(m); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = not_byte(m, destval); - store_data_byte(m,destoffset,destval); - break; - case 3: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - destval = neg_byte(m, destval); - store_data_byte(m,destoffset,destval); - break; - case 4: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - mul_byte(m, destval); - break; - case 5: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - imul_byte(m, destval); - break; - case 6: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - div_byte(m, destval); - break; - case 7: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_byte(m,destoffset); - idiv_byte(m, destval); - break; - } - break; /* end mod==10 */ - case 3: /* mod=11 */ - switch(rh) - { - case 0: /* test byte imm */ - destreg=DECODE_RM_BYTE_REGISTER(m,rl); - srcval = fetch_byte_imm(m); - test_byte(m, *destreg, srcval); - break; - case 1: - halt_sys(m); - break; - case 2: - destreg=DECODE_RM_BYTE_REGISTER(m,rl); - *destreg = not_byte(m, *destreg); - break; - case 3: - destreg=DECODE_RM_BYTE_REGISTER(m,rl); - *destreg = neg_byte(m, *destreg); - break; - case 4: - destreg=DECODE_RM_BYTE_REGISTER(m,rl); - mul_byte(m, *destreg); /*!!! */ - break; - case 5: - destreg=DECODE_RM_BYTE_REGISTER(m,rl); - imul_byte(m, *destreg); - break; - case 6: - destreg=DECODE_RM_BYTE_REGISTER(m,rl); - div_byte(m, *destreg); - break; - case 7: - destreg=DECODE_RM_BYTE_REGISTER(m,rl); - idiv_byte(m, *destreg); - break; - } - break; /* end mod==11 */ - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xf7*/ -static void i86op_opcF7_word_RM(PC_ENV *m) -{ - uint16 mod,rl,rh; - uint16 *destreg; - uint16 destoffset; - uint16 destval,srcval; - /* long, drawn out code follows. Double switch for a total - of 32 cases. */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: /* mod=00 */ - switch(rh) - { - case 0: /* test word imm */ - destoffset=decode_rm00_address(m,rl); - srcval = fetch_word_imm(m); - destval = fetch_data_word(m,destoffset); - test_word(m, destval, srcval); - break; - case 1: - halt_sys(m); - break; - case 2: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = not_word(m, destval); - store_data_word(m,destoffset,destval); - break; - case 3: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = neg_word(m, destval); - store_data_word(m,destoffset,destval); - break; - case 4: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - mul_word(m, destval); - break; - case 5: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - imul_word(m, destval); - break; - case 6: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - div_word(m, destval); - break; - case 7: - destoffset=decode_rm00_address(m,rl); - destval = fetch_data_word(m,destoffset); - idiv_word(m, destval); - break; - } - break; /* end mod==00 */ - case 1: /* mod=01 */ - switch(rh) - { - case 0: /* test word imm */ - destoffset=decode_rm01_address(m,rl); - srcval = fetch_word_imm(m); - destval = fetch_data_word(m,destoffset); - test_word(m, destval, srcval); - break; - case 1: - halt_sys(m); - break; - case 2: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = not_word(m, destval); - store_data_word(m,destoffset,destval); - break; - case 3: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = neg_word(m, destval); - store_data_word(m,destoffset,destval); - break; - case 4: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - mul_word(m, destval); - break; - case 5: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - imul_word(m, destval); - break; - case 6: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - div_word(m, destval); - break; - case 7: - destoffset=decode_rm01_address(m,rl); - destval = fetch_data_word(m,destoffset); - idiv_word(m, destval); - break; - } - break; /* end mod==01 */ - case 2: /* mod=10 */ - switch(rh) - { - case 0: /* test word imm */ - destoffset=decode_rm10_address(m,rl); - srcval = fetch_word_imm(m); - destval = fetch_data_word(m,destoffset); - test_word(m, destval, srcval); - break; - case 1: - halt_sys(m); - break; - case 2: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = not_word(m, destval); - store_data_word(m,destoffset,destval); - break; - case 3: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - destval = neg_word(m, destval); - store_data_word(m,destoffset,destval); - break; - case 4: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - mul_word(m, destval); - break; - case 5: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - imul_word(m, destval); - break; - case 6: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - div_word(m, destval); - break; - case 7: - destoffset=decode_rm10_address(m,rl); - destval = fetch_data_word(m,destoffset); - idiv_word(m, destval); - break; - } - break; /* end mod==10 */ - case 3: /* mod=11 */ - switch(rh) - { - case 0: /* test word imm */ - destreg=DECODE_RM_WORD_REGISTER(m,rl); - srcval = fetch_word_imm(m); - test_word(m, *destreg, srcval); - break; - case 1: - halt_sys(m); - break; - case 2: - destreg=DECODE_RM_WORD_REGISTER(m,rl); - *destreg = not_word(m, *destreg); - break; - case 3: - destreg=DECODE_RM_WORD_REGISTER(m,rl); - *destreg = neg_word(m, *destreg); - break; - case 4: - destreg=DECODE_RM_WORD_REGISTER(m,rl); - mul_word(m, *destreg); /*!!! */ - break; - case 5: - destreg=DECODE_RM_WORD_REGISTER(m,rl); - imul_word(m, *destreg); - break; - case 6: - destreg=DECODE_RM_WORD_REGISTER(m,rl); - div_word(m, *destreg); - break; - case 7: - destreg=DECODE_RM_WORD_REGISTER(m,rl); - idiv_word(m, *destreg); - break; - } - break; /* end mod==11 */ - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xf8*/ -static void i86op_clc(PC_ENV *m) -{ - /* clear the carry flag. */ - CLEAR_FLAG(m, F_CF); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xf9*/ -static void i86op_stc(PC_ENV *m) -{ - /* set the carry flag. */ - SET_FLAG(m, F_CF); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xfa*/ -static void i86op_cli(PC_ENV *m) -{ - /* clear interrupts. */ - CLEAR_FLAG(m, F_IF); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xfb*/ -static void i86op_sti(PC_ENV *m) -{ - /* enable interrupts. */ - SET_FLAG(m, F_IF); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xfc*/ -static void i86op_cld(PC_ENV *m) -{ - /* clear interrupts. */ - CLEAR_FLAG(m, F_DF); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xfd*/ -static void i86op_std(PC_ENV *m) -{ - /* clear interrupts. */ - SET_FLAG(m, F_DF); - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xfe*/ -static void i86op_opcFE_byte_RM(PC_ENV *m) -{ - /* Yet another damned special case instruction. */ - uint16 mod,rh,rl; - uint8 destval; - uint16 destoffset; - uint8 *destreg; - /* ARRGH, ANOTHER GODDAMN SPECIAL CASE INSTRUCTION!!! */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - switch (rh) - { - case 0: /* inc word ptr ... */ - destval = fetch_data_byte(m,destoffset); - destval = inc_byte(m,destval); - store_data_byte(m,destoffset,destval); - break; - case 1: /* dec word ptr ... */ - destval = fetch_data_byte(m,destoffset); - destval = dec_byte(m,destval); - store_data_byte(m,destoffset,destval); - break; - } - break; - case 1: - destoffset=decode_rm01_address(m,rl); - switch (rh) - { - case 0: - destval = fetch_data_byte(m,destoffset); - destval = inc_byte(m,destval); - store_data_byte(m,destoffset,destval); - break; - case 1: - destval = fetch_data_byte(m,destoffset); - destval = dec_byte(m,destval); - store_data_byte(m,destoffset,destval); - break; - } - break; - case 2: - destoffset=decode_rm10_address(m,rl); - switch (rh) - { - case 0: - destval = fetch_data_byte(m,destoffset); - destval = inc_byte(m,destval); - store_data_byte(m,destoffset,destval); - break; - case 1: - destval = fetch_data_byte(m,destoffset); - destval = dec_byte(m,destval); - store_data_byte(m,destoffset,destval); - break; - } - break; - case 3: - destreg = DECODE_RM_BYTE_REGISTER(m,rl); - switch (rh) - { - case 0: - *destreg = inc_byte(m,*destreg); - break; - case 1: - *destreg = dec_byte(m,*destreg); - break; - } - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/*opcode=0xff*/ -static void i86op_opcFF_word_RM(PC_ENV *m) -{ - uint16 mod,rh,rl; - uint16 destval,destval2; - uint16 destoffset; - uint16 *destreg; - /* ANOTHER DAMN SPECIAL CASE INSTRUCTION!!! */ - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - destoffset=decode_rm00_address(m,rl); - switch (rh) - { - case 0: /* inc word ptr ... */ - destval = fetch_data_word(m,destoffset); - destval = inc_word(m,destval); - store_data_word(m,destoffset,destval); - break; - case 1: /* dec word ptr ... */ - destval = fetch_data_word(m,destoffset); - destval = dec_word(m,destval); - store_data_word(m,destoffset,destval); - break; - case 2: /* call word ptr ... */ - destval = fetch_data_word(m,destoffset); - push_word(m,m->R_IP); - m->R_IP = destval; - break; - case 3: /* call far ptr ... */ - destval = fetch_data_word(m,destoffset); - destval2 = fetch_data_word(m,destoffset+2); - push_word(m,m->R_CS); - m->R_CS = destval2; - push_word(m,m->R_IP); - m->R_IP = destval; - break; - case 4: /* jmp word ptr ... */ - destval = fetch_data_word(m,destoffset); - m->R_IP = destval; - break; - case 5: /* jmp far ptr ... */ - destval = fetch_data_word(m,destoffset); - destval2 = fetch_data_word(m,destoffset+2); - m->R_IP = destval; - m->R_CS = destval2; - break; - case 6: /* push word ptr ... */ - destval = fetch_data_word(m,destoffset); - push_word(m,destval); - break; - } - break; - case 1: - destoffset=decode_rm01_address(m,rl); - switch (rh) - { - case 0: - destval = fetch_data_word(m,destoffset); - destval = inc_word(m,destval); - store_data_word(m,destoffset,destval); - break; - case 1: - destval = fetch_data_word(m,destoffset); - destval = dec_word(m,destval); - store_data_word(m,destoffset,destval); - break; - case 2: /* call word ptr ... */ - destval = fetch_data_word(m,destoffset); - push_word(m,m->R_IP); - m->R_IP = destval; - break; - case 3: /* call far ptr ... */ - destval = fetch_data_word(m,destoffset); - destval2 = fetch_data_word(m,destoffset+2); - push_word(m,m->R_CS); - m->R_CS = destval2; - push_word(m,m->R_IP); - m->R_IP = destval; - break; - case 4: /* jmp word ptr ... */ - destval = fetch_data_word(m,destoffset); - m->R_IP = destval; - break; - case 5: /* jmp far ptr ... */ - destval = fetch_data_word(m,destoffset); - destval2 = fetch_data_word(m,destoffset+2); - m->R_IP = destval; - m->R_CS = destval2; - break; - case 6: /* push word ptr ... */ - destval = fetch_data_word(m,destoffset); - push_word(m,destval); - break; - } - break; - case 2: - destoffset=decode_rm10_address(m,rl); - switch (rh) - { - case 0: - destval = fetch_data_word(m,destoffset); - destval = inc_word(m,destval); - store_data_word(m,destoffset,destval); - break; - case 1: - destval = fetch_data_word(m,destoffset); - destval = dec_word(m,destval); - store_data_word(m,destoffset,destval); - break; - case 2: /* call word ptr ... */ - destval = fetch_data_word(m,destoffset); - push_word(m,m->R_IP); - m->R_IP = destval; - break; - case 3: /* call far ptr ... */ - destval = fetch_data_word(m,destoffset); - destval2 = fetch_data_word(m,destoffset+2); - push_word(m,m->R_CS); - m->R_CS = destval2; - push_word(m,m->R_IP); - m->R_IP = destval; - break; - case 4: /* jmp word ptr ... */ - destval = fetch_data_word(m,destoffset); - m->R_IP = destval; - break; - case 5: /* jmp far ptr ... */ - destval = fetch_data_word(m,destoffset); - destval2 = fetch_data_word(m,destoffset+2); - m->R_IP = destval; - m->R_CS = destval2; - break; - case 6: /* push word ptr ... */ - destval = fetch_data_word(m,destoffset); - push_word(m,destval); - break; - } - break; - case 3: - destreg = DECODE_RM_WORD_REGISTER(m,rl); - switch (rh) - { - case 0: - *destreg = inc_word(m,*destreg); - break; - case 1: - *destreg = dec_word(m,*destreg); - break; - case 2: /* call word ptr ... */ - push_word(m,m->R_IP); - m->R_IP = *destreg; - break; - case 3: /* jmp far ptr ... */ - halt_sys(m); - break; - case 4: /* jmp ... */ - m->R_IP = (uint16)(*destreg); - break; - case 5: /* jmp far ptr ... */ - halt_sys(m); - break; - case 6: - push_word(m,*destreg); - break; - } - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xd8*/ -static void i86op_esc_coprocess_d8(PC_ENV *m) -{ - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xd9*/ -static void i86op_esc_coprocess_d9(PC_ENV *m) -{ - uint16 mod,rl,rh; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - decode_rm00_address(m,rl); - break; - case 1: - decode_rm01_address(m,rl); - break; - case 2: - decode_rm10_address(m,rl); - break; - case 3: /* register to register */ - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xda*/ -static void i86op_esc_coprocess_da(PC_ENV *m) -{ - uint16 mod,rl,rh; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - decode_rm00_address(m,rl); - break; - case 1: - decode_rm01_address(m,rl); - break; - case 2: - decode_rm10_address(m,rl); - break; - case 3: /* register to register */ - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xdb*/ -static void i86op_esc_coprocess_db(PC_ENV *m) -{ - uint16 mod,rl,rh; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - decode_rm00_address(m,rl); - break; - case 1: - decode_rm01_address(m,rl); - break; - case 2: - decode_rm10_address(m,rl); - break; - case 3: /* register to register */ - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xdc*/ -static void i86op_esc_coprocess_dc(PC_ENV *m) -{ - uint16 mod,rl,rh; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - decode_rm00_address(m,rl); - break; - case 1: - decode_rm01_address(m,rl); - break; - case 2: - decode_rm10_address(m,rl); - break; - case 3: /* register to register */ - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xdd*/ -static void i86op_esc_coprocess_dd(PC_ENV *m) -{ - uint16 mod,rl,rh; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - decode_rm00_address(m,rl); - break; - case 1: - decode_rm01_address(m,rl); - break; - case 2: - decode_rm10_address(m,rl); - break; - case 3: /* register to register */ - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xde*/ -static void i86op_esc_coprocess_de(PC_ENV *m) - { - uint16 mod,rl,rh; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - decode_rm00_address(m,rl); - break; - case 1: - decode_rm01_address(m,rl); - break; - case 2: - decode_rm10_address(m,rl); - break; - case 3: /* register to register */ - break; - } - DECODE_CLEAR_SEGOVR(m); -} - -/* opcode=0xdf*/ -static void i86op_esc_coprocess_df(PC_ENV *m) - { - uint16 mod,rl,rh; - FETCH_DECODE_MODRM(m,mod,rh,rl); - switch (mod) - { - case 0: - decode_rm00_address(m,rl); - break; - case 1: - decode_rm01_address(m,rl); - break; - case 2: - decode_rm10_address(m,rl); - break; - case 3: /* register to register */ - break; - } - DECODE_CLEAR_SEGOVR(m); - } - -/* OPERAND TABLE */ - -OP i86_optab[256] = { - -/* 0x00 */ i86op_add_byte_RM_R, -/* 0x01 */ i86op_add_word_RM_R, -/* 0x02 */ i86op_add_byte_R_RM, -/* 0x03 */ i86op_add_word_R_RM, -/* 0x04 */ i86op_add_byte_AL_IMM, -/* 0x05 */ i86op_add_word_AX_IMM, -/* 0x06 */ i86op_push_ES, -/* 0x07 */ i86op_pop_ES, - -/* 0x08 */ i86op_or_byte_RM_R, -/* 0x09 */ i86op_or_word_RM_R, -/* 0x0a */ i86op_or_byte_R_RM, -/* 0x0b */ i86op_or_word_R_RM, -/* 0x0c */ i86op_or_byte_AL_IMM, -/* 0x0d */ i86op_or_word_AX_IMM, -/* 0x0e */ i86op_push_CS, -/* 0x0f */ i86op_illegal_op, - -/* 0x10 */ i86op_adc_byte_RM_R, -/* 0x11 */ i86op_adc_word_RM_R, -/* 0x12 */ i86op_adc_byte_R_RM, -/* 0x13 */ i86op_adc_word_R_RM, -/* 0x14 */ i86op_adc_byte_AL_IMM, -/* 0x15 */ i86op_adc_word_AX_IMM, -/* 0x16 */ i86op_push_SS, -/* 0x17 */ i86op_pop_SS, - -/* 0x18 */ i86op_sbb_byte_RM_R, -/* 0x19 */ i86op_sbb_word_RM_R, -/* 0x1a */ i86op_sbb_byte_R_RM, -/* 0x1b */ i86op_sbb_word_R_RM, -/* 0x1c */ i86op_sbb_byte_AL_IMM, -/* 0x1d */ i86op_sbb_word_AX_IMM, -/* 0x1e */ i86op_push_DS, -/* 0x1f */ i86op_pop_DS, - -/* 0x20 */ i86op_and_byte_RM_R, -/* 0x21 */ i86op_and_word_RM_R, -/* 0x22 */ i86op_and_byte_R_RM, -/* 0x23 */ i86op_and_word_R_RM, -/* 0x24 */ i86op_and_byte_AL_IMM, -/* 0x25 */ i86op_and_word_AX_IMM, -/* 0x26 */ i86op_segovr_ES, -/* 0x27 */ i86op_daa, - -/* 0x28 */ i86op_sub_byte_RM_R, -/* 0x29 */ i86op_sub_word_RM_R, -/* 0x2a */ i86op_sub_byte_R_RM, -/* 0x2b */ i86op_sub_word_R_RM, -/* 0x2c */ i86op_sub_byte_AL_IMM, -/* 0x2d */ i86op_sub_word_AX_IMM, -/* 0x2e */ i86op_segovr_CS, -/* 0x2f */ i86op_das, - -/* 0x30 */ i86op_xor_byte_RM_R, -/* 0x31 */ i86op_xor_word_RM_R, -/* 0x32 */ i86op_xor_byte_R_RM, -/* 0x33 */ i86op_xor_word_R_RM, -/* 0x34 */ i86op_xor_byte_AL_IMM, -/* 0x35 */ i86op_xor_word_AX_IMM, -/* 0x36 */ i86op_segovr_SS, -/* 0x37 */ i86op_aaa, - -/* 0x38 */ i86op_cmp_byte_RM_R, -/* 0x39 */ i86op_cmp_word_RM_R, -/* 0x3a */ i86op_cmp_byte_R_RM, -/* 0x3b */ i86op_cmp_word_R_RM, -/* 0x3c */ i86op_cmp_byte_AL_IMM, -/* 0x3d */ i86op_cmp_word_AX_IMM, -/* 0x3e */ i86op_segovr_DS, -/* 0x3f */ i86op_aas, - -/* 0x40 */ i86op_inc_AX, -/* 0x41 */ i86op_inc_CX, -/* 0x42 */ i86op_inc_DX, -/* 0x43 */ i86op_inc_BX, -/* 0x44 */ i86op_inc_SP, -/* 0x45 */ i86op_inc_BP, -/* 0x46 */ i86op_inc_SI, -/* 0x47 */ i86op_inc_DI, - -/* 0x48 */ i86op_dec_AX, -/* 0x49 */ i86op_dec_CX, -/* 0x4a */ i86op_dec_DX, -/* 0x4b */ i86op_dec_BX, -/* 0x4c */ i86op_dec_SP, -/* 0x4d */ i86op_dec_BP, -/* 0x4e */ i86op_dec_SI, -/* 0x4f */ i86op_dec_DI, - -/* 0x50 */ i86op_push_AX, -/* 0x51 */ i86op_push_CX, -/* 0x52 */ i86op_push_DX, -/* 0x53 */ i86op_push_BX, -/* 0x54 */ i86op_push_SP, -/* 0x55 */ i86op_push_BP, -/* 0x56 */ i86op_push_SI, -/* 0x57 */ i86op_push_DI, - -/* 0x58 */ i86op_pop_AX, -/* 0x59 */ i86op_pop_CX, -/* 0x5a */ i86op_pop_DX, -/* 0x5b */ i86op_pop_BX, -/* 0x5c */ i86op_pop_SP, -/* 0x5d */ i86op_pop_BP, -/* 0x5e */ i86op_pop_SI, -/* 0x5f */ i86op_pop_DI, - -/* 0x60 */ i86op_illegal_op, -/* 0x61 */ i86op_illegal_op, -/* 0x62 */ i86op_illegal_op, -/* 0x63 */ i86op_illegal_op, -/* 0x64 */ i86op_illegal_op, -/* 0x65 */ i86op_illegal_op, -/* 0x66 */ i86op_illegal_op, -/* 0x67 */ i86op_illegal_op, - -/* 0x68 */ i86op_illegal_op, -/* 0x69 */ i86op_illegal_op, -/* 0x6a */ i86op_illegal_op, -/* 0x6b */ i86op_illegal_op, -/* 0x6c */ i86op_illegal_op, -/* 0x6d */ i86op_illegal_op, -/* 0x6e */ i86op_illegal_op, -/* 0x6f */ i86op_illegal_op, - -/* 0x70 */ i86op_jump_near_O, -/* 0x71 */ i86op_jump_near_NO, -/* 0x72 */ i86op_jump_near_B, -/* 0x73 */ i86op_jump_near_NB, -/* 0x74 */ i86op_jump_near_Z, -/* 0x75 */ i86op_jump_near_NZ, -/* 0x76 */ i86op_jump_near_BE, -/* 0x77 */ i86op_jump_near_NBE, - -/* 0x78 */ i86op_jump_near_S, -/* 0x79 */ i86op_jump_near_NS, -/* 0x7a */ i86op_jump_near_P, -/* 0x7b */ i86op_jump_near_NP, -/* 0x7c */ i86op_jump_near_L, -/* 0x7d */ i86op_jump_near_NL, -/* 0x7e */ i86op_jump_near_LE, -/* 0x7f */ i86op_jump_near_NLE, - -/* 0x80 */ i86op_opc80_byte_RM_IMM, -/* 0x81 */ i86op_opc81_word_RM_IMM, -/* 0x82 */ i86op_opc82_byte_RM_IMM, -/* 0x83 */ i86op_opc83_word_RM_IMM, -/* 0x84 */ i86op_test_byte_RM_R, -/* 0x85 */ i86op_test_word_RM_R, -/* 0x86 */ i86op_xchg_byte_RM_R, -/* 0x87 */ i86op_xchg_word_RM_R, - -/* 0x88 */ i86op_mov_byte_RM_R, -/* 0x89 */ i86op_mov_word_RM_R, -/* 0x8a */ i86op_mov_byte_R_RM, -/* 0x8b */ i86op_mov_word_R_RM, -/* 0x8c */ i86op_mov_word_RM_SR, -/* 0x8d */ i86op_lea_word_R_M, -/* 0x8e */ i86op_mov_word_SR_RM, -/* 0x8f */ i86op_pop_RM, - -/* 0x90 */ i86op_nop, -/* 0x91 */ i86op_xchg_word_AX_CX, -/* 0x92 */ i86op_xchg_word_AX_DX, -/* 0x93 */ i86op_xchg_word_AX_BX, -/* 0x94 */ i86op_xchg_word_AX_SP, -/* 0x95 */ i86op_xchg_word_AX_BP , -/* 0x96 */ i86op_xchg_word_AX_SI , -/* 0x97 */ i86op_xchg_word_AX_DI , - -/* 0x98 */ i86op_cbw, -/* 0x99 */ i86op_cwd, -/* 0x9a */ i86op_call_far_IMM, -/* 0x9b */ i86op_wait, -/* 0x9c */ i86op_pushf_word, -/* 0x9d */ i86op_popf_word, -/* 0x9e */ i86op_sahf, -/* 0x9f */ i86op_lahf, - -/* 0xa0 */ i86op_mov_AL_M_IMM, -/* 0xa1 */ i86op_mov_AX_M_IMM, -/* 0xa2 */ i86op_mov_M_AL_IMM, -/* 0xa3 */ i86op_mov_M_AX_IMM, -/* 0xa4 */ i86op_movs_byte, -/* 0xa5 */ i86op_movs_word, -/* 0xa6 */ i86op_cmps_byte, -/* 0xa7 */ i86op_cmps_word, -/* 0xa8 */ i86op_test_AL_IMM, -/* 0xa9 */ i86op_test_AX_IMM, -/* 0xaa */ i86op_stos_byte, -/* 0xab */ i86op_stos_word, -/* 0xac */ i86op_lods_byte, -/* 0xad */ i86op_lods_word, -/* 0xac */ i86op_scas_byte, -/* 0xad */ i86op_scas_word, - -/* 0xb0 */ i86op_mov_byte_AL_IMM, -/* 0xb1 */ i86op_mov_byte_CL_IMM, -/* 0xb2 */ i86op_mov_byte_DL_IMM, -/* 0xb3 */ i86op_mov_byte_BL_IMM, -/* 0xb4 */ i86op_mov_byte_AH_IMM, -/* 0xb5 */ i86op_mov_byte_CH_IMM, -/* 0xb6 */ i86op_mov_byte_DH_IMM, -/* 0xb7 */ i86op_mov_byte_BH_IMM, - -/* 0xb8 */ i86op_mov_word_AX_IMM, -/* 0xb9 */ i86op_mov_word_CX_IMM, -/* 0xba */ i86op_mov_word_DX_IMM, -/* 0xbb */ i86op_mov_word_BX_IMM, -/* 0xbc */ i86op_mov_word_SP_IMM, -/* 0xbd */ i86op_mov_word_BP_IMM, -/* 0xbe */ i86op_mov_word_SI_IMM, -/* 0xbf */ i86op_mov_word_DI_IMM, - -/* 0xc0 */ i86op_illegal_op, -/* 0xc1 */ i86op_illegal_op, -/* 0xc2 */ i86op_ret_near_IMM, -/* 0xc3 */ i86op_ret_near, -/* 0xc4 */ i86op_les_R_IMM, -/* 0xc5 */ i86op_lds_R_IMM, -/* 0xc6 */ i86op_mov_byte_RM_IMM, -/* 0xc7 */ i86op_mov_word_RM_IMM, -/* 0xc8 */ i86op_illegal_op, -/* 0xc9 */ i86op_illegal_op, -/* 0xca */ i86op_ret_far_IMM, -/* 0xcb */ i86op_ret_far, -/* 0xcc */ i86op_int3, -/* 0xcd */ i86op_int_IMM, -/* 0xce */ i86op_into, -/* 0xcf */ i86op_iret, - -/* 0xd0 */ i86op_opcD0_byte_RM_1, -/* 0xd1 */ i86op_opcD1_word_RM_1, -/* 0xd2 */ i86op_opcD2_byte_RM_CL, -/* 0xd3 */ i86op_opcD3_word_RM_CL, -/* 0xd4 */ i86op_aam, -/* 0xd5 */ i86op_aad, -/* 0xd6 */ i86op_illegal_op, -/* 0xd7 */ i86op_xlat, -/* 0xd8 */ i86op_esc_coprocess_d8, -/* 0xd9 */ i86op_esc_coprocess_d9, -/* 0xda */ i86op_esc_coprocess_da, -/* 0xdb */ i86op_esc_coprocess_db, -/* 0xdc */ i86op_esc_coprocess_dc, -/* 0xdd */ i86op_esc_coprocess_dd, -/* 0xde */ i86op_esc_coprocess_de, -/* 0xdf */ i86op_esc_coprocess_df, - -/* 0xe0 */ i86op_loopne, -/* 0xe1 */ i86op_loope, -/* 0xe2 */ i86op_loop, -/* 0xe3 */ i86op_jcxz, -/* 0xe4 */ i86op_in_byte_AL_IMM, -/* 0xe5 */ i86op_in_word_AX_IMM, -/* 0xe6 */ i86op_out_byte_IMM_AL, -/* 0xe7 */ i86op_out_word_IMM_AX, - -/* 0xe8 */ i86op_call_near_IMM, -/* 0xe9 */ i86op_jump_near_IMM, -/* 0xea */ i86op_jump_far_IMM, -/* 0xeb */ i86op_jump_byte_IMM, -/* 0xec */ i86op_in_byte_AL_DX, -/* 0xed */ i86op_in_word_AX_DX, -/* 0xee */ i86op_out_byte_DX_AL, -/* 0xef */ i86op_out_word_DX_AX, - -/* 0xf0 */ i86op_lock, -/* 0xf1 */ i86op_illegal_op, -/* 0xf2 */ i86op_repne, -/* 0xf3 */ i86op_repe, -/* 0xf4 */ i86op_halt, -/* 0xf5 */ i86op_cmc, -/* 0xf6 */ i86op_opcF6_byte_RM, -/* 0xf7 */ i86op_opcF7_word_RM, - -/* 0xf8 */ i86op_clc, -/* 0xf9 */ i86op_stc, -/* 0xfa */ i86op_cli, -/* 0xfb */ i86op_sti, -/* 0xfc */ i86op_cld, -/* 0xfd */ i86op_std, -/* 0xfe */ i86op_opcFE_byte_RM, -/* 0xff */ i86op_opcFF_word_RM, - -}; diff --git a/AltairZ80/i86_prim_ops.c b/AltairZ80/i86_prim_ops.c deleted file mode 100644 index 44355110..00000000 --- a/AltairZ80/i86_prim_ops.c +++ /dev/null @@ -1,1527 +0,0 @@ -/* - * Dos/PC Emulator - * 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. - * - */ - -#include "altairz80_defs.h" -#include "i86.h" - -extern uint32 GetBYTEExtended(register uint32 Addr); -extern void PutBYTEExtended(register uint32 Addr, const register uint32 Value); - -/* $Log: i86_prim_ops.c,v $ - * Revision 0.9 2003-01-10 23:33:10 jce - * fixed some more warnings under gcc -Wall - * - * Revision 0.8 1992/04/11 21:58:13 hudgens - * fixed some code causing warnings under gcc -Wall - * - * Revision 0.7 1991/07/30 02:04:34 hudgens - * added copyright. - * - * Revision 0.6 1991/07/21 16:50:37 hudgens - * fixed all flags in the bit shift and rotate instructions so that they - * finally agree. - * Also fixed the flags associated with IMUL and MUL instructions. - * - * Revision 0.5 1991/07/21 01:28:16 hudgens - * added support for aad and aam primitives. - * - * Revision 0.4 1991/07/20 22:26:25 hudgens - * fixed problem with sign extension in subroutine mem_access_word. - * - * Revision 0.3 1991/07/17 03:48:22 hudgens - * fixed bugs having to do with the setting of flags in the - * shift and rotate operations. Also, fixed sign extension problem - * with push_word and pop_word. - * - * Revision 0.2 1991/04/01 02:36:00 hudgens - * Fixed several nasty bugs dealing with flag setting in the subroutines - * sub_byte, sub_word, sbb_byte, sbb_word, and test_word. The results - * now agree with the PC on both of the testaopb and testaopw tests. - * - * Revision 0.1 1991/03/30 21:13:37 hudgens - * Initial checkin. - * - * - */ - -/* [JCE] Stop gcc -Wall complaining */ -extern void i86_intr_raise(PC_ENV *m, uint8 intrnum); - -/* the following table was generated using the following - code (running on an IBM AT, Turbo C++ 2.0), for all values of i - between 0 and 255. AL is loaded with i's value, and then the - operation "and al,al" sets the parity flag. The flags are pushed - onto the stack, and then popped back into AX. Then AX is - returned. So the value of each table entry represents the - parity of its index into the table. This results in a somewhat - faster mechanism for parity calculations than the straightforward - method. - andflags(i,res) int *res; { - int flags; - _AX = i; asm and al,al; asm pushf; *res = _AX; - asm pop ax; flags = _AX; return flags; - } - */ - -uint8 parity_tab[] = { -/*0*/ 1, /*1*/ 0, /*2*/ 0, /*3*/ 1, -/*4*/ 0, /*5*/ 1, /*6*/ 1, /*7*/ 0, -/*8*/ 0, /*9*/ 1, /*a*/ 1, /*b*/ 0, -/*c*/ 1, /*d*/ 0, /*e*/ 0, /*f*/ 1, -/*10*/ 0, /*11*/ 1, /*12*/ 1, /*13*/ 0, -/*14*/ 1, /*15*/ 0, /*16*/ 0, /*17*/ 1, -/*18*/ 1, /*19*/ 0, /*1a*/ 0, /*1b*/ 1, -/*1c*/ 0, /*1d*/ 1, /*1e*/ 1, /*1f*/ 0, -/*20*/ 0, /*21*/ 1, /*22*/ 1, /*23*/ 0, -/*24*/ 1, /*25*/ 0, /*26*/ 0, /*27*/ 1, -/*28*/ 1, /*29*/ 0, /*2a*/ 0, /*2b*/ 1, -/*2c*/ 0, /*2d*/ 1, /*2e*/ 1, /*2f*/ 0, -/*30*/ 1, /*31*/ 0, /*32*/ 0, /*33*/ 1, -/*34*/ 0, /*35*/ 1, /*36*/ 1, /*37*/ 0, -/*38*/ 0, /*39*/ 1, /*3a*/ 1, /*3b*/ 0, -/*3c*/ 1, /*3d*/ 0, /*3e*/ 0, /*3f*/ 1, -/*40*/ 0, /*41*/ 1, /*42*/ 1, /*43*/ 0, -/*44*/ 1, /*45*/ 0, /*46*/ 0, /*47*/ 1, -/*48*/ 1, /*49*/ 0, /*4a*/ 0, /*4b*/ 1, -/*4c*/ 0, /*4d*/ 1, /*4e*/ 1, /*4f*/ 0, -/*50*/ 1, /*51*/ 0, /*52*/ 0, /*53*/ 1, -/*54*/ 0, /*55*/ 1, /*56*/ 1, /*57*/ 0, -/*58*/ 0, /*59*/ 1, /*5a*/ 1, /*5b*/ 0, -/*5c*/ 1, /*5d*/ 0, /*5e*/ 0, /*5f*/ 1, -/*60*/ 1, /*61*/ 0, /*62*/ 0, /*63*/ 1, -/*64*/ 0, /*65*/ 1, /*66*/ 1, /*67*/ 0, -/*68*/ 0, /*69*/ 1, /*6a*/ 1, /*6b*/ 0, -/*6c*/ 1, /*6d*/ 0, /*6e*/ 0, /*6f*/ 1, -/*70*/ 0, /*71*/ 1, /*72*/ 1, /*73*/ 0, -/*74*/ 1, /*75*/ 0, /*76*/ 0, /*77*/ 1, -/*78*/ 1, /*79*/ 0, /*7a*/ 0, /*7b*/ 1, -/*7c*/ 0, /*7d*/ 1, /*7e*/ 1, /*7f*/ 0, -/*80*/ 0, /*81*/ 1, /*82*/ 1, /*83*/ 0, -/*84*/ 1, /*85*/ 0, /*86*/ 0, /*87*/ 1, -/*88*/ 1, /*89*/ 0, /*8a*/ 0, /*8b*/ 1, -/*8c*/ 0, /*8d*/ 1, /*8e*/ 1, /*8f*/ 0, -/*90*/ 1, /*91*/ 0, /*92*/ 0, /*93*/ 1, -/*94*/ 0, /*95*/ 1, /*96*/ 1, /*97*/ 0, -/*98*/ 0, /*99*/ 1, /*9a*/ 1, /*9b*/ 0, -/*9c*/ 1, /*9d*/ 0, /*9e*/ 0, /*9f*/ 1, -/*a0*/ 1, /*a1*/ 0, /*a2*/ 0, /*a3*/ 1, -/*a4*/ 0, /*a5*/ 1, /*a6*/ 1, /*a7*/ 0, -/*a8*/ 0, /*a9*/ 1, /*aa*/ 1, /*ab*/ 0, -/*ac*/ 1, /*ad*/ 0, /*ae*/ 0, /*af*/ 1, -/*b0*/ 0, /*b1*/ 1, /*b2*/ 1, /*b3*/ 0, -/*b4*/ 1, /*b5*/ 0, /*b6*/ 0, /*b7*/ 1, -/*b8*/ 1, /*b9*/ 0, /*ba*/ 0, /*bb*/ 1, -/*bc*/ 0, /*bd*/ 1, /*be*/ 1, /*bf*/ 0, -/*c0*/ 1, /*c1*/ 0, /*c2*/ 0, /*c3*/ 1, -/*c4*/ 0, /*c5*/ 1, /*c6*/ 1, /*c7*/ 0, -/*c8*/ 0, /*c9*/ 1, /*ca*/ 1, /*cb*/ 0, -/*cc*/ 1, /*cd*/ 0, /*ce*/ 0, /*cf*/ 1, -/*d0*/ 0, /*d1*/ 1, /*d2*/ 1, /*d3*/ 0, -/*d4*/ 1, /*d5*/ 0, /*d6*/ 0, /*d7*/ 1, -/*d8*/ 1, /*d9*/ 0, /*da*/ 0, /*db*/ 1, -/*dc*/ 0, /*dd*/ 1, /*de*/ 1, /*df*/ 0, -/*e0*/ 0, /*e1*/ 1, /*e2*/ 1, /*e3*/ 0, -/*e4*/ 1, /*e5*/ 0, /*e6*/ 0, /*e7*/ 1, -/*e8*/ 1, /*e9*/ 0, /*ea*/ 0, /*eb*/ 1, -/*ec*/ 0, /*ed*/ 1, /*ee*/ 1, /*ef*/ 0, -/*f0*/ 1, /*f1*/ 0, /*f2*/ 0, /*f3*/ 1, -/*f4*/ 0, /*f5*/ 1, /*f6*/ 1, /*f7*/ 0, -/*f8*/ 0, /*f9*/ 1, /*fa*/ 1, /*fb*/ 0, -/*fc*/ 1, /*fd*/ 0, /*fe*/ 0, /*ff*/ 1, -}; - -uint8 xor_0x3_tab[] = { 0, 1, 1, 0 }; - -/* 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) - - */ - -uint8 aad_word(PC_ENV *m, uint16 d) -{ - uint16 l; - uint8 hb,lb; - hb = (d>>8)&0xff; - lb = (d&0xff); - l = lb + 10 * hb; - CONDITIONAL_SET_FLAG(l & 0x80, m, F_SF); - CONDITIONAL_SET_FLAG(l == 0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[l & 0xff], m, F_PF); - return (uint8) l; -} - -uint16 aam_word(PC_ENV *m, uint8 d) -{ - uint16 h,l; - h = d / 10; - l = d % 10; - l |= (h<<8); - CONDITIONAL_SET_FLAG(l & 0x80, m, F_SF); - CONDITIONAL_SET_FLAG(l == 0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[l & 0xff], m, F_PF); - return l; -} - -uint8 adc_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint16 res; /* all operands in native machine order */ - register uint16 cc; - if (ACCESS_FLAG(m,F_CF) ) - res = 1 + d + s; - else - res = d + s; - CONDITIONAL_SET_FLAG(res & 0x100, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = (s & d) | ((~res) & (s | d)); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(cc>>6)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(cc&0x8, m, F_AF); - return (uint8) res; -} - -uint16 adc_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 cc; - if (ACCESS_FLAG(m,F_CF) ) - res = 1 + d + s; - else - res = d + s; - /* set the carry flag to be bit 8 */ - CONDITIONAL_SET_FLAG(res & 0x10000, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = (s & d) | ((~res) & (s | d)); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(cc>>14)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(cc&0x8, m, F_AF); - return res; -} - -/* Given flags=f, and bytes d (dest) and s (source) - perform the add and set the flags and the result back to - *d. USE NATIVE MACHINE ORDER... -*/ -uint8 add_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint16 res; /* all operands in native machine order */ - register uint16 cc; - res = d + s; - /* set the carry flag to be bit 8 */ - CONDITIONAL_SET_FLAG(res & 0x100, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = (s & d) | ((~res) & (s | d)); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(cc>>6)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(cc&0x8, m, F_AF); - return (uint8) res; -} - -/* Given flags=f, and bytes d (dest) and s (source) - perform the add and set the flags and the result back to - *d. USE NATIVE MACHINE ORDER... -*/ -uint16 add_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 cc; - res = d + s; - /* set the carry flag to be bit 8 */ - CONDITIONAL_SET_FLAG(res & 0x10000, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = (s & d) | ((~res) & (s | d)); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(cc>>14)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(cc&0x8, m, F_AF); - return res; -} - -/* - Flags m->R_FLG, dest *d, source *s, do a bitwise and of the - source and destination, and then store back to the - destination. Size=byte. -*/ -uint8 and_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint8 res; /* all operands in native machine order */ - res = d & s; - /* set the flags */ - CLEAR_FLAG(m, F_OF); - CLEAR_FLAG(m, F_CF); - CONDITIONAL_SET_FLAG(res&0x80, m, F_SF); - CONDITIONAL_SET_FLAG(res==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res], m, F_PF); - return res; -} - -/* - Flags m->R_FLG, dest *d, source *s, do a bitwise and of the - source and destination, and then store back to the - destination. Size=byte. -*/ -uint16 and_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint16 res; /* all operands in native machine order */ - res = d & s; - /* set the flags */ - CLEAR_FLAG(m, F_OF); - CLEAR_FLAG(m, F_CF); - CONDITIONAL_SET_FLAG(res&0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(res==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - return res; -} - -uint8 cmp_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 bc; - res = d - s; - CLEAR_FLAG(m, F_CF); - CONDITIONAL_SET_FLAG(res&0x80, m, F_SF); - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - CONDITIONAL_SET_FLAG(bc&0x80,m, F_CF); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(bc>>6)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(bc&0x8, m, F_AF); - return d; /* long story why this is needed. Look at opcode - 0x80 in ops.c, for an idea why this is necessary.*/ -} - -uint16 cmp_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 bc; - res = d - s; - CONDITIONAL_SET_FLAG(res&0x8000, m, F_SF); - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - CONDITIONAL_SET_FLAG(bc&0x8000,m, F_CF); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(bc>>14)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(bc&0x8, m, F_AF); - return d; -} - -uint8 dec_byte(PC_ENV *m, uint8 d) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 bc; - res = d - 1; - CONDITIONAL_SET_FLAG(res&0x80, m, F_SF); - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_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 */ - CONDITIONAL_SET_FLAG(xor_0x3_tab[(bc>>6)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(bc&0x8, m, F_AF); - return res; -} - -uint16 dec_word(PC_ENV *m, uint16 d) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 bc; - res = d - 1; - CONDITIONAL_SET_FLAG(res&0x8000, m, F_SF); - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_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 */ - CONDITIONAL_SET_FLAG(xor_0x3_tab[(bc>>14)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(bc&0x8, m, F_AF); - return res; -} - -/* Given flags=f, and byte d (dest) - perform the inc and set the flags and the result back to - d. USE NATIVE MACHINE ORDER... -*/ -uint8 inc_byte(PC_ENV *m, uint8 d) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 cc; - res = d + 1; - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = ((1 & d) | (~res)) & (1 | d); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(cc>>6)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(cc&0x8, m, F_AF); - return res; -} - -/* Given flags=f, and byte d (dest) - perform the inc and set the flags and the result back to - *d. USE NATIVE MACHINE ORDER... -*/ -uint16 inc_word(PC_ENV *m, uint16 d) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 cc; - res = d + 1; - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the carry chain SEE NOTE AT TOP.*/ - cc = (1 & d) | ((~res) & (1 | d)); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(cc>>14)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(cc&0x8, m, F_AF); - return res ; -} - -uint8 or_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint8 res; /* all operands in native machine order */ - res = d | s; - CLEAR_FLAG(m, F_OF); - CLEAR_FLAG(m, F_CF); - CONDITIONAL_SET_FLAG(res&0x80, m, F_SF); - CONDITIONAL_SET_FLAG(res==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res], m, F_PF); - return res; -} - -uint16 or_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint16 res; /* all operands in native machine order */ - res = d | s; - /* set the carry flag to be bit 8 */ - CLEAR_FLAG(m, F_OF); - CLEAR_FLAG(m, F_CF); - CONDITIONAL_SET_FLAG(res&0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(res==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - return res; -} - -uint8 neg_byte(PC_ENV *m, uint8 s) -{ - register uint8 res; - register uint8 bc; - CONDITIONAL_SET_FLAG(s!=0, m, F_CF); - res = -s; - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res], m, F_PF); - /* calculate the borrow chain --- modified such that d=0. - substitutiing d=0 into bc= res&(~d|s)|(~d&s); - (the one used for sub) and simplifying, since ~d=0xff..., - ~d|s == 0xffff..., and res&0xfff... == res. Similarly - ~d&s == s. So the simplified result is:*/ - bc= res|s; - CONDITIONAL_SET_FLAG(xor_0x3_tab[(bc>>6)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(bc&0x8, m, F_AF); - return res; -} - -uint16 neg_word(PC_ENV *m, uint16 s) -{ - register uint16 res; - register uint16 bc; - CONDITIONAL_SET_FLAG(s!=0, m, F_CF); - res = -s; - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the borrow chain --- modified such that d=0. - substitutiing d=0 into bc= res&(~d|s)|(~d&s); - (the one used for sub) and simplifying, since ~d=0xff..., - ~d|s == 0xffff..., and res&0xfff... == res. Similarly - ~d&s == s. So the simplified result is:*/ - bc= res|s; - CONDITIONAL_SET_FLAG(xor_0x3_tab[(bc>>6)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(bc&0x8, m, F_AF); - return res; -} - -uint8 not_byte(PC_ENV *m, uint8 s) -{ - return ~s; -} - -uint16 not_word(PC_ENV *m, uint16 s) -{ - return ~s; -} - -/* access stuff from absolute location in memory. - no segment registers are involved. - */ -uint16 mem_access_word(PC_ENV *m, int addr) -{ - /* Load in two steps. Native byte order independent */ - return GetBYTEExtended(addr) | (GetBYTEExtended(addr + 1) << 8); -} - -/* given the register_set r, and memory descriptor m, - and word w, push w onto the stack. - w ASSUMED IN NATIVE MACHINE ORDER. Doesn't matter in this case??? - */ -void push_word(PC_ENV *m, uint16 w) -{ - m->R_SP --; - PutBYTEExtended((m->R_SS << 4) + m->R_SP, w >> 8); - m->R_SP --; - PutBYTEExtended((m->R_SS << 4) + m->R_SP, w & 0xff); -} - -/* given the memory descriptor m, - and word w, pop word from the stack. - */ -uint16 pop_word(PC_ENV *m) -{ - register uint16 res; - res = GetBYTEExtended((m->R_SS << 4) + m->R_SP); - m->R_SP++; - res |= GetBYTEExtended((m->R_SS << 4) + m->R_SP) << 8; - m->R_SP++; - return res; -} - -/***************************************************************** - BEGIN region consisting of bit shifts and rotates, - much of which may be wrong. Large hirsute factor. -*****************************************************************/ -uint8 rcl_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint32 res, cnt, mask,cf; - /* s is the rotate distance. It varies from 0 - 8. */ - /* have - CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 - want to rotate through the carry by "s" bits. We could - loop, but that's inefficient. So the width is 9, - and we split into three parts: - The new carry flag (was B_n) - the stuff in B_n-1 .. B_0 - the stuff in B_7 .. B_n+1 - The new rotate is done mod 9, and given this, - for a rotation of n bits (mod 9) the new carry flag is - then located n bits from the MSB. The low part is - then shifted up cnt bits, and the high part is or'd - in. Using CAPS for new values, and lowercase for the - original values, this can be expressed as: - IF n > 0 - 1) CF <- b_(8-n) - 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 - 3) B_(n-1) <- cf - 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) - I think this is correct. - */ - res = d; - /* [JCE] Extra brackets to stop gcc -Wall moaning */ - if ((cnt = s % 9)) /* not a typo, do nada if cnt==0 */ - { - /* extract the new CARRY FLAG. */ - /* CF <- b_(8-n) */ - cf = (d >> (8-cnt)) & 0x1; - /* get the low stuff which rotated - into the range B_7 .. B_cnt */ - /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */ - /* note that the right hand side done by the mask */ - res = (d << cnt) & 0xff; - /* now the high stuff which rotated around - into the positions B_cnt-2 .. B_0 */ - /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ - /* shift it downward, 7-(n-2) = 9-n positions. - and mask off the result before or'ing in. - */ - mask = (1<<(cnt-1)) - 1; - res |= (d >> (9-cnt)) & mask; - /* if the carry flag was set, or it in. */ - if (ACCESS_FLAG(m,F_CF)) /* carry flag is set */ - { - /* B_(n-1) <- cf */ - res |= 1 << (cnt-1); - } - /* set the new carry flag, based on the variable "cf" */ - CONDITIONAL_SET_FLAG(cf, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of CF and the most significant bit. Blecck. */ - /* parenthesized this expression since it appears to - be causing OF to be missed. */ - CONDITIONAL_SET_FLAG(cnt==1&&xor_0x3_tab[cf+((res>>6)&0x2)], m, F_OF); - } - return res & 0xff; -} - -uint16 rcl_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint32 res, cnt, mask,cf; - /* see analysis above. */ - /* width here is 16 bits + carry bit */ - res = d; - /* [JCE] Extra brackets to stop gcc -Wall moaning */ - if ((cnt = s % 17)) /* not a typo, do nada if cnt==0 */ - { - /* extract the new CARRY FLAG. */ - /* CF <- b_(16-n) */ - cf = (d >> (16-cnt)) & 0x1; - /* get the low stuff which rotated - into the range B_15 .. B_cnt */ - /* B_(15) .. B_(n) <- b_(16-(n+1)) .. b_0 */ - /* note that the right hand side done by the mask */ - res = (d << cnt) & 0xffff; - /* now the high stuff which rotated around - into the positions B_cnt-2 .. B_0 */ - /* B_(n-2) .. B_0 <- b_15 .. b_(16-(n-1)) */ - /* shift it downward, 15-(n-2) = 17-n positions. - and mask off the result before or'ing in. - */ - mask = (1<<(cnt-1)) - 1; - res |= (d >> (17-cnt)) & mask; - /* if the carry flag was set, or it in. */ - if (ACCESS_FLAG(m, F_CF)) /* carry flag is set */ - { - /* B_(n-1) <- cf */ - res |= 1 << (cnt-1); - } - /* set the new carry flag, based on the variable "cf" */ - CONDITIONAL_SET_FLAG(cf, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of CF and the most significant bit. Blecck. - Note that we're forming a 2 bit word here to index - into the table. The expression cf+(res>>14)&0x2 - represents the two bit word b_15 CF. - */ - /* parenthesized following expression... */ - CONDITIONAL_SET_FLAG(cnt==1&&xor_0x3_tab[cf+((res>>14)&0x2)], m, F_OF); - } - return res & 0xffff; -} - -uint8 rcr_byte(PC_ENV *m, uint8 d, uint8 s) -{ - uint8 res, cnt; - uint8 mask, cf, ocf = 0; - /* rotate right through carry */ - /* - s is the rotate distance. It varies from 0 - 8. - d is the byte object rotated. - have - CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 - The new rotate is done mod 9, and given this, - for a rotation of n bits (mod 9) the new carry flag is - then located n bits from the LSB. The low part is - then shifted up cnt bits, and the high part is or'd - in. Using CAPS for new values, and lowercase for the - original values, this can be expressed as: - IF n > 0 - 1) CF <- b_(n-1) - 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) - 3) B_(8-n) <- cf - 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) - I think this is correct. - */ - res = d; - /* [JCE] Extra brackets to stop gcc -Wall moaning */ - if ((cnt = s % 9)) /* not a typo, do nada if cnt==0 */ - { - /* extract the new CARRY FLAG. */ - /* CF <- b_(n-1) */ - if (cnt == 1) - { - cf = d & 0x1; - /* note hackery here. Access_flag(..) evaluates to either - 0 if flag not set - non-zero if flag is set. - doing access_flag(..) != 0 casts that into either - 0..1 in any representation of the flags register - (i.e. packed bit array or unpacked.) - */ - ocf = ACCESS_FLAG(m,F_CF) != 0; - } - else - cf = (d >> (cnt-1)) & 0x1; - /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */ - /* note that the right hand side done by the mask - This is effectively done by shifting the - object to the right. The result must be masked, - in case the object came in and was treated - as a negative number. Needed???*/ - mask = (1<<(8-cnt))-1; - res = (d >> cnt) & mask; - /* now the high stuff which rotated around - into the positions B_cnt-2 .. B_0 */ - /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ - /* shift it downward, 7-(n-2) = 9-n positions. - and mask off the result before or'ing in. - */ - res |= (d << (9-cnt)); - /* if the carry flag was set, or it in. */ - if (ACCESS_FLAG(m,F_CF)) /* carry flag is set */ - { - /* B_(8-n) <- cf */ - res |= 1 << (8 - cnt); - } - /* set the new carry flag, based on the variable "cf" */ - CONDITIONAL_SET_FLAG(cf, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of CF and the most significant bit. Blecck. */ - /* parenthesized... */ - if (cnt == 1) - { /* [JCE] Explicit braces to stop gcc -Wall moaning */ - CONDITIONAL_SET_FLAG(xor_0x3_tab[ocf+((d>>6)&0x2)], m, F_OF); - } - } - return res; -} - -uint16 rcr_word(PC_ENV *m, uint16 d, uint16 s) -{ - uint16 res, cnt; - uint16 mask, cf, ocf = 0; - /* rotate right through carry */ - /* - s is the rotate distance. It varies from 0 - 8. - d is the byte object rotated. - have - CF B_15 ... B_0 - The new rotate is done mod 17, and given this, - for a rotation of n bits (mod 17) the new carry flag is - then located n bits from the LSB. The low part is - then shifted up cnt bits, and the high part is or'd - in. Using CAPS for new values, and lowercase for the - original values, this can be expressed as: - IF n > 0 - 1) CF <- b_(n-1) - 2) B_(16-(n+1)) .. B_(0) <- b_(15) .. b_(n) - 3) B_(16-n) <- cf - 4) B_(15) .. B_(16-(n-1)) <- b_(n-2) .. b_(0) - I think this is correct. - */ - res = d; - /* [JCE] Extra brackets to stop gcc -Wall moaning */ - if ((cnt = s % 17)) /* not a typo, do nada if cnt==0 */ - { - /* extract the new CARRY FLAG. */ - /* CF <- b_(n-1) */ - if (cnt==1) - { - cf = d & 0x1; - /* see note above on teh byte version */ - ocf = ACCESS_FLAG(m,F_CF) != 0; - } - else - cf = (d >> (cnt-1)) & 0x1; - /* B_(16-(n+1)) .. B_(0) <- b_(15) .. b_n */ - /* note that the right hand side done by the mask - This is effectively done by shifting the - object to the right. The result must be masked, - in case the object came in and was treated - as a negative number. Needed???*/ - mask = (1<<(16-cnt))-1; - res = (d >> cnt) & mask; - /* now the high stuff which rotated around - into the positions B_cnt-2 .. B_0 */ - /* B_(15) .. B_(16-(n-1)) <- b_(n-2) .. b_(0) */ - /* shift it downward, 15-(n-2) = 17-n positions. - and mask off the result before or'ing in. - */ - res |= (d << (17-cnt)); - /* if the carry flag was set, or it in. */ - if (ACCESS_FLAG(m,F_CF)) /* carry flag is set */ - { - /* B_(16-n) <- cf */ - res |= 1 << (16 - cnt); - } - /* set the new carry flag, based on the variable "cf" */ - CONDITIONAL_SET_FLAG(cf, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of CF and the most significant bit. Blecck. */ - if (cnt==1) - { /* [JCE] Explicit braces to stop gcc -Wall moaning */ - CONDITIONAL_SET_FLAG(xor_0x3_tab[ocf+((d>>14)&0x2)], m, F_OF); - } - } - return res; -} - -uint8 rol_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint32 res, cnt, mask; - /* rotate left */ - /* - s is the rotate distance. It varies from 0 - 8. - d is the byte object rotated. - have - CF B_7 ... B_0 - The new rotate is done mod 8. - Much simpler than the "rcl" or "rcr" operations. - IF n > 0 - 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) - 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) - I think this is correct. - */ - res =d; - /* [JCE] Extra brackets to stop gcc -Wall moaning */ - if ((cnt = s % 8)) /* not a typo, do nada if cnt==0 */ - { - /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */ - res = (d << cnt); - /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */ - mask = (1 << cnt) - 1; - res |= (d >> (8-cnt)) & mask; - /* set the new carry flag, Note that it is the low order - bit of the result!!! */ - CONDITIONAL_SET_FLAG(res&0x1, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of CF and the most significant bit. Blecck. */ - CONDITIONAL_SET_FLAG(cnt==1&&xor_0x3_tab[(res&0x1)+((res>>6)&0x2)], m, F_OF); - } - return res&0xff; -} - -uint16 rol_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint32 res, cnt, mask; - /* rotate left */ - /* - s is the rotate distance. It varies from 0 - 8. - d is the byte object rotated. - have - CF B_15 ... B_0 - The new rotate is done mod 8. - Much simpler than the "rcl" or "rcr" operations. - IF n > 0 - 1) B_(15) .. B_(n) <- b_(16-(n+1)) .. b_(0) - 2) B_(n-1) .. B_(0) <- b_(16) .. b_(16-n) - I think this is correct. - */ - res = d; - /* [JCE] Extra brackets to stop gcc -Wall moaning */ - if ((cnt = s % 16)) /* not a typo, do nada if cnt==0 */ - { - /* B_(16) .. B_(n) <- b_(16-(n+1)) .. b_(0) */ - res = (d << cnt); - /* B_(n-1) .. B_(0) <- b_(15) .. b_(16-n) */ - mask = (1 << cnt) - 1; - res |= (d >> (16-cnt)) & mask; - /* set the new carry flag, Note that it is the low order - bit of the result!!! */ - CONDITIONAL_SET_FLAG(res&0x1, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of CF and the most significant bit. Blecck. */ - CONDITIONAL_SET_FLAG(cnt==1&&xor_0x3_tab[(res&0x1)+((res>>14)&0x2)], m, F_OF); - } - return res&0xffff; -} - -uint8 ror_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint32 res, cnt, mask; - /* rotate right */ - /* - s is the rotate distance. It varies from 0 - 8. - d is the byte object rotated. - have - B_7 ... B_0 - The rotate is done mod 8. - IF n > 0 - 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) - 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) - */ - res = d; - /* [JCE] Extra brackets to stop gcc -Wall moaning */ - if ((cnt = s % 8)) /* not a typo, do nada if cnt==0 */ - { - /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)*/ - res = (d << (8-cnt)); - /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */ - mask = (1 << (8-cnt)) - 1; - res |= (d >> (cnt)) & mask; - /* set the new carry flag, Note that it is the low order - bit of the result!!! */ - CONDITIONAL_SET_FLAG(res&0x80, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of the two most significant bits. Blecck. */ - CONDITIONAL_SET_FLAG(cnt==1&& xor_0x3_tab[(res>>6)&0x3], m, F_OF); - } - return res&0xff; -} - -uint16 ror_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint32 res, cnt, mask; - /* rotate right */ - /* - s is the rotate distance. It varies from 0 - 8. - d is the byte object rotated. - have - B_15 ... B_0 - The rotate is done mod 16. - IF n > 0 - 1) B_(16-(n+1)) .. B_(0) <- b_(15) .. b_(n) - 2) B_(15) .. B_(16-n) <- b_(n-1) .. b_(0) - I think this is correct. - */ - res =d ; - /* [JCE] Extra brackets to stop gcc -Wall moaning */ - if ((cnt = s % 16)) /* not a typo, do nada if cnt==0 */ - { - /* B_(15) .. B_(16-n) <- b_(n-1) .. b_(0)*/ - res = (d << (16-cnt)); - /* B_(16-(n+1)) .. B_(0) <- b_(15) .. b_(n) */ - mask = (1 << (16-cnt)) - 1; - res |= (d >> (cnt)) & mask; - /* set the new carry flag, Note that it is the low order - bit of the result!!! */ - CONDITIONAL_SET_FLAG(res&0x8000, m, F_CF); - /* OVERFLOW is set *IFF* cnt==1, then it is the - xor of CF and the most significant bit. Blecck. */ - CONDITIONAL_SET_FLAG(cnt==1 && xor_0x3_tab[(res>>14)&0x3], m, F_OF); - } - return res & 0xffff; -} - -uint8 shl_byte(PC_ENV *m, uint8 d, uint8 s) -{ - uint32 cnt,res,cf; - if (s < 8) - { - cnt = s % 8; - /* last bit shifted out goes into carry flag */ - if (cnt>0) - { - res = d << cnt; - cf = d & (1<<(8-cnt)); - CONDITIONAL_SET_FLAG(cf, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - } - else - { - res = (uint8)d; - } - if (cnt == 1) - { - /* Needs simplification. */ - CONDITIONAL_SET_FLAG( - (((res&0x80)==0x80) ^ - (ACCESS_FLAG(m,F_CF) != 0)) , - /* was (m->R_FLG&F_CF)==F_CF)), */ - m, F_OF); - } - else - { - CLEAR_FLAG(m,F_OF); - } - } - else - { - res = 0; -/* CLEAR_FLAG(m,F_CF);*/ - CONDITIONAL_SET_FLAG((s == 8) && (d & 1), m, F_CF); /* Peter Schorn bug fix */ - CLEAR_FLAG(m,F_OF); - CLEAR_FLAG(m,F_SF); - CLEAR_FLAG(m,F_PF); - SET_FLAG(m,F_ZF); - } - return res & 0xff; -} - -uint16 shl_word(PC_ENV *m, uint16 d, uint16 s) -{ - uint32 cnt,res,cf; - if (s < 16) - { - cnt = s % 16; - if (cnt > 0) - { - res = d << cnt; - /* last bit shifted out goes into carry flag */ - cf = d & (1<<(16-cnt)); - CONDITIONAL_SET_FLAG(cf, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - } - else - { - res = (uint16)d; - } - if (cnt == 1) - { - /* Needs simplification. */ - CONDITIONAL_SET_FLAG( - (((res&0x8000)==0x8000) ^ - (ACCESS_FLAG(m,F_CF) != 0)), - /*((m&F_CF)==F_CF)),*/ - m, F_OF); - } - else - { - CLEAR_FLAG(m,F_OF); - } - } - else - { - res = 0; - /* CLEAR_FLAG(m,F_CF);*/ - CONDITIONAL_SET_FLAG((s == 16) && (d & 1), m, F_CF); /* Peter Schorn bug fix */ - CLEAR_FLAG(m,F_OF); - SET_FLAG(m,F_ZF); - CLEAR_FLAG(m,F_SF); - CLEAR_FLAG(m,F_PF); - } - return res & 0xffff; -} - -uint8 shr_byte(PC_ENV *m, 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, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - } - else - { - res = (uint8) d; - } - if (cnt == 1) - { - CONDITIONAL_SET_FLAG(xor_0x3_tab[(res>>6)&0x3], m, F_OF); - } - else - { - CLEAR_FLAG(m,F_OF); - } - } - else - { - res = 0; - /* CLEAR_FLAG(m,F_CF);*/ - CONDITIONAL_SET_FLAG((s == 8) && (d & 0x80), m, F_CF); /* Peter Schorn bug fix */ - CLEAR_FLAG(m,F_OF); - SET_FLAG(m,F_ZF); - CLEAR_FLAG(m,F_SF); - CLEAR_FLAG(m,F_PF); - } - return res & 0xff; -} - -uint16 shr_word(PC_ENV *m, uint16 d, uint16 s) -{ - uint32 cnt,res,cf,mask; - 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, m, F_CF); - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - } - else - { - res = d; - } - if (cnt == 1) - { - CONDITIONAL_SET_FLAG(xor_0x3_tab[(res>>14)&0x3], m, F_OF); - } - else - { - CLEAR_FLAG(m,F_OF); - } - } - else - { - res = 0; - /* CLEAR_FLAG(m,F_CF);*/ - CONDITIONAL_SET_FLAG((s == 16) && (d & 0x8000), m, F_CF); /* Peter Schorn bug fix */ - CLEAR_FLAG(m,F_OF); - SET_FLAG(m,F_ZF); - CLEAR_FLAG(m,F_SF); - CLEAR_FLAG(m,F_PF); - } - return res & 0xffff; -} - -/* XXXX ??? flags may be wrong??? */ -uint8 sar_byte(PC_ENV *m, 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, m, F_CF); - if (sf) - { - res |= ~mask; - } - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - CONDITIONAL_SET_FLAG(res & 0x80, m, F_SF); - } - else if (cnt >= 8) - { - if (sf) - { - res = 0xff; - SET_FLAG(m,F_CF); - CLEAR_FLAG(m,F_ZF); - SET_FLAG(m, F_SF); - SET_FLAG(m, F_PF); - } - else - { - res = 0; - CLEAR_FLAG(m,F_CF); - SET_FLAG(m,F_ZF); - CLEAR_FLAG(m, F_SF); - CLEAR_FLAG(m, F_PF); - } - } - return res&0xff; -} - -uint16 sar_word(PC_ENV *m, 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, m, F_CF); - if (sf) - { - res |= ~mask; - } - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(res & 0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - } - else if (cnt >= 16) - { - if (sf) - { - res = 0xffff; - SET_FLAG(m,F_CF); - CLEAR_FLAG(m,F_ZF); - SET_FLAG(m, F_SF); - SET_FLAG(m, F_PF); - } - else - { - res = 0; - CLEAR_FLAG(m,F_CF); - SET_FLAG(m,F_ZF); - CLEAR_FLAG(m, F_SF); - CLEAR_FLAG(m, F_PF); - } - } - return res & 0xffff; -} - -uint8 sbb_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 bc; - if (ACCESS_FLAG(m,F_CF) ) - res = d - s - 1; - else - res = d - s; - CONDITIONAL_SET_FLAG(res&0x80, m, F_SF); - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - CONDITIONAL_SET_FLAG(bc&0x80,m, F_CF); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(bc>>6)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(bc&0x8, m, F_AF); - return res & 0xff; -} - -uint16 sbb_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 bc; - if (ACCESS_FLAG(m,F_CF)) - res = d - s - 1; - else - res = d - s; - CONDITIONAL_SET_FLAG(res&0x8000, m, F_SF); - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - CONDITIONAL_SET_FLAG(bc&0x8000,m, F_CF); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(bc>>14)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(bc&0x8, m, F_AF); - return res & 0xffff; -} - -uint8 sub_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 bc; - res = d - s; - CONDITIONAL_SET_FLAG(res&0x80, m, F_SF); - CONDITIONAL_SET_FLAG((res&0xff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - CONDITIONAL_SET_FLAG(bc&0x80,m, F_CF); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(bc>>6)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(bc&0x8, m, F_AF); - return res & 0xff; -} - -uint16 sub_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint32 res; /* all operands in native machine order */ - register uint32 bc; - res = d - s; - CONDITIONAL_SET_FLAG(res&0x8000, m, F_SF); - CONDITIONAL_SET_FLAG((res&0xffff)==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* calculate the borrow chain. See note at top */ - bc= (res&(~d|s))|(~d&s); - CONDITIONAL_SET_FLAG(bc&0x8000,m, F_CF); - CONDITIONAL_SET_FLAG(xor_0x3_tab[(bc>>14)&0x3], m, F_OF); - CONDITIONAL_SET_FLAG(bc&0x8, m, F_AF); - return res & 0xffff; -} - -void test_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint32 res; /* all operands in native machine order */ - res = d & s; - CLEAR_FLAG(m, F_OF); - CONDITIONAL_SET_FLAG(res&0x80, m, F_SF); - CONDITIONAL_SET_FLAG(res==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* AF == dont care*/ - CLEAR_FLAG(m, F_CF); -} - -void test_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint32 res; /* all operands in native machine order */ - res = d & s; - CLEAR_FLAG(m, F_OF); - CONDITIONAL_SET_FLAG(res&0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(res==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - /* AF == dont care*/ - CLEAR_FLAG(m, F_CF); -} - -uint8 xor_byte(PC_ENV *m, uint8 d, uint8 s) -{ - register uint8 res; /* all operands in native machine order */ - res = d ^ s; - CLEAR_FLAG(m, F_OF); - CONDITIONAL_SET_FLAG(res&0x80, m, F_SF); - CONDITIONAL_SET_FLAG(res==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res], m, F_PF); - CLEAR_FLAG(m, F_CF); - return res; -} - -uint16 xor_word(PC_ENV *m, uint16 d, uint16 s) -{ - register uint16 res; /* all operands in native machine order */ - res = d ^ s; - /* set the carry flag to be bit 8 */ - CLEAR_FLAG(m, F_OF); - CONDITIONAL_SET_FLAG(res&0x8000, m, F_SF); - CONDITIONAL_SET_FLAG(res==0, m, F_ZF); - CONDITIONAL_SET_FLAG(parity_tab[res&0xff], m, F_PF); - CLEAR_FLAG(m, F_CF); - return res; -} - -void imul_byte(PC_ENV *m, uint8 s) -{ - int16 res = (int8)m->R_AL * (int8)s; - m->R_AX = res; - /* Undef --- Can't hurt */ - CONDITIONAL_SET_FLAG(res&0x8000,m,F_SF); - CONDITIONAL_SET_FLAG(res==0,m,F_ZF); - if (m->R_AH == 0 || m->R_AH == 0xff) - { - CLEAR_FLAG(m, F_CF); - CLEAR_FLAG(m, F_OF); - } - else - { - SET_FLAG(m, F_CF); - SET_FLAG(m, F_OF); - } -} - -void imul_word(PC_ENV *m, uint16 s) -{ - int32 res = (int16)m->R_AX * (int16)s; - m->R_AX = res & 0xffff; - m->R_DX = (res >> 16) & 0xffff; - /* Undef --- Can't hurt */ - CONDITIONAL_SET_FLAG(res&0x80000000,m,F_SF); - CONDITIONAL_SET_FLAG(res==0,m,F_ZF); - if (m->R_DX == 0 || m->R_DX == 0xffff) - { - CLEAR_FLAG(m, F_CF); - CLEAR_FLAG(m, F_OF); - } - else - { - SET_FLAG(m, F_CF); - SET_FLAG(m, F_OF); - } -} - -void mul_byte(PC_ENV *m, uint8 s) -{ - uint16 res = m->R_AL * s; - m->R_AX = res; - /* Undef --- Can't hurt */ - CLEAR_FLAG(m,F_SF); - CONDITIONAL_SET_FLAG(res==0,m,F_ZF); - if (m->R_AH == 0) - { - CLEAR_FLAG(m, F_CF); - CLEAR_FLAG(m, F_OF); - } - else - { - SET_FLAG(m, F_CF); - SET_FLAG(m, F_OF); - } -} - -void mul_word(PC_ENV *m, uint16 s) -{ - uint32 res = m->R_AX * s; - /* Undef --- Can't hurt */ - CLEAR_FLAG(m,F_SF); - CONDITIONAL_SET_FLAG(res==0,m,F_ZF); - m->R_AX = res & 0xffff; - m->R_DX = (res >> 16) & 0xffff; - if (m->R_DX == 0) - { - CLEAR_FLAG(m, F_CF); - CLEAR_FLAG(m, F_OF); - } - else - { - SET_FLAG(m, F_CF); - SET_FLAG(m, F_OF); - } -} - -void idiv_byte(PC_ENV *m, uint8 s) -{ - int32 dvd,div,mod; - dvd = (int16)m->R_AX; - if (s == 0) - { - i86_intr_raise(m,0); - return; - } - div = dvd / (int8)s; - mod = dvd % (int8)s; - if (abs(div) > 0x7f) - { - i86_intr_raise(m,0); - return; - } - /* Undef --- Can't hurt */ - CONDITIONAL_SET_FLAG(div&0x80,m,F_SF); - CONDITIONAL_SET_FLAG(div==0,m,F_ZF); - m->R_AL = (int8)div; - m->R_AH = (int8)mod; -} - -void idiv_word(PC_ENV *m, uint16 s) -{ - int32 dvd,dvs,div,mod; - dvd = m->R_DX; - dvd = (dvd << 16) | m->R_AX; - if (s == 0) - { - i86_intr_raise(m,0); - return; - } - dvs = (int16)s; - div = dvd / dvs; - mod = dvd % dvs; - if (abs(div) > 0x7fff) - { - i86_intr_raise(m,0); - return; - } - /* Undef --- Can't hurt */ - CONDITIONAL_SET_FLAG(div&0x8000,m,F_SF); - CONDITIONAL_SET_FLAG(div==0,m,F_ZF); -/* debug_printf(m, "\n%d/%d=%d,%d\n",dvd,dvs,div,mod); */ - m->R_AX = div; - m->R_DX = mod; -} - -void div_byte(PC_ENV *m, uint8 s) -{ - uint32 dvd,dvs,div,mod; - dvs = s; - dvd = m->R_AX; - if (s == 0) - { - i86_intr_raise(m,0); - return; - } - div = dvd / dvs; - mod = dvd % dvs; - if (abs(div) > 0xff) - { - i86_intr_raise(m,0); - return; - } - /* Undef --- Can't hurt */ - CLEAR_FLAG(m,F_SF); - CONDITIONAL_SET_FLAG(div==0,m,F_ZF); - m->R_AL = (uint8)div; - m->R_AH = (uint8)mod; -} - -void div_word(PC_ENV *m, uint16 s) -{ - uint32 dvd,dvs,div,mod; - dvd = m->R_DX; - dvd = (dvd << 16) | m->R_AX; - dvs = s; - if (dvs == 0) - { - i86_intr_raise(m,0); - return; - } - div = dvd / dvs; - mod = dvd % dvs; -/* printf("dvd=%x dvs=%x -> div=%x mod=%x\n",dvd, dvs,div, mod);*/ - if (abs(div) > 0xffff) - { - i86_intr_raise(m,0); - return; - } - /* Undef --- Can't hurt */ - CLEAR_FLAG(m,F_SF); - CONDITIONAL_SET_FLAG(div==0,m,F_ZF); - m->R_AX = div; - m->R_DX = mod; -} diff --git a/AltairZ80/insns.h b/AltairZ80/insns.h deleted file mode 100644 index 43548f3f..00000000 --- a/AltairZ80/insns.h +++ /dev/null @@ -1,661 +0,0 @@ -/* insns.h header file for insns.c - * $Id: insns.h,v 1.1 2004/02/11 19:01:38 perrin Exp $ - * - * The Netwide Assembler is copyright (C) 1996 Simon Tatham and - * Julian Hall. All rights reserved. The software is - * redistributable under the licence given in the file "Licence" - * distributed in the NASM archive. - */ - -#ifndef NASM_INSNS_H -#define NASM_INSNS_H - -/* This file is auto-generated from insns.dat by insns.pl - don't edit it */ - -/* This file in included by nasm.h */ - -/* Instruction names */ -enum { - I_AAA, - I_AAD, - I_AAM, - I_AAS, - I_ADC, - I_ADD, - I_ADDPD, - I_ADDPS, - I_ADDSD, - I_ADDSS, - I_ADDSUBPD, - I_ADDSUBPS, - I_AND, - I_ANDNPD, - I_ANDNPS, - I_ANDPD, - I_ANDPS, - I_ARPL, - I_BOUND, - I_BSF, - I_BSR, - I_BSWAP, - I_BT, - I_BTC, - I_BTR, - I_BTS, - I_CALL, - I_CBW, - I_CDQ, - I_CLC, - I_CLD, - I_CLFLUSH, - I_CLI, - I_CLTS, - I_CMC, - I_CMP, - I_CMPEQPD, - I_CMPEQPS, - I_CMPEQSD, - I_CMPEQSS, - I_CMPLEPD, - I_CMPLEPS, - I_CMPLESD, - I_CMPLESS, - I_CMPLTPD, - I_CMPLTPS, - I_CMPLTSD, - I_CMPLTSS, - I_CMPNEQPD, - I_CMPNEQPS, - I_CMPNEQSD, - I_CMPNEQSS, - I_CMPNLEPD, - I_CMPNLEPS, - I_CMPNLESD, - I_CMPNLESS, - I_CMPNLTPD, - I_CMPNLTPS, - I_CMPNLTSD, - I_CMPNLTSS, - I_CMPORDPD, - I_CMPORDPS, - I_CMPORDSD, - I_CMPORDSS, - I_CMPPD, - I_CMPPS, - I_CMPSB, - I_CMPSD, - I_CMPSS, - I_CMPSW, - I_CMPUNORDPD, - I_CMPUNORDPS, - I_CMPUNORDSD, - I_CMPUNORDSS, - I_CMPXCHG, - I_CMPXCHG486, - I_CMPXCHG8B, - I_COMISD, - I_COMISS, - I_CPUID, - I_CVTDQ2PD, - I_CVTDQ2PS, - I_CVTPD2DQ, - I_CVTPD2PI, - I_CVTPD2PS, - I_CVTPI2PD, - I_CVTPI2PS, - I_CVTPS2DQ, - I_CVTPS2PD, - I_CVTPS2PI, - I_CVTSD2SI, - I_CVTSD2SS, - I_CVTSI2SD, - I_CVTSI2SS, - I_CVTSS2SD, - I_CVTSS2SI, - I_CVTTPD2DQ, - I_CVTTPD2PI, - I_CVTTPS2DQ, - I_CVTTPS2PI, - I_CVTTSD2SI, - I_CVTTSS2SI, - I_CWD, - I_CWDE, - I_DAA, - I_DAS, - I_DB, - I_DD, - I_DEC, - I_DIV, - I_DIVPD, - I_DIVPS, - I_DIVSD, - I_DIVSS, - I_DQ, - I_DT, - I_DW, - I_EMMS, - I_ENTER, - I_EQU, - I_F2XM1, - I_FABS, - I_FADD, - I_FADDP, - I_FBLD, - I_FBSTP, - I_FCHS, - I_FCLEX, - I_FCMOVB, - I_FCMOVBE, - I_FCMOVE, - I_FCMOVNB, - I_FCMOVNBE, - I_FCMOVNE, - I_FCMOVNU, - I_FCMOVU, - I_FCOM, - I_FCOMI, - I_FCOMIP, - I_FCOMP, - I_FCOMPP, - I_FCOS, - I_FDECSTP, - I_FDISI, - I_FDIV, - I_FDIVP, - I_FDIVR, - I_FDIVRP, - I_FEMMS, - I_FENI, - I_FFREE, - I_FFREEP, - I_FIADD, - I_FICOM, - I_FICOMP, - I_FIDIV, - I_FIDIVR, - I_FILD, - I_FIMUL, - I_FINCSTP, - I_FINIT, - I_FIST, - I_FISTP, - I_FISTTP, - I_FISUB, - I_FISUBR, - I_FLD, - I_FLD1, - I_FLDCW, - I_FLDENV, - I_FLDL2E, - I_FLDL2T, - I_FLDLG2, - I_FLDLN2, - I_FLDPI, - I_FLDZ, - I_FMUL, - I_FMULP, - I_FNCLEX, - I_FNDISI, - I_FNENI, - I_FNINIT, - I_FNOP, - I_FNSAVE, - I_FNSTCW, - I_FNSTENV, - I_FNSTSW, - I_FPATAN, - I_FPREM, - I_FPREM1, - I_FPTAN, - I_FRNDINT, - I_FRSTOR, - I_FSAVE, - I_FSCALE, - I_FSETPM, - I_FSIN, - I_FSINCOS, - I_FSQRT, - I_FST, - I_FSTCW, - I_FSTENV, - I_FSTP, - I_FSTSW, - I_FSUB, - I_FSUBP, - I_FSUBR, - I_FSUBRP, - I_FTST, - I_FUCOM, - I_FUCOMI, - I_FUCOMIP, - I_FUCOMP, - I_FUCOMPP, - I_FWAIT, - I_FXAM, - I_FXCH, - I_FXRSTOR, - I_FXSAVE, - I_FXTRACT, - I_FYL2X, - I_FYL2XP1, - I_HADDPD, - I_HADDPS, - I_HLT, - I_HSUBPD, - I_HSUBPS, - I_IBTS, - I_ICEBP, - I_IDIV, - I_IMUL, - I_IN, - I_INC, - I_INCBIN, - I_INSB, - I_INSD, - I_INSW, - I_INT, - I_INT01, - I_INT03, - I_INT1, - I_INT3, - I_INTO, - I_INVD, - I_INVLPG, - I_IRET, - I_IRETD, - I_IRETW, - I_JCXZ, - I_JECXZ, - I_JMP, - I_JMPE, - I_LAHF, - I_LAR, - I_LDDQU, - I_LDMXCSR, - I_LDS, - I_LEA, - I_LEAVE, - I_LES, - I_LFENCE, - I_LFS, - I_LGDT, - I_LGS, - I_LIDT, - I_LLDT, - I_LMSW, - I_LOADALL, - I_LOADALL286, - I_LODSB, - I_LODSD, - I_LODSW, - I_LOOP, - I_LOOPE, - I_LOOPNE, - I_LOOPNZ, - I_LOOPZ, - I_LSL, - I_LSS, - I_LTR, - I_MASKMOVDQU, - I_MASKMOVQ, - I_MAXPD, - I_MAXPS, - I_MAXSD, - I_MAXSS, - I_MFENCE, - I_MINPD, - I_MINPS, - I_MINSD, - I_MINSS, - I_MONITOR, - I_MOV, - I_MOVAPD, - I_MOVAPS, - I_MOVD, - I_MOVDDUP, - I_MOVDQ2Q, - I_MOVDQA, - I_MOVDQU, - I_MOVHLPS, - I_MOVHPD, - I_MOVHPS, - I_MOVLHPS, - I_MOVLPD, - I_MOVLPS, - I_MOVMSKPD, - I_MOVMSKPS, - I_MOVNTDQ, - I_MOVNTI, - I_MOVNTPD, - I_MOVNTPS, - I_MOVNTQ, - I_MOVQ, - I_MOVQ2DQ, - I_MOVSB, - I_MOVSD, - I_MOVSHDUP, - I_MOVSLDUP, - I_MOVSS, - I_MOVSW, - I_MOVSX, - I_MOVUPD, - I_MOVUPS, - I_MOVZX, - I_MUL, - I_MULPD, - I_MULPS, - I_MULSD, - I_MULSS, - I_MWAIT, - I_NEG, - I_NOP, - I_NOT, - I_OR, - I_ORPD, - I_ORPS, - I_OUT, - I_OUTSB, - I_OUTSD, - I_OUTSW, - I_PACKSSDW, - I_PACKSSWB, - I_PACKUSWB, - I_PADDB, - I_PADDD, - I_PADDQ, - I_PADDSB, - I_PADDSIW, - I_PADDSW, - I_PADDUSB, - I_PADDUSW, - I_PADDW, - I_PAND, - I_PANDN, - I_PAUSE, - I_PAVEB, - I_PAVGB, - I_PAVGUSB, - I_PAVGW, - I_PCMPEQB, - I_PCMPEQD, - I_PCMPEQW, - I_PCMPGTB, - I_PCMPGTD, - I_PCMPGTW, - I_PDISTIB, - I_PEXTRW, - I_PF2ID, - I_PF2IW, - I_PFACC, - I_PFADD, - I_PFCMPEQ, - I_PFCMPGE, - I_PFCMPGT, - I_PFMAX, - I_PFMIN, - I_PFMUL, - I_PFNACC, - I_PFPNACC, - I_PFRCP, - I_PFRCPIT1, - I_PFRCPIT2, - I_PFRSQIT1, - I_PFRSQRT, - I_PFSUB, - I_PFSUBR, - I_PI2FD, - I_PI2FW, - I_PINSRW, - I_PMACHRIW, - I_PMADDWD, - I_PMAGW, - I_PMAXSW, - I_PMAXUB, - I_PMINSW, - I_PMINUB, - I_PMOVMSKB, - I_PMULHRIW, - I_PMULHRWA, - I_PMULHRWC, - I_PMULHUW, - I_PMULHW, - I_PMULLW, - I_PMULUDQ, - I_PMVGEZB, - I_PMVLZB, - I_PMVNZB, - I_PMVZB, - I_POP, - I_POPA, - I_POPAD, - I_POPAW, - I_POPF, - I_POPFD, - I_POPFW, - I_POR, - I_PREFETCH, - I_PREFETCHNTA, - I_PREFETCHT0, - I_PREFETCHT1, - I_PREFETCHT2, - I_PREFETCHW, - I_PSADBW, - I_PSHUFD, - I_PSHUFHW, - I_PSHUFLW, - I_PSHUFW, - I_PSLLD, - I_PSLLDQ, - I_PSLLQ, - I_PSLLW, - I_PSRAD, - I_PSRAW, - I_PSRLD, - I_PSRLDQ, - I_PSRLQ, - I_PSRLW, - I_PSUBB, - I_PSUBD, - I_PSUBQ, - I_PSUBSB, - I_PSUBSIW, - I_PSUBSW, - I_PSUBUSB, - I_PSUBUSW, - I_PSUBW, - I_PSWAPD, - I_PUNPCKHBW, - I_PUNPCKHDQ, - I_PUNPCKHQDQ, - I_PUNPCKHWD, - I_PUNPCKLBW, - I_PUNPCKLDQ, - I_PUNPCKLQDQ, - I_PUNPCKLWD, - I_PUSH, - I_PUSHA, - I_PUSHAD, - I_PUSHAW, - I_PUSHF, - I_PUSHFD, - I_PUSHFW, - I_PXOR, - I_RCL, - I_RCPPS, - I_RCPSS, - I_RCR, - I_RDMSR, - I_RDPMC, - I_RDSHR, - I_RDTSC, - I_RESB, - I_RESD, - I_RESQ, - I_REST, - I_RESW, - I_RET, - I_RETF, - I_RETN, - I_ROL, - I_ROR, - I_RSDC, - I_RSLDT, - I_RSM, - I_RSQRTPS, - I_RSQRTSS, - I_RSTS, - I_SAHF, - I_SAL, - I_SALC, - I_SAR, - I_SBB, - I_SCASB, - I_SCASD, - I_SCASW, - I_SFENCE, - I_SGDT, - I_SHL, - I_SHLD, - I_SHR, - I_SHRD, - I_SHUFPD, - I_SHUFPS, - I_SIDT, - I_SLDT, - I_SMI, - I_SMINT, - I_SMINTOLD, - I_SMSW, - I_SQRTPD, - I_SQRTPS, - I_SQRTSD, - I_SQRTSS, - I_STC, - I_STD, - I_STI, - I_STMXCSR, - I_STOSB, - I_STOSD, - I_STOSW, - I_STR, - I_SUB, - I_SUBPD, - I_SUBPS, - I_SUBSD, - I_SUBSS, - I_SVDC, - I_SVLDT, - I_SVTS, - I_SYSCALL, - I_SYSENTER, - I_SYSEXIT, - I_SYSRET, - I_TEST, - I_UCOMISD, - I_UCOMISS, - I_UD0, - I_UD1, - I_UD2, - I_UMOV, - I_UNPCKHPD, - I_UNPCKHPS, - I_UNPCKLPD, - I_UNPCKLPS, - I_VERR, - I_VERW, - I_WAIT, - I_WBINVD, - I_WRMSR, - I_WRSHR, - I_XADD, - I_XBTS, - I_XCHG, - I_XLAT, - I_XLATB, - I_XOR, - I_XORPD, - I_XORPS, - I_XSTORE, - I_CMOVcc, - I_Jcc, - I_SETcc -}; - -struct itemplate { - int opcode; /* the token, passed from "parser.c" */ - int operands; /* number of operands */ - long opd[3]; /* bit flags for operand types */ - const char *code; /* the code it assembles to */ - unsigned long flags; /* some flags */ -}; - -/* - * this define is used to signify the end of an itemplate - */ -#define ITEMPLATE_END {-1,-1,{-1,-1,-1},NULL,0} - -/* - * Instruction template flags. These specify which processor - * targets the instruction is eligible for, whether it is - * privileged or undocumented, and also specify extra error - * checking on the matching of the instruction. - * - * IF_SM stands for Size Match: any operand whose size is not - * explicitly specified by the template is `really' intended to be - * the same size as the first size-specified operand. - * Non-specification is tolerated in the input instruction, but - * _wrong_ specification is not. - * - * IF_SM2 invokes Size Match on only the first _two_ operands, for - * three-operand instructions such as SHLD: it implies that the - * first two operands must match in size, but that the third is - * required to be _unspecified_. - * - * IF_SB invokes Size Byte: operands with unspecified size in the - * template are really bytes, and so no non-byte specification in - * the input instruction will be tolerated. IF_SW similarly invokes - * Size Word, and IF_SD invokes Size Doubleword. - * - * (The default state if neither IF_SM nor IF_SM2 is specified is - * that any operand with unspecified size in the template is - * required to have unspecified size in the instruction too...) - */ - -#define IF_SM 0x00000001UL /* size match */ -#define IF_SM2 0x00000002UL /* size match first two operands */ -#define IF_SB 0x00000004UL /* unsized operands can't be non-byte */ -#define IF_SW 0x00000008UL /* unsized operands can't be non-word */ -#define IF_SD 0x00000010UL /* unsized operands can't be nondword */ -#define IF_AR0 0x00000020UL /* SB, SW, SD applies to argument 0 */ -#define IF_AR1 0x00000040UL /* SB, SW, SD applies to argument 1 */ -#define IF_AR2 0x00000060UL /* SB, SW, SD applies to argument 2 */ -#define IF_ARMASK 0x00000060UL /* mask for unsized argument spec */ -#define IF_PRIV 0x00000100UL /* it's a privileged instruction */ -#define IF_SMM 0x00000200UL /* it's only valid in SMM */ -#define IF_PROT 0x00000400UL /* it's protected mode only */ -#define IF_UNDOC 0x00001000UL /* it's an undocumented instruction */ -#define IF_FPU 0x00002000UL /* it's an FPU instruction */ -#define IF_MMX 0x00004000UL /* it's an MMX instruction */ -#define IF_3DNOW 0x00008000UL /* it's a 3DNow! instruction */ -#define IF_SSE 0x00010000UL /* it's a SSE (KNI, MMX2) instruction */ -#define IF_SSE2 0x00020000UL /* it's a SSE2 instruction */ -#define IF_SSE3 0x00040000UL /* it's a SSE3 (PNI) instruction */ -#define IF_PMASK 0xFF000000UL /* the mask for processor types */ -#define IF_PLEVEL 0x0F000000UL /* the mask for processor instr. level */ - /* also the highest possible processor */ -#define IF_PFMASK 0xF001FF00UL /* the mask for disassembly "prefer" */ -#define IF_8086 0x00000000UL /* 8086 instruction */ -#define IF_186 0x01000000UL /* 186+ instruction */ -#define IF_286 0x02000000UL /* 286+ instruction */ -#define IF_386 0x03000000UL /* 386+ instruction */ -#define IF_486 0x04000000UL /* 486+ instruction */ -#define IF_PENT 0x05000000UL /* Pentium instruction */ -#define IF_P6 0x06000000UL /* P6 instruction */ -#define IF_KATMAI 0x07000000UL /* Katmai instructions */ -#define IF_WILLAMETTE 0x08000000UL /* Willamette instructions */ -#define IF_PRESCOTT 0x09000000UL /* Prescott instructions */ -#define IF_IA64 0x0F000000UL /* IA64 instructions */ -#define IF_CYRIX 0x10000000UL /* Cyrix-specific instruction */ -#define IF_AMD 0x20000000UL /* AMD-specific instruction */ - -#endif diff --git a/AltairZ80/insnsd.c b/AltairZ80/insnsd.c deleted file mode 100644 index 1037a369..00000000 --- a/AltairZ80/insnsd.c +++ /dev/null @@ -1,4550 +0,0 @@ -/* This file auto-generated from insns.dat by insns.pl - don't edit it */ - -#include "nasm.h" -#include "insns.h" - -static struct itemplate instrux[] = { - /* 0*/ {I_AAA, 0, {0,0,0}, "\1\x37", IF_8086}, - /* 1*/ {I_AAD, 0, {0,0,0}, "\2\xD5\x0A", IF_8086}, - /* 2*/ {I_AAD, 1, {IMMEDIATE,0,0}, "\1\xD5\24", IF_8086|IF_SB}, - /* 3*/ {I_AAM, 0, {0,0,0}, "\2\xD4\x0A", IF_8086}, - /* 4*/ {I_AAM, 1, {IMMEDIATE,0,0}, "\1\xD4\24", IF_8086|IF_SB}, - /* 5*/ {I_AAS, 0, {0,0,0}, "\1\x3F", IF_8086}, - /* 6*/ {I_ADC, 2, {MEMORY,REG8,0}, "\300\1\x10\101", IF_8086|IF_SM}, - /* 7*/ {I_ADC, 2, {REG8,REG8,0}, "\1\x10\101", IF_8086}, - /* 8*/ {I_ADC, 2, {MEMORY,REG16,0}, "\320\300\1\x11\101", IF_8086|IF_SM}, - /* 9*/ {I_ADC, 2, {REG16,REG16,0}, "\320\1\x11\101", IF_8086}, - /* 10*/ {I_ADC, 2, {MEMORY,REG32,0}, "\321\300\1\x11\101", IF_386|IF_SM}, - /* 11*/ {I_ADC, 2, {REG32,REG32,0}, "\321\1\x11\101", IF_386}, - /* 12*/ {I_ADC, 2, {REG8,MEMORY,0}, "\301\1\x12\110", IF_8086|IF_SM}, - /* 13*/ {I_ADC, 2, {REG8,REG8,0}, "\1\x12\110", IF_8086}, - /* 14*/ {I_ADC, 2, {REG16,MEMORY,0}, "\320\301\1\x13\110", IF_8086|IF_SM}, - /* 15*/ {I_ADC, 2, {REG16,REG16,0}, "\320\1\x13\110", IF_8086}, - /* 16*/ {I_ADC, 2, {REG32,MEMORY,0}, "\321\301\1\x13\110", IF_386|IF_SM}, - /* 17*/ {I_ADC, 2, {REG32,REG32,0}, "\321\1\x13\110", IF_386}, - /* 18*/ {I_ADC, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\202\15", IF_8086}, - /* 19*/ {I_ADC, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\202\15", IF_386}, - /* 20*/ {I_ADC, 2, {REG_AL,IMMEDIATE,0}, "\1\x14\21", IF_8086|IF_SM}, - /* 21*/ {I_ADC, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x15\31", IF_8086|IF_SM}, - /* 22*/ {I_ADC, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x15\41", IF_386|IF_SM}, - /* 23*/ {I_ADC, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\202\21", IF_8086|IF_SM}, - /* 24*/ {I_ADC, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\202\131", IF_8086|IF_SM}, - /* 25*/ {I_ADC, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\202\141", IF_386|IF_SM}, - /* 26*/ {I_ADC, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\202\21", IF_8086|IF_SM}, - /* 27*/ {I_ADC, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\202\131", IF_8086|IF_SM}, - /* 28*/ {I_ADC, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\202\141", IF_386|IF_SM}, - /* 29*/ {I_ADD, 2, {MEMORY,REG8,0}, "\300\17\101", IF_8086|IF_SM}, - /* 30*/ {I_ADD, 2, {REG8,REG8,0}, "\17\101", IF_8086}, - /* 31*/ {I_ADD, 2, {MEMORY,REG16,0}, "\320\300\1\x01\101", IF_8086|IF_SM}, - /* 32*/ {I_ADD, 2, {REG16,REG16,0}, "\320\1\x01\101", IF_8086}, - /* 33*/ {I_ADD, 2, {MEMORY,REG32,0}, "\321\300\1\x01\101", IF_386|IF_SM}, - /* 34*/ {I_ADD, 2, {REG32,REG32,0}, "\321\1\x01\101", IF_386}, - /* 35*/ {I_ADD, 2, {REG8,MEMORY,0}, "\301\1\x02\110", IF_8086|IF_SM}, - /* 36*/ {I_ADD, 2, {REG8,REG8,0}, "\1\x02\110", IF_8086}, - /* 37*/ {I_ADD, 2, {REG16,MEMORY,0}, "\320\301\1\x03\110", IF_8086|IF_SM}, - /* 38*/ {I_ADD, 2, {REG16,REG16,0}, "\320\1\x03\110", IF_8086}, - /* 39*/ {I_ADD, 2, {REG32,MEMORY,0}, "\321\301\1\x03\110", IF_386|IF_SM}, - /* 40*/ {I_ADD, 2, {REG32,REG32,0}, "\321\1\x03\110", IF_386}, - /* 41*/ {I_ADD, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\200\15", IF_8086}, - /* 42*/ {I_ADD, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\200\15", IF_386}, - /* 43*/ {I_ADD, 2, {REG_AL,IMMEDIATE,0}, "\1\x04\21", IF_8086|IF_SM}, - /* 44*/ {I_ADD, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x05\31", IF_8086|IF_SM}, - /* 45*/ {I_ADD, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x05\41", IF_386|IF_SM}, - /* 46*/ {I_ADD, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\200\21", IF_8086|IF_SM}, - /* 47*/ {I_ADD, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\200\131", IF_8086|IF_SM}, - /* 48*/ {I_ADD, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\200\141", IF_386|IF_SM}, - /* 49*/ {I_ADD, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\200\21", IF_8086|IF_SM}, - /* 50*/ {I_ADD, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\200\131", IF_8086|IF_SM}, - /* 51*/ {I_ADD, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\200\141", IF_386|IF_SM}, - /* 52*/ {I_AND, 2, {MEMORY,REG8,0}, "\300\1\x20\101", IF_8086|IF_SM}, - /* 53*/ {I_AND, 2, {REG8,REG8,0}, "\1\x20\101", IF_8086}, - /* 54*/ {I_AND, 2, {MEMORY,REG16,0}, "\320\300\1\x21\101", IF_8086|IF_SM}, - /* 55*/ {I_AND, 2, {REG16,REG16,0}, "\320\1\x21\101", IF_8086}, - /* 56*/ {I_AND, 2, {MEMORY,REG32,0}, "\321\300\1\x21\101", IF_386|IF_SM}, - /* 57*/ {I_AND, 2, {REG32,REG32,0}, "\321\1\x21\101", IF_386}, - /* 58*/ {I_AND, 2, {REG8,MEMORY,0}, "\301\1\x22\110", IF_8086|IF_SM}, - /* 59*/ {I_AND, 2, {REG8,REG8,0}, "\1\x22\110", IF_8086}, - /* 60*/ {I_AND, 2, {REG16,MEMORY,0}, "\320\301\1\x23\110", IF_8086|IF_SM}, - /* 61*/ {I_AND, 2, {REG16,REG16,0}, "\320\1\x23\110", IF_8086}, - /* 62*/ {I_AND, 2, {REG32,MEMORY,0}, "\321\301\1\x23\110", IF_386|IF_SM}, - /* 63*/ {I_AND, 2, {REG32,REG32,0}, "\321\1\x23\110", IF_386}, - /* 64*/ {I_AND, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\204\15", IF_8086}, - /* 65*/ {I_AND, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\204\15", IF_386}, - /* 66*/ {I_AND, 2, {REG_AL,IMMEDIATE,0}, "\1\x24\21", IF_8086|IF_SM}, - /* 67*/ {I_AND, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x25\31", IF_8086|IF_SM}, - /* 68*/ {I_AND, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x25\41", IF_386|IF_SM}, - /* 69*/ {I_AND, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\204\21", IF_8086|IF_SM}, - /* 70*/ {I_AND, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\204\131", IF_8086|IF_SM}, - /* 71*/ {I_AND, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\204\141", IF_386|IF_SM}, - /* 72*/ {I_AND, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\204\21", IF_8086|IF_SM}, - /* 73*/ {I_AND, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\204\131", IF_8086|IF_SM}, - /* 74*/ {I_AND, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\204\141", IF_386|IF_SM}, - /* 75*/ {I_ARPL, 2, {MEMORY,REG16,0}, "\300\1\x63\101", IF_286|IF_PROT|IF_SM}, - /* 76*/ {I_ARPL, 2, {REG16,REG16,0}, "\1\x63\101", IF_286|IF_PROT}, - /* 77*/ {I_BOUND, 2, {REG16,MEMORY,0}, "\320\301\1\x62\110", IF_186}, - /* 78*/ {I_BOUND, 2, {REG32,MEMORY,0}, "\321\301\1\x62\110", IF_386}, - /* 79*/ {I_BSF, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xBC\110", IF_386|IF_SM}, - /* 80*/ {I_BSF, 2, {REG16,REG16,0}, "\320\2\x0F\xBC\110", IF_386}, - /* 81*/ {I_BSF, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xBC\110", IF_386|IF_SM}, - /* 82*/ {I_BSF, 2, {REG32,REG32,0}, "\321\2\x0F\xBC\110", IF_386}, - /* 83*/ {I_BSR, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xBD\110", IF_386|IF_SM}, - /* 84*/ {I_BSR, 2, {REG16,REG16,0}, "\320\2\x0F\xBD\110", IF_386}, - /* 85*/ {I_BSR, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xBD\110", IF_386|IF_SM}, - /* 86*/ {I_BSR, 2, {REG32,REG32,0}, "\321\2\x0F\xBD\110", IF_386}, - /* 87*/ {I_BSWAP, 1, {REG32,0,0}, "\321\1\x0F\10\xC8", IF_486}, - /* 88*/ {I_BT, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xA3\101", IF_386|IF_SM}, - /* 89*/ {I_BT, 2, {REG16,REG16,0}, "\320\2\x0F\xA3\101", IF_386}, - /* 90*/ {I_BT, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xA3\101", IF_386|IF_SM}, - /* 91*/ {I_BT, 2, {REG32,REG32,0}, "\321\2\x0F\xA3\101", IF_386}, - /* 92*/ {I_BT, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\204\25", IF_386|IF_SB}, - /* 93*/ {I_BT, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\204\25", IF_386|IF_SB}, - /* 94*/ {I_BTC, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xBB\101", IF_386|IF_SM}, - /* 95*/ {I_BTC, 2, {REG16,REG16,0}, "\320\2\x0F\xBB\101", IF_386}, - /* 96*/ {I_BTC, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xBB\101", IF_386|IF_SM}, - /* 97*/ {I_BTC, 2, {REG32,REG32,0}, "\321\2\x0F\xBB\101", IF_386}, - /* 98*/ {I_BTC, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\207\25", IF_386|IF_SB}, - /* 99*/ {I_BTC, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\207\25", IF_386|IF_SB}, - /* 100*/ {I_BTR, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xB3\101", IF_386|IF_SM}, - /* 101*/ {I_BTR, 2, {REG16,REG16,0}, "\320\2\x0F\xB3\101", IF_386}, - /* 102*/ {I_BTR, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xB3\101", IF_386|IF_SM}, - /* 103*/ {I_BTR, 2, {REG32,REG32,0}, "\321\2\x0F\xB3\101", IF_386}, - /* 104*/ {I_BTR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\206\25", IF_386|IF_SB}, - /* 105*/ {I_BTR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\206\25", IF_386|IF_SB}, - /* 106*/ {I_BTS, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xAB\101", IF_386|IF_SM}, - /* 107*/ {I_BTS, 2, {REG16,REG16,0}, "\320\2\x0F\xAB\101", IF_386}, - /* 108*/ {I_BTS, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xAB\101", IF_386|IF_SM}, - /* 109*/ {I_BTS, 2, {REG32,REG32,0}, "\321\2\x0F\xAB\101", IF_386}, - /* 110*/ {I_BTS, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\2\x0F\xBA\205\25", IF_386|IF_SB}, - /* 111*/ {I_BTS, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\2\x0F\xBA\205\25", IF_386|IF_SB}, - /* 112*/ {I_CALL, 1, {IMMEDIATE,0,0}, "\322\1\xE8\64", IF_8086}, - /* 113*/ {I_CALL, 1, {IMMEDIATE|NEAR,0,0}, "\322\1\xE8\64", IF_8086}, - /* 114*/ {I_CALL, 1, {IMMEDIATE|BITS16,0,0}, "\320\1\xE8\64", IF_8086}, - /* 115*/ {I_CALL, 1, {IMMEDIATE|BITS16|NEAR,0,0}, "\320\1\xE8\64", IF_8086}, - /* 116*/ {I_CALL, 1, {IMMEDIATE|BITS32,0,0}, "\321\1\xE8\64", IF_386}, - /* 117*/ {I_CALL, 1, {IMMEDIATE|BITS32|NEAR,0,0}, "\321\1\xE8\64", IF_386}, - /* 118*/ {I_CALL, 2, {IMMEDIATE|COLON,IMMEDIATE,0}, "\322\1\x9A\35\30", IF_8086}, - /* 119*/ {I_CALL, 2, {IMMEDIATE|BITS16|COLON,IMMEDIATE,0}, "\320\1\x9A\31\30", IF_8086}, - /* 120*/ {I_CALL, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS16,0}, "\320\1\x9A\31\30", IF_8086}, - /* 121*/ {I_CALL, 2, {IMMEDIATE|BITS32|COLON,IMMEDIATE,0}, "\321\1\x9A\41\30", IF_386}, - /* 122*/ {I_CALL, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS32,0}, "\321\1\x9A\41\30", IF_386}, - /* 123*/ {I_CALL, 1, {MEMORY|FAR,0,0}, "\322\300\1\xFF\203", IF_8086}, - /* 124*/ {I_CALL, 1, {MEMORY|BITS16|FAR,0,0}, "\320\300\1\xFF\203", IF_8086}, - /* 125*/ {I_CALL, 1, {MEMORY|BITS32|FAR,0,0}, "\321\300\1\xFF\203", IF_386}, - /* 126*/ {I_CALL, 1, {MEMORY|NEAR,0,0}, "\322\300\1\xFF\202", IF_8086}, - /* 127*/ {I_CALL, 1, {MEMORY|BITS16|NEAR,0,0}, "\320\300\1\xFF\202", IF_8086}, - /* 128*/ {I_CALL, 1, {MEMORY|BITS32|NEAR,0,0}, "\321\300\1\xFF\202", IF_386}, - /* 129*/ {I_CALL, 1, {REG16,0,0}, "\320\300\1\xFF\202", IF_8086}, - /* 130*/ {I_CALL, 1, {REG32,0,0}, "\321\300\1\xFF\202", IF_386}, - /* 131*/ {I_CALL, 1, {MEMORY,0,0}, "\322\300\1\xFF\202", IF_8086}, - /* 132*/ {I_CALL, 1, {MEMORY|BITS16,0,0}, "\320\300\1\xFF\202", IF_8086}, - /* 133*/ {I_CALL, 1, {MEMORY|BITS32,0,0}, "\321\300\1\xFF\202", IF_386}, - /* 134*/ {I_CBW, 0, {0,0,0}, "\320\1\x98", IF_8086}, - /* 135*/ {I_CDQ, 0, {0,0,0}, "\321\1\x99", IF_386}, - /* 136*/ {I_CLC, 0, {0,0,0}, "\1\xF8", IF_8086}, - /* 137*/ {I_CLD, 0, {0,0,0}, "\1\xFC", IF_8086}, - /* 138*/ {I_CLI, 0, {0,0,0}, "\1\xFA", IF_8086}, - /* 139*/ {I_CLTS, 0, {0,0,0}, "\2\x0F\x06", IF_286|IF_PRIV}, - /* 140*/ {I_CMC, 0, {0,0,0}, "\1\xF5", IF_8086}, - /* 141*/ {I_CMP, 2, {MEMORY,REG8,0}, "\300\1\x38\101", IF_8086|IF_SM}, - /* 142*/ {I_CMP, 2, {REG8,REG8,0}, "\1\x38\101", IF_8086}, - /* 143*/ {I_CMP, 2, {MEMORY,REG16,0}, "\320\300\1\x39\101", IF_8086|IF_SM}, - /* 144*/ {I_CMP, 2, {REG16,REG16,0}, "\320\1\x39\101", IF_8086}, - /* 145*/ {I_CMP, 2, {MEMORY,REG32,0}, "\321\300\1\x39\101", IF_386|IF_SM}, - /* 146*/ {I_CMP, 2, {REG32,REG32,0}, "\321\1\x39\101", IF_386}, - /* 147*/ {I_CMP, 2, {REG8,MEMORY,0}, "\301\1\x3A\110", IF_8086|IF_SM}, - /* 148*/ {I_CMP, 2, {REG8,REG8,0}, "\1\x3A\110", IF_8086}, - /* 149*/ {I_CMP, 2, {REG16,MEMORY,0}, "\320\301\1\x3B\110", IF_8086|IF_SM}, - /* 150*/ {I_CMP, 2, {REG16,REG16,0}, "\320\1\x3B\110", IF_8086}, - /* 151*/ {I_CMP, 2, {REG32,MEMORY,0}, "\321\301\1\x3B\110", IF_386|IF_SM}, - /* 152*/ {I_CMP, 2, {REG32,REG32,0}, "\321\1\x3B\110", IF_386}, - /* 153*/ {I_CMP, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\207\15", IF_8086}, - /* 154*/ {I_CMP, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\207\15", IF_386}, - /* 155*/ {I_CMP, 2, {REG_AL,IMMEDIATE,0}, "\1\x3C\21", IF_8086|IF_SM}, - /* 156*/ {I_CMP, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x3D\31", IF_8086|IF_SM}, - /* 157*/ {I_CMP, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x3D\41", IF_386|IF_SM}, - /* 158*/ {I_CMP, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\207\21", IF_8086|IF_SM}, - /* 159*/ {I_CMP, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\207\131", IF_8086|IF_SM}, - /* 160*/ {I_CMP, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\207\141", IF_386|IF_SM}, - /* 161*/ {I_CMP, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\207\21", IF_8086|IF_SM}, - /* 162*/ {I_CMP, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\207\131", IF_8086|IF_SM}, - /* 163*/ {I_CMP, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\207\141", IF_386|IF_SM}, - /* 164*/ {I_CMPSB, 0, {0,0,0}, "\332\1\xA6", IF_8086}, - /* 165*/ {I_CMPSD, 0, {0,0,0}, "\332\321\1\xA7", IF_386}, - /* 166*/ {I_CMPSW, 0, {0,0,0}, "\332\320\1\xA7", IF_8086}, - /* 167*/ {I_CMPXCHG, 2, {MEMORY,REG8,0}, "\300\2\x0F\xB0\101", IF_PENT|IF_SM}, - /* 168*/ {I_CMPXCHG, 2, {REG8,REG8,0}, "\2\x0F\xB0\101", IF_PENT}, - /* 169*/ {I_CMPXCHG, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xB1\101", IF_PENT|IF_SM}, - /* 170*/ {I_CMPXCHG, 2, {REG16,REG16,0}, "\320\2\x0F\xB1\101", IF_PENT}, - /* 171*/ {I_CMPXCHG, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xB1\101", IF_PENT|IF_SM}, - /* 172*/ {I_CMPXCHG, 2, {REG32,REG32,0}, "\321\2\x0F\xB1\101", IF_PENT}, - /* 173*/ {I_CMPXCHG486, 2, {MEMORY,REG8,0}, "\300\2\x0F\xA6\101", IF_486|IF_SM|IF_UNDOC}, - /* 174*/ {I_CMPXCHG486, 2, {REG8,REG8,0}, "\2\x0F\xA6\101", IF_486|IF_UNDOC}, - /* 175*/ {I_CMPXCHG486, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xA7\101", IF_486|IF_SM|IF_UNDOC}, - /* 176*/ {I_CMPXCHG486, 2, {REG16,REG16,0}, "\320\2\x0F\xA7\101", IF_486|IF_UNDOC}, - /* 177*/ {I_CMPXCHG486, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xA7\101", IF_486|IF_SM|IF_UNDOC}, - /* 178*/ {I_CMPXCHG486, 2, {REG32,REG32,0}, "\321\2\x0F\xA7\101", IF_486|IF_UNDOC}, - /* 179*/ {I_CMPXCHG8B, 1, {MEMORY,0,0}, "\300\2\x0F\xC7\201", IF_PENT}, - /* 180*/ {I_CPUID, 0, {0,0,0}, "\2\x0F\xA2", IF_PENT}, - /* 181*/ {I_CWD, 0, {0,0,0}, "\320\1\x99", IF_8086}, - /* 182*/ {I_CWDE, 0, {0,0,0}, "\321\1\x98", IF_386}, - /* 183*/ {I_DAA, 0, {0,0,0}, "\1\x27", IF_8086}, - /* 184*/ {I_DAS, 0, {0,0,0}, "\1\x2F", IF_8086}, - /* 185*/ {I_DEC, 1, {REG16,0,0}, "\320\10\x48", IF_8086}, - /* 186*/ {I_DEC, 1, {REG32,0,0}, "\321\10\x48", IF_386}, - /* 187*/ {I_DEC, 1, {REGMEM|BITS8,0,0}, "\300\1\xFE\201", IF_8086}, - /* 188*/ {I_DEC, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xFF\201", IF_8086}, - /* 189*/ {I_DEC, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xFF\201", IF_386}, - /* 190*/ {I_DIV, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\206", IF_8086}, - /* 191*/ {I_DIV, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\206", IF_8086}, - /* 192*/ {I_DIV, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\206", IF_386}, - /* 193*/ {I_EMMS, 0, {0,0,0}, "\2\x0F\x77", IF_PENT|IF_MMX}, - /* 194*/ {I_ENTER, 2, {IMMEDIATE,IMMEDIATE,0}, "\1\xC8\30\25", IF_186}, - /* 195*/ {I_EQU, 1, {IMMEDIATE,0,0}, "\0", IF_8086}, - /* 196*/ {I_EQU, 2, {IMMEDIATE|COLON,IMMEDIATE,0}, "\0", IF_8086}, - /* 197*/ {I_F2XM1, 0, {0,0,0}, "\2\xD9\xF0", IF_8086|IF_FPU}, - /* 198*/ {I_FABS, 0, {0,0,0}, "\2\xD9\xE1", IF_8086|IF_FPU}, - /* 199*/ {I_FADD, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\200", IF_8086|IF_FPU}, - /* 200*/ {I_FADD, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\200", IF_8086|IF_FPU}, - /* 201*/ {I_FADD, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xC0", IF_8086|IF_FPU}, - /* 202*/ {I_FADD, 1, {FPUREG,0,0}, "\1\xD8\10\xC0", IF_8086|IF_FPU}, - /* 203*/ {I_FADD, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xC0", IF_8086|IF_FPU}, - /* 204*/ {I_FADD, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xC0", IF_8086|IF_FPU}, - /* 205*/ {I_FADDP, 1, {FPUREG,0,0}, "\1\xDE\10\xC0", IF_8086|IF_FPU}, - /* 206*/ {I_FADDP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xC0", IF_8086|IF_FPU}, - /* 207*/ {I_FBLD, 1, {MEMORY|BITS80,0,0}, "\300\1\xDF\204", IF_8086|IF_FPU}, - /* 208*/ {I_FBLD, 1, {MEMORY,0,0}, "\300\1\xDF\204", IF_8086|IF_FPU}, - /* 209*/ {I_FBSTP, 1, {MEMORY|BITS80,0,0}, "\300\1\xDF\206", IF_8086|IF_FPU}, - /* 210*/ {I_FBSTP, 1, {MEMORY,0,0}, "\300\1\xDF\206", IF_8086|IF_FPU}, - /* 211*/ {I_FCHS, 0, {0,0,0}, "\2\xD9\xE0", IF_8086|IF_FPU}, - /* 212*/ {I_FCLEX, 0, {0,0,0}, "\3\x9B\xDB\xE2", IF_8086|IF_FPU}, - /* 213*/ {I_FCMOVB, 1, {FPUREG,0,0}, "\1\xDA\10\xC0", IF_P6|IF_FPU}, - /* 214*/ {I_FCMOVB, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xC0", IF_P6|IF_FPU}, - /* 215*/ {I_FCMOVBE, 1, {FPUREG,0,0}, "\1\xDA\10\xD0", IF_P6|IF_FPU}, - /* 216*/ {I_FCMOVBE, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xD0", IF_P6|IF_FPU}, - /* 217*/ {I_FCMOVE, 1, {FPUREG,0,0}, "\1\xDA\10\xC8", IF_P6|IF_FPU}, - /* 218*/ {I_FCMOVE, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xC8", IF_P6|IF_FPU}, - /* 219*/ {I_FCMOVNB, 1, {FPUREG,0,0}, "\1\xDB\10\xC0", IF_P6|IF_FPU}, - /* 220*/ {I_FCMOVNB, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xC0", IF_P6|IF_FPU}, - /* 221*/ {I_FCMOVNBE, 1, {FPUREG,0,0}, "\1\xDB\10\xD0", IF_P6|IF_FPU}, - /* 222*/ {I_FCMOVNBE, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xD0", IF_P6|IF_FPU}, - /* 223*/ {I_FCMOVNE, 1, {FPUREG,0,0}, "\1\xDB\10\xC8", IF_P6|IF_FPU}, - /* 224*/ {I_FCMOVNE, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xC8", IF_P6|IF_FPU}, - /* 225*/ {I_FCMOVNU, 1, {FPUREG,0,0}, "\1\xDB\10\xD8", IF_P6|IF_FPU}, - /* 226*/ {I_FCMOVNU, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xD8", IF_P6|IF_FPU}, - /* 227*/ {I_FCMOVU, 1, {FPUREG,0,0}, "\1\xDA\10\xD8", IF_P6|IF_FPU}, - /* 228*/ {I_FCMOVU, 2, {FPU0,FPUREG,0}, "\1\xDA\11\xD8", IF_P6|IF_FPU}, - /* 229*/ {I_FCOM, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\202", IF_8086|IF_FPU}, - /* 230*/ {I_FCOM, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\202", IF_8086|IF_FPU}, - /* 231*/ {I_FCOM, 1, {FPUREG,0,0}, "\1\xD8\10\xD0", IF_8086|IF_FPU}, - /* 232*/ {I_FCOM, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xD0", IF_8086|IF_FPU}, - /* 233*/ {I_FCOMI, 1, {FPUREG,0,0}, "\1\xDB\10\xF0", IF_P6|IF_FPU}, - /* 234*/ {I_FCOMI, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xF0", IF_P6|IF_FPU}, - /* 235*/ {I_FCOMIP, 1, {FPUREG,0,0}, "\1\xDF\10\xF0", IF_P6|IF_FPU}, - /* 236*/ {I_FCOMIP, 2, {FPU0,FPUREG,0}, "\1\xDF\11\xF0", IF_P6|IF_FPU}, - /* 237*/ {I_FCOMP, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\203", IF_8086|IF_FPU}, - /* 238*/ {I_FCOMP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\203", IF_8086|IF_FPU}, - /* 239*/ {I_FCOMP, 1, {FPUREG,0,0}, "\1\xD8\10\xD8", IF_8086|IF_FPU}, - /* 240*/ {I_FCOMP, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xD8", IF_8086|IF_FPU}, - /* 241*/ {I_FCOMPP, 0, {0,0,0}, "\2\xDE\xD9", IF_8086|IF_FPU}, - /* 242*/ {I_FCOS, 0, {0,0,0}, "\2\xD9\xFF", IF_386|IF_FPU}, - /* 243*/ {I_FDECSTP, 0, {0,0,0}, "\2\xD9\xF6", IF_8086|IF_FPU}, - /* 244*/ {I_FDISI, 0, {0,0,0}, "\3\x9B\xDB\xE1", IF_8086|IF_FPU}, - /* 245*/ {I_FDIV, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\206", IF_8086|IF_FPU}, - /* 246*/ {I_FDIV, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\206", IF_8086|IF_FPU}, - /* 247*/ {I_FDIV, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xF8", IF_8086|IF_FPU}, - /* 248*/ {I_FDIV, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xF8", IF_8086|IF_FPU}, - /* 249*/ {I_FDIV, 1, {FPUREG,0,0}, "\1\xD8\10\xF0", IF_8086|IF_FPU}, - /* 250*/ {I_FDIV, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xF0", IF_8086|IF_FPU}, - /* 251*/ {I_FDIVP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xF8", IF_8086|IF_FPU}, - /* 252*/ {I_FDIVP, 1, {FPUREG,0,0}, "\1\xDE\10\xF8", IF_8086|IF_FPU}, - /* 253*/ {I_FDIVR, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\207", IF_8086|IF_FPU}, - /* 254*/ {I_FDIVR, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\207", IF_8086|IF_FPU}, - /* 255*/ {I_FDIVR, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xF0", IF_8086|IF_FPU}, - /* 256*/ {I_FDIVR, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xF0", IF_8086|IF_FPU}, - /* 257*/ {I_FDIVR, 1, {FPUREG,0,0}, "\1\xD8\10\xF8", IF_8086|IF_FPU}, - /* 258*/ {I_FDIVR, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xF8", IF_8086|IF_FPU}, - /* 259*/ {I_FDIVRP, 1, {FPUREG,0,0}, "\1\xDE\10\xF0", IF_8086|IF_FPU}, - /* 260*/ {I_FDIVRP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xF0", IF_8086|IF_FPU}, - /* 261*/ {I_FEMMS, 0, {0,0,0}, "\2\x0F\x0E", IF_PENT|IF_3DNOW}, - /* 262*/ {I_FENI, 0, {0,0,0}, "\3\x9B\xDB\xE0", IF_8086|IF_FPU}, - /* 263*/ {I_FFREE, 1, {FPUREG,0,0}, "\1\xDD\10\xC0", IF_8086|IF_FPU}, - /* 264*/ {I_FFREEP, 1, {FPUREG,0,0}, "\1\xDF\10\xC0", IF_286|IF_FPU|IF_UNDOC}, - /* 265*/ {I_FIADD, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\200", IF_8086|IF_FPU}, - /* 266*/ {I_FIADD, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\200", IF_8086|IF_FPU}, - /* 267*/ {I_FICOM, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\202", IF_8086|IF_FPU}, - /* 268*/ {I_FICOM, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\202", IF_8086|IF_FPU}, - /* 269*/ {I_FICOMP, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\203", IF_8086|IF_FPU}, - /* 270*/ {I_FICOMP, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\203", IF_8086|IF_FPU}, - /* 271*/ {I_FIDIV, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\206", IF_8086|IF_FPU}, - /* 272*/ {I_FIDIV, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\206", IF_8086|IF_FPU}, - /* 273*/ {I_FIDIVR, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\207", IF_8086|IF_FPU}, - /* 274*/ {I_FIDIVR, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\207", IF_8086|IF_FPU}, - /* 275*/ {I_FILD, 1, {MEMORY|BITS32,0,0}, "\300\1\xDB\200", IF_8086|IF_FPU}, - /* 276*/ {I_FILD, 1, {MEMORY|BITS16,0,0}, "\300\1\xDF\200", IF_8086|IF_FPU}, - /* 277*/ {I_FILD, 1, {MEMORY|BITS64,0,0}, "\300\1\xDF\205", IF_8086|IF_FPU}, - /* 278*/ {I_FIMUL, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\201", IF_8086|IF_FPU}, - /* 279*/ {I_FIMUL, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\201", IF_8086|IF_FPU}, - /* 280*/ {I_FINCSTP, 0, {0,0,0}, "\2\xD9\xF7", IF_8086|IF_FPU}, - /* 281*/ {I_FINIT, 0, {0,0,0}, "\3\x9B\xDB\xE3", IF_8086|IF_FPU}, - /* 282*/ {I_FIST, 1, {MEMORY|BITS32,0,0}, "\300\1\xDB\202", IF_8086|IF_FPU}, - /* 283*/ {I_FIST, 1, {MEMORY|BITS16,0,0}, "\300\1\xDF\202", IF_8086|IF_FPU}, - /* 284*/ {I_FISTP, 1, {MEMORY|BITS32,0,0}, "\300\1\xDB\203", IF_8086|IF_FPU}, - /* 285*/ {I_FISTP, 1, {MEMORY|BITS16,0,0}, "\300\1\xDF\203", IF_8086|IF_FPU}, - /* 286*/ {I_FISTP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDF\207", IF_8086|IF_FPU}, - /* 287*/ {I_FISTTP, 1, {MEMORY|BITS32,0,0}, "\300\1\xDD\201", IF_PRESCOTT|IF_FPU}, - /* 288*/ {I_FISTTP, 1, {MEMORY|BITS16,0,0}, "\300\1\xDB\201", IF_PRESCOTT|IF_FPU}, - /* 289*/ {I_FISTTP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDF\201", IF_PRESCOTT|IF_FPU}, - /* 290*/ {I_FISUB, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\204", IF_8086|IF_FPU}, - /* 291*/ {I_FISUB, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\204", IF_8086|IF_FPU}, - /* 292*/ {I_FISUBR, 1, {MEMORY|BITS32,0,0}, "\300\1\xDA\205", IF_8086|IF_FPU}, - /* 293*/ {I_FISUBR, 1, {MEMORY|BITS16,0,0}, "\300\1\xDE\205", IF_8086|IF_FPU}, - /* 294*/ {I_FLD, 1, {MEMORY|BITS32,0,0}, "\300\1\xD9\200", IF_8086|IF_FPU}, - /* 295*/ {I_FLD, 1, {MEMORY|BITS64,0,0}, "\300\1\xDD\200", IF_8086|IF_FPU}, - /* 296*/ {I_FLD, 1, {MEMORY|BITS80,0,0}, "\300\1\xDB\205", IF_8086|IF_FPU}, - /* 297*/ {I_FLD, 1, {FPUREG,0,0}, "\1\xD9\10\xC0", IF_8086|IF_FPU}, - /* 298*/ {I_FLD1, 0, {0,0,0}, "\2\xD9\xE8", IF_8086|IF_FPU}, - /* 299*/ {I_FLDCW, 1, {MEMORY,0,0}, "\300\1\xD9\205", IF_8086|IF_FPU|IF_SW}, - /* 300*/ {I_FLDENV, 1, {MEMORY,0,0}, "\300\1\xD9\204", IF_8086|IF_FPU}, - /* 301*/ {I_FLDL2E, 0, {0,0,0}, "\2\xD9\xEA", IF_8086|IF_FPU}, - /* 302*/ {I_FLDL2T, 0, {0,0,0}, "\2\xD9\xE9", IF_8086|IF_FPU}, - /* 303*/ {I_FLDLG2, 0, {0,0,0}, "\2\xD9\xEC", IF_8086|IF_FPU}, - /* 304*/ {I_FLDLN2, 0, {0,0,0}, "\2\xD9\xED", IF_8086|IF_FPU}, - /* 305*/ {I_FLDPI, 0, {0,0,0}, "\2\xD9\xEB", IF_8086|IF_FPU}, - /* 306*/ {I_FLDZ, 0, {0,0,0}, "\2\xD9\xEE", IF_8086|IF_FPU}, - /* 307*/ {I_FMUL, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\201", IF_8086|IF_FPU}, - /* 308*/ {I_FMUL, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\201", IF_8086|IF_FPU}, - /* 309*/ {I_FMUL, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xC8", IF_8086|IF_FPU}, - /* 310*/ {I_FMUL, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xC8", IF_8086|IF_FPU}, - /* 311*/ {I_FMUL, 1, {FPUREG,0,0}, "\1\xD8\10\xC8", IF_8086|IF_FPU}, - /* 312*/ {I_FMUL, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xC8", IF_8086|IF_FPU}, - /* 313*/ {I_FMULP, 1, {FPUREG,0,0}, "\1\xDE\10\xC8", IF_8086|IF_FPU}, - /* 314*/ {I_FMULP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xC8", IF_8086|IF_FPU}, - /* 315*/ {I_FNCLEX, 0, {0,0,0}, "\2\xDB\xE2", IF_8086|IF_FPU}, - /* 316*/ {I_FNDISI, 0, {0,0,0}, "\2\xDB\xE1", IF_8086|IF_FPU}, - /* 317*/ {I_FNENI, 0, {0,0,0}, "\2\xDB\xE0", IF_8086|IF_FPU}, - /* 318*/ {I_FNINIT, 0, {0,0,0}, "\2\xDB\xE3", IF_8086|IF_FPU}, - /* 319*/ {I_FNOP, 0, {0,0,0}, "\2\xD9\xD0", IF_8086|IF_FPU}, - /* 320*/ {I_FNSAVE, 1, {MEMORY,0,0}, "\300\1\xDD\206", IF_8086|IF_FPU}, - /* 321*/ {I_FNSTCW, 1, {MEMORY,0,0}, "\300\1\xD9\207", IF_8086|IF_FPU|IF_SW}, - /* 322*/ {I_FNSTENV, 1, {MEMORY,0,0}, "\300\1\xD9\206", IF_8086|IF_FPU}, - /* 323*/ {I_FNSTSW, 1, {MEMORY,0,0}, "\300\1\xDD\207", IF_8086|IF_FPU|IF_SW}, - /* 324*/ {I_FNSTSW, 1, {REG_AX,0,0}, "\2\xDF\xE0", IF_286|IF_FPU}, - /* 325*/ {I_FPATAN, 0, {0,0,0}, "\2\xD9\xF3", IF_8086|IF_FPU}, - /* 326*/ {I_FPREM, 0, {0,0,0}, "\2\xD9\xF8", IF_8086|IF_FPU}, - /* 327*/ {I_FPREM1, 0, {0,0,0}, "\2\xD9\xF5", IF_386|IF_FPU}, - /* 328*/ {I_FPTAN, 0, {0,0,0}, "\2\xD9\xF2", IF_8086|IF_FPU}, - /* 329*/ {I_FRNDINT, 0, {0,0,0}, "\2\xD9\xFC", IF_8086|IF_FPU}, - /* 330*/ {I_FRSTOR, 1, {MEMORY,0,0}, "\300\1\xDD\204", IF_8086|IF_FPU}, - /* 331*/ {I_FSAVE, 1, {MEMORY,0,0}, "\300\2\x9B\xDD\206", IF_8086|IF_FPU}, - /* 332*/ {I_FSCALE, 0, {0,0,0}, "\2\xD9\xFD", IF_8086|IF_FPU}, - /* 333*/ {I_FSETPM, 0, {0,0,0}, "\2\xDB\xE4", IF_286|IF_FPU}, - /* 334*/ {I_FSIN, 0, {0,0,0}, "\2\xD9\xFE", IF_386|IF_FPU}, - /* 335*/ {I_FSINCOS, 0, {0,0,0}, "\2\xD9\xFB", IF_386|IF_FPU}, - /* 336*/ {I_FSQRT, 0, {0,0,0}, "\2\xD9\xFA", IF_8086|IF_FPU}, - /* 337*/ {I_FST, 1, {MEMORY|BITS32,0,0}, "\300\1\xD9\202", IF_8086|IF_FPU}, - /* 338*/ {I_FST, 1, {MEMORY|BITS64,0,0}, "\300\1\xDD\202", IF_8086|IF_FPU}, - /* 339*/ {I_FST, 1, {FPUREG,0,0}, "\1\xDD\10\xD0", IF_8086|IF_FPU}, - /* 340*/ {I_FSTCW, 1, {MEMORY,0,0}, "\300\2\x9B\xD9\207", IF_8086|IF_FPU|IF_SW}, - /* 341*/ {I_FSTENV, 1, {MEMORY,0,0}, "\300\2\x9B\xD9\206", IF_8086|IF_FPU}, - /* 342*/ {I_FSTP, 1, {MEMORY|BITS32,0,0}, "\300\1\xD9\203", IF_8086|IF_FPU}, - /* 343*/ {I_FSTP, 1, {MEMORY|BITS64,0,0}, "\300\1\xDD\203", IF_8086|IF_FPU}, - /* 344*/ {I_FSTP, 1, {MEMORY|BITS80,0,0}, "\300\1\xDB\207", IF_8086|IF_FPU}, - /* 345*/ {I_FSTP, 1, {FPUREG,0,0}, "\1\xDD\10\xD8", IF_8086|IF_FPU}, - /* 346*/ {I_FSTSW, 1, {MEMORY,0,0}, "\300\2\x9B\xDD\207", IF_8086|IF_FPU|IF_SW}, - /* 347*/ {I_FSTSW, 1, {REG_AX,0,0}, "\3\x9B\xDF\xE0", IF_286|IF_FPU}, - /* 348*/ {I_FSUB, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\204", IF_8086|IF_FPU}, - /* 349*/ {I_FSUB, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\204", IF_8086|IF_FPU}, - /* 350*/ {I_FSUB, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xE8", IF_8086|IF_FPU}, - /* 351*/ {I_FSUB, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xE8", IF_8086|IF_FPU}, - /* 352*/ {I_FSUB, 1, {FPUREG,0,0}, "\1\xD8\10\xE0", IF_8086|IF_FPU}, - /* 353*/ {I_FSUB, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xE0", IF_8086|IF_FPU}, - /* 354*/ {I_FSUBP, 1, {FPUREG,0,0}, "\1\xDE\10\xE8", IF_8086|IF_FPU}, - /* 355*/ {I_FSUBP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xE8", IF_8086|IF_FPU}, - /* 356*/ {I_FSUBR, 1, {MEMORY|BITS32,0,0}, "\300\1\xD8\205", IF_8086|IF_FPU}, - /* 357*/ {I_FSUBR, 1, {MEMORY|BITS64,0,0}, "\300\1\xDC\205", IF_8086|IF_FPU}, - /* 358*/ {I_FSUBR, 1, {FPUREG|TO,0,0}, "\1\xDC\10\xE0", IF_8086|IF_FPU}, - /* 359*/ {I_FSUBR, 2, {FPUREG,FPU0,0}, "\1\xDC\10\xE0", IF_8086|IF_FPU}, - /* 360*/ {I_FSUBR, 1, {FPUREG,0,0}, "\1\xD8\10\xE8", IF_8086|IF_FPU}, - /* 361*/ {I_FSUBR, 2, {FPU0,FPUREG,0}, "\1\xD8\11\xE8", IF_8086|IF_FPU}, - /* 362*/ {I_FSUBRP, 1, {FPUREG,0,0}, "\1\xDE\10\xE0", IF_8086|IF_FPU}, - /* 363*/ {I_FSUBRP, 2, {FPUREG,FPU0,0}, "\1\xDE\10\xE0", IF_8086|IF_FPU}, - /* 364*/ {I_FTST, 0, {0,0,0}, "\2\xD9\xE4", IF_8086|IF_FPU}, - /* 365*/ {I_FUCOM, 1, {FPUREG,0,0}, "\1\xDD\10\xE0", IF_386|IF_FPU}, - /* 366*/ {I_FUCOM, 2, {FPU0,FPUREG,0}, "\1\xDD\11\xE0", IF_386|IF_FPU}, - /* 367*/ {I_FUCOMI, 1, {FPUREG,0,0}, "\1\xDB\10\xE8", IF_P6|IF_FPU}, - /* 368*/ {I_FUCOMI, 2, {FPU0,FPUREG,0}, "\1\xDB\11\xE8", IF_P6|IF_FPU}, - /* 369*/ {I_FUCOMIP, 1, {FPUREG,0,0}, "\1\xDF\10\xE8", IF_P6|IF_FPU}, - /* 370*/ {I_FUCOMIP, 2, {FPU0,FPUREG,0}, "\1\xDF\11\xE8", IF_P6|IF_FPU}, - /* 371*/ {I_FUCOMP, 1, {FPUREG,0,0}, "\1\xDD\10\xE8", IF_386|IF_FPU}, - /* 372*/ {I_FUCOMP, 2, {FPU0,FPUREG,0}, "\1\xDD\11\xE8", IF_386|IF_FPU}, - /* 373*/ {I_FUCOMPP, 0, {0,0,0}, "\2\xDA\xE9", IF_386|IF_FPU}, - /* 374*/ {I_FXAM, 0, {0,0,0}, "\2\xD9\xE5", IF_8086|IF_FPU}, - /* 375*/ {I_FXCH, 0, {0,0,0}, "\2\xD9\xC9", IF_8086|IF_FPU}, - /* 376*/ {I_FXCH, 1, {FPUREG,0,0}, "\1\xD9\10\xC8", IF_8086|IF_FPU}, - /* 377*/ {I_FXCH, 2, {FPUREG,FPU0,0}, "\1\xD9\10\xC8", IF_8086|IF_FPU}, - /* 378*/ {I_FXCH, 2, {FPU0,FPUREG,0}, "\1\xD9\11\xC8", IF_8086|IF_FPU}, - /* 379*/ {I_FXTRACT, 0, {0,0,0}, "\2\xD9\xF4", IF_8086|IF_FPU}, - /* 380*/ {I_FYL2X, 0, {0,0,0}, "\2\xD9\xF1", IF_8086|IF_FPU}, - /* 381*/ {I_FYL2XP1, 0, {0,0,0}, "\2\xD9\xF9", IF_8086|IF_FPU}, - /* 382*/ {I_HLT, 0, {0,0,0}, "\1\xF4", IF_8086|IF_PRIV}, - /* 383*/ {I_IDIV, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\207", IF_8086}, - /* 384*/ {I_IDIV, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\207", IF_8086}, - /* 385*/ {I_IDIV, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\207", IF_386}, - /* 386*/ {I_IMUL, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\205", IF_8086}, - /* 387*/ {I_IMUL, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\205", IF_8086}, - /* 388*/ {I_IMUL, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\205", IF_386}, - /* 389*/ {I_IMUL, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xAF\110", IF_386|IF_SM}, - /* 390*/ {I_IMUL, 2, {REG16,REG16,0}, "\320\2\x0F\xAF\110", IF_386}, - /* 391*/ {I_IMUL, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xAF\110", IF_386|IF_SM}, - /* 392*/ {I_IMUL, 2, {REG32,REG32,0}, "\321\2\x0F\xAF\110", IF_386}, - /* 393*/ {I_IMUL, 3, {REG16,MEMORY,IMMEDIATE|BITS8}, "\320\301\1\x6B\110\16", IF_186|IF_SM}, - /* 394*/ {I_IMUL, 3, {REG16,MEMORY,IMMEDIATE|BITS16}, "\320\301\1\x69\110\32", IF_186|IF_SM}, - /* 395*/ {I_IMUL, 3, {REG16,REG16,IMMEDIATE|BITS8}, "\320\1\x6B\110\16", IF_186}, - /* 396*/ {I_IMUL, 3, {REG16,REG16,IMMEDIATE|BITS16}, "\320\1\x69\110\32", IF_186}, - /* 397*/ {I_IMUL, 3, {REG32,MEMORY,IMMEDIATE|BITS8}, "\321\301\1\x6B\110\16", IF_386|IF_SM}, - /* 398*/ {I_IMUL, 3, {REG32,MEMORY,IMMEDIATE|BITS32}, "\321\301\1\x69\110\42", IF_386|IF_SM}, - /* 399*/ {I_IMUL, 3, {REG32,REG32,IMMEDIATE|BITS8}, "\321\1\x6B\110\16", IF_386}, - /* 400*/ {I_IMUL, 3, {REG32,REG32,IMMEDIATE|BITS32}, "\321\1\x69\110\42", IF_386}, - /* 401*/ {I_IMUL, 2, {REG16,IMMEDIATE|BITS8,0}, "\320\1\x6B\100\15", IF_186}, - /* 402*/ {I_IMUL, 2, {REG16,IMMEDIATE|BITS16,0}, "\320\1\x69\100\31", IF_186}, - /* 403*/ {I_IMUL, 2, {REG32,IMMEDIATE|BITS8,0}, "\321\1\x6B\100\15", IF_386}, - /* 404*/ {I_IMUL, 2, {REG32,IMMEDIATE|BITS32,0}, "\321\1\x69\100\41", IF_386}, - /* 405*/ {I_IN, 2, {REG_AL,IMMEDIATE,0}, "\1\xE4\25", IF_8086|IF_SB}, - /* 406*/ {I_IN, 2, {REG_AX,IMMEDIATE,0}, "\320\1\xE5\25", IF_8086|IF_SB}, - /* 407*/ {I_IN, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\xE5\25", IF_386|IF_SB}, - /* 408*/ {I_IN, 2, {REG_AL,REG_DX,0}, "\1\xEC", IF_8086}, - /* 409*/ {I_IN, 2, {REG_AX,REG_DX,0}, "\320\1\xED", IF_8086}, - /* 410*/ {I_IN, 2, {REG_EAX,REG_DX,0}, "\321\1\xED", IF_386}, - /* 411*/ {I_INC, 1, {REG16,0,0}, "\320\10\x40", IF_8086}, - /* 412*/ {I_INC, 1, {REG32,0,0}, "\321\10\x40", IF_386}, - /* 413*/ {I_INC, 1, {REGMEM|BITS8,0,0}, "\300\1\xFE\200", IF_8086}, - /* 414*/ {I_INC, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xFF\200", IF_8086}, - /* 415*/ {I_INC, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xFF\200", IF_386}, - /* 416*/ {I_INSB, 0, {0,0,0}, "\1\x6C", IF_186}, - /* 417*/ {I_INSD, 0, {0,0,0}, "\321\1\x6D", IF_386}, - /* 418*/ {I_INSW, 0, {0,0,0}, "\320\1\x6D", IF_186}, - /* 419*/ {I_INT, 1, {IMMEDIATE,0,0}, "\1\xCD\24", IF_8086|IF_SB}, - /* 420*/ {I_INT1, 0, {0,0,0}, "\1\xF1", IF_386}, - /* 421*/ {I_INT3, 0, {0,0,0}, "\1\xCC", IF_8086}, - /* 422*/ {I_INTO, 0, {0,0,0}, "\1\xCE", IF_8086}, - /* 423*/ {I_INVD, 0, {0,0,0}, "\2\x0F\x08", IF_486|IF_PRIV}, - /* 424*/ {I_INVLPG, 1, {MEMORY,0,0}, "\300\2\x0F\x01\207", IF_486|IF_PRIV}, - /* 425*/ {I_IRET, 0, {0,0,0}, "\322\1\xCF", IF_8086}, - /* 426*/ {I_IRETD, 0, {0,0,0}, "\321\1\xCF", IF_386}, - /* 427*/ {I_IRETW, 0, {0,0,0}, "\320\1\xCF", IF_8086}, - /* 428*/ {I_JCXZ, 1, {IMMEDIATE,0,0}, "\310\1\xE3\50", IF_8086}, - /* 429*/ {I_JECXZ, 1, {IMMEDIATE,0,0}, "\311\1\xE3\50", IF_386}, - /* 430*/ {I_JMP, 1, {IMMEDIATE|SHORT,0,0}, "\1\xEB\50", IF_8086}, - /* 431*/ {I_JMP, 1, {IMMEDIATE,0,0}, "\322\1\xE9\64", IF_8086}, - /* 432*/ {I_JMP, 1, {IMMEDIATE|BITS16,0,0}, "\320\1\xE9\64", IF_8086}, - /* 433*/ {I_JMP, 1, {IMMEDIATE|BITS32,0,0}, "\321\1\xE9\64", IF_386}, - /* 434*/ {I_JMP, 2, {IMMEDIATE|COLON,IMMEDIATE,0}, "\322\1\xEA\35\30", IF_8086}, - /* 435*/ {I_JMP, 2, {IMMEDIATE|BITS16|COLON,IMMEDIATE,0}, "\320\1\xEA\31\30", IF_8086}, - /* 436*/ {I_JMP, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS16,0}, "\320\1\xEA\31\30", IF_8086}, - /* 437*/ {I_JMP, 2, {IMMEDIATE|BITS32|COLON,IMMEDIATE,0}, "\321\1\xEA\41\30", IF_386}, - /* 438*/ {I_JMP, 2, {IMMEDIATE|COLON,IMMEDIATE|BITS32,0}, "\321\1\xEA\41\30", IF_386}, - /* 439*/ {I_JMP, 1, {MEMORY|FAR,0,0}, "\322\300\1\xFF\205", IF_8086}, - /* 440*/ {I_JMP, 1, {MEMORY|BITS16|FAR,0,0}, "\320\300\1\xFF\205", IF_8086}, - /* 441*/ {I_JMP, 1, {MEMORY|BITS32|FAR,0,0}, "\321\300\1\xFF\205", IF_386}, - /* 442*/ {I_JMP, 1, {MEMORY|NEAR,0,0}, "\322\300\1\xFF\204", IF_8086}, - /* 443*/ {I_JMP, 1, {MEMORY|BITS16|NEAR,0,0}, "\320\300\1\xFF\204", IF_8086}, - /* 444*/ {I_JMP, 1, {MEMORY|BITS32|NEAR,0,0}, "\321\300\1\xFF\204", IF_386}, - /* 445*/ {I_JMP, 1, {REG16,0,0}, "\320\300\1\xFF\204", IF_8086}, - /* 446*/ {I_JMP, 1, {REG32,0,0}, "\321\300\1\xFF\204", IF_386}, - /* 447*/ {I_JMP, 1, {MEMORY,0,0}, "\322\300\1\xFF\204", IF_8086}, - /* 448*/ {I_JMP, 1, {MEMORY|BITS16,0,0}, "\320\300\1\xFF\204", IF_8086}, - /* 449*/ {I_JMP, 1, {MEMORY|BITS32,0,0}, "\321\300\1\xFF\204", IF_386}, - /* 450*/ {I_JMPE, 1, {IMMEDIATE,0,0}, "\322\2\x0F\xB8\64", IF_IA64}, - /* 451*/ {I_JMPE, 1, {IMMEDIATE|BITS16,0,0}, "\320\2\x0F\xB8\64", IF_IA64}, - /* 452*/ {I_JMPE, 1, {IMMEDIATE|BITS32,0,0}, "\321\2\x0F\xB8\64", IF_IA64}, - /* 453*/ {I_JMPE, 1, {REGMEM|BITS16,0,0}, "\320\2\x0F\x00\206", IF_IA64}, - /* 454*/ {I_JMPE, 1, {REGMEM|BITS32,0,0}, "\321\2\x0F\x00\206", IF_IA64}, - /* 455*/ {I_LAHF, 0, {0,0,0}, "\1\x9F", IF_8086}, - /* 456*/ {I_LAR, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\x02\110", IF_286|IF_PROT|IF_SM}, - /* 457*/ {I_LAR, 2, {REG16,REG16,0}, "\320\2\x0F\x02\110", IF_286|IF_PROT}, - /* 458*/ {I_LAR, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\x02\110", IF_386|IF_PROT|IF_SM}, - /* 459*/ {I_LAR, 2, {REG32,REG32,0}, "\321\2\x0F\x02\110", IF_386|IF_PROT}, - /* 460*/ {I_LDS, 2, {REG16,MEMORY,0}, "\320\301\1\xC5\110", IF_8086}, - /* 461*/ {I_LDS, 2, {REG32,MEMORY,0}, "\321\301\1\xC5\110", IF_386}, - /* 462*/ {I_LEA, 2, {REG16,MEMORY,0}, "\320\301\1\x8D\110", IF_8086}, - /* 463*/ {I_LEA, 2, {REG32,MEMORY,0}, "\321\301\1\x8D\110", IF_386}, - /* 464*/ {I_LEAVE, 0, {0,0,0}, "\1\xC9", IF_186}, - /* 465*/ {I_LES, 2, {REG16,MEMORY,0}, "\320\301\1\xC4\110", IF_8086}, - /* 466*/ {I_LES, 2, {REG32,MEMORY,0}, "\321\301\1\xC4\110", IF_386}, - /* 467*/ {I_LFS, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB4\110", IF_386}, - /* 468*/ {I_LFS, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xB4\110", IF_386}, - /* 469*/ {I_LGDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\202", IF_286|IF_PRIV}, - /* 470*/ {I_LGS, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB5\110", IF_386}, - /* 471*/ {I_LGS, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xB5\110", IF_386}, - /* 472*/ {I_LIDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\203", IF_286|IF_PRIV}, - /* 473*/ {I_LLDT, 1, {MEMORY,0,0}, "\300\1\x0F\17\202", IF_286|IF_PROT|IF_PRIV}, - /* 474*/ {I_LLDT, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\202", IF_286|IF_PROT|IF_PRIV}, - /* 475*/ {I_LLDT, 1, {REG16,0,0}, "\1\x0F\17\202", IF_286|IF_PROT|IF_PRIV}, - /* 476*/ {I_LMSW, 1, {MEMORY,0,0}, "\300\2\x0F\x01\206", IF_286|IF_PRIV}, - /* 477*/ {I_LMSW, 1, {MEMORY|BITS16,0,0}, "\300\2\x0F\x01\206", IF_286|IF_PRIV}, - /* 478*/ {I_LMSW, 1, {REG16,0,0}, "\2\x0F\x01\206", IF_286|IF_PRIV}, - /* 479*/ {I_LOADALL, 0, {0,0,0}, "\2\x0F\x07", IF_386|IF_UNDOC}, - /* 480*/ {I_LOADALL286, 0, {0,0,0}, "\2\x0F\x05", IF_286|IF_UNDOC}, - /* 481*/ {I_LODSB, 0, {0,0,0}, "\1\xAC", IF_8086}, - /* 482*/ {I_LODSD, 0, {0,0,0}, "\321\1\xAD", IF_386}, - /* 483*/ {I_LODSW, 0, {0,0,0}, "\320\1\xAD", IF_8086}, - /* 484*/ {I_LOOP, 1, {IMMEDIATE,0,0}, "\312\1\xE2\50", IF_8086}, - /* 485*/ {I_LOOP, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE2\50", IF_8086}, - /* 486*/ {I_LOOP, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE2\50", IF_386}, - /* 487*/ {I_LOOPE, 1, {IMMEDIATE,0,0}, "\312\1\xE1\50", IF_8086}, - /* 488*/ {I_LOOPE, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE1\50", IF_8086}, - /* 489*/ {I_LOOPE, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE1\50", IF_386}, - /* 490*/ {I_LOOPNE, 1, {IMMEDIATE,0,0}, "\312\1\xE0\50", IF_8086}, - /* 491*/ {I_LOOPNE, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE0\50", IF_8086}, - /* 492*/ {I_LOOPNE, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE0\50", IF_386}, - /* 493*/ {I_LOOPNZ, 1, {IMMEDIATE,0,0}, "\312\1\xE0\50", IF_8086}, - /* 494*/ {I_LOOPNZ, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE0\50", IF_8086}, - /* 495*/ {I_LOOPNZ, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE0\50", IF_386}, - /* 496*/ {I_LOOPZ, 1, {IMMEDIATE,0,0}, "\312\1\xE1\50", IF_8086}, - /* 497*/ {I_LOOPZ, 2, {IMMEDIATE,REG_CX,0}, "\310\1\xE1\50", IF_8086}, - /* 498*/ {I_LOOPZ, 2, {IMMEDIATE,REG_ECX,0}, "\311\1\xE1\50", IF_386}, - /* 499*/ {I_LSL, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\x03\110", IF_286|IF_PROT|IF_SM}, - /* 500*/ {I_LSL, 2, {REG16,REG16,0}, "\320\2\x0F\x03\110", IF_286|IF_PROT}, - /* 501*/ {I_LSL, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\x03\110", IF_386|IF_PROT|IF_SM}, - /* 502*/ {I_LSL, 2, {REG32,REG32,0}, "\321\2\x0F\x03\110", IF_386|IF_PROT}, - /* 503*/ {I_LSS, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB2\110", IF_386}, - /* 504*/ {I_LSS, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\xB2\110", IF_386}, - /* 505*/ {I_LTR, 1, {MEMORY,0,0}, "\300\1\x0F\17\203", IF_286|IF_PROT|IF_PRIV}, - /* 506*/ {I_LTR, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\203", IF_286|IF_PROT|IF_PRIV}, - /* 507*/ {I_LTR, 1, {REG16,0,0}, "\1\x0F\17\203", IF_286|IF_PROT|IF_PRIV}, - /* 508*/ {I_MONITOR, 0, {0,0,0}, "\3\x0F\x01\xC8", IF_PRESCOTT}, - /* 509*/ {I_MOV, 2, {MEMORY,REG_SREG,0}, "\300\1\x8C\101", IF_8086|IF_SM}, - /* 510*/ {I_MOV, 2, {REG16,REG_SREG,0}, "\320\1\x8C\101", IF_8086}, - /* 511*/ {I_MOV, 2, {REG32,REG_SREG,0}, "\321\1\x8C\101", IF_386}, - /* 512*/ {I_MOV, 2, {REG_SREG,MEMORY,0}, "\301\1\x8E\110", IF_8086|IF_SM}, - /* 513*/ {I_MOV, 2, {REG_SREG,REG16,0}, "\1\x8E\110", IF_8086}, - /* 514*/ {I_MOV, 2, {REG_SREG,REG32,0}, "\1\x8E\110", IF_386}, - /* 515*/ {I_MOV, 2, {REG_AL,MEM_OFFS,0}, "\301\1\xA0\45", IF_8086|IF_SM}, - /* 516*/ {I_MOV, 2, {REG_AX,MEM_OFFS,0}, "\301\320\1\xA1\45", IF_8086|IF_SM}, - /* 517*/ {I_MOV, 2, {REG_EAX,MEM_OFFS,0}, "\301\321\1\xA1\45", IF_386|IF_SM}, - /* 518*/ {I_MOV, 2, {MEM_OFFS,REG_AL,0}, "\300\1\xA2\44", IF_8086|IF_SM}, - /* 519*/ {I_MOV, 2, {MEM_OFFS,REG_AX,0}, "\300\320\1\xA3\44", IF_8086|IF_SM}, - /* 520*/ {I_MOV, 2, {MEM_OFFS,REG_EAX,0}, "\300\321\1\xA3\44", IF_386|IF_SM}, - /* 521*/ {I_MOV, 2, {REG32,REG_CREG,0}, "\2\x0F\x20\101", IF_386|IF_PRIV}, - /* 522*/ {I_MOV, 2, {REG32,REG_DREG,0}, "\2\x0F\x21\101", IF_386|IF_PRIV}, - /* 523*/ {I_MOV, 2, {REG32,REG_TREG,0}, "\2\x0F\x24\101", IF_386|IF_PRIV}, - /* 524*/ {I_MOV, 2, {REG_CREG,REG32,0}, "\2\x0F\x22\110", IF_386|IF_PRIV}, - /* 525*/ {I_MOV, 2, {REG_DREG,REG32,0}, "\2\x0F\x23\110", IF_386|IF_PRIV}, - /* 526*/ {I_MOV, 2, {REG_TREG,REG32,0}, "\2\x0F\x26\110", IF_386|IF_PRIV}, - /* 527*/ {I_MOV, 2, {MEMORY,REG8,0}, "\300\1\x88\101", IF_8086|IF_SM}, - /* 528*/ {I_MOV, 2, {REG8,REG8,0}, "\1\x88\101", IF_8086}, - /* 529*/ {I_MOV, 2, {MEMORY,REG16,0}, "\320\300\1\x89\101", IF_8086|IF_SM}, - /* 530*/ {I_MOV, 2, {REG16,REG16,0}, "\320\1\x89\101", IF_8086}, - /* 531*/ {I_MOV, 2, {MEMORY,REG32,0}, "\321\300\1\x89\101", IF_386|IF_SM}, - /* 532*/ {I_MOV, 2, {REG32,REG32,0}, "\321\1\x89\101", IF_386}, - /* 533*/ {I_MOV, 2, {REG8,MEMORY,0}, "\301\1\x8A\110", IF_8086|IF_SM}, - /* 534*/ {I_MOV, 2, {REG8,REG8,0}, "\1\x8A\110", IF_8086}, - /* 535*/ {I_MOV, 2, {REG16,MEMORY,0}, "\320\301\1\x8B\110", IF_8086|IF_SM}, - /* 536*/ {I_MOV, 2, {REG16,REG16,0}, "\320\1\x8B\110", IF_8086}, - /* 537*/ {I_MOV, 2, {REG32,MEMORY,0}, "\321\301\1\x8B\110", IF_386|IF_SM}, - /* 538*/ {I_MOV, 2, {REG32,REG32,0}, "\321\1\x8B\110", IF_386}, - /* 539*/ {I_MOV, 2, {REG8,IMMEDIATE,0}, "\10\xB0\21", IF_8086|IF_SM}, - /* 540*/ {I_MOV, 2, {REG16,IMMEDIATE,0}, "\320\10\xB8\31", IF_8086|IF_SM}, - /* 541*/ {I_MOV, 2, {REG32,IMMEDIATE,0}, "\321\10\xB8\41", IF_386|IF_SM}, - /* 542*/ {I_MOV, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC6\200\21", IF_8086|IF_SM}, - /* 543*/ {I_MOV, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC7\200\31", IF_8086|IF_SM}, - /* 544*/ {I_MOV, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC7\200\41", IF_386|IF_SM}, - /* 545*/ {I_MOV, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\xC6\200\21", IF_8086|IF_SM}, - /* 546*/ {I_MOV, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\1\xC7\200\31", IF_8086|IF_SM}, - /* 547*/ {I_MOV, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\1\xC7\200\41", IF_386|IF_SM}, - /* 548*/ {I_MOVD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6E\110", IF_PENT|IF_MMX|IF_SD}, - /* 549*/ {I_MOVD, 2, {MMXREG,REG32,0}, "\2\x0F\x6E\110", IF_PENT|IF_MMX}, - /* 550*/ {I_MOVD, 2, {MEMORY,MMXREG,0}, "\300\2\x0F\x7E\101", IF_PENT|IF_MMX|IF_SD}, - /* 551*/ {I_MOVD, 2, {REG32,MMXREG,0}, "\2\x0F\x7E\101", IF_PENT|IF_MMX}, - /* 552*/ {I_MOVQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6F\110", IF_PENT|IF_MMX|IF_SM}, - /* 553*/ {I_MOVQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x6F\110", IF_PENT|IF_MMX}, - /* 554*/ {I_MOVQ, 2, {MEMORY,MMXREG,0}, "\300\2\x0F\x7F\101", IF_PENT|IF_MMX|IF_SM}, - /* 555*/ {I_MOVQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x7F\101", IF_PENT|IF_MMX}, - /* 556*/ {I_MOVSB, 0, {0,0,0}, "\1\xA4", IF_8086}, - /* 557*/ {I_MOVSD, 0, {0,0,0}, "\321\1\xA5", IF_386}, - /* 558*/ {I_MOVSW, 0, {0,0,0}, "\320\1\xA5", IF_8086}, - /* 559*/ {I_MOVSX, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xBE\110", IF_386|IF_SB}, - /* 560*/ {I_MOVSX, 2, {REG16,REG8,0}, "\320\2\x0F\xBE\110", IF_386}, - /* 561*/ {I_MOVSX, 2, {REG32,REGMEM|BITS8,0}, "\321\301\2\x0F\xBE\110", IF_386}, - /* 562*/ {I_MOVSX, 2, {REG32,REGMEM|BITS16,0}, "\321\301\2\x0F\xBF\110", IF_386}, - /* 563*/ {I_MOVZX, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\xB6\110", IF_386|IF_SB}, - /* 564*/ {I_MOVZX, 2, {REG16,REG8,0}, "\320\2\x0F\xB6\110", IF_386}, - /* 565*/ {I_MOVZX, 2, {REG32,REGMEM|BITS8,0}, "\321\301\2\x0F\xB6\110", IF_386}, - /* 566*/ {I_MOVZX, 2, {REG32,REGMEM|BITS16,0}, "\321\301\2\x0F\xB7\110", IF_386}, - /* 567*/ {I_MUL, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\204", IF_8086}, - /* 568*/ {I_MUL, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\204", IF_8086}, - /* 569*/ {I_MUL, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\204", IF_386}, - /* 570*/ {I_MWAIT, 0, {0,0,0}, "\3\x0F\x01\xC9", IF_PRESCOTT}, - /* 571*/ {I_NEG, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\203", IF_8086}, - /* 572*/ {I_NEG, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\203", IF_8086}, - /* 573*/ {I_NEG, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\203", IF_386}, - /* 574*/ {I_NOP, 0, {0,0,0}, "\1\x90", IF_8086}, - /* 575*/ {I_NOT, 1, {REGMEM|BITS8,0,0}, "\300\1\xF6\202", IF_8086}, - /* 576*/ {I_NOT, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xF7\202", IF_8086}, - /* 577*/ {I_NOT, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xF7\202", IF_386}, - /* 578*/ {I_OR, 2, {MEMORY,REG8,0}, "\300\1\x08\101", IF_8086|IF_SM}, - /* 579*/ {I_OR, 2, {REG8,REG8,0}, "\1\x08\101", IF_8086}, - /* 580*/ {I_OR, 2, {MEMORY,REG16,0}, "\320\300\1\x09\101", IF_8086|IF_SM}, - /* 581*/ {I_OR, 2, {REG16,REG16,0}, "\320\1\x09\101", IF_8086}, - /* 582*/ {I_OR, 2, {MEMORY,REG32,0}, "\321\300\1\x09\101", IF_386|IF_SM}, - /* 583*/ {I_OR, 2, {REG32,REG32,0}, "\321\1\x09\101", IF_386}, - /* 584*/ {I_OR, 2, {REG8,MEMORY,0}, "\301\1\x0A\110", IF_8086|IF_SM}, - /* 585*/ {I_OR, 2, {REG8,REG8,0}, "\1\x0A\110", IF_8086}, - /* 586*/ {I_OR, 2, {REG16,MEMORY,0}, "\320\301\1\x0B\110", IF_8086|IF_SM}, - /* 587*/ {I_OR, 2, {REG16,REG16,0}, "\320\1\x0B\110", IF_8086}, - /* 588*/ {I_OR, 2, {REG32,MEMORY,0}, "\321\301\1\x0B\110", IF_386|IF_SM}, - /* 589*/ {I_OR, 2, {REG32,REG32,0}, "\321\1\x0B\110", IF_386}, - /* 590*/ {I_OR, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\201\15", IF_8086}, - /* 591*/ {I_OR, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\201\15", IF_386}, - /* 592*/ {I_OR, 2, {REG_AL,IMMEDIATE,0}, "\1\x0C\21", IF_8086|IF_SM}, - /* 593*/ {I_OR, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x0D\31", IF_8086|IF_SM}, - /* 594*/ {I_OR, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x0D\41", IF_386|IF_SM}, - /* 595*/ {I_OR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\201\21", IF_8086|IF_SM}, - /* 596*/ {I_OR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\201\131", IF_8086|IF_SM}, - /* 597*/ {I_OR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\201\141", IF_386|IF_SM}, - /* 598*/ {I_OR, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\201\21", IF_8086|IF_SM}, - /* 599*/ {I_OR, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\201\131", IF_8086|IF_SM}, - /* 600*/ {I_OR, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\201\141", IF_386|IF_SM}, - /* 601*/ {I_OUT, 2, {IMMEDIATE,REG_AL,0}, "\1\xE6\24", IF_8086|IF_SB}, - /* 602*/ {I_OUT, 2, {IMMEDIATE,REG_AX,0}, "\320\1\xE7\24", IF_8086|IF_SB}, - /* 603*/ {I_OUT, 2, {IMMEDIATE,REG_EAX,0}, "\321\1\xE7\24", IF_386|IF_SB}, - /* 604*/ {I_OUT, 2, {REG_DX,REG_AL,0}, "\1\xEE", IF_8086}, - /* 605*/ {I_OUT, 2, {REG_DX,REG_AX,0}, "\320\1\xEF", IF_8086}, - /* 606*/ {I_OUT, 2, {REG_DX,REG_EAX,0}, "\321\1\xEF", IF_386}, - /* 607*/ {I_OUTSB, 0, {0,0,0}, "\1\x6E", IF_186}, - /* 608*/ {I_OUTSD, 0, {0,0,0}, "\321\1\x6F", IF_386}, - /* 609*/ {I_OUTSW, 0, {0,0,0}, "\320\1\x6F", IF_186}, - /* 610*/ {I_PACKSSDW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6B\110", IF_PENT|IF_MMX|IF_SM}, - /* 611*/ {I_PACKSSDW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x6B\110", IF_PENT|IF_MMX}, - /* 612*/ {I_PACKSSWB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x63\110", IF_PENT|IF_MMX|IF_SM}, - /* 613*/ {I_PACKSSWB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x63\110", IF_PENT|IF_MMX}, - /* 614*/ {I_PACKUSWB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x67\110", IF_PENT|IF_MMX|IF_SM}, - /* 615*/ {I_PACKUSWB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x67\110", IF_PENT|IF_MMX}, - /* 616*/ {I_PADDB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFC\110", IF_PENT|IF_MMX|IF_SM}, - /* 617*/ {I_PADDB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFC\110", IF_PENT|IF_MMX}, - /* 618*/ {I_PADDD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFE\110", IF_PENT|IF_MMX|IF_SM}, - /* 619*/ {I_PADDD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFE\110", IF_PENT|IF_MMX}, - /* 620*/ {I_PADDSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEC\110", IF_PENT|IF_MMX|IF_SM}, - /* 621*/ {I_PADDSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEC\110", IF_PENT|IF_MMX}, - /* 622*/ {I_PADDSIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x51\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 623*/ {I_PADDSIW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x51\110", IF_PENT|IF_MMX|IF_CYRIX}, - /* 624*/ {I_PADDSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xED\110", IF_PENT|IF_MMX|IF_SM}, - /* 625*/ {I_PADDSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xED\110", IF_PENT|IF_MMX}, - /* 626*/ {I_PADDUSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDC\110", IF_PENT|IF_MMX|IF_SM}, - /* 627*/ {I_PADDUSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDC\110", IF_PENT|IF_MMX}, - /* 628*/ {I_PADDUSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDD\110", IF_PENT|IF_MMX|IF_SM}, - /* 629*/ {I_PADDUSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDD\110", IF_PENT|IF_MMX}, - /* 630*/ {I_PADDW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFD\110", IF_PENT|IF_MMX|IF_SM}, - /* 631*/ {I_PADDW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFD\110", IF_PENT|IF_MMX}, - /* 632*/ {I_PAND, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDB\110", IF_PENT|IF_MMX|IF_SM}, - /* 633*/ {I_PAND, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDB\110", IF_PENT|IF_MMX}, - /* 634*/ {I_PANDN, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDF\110", IF_PENT|IF_MMX|IF_SM}, - /* 635*/ {I_PANDN, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDF\110", IF_PENT|IF_MMX}, - /* 636*/ {I_PAVEB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x50\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 637*/ {I_PAVEB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x50\110", IF_PENT|IF_MMX|IF_CYRIX}, - /* 638*/ {I_PAVGUSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xBF", IF_PENT|IF_3DNOW|IF_SM}, - /* 639*/ {I_PAVGUSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xBF", IF_PENT|IF_3DNOW}, - /* 640*/ {I_PCMPEQB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x74\110", IF_PENT|IF_MMX|IF_SM}, - /* 641*/ {I_PCMPEQB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x74\110", IF_PENT|IF_MMX}, - /* 642*/ {I_PCMPEQD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x76\110", IF_PENT|IF_MMX|IF_SM}, - /* 643*/ {I_PCMPEQD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x76\110", IF_PENT|IF_MMX}, - /* 644*/ {I_PCMPEQW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x75\110", IF_PENT|IF_MMX|IF_SM}, - /* 645*/ {I_PCMPEQW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x75\110", IF_PENT|IF_MMX}, - /* 646*/ {I_PCMPGTB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x64\110", IF_PENT|IF_MMX|IF_SM}, - /* 647*/ {I_PCMPGTB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x64\110", IF_PENT|IF_MMX}, - /* 648*/ {I_PCMPGTD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x66\110", IF_PENT|IF_MMX|IF_SM}, - /* 649*/ {I_PCMPGTD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x66\110", IF_PENT|IF_MMX}, - /* 650*/ {I_PCMPGTW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x65\110", IF_PENT|IF_MMX|IF_SM}, - /* 651*/ {I_PCMPGTW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x65\110", IF_PENT|IF_MMX}, - /* 652*/ {I_PDISTIB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x54\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 653*/ {I_PF2ID, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x1D", IF_PENT|IF_3DNOW|IF_SM}, - /* 654*/ {I_PF2ID, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x1D", IF_PENT|IF_3DNOW}, - /* 655*/ {I_PFACC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xAE", IF_PENT|IF_3DNOW|IF_SM}, - /* 656*/ {I_PFACC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xAE", IF_PENT|IF_3DNOW}, - /* 657*/ {I_PFADD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x9E", IF_PENT|IF_3DNOW|IF_SM}, - /* 658*/ {I_PFADD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x9E", IF_PENT|IF_3DNOW}, - /* 659*/ {I_PFCMPEQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xB0", IF_PENT|IF_3DNOW|IF_SM}, - /* 660*/ {I_PFCMPEQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xB0", IF_PENT|IF_3DNOW}, - /* 661*/ {I_PFCMPGE, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x90", IF_PENT|IF_3DNOW|IF_SM}, - /* 662*/ {I_PFCMPGE, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x90", IF_PENT|IF_3DNOW}, - /* 663*/ {I_PFCMPGT, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA0", IF_PENT|IF_3DNOW|IF_SM}, - /* 664*/ {I_PFCMPGT, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA0", IF_PENT|IF_3DNOW}, - /* 665*/ {I_PFMAX, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA4", IF_PENT|IF_3DNOW|IF_SM}, - /* 666*/ {I_PFMAX, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA4", IF_PENT|IF_3DNOW}, - /* 667*/ {I_PFMIN, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x94", IF_PENT|IF_3DNOW|IF_SM}, - /* 668*/ {I_PFMIN, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x94", IF_PENT|IF_3DNOW}, - /* 669*/ {I_PFMUL, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xB4", IF_PENT|IF_3DNOW|IF_SM}, - /* 670*/ {I_PFMUL, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xB4", IF_PENT|IF_3DNOW}, - /* 671*/ {I_PFRCP, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x96", IF_PENT|IF_3DNOW|IF_SM}, - /* 672*/ {I_PFRCP, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x96", IF_PENT|IF_3DNOW}, - /* 673*/ {I_PFRCPIT1, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA6", IF_PENT|IF_3DNOW|IF_SM}, - /* 674*/ {I_PFRCPIT1, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA6", IF_PENT|IF_3DNOW}, - /* 675*/ {I_PFRCPIT2, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xB6", IF_PENT|IF_3DNOW|IF_SM}, - /* 676*/ {I_PFRCPIT2, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xB6", IF_PENT|IF_3DNOW}, - /* 677*/ {I_PFRSQIT1, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xA7", IF_PENT|IF_3DNOW|IF_SM}, - /* 678*/ {I_PFRSQIT1, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xA7", IF_PENT|IF_3DNOW}, - /* 679*/ {I_PFRSQRT, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x97", IF_PENT|IF_3DNOW|IF_SM}, - /* 680*/ {I_PFRSQRT, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x97", IF_PENT|IF_3DNOW}, - /* 681*/ {I_PFSUB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x9A", IF_PENT|IF_3DNOW|IF_SM}, - /* 682*/ {I_PFSUB, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x9A", IF_PENT|IF_3DNOW}, - /* 683*/ {I_PFSUBR, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xAA", IF_PENT|IF_3DNOW|IF_SM}, - /* 684*/ {I_PFSUBR, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xAA", IF_PENT|IF_3DNOW}, - /* 685*/ {I_PI2FD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x0D", IF_PENT|IF_3DNOW|IF_SM}, - /* 686*/ {I_PI2FD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x0D", IF_PENT|IF_3DNOW}, - /* 687*/ {I_PMACHRIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5E\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 688*/ {I_PMADDWD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF5\110", IF_PENT|IF_MMX|IF_SM}, - /* 689*/ {I_PMADDWD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF5\110", IF_PENT|IF_MMX}, - /* 690*/ {I_PMAGW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x52\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 691*/ {I_PMAGW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x52\110", IF_PENT|IF_MMX|IF_CYRIX}, - /* 692*/ {I_PMULHRIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5D\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 693*/ {I_PMULHRIW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x5D\110", IF_PENT|IF_MMX|IF_CYRIX}, - /* 694*/ {I_PMULHRWA, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\1\xB7", IF_PENT|IF_3DNOW|IF_SM}, - /* 695*/ {I_PMULHRWA, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\1\xB7", IF_PENT|IF_3DNOW}, - /* 696*/ {I_PMULHRWC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x59\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 697*/ {I_PMULHRWC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x59\110", IF_PENT|IF_MMX|IF_CYRIX}, - /* 698*/ {I_PMULHW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE5\110", IF_PENT|IF_MMX|IF_SM}, - /* 699*/ {I_PMULHW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE5\110", IF_PENT|IF_MMX}, - /* 700*/ {I_PMULLW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD5\110", IF_PENT|IF_MMX|IF_SM}, - /* 701*/ {I_PMULLW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD5\110", IF_PENT|IF_MMX}, - /* 702*/ {I_PMVGEZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5C\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 703*/ {I_PMVLZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5B\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 704*/ {I_PMVNZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x5A\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 705*/ {I_PMVZB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x58\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 706*/ {I_POP, 1, {REG16,0,0}, "\320\10\x58", IF_8086}, - /* 707*/ {I_POP, 1, {REG32,0,0}, "\321\10\x58", IF_386}, - /* 708*/ {I_POP, 1, {REGMEM|BITS16,0,0}, "\320\300\1\x8F\200", IF_8086}, - /* 709*/ {I_POP, 1, {REGMEM|BITS32,0,0}, "\321\300\1\x8F\200", IF_386}, - /* 710*/ {I_POP, 1, {REG_DESS,0,0}, "\4", IF_8086}, - /* 711*/ {I_POP, 1, {REG_FSGS,0,0}, "\1\x0F\5", IF_386}, - /* 712*/ {I_POPA, 0, {0,0,0}, "\322\1\x61", IF_186}, - /* 713*/ {I_POPAD, 0, {0,0,0}, "\321\1\x61", IF_386}, - /* 714*/ {I_POPAW, 0, {0,0,0}, "\320\1\x61", IF_186}, - /* 715*/ {I_POPF, 0, {0,0,0}, "\322\1\x9D", IF_8086}, - /* 716*/ {I_POPFD, 0, {0,0,0}, "\321\1\x9D", IF_386}, - /* 717*/ {I_POPFW, 0, {0,0,0}, "\320\1\x9D", IF_8086}, - /* 718*/ {I_POR, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEB\110", IF_PENT|IF_MMX|IF_SM}, - /* 719*/ {I_POR, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEB\110", IF_PENT|IF_MMX}, - /* 720*/ {I_PREFETCH, 1, {MEMORY,0,0}, "\2\x0F\x0D\200", IF_PENT|IF_3DNOW|IF_SM}, - /* 721*/ {I_PREFETCHW, 1, {MEMORY,0,0}, "\2\x0F\x0D\201", IF_PENT|IF_3DNOW|IF_SM}, - /* 722*/ {I_PSLLD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF2\110", IF_PENT|IF_MMX|IF_SM}, - /* 723*/ {I_PSLLD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF2\110", IF_PENT|IF_MMX}, - /* 724*/ {I_PSLLD, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x72\206\25", IF_PENT|IF_MMX}, - /* 725*/ {I_PSLLQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF3\110", IF_PENT|IF_MMX|IF_SM}, - /* 726*/ {I_PSLLQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF3\110", IF_PENT|IF_MMX}, - /* 727*/ {I_PSLLQ, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x73\206\25", IF_PENT|IF_MMX}, - /* 728*/ {I_PSLLW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF1\110", IF_PENT|IF_MMX|IF_SM}, - /* 729*/ {I_PSLLW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF1\110", IF_PENT|IF_MMX}, - /* 730*/ {I_PSLLW, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x71\206\25", IF_PENT|IF_MMX}, - /* 731*/ {I_PSRAD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE2\110", IF_PENT|IF_MMX|IF_SM}, - /* 732*/ {I_PSRAD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE2\110", IF_PENT|IF_MMX}, - /* 733*/ {I_PSRAD, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x72\204\25", IF_PENT|IF_MMX}, - /* 734*/ {I_PSRAW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE1\110", IF_PENT|IF_MMX|IF_SM}, - /* 735*/ {I_PSRAW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE1\110", IF_PENT|IF_MMX}, - /* 736*/ {I_PSRAW, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x71\204\25", IF_PENT|IF_MMX}, - /* 737*/ {I_PSRLD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD2\110", IF_PENT|IF_MMX|IF_SM}, - /* 738*/ {I_PSRLD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD2\110", IF_PENT|IF_MMX}, - /* 739*/ {I_PSRLD, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x72\202\25", IF_PENT|IF_MMX}, - /* 740*/ {I_PSRLQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD3\110", IF_PENT|IF_MMX|IF_SM}, - /* 741*/ {I_PSRLQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD3\110", IF_PENT|IF_MMX}, - /* 742*/ {I_PSRLQ, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x73\202\25", IF_PENT|IF_MMX}, - /* 743*/ {I_PSRLW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD1\110", IF_PENT|IF_MMX|IF_SM}, - /* 744*/ {I_PSRLW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD1\110", IF_PENT|IF_MMX}, - /* 745*/ {I_PSRLW, 2, {MMXREG,IMMEDIATE,0}, "\2\x0F\x71\202\25", IF_PENT|IF_MMX}, - /* 746*/ {I_PSUBB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF8\110", IF_PENT|IF_MMX|IF_SM}, - /* 747*/ {I_PSUBB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF8\110", IF_PENT|IF_MMX}, - /* 748*/ {I_PSUBD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFA\110", IF_PENT|IF_MMX|IF_SM}, - /* 749*/ {I_PSUBD, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFA\110", IF_PENT|IF_MMX}, - /* 750*/ {I_PSUBSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE8\110", IF_PENT|IF_MMX|IF_SM}, - /* 751*/ {I_PSUBSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE8\110", IF_PENT|IF_MMX}, - /* 752*/ {I_PSUBSIW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x55\110", IF_PENT|IF_MMX|IF_SM|IF_CYRIX}, - /* 753*/ {I_PSUBSIW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x55\110", IF_PENT|IF_MMX|IF_CYRIX}, - /* 754*/ {I_PSUBSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE9\110", IF_PENT|IF_MMX|IF_SM}, - /* 755*/ {I_PSUBSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE9\110", IF_PENT|IF_MMX}, - /* 756*/ {I_PSUBUSB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD8\110", IF_PENT|IF_MMX|IF_SM}, - /* 757*/ {I_PSUBUSB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD8\110", IF_PENT|IF_MMX}, - /* 758*/ {I_PSUBUSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD9\110", IF_PENT|IF_MMX|IF_SM}, - /* 759*/ {I_PSUBUSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD9\110", IF_PENT|IF_MMX}, - /* 760*/ {I_PSUBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF9\110", IF_PENT|IF_MMX|IF_SM}, - /* 761*/ {I_PSUBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF9\110", IF_PENT|IF_MMX}, - /* 762*/ {I_PUNPCKHBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x68\110", IF_PENT|IF_MMX|IF_SM}, - /* 763*/ {I_PUNPCKHBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x68\110", IF_PENT|IF_MMX}, - /* 764*/ {I_PUNPCKHDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x6A\110", IF_PENT|IF_MMX|IF_SM}, - /* 765*/ {I_PUNPCKHDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x6A\110", IF_PENT|IF_MMX}, - /* 766*/ {I_PUNPCKHWD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x69\110", IF_PENT|IF_MMX|IF_SM}, - /* 767*/ {I_PUNPCKHWD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x69\110", IF_PENT|IF_MMX}, - /* 768*/ {I_PUNPCKLBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x60\110", IF_PENT|IF_MMX|IF_SM}, - /* 769*/ {I_PUNPCKLBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x60\110", IF_PENT|IF_MMX}, - /* 770*/ {I_PUNPCKLDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x62\110", IF_PENT|IF_MMX|IF_SM}, - /* 771*/ {I_PUNPCKLDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\x62\110", IF_PENT|IF_MMX}, - /* 772*/ {I_PUNPCKLWD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x61\110", IF_PENT|IF_MMX|IF_SM}, - /* 773*/ {I_PUNPCKLWD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x61\110", IF_PENT|IF_MMX}, - /* 774*/ {I_PUSH, 1, {REG16,0,0}, "\320\10\x50", IF_8086}, - /* 775*/ {I_PUSH, 1, {REG32,0,0}, "\321\10\x50", IF_386}, - /* 776*/ {I_PUSH, 1, {REGMEM|BITS16,0,0}, "\320\300\1\xFF\206", IF_8086}, - /* 777*/ {I_PUSH, 1, {REGMEM|BITS32,0,0}, "\321\300\1\xFF\206", IF_386}, - /* 778*/ {I_PUSH, 1, {REG_CS,0,0}, "\6", IF_8086}, - /* 779*/ {I_PUSH, 1, {REG_DESS,0,0}, "\6", IF_8086}, - /* 780*/ {I_PUSH, 1, {REG_FSGS,0,0}, "\1\x0F\7", IF_386}, - /* 781*/ {I_PUSH, 1, {IMMEDIATE|BITS8,0,0}, "\1\x6A\14", IF_186}, - /* 782*/ {I_PUSH, 1, {IMMEDIATE|BITS16,0,0}, "\320\133\1\x68\130", IF_186}, - /* 783*/ {I_PUSH, 1, {IMMEDIATE|BITS32,0,0}, "\321\143\1\x68\140", IF_386}, - /* 784*/ {I_PUSH, 1, {IMMEDIATE,0,0}, "\1\x68\34", IF_186}, - /* 785*/ {I_PUSHA, 0, {0,0,0}, "\322\1\x60", IF_186}, - /* 786*/ {I_PUSHAD, 0, {0,0,0}, "\321\1\x60", IF_386}, - /* 787*/ {I_PUSHAW, 0, {0,0,0}, "\320\1\x60", IF_186}, - /* 788*/ {I_PUSHF, 0, {0,0,0}, "\322\1\x9C", IF_8086}, - /* 789*/ {I_PUSHFD, 0, {0,0,0}, "\321\1\x9C", IF_386}, - /* 790*/ {I_PUSHFW, 0, {0,0,0}, "\320\1\x9C", IF_8086}, - /* 791*/ {I_PXOR, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEF\110", IF_PENT|IF_MMX|IF_SM}, - /* 792*/ {I_PXOR, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEF\110", IF_PENT|IF_MMX}, - /* 793*/ {I_RCL, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\202", IF_8086}, - /* 794*/ {I_RCL, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\202", IF_8086}, - /* 795*/ {I_RCL, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\202\25", IF_186|IF_SB}, - /* 796*/ {I_RCL, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\202", IF_8086}, - /* 797*/ {I_RCL, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\202", IF_8086}, - /* 798*/ {I_RCL, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\202\25", IF_186|IF_SB}, - /* 799*/ {I_RCL, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\202", IF_386}, - /* 800*/ {I_RCL, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\202", IF_386}, - /* 801*/ {I_RCL, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\202\25", IF_386|IF_SB}, - /* 802*/ {I_RCR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\203", IF_8086}, - /* 803*/ {I_RCR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\203", IF_8086}, - /* 804*/ {I_RCR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\203\25", IF_186|IF_SB}, - /* 805*/ {I_RCR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\203", IF_8086}, - /* 806*/ {I_RCR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\203", IF_8086}, - /* 807*/ {I_RCR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\203\25", IF_186|IF_SB}, - /* 808*/ {I_RCR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\203", IF_386}, - /* 809*/ {I_RCR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\203", IF_386}, - /* 810*/ {I_RCR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\203\25", IF_386|IF_SB}, - /* 811*/ {I_RDSHR, 1, {REGMEM|BITS32,0,0}, "\321\300\2\x0F\x36\200", IF_P6|IF_CYRIX|IF_SMM}, - /* 812*/ {I_RDMSR, 0, {0,0,0}, "\2\x0F\x32", IF_PENT|IF_PRIV}, - /* 813*/ {I_RDPMC, 0, {0,0,0}, "\2\x0F\x33", IF_P6}, - /* 814*/ {I_RDTSC, 0, {0,0,0}, "\2\x0F\x31", IF_PENT}, - /* 815*/ {I_RESB, 1, {IMMEDIATE,0,0}, "\340", IF_8086}, - /* 816*/ {I_RET, 0, {0,0,0}, "\1\xC3", IF_8086}, - /* 817*/ {I_RET, 1, {IMMEDIATE,0,0}, "\1\xC2\30", IF_8086|IF_SW}, - /* 818*/ {I_RETF, 0, {0,0,0}, "\1\xCB", IF_8086}, - /* 819*/ {I_RETF, 1, {IMMEDIATE,0,0}, "\1\xCA\30", IF_8086|IF_SW}, - /* 820*/ {I_RETN, 0, {0,0,0}, "\1\xC3", IF_8086}, - /* 821*/ {I_RETN, 1, {IMMEDIATE,0,0}, "\1\xC2\30", IF_8086|IF_SW}, - /* 822*/ {I_ROL, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\200", IF_8086}, - /* 823*/ {I_ROL, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\200", IF_8086}, - /* 824*/ {I_ROL, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\200\25", IF_186|IF_SB}, - /* 825*/ {I_ROL, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\200", IF_8086}, - /* 826*/ {I_ROL, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\200", IF_8086}, - /* 827*/ {I_ROL, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\200\25", IF_186|IF_SB}, - /* 828*/ {I_ROL, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\200", IF_386}, - /* 829*/ {I_ROL, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\200", IF_386}, - /* 830*/ {I_ROL, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\200\25", IF_386|IF_SB}, - /* 831*/ {I_ROR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\201", IF_8086}, - /* 832*/ {I_ROR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\201", IF_8086}, - /* 833*/ {I_ROR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\201\25", IF_186|IF_SB}, - /* 834*/ {I_ROR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\201", IF_8086}, - /* 835*/ {I_ROR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\201", IF_8086}, - /* 836*/ {I_ROR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\201\25", IF_186|IF_SB}, - /* 837*/ {I_ROR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\201", IF_386}, - /* 838*/ {I_ROR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\201", IF_386}, - /* 839*/ {I_ROR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\201\25", IF_386|IF_SB}, - /* 840*/ {I_RSDC, 2, {REG_SREG,MEMORY|BITS80,0}, "\301\2\x0F\x79\110", IF_486|IF_CYRIX|IF_SMM}, - /* 841*/ {I_RSLDT, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7B\200", IF_486|IF_CYRIX|IF_SMM}, - /* 842*/ {I_RSM, 0, {0,0,0}, "\2\x0F\xAA", IF_PENT|IF_SMM}, - /* 843*/ {I_RSTS, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7D\200", IF_486|IF_CYRIX|IF_SMM}, - /* 844*/ {I_SAHF, 0, {0,0,0}, "\1\x9E", IF_8086}, - /* 845*/ {I_SALC, 0, {0,0,0}, "\1\xD6", IF_8086|IF_UNDOC}, - /* 846*/ {I_SAR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\207", IF_8086}, - /* 847*/ {I_SAR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\207", IF_8086}, - /* 848*/ {I_SAR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\207\25", IF_186|IF_SB}, - /* 849*/ {I_SAR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\207", IF_8086}, - /* 850*/ {I_SAR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\207", IF_8086}, - /* 851*/ {I_SAR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\207\25", IF_186|IF_SB}, - /* 852*/ {I_SAR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\207", IF_386}, - /* 853*/ {I_SAR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\207", IF_386}, - /* 854*/ {I_SAR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\207\25", IF_386|IF_SB}, - /* 855*/ {I_SBB, 2, {MEMORY,REG8,0}, "\300\1\x18\101", IF_8086|IF_SM}, - /* 856*/ {I_SBB, 2, {REG8,REG8,0}, "\1\x18\101", IF_8086}, - /* 857*/ {I_SBB, 2, {MEMORY,REG16,0}, "\320\300\1\x19\101", IF_8086|IF_SM}, - /* 858*/ {I_SBB, 2, {REG16,REG16,0}, "\320\1\x19\101", IF_8086}, - /* 859*/ {I_SBB, 2, {MEMORY,REG32,0}, "\321\300\1\x19\101", IF_386|IF_SM}, - /* 860*/ {I_SBB, 2, {REG32,REG32,0}, "\321\1\x19\101", IF_386}, - /* 861*/ {I_SBB, 2, {REG8,MEMORY,0}, "\301\1\x1A\110", IF_8086|IF_SM}, - /* 862*/ {I_SBB, 2, {REG8,REG8,0}, "\1\x1A\110", IF_8086}, - /* 863*/ {I_SBB, 2, {REG16,MEMORY,0}, "\320\301\1\x1B\110", IF_8086|IF_SM}, - /* 864*/ {I_SBB, 2, {REG16,REG16,0}, "\320\1\x1B\110", IF_8086}, - /* 865*/ {I_SBB, 2, {REG32,MEMORY,0}, "\321\301\1\x1B\110", IF_386|IF_SM}, - /* 866*/ {I_SBB, 2, {REG32,REG32,0}, "\321\1\x1B\110", IF_386}, - /* 867*/ {I_SBB, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\203\15", IF_8086}, - /* 868*/ {I_SBB, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\203\15", IF_386}, - /* 869*/ {I_SBB, 2, {REG_AL,IMMEDIATE,0}, "\1\x1C\21", IF_8086|IF_SM}, - /* 870*/ {I_SBB, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x1D\31", IF_8086|IF_SM}, - /* 871*/ {I_SBB, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x1D\41", IF_386|IF_SM}, - /* 872*/ {I_SBB, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\203\21", IF_8086|IF_SM}, - /* 873*/ {I_SBB, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\203\131", IF_8086|IF_SM}, - /* 874*/ {I_SBB, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\203\141", IF_386|IF_SM}, - /* 875*/ {I_SBB, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\203\21", IF_8086|IF_SM}, - /* 876*/ {I_SBB, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\203\131", IF_8086|IF_SM}, - /* 877*/ {I_SBB, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\203\141", IF_386|IF_SM}, - /* 878*/ {I_SCASB, 0, {0,0,0}, "\332\1\xAE", IF_8086}, - /* 879*/ {I_SCASD, 0, {0,0,0}, "\332\321\1\xAF", IF_386}, - /* 880*/ {I_SCASW, 0, {0,0,0}, "\332\320\1\xAF", IF_8086}, - /* 881*/ {I_SGDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\200", IF_286}, - /* 882*/ {I_SHL, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\204", IF_8086}, - /* 883*/ {I_SHL, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\204", IF_8086}, - /* 884*/ {I_SHL, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\204\25", IF_186|IF_SB}, - /* 885*/ {I_SHL, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\204", IF_8086}, - /* 886*/ {I_SHL, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\204", IF_8086}, - /* 887*/ {I_SHL, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\204\25", IF_186|IF_SB}, - /* 888*/ {I_SHL, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\204", IF_386}, - /* 889*/ {I_SHL, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\204", IF_386}, - /* 890*/ {I_SHL, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\204\25", IF_386|IF_SB}, - /* 891*/ {I_SHLD, 3, {MEMORY,REG16,IMMEDIATE}, "\300\320\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - /* 892*/ {I_SHLD, 3, {REG16,REG16,IMMEDIATE}, "\320\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - /* 893*/ {I_SHLD, 3, {MEMORY,REG32,IMMEDIATE}, "\300\321\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - /* 894*/ {I_SHLD, 3, {REG32,REG32,IMMEDIATE}, "\321\2\x0F\xA4\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - /* 895*/ {I_SHLD, 3, {MEMORY,REG16,REG_CL}, "\300\320\2\x0F\xA5\101", IF_386|IF_SM}, - /* 896*/ {I_SHLD, 3, {REG16,REG16,REG_CL}, "\320\2\x0F\xA5\101", IF_386}, - /* 897*/ {I_SHLD, 3, {MEMORY,REG32,REG_CL}, "\300\321\2\x0F\xA5\101", IF_386|IF_SM}, - /* 898*/ {I_SHLD, 3, {REG32,REG32,REG_CL}, "\321\2\x0F\xA5\101", IF_386}, - /* 899*/ {I_SHR, 2, {REGMEM|BITS8,UNITY,0}, "\300\1\xD0\205", IF_8086}, - /* 900*/ {I_SHR, 2, {REGMEM|BITS8,REG_CL,0}, "\300\1\xD2\205", IF_8086}, - /* 901*/ {I_SHR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xC0\205\25", IF_186|IF_SB}, - /* 902*/ {I_SHR, 2, {REGMEM|BITS16,UNITY,0}, "\320\300\1\xD1\205", IF_8086}, - /* 903*/ {I_SHR, 2, {REGMEM|BITS16,REG_CL,0}, "\320\300\1\xD3\205", IF_8086}, - /* 904*/ {I_SHR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xC1\205\25", IF_186|IF_SB}, - /* 905*/ {I_SHR, 2, {REGMEM|BITS32,UNITY,0}, "\321\300\1\xD1\205", IF_386}, - /* 906*/ {I_SHR, 2, {REGMEM|BITS32,REG_CL,0}, "\321\300\1\xD3\205", IF_386}, - /* 907*/ {I_SHR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xC1\205\25", IF_386|IF_SB}, - /* 908*/ {I_SHRD, 3, {MEMORY,REG16,IMMEDIATE}, "\300\320\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - /* 909*/ {I_SHRD, 3, {REG16,REG16,IMMEDIATE}, "\320\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - /* 910*/ {I_SHRD, 3, {MEMORY,REG32,IMMEDIATE}, "\300\321\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - /* 911*/ {I_SHRD, 3, {REG32,REG32,IMMEDIATE}, "\321\2\x0F\xAC\101\26", IF_386|IF_SM2|IF_SB|IF_AR2}, - /* 912*/ {I_SHRD, 3, {MEMORY,REG16,REG_CL}, "\300\320\2\x0F\xAD\101", IF_386|IF_SM}, - /* 913*/ {I_SHRD, 3, {REG16,REG16,REG_CL}, "\320\2\x0F\xAD\101", IF_386}, - /* 914*/ {I_SHRD, 3, {MEMORY,REG32,REG_CL}, "\300\321\2\x0F\xAD\101", IF_386|IF_SM}, - /* 915*/ {I_SHRD, 3, {REG32,REG32,REG_CL}, "\321\2\x0F\xAD\101", IF_386}, - /* 916*/ {I_SIDT, 1, {MEMORY,0,0}, "\300\2\x0F\x01\201", IF_286}, - /* 917*/ {I_SLDT, 1, {MEMORY,0,0}, "\300\1\x0F\17\200", IF_286}, - /* 918*/ {I_SLDT, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\200", IF_286}, - /* 919*/ {I_SLDT, 1, {REG16,0,0}, "\320\1\x0F\17\200", IF_286}, - /* 920*/ {I_SLDT, 1, {REG32,0,0}, "\321\1\x0F\17\200", IF_386}, - /* 921*/ {I_SMI, 0, {0,0,0}, "\1\xF1", IF_386|IF_UNDOC}, - /* 922*/ {I_SMINT, 0, {0,0,0}, "\2\x0F\x38", IF_P6|IF_CYRIX}, - /* 923*/ {I_SMSW, 1, {MEMORY,0,0}, "\300\2\x0F\x01\204", IF_286}, - /* 924*/ {I_SMSW, 1, {MEMORY|BITS16,0,0}, "\300\2\x0F\x01\204", IF_286}, - /* 925*/ {I_SMSW, 1, {REG16,0,0}, "\320\2\x0F\x01\204", IF_286}, - /* 926*/ {I_SMSW, 1, {REG32,0,0}, "\321\2\x0F\x01\204", IF_386}, - /* 927*/ {I_STC, 0, {0,0,0}, "\1\xF9", IF_8086}, - /* 928*/ {I_STD, 0, {0,0,0}, "\1\xFD", IF_8086}, - /* 929*/ {I_STI, 0, {0,0,0}, "\1\xFB", IF_8086}, - /* 930*/ {I_STOSB, 0, {0,0,0}, "\1\xAA", IF_8086}, - /* 931*/ {I_STOSD, 0, {0,0,0}, "\321\1\xAB", IF_386}, - /* 932*/ {I_STOSW, 0, {0,0,0}, "\320\1\xAB", IF_8086}, - /* 933*/ {I_STR, 1, {MEMORY,0,0}, "\300\1\x0F\17\201", IF_286|IF_PROT}, - /* 934*/ {I_STR, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\201", IF_286|IF_PROT}, - /* 935*/ {I_STR, 1, {REG16,0,0}, "\320\1\x0F\17\201", IF_286|IF_PROT}, - /* 936*/ {I_STR, 1, {REG32,0,0}, "\321\1\x0F\17\201", IF_386|IF_PROT}, - /* 937*/ {I_SUB, 2, {MEMORY,REG8,0}, "\300\1\x28\101", IF_8086|IF_SM}, - /* 938*/ {I_SUB, 2, {REG8,REG8,0}, "\1\x28\101", IF_8086}, - /* 939*/ {I_SUB, 2, {MEMORY,REG16,0}, "\320\300\1\x29\101", IF_8086|IF_SM}, - /* 940*/ {I_SUB, 2, {REG16,REG16,0}, "\320\1\x29\101", IF_8086}, - /* 941*/ {I_SUB, 2, {MEMORY,REG32,0}, "\321\300\1\x29\101", IF_386|IF_SM}, - /* 942*/ {I_SUB, 2, {REG32,REG32,0}, "\321\1\x29\101", IF_386}, - /* 943*/ {I_SUB, 2, {REG8,MEMORY,0}, "\301\1\x2A\110", IF_8086|IF_SM}, - /* 944*/ {I_SUB, 2, {REG8,REG8,0}, "\1\x2A\110", IF_8086}, - /* 945*/ {I_SUB, 2, {REG16,MEMORY,0}, "\320\301\1\x2B\110", IF_8086|IF_SM}, - /* 946*/ {I_SUB, 2, {REG16,REG16,0}, "\320\1\x2B\110", IF_8086}, - /* 947*/ {I_SUB, 2, {REG32,MEMORY,0}, "\321\301\1\x2B\110", IF_386|IF_SM}, - /* 948*/ {I_SUB, 2, {REG32,REG32,0}, "\321\1\x2B\110", IF_386}, - /* 949*/ {I_SUB, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\205\15", IF_8086}, - /* 950*/ {I_SUB, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\205\15", IF_386}, - /* 951*/ {I_SUB, 2, {REG_AL,IMMEDIATE,0}, "\1\x2C\21", IF_8086|IF_SM}, - /* 952*/ {I_SUB, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x2D\31", IF_8086|IF_SM}, - /* 953*/ {I_SUB, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x2D\41", IF_386|IF_SM}, - /* 954*/ {I_SUB, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\205\21", IF_8086|IF_SM}, - /* 955*/ {I_SUB, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\205\131", IF_8086|IF_SM}, - /* 956*/ {I_SUB, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\205\141", IF_386|IF_SM}, - /* 957*/ {I_SUB, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\205\21", IF_8086|IF_SM}, - /* 958*/ {I_SUB, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\205\131", IF_8086|IF_SM}, - /* 959*/ {I_SUB, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\205\141", IF_386|IF_SM}, - /* 960*/ {I_SVDC, 2, {MEMORY|BITS80,REG_SREG,0}, "\300\2\x0F\x78\101", IF_486|IF_CYRIX|IF_SMM}, - /* 961*/ {I_SVLDT, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7A\200", IF_486|IF_CYRIX|IF_SMM}, - /* 962*/ {I_SVTS, 1, {MEMORY|BITS80,0,0}, "\300\2\x0F\x7C\200", IF_486|IF_CYRIX|IF_SMM}, - /* 963*/ {I_SYSCALL, 0, {0,0,0}, "\2\x0F\x05", IF_P6|IF_AMD}, - /* 964*/ {I_SYSENTER, 0, {0,0,0}, "\2\x0F\x34", IF_P6}, - /* 965*/ {I_SYSEXIT, 0, {0,0,0}, "\2\x0F\x35", IF_P6|IF_PRIV}, - /* 966*/ {I_SYSRET, 0, {0,0,0}, "\2\x0F\x07", IF_P6|IF_PRIV|IF_AMD}, - /* 967*/ {I_TEST, 2, {MEMORY,REG8,0}, "\300\1\x84\101", IF_8086|IF_SM}, - /* 968*/ {I_TEST, 2, {REG8,REG8,0}, "\1\x84\101", IF_8086}, - /* 969*/ {I_TEST, 2, {MEMORY,REG16,0}, "\320\300\1\x85\101", IF_8086|IF_SM}, - /* 970*/ {I_TEST, 2, {REG16,REG16,0}, "\320\1\x85\101", IF_8086}, - /* 971*/ {I_TEST, 2, {MEMORY,REG32,0}, "\321\300\1\x85\101", IF_386|IF_SM}, - /* 972*/ {I_TEST, 2, {REG32,REG32,0}, "\321\1\x85\101", IF_386}, - /* 973*/ {I_TEST, 2, {REG8,MEMORY,0}, "\301\1\x84\110", IF_8086|IF_SM}, - /* 974*/ {I_TEST, 2, {REG16,MEMORY,0}, "\320\301\1\x85\110", IF_8086|IF_SM}, - /* 975*/ {I_TEST, 2, {REG32,MEMORY,0}, "\321\301\1\x85\110", IF_386|IF_SM}, - /* 976*/ {I_TEST, 2, {REG_AL,IMMEDIATE,0}, "\1\xA8\21", IF_8086|IF_SM}, - /* 977*/ {I_TEST, 2, {REG_AX,IMMEDIATE,0}, "\320\1\xA9\31", IF_8086|IF_SM}, - /* 978*/ {I_TEST, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\xA9\41", IF_386|IF_SM}, - /* 979*/ {I_TEST, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\xF6\200\21", IF_8086|IF_SM}, - /* 980*/ {I_TEST, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\1\xF7\200\31", IF_8086|IF_SM}, - /* 981*/ {I_TEST, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\1\xF7\200\41", IF_386|IF_SM}, - /* 982*/ {I_TEST, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\xF6\200\21", IF_8086|IF_SM}, - /* 983*/ {I_TEST, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\1\xF7\200\31", IF_8086|IF_SM}, - /* 984*/ {I_TEST, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\1\xF7\200\41", IF_386|IF_SM}, - /* 985*/ {I_UD0, 0, {0,0,0}, "\2\x0F\xFF", IF_286|IF_UNDOC}, - /* 986*/ {I_UD1, 0, {0,0,0}, "\2\x0F\xB9", IF_286|IF_UNDOC}, - /* 987*/ {I_UD2, 0, {0,0,0}, "\2\x0F\x0B", IF_286}, - /* 988*/ {I_UMOV, 2, {MEMORY,REG8,0}, "\300\2\x0F\x10\101", IF_386|IF_UNDOC|IF_SM}, - /* 989*/ {I_UMOV, 2, {REG8,REG8,0}, "\2\x0F\x10\101", IF_386|IF_UNDOC}, - /* 990*/ {I_UMOV, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\x11\101", IF_386|IF_UNDOC|IF_SM}, - /* 991*/ {I_UMOV, 2, {REG16,REG16,0}, "\320\2\x0F\x11\101", IF_386|IF_UNDOC}, - /* 992*/ {I_UMOV, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\x11\101", IF_386|IF_UNDOC|IF_SM}, - /* 993*/ {I_UMOV, 2, {REG32,REG32,0}, "\321\2\x0F\x11\101", IF_386|IF_UNDOC}, - /* 994*/ {I_UMOV, 2, {REG8,MEMORY,0}, "\301\2\x0F\x12\110", IF_386|IF_UNDOC|IF_SM}, - /* 995*/ {I_UMOV, 2, {REG8,REG8,0}, "\2\x0F\x12\110", IF_386|IF_UNDOC}, - /* 996*/ {I_UMOV, 2, {REG16,MEMORY,0}, "\320\301\2\x0F\x13\110", IF_386|IF_UNDOC|IF_SM}, - /* 997*/ {I_UMOV, 2, {REG16,REG16,0}, "\320\2\x0F\x13\110", IF_386|IF_UNDOC}, - /* 998*/ {I_UMOV, 2, {REG32,MEMORY,0}, "\321\301\2\x0F\x13\110", IF_386|IF_UNDOC|IF_SM}, - /* 999*/ {I_UMOV, 2, {REG32,REG32,0}, "\321\2\x0F\x13\110", IF_386|IF_UNDOC}, - /*1000*/ {I_VERR, 1, {MEMORY,0,0}, "\300\1\x0F\17\204", IF_286|IF_PROT}, - /*1001*/ {I_VERR, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\204", IF_286|IF_PROT}, - /*1002*/ {I_VERR, 1, {REG16,0,0}, "\1\x0F\17\204", IF_286|IF_PROT}, - /*1003*/ {I_VERW, 1, {MEMORY,0,0}, "\300\1\x0F\17\205", IF_286|IF_PROT}, - /*1004*/ {I_VERW, 1, {MEMORY|BITS16,0,0}, "\300\1\x0F\17\205", IF_286|IF_PROT}, - /*1005*/ {I_VERW, 1, {REG16,0,0}, "\1\x0F\17\205", IF_286|IF_PROT}, - /*1006*/ {I_WAIT, 0, {0,0,0}, "\1\x9B", IF_8086}, - /*1007*/ {I_FWAIT, 0, {0,0,0}, "\1\x9B", IF_8086}, - /*1008*/ {I_WBINVD, 0, {0,0,0}, "\2\x0F\x09", IF_486|IF_PRIV}, - /*1009*/ {I_WRSHR, 1, {REGMEM|BITS32,0,0}, "\321\300\2\x0F\x37\200", IF_P6|IF_CYRIX|IF_SMM}, - /*1010*/ {I_WRMSR, 0, {0,0,0}, "\2\x0F\x30", IF_PENT|IF_PRIV}, - /*1011*/ {I_XADD, 2, {MEMORY,REG8,0}, "\300\2\x0F\xC0\101", IF_486|IF_SM}, - /*1012*/ {I_XADD, 2, {REG8,REG8,0}, "\2\x0F\xC0\101", IF_486}, - /*1013*/ {I_XADD, 2, {MEMORY,REG16,0}, "\320\300\2\x0F\xC1\101", IF_486|IF_SM}, - /*1014*/ {I_XADD, 2, {REG16,REG16,0}, "\320\2\x0F\xC1\101", IF_486}, - /*1015*/ {I_XADD, 2, {MEMORY,REG32,0}, "\321\300\2\x0F\xC1\101", IF_486|IF_SM}, - /*1016*/ {I_XADD, 2, {REG32,REG32,0}, "\321\2\x0F\xC1\101", IF_486}, - /*1017*/ {I_XCHG, 2, {REG_AX,REG16,0}, "\320\11\x90", IF_8086}, - /*1018*/ {I_XCHG, 2, {REG_EAX,REG32,0}, "\321\11\x90", IF_386}, - /*1019*/ {I_XCHG, 2, {REG16,REG_AX,0}, "\320\10\x90", IF_8086}, - /*1020*/ {I_XCHG, 2, {REG32,REG_EAX,0}, "\321\10\x90", IF_386}, - /*1021*/ {I_XCHG, 2, {REG8,MEMORY,0}, "\301\1\x86\110", IF_8086|IF_SM}, - /*1022*/ {I_XCHG, 2, {REG8,REG8,0}, "\1\x86\110", IF_8086}, - /*1023*/ {I_XCHG, 2, {REG16,MEMORY,0}, "\320\301\1\x87\110", IF_8086|IF_SM}, - /*1024*/ {I_XCHG, 2, {REG16,REG16,0}, "\320\1\x87\110", IF_8086}, - /*1025*/ {I_XCHG, 2, {REG32,MEMORY,0}, "\321\301\1\x87\110", IF_386|IF_SM}, - /*1026*/ {I_XCHG, 2, {REG32,REG32,0}, "\321\1\x87\110", IF_386}, - /*1027*/ {I_XCHG, 2, {MEMORY,REG8,0}, "\300\1\x86\101", IF_8086|IF_SM}, - /*1028*/ {I_XCHG, 2, {REG8,REG8,0}, "\1\x86\101", IF_8086}, - /*1029*/ {I_XCHG, 2, {MEMORY,REG16,0}, "\320\300\1\x87\101", IF_8086|IF_SM}, - /*1030*/ {I_XCHG, 2, {REG16,REG16,0}, "\320\1\x87\101", IF_8086}, - /*1031*/ {I_XCHG, 2, {MEMORY,REG32,0}, "\321\300\1\x87\101", IF_386|IF_SM}, - /*1032*/ {I_XCHG, 2, {REG32,REG32,0}, "\321\1\x87\101", IF_386}, - /*1033*/ {I_XLATB, 0, {0,0,0}, "\1\xD7", IF_8086}, - /*1034*/ {I_XLAT, 0, {0,0,0}, "\1\xD7", IF_8086}, - /*1035*/ {I_XOR, 2, {MEMORY,REG8,0}, "\300\1\x30\101", IF_8086|IF_SM}, - /*1036*/ {I_XOR, 2, {REG8,REG8,0}, "\1\x30\101", IF_8086}, - /*1037*/ {I_XOR, 2, {MEMORY,REG16,0}, "\320\300\1\x31\101", IF_8086|IF_SM}, - /*1038*/ {I_XOR, 2, {REG16,REG16,0}, "\320\1\x31\101", IF_8086}, - /*1039*/ {I_XOR, 2, {MEMORY,REG32,0}, "\321\300\1\x31\101", IF_386|IF_SM}, - /*1040*/ {I_XOR, 2, {REG32,REG32,0}, "\321\1\x31\101", IF_386}, - /*1041*/ {I_XOR, 2, {REG8,MEMORY,0}, "\301\1\x32\110", IF_8086|IF_SM}, - /*1042*/ {I_XOR, 2, {REG8,REG8,0}, "\1\x32\110", IF_8086}, - /*1043*/ {I_XOR, 2, {REG16,MEMORY,0}, "\320\301\1\x33\110", IF_8086|IF_SM}, - /*1044*/ {I_XOR, 2, {REG16,REG16,0}, "\320\1\x33\110", IF_8086}, - /*1045*/ {I_XOR, 2, {REG32,MEMORY,0}, "\321\301\1\x33\110", IF_386|IF_SM}, - /*1046*/ {I_XOR, 2, {REG32,REG32,0}, "\321\1\x33\110", IF_386}, - /*1047*/ {I_XOR, 2, {REGMEM|BITS16,IMMEDIATE|BITS8,0}, "\320\300\1\x83\206\15", IF_8086}, - /*1048*/ {I_XOR, 2, {REGMEM|BITS32,IMMEDIATE|BITS8,0}, "\321\300\1\x83\206\15", IF_386}, - /*1049*/ {I_XOR, 2, {REG_AL,IMMEDIATE,0}, "\1\x34\21", IF_8086|IF_SM}, - /*1050*/ {I_XOR, 2, {REG_AX,IMMEDIATE,0}, "\320\1\x35\31", IF_8086|IF_SM}, - /*1051*/ {I_XOR, 2, {REG_EAX,IMMEDIATE,0}, "\321\1\x35\41", IF_386|IF_SM}, - /*1052*/ {I_XOR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x80\206\21", IF_8086|IF_SM}, - /*1053*/ {I_XOR, 2, {REGMEM|BITS16,IMMEDIATE,0}, "\320\300\134\1\x81\206\131", IF_8086|IF_SM}, - /*1054*/ {I_XOR, 2, {REGMEM|BITS32,IMMEDIATE,0}, "\321\300\144\1\x81\206\141", IF_386|IF_SM}, - /*1055*/ {I_XOR, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x80\206\21", IF_8086|IF_SM}, - /*1056*/ {I_XOR, 2, {MEMORY,IMMEDIATE|BITS16,0}, "\320\300\134\1\x81\206\131", IF_8086|IF_SM}, - /*1057*/ {I_XOR, 2, {MEMORY,IMMEDIATE|BITS32,0}, "\321\300\144\1\x81\206\141", IF_386|IF_SM}, - /*1058*/ {I_XSTORE, 0, {0,0,0}, "\3\x0F\xA7\xC0", IF_P6|IF_CYRIX}, - /*1059*/ {I_CMOVcc, 2, {REG16,MEMORY,0}, "\320\301\1\x0F\330\x40\110", IF_P6|IF_SM}, - /*1060*/ {I_CMOVcc, 2, {REG16,REG16,0}, "\320\1\x0F\330\x40\110", IF_P6}, - /*1061*/ {I_CMOVcc, 2, {REG32,MEMORY,0}, "\321\301\1\x0F\330\x40\110", IF_P6|IF_SM}, - /*1062*/ {I_CMOVcc, 2, {REG32,REG32,0}, "\321\1\x0F\330\x40\110", IF_P6}, - /*1063*/ {I_Jcc, 1, {IMMEDIATE|NEAR,0,0}, "\322\1\x0F\330\x80\64", IF_386}, - /*1064*/ {I_Jcc, 1, {IMMEDIATE|BITS16|NEAR,0,0}, "\320\1\x0F\330\x80\64", IF_386}, - /*1065*/ {I_Jcc, 1, {IMMEDIATE|BITS32|NEAR,0,0}, "\321\1\x0F\330\x80\64", IF_386}, - /*1066*/ {I_Jcc, 1, {IMMEDIATE,0,0}, "\330\x70\50", IF_8086}, - /*1067*/ {I_SETcc, 1, {MEMORY,0,0}, "\300\1\x0F\330\x90\200", IF_386|IF_SB}, - /*1068*/ {I_SETcc, 1, {REG8,0,0}, "\300\1\x0F\330\x90\200", IF_386}, - /*1069*/ {I_ADDPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x58\110", IF_KATMAI|IF_SSE}, - /*1070*/ {I_ADDPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x58\110", IF_KATMAI|IF_SSE}, - /*1071*/ {I_ADDSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x58\110", IF_KATMAI|IF_SSE}, - /*1072*/ {I_ADDSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x58\110", IF_KATMAI|IF_SSE}, - /*1073*/ {I_ANDNPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x55\110", IF_KATMAI|IF_SSE}, - /*1074*/ {I_ANDNPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x55\110", IF_KATMAI|IF_SSE}, - /*1075*/ {I_ANDPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x54\110", IF_KATMAI|IF_SSE}, - /*1076*/ {I_ANDPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x54\110", IF_KATMAI|IF_SSE}, - /*1077*/ {I_CMPEQPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, - /*1078*/ {I_CMPEQPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, - /*1079*/ {I_CMPEQSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, - /*1080*/ {I_CMPEQSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x00", IF_KATMAI|IF_SSE}, - /*1081*/ {I_CMPLEPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, - /*1082*/ {I_CMPLEPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, - /*1083*/ {I_CMPLESS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, - /*1084*/ {I_CMPLESS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x02", IF_KATMAI|IF_SSE}, - /*1085*/ {I_CMPLTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, - /*1086*/ {I_CMPLTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, - /*1087*/ {I_CMPLTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, - /*1088*/ {I_CMPLTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x01", IF_KATMAI|IF_SSE}, - /*1089*/ {I_CMPNEQPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, - /*1090*/ {I_CMPNEQPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, - /*1091*/ {I_CMPNEQSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, - /*1092*/ {I_CMPNEQSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x04", IF_KATMAI|IF_SSE}, - /*1093*/ {I_CMPNLEPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, - /*1094*/ {I_CMPNLEPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, - /*1095*/ {I_CMPNLESS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, - /*1096*/ {I_CMPNLESS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x06", IF_KATMAI|IF_SSE}, - /*1097*/ {I_CMPNLTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, - /*1098*/ {I_CMPNLTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, - /*1099*/ {I_CMPNLTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, - /*1100*/ {I_CMPNLTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x05", IF_KATMAI|IF_SSE}, - /*1101*/ {I_CMPORDPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, - /*1102*/ {I_CMPORDPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, - /*1103*/ {I_CMPORDSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, - /*1104*/ {I_CMPORDSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x07", IF_KATMAI|IF_SSE}, - /*1105*/ {I_CMPUNORDPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, - /*1106*/ {I_CMPUNORDPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, - /*1107*/ {I_CMPUNORDSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, - /*1108*/ {I_CMPUNORDSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xC2\110\1\x03", IF_KATMAI|IF_SSE}, - /*1109*/ {I_CMPPS, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\331\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - /*1110*/ {I_CMPPS, 3, {XMMREG,XMMREG,IMMEDIATE}, "\331\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - /*1111*/ {I_CMPSS, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\333\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - /*1112*/ {I_CMPSS, 3, {XMMREG,XMMREG,IMMEDIATE}, "\333\2\x0F\xC2\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - /*1113*/ {I_COMISS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x2F\110", IF_KATMAI|IF_SSE}, - /*1114*/ {I_COMISS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x2F\110", IF_KATMAI|IF_SSE}, - /*1115*/ {I_CVTPI2PS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x2A\110", IF_KATMAI|IF_SSE|IF_MMX}, - /*1116*/ {I_CVTPI2PS, 2, {XMMREG,MMXREG,0}, "\331\2\x0F\x2A\110", IF_KATMAI|IF_SSE|IF_MMX}, - /*1117*/ {I_CVTPS2PI, 2, {MMXREG,MEMORY,0}, "\301\331\2\x0F\x2D\110", IF_KATMAI|IF_SSE|IF_MMX}, - /*1118*/ {I_CVTPS2PI, 2, {MMXREG,XMMREG,0}, "\331\2\x0F\x2D\110", IF_KATMAI|IF_SSE|IF_MMX}, - /*1119*/ {I_CVTSI2SS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x2A\110", IF_KATMAI|IF_SSE|IF_SD|IF_AR1}, - /*1120*/ {I_CVTSI2SS, 2, {XMMREG,REG32,0}, "\333\2\x0F\x2A\110", IF_KATMAI|IF_SSE}, - /*1121*/ {I_CVTSS2SI, 2, {REG32,MEMORY,0}, "\301\333\2\x0F\x2D\110", IF_KATMAI|IF_SSE}, - /*1122*/ {I_CVTSS2SI, 2, {REG32,XMMREG,0}, "\333\2\x0F\x2D\110", IF_KATMAI|IF_SSE}, - /*1123*/ {I_CVTTPS2PI, 2, {MMXREG,MEMORY,0}, "\301\331\2\x0F\x2C\110", IF_KATMAI|IF_SSE|IF_MMX}, - /*1124*/ {I_CVTTPS2PI, 2, {MMXREG,XMMREG,0}, "\331\2\x0F\x2C\110", IF_KATMAI|IF_SSE|IF_MMX}, - /*1125*/ {I_CVTTSS2SI, 2, {REG32,MEMORY,0}, "\301\333\2\x0F\x2C\110", IF_KATMAI|IF_SSE}, - /*1126*/ {I_CVTTSS2SI, 2, {REG32,XMMREG,0}, "\333\2\x0F\x2C\110", IF_KATMAI|IF_SSE}, - /*1127*/ {I_DIVPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, - /*1128*/ {I_DIVPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, - /*1129*/ {I_DIVSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, - /*1130*/ {I_DIVSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5E\110", IF_KATMAI|IF_SSE}, - /*1131*/ {I_LDMXCSR, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\202", IF_KATMAI|IF_SSE|IF_SD}, - /*1132*/ {I_MAXPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, - /*1133*/ {I_MAXPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, - /*1134*/ {I_MAXSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, - /*1135*/ {I_MAXSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5F\110", IF_KATMAI|IF_SSE}, - /*1136*/ {I_MINPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, - /*1137*/ {I_MINPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, - /*1138*/ {I_MINSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, - /*1139*/ {I_MINSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5D\110", IF_KATMAI|IF_SSE}, - /*1140*/ {I_MOVAPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x28\110", IF_KATMAI|IF_SSE}, - /*1141*/ {I_MOVAPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x29\101", IF_KATMAI|IF_SSE}, - /*1142*/ {I_MOVAPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x28\110", IF_KATMAI|IF_SSE}, - /*1143*/ {I_MOVAPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x29\101", IF_KATMAI|IF_SSE}, - /*1144*/ {I_MOVHPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x16\110", IF_KATMAI|IF_SSE}, - /*1145*/ {I_MOVHPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x17\101", IF_KATMAI|IF_SSE}, - /*1146*/ {I_MOVLHPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x16\110", IF_KATMAI|IF_SSE}, - /*1147*/ {I_MOVLPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x12\110", IF_KATMAI|IF_SSE}, - /*1148*/ {I_MOVLPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x13\101", IF_KATMAI|IF_SSE}, - /*1149*/ {I_MOVHLPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x12\110", IF_KATMAI|IF_SSE}, - /*1150*/ {I_MOVMSKPS, 2, {REG32,XMMREG,0}, "\2\x0F\x50\110", IF_KATMAI|IF_SSE}, - /*1151*/ {I_MOVNTPS, 2, {MEMORY,XMMREG,0}, "\300\2\x0F\x2B\101", IF_KATMAI|IF_SSE}, - /*1152*/ {I_MOVSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x10\110", IF_KATMAI|IF_SSE}, - /*1153*/ {I_MOVSS, 2, {MEMORY,XMMREG,0}, "\300\333\2\x0F\x11\101", IF_KATMAI|IF_SSE}, - /*1154*/ {I_MOVSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x10\110", IF_KATMAI|IF_SSE}, - /*1155*/ {I_MOVSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x11\101", IF_KATMAI|IF_SSE}, - /*1156*/ {I_MOVUPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x10\110", IF_KATMAI|IF_SSE}, - /*1157*/ {I_MOVUPS, 2, {MEMORY,XMMREG,0}, "\300\331\2\x0F\x11\101", IF_KATMAI|IF_SSE}, - /*1158*/ {I_MOVUPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x10\110", IF_KATMAI|IF_SSE}, - /*1159*/ {I_MOVUPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x11\101", IF_KATMAI|IF_SSE}, - /*1160*/ {I_MULPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x59\110", IF_KATMAI|IF_SSE}, - /*1161*/ {I_MULPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x59\110", IF_KATMAI|IF_SSE}, - /*1162*/ {I_MULSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x59\110", IF_KATMAI|IF_SSE}, - /*1163*/ {I_MULSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x59\110", IF_KATMAI|IF_SSE}, - /*1164*/ {I_ORPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x56\110", IF_KATMAI|IF_SSE}, - /*1165*/ {I_ORPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x56\110", IF_KATMAI|IF_SSE}, - /*1166*/ {I_RCPPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x53\110", IF_KATMAI|IF_SSE}, - /*1167*/ {I_RCPPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x53\110", IF_KATMAI|IF_SSE}, - /*1168*/ {I_RCPSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x53\110", IF_KATMAI|IF_SSE}, - /*1169*/ {I_RCPSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x53\110", IF_KATMAI|IF_SSE}, - /*1170*/ {I_RSQRTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x52\110", IF_KATMAI|IF_SSE}, - /*1171*/ {I_RSQRTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x52\110", IF_KATMAI|IF_SSE}, - /*1172*/ {I_RSQRTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x52\110", IF_KATMAI|IF_SSE}, - /*1173*/ {I_RSQRTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x52\110", IF_KATMAI|IF_SSE}, - /*1174*/ {I_SHUFPS, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\2\x0F\xC6\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - /*1175*/ {I_SHUFPS, 3, {XMMREG,XMMREG,IMMEDIATE}, "\2\x0F\xC6\110\26", IF_KATMAI|IF_SSE|IF_SB|IF_AR2}, - /*1176*/ {I_SQRTPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x51\110", IF_KATMAI|IF_SSE}, - /*1177*/ {I_SQRTPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x51\110", IF_KATMAI|IF_SSE}, - /*1178*/ {I_SQRTSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x51\110", IF_KATMAI|IF_SSE}, - /*1179*/ {I_SQRTSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x51\110", IF_KATMAI|IF_SSE}, - /*1180*/ {I_STMXCSR, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\203", IF_KATMAI|IF_SSE|IF_SD}, - /*1181*/ {I_SUBPS, 2, {XMMREG,MEMORY,0}, "\301\331\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, - /*1182*/ {I_SUBPS, 2, {XMMREG,XMMREG,0}, "\331\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, - /*1183*/ {I_SUBSS, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, - /*1184*/ {I_SUBSS, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5C\110", IF_KATMAI|IF_SSE}, - /*1185*/ {I_UCOMISS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x2E\110", IF_KATMAI|IF_SSE}, - /*1186*/ {I_UCOMISS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x2E\110", IF_KATMAI|IF_SSE}, - /*1187*/ {I_UNPCKHPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x15\110", IF_KATMAI|IF_SSE}, - /*1188*/ {I_UNPCKHPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x15\110", IF_KATMAI|IF_SSE}, - /*1189*/ {I_UNPCKLPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x14\110", IF_KATMAI|IF_SSE}, - /*1190*/ {I_UNPCKLPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x14\110", IF_KATMAI|IF_SSE}, - /*1191*/ {I_XORPS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x57\110", IF_KATMAI|IF_SSE}, - /*1192*/ {I_XORPS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x57\110", IF_KATMAI|IF_SSE}, - /*1193*/ {I_FXRSTOR, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\201", IF_P6|IF_SSE|IF_FPU}, - /*1194*/ {I_FXSAVE, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\200", IF_P6|IF_SSE|IF_FPU}, - /*1195*/ {I_PREFETCHNTA, 1, {MEMORY,0,0}, "\300\2\x0F\x18\200", IF_KATMAI}, - /*1196*/ {I_PREFETCHT0, 1, {MEMORY,0,0}, "\300\2\x0F\x18\201", IF_KATMAI}, - /*1197*/ {I_PREFETCHT1, 1, {MEMORY,0,0}, "\300\2\x0F\x18\202", IF_KATMAI}, - /*1198*/ {I_PREFETCHT2, 1, {MEMORY,0,0}, "\300\2\x0F\x18\203", IF_KATMAI}, - /*1199*/ {I_SFENCE, 0, {0,0,0}, "\3\x0F\xAE\xF8", IF_KATMAI}, - /*1200*/ {I_MASKMOVQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF7\110", IF_KATMAI|IF_MMX}, - /*1201*/ {I_MOVNTQ, 2, {MEMORY,MMXREG,0}, "\300\2\x0F\xE7\101", IF_KATMAI|IF_MMX|IF_SM}, - /*1202*/ {I_PAVGB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE0\110", IF_KATMAI|IF_MMX}, - /*1203*/ {I_PAVGB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE0\110", IF_KATMAI|IF_MMX|IF_SM}, - /*1204*/ {I_PAVGW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE3\110", IF_KATMAI|IF_MMX}, - /*1205*/ {I_PAVGW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE3\110", IF_KATMAI|IF_MMX|IF_SM}, - /*1206*/ {I_PEXTRW, 3, {REG32,MMXREG,IMMEDIATE}, "\2\x0F\xC5\110\26", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, - /*1207*/ {I_PINSRW, 3, {MMXREG,REG16,IMMEDIATE}, "\2\x0F\xC4\110\26", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, - /*1208*/ {I_PINSRW, 3, {MMXREG,MEMORY,IMMEDIATE}, "\301\2\x0F\xC4\110\26", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, - /*1209*/ {I_PMAXSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEE\110", IF_KATMAI|IF_MMX}, - /*1210*/ {I_PMAXSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEE\110", IF_KATMAI|IF_MMX|IF_SM}, - /*1211*/ {I_PMAXUB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDE\110", IF_KATMAI|IF_MMX}, - /*1212*/ {I_PMAXUB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDE\110", IF_KATMAI|IF_MMX|IF_SM}, - /*1213*/ {I_PMINSW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xEA\110", IF_KATMAI|IF_MMX}, - /*1214*/ {I_PMINSW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xEA\110", IF_KATMAI|IF_MMX|IF_SM}, - /*1215*/ {I_PMINUB, 2, {MMXREG,MMXREG,0}, "\2\x0F\xDA\110", IF_KATMAI|IF_MMX}, - /*1216*/ {I_PMINUB, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xDA\110", IF_KATMAI|IF_MMX|IF_SM}, - /*1217*/ {I_PMOVMSKB, 2, {REG32,MMXREG,0}, "\2\x0F\xD7\110", IF_KATMAI|IF_MMX}, - /*1218*/ {I_PMULHUW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xE4\110", IF_KATMAI|IF_MMX}, - /*1219*/ {I_PMULHUW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xE4\110", IF_KATMAI|IF_MMX|IF_SM}, - /*1220*/ {I_PSADBW, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF6\110", IF_KATMAI|IF_MMX}, - /*1221*/ {I_PSADBW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF6\110", IF_KATMAI|IF_MMX|IF_SM}, - /*1222*/ {I_PSHUFW, 3, {MMXREG,MMXREG,IMMEDIATE}, "\2\x0F\x70\110\22", IF_KATMAI|IF_MMX|IF_SB|IF_AR2}, - /*1223*/ {I_PSHUFW, 3, {MMXREG,MEMORY,IMMEDIATE}, "\301\2\x0F\x70\110\22", IF_KATMAI|IF_MMX|IF_SM2|IF_SB|IF_AR2}, - /*1224*/ {I_PF2IW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x1C", IF_PENT|IF_3DNOW|IF_SM}, - /*1225*/ {I_PF2IW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x1C", IF_PENT|IF_3DNOW}, - /*1226*/ {I_PFNACC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x8A", IF_PENT|IF_3DNOW|IF_SM}, - /*1227*/ {I_PFNACC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x8A", IF_PENT|IF_3DNOW}, - /*1228*/ {I_PFPNACC, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x8E", IF_PENT|IF_3DNOW|IF_SM}, - /*1229*/ {I_PFPNACC, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x8E", IF_PENT|IF_3DNOW}, - /*1230*/ {I_PI2FW, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\x0C", IF_PENT|IF_3DNOW|IF_SM}, - /*1231*/ {I_PI2FW, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\x0C", IF_PENT|IF_3DNOW}, - /*1232*/ {I_PSWAPD, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\x0F\110\01\xBB", IF_PENT|IF_3DNOW|IF_SM}, - /*1233*/ {I_PSWAPD, 2, {MMXREG,MMXREG,0}, "\2\x0F\x0F\110\01\xBB", IF_PENT|IF_3DNOW}, - /*1234*/ {I_MASKMOVDQU, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF7\110", IF_WILLAMETTE|IF_SSE2}, - /*1235*/ {I_CLFLUSH, 1, {MEMORY,0,0}, "\300\2\x0F\xAE\207", IF_WILLAMETTE|IF_SSE2}, - /*1236*/ {I_MOVNTDQ, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\xE7\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1237*/ {I_MOVNTI, 2, {MEMORY,REG32,0}, "\300\2\x0F\xC3\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1238*/ {I_MOVNTPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x2B\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1239*/ {I_PAUSE, 0, {0,0,0}, "\333\1\x90", IF_WILLAMETTE|IF_SSE2}, - /*1240*/ {I_LFENCE, 0, {0,0,0}, "\3\x0F\xAE\xE8", IF_WILLAMETTE|IF_SSE2}, - /*1241*/ {I_MFENCE, 0, {0,0,0}, "\3\x0F\xAE\xF0", IF_WILLAMETTE|IF_SSE2}, - /*1242*/ {I_MOVD, 2, {XMMREG,REG32,0}, "\3\x66\x0F\x6E\110", IF_WILLAMETTE|IF_SSE2}, - /*1243*/ {I_MOVD, 2, {REG32,XMMREG,0}, "\3\x66\x0F\x7E\101", IF_WILLAMETTE|IF_SSE2}, - /*1244*/ {I_MOVD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x7E\101", IF_WILLAMETTE|IF_SSE2}, - /*1245*/ {I_MOVD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6E\110", IF_WILLAMETTE|IF_SSE2}, - /*1246*/ {I_MOVDQA, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2}, - /*1247*/ {I_MOVDQA, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x7F\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1248*/ {I_MOVDQA, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1249*/ {I_MOVDQA, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x7F\110", IF_WILLAMETTE|IF_SSE2}, - /*1250*/ {I_MOVDQU, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2}, - /*1251*/ {I_MOVDQU, 2, {MEMORY,XMMREG,0}, "\333\300\2\x0F\x7F\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1252*/ {I_MOVDQU, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x6F\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1253*/ {I_MOVDQU, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x7F\110", IF_WILLAMETTE|IF_SSE2}, - /*1254*/ {I_MOVDQ2Q, 2, {MMXREG,XMMREG,0}, "\3\xF2\x0F\xD6\110", IF_WILLAMETTE|IF_SSE2}, - /*1255*/ {I_MOVQ, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x7E\110", IF_WILLAMETTE|IF_SSE2}, - /*1256*/ {I_MOVQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD6\110", IF_WILLAMETTE|IF_SSE2}, - /*1257*/ {I_MOVQ, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\xD6\101", IF_WILLAMETTE|IF_SSE2}, - /*1258*/ {I_MOVQ, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x7E\110", IF_WILLAMETTE|IF_SSE2}, - /*1259*/ {I_MOVQ2DQ, 2, {XMMREG,MMXREG,0}, "\333\2\x0F\xD6\110", IF_WILLAMETTE|IF_SSE2}, - /*1260*/ {I_PACKSSWB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x63\110", IF_WILLAMETTE|IF_SSE2}, - /*1261*/ {I_PACKSSWB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x63\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1262*/ {I_PACKSSDW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6B\110", IF_WILLAMETTE|IF_SSE2}, - /*1263*/ {I_PACKSSDW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1264*/ {I_PACKUSWB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x67\110", IF_WILLAMETTE|IF_SSE2}, - /*1265*/ {I_PACKUSWB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x67\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1266*/ {I_PADDB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFC\110", IF_WILLAMETTE|IF_SSE2}, - /*1267*/ {I_PADDB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFC\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1268*/ {I_PADDW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFD\110", IF_WILLAMETTE|IF_SSE2}, - /*1269*/ {I_PADDW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFD\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1270*/ {I_PADDD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFE\110", IF_WILLAMETTE|IF_SSE2}, - /*1271*/ {I_PADDD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFE\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1272*/ {I_PADDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2}, - /*1273*/ {I_PADDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1274*/ {I_PADDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2}, - /*1275*/ {I_PADDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1276*/ {I_PADDSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEC\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1277*/ {I_PADDSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEC\110", IF_WILLAMETTE|IF_SSE2}, - /*1278*/ {I_PADDSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xED\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1279*/ {I_PADDSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xED\110", IF_WILLAMETTE|IF_SSE2}, - /*1280*/ {I_PADDUSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDC\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1281*/ {I_PADDUSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDC\110", IF_WILLAMETTE|IF_SSE2}, - /*1282*/ {I_PADDUSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDD\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1283*/ {I_PADDUSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDD\110", IF_WILLAMETTE|IF_SSE2}, - /*1284*/ {I_PAND, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDB\110", IF_WILLAMETTE|IF_SSE2}, - /*1285*/ {I_PAND, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1286*/ {I_PANDN, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDF\110", IF_WILLAMETTE|IF_SSE2}, - /*1287*/ {I_PANDN, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDF\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1288*/ {I_PAVGB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE0\110", IF_WILLAMETTE|IF_SSE2}, - /*1289*/ {I_PAVGB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE0\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1290*/ {I_PAVGW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE3\110", IF_WILLAMETTE|IF_SSE2}, - /*1291*/ {I_PAVGW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE3\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1292*/ {I_PCMPEQB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x74\110", IF_WILLAMETTE|IF_SSE2}, - /*1293*/ {I_PCMPEQB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x74\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1294*/ {I_PCMPEQW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x75\110", IF_WILLAMETTE|IF_SSE2}, - /*1295*/ {I_PCMPEQW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x75\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1296*/ {I_PCMPEQD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x76\110", IF_WILLAMETTE|IF_SSE2}, - /*1297*/ {I_PCMPEQD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x76\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1298*/ {I_PCMPGTB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x64\110", IF_WILLAMETTE|IF_SSE2}, - /*1299*/ {I_PCMPGTB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x64\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1300*/ {I_PCMPGTW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x65\110", IF_WILLAMETTE|IF_SSE2}, - /*1301*/ {I_PCMPGTW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x65\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1302*/ {I_PCMPGTD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x66\110", IF_WILLAMETTE|IF_SSE2}, - /*1303*/ {I_PCMPGTD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x66\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1304*/ {I_PEXTRW, 3, {REG32,XMMREG,IMMEDIATE}, "\3\x66\x0F\xC5\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - /*1305*/ {I_PINSRW, 3, {XMMREG,REG16,IMMEDIATE}, "\3\x66\x0F\xC4\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - /*1306*/ {I_PINSRW, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\x66\x0F\xC4\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - /*1307*/ {I_PMADDWD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF5\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1308*/ {I_PMADDWD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF5\110", IF_WILLAMETTE|IF_SSE2}, - /*1309*/ {I_PMAXSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEE\110", IF_WILLAMETTE|IF_SSE2}, - /*1310*/ {I_PMAXSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEE\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1311*/ {I_PMAXUB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDE\110", IF_WILLAMETTE|IF_SSE2}, - /*1312*/ {I_PMAXUB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDE\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1313*/ {I_PMINSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEA\110", IF_WILLAMETTE|IF_SSE2}, - /*1314*/ {I_PMINSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEA\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1315*/ {I_PMINUB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xDA\110", IF_WILLAMETTE|IF_SSE2}, - /*1316*/ {I_PMINUB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xDA\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1317*/ {I_PMOVMSKB, 2, {REG32,XMMREG,0}, "\3\x66\x0F\xD7\110", IF_WILLAMETTE|IF_SSE2}, - /*1318*/ {I_PMULHUW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE4\110", IF_WILLAMETTE|IF_SSE2}, - /*1319*/ {I_PMULHUW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1320*/ {I_PMULHW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE5\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1321*/ {I_PMULHW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE5\110", IF_WILLAMETTE|IF_SSE2}, - /*1322*/ {I_PMULLW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD5\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1323*/ {I_PMULLW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD5\110", IF_WILLAMETTE|IF_SSE2}, - /*1324*/ {I_PMULUDQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2}, - /*1325*/ {I_PMULUDQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1326*/ {I_PMULUDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2}, - /*1327*/ {I_PMULUDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF4\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1328*/ {I_POR, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1329*/ {I_POR, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEB\110", IF_WILLAMETTE|IF_SSE2}, - /*1330*/ {I_PSADBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF6\110", IF_WILLAMETTE|IF_SSE2}, - /*1331*/ {I_PSADBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF6\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1332*/ {I_PSHUFD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\3\x66\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - /*1333*/ {I_PSHUFD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\x66\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, - /*1334*/ {I_PSHUFHW, 3, {XMMREG,XMMREG,IMMEDIATE}, "\333\2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - /*1335*/ {I_PSHUFHW, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\333\2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, - /*1336*/ {I_PSHUFLW, 3, {XMMREG,XMMREG,IMMEDIATE}, "\3\xF2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - /*1337*/ {I_PSHUFLW, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\xF2\x0F\x70\110\22", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, - /*1338*/ {I_PSLLDQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\207\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - /*1339*/ {I_PSLLW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF1\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1340*/ {I_PSLLW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF1\110", IF_WILLAMETTE|IF_SSE2}, - /*1341*/ {I_PSLLW, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x71\206\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - /*1342*/ {I_PSLLD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF2\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1343*/ {I_PSLLD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF2\110", IF_WILLAMETTE|IF_SSE2}, - /*1344*/ {I_PSLLD, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x72\206\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - /*1345*/ {I_PSLLQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF3\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1346*/ {I_PSLLQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF3\110", IF_WILLAMETTE|IF_SSE2}, - /*1347*/ {I_PSLLQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\206\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - /*1348*/ {I_PSRAW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE1\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1349*/ {I_PSRAW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE1\110", IF_WILLAMETTE|IF_SSE2}, - /*1350*/ {I_PSRAW, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x71\204\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - /*1351*/ {I_PSRAD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE2\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1352*/ {I_PSRAD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE2\110", IF_WILLAMETTE|IF_SSE2}, - /*1353*/ {I_PSRAD, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x72\204\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - /*1354*/ {I_PSRLDQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\203\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - /*1355*/ {I_PSRLW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD1\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1356*/ {I_PSRLW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD1\110", IF_WILLAMETTE|IF_SSE2}, - /*1357*/ {I_PSRLW, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x71\202\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - /*1358*/ {I_PSRLD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD2\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1359*/ {I_PSRLD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD2\110", IF_WILLAMETTE|IF_SSE2}, - /*1360*/ {I_PSRLD, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x72\202\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - /*1361*/ {I_PSRLQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD3\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1362*/ {I_PSRLQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD3\110", IF_WILLAMETTE|IF_SSE2}, - /*1363*/ {I_PSRLQ, 2, {XMMREG,IMMEDIATE,0}, "\3\x66\x0F\x73\202\25", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR1}, - /*1364*/ {I_PSUBB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF8\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1365*/ {I_PSUBB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF8\110", IF_WILLAMETTE|IF_SSE2}, - /*1366*/ {I_PSUBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xF9\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1367*/ {I_PSUBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xF9\110", IF_WILLAMETTE|IF_SSE2}, - /*1368*/ {I_PSUBD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFA\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1369*/ {I_PSUBD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFA\110", IF_WILLAMETTE|IF_SSE2}, - /*1370*/ {I_PSUBQ, 2, {MMXREG,MMXREG,0}, "\2\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2}, - /*1371*/ {I_PSUBQ, 2, {MMXREG,MEMORY,0}, "\301\2\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1372*/ {I_PSUBQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2}, - /*1373*/ {I_PSUBQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xFB\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1374*/ {I_PSUBSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE8\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1375*/ {I_PSUBSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE8\110", IF_WILLAMETTE|IF_SSE2}, - /*1376*/ {I_PSUBSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE9\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1377*/ {I_PSUBSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE9\110", IF_WILLAMETTE|IF_SSE2}, - /*1378*/ {I_PSUBUSB, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD8\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1379*/ {I_PSUBUSB, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD8\110", IF_WILLAMETTE|IF_SSE2}, - /*1380*/ {I_PSUBUSW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD9\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1381*/ {I_PSUBUSW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD9\110", IF_WILLAMETTE|IF_SSE2}, - /*1382*/ {I_PUNPCKHBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x68\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1383*/ {I_PUNPCKHBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x68\110", IF_WILLAMETTE|IF_SSE2}, - /*1384*/ {I_PUNPCKHWD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x69\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1385*/ {I_PUNPCKHWD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x69\110", IF_WILLAMETTE|IF_SSE2}, - /*1386*/ {I_PUNPCKHDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6A\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1387*/ {I_PUNPCKHDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6A\110", IF_WILLAMETTE|IF_SSE2}, - /*1388*/ {I_PUNPCKHQDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6D\110", IF_WILLAMETTE|IF_SSE2}, - /*1389*/ {I_PUNPCKHQDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6D\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1390*/ {I_PUNPCKLBW, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x60\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1391*/ {I_PUNPCKLBW, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x60\110", IF_WILLAMETTE|IF_SSE2}, - /*1392*/ {I_PUNPCKLWD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x61\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1393*/ {I_PUNPCKLWD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x61\110", IF_WILLAMETTE|IF_SSE2}, - /*1394*/ {I_PUNPCKLDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x62\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1395*/ {I_PUNPCKLDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x62\110", IF_WILLAMETTE|IF_SSE2}, - /*1396*/ {I_PUNPCKLQDQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x6C\110", IF_WILLAMETTE|IF_SSE2}, - /*1397*/ {I_PUNPCKLQDQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x6C\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1398*/ {I_PXOR, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xEF\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1399*/ {I_PXOR, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xEF\110", IF_WILLAMETTE|IF_SSE2}, - /*1400*/ {I_ADDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x58\110", IF_WILLAMETTE|IF_SSE2}, - /*1401*/ {I_ADDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x58\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1402*/ {I_ADDSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\x58\110", IF_WILLAMETTE|IF_SSE2}, - /*1403*/ {I_ADDSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\x58\110", IF_WILLAMETTE|IF_SSE2}, - /*1404*/ {I_ANDNPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x55\110", IF_WILLAMETTE|IF_SSE2}, - /*1405*/ {I_ANDNPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x55\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1406*/ {I_ANDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x54\110", IF_WILLAMETTE|IF_SSE2}, - /*1407*/ {I_ANDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x54\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1408*/ {I_CMPEQPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1409*/ {I_CMPEQPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2}, - /*1410*/ {I_CMPEQSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2}, - /*1411*/ {I_CMPEQSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x00", IF_WILLAMETTE|IF_SSE2}, - /*1412*/ {I_CMPLEPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1413*/ {I_CMPLEPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2}, - /*1414*/ {I_CMPLESD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2}, - /*1415*/ {I_CMPLESD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x02", IF_WILLAMETTE|IF_SSE2}, - /*1416*/ {I_CMPLTPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1417*/ {I_CMPLTPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2}, - /*1418*/ {I_CMPLTSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2}, - /*1419*/ {I_CMPLTSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x01", IF_WILLAMETTE|IF_SSE2}, - /*1420*/ {I_CMPNEQPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1421*/ {I_CMPNEQPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2}, - /*1422*/ {I_CMPNEQSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2}, - /*1423*/ {I_CMPNEQSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x04", IF_WILLAMETTE|IF_SSE2}, - /*1424*/ {I_CMPNLEPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1425*/ {I_CMPNLEPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2}, - /*1426*/ {I_CMPNLESD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2}, - /*1427*/ {I_CMPNLESD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x06", IF_WILLAMETTE|IF_SSE2}, - /*1428*/ {I_CMPNLTPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1429*/ {I_CMPNLTPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2}, - /*1430*/ {I_CMPNLTSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2}, - /*1431*/ {I_CMPNLTSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x05", IF_WILLAMETTE|IF_SSE2}, - /*1432*/ {I_CMPORDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1433*/ {I_CMPORDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2}, - /*1434*/ {I_CMPORDSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2}, - /*1435*/ {I_CMPORDSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x07", IF_WILLAMETTE|IF_SSE2}, - /*1436*/ {I_CMPUNORDPD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1437*/ {I_CMPUNORDPD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2}, - /*1438*/ {I_CMPUNORDSD, 2, {XMMREG,MEMORY,0}, "\301\331\3\xF2\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2}, - /*1439*/ {I_CMPUNORDSD, 2, {XMMREG,XMMREG,0}, "\331\3\xF2\x0F\xC2\110\1\x03", IF_WILLAMETTE|IF_SSE2}, - /*1440*/ {I_CMPPD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\331\3\x66\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - /*1441*/ {I_CMPPD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\331\3\x66\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SM2|IF_SB|IF_AR2}, - /*1442*/ {I_CMPSD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\331\3\xF2\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - /*1443*/ {I_CMPSD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\331\3\xF2\x0F\xC2\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - /*1444*/ {I_COMISD, 2, {XMMREG,XMMREG,0}, "\331\3\x66\x0F\x2F\110", IF_WILLAMETTE|IF_SSE2}, - /*1445*/ {I_COMISD, 2, {XMMREG,MEMORY,0}, "\301\331\3\x66\x0F\x2F\110", IF_WILLAMETTE|IF_SSE2}, - /*1446*/ {I_CVTDQ2PD, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, - /*1447*/ {I_CVTDQ2PD, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, - /*1448*/ {I_CVTDQ2PS, 2, {XMMREG,XMMREG,0}, "\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2}, - /*1449*/ {I_CVTDQ2PS, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1450*/ {I_CVTPD2DQ, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, - /*1451*/ {I_CVTPD2DQ, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1452*/ {I_CVTPD2PI, 2, {MMXREG,XMMREG,0}, "\3\x66\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, - /*1453*/ {I_CVTPD2PI, 2, {MMXREG,MEMORY,0}, "\301\3\x66\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, - /*1454*/ {I_CVTPD2PS, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - /*1455*/ {I_CVTPD2PS, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1456*/ {I_CVTPI2PD, 2, {XMMREG,MMXREG,0}, "\3\x66\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, - /*1457*/ {I_CVTPI2PD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, - /*1458*/ {I_CVTPS2DQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2}, - /*1459*/ {I_CVTPS2DQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1460*/ {I_CVTPS2PD, 2, {XMMREG,XMMREG,0}, "\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - /*1461*/ {I_CVTPS2PD, 2, {XMMREG,MEMORY,0}, "\301\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - /*1462*/ {I_CVTSD2SI, 2, {REG32,XMMREG,0}, "\3\xF2\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, - /*1463*/ {I_CVTSD2SI, 2, {REG32,MEMORY,0}, "\301\3\xF2\x0F\x2D\110", IF_WILLAMETTE|IF_SSE2}, - /*1464*/ {I_CVTSD2SS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - /*1465*/ {I_CVTSD2SS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - /*1466*/ {I_CVTSI2SD, 2, {XMMREG,REG32,0}, "\3\xF2\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, - /*1467*/ {I_CVTSI2SD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x2A\110", IF_WILLAMETTE|IF_SSE2}, - /*1468*/ {I_CVTSS2SD, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - /*1469*/ {I_CVTSS2SD, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5A\110", IF_WILLAMETTE|IF_SSE2}, - /*1470*/ {I_CVTTPD2PI, 2, {MMXREG,XMMREG,0}, "\3\x66\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, - /*1471*/ {I_CVTTPD2PI, 2, {MMXREG,MEMORY,0}, "\301\3\x66\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, - /*1472*/ {I_CVTTPD2DQ, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2}, - /*1473*/ {I_CVTTPD2DQ, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xE6\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1474*/ {I_CVTTPS2DQ, 2, {XMMREG,XMMREG,0}, "\333\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2}, - /*1475*/ {I_CVTTPS2DQ, 2, {XMMREG,MEMORY,0}, "\301\333\2\x0F\x5B\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1476*/ {I_CVTTSD2SI, 2, {REG32,XMMREG,0}, "\3\xF2\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, - /*1477*/ {I_CVTTSD2SI, 2, {REG32,MEMORY,0}, "\301\3\xF2\x0F\x2C\110", IF_WILLAMETTE|IF_SSE2}, - /*1478*/ {I_DIVPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2}, - /*1479*/ {I_DIVPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1480*/ {I_DIVSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2}, - /*1481*/ {I_DIVSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5E\110", IF_WILLAMETTE|IF_SSE2}, - /*1482*/ {I_MAXPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2}, - /*1483*/ {I_MAXPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1484*/ {I_MAXSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2}, - /*1485*/ {I_MAXSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5F\110", IF_WILLAMETTE|IF_SSE2}, - /*1486*/ {I_MINPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2}, - /*1487*/ {I_MINPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1488*/ {I_MINSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2}, - /*1489*/ {I_MINSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5D\110", IF_WILLAMETTE|IF_SSE2}, - /*1490*/ {I_MOVAPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x28\110", IF_WILLAMETTE|IF_SSE2}, - /*1491*/ {I_MOVAPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x29\110", IF_WILLAMETTE|IF_SSE2}, - /*1492*/ {I_MOVAPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x29\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1493*/ {I_MOVAPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x28\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1494*/ {I_MOVHPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x17\101", IF_WILLAMETTE|IF_SSE2}, - /*1495*/ {I_MOVHPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x16\110", IF_WILLAMETTE|IF_SSE2}, - /*1496*/ {I_MOVLPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x13\101", IF_WILLAMETTE|IF_SSE2}, - /*1497*/ {I_MOVLPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x12\110", IF_WILLAMETTE|IF_SSE2}, - /*1498*/ {I_MOVMSKPD, 2, {REG32,XMMREG,0}, "\3\x66\x0F\x50\110", IF_WILLAMETTE|IF_SSE2}, - /*1499*/ {I_MOVSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x10\110", IF_WILLAMETTE|IF_SSE2}, - /*1500*/ {I_MOVSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x11\110", IF_WILLAMETTE|IF_SSE2}, - /*1501*/ {I_MOVSD, 2, {MEMORY,XMMREG,0}, "\300\3\xF2\x0F\x11\101", IF_WILLAMETTE|IF_SSE2}, - /*1502*/ {I_MOVSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x10\110", IF_WILLAMETTE|IF_SSE2}, - /*1503*/ {I_MOVUPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x10\110", IF_WILLAMETTE|IF_SSE2}, - /*1504*/ {I_MOVUPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x11\110", IF_WILLAMETTE|IF_SSE2}, - /*1505*/ {I_MOVUPD, 2, {MEMORY,XMMREG,0}, "\300\3\x66\x0F\x11\101", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1506*/ {I_MOVUPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x10\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1507*/ {I_MULPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x59\110", IF_WILLAMETTE|IF_SSE2}, - /*1508*/ {I_MULPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x59\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1509*/ {I_MULSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x59\110", IF_WILLAMETTE|IF_SSE2}, - /*1510*/ {I_MULSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x59\110", IF_WILLAMETTE|IF_SSE2}, - /*1511*/ {I_ORPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x56\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1512*/ {I_ORPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x56\110", IF_WILLAMETTE|IF_SSE2}, - /*1513*/ {I_SHUFPD, 3, {XMMREG,XMMREG,IMMEDIATE}, "\3\x66\x0F\xC6\110\26", IF_WILLAMETTE|IF_SSE2|IF_SB|IF_AR2}, - /*1514*/ {I_SHUFPD, 3, {XMMREG,MEMORY,IMMEDIATE}, "\301\3\x66\x0F\xC6\110\26", IF_WILLAMETTE|IF_SSE2|IF_SM|IF_SB|IF_AR2}, - /*1515*/ {I_SQRTPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x51\110", IF_WILLAMETTE|IF_SSE2}, - /*1516*/ {I_SQRTPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x51\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1517*/ {I_SQRTSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x51\110", IF_WILLAMETTE|IF_SSE2}, - /*1518*/ {I_SQRTSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x51\110", IF_WILLAMETTE|IF_SSE2}, - /*1519*/ {I_SUBPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2}, - /*1520*/ {I_SUBPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1521*/ {I_SUBSD, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2}, - /*1522*/ {I_SUBSD, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x5C\110", IF_WILLAMETTE|IF_SSE2}, - /*1523*/ {I_UCOMISD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x2E\110", IF_WILLAMETTE|IF_SSE2}, - /*1524*/ {I_UCOMISD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x2E\110", IF_WILLAMETTE|IF_SSE2}, - /*1525*/ {I_UNPCKHPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x15\110", IF_WILLAMETTE|IF_SSE2}, - /*1526*/ {I_UNPCKHPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x15\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1527*/ {I_UNPCKLPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x14\110", IF_WILLAMETTE|IF_SSE2}, - /*1528*/ {I_UNPCKLPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x14\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1529*/ {I_XORPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x57\110", IF_WILLAMETTE|IF_SSE2}, - /*1530*/ {I_XORPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x57\110", IF_WILLAMETTE|IF_SSE2|IF_SM}, - /*1531*/ {I_ADDSUBPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\xD0\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - /*1532*/ {I_ADDSUBPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\xD0\110", IF_PRESCOTT|IF_SSE3}, - /*1533*/ {I_ADDSUBPS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\xD0\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - /*1534*/ {I_ADDSUBPS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\xD0\110", IF_PRESCOTT|IF_SSE3}, - /*1535*/ {I_HADDPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x7C\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - /*1536*/ {I_HADDPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x7C\110", IF_PRESCOTT|IF_SSE3}, - /*1537*/ {I_HADDPS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x7C\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - /*1538*/ {I_HADDPS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x7C\110", IF_PRESCOTT|IF_SSE3}, - /*1539*/ {I_HSUBPD, 2, {XMMREG,MEMORY,0}, "\301\3\x66\x0F\x7D\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - /*1540*/ {I_HSUBPD, 2, {XMMREG,XMMREG,0}, "\3\x66\x0F\x7D\110", IF_PRESCOTT|IF_SSE3}, - /*1541*/ {I_HSUBPS, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x7D\110", IF_PRESCOTT|IF_SSE3|IF_SM}, - /*1542*/ {I_HSUBPS, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x7D\110", IF_PRESCOTT|IF_SSE3}, - /*1543*/ {I_LDDQU, 2, {XMMREG,MEMORY,0}, "\3\xF2\x0F\xF0\110", IF_PRESCOTT|IF_SSE3}, - /*1544*/ {I_MOVDDUP, 2, {XMMREG,MEMORY,0}, "\301\3\xF2\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, - /*1545*/ {I_MOVDDUP, 2, {XMMREG,XMMREG,0}, "\3\xF2\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, - /*1546*/ {I_MOVSHDUP, 2, {XMMREG,MEMORY,0}, "\301\3\xF3\x0F\x16\110", IF_PRESCOTT|IF_SSE3}, - /*1547*/ {I_MOVSHDUP, 2, {XMMREG,XMMREG,0}, "\3\xF3\x0F\x16\110", IF_PRESCOTT|IF_SSE3}, - /*1548*/ {I_MOVSLDUP, 2, {XMMREG,MEMORY,0}, "\301\3\xF3\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, - /*1549*/ {I_MOVSLDUP, 2, {XMMREG,XMMREG,0}, "\3\xF3\x0F\x12\110", IF_PRESCOTT|IF_SSE3}, - - /*1550 23*/ {I_ADC, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\202\21", IF_8086|IF_SM}, - /*1551 26*/ {I_ADC, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\202\21", IF_8086|IF_SM}, - /*1552 46*/ {I_ADD, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\200\21", IF_8086|IF_SM}, - /*1553 49*/ {I_ADD, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\200\21", IF_8086|IF_SM}, - /*1554 69*/ {I_AND, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\204\21", IF_8086|IF_SM}, - /*1555 72*/ {I_AND, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\204\21", IF_8086|IF_SM}, - /*1556 158*/ {I_CMP, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\207\21", IF_8086|IF_SM}, - /*1557 161*/ {I_CMP, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\207\21", IF_8086|IF_SM}, - /*1558 595*/ {I_OR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\201\21", IF_8086|IF_SM}, - /*1559 598*/ {I_OR, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\201\21", IF_8086|IF_SM}, - /*1560 872*/ {I_SBB, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\203\21", IF_8086|IF_SM}, - /*1561 875*/ {I_SBB, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\203\21", IF_8086|IF_SM}, - /*1562 954*/ {I_SUB, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\205\21", IF_8086|IF_SM}, - /*1563 957*/ {I_SUB, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\205\21", IF_8086|IF_SM}, - /*1564 1052*/ {I_XOR, 2, {REGMEM|BITS8,IMMEDIATE,0}, "\300\1\x82\206\21", IF_8086|IF_SM}, - /*1565 1055*/ {I_XOR, 2, {MEMORY,IMMEDIATE|BITS8,0}, "\300\1\x82\206\21", IF_8086|IF_SM}, - - /*1566*/ ITEMPLATE_END -}; - -static struct itemplate *itable_00[] = { - instrux + 29, - instrux + 30, - NULL -}; - -static struct itemplate *itable_01[] = { - instrux + 31, - instrux + 32, - instrux + 33, - instrux + 34, - NULL -}; - -static struct itemplate *itable_02[] = { - instrux + 35, - instrux + 36, - NULL -}; - -static struct itemplate *itable_03[] = { - instrux + 37, - instrux + 38, - instrux + 39, - instrux + 40, - NULL -}; - -static struct itemplate *itable_04[] = { - instrux + 43, - NULL -}; - -static struct itemplate *itable_05[] = { - instrux + 44, - instrux + 45, - NULL -}; - -static struct itemplate *itable_06[] = { - instrux + 778, - instrux + 779, - NULL -}; - -static struct itemplate *itable_07[] = { - instrux + 710, - NULL -}; - -static struct itemplate *itable_08[] = { - instrux + 578, - instrux + 579, - NULL -}; - -static struct itemplate *itable_09[] = { - instrux + 580, - instrux + 581, - instrux + 582, - instrux + 583, - NULL -}; - -static struct itemplate *itable_0A[] = { - instrux + 584, - instrux + 585, - NULL -}; - -static struct itemplate *itable_0B[] = { - instrux + 586, - instrux + 587, - instrux + 588, - instrux + 589, - NULL -}; - -static struct itemplate *itable_0C[] = { - instrux + 592, - NULL -}; - -static struct itemplate *itable_0D[] = { - instrux + 593, - instrux + 594, - NULL -}; - -static struct itemplate *itable_0E[] = { - instrux + 778, - instrux + 779, - NULL -}; - -static struct itemplate *itable_0F[] = { - instrux + 79, - instrux + 80, - instrux + 81, - instrux + 82, - instrux + 83, - instrux + 84, - instrux + 85, - instrux + 86, - instrux + 87, - instrux + 88, - instrux + 89, - instrux + 90, - instrux + 91, - instrux + 92, - instrux + 93, - instrux + 94, - instrux + 95, - instrux + 96, - instrux + 97, - instrux + 98, - instrux + 99, - instrux + 100, - instrux + 101, - instrux + 102, - instrux + 103, - instrux + 104, - instrux + 105, - instrux + 106, - instrux + 107, - instrux + 108, - instrux + 109, - instrux + 110, - instrux + 111, - instrux + 139, - instrux + 167, - instrux + 168, - instrux + 169, - instrux + 170, - instrux + 171, - instrux + 172, - instrux + 173, - instrux + 174, - instrux + 175, - instrux + 176, - instrux + 177, - instrux + 178, - instrux + 179, - instrux + 180, - instrux + 193, - instrux + 261, - instrux + 389, - instrux + 390, - instrux + 391, - instrux + 392, - instrux + 423, - instrux + 424, - instrux + 450, - instrux + 451, - instrux + 452, - instrux + 453, - instrux + 454, - instrux + 456, - instrux + 457, - instrux + 458, - instrux + 459, - instrux + 467, - instrux + 468, - instrux + 469, - instrux + 470, - instrux + 471, - instrux + 472, - instrux + 473, - instrux + 474, - instrux + 475, - instrux + 476, - instrux + 477, - instrux + 478, - instrux + 479, - instrux + 480, - instrux + 499, - instrux + 500, - instrux + 501, - instrux + 502, - instrux + 503, - instrux + 504, - instrux + 505, - instrux + 506, - instrux + 507, - instrux + 508, - instrux + 521, - instrux + 522, - instrux + 523, - instrux + 524, - instrux + 525, - instrux + 526, - instrux + 548, - instrux + 549, - instrux + 550, - instrux + 551, - instrux + 552, - instrux + 553, - instrux + 554, - instrux + 555, - instrux + 559, - instrux + 560, - instrux + 561, - instrux + 562, - instrux + 563, - instrux + 564, - instrux + 565, - instrux + 566, - instrux + 570, - instrux + 610, - instrux + 611, - instrux + 612, - instrux + 613, - instrux + 614, - instrux + 615, - instrux + 616, - instrux + 617, - instrux + 618, - instrux + 619, - instrux + 620, - instrux + 621, - instrux + 622, - instrux + 623, - instrux + 624, - instrux + 625, - instrux + 626, - instrux + 627, - instrux + 628, - instrux + 629, - instrux + 630, - instrux + 631, - instrux + 632, - instrux + 633, - instrux + 634, - instrux + 635, - instrux + 636, - instrux + 637, - instrux + 638, - instrux + 639, - instrux + 640, - instrux + 641, - instrux + 642, - instrux + 643, - instrux + 644, - instrux + 645, - instrux + 646, - instrux + 647, - instrux + 648, - instrux + 649, - instrux + 650, - instrux + 651, - instrux + 652, - instrux + 653, - instrux + 654, - instrux + 655, - instrux + 656, - instrux + 657, - instrux + 658, - instrux + 659, - instrux + 660, - instrux + 661, - instrux + 662, - instrux + 663, - instrux + 664, - instrux + 665, - instrux + 666, - instrux + 667, - instrux + 668, - instrux + 669, - instrux + 670, - instrux + 671, - instrux + 672, - instrux + 673, - instrux + 674, - instrux + 675, - instrux + 676, - instrux + 677, - instrux + 678, - instrux + 679, - instrux + 680, - instrux + 681, - instrux + 682, - instrux + 683, - instrux + 684, - instrux + 685, - instrux + 686, - instrux + 687, - instrux + 688, - instrux + 689, - instrux + 690, - instrux + 691, - instrux + 692, - instrux + 693, - instrux + 694, - instrux + 695, - instrux + 696, - instrux + 697, - instrux + 698, - instrux + 699, - instrux + 700, - instrux + 701, - instrux + 702, - instrux + 703, - instrux + 704, - instrux + 705, - instrux + 711, - instrux + 718, - instrux + 719, - instrux + 720, - instrux + 721, - instrux + 722, - instrux + 723, - instrux + 724, - instrux + 725, - instrux + 726, - instrux + 727, - instrux + 728, - instrux + 729, - instrux + 730, - instrux + 731, - instrux + 732, - instrux + 733, - instrux + 734, - instrux + 735, - instrux + 736, - instrux + 737, - instrux + 738, - instrux + 739, - instrux + 740, - instrux + 741, - instrux + 742, - instrux + 743, - instrux + 744, - instrux + 745, - instrux + 746, - instrux + 747, - instrux + 748, - instrux + 749, - instrux + 750, - instrux + 751, - instrux + 752, - instrux + 753, - instrux + 754, - instrux + 755, - instrux + 756, - instrux + 757, - instrux + 758, - instrux + 759, - instrux + 760, - instrux + 761, - instrux + 762, - instrux + 763, - instrux + 764, - instrux + 765, - instrux + 766, - instrux + 767, - instrux + 768, - instrux + 769, - instrux + 770, - instrux + 771, - instrux + 772, - instrux + 773, - instrux + 780, - instrux + 791, - instrux + 792, - instrux + 811, - instrux + 812, - instrux + 813, - instrux + 814, - instrux + 840, - instrux + 841, - instrux + 842, - instrux + 843, - instrux + 881, - instrux + 891, - instrux + 892, - instrux + 893, - instrux + 894, - instrux + 895, - instrux + 896, - instrux + 897, - instrux + 898, - instrux + 908, - instrux + 909, - instrux + 910, - instrux + 911, - instrux + 912, - instrux + 913, - instrux + 914, - instrux + 915, - instrux + 916, - instrux + 917, - instrux + 918, - instrux + 919, - instrux + 920, - instrux + 922, - instrux + 923, - instrux + 924, - instrux + 925, - instrux + 926, - instrux + 933, - instrux + 934, - instrux + 935, - instrux + 936, - instrux + 960, - instrux + 961, - instrux + 962, - instrux + 963, - instrux + 964, - instrux + 965, - instrux + 966, - instrux + 985, - instrux + 986, - instrux + 987, - instrux + 988, - instrux + 989, - instrux + 990, - instrux + 991, - instrux + 992, - instrux + 993, - instrux + 994, - instrux + 995, - instrux + 996, - instrux + 997, - instrux + 998, - instrux + 999, - instrux + 1000, - instrux + 1001, - instrux + 1002, - instrux + 1003, - instrux + 1004, - instrux + 1005, - instrux + 1008, - instrux + 1009, - instrux + 1010, - instrux + 1011, - instrux + 1012, - instrux + 1013, - instrux + 1014, - instrux + 1015, - instrux + 1016, - instrux + 1058, - instrux + 1059, - instrux + 1060, - instrux + 1061, - instrux + 1062, - instrux + 1063, - instrux + 1064, - instrux + 1065, - instrux + 1067, - instrux + 1068, - instrux + 1069, - instrux + 1070, - instrux + 1071, - instrux + 1072, - instrux + 1073, - instrux + 1074, - instrux + 1075, - instrux + 1076, - instrux + 1077, - instrux + 1078, - instrux + 1079, - instrux + 1080, - instrux + 1081, - instrux + 1082, - instrux + 1083, - instrux + 1084, - instrux + 1085, - instrux + 1086, - instrux + 1087, - instrux + 1088, - instrux + 1089, - instrux + 1090, - instrux + 1091, - instrux + 1092, - instrux + 1093, - instrux + 1094, - instrux + 1095, - instrux + 1096, - instrux + 1097, - instrux + 1098, - instrux + 1099, - instrux + 1100, - instrux + 1101, - instrux + 1102, - instrux + 1103, - instrux + 1104, - instrux + 1105, - instrux + 1106, - instrux + 1107, - instrux + 1108, - instrux + 1109, - instrux + 1110, - instrux + 1111, - instrux + 1112, - instrux + 1113, - instrux + 1114, - instrux + 1115, - instrux + 1116, - instrux + 1117, - instrux + 1118, - instrux + 1119, - instrux + 1120, - instrux + 1121, - instrux + 1122, - instrux + 1123, - instrux + 1124, - instrux + 1125, - instrux + 1126, - instrux + 1127, - instrux + 1128, - instrux + 1129, - instrux + 1130, - instrux + 1131, - instrux + 1132, - instrux + 1133, - instrux + 1134, - instrux + 1135, - instrux + 1136, - instrux + 1137, - instrux + 1138, - instrux + 1139, - instrux + 1140, - instrux + 1141, - instrux + 1142, - instrux + 1143, - instrux + 1144, - instrux + 1145, - instrux + 1146, - instrux + 1147, - instrux + 1148, - instrux + 1149, - instrux + 1150, - instrux + 1151, - instrux + 1152, - instrux + 1153, - instrux + 1154, - instrux + 1155, - instrux + 1156, - instrux + 1157, - instrux + 1158, - instrux + 1159, - instrux + 1160, - instrux + 1161, - instrux + 1162, - instrux + 1163, - instrux + 1164, - instrux + 1165, - instrux + 1166, - instrux + 1167, - instrux + 1168, - instrux + 1169, - instrux + 1170, - instrux + 1171, - instrux + 1172, - instrux + 1173, - instrux + 1174, - instrux + 1175, - instrux + 1176, - instrux + 1177, - instrux + 1178, - instrux + 1179, - instrux + 1180, - instrux + 1181, - instrux + 1182, - instrux + 1183, - instrux + 1184, - instrux + 1185, - instrux + 1186, - instrux + 1187, - instrux + 1188, - instrux + 1189, - instrux + 1190, - instrux + 1191, - instrux + 1192, - instrux + 1193, - instrux + 1194, - instrux + 1195, - instrux + 1196, - instrux + 1197, - instrux + 1198, - instrux + 1199, - instrux + 1200, - instrux + 1201, - instrux + 1202, - instrux + 1203, - instrux + 1204, - instrux + 1205, - instrux + 1206, - instrux + 1207, - instrux + 1208, - instrux + 1209, - instrux + 1210, - instrux + 1211, - instrux + 1212, - instrux + 1213, - instrux + 1214, - instrux + 1215, - instrux + 1216, - instrux + 1217, - instrux + 1218, - instrux + 1219, - instrux + 1220, - instrux + 1221, - instrux + 1222, - instrux + 1223, - instrux + 1224, - instrux + 1225, - instrux + 1226, - instrux + 1227, - instrux + 1228, - instrux + 1229, - instrux + 1230, - instrux + 1231, - instrux + 1232, - instrux + 1233, - instrux + 1235, - instrux + 1237, - instrux + 1240, - instrux + 1241, - instrux + 1250, - instrux + 1251, - instrux + 1252, - instrux + 1253, - instrux + 1255, - instrux + 1258, - instrux + 1259, - instrux + 1272, - instrux + 1273, - instrux + 1324, - instrux + 1325, - instrux + 1334, - instrux + 1335, - instrux + 1370, - instrux + 1371, - instrux + 1446, - instrux + 1447, - instrux + 1448, - instrux + 1449, - instrux + 1460, - instrux + 1461, - instrux + 1468, - instrux + 1469, - instrux + 1474, - instrux + 1475, - NULL -}; - -static struct itemplate *itable_10[] = { - instrux + 6, - instrux + 7, - NULL -}; - -static struct itemplate *itable_11[] = { - instrux + 8, - instrux + 9, - instrux + 10, - instrux + 11, - NULL -}; - -static struct itemplate *itable_12[] = { - instrux + 12, - instrux + 13, - NULL -}; - -static struct itemplate *itable_13[] = { - instrux + 14, - instrux + 15, - instrux + 16, - instrux + 17, - NULL -}; - -static struct itemplate *itable_14[] = { - instrux + 20, - NULL -}; - -static struct itemplate *itable_15[] = { - instrux + 21, - instrux + 22, - NULL -}; - -static struct itemplate *itable_16[] = { - instrux + 778, - instrux + 779, - NULL -}; - -static struct itemplate *itable_17[] = { - instrux + 710, - NULL -}; - -static struct itemplate *itable_18[] = { - instrux + 855, - instrux + 856, - NULL -}; - -static struct itemplate *itable_19[] = { - instrux + 857, - instrux + 858, - instrux + 859, - instrux + 860, - NULL -}; - -static struct itemplate *itable_1A[] = { - instrux + 861, - instrux + 862, - NULL -}; - -static struct itemplate *itable_1B[] = { - instrux + 863, - instrux + 864, - instrux + 865, - instrux + 866, - NULL -}; - -static struct itemplate *itable_1C[] = { - instrux + 869, - NULL -}; - -static struct itemplate *itable_1D[] = { - instrux + 870, - instrux + 871, - NULL -}; - -static struct itemplate *itable_1E[] = { - instrux + 778, - instrux + 779, - NULL -}; - -static struct itemplate *itable_1F[] = { - instrux + 710, - NULL -}; - -static struct itemplate *itable_20[] = { - instrux + 52, - instrux + 53, - NULL -}; - -static struct itemplate *itable_21[] = { - instrux + 54, - instrux + 55, - instrux + 56, - instrux + 57, - NULL -}; - -static struct itemplate *itable_22[] = { - instrux + 58, - instrux + 59, - NULL -}; - -static struct itemplate *itable_23[] = { - instrux + 60, - instrux + 61, - instrux + 62, - instrux + 63, - NULL -}; - -static struct itemplate *itable_24[] = { - instrux + 66, - NULL -}; - -static struct itemplate *itable_25[] = { - instrux + 67, - instrux + 68, - NULL -}; - -static struct itemplate *itable_26[] = { - NULL -}; - -static struct itemplate *itable_27[] = { - instrux + 183, - NULL -}; - -static struct itemplate *itable_28[] = { - instrux + 937, - instrux + 938, - NULL -}; - -static struct itemplate *itable_29[] = { - instrux + 939, - instrux + 940, - instrux + 941, - instrux + 942, - NULL -}; - -static struct itemplate *itable_2A[] = { - instrux + 943, - instrux + 944, - NULL -}; - -static struct itemplate *itable_2B[] = { - instrux + 945, - instrux + 946, - instrux + 947, - instrux + 948, - NULL -}; - -static struct itemplate *itable_2C[] = { - instrux + 951, - NULL -}; - -static struct itemplate *itable_2D[] = { - instrux + 952, - instrux + 953, - NULL -}; - -static struct itemplate *itable_2E[] = { - NULL -}; - -static struct itemplate *itable_2F[] = { - instrux + 184, - NULL -}; - -static struct itemplate *itable_30[] = { - instrux + 1035, - instrux + 1036, - NULL -}; - -static struct itemplate *itable_31[] = { - instrux + 1037, - instrux + 1038, - instrux + 1039, - instrux + 1040, - NULL -}; - -static struct itemplate *itable_32[] = { - instrux + 1041, - instrux + 1042, - NULL -}; - -static struct itemplate *itable_33[] = { - instrux + 1043, - instrux + 1044, - instrux + 1045, - instrux + 1046, - NULL -}; - -static struct itemplate *itable_34[] = { - instrux + 1049, - NULL -}; - -static struct itemplate *itable_35[] = { - instrux + 1050, - instrux + 1051, - NULL -}; - -static struct itemplate *itable_36[] = { - NULL -}; - -static struct itemplate *itable_37[] = { - instrux + 0, - NULL -}; - -static struct itemplate *itable_38[] = { - instrux + 141, - instrux + 142, - NULL -}; - -static struct itemplate *itable_39[] = { - instrux + 143, - instrux + 144, - instrux + 145, - instrux + 146, - NULL -}; - -static struct itemplate *itable_3A[] = { - instrux + 147, - instrux + 148, - NULL -}; - -static struct itemplate *itable_3B[] = { - instrux + 149, - instrux + 150, - instrux + 151, - instrux + 152, - NULL -}; - -static struct itemplate *itable_3C[] = { - instrux + 155, - NULL -}; - -static struct itemplate *itable_3D[] = { - instrux + 156, - instrux + 157, - NULL -}; - -static struct itemplate *itable_3E[] = { - NULL -}; - -static struct itemplate *itable_3F[] = { - instrux + 5, - NULL -}; - -static struct itemplate *itable_40[] = { - instrux + 411, - instrux + 412, - NULL -}; - -static struct itemplate *itable_41[] = { - instrux + 411, - instrux + 412, - NULL -}; - -static struct itemplate *itable_42[] = { - instrux + 411, - instrux + 412, - NULL -}; - -static struct itemplate *itable_43[] = { - instrux + 411, - instrux + 412, - NULL -}; - -static struct itemplate *itable_44[] = { - instrux + 411, - instrux + 412, - NULL -}; - -static struct itemplate *itable_45[] = { - instrux + 411, - instrux + 412, - NULL -}; - -static struct itemplate *itable_46[] = { - instrux + 411, - instrux + 412, - NULL -}; - -static struct itemplate *itable_47[] = { - instrux + 411, - instrux + 412, - NULL -}; - -static struct itemplate *itable_48[] = { - instrux + 185, - instrux + 186, - NULL -}; - -static struct itemplate *itable_49[] = { - instrux + 185, - instrux + 186, - NULL -}; - -static struct itemplate *itable_4A[] = { - instrux + 185, - instrux + 186, - NULL -}; - -static struct itemplate *itable_4B[] = { - instrux + 185, - instrux + 186, - NULL -}; - -static struct itemplate *itable_4C[] = { - instrux + 185, - instrux + 186, - NULL -}; - -static struct itemplate *itable_4D[] = { - instrux + 185, - instrux + 186, - NULL -}; - -static struct itemplate *itable_4E[] = { - instrux + 185, - instrux + 186, - NULL -}; - -static struct itemplate *itable_4F[] = { - instrux + 185, - instrux + 186, - NULL -}; - -static struct itemplate *itable_50[] = { - instrux + 774, - instrux + 775, - NULL -}; - -static struct itemplate *itable_51[] = { - instrux + 774, - instrux + 775, - NULL -}; - -static struct itemplate *itable_52[] = { - instrux + 774, - instrux + 775, - NULL -}; - -static struct itemplate *itable_53[] = { - instrux + 774, - instrux + 775, - NULL -}; - -static struct itemplate *itable_54[] = { - instrux + 774, - instrux + 775, - NULL -}; - -static struct itemplate *itable_55[] = { - instrux + 774, - instrux + 775, - NULL -}; - -static struct itemplate *itable_56[] = { - instrux + 774, - instrux + 775, - NULL -}; - -static struct itemplate *itable_57[] = { - instrux + 774, - instrux + 775, - NULL -}; - -static struct itemplate *itable_58[] = { - instrux + 706, - instrux + 707, - NULL -}; - -static struct itemplate *itable_59[] = { - instrux + 706, - instrux + 707, - NULL -}; - -static struct itemplate *itable_5A[] = { - instrux + 706, - instrux + 707, - NULL -}; - -static struct itemplate *itable_5B[] = { - instrux + 706, - instrux + 707, - NULL -}; - -static struct itemplate *itable_5C[] = { - instrux + 706, - instrux + 707, - NULL -}; - -static struct itemplate *itable_5D[] = { - instrux + 706, - instrux + 707, - NULL -}; - -static struct itemplate *itable_5E[] = { - instrux + 706, - instrux + 707, - NULL -}; - -static struct itemplate *itable_5F[] = { - instrux + 706, - instrux + 707, - NULL -}; - -static struct itemplate *itable_60[] = { - instrux + 785, - instrux + 786, - instrux + 787, - NULL -}; - -static struct itemplate *itable_61[] = { - instrux + 712, - instrux + 713, - instrux + 714, - NULL -}; - -static struct itemplate *itable_62[] = { - instrux + 77, - instrux + 78, - NULL -}; - -static struct itemplate *itable_63[] = { - instrux + 75, - instrux + 76, - NULL -}; - -static struct itemplate *itable_64[] = { - NULL -}; - -static struct itemplate *itable_65[] = { - NULL -}; - -static struct itemplate *itable_66[] = { - instrux + 1234, - instrux + 1236, - instrux + 1238, - instrux + 1242, - instrux + 1243, - instrux + 1244, - instrux + 1245, - instrux + 1246, - instrux + 1247, - instrux + 1248, - instrux + 1249, - instrux + 1256, - instrux + 1257, - instrux + 1260, - instrux + 1261, - instrux + 1262, - instrux + 1263, - instrux + 1264, - instrux + 1265, - instrux + 1266, - instrux + 1267, - instrux + 1268, - instrux + 1269, - instrux + 1270, - instrux + 1271, - instrux + 1274, - instrux + 1275, - instrux + 1276, - instrux + 1277, - instrux + 1278, - instrux + 1279, - instrux + 1280, - instrux + 1281, - instrux + 1282, - instrux + 1283, - instrux + 1284, - instrux + 1285, - instrux + 1286, - instrux + 1287, - instrux + 1288, - instrux + 1289, - instrux + 1290, - instrux + 1291, - instrux + 1292, - instrux + 1293, - instrux + 1294, - instrux + 1295, - instrux + 1296, - instrux + 1297, - instrux + 1298, - instrux + 1299, - instrux + 1300, - instrux + 1301, - instrux + 1302, - instrux + 1303, - instrux + 1304, - instrux + 1305, - instrux + 1306, - instrux + 1307, - instrux + 1308, - instrux + 1309, - instrux + 1310, - instrux + 1311, - instrux + 1312, - instrux + 1313, - instrux + 1314, - instrux + 1315, - instrux + 1316, - instrux + 1317, - instrux + 1318, - instrux + 1319, - instrux + 1320, - instrux + 1321, - instrux + 1322, - instrux + 1323, - instrux + 1326, - instrux + 1327, - instrux + 1328, - instrux + 1329, - instrux + 1330, - instrux + 1331, - instrux + 1332, - instrux + 1333, - instrux + 1338, - instrux + 1339, - instrux + 1340, - instrux + 1341, - instrux + 1342, - instrux + 1343, - instrux + 1344, - instrux + 1345, - instrux + 1346, - instrux + 1347, - instrux + 1348, - instrux + 1349, - instrux + 1350, - instrux + 1351, - instrux + 1352, - instrux + 1353, - instrux + 1354, - instrux + 1355, - instrux + 1356, - instrux + 1357, - instrux + 1358, - instrux + 1359, - instrux + 1360, - instrux + 1361, - instrux + 1362, - instrux + 1363, - instrux + 1364, - instrux + 1365, - instrux + 1366, - instrux + 1367, - instrux + 1368, - instrux + 1369, - instrux + 1372, - instrux + 1373, - instrux + 1374, - instrux + 1375, - instrux + 1376, - instrux + 1377, - instrux + 1378, - instrux + 1379, - instrux + 1380, - instrux + 1381, - instrux + 1382, - instrux + 1383, - instrux + 1384, - instrux + 1385, - instrux + 1386, - instrux + 1387, - instrux + 1388, - instrux + 1389, - instrux + 1390, - instrux + 1391, - instrux + 1392, - instrux + 1393, - instrux + 1394, - instrux + 1395, - instrux + 1396, - instrux + 1397, - instrux + 1398, - instrux + 1399, - instrux + 1400, - instrux + 1401, - instrux + 1404, - instrux + 1405, - instrux + 1406, - instrux + 1407, - instrux + 1408, - instrux + 1409, - instrux + 1412, - instrux + 1413, - instrux + 1416, - instrux + 1417, - instrux + 1420, - instrux + 1421, - instrux + 1424, - instrux + 1425, - instrux + 1428, - instrux + 1429, - instrux + 1432, - instrux + 1433, - instrux + 1436, - instrux + 1437, - instrux + 1440, - instrux + 1441, - instrux + 1444, - instrux + 1445, - instrux + 1452, - instrux + 1453, - instrux + 1454, - instrux + 1455, - instrux + 1456, - instrux + 1457, - instrux + 1458, - instrux + 1459, - instrux + 1470, - instrux + 1471, - instrux + 1472, - instrux + 1473, - instrux + 1478, - instrux + 1479, - instrux + 1482, - instrux + 1483, - instrux + 1486, - instrux + 1487, - instrux + 1490, - instrux + 1491, - instrux + 1492, - instrux + 1493, - instrux + 1494, - instrux + 1495, - instrux + 1496, - instrux + 1497, - instrux + 1498, - instrux + 1503, - instrux + 1504, - instrux + 1505, - instrux + 1506, - instrux + 1507, - instrux + 1508, - instrux + 1511, - instrux + 1512, - instrux + 1513, - instrux + 1514, - instrux + 1515, - instrux + 1516, - instrux + 1519, - instrux + 1520, - instrux + 1523, - instrux + 1524, - instrux + 1525, - instrux + 1526, - instrux + 1527, - instrux + 1528, - instrux + 1529, - instrux + 1530, - instrux + 1531, - instrux + 1532, - instrux + 1535, - instrux + 1536, - instrux + 1539, - instrux + 1540, - NULL -}; - -static struct itemplate *itable_67[] = { - NULL -}; - -static struct itemplate *itable_68[] = { - instrux + 782, - instrux + 783, - instrux + 784, - NULL -}; - -static struct itemplate *itable_69[] = { - instrux + 394, - instrux + 396, - instrux + 398, - instrux + 400, - instrux + 402, - instrux + 404, - NULL -}; - -static struct itemplate *itable_6A[] = { - instrux + 781, - NULL -}; - -static struct itemplate *itable_6B[] = { - instrux + 393, - instrux + 395, - instrux + 397, - instrux + 399, - instrux + 401, - instrux + 403, - NULL -}; - -static struct itemplate *itable_6C[] = { - instrux + 416, - NULL -}; - -static struct itemplate *itable_6D[] = { - instrux + 417, - instrux + 418, - NULL -}; - -static struct itemplate *itable_6E[] = { - instrux + 607, - NULL -}; - -static struct itemplate *itable_6F[] = { - instrux + 608, - instrux + 609, - NULL -}; - -static struct itemplate *itable_70[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_71[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_72[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_73[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_74[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_75[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_76[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_77[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_78[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_79[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_7A[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_7B[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_7C[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_7D[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_7E[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_7F[] = { - instrux + 1066, - NULL -}; - -static struct itemplate *itable_80[] = { - instrux + 23, - instrux + 26, - instrux + 46, - instrux + 49, - instrux + 69, - instrux + 72, - instrux + 158, - instrux + 161, - instrux + 595, - instrux + 598, - instrux + 872, - instrux + 875, - instrux + 954, - instrux + 957, - instrux + 1052, - instrux + 1055, - NULL -}; - -static struct itemplate *itable_81[] = { - instrux + 24, - instrux + 25, - instrux + 27, - instrux + 28, - instrux + 47, - instrux + 48, - instrux + 50, - instrux + 51, - instrux + 70, - instrux + 71, - instrux + 73, - instrux + 74, - instrux + 159, - instrux + 160, - instrux + 162, - instrux + 163, - instrux + 596, - instrux + 597, - instrux + 599, - instrux + 600, - instrux + 873, - instrux + 874, - instrux + 876, - instrux + 877, - instrux + 955, - instrux + 956, - instrux + 958, - instrux + 959, - instrux + 1053, - instrux + 1054, - instrux + 1056, - instrux + 1057, - NULL -}; - -static struct itemplate *itable_82[] = { - instrux + 1550, - instrux + 1551, - instrux + 1552, - instrux + 1553, - instrux + 1554, - instrux + 1555, - instrux + 1556, - instrux + 1557, - instrux + 1558, - instrux + 1559, - instrux + 1560, - instrux + 1561, - instrux + 1562, - instrux + 1563, - instrux + 1564, - instrux + 1565, - NULL -}; - -static struct itemplate *itable_83[] = { - instrux + 18, - instrux + 19, - instrux + 41, - instrux + 42, - instrux + 64, - instrux + 65, - instrux + 153, - instrux + 154, - instrux + 590, - instrux + 591, - instrux + 867, - instrux + 868, - instrux + 949, - instrux + 950, - instrux + 1047, - instrux + 1048, - NULL -}; - -static struct itemplate *itable_84[] = { - instrux + 967, - instrux + 968, - instrux + 973, - NULL -}; - -static struct itemplate *itable_85[] = { - instrux + 969, - instrux + 970, - instrux + 971, - instrux + 972, - instrux + 974, - instrux + 975, - NULL -}; - -static struct itemplate *itable_86[] = { - instrux + 1021, - instrux + 1022, - instrux + 1027, - instrux + 1028, - NULL -}; - -static struct itemplate *itable_87[] = { - instrux + 1023, - instrux + 1024, - instrux + 1025, - instrux + 1026, - instrux + 1029, - instrux + 1030, - instrux + 1031, - instrux + 1032, - NULL -}; - -static struct itemplate *itable_88[] = { - instrux + 527, - instrux + 528, - NULL -}; - -static struct itemplate *itable_89[] = { - instrux + 529, - instrux + 530, - instrux + 531, - instrux + 532, - NULL -}; - -static struct itemplate *itable_8A[] = { - instrux + 533, - instrux + 534, - NULL -}; - -static struct itemplate *itable_8B[] = { - instrux + 535, - instrux + 536, - instrux + 537, - instrux + 538, - NULL -}; - -static struct itemplate *itable_8C[] = { - instrux + 509, - instrux + 510, - instrux + 511, - NULL -}; - -static struct itemplate *itable_8D[] = { - instrux + 462, - instrux + 463, - NULL -}; - -static struct itemplate *itable_8E[] = { - instrux + 512, - instrux + 513, - instrux + 514, - NULL -}; - -static struct itemplate *itable_8F[] = { - instrux + 708, - instrux + 709, - NULL -}; - -static struct itemplate *itable_90[] = { - instrux + 574, - instrux + 1017, - instrux + 1018, - instrux + 1019, - instrux + 1020, - instrux + 1239, - NULL -}; - -static struct itemplate *itable_91[] = { - instrux + 1017, - instrux + 1018, - instrux + 1019, - instrux + 1020, - NULL -}; - -static struct itemplate *itable_92[] = { - instrux + 1017, - instrux + 1018, - instrux + 1019, - instrux + 1020, - NULL -}; - -static struct itemplate *itable_93[] = { - instrux + 1017, - instrux + 1018, - instrux + 1019, - instrux + 1020, - NULL -}; - -static struct itemplate *itable_94[] = { - instrux + 1017, - instrux + 1018, - instrux + 1019, - instrux + 1020, - NULL -}; - -static struct itemplate *itable_95[] = { - instrux + 1017, - instrux + 1018, - instrux + 1019, - instrux + 1020, - NULL -}; - -static struct itemplate *itable_96[] = { - instrux + 1017, - instrux + 1018, - instrux + 1019, - instrux + 1020, - NULL -}; - -static struct itemplate *itable_97[] = { - instrux + 1017, - instrux + 1018, - instrux + 1019, - instrux + 1020, - NULL -}; - -static struct itemplate *itable_98[] = { - instrux + 134, - instrux + 182, - NULL -}; - -static struct itemplate *itable_99[] = { - instrux + 135, - instrux + 181, - NULL -}; - -static struct itemplate *itable_9A[] = { - instrux + 118, - instrux + 119, - instrux + 120, - instrux + 121, - instrux + 122, - NULL -}; - -static struct itemplate *itable_9B[] = { - instrux + 212, - instrux + 244, - instrux + 262, - instrux + 281, - instrux + 331, - instrux + 340, - instrux + 341, - instrux + 346, - instrux + 347, - instrux + 1006, - instrux + 1007, - NULL -}; - -static struct itemplate *itable_9C[] = { - instrux + 788, - instrux + 789, - instrux + 790, - NULL -}; - -static struct itemplate *itable_9D[] = { - instrux + 715, - instrux + 716, - instrux + 717, - NULL -}; - -static struct itemplate *itable_9E[] = { - instrux + 844, - NULL -}; - -static struct itemplate *itable_9F[] = { - instrux + 455, - NULL -}; - -static struct itemplate *itable_A0[] = { - instrux + 515, - NULL -}; - -static struct itemplate *itable_A1[] = { - instrux + 516, - instrux + 517, - NULL -}; - -static struct itemplate *itable_A2[] = { - instrux + 518, - NULL -}; - -static struct itemplate *itable_A3[] = { - instrux + 519, - instrux + 520, - NULL -}; - -static struct itemplate *itable_A4[] = { - instrux + 556, - NULL -}; - -static struct itemplate *itable_A5[] = { - instrux + 557, - instrux + 558, - NULL -}; - -static struct itemplate *itable_A6[] = { - instrux + 164, - NULL -}; - -static struct itemplate *itable_A7[] = { - instrux + 165, - instrux + 166, - NULL -}; - -static struct itemplate *itable_A8[] = { - instrux + 976, - NULL -}; - -static struct itemplate *itable_A9[] = { - instrux + 977, - instrux + 978, - NULL -}; - -static struct itemplate *itable_AA[] = { - instrux + 930, - NULL -}; - -static struct itemplate *itable_AB[] = { - instrux + 931, - instrux + 932, - NULL -}; - -static struct itemplate *itable_AC[] = { - instrux + 481, - NULL -}; - -static struct itemplate *itable_AD[] = { - instrux + 482, - instrux + 483, - NULL -}; - -static struct itemplate *itable_AE[] = { - instrux + 878, - NULL -}; - -static struct itemplate *itable_AF[] = { - instrux + 879, - instrux + 880, - NULL -}; - -static struct itemplate *itable_B0[] = { - instrux + 539, - NULL -}; - -static struct itemplate *itable_B1[] = { - instrux + 539, - NULL -}; - -static struct itemplate *itable_B2[] = { - instrux + 539, - NULL -}; - -static struct itemplate *itable_B3[] = { - instrux + 539, - NULL -}; - -static struct itemplate *itable_B4[] = { - instrux + 539, - NULL -}; - -static struct itemplate *itable_B5[] = { - instrux + 539, - NULL -}; - -static struct itemplate *itable_B6[] = { - instrux + 539, - NULL -}; - -static struct itemplate *itable_B7[] = { - instrux + 539, - NULL -}; - -static struct itemplate *itable_B8[] = { - instrux + 540, - instrux + 541, - NULL -}; - -static struct itemplate *itable_B9[] = { - instrux + 540, - instrux + 541, - NULL -}; - -static struct itemplate *itable_BA[] = { - instrux + 540, - instrux + 541, - NULL -}; - -static struct itemplate *itable_BB[] = { - instrux + 540, - instrux + 541, - NULL -}; - -static struct itemplate *itable_BC[] = { - instrux + 540, - instrux + 541, - NULL -}; - -static struct itemplate *itable_BD[] = { - instrux + 540, - instrux + 541, - NULL -}; - -static struct itemplate *itable_BE[] = { - instrux + 540, - instrux + 541, - NULL -}; - -static struct itemplate *itable_BF[] = { - instrux + 540, - instrux + 541, - NULL -}; - -static struct itemplate *itable_C0[] = { - instrux + 795, - instrux + 804, - instrux + 824, - instrux + 833, - instrux + 848, - instrux + 884, - instrux + 901, - NULL -}; - -static struct itemplate *itable_C1[] = { - instrux + 798, - instrux + 801, - instrux + 807, - instrux + 810, - instrux + 827, - instrux + 830, - instrux + 836, - instrux + 839, - instrux + 851, - instrux + 854, - instrux + 887, - instrux + 890, - instrux + 904, - instrux + 907, - NULL -}; - -static struct itemplate *itable_C2[] = { - instrux + 817, - instrux + 821, - NULL -}; - -static struct itemplate *itable_C3[] = { - instrux + 816, - instrux + 820, - NULL -}; - -static struct itemplate *itable_C4[] = { - instrux + 465, - instrux + 466, - NULL -}; - -static struct itemplate *itable_C5[] = { - instrux + 460, - instrux + 461, - NULL -}; - -static struct itemplate *itable_C6[] = { - instrux + 542, - instrux + 545, - NULL -}; - -static struct itemplate *itable_C7[] = { - instrux + 543, - instrux + 544, - instrux + 546, - instrux + 547, - NULL -}; - -static struct itemplate *itable_C8[] = { - instrux + 194, - NULL -}; - -static struct itemplate *itable_C9[] = { - instrux + 464, - NULL -}; - -static struct itemplate *itable_CA[] = { - instrux + 819, - NULL -}; - -static struct itemplate *itable_CB[] = { - instrux + 818, - NULL -}; - -static struct itemplate *itable_CC[] = { - instrux + 421, - NULL -}; - -static struct itemplate *itable_CD[] = { - instrux + 419, - NULL -}; - -static struct itemplate *itable_CE[] = { - instrux + 422, - NULL -}; - -static struct itemplate *itable_CF[] = { - instrux + 425, - instrux + 426, - instrux + 427, - NULL -}; - -static struct itemplate *itable_D0[] = { - instrux + 793, - instrux + 802, - instrux + 822, - instrux + 831, - instrux + 846, - instrux + 882, - instrux + 899, - NULL -}; - -static struct itemplate *itable_D1[] = { - instrux + 796, - instrux + 799, - instrux + 805, - instrux + 808, - instrux + 825, - instrux + 828, - instrux + 834, - instrux + 837, - instrux + 849, - instrux + 852, - instrux + 885, - instrux + 888, - instrux + 902, - instrux + 905, - NULL -}; - -static struct itemplate *itable_D2[] = { - instrux + 794, - instrux + 803, - instrux + 823, - instrux + 832, - instrux + 847, - instrux + 883, - instrux + 900, - NULL -}; - -static struct itemplate *itable_D3[] = { - instrux + 797, - instrux + 800, - instrux + 806, - instrux + 809, - instrux + 826, - instrux + 829, - instrux + 835, - instrux + 838, - instrux + 850, - instrux + 853, - instrux + 886, - instrux + 889, - instrux + 903, - instrux + 906, - NULL -}; - -static struct itemplate *itable_D4[] = { - instrux + 3, - instrux + 4, - NULL -}; - -static struct itemplate *itable_D5[] = { - instrux + 1, - instrux + 2, - NULL -}; - -static struct itemplate *itable_D6[] = { - instrux + 845, - NULL -}; - -static struct itemplate *itable_D7[] = { - instrux + 1033, - instrux + 1034, - NULL -}; - -static struct itemplate *itable_D8[] = { - instrux + 199, - instrux + 202, - instrux + 204, - instrux + 229, - instrux + 231, - instrux + 232, - instrux + 237, - instrux + 239, - instrux + 240, - instrux + 245, - instrux + 249, - instrux + 250, - instrux + 253, - instrux + 257, - instrux + 258, - instrux + 307, - instrux + 311, - instrux + 312, - instrux + 348, - instrux + 352, - instrux + 353, - instrux + 356, - instrux + 360, - instrux + 361, - NULL -}; - -static struct itemplate *itable_D9[] = { - instrux + 197, - instrux + 198, - instrux + 211, - instrux + 242, - instrux + 243, - instrux + 280, - instrux + 294, - instrux + 297, - instrux + 298, - instrux + 299, - instrux + 300, - instrux + 301, - instrux + 302, - instrux + 303, - instrux + 304, - instrux + 305, - instrux + 306, - instrux + 319, - instrux + 321, - instrux + 322, - instrux + 325, - instrux + 326, - instrux + 327, - instrux + 328, - instrux + 329, - instrux + 332, - instrux + 334, - instrux + 335, - instrux + 336, - instrux + 337, - instrux + 342, - instrux + 364, - instrux + 374, - instrux + 375, - instrux + 376, - instrux + 377, - instrux + 378, - instrux + 379, - instrux + 380, - instrux + 381, - NULL -}; - -static struct itemplate *itable_DA[] = { - instrux + 213, - instrux + 214, - instrux + 215, - instrux + 216, - instrux + 217, - instrux + 218, - instrux + 227, - instrux + 228, - instrux + 265, - instrux + 267, - instrux + 269, - instrux + 271, - instrux + 273, - instrux + 278, - instrux + 290, - instrux + 292, - instrux + 373, - NULL -}; - -static struct itemplate *itable_DB[] = { - instrux + 219, - instrux + 220, - instrux + 221, - instrux + 222, - instrux + 223, - instrux + 224, - instrux + 225, - instrux + 226, - instrux + 233, - instrux + 234, - instrux + 275, - instrux + 282, - instrux + 284, - instrux + 288, - instrux + 296, - instrux + 315, - instrux + 316, - instrux + 317, - instrux + 318, - instrux + 333, - instrux + 344, - instrux + 367, - instrux + 368, - NULL -}; - -static struct itemplate *itable_DC[] = { - instrux + 200, - instrux + 201, - instrux + 203, - instrux + 230, - instrux + 238, - instrux + 246, - instrux + 247, - instrux + 248, - instrux + 254, - instrux + 255, - instrux + 256, - instrux + 308, - instrux + 309, - instrux + 310, - instrux + 349, - instrux + 350, - instrux + 351, - instrux + 357, - instrux + 358, - instrux + 359, - NULL -}; - -static struct itemplate *itable_DD[] = { - instrux + 263, - instrux + 287, - instrux + 295, - instrux + 320, - instrux + 323, - instrux + 330, - instrux + 338, - instrux + 339, - instrux + 343, - instrux + 345, - instrux + 365, - instrux + 366, - instrux + 371, - instrux + 372, - NULL -}; - -static struct itemplate *itable_DE[] = { - instrux + 205, - instrux + 206, - instrux + 241, - instrux + 251, - instrux + 252, - instrux + 259, - instrux + 260, - instrux + 266, - instrux + 268, - instrux + 270, - instrux + 272, - instrux + 274, - instrux + 279, - instrux + 291, - instrux + 293, - instrux + 313, - instrux + 314, - instrux + 354, - instrux + 355, - instrux + 362, - instrux + 363, - NULL -}; - -static struct itemplate *itable_DF[] = { - instrux + 207, - instrux + 208, - instrux + 209, - instrux + 210, - instrux + 235, - instrux + 236, - instrux + 264, - instrux + 276, - instrux + 277, - instrux + 283, - instrux + 285, - instrux + 286, - instrux + 289, - instrux + 324, - instrux + 369, - instrux + 370, - NULL -}; - -static struct itemplate *itable_E0[] = { - instrux + 490, - instrux + 491, - instrux + 492, - instrux + 493, - instrux + 494, - instrux + 495, - NULL -}; - -static struct itemplate *itable_E1[] = { - instrux + 487, - instrux + 488, - instrux + 489, - instrux + 496, - instrux + 497, - instrux + 498, - NULL -}; - -static struct itemplate *itable_E2[] = { - instrux + 484, - instrux + 485, - instrux + 486, - NULL -}; - -static struct itemplate *itable_E3[] = { - instrux + 428, - instrux + 429, - NULL -}; - -static struct itemplate *itable_E4[] = { - instrux + 405, - NULL -}; - -static struct itemplate *itable_E5[] = { - instrux + 406, - instrux + 407, - NULL -}; - -static struct itemplate *itable_E6[] = { - instrux + 601, - NULL -}; - -static struct itemplate *itable_E7[] = { - instrux + 602, - instrux + 603, - NULL -}; - -static struct itemplate *itable_E8[] = { - instrux + 112, - instrux + 113, - instrux + 114, - instrux + 115, - instrux + 116, - instrux + 117, - NULL -}; - -static struct itemplate *itable_E9[] = { - instrux + 431, - instrux + 432, - instrux + 433, - NULL -}; - -static struct itemplate *itable_EA[] = { - instrux + 434, - instrux + 435, - instrux + 436, - instrux + 437, - instrux + 438, - NULL -}; - -static struct itemplate *itable_EB[] = { - instrux + 430, - NULL -}; - -static struct itemplate *itable_EC[] = { - instrux + 408, - NULL -}; - -static struct itemplate *itable_ED[] = { - instrux + 409, - instrux + 410, - NULL -}; - -static struct itemplate *itable_EE[] = { - instrux + 604, - NULL -}; - -static struct itemplate *itable_EF[] = { - instrux + 605, - instrux + 606, - NULL -}; - -static struct itemplate *itable_F0[] = { - NULL -}; - -static struct itemplate *itable_F1[] = { - instrux + 420, - instrux + 921, - NULL -}; - -static struct itemplate *itable_F2[] = { - instrux + 1254, - instrux + 1336, - instrux + 1337, - instrux + 1402, - instrux + 1403, - instrux + 1410, - instrux + 1411, - instrux + 1414, - instrux + 1415, - instrux + 1418, - instrux + 1419, - instrux + 1422, - instrux + 1423, - instrux + 1426, - instrux + 1427, - instrux + 1430, - instrux + 1431, - instrux + 1434, - instrux + 1435, - instrux + 1438, - instrux + 1439, - instrux + 1442, - instrux + 1443, - instrux + 1450, - instrux + 1451, - instrux + 1462, - instrux + 1463, - instrux + 1464, - instrux + 1465, - instrux + 1466, - instrux + 1467, - instrux + 1476, - instrux + 1477, - instrux + 1480, - instrux + 1481, - instrux + 1484, - instrux + 1485, - instrux + 1488, - instrux + 1489, - instrux + 1499, - instrux + 1500, - instrux + 1501, - instrux + 1502, - instrux + 1509, - instrux + 1510, - instrux + 1517, - instrux + 1518, - instrux + 1521, - instrux + 1522, - instrux + 1533, - instrux + 1534, - instrux + 1537, - instrux + 1538, - instrux + 1541, - instrux + 1542, - instrux + 1543, - instrux + 1544, - instrux + 1545, - NULL -}; - -static struct itemplate *itable_F3[] = { - instrux + 1546, - instrux + 1547, - instrux + 1548, - instrux + 1549, - NULL -}; - -static struct itemplate *itable_F4[] = { - instrux + 382, - NULL -}; - -static struct itemplate *itable_F5[] = { - instrux + 140, - NULL -}; - -static struct itemplate *itable_F6[] = { - instrux + 190, - instrux + 383, - instrux + 386, - instrux + 567, - instrux + 571, - instrux + 575, - instrux + 979, - instrux + 982, - NULL -}; - -static struct itemplate *itable_F7[] = { - instrux + 191, - instrux + 192, - instrux + 384, - instrux + 385, - instrux + 387, - instrux + 388, - instrux + 568, - instrux + 569, - instrux + 572, - instrux + 573, - instrux + 576, - instrux + 577, - instrux + 980, - instrux + 981, - instrux + 983, - instrux + 984, - NULL -}; - -static struct itemplate *itable_F8[] = { - instrux + 136, - NULL -}; - -static struct itemplate *itable_F9[] = { - instrux + 927, - NULL -}; - -static struct itemplate *itable_FA[] = { - instrux + 138, - NULL -}; - -static struct itemplate *itable_FB[] = { - instrux + 929, - NULL -}; - -static struct itemplate *itable_FC[] = { - instrux + 137, - NULL -}; - -static struct itemplate *itable_FD[] = { - instrux + 928, - NULL -}; - -static struct itemplate *itable_FE[] = { - instrux + 187, - instrux + 413, - NULL -}; - -static struct itemplate *itable_FF[] = { - instrux + 123, - instrux + 124, - instrux + 125, - instrux + 126, - instrux + 127, - instrux + 128, - instrux + 129, - instrux + 130, - instrux + 131, - instrux + 132, - instrux + 133, - instrux + 188, - instrux + 189, - instrux + 414, - instrux + 415, - instrux + 439, - instrux + 440, - instrux + 441, - instrux + 442, - instrux + 443, - instrux + 444, - instrux + 445, - instrux + 446, - instrux + 447, - instrux + 448, - instrux + 449, - instrux + 776, - instrux + 777, - NULL -}; - -struct itemplate **itable[] = { - itable_00, - itable_01, - itable_02, - itable_03, - itable_04, - itable_05, - itable_06, - itable_07, - itable_08, - itable_09, - itable_0A, - itable_0B, - itable_0C, - itable_0D, - itable_0E, - itable_0F, - itable_10, - itable_11, - itable_12, - itable_13, - itable_14, - itable_15, - itable_16, - itable_17, - itable_18, - itable_19, - itable_1A, - itable_1B, - itable_1C, - itable_1D, - itable_1E, - itable_1F, - itable_20, - itable_21, - itable_22, - itable_23, - itable_24, - itable_25, - itable_26, - itable_27, - itable_28, - itable_29, - itable_2A, - itable_2B, - itable_2C, - itable_2D, - itable_2E, - itable_2F, - itable_30, - itable_31, - itable_32, - itable_33, - itable_34, - itable_35, - itable_36, - itable_37, - itable_38, - itable_39, - itable_3A, - itable_3B, - itable_3C, - itable_3D, - itable_3E, - itable_3F, - itable_40, - itable_41, - itable_42, - itable_43, - itable_44, - itable_45, - itable_46, - itable_47, - itable_48, - itable_49, - itable_4A, - itable_4B, - itable_4C, - itable_4D, - itable_4E, - itable_4F, - itable_50, - itable_51, - itable_52, - itable_53, - itable_54, - itable_55, - itable_56, - itable_57, - itable_58, - itable_59, - itable_5A, - itable_5B, - itable_5C, - itable_5D, - itable_5E, - itable_5F, - itable_60, - itable_61, - itable_62, - itable_63, - itable_64, - itable_65, - itable_66, - itable_67, - itable_68, - itable_69, - itable_6A, - itable_6B, - itable_6C, - itable_6D, - itable_6E, - itable_6F, - itable_70, - itable_71, - itable_72, - itable_73, - itable_74, - itable_75, - itable_76, - itable_77, - itable_78, - itable_79, - itable_7A, - itable_7B, - itable_7C, - itable_7D, - itable_7E, - itable_7F, - itable_80, - itable_81, - itable_82, - itable_83, - itable_84, - itable_85, - itable_86, - itable_87, - itable_88, - itable_89, - itable_8A, - itable_8B, - itable_8C, - itable_8D, - itable_8E, - itable_8F, - itable_90, - itable_91, - itable_92, - itable_93, - itable_94, - itable_95, - itable_96, - itable_97, - itable_98, - itable_99, - itable_9A, - itable_9B, - itable_9C, - itable_9D, - itable_9E, - itable_9F, - itable_A0, - itable_A1, - itable_A2, - itable_A3, - itable_A4, - itable_A5, - itable_A6, - itable_A7, - itable_A8, - itable_A9, - itable_AA, - itable_AB, - itable_AC, - itable_AD, - itable_AE, - itable_AF, - itable_B0, - itable_B1, - itable_B2, - itable_B3, - itable_B4, - itable_B5, - itable_B6, - itable_B7, - itable_B8, - itable_B9, - itable_BA, - itable_BB, - itable_BC, - itable_BD, - itable_BE, - itable_BF, - itable_C0, - itable_C1, - itable_C2, - itable_C3, - itable_C4, - itable_C5, - itable_C6, - itable_C7, - itable_C8, - itable_C9, - itable_CA, - itable_CB, - itable_CC, - itable_CD, - itable_CE, - itable_CF, - itable_D0, - itable_D1, - itable_D2, - itable_D3, - itable_D4, - itable_D5, - itable_D6, - itable_D7, - itable_D8, - itable_D9, - itable_DA, - itable_DB, - itable_DC, - itable_DD, - itable_DE, - itable_DF, - itable_E0, - itable_E1, - itable_E2, - itable_E3, - itable_E4, - itable_E5, - itable_E6, - itable_E7, - itable_E8, - itable_E9, - itable_EA, - itable_EB, - itable_EC, - itable_ED, - itable_EE, - itable_EF, - itable_F0, - itable_F1, - itable_F2, - itable_F3, - itable_F4, - itable_F5, - itable_F6, - itable_F7, - itable_F8, - itable_F9, - itable_FA, - itable_FB, - itable_FC, - itable_FD, - itable_FE, - itable_FF, -}; diff --git a/AltairZ80/mfdc.c b/AltairZ80/mfdc.c deleted file mode 100644 index 7438039c..00000000 --- a/AltairZ80/mfdc.c +++ /dev/null @@ -1,680 +0,0 @@ -/************************************************************************* - * * - * $Id: mfdc.c 1995 2008-07-15 03:59:13Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Micropolis FD Control module for SIMH. * - * See the "Vector Using MDOS Revision 8.4" manual at: * - * www.hartetechnologies.com/manuals in the Vector Graphic section * - * for details of the on-disk sector format and programming information. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/*#define DBG_MSG */ -#define USE_VGI /* Use 275-byte VGI-format sectors (includes all metadata) */ - -#include "altairz80_defs.h" -#include "sim_imd.h" - -#if defined (_WIN32) -#include -#endif - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define STATUS_MSG (1 << 5) -#define ORDERS_MSG (1 << 7) - -extern uint32 PCX; -extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern int32 find_unit_index(UNIT *uptr); - -static void MFDC_Command(uint8 cData); - -#define MFDC_MAX_DRIVES 4 -#define JUMPER_W9 1 /* Not Installed (0) = 2MHz, Installed (1) = 4MHz. */ -#define JUMPER_W10 0 - -#define MFDC_SECTOR_LEN 275 - -typedef union { - struct { - uint8 sync; - uint8 header[2]; - uint8 unused[10]; - uint8 data[256]; - uint8 checksum; - uint8 ecc[4]; - uint8 ecc_valid; /* Not used for Micropolis FDC, but is used by FDHD. */ - } u; - uint8 raw[MFDC_SECTOR_LEN]; - -} SECTOR_FORMAT; - -typedef struct { - UNIT *uptr; - DISK_INFO *imd; - uint8 track; - uint8 wp; /* Disk write protected */ - uint8 ready; /* Drive is ready */ - uint8 sector; /* Current Sector number */ - uint32 sector_wait_count; -} MFDC_DRIVE_INFO; - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint8 xfr_flag; /* Indicates controller is ready to send/receive data */ - uint8 sel_drive; /* Currently selected drive */ - uint8 selected; /* 1 if drive is selected */ - uint8 track0; /* Set it selected drive is on track 0 */ - uint8 head; /* Currently selected head */ - uint8 wr_latch; /* Write enable latch */ - uint8 int_enable; /* Interrupt Enable */ - uint32 datacount; /* Number of data bytes transferred from controller for current sector */ - uint8 read_in_progress; /* TRUE if a read is in progress */ - MFDC_DRIVE_INFO drive[MFDC_MAX_DRIVES]; -} MFDC_INFO; - -static MFDC_INFO mfdc_info_data = { { 0xF800, 1024, 0, 0 } }; -static MFDC_INFO *mfdc_info = &mfdc_info_data; - -static SECTOR_FORMAT sdata; - -#define UNIT_V_MFDC_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_MFDC_WLK (1 << UNIT_V_MFDC_WLK) -#define UNIT_V_MFDC_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_MFDC_VERBOSE (1 << UNIT_V_MFDC_VERBOSE) -#define MFDC_CAPACITY (77*16*MFDC_SECTOR_LEN) /* Default Micropolis Disk Capacity */ - -static t_stat mfdc_reset(DEVICE *mfdc_dev); -static t_stat mfdc_attach(UNIT *uptr, char *cptr); -static t_stat mfdc_detach(UNIT *uptr); -static uint8 MFDC_Read(const uint32 Addr); -static uint8 MFDC_Write(const uint32 Addr, uint8 cData); - -static int32 mdskdev(const int32 Addr, const int32 rw, const int32 data); - -static UNIT mfdc_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MFDC_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MFDC_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MFDC_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MFDC_CAPACITY) } -}; - -static REG mfdc_reg[] = { - { NULL } -}; - -static MTAB mfdc_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, - { UNIT_MFDC_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_MFDC_WLK, UNIT_MFDC_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_MFDC_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_MFDC_VERBOSE, UNIT_MFDC_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB mfdc_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "CMD", CMD_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "STATUS", STATUS_MSG }, - { "ORDERS", ORDERS_MSG }, - { NULL, 0 } -}; - -DEVICE mfdc_dev = { - "MDSK", mfdc_unit, mfdc_reg, mfdc_mod, - MFDC_MAX_DRIVES, 10, 31, 1, MFDC_MAX_DRIVES, MFDC_MAX_DRIVES, - NULL, NULL, &mfdc_reset, - NULL, &mfdc_attach, &mfdc_detach, - &mfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - mfdc_dt, NULL, "Micropolis FD Control MDSK" -}; - -/* Micropolis FD Control Boot ROM - * This ROM code is runtime-relocatable. See Appendix F of the "Vector Using MDOS Revision 8.4" - * manual at www.hartetechnologies.com/manuals in the Vector Graphic section. - */ -static uint8 mfdc_rom[256] = { - 0xF3, 0x21, 0xA2, 0x00, 0xF9, 0x36, 0xC9, 0xCD, 0xA2, 0x00, 0xEB, 0x2A, 0xA0, 0x00, 0x2E, 0x00, /* 0x00 */ - 0xE5, 0x01, 0x1D, 0x00, 0x09, 0xE5, 0xE1, 0x0E, 0x1A, 0x09, 0x06, 0xBD, 0xEB, 0x3B, 0x3B, 0x1A, /* 0x10 */ - 0x77, 0xBE, 0xC0, 0x23, 0x13, 0x05, 0xC0, 0xE1, 0x2A, 0xA0, 0x00, 0x11, 0x00, 0x02, 0x19, 0x22, /* 0x20 */ - 0xA2, 0x00, 0x36, 0xA0, 0xC3, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xA2, 0x00, 0x7E, 0xE6, /* 0x30 */ - 0x80, 0xCA, 0xA9, 0x00, 0x7E, 0xE6, 0x0F, 0xA8, 0xC2, 0xA9, 0x00, 0x23, 0xB6, 0xF2, 0xB7, 0x00, /* 0x40 */ - 0x23, 0x7E, 0xAF, 0xEB, 0x06, 0x00, 0x00, 0x00, 0x1A, 0x77, 0x23, 0x88, 0x47, 0x1A, 0x77, 0x23, /* 0x50 */ - 0x88, 0x47, 0x0D, 0xC2, 0xC3, 0x00, 0x1A, 0xB8, 0xC9, 0x2A, 0xA2, 0x00, 0x36, 0x20, 0x23, 0x7E, /* 0x60 */ - 0x2B, 0xE6, 0x24, 0xEE, 0x20, 0xC2, 0xD4, 0x00, 0x0E, 0x5E, 0xCD, 0x49, 0x01, 0x23, 0x7E, 0x2B, /* 0x70 */ - 0xE6, 0x24, 0xEE, 0x20, 0xC2, 0xD4, 0x00, 0x23, 0x7E, 0xE6, 0x08, 0x2B, 0xCA, 0x07, 0x01, 0x06, /* 0x80 */ - 0x08, 0x36, 0x61, 0x0E, 0x0F, 0xCD, 0x49, 0x01, 0x05, 0xC2, 0xFC, 0x00, 0x23, 0x7E, 0xE6, 0x08, /* 0x90 */ - 0x2B, 0xC2, 0x19, 0x01, 0x36, 0x60, 0x0E, 0x0F, 0xCD, 0x49, 0x01, 0xC3, 0x07, 0x01, 0x21, 0x5F, /* 0xA0 */ - 0x01, 0xCD, 0x37, 0x01, 0xC2, 0xD4, 0x00, 0x2A, 0x69, 0x02, 0x22, 0xA4, 0x00, 0xCD, 0x37, 0x01, /* 0xB0 */ - 0xC2, 0xD4, 0x00, 0x2A, 0xA4, 0x00, 0x11, 0x0C, 0x00, 0x19, 0xD1, 0xE9, 0xE5, 0xEB, 0x01, 0x86, /* 0xC0 */ - 0x00, 0xCD, 0xA6, 0x00, 0xE1, 0xC2, 0x37, 0x01, 0xE5, 0x7E, 0x23, 0xB6, 0xE1, 0xC9, 0x7E, 0xE6, /* 0xD0 */ - 0x20, 0x79, 0xC2, 0x51, 0x01, 0x07, 0x4F, 0x3E, 0xFF, 0xD6, 0x01, 0xB7, 0xC2, 0x54, 0x01, 0x0D, /* 0xE0 */ - 0xC2, 0x52, 0x01, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xA6, 0x00 /* 0xF0 */ -}; - -/* Reset routine */ -t_stat mfdc_reset(DEVICE *dptr) -{ - uint8 i; - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { - sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &mdskdev, TRUE); - } else { - /* Connect MFDC at base address */ - for(i = 0; i < MFDC_MAX_DRIVES; i++) { - mfdc_info->drive[i].uptr = &mfdc_dev.units[i]; - } - if(sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &mdskdev, FALSE) != 0) { - printf("%s: error mapping resource at 0x%04x\n", __FUNCTION__, pnp->mem_base); - dptr->flags |= DEV_DIS; - return SCPE_ARG; - } - } - return SCPE_OK; -} - -/* Attach routine */ -t_stat mfdc_attach(UNIT *uptr, char *cptr) -{ - t_stat r; - unsigned int i = 0; - - r = attach_unit(uptr, cptr); /* attach unit */ - if ( r != SCPE_OK) /* error? */ - return r; - - /* Determine length of this disk */ - if(sim_fsize(uptr->fileref) != 0) { - uptr->capac = sim_fsize(uptr->fileref); - } else { - uptr->capac = MFDC_CAPACITY; - } - - i = find_unit_index(uptr); - - /* Default for new file is DSK */ - uptr->u3 = IMAGE_TYPE_DSK; - - if(uptr->capac > 0) { - r = assignDiskType(uptr); - if (r != SCPE_OK) { - mfdc_detach(uptr); - return r; - } - } - - if (uptr->flags & UNIT_MFDC_VERBOSE) - printf("MDSK%d, attached to '%s', type=%s, len=%d\n", i, cptr, - uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", - uptr->capac); - - if(uptr->u3 == IMAGE_TYPE_IMD) { - if(uptr->capac < 318000) { - printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n"); - mfdc_detach(uptr); - return SCPE_OPENERR; - } - - if (uptr->flags & UNIT_MFDC_VERBOSE) - printf("--------------------------------------------------------\n"); - mfdc_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_MFDC_VERBOSE)); - if (uptr->flags & UNIT_MFDC_VERBOSE) - printf("\n"); - } else { - mfdc_info->drive[i].imd = NULL; - } - - return SCPE_OK; -} - - -/* Detach routine */ -t_stat mfdc_detach(UNIT *uptr) -{ - t_stat r; - int8 i; - - for(i = 0; i < MFDC_MAX_DRIVES; i++) { - if(mfdc_dev.units[i].fileref == uptr->fileref) { - break; - } - } - - if (i >= MFDC_MAX_DRIVES) - return SCPE_ARG; - - DBG_PRINT(("Detach MFDC%d\n", i)); - r = diskClose(&mfdc_info->drive[i].imd); - if (r != SCPE_OK) - return r; - - r = detach_unit(uptr); /* detach unit */ - if (r != SCPE_OK) - return r; - - return SCPE_OK; -} - - - -static uint8 cy; -static uint8 adc(uint8 sum, uint8 a1) -{ - uint32 total; - - total = sum + a1 + cy; - - if(total > 0xFF) { - cy = 1; - } else { - cy = 0; - } - - return(total & 0xFF); -} - -/* Main Entry Point for Memory-Mapped I/O to the Micropolis FD Control Board - * - * The controller is typically located at 0xF800 in the Memory Map, and occupies - * 1K of address space. Accesses are broken down as follows: - * - * 0xF800-0xF8FF: Bootstrap ROM - * 0xF900-0xF9FF: Nothing (reads 0xFF) - * 0xFA00-0xFBFF: Controller registers: there are four registers, which are shadowed - * throughout this 512-byte range. - * - * The controller can be relocated on any 1K boundary in the memory map, and since the - * boot ROM code is runtime relocatable, it moves with the controller registers. - */ -static int32 mdskdev(const int32 Addr, const int32 rw, const int32 data) -{ - switch(Addr & 0x300) { - case 0x000: /* Boot ROM */ - if(rw == 0) { /* Read boot ROM */ - return(mfdc_rom[Addr & 0xFF]); - } else { - printf("MFDC: Attempt to write to boot ROM." NLP); - return (-1); - } - break; - case 0x100: /* Nothing */ - return(0xFF); - break; - case 0x200: - case 0x300: /* Controller Registers */ - if(rw == 0) { /* Read Register */ - return(MFDC_Read(Addr)); - } else { /* Write Register */ - return(MFDC_Write(Addr, data)); - } - break; - } - - return(-1); -} - - -static uint8 MFDC_Read(const uint32 Addr) -{ - uint8 cData; - MFDC_DRIVE_INFO *pDrive; - int32 rtn; - - cData = 0x00; - - pDrive = &mfdc_info->drive[mfdc_info->sel_drive]; - - switch(Addr & 0x3) { - case 0: - if(mfdc_info->read_in_progress == FALSE) { - pDrive->sector_wait_count++; - if(pDrive->sector_wait_count > 10) { - pDrive->sector++; - pDrive->sector &= 0x0F; /* Max of 16 sectors */ - mfdc_info->wr_latch = 0; /* on new sector, disable the write latch */ - DBG_PRINT(("Head over sector %d" NLP, pDrive->sector)); - pDrive->sector_wait_count = 0; - } - } - - cData = (pDrive->sector) & 0xF; /* [3:0] current sector */ - cData |= (JUMPER_W10 << 4); - cData |= ((~JUMPER_W9) & 1) << 5; - cData |= (0 << 6); /* Sector Interrupt Flag, reset by RESET command or Interrupt Disable */ - cData |= (1 << 7); /* Sector Flag */ - mfdc_info->xfr_flag = 1; /* Drive has data */ - mfdc_info->datacount = 0; - sim_debug(STATUS_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " RD Sector Register = 0x%02x\n", PCX, cData); - break; - case 1: - cData = (mfdc_info->sel_drive & 0x3); /* [1:0] selected drive */ - cData |= (!mfdc_info->selected << 2); /* [2] drive is selected */ - cData |= (pDrive->track == 0) ? 0x08 : 0; /* [3] TK0 */ - pDrive->wp = ((pDrive->uptr)->flags & UNIT_MFDC_WLK) ? 1 : 0; - cData |= (pDrive->wp << 4); /* [4] Write Protect */ - cData |= (pDrive->ready << 5); /* [5] Drive Ready */ - cData |= (0 << 6); /* [6] PINTE from S-100 Bus */ - cData |= (mfdc_info->xfr_flag << 7); /* [7] Transfer Flag */ - - sim_debug(STATUS_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " RD Status = 0x%02x\n", PCX, cData); - break; - case 2: - case 3: - if(mfdc_info->datacount == 0) { - unsigned int i, checksum; - unsigned long sec_offset; - uint32 flags; - uint32 readlen; - - /* Clear out unused portion of sector. */ - memset(&sdata.u.unused[0], 0x00, 10); - - sdata.u.sync = 0xFF; - sdata.u.header[0] = pDrive->track; - sdata.u.header[1] = pDrive->sector; - - sim_debug(RD_DATA_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " RD Data T:%d S:[%d]\n", PCX, pDrive->track, pDrive->sector); - -#ifdef USE_VGI - sec_offset = (pDrive->track * MFDC_SECTOR_LEN * 16) + \ - (pDrive->sector * MFDC_SECTOR_LEN); -#else - sec_offset = (pDrive->track * 4096) + \ - (pDrive->sector * 256); -#endif /* USE_VGI */ - - if (!(pDrive->uptr->flags & UNIT_ATT)) { - if (pDrive->uptr->flags & UNIT_MFDC_VERBOSE) - printf("MFDC: " ADDRESS_FORMAT " MDSK%i not attached." NLP, PCX, - mfdc_info->sel_drive); - return 0x00; - } - - switch((pDrive->uptr)->u3) - { - case IMAGE_TYPE_IMD: - if(pDrive->imd == NULL) { - printf(".imd is NULL!" NLP); - } -/* printf("%s: Read: imd=%p" NLP, __FUNCTION__, pDrive->imd); */ - sectRead(pDrive->imd, - pDrive->track, - mfdc_info->head, - pDrive->sector, - sdata.u.data, - 256, - &flags, - &readlen); - break; - case IMAGE_TYPE_DSK: - if(pDrive->uptr->fileref == NULL) { - printf(".fileref is NULL!" NLP); - } else { - sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); -#ifdef USE_VGI - rtn = sim_fread(sdata.raw, 1, MFDC_SECTOR_LEN, (pDrive->uptr)->fileref); - if (rtn != MFDC_SECTOR_LEN) -#else - rtn = sim_fread(sdata.u.data, 1, 256, (pDrive->uptr)->fileref); - if (rtn != 256) -#endif /* USE_VGI */ - printf("%s: sim_fread error. Result = %d." NLP, __FUNCTION__, rtn); - } - break; - case IMAGE_TYPE_CPT: - printf("%s: CPT Format not supported" NLP, __FUNCTION__); - break; - default: - printf("%s: Unknown image Format" NLP, __FUNCTION__); - break; - } - -/* printf("%d/%d @%04x Len=%04x" NLP, sdata.u.header[0], sdata.u.header[1], sdata.u.header[9]<<8|sdata.u.header[8], sdata.u.header[11]<<8|sdata.u.header[10]); */ - - adc(0,0); /* clear Carry bit */ - checksum = 0; - - /* Checksum everything except the sync byte */ - for(i=1;i<269;i++) { - checksum = adc(checksum, sdata.raw[i]); - } - - sdata.u.checksum = checksum & 0xFF; -/* DBG_PRINT(("Checksum=%x" NLP, sdata.u.checksum)); */ - mfdc_info->read_in_progress = TRUE; - } - - cData = sdata.raw[mfdc_info->datacount]; - - mfdc_info->datacount++; - if(mfdc_info->datacount == 270) { - sim_debug(RD_DATA_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " Read sector [%d] complete\n", PCX, pDrive->sector); - mfdc_info->read_in_progress = FALSE; - } - -/* DBG_PRINT(("MFDC: " ADDRESS_FORMAT " RD Data Sector %d[%03d]: 0x%02x" NLP, PCX, pDrive->sector, mfdc_info->datacount, cData)); */ - break; - } - - return (cData); -} - -static uint8 MFDC_Write(const uint32 Addr, uint8 cData) -{ - unsigned int sec_offset; - uint32 flags = 0; - uint32 writelen; - MFDC_DRIVE_INFO *pDrive; - - pDrive = &mfdc_info->drive[mfdc_info->sel_drive]; - - switch(Addr & 0x3) { - case 0: - case 1: - MFDC_Command(cData); - break; - case 2: - case 3: -/* DBG_PRINT(("MFDC: " ADDRESS_FORMAT " WR Data" NLP, PCX)); */ - if(mfdc_info->wr_latch == 0) { - printf("MFDC: " ADDRESS_FORMAT " Error, attempt to write data when write latch is not set." NLP, PCX); - } else { -#ifdef USE_VGI - sec_offset = (pDrive->track * MFDC_SECTOR_LEN * 16) + \ - (pDrive->sector * MFDC_SECTOR_LEN); - - sdata.raw[mfdc_info->datacount] = cData; -#else - int data_index = mfdc_info->datacount - 13; - - sec_offset = (pDrive->track * 4096) + \ - (pDrive->sector * 256); - - if((data_index >= 0) && (data_index < 256)) { - DBG_PRINT(("writing data [%03d]=%02x" NLP, data_index, cData)); - - sdata.u.data[data_index] = cData; - - } - -#endif /* USE_VGI */ - - mfdc_info->datacount ++; - - if(mfdc_info->datacount == 270) { - sim_debug(WR_DATA_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " WR Data T:%d S:[%d]\n", PCX, pDrive->track, pDrive->sector); - - if (!(pDrive->uptr->flags & UNIT_ATT)) { - if (pDrive->uptr->flags & UNIT_MFDC_VERBOSE) - printf("MFDC: " ADDRESS_FORMAT " MDSK%i not attached." NLP, PCX, - mfdc_info->sel_drive); - return 0x00; - } - - switch((pDrive->uptr)->u3) - { - case IMAGE_TYPE_IMD: - if(pDrive->imd == NULL) { - printf(".imd is NULL!" NLP); - } - sectWrite(pDrive->imd, - pDrive->track, - mfdc_info->head, - pDrive->sector, - sdata.u.data, - 256, - &flags, - &writelen); - break; - case IMAGE_TYPE_DSK: - if(pDrive->uptr->fileref == NULL) { - printf(".fileref is NULL!" NLP); - } else { - sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); -#ifdef USE_VGI - sim_fwrite(sdata.raw, 1, MFDC_SECTOR_LEN, (pDrive->uptr)->fileref); -#else - sim_fwrite(sdata.u.data, 1, 256, (pDrive->uptr)->fileref); -#endif /* USE_VGI */ - } - break; - case IMAGE_TYPE_CPT: - printf("%s: CPT Format not supported" NLP, __FUNCTION__); - break; - default: - printf("%s: Unknown image Format" NLP, __FUNCTION__); - break; - } - } - } - break; - } - - cData = 0x00; - - return (cData); -} - -#define MFDC_CMD_NOP 0 -#define MFDC_CMD_SELECT 1 -#define MFDC_CMD_INTR 2 -#define MFDC_CMD_STEP 3 -#define MFDC_CMD_SET_WRITE 4 -#define MFDC_CMD_RESET 5 - -static void MFDC_Command(uint8 cData) -{ - uint8 cCommand; - uint8 cModifier; - MFDC_DRIVE_INFO *pDrive; - - pDrive = &mfdc_info->drive[mfdc_info->sel_drive]; - - - cCommand = cData >> 5; - cModifier = cData & 0x1F; - - switch(cCommand) { - case MFDC_CMD_NOP: - sim_debug(CMD_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " No Op.\n", PCX); - break; - case MFDC_CMD_SELECT: - mfdc_info->sel_drive = cModifier & 0x03; - mfdc_info->head = (cModifier & 0x10) >> 4; - mfdc_info->selected = TRUE; - - if(pDrive->uptr->fileref != NULL) { - pDrive->ready = 1; - } else { - pDrive->ready = 0; - } - - sim_debug(CMD_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " Select Drive: %d, Head: %s\n", PCX, mfdc_info->sel_drive, (mfdc_info->head) ? "Upper" : "Lower"); - break; - case MFDC_CMD_INTR: - mfdc_info->int_enable = cModifier & 1; /* 0=int disable, 1=enable */ - sim_debug(CMD_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " Interrupts %s.\n", PCX, mfdc_info->int_enable ? "Enabled" : "Disabled"); - break; - case MFDC_CMD_STEP: - if(cModifier & 1) { /* Step IN */ - pDrive->track++; - } - else { /* Step OUT */ - if(pDrive->track != 0) { - pDrive->track--; - } - } - - sim_debug(SEEK_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " Step %s, Track=%d.\n", PCX, (cModifier & 1) ? "IN" : "OUT", pDrive->track); - - break; - case MFDC_CMD_SET_WRITE: - sim_debug(CMD_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " Set WRITE.\n", PCX); - mfdc_info->wr_latch = 1; /* Allow writes for the current sector */ - mfdc_info->datacount = 0; /* reset the byte counter */ - break; - case MFDC_CMD_RESET: - sim_debug(CMD_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " Reset Controller.\n", PCX); - mfdc_info->selected = 0; /* de-select the drive */ - mfdc_info->wr_latch = 0; /* Disable the write latch */ - mfdc_info->datacount = 0; /* reset the byte counter */ - break; - default: - sim_debug(CMD_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " Unsupported command.\n", PCX); - break; - } -} diff --git a/AltairZ80/mfdc.h b/AltairZ80/mfdc.h deleted file mode 100644 index 991e1c8a..00000000 --- a/AltairZ80/mfdc.h +++ /dev/null @@ -1,46 +0,0 @@ -/************************************************************************* - * * - * $Id: mfdc.h 1694 2007-12-14 05:23:11Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Micropolis FDC module for SIMH definitions * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -extern uint8 MFDC_Read(const uint32 Addr); -extern uint8 MFDC_Write(const uint32 Addr, uint8 cData); - - - diff --git a/AltairZ80/n8vem.c b/AltairZ80/n8vem.c deleted file mode 100644 index 99bfb446..00000000 --- a/AltairZ80/n8vem.c +++ /dev/null @@ -1,492 +0,0 @@ -/************************************************************************* - * * - * $Id: n8vem.c 1995 2008-07-15 03:59:13Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * N8VEM Single-Board Computer I/O module for SIMH. * - * http://groups.google.com/group/n8vem/web/n8vem-single-board-computer-home-page * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/* #define DBG_MSG */ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define PIO_MSG (1 << 1) -#define UART_MSG (1 << 2) -#define RTC_MSG (1 << 3) -#define MPCL_MSG (1 << 4) -#define ROM_MSG (1 << 5) -#define VERBOSE_MSG (1 << 7) - -#define N8VEM_MAX_DRIVES 2 - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint8 *ram; - uint8 *rom; - uint8 rom_attached; - uint8 uart_scr; - uint8 uart_lcr; - uint8 mpcl_ram; - uint8 mpcl_rom; -} N8VEM_INFO; - -static N8VEM_INFO n8vem_info_data = { { 0x0, 0x8000, 0x60, 32 } }; -static N8VEM_INFO *n8vem_info = &n8vem_info_data; - -extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern uint32 PCX; -extern REG *sim_PC; -extern int32 find_unit_index (UNIT *uptr); - -static t_stat n8vem_reset(DEVICE *n8vem_dev); -static t_stat n8vem_boot(int32 unitno, DEVICE *dptr); -static t_stat n8vem_attach(UNIT *uptr, char *cptr); -static t_stat n8vem_detach(UNIT *uptr); - -static uint8 N8VEM_Read(const uint32 Addr); -static uint8 N8VEM_Write(const uint32 Addr, uint8 cData); - -static int32 n8vemdev(const int32 port, const int32 io, const int32 data); -static int32 n8vem_mem(const int32 port, const int32 io, const int32 data); - -static int32 save_rom = 0x00; /* When set to 1, saves ROM back to file on disk at detach time */ -static int32 save_ram = 0x00; /* When set to 1, saves RAM back to file on disk at detach time */ -static int32 n8vem_pio1a = 0x00; /* 8255 PIO1A IN Port */ -static int32 n8vem_pio1b = 0x00; /* 8255 PIO1B OUT Port */ -static int32 n8vem_pio1c = 0x00; /* 8255 PIO1C IN Port */ -static int32 n8vem_pio1ctrl = 0x00; /* 8255 PIO1 Control Port */ - -#define N8VEM_ROM_SIZE (1024 * 1024) -#define N8VEM_RAM_SIZE (512 * 1024) - -#define N8VEM_RAM_SELECT (1 << 7) -#define N8VEM_RAM_MASK 0x0F -#define N8VEM_ROM_MASK 0x1F -#define N8VEM_ADDR_MASK 0x7FFF - -static UNIT n8vem_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, N8VEM_ROM_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, N8VEM_RAM_SIZE) } -}; - -static REG n8vem_reg[] = { - { HRDATA (SAVEROM, save_rom, 1), }, - { HRDATA (SAVERAM, save_ram, 1), }, - { HRDATA (PIO1A, n8vem_pio1a, 8), }, - { HRDATA (PIO1B, n8vem_pio1b, 8), }, - { HRDATA (PIO1C, n8vem_pio1c, 8), }, - { HRDATA (PIO1CTRL, n8vem_pio1ctrl, 8), }, - { NULL } -}; - -static MTAB n8vem_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB n8vem_dt[] = { - { "ERROR", ERROR_MSG }, - { "PIO", PIO_MSG }, - { "UART", UART_MSG }, - { "RTC", RTC_MSG }, - { "ROM", ROM_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { NULL, 0 } -}; - -DEVICE n8vem_dev = { - "N8VEM", n8vem_unit, n8vem_reg, n8vem_mod, - N8VEM_MAX_DRIVES, 10, 31, 1, N8VEM_MAX_DRIVES, N8VEM_MAX_DRIVES, - NULL, NULL, &n8vem_reset, - &n8vem_boot, &n8vem_attach, &n8vem_detach, - &n8vem_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - n8vem_dt, NULL, "Single-Board Computer N8VEM" -}; - -/* Reset routine */ -static t_stat n8vem_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - sim_debug(VERBOSE_MSG, &n8vem_dev, "N8VEM: Reset.\n"); - - if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &n8vemdev, TRUE); - sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &n8vem_mem, TRUE); - free(n8vem_info->ram); - free(n8vem_info->rom); - } else { - /* Connect N8VEM at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &n8vemdev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - /* Connect N8VEM Memory (512K RAM, 1MB FLASH) */ - if(sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &n8vem_mem, FALSE) != 0) { - printf("%s: error mapping MEM resource at 0x%04x\n", __FUNCTION__, pnp->mem_base); - return SCPE_ARG; - } - - n8vem_info->ram = calloc(1, (N8VEM_RAM_SIZE)); - n8vem_info->rom = calloc(1, (N8VEM_ROM_SIZE)); - - /* Clear the RAM and ROM mapping registers */ - n8vem_info->mpcl_ram = 0; - n8vem_info->mpcl_rom = 0; - } - return SCPE_OK; -} - -static t_stat n8vem_boot(int32 unitno, DEVICE *dptr) -{ - sim_debug(VERBOSE_MSG, &n8vem_dev, "N8VEM: Boot.\n"); - - /* Clear the RAM and ROM mapping registers */ - n8vem_info->mpcl_ram = 0; - n8vem_info->mpcl_rom = 0; - - /* Set the PC to 0, and go. */ - *((int32 *) sim_PC->loc) = 0; - return SCPE_OK; -} - -/* Attach routine */ -static t_stat n8vem_attach(UNIT *uptr, char *cptr) -{ - t_stat r; - int32 i = 0, rtn; - - i = find_unit_index(uptr); - - if (i == -1) { - return (SCPE_IERR); - } - - r = attach_unit(uptr, cptr); /* attach unit */ - if ( r != SCPE_OK) /* error? */ - return r; - - /* Determine length of this disk */ - uptr->capac = sim_fsize(uptr->fileref); - - sim_debug(VERBOSE_MSG, &n8vem_dev, "N8VEM: Attach %s.\n", i == 0 ? "ROM" : "RAM"); - - if(i == 0) { /* Attaching ROM */ - n8vem_info->rom_attached = TRUE; - - /* Erase ROM */ - memset(n8vem_info->rom, 0xFF, N8VEM_ROM_SIZE); - - if(uptr->capac > 0) { - /* Only read in enough of the file to fill the ROM. */ - if (uptr->capac > N8VEM_ROM_SIZE) - uptr->capac = N8VEM_ROM_SIZE; - - rtn = fread((void *)(n8vem_info->rom), uptr->capac, 1, uptr->fileref); - sim_debug(VERBOSE_MSG, &n8vem_dev, "N8VEM: Reading %d bytes into ROM." " Result = %ssuccessful.\n", uptr->capac, rtn == 1 ? "" : "not "); - } - } else { /* attaching RAM */ - /* Erase RAM */ - memset(n8vem_info->ram, 0x00, N8VEM_RAM_SIZE); - - if(uptr->capac > 0) { - /* Only read in enough of the file to fill the RAM. */ - if(uptr->capac > N8VEM_RAM_SIZE) - uptr->capac = N8VEM_RAM_SIZE; - - rtn = fread((void *)(n8vem_info->ram), uptr->capac, 1, uptr->fileref); - sim_debug(VERBOSE_MSG, &n8vem_dev, "N8VEM: Reading %d bytes into RAM." " Result = %ssuccessful.\n", uptr->capac, rtn == 1 ? "" : "not "); - } - } - return r; -} - -/* Detach routine */ -static t_stat n8vem_detach(UNIT *uptr) -{ - t_stat r; - int32 i = 0; - - i = find_unit_index(uptr); - - if (i == -1) { - return (SCPE_IERR); - } - - sim_debug(VERBOSE_MSG, &n8vem_dev, "N8VEM: Detach %s.\n", i == 0 ? "ROM" : "RAM"); - - /* rewind to the beginning of the file. */ - sim_fseek(uptr->fileref, 0, SEEK_SET); - - if(i == 0) { /* ROM */ - /* Save the ROM back to disk if SAVEROM is set. */ - if(save_rom == 1) { - sim_debug(VERBOSE_MSG, &n8vem_dev, "N8VEM: Writing %d bytes into ROM image.\n", N8VEM_ROM_SIZE); - fwrite((void *)(n8vem_info->rom), N8VEM_ROM_SIZE, 1, uptr->fileref); - } - } else { /* RAM */ - /* Save the RAM back to disk if SAVERAM is set. */ - if(save_ram == 1) { - sim_debug(VERBOSE_MSG, &n8vem_dev, "N8VEM: Writing %d bytes into RAM image.\n", N8VEM_RAM_SIZE); - fwrite((void *)(n8vem_info->ram), N8VEM_RAM_SIZE, 1, uptr->fileref); - } - } - r = detach_unit(uptr); /* detach unit */ - - return r; -} - -/* RAM MEMORY PAGE CONFIGURATION LATCH CONTROL PORT ( IO_Y3 ) INFORMATION - * - * 7 6 5 4 3 2 1 0 ONLY APPLICABLE TO THE LOWER MEMORY PAGE $0000-$7FFF - * ^ ^ ^ ^ ^ ^ ^ ^ - * : : : : : : : :--0 = A15 RAM ADDRESS LINE DEFAULT IS 0 - * : : : : : : :----0 = A16 RAM ADDRESS LINE DEFAULT IS 0 - * : : : : : :------0 = A17 RAM ADDRESS LINE DEFAULT IS 0 - * : : : : :--------0 = A18 RAM ADDRESS LINE DEFAULT IS 0 - * : : : :-----------0 = - * : : :-------------0 = - * : :---------------0 = - * :-----------------0 = - * - * ROM MEMORY PAGE CONFIGURATION LATCH CONTROL PORT ( IO_Y3+$04 ) INFORMATION - * - * 7 6 5 4 3 2 1 0 ONLY APPLICABLE TO THE LOWER MEMORY PAGE $0000-$7FFF - * ^ ^ ^ ^ ^ ^ ^ ^ - * : : : : : : : :--0 = A15 ROM ADDRESS LINE DEFAULT IS 0 - * : : : : : : :----0 = A16 ROM ADDRESS LINE DEFAULT IS 0 - * : : : : : :------0 = A17 ROM ADDRESS LINE DEFAULT IS 0 - * : : : : :--------0 = A18 ROM ADDRESS LINE DEFAULT IS 0 - * : : : :-----------0 = A19 ROM ONLY ADDRESS LINE DEFAULT IS 0 - * : : :-------------0 = - * : :---------------0 = - * :-----------------0 = ROM SELECT (0=ROM, 1=RAM) DEFAULT IS 0 - */ - static int32 n8vem_mem(const int32 Addr, const int32 write, const int32 data) -{ -/* DBG_PRINT(("N8VEM: ROM %s, Addr %04x" NLP, write ? "WR" : "RD", Addr)); */ - if(write) { - if(n8vem_info->mpcl_rom & N8VEM_RAM_SELECT) - { - n8vem_info->ram[((n8vem_info->mpcl_ram & N8VEM_RAM_MASK) << 15) | (Addr & N8VEM_ADDR_MASK)] = data; - } else { - if(save_rom == 1) { - n8vem_info->rom[((n8vem_info->mpcl_rom & N8VEM_ROM_MASK) << 15) | (Addr & N8VEM_ADDR_MASK)] = data; - } else { - sim_debug(ROM_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " WR ROM[0x%05x]: Cannot write to ROM.\n", PCX, ((n8vem_info->mpcl_rom & N8VEM_ROM_MASK) << 15) | (Addr & N8VEM_ADDR_MASK)); - } - } - return 0; - } else { - if(n8vem_info->mpcl_rom & N8VEM_RAM_SELECT) - { - return n8vem_info->ram[((n8vem_info->mpcl_ram & N8VEM_RAM_MASK) << 15) | (Addr & N8VEM_ADDR_MASK)]; - } else { - return n8vem_info->rom[((n8vem_info->mpcl_rom & N8VEM_ROM_MASK) << 15) | (Addr & N8VEM_ADDR_MASK)]; - } - } -} - -static int32 n8vemdev(const int32 port, const int32 io, const int32 data) -{ -/* DBG_PRINT(("N8VEM: IO %s, Port %02x\n", io ? "WR" : "RD", port)); */ - if(io) { - N8VEM_Write(port, data); - return 0; - } else { - return(N8VEM_Read(port)); - } -} - -#define N8VEM_PIO1A 0x00 /* (INPUT) IN 1-8 */ -#define N8VEM_PIO1B 0x01 /* (OUTPUT) OUT TO LEDS */ -#define N8VEM_PIO1C 0x02 /* (INPUT) */ -#define N8VEM_PIO1CONT 0x03 /* CONTROL BYTE PIO 82C55 */ - -#define N8VEM_UART_DATA 0x08 -#define N8VEM_UART_RSR 0x09 -#define N8VEM_UART_INTR 0x0A -#define N8VEM_UART_LCR 0x0B -#define N8VEM_UART_MCR 0x0C -#define N8VEM_UART_LSR 0x0D -#define N8VEM_UART_MSR 0x0E -#define N8VEM_UART_SCR 0x0F - -#define N8VEM_MPCL_RAM 0x18 /* RAM Address control port */ -#define N8VEM_MPCL_RAM1 0x19 /* RAM Address control port */ -#define N8VEM_MPCL_RAM2 0x1A /* RAM Address control port */ -#define N8VEM_MPCL_RAM3 0x1B /* RAM Address control port */ -#define N8VEM_MPCL_ROM 0x1C /* ROM Address control port */ -#define N8VEM_MPCL_ROM1 0x1D /* ROM Address control port */ -#define N8VEM_MPCL_ROM2 0x1E /* ROM Address control port */ -#define N8VEM_MPCL_ROM3 0x1F /* ROM Address control port */ - -extern int32 sio0d(const int32 port, const int32 io, const int32 data); -extern int32 sio0s(const int32 port, const int32 io, const int32 data); - -static uint8 N8VEM_Read(const uint32 Addr) -{ - uint8 cData = 0xFF; - - switch(Addr & 0x1F) { - case N8VEM_PIO1A: - sim_debug(PIO_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " RD: PIO1A\n", PCX); - cData = n8vem_pio1a; - break; - case N8VEM_PIO1B: - sim_debug(PIO_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " RD: PIO1B\n", PCX); - cData = n8vem_pio1b; - break; - case N8VEM_PIO1C: - sim_debug(PIO_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " RD: PIO1C\n", PCX); - cData = n8vem_pio1c; - break; - case N8VEM_PIO1CONT: - sim_debug(PIO_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " RD: PIO1CTRL\n", PCX); - cData = n8vem_pio1ctrl; - break; - case N8VEM_UART_LCR: - cData = n8vem_info->uart_lcr; - break; - case N8VEM_UART_DATA: - case N8VEM_UART_RSR: - case N8VEM_UART_LSR: - case N8VEM_UART_INTR: - case N8VEM_UART_MCR: - case N8VEM_UART_MSR: - sim_debug(UART_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " RD[%02x]: UART not Implemented.\n", PCX, Addr); - break; - case N8VEM_UART_SCR: /* 16550 Scratchpad, implemented so software can detect UART is present */ - cData = n8vem_info->uart_scr; - break; - case N8VEM_MPCL_RAM: - case N8VEM_MPCL_RAM1: - case N8VEM_MPCL_RAM2: - case N8VEM_MPCL_RAM3: - sim_debug(MPCL_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " RD: MPCL_RAM not Implemented.\n", PCX); - break; - case N8VEM_MPCL_ROM: - case N8VEM_MPCL_ROM1: - case N8VEM_MPCL_ROM2: - case N8VEM_MPCL_ROM3: - sim_debug(MPCL_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " RD: MPCL_ROM not Implemented.\n", PCX); - break; - default: - sim_debug(VERBOSE_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " RD[%02x]: not Implemented.\n", PCX, Addr); - break; - } - - return (cData); - -} - -static uint8 N8VEM_Write(const uint32 Addr, uint8 cData) -{ - - switch(Addr & 0x1F) { - case N8VEM_PIO1A: - sim_debug(PIO_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " WR: PIO1A=0x%02x\n", PCX, cData); - n8vem_pio1a = cData; - break; - case N8VEM_PIO1B: - sim_debug(PIO_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " WR: PIO1B=0x%02x\n", PCX, cData); - n8vem_pio1b = cData; - break; - case N8VEM_PIO1C: - sim_debug(PIO_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " WR: PIO1C=0x%02x\n", PCX, cData); - n8vem_pio1c = cData; - break; - case N8VEM_PIO1CONT: - sim_debug(PIO_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " WR: PIO1_CTRL=0x%02x\n", PCX, cData); - n8vem_pio1ctrl = cData; - break; - case N8VEM_UART_LCR: - sim_debug(UART_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " WR: UART LCR=%02x.\n", PCX, cData); - n8vem_info->uart_lcr = cData; - break; - case N8VEM_UART_DATA: - case N8VEM_UART_RSR: - case N8VEM_UART_INTR: - case N8VEM_UART_MCR: - case N8VEM_UART_LSR: - case N8VEM_UART_MSR: - sim_debug(UART_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " WR[%02x]: UART not Implemented.\n", PCX, Addr); - break; - case N8VEM_UART_SCR: /* 16550 Scratchpad, implemented so software can detect UART is present */ - n8vem_info->uart_scr = cData; - break; - case N8VEM_MPCL_RAM: - case N8VEM_MPCL_RAM1: - case N8VEM_MPCL_RAM2: - case N8VEM_MPCL_RAM3: - sim_debug(MPCL_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " WR: MPCL_RAM=0x%02x\n", PCX, cData); - n8vem_info->mpcl_ram = cData; - break; - case N8VEM_MPCL_ROM: - case N8VEM_MPCL_ROM1: - case N8VEM_MPCL_ROM2: - case N8VEM_MPCL_ROM3: - sim_debug(MPCL_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " WR: MPCL_ROM=0x%02x\n", PCX, cData); - n8vem_info->mpcl_rom = cData; - break; - default: - sim_debug(VERBOSE_MSG, &n8vem_dev, "N8VEM: " ADDRESS_FORMAT " WR[0x%02x]=0x%02x: not Implemented.\n", PCX, Addr, cData); - break; - } - - return(0); -} - diff --git a/AltairZ80/nasm.h b/AltairZ80/nasm.h deleted file mode 100644 index 2745189b..00000000 --- a/AltairZ80/nasm.h +++ /dev/null @@ -1,357 +0,0 @@ -/* nasm.h main header file for the Netwide Assembler: inter-module interface - * - * The Netwide Assembler is copyright (C) 1996 Simon Tatham and - * Julian Hall. All rights reserved. The software is - * redistributable under the licence given in the file "Licence" - * distributed in the NASM archive. - * - * initial version: 27/iii/95 by Simon Tatham - */ - -#ifndef NASM_NASM_H -#define NASM_NASM_H - -#include - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef FALSE -#define FALSE 0 /* comes in handy */ -#endif -#ifndef TRUE -#define TRUE 1 -#endif - -/* - * Name pollution problems: on Digital UNIX pulls in some - * strange hardware header file which sees fit to define R_SP. We - * undefine it here so as not to break the enum below. - */ -#ifdef R_SP -#undef R_SP -#endif - -/* - * Special values for expr->type. ASSUMPTION MADE HERE: the number - * of distinct register names (i.e. possible "type" fields for an - * expr structure) does not exceed 124 (EXPR_REG_START through - * EXPR_REG_END). - */ -#define EXPR_REG_START 1 - -/* - * Here we define the operand types. These are implemented as bit - * masks, since some are subsets of others; e.g. AX in a MOV - * instruction is a special operand type, whereas AX in other - * contexts is just another 16-bit register. (Also, consider CL in - * shift instructions, DX in OUT, etc.) - */ - -/* size, and other attributes, of the operand */ -#define BITS8 0x00000001L -#define BITS16 0x00000002L -#define BITS32 0x00000004L -#define BITS64 0x00000008L /* FPU only */ -#define BITS80 0x00000010L /* FPU only */ -#define FAR 0x00000020L /* grotty: this means 16:16 or */ - /* 16:32, like in CALL/JMP */ -#define NEAR 0x00000040L -#define SHORT 0x00000080L /* and this means what it says :) */ - -#define SIZE_MASK 0x000000FFL /* all the size attributes */ -#define NON_SIZE (~SIZE_MASK) - -#define TO 0x00000100L /* reverse effect in FADD, FSUB &c */ -#define COLON 0x00000200L /* operand is followed by a colon */ - -/* type of operand: memory reference, register, etc. */ -#define MEMORY 0x00204000L -#define REGISTER 0x00001000L /* register number in 'basereg' */ -#define IMMEDIATE 0x00002000L - -#define REGMEM 0x00200000L /* for r/m, ie EA, operands */ -#define REGNORM 0x00201000L /* 'normal' reg, qualifies as EA */ -#define REG8 0x00201001L -#define REG16 0x00201002L -#define REG32 0x00201004L -#define MMXREG 0x00201008L /* MMX registers */ -#define XMMREG 0x00201010L /* XMM Katmai reg */ -#define FPUREG 0x01000000L /* floating point stack registers */ -#define FPU0 0x01000800L /* FPU stack register zero */ - -/* special register operands: these may be treated differently */ -#define REG_SMASK 0x00070000L /* a mask for the following */ -#define REG_ACCUM 0x00211000L /* accumulator: AL, AX or EAX */ -#define REG_AL 0x00211001L /* REG_ACCUM | BITSxx */ -#define REG_AX 0x00211002L /* ditto */ -#define REG_EAX 0x00211004L /* and again */ -#define REG_COUNT 0x00221000L /* counter: CL, CX or ECX */ -#define REG_CL 0x00221001L /* REG_COUNT | BITSxx */ -#define REG_CX 0x00221002L /* ditto */ -#define REG_ECX 0x00221004L /* another one */ -#define REG_DL 0x00241001L -#define REG_DX 0x00241002L -#define REG_EDX 0x00241004L -#define REG_SREG 0x00081002L /* any segment register */ -#define REG_CS 0x01081002L /* CS */ -#define REG_DESS 0x02081002L /* DS, ES, SS (non-CS 86 registers) */ -#define REG_FSGS 0x04081002L /* FS, GS (386 extended registers) */ -#define REG_SEG67 0x08081002L /* Non-implemented segment registers */ -#define REG_CDT 0x00101004L /* CRn, DRn and TRn */ -#define REG_CREG 0x08101004L /* CRn */ -#define REG_DREG 0x10101004L /* DRn */ -#define REG_TREG 0x20101004L /* TRn */ - -/* special type of EA */ -#define MEM_OFFS 0x00604000L /* simple [address] offset */ - -/* special type of immediate operand */ -#define ONENESS 0x00800000L /* so UNITY == IMMEDIATE | ONENESS */ -#define UNITY 0x00802000L /* for shift/rotate instructions */ -#define BYTENESS 0x40000000L /* so SBYTE == IMMEDIATE | BYTENESS */ -#define SBYTE 0x40002000L /* for op r16/32,immediate instrs. */ - -/* Register names automatically generated from regs.dat */ -/* automatically generated from ./regs.dat - do not edit */ -enum reg_enum { - R_AH = EXPR_REG_START, - R_AL, - R_AX, - R_BH, - R_BL, - R_BP, - R_BX, - R_CH, - R_CL, - R_CR0, - R_CR1, - R_CR2, - R_CR3, - R_CR4, - R_CR5, - R_CR6, - R_CR7, - R_CS, - R_CX, - R_DH, - R_DI, - R_DL, - R_DR0, - R_DR1, - R_DR2, - R_DR3, - R_DR4, - R_DR5, - R_DR6, - R_DR7, - R_DS, - R_DX, - R_EAX, - R_EBP, - R_EBX, - R_ECX, - R_EDI, - R_EDX, - R_ES, - R_ESI, - R_ESP, - R_FS, - R_GS, - R_MM0, - R_MM1, - R_MM2, - R_MM3, - R_MM4, - R_MM5, - R_MM6, - R_MM7, - R_SEGR6, - R_SEGR7, - R_SI, - R_SP, - R_SS, - R_ST0, - R_ST1, - R_ST2, - R_ST3, - R_ST4, - R_ST5, - R_ST6, - R_ST7, - R_TR0, - R_TR1, - R_TR2, - R_TR3, - R_TR4, - R_TR5, - R_TR6, - R_TR7, - R_XMM0, - R_XMM1, - R_XMM2, - R_XMM3, - R_XMM4, - R_XMM5, - R_XMM6, - R_XMM7, - REG_ENUM_LIMIT -}; - -enum { /* condition code names */ - C_A, C_AE, C_B, C_BE, C_C, C_E, C_G, C_GE, C_L, C_LE, C_NA, C_NAE, - C_NB, C_NBE, C_NC, C_NE, C_NG, C_NGE, C_NL, C_NLE, C_NO, C_NP, - C_NS, C_NZ, C_O, C_P, C_PE, C_PO, C_S, C_Z -}; - -/* - * Note that because segment registers may be used as instruction - * prefixes, we must ensure the enumerations for prefixes and - * register names do not overlap. - */ -enum { /* instruction prefixes */ - PREFIX_ENUM_START = REG_ENUM_LIMIT, - P_A16 = PREFIX_ENUM_START, P_A32, P_LOCK, P_O16, P_O32, P_REP, P_REPE, - P_REPNE, P_REPNZ, P_REPZ, P_TIMES -}; - -enum { /* extended operand types */ - EOT_NOTHING, EOT_DB_STRING, EOT_DB_NUMBER -}; - -enum { /* special EA flags */ - EAF_BYTEOFFS = 1, /* force offset part to byte size */ - EAF_WORDOFFS = 2, /* force offset part to [d]word size */ - EAF_TIMESTWO = 4 /* really do EAX*2 not EAX+EAX */ -}; - -enum { /* values for `hinttype' */ - EAH_NOHINT = 0, /* no hint at all - our discretion */ - EAH_MAKEBASE = 1, /* try to make given reg the base */ - EAH_NOTBASE = 2 /* try _not_ to make reg the base */ -}; - -typedef struct { /* operand to an instruction */ - long type; /* type of operand */ - int addr_size; /* 0 means default; 16; 32 */ - int basereg, indexreg, scale; /* registers and scale involved */ - int hintbase, hinttype; /* hint as to real base register */ - long segment; /* immediate segment, if needed */ - long offset; /* any immediate number */ - long wrt; /* segment base it's relative to */ - int eaflags; /* special EA flags */ - int opflags; /* see OPFLAG_* defines below */ -} operand; - -#define OPFLAG_FORWARD 1 /* operand is a forward reference */ -#define OPFLAG_EXTERN 2 /* operand is an external reference */ - -typedef struct extop { /* extended operand */ - struct extop *next; /* linked list */ - long type; /* defined above */ - char *stringval; /* if it's a string, then here it is */ - int stringlen; /* ... and here's how long it is */ - long segment; /* if it's a number/address, then... */ - long offset; /* ... it's given here ... */ - long wrt; /* ... and here */ -} extop; - -#define MAXPREFIX 4 - -typedef struct { /* an instruction itself */ - char *label; /* the label defined, or NULL */ - int prefixes[MAXPREFIX]; /* instruction prefixes, if any */ - int nprefix; /* number of entries in above */ - int opcode; /* the opcode - not just the string */ - int condition; /* the condition code, if Jcc/SETcc */ - int operands; /* how many operands? 0-3 - * (more if db et al) */ - operand oprs[3]; /* the operands, defined as above */ - extop *eops; /* extended operands */ - int eops_float; /* true if DD and floating */ - long times; /* repeat count (TIMES prefix) */ - int forw_ref; /* is there a forward reference? */ -} insn; - -enum geninfo { GI_SWITCH }; - -/* - * values for the `type' parameter to an output function. Each one - * must have the actual number of _bytes_ added to it. - * - * Exceptions are OUT_RELxADR, which denote an x-byte relocation - * which will be a relative jump. For this we need to know the - * distance in bytes from the start of the relocated record until - * the end of the containing instruction. _This_ is what is stored - * in the size part of the parameter, in this case. - * - * Also OUT_RESERVE denotes reservation of N bytes of BSS space, - * and the contents of the "data" parameter is irrelevant. - * - * The "data" parameter for the output function points to a "long", - * containing the address in question, unless the type is - * OUT_RAWDATA, in which case it points to an "unsigned char" - * array. - */ -#define OUT_RAWDATA 0x00000000UL -#define OUT_ADDRESS 0x10000000UL -#define OUT_REL2ADR 0x20000000UL -#define OUT_REL4ADR 0x30000000UL -#define OUT_RESERVE 0x40000000UL -#define OUT_TYPMASK 0xF0000000UL -#define OUT_SIZMASK 0x0FFFFFFFUL - -/* - * The type definition macros - * for debugging - * - * low 3 bits: reserved - * next 5 bits: type - * next 24 bits: number of elements for arrays (0 for labels) - */ - -#define TY_UNKNOWN 0x00 -#define TY_LABEL 0x08 -#define TY_BYTE 0x10 -#define TY_WORD 0x18 -#define TY_DWORD 0x20 -#define TY_FLOAT 0x28 -#define TY_QWORD 0x30 -#define TY_TBYTE 0x38 -#define TY_COMMON 0xE0 -#define TY_SEG 0xE8 -#define TY_EXTERN 0xF0 -#define TY_EQU 0xF8 - -#define TYM_TYPE(x) ((x) & 0xF8) -#define TYM_ELEMENTS(x) (((x) & 0xFFFFFF00) >> 8) - -#define TYS_ELEMENTS(x) ((x) << 8) -/* - * ----- - * Other - * ----- - */ - -/* - * This is a useful #define which I keep meaning to use more often: - * the number of elements of a statically defined array. - */ - -#define elements(x) ( sizeof(x) / sizeof(*(x)) ) - -extern int tasm_compatible_mode; - -/* - * This declaration passes the "pass" number to all other modules - * "pass0" assumes the values: 0, 0, ..., 0, 1, 2 - * where 0 = optimizing pass - * 1 = pass 1 - * 2 = pass 2 - */ - -extern int pass0; /* this is globally known */ -extern int optimizing; - -#endif diff --git a/AltairZ80/s100_64fdc.c b/AltairZ80/s100_64fdc.c deleted file mode 100644 index 03c4f395..00000000 --- a/AltairZ80/s100_64fdc.c +++ /dev/null @@ -1,1786 +0,0 @@ -/************************************************************************* - * * - * $Id: s100_64fdc.c 1999 2008-07-22 04:25:28Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Cromemco 4FDC/16FDC/64FDC Floppy Controller module for SIMH. * - * This module is a wrapper around the wd179x FDC module, and adds the * - * Cromemco-specific registers as well as the Cromemco RDOS Boot ROM. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/*#define DBG_MSG */ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#include "sim_defs.h" /* simulator definitions */ -#include "wd179x.h" - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define STATUS_MSG (1 << 5) -#define DRIVE_MSG (1 << 6) -#define VERBOSE_MSG (1 << 7) -#define IRQ_MSG (1 << 8) - -#define CROMFDC_MAX_DRIVES 4 -#define CROMFDC_ROM_SIZE (8 * 1024) -#define CROMFDC_ADDR_MASK (CROMFDC_ROM_SIZE - 1) - -#define CROMFDC_SIM_64US 186 /* Number of "ticks" in 64uS, where does this come from? */ - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint32 dma_addr; /* DMA Transfer Address */ - uint8 rom_disabled; /* TRUE if ROM has been disabled */ - uint8 motor_on; - uint8 autowait; - uint8 rtc; - uint8 imask; /* Interrupt Mask Register */ - uint8 ipend; /* Interrupt Pending Register */ -} CROMFDC_INFO; - -extern WD179X_INFO_PUB *wd179x_infop; - -static CROMFDC_INFO cromfdc_info_data = { { 0xC000, CROMFDC_ROM_SIZE, 0x3, 2 } }; -static CROMFDC_INFO *cromfdc_info = &cromfdc_info_data; - -extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); - -static t_stat cromfdc_svc (UNIT *uptr); - -extern REG *sim_PC; -extern uint32 PCX; /* external view of PC */ - -#define UNIT_V_CROMFDC_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_CROMFDC_WLK (1 << UNIT_V_CROMFDC_WLK) -#define UNIT_V_CROMFDC_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_CROMFDC_VERBOSE (1 << UNIT_V_CROMFDC_VERBOSE) -#define UNIT_V_CROMFDC_ROM (UNIT_V_UF + 2) /* boot ROM enabled */ -#define UNIT_CROMFDC_ROM (1 << UNIT_V_CROMFDC_ROM) -#define CROMFDC_CAPACITY (77*1*26*128) /* Default SSSD 8" (IBM 3740) Disk Capacity */ - -#define MOTOR_TO_LIMIT 128 - -static t_stat cromfdc_reset(DEVICE *cromfdc_dev); -static t_stat cromfdc_boot(int32 unitno, DEVICE *dptr); - -static int32 cromfdc_ext(const int32 port, const int32 io, const int32 data); -static int32 cromfdc_timer(const int32 port, const int32 io, const int32 data); -static int32 cromfdc_control(const int32 port, const int32 io, const int32 data); -static int32 cromfdc_banksel(const int32 port, const int32 io, const int32 data); -static int32 cromfdcrom(const int32 port, const int32 io, const int32 data); -static int32 ccs2810_uart_status(const int32 port, const int32 io, const int32 data); - -static int32 dipswitch = 0; /* 5-position DIP switch on 64FDC card */ -static int32 bootstrap = 0; /* 0 for RDOS 2.52, 1 for RDOS 3.12. */ -static int32 crofdc_type = 64; /* controller type, either 4, 16, or 64 for Cromemco, 50 for CCS-2422. */ -static int32 crofdc_boot = 1; /* BOOT jumper setting, default is auto-boot */ -static int32 crofdc_inh_init = 0; /* Inhibit Init (Format) switch, default is not inhibited */ - -/* Disk Control/Flags Register, 0x34 (IN) / CCS Status Register 1 */ -#define CROMFDC_FLAG_DRQ (1 << 7) /* DRQ (All controllers) */ -#define CROMFDC_FLAG_BOOT (1 << 6) /* boot# jumper (active low) (All controllers) */ -#define CROMFDC_FLAG_SEL_REQ (1 << 5) /* Head Load (4FDC, 16FDC) / Select Request (64FDC) / CCS2422 HLD */ -#define CROMFDC_FLAG_INH_INIT (1 << 4) /* Unassigned (4FDC) / Inhibit_Init# (16FDC, 64FDC) / CCS2422 DS4 */ -#define CROMFDC_FLAG_MTRON (1 << 3) /* Unassigned (4FDC) / Motor On (16FDC, 64FDC) / CCS2422 DS3 */ -#define CROMFDC_FLAG_MTO (1 << 2) /* Unassigned (4FDC) / Motor Timeout (16FDC, 64FDC) / CCS2422 DS2 */ -#define CROMFDC_FLAG_ATO (1 << 1) /* Unassigned (4FDC) / Autowait Timeout (16FDC, 64FDC) / CCS2422 DS1 */ -#define CROMFDC_FLAG_EOJ (1 << 0) /* End of Job (INTRQ) (All Controllers) (16FDC, 64FDC) */ - -/* Disk Control/Flags Register, 0x34 (OUT) / CCS Control Register 1 */ -#define CROMFDC_CTRL_AUTOWAIT (1 << 7) /* Auto Wait Enable (All controllers) */ -#define CROMFDC_CTRL_DDENS (1 << 6) /* Unassigned (4FDC) / Double Density (16FDC, 64FDC) */ -#define CROMFDC_CTRL_MTRON (1 << 5) /* Motor On (All controllers) */ -#define CROMFDC_CTRL_MAXI (1 << 4) /* Maxi (8") (All controllers) */ -#define CROMFDC_CTRL_DS4 (1 << 3) /* Drive Select 4 (All controllers) */ -#define CROMFDC_CTRL_DS3 (1 << 2) /* Drive Select 3 (All controllers) */ -#define CROMFDC_CTRL_DS2 (1 << 1) /* Drive Select 2 (All controllers) */ -#define CROMFDC_CTRL_DS1 (1 << 0) /* Drive Select 1 (All controllers) */ - -/* 64FDC Auxiliary Disk Command, 0x04 (OUT) / CCS Control Register 2 */ -#define CROMFDC_AUX_RESERVED7 (1 << 7) /* Unused (All Controllers) */ -#define CROMFDC_AUX_EJECT (1 << 6) /* 4FDC Eject Left* / 16FDC Eject*, 64FDC Unused / CCS2422 - Side Select# */ -#define CCSFDC_CMD_SIDE (1 << 6) /* CCS2422 - Side Select# */ -#define CROMFDC_AUX_SEL_OVERRIDE (1 << 5) /* 4FDC Eject Right* / 16FDC, 64FDC Drive Select Override */ -#define CROMFDC_AUX_FAST_SEEK (1 << 4) /* 4FDC, 16FDC Fast Seek* / 64FDC Unused */ -#define CROMFDC_AUX_RESTORE (1 << 3) /* 4FDC, 16FDC Restore* / 64FDC Unused */ -#define CROMFDC_AUX_CTRL_OUT (1 << 2) /* Control Out* (All Controllers) */ -#define CROMFDC_AUX_CMD_SIDE (1 << 1) /* 16FDC, 64FDC: Side Select* Low=Side 1, High=Side 0. */ -#define CROMFDC_AUX_RESERVED0 (1 << 0) /* Unused (All Controllers) */ - - -/* 64FDC Interrupt Mask Register, 0x03 (OUT) */ -#define CROMFDC_IRQ_TIMER5 (1 << 7) /* Timer5 Interrupt Mask */ -#define CROMFDC_IRQ_TIMER4 (1 << 6) /* Timer4 Interrupt Mask */ -#define CROMFDC_IRQ_TBE (1 << 5) /* Transmit Buffer Empty Interrupt Mask */ -#define CROMFDC_IRQ_RDA (1 << 4) /* Read Data Available Interrupt Mask */ -#define CROMFDC_IRQ_TIMER3 (1 << 3) /* Timer3 Interrupt Mask */ -#define CROMFDC_IRQ_EOJ (1 << 2) /* End of Job Interrupt Mask */ -#define CROMFDC_IRQ_TIMER2 (1 << 1) /* Timer2 Interrupt Mask */ -#define CROMFDC_IRQ_TIMER1 (1 << 0) /* Timer1 Interrupt Mask */ - -/* 64FDC interrupt "restart" instruction opcodes */ -#define CROMFDC_TIMER1_RST 0xC7 /* RST0 - 0xC7 */ -#define CROMFDC_TIMER2_RST 0xCF /* RST8 - 0xCF */ -#define CROMFDC_EOJ_RST 0xD7 /* RST10 - 0xD7 */ -#define CROMFDC_TIMER3_RST 0xDF /* RST18 - 0xDF */ -#define CROMFDC_RDA_RST 0xE7 /* RST20 - 0xE7 */ -#define CROMFDC_TBE_RST 0xEF /* RST28 - 0xEF */ -#define CROMFDC_TIMER4_RST 0xF7 /* RST30 - 0xF7 */ -#define CROMFDC_TIMER5_RST 0xFF /* RST38 - 0xFF */ - -#define RST_OPCODE_TO_VECTOR(x) (x & 0x38) - -static unsigned char cromfdc_irq_table[8] = { - CROMFDC_TIMER1_RST, - CROMFDC_TIMER2_RST, - CROMFDC_EOJ_RST, - CROMFDC_TIMER3_RST, - CROMFDC_RDA_RST, - CROMFDC_TBE_RST, - CROMFDC_TIMER4_RST, - CROMFDC_TIMER5_RST }; - -static uint8 ipend_to_rst_opcode(uint8 ipend) -{ - uint8 active_intr; - uint8 i,j = 0; - - active_intr = cromfdc_info->imask & cromfdc_info->ipend; - - for(i=1;i != 0;i <<= 1) { -/* printf("%d: %d" NLP, i, active_intr & i); */ - if (active_intr & i) { - return(cromfdc_irq_table[j]); - } - j++; - } - - return (0); -} - - -/* The CROMFDC does not really have RAM associated with it, but for ease of integration with the - * SIMH/AltairZ80 Resource Mapping Scheme, rather than Map and Unmap the ROM, simply implement our - * own RAM that can be swapped in when the CROMFDC Boot ROM is disabled. - */ -static uint8 cromfdcram[CROMFDC_ROM_SIZE]; - -static UNIT cromfdc_unit[] = { - { UDATA (&cromfdc_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE + UNIT_CROMFDC_ROM, CROMFDC_CAPACITY), 1024 }, - { UDATA (&cromfdc_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, CROMFDC_CAPACITY) }, - { UDATA (&cromfdc_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, CROMFDC_CAPACITY) }, - { UDATA (&cromfdc_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, CROMFDC_CAPACITY) } -}; - -static REG cromfdc_reg[] = { - { HRDATA (DIPSW, dipswitch, 8), }, - { DRDATA (BOOTSTRAP, bootstrap, 2), }, - { DRDATA (FDCTYPE, crofdc_type, 8), }, - { DRDATA (BOOT, crofdc_boot, 10), }, - { DRDATA (INHINIT, crofdc_inh_init, 10), }, - { NULL } -}; - -static MTAB cromfdc_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_CROMFDC_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_CROMFDC_WLK, UNIT_CROMFDC_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_CROMFDC_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_CROMFDC_VERBOSE, UNIT_CROMFDC_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { UNIT_CROMFDC_ROM, 0, "NOROM", "NOROM", NULL }, - { UNIT_CROMFDC_ROM, UNIT_CROMFDC_ROM, "ROM", "ROM", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB cromfdc_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "CMD", CMD_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "STATUS", STATUS_MSG }, - { "DRIVE", DRIVE_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { "IRQ", IRQ_MSG }, - { NULL, 0 } -}; - -DEVICE cromfdc_dev = { - "CROMFDC", cromfdc_unit, cromfdc_reg, cromfdc_mod, - CROMFDC_MAX_DRIVES, 10, 31, 1, CROMFDC_MAX_DRIVES, CROMFDC_MAX_DRIVES, - NULL, NULL, &cromfdc_reset, - &cromfdc_boot, &wd179x_attach, &wd179x_detach, - &cromfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - cromfdc_dt, NULL, "Cromemco 4/16/64 FDC CROMFDC" -}; - -/* This is the CROMFDC RDOS-II ROM. - * The CROMFDC has a single 8K ROM; however ths simulation includes - * two different versions of RDOS: - * RDOS 2.52 and RDOS 3.12 - * RDOS 2.52 is the default, but RDOS 3.12 can be - * selected with 'd cromfdc bootstrap ' at the SIMH SCP Prompt. - */ -static uint8 cromfdc_rom[2][CROMFDC_ROM_SIZE] = { -{ /* RDOS 2.52 */ - 0xF3, 0x18, 0x3C, 0xC3, 0x30, 0xC0, 0xC3, 0x04, 0xC5, 0xC3, 0x37, 0xC0, 0xC3, 0x3B, 0xC0, 0xC3, - 0x9E, 0xCB, 0xC3, 0x37, 0xCD, 0xC3, 0xD4, 0xC4, 0xC3, 0x52, 0xCD, 0xC3, 0xAB, 0xC5, 0xC3, 0x4B, - 0xC2, 0xC3, 0x6C, 0xCC, 0xC3, 0x76, 0xCC, 0xC3, 0xEA, 0xCB, 0xC3, 0xFE, 0xC7, 0xC3, 0x97, 0xCC, - 0x32, 0x77, 0x00, 0x78, 0xC3, 0x87, 0xC3, 0x32, 0x75, 0x00, 0xC9, 0x32, 0x76, 0x00, 0xC9, 0xAF, - 0xD3, 0x03, 0x47, 0xD9, 0x2F, 0xD3, 0x04, 0x3E, 0xD0, 0xD3, 0x30, 0x21, 0x2E, 0x00, 0xF9, 0x25, - 0x20, 0xFD, 0x74, 0x2C, 0x20, 0xFC, 0x24, 0x22, 0x62, 0x00, 0x22, 0x64, 0x00, 0xCD, 0x4B, 0xC2, - 0xDB, 0x34, 0xE6, 0x40, 0xC2, 0x39, 0xC1, 0xDB, 0x04, 0x2F, 0xE6, 0x03, 0x32, 0x77, 0x00, 0xCD, - 0x06, 0xC8, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x74, 0x6F, 0x20, 0x62, - 0x6F, 0x6F, 0x74, 0x2C, 0x20, 0x45, 0x53, 0x43, 0x20, 0x74, 0x6F, 0x20, 0x61, 0x62, 0x6F, 0x72, - 0x74, 0x8D, 0xCD, 0xA8, 0xCF, 0x57, 0xD3, 0x34, 0x06, 0x64, 0xCD, 0x28, 0xC1, 0x21, 0x64, 0x00, - 0xCD, 0xF1, 0xCF, 0x10, 0xF5, 0x32, 0x75, 0x00, 0x32, 0x7D, 0x00, 0x32, 0x78, 0x00, 0x3C, 0x32, - 0x76, 0x00, 0xCD, 0xF7, 0xC1, 0x32, 0x7E, 0x00, 0x21, 0x80, 0x00, 0x22, 0x7B, 0x00, 0x22, 0x79, - 0x00, 0x3E, 0x42, 0x32, 0x70, 0x00, 0x06, 0x02, 0xC5, 0xCD, 0x37, 0xCD, 0xD4, 0xCB, 0xCD, 0xD4, - 0x52, 0xCD, 0xC1, 0x30, 0x13, 0xCD, 0x28, 0xC1, 0x10, 0xEE, 0xCD, 0x06, 0xC8, 0x0D, 0x55, 0x6E, - 0x61, 0x62, 0x6C, 0x65, 0x20, 0xF4, 0x18, 0x2D, 0x3A, 0x80, 0x00, 0xFE, 0x40, 0x28, 0x04, 0xFE, - 0xE5, 0x20, 0x07, 0xCD, 0x06, 0xC8, 0x0D, 0xCE, 0x18, 0x1B, 0xCD, 0x28, 0xC1, 0xCD, 0xA8, 0xCF, - 0x57, 0x3A, 0x77, 0x00, 0x08, 0xCD, 0x06, 0xC8, 0x0D, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x62, 0x79, - 0x8D, 0x37, 0xC3, 0x80, 0x00, 0xCD, 0x06, 0xC8, 0x6F, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x8D, 0x3A, - 0x71, 0x00, 0xB7, 0xC4, 0x59, 0xC3, 0x18, 0x09, 0xCD, 0x76, 0xCC, 0xC4, 0x6C, 0xCC, 0xFE, 0x1B, - 0xC0, 0x3E, 0xD0, 0xD3, 0x30, 0x3E, 0x7C, 0xD3, 0x04, 0xCD, 0x06, 0xC8, 0x0D, 0x43, 0x72, 0x6F, - 0x6D, 0x65, 0x6D, 0x63, 0x6F, 0x20, 0x52, 0x44, 0x4F, 0x53, 0x20, 0x30, 0x32, 0x2E, 0x35, 0x32, - 0x8D, 0xAF, 0x32, 0x6C, 0x00, 0x3A, 0x7E, 0x00, 0x47, 0xCD, 0xE2, 0xC1, 0x31, 0x2E, 0x00, 0xCD, - 0x06, 0xC8, 0xBB, 0xCD, 0xA3, 0xC7, 0xCD, 0x14, 0xC8, 0xA7, 0x28, 0xE5, 0xCD, 0xC1, 0xC2, 0x28, - 0xE4, 0x78, 0xFE, 0x17, 0x30, 0x47, 0x87, 0x21, 0x8B, 0xC1, 0xCD, 0x86, 0xC1, 0x7E, 0x23, 0x66, - 0x6F, 0xCD, 0xC7, 0xC1, 0x18, 0xCF, 0x85, 0x6F, 0xD0, 0x24, 0xC9, 0xFD, 0xCC, 0xC8, 0xC1, 0xBD, - 0xC1, 0x2B, 0xC7, 0x2A, 0xC6, 0xBD, 0xC1, 0xC4, 0xC1, 0xBD, 0xC1, 0x45, 0xC2, 0xBD, 0xC1, 0xBD, - 0xC1, 0x39, 0xC4, 0x45, 0xC6, 0xBD, 0xC1, 0x36, 0xC6, 0xBD, 0xC1, 0xC2, 0xC6, 0x16, 0xC5, 0x7A, - 0xC6, 0x41, 0xC9, 0xBD, 0xC1, 0x52, 0xC6, 0x1A, 0xC5, 0xAF, 0x32, 0x6C, 0x00, 0xCD, 0x06, 0xC8, - 0x3F, 0x8D, 0x18, 0x91, 0xCD, 0x53, 0xC8, 0xE9, 0xCD, 0x14, 0xC8, 0xB7, 0xCA, 0x67, 0xC0, 0xFE, - 0x45, 0xD2, 0x2A, 0xC4, 0xD6, 0x41, 0xDA, 0x2A, 0xC4, 0xF5, 0x13, 0xCD, 0x27, 0xC8, 0xF1, 0xC3, - 0x6C, 0xC0, 0x3A, 0x6C, 0x00, 0xB7, 0xC8, 0xCD, 0xFE, 0xC7, 0xCB, 0x58, 0xC0, 0xCB, 0x78, 0x3E, - 0x3B, 0xC4, 0xFE, 0xC7, 0xC3, 0xFE, 0xC7, 0x7A, 0xD3, 0x34, 0x3E, 0xDF, 0xD3, 0x04, 0x3E, 0xD4, - 0xD3, 0x30, 0xDB, 0x34, 0x0F, 0x30, 0xFB, 0xDB, 0x30, 0x01, 0x00, 0x02, 0xCD, 0x3B, 0xC2, 0x3E, - 0xD4, 0xD3, 0x30, 0xCD, 0x34, 0xC2, 0x28, 0xDF, 0xDB, 0x34, 0x0F, 0x30, 0xF6, 0xDB, 0x30, 0x10, - 0xEE, 0xAF, 0xD3, 0x03, 0x79, 0xFE, 0x5A, 0x30, 0x03, 0x87, 0x87, 0x87, 0xFE, 0xB7, 0x3E, 0x80, - 0xD0, 0x3E, 0x04, 0xC9, 0xDB, 0x03, 0xFE, 0xC7, 0xC0, 0x0C, 0xC8, 0x3E, 0x01, 0xD3, 0x03, 0x3E, - 0xFA, 0xD3, 0x05, 0x18, 0xEF, 0xCD, 0x27, 0xC8, 0xCD, 0x97, 0xCC, 0xDB, 0x04, 0xE6, 0x08, 0x28, - 0x5D, 0x3E, 0x0A, 0xD3, 0x02, 0x21, 0xD0, 0x07, 0xCD, 0xF1, 0xCF, 0x3E, 0x08, 0xD3, 0x02, 0x16, - 0x64, 0x15, 0x28, 0xED, 0x21, 0xB9, 0xC2, 0x0E, 0x00, 0x3E, 0x19, 0x06, 0x09, 0xD3, 0x02, 0xED, - 0xA3, 0x28, 0xEE, 0xCD, 0x98, 0xC2, 0xCD, 0x98, 0xC2, 0x38, 0xE9, 0xFE, 0x0D, 0x3E, 0x09, 0x20, - 0xEC, 0x3E, 0x0D, 0xD3, 0x01, 0x21, 0xA0, 0x0F, 0xCD, 0xF1, 0xCF, 0xCD, 0x76, 0xCC, 0xC4, 0x6C, - 0xCC, 0xFE, 0x0D, 0x28, 0xEC, 0xC3, 0x97, 0xCC, 0xD5, 0x11, 0xA0, 0x8C, 0xCD, 0x76, 0xCC, 0x28, - 0x05, 0xCD, 0x6C, 0xCC, 0x18, 0x06, 0x1B, 0x7A, 0xB3, 0x20, 0xF1, 0x37, 0xD1, 0xC9, 0x3E, 0x09, - 0xD3, 0x02, 0x3E, 0x84, 0xD3, 0x00, 0xC3, 0x97, 0xCC, 0x90, 0xC0, 0xA0, 0x90, 0x88, 0x84, 0x82, - 0x01, 0xD6, 0x41, 0xDA, 0xBD, 0xC1, 0x47, 0x13, 0x1A, 0xFE, 0x3B, 0xC0, 0x78, 0xFE, 0x04, 0xD2, - 0x2A, 0xC4, 0xC6, 0x41, 0x32, 0x6C, 0x00, 0xCD, 0xF6, 0xC3, 0x13, 0x1A, 0xFE, 0x3B, 0x06, 0x0C, - 0x20, 0x0B, 0x13, 0x1A, 0xFE, 0x3B, 0x06, 0x04, 0x20, 0x03, 0x06, 0x80, 0x13, 0xC5, 0xCD, 0xB7, - 0xC3, 0xC1, 0x70, 0x30, 0x06, 0x3A, 0x6D, 0x00, 0xB0, 0x77, 0x37, 0xF5, 0xCD, 0x84, 0xC3, 0x32, - 0x78, 0x00, 0x32, 0x7D, 0x00, 0x3C, 0x32, 0x76, 0x00, 0xCD, 0x04, 0xC6, 0x3E, 0x48, 0x32, 0x70, - 0x00, 0xCD, 0x37, 0xCD, 0xF5, 0xCD, 0x1E, 0xC6, 0xF1, 0xDA, 0x0D, 0xC4, 0xF1, 0xDA, 0xB5, 0xC3, - 0xCD, 0x04, 0xC6, 0x21, 0x00, 0x01, 0x22, 0x7B, 0x00, 0xCD, 0xCB, 0xCD, 0xCD, 0x52, 0xCD, 0xF5, - 0xCD, 0x1E, 0xC6, 0xF1, 0x30, 0x2D, 0x3A, 0x71, 0x00, 0xB7, 0xF2, 0x45, 0xC3, 0x21, 0x64, 0x00, - 0xCD, 0xF1, 0xCF, 0x18, 0xDB, 0xCD, 0x06, 0xC8, 0x43, 0x61, 0x6E, 0x27, 0x74, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x20, 0x4C, 0x61, 0x62, 0x65, 0x6C, 0x8D, 0x1E, 0x01, 0xCD, 0xF2, 0xC5, 0xCD, 0x13, - 0xC4, 0xAF, 0xC9, 0x01, 0x10, 0x00, 0x11, 0x7A, 0x01, 0xCD, 0xEE, 0xC3, 0x0E, 0x01, 0xCD, 0xEE, - 0xC3, 0x3A, 0x78, 0x01, 0xFE, 0x43, 0x20, 0x02, 0xCB, 0xC8, 0x3A, 0x7E, 0x00, 0xE6, 0xCC, 0xB0, - 0x2A, 0x6A, 0x00, 0x77, 0xCD, 0xF6, 0xC3, 0x32, 0x7E, 0x00, 0xCB, 0x47, 0x11, 0x0A, 0x10, 0x21, - 0x00, 0x02, 0x20, 0x0D, 0xCB, 0x4F, 0x11, 0x05, 0x08, 0x20, 0x06, 0x11, 0x12, 0x1A, 0x21, 0x80, - 0x00, 0x22, 0x79, 0x00, 0xCB, 0x7F, 0x3E, 0x4C, 0x42, 0x28, 0x03, 0x3E, 0x27, 0x43, 0x32, 0x6F, - 0x00, 0x78, 0x32, 0x6E, 0x00, 0xAF, 0xC9, 0xCD, 0x14, 0xC8, 0xB7, 0xC8, 0x01, 0x10, 0x00, 0xCD, - 0xDE, 0xC3, 0x0E, 0x01, 0xCD, 0xDE, 0xC3, 0xCD, 0x14, 0xC8, 0xFE, 0x43, 0x20, 0x06, 0xCB, 0xC8, - 0x13, 0xCD, 0x14, 0xC8, 0xB7, 0xC2, 0xB9, 0xC1, 0x78, 0x32, 0x6D, 0x00, 0x37, 0xC9, 0xCD, 0x14, - 0xC8, 0x13, 0xFE, 0x53, 0xC8, 0xFE, 0x44, 0xC2, 0xB9, 0xC1, 0x78, 0xB1, 0x47, 0xC9, 0x1A, 0x13, - 0x13, 0xFE, 0x44, 0xC0, 0x18, 0xF4, 0x3A, 0x6C, 0x00, 0xD6, 0x41, 0x32, 0x77, 0x00, 0x21, 0x66, - 0x00, 0xCD, 0x86, 0xC1, 0x22, 0x6A, 0x00, 0x7E, 0xB7, 0xC9, 0xCD, 0xF2, 0xC5, 0xCD, 0x13, 0xC4, - 0xC3, 0x55, 0xC1, 0xCD, 0x06, 0xC8, 0x20, 0x45, 0x72, 0x72, 0xAD, 0x3A, 0x70, 0x00, 0xCD, 0xFE, - 0xC7, 0x3A, 0x71, 0x00, 0xCD, 0xDB, 0xC7, 0xC3, 0x97, 0xCC, 0xCD, 0x06, 0xC8, 0x41, 0x2D, 0x44, - 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x8D, 0xC3, 0x55, 0xC1, 0xCD, 0x27, 0xC8, 0x3A, 0x77, 0x00, 0xF5, - 0x3A, 0x6C, 0x00, 0xF5, 0x3E, 0x41, 0xF5, 0x32, 0x6C, 0x00, 0xCD, 0xF6, 0xC3, 0x2A, 0x6A, 0x00, - 0x46, 0xC4, 0x63, 0xC4, 0xF1, 0x3C, 0xFE, 0x45, 0x38, 0xEC, 0xF1, 0x32, 0x6C, 0x00, 0xF1, 0x32, - 0x77, 0x00, 0xC9, 0xCD, 0x06, 0xC8, 0x20, 0xA0, 0xCD, 0xE2, 0xC1, 0xCD, 0x06, 0xC8, 0x3B, 0xA0, - 0xCB, 0x58, 0xC4, 0xFC, 0xC7, 0xCB, 0x78, 0xCC, 0xFC, 0xC7, 0xCB, 0x60, 0xCD, 0x98, 0xC4, 0xCD, - 0xFC, 0xC7, 0xCB, 0x40, 0xCD, 0x98, 0xC4, 0xCB, 0x48, 0x28, 0x0A, 0xCD, 0x06, 0xC8, 0x20, 0x43, - 0x72, 0x6F, 0x6D, 0x69, 0xF8, 0xC3, 0x97, 0xCC, 0x3E, 0x44, 0x20, 0x02, 0x3E, 0x53, 0xC3, 0xFE, - 0xC7, 0x47, 0x3A, 0x6C, 0x00, 0xB7, 0xCA, 0xBD, 0xC1, 0x78, 0xFE, 0x53, 0x28, 0x2C, 0xCD, 0xB0, - 0xC8, 0xDA, 0xBD, 0xC1, 0xE5, 0xCD, 0xE1, 0xC4, 0x3E, 0x53, 0x32, 0x70, 0x00, 0xE1, 0xAF, 0xB4, - 0xC2, 0xBD, 0xC1, 0x3A, 0x6F, 0x00, 0xBD, 0x38, 0xE8, 0x7D, 0x32, 0x75, 0x00, 0xCD, 0xD4, 0xC4, - 0xD0, 0xC3, 0x0D, 0xC4, 0xCD, 0xF8, 0xC5, 0xC3, 0xCB, 0xCD, 0x13, 0xCD, 0xE1, 0xC4, 0xC3, 0xCB, - 0xCD, 0x3A, 0x75, 0x00, 0x32, 0x7D, 0x00, 0xCD, 0xAD, 0xC8, 0xD8, 0xAF, 0xB4, 0xC2, 0xBD, 0xC1, - 0x7D, 0xB7, 0x20, 0x04, 0x32, 0x78, 0x00, 0xC9, 0x3D, 0x20, 0xF2, 0xCD, 0xF6, 0xC3, 0xCB, 0x67, - 0x28, 0x06, 0x3E, 0x01, 0x32, 0x78, 0x00, 0xC9, 0xCD, 0x06, 0xC8, 0x53, 0x2E, 0x53, 0x69, 0x64, - 0x65, 0x64, 0x8D, 0xC3, 0x55, 0xC1, 0x06, 0x52, 0x18, 0x02, 0x06, 0x57, 0x1A, 0xFE, 0x44, 0xC2, - 0xBD, 0xC1, 0x78, 0x32, 0x70, 0x00, 0xCD, 0xBB, 0xC5, 0xE5, 0xFD, 0xE1, 0x60, 0x69, 0xD5, 0xE5, - 0x7B, 0x32, 0x76, 0x00, 0xFD, 0x22, 0x7B, 0x00, 0xCD, 0xD4, 0xC4, 0x3A, 0x70, 0x00, 0xFE, 0x57, - 0x37, 0x3F, 0xCC, 0xAB, 0xC5, 0x38, 0x08, 0x3A, 0x70, 0x00, 0xFE, 0x52, 0xCC, 0x52, 0xCD, 0xE1, - 0xD1, 0xDA, 0x0A, 0xC4, 0xED, 0x4B, 0x79, 0x00, 0xFD, 0x09, 0x03, 0xED, 0x42, 0x23, 0xDA, 0xF2, - 0xC5, 0x1C, 0x3A, 0x6E, 0x00, 0xBB, 0x30, 0xC6, 0x3A, 0x75, 0x00, 0x32, 0x7D, 0x00, 0x3C, 0x47, - 0x3A, 0x6F, 0x00, 0xB8, 0x38, 0x08, 0x78, 0x32, 0x75, 0x00, 0x1E, 0x01, 0x18, 0xB0, 0x1D, 0xCD, - 0xF2, 0xC5, 0xCD, 0x06, 0xC8, 0x4E, 0x65, 0x78, 0x74, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, - 0x3A, 0xA0, 0xFD, 0xE5, 0xE1, 0xCD, 0xE2, 0xC7, 0xCD, 0x06, 0xC8, 0x0D, 0x45, 0x6E, 0x64, 0x20, - 0x6F, 0x66, 0x20, 0x44, 0x69, 0x73, 0x6B, 0x8D, 0xC3, 0x55, 0xC1, 0x21, 0x7E, 0x00, 0x46, 0xC5, - 0xCB, 0xCE, 0xCD, 0x5F, 0xCD, 0xC1, 0x78, 0x32, 0x7E, 0x00, 0xC9, 0x3A, 0x6C, 0x00, 0xB7, 0xCA, - 0xBD, 0xC1, 0x13, 0xCD, 0x2F, 0xC8, 0xAF, 0xB2, 0xC2, 0xBD, 0xC1, 0xB3, 0xCA, 0xBD, 0xC1, 0xC5, - 0xD5, 0xE5, 0xCD, 0xF8, 0xC5, 0xE1, 0xD1, 0xC1, 0x3A, 0x6E, 0x00, 0xBB, 0x38, 0xEA, 0xDB, 0x31, - 0x57, 0xEB, 0xCD, 0xFC, 0xC7, 0xCD, 0xE2, 0xC7, 0xEB, 0xCD, 0xFC, 0xC7, 0x3A, 0x78, 0x00, 0xC3, - 0xF0, 0xC7, 0xCD, 0xDE, 0xC5, 0xC3, 0x97, 0xCC, 0x3A, 0x75, 0x00, 0xB7, 0x20, 0x20, 0x3A, 0x78, - 0x00, 0xB7, 0x20, 0x1A, 0x3A, 0x7E, 0x00, 0xCB, 0x6F, 0xC0, 0xCB, 0x4F, 0x20, 0x03, 0xCB, 0x47, - 0xC8, 0x32, 0x7F, 0x00, 0xCB, 0xEF, 0xCB, 0x87, 0x32, 0x7E, 0x00, 0xC3, 0x9B, 0xC3, 0x3A, 0x7E, - 0x00, 0xCB, 0x6F, 0xC8, 0x3A, 0x7F, 0x00, 0xC3, 0x87, 0xC3, 0xCD, 0x53, 0xC8, 0x4D, 0xED, 0x78, - 0xCD, 0xE7, 0xC7, 0xC3, 0x97, 0xCC, 0xCD, 0xAD, 0xC8, 0xE5, 0xCD, 0x1B, 0xC8, 0xCD, 0x53, 0xC8, - 0xD1, 0x4D, 0xED, 0x59, 0xC9, 0xCD, 0x2F, 0xC8, 0xC5, 0xD5, 0xE5, 0xED, 0xB0, 0xE1, 0xD1, 0xC1, - 0x18, 0x03, 0xCD, 0x2F, 0xC8, 0x1A, 0xBE, 0x28, 0x19, 0xCD, 0xE2, 0xC7, 0x7E, 0xCD, 0xDB, 0xC7, - 0xCD, 0xFC, 0xC7, 0x1A, 0xCD, 0xDB, 0xC7, 0xCD, 0xFC, 0xC7, 0xEB, 0xCD, 0xE2, 0xC7, 0xEB, 0xCD, - 0x97, 0xCC, 0x13, 0x23, 0x0B, 0x78, 0xB1, 0x20, 0xDC, 0xC9, 0xCD, 0x14, 0xC8, 0xFE, 0x4D, 0xC2, - 0xA1, 0xC4, 0x13, 0x2A, 0x64, 0x00, 0xCD, 0x5B, 0xC8, 0xCD, 0xE2, 0xC7, 0x7E, 0xCD, 0xDB, 0xC7, - 0xCD, 0xFC, 0xC7, 0xCD, 0xA3, 0xC7, 0xCD, 0x14, 0xC8, 0xFE, 0x2E, 0xC8, 0xFE, 0x2D, 0x20, 0x03, - 0x2B, 0x18, 0x1A, 0xCD, 0xF1, 0xC6, 0x30, 0x07, 0xCD, 0x06, 0xC8, 0x3F, 0x8D, 0x18, 0xDA, 0xAF, - 0x80, 0x20, 0x03, 0x23, 0x18, 0x07, 0x48, 0x06, 0x00, 0xEB, 0xED, 0xB0, 0xEB, 0x22, 0x64, 0x00, - 0x18, 0xC7, 0xCD, 0x65, 0xC8, 0xC5, 0xCD, 0xF1, 0xC6, 0xD1, 0xDA, 0xBD, 0xC1, 0xAF, 0x80, 0xCA, - 0xBD, 0xC1, 0xC5, 0xD5, 0xE5, 0x11, 0x2E, 0x00, 0x1A, 0xBE, 0x20, 0x04, 0x13, 0x23, 0x10, 0xF8, - 0xE1, 0xE5, 0x06, 0x10, 0xCC, 0x60, 0xC7, 0xE1, 0xD1, 0xC1, 0x23, 0x1B, 0x7A, 0xB3, 0x20, 0xE2, - 0xC9, 0xE5, 0x06, 0x00, 0x21, 0x2E, 0x00, 0xCD, 0x14, 0xC8, 0xB7, 0x28, 0x29, 0xFE, 0x2C, 0x13, - 0x28, 0xF5, 0x4F, 0xFE, 0x27, 0x28, 0x12, 0xFE, 0x22, 0x28, 0x0E, 0x1B, 0xE5, 0xCD, 0xAD, 0xC8, - 0x7D, 0xE1, 0x38, 0x12, 0x77, 0x23, 0x04, 0x18, 0xDE, 0x1A, 0x13, 0xB7, 0x28, 0x08, 0xB9, 0x28, - 0xD6, 0x77, 0x23, 0x04, 0x18, 0xF3, 0x11, 0x2E, 0x00, 0xE1, 0xC9, 0xCD, 0x14, 0xC8, 0xFE, 0x4D, - 0x20, 0x01, 0x13, 0x01, 0x80, 0x00, 0x2A, 0x62, 0x00, 0xCD, 0x4E, 0xC8, 0x1E, 0x10, 0xAF, 0xB0, - 0x20, 0x0A, 0x3E, 0x0F, 0xB9, 0x38, 0x05, 0xAF, 0xB1, 0x28, 0x01, 0x59, 0xC5, 0x43, 0xCD, 0x60, - 0xC7, 0x22, 0x62, 0x00, 0xC1, 0x79, 0x93, 0x4F, 0x30, 0x01, 0x05, 0x78, 0xB1, 0x20, 0xDD, 0xC9, - 0xCD, 0xE2, 0xC7, 0xC5, 0xE5, 0xD5, 0x0E, 0x00, 0x1E, 0x04, 0x3E, 0x03, 0xA1, 0xCC, 0xA0, 0xC7, - 0xCD, 0xA0, 0xC7, 0x7E, 0xCD, 0xE7, 0xC7, 0x1C, 0x1C, 0x23, 0x0C, 0x10, 0xED, 0xCD, 0xA0, 0xC7, - 0x3E, 0x3A, 0xBB, 0x20, 0xF8, 0xD1, 0xE1, 0xC1, 0x7E, 0x23, 0xCD, 0x92, 0xC7, 0x10, 0xF9, 0xC3, - 0x97, 0xCC, 0xE6, 0x7F, 0xFE, 0x7F, 0x28, 0x04, 0xFE, 0x20, 0x30, 0x62, 0x3E, 0x2E, 0x18, 0x5E, - 0x1C, 0x18, 0x59, 0x3E, 0x31, 0x11, 0x2E, 0x00, 0x12, 0xD5, 0xCD, 0xEA, 0xCB, 0xE3, 0x23, 0x46, - 0x04, 0x23, 0xE5, 0x05, 0x28, 0x17, 0x7E, 0xCD, 0xD2, 0xC7, 0x77, 0x23, 0xFE, 0x22, 0x28, 0x04, - 0xFE, 0x27, 0x20, 0xEF, 0x05, 0x28, 0x06, 0xBE, 0x23, 0x20, 0xF9, 0x18, 0xE6, 0x36, 0x00, 0xD1, - 0xE1, 0xC9, 0xFE, 0x61, 0xD8, 0xFE, 0x7B, 0xD0, 0xD6, 0x20, 0xC9, 0xF5, 0xCD, 0xFC, 0xC7, 0xF1, - 0x18, 0x05, 0x7C, 0xCD, 0xE7, 0xC7, 0x7D, 0xF5, 0x1F, 0x1F, 0x1F, 0x1F, 0xCD, 0xF0, 0xC7, 0xF1, - 0xE6, 0x0F, 0xFE, 0x0A, 0x38, 0x02, 0xC6, 0x07, 0xC6, 0x30, 0x18, 0x02, 0x3E, 0x20, 0xF5, 0xE6, - 0x7F, 0xCD, 0x99, 0xCC, 0xF1, 0xC9, 0xE3, 0x7E, 0x23, 0xB7, 0x28, 0x06, 0xCD, 0xFE, 0xC7, 0xF2, - 0x07, 0xC8, 0xE3, 0xC9, 0x1A, 0xFE, 0x20, 0xC0, 0x13, 0x18, 0xF9, 0xCD, 0x14, 0xC8, 0xFE, 0x2C, - 0xC0, 0x13, 0xCD, 0x14, 0xC8, 0xAF, 0xC9, 0xCD, 0x14, 0xC8, 0xB7, 0xC8, 0xC3, 0xBD, 0xC1, 0x21, - 0x80, 0x00, 0x44, 0x4D, 0xCD, 0x68, 0xC8, 0xE5, 0xC5, 0xCD, 0x1B, 0xC8, 0xCD, 0xAD, 0xC8, 0xDA, - 0xBD, 0xC1, 0xCD, 0x27, 0xC8, 0xEB, 0xC1, 0xE1, 0xC9, 0xCD, 0x65, 0xC8, 0x18, 0xD9, 0xCD, 0x68, - 0xC8, 0x18, 0xD4, 0xCD, 0xAD, 0xC8, 0xDA, 0xBD, 0xC1, 0x18, 0xCC, 0xE5, 0xCD, 0xAD, 0xC8, 0x38, - 0x01, 0xE3, 0xE1, 0x18, 0xC2, 0x37, 0x18, 0x01, 0xB7, 0x08, 0xC5, 0xE5, 0xCD, 0xAD, 0xC8, 0x30, - 0x08, 0x08, 0xDA, 0xBD, 0xC1, 0x08, 0xE1, 0x18, 0x01, 0xF1, 0xCD, 0x87, 0xC8, 0x30, 0x06, 0x08, - 0xC1, 0xD0, 0xC3, 0xBD, 0xC1, 0xF1, 0xC9, 0xCD, 0x1B, 0xC8, 0x1A, 0xFE, 0x53, 0x20, 0x01, 0x13, - 0xE5, 0xF5, 0xCD, 0xAD, 0xC8, 0x38, 0x0F, 0x44, 0x4D, 0xF1, 0xE1, 0x28, 0x07, 0x79, 0x95, 0x4F, - 0x78, 0x9C, 0x47, 0x03, 0xB7, 0xC9, 0xF1, 0xE1, 0xCA, 0xBD, 0xC1, 0x37, 0xC9, 0xCD, 0x14, 0xC8, - 0xCD, 0xE0, 0xC8, 0xD8, 0xD5, 0x13, 0xCD, 0xE0, 0xC8, 0x30, 0xFA, 0xD1, 0xFE, 0x2E, 0x28, 0x05, - 0xCD, 0xCA, 0xC8, 0xA7, 0xC9, 0xCD, 0xF4, 0xC8, 0xA7, 0xC9, 0x21, 0x00, 0x00, 0xCD, 0xE0, 0xC8, - 0x38, 0x09, 0x29, 0x29, 0x29, 0x29, 0x85, 0x6F, 0x13, 0x18, 0xF2, 0xFE, 0x48, 0xC0, 0x13, 0xC9, - 0x1A, 0xFE, 0x30, 0xD8, 0xFE, 0x3A, 0x38, 0x09, 0xFE, 0x41, 0xD8, 0xFE, 0x47, 0x3F, 0xD8, 0xD6, - 0x07, 0xD6, 0x30, 0xC9, 0x21, 0x00, 0x00, 0xCD, 0x10, 0xC9, 0x13, 0x38, 0x0D, 0xC5, 0x29, 0x44, - 0x4D, 0x29, 0x29, 0x09, 0xC1, 0xCD, 0x86, 0xC1, 0x18, 0xED, 0xFE, 0x2E, 0xC8, 0xC3, 0xBD, 0xC1, - 0x1A, 0xFE, 0x30, 0xD8, 0xFE, 0x3A, 0x3F, 0xD8, 0xD6, 0x30, 0xC9, 0x01, 0x18, 0x00, 0x11, 0x00, - 0x01, 0x21, 0x29, 0xC9, 0xED, 0xB0, 0xC3, 0x00, 0x01, 0x01, 0x00, 0x10, 0x11, 0x00, 0x10, 0x21, - 0x00, 0xC0, 0xC5, 0xD5, 0xE5, 0xED, 0xB0, 0x3E, 0x01, 0xD3, 0x40, 0xD1, 0xE1, 0xC1, 0xED, 0xB0, - 0xC9, 0xCD, 0x14, 0xC8, 0xFE, 0x5A, 0xF5, 0x20, 0x01, 0x13, 0xCD, 0x27, 0xC8, 0xF1, 0xC4, 0x1B, - 0xC9, 0xCD, 0x06, 0xC8, 0x0D, 0x4D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0xBA, 0x01, 0x00, 0x10, 0xCD, - 0xFC, 0xC7, 0x79, 0xCD, 0xF0, 0xC7, 0x0C, 0x10, 0xF6, 0xCD, 0x97, 0xCC, 0x06, 0x07, 0xCD, 0xFC, - 0xC7, 0x10, 0xFB, 0x60, 0x68, 0xCD, 0xFC, 0xC7, 0xE5, 0x11, 0x00, 0x10, 0x7C, 0xFE, 0xC9, 0x20, - 0x09, 0x7D, 0xFE, 0x8D, 0x38, 0x04, 0xFE, 0x9C, 0x38, 0x12, 0x46, 0x3E, 0x55, 0x77, 0xBE, 0x20, - 0x05, 0x2F, 0x77, 0xBE, 0x28, 0x05, 0x70, 0x3E, 0x58, 0x18, 0x09, 0x70, 0x23, 0x1B, 0x7A, 0xB3, - 0x20, 0xDA, 0x3E, 0x5E, 0xCD, 0xFE, 0xC7, 0xE1, 0x3E, 0x10, 0x84, 0x67, 0x20, 0xC7, 0xCD, 0x06, - 0xC8, 0x0D, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x20, 0x28, - 0x65, 0x67, 0x2C, 0x20, 0x41, 0x3B, 0x20, 0x6F, 0x72, 0x20, 0x41, 0x3B, 0x3B, 0x20, 0x6F, 0x72, - 0x20, 0x41, 0x3B, 0x3B, 0x3B, 0x29, 0xA0, 0xCD, 0xA3, 0xC7, 0xCD, 0x14, 0xC8, 0xB7, 0xCA, 0x97, - 0xCC, 0xCD, 0xC1, 0xC2, 0xC2, 0xB9, 0xC1, 0xCD, 0x06, 0xC8, 0x53, 0x65, 0x65, 0x6B, 0x20, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x3A, 0x8D, 0x06, 0x15, 0x21, 0x20, 0xCA, 0xDB, 0x31, 0x32, 0x7D, 0x00, - 0x7E, 0xC5, 0xE5, 0xFE, 0xFF, 0x20, 0x2E, 0xCD, 0x06, 0xC8, 0x20, 0x52, 0x65, 0x73, 0x74, 0x6F, - 0x72, 0x65, 0xBA, 0xCD, 0x04, 0xC6, 0xCD, 0x37, 0xCD, 0x08, 0xCD, 0x1E, 0xC6, 0x08, 0x18, 0x2C, - 0x01, 0x02, 0x03, 0x04, 0x05, 0xFE, 0x06, 0x07, 0x08, 0x09, 0x00, 0xFE, 0x27, 0x00, 0x15, 0x00, - 0x01, 0xFE, 0xFF, 0xFE, 0x27, 0xFE, 0xFE, 0x20, 0x06, 0xCD, 0x97, 0xCC, 0xB7, 0x18, 0x12, 0x32, - 0x75, 0x00, 0xCD, 0xDB, 0xC7, 0xCD, 0x06, 0xC8, 0xBA, 0xCD, 0xD4, 0xC4, 0xF5, 0xCD, 0x7A, 0xCB, - 0xF1, 0xE1, 0xC1, 0xDA, 0x97, 0xCC, 0x23, 0x10, 0xA2, 0xCD, 0x06, 0xC8, 0x0D, 0x52, 0x65, 0x61, - 0x64, 0x2F, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x74, 0x65, 0x73, 0x74, 0x73, 0x8D, 0xCD, 0x94, - 0xCB, 0xCD, 0xB0, 0xCB, 0xDA, 0x97, 0xCC, 0xCD, 0x06, 0xC8, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, - 0x74, 0x65, 0x73, 0x74, 0x20, 0x4D, 0x41, 0x59, 0x20, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4F, 0x59, - 0x20, 0x64, 0x61, 0x74, 0x61, 0x0D, 0x45, 0x53, 0x43, 0x3D, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x20, - 0x52, 0x45, 0x54, 0x55, 0x52, 0x4E, 0x3D, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x65, 0x64, 0xA0, 0xCD, - 0xA3, 0xC7, 0x21, 0x00, 0x09, 0xCD, 0xA2, 0xCB, 0x01, 0x00, 0x02, 0x75, 0x23, 0x0B, 0x78, 0xB1, - 0x20, 0xF9, 0xCD, 0xC1, 0xCB, 0x30, 0x6E, 0xCD, 0x06, 0xC8, 0x54, 0x65, 0x73, 0x74, 0x20, 0x66, - 0x61, 0x69, 0x6C, 0x65, 0x64, 0x21, 0x0D, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x64, 0x61, 0x74, 0x61, - 0x20, 0x61, 0xF4, 0x1E, 0x01, 0xCD, 0xDE, 0xC5, 0xCD, 0x06, 0xC8, 0x20, 0x6D, 0x61, 0x79, 0x20, - 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6E, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6F, - 0x79, 0x65, 0x64, 0x0D, 0x4F, 0x72, 0x69, 0x67, 0x69, 0x6E, 0x61, 0x6C, 0x20, 0x69, 0x73, 0x20, - 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, 0x30, 0x44, 0x30, 0x30, 0xF3, - 0x2A, 0x79, 0x00, 0xCD, 0xE2, 0xC7, 0xCD, 0x06, 0xC8, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x65, 0x6D, - 0x6F, 0x72, 0x79, 0x8D, 0xC9, 0x21, 0x00, 0x0B, 0xCD, 0xA2, 0xCB, 0xCD, 0xB0, 0xCB, 0x38, 0x87, - 0xCD, 0x06, 0xC8, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6E, 0x20, 0x63, 0x6F, 0x6D, 0x70, 0x61, - 0x72, 0x65, 0xA0, 0xED, 0x4B, 0x79, 0x00, 0x11, 0x00, 0x09, 0x21, 0x00, 0x0B, 0x1A, 0xBE, 0x20, - 0x09, 0x13, 0x23, 0x0B, 0x78, 0xB1, 0x20, 0xF5, 0x18, 0x01, 0x37, 0xCD, 0xD1, 0xCB, 0xCD, 0x94, - 0xCB, 0xCD, 0xC1, 0xCB, 0xDA, 0xC7, 0xCA, 0xC3, 0x97, 0xCC, 0x38, 0x06, 0xCD, 0x06, 0xC8, 0x4F, - 0xCB, 0xC9, 0xCD, 0x06, 0xC8, 0x65, 0x72, 0x72, 0x6F, 0x72, 0xA0, 0x3A, 0x71, 0x00, 0xCD, 0xE7, - 0xC7, 0xC3, 0x97, 0xCC, 0xCD, 0x06, 0xC8, 0x44, 0x61, 0x74, 0xE1, 0x21, 0x00, 0x0D, 0x22, 0x7B, - 0x00, 0xC9, 0x22, 0x7B, 0x00, 0xCD, 0x06, 0xC8, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0xEE, 0xC9, - 0xCD, 0xDA, 0xCB, 0xCD, 0x06, 0xC8, 0x20, 0x72, 0x65, 0x61, 0x64, 0xA0, 0xCD, 0x52, 0xCD, 0x18, - 0x10, 0xCD, 0xDA, 0xCB, 0xCD, 0x06, 0xC8, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0xA0, 0xCD, 0xAB, - 0xC5, 0xF5, 0xCD, 0x7A, 0xCB, 0xCD, 0x97, 0xCC, 0xF1, 0xC9, 0x3E, 0x27, 0x32, 0x75, 0x00, 0x32, - 0x7D, 0x00, 0x3E, 0x01, 0x32, 0x76, 0x00, 0xC3, 0xCB, 0xCD, 0xC5, 0xE5, 0x06, 0x00, 0x21, 0x02, - 0x00, 0x19, 0xCD, 0x64, 0xCC, 0xFE, 0x10, 0xCC, 0xBB, 0xCC, 0x28, 0xF6, 0xFE, 0x1B, 0xCA, 0x8E, - 0xCC, 0xFE, 0x08, 0x28, 0x04, 0xFE, 0x7F, 0x20, 0x11, 0xAF, 0xB0, 0x28, 0xE5, 0x2B, 0x05, 0xCD, - 0x4B, 0xCC, 0x7E, 0xFE, 0x20, 0xDC, 0x4B, 0xCC, 0x18, 0xD8, 0xFE, 0x0D, 0xCC, 0x45, 0xCC, 0x28, - 0x1B, 0xFE, 0x15, 0x20, 0x08, 0xCD, 0x45, 0xCC, 0xCD, 0x97, 0xCC, 0x18, 0xBF, 0x4F, 0x1A, 0x3D, - 0xB8, 0x28, 0xBF, 0x79, 0xCD, 0x45, 0xCC, 0x77, 0x23, 0x04, 0x18, 0xB6, 0x36, 0x00, 0x78, 0x13, - 0x12, 0x1B, 0xE1, 0xC1, 0xC9, 0xF5, 0xCD, 0x52, 0xCC, 0xF1, 0xC9, 0xCD, 0x06, 0xC8, 0x08, 0x20, - 0x88, 0xC9, 0xFE, 0x20, 0x30, 0x43, 0xFE, 0x0D, 0x28, 0x3F, 0xF5, 0xCD, 0x06, 0xC8, 0xDE, 0xF1, - 0xC6, 0x40, 0x18, 0x35, 0xCD, 0x23, 0xCD, 0xCD, 0x76, 0xCC, 0x28, 0xF8, 0xCD, 0x76, 0xCC, 0x28, - 0xFB, 0xDB, 0x01, 0xE6, 0x7F, 0xC9, 0xDB, 0x00, 0xE6, 0x40, 0xC9, 0xCD, 0x76, 0xCC, 0xC8, 0xCD, - 0x6C, 0xCC, 0xFE, 0x13, 0xCC, 0x6C, 0xCC, 0xFE, 0x0D, 0x28, 0x03, 0xFE, 0x1B, 0xC0, 0x31, 0x2E, - 0x00, 0xCD, 0x97, 0xCC, 0xC3, 0x55, 0xC1, 0x3E, 0x0D, 0xF5, 0xD9, 0xCB, 0x78, 0xD9, 0xC4, 0xCB, - 0xCC, 0xCD, 0x23, 0xCD, 0xDB, 0x00, 0xE6, 0x80, 0x28, 0xFA, 0xF1, 0xD3, 0x01, 0xFE, 0x0D, 0xC0, - 0x3E, 0x0A, 0xCD, 0x99, 0xCC, 0xCD, 0x7B, 0xCC, 0xFE, 0x10, 0xC0, 0xF5, 0xD9, 0x3E, 0x80, 0xA8, - 0x47, 0xCB, 0x78, 0xD9, 0xC4, 0xC9, 0xCC, 0xF1, 0xC9, 0x3E, 0x11, 0xF5, 0xE5, 0x21, 0x08, 0x00, - 0xCD, 0xF1, 0xCF, 0xE1, 0xF1, 0xF5, 0xFE, 0x11, 0x28, 0x13, 0xCD, 0x7B, 0xCC, 0xFE, 0x10, 0x20, - 0x05, 0xCD, 0xBB, 0xCC, 0xF1, 0xC9, 0xDB, 0x54, 0x2F, 0xE6, 0x20, 0x28, 0xED, 0xF1, 0xCB, 0xFF, - 0xD3, 0x54, 0xCB, 0xBF, 0xD3, 0x54, 0xCB, 0xFF, 0xD3, 0x54, 0xCB, 0xBF, 0xC9, 0xCD, 0x14, 0xC8, - 0xFE, 0x4F, 0xC2, 0xBD, 0xC1, 0x13, 0x1A, 0xFE, 0x4E, 0x28, 0x0E, 0xFE, 0x46, 0xC2, 0xBD, 0xC1, - 0xD9, 0xCB, 0xA8, 0xD9, 0x3E, 0xFF, 0xD3, 0x04, 0xC9, 0xD9, 0xCB, 0xE8, 0xD9, 0x3E, 0x01, 0x32, - 0x72, 0x00, 0xC9, 0xD9, 0xCB, 0x68, 0xD9, 0xC8, 0xC5, 0xCD, 0xA8, 0xCF, 0xC1, 0xD3, 0x34, 0xCD, - 0xD6, 0xCF, 0xEE, 0xA0, 0xD3, 0x04, 0xC9, 0x16, 0x02, 0xD5, 0xCD, 0x70, 0xCD, 0xD1, 0xD0, 0xD5, - 0x3E, 0x0A, 0x32, 0x75, 0x00, 0xCD, 0xCB, 0xCD, 0xCD, 0x70, 0xCD, 0xD1, 0xD0, 0x15, 0x20, 0xE9, - 0x18, 0x18, 0x16, 0x0A, 0xD5, 0xCD, 0x58, 0xCE, 0xD1, 0xD0, 0x15, 0x20, 0xF7, 0x18, 0x0B, 0x16, - 0x04, 0xD5, 0xCD, 0x9F, 0xCE, 0xD1, 0xD0, 0x15, 0x20, 0xF7, 0x3A, 0x71, 0x00, 0x4F, 0x37, 0xC9, - 0x97, 0x32, 0x75, 0x00, 0x32, 0x78, 0x00, 0xCD, 0x55, 0xCF, 0xD3, 0x34, 0xCD, 0x25, 0xCE, 0x38, - 0x0E, 0xD3, 0x30, 0xDB, 0x34, 0xCB, 0x57, 0x20, 0x3B, 0x1F, 0x30, 0xF7, 0xC3, 0x3E, 0xCE, 0x3E, - 0xC4, 0xD3, 0x30, 0xCD, 0xD6, 0xCF, 0xE6, 0x57, 0xD3, 0x04, 0xCD, 0xE4, 0xCF, 0xDB, 0x04, 0xE6, - 0x40, 0x20, 0x16, 0xCD, 0xCF, 0xCF, 0xDB, 0x34, 0xCB, 0x57, 0x20, 0x18, 0x1F, 0x30, 0xF7, 0x3E, - 0xD0, 0xD3, 0x30, 0x97, 0xD3, 0x31, 0xC3, 0x50, 0xCE, 0xDB, 0x34, 0xCB, 0x57, 0x20, 0x05, 0x1F, - 0x30, 0xDB, 0x18, 0xCB, 0x3E, 0x80, 0x32, 0x71, 0x00, 0x37, 0xC9, 0x97, 0xCD, 0x55, 0xCF, 0xD3, - 0x34, 0x3A, 0x75, 0x00, 0xD3, 0x33, 0x4F, 0x3A, 0x76, 0x00, 0xD3, 0x32, 0x3A, 0x7D, 0x00, 0xD3, - 0x31, 0x91, 0xCA, 0xCF, 0xCF, 0xCD, 0x25, 0xCE, 0x38, 0x0F, 0xF6, 0x10, 0xD3, 0x30, 0xDB, 0x34, - 0xCB, 0x57, 0x20, 0xD0, 0x1F, 0x30, 0xF7, 0x18, 0x45, 0xCD, 0xD6, 0xCF, 0xE6, 0x4F, 0xD3, 0x04, - 0x3E, 0x18, 0xD3, 0x30, 0xDB, 0x34, 0xCB, 0x57, 0x20, 0xBA, 0x1F, 0x30, 0xF7, 0xDB, 0x30, 0x2E, - 0x32, 0xDB, 0x04, 0xE6, 0x40, 0x20, 0xFA, 0x2D, 0x20, 0xF7, 0xDB, 0x04, 0xE6, 0x40, 0x20, 0xFA, - 0xCD, 0xCF, 0xCF, 0x18, 0x2B, 0x3A, 0x7E, 0x00, 0xCB, 0x57, 0x20, 0x0A, 0xCB, 0x5F, 0x3E, 0x0E, - 0x28, 0x02, 0x3E, 0x0C, 0xA7, 0xC9, 0xCB, 0x5F, 0x3E, 0x0F, 0x28, 0xF8, 0x37, 0xC9, 0xCD, 0xCF, - 0xCF, 0x21, 0x64, 0x00, 0xCD, 0xF1, 0xCF, 0xDB, 0x30, 0x32, 0x71, 0x00, 0xE6, 0x98, 0x37, 0xC0, - 0x3A, 0x75, 0x00, 0x32, 0x7D, 0x00, 0xA7, 0xC9, 0xCD, 0x8F, 0xCE, 0xD3, 0x30, 0xDB, 0x34, 0x1F, - 0x38, 0x16, 0xED, 0xA2, 0x04, 0xDB, 0x34, 0x1F, 0x38, 0x0E, 0xED, 0xA2, 0xC2, 0x5D, 0xCE, 0xDB, - 0x34, 0xCB, 0x4F, 0x20, 0x10, 0x1F, 0x30, 0xF7, 0xCD, 0xCF, 0xCF, 0xDB, 0x30, 0x32, 0x71, 0x00, - 0xE6, 0x9C, 0xC8, 0x18, 0x08, 0xCD, 0xCF, 0xCF, 0x3E, 0x80, 0x32, 0x71, 0x00, 0x37, 0xC9, 0xCD, - 0x40, 0xCF, 0x57, 0xF3, 0xCD, 0xC6, 0xCF, 0xC6, 0x88, 0x5F, 0x7A, 0xD3, 0x34, 0x7B, 0xC9, 0xCD, - 0xE4, 0xCF, 0xCD, 0x40, 0xCF, 0x57, 0xF3, 0xCD, 0xC6, 0xCF, 0xC6, 0xA8, 0x5F, 0x7A, 0xD3, 0x34, - 0x7B, 0xD3, 0x30, 0xDB, 0x34, 0x1F, 0x38, 0x12, 0xED, 0xA3, 0x04, 0xDB, 0x34, 0x1F, 0x38, 0x0A, - 0xED, 0xA3, 0xC2, 0xB3, 0xCE, 0xDB, 0x34, 0x1F, 0x30, 0xFB, 0xCD, 0xCF, 0xCF, 0xCD, 0xE4, 0xCF, - 0xDB, 0x30, 0x32, 0x71, 0x00, 0xE6, 0xFC, 0x37, 0xC0, 0xA7, 0x3A, 0x7E, 0x00, 0xCB, 0x4F, 0xC8, - 0xCD, 0x00, 0xCF, 0x38, 0x0A, 0xDB, 0x34, 0x1F, 0x38, 0x04, 0xDB, 0x33, 0x18, 0xF7, 0x1C, 0xCD, - 0xCF, 0xCF, 0xDB, 0x30, 0x32, 0x71, 0x00, 0xE6, 0x9C, 0x37, 0xC0, 0x7B, 0xA7, 0xC8, 0x37, 0xC9, - 0xCD, 0x8F, 0xCE, 0xED, 0x4B, 0x79, 0x00, 0xCB, 0x38, 0xCB, 0x19, 0xCB, 0x38, 0xCB, 0x19, 0x41, - 0x1E, 0x00, 0xD3, 0x30, 0xDB, 0x34, 0x1F, 0xD8, 0xDB, 0x33, 0xAE, 0xC0, 0x23, 0xDB, 0x34, 0x1F, - 0xD8, 0xDB, 0x33, 0xAE, 0xC0, 0x23, 0xDB, 0x34, 0x1F, 0xD8, 0xDB, 0x33, 0xAE, 0xC0, 0x23, 0xDB, - 0x34, 0x1F, 0xD8, 0xDB, 0x33, 0xAE, 0xC0, 0x23, 0x10, 0xDA, 0xDB, 0x34, 0x1F, 0x30, 0xFB, 0xC9, - 0xDB, 0x33, 0x3E, 0x80, 0xCD, 0x55, 0xCF, 0x2A, 0x79, 0x00, 0xCB, 0x1C, 0xCB, 0x1D, 0x45, 0x0E, - 0x33, 0x2A, 0x7B, 0x00, 0xC9, 0x4F, 0xDB, 0x34, 0xE6, 0x04, 0x28, 0x04, 0x97, 0x32, 0x72, 0x00, - 0xCD, 0xA8, 0xCF, 0xD3, 0x34, 0xF5, 0xE5, 0xCD, 0xD6, 0xCF, 0xE6, 0x5F, 0xD3, 0x04, 0x3A, 0x72, - 0x00, 0xA7, 0x28, 0x21, 0x21, 0x90, 0x01, 0x3A, 0x73, 0x00, 0xB8, 0x20, 0x1B, 0x3A, 0x74, 0x00, - 0x67, 0x3A, 0x78, 0x00, 0x32, 0x74, 0x00, 0xBC, 0x20, 0x06, 0xDB, 0x34, 0xE6, 0x20, 0x20, 0x0B, - 0xCD, 0xE4, 0xCF, 0x18, 0x06, 0x21, 0x20, 0x4E, 0xCD, 0xF1, 0xCF, 0xE1, 0x78, 0x32, 0x73, 0x00, - 0x3E, 0x01, 0x32, 0x72, 0x00, 0xF1, 0xB1, 0xC9, 0x3A, 0x77, 0x00, 0x47, 0x04, 0x97, 0x37, 0x17, - 0x10, 0xFD, 0x47, 0x3A, 0x7E, 0x00, 0xCB, 0x57, 0x28, 0x02, 0xCB, 0xE0, 0xCB, 0x47, 0x28, 0x02, - 0xCB, 0xF0, 0x78, 0xF6, 0x20, 0xC9, 0xDB, 0x34, 0x2F, 0xE6, 0x20, 0xC8, 0x3E, 0x04, 0xC9, 0xCD, - 0xD6, 0xCF, 0xD3, 0x04, 0xAF, 0xC9, 0xC5, 0x06, 0x7F, 0x3A, 0x78, 0x00, 0xA7, 0x28, 0x02, 0x06, - 0x7D, 0x78, 0xC1, 0xC9, 0x21, 0x08, 0x00, 0x3A, 0x7E, 0x00, 0xCB, 0x57, 0x20, 0x03, 0x21, 0x0C, - 0x00, 0xC5, 0x2B, 0x06, 0x1C, 0x10, 0xFE, 0x00, 0x00, 0x7D, 0xB4, 0x20, 0xF5, 0xC1, 0xC9, 0xFF, - 0xF3, 0x18, 0x3C, 0xC3, 0x30, 0xC0, 0xC3, 0x04, 0xC5, 0xC3, 0x37, 0xC0, 0xC3, 0x3B, 0xC0, 0xC3, - 0x9E, 0xCB, 0xC3, 0x37, 0xCD, 0xC3, 0xD4, 0xC4, 0xC3, 0x52, 0xCD, 0xC3, 0xAB, 0xC5, 0xC3, 0x4B, - 0xC2, 0xC3, 0x6C, 0xCC, 0xC3, 0x76, 0xCC, 0xC3, 0xEA, 0xCB, 0xC3, 0xFE, 0xC7, 0xC3, 0x97, 0xCC, - 0x32, 0x77, 0x00, 0x78, 0xC3, 0x87, 0xC3, 0x32, 0x75, 0x00, 0xC9, 0x32, 0x76, 0x00, 0xC9, 0xAF, - 0xD3, 0x03, 0x47, 0xD9, 0x2F, 0xD3, 0x04, 0x3E, 0xD0, 0xD3, 0x30, 0x21, 0x2E, 0x00, 0xF9, 0x25, - 0x20, 0xFD, 0x74, 0x2C, 0x20, 0xFC, 0x24, 0x22, 0x62, 0x00, 0x22, 0x64, 0x00, 0xCD, 0x4B, 0xC2, - 0xDB, 0x34, 0xE6, 0x40, 0xC2, 0x39, 0xC1, 0xDB, 0x04, 0x2F, 0xE6, 0x03, 0x32, 0x77, 0x00, 0xCD, - 0x06, 0xC8, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x74, 0x6F, 0x20, 0x62, - 0x6F, 0x6F, 0x74, 0x2C, 0x20, 0x45, 0x53, 0x43, 0x20, 0x74, 0x6F, 0x20, 0x61, 0x62, 0x6F, 0x72, - 0x74, 0x8D, 0xCD, 0xA8, 0xCF, 0x57, 0xD3, 0x34, 0x06, 0x64, 0xCD, 0x28, 0xC1, 0x21, 0x64, 0x00, - 0xCD, 0xF1, 0xCF, 0x10, 0xF5, 0x32, 0x75, 0x00, 0x32, 0x7D, 0x00, 0x32, 0x78, 0x00, 0x3C, 0x32, - 0x76, 0x00, 0xCD, 0xF7, 0xC1, 0x32, 0x7E, 0x00, 0x21, 0x80, 0x00, 0x22, 0x7B, 0x00, 0x22, 0x79, - 0x00, 0x3E, 0x42, 0x32, 0x70, 0x00, 0x06, 0x02, 0xC5, 0xCD, 0x37, 0xCD, 0xD4, 0xCB, 0xCD, 0xD4, - 0x52, 0xCD, 0xC1, 0x30, 0x13, 0xCD, 0x28, 0xC1, 0x10, 0xEE, 0xCD, 0x06, 0xC8, 0x0D, 0x55, 0x6E, - 0x61, 0x62, 0x6C, 0x65, 0x20, 0xF4, 0x18, 0x2D, 0x3A, 0x80, 0x00, 0xFE, 0x40, 0x28, 0x04, 0xFE, - 0xE5, 0x20, 0x07, 0xCD, 0x06, 0xC8, 0x0D, 0xCE, 0x18, 0x1B, 0xCD, 0x28, 0xC1, 0xCD, 0xA8, 0xCF, - 0x57, 0x3A, 0x77, 0x00, 0x08, 0xCD, 0x06, 0xC8, 0x0D, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x62, 0x79, - 0x8D, 0x37, 0xC3, 0x80, 0x00, 0xCD, 0x06, 0xC8, 0x6F, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x8D, 0x3A, - 0x71, 0x00, 0xB7, 0xC4, 0x59, 0xC3, 0x18, 0x09, 0xCD, 0x76, 0xCC, 0xC4, 0x6C, 0xCC, 0xFE, 0x1B, - 0xC0, 0x3E, 0xD0, 0xD3, 0x30, 0x3E, 0x7C, 0xD3, 0x04, 0xCD, 0x06, 0xC8, 0x0D, 0x43, 0x72, 0x6F, - 0x6D, 0x65, 0x6D, 0x63, 0x6F, 0x20, 0x52, 0x44, 0x4F, 0x53, 0x20, 0x30, 0x32, 0x2E, 0x35, 0x32, - 0x8D, 0xAF, 0x32, 0x6C, 0x00, 0x3A, 0x7E, 0x00, 0x47, 0xCD, 0xE2, 0xC1, 0x31, 0x2E, 0x00, 0xCD, - 0x06, 0xC8, 0xBB, 0xCD, 0xA3, 0xC7, 0xCD, 0x14, 0xC8, 0xA7, 0x28, 0xE5, 0xCD, 0xC1, 0xC2, 0x28, - 0xE4, 0x78, 0xFE, 0x17, 0x30, 0x47, 0x87, 0x21, 0x8B, 0xC1, 0xCD, 0x86, 0xC1, 0x7E, 0x23, 0x66, - 0x6F, 0xCD, 0xC7, 0xC1, 0x18, 0xCF, 0x85, 0x6F, 0xD0, 0x24, 0xC9, 0xFD, 0xCC, 0xC8, 0xC1, 0xBD, - 0xC1, 0x2B, 0xC7, 0x2A, 0xC6, 0xBD, 0xC1, 0xC4, 0xC1, 0xBD, 0xC1, 0x45, 0xC2, 0xBD, 0xC1, 0xBD, - 0xC1, 0x39, 0xC4, 0x45, 0xC6, 0xBD, 0xC1, 0x36, 0xC6, 0xBD, 0xC1, 0xC2, 0xC6, 0x16, 0xC5, 0x7A, - 0xC6, 0x41, 0xC9, 0xBD, 0xC1, 0x52, 0xC6, 0x1A, 0xC5, 0xAF, 0x32, 0x6C, 0x00, 0xCD, 0x06, 0xC8, - 0x3F, 0x8D, 0x18, 0x91, 0xCD, 0x53, 0xC8, 0xE9, 0xCD, 0x14, 0xC8, 0xB7, 0xCA, 0x67, 0xC0, 0xFE, - 0x45, 0xD2, 0x2A, 0xC4, 0xD6, 0x41, 0xDA, 0x2A, 0xC4, 0xF5, 0x13, 0xCD, 0x27, 0xC8, 0xF1, 0xC3, - 0x6C, 0xC0, 0x3A, 0x6C, 0x00, 0xB7, 0xC8, 0xCD, 0xFE, 0xC7, 0xCB, 0x58, 0xC0, 0xCB, 0x78, 0x3E, - 0x3B, 0xC4, 0xFE, 0xC7, 0xC3, 0xFE, 0xC7, 0x7A, 0xD3, 0x34, 0x3E, 0xDF, 0xD3, 0x04, 0x3E, 0xD4, - 0xD3, 0x30, 0xDB, 0x34, 0x0F, 0x30, 0xFB, 0xDB, 0x30, 0x01, 0x00, 0x02, 0xCD, 0x3B, 0xC2, 0x3E, - 0xD4, 0xD3, 0x30, 0xCD, 0x34, 0xC2, 0x28, 0xDF, 0xDB, 0x34, 0x0F, 0x30, 0xF6, 0xDB, 0x30, 0x10, - 0xEE, 0xAF, 0xD3, 0x03, 0x79, 0xFE, 0x5A, 0x30, 0x03, 0x87, 0x87, 0x87, 0xFE, 0xB7, 0x3E, 0x80, - 0xD0, 0x3E, 0x04, 0xC9, 0xDB, 0x03, 0xFE, 0xC7, 0xC0, 0x0C, 0xC8, 0x3E, 0x01, 0xD3, 0x03, 0x3E, - 0xFA, 0xD3, 0x05, 0x18, 0xEF, 0xCD, 0x27, 0xC8, 0xCD, 0x97, 0xCC, 0xDB, 0x04, 0xE6, 0x08, 0x28, - 0x5D, 0x3E, 0x0A, 0xD3, 0x02, 0x21, 0xD0, 0x07, 0xCD, 0xF1, 0xCF, 0x3E, 0x08, 0xD3, 0x02, 0x16, - 0x64, 0x15, 0x28, 0xED, 0x21, 0xB9, 0xC2, 0x0E, 0x00, 0x3E, 0x19, 0x06, 0x09, 0xD3, 0x02, 0xED, - 0xA3, 0x28, 0xEE, 0xCD, 0x98, 0xC2, 0xCD, 0x98, 0xC2, 0x38, 0xE9, 0xFE, 0x0D, 0x3E, 0x09, 0x20, - 0xEC, 0x3E, 0x0D, 0xD3, 0x01, 0x21, 0xA0, 0x0F, 0xCD, 0xF1, 0xCF, 0xCD, 0x76, 0xCC, 0xC4, 0x6C, - 0xCC, 0xFE, 0x0D, 0x28, 0xEC, 0xC3, 0x97, 0xCC, 0xD5, 0x11, 0xA0, 0x8C, 0xCD, 0x76, 0xCC, 0x28, - 0x05, 0xCD, 0x6C, 0xCC, 0x18, 0x06, 0x1B, 0x7A, 0xB3, 0x20, 0xF1, 0x37, 0xD1, 0xC9, 0x3E, 0x09, - 0xD3, 0x02, 0x3E, 0x84, 0xD3, 0x00, 0xC3, 0x97, 0xCC, 0x90, 0xC0, 0xA0, 0x90, 0x88, 0x84, 0x82, - 0x01, 0xD6, 0x41, 0xDA, 0xBD, 0xC1, 0x47, 0x13, 0x1A, 0xFE, 0x3B, 0xC0, 0x78, 0xFE, 0x04, 0xD2, - 0x2A, 0xC4, 0xC6, 0x41, 0x32, 0x6C, 0x00, 0xCD, 0xF6, 0xC3, 0x13, 0x1A, 0xFE, 0x3B, 0x06, 0x0C, - 0x20, 0x0B, 0x13, 0x1A, 0xFE, 0x3B, 0x06, 0x04, 0x20, 0x03, 0x06, 0x80, 0x13, 0xC5, 0xCD, 0xB7, - 0xC3, 0xC1, 0x70, 0x30, 0x06, 0x3A, 0x6D, 0x00, 0xB0, 0x77, 0x37, 0xF5, 0xCD, 0x84, 0xC3, 0x32, - 0x78, 0x00, 0x32, 0x7D, 0x00, 0x3C, 0x32, 0x76, 0x00, 0xCD, 0x04, 0xC6, 0x3E, 0x48, 0x32, 0x70, - 0x00, 0xCD, 0x37, 0xCD, 0xF5, 0xCD, 0x1E, 0xC6, 0xF1, 0xDA, 0x0D, 0xC4, 0xF1, 0xDA, 0xB5, 0xC3, - 0xCD, 0x04, 0xC6, 0x21, 0x00, 0x01, 0x22, 0x7B, 0x00, 0xCD, 0xCB, 0xCD, 0xCD, 0x52, 0xCD, 0xF5, - 0xCD, 0x1E, 0xC6, 0xF1, 0x30, 0x2D, 0x3A, 0x71, 0x00, 0xB7, 0xF2, 0x45, 0xC3, 0x21, 0x64, 0x00, - 0xCD, 0xF1, 0xCF, 0x18, 0xDB, 0xCD, 0x06, 0xC8, 0x43, 0x61, 0x6E, 0x27, 0x74, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x20, 0x4C, 0x61, 0x62, 0x65, 0x6C, 0x8D, 0x1E, 0x01, 0xCD, 0xF2, 0xC5, 0xCD, 0x13, - 0xC4, 0xAF, 0xC9, 0x01, 0x10, 0x00, 0x11, 0x7A, 0x01, 0xCD, 0xEE, 0xC3, 0x0E, 0x01, 0xCD, 0xEE, - 0xC3, 0x3A, 0x78, 0x01, 0xFE, 0x43, 0x20, 0x02, 0xCB, 0xC8, 0x3A, 0x7E, 0x00, 0xE6, 0xCC, 0xB0, - 0x2A, 0x6A, 0x00, 0x77, 0xCD, 0xF6, 0xC3, 0x32, 0x7E, 0x00, 0xCB, 0x47, 0x11, 0x0A, 0x10, 0x21, - 0x00, 0x02, 0x20, 0x0D, 0xCB, 0x4F, 0x11, 0x05, 0x08, 0x20, 0x06, 0x11, 0x12, 0x1A, 0x21, 0x80, - 0x00, 0x22, 0x79, 0x00, 0xCB, 0x7F, 0x3E, 0x4C, 0x42, 0x28, 0x03, 0x3E, 0x27, 0x43, 0x32, 0x6F, - 0x00, 0x78, 0x32, 0x6E, 0x00, 0xAF, 0xC9, 0xCD, 0x14, 0xC8, 0xB7, 0xC8, 0x01, 0x10, 0x00, 0xCD, - 0xDE, 0xC3, 0x0E, 0x01, 0xCD, 0xDE, 0xC3, 0xCD, 0x14, 0xC8, 0xFE, 0x43, 0x20, 0x06, 0xCB, 0xC8, - 0x13, 0xCD, 0x14, 0xC8, 0xB7, 0xC2, 0xB9, 0xC1, 0x78, 0x32, 0x6D, 0x00, 0x37, 0xC9, 0xCD, 0x14, - 0xC8, 0x13, 0xFE, 0x53, 0xC8, 0xFE, 0x44, 0xC2, 0xB9, 0xC1, 0x78, 0xB1, 0x47, 0xC9, 0x1A, 0x13, - 0x13, 0xFE, 0x44, 0xC0, 0x18, 0xF4, 0x3A, 0x6C, 0x00, 0xD6, 0x41, 0x32, 0x77, 0x00, 0x21, 0x66, - 0x00, 0xCD, 0x86, 0xC1, 0x22, 0x6A, 0x00, 0x7E, 0xB7, 0xC9, 0xCD, 0xF2, 0xC5, 0xCD, 0x13, 0xC4, - 0xC3, 0x55, 0xC1, 0xCD, 0x06, 0xC8, 0x20, 0x45, 0x72, 0x72, 0xAD, 0x3A, 0x70, 0x00, 0xCD, 0xFE, - 0xC7, 0x3A, 0x71, 0x00, 0xCD, 0xDB, 0xC7, 0xC3, 0x97, 0xCC, 0xCD, 0x06, 0xC8, 0x41, 0x2D, 0x44, - 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x8D, 0xC3, 0x55, 0xC1, 0xCD, 0x27, 0xC8, 0x3A, 0x77, 0x00, 0xF5, - 0x3A, 0x6C, 0x00, 0xF5, 0x3E, 0x41, 0xF5, 0x32, 0x6C, 0x00, 0xCD, 0xF6, 0xC3, 0x2A, 0x6A, 0x00, - 0x46, 0xC4, 0x63, 0xC4, 0xF1, 0x3C, 0xFE, 0x45, 0x38, 0xEC, 0xF1, 0x32, 0x6C, 0x00, 0xF1, 0x32, - 0x77, 0x00, 0xC9, 0xCD, 0x06, 0xC8, 0x20, 0xA0, 0xCD, 0xE2, 0xC1, 0xCD, 0x06, 0xC8, 0x3B, 0xA0, - 0xCB, 0x58, 0xC4, 0xFC, 0xC7, 0xCB, 0x78, 0xCC, 0xFC, 0xC7, 0xCB, 0x60, 0xCD, 0x98, 0xC4, 0xCD, - 0xFC, 0xC7, 0xCB, 0x40, 0xCD, 0x98, 0xC4, 0xCB, 0x48, 0x28, 0x0A, 0xCD, 0x06, 0xC8, 0x20, 0x43, - 0x72, 0x6F, 0x6D, 0x69, 0xF8, 0xC3, 0x97, 0xCC, 0x3E, 0x44, 0x20, 0x02, 0x3E, 0x53, 0xC3, 0xFE, - 0xC7, 0x47, 0x3A, 0x6C, 0x00, 0xB7, 0xCA, 0xBD, 0xC1, 0x78, 0xFE, 0x53, 0x28, 0x2C, 0xCD, 0xB0, - 0xC8, 0xDA, 0xBD, 0xC1, 0xE5, 0xCD, 0xE1, 0xC4, 0x3E, 0x53, 0x32, 0x70, 0x00, 0xE1, 0xAF, 0xB4, - 0xC2, 0xBD, 0xC1, 0x3A, 0x6F, 0x00, 0xBD, 0x38, 0xE8, 0x7D, 0x32, 0x75, 0x00, 0xCD, 0xD4, 0xC4, - 0xD0, 0xC3, 0x0D, 0xC4, 0xCD, 0xF8, 0xC5, 0xC3, 0xCB, 0xCD, 0x13, 0xCD, 0xE1, 0xC4, 0xC3, 0xCB, - 0xCD, 0x3A, 0x75, 0x00, 0x32, 0x7D, 0x00, 0xCD, 0xAD, 0xC8, 0xD8, 0xAF, 0xB4, 0xC2, 0xBD, 0xC1, - 0x7D, 0xB7, 0x20, 0x04, 0x32, 0x78, 0x00, 0xC9, 0x3D, 0x20, 0xF2, 0xCD, 0xF6, 0xC3, 0xCB, 0x67, - 0x28, 0x06, 0x3E, 0x01, 0x32, 0x78, 0x00, 0xC9, 0xCD, 0x06, 0xC8, 0x53, 0x2E, 0x53, 0x69, 0x64, - 0x65, 0x64, 0x8D, 0xC3, 0x55, 0xC1, 0x06, 0x52, 0x18, 0x02, 0x06, 0x57, 0x1A, 0xFE, 0x44, 0xC2, - 0xBD, 0xC1, 0x78, 0x32, 0x70, 0x00, 0xCD, 0xBB, 0xC5, 0xE5, 0xFD, 0xE1, 0x60, 0x69, 0xD5, 0xE5, - 0x7B, 0x32, 0x76, 0x00, 0xFD, 0x22, 0x7B, 0x00, 0xCD, 0xD4, 0xC4, 0x3A, 0x70, 0x00, 0xFE, 0x57, - 0x37, 0x3F, 0xCC, 0xAB, 0xC5, 0x38, 0x08, 0x3A, 0x70, 0x00, 0xFE, 0x52, 0xCC, 0x52, 0xCD, 0xE1, - 0xD1, 0xDA, 0x0A, 0xC4, 0xED, 0x4B, 0x79, 0x00, 0xFD, 0x09, 0x03, 0xED, 0x42, 0x23, 0xDA, 0xF2, - 0xC5, 0x1C, 0x3A, 0x6E, 0x00, 0xBB, 0x30, 0xC6, 0x3A, 0x75, 0x00, 0x32, 0x7D, 0x00, 0x3C, 0x47, - 0x3A, 0x6F, 0x00, 0xB8, 0x38, 0x08, 0x78, 0x32, 0x75, 0x00, 0x1E, 0x01, 0x18, 0xB0, 0x1D, 0xCD, - 0xF2, 0xC5, 0xCD, 0x06, 0xC8, 0x4E, 0x65, 0x78, 0x74, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, - 0x3A, 0xA0, 0xFD, 0xE5, 0xE1, 0xCD, 0xE2, 0xC7, 0xCD, 0x06, 0xC8, 0x0D, 0x45, 0x6E, 0x64, 0x20, - 0x6F, 0x66, 0x20, 0x44, 0x69, 0x73, 0x6B, 0x8D, 0xC3, 0x55, 0xC1, 0x21, 0x7E, 0x00, 0x46, 0xC5, - 0xCB, 0xCE, 0xCD, 0x5F, 0xCD, 0xC1, 0x78, 0x32, 0x7E, 0x00, 0xC9, 0x3A, 0x6C, 0x00, 0xB7, 0xCA, - 0xBD, 0xC1, 0x13, 0xCD, 0x2F, 0xC8, 0xAF, 0xB2, 0xC2, 0xBD, 0xC1, 0xB3, 0xCA, 0xBD, 0xC1, 0xC5, - 0xD5, 0xE5, 0xCD, 0xF8, 0xC5, 0xE1, 0xD1, 0xC1, 0x3A, 0x6E, 0x00, 0xBB, 0x38, 0xEA, 0xDB, 0x31, - 0x57, 0xEB, 0xCD, 0xFC, 0xC7, 0xCD, 0xE2, 0xC7, 0xEB, 0xCD, 0xFC, 0xC7, 0x3A, 0x78, 0x00, 0xC3, - 0xF0, 0xC7, 0xCD, 0xDE, 0xC5, 0xC3, 0x97, 0xCC, 0x3A, 0x75, 0x00, 0xB7, 0x20, 0x20, 0x3A, 0x78, - 0x00, 0xB7, 0x20, 0x1A, 0x3A, 0x7E, 0x00, 0xCB, 0x6F, 0xC0, 0xCB, 0x4F, 0x20, 0x03, 0xCB, 0x47, - 0xC8, 0x32, 0x7F, 0x00, 0xCB, 0xEF, 0xCB, 0x87, 0x32, 0x7E, 0x00, 0xC3, 0x9B, 0xC3, 0x3A, 0x7E, - 0x00, 0xCB, 0x6F, 0xC8, 0x3A, 0x7F, 0x00, 0xC3, 0x87, 0xC3, 0xCD, 0x53, 0xC8, 0x4D, 0xED, 0x78, - 0xCD, 0xE7, 0xC7, 0xC3, 0x97, 0xCC, 0xCD, 0xAD, 0xC8, 0xE5, 0xCD, 0x1B, 0xC8, 0xCD, 0x53, 0xC8, - 0xD1, 0x4D, 0xED, 0x59, 0xC9, 0xCD, 0x2F, 0xC8, 0xC5, 0xD5, 0xE5, 0xED, 0xB0, 0xE1, 0xD1, 0xC1, - 0x18, 0x03, 0xCD, 0x2F, 0xC8, 0x1A, 0xBE, 0x28, 0x19, 0xCD, 0xE2, 0xC7, 0x7E, 0xCD, 0xDB, 0xC7, - 0xCD, 0xFC, 0xC7, 0x1A, 0xCD, 0xDB, 0xC7, 0xCD, 0xFC, 0xC7, 0xEB, 0xCD, 0xE2, 0xC7, 0xEB, 0xCD, - 0x97, 0xCC, 0x13, 0x23, 0x0B, 0x78, 0xB1, 0x20, 0xDC, 0xC9, 0xCD, 0x14, 0xC8, 0xFE, 0x4D, 0xC2, - 0xA1, 0xC4, 0x13, 0x2A, 0x64, 0x00, 0xCD, 0x5B, 0xC8, 0xCD, 0xE2, 0xC7, 0x7E, 0xCD, 0xDB, 0xC7, - 0xCD, 0xFC, 0xC7, 0xCD, 0xA3, 0xC7, 0xCD, 0x14, 0xC8, 0xFE, 0x2E, 0xC8, 0xFE, 0x2D, 0x20, 0x03, - 0x2B, 0x18, 0x1A, 0xCD, 0xF1, 0xC6, 0x30, 0x07, 0xCD, 0x06, 0xC8, 0x3F, 0x8D, 0x18, 0xDA, 0xAF, - 0x80, 0x20, 0x03, 0x23, 0x18, 0x07, 0x48, 0x06, 0x00, 0xEB, 0xED, 0xB0, 0xEB, 0x22, 0x64, 0x00, - 0x18, 0xC7, 0xCD, 0x65, 0xC8, 0xC5, 0xCD, 0xF1, 0xC6, 0xD1, 0xDA, 0xBD, 0xC1, 0xAF, 0x80, 0xCA, - 0xBD, 0xC1, 0xC5, 0xD5, 0xE5, 0x11, 0x2E, 0x00, 0x1A, 0xBE, 0x20, 0x04, 0x13, 0x23, 0x10, 0xF8, - 0xE1, 0xE5, 0x06, 0x10, 0xCC, 0x60, 0xC7, 0xE1, 0xD1, 0xC1, 0x23, 0x1B, 0x7A, 0xB3, 0x20, 0xE2, - 0xC9, 0xE5, 0x06, 0x00, 0x21, 0x2E, 0x00, 0xCD, 0x14, 0xC8, 0xB7, 0x28, 0x29, 0xFE, 0x2C, 0x13, - 0x28, 0xF5, 0x4F, 0xFE, 0x27, 0x28, 0x12, 0xFE, 0x22, 0x28, 0x0E, 0x1B, 0xE5, 0xCD, 0xAD, 0xC8, - 0x7D, 0xE1, 0x38, 0x12, 0x77, 0x23, 0x04, 0x18, 0xDE, 0x1A, 0x13, 0xB7, 0x28, 0x08, 0xB9, 0x28, - 0xD6, 0x77, 0x23, 0x04, 0x18, 0xF3, 0x11, 0x2E, 0x00, 0xE1, 0xC9, 0xCD, 0x14, 0xC8, 0xFE, 0x4D, - 0x20, 0x01, 0x13, 0x01, 0x80, 0x00, 0x2A, 0x62, 0x00, 0xCD, 0x4E, 0xC8, 0x1E, 0x10, 0xAF, 0xB0, - 0x20, 0x0A, 0x3E, 0x0F, 0xB9, 0x38, 0x05, 0xAF, 0xB1, 0x28, 0x01, 0x59, 0xC5, 0x43, 0xCD, 0x60, - 0xC7, 0x22, 0x62, 0x00, 0xC1, 0x79, 0x93, 0x4F, 0x30, 0x01, 0x05, 0x78, 0xB1, 0x20, 0xDD, 0xC9, - 0xCD, 0xE2, 0xC7, 0xC5, 0xE5, 0xD5, 0x0E, 0x00, 0x1E, 0x04, 0x3E, 0x03, 0xA1, 0xCC, 0xA0, 0xC7, - 0xCD, 0xA0, 0xC7, 0x7E, 0xCD, 0xE7, 0xC7, 0x1C, 0x1C, 0x23, 0x0C, 0x10, 0xED, 0xCD, 0xA0, 0xC7, - 0x3E, 0x3A, 0xBB, 0x20, 0xF8, 0xD1, 0xE1, 0xC1, 0x7E, 0x23, 0xCD, 0x92, 0xC7, 0x10, 0xF9, 0xC3, - 0x97, 0xCC, 0xE6, 0x7F, 0xFE, 0x7F, 0x28, 0x04, 0xFE, 0x20, 0x30, 0x62, 0x3E, 0x2E, 0x18, 0x5E, - 0x1C, 0x18, 0x59, 0x3E, 0x31, 0x11, 0x2E, 0x00, 0x12, 0xD5, 0xCD, 0xEA, 0xCB, 0xE3, 0x23, 0x46, - 0x04, 0x23, 0xE5, 0x05, 0x28, 0x17, 0x7E, 0xCD, 0xD2, 0xC7, 0x77, 0x23, 0xFE, 0x22, 0x28, 0x04, - 0xFE, 0x27, 0x20, 0xEF, 0x05, 0x28, 0x06, 0xBE, 0x23, 0x20, 0xF9, 0x18, 0xE6, 0x36, 0x00, 0xD1, - 0xE1, 0xC9, 0xFE, 0x61, 0xD8, 0xFE, 0x7B, 0xD0, 0xD6, 0x20, 0xC9, 0xF5, 0xCD, 0xFC, 0xC7, 0xF1, - 0x18, 0x05, 0x7C, 0xCD, 0xE7, 0xC7, 0x7D, 0xF5, 0x1F, 0x1F, 0x1F, 0x1F, 0xCD, 0xF0, 0xC7, 0xF1, - 0xE6, 0x0F, 0xFE, 0x0A, 0x38, 0x02, 0xC6, 0x07, 0xC6, 0x30, 0x18, 0x02, 0x3E, 0x20, 0xF5, 0xE6, - 0x7F, 0xCD, 0x99, 0xCC, 0xF1, 0xC9, 0xE3, 0x7E, 0x23, 0xB7, 0x28, 0x06, 0xCD, 0xFE, 0xC7, 0xF2, - 0x07, 0xC8, 0xE3, 0xC9, 0x1A, 0xFE, 0x20, 0xC0, 0x13, 0x18, 0xF9, 0xCD, 0x14, 0xC8, 0xFE, 0x2C, - 0xC0, 0x13, 0xCD, 0x14, 0xC8, 0xAF, 0xC9, 0xCD, 0x14, 0xC8, 0xB7, 0xC8, 0xC3, 0xBD, 0xC1, 0x21, - 0x80, 0x00, 0x44, 0x4D, 0xCD, 0x68, 0xC8, 0xE5, 0xC5, 0xCD, 0x1B, 0xC8, 0xCD, 0xAD, 0xC8, 0xDA, - 0xBD, 0xC1, 0xCD, 0x27, 0xC8, 0xEB, 0xC1, 0xE1, 0xC9, 0xCD, 0x65, 0xC8, 0x18, 0xD9, 0xCD, 0x68, - 0xC8, 0x18, 0xD4, 0xCD, 0xAD, 0xC8, 0xDA, 0xBD, 0xC1, 0x18, 0xCC, 0xE5, 0xCD, 0xAD, 0xC8, 0x38, - 0x01, 0xE3, 0xE1, 0x18, 0xC2, 0x37, 0x18, 0x01, 0xB7, 0x08, 0xC5, 0xE5, 0xCD, 0xAD, 0xC8, 0x30, - 0x08, 0x08, 0xDA, 0xBD, 0xC1, 0x08, 0xE1, 0x18, 0x01, 0xF1, 0xCD, 0x87, 0xC8, 0x30, 0x06, 0x08, - 0xC1, 0xD0, 0xC3, 0xBD, 0xC1, 0xF1, 0xC9, 0xCD, 0x1B, 0xC8, 0x1A, 0xFE, 0x53, 0x20, 0x01, 0x13, - 0xE5, 0xF5, 0xCD, 0xAD, 0xC8, 0x38, 0x0F, 0x44, 0x4D, 0xF1, 0xE1, 0x28, 0x07, 0x79, 0x95, 0x4F, - 0x78, 0x9C, 0x47, 0x03, 0xB7, 0xC9, 0xF1, 0xE1, 0xCA, 0xBD, 0xC1, 0x37, 0xC9, 0xCD, 0x14, 0xC8, - 0xCD, 0xE0, 0xC8, 0xD8, 0xD5, 0x13, 0xCD, 0xE0, 0xC8, 0x30, 0xFA, 0xD1, 0xFE, 0x2E, 0x28, 0x05, - 0xCD, 0xCA, 0xC8, 0xA7, 0xC9, 0xCD, 0xF4, 0xC8, 0xA7, 0xC9, 0x21, 0x00, 0x00, 0xCD, 0xE0, 0xC8, - 0x38, 0x09, 0x29, 0x29, 0x29, 0x29, 0x85, 0x6F, 0x13, 0x18, 0xF2, 0xFE, 0x48, 0xC0, 0x13, 0xC9, - 0x1A, 0xFE, 0x30, 0xD8, 0xFE, 0x3A, 0x38, 0x09, 0xFE, 0x41, 0xD8, 0xFE, 0x47, 0x3F, 0xD8, 0xD6, - 0x07, 0xD6, 0x30, 0xC9, 0x21, 0x00, 0x00, 0xCD, 0x10, 0xC9, 0x13, 0x38, 0x0D, 0xC5, 0x29, 0x44, - 0x4D, 0x29, 0x29, 0x09, 0xC1, 0xCD, 0x86, 0xC1, 0x18, 0xED, 0xFE, 0x2E, 0xC8, 0xC3, 0xBD, 0xC1, - 0x1A, 0xFE, 0x30, 0xD8, 0xFE, 0x3A, 0x3F, 0xD8, 0xD6, 0x30, 0xC9, 0x01, 0x18, 0x00, 0x11, 0x00, - 0x01, 0x21, 0x29, 0xC9, 0xED, 0xB0, 0xC3, 0x00, 0x01, 0x01, 0x00, 0x10, 0x11, 0x00, 0x10, 0x21, - 0x00, 0xC0, 0xC5, 0xD5, 0xE5, 0xED, 0xB0, 0x3E, 0x01, 0xD3, 0x40, 0xD1, 0xE1, 0xC1, 0xED, 0xB0, - 0xC9, 0xCD, 0x14, 0xC8, 0xFE, 0x5A, 0xF5, 0x20, 0x01, 0x13, 0xCD, 0x27, 0xC8, 0xF1, 0xC4, 0x1B, - 0xC9, 0xCD, 0x06, 0xC8, 0x0D, 0x4D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0xBA, 0x01, 0x00, 0x10, 0xCD, - 0xFC, 0xC7, 0x79, 0xCD, 0xF0, 0xC7, 0x0C, 0x10, 0xF6, 0xCD, 0x97, 0xCC, 0x06, 0x07, 0xCD, 0xFC, - 0xC7, 0x10, 0xFB, 0x60, 0x68, 0xCD, 0xFC, 0xC7, 0xE5, 0x11, 0x00, 0x10, 0x7C, 0xFE, 0xC9, 0x20, - 0x09, 0x7D, 0xFE, 0x8D, 0x38, 0x04, 0xFE, 0x9C, 0x38, 0x12, 0x46, 0x3E, 0x55, 0x77, 0xBE, 0x20, - 0x05, 0x2F, 0x77, 0xBE, 0x28, 0x05, 0x70, 0x3E, 0x58, 0x18, 0x09, 0x70, 0x23, 0x1B, 0x7A, 0xB3, - 0x20, 0xDA, 0x3E, 0x5E, 0xCD, 0xFE, 0xC7, 0xE1, 0x3E, 0x10, 0x84, 0x67, 0x20, 0xC7, 0xCD, 0x06, - 0xC8, 0x0D, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x20, 0x28, - 0x65, 0x67, 0x2C, 0x20, 0x41, 0x3B, 0x20, 0x6F, 0x72, 0x20, 0x41, 0x3B, 0x3B, 0x20, 0x6F, 0x72, - 0x20, 0x41, 0x3B, 0x3B, 0x3B, 0x29, 0xA0, 0xCD, 0xA3, 0xC7, 0xCD, 0x14, 0xC8, 0xB7, 0xCA, 0x97, - 0xCC, 0xCD, 0xC1, 0xC2, 0xC2, 0xB9, 0xC1, 0xCD, 0x06, 0xC8, 0x53, 0x65, 0x65, 0x6B, 0x20, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x3A, 0x8D, 0x06, 0x15, 0x21, 0x20, 0xCA, 0xDB, 0x31, 0x32, 0x7D, 0x00, - 0x7E, 0xC5, 0xE5, 0xFE, 0xFF, 0x20, 0x2E, 0xCD, 0x06, 0xC8, 0x20, 0x52, 0x65, 0x73, 0x74, 0x6F, - 0x72, 0x65, 0xBA, 0xCD, 0x04, 0xC6, 0xCD, 0x37, 0xCD, 0x08, 0xCD, 0x1E, 0xC6, 0x08, 0x18, 0x2C, - 0x01, 0x02, 0x03, 0x04, 0x05, 0xFE, 0x06, 0x07, 0x08, 0x09, 0x00, 0xFE, 0x27, 0x00, 0x15, 0x00, - 0x01, 0xFE, 0xFF, 0xFE, 0x27, 0xFE, 0xFE, 0x20, 0x06, 0xCD, 0x97, 0xCC, 0xB7, 0x18, 0x12, 0x32, - 0x75, 0x00, 0xCD, 0xDB, 0xC7, 0xCD, 0x06, 0xC8, 0xBA, 0xCD, 0xD4, 0xC4, 0xF5, 0xCD, 0x7A, 0xCB, - 0xF1, 0xE1, 0xC1, 0xDA, 0x97, 0xCC, 0x23, 0x10, 0xA2, 0xCD, 0x06, 0xC8, 0x0D, 0x52, 0x65, 0x61, - 0x64, 0x2F, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x74, 0x65, 0x73, 0x74, 0x73, 0x8D, 0xCD, 0x94, - 0xCB, 0xCD, 0xB0, 0xCB, 0xDA, 0x97, 0xCC, 0xCD, 0x06, 0xC8, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, - 0x74, 0x65, 0x73, 0x74, 0x20, 0x4D, 0x41, 0x59, 0x20, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4F, 0x59, - 0x20, 0x64, 0x61, 0x74, 0x61, 0x0D, 0x45, 0x53, 0x43, 0x3D, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x20, - 0x52, 0x45, 0x54, 0x55, 0x52, 0x4E, 0x3D, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x65, 0x64, 0xA0, 0xCD, - 0xA3, 0xC7, 0x21, 0x00, 0x09, 0xCD, 0xA2, 0xCB, 0x01, 0x00, 0x02, 0x75, 0x23, 0x0B, 0x78, 0xB1, - 0x20, 0xF9, 0xCD, 0xC1, 0xCB, 0x30, 0x6E, 0xCD, 0x06, 0xC8, 0x54, 0x65, 0x73, 0x74, 0x20, 0x66, - 0x61, 0x69, 0x6C, 0x65, 0x64, 0x21, 0x0D, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x64, 0x61, 0x74, 0x61, - 0x20, 0x61, 0xF4, 0x1E, 0x01, 0xCD, 0xDE, 0xC5, 0xCD, 0x06, 0xC8, 0x20, 0x6D, 0x61, 0x79, 0x20, - 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6E, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6F, - 0x79, 0x65, 0x64, 0x0D, 0x4F, 0x72, 0x69, 0x67, 0x69, 0x6E, 0x61, 0x6C, 0x20, 0x69, 0x73, 0x20, - 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, 0x30, 0x44, 0x30, 0x30, 0xF3, - 0x2A, 0x79, 0x00, 0xCD, 0xE2, 0xC7, 0xCD, 0x06, 0xC8, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x65, 0x6D, - 0x6F, 0x72, 0x79, 0x8D, 0xC9, 0x21, 0x00, 0x0B, 0xCD, 0xA2, 0xCB, 0xCD, 0xB0, 0xCB, 0x38, 0x87, - 0xCD, 0x06, 0xC8, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6E, 0x20, 0x63, 0x6F, 0x6D, 0x70, 0x61, - 0x72, 0x65, 0xA0, 0xED, 0x4B, 0x79, 0x00, 0x11, 0x00, 0x09, 0x21, 0x00, 0x0B, 0x1A, 0xBE, 0x20, - 0x09, 0x13, 0x23, 0x0B, 0x78, 0xB1, 0x20, 0xF5, 0x18, 0x01, 0x37, 0xCD, 0xD1, 0xCB, 0xCD, 0x94, - 0xCB, 0xCD, 0xC1, 0xCB, 0xDA, 0xC7, 0xCA, 0xC3, 0x97, 0xCC, 0x38, 0x06, 0xCD, 0x06, 0xC8, 0x4F, - 0xCB, 0xC9, 0xCD, 0x06, 0xC8, 0x65, 0x72, 0x72, 0x6F, 0x72, 0xA0, 0x3A, 0x71, 0x00, 0xCD, 0xE7, - 0xC7, 0xC3, 0x97, 0xCC, 0xCD, 0x06, 0xC8, 0x44, 0x61, 0x74, 0xE1, 0x21, 0x00, 0x0D, 0x22, 0x7B, - 0x00, 0xC9, 0x22, 0x7B, 0x00, 0xCD, 0x06, 0xC8, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0xEE, 0xC9, - 0xCD, 0xDA, 0xCB, 0xCD, 0x06, 0xC8, 0x20, 0x72, 0x65, 0x61, 0x64, 0xA0, 0xCD, 0x52, 0xCD, 0x18, - 0x10, 0xCD, 0xDA, 0xCB, 0xCD, 0x06, 0xC8, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0xA0, 0xCD, 0xAB, - 0xC5, 0xF5, 0xCD, 0x7A, 0xCB, 0xCD, 0x97, 0xCC, 0xF1, 0xC9, 0x3E, 0x27, 0x32, 0x75, 0x00, 0x32, - 0x7D, 0x00, 0x3E, 0x01, 0x32, 0x76, 0x00, 0xC3, 0xCB, 0xCD, 0xC5, 0xE5, 0x06, 0x00, 0x21, 0x02, - 0x00, 0x19, 0xCD, 0x64, 0xCC, 0xFE, 0x10, 0xCC, 0xBB, 0xCC, 0x28, 0xF6, 0xFE, 0x1B, 0xCA, 0x8E, - 0xCC, 0xFE, 0x08, 0x28, 0x04, 0xFE, 0x7F, 0x20, 0x11, 0xAF, 0xB0, 0x28, 0xE5, 0x2B, 0x05, 0xCD, - 0x4B, 0xCC, 0x7E, 0xFE, 0x20, 0xDC, 0x4B, 0xCC, 0x18, 0xD8, 0xFE, 0x0D, 0xCC, 0x45, 0xCC, 0x28, - 0x1B, 0xFE, 0x15, 0x20, 0x08, 0xCD, 0x45, 0xCC, 0xCD, 0x97, 0xCC, 0x18, 0xBF, 0x4F, 0x1A, 0x3D, - 0xB8, 0x28, 0xBF, 0x79, 0xCD, 0x45, 0xCC, 0x77, 0x23, 0x04, 0x18, 0xB6, 0x36, 0x00, 0x78, 0x13, - 0x12, 0x1B, 0xE1, 0xC1, 0xC9, 0xF5, 0xCD, 0x52, 0xCC, 0xF1, 0xC9, 0xCD, 0x06, 0xC8, 0x08, 0x20, - 0x88, 0xC9, 0xFE, 0x20, 0x30, 0x43, 0xFE, 0x0D, 0x28, 0x3F, 0xF5, 0xCD, 0x06, 0xC8, 0xDE, 0xF1, - 0xC6, 0x40, 0x18, 0x35, 0xCD, 0x23, 0xCD, 0xCD, 0x76, 0xCC, 0x28, 0xF8, 0xCD, 0x76, 0xCC, 0x28, - 0xFB, 0xDB, 0x01, 0xE6, 0x7F, 0xC9, 0xDB, 0x00, 0xE6, 0x40, 0xC9, 0xCD, 0x76, 0xCC, 0xC8, 0xCD, - 0x6C, 0xCC, 0xFE, 0x13, 0xCC, 0x6C, 0xCC, 0xFE, 0x0D, 0x28, 0x03, 0xFE, 0x1B, 0xC0, 0x31, 0x2E, - 0x00, 0xCD, 0x97, 0xCC, 0xC3, 0x55, 0xC1, 0x3E, 0x0D, 0xF5, 0xD9, 0xCB, 0x78, 0xD9, 0xC4, 0xCB, - 0xCC, 0xCD, 0x23, 0xCD, 0xDB, 0x00, 0xE6, 0x80, 0x28, 0xFA, 0xF1, 0xD3, 0x01, 0xFE, 0x0D, 0xC0, - 0x3E, 0x0A, 0xCD, 0x99, 0xCC, 0xCD, 0x7B, 0xCC, 0xFE, 0x10, 0xC0, 0xF5, 0xD9, 0x3E, 0x80, 0xA8, - 0x47, 0xCB, 0x78, 0xD9, 0xC4, 0xC9, 0xCC, 0xF1, 0xC9, 0x3E, 0x11, 0xF5, 0xE5, 0x21, 0x08, 0x00, - 0xCD, 0xF1, 0xCF, 0xE1, 0xF1, 0xF5, 0xFE, 0x11, 0x28, 0x13, 0xCD, 0x7B, 0xCC, 0xFE, 0x10, 0x20, - 0x05, 0xCD, 0xBB, 0xCC, 0xF1, 0xC9, 0xDB, 0x54, 0x2F, 0xE6, 0x20, 0x28, 0xED, 0xF1, 0xCB, 0xFF, - 0xD3, 0x54, 0xCB, 0xBF, 0xD3, 0x54, 0xCB, 0xFF, 0xD3, 0x54, 0xCB, 0xBF, 0xC9, 0xCD, 0x14, 0xC8, - 0xFE, 0x4F, 0xC2, 0xBD, 0xC1, 0x13, 0x1A, 0xFE, 0x4E, 0x28, 0x0E, 0xFE, 0x46, 0xC2, 0xBD, 0xC1, - 0xD9, 0xCB, 0xA8, 0xD9, 0x3E, 0xFF, 0xD3, 0x04, 0xC9, 0xD9, 0xCB, 0xE8, 0xD9, 0x3E, 0x01, 0x32, - 0x72, 0x00, 0xC9, 0xD9, 0xCB, 0x68, 0xD9, 0xC8, 0xC5, 0xCD, 0xA8, 0xCF, 0xC1, 0xD3, 0x34, 0xCD, - 0xD6, 0xCF, 0xEE, 0xA0, 0xD3, 0x04, 0xC9, 0x16, 0x02, 0xD5, 0xCD, 0x70, 0xCD, 0xD1, 0xD0, 0xD5, - 0x3E, 0x0A, 0x32, 0x75, 0x00, 0xCD, 0xCB, 0xCD, 0xCD, 0x70, 0xCD, 0xD1, 0xD0, 0x15, 0x20, 0xE9, - 0x18, 0x18, 0x16, 0x0A, 0xD5, 0xCD, 0x58, 0xCE, 0xD1, 0xD0, 0x15, 0x20, 0xF7, 0x18, 0x0B, 0x16, - 0x04, 0xD5, 0xCD, 0x9F, 0xCE, 0xD1, 0xD0, 0x15, 0x20, 0xF7, 0x3A, 0x71, 0x00, 0x4F, 0x37, 0xC9, - 0x97, 0x32, 0x75, 0x00, 0x32, 0x78, 0x00, 0xCD, 0x55, 0xCF, 0xD3, 0x34, 0xCD, 0x25, 0xCE, 0x38, - 0x0E, 0xD3, 0x30, 0xDB, 0x34, 0xCB, 0x57, 0x20, 0x3B, 0x1F, 0x30, 0xF7, 0xC3, 0x3E, 0xCE, 0x3E, - 0xC4, 0xD3, 0x30, 0xCD, 0xD6, 0xCF, 0xE6, 0x57, 0xD3, 0x04, 0xCD, 0xE4, 0xCF, 0xDB, 0x04, 0xE6, - 0x40, 0x20, 0x16, 0xCD, 0xCF, 0xCF, 0xDB, 0x34, 0xCB, 0x57, 0x20, 0x18, 0x1F, 0x30, 0xF7, 0x3E, - 0xD0, 0xD3, 0x30, 0x97, 0xD3, 0x31, 0xC3, 0x50, 0xCE, 0xDB, 0x34, 0xCB, 0x57, 0x20, 0x05, 0x1F, - 0x30, 0xDB, 0x18, 0xCB, 0x3E, 0x80, 0x32, 0x71, 0x00, 0x37, 0xC9, 0x97, 0xCD, 0x55, 0xCF, 0xD3, - 0x34, 0x3A, 0x75, 0x00, 0xD3, 0x33, 0x4F, 0x3A, 0x76, 0x00, 0xD3, 0x32, 0x3A, 0x7D, 0x00, 0xD3, - 0x31, 0x91, 0xCA, 0xCF, 0xCF, 0xCD, 0x25, 0xCE, 0x38, 0x0F, 0xF6, 0x10, 0xD3, 0x30, 0xDB, 0x34, - 0xCB, 0x57, 0x20, 0xD0, 0x1F, 0x30, 0xF7, 0x18, 0x45, 0xCD, 0xD6, 0xCF, 0xE6, 0x4F, 0xD3, 0x04, - 0x3E, 0x18, 0xD3, 0x30, 0xDB, 0x34, 0xCB, 0x57, 0x20, 0xBA, 0x1F, 0x30, 0xF7, 0xDB, 0x30, 0x2E, - 0x32, 0xDB, 0x04, 0xE6, 0x40, 0x20, 0xFA, 0x2D, 0x20, 0xF7, 0xDB, 0x04, 0xE6, 0x40, 0x20, 0xFA, - 0xCD, 0xCF, 0xCF, 0x18, 0x2B, 0x3A, 0x7E, 0x00, 0xCB, 0x57, 0x20, 0x0A, 0xCB, 0x5F, 0x3E, 0x0E, - 0x28, 0x02, 0x3E, 0x0C, 0xA7, 0xC9, 0xCB, 0x5F, 0x3E, 0x0F, 0x28, 0xF8, 0x37, 0xC9, 0xCD, 0xCF, - 0xCF, 0x21, 0x64, 0x00, 0xCD, 0xF1, 0xCF, 0xDB, 0x30, 0x32, 0x71, 0x00, 0xE6, 0x98, 0x37, 0xC0, - 0x3A, 0x75, 0x00, 0x32, 0x7D, 0x00, 0xA7, 0xC9, 0xCD, 0x8F, 0xCE, 0xD3, 0x30, 0xDB, 0x34, 0x1F, - 0x38, 0x16, 0xED, 0xA2, 0x04, 0xDB, 0x34, 0x1F, 0x38, 0x0E, 0xED, 0xA2, 0xC2, 0x5D, 0xCE, 0xDB, - 0x34, 0xCB, 0x4F, 0x20, 0x10, 0x1F, 0x30, 0xF7, 0xCD, 0xCF, 0xCF, 0xDB, 0x30, 0x32, 0x71, 0x00, - 0xE6, 0x9C, 0xC8, 0x18, 0x08, 0xCD, 0xCF, 0xCF, 0x3E, 0x80, 0x32, 0x71, 0x00, 0x37, 0xC9, 0xCD, - 0x40, 0xCF, 0x57, 0xF3, 0xCD, 0xC6, 0xCF, 0xC6, 0x88, 0x5F, 0x7A, 0xD3, 0x34, 0x7B, 0xC9, 0xCD, - 0xE4, 0xCF, 0xCD, 0x40, 0xCF, 0x57, 0xF3, 0xCD, 0xC6, 0xCF, 0xC6, 0xA8, 0x5F, 0x7A, 0xD3, 0x34, - 0x7B, 0xD3, 0x30, 0xDB, 0x34, 0x1F, 0x38, 0x12, 0xED, 0xA3, 0x04, 0xDB, 0x34, 0x1F, 0x38, 0x0A, - 0xED, 0xA3, 0xC2, 0xB3, 0xCE, 0xDB, 0x34, 0x1F, 0x30, 0xFB, 0xCD, 0xCF, 0xCF, 0xCD, 0xE4, 0xCF, - 0xDB, 0x30, 0x32, 0x71, 0x00, 0xE6, 0xFC, 0x37, 0xC0, 0xA7, 0x3A, 0x7E, 0x00, 0xCB, 0x4F, 0xC8, - 0xCD, 0x00, 0xCF, 0x38, 0x0A, 0xDB, 0x34, 0x1F, 0x38, 0x04, 0xDB, 0x33, 0x18, 0xF7, 0x1C, 0xCD, - 0xCF, 0xCF, 0xDB, 0x30, 0x32, 0x71, 0x00, 0xE6, 0x9C, 0x37, 0xC0, 0x7B, 0xA7, 0xC8, 0x37, 0xC9, - 0xCD, 0x8F, 0xCE, 0xED, 0x4B, 0x79, 0x00, 0xCB, 0x38, 0xCB, 0x19, 0xCB, 0x38, 0xCB, 0x19, 0x41, - 0x1E, 0x00, 0xD3, 0x30, 0xDB, 0x34, 0x1F, 0xD8, 0xDB, 0x33, 0xAE, 0xC0, 0x23, 0xDB, 0x34, 0x1F, - 0xD8, 0xDB, 0x33, 0xAE, 0xC0, 0x23, 0xDB, 0x34, 0x1F, 0xD8, 0xDB, 0x33, 0xAE, 0xC0, 0x23, 0xDB, - 0x34, 0x1F, 0xD8, 0xDB, 0x33, 0xAE, 0xC0, 0x23, 0x10, 0xDA, 0xDB, 0x34, 0x1F, 0x30, 0xFB, 0xC9, - 0xDB, 0x33, 0x3E, 0x80, 0xCD, 0x55, 0xCF, 0x2A, 0x79, 0x00, 0xCB, 0x1C, 0xCB, 0x1D, 0x45, 0x0E, - 0x33, 0x2A, 0x7B, 0x00, 0xC9, 0x4F, 0xDB, 0x34, 0xE6, 0x04, 0x28, 0x04, 0x97, 0x32, 0x72, 0x00, - 0xCD, 0xA8, 0xCF, 0xD3, 0x34, 0xF5, 0xE5, 0xCD, 0xD6, 0xCF, 0xE6, 0x5F, 0xD3, 0x04, 0x3A, 0x72, - 0x00, 0xA7, 0x28, 0x21, 0x21, 0x90, 0x01, 0x3A, 0x73, 0x00, 0xB8, 0x20, 0x1B, 0x3A, 0x74, 0x00, - 0x67, 0x3A, 0x78, 0x00, 0x32, 0x74, 0x00, 0xBC, 0x20, 0x06, 0xDB, 0x34, 0xE6, 0x20, 0x20, 0x0B, - 0xCD, 0xE4, 0xCF, 0x18, 0x06, 0x21, 0x20, 0x4E, 0xCD, 0xF1, 0xCF, 0xE1, 0x78, 0x32, 0x73, 0x00, - 0x3E, 0x01, 0x32, 0x72, 0x00, 0xF1, 0xB1, 0xC9, 0x3A, 0x77, 0x00, 0x47, 0x04, 0x97, 0x37, 0x17, - 0x10, 0xFD, 0x47, 0x3A, 0x7E, 0x00, 0xCB, 0x57, 0x28, 0x02, 0xCB, 0xE0, 0xCB, 0x47, 0x28, 0x02, - 0xCB, 0xF0, 0x78, 0xF6, 0x20, 0xC9, 0xDB, 0x34, 0x2F, 0xE6, 0x20, 0xC8, 0x3E, 0x04, 0xC9, 0xCD, - 0xD6, 0xCF, 0xD3, 0x04, 0xAF, 0xC9, 0xC5, 0x06, 0x7F, 0x3A, 0x78, 0x00, 0xA7, 0x28, 0x02, 0x06, - 0x7D, 0x78, 0xC1, 0xC9, 0x21, 0x08, 0x00, 0x3A, 0x7E, 0x00, 0xCB, 0x57, 0x20, 0x03, 0x21, 0x0C, - 0x00, 0xC5, 0x2B, 0x06, 0x1C, 0x10, 0xFE, 0x00, 0x00, 0x7D, 0xB4, 0x20, 0xF5, 0xC1, 0xC9, 0xFF -}, -{ /* RDOS 3.12 */ - 0xF3, 0x18, 0x36, 0xC3, 0x43, 0xC3, 0xC3, 0x75, 0xC3, 0xC3, 0x79, 0xC3, 0xC3, 0x7D, 0xC3, 0xC3, - 0x06, 0xCA, 0xC3, 0x88, 0xC3, 0xC3, 0xAF, 0xC3, 0xC3, 0xC0, 0xC3, 0xC3, 0xD0, 0xC3, 0xC3, 0x81, - 0xC3, 0xC3, 0xAA, 0xCF, 0xC3, 0x02, 0xD5, 0xC3, 0xF8, 0xD4, 0xC3, 0xA1, 0xD4, 0xC3, 0x1F, 0xD4, - 0xC3, 0xE4, 0xD4, 0xC3, 0xF2, 0xD4, 0xC3, 0x80, 0xD4, 0xAF, 0x47, 0xD3, 0x03, 0xD3, 0xE1, 0x2F, - 0xD3, 0x04, 0x3E, 0xD0, 0xD3, 0x30, 0x0E, 0x00, 0xD9, 0x21, 0x03, 0x00, 0x25, 0x20, 0xFD, 0x74, - 0x2C, 0xF2, 0x4F, 0xC0, 0x31, 0xF0, 0x7F, 0x3E, 0xFF, 0x32, 0x07, 0x00, 0x3E, 0x20, 0x32, 0x10, - 0x00, 0x22, 0x05, 0x00, 0x22, 0x03, 0x00, 0xCD, 0xAA, 0xCF, 0xDB, 0x34, 0xE6, 0x40, 0xCC, 0x74, - 0xC4, 0xCD, 0xF2, 0xD4, 0x43, 0x72, 0x6F, 0x6D, 0x65, 0x6D, 0x63, 0x6F, 0x20, 0x52, 0x44, 0x4F, - 0x53, 0x20, 0x30, 0x33, 0x2E, 0x31, 0x32, 0x8D, 0x3E, 0xFF, 0x32, 0x07, 0x00, 0x31, 0xF0, 0x7F, - 0xCD, 0x58, 0xD3, 0x21, 0x15, 0x00, 0x3A, 0x07, 0x00, 0xCD, 0xCB, 0xC0, 0xCD, 0x1A, 0xD4, 0xCD, - 0x45, 0xD3, 0xB7, 0x28, 0xE3, 0xD6, 0x41, 0xFE, 0x1A, 0x30, 0x4C, 0x21, 0x8D, 0xC0, 0xE5, 0x47, - 0x13, 0xCD, 0x45, 0xD3, 0xFE, 0x3B, 0x78, 0x28, 0x76, 0x87, 0x21, 0x5D, 0xD5, 0xCD, 0x84, 0xD2, - 0x7E, 0x23, 0x66, 0x6F, 0xE5, 0x21, 0x80, 0x00, 0xC3, 0x45, 0xD3, 0x28, 0x10, 0xFE, 0xFF, 0x28, - 0x15, 0xCD, 0xF2, 0xD4, 0x53, 0xD4, 0xCD, 0xFE, 0xD2, 0x3E, 0x3A, 0x18, 0x17, 0xFE, 0xFF, 0x28, - 0x05, 0xC6, 0x41, 0xCD, 0xA1, 0xD4, 0x3E, 0x3B, 0x28, 0x0A, 0xCB, 0x5E, 0xCC, 0xA1, 0xD4, 0xCB, - 0x56, 0xCC, 0xA1, 0xD4, 0xC3, 0xA1, 0xD4, 0xCD, 0xF2, 0xD4, 0x3F, 0x8D, 0x18, 0x8F, 0xCD, 0x27, - 0xC1, 0x1B, 0x1F, 0x41, 0x2D, 0xC4, 0x18, 0x0D, 0xCD, 0x27, 0xC1, 0x1B, 0x1F, 0x53, 0x54, 0x30, - 0x2D, 0x53, 0x54, 0x33, 0xC6, 0xCD, 0xF2, 0xD4, 0x20, 0x4F, 0x6E, 0x6C, 0x79, 0x8D, 0x18, 0xDC, - 0xCD, 0x27, 0xC1, 0x01, 0x07, 0xA0, 0xC9, 0xE3, 0xF5, 0xCD, 0xA9, 0xCC, 0xF1, 0xE3, 0xC9, 0xFE, - 0x04, 0x30, 0xCB, 0xF5, 0x13, 0x1A, 0xFE, 0x3B, 0x06, 0x0C, 0x20, 0x0B, 0x13, 0x1A, 0xFE, 0x3B, - 0x06, 0x04, 0x20, 0x03, 0x13, 0xAF, 0x47, 0xCD, 0x66, 0xC2, 0xD1, 0xF5, 0xAF, 0x32, 0x08, 0x00, - 0x7A, 0x32, 0x16, 0x00, 0x32, 0x07, 0x00, 0xF1, 0x21, 0x15, 0x00, 0x70, 0x38, 0x02, 0xB0, 0x77, - 0xF5, 0xCD, 0xAF, 0xC1, 0xCD, 0xB5, 0xC2, 0x3E, 0x48, 0x32, 0x09, 0x00, 0xCD, 0x88, 0xC3, 0xDA, - 0xE6, 0xCB, 0xF1, 0xD0, 0x3E, 0xD2, 0x32, 0x09, 0x00, 0x21, 0x80, 0x00, 0x22, 0x1B, 0x00, 0xCD, - 0x60, 0xD6, 0xCD, 0xD2, 0xD5, 0x30, 0x1F, 0x3A, 0x21, 0x00, 0xB7, 0xF2, 0x96, 0xC1, 0x21, 0x64, - 0x00, 0xCD, 0x7C, 0xD8, 0x18, 0xE3, 0xCD, 0xE6, 0xCB, 0xCD, 0x20, 0xC1, 0xCD, 0xF2, 0xD4, 0x4C, - 0x61, 0x62, 0x65, 0x6C, 0x8D, 0xC9, 0x21, 0xF8, 0x00, 0xCD, 0x9A, 0xC2, 0xCD, 0xB5, 0xC2, 0xAF, - 0x32, 0x08, 0x00, 0x21, 0x27, 0x00, 0x3A, 0x16, 0x00, 0xCD, 0x84, 0xD2, 0x3A, 0x15, 0x00, 0xCB, - 0xFF, 0x77, 0xC9, 0x13, 0xCD, 0xB2, 0xD3, 0xFE, 0x3A, 0xC2, 0xF7, 0xC0, 0x45, 0x7C, 0xB7, 0xC2, - 0xF7, 0xC0, 0x13, 0xCD, 0xE9, 0xD2, 0x78, 0xF5, 0xFE, 0x40, 0xD2, 0x08, 0xC1, 0x32, 0x16, 0x00, - 0x32, 0x07, 0x00, 0x3E, 0x80, 0x32, 0x08, 0x00, 0x3E, 0xD8, 0x32, 0x09, 0x00, 0xCD, 0xA3, 0xC3, - 0xCD, 0x8A, 0xD8, 0xDA, 0x8D, 0xC0, 0x21, 0x80, 0x00, 0x22, 0x1B, 0x00, 0x21, 0x00, 0x02, 0x22, - 0x1D, 0x00, 0xCD, 0x37, 0xD9, 0xF1, 0x38, 0x0F, 0xCD, 0x51, 0xDA, 0xDC, 0xF4, 0xCB, 0xCC, 0x3D, - 0xC2, 0xCD, 0x51, 0xDA, 0x11, 0xF8, 0x00, 0xCD, 0xEF, 0xC2, 0xCB, 0x77, 0xC8, 0x21, 0x1A, 0x00, - 0x34, 0xCD, 0x7D, 0xD9, 0xCD, 0x51, 0xDA, 0xD0, 0xCD, 0xF4, 0xCB, 0xCD, 0x20, 0xC1, 0xCD, 0xF2, - 0xD4, 0x53, 0x75, 0x70, 0x65, 0x72, 0x42, 0x6C, 0x6F, 0x63, 0x6B, 0x8D, 0xC9, 0x3E, 0xC8, 0x32, - 0x09, 0x00, 0x21, 0x80, 0x00, 0x22, 0x1B, 0x00, 0x21, 0xE5, 0xE5, 0x22, 0xF8, 0x00, 0xCD, 0x88, - 0xC3, 0xDA, 0xF4, 0xCB, 0x3E, 0xD2, 0x32, 0x09, 0x00, 0xCD, 0x7D, 0xD9, 0xCD, 0x51, 0xDA, 0xD0, - 0xCD, 0xF4, 0xCB, 0xC3, 0x99, 0xC1, 0xE5, 0x0E, 0x00, 0x21, 0x10, 0x44, 0xCD, 0x85, 0xC2, 0x38, - 0x0F, 0x2E, 0x01, 0xCD, 0x85, 0xC2, 0xDA, 0xF7, 0xC0, 0x21, 0x02, 0x58, 0xCD, 0x8F, 0xC2, 0xB7, - 0x79, 0xE1, 0xC3, 0xE9, 0xD2, 0xCD, 0x8F, 0xC2, 0xD0, 0xD6, 0x53, 0x28, 0x0B, 0x37, 0xC9, 0xCD, - 0x45, 0xD3, 0xBC, 0x37, 0xC0, 0x79, 0xB5, 0x4F, 0x13, 0xC9, 0x01, 0x02, 0x43, 0xCD, 0xA8, 0xC2, - 0x01, 0x10, 0x44, 0xCD, 0xA8, 0xC2, 0x0E, 0x01, 0x7E, 0x23, 0x23, 0xB8, 0xC0, 0x3A, 0x15, 0x00, - 0xB1, 0x32, 0x15, 0x00, 0xC9, 0x3A, 0x15, 0x00, 0x47, 0xCB, 0x40, 0x11, 0x10, 0x0A, 0x21, 0x00, - 0x02, 0x20, 0x0D, 0xCB, 0x48, 0x11, 0x08, 0x05, 0x20, 0x06, 0x11, 0x1A, 0x12, 0x21, 0x80, 0x00, - 0x22, 0x1D, 0x00, 0xCB, 0x50, 0x7B, 0x1E, 0x4C, 0x20, 0x03, 0x7A, 0x1E, 0x27, 0x32, 0x11, 0x00, - 0xAF, 0x57, 0xED, 0x53, 0x12, 0x00, 0xCB, 0x60, 0x28, 0x01, 0x3C, 0x32, 0x14, 0x00, 0xC9, 0x3E, - 0x80, 0x21, 0x08, 0x00, 0x77, 0x38, 0x35, 0x1A, 0xFE, 0x43, 0x20, 0x02, 0xCB, 0xF6, 0x13, 0x1A, - 0xFE, 0x53, 0x20, 0x28, 0x13, 0x1A, 0xFE, 0x54, 0x20, 0x22, 0x21, 0xEE, 0xFF, 0x19, 0xC5, 0x56, - 0x23, 0x5E, 0x23, 0xD5, 0x56, 0x23, 0x5E, 0x23, 0x4E, 0x06, 0x00, 0xEB, 0xCD, 0xBF, 0xD2, 0x7B, - 0xB2, 0x28, 0x01, 0x23, 0xD1, 0x19, 0x79, 0x3D, 0x2B, 0xC1, 0x18, 0x05, 0x3E, 0x05, 0x21, 0x31, - 0x01, 0x32, 0x14, 0x00, 0x22, 0x12, 0x00, 0x3E, 0x13, 0x32, 0x11, 0x00, 0x21, 0x00, 0x02, 0x22, - 0x1D, 0x00, 0xC9, 0x32, 0x07, 0x00, 0xFE, 0x40, 0x30, 0x08, 0x47, 0x37, 0xCD, 0xD6, 0xC1, 0xC3, - 0x57, 0xDA, 0xD6, 0x41, 0xFE, 0x04, 0x38, 0x07, 0x3E, 0xFF, 0x32, 0x07, 0x00, 0x37, 0xC9, 0x32, - 0x07, 0x00, 0x32, 0x16, 0x00, 0x78, 0x32, 0x15, 0x00, 0xD9, 0xCB, 0xA8, 0xD9, 0xDB, 0x31, 0x32, - 0x1F, 0x00, 0xC3, 0xAC, 0xC1, 0x32, 0x17, 0x00, 0xC9, 0x22, 0x18, 0x00, 0xC9, 0x32, 0x1A, 0x00, - 0xC9, 0xCD, 0x51, 0xDA, 0x47, 0xC3, 0x57, 0xDA, 0xCD, 0xA3, 0xC3, 0x20, 0x06, 0xCD, 0x3B, 0xDA, - 0xC3, 0x51, 0xDA, 0xD9, 0xCB, 0xA8, 0xD9, 0xCD, 0x12, 0xC4, 0xCD, 0x91, 0xD5, 0xF5, 0xCD, 0x30, - 0xC4, 0xF1, 0xC9, 0xAF, 0x67, 0x6F, 0x32, 0x17, 0x00, 0x22, 0x18, 0x00, 0xC3, 0xE6, 0xCE, 0xCD, - 0x58, 0xD3, 0x20, 0x06, 0xCD, 0x08, 0xC4, 0xC3, 0x60, 0xD6, 0xCD, 0x17, 0xDA, 0xC3, 0x51, 0xDA, - 0xCD, 0xEA, 0xC3, 0xD8, 0xF5, 0xC4, 0x7D, 0xD9, 0xF1, 0x20, 0x18, 0xCD, 0xD2, 0xD5, 0x18, 0x0E, - 0xCD, 0xEA, 0xC3, 0xD8, 0xF5, 0xC4, 0x04, 0xDA, 0xF1, 0x20, 0x08, 0xCD, 0xF8, 0xC3, 0xED, 0x4B, - 0x1D, 0x00, 0xC9, 0xED, 0x4B, 0x1D, 0x00, 0xC3, 0x51, 0xDA, 0xCD, 0xAF, 0xC3, 0x3A, 0x08, 0x00, - 0xCB, 0x7F, 0x20, 0x01, 0xD8, 0xE6, 0x80, 0xC9, 0x21, 0x15, 0x00, 0x46, 0xC5, 0xCB, 0xCE, 0xCD, - 0xE7, 0xD5, 0xC1, 0x78, 0x32, 0x15, 0x00, 0xC9, 0x3A, 0x18, 0x00, 0x47, 0x3A, 0x17, 0x00, 0xB0, - 0x20, 0x1E, 0xD9, 0xCB, 0x68, 0xD9, 0xC0, 0x3A, 0x15, 0x00, 0xCB, 0x4F, 0x20, 0x03, 0xCB, 0x47, - 0xC8, 0x32, 0x26, 0x00, 0xE6, 0xFC, 0x32, 0x15, 0x00, 0xD9, 0xCB, 0xE8, 0xD9, 0xC3, 0xB5, 0xC2, - 0xD9, 0xCB, 0x68, 0xCB, 0xA8, 0xD9, 0xC8, 0x3A, 0x26, 0x00, 0x32, 0x15, 0x00, 0xC3, 0xB5, 0xC2, - 0xB7, 0x28, 0x31, 0x13, 0xFE, 0x53, 0x20, 0x20, 0x1A, 0xCD, 0x2C, 0xD3, 0xFE, 0x54, 0xC2, 0x08, - 0xC1, 0x13, 0xCD, 0xB2, 0xD3, 0xB7, 0xC2, 0x08, 0xC1, 0x7C, 0xA7, 0xC2, 0x08, 0xC1, 0x7D, 0xFE, - 0x40, 0xD2, 0x08, 0xC1, 0xF6, 0x80, 0x18, 0x2F, 0xCD, 0xE9, 0xD2, 0xD6, 0x41, 0xFE, 0x04, 0xD2, - 0xFE, 0xC0, 0x18, 0x23, 0xDB, 0x04, 0x2F, 0xC5, 0xE6, 0x17, 0x47, 0xE6, 0x03, 0xCB, 0x50, 0x28, - 0x02, 0xCB, 0xFF, 0xCB, 0x60, 0x20, 0x0F, 0xCB, 0xEF, 0xCB, 0x48, 0x20, 0x09, 0xCB, 0xFF, 0x3D, - 0xCB, 0x40, 0x28, 0x02, 0xC6, 0x1F, 0xC1, 0xF5, 0xCB, 0x7F, 0x28, 0x05, 0x3E, 0x01, 0xCD, 0xB3, - 0xCB, 0xDB, 0x04, 0x2F, 0xE6, 0x08, 0xCC, 0x00, 0xCB, 0xCC, 0x80, 0xD4, 0xCD, 0xF2, 0xD4, 0x50, - 0x72, 0x65, 0x70, 0x61, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x6F, 0x6F, 0x74, - 0x2C, 0x20, 0x45, 0x53, 0x43, 0x20, 0x74, 0x6F, 0x20, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x8D, 0xF1, - 0xCB, 0x7F, 0xF5, 0xF5, 0xCB, 0xBF, 0x32, 0x16, 0x00, 0x3E, 0x80, 0x20, 0x01, 0xAF, 0x32, 0x08, - 0x00, 0x3E, 0xFF, 0x32, 0x07, 0x00, 0xCD, 0xA3, 0xC3, 0x21, 0x80, 0x00, 0x22, 0x1B, 0x00, 0xF1, - 0x20, 0x65, 0xCB, 0x6F, 0x28, 0x23, 0xCD, 0xF2, 0xD4, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, - 0x73, 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x73, 0x73, - 0x69, 0x67, 0x6E, 0x65, 0x64, 0x8D, 0xC3, 0x71, 0xC0, 0xCD, 0x33, 0xD8, 0x57, 0xD3, 0x34, 0xCD, - 0x12, 0xC6, 0xCD, 0x2E, 0xC6, 0x32, 0x15, 0x00, 0x21, 0x80, 0x00, 0x22, 0x1D, 0x00, 0x06, 0x02, - 0xC5, 0xCD, 0x23, 0xC6, 0x3E, 0xC8, 0x32, 0x09, 0x00, 0xCD, 0x91, 0xD5, 0xD4, 0x60, 0xD6, 0x3E, - 0xD2, 0x32, 0x09, 0x00, 0xD4, 0xD2, 0xD5, 0xC1, 0x30, 0x53, 0xCD, 0x23, 0xC6, 0x10, 0xE1, 0xCD, - 0x80, 0xD4, 0xCD, 0xE3, 0xCB, 0x18, 0x5E, 0x3E, 0xC8, 0x32, 0x09, 0x00, 0x21, 0x00, 0x28, 0x22, - 0x1D, 0x00, 0xCD, 0x8A, 0xD8, 0x38, 0x48, 0x01, 0x00, 0x00, 0xC5, 0xCD, 0x23, 0xC6, 0xCD, 0x37, - 0xD9, 0xC1, 0xCD, 0x51, 0xDA, 0x28, 0x0B, 0xFE, 0x07, 0x20, 0x34, 0x0B, 0x78, 0xB1, 0x20, 0xEA, - 0x18, 0x2D, 0xCD, 0x3B, 0xDA, 0xCD, 0x51, 0xDA, 0x20, 0x25, 0xCD, 0x23, 0xC6, 0x3E, 0xD2, 0x32, - 0x09, 0x00, 0xCD, 0x6B, 0xD9, 0xCD, 0x51, 0xDA, 0x20, 0x15, 0xCD, 0x12, 0xC6, 0x3A, 0x80, 0x00, - 0xFE, 0x40, 0x28, 0x04, 0xFE, 0xE5, 0x20, 0x31, 0xCD, 0xF2, 0xD4, 0x0D, 0xCE, 0x18, 0x12, 0xCD, - 0x80, 0xD4, 0xCD, 0xF1, 0xCB, 0xCD, 0xF2, 0xD4, 0x0D, 0x55, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x20, - 0xF4, 0xCD, 0xF2, 0xD4, 0x6F, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x8D, 0x3E, 0xD0, 0xD3, 0x30, 0x3E, - 0xFF, 0xD3, 0x04, 0xCD, 0x80, 0xD4, 0xC3, 0x71, 0xC0, 0xCD, 0x58, 0xD3, 0xCC, 0x33, 0xD8, 0x57, - 0xCD, 0x23, 0xC6, 0xF1, 0x08, 0xCD, 0xF2, 0xD4, 0x0D, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x62, 0x79, - 0x8D, 0xCD, 0x58, 0xD3, 0x37, 0xCA, 0x80, 0x00, 0x21, 0x80, 0x04, 0x11, 0x00, 0x00, 0x01, 0x00, - 0x22, 0xED, 0xB0, 0x08, 0xE6, 0x7F, 0x32, 0x07, 0x04, 0x3E, 0x06, 0x32, 0x06, 0x04, 0x3E, 0xFF, - 0xD3, 0xFF, 0x01, 0xE8, 0x03, 0xCD, 0x23, 0xC6, 0x21, 0x0A, 0x00, 0xCD, 0x7C, 0xD8, 0x0B, 0x78, - 0xB1, 0x20, 0xF2, 0xCD, 0xF8, 0xD4, 0xC4, 0x0A, 0xD5, 0xFE, 0x1B, 0xC0, 0x18, 0x9D, 0x7A, 0xD3, - 0x34, 0x3E, 0xDF, 0xD3, 0x04, 0x3E, 0xD4, 0xD3, 0x30, 0xDB, 0x34, 0x0F, 0x30, 0xFB, 0xDB, 0x30, - 0x01, 0x00, 0x02, 0xCD, 0x72, 0xC6, 0x3E, 0xD4, 0xD3, 0x30, 0xCD, 0x6B, 0xC6, 0x28, 0xDF, 0xDB, - 0x34, 0x0F, 0x30, 0xF6, 0xDB, 0x30, 0x10, 0xEE, 0xAF, 0xD3, 0x03, 0x79, 0xFE, 0x5A, 0x30, 0x03, - 0x87, 0x87, 0x87, 0xFE, 0xB7, 0x3E, 0x80, 0xD0, 0x3E, 0x04, 0xC9, 0xDB, 0x03, 0xFE, 0xC7, 0xC0, - 0x0C, 0xC8, 0x3E, 0x01, 0xD3, 0x03, 0x3E, 0xFA, 0xD3, 0x05, 0x18, 0xEF, 0x13, 0xFE, 0x41, 0xCA, - 0x4B, 0xC7, 0x06, 0x52, 0x18, 0x03, 0x13, 0x06, 0x57, 0xFE, 0x44, 0xC2, 0xF7, 0xC0, 0xCD, 0x5F, - 0xD3, 0x78, 0x32, 0x09, 0x00, 0xCD, 0x84, 0xD3, 0xAF, 0xB2, 0xC2, 0xF7, 0xC0, 0xB0, 0xB1, 0xCA, - 0xF7, 0xC0, 0xCD, 0x58, 0xD3, 0x20, 0x05, 0xAF, 0xB3, 0xCA, 0xF7, 0xC0, 0x22, 0x1B, 0x00, 0x0B, - 0xC5, 0xD5, 0xD4, 0x08, 0xC4, 0xD1, 0xFD, 0xE1, 0x3A, 0x11, 0x00, 0xBB, 0xDA, 0xF7, 0xC0, 0x7B, - 0x32, 0x1A, 0x00, 0xCD, 0x28, 0xCE, 0xCD, 0x9F, 0xD4, 0xFD, 0xE5, 0x3A, 0x09, 0x00, 0xFE, 0x52, - 0x28, 0x0A, 0xFE, 0x57, 0xC2, 0xF7, 0xC0, 0xCD, 0xD0, 0xC3, 0x18, 0x03, 0xCD, 0xC0, 0xC3, 0x30, - 0x09, 0xCD, 0x58, 0xD3, 0xCA, 0xE3, 0xCB, 0xC3, 0xF1, 0xCB, 0x2A, 0x1B, 0x00, 0x09, 0x22, 0x1B, - 0x00, 0xE1, 0xB7, 0xED, 0x42, 0xDA, 0x22, 0xCE, 0xE5, 0xFD, 0xE1, 0x21, 0x1A, 0x00, 0x34, 0x3A, - 0x11, 0x00, 0xBE, 0x30, 0xC4, 0xCD, 0xE6, 0xCE, 0x2A, 0x18, 0x00, 0x7D, 0x32, 0x1F, 0x00, 0xE5, - 0x23, 0x22, 0x18, 0x00, 0xED, 0x4B, 0x12, 0x00, 0x37, 0xED, 0x42, 0xE1, 0x38, 0xAB, 0x22, 0x18, - 0x00, 0x3A, 0x11, 0x00, 0x32, 0x1A, 0x00, 0xCD, 0x22, 0xCE, 0xCD, 0xF2, 0xD4, 0x4E, 0x65, 0x78, - 0x74, 0x20, 0x3D, 0xA0, 0x2A, 0x1B, 0x00, 0xCD, 0xF9, 0xD2, 0xCD, 0xF2, 0xD4, 0x0D, 0x45, 0x6E, - 0x64, 0x20, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x8D, 0xC9, 0xCD, 0xE9, 0xD2, 0xCD, 0x5F, - 0xD3, 0xCD, 0xF1, 0xCE, 0x3E, 0xD2, 0x32, 0x09, 0x00, 0xCD, 0xE6, 0xCE, 0x3E, 0x0D, 0xCD, 0x18, - 0xD5, 0xCD, 0x13, 0xCE, 0x21, 0x80, 0x00, 0x22, 0x1B, 0x00, 0xCD, 0xC0, 0xC3, 0x38, 0x0A, 0xCD, - 0x58, 0xD3, 0x28, 0x1B, 0xCD, 0x57, 0xDA, 0x28, 0x16, 0x3A, 0x1A, 0x00, 0xCD, 0x9C, 0xD4, 0xCD, - 0x58, 0xD3, 0x20, 0x05, 0xCD, 0xE6, 0xCB, 0x18, 0x03, 0xCD, 0xF4, 0xCB, 0xCD, 0x13, 0xCE, 0xCD, - 0xC1, 0xD4, 0xCD, 0x58, 0xD3, 0x20, 0x05, 0xCD, 0x9B, 0xCE, 0x20, 0xC8, 0xCD, 0x67, 0xCE, 0x20, - 0xBB, 0xC3, 0x80, 0xD4, 0xFE, 0x54, 0xCA, 0xC3, 0xC1, 0xFE, 0x4D, 0xCA, 0x86, 0xD0, 0xF5, 0xCD, - 0x5F, 0xD3, 0xF1, 0xFE, 0x53, 0x20, 0x0A, 0x13, 0xED, 0x4B, 0x18, 0x00, 0xCD, 0x72, 0xD3, 0x18, - 0x16, 0xCD, 0xB2, 0xD3, 0x38, 0x1A, 0xE5, 0xED, 0x4B, 0x12, 0x00, 0x03, 0xED, 0x42, 0xC1, 0xD2, - 0xF7, 0xC0, 0xCD, 0x79, 0xD3, 0x38, 0x10, 0xAF, 0xB4, 0xC2, 0xF7, 0xC0, 0x3A, 0x14, 0x00, 0xBD, - 0xDA, 0xF7, 0xC0, 0x7D, 0x32, 0x17, 0x00, 0xED, 0x43, 0x18, 0x00, 0x3E, 0xD3, 0x32, 0x09, 0x00, - 0xCD, 0xAF, 0xC3, 0xD0, 0xCD, 0x58, 0xD3, 0xCA, 0xE6, 0xCB, 0xC3, 0xF4, 0xCB, 0xFE, 0x4F, 0xC2, - 0xF7, 0xC0, 0x13, 0xCD, 0x45, 0xD3, 0xFE, 0x4E, 0x28, 0x0D, 0xFE, 0x46, 0xC2, 0xF7, 0xC0, 0xD9, - 0xCB, 0xB0, 0xD9, 0x3E, 0xFF, 0x18, 0x1F, 0xD9, 0xCB, 0xF0, 0xD9, 0x3E, 0x01, 0x32, 0x23, 0x00, - 0xC9, 0xD9, 0xCB, 0x70, 0xD9, 0xC8, 0xCD, 0x58, 0xD3, 0xD8, 0xC5, 0xCD, 0x33, 0xD8, 0xC1, 0xD3, - 0x34, 0xCD, 0x61, 0xD8, 0xEE, 0xA0, 0xD3, 0x04, 0xC9, 0xFE, 0x58, 0x32, 0x2C, 0x00, 0x06, 0x81, - 0x28, 0x16, 0xD6, 0x5A, 0x06, 0x01, 0x20, 0x11, 0xCD, 0x50, 0xCA, 0xC2, 0xF7, 0xC0, 0x47, 0x3A, - 0x2B, 0x00, 0x20, 0x04, 0x3D, 0x32, 0x2C, 0x00, 0x13, 0xCD, 0xE9, 0xD2, 0x78, 0xB7, 0xF5, 0xC4, - 0xB3, 0xCB, 0xAF, 0xCD, 0xFD, 0xCA, 0xF1, 0xFC, 0x8F, 0xCB, 0xCD, 0x54, 0xCA, 0xCD, 0x80, 0xD4, - 0xCD, 0x78, 0xC9, 0xDA, 0x80, 0xD4, 0xCD, 0x27, 0xC1, 0x07, 0x2F, 0x08, 0x00, 0xF3, 0xCD, 0x80, - 0xD4, 0xCD, 0xFE, 0xC9, 0xCD, 0x19, 0xCA, 0xDA, 0x80, 0xD4, 0xCD, 0x27, 0xC1, 0x08, 0x00, 0x20, - 0x4D, 0x41, 0x59, 0x20, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4F, 0x59, 0x20, 0x98, 0xCD, 0xF2, 0xD4, - 0x0D, 0x43, 0x52, 0x3D, 0x50, 0x72, 0x6F, 0x63, 0x65, 0x65, 0x64, 0x20, 0x45, 0x53, 0x43, 0x3D, - 0x41, 0x62, 0x6F, 0x72, 0x74, 0xA0, 0xCD, 0x1A, 0xD4, 0x21, 0x00, 0x06, 0xCD, 0x0A, 0xCA, 0x01, - 0x00, 0x02, 0x75, 0x23, 0x0B, 0x78, 0xB1, 0x20, 0xF9, 0xCD, 0x27, 0xCA, 0x30, 0x60, 0xCD, 0xF2, - 0xD4, 0x54, 0x65, 0x73, 0x74, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x21, 0x0D, 0x44, 0x69, - 0x73, 0x6B, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x61, 0xF4, 0xCD, 0x4C, 0xCE, 0xCD, 0xF2, 0xD4, - 0x20, 0x6D, 0x61, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6E, 0x20, 0x44, - 0x45, 0x53, 0x54, 0x52, 0x4F, 0x59, 0x45, 0x44, 0x0D, 0x4F, 0x72, 0x69, 0x67, 0x69, 0x6E, 0x61, - 0x6C, 0x20, 0x69, 0x73, 0x20, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, - 0x34, 0x30, 0x30, 0x48, 0xF3, 0x2A, 0x1D, 0x00, 0xCD, 0x15, 0xD3, 0xC3, 0x80, 0xD4, 0x21, 0x00, - 0x08, 0xCD, 0x0A, 0xCA, 0xCD, 0x19, 0xCA, 0x38, 0x95, 0xCD, 0x0A, 0xCA, 0xCD, 0x27, 0xC1, 0x43, - 0x6F, 0x6D, 0x70, 0x61, 0x72, 0xE5, 0xED, 0x4B, 0x1D, 0x00, 0x11, 0x00, 0x06, 0x21, 0x00, 0x08, - 0x1A, 0xBE, 0x20, 0x09, 0x13, 0x23, 0x0B, 0x78, 0xB1, 0x20, 0xF5, 0x18, 0x0D, 0xCD, 0xF2, 0xD4, - 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x8D, 0x18, 0x03, 0xCD, 0x33, 0xCA, 0xCD, 0xFE, 0xC9, - 0xCD, 0x27, 0xCA, 0xDA, 0xCE, 0xC8, 0x18, 0xB3, 0xCD, 0x27, 0xC1, 0x06, 0x00, 0xF3, 0x06, 0x17, - 0x21, 0xD4, 0xC9, 0xDB, 0x31, 0x32, 0x1F, 0x00, 0x7E, 0x5F, 0x16, 0x00, 0xC5, 0xE5, 0xFE, 0xFF, - 0x20, 0x06, 0xCD, 0x80, 0xD4, 0xB7, 0x18, 0x35, 0xFE, 0xFE, 0x20, 0x13, 0xCD, 0x27, 0xC1, 0x20, - 0x19, 0x73, 0x74, 0x14, 0xE5, 0x3E, 0xC8, 0x32, 0x09, 0x00, 0xCD, 0x88, 0xC3, 0x18, 0x19, 0xFE, - 0xFD, 0x20, 0x04, 0xED, 0x5B, 0x12, 0x00, 0xED, 0x53, 0x18, 0x00, 0xEB, 0xCD, 0x15, 0xD3, 0xEB, - 0x3E, 0xD3, 0x32, 0x09, 0x00, 0xCD, 0xAF, 0xC3, 0xF5, 0xCD, 0xEB, 0xC9, 0xF1, 0xE1, 0xC1, 0xD8, - 0x23, 0x10, 0xB0, 0xC9, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF, 0x06, 0x07, 0x08, 0x09, 0x00, - 0xFF, 0xFD, 0x10, 0x20, 0x00, 0x01, 0xFF, 0xFE, 0xFF, 0xFD, 0xFF, 0x30, 0x09, 0xCD, 0x58, 0xD3, - 0xCA, 0xE6, 0xCB, 0xC3, 0xF4, 0xCB, 0xCD, 0xF2, 0xD4, 0x20, 0x4F, 0x4B, 0xA0, 0xC9, 0xCD, 0x27, - 0xC1, 0x20, 0x98, 0x21, 0x00, 0x04, 0x22, 0x1B, 0x00, 0xC9, 0x22, 0x1B, 0x00, 0xCD, 0x27, 0xC1, - 0x20, 0x50, 0x61, 0x74, 0x74, 0x16, 0x6E, 0xA0, 0xC9, 0x3E, 0xD2, 0xCD, 0x3C, 0xCA, 0xCD, 0x27, - 0xC1, 0x87, 0xCD, 0xC0, 0xC3, 0x18, 0x0C, 0x3E, 0xD7, 0xCD, 0x3C, 0xCA, 0xCD, 0x27, 0xC1, 0x88, - 0xCD, 0xD0, 0xC3, 0xF5, 0xCD, 0xEB, 0xC9, 0xF1, 0xD2, 0x80, 0xD4, 0xC9, 0x32, 0x09, 0x00, 0x3A, - 0x12, 0x00, 0x32, 0x18, 0x00, 0xDB, 0x31, 0x32, 0x1F, 0x00, 0x3E, 0x01, 0x32, 0x1A, 0x00, 0xC9, - 0xDB, 0x44, 0x3C, 0xC9, 0xCD, 0xF2, 0xD4, 0x0D, 0x54, 0x79, 0x70, 0x65, 0x20, 0x28, 0x46, 0x2C, - 0x20, 0x48, 0x29, 0xA0, 0xCD, 0xE9, 0xCA, 0xFE, 0x48, 0x20, 0x26, 0xCD, 0xF2, 0xD4, 0x55, 0x6E, - 0x69, 0x74, 0x20, 0x28, 0x30, 0x2D, 0x33, 0x46, 0x29, 0xA0, 0xCD, 0x1A, 0xD4, 0xCD, 0xB2, 0xD3, - 0xB7, 0xC2, 0x08, 0xC1, 0x7C, 0xA7, 0xC2, 0x08, 0xC1, 0x7D, 0x47, 0xCD, 0xD6, 0xC1, 0xC3, 0x51, - 0xDA, 0xFE, 0x46, 0xC2, 0xF7, 0xC0, 0xCD, 0x27, 0xC1, 0x0F, 0x28, 0x41, 0x2D, 0x44, 0x29, 0xA0, - 0xCD, 0xE9, 0xCA, 0xD6, 0x41, 0xFE, 0x04, 0xD2, 0xFE, 0xC0, 0x57, 0xCD, 0xF2, 0xD4, 0x53, 0x69, - 0x7A, 0x65, 0x20, 0x28, 0x4C, 0x2C, 0x20, 0x53, 0x29, 0xA0, 0xCD, 0xE9, 0xCA, 0xFE, 0x4C, 0x06, - 0x04, 0x28, 0x05, 0xD6, 0x53, 0x20, 0xCC, 0x47, 0xCD, 0xF2, 0xD4, 0x53, 0x70, 0x65, 0x65, 0x64, - 0x20, 0x28, 0x46, 0x2C, 0x20, 0x53, 0x29, 0xA0, 0xCD, 0xE9, 0xCA, 0xFE, 0x53, 0x28, 0x06, 0xFE, - 0x46, 0x20, 0xB0, 0xCB, 0xD8, 0x37, 0xC3, 0x4B, 0xC1, 0xCD, 0x02, 0xD5, 0xCD, 0xD1, 0xD4, 0xCD, - 0x2C, 0xD3, 0xFE, 0x0D, 0xCA, 0xD8, 0xD4, 0xCD, 0x8C, 0xD4, 0xC3, 0x80, 0xD4, 0xCD, 0x80, 0xD4, - 0xCD, 0xF2, 0xD4, 0x42, 0x61, 0x6E, 0x6B, 0xA0, 0x47, 0xCD, 0x07, 0xD3, 0xCD, 0x51, 0xD3, 0x78, - 0xCD, 0x89, 0xD2, 0x08, 0x01, 0x00, 0x10, 0xAF, 0xC4, 0x9F, 0xD4, 0x79, 0xCD, 0x07, 0xD3, 0x0C, - 0x10, 0xF6, 0xCD, 0x80, 0xD4, 0x06, 0x08, 0xCD, 0x9F, 0xD4, 0x10, 0xFB, 0x60, 0x68, 0xCD, 0x9F, - 0xD4, 0xE5, 0x01, 0x00, 0x10, 0xE5, 0xE5, 0x21, 0x00, 0x00, 0x11, 0x62, 0xCB, 0xA7, 0xED, 0x52, - 0xEB, 0xE1, 0x19, 0xE1, 0x30, 0x11, 0xE5, 0xE5, 0x21, 0x00, 0x00, 0x11, 0x71, 0xCB, 0xA7, 0xED, - 0x52, 0xEB, 0xE1, 0x19, 0xE1, 0x30, 0x1A, 0x08, 0xFE, 0x01, 0x28, 0x02, 0xD3, 0x40, 0x08, 0x56, - 0x3E, 0x55, 0x77, 0xBE, 0x20, 0x05, 0x2F, 0x77, 0xBE, 0x28, 0x05, 0x72, 0x16, 0x58, 0x18, 0x09, - 0x72, 0x23, 0x0B, 0x78, 0xB1, 0x20, 0xBE, 0x16, 0x5E, 0x08, 0x47, 0x08, 0x3E, 0x01, 0xB8, 0x28, - 0x02, 0xD3, 0x40, 0x7A, 0xCD, 0xA1, 0xD4, 0xE1, 0x3E, 0x10, 0x84, 0x67, 0x20, 0xA0, 0xC9, 0x21, - 0xB2, 0xCB, 0x36, 0xAA, 0x01, 0x01, 0x06, 0x79, 0xCD, 0x89, 0xD2, 0xD3, 0x40, 0x3E, 0x55, 0xBE, - 0x3E, 0x01, 0xD3, 0x40, 0x79, 0xC5, 0xE5, 0xCC, 0xFD, 0xCA, 0xE1, 0xC1, 0x0C, 0x10, 0xE8, 0x36, - 0x55, 0xC9, 0x55, 0x01, 0x22, 0x00, 0x11, 0x5E, 0x00, 0x21, 0xC1, 0xCB, 0xED, 0xB0, 0xC3, 0x5E, - 0x00, 0x01, 0x00, 0x20, 0x11, 0x00, 0x01, 0x21, 0x00, 0xC0, 0xC5, 0xD5, 0xE5, 0xED, 0xB0, 0xD1, - 0xE1, 0xC1, 0xD3, 0x40, 0xED, 0xB0, 0x3E, 0x55, 0x32, 0xB2, 0xCB, 0x32, 0x2B, 0x00, 0x3E, 0x01, - 0xD3, 0x40, 0xC9, 0xCD, 0x22, 0xCE, 0x3A, 0x21, 0x00, 0xCD, 0x0E, 0xCC, 0xCD, 0x1F, 0xCC, 0x18, - 0x12, 0xCD, 0x22, 0xCE, 0x3A, 0x44, 0x00, 0xCD, 0x0E, 0xCC, 0x3A, 0x45, 0x00, 0xCD, 0xFE, 0xD2, - 0xCD, 0x7C, 0xCC, 0xCD, 0x80, 0xD4, 0x3A, 0x09, 0x00, 0xB7, 0xF8, 0xC3, 0x8D, 0xC0, 0xF5, 0xCD, - 0x27, 0xC1, 0x20, 0x02, 0xAD, 0x3A, 0x09, 0x00, 0xCD, 0xA1, 0xD4, 0xF1, 0xC3, 0xF3, 0xD2, 0x2E, - 0xD9, 0x3A, 0x09, 0x00, 0xE6, 0x7F, 0xFE, 0x48, 0x28, 0x0F, 0xFE, 0x53, 0x28, 0x0B, 0x2E, 0x9F, - 0xFE, 0x52, 0x28, 0x05, 0x2E, 0xFF, 0xFE, 0x57, 0xC0, 0xCD, 0x51, 0xD3, 0x3A, 0x21, 0x00, 0xA5, - 0x21, 0x59, 0xCC, 0x17, 0xD4, 0x35, 0xD3, 0x30, 0x0C, 0xF5, 0xCD, 0xA9, 0xCC, 0xF1, 0xB7, 0xC8, - 0xCD, 0xF2, 0xD4, 0x2C, 0xA0, 0xB7, 0xC8, 0x18, 0xEA, 0x0F, 0x10, 0x07, 0xF9, 0x08, 0x97, 0x08, - 0x20, 0x9A, 0x19, 0x63, 0x14, 0x64, 0x20, 0x10, 0x46, 0x6F, 0x75, 0x6E, 0xE4, 0x0C, 0x82, 0x18, - 0x4C, 0x6F, 0x73, 0xF4, 0x18, 0x19, 0x71, 0x75, 0x65, 0x73, 0xF4, 0x9E, 0xCD, 0x51, 0xD3, 0x3A, - 0x44, 0x00, 0xF5, 0x21, 0xC8, 0xCC, 0xCD, 0x9F, 0xCC, 0xE1, 0x3A, 0x45, 0x00, 0x28, 0x0D, 0x6F, - 0x3C, 0xC8, 0x84, 0xFE, 0x10, 0xC8, 0x7D, 0xCD, 0xF2, 0xD4, 0x3B, 0xA0, 0x21, 0x46, 0xCD, 0x3C, - 0xC8, 0x3D, 0x28, 0x05, 0xCD, 0x35, 0xD3, 0x18, 0xF8, 0x7E, 0xE6, 0x7F, 0xFE, 0x20, 0xD4, 0xA1, - 0xD4, 0x30, 0x0F, 0xE5, 0x21, 0x90, 0xCD, 0x3D, 0xF4, 0x35, 0xD3, 0xF2, 0xB7, 0xCC, 0xCD, 0xA9, - 0xCC, 0xE1, 0x7E, 0x23, 0xB7, 0xF8, 0x18, 0xE1, 0x01, 0x06, 0x20, 0x26, 0x20, 0x07, 0x20, 0x8E, - 0x01, 0x06, 0x11, 0x84, 0x03, 0x09, 0x0A, 0x86, 0x01, 0x06, 0x20, 0x43, 0x14, 0x72, 0x12, 0x20, - 0x54, 0x72, 0x61, 0x63, 0xEB, 0x01, 0x07, 0x20, 0x8E, 0x01, 0x05, 0x11, 0x84, 0x03, 0x09, 0x0B, - 0x85, 0x0F, 0x10, 0x07, 0xF9, 0x01, 0x08, 0x11, 0x03, 0x82, 0x01, 0x0D, 0x0B, 0x88, 0x01, 0x07, - 0x11, 0x03, 0x82, 0x01, 0x07, 0x11, 0x0C, 0x82, 0x43, 0x61, 0x6E, 0x10, 0x4C, 0x6F, 0x63, 0x61, - 0x74, 0x65, 0x20, 0x53, 0x12, 0x94, 0x0F, 0x08, 0x97, 0x01, 0x53, 0x65, 0x6C, 0x12, 0x20, 0x9B, - 0x01, 0x53, 0x65, 0x6C, 0x12, 0x20, 0x48, 0x65, 0x61, 0xE4, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x20, - 0x50, 0x75, 0x6C, 0x73, 0x65, 0x20, 0x84, 0x06, 0x20, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x20, 0x82, - 0x1D, 0x42, 0x75, 0x66, 0x66, 0x96, 0x1D, 0x13, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x9B, 0x0F, 0x1E, - 0x11, 0x13, 0x4C, 0x6F, 0xF7, 0x04, 0x20, 0x09, 0x0A, 0x85, 0x03, 0x19, 0x70, 0x14, 0x74, 0x95, - 0x01, 0x07, 0x11, 0x0C, 0x82, 0x0E, 0x20, 0x44, 0x6F, 0x65, 0x1F, 0x10, 0x43, 0x6F, 0x6D, 0x70, - 0x61, 0x72, 0xE5, 0x01, 0x0D, 0x0B, 0x88, 0x18, 0x41, 0x6C, 0x69, 0x67, 0x6E, 0x6D, 0x65, 0x6E, - 0x74, 0x20, 0x82, 0x0E, 0x20, 0x41, 0x6C, 0x69, 0x67, 0x6E, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x82, - 0x20, 0x54, 0x65, 0x73, 0xF4, 0x46, 0x61, 0x69, 0x6C, 0x15, 0x20, 0x74, 0x6F, 0xA0, 0x45, 0x72, - 0x72, 0x94, 0x1A, 0xA0, 0x54, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0xF4, 0x19, 0x5A, 0x16, 0xEF, 0x53, - 0x65, 0x65, 0xEB, 0x19, 0x61, 0xE4, 0x57, 0x1C, 0x74, 0xE5, 0x4F, 0x63, 0x63, 0x75, 0x72, 0x72, - 0x95, 0x20, 0x44, 0x75, 0x1C, 0x6E, 0x67, 0xA0, 0x20, 0x41, 0x66, 0x74, 0x16, 0xA0, 0x43, 0x52, - 0x43, 0xA0, 0x56, 0x16, 0x69, 0x66, 0xF9, 0x48, 0x65, 0x61, 0x64, 0x96, 0x1B, 0xA0, 0x6E, 0x6F, - 0x74, 0xA0, 0x2C, 0xA0, 0x65, 0x63, 0xF4, 0x41, 0x43, 0x4B, 0xA0, 0x6F, 0xF2, 0x65, 0xE4, 0x65, - 0xF2, 0x20, 0x50, 0x72, 0x6F, 0x74, 0x12, 0x95, 0x44, 0x61, 0x74, 0x61, 0xA0, 0x52, 0xE5, 0x46, - 0x61, 0x75, 0x6C, 0xF4, 0x44, 0x1C, 0x76, 0xE5, 0x72, 0xE9, 0x4E, 0x6F, 0xA0, 0x42, 0x75, 0x73, - 0xF9, 0x73, 0xA0, 0x21, 0x1A, 0x00, 0x7E, 0xF5, 0x36, 0xFF, 0xCD, 0x28, 0xCE, 0xF1, 0x32, 0x1A, - 0x00, 0xC9, 0xCD, 0x28, 0xCE, 0xC3, 0x80, 0xD4, 0xCD, 0x58, 0xD3, 0x28, 0x1F, 0xCD, 0x9F, 0xD4, - 0x3A, 0x17, 0x00, 0xCD, 0x07, 0xD3, 0xCD, 0x9F, 0xD4, 0x2A, 0x18, 0x00, 0x7C, 0xCD, 0x07, 0xD3, - 0x7D, 0xCD, 0xFE, 0xD2, 0x3A, 0x1A, 0x00, 0xB7, 0xF8, 0xC3, 0xF3, 0xD2, 0xED, 0x5B, 0x1A, 0x00, - 0x3A, 0x18, 0x00, 0x57, 0xCD, 0x9F, 0xD4, 0x3A, 0x17, 0x00, 0xCD, 0x07, 0xD3, 0xCD, 0x9F, 0xD4, - 0x7A, 0xCD, 0xFE, 0xD2, 0x7B, 0x18, 0xE0, 0x21, 0x17, 0x00, 0x3A, 0x0C, 0x00, 0xFE, 0xFF, 0x46, - 0x38, 0x09, 0x34, 0x3A, 0x14, 0x00, 0xBE, 0x3C, 0xD0, 0x36, 0x00, 0x2A, 0x18, 0x00, 0x7D, 0x32, - 0x1F, 0x00, 0xE5, 0xED, 0x5B, 0x0A, 0x00, 0xB7, 0xED, 0x52, 0xE1, 0x28, 0x09, 0x23, 0x38, 0x02, - 0x2B, 0x2B, 0x22, 0x18, 0x00, 0xC9, 0x78, 0x32, 0x17, 0x00, 0xC9, 0x3A, 0x11, 0x00, 0x3C, 0x47, - 0x21, 0x1A, 0x00, 0xCD, 0x58, 0xD3, 0x28, 0x09, 0x3E, 0x01, 0x86, 0x77, 0xB8, 0xD8, 0x90, 0x77, - 0xC9, 0x3A, 0x15, 0x00, 0xE6, 0x07, 0xE5, 0x21, 0xDE, 0xCE, 0xCD, 0x84, 0xD2, 0x7E, 0xE1, 0xF5, - 0x86, 0xB8, 0x38, 0x02, 0x05, 0x90, 0x77, 0x47, 0xF1, 0xFE, 0x04, 0x28, 0x06, 0xFE, 0x06, 0x28, - 0x02, 0x05, 0xC9, 0x3E, 0x02, 0x05, 0x28, 0x03, 0x05, 0xC0, 0x3D, 0x77, 0x3D, 0xC9, 0x05, 0x04, - 0x02, 0x04, 0x06, 0x0B, 0x03, 0x06, 0x3A, 0x08, 0x00, 0x07, 0x2F, 0xE6, 0x01, 0x32, 0x1A, 0x00, - 0xC9, 0xCD, 0xF2, 0xD4, 0x53, 0x74, 0x61, 0x72, 0xF4, 0x21, 0x00, 0x00, 0xCD, 0x73, 0xCF, 0x38, - 0xF0, 0x22, 0x18, 0x00, 0xCD, 0xF2, 0xD4, 0x45, 0x6E, 0xE4, 0x2A, 0x12, 0x00, 0xCD, 0x73, 0xCF, - 0x38, 0xF2, 0x22, 0x0A, 0x00, 0xAF, 0x32, 0x17, 0x00, 0x32, 0x0C, 0x00, 0x3A, 0x14, 0x00, 0xB7, - 0xC8, 0xCD, 0xF2, 0xD4, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0xA8, 0x47, 0x04, 0x3E, - 0x00, 0xF5, 0xFE, 0x10, 0x38, 0x05, 0xCD, 0xFE, 0xD2, 0x18, 0x03, 0xCD, 0x07, 0xD3, 0xCD, 0xF2, - 0xD4, 0xAF, 0xF1, 0x3C, 0x10, 0xEB, 0xCD, 0xF2, 0xD4, 0x41, 0x6C, 0x6C, 0x29, 0x20, 0x5B, 0x41, - 0x6C, 0x6C, 0x5D, 0xA0, 0xCD, 0x1A, 0xD4, 0x21, 0xFF, 0x00, 0xCD, 0x79, 0xD3, 0xAF, 0xB4, 0x20, - 0xB4, 0x7D, 0x32, 0x0C, 0x00, 0xFE, 0xFF, 0xC8, 0x3A, 0x14, 0x00, 0xBD, 0x38, 0xA7, 0x7D, 0x32, - 0x17, 0x00, 0xC9, 0xCD, 0x27, 0xC1, 0x69, 0x6E, 0x67, 0x20, 0x43, 0x79, 0x6C, 0x69, 0x6E, 0x64, - 0x16, 0x20, 0x28, 0x30, 0xAD, 0xE5, 0x2A, 0x12, 0x00, 0xCD, 0x15, 0xD3, 0xE1, 0xCD, 0xF2, 0xD4, - 0x29, 0x20, 0xDB, 0xCD, 0x15, 0xD3, 0xCD, 0xF2, 0xD4, 0x5D, 0xA0, 0xCD, 0x1A, 0xD4, 0xCD, 0x79, - 0xD3, 0xEB, 0x2A, 0x12, 0x00, 0xB7, 0xED, 0x52, 0xEB, 0xC9, 0xDB, 0x04, 0xE6, 0x08, 0x20, 0x14, - 0x3E, 0x09, 0xD3, 0x02, 0x3E, 0x84, 0xD3, 0x00, 0xD9, 0x0E, 0x00, 0xD9, 0x18, 0x3B, 0xCD, 0x33, - 0xD0, 0xCD, 0x22, 0xD0, 0x3E, 0x0A, 0xCD, 0x06, 0xD0, 0x21, 0xD0, 0x07, 0xCD, 0x7C, 0xD8, 0x3E, - 0x08, 0xCD, 0x06, 0xD0, 0x16, 0x64, 0x15, 0x28, 0xEB, 0x21, 0x2B, 0xD0, 0x3E, 0x19, 0x06, 0x09, - 0xCD, 0x06, 0xD0, 0xD9, 0x79, 0xD9, 0x4F, 0xED, 0xA3, 0x28, 0xEB, 0xCD, 0x0F, 0xD0, 0xCD, 0x0F, - 0xD0, 0x28, 0xE6, 0xFE, 0x0D, 0x3E, 0x09, 0x20, 0xE7, 0x3E, 0xFF, 0xCD, 0x18, 0xD5, 0x3E, 0x0D, - 0xCD, 0x18, 0xD5, 0xC3, 0x80, 0xD4, 0xD9, 0x0C, 0x0C, 0xED, 0x79, 0x0D, 0x0D, 0xD9, 0xC9, 0xD5, - 0x11, 0xA0, 0x8C, 0xCD, 0xF8, 0xD4, 0xC4, 0x0A, 0xD5, 0x20, 0x05, 0x1B, 0x7A, 0xB3, 0x20, 0xF3, - 0xD1, 0xC9, 0x06, 0x08, 0xAF, 0xCD, 0x18, 0xD5, 0x10, 0xFA, 0xC9, 0x90, 0xC0, 0xA0, 0x90, 0x88, - 0x84, 0x82, 0x01, 0xCD, 0x79, 0xD3, 0xD8, 0x7D, 0xFE, 0x08, 0xD2, 0xF7, 0xC0, 0x21, 0x4F, 0xD0, - 0xCD, 0x84, 0xD2, 0x4E, 0xED, 0x78, 0x3C, 0xCA, 0xF7, 0xC0, 0x79, 0xD9, 0x4F, 0xD9, 0xC9, 0x00, - 0x20, 0x50, 0x60, 0x70, 0x80, 0x90, 0xF0, 0xCD, 0x84, 0xD3, 0xC5, 0xD5, 0xE5, 0xED, 0xB0, 0xE1, - 0xD1, 0xC1, 0x18, 0x03, 0xCD, 0x84, 0xD3, 0x1A, 0xBE, 0x28, 0x13, 0xCD, 0xF9, 0xD2, 0x7E, 0xCD, - 0x9C, 0xD4, 0x1A, 0xCD, 0x9C, 0xD4, 0xEB, 0xCD, 0xF9, 0xD2, 0xEB, 0xCD, 0x80, 0xD4, 0x13, 0x23, - 0x0B, 0x78, 0xB1, 0x20, 0xE2, 0xC9, 0x13, 0x2A, 0x05, 0x00, 0xCD, 0x79, 0xD3, 0xCD, 0xF9, 0xD2, - 0x7E, 0xCD, 0x9C, 0xD4, 0xCD, 0x1A, 0xD4, 0xCD, 0xFA, 0xD0, 0x30, 0x07, 0xCD, 0xF2, 0xD4, 0x3F, - 0x8D, 0x18, 0xEA, 0xF5, 0xAF, 0x80, 0x20, 0x07, 0xF1, 0xB7, 0x20, 0x0B, 0x23, 0x18, 0x08, 0x48, - 0x06, 0x00, 0xEB, 0xED, 0xB0, 0xEB, 0xF1, 0x22, 0x05, 0x00, 0xFE, 0x2E, 0xC8, 0xFE, 0x2D, 0x20, - 0xCC, 0x2B, 0x22, 0x05, 0x00, 0x18, 0xC6, 0xCD, 0x90, 0xD3, 0x38, 0x05, 0xC5, 0xCD, 0xFA, 0xD0, - 0xD1, 0xDA, 0xF7, 0xC0, 0xC2, 0xF7, 0xC0, 0x80, 0xCA, 0xF7, 0xC0, 0xC5, 0xD5, 0xE5, 0x11, 0x5E, - 0x00, 0x1A, 0xBE, 0x20, 0x04, 0x13, 0x23, 0x10, 0xF8, 0xE1, 0xE5, 0x06, 0x10, 0xCC, 0x6B, 0xD1, - 0xE1, 0xD1, 0xC1, 0x23, 0x1B, 0x7A, 0xB3, 0x20, 0xE2, 0xC9, 0xE5, 0x06, 0x00, 0x21, 0x5E, 0x00, - 0xCD, 0x3E, 0xD3, 0xB7, 0x28, 0x2D, 0xFE, 0x2D, 0x28, 0x29, 0xFE, 0x2E, 0x28, 0x25, 0x13, 0x4F, - 0xFE, 0x27, 0x28, 0x12, 0xFE, 0x22, 0x28, 0x0E, 0x1B, 0xE5, 0xCD, 0xB2, 0xD3, 0x7D, 0xE1, 0x38, - 0x13, 0x77, 0x23, 0x04, 0x18, 0xDA, 0x1A, 0x13, 0xB7, 0x28, 0x08, 0xB9, 0x28, 0xD2, 0x77, 0x23, - 0x04, 0x18, 0xF3, 0xB7, 0x11, 0x5E, 0x00, 0xE1, 0xC9, 0xFE, 0x4D, 0x20, 0x01, 0x13, 0x01, 0x80, - 0x00, 0x2A, 0x03, 0x00, 0xCD, 0x7F, 0xD3, 0x1E, 0x10, 0xAF, 0xB0, 0x20, 0x0A, 0x3E, 0x0F, 0xB9, - 0x38, 0x05, 0xAF, 0xB1, 0x28, 0x01, 0x59, 0xC5, 0x43, 0xCD, 0x6B, 0xD1, 0x22, 0x03, 0x00, 0xC1, - 0x79, 0x93, 0x4F, 0x30, 0x01, 0x05, 0x78, 0xB1, 0x20, 0xDD, 0xC9, 0xCD, 0xF9, 0xD2, 0xC5, 0xE5, - 0xD5, 0x0E, 0x00, 0x1E, 0x04, 0x3E, 0x03, 0xA1, 0xCC, 0xAD, 0xD1, 0xCD, 0xAD, 0xD1, 0x7E, 0xCD, - 0xFE, 0xD2, 0x1C, 0x1C, 0x23, 0x0C, 0x10, 0xED, 0xCD, 0xAD, 0xD1, 0x3E, 0x3A, 0xBB, 0x20, 0xF8, - 0xD1, 0xE1, 0xC1, 0x7E, 0x23, 0xCD, 0x9D, 0xD1, 0x10, 0xF9, 0xC3, 0x80, 0xD4, 0xE6, 0x7F, 0xFE, - 0x7F, 0x28, 0x05, 0xFE, 0x20, 0xD2, 0xA1, 0xD4, 0x3E, 0x2E, 0xC3, 0xA1, 0xD4, 0x1C, 0xC3, 0x9F, - 0xD4, 0xCD, 0x90, 0xD3, 0x38, 0x04, 0xC5, 0xCD, 0xFA, 0xD0, 0xDA, 0xF7, 0xC0, 0xC2, 0xF7, 0xC0, - 0x80, 0xCA, 0xF7, 0xC0, 0xC1, 0xE5, 0xEB, 0xED, 0xA0, 0xE2, 0xD3, 0xD1, 0x3D, 0x20, 0xF8, 0xE1, - 0xED, 0xB0, 0xC9, 0xE1, 0xC9, 0xCD, 0x72, 0xD3, 0xE9, 0xCD, 0x72, 0xD3, 0x4D, 0xED, 0x78, 0xCD, - 0xFE, 0xD2, 0xC3, 0x80, 0xD4, 0xCD, 0xB2, 0xD3, 0x45, 0xCD, 0x72, 0xD3, 0x4D, 0xED, 0x41, 0xC9, - 0xCD, 0xB2, 0xD3, 0xDA, 0xF7, 0xC0, 0xCD, 0x45, 0xD3, 0xA7, 0x28, 0x74, 0xE5, 0xFE, 0x2B, 0x28, - 0x2D, 0xFE, 0x2D, 0x28, 0x36, 0xFE, 0x2A, 0x28, 0x41, 0xFE, 0x2F, 0x28, 0x50, 0xCD, 0xB2, 0xD3, - 0xDA, 0xF7, 0xC0, 0xCD, 0x45, 0xD3, 0xA7, 0xC2, 0xF7, 0xC0, 0xEB, 0xE1, 0xE5, 0xD5, 0x19, 0xCD, - 0x76, 0xD2, 0xCD, 0xF2, 0xD4, 0x2C, 0xA0, 0xD1, 0xE1, 0xA7, 0xED, 0x52, 0x18, 0x42, 0x13, 0xCD, - 0xB2, 0xD3, 0xDA, 0xF7, 0xC0, 0xEB, 0xE3, 0x19, 0xD1, 0x18, 0xBB, 0x13, 0xCD, 0xB2, 0xD3, 0xDA, - 0xF7, 0xC0, 0xEB, 0xE3, 0xA7, 0xED, 0x52, 0xD1, 0x18, 0xAC, 0x13, 0xCD, 0xB2, 0xD3, 0xDA, 0xF7, - 0xC0, 0xEB, 0xE3, 0xC5, 0x42, 0x4B, 0xCD, 0xA6, 0xD2, 0xC1, 0xD1, 0x18, 0x99, 0x13, 0xCD, 0xB2, - 0xD3, 0xDA, 0xF7, 0xC0, 0xEB, 0xE3, 0xC5, 0x42, 0x4B, 0xCD, 0xBF, 0xD2, 0xC1, 0xD1, 0x18, 0x86, - 0xCD, 0x76, 0xD2, 0xC3, 0x80, 0xD4, 0xCD, 0xF9, 0xD2, 0xCD, 0x9F, 0xD4, 0xCD, 0x96, 0xD2, 0x3E, - 0x2E, 0xC3, 0xA1, 0xD4, 0x85, 0x6F, 0xD0, 0x24, 0xC9, 0xC5, 0x47, 0x3E, 0x01, 0x05, 0xFA, 0x94, - 0xD2, 0x07, 0x30, 0xF9, 0xC1, 0xC9, 0x01, 0x0A, 0x00, 0xCD, 0xBF, 0xD2, 0x7B, 0xF5, 0x7C, 0xB5, - 0xC4, 0x96, 0xD2, 0xF1, 0x18, 0x61, 0x11, 0x00, 0x00, 0xEB, 0x3E, 0x10, 0xB7, 0xCB, 0x43, 0x28, - 0x01, 0x09, 0xCB, 0x1C, 0xCB, 0x1D, 0xCB, 0x1A, 0xCB, 0x1B, 0x3D, 0x20, 0xEF, 0xEB, 0xC9, 0x11, - 0x00, 0x00, 0x7A, 0xB8, 0x20, 0x02, 0x7B, 0xB9, 0x3F, 0xD8, 0xEB, 0x3E, 0x10, 0x37, 0xCB, 0x13, - 0xCB, 0x12, 0xCB, 0x15, 0xCB, 0x14, 0x30, 0x05, 0xB7, 0xED, 0x42, 0x18, 0x06, 0xED, 0x42, 0x30, - 0x02, 0x1D, 0x09, 0x3D, 0x20, 0xE7, 0xEB, 0xB7, 0xC9, 0xF5, 0xCD, 0x45, 0xD3, 0xB7, 0xC2, 0xF7, - 0xC0, 0xF1, 0xC9, 0xCD, 0xF2, 0xD4, 0xA0, 0x18, 0x05, 0x7C, 0xCD, 0xFE, 0xD2, 0x7D, 0xF5, 0x0F, - 0x0F, 0x0F, 0x0F, 0xCD, 0x07, 0xD3, 0xF1, 0xE6, 0x0F, 0xC6, 0x30, 0xFE, 0x3A, 0xDA, 0xA1, 0xD4, - 0xC6, 0x07, 0xC3, 0xA1, 0xD4, 0x7C, 0xB7, 0x28, 0x0C, 0xCD, 0x07, 0xD3, 0x7D, 0xCD, 0xFE, 0xD2, - 0xCD, 0xF2, 0xD4, 0xC8, 0xC9, 0x7D, 0xFE, 0x0A, 0x30, 0xF3, 0x18, 0xDB, 0xFE, 0x61, 0xD8, 0xFE, - 0x7B, 0xD0, 0xD6, 0x20, 0xC9, 0xF5, 0x7E, 0x23, 0x3D, 0xF2, 0x36, 0xD3, 0xF1, 0xC9, 0xCD, 0x45, - 0xD3, 0xFE, 0x2C, 0xC0, 0x13, 0x1A, 0xFE, 0x20, 0x28, 0x04, 0xFE, 0x09, 0x20, 0xDE, 0x13, 0x18, - 0xF4, 0xCD, 0xF2, 0xD4, 0x20, 0x3E, 0xA0, 0xC9, 0x3A, 0x08, 0x00, 0xE6, 0x80, 0x07, 0xC9, 0x3A, - 0x07, 0x00, 0xFE, 0xFF, 0xC0, 0xCD, 0x27, 0xC1, 0x1D, 0x0F, 0x53, 0x65, 0x6C, 0x12, 0x95, 0xC3, - 0xDE, 0xD4, 0xCD, 0x79, 0xD3, 0xD0, 0xC3, 0xF7, 0xC0, 0xCD, 0xB2, 0xD3, 0xC3, 0xE9, 0xD2, 0xCD, - 0x90, 0xD3, 0x18, 0xF8, 0xCD, 0x90, 0xD3, 0x38, 0xED, 0xE5, 0xCD, 0x72, 0xD3, 0xEB, 0xE1, 0xC9, - 0xCD, 0xB2, 0xD3, 0xCD, 0x3E, 0xD3, 0xFE, 0x53, 0xE5, 0x20, 0x0A, 0x13, 0xCD, 0xB2, 0xD3, 0x38, - 0xD5, 0x44, 0x4D, 0xE1, 0xC9, 0xCD, 0xB2, 0xD3, 0x38, 0xF9, 0xC1, 0xC5, 0xED, 0x42, 0x23, 0xB7, - 0x18, 0xEF, 0xCD, 0x3E, 0xD3, 0xD5, 0xE5, 0xCD, 0xEE, 0xD3, 0xFE, 0x2E, 0xE1, 0xD1, 0x28, 0x0D, - 0xCD, 0x09, 0xD4, 0xD8, 0xCD, 0xEE, 0xD3, 0xFE, 0x48, 0x28, 0x09, 0xB7, 0xC9, 0xCD, 0xFE, 0xD3, - 0xD8, 0xCD, 0xD9, 0xD3, 0xCD, 0x4E, 0xD3, 0xB7, 0xC9, 0x21, 0x00, 0x00, 0xCD, 0xFE, 0xD3, 0xD8, - 0x13, 0xC5, 0x44, 0x4D, 0x29, 0x29, 0x09, 0x29, 0xC1, 0xCD, 0x84, 0xD2, 0x18, 0xEE, 0x21, 0x00, - 0x00, 0xCD, 0x09, 0xD4, 0xD8, 0x13, 0x29, 0x29, 0x29, 0x29, 0x85, 0x6F, 0x18, 0xF3, 0x1A, 0xFE, - 0x30, 0xD8, 0xFE, 0x3A, 0x3F, 0xD8, 0xD6, 0x30, 0xC9, 0xCD, 0xFE, 0xD3, 0xD0, 0xCD, 0x2C, 0xD3, - 0xFE, 0x41, 0xD8, 0xFE, 0x47, 0x3F, 0xD8, 0xD6, 0x37, 0xC9, 0x11, 0x5E, 0x00, 0x3E, 0x24, 0xC5, - 0xE5, 0x4F, 0x06, 0x00, 0x62, 0x6B, 0xCD, 0x02, 0xD5, 0xCD, 0xC7, 0xD4, 0xFE, 0x10, 0x28, 0xF6, - 0xFE, 0x05, 0xCC, 0x80, 0xD4, 0x28, 0xEF, 0xFE, 0x0D, 0x28, 0x3F, 0xFE, 0x08, 0x28, 0x04, 0xFE, - 0x7F, 0x20, 0x10, 0x05, 0xFA, 0x22, 0xD4, 0x2B, 0xCD, 0x85, 0xD4, 0x7E, 0xFE, 0x20, 0xDC, 0x85, - 0xD4, 0x18, 0xD3, 0xFE, 0x16, 0x20, 0x10, 0x05, 0xFA, 0x22, 0xD4, 0x2B, 0xCD, 0x85, 0xD4, 0x7E, - 0xFE, 0x20, 0xDC, 0x85, 0xD4, 0x18, 0xF0, 0xF5, 0xCD, 0x8C, 0xD4, 0xF1, 0xFE, 0x15, 0xCC, 0x80, - 0xD4, 0x28, 0xAF, 0x77, 0x23, 0x04, 0x79, 0xB8, 0x20, 0xAC, 0x36, 0x00, 0x78, 0xE1, 0xC1, 0xB7, - 0xCD, 0xF2, 0xD4, 0x8D, 0xC9, 0xCD, 0xF2, 0xD4, 0x08, 0x20, 0x88, 0xC9, 0xFE, 0x20, 0x30, 0x11, - 0xFE, 0x0D, 0x28, 0x0D, 0xC6, 0x40, 0xCD, 0xF2, 0xD4, 0xDE, 0x18, 0x05, 0xCD, 0xF3, 0xD2, 0x3E, - 0x20, 0xF5, 0xE6, 0x7F, 0xD9, 0xCB, 0x78, 0xD9, 0xC4, 0x29, 0xD5, 0xD9, 0xCB, 0x60, 0xD9, 0xCC, - 0x18, 0xD5, 0xFE, 0x0D, 0x3E, 0x0A, 0xCC, 0xA1, 0xD4, 0xCC, 0xC1, 0xD4, 0xCD, 0x21, 0xC8, 0xF1, - 0xC9, 0xCD, 0xF8, 0xD4, 0xC4, 0x0A, 0xD5, 0xFE, 0x10, 0xCC, 0x4D, 0xD5, 0xFE, 0x13, 0xCC, 0x02, - 0xD5, 0xFE, 0x03, 0x28, 0x03, 0xFE, 0x1B, 0xC0, 0x31, 0xF0, 0x7F, 0xCD, 0x8C, 0xD4, 0xCD, 0x80, - 0xD4, 0xC3, 0x8D, 0xC0, 0xF5, 0x7E, 0x23, 0xB7, 0x28, 0x06, 0xCD, 0xA1, 0xD4, 0xF2, 0xE5, 0xD4, - 0xF1, 0xC9, 0xE3, 0xCD, 0xE4, 0xD4, 0xE3, 0xC9, 0xD9, 0xED, 0x78, 0xD9, 0xE6, 0x40, 0xC8, 0x3E, - 0xFF, 0xC9, 0xCD, 0x21, 0xC8, 0xCD, 0xF8, 0xD4, 0x28, 0xF8, 0xCD, 0xF8, 0xD4, 0x28, 0xFB, 0xD9, - 0x0C, 0xED, 0x78, 0x0D, 0xD9, 0xE6, 0x7F, 0xC9, 0xF5, 0xD9, 0xED, 0x78, 0xE6, 0x80, 0x28, 0xFA, - 0x0C, 0xF1, 0xED, 0x79, 0xF5, 0x0D, 0xD9, 0xF1, 0xC9, 0xF5, 0xC5, 0x06, 0xF7, 0x10, 0xFE, 0xC1, - 0xCD, 0xC1, 0xD4, 0xFE, 0x10, 0x28, 0x24, 0xDB, 0x54, 0xE6, 0x20, 0x20, 0xF3, 0xF1, 0xCB, 0xFF, - 0xD3, 0x54, 0xCB, 0xBF, 0xD3, 0x54, 0xCB, 0xFF, 0xD3, 0x54, 0xCB, 0xBF, 0xC9, 0xF5, 0xD9, 0x3E, - 0x80, 0xA8, 0x47, 0xD9, 0xCB, 0x7F, 0x3E, 0x11, 0xC4, 0x3E, 0xD5, 0xF1, 0xC9, 0xFD, 0xC7, 0x40, - 0xC4, 0xF7, 0xC0, 0x39, 0xD1, 0xD9, 0xD1, 0xF7, 0xC0, 0xD5, 0xD1, 0xF0, 0xD1, 0xBE, 0xCF, 0xF7, - 0xC0, 0xF7, 0xC0, 0xF7, 0xC0, 0x57, 0xD0, 0xF7, 0xC0, 0xE5, 0xD1, 0xF7, 0xC0, 0xC7, 0xD0, 0x7C, - 0xC6, 0xA4, 0xC7, 0x39, 0xC8, 0xF7, 0xC0, 0x64, 0xD0, 0x86, 0xC6, 0xF7, 0xC0, 0xF7, 0xC0, 0xB1, - 0xD1, 0x16, 0x02, 0xD5, 0xCD, 0x02, 0xD6, 0xD1, 0xD0, 0xD5, 0x3E, 0x0A, 0x32, 0x18, 0x00, 0xCD, - 0x60, 0xD6, 0xCD, 0x02, 0xD6, 0xD1, 0xD0, 0x15, 0x20, 0xE9, 0x18, 0x50, 0xD5, 0x3A, 0x17, 0x00, - 0xF5, 0x3A, 0x18, 0x00, 0xF5, 0x3A, 0x15, 0x00, 0xF5, 0xCB, 0x87, 0x32, 0x15, 0x00, 0xCD, 0x02, - 0xD6, 0xF1, 0x32, 0x15, 0x00, 0xF1, 0x32, 0x18, 0x00, 0xF1, 0x32, 0x17, 0x00, 0xCD, 0x60, 0xD6, - 0xD1, 0xC9, 0x1E, 0x02, 0x16, 0x0A, 0xD5, 0xCD, 0xE5, 0xD6, 0xD1, 0xD0, 0x15, 0x20, 0xF7, 0x1D, - 0x28, 0x1A, 0xCD, 0xAC, 0xD5, 0x18, 0xED, 0x1E, 0x02, 0x16, 0x04, 0xD5, 0xCD, 0x2B, 0xD7, 0xD1, - 0xD0, 0x15, 0x20, 0xF7, 0x1D, 0x28, 0x05, 0xCD, 0xAC, 0xD5, 0x18, 0xED, 0x3A, 0x21, 0x00, 0x4F, - 0x37, 0xC9, 0x97, 0x32, 0x18, 0x00, 0x32, 0x17, 0x00, 0x32, 0x1F, 0x00, 0xCD, 0xE0, 0xD7, 0xD3, - 0x34, 0xCD, 0xBA, 0xD6, 0x38, 0x0E, 0xD3, 0x30, 0xDB, 0x34, 0xCB, 0x57, 0x20, 0x3B, 0x1F, 0x30, - 0xF7, 0xC3, 0xCB, 0xD6, 0x3E, 0xC4, 0xD3, 0x30, 0xCD, 0x61, 0xD8, 0xE6, 0x57, 0xD3, 0x04, 0xCD, - 0x6F, 0xD8, 0xDB, 0x04, 0xE6, 0x40, 0x20, 0x16, 0xCD, 0x5A, 0xD8, 0xDB, 0x34, 0xCB, 0x57, 0x20, - 0x18, 0x1F, 0x30, 0xF7, 0x3E, 0xD0, 0xD3, 0x30, 0x97, 0xD3, 0x31, 0xC3, 0xDD, 0xD6, 0xDB, 0x34, - 0xCB, 0x57, 0x20, 0x05, 0x1F, 0x30, 0xDB, 0x18, 0xCB, 0x3E, 0x80, 0x32, 0x21, 0x00, 0x37, 0xC9, - 0x97, 0xCD, 0xE0, 0xD7, 0xD3, 0x34, 0x3A, 0x18, 0x00, 0xD3, 0x33, 0x4F, 0x3A, 0x1A, 0x00, 0xD3, - 0x32, 0x3A, 0x1F, 0x00, 0xD3, 0x31, 0x91, 0xCA, 0x5A, 0xD8, 0xCD, 0xBA, 0xD6, 0x38, 0x0F, 0xF6, - 0x10, 0xD3, 0x30, 0xDB, 0x34, 0xCB, 0x57, 0x20, 0xD0, 0x1F, 0x30, 0xF7, 0x18, 0x3D, 0xCD, 0x61, - 0xD8, 0xE6, 0x4F, 0xD3, 0x04, 0x3E, 0x18, 0xD3, 0x30, 0xDB, 0x34, 0xCB, 0x57, 0x20, 0xBA, 0x1F, - 0x30, 0xF7, 0xDB, 0x30, 0x2E, 0x32, 0xDB, 0x04, 0xE6, 0x40, 0x20, 0xFA, 0x2D, 0x20, 0xF7, 0xDB, - 0x04, 0xE6, 0x40, 0x20, 0xFA, 0xCD, 0x5A, 0xD8, 0x18, 0x23, 0x3A, 0x15, 0x00, 0xCB, 0x5F, 0x3E, - 0x0E, 0x28, 0x06, 0xE6, 0x04, 0x37, 0xC0, 0x3E, 0x0C, 0xA7, 0xC9, 0xCD, 0x5A, 0xD8, 0x21, 0x64, - 0x00, 0xCD, 0x7C, 0xD8, 0xDB, 0x30, 0x32, 0x21, 0x00, 0xE6, 0x98, 0x37, 0xC0, 0x3A, 0x18, 0x00, - 0x32, 0x1F, 0x00, 0xA7, 0xC9, 0xCD, 0x1C, 0xD7, 0xD3, 0x30, 0xDB, 0x34, 0x1F, 0x38, 0x16, 0xED, - 0xA2, 0x04, 0xDB, 0x34, 0x1F, 0x38, 0x0E, 0xED, 0xA2, 0xC2, 0xEA, 0xD6, 0xDB, 0x34, 0xCB, 0x4F, - 0x20, 0x10, 0x1F, 0x30, 0xF7, 0xCD, 0x5A, 0xD8, 0xDB, 0x30, 0x32, 0x21, 0x00, 0xE6, 0x9C, 0xC8, - 0x18, 0x08, 0xCD, 0x5A, 0xD8, 0x3E, 0x80, 0x32, 0x21, 0x00, 0x37, 0xC9, 0xCD, 0xCB, 0xD7, 0x57, - 0xCD, 0x51, 0xD8, 0xC6, 0x88, 0x5F, 0x7A, 0xD3, 0x34, 0x7B, 0xC9, 0xCD, 0x6F, 0xD8, 0xCD, 0xCB, - 0xD7, 0x57, 0xCD, 0x51, 0xD8, 0xC6, 0xA8, 0x5F, 0x7A, 0xD3, 0x34, 0x7B, 0xD3, 0x30, 0xDB, 0x34, - 0x1F, 0x38, 0x12, 0xED, 0xA3, 0x04, 0xDB, 0x34, 0x1F, 0x38, 0x0A, 0xED, 0xA3, 0xC2, 0x3E, 0xD7, - 0xDB, 0x34, 0x1F, 0x30, 0xFB, 0xCD, 0x5A, 0xD8, 0xCD, 0x6F, 0xD8, 0xDB, 0x30, 0x32, 0x21, 0x00, - 0xE6, 0xFC, 0x37, 0xC0, 0xA7, 0x3A, 0x15, 0x00, 0xCB, 0x4F, 0xC8, 0xCD, 0x8B, 0xD7, 0x38, 0x0A, - 0xDB, 0x34, 0x1F, 0x38, 0x04, 0xDB, 0x33, 0x18, 0xF7, 0x1C, 0xCD, 0x5A, 0xD8, 0xDB, 0x30, 0x32, - 0x21, 0x00, 0xE6, 0x9C, 0x37, 0xC0, 0x7B, 0xA7, 0xC8, 0x37, 0xC9, 0xCD, 0x1C, 0xD7, 0xED, 0x4B, - 0x1D, 0x00, 0xCB, 0x38, 0xCB, 0x19, 0xCB, 0x38, 0xCB, 0x19, 0x41, 0x1E, 0x00, 0xD3, 0x30, 0xDB, - 0x34, 0x1F, 0xD8, 0xDB, 0x33, 0xAE, 0xC0, 0x23, 0xDB, 0x34, 0x1F, 0xD8, 0xDB, 0x33, 0xAE, 0xC0, - 0x23, 0xDB, 0x34, 0x1F, 0xD8, 0xDB, 0x33, 0xAE, 0xC0, 0x23, 0xDB, 0x34, 0x1F, 0xD8, 0xDB, 0x33, - 0xAE, 0xC0, 0x23, 0x10, 0xDA, 0xDB, 0x34, 0x1F, 0x30, 0xFB, 0xC9, 0xDB, 0x33, 0x3E, 0x80, 0xCD, - 0xE0, 0xD7, 0x2A, 0x1D, 0x00, 0xCB, 0x1C, 0xCB, 0x1D, 0x45, 0x0E, 0x33, 0x2A, 0x1B, 0x00, 0xC9, - 0x4F, 0xDB, 0x34, 0xE6, 0x04, 0x28, 0x04, 0x97, 0x32, 0x23, 0x00, 0xCD, 0x33, 0xD8, 0xD3, 0x34, - 0xF5, 0xE5, 0xCD, 0x61, 0xD8, 0xE6, 0x5F, 0xD3, 0x04, 0x3A, 0x23, 0x00, 0xA7, 0x28, 0x21, 0x21, - 0x90, 0x01, 0x3A, 0x24, 0x00, 0xB8, 0x20, 0x1B, 0x3A, 0x25, 0x00, 0x67, 0x3A, 0x17, 0x00, 0x32, - 0x25, 0x00, 0xBC, 0x20, 0x06, 0xDB, 0x34, 0xE6, 0x20, 0x20, 0x0B, 0xCD, 0x6F, 0xD8, 0x18, 0x06, - 0x21, 0x20, 0x4E, 0xCD, 0x7C, 0xD8, 0xE1, 0x78, 0x32, 0x24, 0x00, 0x3E, 0x01, 0x32, 0x23, 0x00, - 0xF1, 0xB1, 0xC9, 0x3A, 0x16, 0x00, 0x47, 0x04, 0x97, 0x37, 0x17, 0x10, 0xFD, 0x47, 0x3A, 0x15, - 0x00, 0xCB, 0x57, 0x28, 0x02, 0xCB, 0xE0, 0xCB, 0x47, 0x28, 0x02, 0xCB, 0xF0, 0x78, 0xF6, 0x20, - 0xC9, 0xDB, 0x34, 0x2F, 0xE6, 0x20, 0xC8, 0x3E, 0x04, 0xC9, 0xCD, 0x61, 0xD8, 0xD3, 0x04, 0xAF, - 0xC9, 0xC5, 0x06, 0x7F, 0x3A, 0x17, 0x00, 0xA7, 0x28, 0x02, 0x06, 0x7D, 0x78, 0xC1, 0xC9, 0x21, - 0x08, 0x00, 0x3A, 0x15, 0x00, 0xCB, 0x57, 0x20, 0x03, 0x21, 0x0C, 0x00, 0xC5, 0x2B, 0x06, 0x1C, - 0x10, 0xFE, 0x00, 0x00, 0x7D, 0xB4, 0x20, 0xF5, 0xC1, 0xC9, 0x3A, 0x2D, 0x00, 0xA7, 0x28, 0x05, - 0xFE, 0x01, 0xC8, 0x18, 0x4F, 0x3C, 0x32, 0x2D, 0x00, 0xDB, 0xF8, 0xA7, 0x28, 0x04, 0xFE, 0x01, - 0x20, 0x42, 0x21, 0x29, 0xD9, 0x11, 0x2E, 0x00, 0x01, 0x0E, 0x00, 0xED, 0xB0, 0x21, 0x2E, 0x00, - 0x7C, 0x32, 0x32, 0x00, 0x7D, 0x32, 0x34, 0x00, 0x06, 0x07, 0x0E, 0x00, 0x21, 0x2E, 0x00, 0x7E, - 0x23, 0xD3, 0xF8, 0x81, 0x4F, 0xCD, 0x10, 0xD9, 0x38, 0x1A, 0x10, 0xF3, 0x79, 0xD3, 0xF8, 0x21, - 0x2E, 0x00, 0x11, 0x2F, 0x00, 0x01, 0x2F, 0x00, 0x36, 0x00, 0xED, 0xB0, 0xDB, 0xF8, 0xA7, 0xC8, - 0xFE, 0x01, 0x20, 0xF8, 0xCD, 0xF2, 0xD4, 0x43, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x69, 0x6E, - 0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, 0x20, 0x53, 0x54, 0x44, 0x43, 0x20, 0x63, 0x6F, - 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x6C, 0x65, 0x72, 0x8D, 0x3E, 0xFF, 0x32, 0x2D, 0x00, 0x37, 0xC9, - 0xD5, 0xC5, 0x4E, 0x23, 0x06, 0x0A, 0x11, 0x00, 0x00, 0xDB, 0xF8, 0xB9, 0x28, 0x08, 0x1B, 0x7A, - 0xB3, 0x20, 0xF6, 0x10, 0xF1, 0x37, 0xC1, 0xD1, 0xC9, 0x11, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, - 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xCD, 0x5D, 0xDA, 0x3E, 0xFF, 0x32, 0x0D, 0x00, 0x3E, - 0x12, 0xF5, 0x7E, 0xE6, 0x60, 0x77, 0xF1, 0xD3, 0xF8, 0xC5, 0xD5, 0x06, 0x1E, 0x11, 0x00, 0x00, - 0x7E, 0xCB, 0x7F, 0x20, 0x13, 0x1B, 0x7A, 0xB3, 0x20, 0xF6, 0x10, 0xF1, 0xAF, 0x32, 0x45, 0x00, - 0x3E, 0x07, 0x32, 0x44, 0x00, 0x3E, 0x01, 0x77, 0xD1, 0xC1, 0xC9, 0xCD, 0x5D, 0xDA, 0x3A, 0x16, - 0x00, 0x32, 0x2F, 0x00, 0x3E, 0x81, 0x32, 0x2E, 0x00, 0x3E, 0x19, 0x18, 0xC4, 0xCD, 0xA5, 0xD9, - 0x3E, 0xFF, 0x32, 0x0D, 0x00, 0x32, 0x2E, 0x00, 0x20, 0x11, 0xE5, 0xD5, 0xC5, 0x21, 0x4B, 0x00, - 0x11, 0x0D, 0x00, 0x01, 0x03, 0x00, 0xED, 0xB0, 0xC1, 0xD1, 0xE1, 0x3E, 0x17, 0xCD, 0x41, 0xD9, - 0xED, 0x53, 0x44, 0x00, 0xC9, 0xCD, 0x5D, 0xDA, 0xE5, 0x11, 0x0D, 0x00, 0x21, 0x47, 0x00, 0x06, - 0x03, 0x1A, 0xBE, 0x20, 0x04, 0x23, 0x13, 0x10, 0xF8, 0xE1, 0x11, 0xFF, 0xFF, 0xC8, 0x0E, 0xFF, - 0x06, 0x0A, 0x3E, 0x15, 0xCD, 0x41, 0xD9, 0xED, 0x5B, 0x44, 0x00, 0xE6, 0x02, 0xC0, 0x3E, 0xFF, - 0xBA, 0x20, 0x02, 0xBB, 0xC8, 0x4A, 0x10, 0xEA, 0xBB, 0xC0, 0x79, 0xFE, 0x05, 0x20, 0x04, 0x3E, - 0x03, 0x18, 0x1A, 0xFE, 0x04, 0x20, 0x04, 0x3E, 0x0B, 0x18, 0x12, 0xFE, 0x07, 0x38, 0x04, 0x3E, - 0x0C, 0x18, 0x0A, 0xFE, 0x06, 0x20, 0x04, 0x3E, 0x09, 0x18, 0x02, 0x3E, 0x07, 0x32, 0x44, 0x00, - 0x5F, 0x51, 0xA7, 0xC9, 0xCD, 0xA5, 0xD9, 0xC0, 0x3E, 0x80, 0x32, 0x2E, 0x00, 0x3E, 0x17, 0xCD, - 0x41, 0xD9, 0x3E, 0x16, 0xC3, 0x41, 0xD9, 0xCD, 0x5D, 0xDA, 0x3E, 0xFF, 0x32, 0x0D, 0x00, 0x3E, - 0x13, 0xCD, 0x41, 0xD9, 0xED, 0x5B, 0x44, 0x00, 0x3E, 0xFF, 0xBB, 0xC0, 0xBA, 0x20, 0x06, 0x06, - 0x0A, 0xCD, 0xC2, 0xD9, 0xC8, 0x3E, 0x00, 0x32, 0x44, 0x00, 0xC9, 0xCD, 0x5D, 0xDA, 0x3E, 0x14, - 0xCD, 0x41, 0xD9, 0x3A, 0x44, 0x00, 0xFE, 0xFF, 0xC0, 0x32, 0x2E, 0x00, 0x3E, 0x1B, 0xC3, 0x41, - 0xD9, 0x3A, 0x44, 0x00, 0xFE, 0xFF, 0xC9, 0x3A, 0x45, 0x00, 0xFE, 0xFF, 0xC9, 0x21, 0x2E, 0x00, - 0x11, 0x2F, 0x00, 0x01, 0x2F, 0x00, 0x36, 0x00, 0xED, 0xB0, 0xDD, 0xE5, 0xDD, 0x21, 0x2E, 0x00, - 0x3A, 0x16, 0x00, 0xF6, 0x1F, 0xDD, 0x77, 0x01, 0x3A, 0x17, 0x00, 0xDD, 0x77, 0x19, 0x2A, 0x18, - 0x00, 0xDD, 0x74, 0x1A, 0xDD, 0x75, 0x1B, 0x3A, 0x1A, 0x00, 0xDD, 0x77, 0x18, 0x2A, 0x1B, 0x00, - 0xDD, 0x74, 0x0A, 0xDD, 0x75, 0x0B, 0x2A, 0x1D, 0x00, 0xDD, 0x74, 0x06, 0xDD, 0x75, 0x07, 0x3A, - 0x10, 0x00, 0xE6, 0x60, 0xDD, 0x77, 0x15, 0xDD, 0xE1, 0x21, 0x43, 0x00, 0xC9, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -} -}; - -unsigned char ccs2422_rom[2048] = { - 0xC3, 0x5B, 0xF0, 0xC3, 0x46, 0xF6, 0xC3, 0x56, 0xF6, 0xC3, 0x00, 0xF6, 0xC3, 0x7C, 0xF6, 0xC3, - 0x10, 0xF6, 0xC3, 0x23, 0xF6, 0xC3, 0x6A, 0xF1, 0xC3, 0x65, 0xF1, 0xC3, 0x8A, 0xF0, 0xC3, 0x94, - 0xF6, 0xC3, 0x94, 0xF6, 0xC3, 0xCF, 0xF3, 0xF8, 0xF0, 0x5E, 0xF5, 0x09, 0xF1, 0xAC, 0xF1, 0x09, - 0xF1, 0x3C, 0xF1, 0xFD, 0xF1, 0xD0, 0xF5, 0x4D, 0xF2, 0x09, 0xF1, 0x09, 0xF1, 0x09, 0xF1, 0x5D, - 0xF2, 0x09, 0xF1, 0x55, 0xF2, 0xA7, 0xF5, 0xBD, 0xF5, 0xF6, 0xF4, 0x67, 0xF2, 0x8F, 0xF2, 0x09, - 0xF1, 0x91, 0xF1, 0xF7, 0xF4, 0xEC, 0xF2, 0x9F, 0xF4, 0x82, 0xF1, 0xF3, 0x31, 0x3F, 0x00, 0x21, - 0x00, 0xC3, 0x11, 0xB2, 0xF6, 0x06, 0x10, 0xD5, 0xE5, 0x10, 0xFC, 0x31, 0x95, 0xF0, 0x3E, 0xC5, - 0x01, 0x00, 0xF0, 0x21, 0xFF, 0xFF, 0x24, 0x7E, 0x2F, 0x77, 0xBE, 0x2F, 0x77, 0x20, 0x04, 0x7C, - 0xB8, 0x20, 0xF3, 0x25, 0x01, 0xDE, 0xFF, 0x09, 0xC1, 0xC9, 0xE5, 0xCD, 0x6F, 0xF0, 0x7D, 0xD6, - 0x3C, 0x30, 0x01, 0x25, 0x44, 0xE1, 0xC9, 0x99, 0xF0, 0xF9, 0x11, 0x45, 0xF4, 0xEB, 0x01, 0x1D, - 0x00, 0xED, 0xB0, 0x01, 0x06, 0x00, 0xD5, 0xE1, 0x2B, 0xED, 0xB0, 0x21, 0xE8, 0xFF, 0x39, 0xE5, - 0x23, 0x23, 0x22, 0x06, 0x00, 0x16, 0x0A, 0xC5, 0x15, 0x20, 0xFC, 0xCD, 0x59, 0xF5, 0xCD, 0x9F, - 0xF4, 0xCD, 0x94, 0xF6, 0x21, 0x90, 0xF4, 0xCD, 0x95, 0xF6, 0x18, 0x43, 0x06, 0x01, 0x21, 0x00, - 0x00, 0x18, 0x0C, 0x10, 0x79, 0x20, 0x32, 0x05, 0xC8, 0x21, 0x00, 0x00, 0xCD, 0x7B, 0xF3, 0x4F, - 0xCD, 0xB0, 0xF3, 0x38, 0x08, 0x29, 0x29, 0x29, 0x29, 0xB5, 0x6F, 0x18, 0xEF, 0xE3, 0xE5, 0x79, - 0xCD, 0xC3, 0xF3, 0x30, 0xE0, 0x10, 0x12, 0xC9, 0xCD, 0x7B, 0xF3, 0x21, 0x6E, 0xF1, 0x11, 0x05, - 0x00, 0x06, 0x04, 0xBE, 0x28, 0x42, 0x19, 0x10, 0xFA, 0x21, 0x8C, 0xF4, 0xCD, 0x98, 0xF6, 0x2A, - 0x06, 0x00, 0xF9, 0x21, 0x0F, 0xF1, 0xE5, 0x22, 0x01, 0x00, 0x3E, 0xC3, 0x32, 0x00, 0x00, 0xCD, - 0xA9, 0xF6, 0xCD, 0x78, 0xF3, 0xD6, 0x41, 0x38, 0xE0, 0xFE, 0x1A, 0x30, 0xDC, 0x87, 0x5F, 0x16, - 0x00, 0x06, 0x02, 0x21, 0x27, 0xF0, 0x19, 0x7E, 0x23, 0x66, 0x6F, 0xE9, 0xCD, 0x86, 0xF3, 0x71, - 0xCD, 0x8F, 0xF3, 0x30, 0xFA, 0xD1, 0x18, 0xC7, 0x50, 0x06, 0x04, 0xCD, 0x78, 0xF3, 0x23, 0xBE, - 0x20, 0x81, 0x68, 0x2D, 0x42, 0x26, 0x03, 0x05, 0x28, 0x04, 0x29, 0x29, 0x10, 0xFC, 0x3A, 0x03, - 0x00, 0xB4, 0xAC, 0xB5, 0x4F, 0x79, 0x32, 0x03, 0x00, 0xC9, 0x3A, 0x03, 0x00, 0xC9, 0x4C, 0x32, - 0x31, 0x4C, 0x54, 0x50, 0x32, 0x31, 0x50, 0x54, 0x52, 0x32, 0x31, 0x50, 0x54, 0x43, 0x31, 0x42, - 0x43, 0x54, 0x06, 0x02, 0xCD, 0x8F, 0xF6, 0xFE, 0x07, 0x20, 0xF7, 0xCD, 0x7E, 0xF3, 0x10, 0xF4, - 0xC9, 0xCD, 0x86, 0xF3, 0x0A, 0xC5, 0x46, 0xB8, 0x28, 0x0C, 0xF5, 0xCD, 0xFB, 0xF5, 0x78, 0xCD, - 0xF4, 0xF5, 0xF1, 0xCD, 0xE6, 0xF5, 0xC1, 0xCD, 0x9B, 0xF3, 0x18, 0xE8, 0xCD, 0xA4, 0xF6, 0xCD, - 0xFB, 0xF5, 0x7D, 0xCD, 0xF0, 0xF1, 0xE5, 0x7E, 0xCD, 0xE6, 0xF5, 0xCD, 0x8F, 0xF3, 0x38, 0x2A, - 0xCD, 0xFE, 0xF5, 0x7D, 0xE6, 0x0F, 0x20, 0xEF, 0xE1, 0x7D, 0xE6, 0x0F, 0xCD, 0xF5, 0xF1, 0x7E, - 0xE6, 0x7F, 0x4F, 0xFE, 0x20, 0x38, 0x04, 0xFE, 0x7E, 0x38, 0x02, 0x0E, 0x2E, 0xCD, 0x09, 0xF0, - 0xCD, 0x9C, 0xF3, 0x7D, 0xE6, 0x0F, 0x20, 0xE7, 0x18, 0xC5, 0x93, 0xCD, 0xF0, 0xF1, 0x18, 0xD8, - 0xE6, 0x0F, 0x47, 0x87, 0x80, 0x47, 0x04, 0xCD, 0xFE, 0xF5, 0x10, 0xFB, 0xC9, 0xCD, 0xC0, 0xF3, - 0x38, 0x37, 0x28, 0x10, 0xCD, 0xCC, 0xF0, 0xD1, 0x21, 0x34, 0x00, 0x39, 0x72, 0x2B, 0x73, 0x79, - 0xFE, 0x0D, 0x28, 0x25, 0x06, 0x02, 0x21, 0x35, 0x00, 0x39, 0xC5, 0xE5, 0x06, 0x02, 0xCD, 0xD7, - 0xF0, 0xD1, 0xE1, 0x7A, 0xB3, 0x28, 0x0A, 0x73, 0x23, 0x72, 0x23, 0x1A, 0x77, 0x23, 0x3E, 0xCF, - 0x12, 0x79, 0xFE, 0x0D, 0xC1, 0x28, 0x02, 0x10, 0xE1, 0xCD, 0xA9, 0xF6, 0xE1, 0x21, 0x43, 0xF4, - 0xE5, 0x21, 0xCF, 0xF3, 0x22, 0x09, 0x00, 0x21, 0x18, 0x00, 0x39, 0xD1, 0xE9, 0xCD, 0xD7, 0xF0, - 0xC1, 0xED, 0x58, 0x18, 0x51, 0xCD, 0xD9, 0xF0, 0xD1, 0xC1, 0xED, 0x59, 0xC9, 0xCD, 0x86, 0xF3, - 0x7E, 0x02, 0xCD, 0x9B, 0xF3, 0x18, 0xF9, 0xCD, 0xD7, 0xF0, 0xE1, 0x7E, 0xCD, 0xF4, 0xF5, 0xCD, - 0xC0, 0xF3, 0xD8, 0x28, 0x0F, 0xFE, 0x0A, 0x28, 0x0D, 0xE5, 0xCD, 0xCC, 0xF0, 0xD1, 0xE1, 0x73, - 0x79, 0xFE, 0x0D, 0xC8, 0x23, 0x23, 0x2B, 0x7D, 0xE6, 0x07, 0xCC, 0xFB, 0xF5, 0x18, 0xDC, 0xCD, - 0xA4, 0xF6, 0x7E, 0xF5, 0x2F, 0x77, 0xAE, 0xC4, 0xA1, 0xF2, 0xF1, 0x77, 0xCD, 0x9C, 0xF3, 0x18, - 0xF1, 0xD5, 0x5F, 0xCD, 0xFB, 0xF5, 0x06, 0x08, 0x7B, 0x07, 0x5F, 0x3E, 0x18, 0x17, 0x4F, 0xCD, - 0x09, 0xF0, 0x10, 0xF4, 0xD1, 0xC9, 0x23, 0x23, 0x34, 0xC8, 0xF2, 0xC1, 0xF2, 0xF6, 0x80, 0x18, - 0x02, 0xE6, 0x7F, 0x35, 0xBE, 0x20, 0xEF, 0xCD, 0xFE, 0xF5, 0xCD, 0x15, 0xF3, 0xCD, 0xF7, 0xF5, - 0xCD, 0xC0, 0xF3, 0xD8, 0x28, 0x12, 0xE5, 0xCD, 0xCC, 0xF0, 0xE1, 0x7D, 0x13, 0x12, 0xE3, 0x7E, - 0xE3, 0x07, 0x30, 0x03, 0x13, 0x7C, 0x12, 0xE1, 0x79, 0xFE, 0x0D, 0xC8, 0x21, 0x3D, 0xF3, 0xCD, - 0xC0, 0xF3, 0x38, 0x0B, 0x28, 0xF9, 0xFE, 0x27, 0x20, 0xBE, 0x21, 0x55, 0xF3, 0x18, 0xF0, 0x7E, - 0x4F, 0x3C, 0xC8, 0xFC, 0xA9, 0xF6, 0xCD, 0x09, 0xF0, 0xCD, 0xF7, 0xF5, 0xCD, 0x15, 0xF3, 0xCD, - 0xFE, 0xF5, 0x23, 0x18, 0xEA, 0x23, 0x7E, 0xE6, 0x3F, 0xC6, 0x02, 0xEB, 0x6F, 0x26, 0x00, 0x39, - 0xEB, 0x7E, 0x06, 0x01, 0x07, 0x30, 0x0E, 0x04, 0x07, 0x30, 0x0A, 0xE5, 0x1A, 0x67, 0x1B, 0x1A, - 0x6F, 0x7E, 0xE1, 0x10, 0x01, 0x1A, 0xCD, 0xE6, 0xF5, 0x1B, 0x10, 0xF9, 0xC9, 0xC1, 0x15, 0x42, - 0x13, 0x43, 0x12, 0x44, 0x11, 0x45, 0x10, 0x46, 0x14, 0x48, 0x31, 0x4C, 0x30, 0xCD, 0xF1, 0x50, - 0xB4, 0x53, 0x97, 0x49, 0x03, 0xC1, 0x09, 0x42, 0x0B, 0x43, 0x0A, 0x44, 0x0D, 0x45, 0x0C, 0x46, - 0x08, 0x48, 0x0F, 0x4C, 0x0E, 0xCD, 0xCF, 0x58, 0x87, 0x59, 0x85, 0x52, 0x02, 0xFF, 0xE6, 0x0F, - 0xC6, 0x90, 0x27, 0xCE, 0x40, 0x27, 0x4F, 0xC9, 0xCD, 0xF7, 0xF5, 0xCD, 0x8F, 0xF6, 0xC5, 0x4F, - 0xCD, 0x09, 0xF0, 0x79, 0xC1, 0xC9, 0x04, 0xCD, 0xD9, 0xF0, 0xC1, 0xD1, 0xC3, 0xAA, 0xF6, 0x23, - 0x7C, 0xB5, 0x37, 0xC8, 0x7B, 0x95, 0x7A, 0x9C, 0xC9, 0xD1, 0xC9, 0x03, 0xCD, 0x8F, 0xF3, 0x38, - 0xF8, 0xCD, 0x12, 0xF0, 0xB7, 0xC8, 0xCD, 0x8F, 0xF6, 0xFE, 0x13, 0x20, 0xEC, 0xC3, 0x8F, 0xF6, - 0xD6, 0x30, 0xD8, 0xFE, 0x17, 0x3F, 0xD8, 0xFE, 0x0A, 0x3F, 0xD0, 0xD6, 0x07, 0xFE, 0x0A, 0xC9, - 0xCD, 0x7B, 0xF3, 0xFE, 0x20, 0xC8, 0xFE, 0x2C, 0xC8, 0xFE, 0x0D, 0x37, 0xC8, 0x3F, 0xC9, 0xE5, - 0xD5, 0xC5, 0xF5, 0xCD, 0x6F, 0xF0, 0xEB, 0x21, 0x0A, 0x00, 0x39, 0x06, 0x04, 0xEB, 0x2B, 0x72, - 0x2B, 0x73, 0xD1, 0x10, 0xF9, 0xC1, 0x0B, 0xF9, 0x21, 0x25, 0x00, 0x39, 0xD5, 0x16, 0x02, 0x7E, - 0x91, 0x23, 0x7E, 0x98, 0x28, 0x06, 0x23, 0x23, 0x15, 0x20, 0xF4, 0x03, 0x21, 0x20, 0x00, 0xD1, - 0x39, 0x73, 0x23, 0x72, 0xC5, 0x0E, 0x2A, 0xCD, 0x09, 0xF0, 0xD1, 0x3E, 0xF4, 0xBA, 0x28, 0x09, - 0x23, 0x23, 0x73, 0x23, 0x72, 0xEB, 0xCD, 0xE1, 0xF5, 0x21, 0x25, 0x00, 0x39, 0x01, 0x00, 0x02, - 0x5E, 0x71, 0x23, 0x56, 0x71, 0x23, 0x7B, 0xB2, 0x28, 0x02, 0x7E, 0x12, 0x23, 0x10, 0xF1, 0x08, - 0xD9, 0xE5, 0xD5, 0xC5, 0xF5, 0xDD, 0xE5, 0xFD, 0xE5, 0xED, 0x57, 0x47, 0xED, 0x5F, 0x4F, 0xC5, - 0xC3, 0x13, 0xF1, 0xE5, 0xCF, 0xC1, 0x79, 0xED, 0x4F, 0x78, 0xED, 0x47, 0xDD, 0xE1, 0xFD, 0xE1, - 0xF1, 0xC1, 0xD1, 0xE1, 0x08, 0xD9, 0xD1, 0xC1, 0xF1, 0xE1, 0xF9, 0x00, 0x21, 0x00, 0x00, 0xC3, - 0x00, 0x00, 0xAF, 0x32, 0x03, 0x00, 0x21, 0x6C, 0xF4, 0xC3, 0xB5, 0xF6, 0x49, 0x2F, 0x4F, 0x20, - 0x45, 0x52, 0xD2, 0x44, 0x53, 0x4B, 0x20, 0x45, 0x52, 0x52, 0x3A, 0x20, 0x55, 0xAD, 0x20, 0x54, - 0xAD, 0x20, 0x53, 0xAD, 0x20, 0x43, 0xAD, 0x20, 0x45, 0xAD, 0x0D, 0x8A, 0x3F, 0x3F, 0x3F, 0xBF, - 0x4D, 0x4F, 0x53, 0x53, 0x20, 0x56, 0x45, 0x52, 0x53, 0x20, 0x32, 0x2E, 0x32, 0x0D, 0x8A, 0x3E, - 0x0F, 0xD3, 0x24, 0x11, 0x40, 0x00, 0x62, 0x6A, 0xDB, 0x26, 0xA3, 0x28, 0xFB, 0xDB, 0x26, 0x23, - 0xA3, 0xA3, 0xC2, 0xAD, 0xF4, 0xE5, 0x29, 0x5C, 0x19, 0x19, 0xE5, 0x29, 0x29, 0xDB, 0x20, 0x2B, - 0x7D, 0xB4, 0xC2, 0xBD, 0xF4, 0xE1, 0x3E, 0x83, 0xD3, 0x23, 0x7C, 0xD3, 0x21, 0x7D, 0xD3, 0x20, - 0x3E, 0x03, 0xD3, 0x23, 0xAF, 0xD3, 0x21, 0xD3, 0x25, 0xCD, 0xCE, 0xF6, 0xE6, 0x7F, 0xFE, 0x0D, - 0xE1, 0xC8, 0x5D, 0x54, 0xCD, 0xEE, 0xF4, 0xCD, 0xEE, 0xF4, 0x19, 0xE5, 0x18, 0xD8, 0xB7, 0x7C, - 0x1F, 0x67, 0x7D, 0x1F, 0x6F, 0xC9, 0x3E, 0xAF, 0x32, 0x4B, 0x00, 0x21, 0x80, 0x00, 0x22, 0x49, - 0x00, 0xCD, 0xA4, 0xF6, 0xD5, 0x3A, 0x4B, 0x00, 0xB7, 0x20, 0x08, 0x22, 0x4C, 0x00, 0xCD, 0xEB, - 0xF6, 0x18, 0x03, 0xCD, 0xE7, 0xF6, 0xD1, 0x20, 0x67, 0x3A, 0x44, 0x00, 0x47, 0xDB, 0x31, 0xB7, - 0x20, 0x0B, 0x06, 0x1A, 0x3A, 0x4A, 0x00, 0xE6, 0x10, 0x20, 0x02, 0x06, 0x12, 0xE5, 0x21, 0x42, - 0x00, 0x7E, 0xB8, 0x38, 0x1B, 0x3A, 0x45, 0x00, 0xB7, 0x28, 0x0B, 0x3A, 0x43, 0x00, 0xFE, 0xD0, - 0x20, 0x04, 0x3E, 0x90, 0x18, 0x05, 0x3E, 0xD0, 0x2B, 0x34, 0x23, 0x32, 0x43, 0x00, 0x36, 0x00, - 0x34, 0xE1, 0x2B, 0xCD, 0x9C, 0xF3, 0xD5, 0x18, 0xAC, 0xDB, 0x34, 0xE6, 0x40, 0xC0, 0x21, 0x00, - 0x00, 0x22, 0x40, 0x00, 0x21, 0x01, 0xD0, 0x22, 0x42, 0x00, 0x21, 0x80, 0x00, 0x22, 0x49, 0x00, - 0xCD, 0xE7, 0xF6, 0x20, 0x0B, 0x3E, 0x02, 0x32, 0x42, 0x00, 0xCD, 0xE7, 0xF6, 0xCA, 0x80, 0x00, - 0x21, 0x73, 0xF4, 0xCD, 0x95, 0xF6, 0x3A, 0x40, 0x00, 0xCD, 0xA1, 0xF5, 0x3A, 0x41, 0x00, 0xCD, - 0xA1, 0xF5, 0x3A, 0x42, 0x00, 0xCD, 0xA1, 0xF5, 0x3A, 0x48, 0x00, 0xCD, 0xA1, 0xF5, 0x3A, 0x47, - 0x00, 0xCD, 0xE6, 0xF5, 0xC3, 0x98, 0xF6, 0xCD, 0x86, 0xF3, 0x7D, 0xB7, 0xFA, 0x09, 0xF1, 0xFE, - 0x04, 0xD2, 0x09, 0xF1, 0x32, 0x40, 0x00, 0x6B, 0x61, 0x22, 0x44, 0x00, 0xC9, 0xCD, 0x86, 0xF3, - 0x61, 0x22, 0x41, 0x00, 0x7B, 0xB7, 0x3E, 0xD0, 0x28, 0x02, 0x3E, 0x90, 0x32, 0x43, 0x00, 0xC9, - 0xCD, 0xA4, 0xF6, 0xE5, 0x19, 0xCD, 0xFB, 0xF5, 0xE1, 0xB7, 0xED, 0x52, 0x18, 0x03, 0xCD, 0xA9, - 0xF6, 0x7C, 0xCD, 0xE6, 0xF5, 0x7D, 0xF5, 0x0F, 0x0F, 0x0F, 0x0F, 0xCD, 0xEF, 0xF5, 0xF1, 0xCD, - 0x6E, 0xF3, 0x18, 0x0C, 0xCD, 0xE6, 0xF5, 0x0E, 0x2D, 0x18, 0x05, 0xCD, 0xDE, 0xF5, 0x0E, 0x20, - 0x3A, 0x03, 0x00, 0xE6, 0x03, 0xCA, 0xDE, 0xF6, 0xFE, 0x02, 0xFA, 0x62, 0xF4, 0xC2, 0x62, 0xF4, - 0x3A, 0x03, 0x00, 0xE6, 0xC0, 0xCA, 0xDE, 0xF6, 0xFE, 0x80, 0xFA, 0x62, 0xF4, 0xCA, 0x62, 0xF4, - 0xC3, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, 0x03, 0xCA, 0xC6, 0xF6, 0xFE, 0x02, 0xFA, 0x62, 0xF4, - 0xC2, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, 0x0C, 0xCA, 0xC6, 0xF6, 0xFE, 0x08, 0xFA, 0x62, 0xF4, - 0xCA, 0x62, 0xF4, 0xC3, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, 0x03, 0xCA, 0xCE, 0xF6, 0xFE, 0x02, - 0xFA, 0x62, 0xF4, 0xC2, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, 0x0C, 0xCA, 0xCE, 0xF6, 0xFE, 0x08, - 0xFA, 0x62, 0xF4, 0xCA, 0x62, 0xF4, 0xC3, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, 0xC0, 0xCA, 0xD6, - 0xF6, 0xFE, 0x80, 0xFA, 0x62, 0xF4, 0xCA, 0x62, 0xF4, 0xC3, 0x62, 0xF4, 0x3A, 0x03, 0x00, 0xE6, - 0x30, 0xCA, 0xDE, 0xF6, 0xFE, 0x20, 0xFA, 0x62, 0xF4, 0xCA, 0x62, 0xF4, 0xC3, 0x62, 0xF4, 0xCD, - 0x46, 0xF6, 0xE6, 0x7F, 0xC9, 0xCD, 0xA9, 0xF6, 0xC5, 0x4E, 0xCD, 0x00, 0xF6, 0x23, 0x79, 0x07, - 0x30, 0xF7, 0xC1, 0xC9, 0xCD, 0xD9, 0xF0, 0xD1, 0xE1, 0xE5, 0x21, 0xC2, 0xF6, 0xCD, 0x98, 0xF6, - 0xE1, 0xC9, 0x21, 0xBB, 0xF6, 0xCD, 0x95, 0xF6, 0xC3, 0x00, 0x00, 0x52, 0x53, 0x54, 0x20, 0x45, - 0x52, 0xD2, 0x0D, 0x0A, 0x00, 0x80, 0xDB, 0x25, 0xE6, 0x01, 0xC8, 0xC6, 0xFE, 0xC9, 0xDB, 0x25, - 0x1F, 0x30, 0xFB, 0xDB, 0x20, 0xC9, 0xDB, 0x25, 0xE6, 0x20, 0xC8, 0xC6, 0xBF, 0xC9, 0xCD, 0xD6, - 0xF6, 0x28, 0xFB, 0x79, 0xD3, 0x20, 0xC9, 0x22, 0x4C, 0x00, 0x3E, 0xAF, 0x32, 0x4B, 0x00, 0x06, - 0x0A, 0xC5, 0xCD, 0x3B, 0xF7, 0xCC, 0xFD, 0xF6, 0xC1, 0xC8, 0x10, 0xF5, 0xC9, 0x5F, 0x3A, 0x4B, - 0x00, 0xB7, 0x7B, 0x28, 0x10, 0x32, 0x48, 0x00, 0xD3, 0x30, 0xED, 0xB2, 0x15, 0x20, 0xFB, 0xCD, - 0x2E, 0xF7, 0xE6, 0x9C, 0xC9, 0xF6, 0x20, 0x32, 0x48, 0x00, 0xD3, 0x30, 0xED, 0xB3, 0x15, 0x20, - 0xFB, 0x18, 0x0B, 0x06, 0x08, 0x3A, 0x46, 0x00, 0xB0, 0x32, 0x48, 0x00, 0xD3, 0x30, 0xDB, 0x34, - 0x1F, 0x30, 0xFB, 0xDB, 0x30, 0x32, 0x47, 0x00, 0xE6, 0xFC, 0xC9, 0xCD, 0x8E, 0xF7, 0xC4, 0x23, - 0xF7, 0xF8, 0x3A, 0x42, 0x00, 0xD3, 0x32, 0xDB, 0x31, 0x4F, 0x3A, 0x41, 0x00, 0xB9, 0x28, 0x0C, - 0xD3, 0x33, 0x06, 0x1C, 0xCD, 0x25, 0xF7, 0xE6, 0x98, 0xC0, 0xDB, 0x31, 0xB7, 0x21, 0x40, 0x00, - 0x28, 0x03, 0x3A, 0x51, 0x00, 0x29, 0x3D, 0xF2, 0x65, 0xF7, 0xE5, 0x0E, 0x80, 0xCD, 0xC3, 0xF7, - 0xDB, 0x34, 0xE6, 0x20, 0x3E, 0x04, 0x28, 0x01, 0xAF, 0xC6, 0x88, 0x2A, 0x4C, 0x00, 0xD1, 0x43, - 0x15, 0x14, 0x20, 0x01, 0x14, 0x0E, 0x33, 0xBF, 0xC9, 0x06, 0x58, 0xCD, 0x25, 0xF7, 0x2A, 0x49, - 0x00, 0x7C, 0xBD, 0xC8, 0x0E, 0x80, 0xCD, 0xC3, 0xF7, 0xCD, 0x33, 0xF7, 0xF8, 0xE5, 0x21, 0x4E, - 0x00, 0x01, 0x33, 0x06, 0x16, 0x01, 0x3E, 0xC4, 0xCD, 0x05, 0xF7, 0xE1, 0x28, 0x08, 0x3E, 0x40, - 0xBE, 0xD8, 0xB6, 0x77, 0x18, 0xD8, 0xDB, 0x32, 0xD3, 0x31, 0xB7, 0x28, 0xCC, 0x7E, 0x32, 0x49, - 0x00, 0xAF, 0xC9, 0x21, 0x4A, 0x00, 0x7E, 0xB7, 0x20, 0x25, 0x3A, 0x40, 0x00, 0x47, 0x04, 0xAF, - 0x37, 0x17, 0x10, 0xFD, 0xF6, 0x20, 0x77, 0xD3, 0x34, 0x11, 0x46, 0x00, 0x3E, 0x03, 0x12, 0xCD, - 0x23, 0xF7, 0xF8, 0xDB, 0x04, 0x1F, 0x30, 0x07, 0x3E, 0x10, 0xB6, 0x77, 0x3E, 0x02, 0x12, 0xDB, - 0x31, 0xB7, 0x7E, 0x20, 0x02, 0xE6, 0xBF, 0xB1, 0xD3, 0x34, 0x3A, 0x43, 0x00, 0xD3, 0x04, 0xC9 -}; - -/* returns TRUE iff there exists a disk with 'property' */ -static int32 cromfdc_hasProperty(uint32 property) -{ - int32 i; - for (i = 0; i < CROMFDC_MAX_DRIVES; i++) - if (cromfdc_dev.units[i].flags & property) - return TRUE; - return FALSE; -} - -static uint8 motor_timeout = 0; - -/* Unit service routine */ -static t_stat cromfdc_svc (UNIT *uptr) -{ - if(cromfdc_info->motor_on == 1) { - motor_timeout ++; - if(motor_timeout == MOTOR_TO_LIMIT) { - cromfdc_info->motor_on = 0; - sim_debug(DRIVE_MSG, &cromfdc_dev, "CROMFDC: Motor OFF\n"); - } - } - - cromfdc_info->rtc ++; - - sim_debug(VERBOSE_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT " Timer IRQ\n", PCX); - cromfdc_info->ipend |= CROMFDC_IRQ_TIMER3; - -/* sim_activate (cromfdc_unit, cromfdc_unit->wait); */ /* requeue! */ - - return SCPE_OK; -} - - -/* Reset routine */ -static t_stat cromfdc_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect ROM and I/O Ports */ - if (cromfdc_hasProperty(UNIT_CROMFDC_ROM)) { - sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &cromfdcrom, TRUE); - } - /* Unmap I/O Ports (0x3-4,0x5-9,0x34,0x40 */ - sim_map_resource(0x03, 2, RESOURCE_TYPE_IO, &cromfdc_ext, TRUE); - sim_map_resource(0x05, 5, RESOURCE_TYPE_IO, &cromfdc_timer, TRUE); - sim_map_resource(0x34, 1, RESOURCE_TYPE_IO, &cromfdc_control, TRUE); - sim_map_resource(0x40, 1, RESOURCE_TYPE_IO, &cromfdc_banksel, TRUE); - if(crofdc_type == 50) { /* CCS2422 */ - sim_map_resource(0x26, 1, RESOURCE_TYPE_IO, &ccs2810_uart_status, TRUE); - } - } else { - /* Connect CROMFDC ROM at base address */ - if (cromfdc_hasProperty(UNIT_CROMFDC_ROM)) { - sim_debug(VERBOSE_MSG, &cromfdc_dev, "CROMFDC: ROM Enabled.\n"); - if(sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &cromfdcrom, FALSE) != 0) { - printf("%s: error mapping MEM resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } else - sim_debug(VERBOSE_MSG, &cromfdc_dev, "CROMFDC: ROM Disabled.\n"); - /* Connect CROMFDC Interrupt, and Aux Disk Registers */ - if(sim_map_resource(0x03, 0x02, RESOURCE_TYPE_IO, &cromfdc_ext, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - - /* Connect CROMFDC Timer Registers */ - if(sim_map_resource(0x05, 0x05, RESOURCE_TYPE_IO, &cromfdc_timer, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - - /* Connect CROMFDC Disk Flags and Control Register */ - if(sim_map_resource(0x34, 0x01, RESOURCE_TYPE_IO, &cromfdc_control, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - - /* Connect CROMFDC Bank Select Register */ - if(sim_map_resource(0x40, 0x1, RESOURCE_TYPE_IO, &cromfdc_banksel, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - - /* Connect CCS 2810 UART Status Register (needed by MOSS 2.2 Monitor */ - if(sim_map_resource(0x26, 0x01, RESOURCE_TYPE_IO, &ccs2810_uart_status, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x" NLP, __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } else { - sim_debug(VERBOSE_MSG, &cromfdc_dev, "Mapped CCS2810 UART Status at 0x26\n"); - } - - } - - cromfdc_info->rom_disabled = FALSE; -/* sim_activate (cromfdc_unit, cromfdc_unit->wait); */ /* requeue! */ - return SCPE_OK; -} - -static t_stat cromfdc_boot(int32 unitno, DEVICE *dptr) -{ - if((crofdc_type != 4) && (crofdc_type != 16) && (crofdc_type != 64) && (crofdc_type != 50)) { - printf("Invalid fdc_type: %d, must be 4, 16, or 64 (or 50 for CCS2422.)" NLP, crofdc_type); - return SCPE_ARG; - } - - bootstrap &= 0x01; - DBG_PRINT(("Booting %dFDC Controller, bootstrap=%d" NLP, crofdc_type, bootstrap)); - - /* Re-enable the ROM in case it was disabled */ - cromfdc_info->rom_disabled = FALSE; - - /* Set the PC to C000, and go. */ - *((int32 *) sim_PC->loc) = 0xC000; - return SCPE_OK; -} - -static int32 cromfdcrom(const int32 Addr, const int32 write, const int32 data) -{ -/* DBG_PRINT(("CROMFDC: ROM %s, Addr %04x" NLP, write ? "WR" : "RD", Addr)); */ - if(write) { - cromfdcram[Addr & CROMFDC_ADDR_MASK] = data; - return 0; - } else { - if(cromfdc_info->rom_disabled == FALSE) { - return(cromfdc_rom[bootstrap & 0x01][Addr & CROMFDC_ADDR_MASK]); - } else { - return(cromfdcram[Addr & CROMFDC_ADDR_MASK]); - } - } -} - -/* Disk Control/Flags Register, 0x34 / CCS2422 Control1/Status1 */ -static int32 cromfdc_control(const int32 port, const int32 io, const int32 data) -{ - int32 result = 0; - if(io) { /* I/O Write */ - switch(data & 0x0F) { - case 0: - wd179x_infop->sel_drive = 0xFF; - break; - case CROMFDC_CTRL_DS1: - wd179x_infop->sel_drive = 0; - break; - case CROMFDC_CTRL_DS2: - wd179x_infop->sel_drive = 1; - break; - case CROMFDC_CTRL_DS3: - wd179x_infop->sel_drive = 2; - break; - case CROMFDC_CTRL_DS4: - wd179x_infop->sel_drive = 3; - break; - default: - sim_debug(STATUS_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT " WR CTRL = 0x%02x: Invalid drive selected.\n", PCX, data & 0xFF); - break; - } - if(data & CROMFDC_CTRL_MAXI) { - wd179x_infop->drivetype = 8; - } else { - wd179x_infop->drivetype = 5; - } - - if(data & CROMFDC_CTRL_MTRON) { - cromfdc_info->motor_on = 1; - motor_timeout = 0; - } - - if(data & CROMFDC_CTRL_DDENS) { - if(crofdc_type == 4) { /* 4FDC */ - sim_debug(DRIVE_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT " WR CTRL: Cannot set double density on 4FDC\n", PCX); - } else { - wd179x_infop->ddens = 1; - } - } else { - wd179x_infop->ddens = 0; - } - if(data & CROMFDC_CTRL_AUTOWAIT) { - cromfdc_info->autowait = 1; - } else { - cromfdc_info->autowait = 0; - } - - sim_debug(DRIVE_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT " WR CTRL: sel_drive=%d, drivetype=%d, motor=%d, dens=%d, aw=%d\n", PCX, wd179x_infop->sel_drive, wd179x_infop->drivetype, cromfdc_info->motor_on, wd179x_infop->ddens, cromfdc_info->autowait); - } else { /* I/O Read */ - result = (crofdc_boot) ? 0 : CROMFDC_FLAG_BOOT; - result |= (wd179x_infop->intrq) ? CROMFDC_FLAG_EOJ : 0; - result |= (wd179x_infop->drq) ? CROMFDC_FLAG_DRQ : 0; - if(crofdc_type != 50) { /* Cromemco Controller */ - result |= (motor_timeout < MOTOR_TO_LIMIT) ? CROMFDC_FLAG_SEL_REQ : 0; - if(crofdc_type > 4) { /* 16, 64FDC */ - result |= (cromfdc_info->motor_on) ? CROMFDC_FLAG_MTRON : 0; - result |= (motor_timeout == MOTOR_TO_LIMIT) ? CROMFDC_FLAG_MTO : 0; - result |= (crofdc_inh_init) ? 0 : CROMFDC_FLAG_INH_INIT; - } else { - result |= 0x1E; /* Make unused bits '1' on 4FDC */ - } - } else { /* CCS 2422 Controller */ - switch(wd179x_infop->sel_drive) { - case 1: - result |= 0x02; - break; - case 2: - result |= 0x04; - break; - case 3: - result |= 0x08; - break; - case 4: - result |= 0x10; - break; - } - -/* printf("CCS2422FDC: " ADDRESS_FORMAT " Read STATUS1=0x%02x" NLP, PCX, result); */ - } - sim_debug(STATUS_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT - " Read DISK FLAGS, Port 0x%02x Result 0x%02x\n", PCX, port, result); - } - - return result; -} - -/* - * 64FDC Interrupt and Auxiliary Disk Status 0x03-04 - * For CCS2422, this is the Control2/Status2 Register (0x04 only) - */ -static int32 cromfdc_ext(const int32 port, const int32 io, const int32 data) -{ - int32 result; - if(io) { /* I/O Write */ - if(port == 0x4) { - if(crofdc_type != 50) { /* Cromemco Controller */ - if((data & CROMFDC_AUX_CMD_SIDE) == 0) { - if(crofdc_type == 4) { /* 4FDC */ - sim_debug(DRIVE_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT " WR CTRL: Cannot set side 1 on 4FDC\n", PCX); - } else { - wd179x_infop->fdc_head = 1; - } - } else { - wd179x_infop->fdc_head = 0; - } -#if 0 /* hharte - nothing implemented for these */ - if((data & CROMFDC_AUX_EJECT) == 0) { - printf("CROMFDC: Eject" NLP); - } - if((data & CROMFDC_AUX_SEL_OVERRIDE) == 0) { - printf("CROMFDC: Sel Override" NLP); - } - if((data & CROMFDC_AUX_CTRL_OUT) == 0) { - printf("CROMFDC: Ctrl Out" NLP); - } -#endif /* 0 */ - if(crofdc_type < 64) { - if((data & CROMFDC_AUX_RESTORE) == 0) { - wd179x_external_restore(); - } - } - } else { /* CCS 2422 Controller */ - if((data & CCSFDC_CMD_SIDE) == 0) { - wd179x_infop->fdc_head = 1; - } else { - wd179x_infop->fdc_head = 0; - } - - } - } else if (port == 0x3) { /* Interrupt Address */ - sim_debug(IRQ_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT " IRQ Mask=0x%02x\n", PCX, data); - cromfdc_info->imask = data; - } else { - } - - sim_debug(DRIVE_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT - " AUX OUT, Port 0x%02x Data 0x%02x\n", PCX, port, data); - result = 0; - } else { /* I/O Read */ - if(port == 0x4) { - result = dipswitch & 0x1F; - result |= 0x00; /* Bit 6 is Seek in Progress for Persci drives. */ - result |= (cromfdc_info->rtc & 1) ? 0x80 : 0; - if(crofdc_type == 50) { - sim_debug(STATUS_MSG, &cromfdc_dev, "CCS2422FDC: " ADDRESS_FORMAT " Read STATUS2=0x%02x\n", PCX, result); - } - } else if (port == 0x3) { /* Interrupt Address */ - result = ipend_to_rst_opcode(cromfdc_info->ipend); - if(result != 0) { - sim_debug(IRQ_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT " RST Opcode=%x, Vector=%04x\n", PCX, result, RST_OPCODE_TO_VECTOR(result)); - } - } else { - result = 0xFF; - } - sim_debug(STATUS_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT - " AUX IN, Port 0x%02x Result 0x%02x\n", PCX, port, result); - } - return result; -} - -/* 64FDC Timer registers */ -static int32 cromfdc_timer(const int32 port, const int32 io, const int32 data) -{ - static int32 result = 0; - if(io) { - sim_debug(VERBOSE_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT - " TIMER%d OUT, Port 0x%02x Data 0x%02x\n", PCX, (port-4), port, data); - result = 0; - sim_activate(cromfdc_unit, (CROMFDC_SIM_64US * data)); - } else { - result++; - sim_debug(VERBOSE_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT - " TIMER%d IN, Port 0x%02x Result 0x%02x\n", PCX, (port-4), port, result); - } - return result; -} - -/* 64FDC Bank Select (Write Disables boot ROM) */ -static int32 cromfdc_banksel(const int32 port, const int32 io, const int32 data) -{ - int32 result; - if(io) { - sim_debug(VERBOSE_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT - " BANKSEL OUT, Port 0x%02x Data 0x%02x\n", PCX, port, data); - /* Unmap Boot ROM */ - cromfdc_info->rom_disabled = TRUE; - result = 0; - } else { - result = 0xFF; - sim_debug(VERBOSE_MSG, &cromfdc_dev, "CROMFDC: " ADDRESS_FORMAT - " BANKSEL IN, Port 0x%02x Result 0x%02x\n", PCX, port, result); - } - return result; -} - -static uint8 ccs2810_uart_status_reg = 0x00; - -/* CCS 2810 UART Status Register, needed by MOSS 2.2 Monitor */ -static int32 ccs2810_uart_status(const int32 port, const int32 io, const int32 data) -{ - if(io) { /* I/O Write */ - return (0x00); - } else { /* I/O Read */ - ccs2810_uart_status_reg = ~ccs2810_uart_status_reg; - return (ccs2810_uart_status_reg); - } -} diff --git a/AltairZ80/s100_adcs6.c b/AltairZ80/s100_adcs6.c deleted file mode 100644 index 353b92e6..00000000 --- a/AltairZ80/s100_adcs6.c +++ /dev/null @@ -1,711 +0,0 @@ -/************************************************************************* - * * - * $Id: s100_adcs6.c 1970 2008-06-26 06:01:27Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Advanced Digital Corporation (ADC) Super-Six CPU Board * - * module for SIMH. * - * * - * This module is a wrapper around the wd179x FDC module, and adds the * - * ADC-specific registers as well as the Digitex Monitor Boot ROM. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/*#define DBG_MSG */ -#define DBG_MSG -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#include "sim_defs.h" /* simulator definitions */ -#include "wd179x.h" - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define STATUS_MSG (1 << 5) -#define DRIVE_MSG (1 << 6) -#define VERBOSE_MSG (1 << 7) -#define IRQ_MSG (1 << 8) -#define DMA_MSG (1 << 9) - -#define ADCS6_MAX_DRIVES 4 -#define ADCS6_ROM_SIZE (2 * 1024) -#define ADCS6_ADDR_MASK (ADCS6_ROM_SIZE - 1) - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint32 dma_addr; /* DMA Transfer Address */ - uint8 rom_disabled; /* TRUE if ROM has been disabled */ - uint8 head_sel; - uint8 autowait; - uint8 rtc; - uint8 imask; /* Interrupt Mask Register */ - uint8 ipend; /* Interrupt Pending Register */ - uint8 s100_addr_u; /* A23:16 of S-100 bus */ -} ADCS6_INFO; - -extern WD179X_INFO_PUB *wd179x_infop; - -static ADCS6_INFO adcs6_info_data = { { 0xF000, ADCS6_ROM_SIZE, 0x3, 2 } }; -static ADCS6_INFO *adcs6_info = &adcs6_info_data; - -extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); - -static t_stat adcs6_svc (UNIT *uptr); - -extern REG *sim_PC; -extern uint32 PCX; /* external view of PC */ - -#define UNIT_V_ADCS6_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_ADCS6_WLK (1 << UNIT_V_ADCS6_WLK) -#define UNIT_V_ADCS6_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_ADCS6_VERBOSE (1 << UNIT_V_ADCS6_VERBOSE) -#define UNIT_V_ADCS6_ROM (UNIT_V_UF + 2) /* boot ROM enabled */ -#define UNIT_ADCS6_ROM (1 << UNIT_V_ADCS6_ROM) -#define ADCS6_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ - -#define MOTOR_TO_LIMIT 128 - -static t_stat adcs6_reset(DEVICE *adcs6_dev); -static t_stat adcs6_boot(int32 unitno, DEVICE *dptr); -static t_stat adcs6_attach(UNIT *uptr, char *cptr); -static t_stat adcs6_detach(UNIT *uptr); - -static int32 adcs6_dma(const int32 port, const int32 io, const int32 data); -static int32 adcs6_timer(const int32 port, const int32 io, const int32 data); -static int32 adcs6_control(const int32 port, const int32 io, const int32 data); -static int32 adcs6_banksel(const int32 port, const int32 io, const int32 data); -static int32 adcs6rom(const int32 port, const int32 io, const int32 data); - -static int32 dipswitch = 0x00; /* 5-position DIP switch on 64FDC card */ - -/* Disk Control/Flags Register, 0x34 (IN) */ -#define ADCS6_FLAG_DRQ (1 << 7) /* DRQ (All controllers) */ -#define ADCS6_FLAG_BOOT (1 << 6) /* boot# jumper (active low) (All controllers) */ -#define ADCS6_FLAG_SEL_REQ (1 << 5) /* Head Load (4FDC, 16FDC) / Select Request (64FDC) */ -#define ADCS6_FLAG_INH_INIT (1 << 4) /* Unassigned (4FDC) / Inhibit_Init# (16FDC, 64FDC) */ -#define ADCS6_FLAG_MTRON (1 << 3) /* Unassigned (4FDC) / Motor On (16FDC, 64FDC) */ -#define ADCS6_FLAG_MTO (1 << 2) /* Unassigned (4FDC) / Motor Timeout (16FDC, 64FDC) */ -#define ADCS6_FLAG_ATO (1 << 1) /* Unassigned (4FDC) / Autowait Timeout (16FDC, 64FDC) */ -#define ADCS6_FLAG_EOJ (1 << 0) /* End of Job (INTRQ) (All Controllers) (16FDC, 64FDC) */ - -/* Disk Control/Flags Register, 0x34 (OUT) */ -#define ADCS6_CTRL_AUTOWAIT (1 << 7) /* Auto Wait Enable (All controllers) */ -#define ADCS6_CTRL_DDENS (1 << 3) /* Unassigned (4FDC) / Double Density (16FDC, 64FDC) */ -#define ADCS6_CTRL_HDS (1 << 2) /* Motor On (All controllers) */ -#define ADCS6_CTRL_MINI (1 << 4) /* Mini (5.25") (All controllers) */ - -/* 64FDC Auxiliary Disk Command, 0x04 (OUT) */ -#define ADCS6_AUX_RESERVED0 (1 << 0) /* Unused (All Controllers) */ -#define ADCS6_AUX_CMD_SIDE (1 << 1) /* 16FDC, 64FDC: Side Select* Low=Side 1, High=Side 0. */ -#define ADCS6_AUX_CTRL_OUT (1 << 2) /* Control Out* (All Controllers) */ -#define ADCS6_AUX_RESTORE (1 << 3) /* 4FDC, 16FDC Restore* / 64FDC Unused */ -#define ADCS6_AUX_FAST_SEEK (1 << 4) /* 4FDC, 16FDC Fast Seek* / 64FDC Unused */ -#define ADCS6_AUX_SEL_OVERRIDE (1 << 5) /* 4FDC Eject Right* / 16FDC, 64FDC Drive Select Override */ -#define ADCS6_AUX_EJECT (1 << 6) /* 4FDC Eject Left* / 16FDC Eject*, 64FDC Unused */ -#define ADCS6_AUX_RESERVED7 (1 << 7) /* Unused (All Controllers) */ - -/* 64FDC Interrupt Mask Register, 0x03 (OUT) */ -#define ADCS6_IRQ_TIMER1 (1 << 0) /* Timer1 Interrupt Mask */ -#define ADCS6_IRQ_TIMER2 (1 << 1) /* Timer2 Interrupt Mask */ -#define ADCS6_IRQ_EOJ (1 << 2) /* End of Job Interrupt Mask */ -#define ADCS6_IRQ_TIMER3 (1 << 3) /* Timer3 Interrupt Mask */ -#define ADCS6_IRQ_RDA (1 << 4) /* Read Data Available Interrupt Mask */ -#define ADCS6_IRQ_TBE (1 << 5) /* Transmit Buffer Empty Interrupt Mask */ -#define ADCS6_IRQ_TIMER4 (1 << 6) /* Timer4 Interrupt Mask */ -#define ADCS6_IRQ_TIMER5 (1 << 7) /* Timer5 Interrupt Mask */ - -#define ADCS6_TIMER1_RST 0xC7 /* RST0 - 0xC7 */ -#define ADCS6_TIMER2_RST 0xCF /* RST8 - 0xCF */ -#define ADCS6_EOJ_RST 0xD7 /* RST10 - 0xD7 */ -#define ADCS6_TIMER3_RST 0xDF /* RST18 - 0xDF */ -#define ADCS6_RDA_RST 0xE7 /* RST20 - 0xE7 */ -#define ADCS6_TBE_RST 0xEF /* RST28 - 0xEF */ -#define ADCS6_TIMER4_RST 0xF7 /* RST30 - 0xF7 */ -#define ADCS6_TIMER5_RST 0xFF /* RST38 - 0xFF */ - -#define RST_OPCODE_TO_VECTOR(x) (x & 0x38) - -/* The ADCS6 does not really have RAM associated with it, but for ease of integration with the - * SIMH/AltairZ80 Resource Mapping Scheme, rather than Map and Unmap the ROM, simply implement our - * own RAM that can be swapped in when the ADCS6 Boot ROM is disabled. - */ -static uint8 adcs6ram[ADCS6_ROM_SIZE]; - -static UNIT adcs6_unit[] = { - { UDATA (&adcs6_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE + UNIT_ADCS6_ROM, ADCS6_CAPACITY), 1024 }, - { UDATA (&adcs6_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, ADCS6_CAPACITY) }, - { UDATA (&adcs6_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, ADCS6_CAPACITY) }, - { UDATA (&adcs6_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, ADCS6_CAPACITY) } -}; - -static REG adcs6_reg[] = { - { HRDATA (J7, dipswitch, 8), }, - { NULL } -}; - -static MTAB adcs6_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_ADCS6_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_ADCS6_WLK, UNIT_ADCS6_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_ADCS6_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_ADCS6_VERBOSE, UNIT_ADCS6_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { UNIT_ADCS6_ROM, 0, "NOROM", "NOROM", NULL }, - { UNIT_ADCS6_ROM, UNIT_ADCS6_ROM, "ROM", "ROM", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB adcs6_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "CMD", CMD_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "STATUS", STATUS_MSG }, - { "DRIVE", DRIVE_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { "IRQ", IRQ_MSG }, - { "DMA", DMA_MSG }, - { NULL, 0 } -}; - -DEVICE adcs6_dev = { - "ADCS6", adcs6_unit, adcs6_reg, adcs6_mod, - ADCS6_MAX_DRIVES, 10, 31, 1, ADCS6_MAX_DRIVES, ADCS6_MAX_DRIVES, - NULL, NULL, &adcs6_reset, - &adcs6_boot, &adcs6_attach, &adcs6_detach, - &adcs6_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - adcs6_dt, NULL, "ADC Super-Six ADCS6" -}; - -/* This is the DIGITEX Monitor version 1.2.A -- 10/06/83 - * - * MONITOR COMMANDS : - * B = LOAD DISK BOOT LOADER - * DSSSS,QQQQ = DUMP MEMORY IN HEX FROM S TO Q - * FSSSS,QQQQ,BB = FILL MEMORY FROM S TO Q WITH B - * GAAAA = GO TO ADDRESS A - * IPP = INPUT FROM PORT P - * LAAAA = LOAD MEMORY STARTING AT A - * MSSSS,QQQQ,DDDD = MOVE STARTING AT S TO Q TO ADDR. D - * OPP,DD = OUTPUT DATA D TO PORT P - * ESC WILL TERMINATE ANY COMMAND - */ -static uint8 adcs6_rom[ADCS6_ROM_SIZE] = { - 0xC3, 0x3C, 0xF0, 0xC3, 0xA4, 0xF0, 0xC3, 0xB6, 0xF0, 0xC3, 0xAF, 0xF0, 0xC3, 0xC9, 0xF0, 0xC3, - 0xE1, 0xF0, 0xC3, 0xF0, 0xF0, 0xC3, 0x06, 0xF1, 0xC3, 0x14, 0xF1, 0xC3, 0x0B, 0xF1, 0xC3, 0x22, - 0xF1, 0xC3, 0x2D, 0xF1, 0xC3, 0x4A, 0xF1, 0xC3, 0x77, 0xF1, 0xC3, 0xA1, 0xF1, 0xC3, 0xFA, 0xF1, - 0xC3, 0xBC, 0xF3, 0xC3, 0x53, 0xF3, 0xC3, 0x8E, 0xF2, 0xC3, 0xA0, 0xF2, 0xDB, 0x15, 0xD3, 0x18, - 0xCB, 0x77, 0x28, 0x10, 0xAF, 0xD3, 0x15, 0xD3, 0x40, 0xD3, 0x17, 0x3E, 0x40, 0xD3, 0x16, 0x21, - 0x3E, 0x60, 0x18, 0x0A, 0xAF, 0xD3, 0x17, 0x3E, 0x4F, 0xD3, 0x16, 0x21, 0x3E, 0x6F, 0x22, 0x04, - 0xEE, 0xAF, 0x32, 0x01, 0xEE, 0x31, 0x64, 0xEE, 0x21, 0xCA, 0xF3, 0x01, 0x01, 0x08, 0xED, 0xB3, - 0x21, 0xD2, 0xF3, 0xCD, 0xE1, 0xF0, 0xC3, 0xB2, 0xF2, 0x31, 0x64, 0xEE, 0x21, 0x4D, 0xF4, 0xCD, - 0xE1, 0xF0, 0xCD, 0xC9, 0xF0, 0x47, 0x21, 0xAF, 0xF6, 0x7E, 0xFE, 0xFF, 0x28, 0x08, 0xB8, 0x28, - 0x0D, 0x23, 0x23, 0x23, 0x18, 0xF3, 0x21, 0x52, 0xF4, 0xCD, 0xE1, 0xF0, 0x18, 0xDB, 0x23, 0x5E, - 0x23, 0x56, 0xEB, 0xE9, 0xF5, 0xDB, 0x01, 0xE6, 0x04, 0x28, 0xFA, 0xF1, 0xD3, 0x00, 0xC9, 0xDB, - 0x01, 0xE6, 0x01, 0xC8, 0x18, 0x06, 0xDB, 0x01, 0xE6, 0x01, 0x28, 0xFA, 0xDB, 0x00, 0xE6, 0x7F, - 0xFE, 0x61, 0xD8, 0xFE, 0x7B, 0xD0, 0xE6, 0x5F, 0xC9, 0x3E, 0xFF, 0x32, 0x00, 0xEE, 0xCD, 0xB6, - 0xF0, 0xF5, 0x3A, 0x00, 0xEE, 0xA7, 0x20, 0x02, 0xF1, 0xC9, 0xF1, 0xFE, 0x20, 0xD4, 0xA4, 0xF0, - 0xC9, 0xF5, 0xE5, 0x7E, 0xB7, 0x28, 0x06, 0xCD, 0xA4, 0xF0, 0x23, 0x18, 0xF6, 0xE1, 0xF1, 0xC9, - 0xE5, 0x21, 0x14, 0xF5, 0xCD, 0xE1, 0xF0, 0xE1, 0xC9, 0xCD, 0xAF, 0xF0, 0xFE, 0x1B, 0xCA, 0x79, - 0xF0, 0xFE, 0x08, 0xD0, 0x18, 0xF3, 0xF5, 0x3E, 0x20, 0x18, 0x12, 0xF5, 0x0F, 0x0F, 0x0F, 0x0F, - 0xCD, 0x14, 0xF1, 0xF1, 0xF5, 0xE6, 0x0F, 0xC6, 0x90, 0x27, 0xCE, 0x40, 0x27, 0xCD, 0xA4, 0xF0, - 0xF1, 0xC9, 0xF5, 0x7C, 0xCD, 0x0B, 0xF1, 0x7D, 0xCD, 0x0B, 0xF1, 0xF1, 0xC9, 0xCD, 0xC9, 0xF0, - 0xFE, 0x2C, 0xC8, 0xFE, 0x20, 0xC8, 0xFE, 0x30, 0xD8, 0xFE, 0x3A, 0xDA, 0x47, 0xF1, 0xFE, 0x41, - 0xD8, 0xFE, 0x47, 0x3F, 0xD8, 0xD6, 0x07, 0xD6, 0x30, 0xC9, 0xC5, 0xD5, 0x0E, 0x00, 0x1E, 0x00, - 0xCD, 0x2D, 0xF1, 0x30, 0x0E, 0xFE, 0x0D, 0x37, 0x20, 0x1A, 0x7B, 0xB7, 0x20, 0x15, 0x37, 0x3E, - 0x0D, 0x18, 0x11, 0xFE, 0x10, 0x30, 0x0C, 0x1C, 0x47, 0x79, 0x87, 0x87, 0x87, 0x87, 0x80, 0x4F, - 0xC3, 0x50, 0xF1, 0x79, 0xD1, 0xC1, 0xC9, 0xD5, 0x21, 0x00, 0x00, 0x37, 0x3F, 0xF5, 0xCD, 0x2D, - 0xF1, 0x30, 0x0D, 0xFE, 0x0D, 0x20, 0x05, 0xCD, 0x06, 0xF1, 0x18, 0x12, 0xF1, 0x37, 0xD1, 0xC9, - 0xFE, 0x10, 0x30, 0x0A, 0x29, 0x29, 0x29, 0x29, 0x5F, 0x16, 0x00, 0x19, 0x18, 0xE0, 0xF1, 0xD1, - 0xC9, 0x77, 0xBE, 0xC8, 0xE5, 0x21, 0x63, 0xF4, 0xCD, 0xE1, 0xF0, 0xE1, 0xCD, 0x22, 0xF1, 0xC3, - 0x79, 0xF0, 0xCD, 0x77, 0xF1, 0xD2, 0xBE, 0xF1, 0x21, 0x5D, 0xF4, 0xC3, 0x99, 0xF0, 0x22, 0x02, - 0xEE, 0xCD, 0xF0, 0xF0, 0x2A, 0x02, 0xEE, 0xCD, 0x22, 0xF1, 0xCD, 0x06, 0xF1, 0x7E, 0xCD, 0x0B, - 0xF1, 0xCD, 0x06, 0xF1, 0xCD, 0x4A, 0xF1, 0xDA, 0xE4, 0xF1, 0xCD, 0xA1, 0xF1, 0x2A, 0x02, 0xEE, - 0x23, 0xC3, 0xBE, 0xF1, 0xFE, 0x0D, 0xCA, 0x79, 0xF0, 0xFE, 0x20, 0xCA, 0xDD, 0xF1, 0xFE, 0x2D, - 0xC2, 0xB8, 0xF1, 0x2A, 0x02, 0xEE, 0x2B, 0xC3, 0xBE, 0xF1, 0xF5, 0x7A, 0x2F, 0x57, 0x7B, 0x2F, - 0x5F, 0x13, 0xF1, 0xC9, 0xCD, 0x7E, 0xF2, 0xCD, 0x7E, 0xF2, 0xCD, 0xFA, 0xF1, 0xCD, 0xF0, 0xF0, - 0xCD, 0x22, 0xF1, 0xCD, 0x06, 0xF1, 0xCD, 0x06, 0xF1, 0x7E, 0xCD, 0x0B, 0xF1, 0xCD, 0x3F, 0xF2, - 0xCD, 0x86, 0xF2, 0xFE, 0x13, 0xCC, 0xF9, 0xF0, 0x7D, 0xE6, 0x0F, 0xCA, 0x0D, 0xF2, 0xC3, 0x16, - 0xF2, 0xCD, 0x7E, 0xF2, 0xEB, 0xE9, 0x21, 0x17, 0xF5, 0xCD, 0xE1, 0xF0, 0xC3, 0x79, 0xF0, 0xE5, - 0x19, 0xDA, 0x79, 0xF0, 0xE1, 0x23, 0xC9, 0xCD, 0x7E, 0xF2, 0xD5, 0xCD, 0x7E, 0xF2, 0xCD, 0x7E, - 0xF2, 0xEB, 0xE3, 0x8D, 0xFA, 0xF1, 0x7E, 0xE3, 0xCD, 0xA1, 0xF1, 0x23, 0xE3, 0xCD, 0x3F, 0xF2, - 0xCD, 0x86, 0xF2, 0xC3, 0x56, 0xF2, 0xCD, 0x7E, 0xF2, 0xCD, 0x7E, 0xF2, 0xCD, 0xFA, 0xF1, 0xCD, - 0x4A, 0xF1, 0xDA, 0xB8, 0xF1, 0xCD, 0xA1, 0xF1, 0xCD, 0x3F, 0xF2, 0xC3, 0x75, 0xF2, 0xCD, 0x77, - 0xF1, 0xDA, 0xB8, 0xF1, 0xEB, 0xC9, 0xCD, 0xAF, 0xF0, 0xB7, 0xC2, 0x79, 0xF0, 0xC9, 0xCD, 0x4A, - 0xF1, 0xDA, 0xB8, 0xF1, 0x4F, 0xED, 0x78, 0xCD, 0xF0, 0xF0, 0xCD, 0x0B, 0xF1, 0xC3, 0x79, 0xF0, - 0xCD, 0x4A, 0xF1, 0xDA, 0xB8, 0xF1, 0x4F, 0xCD, 0x4A, 0xF1, 0xDA, 0xB8, 0xF1, 0xED, 0x79, 0xC3, - 0x79, 0xF0, 0xCD, 0x86, 0xF2, 0xCD, 0xC6, 0xF2, 0xCD, 0x6F, 0xF3, 0xCD, 0x86, 0xF2, 0xCD, 0xE8, - 0xF2, 0xCD, 0x8F, 0xF3, 0x18, 0xF5, 0xDB, 0x15, 0x47, 0x3E, 0x18, 0xCB, 0x60, 0x20, 0x01, 0xAF, - 0x32, 0x06, 0xEE, 0xD3, 0x14, 0x3E, 0x0B, 0xD3, 0x0C, 0x00, 0xDB, 0x14, 0xDB, 0x0C, 0xE6, 0x80, - 0xC8, 0xAF, 0x32, 0x06, 0xEE, 0xD3, 0x14, 0xC9, 0xDB, 0x0C, 0x17, 0xD8, 0x21, 0xE8, 0x03, 0xDB, - 0x0C, 0xE6, 0x02, 0x28, 0x06, 0x2B, 0x7D, 0xB4, 0x20, 0xF5, 0xC9, 0x06, 0x0A, 0x21, 0x80, 0x3E, - 0xDB, 0x0C, 0xE6, 0x02, 0x20, 0x08, 0x2B, 0x7D, 0xB4, 0x20, 0xF5, 0x10, 0xF0, 0xC9, 0x3E, 0xFF, - 0x32, 0x01, 0xEE, 0x3E, 0x01, 0x21, 0x00, 0xC0, 0x32, 0x08, 0xEE, 0xD3, 0x0E, 0x3E, 0x8C, 0xD3, - 0x0C, 0x00, 0xDB, 0x14, 0xB7, 0xF2, 0x2E, 0xF3, 0xDB, 0x0F, 0x77, 0x23, 0x18, 0xF4, 0xDB, 0x0C, - 0xB7, 0x20, 0x19, 0x3A, 0x08, 0xEE, 0x3C, 0xFE, 0x04, 0x20, 0xDD, 0x2A, 0x04, 0xEE, 0x22, 0xFC, - 0xBF, 0x2A, 0x4A, 0xF3, 0x22, 0xFE, 0xBF, 0xC3, 0xFC, 0xBF, 0xD3, 0x16, 0xF5, 0x3A, 0x01, 0xEE, - 0xB7, 0x28, 0x0D, 0x21, 0xB8, 0xF4, 0xCD, 0xE1, 0xF0, 0xF1, 0xCD, 0x0B, 0xF1, 0xC3, 0x79, 0xF0, - 0xF1, 0x21, 0xD4, 0xF4, 0xCD, 0xE1, 0xF0, 0x3E, 0xFF, 0x32, 0x01, 0xEE, 0xC3, 0x79, 0xF0, 0xAF, - 0xD3, 0xE6, 0x3E, 0x08, 0xD3, 0xE6, 0x3E, 0x10, 0xD3, 0xE6, 0x3E, 0x18, 0xD3, 0xE6, 0xAF, 0xD3, - 0xE6, 0xD3, 0xE3, 0xD3, 0xE4, 0xD3, 0xE5, 0x3C, 0xD3, 0xE2, 0x3E, 0x70, 0xD3, 0xE7, 0xC9, 0xDB, - 0xE7, 0xE6, 0x50, 0xFE, 0x50, 0xC0, 0xDB, 0xE7, 0xB7, 0xF8, 0xAF, 0xD3, 0xE6, 0x3E, 0x20, 0xD3, - 0xE7, 0xDB, 0xE7, 0xB7, 0xFA, 0xA1, 0xF3, 0xE6, 0x01, 0x20, 0x11, 0x21, 0x00, 0x80, 0x01, 0xE0, - 0x00, 0xED, 0xB2, 0x2A, 0x04, 0xEE, 0x22, 0x00, 0x80, 0xC3, 0x00, 0x80, 0x21, 0xF4, 0xF4, 0xCD, - 0xE1, 0xF0, 0xDB, 0xE1, 0xCD, 0x0B, 0xF1, 0xC3, 0x79, 0xF0, 0x18, 0x04, 0x44, 0x03, 0xC1, 0x05, - 0xEA, 0x00, 0x0D, 0x0A, 0x0A, 0x0A, 0x44, 0x49, 0x47, 0x49, 0x54, 0x45, 0x58, 0x20, 0x4D, 0x6F, - 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x31, 0x2E, - 0x32, 0x2E, 0x41, 0x20, 0x2D, 0x2D, 0x20, 0x31, 0x30, 0x2F, 0x30, 0x36, 0x2F, 0x38, 0x33, 0x0D, - 0x0A, 0x0A, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x22, 0x48, 0x22, 0x20, 0x66, 0x6F, 0x72, 0x20, - 0x48, 0x65, 0x6C, 0x70, 0x0D, 0x0A, 0x0A, 0x41, 0x74, 0x74, 0x65, 0x6D, 0x70, 0x74, 0x69, 0x6E, - 0x67, 0x20, 0x74, 0x6F, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x2E, 0x2E, 0x2E, 0x0D, 0x0A, 0x50, 0x72, - 0x65, 0x73, 0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x61, - 0x62, 0x6F, 0x72, 0x74, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x2E, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x20, - 0x3E, 0x00, 0x20, 0x55, 0x4E, 0x44, 0x45, 0x46, 0x49, 0x4E, 0x45, 0x44, 0x00, 0x20, 0x3F, 0x3F, - 0x3F, 0x3F, 0x00, 0x0D, 0x0D, 0x0A, 0x4D, 0x45, 0x4D, 0x4F, 0x52, 0x59, 0x20, 0x57, 0x52, 0x49, - 0x54, 0x45, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x20, 0x41, 0x54, 0x20, 0x00, 0x45, 0x52, 0x52, - 0x4F, 0x52, 0x00, 0x20, 0x50, 0x41, 0x55, 0x53, 0x45, 0x00, 0x3F, 0x20, 0x00, 0x20, 0x41, 0x42, - 0x4F, 0x52, 0x54, 0x45, 0x44, 0x00, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4E, 0x47, 0x20, 0x41, - 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x3A, 0x00, 0x45, 0x4E, 0x44, 0x49, 0x4E, 0x47, 0x20, 0x41, - 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x3A, 0x00, 0x0D, 0x0A, 0x46, 0x44, 0x43, 0x20, 0x43, 0x4F, - 0x4C, 0x44, 0x20, 0x42, 0x4F, 0x4F, 0x54, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x20, 0x43, 0x4F, - 0x44, 0x45, 0x20, 0x00, 0x0D, 0x0A, 0x49, 0x4E, 0x53, 0x45, 0x52, 0x54, 0x20, 0x44, 0x49, 0x53, - 0x4B, 0x20, 0x26, 0x20, 0x50, 0x52, 0x45, 0x53, 0x53, 0x20, 0x42, 0x20, 0x54, 0x4F, 0x20, 0x42, - 0x4F, 0x4F, 0x54, 0x00, 0x0D, 0x0A, 0x48, 0x44, 0x43, 0x31, 0x30, 0x30, 0x31, 0x20, 0x43, 0x4F, - 0x4C, 0x44, 0x20, 0x42, 0x4F, 0x4F, 0x54, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x20, 0x43, 0x4F, - 0x44, 0x45, 0x20, 0x00, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x4D, 0x4F, 0x4E, 0x49, 0x54, 0x4F, 0x52, - 0x20, 0x43, 0x4F, 0x4D, 0x4D, 0x41, 0x4E, 0x44, 0x53, 0x20, 0x3A, 0x0D, 0x0A, 0xC2, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xBD, 0x20, 0x4C, - 0x4F, 0x41, 0x44, 0x20, 0x44, 0x49, 0x53, 0x4B, 0x20, 0x42, 0x4F, 0x4F, 0x54, 0x20, 0x4C, 0x4F, - 0x41, 0x44, 0x45, 0x52, 0x0D, 0x0A, 0x44, 0x53, 0x53, 0x53, 0x53, 0x2C, 0x51, 0x51, 0x51, 0x51, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x20, 0x44, 0x55, 0x4D, 0x50, 0x20, 0x4D, 0x45, 0x4D, - 0x4F, 0x52, 0x59, 0x20, 0x49, 0x4E, 0x20, 0x48, 0x45, 0x58, 0x20, 0x46, 0x52, 0x4F, 0x4D, 0x20, - 0x53, 0x20, 0x54, 0x4F, 0x20, 0x51, 0x0D, 0x0A, 0x46, 0x53, 0x53, 0x53, 0x53, 0x2C, 0x51, 0x51, - 0x51, 0x51, 0x2C, 0x42, 0x42, 0x20, 0x20, 0x20, 0x3D, 0x20, 0x46, 0x49, 0x4C, 0x4C, 0x20, 0x4D, - 0x45, 0x4D, 0x4F, 0x52, 0x59, 0x20, 0x46, 0x52, 0x4F, 0x4D, 0x20, 0x53, 0x20, 0x54, 0x4F, 0x20, - 0x51, 0x20, 0x57, 0x49, 0x54, 0x48, 0x20, 0x42, 0x0D, 0x0A, 0x47, 0x41, 0x41, 0x41, 0x41, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x20, 0x47, 0x4F, 0x20, 0x54, - 0x4F, 0x20, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x20, 0x41, 0x0D, 0x0A, 0x49, 0x50, 0x50, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x20, 0x49, - 0x4E, 0x50, 0x55, 0x54, 0x20, 0x46, 0x52, 0x4F, 0x4D, 0x20, 0x50, 0x4F, 0x52, 0x54, 0x20, 0x50, - 0x0D, 0x0A, 0x4C, 0x41, 0x41, 0x41, 0x41, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3D, 0x20, 0x4C, 0x4F, 0x41, 0x44, 0x20, 0x4D, 0x45, 0x4D, 0x4F, 0x52, 0x59, 0x20, - 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4E, 0x47, 0x20, 0x41, 0x54, 0x20, 0x41, 0x0D, 0x0A, 0x4D, - 0x53, 0x53, 0x53, 0x53, 0x2C, 0x51, 0x51, 0x51, 0x51, 0x2C, 0x44, 0x44, 0x44, 0x44, 0x20, 0x3D, - 0x20, 0x4D, 0x4F, 0x56, 0x45, 0x20, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4E, 0x47, 0x20, 0x41, - 0x54, 0x20, 0x53, 0x20, 0x54, 0x4F, 0x20, 0x51, 0x20, 0x54, 0x4F, 0x20, 0x41, 0x44, 0x44, 0x52, - 0x2E, 0x20, 0x44, 0x0D, 0x0A, 0x4F, 0x50, 0x50, 0x2C, 0x44, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x20, 0x4F, 0x55, 0x54, 0x50, 0x55, 0x54, 0x20, 0x44, 0x41, - 0x54, 0x41, 0x20, 0x44, 0x20, 0x54, 0x4F, 0x20, 0x50, 0x4F, 0x52, 0x54, 0x20, 0x50, 0x0D, 0x0A, - 0x45, 0x53, 0x43, 0x20, 0x57, 0x49, 0x4C, 0x4C, 0x20, 0x54, 0x45, 0x52, 0x4D, 0x49, 0x4E, 0x41, - 0x54, 0x45, 0x20, 0x41, 0x4E, 0x59, 0x20, 0x43, 0x4F, 0x4D, 0x4D, 0x41, 0x4E, 0x44, 0x00, 0x4C, - 0xB2, 0xF1, 0x0D, 0x79, 0xF0, 0x2E, 0xC1, 0xF1, 0x2D, 0xF3, 0xF1, 0x44, 0x04, 0xF2, 0x49, 0x8E, - 0xF2, 0x4F, 0xA0, 0xF2, 0x46, 0x66, 0xF2, 0x47, 0x31, 0xF2, 0x4D, 0x47, 0xF2, 0x48, 0x36, 0xF2, - 0x42, 0xB2, 0xF2, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0x01, 0x00, 0x04, 0x00, 0x07, 0x00, 0x0A, 0x00, 0x0D, 0x00, 0x10, 0x00, 0x13, 0x00, 0x16, - 0x00, 0x19, 0x00, 0x1C, 0x00, 0x1F, 0x00, 0x22, 0x00, 0x25, 0x00, 0x28, 0x00, 0x2B, 0x00, 0x2E, - 0x00, 0x31, 0x00, 0x34, 0x00, 0x37, 0x00, 0x3A, 0x00, 0x69, 0x00, 0x71, 0x00, 0x74, 0x00, 0x77, - 0x00, 0x7D, 0x00, 0x80, 0x00, 0x83, 0x00, 0x87, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xCF, 0x00, 0xDE, - 0x00, 0xE8, 0x00, 0xF2, 0x00, 0xF5, 0x00, 0xFA, 0x00, 0xFF, 0x00, 0x11, 0x01, 0x1E, 0x01, 0x25, - 0x01, 0x29, 0x01, 0x2E, 0x01, 0x3C, 0x01, 0x51, 0x01, 0x71, 0x01, 0x7F, 0x01, 0x88, 0x01, 0xA6, - 0x01, 0xA9, 0x01, 0xAD, 0x01, 0xB0, 0x01, 0xB3, 0x01, 0xB6, 0x01, 0xB9, 0x01, 0xBC, 0x01, 0xC2, - 0x01, 0xC8, 0x01, 0xCB, 0x01, 0xCF, 0x01, 0xD2, 0x01, 0xD5, 0x01, 0xD8, 0x01, 0xDB, 0x01, 0xE2, - 0x01, 0xE7, 0x01, 0xEC, 0x01, 0xF1, 0x01, 0xF8, 0x01, 0x05, 0x02, 0x08, 0x02, 0x0B, 0x02, 0x0E, - 0x02, 0x11, 0x02, 0x14, 0x02, 0x17, 0x02, 0x1B, 0x02, 0x1E, 0x02, 0x21, 0x02, 0x26, 0x02, 0x2C, - 0x02, 0x2F, 0x02, 0x32, 0x02, 0x37, 0x02, 0x3A, 0x02, 0x3D, 0x02, 0x42, 0x02, 0x48, 0x02, 0x4C, - 0x02, 0x4F, 0x02, 0x54, 0x02, 0x59, 0x02, 0x5E, 0x02, 0x61, 0x02, 0x64, 0x02, 0x67, 0x02, 0x6A, - 0x02, 0x6D, 0x02, 0x70, 0x02, 0x73, 0x02, 0x76, 0x02, 0x79, 0x02, 0x7C, 0x02, 0x7F, 0x02, 0x82, - 0x02, 0x87, 0x02, 0x8B, 0x02, 0x8F, 0x02, 0x92, 0x02, 0x98, 0x02, 0x9B, 0x02, 0x9E, 0x02, 0xA1, - 0x02, 0xA4, 0x02, 0xA8, 0x02, 0xAB, 0x02, 0xB0, 0x02, 0xB3, 0x02, 0xB6, 0x02, 0xB9, 0x02, 0xBC, - 0x02, 0xBF, 0x02, 0xC2, 0x02, 0x26, 0x03, 0x42, 0x03, 0x54, 0x03, 0x57, 0x03, 0x5B, 0x03, 0x00 -}; - -/* returns TRUE iff there exists a disk with VERBOSE */ -static int32 adcs6_hasProperty(uint32 property) { - int32 i; - for (i = 0; i < ADCS6_MAX_DRIVES; i++) - if (adcs6_dev.units[i].flags & property) - return TRUE; - return FALSE; -} - -static uint8 motor_timeout = 0; - -/* Unit service routine */ -static t_stat adcs6_svc (UNIT *uptr) -{ - - if(adcs6_info->head_sel == 1) { - motor_timeout ++; - if(motor_timeout == MOTOR_TO_LIMIT) { - adcs6_info->head_sel = 0; - sim_debug(DRIVE_MSG, &adcs6_dev, "ADCS6: Motor OFF\n"); - } - } - - adcs6_info->rtc ++; - - printf("Timer IRQ\n"); - adcs6_info->ipend |= ADCS6_IRQ_TIMER3; - -/* sim_activate (adcs6_unit, adcs6_unit->wait); */ /* requeue! */ - - return SCPE_OK; -} - - -/* Reset routine */ -static t_stat adcs6_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect ROM and I/O Ports */ - if (adcs6_hasProperty(UNIT_ADCS6_ROM)) { - sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &adcs6rom, TRUE); - } - /* Unmap I/O Ports (0x3-4,0x5-9,0x34,0x40 */ - sim_map_resource(0x10, 4, RESOURCE_TYPE_IO, &adcs6_dma, TRUE); - sim_map_resource(0x04, 8, RESOURCE_TYPE_IO, &adcs6_timer, TRUE); - sim_map_resource(0x14, 1, RESOURCE_TYPE_IO, &adcs6_control, TRUE); - sim_map_resource(0x15, 7, RESOURCE_TYPE_IO, &adcs6_banksel, TRUE); - } else { - /* Connect ADCS6 ROM at base address */ - if (adcs6_hasProperty(UNIT_ADCS6_ROM)) { - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: ROM Enabled.\n"); - if(sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &adcs6rom, FALSE) != 0) { - printf("%s: error mapping MEM resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - adcs6_info->rom_disabled = FALSE; - } else { - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: ROM Disabled.\n"); - adcs6_info->rom_disabled = TRUE; - } - - /* Connect ADCS6 FDC Synchronization / Drive / Density Register */ - if(sim_map_resource(0x14, 0x01, RESOURCE_TYPE_IO, &adcs6_control, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } -/*#define ADCS6 */ -#ifdef ADCS6 - /* Connect ADCS6 Interrupt, and Aux Disk Registers */ - - if(sim_map_resource(0x10, 0x04, RESOURCE_TYPE_IO, &adcs6_dma, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - - /* Connect ADCS6 Timer Registers */ - if(sim_map_resource(0x04, 0x08, RESOURCE_TYPE_IO, &adcs6_timer, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } -#endif - /* Connect ADCS6 Memory Management / Bank Select Register */ - if(sim_map_resource(0x15, 0x7, RESOURCE_TYPE_IO, &adcs6_banksel, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - -/* sim_activate (adcs6_unit, adcs6_unit->wait); */ /* requeue! */ - return SCPE_OK; -} - -static t_stat adcs6_boot(int32 unitno, DEVICE *dptr) -{ - DBG_PRINT(("Booting ADCS6 Controller" NLP)); - - /* Re-enable the ROM in case it was disabled */ - adcs6_info->rom_disabled = FALSE; - - /* Set the PC to 0, and go. */ - *((int32 *) sim_PC->loc) = 0xF000; - return SCPE_OK; -} - -/* Attach routine */ -static t_stat adcs6_attach(UNIT *uptr, char *cptr) -{ - t_stat r; - r = wd179x_attach(uptr, cptr); - - return r; -} - -/* Detach routine */ -static t_stat adcs6_detach(UNIT *uptr) -{ - t_stat r; - - r = wd179x_detach(uptr); - - return r; -} - -static int32 adcs6rom(const int32 Addr, const int32 write, const int32 data) -{ -/* DBG_PRINT(("ADCS6: ROM %s, Addr %04x" NLP, write ? "WR" : "RD", Addr)); */ - if(write) { - if(adcs6_info->rom_disabled == FALSE) { - sim_debug(ERROR_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " Cannot write to ROM.\n", PCX); - } else { - adcs6ram[Addr & ADCS6_ADDR_MASK] = data; - } - return 0; - } else { - if(adcs6_info->rom_disabled == FALSE) { - return(adcs6_rom[Addr & ADCS6_ADDR_MASK]); - } else { - return(adcs6ram[Addr & ADCS6_ADDR_MASK]); - } - } -} - -/* Disk Control/Flags Register, 0x14 */ -static int32 adcs6_control(const int32 port, const int32 io, const int32 data) -{ - int32 result = 0; - if(io) { /* I/O Write */ - wd179x_infop->sel_drive = data & 0x03; - - if(data & ADCS6_CTRL_MINI) { - wd179x_infop->drivetype = 5; - } else { - wd179x_infop->drivetype = 8; - } - - if(data & ADCS6_CTRL_HDS) { - adcs6_info->head_sel = 1; - wd179x_infop->fdc_head = 1; - } else { - adcs6_info->head_sel = 0; - wd179x_infop->fdc_head = 0; - } - - if(data & ADCS6_CTRL_DDENS) { - wd179x_infop->ddens = 1; - } else { - wd179x_infop->ddens = 0; - } - if(data & ADCS6_CTRL_AUTOWAIT) { - adcs6_info->autowait = 1; - } else { - adcs6_info->autowait = 0; - } - - sim_debug(DRIVE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR CTRL: sel_drive=%d, drivetype=%d, head_sel=%d, dens=%d, aw=%d\n", - PCX, wd179x_infop->sel_drive, - wd179x_infop->drivetype, adcs6_info->head_sel, - wd179x_infop->ddens, adcs6_info->autowait); - } else { /* I/O Read */ - result = wd179x_infop->drq ? 0xFF : 0; - if (wd179x_infop->intrq) - result &= 0x7F; - } - - return result; -} - -/* ADC Super Six DMA (Z80-DMA) */ -static int32 adcs6_dma(const int32 port, const int32 io, const int32 data) -{ - int32 result = 0xff; - if(io) { /* I/O Write */ - sim_debug(DMA_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR DMA: 0x%02x\n", PCX, data & 0xFF); - } else { /* I/O Read */ - result = 0xFF; - sim_debug(DMA_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " RD DMA: 0x%02x\n", PCX, result); - } - return result; -} - -/* ADC Super-Six PIO and CTC ports */ -static int32 adcs6_timer(const int32 port, const int32 io, const int32 data) -{ - static int32 result = 0xFF; - if(io) { /* Write */ - switch(port) { - case 0x04: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR PIOA DATA=0x%02x\n", PCX, data); - break; - case 0x05: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR PIOB DATA=0x%02x\n", PCX, data); - break; - case 0x06: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR PIOA CTRL=0x%02x\n", PCX, data); - break; - case 0x07: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR PIOB CTRL=0x%02x\n", PCX, data); - break; - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR CTC%d: 0x%02x\n", PCX, port - 8, data); - break; - default: - sim_debug(ERROR_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR Unhandled Port: 0x%02x=0x%02x\n", PCX, port, data); - break; - } - } else { /* Read */ - result = 0xFF; - switch(port) { - case 0x04: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " RD PIOA DATA=0x%02x\n", PCX, result); - break; - case 0x05: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " RD PIOB DATA=0x%02x\n", PCX, result); - break; - case 0x06: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " RD PIOA CTRL=0x%02x\n", PCX, result); - break; - case 0x07: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " RD PIOB CTRL=0x%02x\n", PCX, result); - break; - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " RD CTC%d: 0x%02x\n", PCX, port - 8, data); - break; - default: - sim_debug(ERROR_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " RD Unhandled Port: 0x%02x=0x%02x\n", PCX, port, data); - break; - } - } - return result; -} - -/* 64FDC Bank Select (Write Disables boot ROM) */ -static int32 adcs6_banksel(const int32 port, const int32 io, const int32 data) -{ - int32 result; - if(io) { /* Write */ - switch(port) { - case 0x15: - adcs6_info->s100_addr_u = data & 0xFF; - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR S100 A[23:16]=0x%02x\n", PCX, data); - break; - case 0x16: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR MCTRL0: 0x%02x\n", PCX, data); - adcs6_info->rom_disabled = (data & 0x20) ? TRUE : FALSE; /* Unmap Boot ROM */ - break; - case 0x17: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR MCTRL1: 0x%02x\n", PCX, data); - break; - case 0x18: - case 0x19: - case 0x1A: - case 0x1B: - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR BAUD RATE=0x%02x\n", PCX, data); - break; - default: - sim_debug(ERROR_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " WR Unhandled Port: 0x%02x=0x%02x\n", PCX, port, data); - break; - } - result = 0; - } else { /* Read */ - result = 0xFF; - switch(port) { - case 0x15: - /* These are the Jumpers at J7. - * Bit 7=0 = double-sided disk, bit 7=1 = single sided. - * Bit 6=0 = use on-board RAM, Bit 6=1 = use S-100 RAM cards. - * Bit 5:0 = "Baud Rate" - */ - result = dipswitch; - sim_debug(VERBOSE_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " RD BAUD RATE=0x%02x\n", PCX, result); - break; - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1A: - case 0x1B: - default: - sim_debug(ERROR_MSG, &adcs6_dev, "ADCS6: " ADDRESS_FORMAT - " RD attempt from write-only 0x%02x=0x%02x\n", PCX, port, result); - break; - } - } - return result; -} diff --git a/AltairZ80/s100_disk1a.c b/AltairZ80/s100_disk1a.c deleted file mode 100644 index 5a71aa94..00000000 --- a/AltairZ80/s100_disk1a.c +++ /dev/null @@ -1,890 +0,0 @@ -/************************************************************************* - * * - * $Id: s100_disk1a.c 1996 2008-07-16 05:31:21Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * CompuPro DISK1A Floppy Controller module for SIMH. * - * This module is a wrapper around the i8272 FDC module, and adds the * - * CompuPro-specific registers as well as the CompuPro Boot ROM. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/*#define DBG_MSG */ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#include "sim_defs.h" /* simulator definitions */ -#include "i8272.h" - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define STATUS_MSG (1 << 5) -#define VERBOSE_MSG (1 << 7) -#define IRQ_MSG (1 << 8) - -#define DISK1A_MAX_DRIVES 4 - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint32 dma_addr; /* DMA Transfer Address */ - uint8 rom_disabled; /* TRUE if ROM has been disabled */ -} DISK1A_INFO; - -static DISK1A_INFO disk1a_info_data = { { 0x0, 512, 0xC0, 4 } }; -static DISK1A_INFO *disk1a_info = &disk1a_info_data; - -extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); - -extern void raise_ss1_interrupt(uint8 intnum); - -extern REG *sim_PC; -extern uint32 PCX; /* external view of PC */ - -#define UNIT_V_DISK1A_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_DISK1A_WLK (1 << UNIT_V_DISK1A_WLK) -#define UNIT_V_DISK1A_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_DISK1A_VERBOSE (1 << UNIT_V_DISK1A_VERBOSE) -#define UNIT_V_DISK1A_ROM (UNIT_V_UF + 2) /* boot ROM enabled */ -#define UNIT_DISK1A_ROM (1 << UNIT_V_DISK1A_ROM) -#define DISK1A_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ - -static t_stat disk1a_reset(DEVICE *disk1a_dev); -static t_stat disk1a_boot(int32 unitno, DEVICE *dptr); -static t_stat disk1a_attach(UNIT *uptr, char *cptr); -static t_stat disk1a_detach(UNIT *uptr); - -static int32 disk1adev(const int32 port, const int32 io, const int32 data); -static int32 disk1arom(const int32 port, const int32 io, const int32 data); - -static uint8 DISK1A_Read(const uint32 Addr); -static uint8 DISK1A_Write(const uint32 Addr, uint8 cData); -void raise_disk1a_interrupt(void); - -static int32 bootstrap = 0; - -/* The DISK1A does not really have RAM associated with it, but for ease of integration with the - * SIMH/AltairZ80 Resource Mapping Scheme, rather than Map and Unmap the ROM, simply implement our - * own RAM that can be swapped in when the DISK1A Boot ROM is disabled. - */ -static uint8 disk1aram[512]; - -static UNIT disk1a_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK1A_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK1A_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK1A_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK1A_CAPACITY) } -}; - -static REG disk1a_reg[] = { - { DRDATA (BOOTSTRAP, bootstrap, 10), }, - { NULL } -}; - -static MTAB disk1a_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_DISK1A_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_DISK1A_WLK, UNIT_DISK1A_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_DISK1A_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_DISK1A_VERBOSE, UNIT_DISK1A_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { UNIT_DISK1A_ROM, 0, "NOROM", "NOROM", NULL }, - { UNIT_DISK1A_ROM, UNIT_DISK1A_ROM, "ROM", "ROM", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB disk1a_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "CMD", CMD_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "STATUS", STATUS_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { "IRQ", IRQ_MSG }, - { NULL, 0 } -}; - -DEVICE disk1a_dev = { - "DISK1A", disk1a_unit, disk1a_reg, disk1a_mod, - DISK1A_MAX_DRIVES, 10, 31, 1, DISK1A_MAX_DRIVES, DISK1A_MAX_DRIVES, - NULL, NULL, &disk1a_reset, - &disk1a_boot, &disk1a_attach, &disk1a_detach, - &disk1a_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - disk1a_dt, NULL, "Compupro Floppy Controller DISK1A" -}; - -/* This is the DISK1A Boot ROM. - * It consists of an 8K ROM, broken down into 16 bootstraps of - * 512-bytes each. See the DISK1A Manual for details of each - * bootstrap. Bootstrap 0 is the default, but others can be - * selected with 'd disk1a bootstrap ' at the SIMH SCP Prompt. - * - * Bootstraps 0- 3 8085/8088/Z80 - * Bootstraps 4- 7 8086/80286 - * Bootstraps 8-11 68000 - * Bootstraps 12-15 32016 - * - * 0,4, 8,12: Attempt to boot 8" drive 0, if not ready boot from DISK3. - * 1,5, 9,13: Always boot from DISK3. - * 2,6,10,14: Attempt to boot 8" drive 0, if not ready, attempt to boot 5.25" drive 2. - * 3,7,11,15: Attempt to boot 5.25" drive 0, if not ready, attempt to boot DISK3. - */ -static uint8 disk1a_rom[16][512] = { -{ 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x80, 0x3E, 0xFF, 0xD3, 0xC3, 0x01, 0x00, 0x40, 0xE3, 0xE3, /* 0 */ - 0x0B, 0x78, 0xB1, 0xC2, 0x0E, 0x00, 0x21, 0x00, 0x02, 0x11, 0x00, 0x82, 0x7E, 0x12, 0x1B, 0x2B, - 0x7D, 0xB4, 0xC2, 0x1C, 0x00, 0x11, 0x5D, 0x00, 0x3E, 0x85, 0x12, 0x13, 0x3E, 0x81, 0x12, 0x13, - 0x3E, 0x00, 0x12, 0x11, 0x50, 0x00, 0x12, 0x13, 0x13, 0x12, 0xC3, 0x49, 0x80, 0x01, 0x00, 0xC0, - 0xE3, 0xE3, 0x0B, 0x78, 0xB1, 0xC2, 0x40, 0x80, 0xC9, 0x3E, 0xFE, 0xD3, 0xC3, 0x11, 0x70, 0x81, - 0x06, 0x03, 0xDB, 0xC0, 0xB7, 0xF2, 0x52, 0x80, 0x1A, 0xD3, 0xC1, 0x13, 0x05, 0xC2, 0x52, 0x80, - 0x06, 0x02, 0xDB, 0xC0, 0xB7, 0xF2, 0x62, 0x80, 0x1A, 0xD3, 0xC1, 0x13, 0x05, 0xC2, 0x62, 0x80, - 0xDB, 0xC2, 0xB7, 0xF2, 0x70, 0x80, 0x3E, 0x08, 0xD3, 0xC1, 0xCD, 0x3D, 0x80, 0xDB, 0xC0, 0xB7, - 0xF2, 0x7D, 0x80, 0xDB, 0xC1, 0xEE, 0x20, 0x4F, 0xDB, 0xC0, 0xB7, 0xF2, 0x88, 0x80, 0xDB, 0xC1, - 0xB1, 0xC2, 0xDD, 0x80, 0x06, 0x03, 0x1A, 0xD3, 0xC2, 0x13, 0x05, 0xC2, 0x96, 0x80, 0x06, 0x09, - 0xDB, 0xC0, 0xB7, 0xF2, 0xA0, 0x80, 0x1A, 0xD3, 0xC1, 0x13, 0x05, 0xC2, 0xA0, 0x80, 0xDB, 0xC2, - 0xB7, 0xF2, 0xAE, 0x80, 0xDB, 0xC0, 0xB7, 0xF2, 0xB4, 0x80, 0xDB, 0xC1, 0xD6, 0x40, 0x67, 0xDB, - 0xC0, 0xB7, 0xF2, 0xBF, 0x80, 0xDB, 0xC1, 0xEE, 0x80, 0x6F, 0x06, 0x05, 0xDB, 0xC0, 0xB7, 0xF2, - 0xCC, 0x80, 0xDB, 0xC1, 0x05, 0xC2, 0xCC, 0x80, 0x7D, 0xB4, 0xCA, 0x53, 0x81, 0x3E, 0x01, 0xD3, - 0x90, 0xAF, 0x32, 0x86, 0x81, 0xD3, 0x90, 0xCD, 0x3D, 0x80, 0x3A, 0x86, 0x81, 0xB7, 0xFA, 0x13, - 0x81, 0xAF, 0x32, 0x86, 0x81, 0xD3, 0x90, 0xCD, 0x3D, 0x80, 0x3A, 0x86, 0x81, 0xB7, 0xFA, 0x13, - 0x81, 0xC3, 0x49, 0x80, 0xAF, 0x12, 0xD3, 0x90, 0x1A, 0xB7, 0xCA, 0x08, 0x81, 0x07, 0xF8, 0xC1, - 0xC3, 0x49, 0x80, 0x11, 0x96, 0x81, 0xCD, 0x04, 0x81, 0x11, 0xA6, 0x81, 0xCD, 0x04, 0x81, 0x11, - 0xB6, 0x81, 0x2A, 0xBF, 0x81, 0xCD, 0x04, 0x81, 0x11, 0x81, 0x81, 0x06, 0x04, 0x1A, 0xBE, 0xC2, - 0x49, 0x80, 0x23, 0x13, 0x05, 0xC2, 0x2D, 0x81, 0x11, 0xC6, 0x81, 0xCD, 0x04, 0x81, 0x11, 0xD6, - 0x81, 0xCD, 0x04, 0x81, 0x11, 0xE6, 0x81, 0x2A, 0xEF, 0x81, 0xCD, 0x04, 0x81, 0x7E, 0xFE, 0xE5, - 0xCA, 0x49, 0x80, 0xDB, 0xC2, 0x0F, 0x0F, 0xE6, 0x01, 0xF6, 0x02, 0x4F, 0xC3, 0x00, 0x01, 0x52, - 0x52, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x8F, 0x24, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1A, 0x07, - 0x80, 0x43, 0x6F, 0x6D, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x95, 0x81, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xA5, 0x81, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xB5, 0x81, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x01, 0x00, 0xC5, 0x81, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x01, 0x00, 0xD5, 0x81, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0xE5, 0x81, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x01, 0x00, 0x50, 0x00, 0x00, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A }, - -{ 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x80, 0x01, 0x00, 0x40, 0xE3, 0xE3, 0x0B, 0x78, 0xB1, 0xC2, /* 1 */ - 0x0A, 0x00, 0x21, 0x00, 0x02, 0x11, 0x00, 0x82, 0x7E, 0x12, 0x1B, 0x2B, 0x7D, 0xB4, 0xC2, 0x18, - 0x00, 0x11, 0x5D, 0x00, 0x3E, 0xD2, 0x12, 0x13, 0x3E, 0x80, 0x12, 0x13, 0x3E, 0x00, 0x12, 0x11, - 0x50, 0x00, 0x12, 0x13, 0x13, 0x12, 0xC3, 0x39, 0x80, 0x3E, 0xFE, 0xD3, 0xC3, 0x3E, 0x01, 0xD3, - 0x90, 0xAF, 0x32, 0xD3, 0x80, 0xD3, 0x90, 0x01, 0x00, 0x14, 0x0B, 0x78, 0xB1, 0xC2, 0x4A, 0x80, - 0x3A, 0xD3, 0x80, 0xB7, 0xFA, 0x7F, 0x80, 0xAF, 0x32, 0xD3, 0x80, 0xD3, 0x90, 0x01, 0x00, 0x14, - 0x0B, 0x78, 0xB1, 0xC2, 0x60, 0x80, 0x3A, 0xD3, 0x80, 0xB7, 0xFA, 0x7F, 0x80, 0xC3, 0x39, 0x80, - 0xAF, 0x12, 0xD3, 0x90, 0x1A, 0xB7, 0xCA, 0x74, 0x80, 0x07, 0xF8, 0xC1, 0xC3, 0x39, 0x80, 0x11, - 0xE3, 0x80, 0xCD, 0x70, 0x80, 0x11, 0xF3, 0x80, 0xCD, 0x70, 0x80, 0x11, 0x03, 0x81, 0x2A, 0x0C, - 0x81, 0xCD, 0x70, 0x80, 0x11, 0xCE, 0x80, 0x06, 0x04, 0x1A, 0xBE, 0xC2, 0x39, 0x80, 0x23, 0x13, - 0x05, 0xC2, 0x99, 0x80, 0x11, 0x13, 0x81, 0xCD, 0x70, 0x80, 0x11, 0x23, 0x81, 0xCD, 0x70, 0x80, - 0x11, 0x33, 0x81, 0x2A, 0x3C, 0x81, 0xCD, 0x70, 0x80, 0x7E, 0xFE, 0xE5, 0xCA, 0x39, 0x80, 0xDB, - 0xC2, 0x0F, 0x0F, 0xE6, 0x01, 0xF6, 0x02, 0x4F, 0xC3, 0x00, 0x01, 0x52, 0x52, 0x32, 0x43, 0x6F, - 0x6D, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, - 0x80, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, - 0x80, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x81, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x12, - 0x81, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x22, - 0x81, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x32, - 0x81, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x50, - 0x00, 0x00, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - -{ 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x80, 0x3E, 0xFF, 0xD3, 0xC3, 0x01, 0x00, 0x40, 0xE3, 0xE3, /* 2 */ - 0x0B, 0x78, 0xB1, 0xC2, 0x0E, 0x00, 0x21, 0x00, 0x02, 0x11, 0x00, 0x82, 0x7E, 0x12, 0x1B, 0x2B, - 0x7D, 0xB4, 0xC2, 0x1C, 0x00, 0xC3, 0x34, 0x80, 0x01, 0x00, 0xC0, 0xE3, 0xE3, 0x0B, 0x78, 0xB1, - 0xC2, 0x2B, 0x80, 0xC9, 0x11, 0x00, 0x81, 0x3E, 0xFE, 0xD3, 0xC3, 0x1A, 0xD3, 0xC0, 0xCD, 0x28, - 0x80, 0x13, 0x06, 0x03, 0xDB, 0xC0, 0xB7, 0xF2, 0x44, 0x80, 0x1A, 0xD3, 0xC1, 0x13, 0x05, 0xC2, - 0x44, 0x80, 0xCD, 0x28, 0x80, 0x06, 0x02, 0xDB, 0xC0, 0xB7, 0xF2, 0x57, 0x80, 0x1A, 0xD3, 0xC1, - 0x13, 0x05, 0xC2, 0x57, 0x80, 0xDB, 0xC2, 0xB7, 0xF2, 0x65, 0x80, 0x3E, 0x08, 0xD3, 0xC1, 0xCD, - 0x28, 0x80, 0xDB, 0xC0, 0xB7, 0xF2, 0x72, 0x80, 0xDB, 0xC1, 0xEE, 0x20, 0x4F, 0xDB, 0xC0, 0xB7, - 0xF2, 0x7D, 0x80, 0xDB, 0xC1, 0xB1, 0xE6, 0xFC, 0xC2, 0xD6, 0x80, 0x06, 0x03, 0x1A, 0xD3, 0xC2, - 0x13, 0x05, 0xC2, 0x8D, 0x80, 0x06, 0x09, 0xDB, 0xC0, 0xB7, 0xF2, 0x97, 0x80, 0x1A, 0xD3, 0xC1, - 0x13, 0x05, 0xC2, 0x97, 0x80, 0xDB, 0xC2, 0xB7, 0xF2, 0xA5, 0x80, 0xDB, 0xC0, 0xB7, 0xF2, 0xAB, - 0x80, 0xDB, 0xC1, 0xD6, 0x40, 0xE6, 0xFC, 0x67, 0xDB, 0xC0, 0xB7, 0xF2, 0xB8, 0x80, 0xDB, 0xC1, - 0xEE, 0x80, 0x6F, 0x06, 0x05, 0xDB, 0xC0, 0xB7, 0xF2, 0xC5, 0x80, 0xDB, 0xC1, 0x05, 0xC2, 0xC5, - 0x80, 0x7D, 0xB4, 0xCA, 0xE7, 0x80, 0x7B, 0xFE, 0x18, 0xCA, 0x34, 0x80, 0xFE, 0x24, 0xCA, 0x34, - 0x80, 0x11, 0x12, 0x81, 0xC3, 0x37, 0x80, 0xDB, 0xC2, 0x0F, 0x0F, 0xE6, 0x01, 0xF6, 0x02, 0x4F, - 0xC3, 0x00, 0x01, 0x52, 0x52, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x8F, 0x24, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1A, - 0x07, 0x80, 0x28, 0x03, 0xDF, 0x1E, 0x07, 0x02, 0x00, 0x01, 0x00, 0x46, 0x02, 0x00, 0x00, 0x01, - 0x03, 0x05, 0x35, 0xFF, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, - 0x72, 0x79, 0x2E, 0x20, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, - 0x39, 0x38, 0x33, 0x20, 0x62, 0x79, 0x20, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6C, 0x20, 0x52, - 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2E, 0x00, 0x24, 0x4C, 0x53, 0x54, 0x3A, 0x00, 0x00, - 0x1A, 0x00, 0x00, 0x00, 0xC4, 0x09, 0x00, 0x00, 0xFF, 0xFF, 0xC4, 0x09, 0x00, 0x00, 0x00, 0x00, - 0x3C, 0x3E, 0x2E, 0x2C, 0x3D, 0x3A, 0x7C, 0x5B, 0x5D, 0x2A, 0x0A, 0x0D, 0x00, 0x00, 0x00, 0x00, - 0x63, 0x68, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x73, 0x20, 0x6E, 0x61, 0x6D, 0x65, - 0x20, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x0A, 0x00, 0x43, 0x6F, 0x75, 0x6C, 0x64, 0x20, - 0x6E, 0x6F, 0x74, 0x20, 0x6C, 0x6F, 0x67, 0x6F, 0x6E, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65 }, - -{ 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x80, 0x3E, 0xFF, 0xD3, 0xC3, 0x01, 0x00, 0x40, 0xE3, 0xE3, /* 3 */ - 0x0B, 0x78, 0xB1, 0xC2, 0x0E, 0x00, 0x21, 0x00, 0x02, 0x11, 0x00, 0x82, 0x7E, 0x12, 0x1B, 0x2B, - 0x7D, 0xB4, 0xC2, 0x1C, 0x00, 0x11, 0x5D, 0x00, 0x3E, 0x85, 0x12, 0x13, 0x3E, 0x81, 0x12, 0x13, - 0x3E, 0x00, 0x12, 0x11, 0x50, 0x00, 0x12, 0x13, 0x13, 0x12, 0xC3, 0x49, 0x80, 0x01, 0x00, 0x80, - 0xE3, 0xE3, 0x0B, 0x78, 0xB1, 0xC2, 0x40, 0x80, 0xC9, 0x3E, 0xFE, 0xD3, 0xC3, 0x3E, 0x28, 0xD3, - 0xC0, 0xCD, 0x3D, 0x80, 0x11, 0x70, 0x81, 0x06, 0x03, 0xDB, 0xC0, 0xB7, 0xF2, 0x59, 0x80, 0x1A, - 0xD3, 0xC1, 0x13, 0x05, 0xC2, 0x59, 0x80, 0x06, 0x02, 0xDB, 0xC0, 0xB7, 0xF2, 0x69, 0x80, 0x1A, - 0xD3, 0xC1, 0x13, 0x05, 0xC2, 0x69, 0x80, 0xDB, 0xC2, 0xB7, 0xF2, 0x77, 0x80, 0x3E, 0x08, 0xD3, - 0xC1, 0xCD, 0x3D, 0x80, 0xDB, 0xC0, 0xB7, 0xF2, 0x84, 0x80, 0xDB, 0xC1, 0xEE, 0x20, 0x4F, 0xDB, - 0xC0, 0xB7, 0xF2, 0x8F, 0x80, 0xDB, 0xC1, 0xB1, 0xE6, 0xFC, 0xC2, 0xE8, 0x80, 0x06, 0x03, 0x1A, - 0xD3, 0xC2, 0x13, 0x05, 0xC2, 0x9F, 0x80, 0x06, 0x09, 0xDB, 0xC0, 0xB7, 0xF2, 0xA9, 0x80, 0x1A, - 0xD3, 0xC1, 0x13, 0x05, 0xC2, 0xA9, 0x80, 0xDB, 0xC2, 0xB7, 0xF2, 0xB7, 0x80, 0xDB, 0xC0, 0xB7, - 0xF2, 0xBD, 0x80, 0xDB, 0xC1, 0xD6, 0x40, 0xE6, 0xFC, 0x67, 0xDB, 0xC0, 0xB7, 0xF2, 0xCA, 0x80, - 0xDB, 0xC1, 0xEE, 0x80, 0x6F, 0x06, 0x05, 0xDB, 0xC0, 0xB7, 0xF2, 0xD7, 0x80, 0xDB, 0xC1, 0x05, - 0xC2, 0xD7, 0x80, 0x7D, 0xB4, 0xCA, 0x5E, 0x81, 0x3E, 0x01, 0xD3, 0x90, 0xAF, 0x32, 0x86, 0x81, - 0xD3, 0x90, 0xCD, 0x3D, 0x80, 0x3A, 0x86, 0x81, 0xB7, 0xFA, 0x1E, 0x81, 0xAF, 0x32, 0x86, 0x81, - 0xD3, 0x90, 0xCD, 0x3D, 0x80, 0x3A, 0x86, 0x81, 0xB7, 0xFA, 0x1E, 0x81, 0xC3, 0x49, 0x80, 0xAF, - 0x12, 0xD3, 0x90, 0x1A, 0xB7, 0xCA, 0x13, 0x81, 0x07, 0xF8, 0xC1, 0xC3, 0x49, 0x80, 0x11, 0x96, - 0x81, 0xCD, 0x0F, 0x81, 0x11, 0xA6, 0x81, 0xCD, 0x0F, 0x81, 0x11, 0xB6, 0x81, 0x2A, 0xBF, 0x81, - 0xCD, 0x0F, 0x81, 0x11, 0x81, 0x81, 0x06, 0x04, 0x1A, 0xBE, 0xC2, 0x49, 0x80, 0x23, 0x13, 0x05, - 0xC2, 0x38, 0x81, 0x11, 0xC6, 0x81, 0xCD, 0x0F, 0x81, 0x11, 0xD6, 0x81, 0xCD, 0x0F, 0x81, 0x11, - 0xE6, 0x81, 0x2A, 0xEF, 0x81, 0xCD, 0x0F, 0x81, 0x7E, 0xFE, 0xE5, 0xCA, 0x49, 0x80, 0xDB, 0xC2, - 0x0F, 0x0F, 0xE6, 0x01, 0xF6, 0x02, 0x4F, 0xC3, 0x00, 0x01, 0x52, 0x52, 0x34, 0x00, 0x00, 0x00, - 0x03, 0xDF, 0x1E, 0x07, 0x02, 0x00, 0x01, 0x00, 0x46, 0x02, 0x00, 0x00, 0x01, 0x03, 0x05, 0x20, - 0xFF, 0x43, 0x6F, 0x6D, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x95, 0x81, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xA5, 0x81, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xB5, 0x81, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x01, 0x00, 0xC5, 0x81, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x01, 0x00, 0xD5, 0x81, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0xE5, 0x81, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x01, 0x00, 0x50, 0x00, 0x00, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A }, - -{ 0xDB, 0xFD, 0x90, 0x90, 0xB0, 0xFF, 0xE6, 0xC3, 0xB9, 0x00, 0xD0, 0x50, 0x58, 0xE2, 0xFC, 0x33, /* 4 */ - 0xC0, 0x8E, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC, 0x04, 0x00, 0xBA, 0x90, 0x00, 0xBE, 0x00, 0x00, - 0x8B, 0xFE, 0xB9, 0x00, 0x01, 0xF3, 0xA5, 0xEB, 0x0F, 0xFC, 0x33, 0xC0, 0xE4, 0xC0, 0x0A, 0xC0, - 0x79, 0xFA, 0xAC, 0xE6, 0xC1, 0xE2, 0xF5, 0xC3, 0xB0, 0xFE, 0xE6, 0xC3, 0xB9, 0x03, 0x00, 0xBE, - 0xC6, 0x00, 0xE8, 0xE4, 0xFF, 0xB9, 0x02, 0x00, 0xE8, 0xDE, 0xFF, 0xEB, 0x13, 0x52, 0x52, 0x31, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, - 0xE4, 0xC2, 0x0A, 0xC0, 0x79, 0xFA, 0xB0, 0x08, 0xE6, 0xC1, 0xB9, 0x00, 0xF0, 0x50, 0x58, 0xE2, - 0xFC, 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, 0xE4, 0xC1, 0x34, 0x20, 0x8A, 0xE0, 0xE4, 0xC0, 0x0A, - 0xC0, 0x79, 0xFA, 0xE4, 0xC1, 0x0A, 0xC4, 0x74, 0x03, 0xE9, 0x84, 0x00, 0xB9, 0x03, 0x00, 0xAC, - 0xE6, 0xC2, 0xE2, 0xFB, 0xB9, 0x09, 0x00, 0xE8, 0x8F, 0xFF, 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, - 0xE4, 0xC1, 0x2C, 0x40, 0x8A, 0xD8, 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, 0xE4, 0xC1, 0x34, 0x80, - 0x8A, 0xF8, 0xB9, 0x05, 0x00, 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, 0xE4, 0xC1, 0xE2, 0xF6, 0x0A, - 0xFB, 0x74, 0x24, 0xE9, 0x4A, 0x00, 0x03, 0x8F, 0x46, 0x07, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x1A, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x02, 0xAC, - 0x3C, 0xE5, 0x75, 0x03, 0xE9, 0x51, 0xFF, 0xBE, 0x00, 0x02, 0xBF, 0x00, 0x01, 0xB9, 0x00, 0x12, - 0xF3, 0xA5, 0x33, 0xC0, 0xE4, 0xC2, 0xB1, 0x02, 0xD3, 0xD8, 0x24, 0x01, 0x0C, 0x02, 0x8B, 0xC8, - 0x43, 0x6F, 0x6D, 0x70, 0x33, 0xC0, 0xEE, 0x0A, 0x44, 0x01, 0x74, 0xFB, 0x79, 0x01, 0xC3, 0x58, - 0xBE, 0x50, 0x00, 0xB0, 0x01, 0xEE, 0xB0, 0x00, 0x88, 0x44, 0x01, 0xEE, 0xB9, 0x00, 0xF0, 0x50, - 0x58, 0xE2, 0xFC, 0x0A, 0x44, 0x01, 0x75, 0x13, 0x88, 0x44, 0x01, 0xEF, 0xB9, 0x00, 0xF0, 0x50, - 0x58, 0xE2, 0xFC, 0x0A, 0x44, 0x01, 0x75, 0x03, 0xE9, 0xFD, 0xFE, 0xC7, 0x04, 0x05, 0x00, 0xE8, - 0xC2, 0xFF, 0xC7, 0x44, 0x04, 0x08, 0x01, 0xC7, 0x04, 0x02, 0x00, 0xE8, 0xB6, 0xFF, 0xC7, 0x44, - 0x04, 0x00, 0x00, 0xC7, 0x44, 0x0A, 0x00, 0x02, 0xC7, 0x44, 0x08, 0x02, 0x00, 0xC6, 0x44, 0x03, - 0x01, 0xC7, 0x04, 0x08, 0x00, 0xE8, 0x9C, 0xFF, 0xBE, 0x00, 0x02, 0xBF, 0x00, 0x01, 0xB9, 0x04, - 0x00, 0xF3, 0xA6, 0x75, 0xC3, 0xBE, 0x50, 0x00, 0xC7, 0x44, 0x0A, 0x10, 0x02, 0xC7, 0x04, 0x03, - 0x00, 0xE8, 0x80, 0xFF, 0xC7, 0x44, 0x0A, 0x00, 0x06, 0xC7, 0x04, 0x04, 0x00, 0xE8, 0x74, 0xFF, - 0xC7, 0x44, 0x0A, 0x00, 0x02, 0xC7, 0x44, 0x08, 0x09, 0x00, 0xC6, 0x44, 0x03, 0x01, 0x33, 0xC0, - 0x89, 0x44, 0x04, 0x89, 0x44, 0x06, 0xC7, 0x04, 0x08, 0x00, 0xE8, 0x57, 0xFF, 0xE9, 0x2C, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x04, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00 }, - -{ 0xDB, 0xFD, 0x33, 0xC0, 0x8E, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC, 0x1D, 0x00, 0xBA, 0x90, 0x00, /* 5 */ - 0xBE, 0x00, 0x00, 0x8B, 0xFE, 0xFC, 0xB9, 0x00, 0x01, 0xF3, 0xA5, 0xEB, 0x18, 0x43, 0x6F, 0x6D, - 0x70, 0xB9, 0x00, 0xD0, 0x50, 0x58, 0xE2, 0xFC, 0xC3, 0x33, 0xC0, 0xEE, 0x0A, 0x44, 0x01, 0x74, - 0xFB, 0x79, 0x01, 0xC3, 0x58, 0xB0, 0xFE, 0xE6, 0xC3, 0xBE, 0x50, 0x00, 0xB0, 0x01, 0xEE, 0xEB, - 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, - 0xB0, 0x00, 0x88, 0x44, 0x01, 0xEE, 0xE8, 0xB8, 0xFF, 0x0A, 0x44, 0x01, 0x75, 0x0C, 0x88, 0x44, - 0x01, 0xEE, 0xE8, 0xAC, 0xFF, 0x0A, 0x44, 0x01, 0x74, 0xBB, 0xC7, 0x04, 0x05, 0x00, 0xE8, 0xA8, - 0xFF, 0xC7, 0x44, 0x04, 0x08, 0x01, 0xC7, 0x04, 0x02, 0x00, 0xE8, 0x9C, 0xFF, 0xC7, 0x44, 0x04, - 0x00, 0x00, 0xC7, 0x44, 0x0A, 0x00, 0x01, 0xC7, 0x44, 0x08, 0x02, 0x00, 0xC6, 0x44, 0x03, 0x01, - 0xC7, 0x04, 0x08, 0x00, 0xE8, 0x82, 0xFF, 0xBE, 0x00, 0x01, 0xBF, 0x1D, 0x00, 0xB9, 0x02, 0x00, - 0xF3, 0xA7, 0x75, 0x81, 0xBE, 0x50, 0x00, 0xC7, 0x44, 0x0A, 0x10, 0x01, 0xC7, 0x04, 0x03, 0x00, - 0xE8, 0x66, 0xFF, 0xC7, 0x44, 0x0A, 0x00, 0x05, 0xC7, 0x04, 0x04, 0x00, 0xE8, 0x5A, 0xFF, 0xC7, - 0x44, 0x0A, 0x00, 0x01, 0xC7, 0x44, 0x08, 0x09, 0x00, 0xC6, 0x44, 0x03, 0x01, 0x33, 0xC0, 0x89, - 0x44, 0x04, 0x89, 0x44, 0x06, 0xC7, 0x04, 0x08, 0x00, 0xE8, 0x3D, 0xFF, 0x33, 0xC0, 0xEB, 0x04, - 0x00, 0x00, 0x00, 0x00, 0xE4, 0xC2, 0xB1, 0x02, 0xD3, 0xD8, 0x24, 0x01, 0x0C, 0x02, 0x8B, 0xC8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00 }, - -{ 0xDB, 0xFD, 0x90, 0x90, 0xB0, 0xFF, 0xE6, 0xC3, 0xB9, 0x00, 0xD0, 0x50, 0x58, 0xE2, 0xFC, 0x33, /* 6 */ - 0xC0, 0x8E, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC, 0x04, 0x00, 0xBE, 0x00, 0x00, 0x8B, 0xFE, 0xB9, - 0x80, 0x00, 0xF3, 0xA5, 0xEB, 0x17, 0xFC, 0x33, 0xC0, 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, 0xAC, - 0xE6, 0xC1, 0xE2, 0xF5, 0xC3, 0xB9, 0x00, 0xF0, 0x50, 0x58, 0xE2, 0xFC, 0xC3, 0xBE, 0xCA, 0x00, - 0xB0, 0xFE, 0xE6, 0xC3, 0xFC, 0xAC, 0xE6, 0xC0, 0xE8, 0xEA, 0xFF, 0xB9, 0x03, 0x00, 0xE8, 0xD5, - 0xFF, 0xB9, 0x02, 0x00, 0xE8, 0xCF, 0xFF, 0xE4, 0xC2, 0x0A, 0xC0, 0x79, 0xFA, 0xB0, 0x08, 0xE6, - 0xC1, 0xE8, 0xD1, 0xFF, 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, 0xE4, 0xC1, 0x34, 0x20, 0x8A, 0xE0, - 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, 0xE4, 0xC1, 0x0A, 0xC4, 0x24, 0xFC, 0x74, 0x03, 0xE9, 0x39, - 0x00, 0xB9, 0x03, 0x00, 0xAC, 0xE6, 0xC2, 0xE2, 0xFB, 0xB9, 0x09, 0x00, 0xE8, 0x97, 0xFF, 0xE4, - 0xC0, 0x0A, 0xC0, 0x79, 0xFA, 0xE4, 0xC1, 0x2C, 0x40, 0x24, 0xFC, 0x8A, 0xD8, 0xE4, 0xC0, 0x0A, - 0xC0, 0x79, 0xFA, 0xE4, 0xC1, 0x34, 0x80, 0x8A, 0xF8, 0xB9, 0x05, 0x00, 0xE4, 0xC0, 0x0A, 0xC0, - 0x79, 0xFA, 0xE4, 0xC1, 0xE2, 0xF6, 0x0A, 0xFB, 0x74, 0x38, 0x8B, 0xC6, 0x3D, 0xE2, 0x00, 0x7D, - 0x06, 0xBE, 0xDC, 0x00, 0xE9, 0x79, 0xFF, 0xE9, 0x73, 0xFF, 0x00, 0x03, 0x8F, 0x46, 0x07, 0x00, - 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1A, 0x07, 0x80, 0x28, 0x03, 0xDF, 0x1E, - 0x07, 0x02, 0x00, 0x01, 0x00, 0x46, 0x02, 0x00, 0x00, 0x01, 0x03, 0x05, 0x35, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x33, 0xC0, 0xE4, 0xC2, 0xB1, 0x02, 0xD3, 0xD8, 0x24, 0x01, 0x0C, 0x02, 0x8B, 0xC8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x52, 0x52, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x04, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00 }, - -{ 0xDB, 0xFD, 0x90, 0x90, 0xB0, 0xFF, 0xE6, 0xC3, 0xB9, 0x00, 0xA0, 0x50, 0x58, 0xE2, 0xFC, 0x33, /* 7 */ - 0xC0, 0x8E, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC, 0x04, 0x00, 0xBA, 0x90, 0x00, 0xBE, 0x00, 0x00, - 0x8B, 0xFE, 0xB9, 0x00, 0x01, 0xF3, 0xA5, 0xB0, 0xFE, 0xE6, 0xC3, 0xB0, 0x28, 0xE6, 0xC0, 0xB9, - 0x00, 0xA0, 0x50, 0x58, 0xE2, 0xFC, 0xB9, 0x03, 0x00, 0xBE, 0xCA, 0x00, 0xE8, 0xC1, 0x00, 0xB9, - 0x02, 0x00, 0xE8, 0xBB, 0x00, 0xEB, 0x19, 0x52, 0x52, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, - 0xE4, 0xC2, 0x0A, 0xC0, 0x79, 0xFA, 0xB0, 0x08, 0xE6, 0xC1, 0xB9, 0x00, 0xF0, 0x50, 0x58, 0xE2, - 0xFC, 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, 0xE4, 0xC1, 0x34, 0x20, 0x8A, 0xE0, 0xE4, 0xC0, 0x0A, - 0xC0, 0x79, 0xFA, 0xE4, 0xC1, 0x0A, 0xC4, 0x24, 0xFC, 0x74, 0x03, 0xE9, 0x91, 0x00, 0xB9, 0x03, - 0x00, 0xAC, 0xE6, 0xC2, 0xE2, 0xFB, 0xB9, 0x09, 0x00, 0xE8, 0x64, 0x00, 0xE4, 0xC0, 0x0A, 0xC0, - 0x79, 0xFA, 0xE4, 0xC1, 0x2C, 0x40, 0x24, 0xFC, 0x8A, 0xD8, 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, - 0xE4, 0xC1, 0x34, 0x80, 0x8A, 0xF8, 0xB9, 0x05, 0x00, 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, 0xE4, - 0xC1, 0xE2, 0xF6, 0x0A, 0xFB, 0x74, 0x20, 0xE9, 0x55, 0x00, 0x03, 0xDF, 0x1E, 0x07, 0x02, 0x00, - 0x02, 0x00, 0x46, 0x02, 0x00, 0x00, 0x01, 0x03, 0x05, 0x20, 0xFF, 0x00, 0xBE, 0x00, 0x02, 0xAC, - 0x3C, 0xE5, 0x75, 0x03, 0xE9, 0x40, 0xFF, 0xBE, 0x00, 0x02, 0xBF, 0x00, 0x01, 0xB9, 0x00, 0x12, - 0xF3, 0xA5, 0x33, 0xC0, 0xE4, 0xC2, 0xB1, 0x02, 0xD3, 0xD8, 0x24, 0x01, 0x0C, 0x02, 0x8B, 0xC8, - 0xFC, 0x33, 0xC0, 0xE4, 0xC0, 0x0A, 0xC0, 0x79, 0xFA, 0xAC, 0xE6, 0xC1, 0xE2, 0xF5, 0xC3, 0x43, - 0x6F, 0x6D, 0x70, 0x33, 0xC0, 0xEE, 0x0A, 0x44, 0x01, 0x74, 0xFB, 0x79, 0x01, 0xC3, 0x58, 0xBE, - 0x50, 0x00, 0xB0, 0x01, 0xEE, 0xB0, 0x00, 0x88, 0x44, 0x01, 0xEE, 0xB9, 0x00, 0xF0, 0x50, 0x58, - 0xE2, 0xFC, 0x0A, 0x44, 0x01, 0x75, 0x13, 0x88, 0x44, 0x01, 0xEE, 0xB9, 0x00, 0xF0, 0x50, 0x58, - 0xE2, 0xFC, 0x0A, 0x44, 0x01, 0x75, 0x03, 0xE9, 0xDD, 0xFE, 0xC7, 0x04, 0x05, 0x00, 0xE8, 0xC2, - 0xFF, 0xC7, 0x44, 0x04, 0x08, 0x01, 0xC7, 0x04, 0x02, 0x00, 0xE8, 0xB6, 0xFF, 0xC7, 0x44, 0x04, - 0x00, 0x00, 0xC7, 0x44, 0x0A, 0x00, 0x02, 0xC7, 0x44, 0x08, 0x02, 0x00, 0xC6, 0x44, 0x03, 0x01, - 0xC7, 0x04, 0x08, 0x00, 0xE8, 0x9C, 0xFF, 0xBE, 0x00, 0x02, 0xBF, 0x0F, 0x01, 0xB9, 0x04, 0x00, - 0xA6, 0x74, 0x03, 0xE9, 0xA1, 0xFE, 0xE2, 0xF8, 0xBE, 0x50, 0x00, 0xC7, 0x44, 0x0A, 0x10, 0x02, - 0xC7, 0x04, 0x03, 0x00, 0xE8, 0x7C, 0xFF, 0xC7, 0x44, 0x0A, 0x00, 0x06, 0xC7, 0x04, 0x04, 0x00, - 0xE8, 0x70, 0xFF, 0xC7, 0x44, 0x0A, 0x00, 0x02, 0xC7, 0x44, 0x08, 0x09, 0x00, 0xC6, 0x44, 0x03, - 0x01, 0x33, 0xC0, 0x89, 0x44, 0x04, 0x89, 0x44, 0x06, 0xC7, 0x04, 0x08, 0x00, 0xE8, 0x53, 0xFF, - 0xE9, 0x19, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x04, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00 }, - -{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x7F, 0x43, 0xF8, /* 8 */ - 0x00, 0x00, 0x24, 0x7C, 0x00, 0x00, 0x80, 0x00, 0x24, 0xD9, 0x51, 0xC8, 0xFF, 0xFC, 0x24, 0x7C, - 0x00, 0x00, 0x80, 0x2C, 0x42, 0x39, 0x00, 0xFF, 0x00, 0xC3, 0x4E, 0xD2, 0x49, 0xF9, 0x00, 0xFF, - 0x00, 0xC0, 0x4B, 0xEC, 0x00, 0x01, 0x4D, 0xEC, 0x00, 0x02, 0x43, 0xEC, 0x00, 0x02, 0x19, 0x7C, - 0x00, 0x80, 0x00, 0x03, 0x76, 0x07, 0x20, 0x7C, 0x00, 0x00, 0x81, 0xCC, 0x42, 0x14, 0x42, 0x16, - 0x42, 0x16, 0x42, 0x16, 0x70, 0x04, 0x07, 0x14, 0x67, 0xFC, 0x1A, 0x98, 0x51, 0xC8, 0xFF, 0xF8, - 0x60, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x74, 0x80, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x84, 0x80, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x94, 0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x00, 0xA4, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0xB4, 0x80, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x00, 0x50, 0x80, 0x00, 0x07, 0x16, 0x67, 0xFC, 0x1A, 0xBC, 0x00, 0x08, 0x3C, 0x3C, 0x00, 0x03, - 0x70, 0xFF, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x51, 0xC8, 0xFF, 0xF8, 0x51, 0xCE, 0xFF, 0xF2, - 0x07, 0x14, 0x67, 0xFC, 0x14, 0x15, 0x94, 0x3C, 0x00, 0x20, 0x07, 0x14, 0x67, 0xFC, 0x84, 0x15, - 0x66, 0x00, 0x00, 0x48, 0x74, 0x08, 0x07, 0x14, 0x67, 0xFC, 0x1A, 0x98, 0x51, 0xCA, 0xFF, 0xF8, - 0x07, 0x16, 0x67, 0xFC, 0x07, 0x14, 0x67, 0xFC, 0x10, 0x15, 0x90, 0x3C, 0x00, 0x40, 0x07, 0x14, - 0x67, 0xFC, 0xD0, 0x15, 0x90, 0x3C, 0x00, 0x80, 0x74, 0x04, 0x07, 0x14, 0x67, 0xFC, 0x1E, 0x15, - 0x51, 0xCA, 0xFF, 0xF8, 0x4A, 0x00, 0x66, 0x00, 0x00, 0x12, 0x1E, 0x11, 0xCE, 0xBC, 0x00, 0x00, - 0x00, 0x04, 0xE4, 0x07, 0x54, 0x07, 0x4E, 0xF8, 0x00, 0x00, 0x4D, 0xF9, 0x00, 0xFF, 0x00, 0x90, - 0x2A, 0x7C, 0x00, 0x00, 0x80, 0x64, 0x21, 0xFC, 0x00, 0x64, 0x80, 0x00, 0x00, 0x5C, 0x42, 0x2D, - 0x00, 0x01, 0x1C, 0xBC, 0x00, 0x01, 0x42, 0x16, 0x70, 0xFF, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, - 0x51, 0xC8, 0xFF, 0xF8, 0x4A, 0x2D, 0x00, 0x01, 0x6C, 0x00, 0xFE, 0xC2, 0x42, 0x2D, 0x00, 0x11, - 0x42, 0x16, 0x4A, 0x2D, 0x00, 0x11, 0x67, 0xFA, 0x6E, 0x00, 0xFE, 0xB2, 0x42, 0x2D, 0x00, 0x21, - 0x42, 0x16, 0x4A, 0x2D, 0x00, 0x21, 0x67, 0xFA, 0x6E, 0x00, 0xFE, 0xA2, 0x0C, 0xB8, 0x43, 0x6F, - 0x6D, 0x70, 0x00, 0x00, 0x66, 0x00, 0xFE, 0x96, 0x42, 0x2D, 0x00, 0x31, 0x42, 0x16, 0x4A, 0x2D, - 0x00, 0x31, 0x67, 0xFA, 0x6E, 0x00, 0xFE, 0x86, 0x42, 0x2D, 0x00, 0x41, 0x42, 0x16, 0x4A, 0x2D, - 0x00, 0x41, 0x67, 0xFA, 0x6E, 0x00, 0xFE, 0x76, 0x42, 0x2D, 0x00, 0x51, 0x42, 0x16, 0x4A, 0x2D, - 0x00, 0x51, 0x67, 0xFA, 0x6E, 0x00, 0xFE, 0x66, 0x60, 0x00, 0xFF, 0x60, 0x03, 0x8F, 0x46, 0x07, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1A, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - -{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x43, 0xF9, 0x00, 0xFF, 0x00, 0x90, 0x20, 0x3C, /* 9 */ - 0x00, 0x00, 0x00, 0x7F, 0x45, 0xF8, 0x00, 0x00, 0x26, 0x7C, 0x00, 0x00, 0x80, 0x00, 0x26, 0xDA, - 0x51, 0xC8, 0xFF, 0xFC, 0x24, 0x7C, 0x00, 0x00, 0x80, 0x34, 0x41, 0xF9, 0x00, 0xFF, 0x00, 0xC3, - 0x42, 0x10, 0x4E, 0xD2, 0x2A, 0x7C, 0x00, 0x00, 0x80, 0x66, 0x21, 0xFC, 0x00, 0x66, 0x80, 0x00, - 0x00, 0x5C, 0x42, 0x2D, 0x00, 0x01, 0x12, 0xBC, 0x00, 0x01, 0x42, 0x11, 0x70, 0xFF, 0x4E, 0x71, - 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x51, 0xC8, 0xFF, 0xF4, 0x4A, 0x2D, 0x00, 0x01, - 0x6C, 0xD2, 0x60, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x76, 0x80, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x86, 0x80, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x96, 0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0xA6, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x00, 0xB6, 0x80, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x80, 0x00, 0x42, 0x2D, 0x00, 0x11, 0x42, 0x11, 0x4A, 0x2D, 0x00, 0x11, - 0x67, 0xFA, 0x6E, 0x00, 0xFF, 0x60, 0x42, 0x2D, 0x00, 0x21, 0x42, 0x11, 0x4A, 0x2D, 0x00, 0x21, - 0x67, 0xFA, 0x6E, 0x00, 0xFF, 0x50, 0x20, 0x38, 0x00, 0x00, 0xB0, 0xBC, 0x43, 0x6F, 0x6D, 0x70, - 0x66, 0x00, 0xFF, 0x42, 0x42, 0x2D, 0x00, 0x31, 0x42, 0x11, 0x4A, 0x2D, 0x00, 0x31, 0x67, 0xFA, - 0x6E, 0x00, 0xFF, 0x32, 0x42, 0x2D, 0x00, 0x41, 0x42, 0x11, 0x4A, 0x2D, 0x00, 0x41, 0x67, 0xFA, - 0x6E, 0x00, 0xFF, 0x22, 0x42, 0x2D, 0x00, 0x51, 0x42, 0x11, 0x4A, 0x2D, 0x00, 0x51, 0x67, 0xFA, - 0x6E, 0x00, 0xFF, 0x12, 0x53, 0x88, 0x1E, 0x10, 0xCE, 0xBC, 0x00, 0x00, 0x00, 0x04, 0xE4, 0x07, - 0x54, 0x07, 0x4E, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - -{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x7F, 0x41, 0xF8, /* A */ - 0x00, 0x00, 0x22, 0x7C, 0x00, 0x00, 0x80, 0x00, 0x22, 0xD8, 0x51, 0xC8, 0xFF, 0xFC, 0x24, 0x7C, - 0x00, 0x00, 0x80, 0x2C, 0x42, 0x39, 0x00, 0xFF, 0x00, 0xC3, 0x4E, 0xD2, 0x41, 0xF9, 0x00, 0xFF, - 0x00, 0xC0, 0x43, 0xE8, 0x00, 0x01, 0x45, 0xE8, 0x00, 0x02, 0x47, 0xE8, 0x00, 0x03, 0x17, 0x7C, - 0x00, 0x80, 0x00, 0x00, 0x70, 0x07, 0x42, 0x10, 0x28, 0x7C, 0x00, 0x00, 0x81, 0x42, 0x42, 0x12, - 0x42, 0x12, 0x42, 0x12, 0x72, 0x02, 0x01, 0x10, 0x67, 0xFC, 0x12, 0x9C, 0x51, 0xC9, 0xFF, 0xF8, - 0x72, 0xFF, 0x4E, 0x71, 0x51, 0xC9, 0xFF, 0xFC, 0x72, 0x01, 0x01, 0x10, 0x67, 0xFC, 0x12, 0x9C, - 0x51, 0xC9, 0xFF, 0xF8, 0x01, 0x12, 0x67, 0xFC, 0x12, 0xBC, 0x00, 0x08, 0x72, 0xFF, 0x4E, 0x71, - 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x51, 0xC9, 0xFF, 0xF4, 0x01, 0x10, 0x67, 0xFC, - 0x12, 0x11, 0x92, 0x3C, 0x00, 0x20, 0x01, 0x10, 0x67, 0xFC, 0x82, 0x11, 0x67, 0x00, 0x00, 0x5C, - 0xD9, 0xFC, 0x00, 0x00, 0x00, 0x09, 0x10, 0xBC, 0x00, 0x28, 0x72, 0x02, 0x01, 0x10, 0x67, 0xFC, - 0x12, 0x9C, 0x51, 0xC9, 0xFF, 0xF8, 0x72, 0xFF, 0x4E, 0x71, 0x51, 0xC9, 0xFF, 0xFC, 0x72, 0x01, - 0x01, 0x10, 0x67, 0xFC, 0x12, 0x9C, 0x51, 0xC9, 0xFF, 0xF8, 0x01, 0x12, 0x67, 0xFC, 0x12, 0xBC, - 0x00, 0x08, 0x72, 0xFF, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x51, 0xC9, - 0xFF, 0xF4, 0x01, 0x10, 0x67, 0xFC, 0x12, 0x11, 0x92, 0x3C, 0x00, 0x20, 0x01, 0x10, 0x67, 0xFC, - 0x82, 0x11, 0xC2, 0x3C, 0x00, 0xFC, 0x66, 0x00, 0xFF, 0x4E, 0x72, 0x08, 0x01, 0x10, 0x67, 0xFC, - 0x12, 0x9C, 0x51, 0xC9, 0xFF, 0xF8, 0x01, 0x12, 0x67, 0xFC, 0x01, 0x10, 0x67, 0xFC, 0x14, 0x11, - 0x94, 0x3C, 0x00, 0x40, 0x01, 0x10, 0x67, 0xFC, 0xD4, 0x11, 0x94, 0x3C, 0x00, 0x80, 0x72, 0x04, - 0x01, 0x10, 0x67, 0xFC, 0x1E, 0x11, 0x51, 0xC9, 0xFF, 0xF8, 0xC4, 0x3C, 0x00, 0xF8, 0x66, 0x00, - 0xFF, 0x16, 0x1E, 0x12, 0xCE, 0xBC, 0x00, 0x00, 0x00, 0x04, 0xE4, 0x07, 0x54, 0x07, 0x4E, 0xF8, - 0x00, 0x00, 0x03, 0x8F, 0x46, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1A, 0x07, 0x80, - 0x03, 0xEF, 0x1E, 0x07, 0x02, 0xC6, 0x02, 0x00, 0x00, 0x01, 0x03, 0x05, 0x20, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - -{ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x7F, 0x43, 0xF8, /* B */ - 0x00, 0x00, 0x24, 0x7C, 0x00, 0x00, 0x80, 0x00, 0x24, 0xD9, 0x51, 0xC8, 0xFF, 0xFC, 0x24, 0x7C, - 0x00, 0x00, 0x80, 0x2C, 0x42, 0x39, 0x00, 0xFF, 0x00, 0xC3, 0x4E, 0xD2, 0x49, 0xF9, 0x00, 0xFF, - 0x00, 0xC0, 0x4B, 0xEC, 0x00, 0x01, 0x4D, 0xEC, 0x00, 0x02, 0x43, 0xEC, 0x00, 0x02, 0x19, 0x7C, - 0x00, 0x80, 0x00, 0x03, 0x76, 0x07, 0x18, 0xBC, 0x00, 0x28, 0x20, 0x7C, 0x00, 0x00, 0x81, 0xCE, - 0x42, 0x16, 0x42, 0x16, 0x42, 0x16, 0x70, 0x04, 0x07, 0x14, 0x67, 0xFC, 0x1A, 0x98, 0x51, 0xC8, - 0xFF, 0xF8, 0x60, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x76, 0x80, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x86, 0x80, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x96, 0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0xA6, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x00, 0xB6, 0x80, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x07, 0x16, 0x67, 0xFC, 0x1A, 0xBC, 0x00, 0x08, 0x3C, 0x3C, - 0x00, 0x03, 0x70, 0xFF, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x51, 0xC8, 0xFF, 0xF8, 0x51, 0xCE, - 0xFF, 0xF2, 0x07, 0x14, 0x67, 0xFC, 0x14, 0x15, 0x94, 0x3C, 0x00, 0x22, 0x07, 0x14, 0x67, 0xFC, - 0x84, 0x15, 0x66, 0x00, 0x00, 0x48, 0x74, 0x08, 0x07, 0x14, 0x67, 0xFC, 0x1A, 0x98, 0x51, 0xCA, - 0xFF, 0xF8, 0x07, 0x16, 0x67, 0xFC, 0x07, 0x14, 0x67, 0xFC, 0x10, 0x15, 0x90, 0x3C, 0x00, 0x42, - 0x07, 0x14, 0x67, 0xFC, 0xD0, 0x15, 0x90, 0x3C, 0x00, 0x80, 0x74, 0x03, 0x07, 0x14, 0x67, 0xFC, - 0x1E, 0x15, 0x51, 0xCA, 0xFF, 0xF8, 0x4A, 0x00, 0x66, 0x00, 0x00, 0x12, 0x1E, 0x11, 0xCE, 0xBC, - 0x00, 0x00, 0x00, 0x04, 0xE4, 0x07, 0x54, 0x07, 0x4E, 0xF8, 0x00, 0x00, 0x4D, 0xF9, 0x00, 0xFF, - 0x00, 0x90, 0x2A, 0x7C, 0x00, 0x00, 0x80, 0x66, 0x21, 0xFC, 0x00, 0x66, 0x80, 0x00, 0x00, 0x5C, - 0x42, 0x2D, 0x00, 0x01, 0x1C, 0xBC, 0x00, 0x01, 0x42, 0x16, 0x70, 0xFF, 0x4E, 0x71, 0x4E, 0x71, - 0x4E, 0x71, 0x51, 0xC8, 0xFF, 0xF8, 0x4A, 0x2D, 0x00, 0x01, 0x6C, 0x00, 0xFE, 0xC0, 0x42, 0x2D, - 0x00, 0x11, 0x42, 0x16, 0x4A, 0x2D, 0x00, 0x11, 0x67, 0xFA, 0x6E, 0x00, 0xFE, 0xB0, 0x42, 0x2D, - 0x00, 0x21, 0x42, 0x16, 0x4A, 0x2D, 0x00, 0x21, 0x67, 0xFA, 0x6E, 0x00, 0xFE, 0xA0, 0x0C, 0xB8, - 0x43, 0x6F, 0x6D, 0x70, 0x00, 0x00, 0x66, 0x00, 0xFE, 0x94, 0x42, 0x2D, 0x00, 0x31, 0x42, 0x16, - 0x4A, 0x2D, 0x00, 0x31, 0x67, 0xFA, 0x6E, 0x00, 0xFE, 0x84, 0x42, 0x2D, 0x00, 0x41, 0x42, 0x16, - 0x4A, 0x2D, 0x00, 0x41, 0x67, 0xFA, 0x6E, 0x00, 0xFE, 0x74, 0x42, 0x2D, 0x00, 0x51, 0x42, 0x16, - 0x4A, 0x2D, 0x00, 0x51, 0x67, 0xFA, 0x6E, 0x00, 0xFE, 0x64, 0x60, 0x00, 0xFF, 0x60, 0x03, 0xEF, - 0x1E, 0x07, 0x02, 0xC6, 0x02, 0x00, 0x00, 0x01, 0x03, 0x05, 0x20, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - -{ 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, 0x0E, 0x03, 0x00, 0x27, 0xA9, 0xC0, /* C */ - 0xFE, 0x00, 0xC0, 0x67, 0x61, 0x01, 0xA7, 0x61, 0x02, 0x67, 0x60, 0x03, 0x54, 0xA2, 0x80, 0x00, - 0xDC, 0x1B, 0x5C, 0x60, 0x00, 0xE7, 0xA9, 0xC0, 0x00, 0x01, 0xCD, 0x5C, 0x70, 0x00, 0x5C, 0x71, - 0x00, 0x5C, 0x70, 0x00, 0xDC, 0x12, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, 0x8C, - 0x38, 0xCC, 0x17, 0x75, 0xEA, 0xC0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x90, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0xA0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xB0, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, - 0xB4, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0xA3, 0x08, 0x00, 0xDD, 0x17, 0xA2, 0xA2, 0xA2, 0xCD, 0x17, - 0x7D, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x94, 0x68, 0x00, 0xA0, 0xA0, 0x20, 0x34, 0x1B, 0x00, 0x9A, - 0x7D, 0x98, 0x68, 0x00, 0x1C, 0x10, 0x1A, 0xC0, 0x00, 0x00, 0x56, 0x94, 0xA0, 0x09, 0x34, 0x1B, - 0x00, 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, 0x8C, 0x38, 0xCC, 0x17, 0x75, 0xB4, 0x1B, 0x00, 0x9A, - 0x7D, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x14, 0x68, 0x00, 0x20, 0xA0, 0x40, 0x34, 0x1B, 0x00, 0x9A, - 0x7D, 0x00, 0x68, 0x00, 0x20, 0xA0, 0x80, 0xDC, 0x12, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0xD4, 0x69, - 0x00, 0xCC, 0x17, 0x78, 0x1C, 0x00, 0x1A, 0xC0, 0x00, 0x00, 0x16, 0xCE, 0xD8, 0x71, 0x00, 0xE8, - 0xA1, 0x04, 0x4E, 0xC4, 0xA1, 0xFE, 0x0C, 0x39, 0x7F, 0xAA, 0x82, 0x00, 0xA7, 0xA9, 0xC0, 0xFE, - 0x00, 0x90, 0x5C, 0xA8, 0x80, 0x61, 0xDC, 0x70, 0x00, 0x5C, 0x70, 0x00, 0xDD, 0x07, 0xA2, 0xA2, - 0xA2, 0xCD, 0x07, 0x7D, 0x9C, 0xAF, 0x80, 0x61, 0x1A, 0xBE, 0xB5, 0x5C, 0xA8, 0x80, 0x71, 0x5C, - 0x70, 0x00, 0x1C, 0xA8, 0x80, 0x71, 0x0A, 0x7C, 0x9C, 0xAF, 0x80, 0x71, 0x1A, 0xBE, 0xA1, 0x5C, - 0xA8, 0x80, 0x81, 0x5C, 0x70, 0x00, 0x1C, 0xA8, 0x80, 0x81, 0x0A, 0x7C, 0x9C, 0xAF, 0x80, 0x81, - 0x1A, 0xBE, 0x8D, 0x47, 0xA5, 0x70, 0x6D, 0x6F, 0x43, 0x82, 0x00, 0x1A, 0xBE, 0x82, 0x5C, 0xA8, - 0x80, 0x91, 0x5C, 0x70, 0x00, 0x1C, 0xA8, 0x80, 0x91, 0x0A, 0x7C, 0x9C, 0xAF, 0x80, 0x91, 0x1A, - 0xBE, 0x6E, 0x5C, 0xA8, 0x80, 0xA1, 0x5C, 0x70, 0x00, 0x1C, 0xA8, 0x80, 0xA1, 0x0A, 0x7C, 0x9C, - 0xAF, 0x80, 0xA1, 0x1A, 0xBE, 0x5A, 0x5C, 0xA8, 0x80, 0xB1, 0x5C, 0x70, 0x00, 0x1C, 0xA8, 0x80, - 0xB1, 0x0A, 0x7C, 0x9C, 0xAF, 0x80, 0xB1, 0x1A, 0xBE, 0x46, 0xEA, 0xBF, 0x61, 0x03, 0x8F, 0x1E, - 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1A, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - -{ 0xA7, 0xA9, 0xC0, 0xFE, 0x00, 0x90, 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, /* D */ - 0x0E, 0x03, 0x00, 0x67, 0xA8, 0xC0, 0xFE, 0x00, 0xC3, 0x5C, 0x48, 0x00, 0x5C, 0xA8, 0xC0, 0x00, - 0x00, 0x61, 0xDC, 0x70, 0x00, 0x5C, 0x70, 0x00, 0xDD, 0x07, 0xA2, 0xA2, 0xA2, 0xCD, 0x07, 0x7D, - 0x9C, 0xAF, 0xC0, 0x00, 0x00, 0x61, 0x1A, 0x66, 0xEA, 0xC0, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x90, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0xA0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xB0, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, - 0x5C, 0xA8, 0x80, 0x71, 0x5C, 0x70, 0x00, 0x1C, 0xA8, 0x80, 0x71, 0x0A, 0x7C, 0x9C, 0xAF, 0x80, - 0x71, 0x1A, 0xBF, 0x4B, 0x5C, 0xA8, 0x80, 0x81, 0x5C, 0x70, 0x00, 0x1C, 0xA8, 0x80, 0x81, 0x0A, - 0x7C, 0x9C, 0xAF, 0x80, 0x81, 0x1A, 0xBF, 0x37, 0x47, 0xA5, 0x70, 0x6D, 0x6F, 0x43, 0x82, 0x00, - 0x1A, 0xBF, 0x2C, 0x5C, 0xA8, 0x80, 0x91, 0x5C, 0x70, 0x00, 0x1C, 0xA8, 0x80, 0x91, 0x0A, 0x7C, - 0x9C, 0xAF, 0x80, 0x91, 0x1A, 0xBF, 0x18, 0x5C, 0xA8, 0x80, 0xA1, 0x5C, 0x70, 0x00, 0x1C, 0xA8, - 0x80, 0xA1, 0x0A, 0x7C, 0x9C, 0xAF, 0x80, 0xA1, 0x1A, 0xBF, 0x04, 0x5C, 0xA8, 0x80, 0xB1, 0x5C, - 0x70, 0x00, 0x1C, 0xA8, 0x80, 0xB1, 0x0A, 0x7C, 0x9C, 0xAF, 0x80, 0xB1, 0x1A, 0xBE, 0xF0, 0x8F, - 0x0F, 0xCE, 0xD8, 0x49, 0x00, 0xE8, 0xA1, 0x04, 0x4E, 0xC4, 0xA1, 0xFE, 0x0C, 0x39, 0x7F, 0xAA, - 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - -{ 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, 0x0E, 0x03, 0x00, 0x27, 0xA9, 0xC0, /* E */ - 0xFE, 0x00, 0xC0, 0x67, 0x61, 0x01, 0xA7, 0x61, 0x02, 0x67, 0x60, 0x03, 0x54, 0xA2, 0x80, 0x00, - 0xDC, 0x1B, 0x5C, 0x60, 0x00, 0xE7, 0xA9, 0xC0, 0x00, 0x01, 0x33, 0x5C, 0x70, 0x00, 0x5C, 0x71, - 0x00, 0x5C, 0x70, 0x00, 0xDC, 0x11, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, 0x8C, - 0x38, 0xCC, 0x17, 0x75, 0xDC, 0x07, 0xA2, 0xA2, 0xCC, 0x07, 0x7E, 0x5C, 0x11, 0x34, 0x1B, 0x00, - 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, 0x8C, 0x38, 0xCC, 0x17, 0x75, 0xB4, 0x1B, 0x00, 0x9A, 0x7D, - 0x54, 0xA3, 0x08, 0x00, 0xDD, 0x17, 0xA2, 0xA2, 0xA2, 0xCD, 0x17, 0x7D, 0x34, 0x1B, 0x00, 0x9A, - 0x7D, 0x94, 0x68, 0x00, 0xA0, 0xA0, 0x20, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x98, 0x68, 0x00, 0x1C, - 0x10, 0x0A, 0xC0, 0x00, 0x00, 0x60, 0xC1, 0xA1, 0x00, 0x09, 0x14, 0xA3, 0x28, 0x00, 0xDC, 0x11, - 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, 0x8C, 0x38, 0xCC, 0x17, 0x75, 0xDC, 0x07, - 0xA2, 0xA2, 0xCC, 0x07, 0x7E, 0x5C, 0x11, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, - 0x8C, 0x38, 0xCC, 0x17, 0x75, 0xB4, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0xA3, 0x08, 0x00, 0xDD, 0x17, - 0xA2, 0xA2, 0xA2, 0xCD, 0x17, 0x7D, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x94, 0x68, 0x00, 0xA0, 0xA0, - 0x20, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x98, 0x68, 0x00, 0xA8, 0xA0, 0xFC, 0x1C, 0x10, 0x1A, 0xBF, - 0x44, 0x94, 0xA0, 0x09, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, 0x8C, 0x38, 0xCC, - 0x17, 0x75, 0xB4, 0x1B, 0x00, 0x9A, 0x7D, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x14, 0x68, 0x00, 0x20, - 0xA0, 0x40, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x00, 0x68, 0x00, 0x20, 0xA0, 0x80, 0xDC, 0x12, 0x34, - 0x1B, 0x00, 0x9A, 0x7D, 0xD4, 0x69, 0x00, 0xCC, 0x17, 0x78, 0x28, 0xA0, 0xF8, 0x1C, 0x00, 0x1A, - 0xBF, 0x03, 0xCE, 0xD8, 0x71, 0x00, 0xE8, 0xA1, 0x04, 0x4E, 0xC4, 0xA1, 0xFE, 0x0C, 0x39, 0x7F, - 0xAA, 0x82, 0x00, 0x03, 0x8F, 0x46, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1A, 0x07, - 0x80, 0x03, 0xEF, 0x1E, 0x07, 0x02, 0xC6, 0x02, 0x00, 0x00, 0x01, 0x03, 0x05, 0x20, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - -{ 0x17, 0xA0, 0x00, 0x00, 0x00, 0x80, 0x5F, 0x08, 0x5F, 0x10, 0x0E, 0x03, 0x00, 0x27, 0xA9, 0xC0, /* F */ - 0xFE, 0x00, 0xC0, 0x67, 0x61, 0x01, 0xA7, 0x61, 0x02, 0x67, 0x60, 0x03, 0x54, 0xA2, 0x80, 0x00, - 0xDC, 0x1B, 0x14, 0xA3, 0x28, 0x00, 0xE7, 0xA9, 0xC0, 0x00, 0x01, 0xCD, 0x5C, 0x70, 0x00, 0x5C, - 0x71, 0x00, 0x5C, 0x70, 0x00, 0xDC, 0x12, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, - 0x8C, 0x38, 0xCC, 0x17, 0x75, 0xEA, 0xC0, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x90, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0xA0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xB0, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, - 0xB4, 0x1B, 0x00, 0x9A, 0x7D, 0x54, 0xA3, 0x08, 0x00, 0xDD, 0x17, 0xA2, 0xA2, 0xA2, 0xCD, 0x17, - 0x7D, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x94, 0x68, 0x00, 0xA0, 0xA0, 0x22, 0x34, 0x1B, 0x00, 0x9A, - 0x7D, 0x98, 0x68, 0x00, 0x1C, 0x10, 0x1A, 0xC0, 0x00, 0x00, 0x56, 0x94, 0xA0, 0x09, 0x34, 0x1B, - 0x00, 0x9A, 0x7D, 0x54, 0x7B, 0x00, 0x00, 0x8C, 0x38, 0xCC, 0x17, 0x75, 0xB4, 0x1B, 0x00, 0x9A, - 0x7D, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0x14, 0x68, 0x00, 0x20, 0xA0, 0x42, 0x34, 0x1B, 0x00, 0x9A, - 0x7D, 0x00, 0x68, 0x00, 0x20, 0xA0, 0x80, 0xDC, 0x12, 0x34, 0x1B, 0x00, 0x9A, 0x7D, 0xD4, 0x69, - 0x00, 0xCC, 0x17, 0x78, 0x1C, 0x00, 0x1A, 0xC0, 0x00, 0x00, 0x16, 0xCE, 0xD8, 0x71, 0x00, 0xE8, - 0xA1, 0x04, 0x4E, 0xC4, 0xA1, 0xFE, 0x0C, 0x39, 0x7F, 0xAA, 0x82, 0x00, 0xA7, 0xA9, 0xC0, 0xFE, - 0x00, 0x90, 0x5C, 0xA8, 0x80, 0x61, 0xDC, 0x70, 0x00, 0x5C, 0x70, 0x00, 0xDD, 0x07, 0xA2, 0xA2, - 0xA2, 0xCD, 0x07, 0x7D, 0x9C, 0xAF, 0x80, 0x61, 0x1A, 0xBE, 0xB5, 0x5C, 0xA8, 0x80, 0x71, 0x5C, - 0x70, 0x00, 0x1C, 0xA8, 0x80, 0x71, 0x0A, 0x7C, 0x9C, 0xAF, 0x80, 0x71, 0x1A, 0xBE, 0xA1, 0x5C, - 0xA8, 0x80, 0x81, 0x5C, 0x70, 0x00, 0x1C, 0xA8, 0x80, 0x81, 0x0A, 0x7C, 0x9C, 0xAF, 0x80, 0x81, - 0x1A, 0xBE, 0x8D, 0x47, 0xA5, 0x70, 0x6D, 0x6F, 0x43, 0x82, 0x00, 0x1A, 0xBE, 0x82, 0x5C, 0xA8, - 0x80, 0x91, 0x5C, 0x70, 0x00, 0x1C, 0xA8, 0x80, 0x91, 0x0A, 0x7C, 0x9C, 0xAF, 0x80, 0x91, 0x1A, - 0xBE, 0x6E, 0x5C, 0xA8, 0x80, 0xA1, 0x5C, 0x70, 0x00, 0x1C, 0xA8, 0x80, 0xA1, 0x0A, 0x7C, 0x9C, - 0xAF, 0x80, 0xA1, 0x1A, 0xBE, 0x5A, 0x5C, 0xA8, 0x80, 0xB1, 0x5C, 0x70, 0x00, 0x1C, 0xA8, 0x80, - 0xB1, 0x0A, 0x7C, 0x9C, 0xAF, 0x80, 0xB1, 0x1A, 0xBE, 0x46, 0xEA, 0xBF, 0x61, 0x03, 0xEF, 0x1E, - 0x07, 0x02, 0xC6, 0x02, 0x00, 0x00, 0x01, 0x03, 0x05, 0x20, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - - -/* returns TRUE iff there exists a disk with VERBOSE */ -static int32 disk1a_hasProperty(uint32 property) { - int32 i; - for (i = 0; i < DISK1A_MAX_DRIVES; i++) - if (disk1a_dev.units[i].flags & property) - return TRUE; - return FALSE; -} - -/* Reset routine */ -static t_stat disk1a_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect ROM and I/O Ports */ - if (disk1a_hasProperty(UNIT_DISK1A_ROM)) - sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &disk1arom, TRUE); - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &disk1adev, TRUE); - } else { - /* Connect DISK1A ROM at base address */ - if (disk1a_hasProperty(UNIT_DISK1A_ROM)) - if(sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &disk1arom, FALSE) != 0) { - printf("%s: error mapping MEM resource at 0x%04x\n", __FUNCTION__, pnp->mem_base); - return SCPE_ARG; - } - - /* Connect DISK1A at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &disk1adev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - return SCPE_OK; -} - -static t_stat disk1a_boot(int32 unitno, DEVICE *dptr) -{ - bootstrap &= 0xF; - DBG_PRINT(("Booting DISK1A Controller, bootstrap=%d" NLP, bootstrap)); - - /* Re-enable the ROM in case it was disabled */ - disk1a_info->rom_disabled = FALSE; - - /* Set the PC to 0, and go. */ - *((int32 *) sim_PC->loc) = 0; - return SCPE_OK; -} - -/* Attach routine */ -static t_stat disk1a_attach(UNIT *uptr, char *cptr) -{ - t_stat r; - r = i8272_attach(uptr, cptr); - - return r; -} - -/* Detach routine */ -static t_stat disk1a_detach(UNIT *uptr) -{ - t_stat r; - - r = i8272_detach(uptr); - - return r; -} - -static int32 disk1arom(const int32 Addr, const int32 write, const int32 data) -{ -/* DBG_PRINT(("DISK1A: ROM %s, Addr %04x" NLP, write ? "WR" : "RD", Addr)); */ - if(write) { - disk1aram[Addr & 0x1FF] = data; - return 0; - } else { - bootstrap &= 0xF; - if(disk1a_info->rom_disabled == FALSE) { - return(disk1a_rom[bootstrap][Addr & 0x1FF]); - } else { - return(disk1aram[Addr & 0x1FF]); - } - } -} - -static int32 disk1adev(const int32 port, const int32 io, const int32 data) -{ - int32 result; - if(io) { - sim_debug(VERBOSE_MSG, &disk1a_dev, "DISK1A: " ADDRESS_FORMAT - " OUT, Port 0x%02x Data 0x%02x\n", PCX, port, data); - DISK1A_Write(port, data); - result = 0; - } else { - result = DISK1A_Read(port); - sim_debug(VERBOSE_MSG, &disk1a_dev, "DISK1A: " ADDRESS_FORMAT " IN, Port 0x%02x Result 0x%02x\n", PCX, port, result); - } - return result; -} - -#define DISK1A_DRIVE_STATUS 2 /* R=Drive Status Register / W=DMA Address Register */ -#define DISK1A_MOTOR 3 /* R=Unused / W=Motor Control Register */ -#define BOOT_PROM_DISABLE 0x01 -#define FLOPPY_MOTORS 0xF0 -extern uint8 i8272_irq; -static uint8 DISK1A_Read(const uint32 Addr) -{ - uint8 cData; - - cData = 0x00; - - switch(Addr & 0x3) { - case I8272_FDC_MSR: - case I8272_FDC_DATA: - cData = I8272_Read(Addr); - break; - case DISK1A_DRIVE_STATUS: - cData = i8272_irq ? 0x81 : 0x01; /* Ready */ - sim_debug(STATUS_MSG, &disk1a_dev, "DISK1A: " ADDRESS_FORMAT " RD STATUS = 0x%02x\n", PCX, cData); - break; - case DISK1A_MOTOR: - sim_debug(VERBOSE_MSG, &disk1a_dev, "DISK1A: " ADDRESS_FORMAT " Error, can't read from MOTOR register.\n", PCX); - cData = 0xFF; /* Return High-Z data */ - break; - } - - return (cData); -} - -static uint8 DISK1A_Write(const uint32 Addr, uint8 cData) -{ - uint8 result = 0; - - switch(Addr & 0x3) { - case I8272_FDC_MSR: - case I8272_FDC_DATA: - result = I8272_Write(Addr, cData); - break; - - case DISK1A_DRIVE_STATUS: /* DMA Address */ - disk1a_info->dma_addr <<= 8; - disk1a_info->dma_addr &= 0x00FFFF00; - disk1a_info->dma_addr |= cData; - sim_debug(RD_DATA_MSG, &disk1a_dev, "DISK1A: " ADDRESS_FORMAT - " DMA Address=%06x\n", PCX, disk1a_info->dma_addr); - I8272_Set_DMA(disk1a_info->dma_addr); - break; - case DISK1A_MOTOR: - sim_debug(CMD_MSG, &disk1a_dev, "DISK1A: " ADDRESS_FORMAT - " write Motor Reg=0x%02x\n", PCX, cData); - - if((cData & BOOT_PROM_DISABLE) == 0) { - sim_debug(CMD_MSG, &disk1a_dev, "DISK1A: " ADDRESS_FORMAT - " Boot ROM disabled\n", PCX); - - /* Unmap Boot ROM */ - disk1a_info->rom_disabled = TRUE; - } - - sim_debug(CMD_MSG, &disk1a_dev, "DISK1A: " ADDRESS_FORMAT - " Motors = %x\n", PCX, (cData & FLOPPY_MOTORS) >> 4); - break; - } - - return (result); -} - -#define SS1_VI4_INT 4 /* IF3 Tx interrupts tied to VI3 */ - -void raise_disk1a_interrupt(void) -{ - sim_debug(IRQ_MSG, &disk1a_dev, "DISK1A: " ADDRESS_FORMAT " Interrupt\n", PCX); - - raise_ss1_interrupt(SS1_VI4_INT); - -} diff --git a/AltairZ80/s100_disk2.c b/AltairZ80/s100_disk2.c deleted file mode 100644 index 597294df..00000000 --- a/AltairZ80/s100_disk2.c +++ /dev/null @@ -1,627 +0,0 @@ -/************************************************************************* - * * - * $Id: s100_disk2.c 1995 2008-07-15 03:59:13Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * CompuPro DISK2 Hard Disk Controller module for SIMH. * - * This module must be used in conjunction with the CompuPro Selector * - * Channel Module for proper operation. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#include "sim_imd.h" - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define STATUS_MSG (1 << 5) -#define IRQ_MSG (1 << 6) -#define VERBOSE_MSG (1 << 7) - -#define DISK2_MAX_DRIVES 4 - -typedef union { - uint8 raw[2051]; - struct { - uint8 header[3]; - uint8 data[2048]; - } u; -} SECTOR_FORMAT; - -static SECTOR_FORMAT sdata; - -typedef struct { - UNIT *uptr; - DISK_INFO *imd; - uint16 ntracks; /* number of tracks */ - uint8 nheads; /* number of heads */ - uint8 nsectors; /* number of sectors/track */ - uint32 sectsize; /* sector size, not including pre/postamble */ - uint16 track; /* Current Track */ - uint8 ready; /* Is drive ready? */ -} DISK2_DRIVE_INFO; - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint8 sel_drive; /* Currently selected drive */ - uint8 head_sel; /* Head select (signals to drive itself) */ - uint8 head; /* Head set by write to the HEAD register */ - uint8 cyl; /* Cyl that the current operation is targetting */ - uint8 sector; /* Sector the current READ/WRITE operation is targetting */ - uint8 hdr_sector; /* Current sector for WRITE_HEADER */ - uint8 ctl_attn; - uint8 ctl_run; - uint8 ctl_op; - uint8 ctl_fault_clr; - uint8 ctl_us; - uint8 timeout; - uint8 crc_error; - uint8 overrun; - uint8 seek_complete; - uint8 write_fault; - DISK2_DRIVE_INFO drive[DISK2_MAX_DRIVES]; -} DISK2_INFO; - -static DISK2_INFO disk2_info_data = { { 0x0, 0, 0xC8, 2 } }; -static DISK2_INFO *disk2_info = &disk2_info_data; - -/* Default geometry for a 20MB hard disk. */ -#define C20MB_NTRACKS 243 -#define C20MB_NHEADS 8 -#define C20MB_NSECTORS 11 -#define C20MB_SECTSIZE 1024 - -static int32 ntracks = C20MB_NTRACKS; -static int32 nheads = C20MB_NHEADS; -static int32 nsectors = C20MB_NSECTORS; -static int32 sectsize = C20MB_SECTSIZE; - -extern uint32 PCX; -extern REG *sim_PC; -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern int32 selchan_dma(uint8 *buf, uint32 len); -extern int32 find_unit_index(UNIT *uptr); -extern void raise_ss1_interrupt(uint8 intnum); - -#define UNIT_V_DISK2_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_DISK2_WLK (1 << UNIT_V_DISK2_WLK) -#define UNIT_V_DISK2_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_DISK2_VERBOSE (1 << UNIT_V_DISK2_VERBOSE) -#define DISK2_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */ - -static t_stat disk2_reset(DEVICE *disk2_dev); -static t_stat disk2_attach(UNIT *uptr, char *cptr); -static t_stat disk2_detach(UNIT *uptr); -static void raise_disk2_interrupt(void); - -static int32 disk2dev(const int32 port, const int32 io, const int32 data); - -static uint8 DISK2_Read(const uint32 Addr); -static uint8 DISK2_Write(const uint32 Addr, uint8 cData); - -static UNIT disk2_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK2_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK2_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK2_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK2_CAPACITY) } -}; - -static REG disk2_reg[] = { - { DRDATA (NTRACKS, ntracks, 10), }, - { DRDATA (NHEADS, nheads, 8), }, - { DRDATA (NSECTORS, nsectors, 8), }, - { DRDATA (SECTSIZE, sectsize, 11), }, - { HRDATA (SEL_DRIVE, disk2_info_data.sel_drive, 3), }, - { HRDATA (CYL, disk2_info_data.cyl, 8), }, - { HRDATA (HEAD, disk2_info_data.head, 8), }, - { HRDATA (SECTOR, disk2_info_data.sector, 8), }, - - { NULL } -}; - -static MTAB disk2_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_DISK2_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_DISK2_WLK, UNIT_DISK2_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_DISK2_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_DISK2_VERBOSE, UNIT_DISK2_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB disk2_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "CMD", CMD_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "STATUS", STATUS_MSG }, - { "IRQ", IRQ_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { NULL, 0 } -}; - -DEVICE disk2_dev = { - "DISK2", disk2_unit, disk2_reg, disk2_mod, - DISK2_MAX_DRIVES, 10, 31, 1, DISK2_MAX_DRIVES, DISK2_MAX_DRIVES, - NULL, NULL, &disk2_reset, - NULL, &disk2_attach, &disk2_detach, - &disk2_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - disk2_dt, NULL, "Compupro Hard Disk Controller DISK2" -}; - -/* Reset routine */ -static t_stat disk2_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &disk2dev, TRUE); - } else { - /* Connect DISK2 at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &disk2dev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - return SCPE_OK; -} - - -/* Attach routine */ -static t_stat disk2_attach(UNIT *uptr, char *cptr) -{ - t_stat r = SCPE_OK; - DISK2_DRIVE_INFO *pDrive; - int i = 0; - - i = find_unit_index(uptr); - if (i == -1) { - return (SCPE_IERR); - } - pDrive = &disk2_info->drive[i]; - - pDrive->ready = 1; - disk2_info->write_fault = 1; - pDrive->track = 5; - pDrive->ntracks = ntracks; - pDrive->nheads = nheads; - pDrive->nsectors = nsectors; - pDrive->sectsize = sectsize; - - r = attach_unit(uptr, cptr); /* attach unit */ - if ( r != SCPE_OK) /* error? */ - return r; - - /* Determine length of this disk */ - if(sim_fsize(uptr->fileref) != 0) { - uptr->capac = sim_fsize(uptr->fileref); - } else { - uptr->capac = (pDrive->ntracks * pDrive->nsectors * pDrive->nheads * pDrive->sectsize); - } - - pDrive->uptr = uptr; - - /* Default for new file is DSK */ - uptr->u3 = IMAGE_TYPE_DSK; - - if(uptr->capac > 0) { - r = assignDiskType(uptr); - if (r != SCPE_OK) { - disk2_detach(uptr); - return r; - } - } - - if (uptr->flags & UNIT_DISK2_VERBOSE) - printf("DISK2%d, attached to '%s', type=%s, len=%d\n", i, cptr, - uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", - uptr->capac); - - if(uptr->u3 == IMAGE_TYPE_IMD) { - if(uptr->capac < 318000) { - printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n"); - disk2_detach(uptr); - return SCPE_OPENERR; - } - - if (uptr->flags & UNIT_DISK2_VERBOSE) - printf("--------------------------------------------------------\n"); - disk2_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_DISK2_VERBOSE)); - if (uptr->flags & UNIT_DISK2_VERBOSE) - printf("\n"); - } else { - disk2_info->drive[i].imd = NULL; - } - - return SCPE_OK; -} - - -/* Detach routine */ -t_stat disk2_detach(UNIT *uptr) -{ - t_stat r; - int8 i; - - i = find_unit_index(uptr); - - if (i == -1) { - return (SCPE_IERR); - } - - if (uptr->flags & UNIT_DISK2_VERBOSE) - printf("Detach DISK2%d\n", i); - - r = detach_unit(uptr); /* detach unit */ - if ( r != SCPE_OK) - return r; - - return SCPE_OK; -} - - -static int32 disk2dev(const int32 port, const int32 io, const int32 data) -{ -/* sim_debug(VERBOSE_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT " IO %s, Port %02x\n", PCX, io ? "WR" : "RD", port); */ - if(io) { - DISK2_Write(port, data); - return 0; - } else { - return(DISK2_Read(port)); - } -} - -#define DISK2_CSR 0 /* R=DISK2 Status / W=DISK2 Control Register */ -#define DISK2_DATA 1 /* R=Step Pulse / W=Write Data Register */ - -static uint8 DISK2_Read(const uint32 Addr) -{ - uint8 cData; - DISK2_DRIVE_INFO *pDrive; - - pDrive = &disk2_info->drive[disk2_info->sel_drive]; - cData = 0x00; - - switch(Addr & 0x1) { - case DISK2_CSR: - cData = (disk2_info->ctl_attn) << 7; - cData |= (disk2_info->timeout) << 6; - cData |= (disk2_info->crc_error) << 5; - cData |= (disk2_info->overrun) << 4; - cData |= (pDrive->ready == 0) ? 0x08 : 0x00; - cData |= (disk2_info->seek_complete == 0) ? 0x04 : 0x00; - cData |= (disk2_info->write_fault) << 1; - cData |= ((pDrive->track != 0) || (disk2_info->seek_complete == 0)) ? 0x01 : 0x00; - sim_debug(STATUS_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " RD STATUS = 0x%02x\n", PCX, cData); - - disk2_info->seek_complete = 1; - break; - case DISK2_DATA: - if(disk2_info->ctl_op & 0x04) { - if(pDrive->track < pDrive->ntracks) { - pDrive->track ++; - } - } else { - if(pDrive->track > 0) { - pDrive->track --; - } - } - sim_debug(SEEK_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " Step %s, Track=%d\n", PCX, - disk2_info->ctl_op & 0x04 ? "IN" : "OUT", pDrive->track); - disk2_info->seek_complete = 0; - cData = 0xFF; /* Return High-Z data */ - break; - } - - return (cData); -} - -#define DISK2_OP_DRIVE 0x00 -#define DISK2_OP_CYL 0x01 -#define DISK2_OP_HEAD 0x02 -#define DISK2_OP_SECTOR 0x03 - -#define DISK2_CMD_NULL 0x00 -#define DISK2_CMD_READ_DATA 0x01 -#define DISK2_CMD_WRITE_DATA 0x02 -#define DISK2_CMD_WRITE_HEADER 0x03 -#define DISK2_CMD_READ_HEADER 0x04 - -static uint8 DISK2_Write(const uint32 Addr, uint8 cData) -{ - uint32 track_offset; - uint8 result = 0; - uint8 i; - long file_offset; - DISK2_DRIVE_INFO *pDrive; - size_t rtn; - - pDrive = &disk2_info->drive[disk2_info->sel_drive]; - - switch(Addr & 0x1) { - case DISK2_CSR: /* Write CTL register */ - disk2_info->ctl_attn = (cData & 0x80) >> 7; - disk2_info->ctl_run = (cData & 0x40) >> 6; - disk2_info->ctl_op = (cData & 0x38) >> 3; - disk2_info->ctl_fault_clr = (cData & 0x04) >> 2; - if(disk2_info->ctl_fault_clr == 1) { - disk2_info->timeout = 0; - } - disk2_info->ctl_us = (cData & 0x03); - sim_debug(VERBOSE_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " ATTN*=%d, RUN=%d, OP=%d, FAULT_CLR=%d, US=%d\n", - PCX, disk2_info->ctl_attn, disk2_info->ctl_run, - disk2_info->ctl_op, disk2_info->ctl_fault_clr, - disk2_info->ctl_us); - - /* FIXME: seek_complete = 1 is needed by CP/M, but why? Also, maybe related, - * there appears to be a bug in the seeking logic. For some reason, the - * pDrive->track does not equal the disk2_info->cyl, when doing READ_DATA and - * WRITE_DATA commands. For this reason, disk2_info->cyl is used instead of - * pDrive->track for these commands. For READ_HEADER and WRITE_HEADER, - * pDrive->track is used, because the DISK2 format program (DISK2.COM) does not - * issue DISK2_OP_CYL. The root cause of this anomaly needs to be determined, - * because it is surely a bug in the logic somewhere. - */ - /* pDrive->track may be different from disk2_info->cyl when a program such as DISK2.COM - moves the position of the track without informing the CP/M BIOS which stores the - current track for each drive. This appears to be an application program bug. - */ - disk2_info->seek_complete = 1; - - if(disk2_info->ctl_run == 1) { - disk2_info->timeout = 0; - track_offset = disk2_info->cyl * pDrive->nheads * pDrive->nsectors * (pDrive->sectsize + 3); - - switch(disk2_info->ctl_op) { - case DISK2_CMD_NULL: - sim_debug(CMD_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " NULL Command\n", PCX); - break; - case DISK2_CMD_READ_DATA: - sim_debug(RD_DATA_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " READ_DATA: (C:%d/H:%d/S:%d)\n", PCX, disk2_info->cyl, disk2_info->head, disk2_info->sector); - if(disk2_info->head_sel != disk2_info->head) { - printf("DISK2: " ADDRESS_FORMAT - " READ_DATA: head_sel != head" NLP, PCX); - } - /* See FIXME above... that might be why this does not work properly... */ - if(disk2_info->cyl != pDrive->track) { /* problem, should not happen, see above */ - sim_debug(ERROR_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " READ_DATA: cyl=%d, track=%d\n", PCX, disk2_info->cyl, pDrive->track); - pDrive->track = disk2_info->cyl; /* update track */ - } - sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET); - for(i=0;insectors;i++) { - /* Read sector */ - rtn = sim_fread(sdata.raw, 1, (pDrive->sectsize + 3), (pDrive->uptr)->fileref); - if (rtn != (size_t)(pDrive->sectsize + 3)) { - sim_debug(ERROR_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " READ_DATA: sim_fread error.\n", PCX); - } - if(sdata.u.header[2] == disk2_info->sector) { - if(sdata.u.header[0] != disk2_info->cyl) { /*pDrive->track) { */ - printf("DISK2: " ADDRESS_FORMAT - " READ_DATA Incorrect header: track" NLP, PCX); - disk2_info->timeout = 1; - } - if(sdata.u.header[1] != disk2_info->head) { - printf("DISK2: " ADDRESS_FORMAT - " READ_DATA Incorrect header: head" NLP, PCX); - disk2_info->timeout = 1; - } - - selchan_dma(sdata.u.data, pDrive->sectsize); - break; - } - if(i == pDrive->nsectors) { - printf("DISK2: " ADDRESS_FORMAT - " Sector not found" NLP, PCX); - disk2_info->timeout = 1; - } - } - - break; - case DISK2_CMD_WRITE_DATA: - sim_debug(WR_DATA_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " WRITE_DATA: (C:%d/H:%d/S:%d)\n", PCX, disk2_info->cyl, disk2_info->head, disk2_info->sector); - if(disk2_info->head_sel != disk2_info->head) { - printf("DISK2: " ADDRESS_FORMAT " WRITE_DATA: head_sel != head" NLP, PCX); - } - if(disk2_info->cyl != pDrive->track) { /* problem, should not happen, see above */ - sim_debug(ERROR_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " WRITE_DATA = 0x%02x, cyl=%d, track=%d\n", PCX, cData, disk2_info->cyl, pDrive->track); - pDrive->track = disk2_info->cyl; /* update track */ - } - - sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET); - for(i=0;insectors;i++) { - /* Read sector */ - file_offset = ftell((pDrive->uptr)->fileref); - rtn = sim_fread(sdata.raw, 1, 3, (pDrive->uptr)->fileref); - if (rtn != 3) { - sim_debug(ERROR_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " WRITE_DATA: sim_fread error.\n", PCX); - } - if(sdata.u.header[2] == disk2_info->sector) { - if(sdata.u.header[0] != disk2_info->cyl) { - printf("DISK2: " ADDRESS_FORMAT - " WRITE_DATA Incorrect header: track" NLP, PCX); - disk2_info->timeout = 1; - } - if(sdata.u.header[1] != disk2_info->head) { - printf("DISK2: " ADDRESS_FORMAT - " WRITE_DATA Incorrect header: head" NLP, PCX); - disk2_info->timeout = 1; - } - - selchan_dma(sdata.u.data, pDrive->sectsize); - sim_fseek((pDrive->uptr)->fileref, file_offset+3, SEEK_SET); - sim_fwrite(sdata.u.data, 1, (pDrive->sectsize), (pDrive->uptr)->fileref); - break; - } - rtn = sim_fread(sdata.raw, 1, pDrive->sectsize, (pDrive->uptr)->fileref); - if (rtn != (size_t)(pDrive->sectsize)) { - sim_debug(ERROR_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " WRITE_DATA: sim_fread error.\n", PCX); - } - if(i == pDrive->nsectors) { - printf("DISK2: " ADDRESS_FORMAT " Sector not found" NLP, PCX); - disk2_info->timeout = 1; - } - } - break; - case DISK2_CMD_WRITE_HEADER: - track_offset = pDrive->track * pDrive->nheads * pDrive->nsectors * (pDrive->sectsize + 3); - sim_debug(CMD_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " WRITE_HEADER Command: track=%d (%d), Head=%d, Sector=%d\n", - PCX, pDrive->track, disk2_info->cyl, - disk2_info->head_sel, disk2_info->hdr_sector); - - i = disk2_info->hdr_sector; - selchan_dma(sdata.raw, 3); - sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * (pDrive->sectsize + 3) * pDrive->nsectors) + (i * (pDrive->sectsize + 3)), SEEK_SET); - sim_fwrite(sdata.raw, 1, 3, (pDrive->uptr)->fileref); - - disk2_info->hdr_sector++; - if(disk2_info->hdr_sector >= pDrive->nsectors) { - disk2_info->hdr_sector = 0; - disk2_info->timeout = 1; - } - break; - case DISK2_CMD_READ_HEADER: - track_offset = pDrive->track * pDrive->nheads * pDrive->nsectors * (pDrive->sectsize + 3); - sim_debug(CMD_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " READ_HEADER Command\n", PCX); - sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET); - rtn = sim_fread(sdata.raw, 1, 3, (pDrive->uptr)->fileref); - if (rtn != 3) { - sim_debug(ERROR_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " READ_HEADER: sim_fread error.\n", PCX); - } - selchan_dma(sdata.raw, 3); - - break; - default: - printf("DISK2: " ADDRESS_FORMAT " Unknown CMD=%d" NLP, PCX, disk2_info->ctl_op); - break; - } - - raise_disk2_interrupt(); - disk2_info->ctl_attn = 0; - } - - break; - case DISK2_DATA: - switch(disk2_info->ctl_op) { - case DISK2_OP_DRIVE: - switch(cData >> 4) { - case 0x01: - disk2_info->sel_drive = 0; - break; - case 0x02: - disk2_info->sel_drive = 1; - break; - case 0x04: - disk2_info->sel_drive = 2; - break; - case 0x08: - disk2_info->sel_drive = 3; - break; - default: - printf("DISK2: " ADDRESS_FORMAT - " Error, invalid drive select=0x%x" NLP, PCX, cData >> 4); - break; - } - - disk2_info->head_sel = cData & 0x0F; - - sim_debug(VERBOSE_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " Write DATA [DRIVE]=%d, Head=%d\n", - PCX, disk2_info->sel_drive, disk2_info->head); - break; - case DISK2_OP_CYL: - disk2_info->cyl = cData; - sim_debug(VERBOSE_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " Write DATA [CYL] = %02x\n", PCX, cData); - break; - case DISK2_OP_HEAD: - disk2_info->head = cData; - sim_debug(VERBOSE_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " Write DATA [HEAD] = %02x\n", PCX, cData); - break; - case DISK2_OP_SECTOR: - disk2_info->sector = cData; - sim_debug(VERBOSE_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " Write Register [SECTOR] = %02x\n", PCX, cData); - break; - default: - sim_debug(VERBOSE_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " Write Register unknown op [%d] = %02x\n", - PCX, disk2_info->ctl_op, cData); - break; - } - } - - return (result); -} - -#define SS1_VI1_INT 1 /* DISK2/DISK3 interrupts tied to VI1 */ - -static void raise_disk2_interrupt(void) -{ - sim_debug(IRQ_MSG, &disk2_dev, "DISK2: " ADDRESS_FORMAT - " Interrupt\n", PCX); - - raise_ss1_interrupt(SS1_VI1_INT); - -} diff --git a/AltairZ80/s100_disk3.c b/AltairZ80/s100_disk3.c deleted file mode 100644 index 6cb00874..00000000 --- a/AltairZ80/s100_disk3.c +++ /dev/null @@ -1,662 +0,0 @@ -/************************************************************************* - * * - * $Id: s100_disk3.c 1997 2008-07-18 05:29:52Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * CompuPro DISK3 Hard Disk Controller module for SIMH. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#include "sim_imd.h" - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define STATUS_MSG (1 << 5) -#define IRQ_MSG (1 << 6) -#define VERBOSE_MSG (1 << 7) -#define SPECIFY_MSG (1 << 8) - -#define DISK3_MAX_DRIVES 4 - -#define DISK3_CSR 0 /* R=DISK3 Status / W=DISK3 Control Register */ -#define DISK3_DATA 1 /* R=Step Pulse / W=Write Data Register */ - -#define DISK3_OP_DRIVE 0x00 -#define DISK3_OP_CYL 0x01 -#define DISK3_OP_HEAD 0x02 -#define DISK3_OP_SECTOR 0x03 - -#define DISK3_CMD_NULL 0x00 -#define DISK3_CMD_READ_DATA 0x01 -#define DISK3_CMD_WRITE_DATA 0x02 -#define DISK3_CMD_WRITE_HEADER 0x03 -#define DISK3_CMD_READ_HEADER 0x04 - -#define DISK3_STATUS_BUSY 0 -#define DISK3_STATUS_RANGE 1 -#define DISK3_STATUS_NOT_READY 2 -#define DISK3_STATUS_TIMEOUT 3 -#define DISK3_STATUS_DAT_CRC 4 -#define DISK3_STATUS_WR_FAULT 5 -#define DISK3_STATUS_OVERRUN 6 -#define DISK3_STATUS_HDR_CRC 7 -#define DISK3_STATUS_MAP_FULL 8 -#define DISK3_STATUS_COMPLETE 0xFF /* Complete with No Error */ - -#define DISK3_CODE_NOOP 0x00 -#define DISK3_CODE_VERSION 0x01 -#define DISK3_CODE_GLOBAL 0x02 -#define DISK3_CODE_SPECIFY 0x03 -#define DISK3_CODE_SET_MAP 0x04 -#define DISK3_CODE_HOME 0x05 -#define DISK3_CODE_SEEK 0x06 -#define DISK3_CODE_READ_HDR 0x07 -#define DISK3_CODE_READWRITE 0x08 -#define DISK3_CODE_RELOCATE 0x09 -#define DISK3_CODE_FORMAT 0x0A -#define DISK3_CODE_FORMAT_BAD 0x0B -#define DISK3_CODE_STATUS 0x0C -#define DISK3_CODE_SELECT 0x0D -#define DISK3_CODE_EXAMINE 0x0E -#define DISK3_CODE_MODIFY 0x0F - -#define DISK3_CMD_MASK 0x3F -#define DISK3_REQUEST_IRQ 0x80 - -#define DISK3_IOPB_LEN 16 - -#define DISK3_IOPB_CMD 0 -#define DISK3_IOPB_STATUS 1 -#define DISK3_IOPB_DRIVE 2 -#define DISK3_IOPB_ARG1 3 -#define DISK3_IOPB_ARG2 4 -#define DISK3_IOPB_ARG3 5 -#define DISK3_IOPB_ARG4 6 -#define DISK3_IOPB_ARG5 7 -#define DISK3_IOPB_ARG6 8 -#define DISK3_IOPB_ARG7 9 -#define DISK3_IOPB_DATA 10 -#define DISK3_IOPB_LINK 13 - -#define DISK3_MODE_ABS 0xFF -#define DISK3_MODE_LOGICAL 0x00 - -typedef struct { - UNIT *uptr; - DISK_INFO *imd; - uint16 sectsize; /* sector size, not including pre/postamble */ - uint16 nsectors; /* number of sectors/track */ - uint16 nheads; /* number of heads */ - uint16 ntracks; /* number of tracks */ - uint16 res_tracks; /* Number of reserved tracks on drive. */ - uint16 track; /* Current Track */ - - uint16 cur_sect; /* current starting sector of transfer */ - uint16 cur_track; /* Current Track */ - uint16 xfr_nsects; /* Number of sectors to transfer */ - uint8 ready; /* Is drive ready? */ -} DISK3_DRIVE_INFO; - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint8 sel_drive; /* Currently selected drive */ - uint8 mode; /* mode (0xFF=absolute, 0x00=logical) */ - uint8 retries; /* Number of retries to attempt */ - uint8 ndrives; /* Number of drives attached to the controller */ - - uint32 link_addr; /* Link Address for next IOPB */ - uint32 dma_addr; /* DMA Address for the current IOPB */ - - DISK3_DRIVE_INFO drive[DISK3_MAX_DRIVES]; - uint8 iopb[16]; -} DISK3_INFO; - -static DISK3_INFO disk3_info_data = { { 0x0, 0, 0x90, 2 } }; -static DISK3_INFO *disk3_info = &disk3_info_data; - -/* Disk geometries: - * ST506 ST412 CMI5619 Q520 Q540 Q2080 - * Sectsize: 1024 1024 1024 1024 1024 1024 - * Sectors: 9 9 9 9 9 11 - * Heads: 4 4 6 4 8 7 - * Tracks: 153 306 306 512 512 1172 - */ - -/* Default geometry for a 20MB hard disk. */ -#define C20MB_SECTSIZE 1024 -#define C20MB_NSECTORS 9 -#define C20MB_NHEADS 4 -#define C20MB_NTRACKS 512 - -static int32 ntracks = C20MB_NTRACKS; -static int32 nheads = C20MB_NHEADS; -static int32 nsectors = C20MB_NSECTORS; -static int32 sectsize = C20MB_SECTSIZE; - -extern uint32 PCX; -extern REG *sim_PC; -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern int32 find_unit_index(UNIT *uptr); -extern void raise_ss1_interrupt(uint8 intnum); - -/* These are needed for DMA. */ -extern void PutByteDMA(const uint32 Addr, const uint32 Value); -extern uint8 GetByteDMA(const uint32 Addr); - -#define UNIT_V_DISK3_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_DISK3_WLK (1 << UNIT_V_DISK3_WLK) -#define UNIT_V_DISK3_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_DISK3_VERBOSE (1 << UNIT_V_DISK3_VERBOSE) -#define DISK3_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */ - -static t_stat disk3_reset(DEVICE *disk3_dev); -static t_stat disk3_attach(UNIT *uptr, char *cptr); -static t_stat disk3_detach(UNIT *uptr); -static void raise_disk3_interrupt(void); - -static int32 disk3dev(const int32 port, const int32 io, const int32 data); - -/* static uint8 DISK3_Read(const uint32 Addr); */ -static uint8 DISK3_Write(const uint32 Addr, uint8 cData); - -static UNIT disk3_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK3_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK3_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK3_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DISK3_CAPACITY) } -}; - -static REG disk3_reg[] = { - { DRDATA (NTRACKS, ntracks, 10), }, - { DRDATA (NHEADS, nheads, 8), }, - { DRDATA (NSECTORS, nsectors, 8), }, - { DRDATA (SECTSIZE, sectsize, 11), }, - { HRDATA (SEL_DRIVE, disk3_info_data.sel_drive, 3), }, - { HRDATA (MODE, disk3_info_data.mode, 8), }, - { HRDATA (RETRIES, disk3_info_data.retries, 8), }, - { HRDATA (NDRIVES, disk3_info_data.ndrives, 8), }, - { HRDATA (LINK_ADDR, disk3_info_data.link_addr, 32), }, - { HRDATA (DMA_ADDR, disk3_info_data.dma_addr, 32), }, - { BRDATA (IOPB, &disk3_info_data.iopb[DISK3_IOPB_CMD], 16, 8, 16), }, - { NULL } -}; - -static MTAB disk3_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_DISK3_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_DISK3_WLK, UNIT_DISK3_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_DISK3_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_DISK3_VERBOSE, UNIT_DISK3_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB disk3_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "CMD", CMD_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "STATUS", STATUS_MSG }, - { "IRQ", IRQ_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { "SPECIFY",SPECIFY_MSG }, - { NULL, 0 } -}; - -DEVICE disk3_dev = { - "DISK3", disk3_unit, disk3_reg, disk3_mod, - DISK3_MAX_DRIVES, 10, 31, 1, DISK3_MAX_DRIVES, DISK3_MAX_DRIVES, - NULL, NULL, &disk3_reset, - NULL, &disk3_attach, &disk3_detach, - &disk3_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - disk3_dt, NULL, "Compupro ST-506 Disk Controller DISK3" -}; - -/* Reset routine */ -static t_stat disk3_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &disk3dev, TRUE); - } else { - /* Connect DISK3 at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &disk3dev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - - disk3_info->link_addr = 0x50; /* After RESET, the link pointer is at 0x50. */ - - return SCPE_OK; -} - - -/* Attach routine */ -static t_stat disk3_attach(UNIT *uptr, char *cptr) -{ - t_stat r = SCPE_OK; - DISK3_DRIVE_INFO *pDrive; - int i = 0; - - i = find_unit_index(uptr); - if (i == -1) { - return (SCPE_IERR); - } - pDrive = &disk3_info->drive[i]; - - pDrive->ready = 1; - pDrive->track = 5; - pDrive->ntracks = C20MB_NTRACKS; - pDrive->nheads = C20MB_NHEADS; - pDrive->nsectors = C20MB_NSECTORS; - pDrive->sectsize = C20MB_SECTSIZE; - - r = attach_unit(uptr, cptr); /* attach unit */ - if ( r != SCPE_OK) /* error? */ - return r; - - /* Determine length of this disk */ - if(sim_fsize(uptr->fileref) != 0) { - uptr->capac = sim_fsize(uptr->fileref); - } else { - uptr->capac = (pDrive->ntracks * pDrive->nsectors * pDrive->nheads * pDrive->sectsize); - } - - pDrive->uptr = uptr; - - /* Default for new file is DSK */ - uptr->u3 = IMAGE_TYPE_DSK; - - if(uptr->capac > 0) { - r = assignDiskType(uptr); - if (r != SCPE_OK) { - disk3_detach(uptr); - return r; - } - } - - if (uptr->flags & UNIT_DISK3_VERBOSE) - printf("DISK3%d, attached to '%s', type=%s, len=%d\n", i, cptr, - uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", - uptr->capac); - - if(uptr->u3 == IMAGE_TYPE_IMD) { - if(uptr->capac < 318000) { - printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n"); - disk3_detach(uptr); - return SCPE_OPENERR; - } - - if (uptr->flags & UNIT_DISK3_VERBOSE) - printf("--------------------------------------------------------\n"); - disk3_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_DISK3_VERBOSE)); - if (uptr->flags & UNIT_DISK3_VERBOSE) - printf("\n"); - } else { - disk3_info->drive[i].imd = NULL; - } - - return SCPE_OK; -} - - -/* Detach routine */ -t_stat disk3_detach(UNIT *uptr) -{ - DISK3_DRIVE_INFO *pDrive; - t_stat r; - int8 i; - - i = find_unit_index(uptr); - - if (i == -1) { - return (SCPE_IERR); - } - - pDrive = &disk3_info->drive[i]; - - pDrive->ready = 0; - - if (uptr->flags & UNIT_DISK3_VERBOSE) - printf("Detach DISK3%d\n", i); - - r = detach_unit(uptr); /* detach unit */ - if ( r != SCPE_OK) - return r; - - return SCPE_OK; -} - - -static int32 disk3dev(const int32 port, const int32 io, const int32 data) -{ - sim_debug(VERBOSE_MSG, &disk3_dev, "DISK3: " ADDRESS_FORMAT - " IO %s, Port %02x\n", PCX, io ? "WR" : "RD", port); - if(io) { - DISK3_Write(port, data); - return 0; - } else { - return(0xFF); - } -} - -static uint8 DISK3_Write(const uint32 Addr, uint8 cData) -{ - uint32 next_link; - uint8 result = DISK3_STATUS_COMPLETE; - uint8 i; - uint8 cmd; - - DISK3_DRIVE_INFO *pDrive; - - for(i = 0; i < DISK3_IOPB_LEN; i++) { - disk3_info->iopb[i] = GetByteDMA(disk3_info->link_addr + i); - } - - cmd = disk3_info->iopb[DISK3_IOPB_CMD]; - disk3_info->sel_drive = disk3_info->iopb[DISK3_IOPB_DRIVE] & 0x03; - - disk3_info->dma_addr = disk3_info->iopb[0x0A]; - disk3_info->dma_addr |= disk3_info->iopb[0x0B] << 8; - disk3_info->dma_addr |= disk3_info->iopb[0x0C] << 16; - - next_link = disk3_info->iopb[DISK3_IOPB_LINK+0]; - next_link |= disk3_info->iopb[DISK3_IOPB_LINK+1] << 8; - next_link |= disk3_info->iopb[DISK3_IOPB_LINK+2] << 16; - - sim_debug(VERBOSE_MSG, &disk3_dev, "DISK3[%d]: LINK=0x%05x, NEXT=0x%05x, CMD=%x, %s DMA@0x%05x\n", - disk3_info->sel_drive, - disk3_info->link_addr, - next_link, - disk3_info->iopb[DISK3_IOPB_CMD] & DISK3_CMD_MASK, - (disk3_info->iopb[DISK3_IOPB_CMD] & DISK3_REQUEST_IRQ) ? "IRQ" : "POLL", - disk3_info->dma_addr); - - pDrive = &disk3_info->drive[disk3_info->sel_drive]; - - if(pDrive->ready) { - - /* Perform command */ - switch(cmd & DISK3_CMD_MASK) { - case DISK3_CODE_NOOP: - sim_debug(VERBOSE_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT - " NOOP\n", disk3_info->sel_drive, PCX); - break; - case DISK3_CODE_VERSION: - break; - case DISK3_CODE_GLOBAL: - sim_debug(CMD_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT - " GLOBAL\n", disk3_info->sel_drive, PCX); - - disk3_info->mode = disk3_info->iopb[DISK3_IOPB_ARG1]; - disk3_info->retries = disk3_info->iopb[DISK3_IOPB_ARG2]; - disk3_info->ndrives = disk3_info->iopb[DISK3_IOPB_ARG3]; - - sim_debug(SPECIFY_MSG, &disk3_dev, " Mode: 0x%02x\n", disk3_info->mode); - sim_debug(SPECIFY_MSG, &disk3_dev, " # Retries: 0x%02x\n", disk3_info->retries); - sim_debug(SPECIFY_MSG, &disk3_dev, " # Drives: 0x%02x\n", disk3_info->ndrives); - - if(disk3_info->mode == DISK3_MODE_ABS) { - sim_debug(ERROR_MSG, &disk3_dev, "DISK3: Absolute addressing not supported.\n"); - } - - break; - case DISK3_CODE_SPECIFY: - { - uint8 specify_data[22]; - sim_debug(CMD_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT - " SPECIFY\n", disk3_info->sel_drive, PCX); - - for(i = 0; i < 22; i++) { - specify_data[i] = GetByteDMA(disk3_info->dma_addr + i); - } - - pDrive->sectsize = specify_data[4] | (specify_data[5] << 8); - pDrive->nsectors = specify_data[6] | (specify_data[7] << 8); - pDrive->nheads = specify_data[8] | (specify_data[9] << 8); - pDrive->ntracks = specify_data[10] | (specify_data[11] << 8); - pDrive->res_tracks = specify_data[18] | (specify_data[19] << 8); - - sim_debug(SPECIFY_MSG, &disk3_dev, " Sectsize: %d\n", pDrive->sectsize); - sim_debug(SPECIFY_MSG, &disk3_dev, " Sectors: %d\n", pDrive->nsectors); - sim_debug(SPECIFY_MSG, &disk3_dev, " Heads: %d\n", pDrive->nheads); - sim_debug(SPECIFY_MSG, &disk3_dev, " Tracks: %d\n", pDrive->ntracks); - sim_debug(SPECIFY_MSG, &disk3_dev, " Reserved: %d\n", pDrive->res_tracks); - break; - } - case DISK3_CODE_HOME: - pDrive->track = 0; - sim_debug(SEEK_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT - " HOME\n", disk3_info->sel_drive, PCX); - break; - case DISK3_CODE_SEEK: - pDrive->track = disk3_info->iopb[DISK3_IOPB_ARG1]; - pDrive->track |= (disk3_info->iopb[DISK3_IOPB_ARG2] << 8); - - if(pDrive->track > pDrive->ntracks) { - sim_debug(ERROR_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT - " SEEK ERROR %d not found\n", disk3_info->sel_drive, PCX, pDrive->track); - pDrive->track = pDrive->ntracks - 1; - result = DISK3_STATUS_TIMEOUT; - } else { - sim_debug(SEEK_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT - " SEEK %d\n", disk3_info->sel_drive, PCX, pDrive->track); - } - break; - case DISK3_CODE_READ_HDR: - { - sim_debug(CMD_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT - " READ HEADER: %d\n", pDrive->track, PCX, pDrive->track >> 8); - PutByteDMA(disk3_info->dma_addr + 0, pDrive->track & 0xFF); - PutByteDMA(disk3_info->dma_addr + 1, (pDrive->track >> 8) & 0xFF); - PutByteDMA(disk3_info->dma_addr + 2, 0); - PutByteDMA(disk3_info->dma_addr + 3, 1); - - break; - } - case DISK3_CODE_READWRITE: - { - uint32 track_len; - uint32 xfr_len; - uint32 file_offset; - uint32 xfr_count = 0; - uint8 *dataBuffer; - size_t rtn; - - if(disk3_info->mode == DISK3_MODE_ABS) { - sim_debug(ERROR_MSG, &disk3_dev, "DISK3: Absolute addressing not supported.\n"); - break; - } - - pDrive->cur_sect = disk3_info->iopb[DISK3_IOPB_ARG2] | (disk3_info->iopb[DISK3_IOPB_ARG3] << 8); - pDrive->cur_track = disk3_info->iopb[DISK3_IOPB_ARG4] | (disk3_info->iopb[DISK3_IOPB_ARG5] << 8); - pDrive->xfr_nsects = disk3_info->iopb[DISK3_IOPB_ARG6] | (disk3_info->iopb[DISK3_IOPB_ARG7] << 8); - - track_len = pDrive->nsectors * pDrive->sectsize; - - file_offset = (pDrive->cur_track * track_len); /* Calculate offset based on current track */ - file_offset += pDrive->cur_sect * pDrive->sectsize; - - xfr_len = pDrive->xfr_nsects * pDrive->sectsize; - - dataBuffer = malloc(xfr_len); - - sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET); - - if(disk3_info->iopb[DISK3_IOPB_ARG1] == 1) { /* Read */ - rtn = sim_fread(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref); - - sim_debug(RD_DATA_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT - " READ @0x%05x T:%04d/S:%04d/#:%d %s\n", - disk3_info->sel_drive, - PCX, - disk3_info->dma_addr, - pDrive->cur_track, - pDrive->cur_sect, - pDrive->xfr_nsects, - rtn == (size_t)xfr_len ? "OK" : "NOK" ); - - - /* Perform DMA Transfer */ - for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) { - PutByteDMA(disk3_info->dma_addr + xfr_count, dataBuffer[xfr_count]); - } - } else { /* Write */ - sim_debug(WR_DATA_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT - " WRITE @0x%05x T:%04d/S:%04d/#:%d\n", disk3_info->sel_drive, PCX, disk3_info->dma_addr, pDrive->cur_track, pDrive->cur_sect, pDrive->xfr_nsects ); - - /* Perform DMA Transfer */ - for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) { - dataBuffer[xfr_count] = GetByteDMA(disk3_info->dma_addr + xfr_count); - } - - sim_fwrite(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref); - } - - free(dataBuffer); - /* Update Track/Sector in IOPB */ - pDrive->cur_sect += pDrive->xfr_nsects; - if(pDrive->cur_sect >= pDrive->nsectors) { - pDrive->cur_sect = pDrive->cur_sect % pDrive->nsectors; - pDrive->cur_track++; - } - disk3_info->iopb[DISK3_IOPB_ARG2] = pDrive->cur_sect & 0xFF; - disk3_info->iopb[DISK3_IOPB_ARG3] = (pDrive->cur_sect >> 8) & 0xFF; - disk3_info->iopb[DISK3_IOPB_ARG4] = pDrive->cur_track & 0xFF; - disk3_info->iopb[DISK3_IOPB_ARG5] = (pDrive->cur_track >> 8) & 0xFF; - disk3_info->iopb[DISK3_IOPB_ARG6] = 0; - disk3_info->iopb[DISK3_IOPB_ARG7] = 0; - - /* Update the DATA field in the IOPB */ - disk3_info->dma_addr += xfr_len; - disk3_info->iopb[DISK3_IOPB_DATA+0] = disk3_info->dma_addr & 0xFF; - disk3_info->iopb[DISK3_IOPB_DATA+1] = (disk3_info->dma_addr >> 8) & 0xFF; - disk3_info->iopb[DISK3_IOPB_DATA+2] = (disk3_info->dma_addr >> 16) & 0xFF; - - break; - } - case DISK3_CODE_FORMAT: - { - uint32 data_len; - uint32 file_offset; - uint8 *fmtBuffer; - - data_len = pDrive->nsectors * pDrive->sectsize; - - sim_debug(WR_DATA_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT - " FORMAT T:%d/H:%d/Fill=0x%02x/Len=%d\n", - disk3_info->sel_drive, - PCX, - pDrive->track, - disk3_info->iopb[DISK3_IOPB_ARG3], - disk3_info->iopb[DISK3_IOPB_ARG2], - data_len); - - file_offset = (pDrive->track * (pDrive->nheads) * data_len); /* Calculate offset based on current track */ - file_offset += (disk3_info->iopb[DISK3_IOPB_ARG3] * data_len); - - fmtBuffer = malloc(data_len); - memset(fmtBuffer, disk3_info->iopb[DISK3_IOPB_ARG2], data_len); - - sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET); - sim_fwrite(fmtBuffer, 1, data_len, (pDrive->uptr)->fileref); - - free(fmtBuffer); - - break; - } - case DISK3_CODE_SET_MAP: - break; - case DISK3_CODE_RELOCATE: - case DISK3_CODE_FORMAT_BAD: - case DISK3_CODE_STATUS: - case DISK3_CODE_SELECT: - case DISK3_CODE_EXAMINE: - case DISK3_CODE_MODIFY: - default: - sim_debug(ERROR_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT - " CMD=%x Unsupported\n", - disk3_info->sel_drive, - PCX, - cmd & DISK3_CMD_MASK); - break; - } - } else { /* Drive not ready */ - result = DISK3_STATUS_NOT_READY; - } - - /* Return status */ - disk3_info->iopb[DISK3_IOPB_STATUS] = result; - - /* Update IOPB in host memory */ - for(i = 0; i < DISK3_IOPB_LEN; i++) { - PutByteDMA(disk3_info->link_addr + i, disk3_info->iopb[i]); - } - - if(cmd & DISK3_REQUEST_IRQ) { - raise_disk3_interrupt(); - } - disk3_info->link_addr = next_link; - - return 0; -} - -#define SS1_VI1_INT 1 /* DISK2/DISK3 interrupts tied to VI1 */ - -static void raise_disk3_interrupt(void) -{ - sim_debug(IRQ_MSG, &disk3_dev, "DISK3: " ADDRESS_FORMAT " Interrupt\n", PCX); - - raise_ss1_interrupt(SS1_VI1_INT); - -} diff --git a/AltairZ80/s100_fif.c b/AltairZ80/s100_fif.c deleted file mode 100644 index fe8a6b18..00000000 --- a/AltairZ80/s100_fif.c +++ /dev/null @@ -1,472 +0,0 @@ -/* $Id: s100_fif.c 1995 2008-07-15 03:59:13Z hharte $ - - IMSAI FIF Disk Controller by Ernie Price - - Based on altairz80_dsk.c, Copyright (c) 2002-2012, Peter Schorn - - Plug-n-Play added by Howard M. Harte - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - -*/ - -#include "altairz80_defs.h" - -#define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK) -#define UNIT_V_DSK_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_DSK_VERBOSE (1 << UNIT_V_DSK_VERBOSE) -#define DSK_SECTSIZE 137 /* size of sector */ -#define DSK_SECT 32 /* sectors per track */ -#define MAX_TRACKS 254 /* number of tracks, original Altair has 77 tracks only */ -#define DSK_TRACSIZE (DSK_SECTSIZE * DSK_SECT) -#define MAX_DSK_SIZE (DSK_TRACSIZE * MAX_TRACKS) - -static t_stat fif_reset(DEVICE *dptr); -static t_stat fif_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc); -static int32 fif_io(const int32 port, const int32 io, const int32 data); - -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern uint8 GetBYTEWrapper(const uint32 Addr); -extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); - -extern uint32 PCX; - -/* global data on status */ - -/* currently selected drive (values are 0 .. NUM_OF_DSK) - current_disk < NUM_OF_DSK implies that the corresponding disk is attached to a file */ -static int32 current_disk = NUM_OF_DSK; -static int32 warnLevelDSK = 3; -static int32 warnLock [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 warnAttached [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 warnDSK11 = 0; - -/* 88DSK Standard I/O Data Structures */ - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ -} FIF_INFO; - -FIF_INFO fif_info_data = { { 0x0000, 0, 0xFD, 1 } }; -FIF_INFO *fif_info = &fif_info_data; - -static UNIT fif_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) } -}; - -static REG fif_reg[] = { - { DRDATA (DISK, current_disk, 4) }, - { DRDATA (DSKWL, warnLevelDSK, 32) }, - { BRDATA (WARNLOCK, warnLock, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (WARNATTACHED, warnAttached, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { DRDATA (WARNDSK11, warnDSK11, 4), REG_RO }, - { NULL } -}; - -static MTAB fif_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_DSK_WLK, UNIT_DSK_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_DSK_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_DSK_VERBOSE, UNIT_DSK_VERBOSE, "VERBOSE", "VERBOSE", &fif_set_verbose }, - { 0 } -}; - -DEVICE fif_dev = { - "FIF", fif_unit, fif_reg, fif_mod, - 8, 10, 31, 1, 8, 8, - NULL, NULL, &fif_reset, - NULL, NULL, NULL, - &fif_info_data, (DEV_DISABLE | DEV_DIS), 0, - NULL, NULL, "IMSAI FIF" -}; - -static void resetDSKWarningFlags(void) { - int32 i; - for (i = 0; i < NUM_OF_DSK; i++) { - warnLock[i] = 0; - warnAttached[i] = 0; - } - warnDSK11 = 0; -} - -static t_stat fif_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) { - resetDSKWarningFlags(); - return SCPE_OK; -} - -/* returns TRUE iff there exists a disk with VERBOSE */ -static int32 hasVerbose(void) { - int32 i; - for (i = 0; i < NUM_OF_DSK; i++) { - if (((fif_dev.units + i)->flags) & UNIT_DSK_VERBOSE) { - return TRUE; - } - } - return FALSE; -} - -/* service routines to handle simulator functions */ - -/* Reset routine */ -static t_stat fif_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - resetDSKWarningFlags(); - current_disk = NUM_OF_DSK; - - if(dptr->flags & DEV_DIS) { - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &fif_io, TRUE); - } else { - /* Connect HDSK at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &fif_io, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->mem_base); - dptr->flags |= DEV_DIS; - return SCPE_ARG; - } - } - return SCPE_OK; -} - -typedef struct desc_t -{ - uint8 - cmd_unit, /* (cmd << 4) | unit : 1 = A: */ - result, /* result: 0 == busy, 1 = normal completion, */ - nn, /* number of secs ? */ - track, /* track */ - sector, /* sector */ - addr_l, /* low (transfer address) */ - addr_h; /* high (transfer address) */ -} desc_t; - -static desc_t mydesc; - -enum {NONE, WRITE_SEC, READ_SEC, FMT_TRACK}; - -#define SEC_SZ 128 -#define SPT 26 -#define UMASK 0xf - -static uint8 blanksec[SEC_SZ]; -/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -static const uint8 utrans[] = {0,1,2,0,3,0,0,0,4,0,0,0,0,0,0,0}; - -/************************************************** - - Translate an IMSAI FIF disk request into an access into the harddrive file - -*/ -static int DoDiskOperation(desc_t *dsc, uint8 val) -{ - int32 current_disk_flags; - int kt, - addr; - FILE *cpx; - UNIT *uptr; - int32 rtn; - -#if 0 - printf("%02x %02x %02x %02x %02x %02x %02x %02x \n", - val, - dsc->cmd_unit, - dsc->result, - dsc->nn, - dsc->track, - dsc->sector, - dsc->addr_l, - dsc->addr_h); -#endif - - current_disk = (utrans[dsc->cmd_unit & UMASK]) - 1; /* 0 <= current_disk < NUM_OF_DSK */ - if (current_disk >= NUM_OF_DSK) { - if (hasVerbose() && (warnDSK11 < warnLevelDSK)) { - warnDSK11++; -/*03*/ printf("FIF%i: " ADDRESS_FORMAT " Attempt disk io on illegal disk %d - ignored." NLP, current_disk, PCX, current_disk); - } - return 0; /* no drive selected - can do nothing */ - } - current_disk_flags = (fif_dev.units + current_disk)->flags; - if ((current_disk_flags & UNIT_ATT) == 0) { /* nothing attached? */ - if ( (current_disk_flags & UNIT_DSK_VERBOSE) && (warnAttached[current_disk] < warnLevelDSK) ) { - warnAttached[current_disk]++; -/*02*/printf("FIF%i: " ADDRESS_FORMAT " Attempt to select unattached FIF%d - ignored." NLP, current_disk, PCX, current_disk); - } - current_disk = NUM_OF_DSK; - return 2; - } - - uptr = fif_dev.units + current_disk; - cpx = uptr->fileref; - - /* decode request: */ - switch (dsc->cmd_unit >> 4) { - case FMT_TRACK: - /*printf("%c", dsc->track % 10 ? '*' : '0' + + dsc->track / 10); */ - /*Sleep(250); */ - memset(blanksec, 0, SEC_SZ); - addr = dsc->track * SPT; - sim_fseek(cpx, addr * SEC_SZ, SEEK_SET); - - /* write a track worth of sectors */ - for (kt=0; kt < SPT; kt++) { - sim_fwrite(blanksec, 1, sizeof(blanksec), cpx); - } - break; - - case READ_SEC: - addr = (dsc->track * SPT) + dsc->sector - 1; - sim_fseek(cpx, addr * SEC_SZ, SEEK_SET); - rtn = sim_fread(blanksec, 1, SEC_SZ, cpx); - if ( (rtn != SEC_SZ) && (current_disk_flags & UNIT_DSK_VERBOSE) && - (warnAttached[current_disk] < warnLevelDSK) ) { - warnAttached[current_disk]++; - printf("FIF%i: " ADDRESS_FORMAT " sim_fread error." NLP, current_disk, PCX); - } - addr = dsc->addr_l + (dsc->addr_h << 8); /* no assumption on endianness */ - for (kt = 0; kt < SEC_SZ; kt++) { - PutBYTEWrapper(addr++, blanksec[kt]); - } - break; - - case WRITE_SEC: - addr = (dsc->track * SPT) + dsc->sector - 1; - sim_fseek(cpx, addr * SEC_SZ, SEEK_SET); - addr = dsc->addr_l + (dsc->addr_h << 8); /* no assumption on endianness */ - for (kt = 0; kt < SEC_SZ; kt++) { - blanksec[kt] = GetBYTEWrapper(addr++); - } - sim_fwrite(blanksec, 1, SEC_SZ, cpx); - break; - - default: - ; - } - return 1; -} - -/********************************************************************** - - Copy the disk descriptor from target RAM - -*/ -static void getdesc(uint16 addr) { - uint32 x; - uint8 *p1 = (uint8*)&mydesc; - - for (x = 0; x < sizeof(mydesc); x++) { - *p1++ = GetBYTEWrapper(addr++); - } -} - -/********************************************************************** - - handle the IMSAI FIF floppy controller - -*/ -static int32 fif_io(const int32 port, const int32 io, const int32 data) { - - static int32 fdstate = 0; /* chan 0xfd state */ - static int32 desc; - static uint16 fdAdr[16]; /* disk descriptor address in 8080/z80 RAM */ - - /* cmd | desc# */ - /* cmd == 0x00 do operation */ - /* cmd == 0x10 next 2 transfers are desc address */ - /* desc# is one of 16 0x0 - 0xf */ - - if (!io) { - return 0; - } - - switch (fdstate) { - case 0: - desc = data & 0xf; - if ((data & 0x10) != 0) { /* prefix 0x10 */ - fdstate++; /* means desc address is next 2 out (fd),a */ - } - else { /* do what descriptor says */ - getdesc(fdAdr[desc]); - PutBYTEWrapper(fdAdr[desc] + 1, - (uint8)DoDiskOperation(&mydesc, (uint8)data)); - } - break; - - case 1: - /*printf("D1 %02x %02x\n", desc, data); */ - fdAdr[desc] = data; /* LSB of descriptor address */ - fdstate++; - break; - - case 2: - /*printf("D2 %02x %02x\n", desc, data); */ - fdAdr[desc] |= data << 8; /* MSB of descriptor address */ - fdstate = 0; - break; - } - return 0; -} - -#define ERNIES_FTP 0 -#if ERNIES_FTP - -#define WRK_BUF_SZ 150 -#define FCB_SIZE 32 -#define NAME_LTH 8 -#define EXT_LTH 3 - - -/************************************************** -*/ -static void xfero(int32 addr, char *src, int32 lth) -{ - while (lth--) { - PutBYTEWrapper(addr++, *src++); - } -} - -/************************************************** -*/ -static void xferi(int32 addr, char *dst, int32 lth) -{ - while (lth--) { - *dst++ = GetBYTEWrapper(addr++); - } -} - -#if !defined (_WIN32) -static void strupr(char *fn) { - while (*fn) { - if (('a' <= *fn) && (*fn <= 'z')) - *fn -= 'a' - 'A'; - fn++; - } -} -#endif - -/************************************************** -*/ -static void initfcb(char *fcb, char *fn, int32 flg) -{ - char *p1 = fcb; - - if (flg) - { - strupr(fn); - } - memset (fcb, 0 , FCB_SIZE); - memset (fcb + 1, ' ', NAME_LTH + EXT_LTH); - p1++; - while (*fn && (*fn != '.')) - { - *p1++ = *fn++; - } - if (*fn == '.') - { - fn++; - } - p1 = fcb + NAME_LTH + 1; - while (*fn && (*fn != '.')) - { - *p1++ = *fn++; - } -} - -/************************************************** - - FTP interface - most of the work is done here - The IMDOS/CPM application only does minimal work - -*/ - -char message[WRK_BUF_SZ]; -char temp [WRK_BUF_SZ]; -FILE * myfile; - -uint8 FTP(int32 BC, int32 DE) -{ - char *p1, *p2; - int32 retval; - - xferi(DE, temp, SEC_SZ); - p1 = temp; - switch (BC & 0x7f) - { - case 0: - memcpy(message, p1 + 2, *(p1 + 1)); - *(message + *(p1 + 1)) = 0; - p2 = strtok(message, " \t"); - if (!strcmp(p2, "get")) - { - p2 = strtok(NULL, " \t"); - if (myfile = fopen(p2, "rb")) - { - initfcb(temp, p2, 1); - xfero(DE + 2, temp, 32); - retval = 0; - break; - } - } - if (!strcmp(p2, "era")) - { - p2 = strtok(NULL, " \t"); - initfcb(temp, p2, 0); - xfero(DE + 2, temp, 32); - retval = 1; - break; - } - retval = 0xff; - break; - - case 20: - memset(temp, 0x1a, SEC_SZ); - retval = sim_fread(temp, 1, SEC_SZ, myfile) ? 0 : 1; - xfero( DE, temp, SEC_SZ); - if (retval) - { - fclose(myfile); - } - break; - } - return retval; -} - -#endif /* ERNIES_FTP */ - -/* end of the source */ - - - diff --git a/AltairZ80/s100_hdc1001.c b/AltairZ80/s100_hdc1001.c deleted file mode 100644 index d23db1da..00000000 --- a/AltairZ80/s100_hdc1001.c +++ /dev/null @@ -1,579 +0,0 @@ -/************************************************************************* - * * - * $Id: s100_hdc1001.c 1995 2008-07-15 03:59:13Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Advanced Digital Corporation (ADC) HDC-1001 Hard Disk Controller * - * module for SIMH. The HDC-1001 controller uses the standard IDE/ATA * - * task-file, so this controller should be compatible with other con- * - * trollers that use IDE, like the GIDE interface. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#include "sim_imd.h" - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define STATUS_MSG (1 << 5) -#define VERBOSE_MSG (1 << 7) - -#define HDC1001_MAX_DRIVES 4 - -typedef struct { - UNIT *uptr; - DISK_INFO *imd; - uint16 sectsize; /* sector size, not including pre/postamble */ - uint16 nsectors; /* number of sectors/track */ - uint16 nheads; /* number of heads */ - uint16 ntracks; /* number of tracks */ - uint16 res_tracks; /* Number of reserved tracks on drive. */ - uint16 track; /* Current Track */ - - uint16 cur_sect; /* current starting sector of transfer */ - uint16 cur_track; /* Current Track */ - uint16 xfr_nsects; /* Number of sectors to transfer */ - uint8 ready; /* Is drive ready? */ -} HDC1001_DRIVE_INFO; - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint8 sel_drive; /* Currently selected drive */ - uint8 taskfile[8]; /* ATA Task File Registers */ - uint8 mode; /* mode (0xFF=absolute, 0x00=logical) */ - uint8 retries; /* Number of retries to attempt */ - uint8 ndrives; /* Number of drives attached to the controller */ - - uint32 link_addr; /* Link Address for next IOPB */ - uint32 dma_addr; /* DMA Address for the current IOPB */ - - HDC1001_DRIVE_INFO drive[HDC1001_MAX_DRIVES]; - uint8 iopb[16]; -} HDC1001_INFO; - -static HDC1001_INFO hdc1001_info_data = { { 0x0, 0, 0xC8, 8 } }; -static HDC1001_INFO *hdc1001_info = &hdc1001_info_data; - -extern uint32 PCX; -extern REG *sim_PC; -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern int32 find_unit_index(UNIT *uptr); - -/* These are needed for DMA. */ -extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); -extern uint8 GetBYTEWrapper(const uint32 Addr); - -#define UNIT_V_HDC1001_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_HDC1001_WLK (1 << UNIT_V_HDC1001_WLK) -#define UNIT_V_HDC1001_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_HDC1001_VERBOSE (1 << UNIT_V_HDC1001_VERBOSE) -#define HDC1001_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ - -static t_stat hdc1001_reset(DEVICE *hdc1001_dev); -static t_stat hdc1001_attach(UNIT *uptr, char *cptr); -static t_stat hdc1001_detach(UNIT *uptr); - -static int32 hdc1001dev(const int32 port, const int32 io, const int32 data); - -static uint8 HDC1001_Read(const uint32 Addr); -static uint8 HDC1001_Write(const uint32 Addr, uint8 cData); - -static UNIT hdc1001_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDC1001_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDC1001_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDC1001_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDC1001_CAPACITY) } -}; - -static REG hdc1001_reg[] = { - { NULL } -}; - -static MTAB hdc1001_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_HDC1001_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_HDC1001_WLK, UNIT_HDC1001_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_HDC1001_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_HDC1001_VERBOSE, UNIT_HDC1001_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB hdc1001_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "CMD", CMD_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "STATUS", STATUS_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { NULL, 0 } -}; - -DEVICE hdc1001_dev = { - "HDC1001", hdc1001_unit, hdc1001_reg, hdc1001_mod, - HDC1001_MAX_DRIVES, 10, 31, 1, HDC1001_MAX_DRIVES, HDC1001_MAX_DRIVES, - NULL, NULL, &hdc1001_reset, - NULL, &hdc1001_attach, &hdc1001_detach, - &hdc1001_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - hdc1001_dt, NULL, "ADC Hard Disk Controller HDC1001" -}; - -/* Reset routine */ -static t_stat hdc1001_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &hdc1001dev, TRUE); - } else { - /* Connect HDC1001 at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &hdc1001dev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - - hdc1001_info->link_addr = 0x50; /* After RESET, the link pointer is at 0x50. */ - - return SCPE_OK; -} - - -/* Attach routine */ -static t_stat hdc1001_attach(UNIT *uptr, char *cptr) -{ - t_stat r = SCPE_OK; - HDC1001_DRIVE_INFO *pDrive; - int i = 0; - - i = find_unit_index(uptr); - if (i == -1) { - return (SCPE_IERR); - } - pDrive = &hdc1001_info->drive[i]; - - pDrive->ready = 1; - pDrive->track = 5; - pDrive->ntracks = 243; - pDrive->nheads = 8; - pDrive->nsectors = 11; - pDrive->sectsize = 1024; - - r = attach_unit(uptr, cptr); /* attach unit */ - if ( r != SCPE_OK) /* error? */ - return r; - - /* Determine length of this disk */ - if(sim_fsize(uptr->fileref) != 0) { - uptr->capac = sim_fsize(uptr->fileref); - } else { - uptr->capac = (pDrive->ntracks * pDrive->nsectors * pDrive->nheads * pDrive->sectsize); - } - - pDrive->uptr = uptr; - - /* Default for new file is DSK */ - uptr->u3 = IMAGE_TYPE_DSK; - - if(uptr->capac > 0) { - r = assignDiskType(uptr); - if (r != SCPE_OK) { - hdc1001_detach(uptr); - return r; - } - } - - if (uptr->flags & UNIT_HDC1001_VERBOSE) - printf("HDC1001%d, attached to '%s', type=%s, len=%d\n", i, cptr, - uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", - uptr->capac); - - if(uptr->u3 == IMAGE_TYPE_IMD) { - if(uptr->capac < 318000) { - printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n"); - hdc1001_detach(uptr); - return SCPE_OPENERR; - } - - if (uptr->flags & UNIT_HDC1001_VERBOSE) - printf("--------------------------------------------------------\n"); - hdc1001_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_HDC1001_VERBOSE)); - if (uptr->flags & UNIT_HDC1001_VERBOSE) - printf("\n"); - } else { - hdc1001_info->drive[i].imd = NULL; - } - - return SCPE_OK; -} - - -/* Detach routine */ -t_stat hdc1001_detach(UNIT *uptr) -{ - HDC1001_DRIVE_INFO *pDrive; - t_stat r; - int8 i; - - i = find_unit_index(uptr); - - if (i == -1) { - return (SCPE_IERR); - } - - pDrive = &hdc1001_info->drive[i]; - - pDrive->ready = 0; - - if (uptr->flags & UNIT_HDC1001_VERBOSE) - printf("Detach HDC1001%d\n", i); - - r = detach_unit(uptr); /* detach unit */ - if ( r != SCPE_OK) - return r; - - return SCPE_OK; -} - - -static int32 hdc1001dev(const int32 port, const int32 io, const int32 data) -{ -/* sim_debug(VERBOSE_MSG, &hdc1001_dev, "HDC1001: " ADDRESS_FORMAT " IO %s, Port %02x\n", PCX, io ? "WR" : "RD", port); */ - if(io) { - HDC1001_Write(port, data); - return 0; - } else { - return(HDC1001_Read(port)); - } -} - -#define HDC1001_CSR 0 /* R=HDC1001 Status / W=HDC1001 Control Register */ -#define HDC1001_DATA 1 /* R=Step Pulse / W=Write Data Register */ - -#define HDC1001_OP_DRIVE 0x00 -#define HDC1001_OP_CYL 0x01 -#define HDC1001_OP_HEAD 0x02 -#define HDC1001_OP_SECTOR 0x03 - -#define HDC1001_CMD_NULL 0x00 -#define HDC1001_CMD_READ_DATA 0x01 -#define HDC1001_CMD_WRITE_DATA 0x02 -#define HDC1001_CMD_WRITE_HEADER 0x03 -#define HDC1001_CMD_READ_HEADER 0x04 - -#define HDC1001_STATUS_BUSY 0 -#define HDC1001_STATUS_RANGE 1 -#define HDC1001_STATUS_NOT_READY 2 -#define HDC1001_STATUS_TIMEOUT 3 -#define HDC1001_STATUS_DAT_CRC 4 -#define HDC1001_STATUS_WR_FAULT 5 -#define HDC1001_STATUS_OVERRUN 6 -#define HDC1001_STATUS_HDR_CRC 7 -#define HDC1001_STATUS_MAP_FULL 8 -#define HDC1001_STATUS_COMPLETE 0xFF /* Complete with No Error */ - -#define HDC1001_CODE_NOOP 0x00 -#define HDC1001_CODE_VERSION 0x01 -#define HDC1001_CODE_GLOBAL 0x02 -#define HDC1001_CODE_SPECIFY 0x03 -#define HDC1001_CODE_SET_MAP 0x04 -#define HDC1001_CODE_HOME 0x05 -#define HDC1001_CODE_SEEK 0x06 -#define HDC1001_CODE_READ_HDR 0x07 -#define HDC1001_CODE_READWRITE 0x08 -#define HDC1001_CODE_RELOCATE 0x09 -#define HDC1001_CODE_FORMAT 0x0A -#define HDC1001_CODE_FORMAT_BAD 0x0B -#define HDC1001_CODE_STATUS 0x0C -#define HDC1001_CODE_SELECT 0x0D -#define HDC1001_CODE_EXAMINE 0x0E -#define HDC1001_CODE_MODIFY 0x0F - -#define HDC1001_IOPB_LEN 16 - -#define TF_DATA 0 -#define TF_ERROR 1 -#define TF_SECNT 2 -#define TF_SECNO 3 -#define TF_CYLLO 4 -#define TF_CYLHI 5 -#define TF_SDH 6 -#define TF_CMD 7 - -static uint8 HDC1001_Write(const uint32 Addr, uint8 cData) -{ -/* uint8 result = HDC1001_STATUS_COMPLETE; */ - - HDC1001_DRIVE_INFO *pDrive; - - pDrive = &hdc1001_info->drive[hdc1001_info->sel_drive]; - - switch(Addr & 0x07) { - case TF_SDH: - hdc1001_info->sel_drive = (cData >> 3) & 0x03; - case TF_DATA: - case TF_ERROR: - case TF_SECNT: - case TF_SECNO: - case TF_CYLLO: - case TF_CYLHI: - hdc1001_info->taskfile[Addr & 0x07] = cData; - sim_debug(VERBOSE_MSG, &hdc1001_dev, "HDC1001: " ADDRESS_FORMAT - " WR TF[%d]=0x%02x\n", PCX, Addr & 7, cData); - break; - case TF_CMD: - pDrive->track = hdc1001_info->taskfile[TF_CYLLO] | (hdc1001_info->taskfile[TF_CYLHI] << 8); - pDrive->xfr_nsects = hdc1001_info->taskfile[TF_SECNT]; - - sim_debug(CMD_MSG, &hdc1001_dev, "HDC1001[%d]: Command=%d, T:%d/H:%d/S:%d N=%d\n", - hdc1001_info->sel_drive, - hdc1001_info->taskfile[TF_CMD], - pDrive->track, hdc1001_info->taskfile[TF_SDH] & 0x07, - hdc1001_info->taskfile[TF_SECNO], pDrive->xfr_nsects); - break; - default: - break; - } - return 0; -} - -static uint8 HDC1001_Read(const uint32 Addr) -{ - uint8 cData; - - cData = hdc1001_info->taskfile[Addr & 0x07]; - sim_debug(VERBOSE_MSG, &hdc1001_dev, "HDC1001: " ADDRESS_FORMAT - " RD TF[%d]=0x%02x\n", PCX, Addr & 7, cData); - - return (cData); -} - -#if 0 - for(i = 0; i < HDC1001_IOPB_LEN; i++) { - hdc1001_info->iopb[i] = GetBYTEWrapper(hdc1001_info->link_addr + i); - } - - cmd = hdc1001_info->iopb[0]; - hdc1001_info->sel_drive = hdc1001_info->iopb[2]; - - hdc1001_info->dma_addr = hdc1001_info->iopb[0x0A]; - hdc1001_info->dma_addr |= hdc1001_info->iopb[0x0B] << 8; - hdc1001_info->dma_addr |= hdc1001_info->iopb[0x0C] << 16; - - next_link = hdc1001_info->iopb[0x0D]; - next_link |= hdc1001_info->iopb[0x0E] << 8; - next_link |= hdc1001_info->iopb[0x0F] << 16; - - sim_debug(VERBOSE_MSG, &hdc1001_dev, "HDC1001[%d]: LINK=0x%05x, NEXT=0x%05x, CMD=%x, DMA@0x%05x\n", hdc1001_info->sel_drive, hdc1001_info->link_addr, next_link, hdc1001_info->iopb[0], hdc1001_info->dma_addr); - - - - if(pDrive->ready) { - - /* Perform command */ - switch(cmd) { - case HDC1001_CODE_NOOP: - sim_debug(VERBOSE_MSG, &hdc1001_dev, "HDC1001[%d]: " ADDRESS_FORMAT " NOOP\n", hdc1001_info->sel_drive, PCX); - break; - case HDC1001_CODE_VERSION: - break; - case HDC1001_CODE_GLOBAL: - sim_debug(CMD_MSG, &hdc1001_dev, "HDC1001[%d]: " ADDRESS_FORMAT " GLOBAL\n", hdc1001_info->sel_drive, PCX); - - hdc1001_info->mode = hdc1001_info->iopb[3]; - hdc1001_info->retries = hdc1001_info->iopb[4]; - hdc1001_info->ndrives = hdc1001_info->iopb[5]; - - sim_debug(VERBOSE_MSG, &hdc1001_dev, " Mode: 0x%02x\n", hdc1001_info->mode); - sim_debug(VERBOSE_MSG, &hdc1001_dev, " # Retries: 0x%02x\n", hdc1001_info->retries); - sim_debug(VERBOSE_MSG, &hdc1001_dev, " # Drives: 0x%02x\n", hdc1001_info->ndrives); - - break; - case HDC1001_CODE_SPECIFY: - { - uint8 specify_data[22]; - sim_debug(CMD_MSG, &hdc1001_dev, "HDC1001[%d]: " ADDRESS_FORMAT " SPECIFY\n", hdc1001_info->sel_drive, PCX); - - for(i = 0; i < 22; i++) { - specify_data[i] = GetBYTEWrapper(hdc1001_info->dma_addr + i); - } - - pDrive->sectsize = specify_data[4] | (specify_data[5] << 8); - pDrive->nsectors = specify_data[6] | (specify_data[7] << 8); - pDrive->nheads = specify_data[8] | (specify_data[9] << 8); - pDrive->ntracks = specify_data[10] | (specify_data[11] << 8); - pDrive->res_tracks = specify_data[18] | (specify_data[19] << 8); - - sim_debug(VERBOSE_MSG, &hdc1001_dev, " Sectsize: %d\n", pDrive->sectsize); - sim_debug(VERBOSE_MSG, &hdc1001_dev, " Sectors: %d\n", pDrive->nsectors); - sim_debug(VERBOSE_MSG, &hdc1001_dev, " Heads: %d\n", pDrive->nheads); - sim_debug(VERBOSE_MSG, &hdc1001_dev, " Tracks: %d\n", pDrive->ntracks); - sim_debug(VERBOSE_MSG, &hdc1001_dev, " Reserved: %d\n", pDrive->res_tracks); - break; - } - case HDC1001_CODE_HOME: - pDrive->track = 0; - sim_debug(SEEK_MSG, &hdc1001_dev, "HDC1001[%d]: " ADDRESS_FORMAT " HOME\n", hdc1001_info->sel_drive, PCX); - break; - case HDC1001_CODE_SEEK: - pDrive->track = hdc1001_info->iopb[3]; - pDrive->track |= (hdc1001_info->iopb[4] << 8); - - if(pDrive->track > pDrive->ntracks) { - sim_debug(ERROR_MSG, &hdc1001_dev, "HDC1001[%d]: " ADDRESS_FORMAT " SEEK ERROR %d not found\n", hdc1001_info->sel_drive, PCX, pDrive->track); - pDrive->track = pDrive->ntracks - 1; - result = HDC1001_STATUS_TIMEOUT; - } else { - sim_debug(SEEK_MSG, &hdc1001_dev, "HDC1001[%d]: " ADDRESS_FORMAT " SEEK %d\n", hdc1001_info->sel_drive, PCX, pDrive->track); - } - break; - case HDC1001_CODE_READ_HDR: - { - sim_debug(CMD_MSG, &hdc1001_dev, "HDC1001[%d]: " ADDRESS_FORMAT " READ HEADER: %d\n", pDrive->track, PCX); - PutBYTEWrapper(hdc1001_info->dma_addr + 0, pDrive->track & 0xFF); - PutBYTEWrapper(hdc1001_info->dma_addr + 1, (pDrive->track >> 8) & 0xFF); - PutBYTEWrapper(hdc1001_info->dma_addr + 2, 0); - PutBYTEWrapper(hdc1001_info->dma_addr + 3, 1); - - break; - } - case HDC1001_CODE_READWRITE: - { - uint32 track_len; - uint32 xfr_len; - uint32 file_offset; - uint32 xfr_count = 0; - uint8 *dataBuffer; - - pDrive->cur_sect = hdc1001_info->iopb[4] | (hdc1001_info->iopb[5] << 8); - pDrive->cur_track = hdc1001_info->iopb[6] | (hdc1001_info->iopb[7] << 8); - pDrive->xfr_nsects = hdc1001_info->iopb[8] | (hdc1001_info->iopb[9] << 8); - - track_len = pDrive->nsectors * pDrive->sectsize; - - file_offset = (pDrive->cur_track * track_len); /* Calculate offset based on current track */ - file_offset += pDrive->cur_sect + pDrive->sectsize; - - xfr_len = pDrive->xfr_nsects * pDrive->sectsize; - - dataBuffer = malloc(xfr_len); - - sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET); - - if(hdc1001_info->iopb[3] == 1) { /* Read */ - sim_debug(RD_DATA_MSG, &hdc1001_dev, "HDC1001[%d]: " ADDRESS_FORMAT " READ @0x%05x T:%04d/S:%04d/#:%d\n", hdc1001_info->sel_drive, PCX, hdc1001_info->dma_addr, pDrive->cur_track, pDrive->cur_sect, pDrive->xfr_nsects ); - - sim_fread(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref); - - /* Perform DMA Transfer */ - for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) { - PutBYTEWrapper(hdc1001_info->dma_addr + xfr_count, dataBuffer[xfr_count]); - } - } else { /* Write */ - sim_debug(WR_DATA_MSG, &hdc1001_dev, "HDC1001[%d]: " ADDRESS_FORMAT " WRITE @0x%05x T:%04d/S:%04d/#:%d\n", hdc1001_info->sel_drive, PCX, hdc1001_info->dma_addr, pDrive->cur_track, pDrive->cur_sect, pDrive->xfr_nsects ); - - /* Perform DMA Transfer */ - for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) { - dataBuffer[xfr_count] = GetBYTEWrapper(hdc1001_info->dma_addr + xfr_count); - } - - sim_fwrite(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref); - } - - free(dataBuffer); - - break; - } - case HDC1001_CODE_FORMAT: - { - uint32 data_len; - uint32 file_offset; - uint8 *fmtBuffer; - - data_len = pDrive->nsectors * pDrive->sectsize; - - sim_debug(WR_DATA_MSG, &hdc1001_dev, "HDC1001[%d]: " ADDRESS_FORMAT " FORMAT T:%d/H:%d/Fill=0x%02x/Len=%d\n", hdc1001_info->sel_drive, PCX, pDrive->track, hdc1001_info->iopb[5], hdc1001_info->iopb[4], data_len ); - - file_offset = (pDrive->track * (pDrive->nheads) * data_len); /* Calculate offset based on current track */ - file_offset += (hdc1001_info->iopb[5] * data_len); - - fmtBuffer = malloc(data_len); - memset(fmtBuffer, hdc1001_info->iopb[4], data_len); - - sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET); - sim_fwrite(fmtBuffer, 1, data_len, (pDrive->uptr)->fileref); - - free(fmtBuffer); - - break; - } - case HDC1001_CODE_SET_MAP: - case HDC1001_CODE_RELOCATE: - case HDC1001_CODE_FORMAT_BAD: - case HDC1001_CODE_STATUS: - case HDC1001_CODE_SELECT: - case HDC1001_CODE_EXAMINE: - case HDC1001_CODE_MODIFY: - default: - sim_debug(ERROR_MSG, &hdc1001_dev, "HDC1001[%d]: " ADDRESS_FORMAT " CMD=%x Unsupported\n", hdc1001_info->sel_drive, PCX, cmd); - break; - } - } else { /* Drive not ready */ - result = HDC1001_STATUS_NOT_READY; - } - - /* Return status */ - PutBYTEWrapper(hdc1001_info->link_addr + 1, result); - - hdc1001_info->link_addr = next_link; - - return 0; -} -#endif /* 0 */ diff --git a/AltairZ80/s100_if3.c b/AltairZ80/s100_if3.c deleted file mode 100644 index 8c844512..00000000 --- a/AltairZ80/s100_if3.c +++ /dev/null @@ -1,361 +0,0 @@ -/************************************************************************* - * * - * $Id: s100_if3.c 1991 2008-07-10 16:06:12Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * CompuPro System Support 1 module for SIMH. * - * Note this does not include the Boot ROM on the System Support 1 Card * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/*#define DBG_MSG */ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#include - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define TRACE_MSG (1 << 1) -#define RXIRQ_MSG (1 << 2) -#define TXIRQ_MSG (1 << 3) -#define UART_MSG (1 << 4) -#define USER_MSG (1 << 5) - -#define IF3_MAX_BOARDS 4 - -#define UNIT_V_IF3_CONNECT (UNIT_V_UF + 1) /* Connect/Disconnect IF3 unit */ -#define UNIT_IF3_CONNECT (1 << UNIT_V_IF3_CONNECT) - -#define IF3_PORT_BASE 0x300 - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ -} IF3_INFO; - -static IF3_INFO if3_info_data = { { 0x0, 0, 0x10, 8 } }; - -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern uint32 PCX; - -extern int32 sio0d(const int32 port, const int32 io, const int32 data); -extern int32 sio0s(const int32 port, const int32 io, const int32 data); - -static t_stat set_if3_connect(UNIT *uptr, int32 val, char *cptr, void *desc); - -static t_stat if3_reset(DEVICE *if3_dev); -static t_stat if3_svc (UNIT *uptr); -static uint8 IF3_Read(const uint32 Addr); -static uint8 IF3_Write(const uint32 Addr, uint8 cData); -static int32 if3dev(const int32 port, const int32 io, const int32 data); -static t_stat update_rx_tx_isr (UNIT *uptr); - -static UNIT if3_unit[] = { - { UDATA (&if3_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE | UNIT_IF3_CONNECT, 0) }, - { UDATA (&if3_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) }, - { UDATA (&if3_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) }, - { UDATA (&if3_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) } -}; - -static uint8 if3_user = 0; -static uint8 if3_board = 0; -static uint8 if3_rimr[IF3_MAX_BOARDS] = { 0, 0, 0, 0 }; -static uint8 if3_timr[IF3_MAX_BOARDS] = { 0, 0, 0, 0 }; -static uint8 if3_risr[IF3_MAX_BOARDS] = { 0, 0, 0, 0 }; -static uint8 if3_tisr[IF3_MAX_BOARDS] = { 0, 0, 0, 0 }; - -static REG if3_reg[] = { - { HRDATA (USER, if3_user, 3), }, - { HRDATA (BOARD, if3_board, 2), }, - { BRDATA (RIMR, &if3_rimr[0], 16, 8, 4), }, - { BRDATA (RISR, &if3_risr[0], 16, 8, 4), }, - { BRDATA (TIMR, &if3_timr[0], 16, 8, 4), }, - { BRDATA (TISR, &if3_tisr[0], 16, 8, 4), }, - { NULL } -}; - -static MTAB if3_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_IF3_CONNECT, UNIT_IF3_CONNECT,"INSTALLED", "INSTALLED", &set_if3_connect, NULL, NULL }, - { UNIT_IF3_CONNECT, 0, "UNINSTALLED","UNINSTALLED", &set_if3_connect, NULL, NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB if3_dt[] = { - { "ERROR", ERROR_MSG }, - { "TRACE", TRACE_MSG }, - { "RXIRQ", RXIRQ_MSG }, - { "TXIRQ", TXIRQ_MSG }, - { "UART", UART_MSG }, - { "USER", USER_MSG }, - { NULL, 0 } -}; - -DEVICE if3_dev = { - "IF3", if3_unit, if3_reg, if3_mod, - IF3_MAX_BOARDS, 10, 31, 1, IF3_MAX_BOARDS, IF3_MAX_BOARDS, - NULL, NULL, &if3_reset, - NULL, NULL, NULL, - &if3_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0, - if3_dt, NULL, "Compupro Interfacer 3 IF3" -}; - -static t_stat set_if3_connect(UNIT *uptr, int32 val, char *cptr, void *desc) -{ - if(uptr->flags & UNIT_DISABLE) { - sim_debug(ERROR_MSG, &if3_dev, "IF3[%d]: not enabled.\n", uptr->u3); - return SCPE_OK; - } - - if(val & UNIT_IF3_CONNECT) { - sim_debug((RXIRQ_MSG|TXIRQ_MSG), &if3_dev, "IF3[%d]: IRQ polling started...\n", uptr->u3); - sim_activate(uptr, 100000); - } else { - sim_debug((RXIRQ_MSG|TXIRQ_MSG), &if3_dev, "IF3[%d]: IRQ polling stopped.\n", uptr->u3); - sim_cancel(uptr); - } - return (SCPE_OK); -} - -/* Reset routine */ -static t_stat if3_reset(DEVICE *dptr) -{ - uint8 i; - - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ - for(i=0;iio_base, pnp->io_size, RESOURCE_TYPE_IO, &if3dev, TRUE); - } else { - /* Connect IF3 at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &if3dev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - - for(i=0;i> 3; /* guarantees that if3_board < IF3_MAX_BOARDS */ - if3_user = cData & 0x7; - sim_debug(USER_MSG, &if3_dev, "IF3[%d]: " ADDRESS_FORMAT " WR UART_SEL=0x%02x (Board=%d, Rel_User=%d, User=%d)\n", if3_board, PCX, cData, if3_board, if3_user, cData); - break; - } - - return(0); -} - -#define SS1_VI2_INT 2 /* IF3 Rx interrupts tied to VI2 */ -#define SS1_VI3_INT 3 /* IF3 Tx interrupts tied to VI3 */ - -#define IF3_NUM_PORTS 8 /* Number of ports per IF3 board */ - -extern void raise_ss1_interrupt(uint8 isr_index); - -/* Unit service routine */ -static t_stat if3_svc (UNIT *uptr) -{ - uint8 pending_rx_irqs; - uint8 pending_tx_irqs; - uint8 board = uptr->u3; - - update_rx_tx_isr(uptr); - - pending_rx_irqs = if3_risr[board] & if3_rimr[board]; - if(pending_rx_irqs) { - sim_debug(RXIRQ_MSG, &if3_dev, "IF3[%d]: " ADDRESS_FORMAT " Rx IRQ Pending: 0x%02x\n", board, PCX, pending_rx_irqs); - raise_ss1_interrupt(SS1_VI2_INT); - } - - pending_tx_irqs = if3_tisr[board] & if3_timr[board]; - if(pending_tx_irqs) { - sim_debug(TXIRQ_MSG, &if3_dev, "IF3[%d]: " ADDRESS_FORMAT " Tx IRQ Pending: 0x%02x\n", board, PCX, pending_tx_irqs); - raise_ss1_interrupt(SS1_VI3_INT); - } - - sim_activate(&if3_unit[board], 200000); - return SCPE_OK; -} - - -static t_stat update_rx_tx_isr (UNIT *uptr) -{ - uint8 i; - uint8 cData; - uint8 board = uptr->u3; - - if3_risr[board] = 0; - if3_tisr[board] = 0; - - for(i=0;i -#endif - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define VERBOSE_MSG (1 << 7) - -#define MDRIVEH_MAX_DRIVES 8 - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint32 dma_addr; /* DMA Transfer Address */ - UNIT uptr[MDRIVEH_MAX_DRIVES]; - uint8 *storage[MDRIVEH_MAX_DRIVES]; -} MDRIVEH_INFO; - -static MDRIVEH_INFO mdriveh_info_data = { { 0x0, 0, 0xC6, 2 } }; -static MDRIVEH_INFO *mdriveh_info = &mdriveh_info_data; - -extern uint32 PCX; -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); - -extern REG *sim_PC; - -#define UNIT_V_MDRIVEH_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_MDRIVEH_WLK (1 << UNIT_V_MDRIVEH_WLK) -#define UNIT_V_MDRIVEH_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_MDRIVEH_VERBOSE (1 << UNIT_V_MDRIVEH_VERBOSE) -#define MDRIVEH_CAPACITY (512 * 1000) /* Default M-DRIVE/H Capacity */ -#define MDRIVEH_NONE 0 - -static t_stat mdriveh_reset(DEVICE *mdriveh_dev); -static int32 mdrivehdev(const int32 port, const int32 io, const int32 data); -static uint8 MDRIVEH_Read(const uint32 Addr); -static uint8 MDRIVEH_Write(const uint32 Addr, uint8 cData); - -static UNIT mdriveh_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ROABLE, MDRIVEH_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_DIS + UNIT_ROABLE, MDRIVEH_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_DIS + UNIT_ROABLE, MDRIVEH_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_DIS + UNIT_ROABLE, MDRIVEH_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_DIS + UNIT_ROABLE, MDRIVEH_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_DIS + UNIT_ROABLE, MDRIVEH_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_DIS + UNIT_ROABLE, MDRIVEH_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_DIS + UNIT_ROABLE, MDRIVEH_CAPACITY) } -}; - -static REG mdriveh_reg[] = { - { NULL } -}; - -static MTAB mdriveh_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_MDRIVEH_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_MDRIVEH_WLK, UNIT_MDRIVEH_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_MDRIVEH_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_MDRIVEH_VERBOSE, UNIT_MDRIVEH_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB mdriveh_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { NULL, 0 } -}; - -DEVICE mdriveh_dev = { - "MDRIVEH", mdriveh_unit, mdriveh_reg, mdriveh_mod, - MDRIVEH_MAX_DRIVES, 10, 31, 1, MDRIVEH_MAX_DRIVES, MDRIVEH_MAX_DRIVES, - NULL, NULL, &mdriveh_reset, - NULL, NULL, NULL, - &mdriveh_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - mdriveh_dt, NULL, "Compupro Memory Drive MDRIVEH" -}; - - -/* Reset routine */ -static t_stat mdriveh_reset(DEVICE *dptr) -{ - uint8 i; - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect ROM and I/O Ports */ - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &mdrivehdev, TRUE); - } else { - /* Connect MDRIVEH at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &mdrivehdev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - - for(i=0; iuptr[i] = dptr->units[i]; - if((dptr->flags & DEV_DIS) || (dptr->units[i].flags & UNIT_DIS)) { - if (dptr->units[i].flags & UNIT_MDRIVEH_VERBOSE) - printf("MDRIVEH: Unit %d disabled", i); - if(mdriveh_info->storage[i] != NULL) { - if (dptr->units[i].flags & UNIT_MDRIVEH_VERBOSE) - printf(", freed 0x%p\n", mdriveh_info->storage[i]); - free(mdriveh_info->storage[i]); - mdriveh_info->storage[i] = NULL; - } else if (dptr->units[i].flags & UNIT_MDRIVEH_VERBOSE) { - printf(".\n"); - } - } else { - if(mdriveh_info->storage[i] == NULL) { - mdriveh_info->storage[i] = calloc(1, 524288); - } - if (dptr->units[i].flags & UNIT_MDRIVEH_VERBOSE) - printf("MDRIVEH: Unit %d enabled, 512K at 0x%p\n", i, mdriveh_info->storage[i]); - } - } - - return SCPE_OK; -} - -static int32 mdrivehdev(const int32 port, const int32 io, const int32 data) -{ - DBG_PRINT(("MDRIVEH: " ADDRESS_FORMAT " IO %s, Port %02x" NLP, PCX, io ? "WR" : "RD", port)); - if(io) { - MDRIVEH_Write(port, data); - return 0; - } else { - return(MDRIVEH_Read(port)); - } -} - -#define MDRIVEH_DATA 0 /* R=Drive Status Register / W=DMA Address Register */ -#define MDRIVEH_ADDR 1 /* R=Unused / W=Motor Control Register */ - -static uint8 MDRIVEH_Read(const uint32 Addr) -{ - uint8 cData; - uint8 unit; - uint32 offset; - - cData = 0xFF; /* default is High-Z Data */ - - switch(Addr & 0x1) { - case MDRIVEH_ADDR: - sim_debug(VERBOSE_MSG, &mdriveh_dev, "MDRIVEH: " ADDRESS_FORMAT " RD Addr = 0x%02x\n", PCX, cData); - break; - case MDRIVEH_DATA: - unit = (mdriveh_info->dma_addr & 0x380000) >> 19; - offset = mdriveh_info->dma_addr & 0x7FFFF; - - if(mdriveh_info->storage[unit] != NULL) { - cData = mdriveh_info->storage[unit][offset]; - } - - sim_debug(RD_DATA_MSG, &mdriveh_dev, "MDRIVEH: " ADDRESS_FORMAT " RD Data [%x:%05x] = 0x%02x\n", PCX, unit, offset, cData); - - /* Increment M-DRIVE/H Data Address */ - mdriveh_info->dma_addr++; - mdriveh_info->dma_addr &= 0x3FFFFF; - break; - } - - return (cData); -} - -static uint8 MDRIVEH_Write(const uint32 Addr, uint8 cData) -{ - uint8 result = 0; - uint8 unit; - uint32 offset; - - switch(Addr & 0x1) { - case MDRIVEH_ADDR: - mdriveh_info->dma_addr <<= 8; - mdriveh_info->dma_addr &= 0x003FFF00; - mdriveh_info->dma_addr |= cData; - sim_debug(SEEK_MSG, &mdriveh_dev, "MDRIVEH: " ADDRESS_FORMAT " DMA Address=%06x\n", PCX, mdriveh_info->dma_addr); - break; - case MDRIVEH_DATA: - unit = (mdriveh_info->dma_addr & 0x380000) >> 19; - offset = mdriveh_info->dma_addr & 0x7FFFF; - - if(mdriveh_info->storage[unit] != NULL) { - if(mdriveh_info->uptr[unit].flags & UNIT_MDRIVEH_WLK) { - sim_debug(WR_DATA_MSG, &mdriveh_dev, "MDRIVEH: " ADDRESS_FORMAT " WR Data [%x:%05x] = Unit Write Locked\n", PCX, unit, offset); - } else { - sim_debug(WR_DATA_MSG, &mdriveh_dev, "MDRIVEH: " ADDRESS_FORMAT " WR Data [%x:%05x] = 0x%02x\n", PCX, unit, offset, cData); - mdriveh_info->storage[unit][offset] = cData; - } - } else { - sim_debug(WR_DATA_MSG, &mdriveh_dev, "MDRIVEH: " ADDRESS_FORMAT " WR Data [%x:%05x] = Unit OFFLINE\n", PCX, unit, offset); - } - - /* Increment M-DRIVE/H Data Address */ - mdriveh_info->dma_addr++; - mdriveh_info->dma_addr &= 0x3FFFFF; - break; - } - - return (result); -} - diff --git a/AltairZ80/s100_mdsad.c b/AltairZ80/s100_mdsad.c deleted file mode 100644 index fe3c5d65..00000000 --- a/AltairZ80/s100_mdsad.c +++ /dev/null @@ -1,780 +0,0 @@ -/************************************************************************* - * * - * $Id: s100_mdsad.c 1995 2008-07-15 03:59:13Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Northstar MDS-AD Disk Controller module for SIMH * - * Only Double-Density is supported for now. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/*#define DBG_MSG*/ -#include "altairz80_defs.h" -#include "sim_imd.h" - -#if defined (_WIN32) -#include -#endif - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define STATUS_MSG (1 << 5) -#define ORDERS_MSG (1 << 6) -#define VERBOSE_MSG (1 << 7) -#define RD_DATA_DETAIL_MSG (1 << 8) -#define WR_DATA_DETAIL_MSG (1 << 9) - -extern uint32 PCX; -extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern REG *sim_PC; - -#define MDSAD_MAX_DRIVES 4 -#define MDSAD_SECTOR_LEN 512 -#define MDSAD_SECTORS_PER_TRACK 10 -#define MDSAD_TRACKS 35 -#define MDSAD_RAW_LEN (32 + 2 + MDSAD_SECTOR_LEN + 1) - -typedef union { - struct { - uint8 zeros[32]; - uint8 sync[2]; - uint8 data[MDSAD_SECTOR_LEN]; - uint8 checksum; - } u; - uint8 raw[MDSAD_RAW_LEN]; - -} SECTOR_FORMAT; - -typedef struct { - UNIT *uptr; - uint8 track; - uint8 wp; /* Disk write protected */ - uint8 sector; /* Current Sector number */ - uint32 sector_wait_count; -} MDSAD_DRIVE_INFO; - -typedef struct { - uint8 dd; /* Controls density on write DD=1 for double density and DD=0 for single density. */ - uint8 ss; /* Specifies the side of a double-sided diskette. The bottom side (and only side of a single-sided diskette) is selected when SS=0. The second (top) side is selected when SS=1. */ - uint8 dp; /* has shared use. During stepping operations, DP=O specifies a step out and DP=1 specifies a step in. During write operations, write procompensation is invoked if and only if DP=1. */ - uint8 st; /* controls the level of the head step signal to the disk drives. */ - uint8 ds; /* is the drive select field, encoded as follows: */ - /* 0=no drive selected - * 1=drive 1 selected - * 2=drive 2 selected - * 4=drive 3 selected - * 8=drive 4 selected - */ -} ORDERS; - -typedef struct { - uint8 sf; /* Sector Flag: set when sector hole detected, reset by software. */ - uint8 ix; /* Index Detect: true if index hole detected during previous sector. */ - uint8 dd; /* Double Density Indicator: true if data being read is encoded in double density. */ - uint8 mo; /* Motor On: true while motor(s) are on. */ -} COM_STATUS; - -typedef struct { - uint8 wi; /* Window: true during 96-microsecond window at beginning of sector. */ - uint8 re; /* Read Enable: true while phase-locked loop is enabled. */ - uint8 sp; /* Spare: reserved for future use. */ - uint8 bd; /* Body: set when sync character is detected. */ -} A_STATUS; - -typedef struct { - uint8 wr; /* Write: true during valid write operation. */ - uint8 sp; /* Spare: reserved for future use. */ - uint8 wp; /* Write Protect: true while the diskette installed in the selected drive is write protected. */ - uint8 t0; /* Track 0: true if selected drive is at track zero. */ -} B_STATUS; - -typedef struct { - uint8 sc; /* Sector Counter: indicates the current sector position. */ -} C_STATUS; - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - - ORDERS orders; - COM_STATUS com_status; - A_STATUS a_status; - B_STATUS b_status; - C_STATUS c_status; - - uint8 int_enable; /* Interrupt Enable */ - uint32 datacount; /* Number of data bytes transferred from controller for current sector */ - MDSAD_DRIVE_INFO drive[MDSAD_MAX_DRIVES]; -} MDSAD_INFO; - -static MDSAD_INFO mdsad_info_data = { { 0xE800, 1024, 0, 0 } }; -static MDSAD_INFO *mdsad_info = &mdsad_info_data; - -static SECTOR_FORMAT sdata; - -#define UNIT_V_MDSAD_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_MDSAD_WLK (1 << UNIT_V_MDSAD_WLK) -#define UNIT_V_MDSAD_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_MDSAD_VERBOSE (1 << UNIT_V_MDSAD_VERBOSE) -#define MDSAD_CAPACITY (70*10*MDSAD_SECTOR_LEN) /* Default North Star Disk Capacity */ - -/* MDS-AD Controller Subcases */ -#define MDSAD_READ_ROM 0 -#define MDSAD_WRITE_DATA 1 -#define MDSAD_CTLR_ORDERS 2 -#define MDSAD_CTLR_COMMAND 3 - -/* MDS-AD Controller Commands */ -#define MDSAD_CMD_NOP 0 -#define MDSAD_CMD_RESET_SF 1 -#define MDSAD_CMD_INTR_DIS 2 -#define MDSAD_CMD_INTR_ARM 3 -#define MDSAD_CMD_SET_BODY 4 -#define MDSAD_CMD_MOTORS_ON 5 -#define MDSAD_CMD_BEGIN_WR 6 -#define MDSAD_CMD_RESET 7 - -/* MDS-AD Data returned on DI bus */ -#define MDSAD_A_STATUS 1 -#define MDSAD_B_STATUS 2 -#define MDSAD_C_STATUS 3 -#define MDSAD_READ_DATA 4 - -/* MDS-AD status byte masks */ -/* A-Status */ -#define MDSAD_A_SF 0x80 -#define MDSAD_A_IX 0x40 -#define MDSAD_A_DD 0x20 -#define MDSAD_A_MO 0x10 -#define MDSAD_A_WI 0x08 -#define MDSAD_A_RE 0x04 -#define MDSAD_A_SP 0x02 -#define MDSAD_A_BD 0x01 - -/* B-Status */ -#define MDSAD_B_SF 0x80 -#define MDSAD_B_IX 0x40 -#define MDSAD_B_DD 0x20 -#define MDSAD_B_MO 0x10 -#define MDSAD_B_WR 0x08 -#define MDSAD_B_SP 0x04 -#define MDSAD_B_WP 0x02 -#define MDSAD_B_T0 0x01 - -/* C-Status */ -#define MDSAD_C_SF 0x80 -#define MDSAD_C_IX 0x40 -#define MDSAD_C_DD 0x20 -#define MDSAD_C_MO 0x10 -#define MDSAD_C_SC 0x0f - -/* Local function prototypes */ -static t_stat mdsad_reset(DEVICE *mdsad_dev); -static t_stat mdsad_attach(UNIT *uptr, char *cptr); -static t_stat mdsad_detach(UNIT *uptr); -static t_stat mdsad_boot(int32 unitno, DEVICE *dptr); -static uint8 MDSAD_Read(const uint32 Addr); - -static int32 mdsaddev(const int32 Addr, const int32 rw, const int32 data); - -static UNIT mdsad_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MDSAD_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MDSAD_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MDSAD_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MDSAD_CAPACITY) } -}; - -static REG mdsad_reg[] = { - { NULL } -}; - -static MTAB mdsad_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, - { UNIT_MDSAD_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_MDSAD_WLK, UNIT_MDSAD_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_MDSAD_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_MDSAD_VERBOSE, UNIT_MDSAD_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB mdsad_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "CMD", CMD_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "STATUS", STATUS_MSG }, - { "ORDERS", ORDERS_MSG }, - { "RDDETAIL", RD_DATA_DETAIL_MSG }, - { "WRDETAIL", WR_DATA_DETAIL_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { NULL, 0 } -}; - -DEVICE mdsad_dev = { - "MDSAD", mdsad_unit, mdsad_reg, mdsad_mod, - MDSAD_MAX_DRIVES, 10, 31, 1, MDSAD_MAX_DRIVES, MDSAD_MAX_DRIVES, - NULL, NULL, &mdsad_reset, - &mdsad_boot, &mdsad_attach, &mdsad_detach, - &mdsad_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - mdsad_dt, NULL, "North Star Floppy Controller MDSAD" -}; - -/* Reset routine */ -t_stat mdsad_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { - sim_map_resource(pnp->mem_base, pnp->mem_size, - RESOURCE_TYPE_MEMORY, &mdsaddev, TRUE); - } else { - /* Connect MDSAD at base address */ - if(sim_map_resource(pnp->mem_base, pnp->mem_size, - RESOURCE_TYPE_MEMORY, &mdsaddev, FALSE) != 0) { - printf("%s: error mapping resource at 0x%04x\n", - __FUNCTION__, pnp->mem_base); - dptr->flags |= DEV_DIS; - return SCPE_ARG; - } - } - return SCPE_OK; -} - -/* Attach routine */ -t_stat mdsad_attach(UNIT *uptr, char *cptr) -{ - char header[4]; - t_stat r; - unsigned int i = 0; - - r = attach_unit(uptr, cptr); /* attach unit */ - if(r != SCPE_OK) /* error? */ - return r; - - /* Determine length of this disk */ - if(sim_fsize(uptr->fileref) != 0) { - uptr->capac = sim_fsize(uptr->fileref); - } else { - uptr->capac = MDSAD_CAPACITY; - } - - for(i = 0; i < MDSAD_MAX_DRIVES; i++) { - mdsad_info->drive[i].uptr = &mdsad_dev.units[i]; - } - - for(i = 0; i < MDSAD_MAX_DRIVES; i++) { - if(mdsad_dev.units[i].fileref == uptr->fileref) { - break; - } - } - - /* Default for new file is DSK */ - uptr->u3 = IMAGE_TYPE_DSK; - - if(uptr->capac > 0) { - char *rtn = fgets(header, 4, uptr->fileref); - if((rtn != NULL) && (strncmp(header, "CPT", 3) == 0)) { - printf("CPT images not yet supported\n"); - uptr->u3 = IMAGE_TYPE_CPT; - mdsad_detach(uptr); - return SCPE_OPENERR; - } else { - uptr->u3 = IMAGE_TYPE_DSK; - } - } - - if (uptr->flags & UNIT_MDSAD_VERBOSE) - printf("MDSAD%d, attached to '%s', type=%s, len=%d\n", i, cptr, - uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", - uptr->capac); - - return SCPE_OK; -} - - -/* Detach routine */ -t_stat mdsad_detach(UNIT *uptr) -{ - t_stat r; - int8 i; - - for(i = 0; i < MDSAD_MAX_DRIVES; i++) { - if(mdsad_dev.units[i].fileref == uptr->fileref) { - break; - } - } - - if (i >= MDSAD_MAX_DRIVES) - return SCPE_ARG; - - DBG_PRINT(("Detach MDSAD%d\n", i)); - - r = detach_unit(uptr); /* detach unit */ - if(r != SCPE_OK) - return r; - - mdsad_dev.units[i].fileref = NULL; - return SCPE_OK; -} - -static t_stat mdsad_boot(int32 unitno, DEVICE *dptr) -{ - - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - DBG_PRINT(("Booting MDSAD Controller at 0x%04x, unit %d" NLP, - pnp->mem_base+1+(unitno&3), unitno & 3)); - - /* Unit 3 can't be booted yet. This involves modifying the A register. */ - *((int32 *) sim_PC->loc) = pnp->mem_base+1+(unitno&3); - return SCPE_OK; -} - -static int32 mdsaddev(const int32 Addr, const int32 rw, const int32 data) -{ - if(rw == 0) { /* Read */ - return(MDSAD_Read(Addr)); - } else { /* Write */ - DBG_PRINT(("MDSAD: write attempt at 0x%04x ignored." NLP, Addr)); - return (-1); - } -} - -/* This ROM image is taken from the Solace Emulator, which uses */ -/* a ROM from a "Micro Complex Phase Lock II" dual- */ -/* density controller card. It is supposedly compatible with the */ -/* Northstar-designed dual density floppy controller. It has the */ -/* interesting property that by jumping to base_addr+0 (or +1) and */ -/* it boots from floppy 0; jump to base_addr+2 you boot from floppy 1; */ -/* jump to base_addr+3 and you boot from floppy 2. You can boot from */ -/* floppy 3 by loading A with 08H and jumping to base_addr+7. */ -static uint8 mdsad_rom[] = { - 0x44, 0x01, 0x01, 0x01, 0x82, 0x84, 0x78, 0xE6, 0x07, 0x4F, 0x00, 0x31, 0x30, 0x00, 0x21, 0x29, /* 0x00 */ - 0x00, 0xE5, 0x21, 0x2C, 0xC2, 0xE5, 0x21, 0x77, 0x13, 0xE5, 0x21, 0xC9, 0x1A, 0xE5, 0xCD, 0x28, /* 0x10 */ - 0x00, 0x21, 0x30, 0x00, 0x5B, 0x52, 0x44, 0x54, 0x5D, 0x3A, 0x27, 0x00, 0x57, 0xC3, 0x29, 0x00, /* 0x20 */ - 0x14, 0x14, 0x1E, 0x15, 0x1A, 0x26, 0x30, 0xCD, 0xD9, 0x00, 0x42, 0x05, 0x0A, 0xCD, 0xD4, 0x00, /* 0x30 */ - 0x2E, 0x0D, 0x2D, 0xCA, 0x43, 0x00, 0xCD, 0xD7, 0x00, 0x1A, 0xE6, 0x40, 0xCA, 0x42, 0x00, 0x3E, /* 0x40 */ - 0x0A, 0xF5, 0xCD, 0xC1, 0x00, 0x1E, 0x20, 0x1A, 0xE6, 0x01, 0xC2, 0x63, 0x00, 0xCD, 0xC5, 0x00, /* 0x50 */ - 0xC3, 0x55, 0x00, 0x2E, 0x04, 0xCD, 0xE7, 0x00, 0x1E, 0x10, 0x1A, 0xE6, 0x04, 0xCA, 0x68, 0x00, /* 0x60 */ - 0x3E, 0x09, 0x3D, 0xC2, 0x72, 0x00, 0x1A, 0xE6, 0x20, 0xC2, 0x84, 0x00, 0xCD, 0xC1, 0x00, 0x2E, /* 0x70 */ - 0x08, 0xCD, 0xE7, 0x00, 0x06, 0xA3, 0x1E, 0x10, 0x05, 0xCA, 0xF4, 0x00, 0x1A, 0x0F, 0xD2, 0x88, /* 0x80 */ - 0x00, 0x1E, 0x40, 0x1A, 0x67, 0x2E, 0x00, 0x36, 0x59, 0x07, 0x47, 0x23, 0x1A, 0x77, 0xA8, 0x07, /* 0x90 */ - 0x47, 0x2C, 0xC2, 0x9C, 0x00, 0x24, 0x1A, 0x77, 0xA8, 0x07, 0x47, 0x2C, 0xC2, 0xA6, 0x00, 0x1A, /* 0xA0 */ - 0xA8, 0xC2, 0xF4, 0x00, 0x25, 0x2E, 0x03, 0x71, 0x2D, 0x36, 0x59, 0xC2, 0xB8, 0x00, 0x2E, 0x0A, /* 0xB0 */ - 0xE9, 0x3E, 0x20, 0x81, 0x4F, 0x0A, 0x3E, 0x10, 0x81, 0x4F, 0x0A, 0x3E, 0xF0, 0x81, 0x4F, 0x0A, /* 0xC0 */ - 0x79, 0xE6, 0x0F, 0x4F, 0xCD, 0xD7, 0x00, 0x26, 0x01, 0x1E, 0x11, 0x1A, 0x1D, 0x1A, 0xB7, 0xF2, /* 0xD0 */ - 0xDD, 0x00, 0x25, 0xC2, 0xD9, 0x00, 0xC9, 0xCD, 0xD7, 0x00, 0x1E, 0x35, 0x1A, 0xE6, 0x0F, 0xBD, /* 0xE0 */ - 0xC2, 0xE7, 0x00, 0xC9, 0xF1, 0x3D, 0xF5, 0xC2, 0x55, 0x00, 0xC3, 0xFA, 0x00, 0x52, 0x44, 0x54 /* 0xF0 */ -}; - -static void showdata(int32 isRead) { - int32 i; - printf("MDSAD: " ADDRESS_FORMAT " %s Sector =" NLP "\t", PCX, isRead ? "Read" : "Write"); - for(i=0; i < MDSAD_SECTOR_LEN; i++) { - printf("%02X ", sdata.u.data[i]); - if(((i+1) & 0xf) == 0) - printf(NLP "\t"); - } - printf(NLP); -} - -static int checksum; -static uint32 sec_offset; - -static uint32 calculate_mdsad_sec_offset(uint8 track, uint8 head, uint8 sector) -{ - if(mdsad_info->orders.ss == 0) { - return ((track * (MDSAD_SECTOR_LEN * MDSAD_SECTORS_PER_TRACK)) + (sector * MDSAD_SECTOR_LEN)); - } else { - return ((((MDSAD_TRACKS-1) - track) * (MDSAD_SECTOR_LEN * MDSAD_SECTORS_PER_TRACK)) + - ((MDSAD_SECTOR_LEN * MDSAD_SECTORS_PER_TRACK) * MDSAD_TRACKS) + /* Skip over side 0 */ - (sector * MDSAD_SECTOR_LEN)); /* Sector offset from beginning of track. */ - } -} - -static uint8 MDSAD_Read(const uint32 Addr) -{ - uint8 cData; - uint8 ds; - MDSAD_DRIVE_INFO *pDrive; - int32 rtn; - - cData = 0x00; - - pDrive = &mdsad_info->drive[mdsad_info->orders.ds]; - - switch( (Addr & 0x300) >> 8 ) { - case MDSAD_READ_ROM: - cData = mdsad_rom[Addr & 0xFF]; - break; - case MDSAD_WRITE_DATA: - { - if(mdsad_info->datacount == 0) { - sim_debug(WR_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " WRITE Start: Drive: %d, Track=%d, Head=%d, Sector=%d\n", - PCX, mdsad_info->orders.ds, pDrive->track, - mdsad_info->orders.ss, pDrive->sector); - - sec_offset = calculate_mdsad_sec_offset(pDrive->track, - mdsad_info->orders.ss, - pDrive->sector); - - } - - DBG_PRINT(("MDSAD: " ADDRESS_FORMAT - " WRITE-DATA[offset:%06x+%03x]=%02x" NLP, - PCX, sec_offset, mdsad_info->datacount, Addr & 0xFF)); - mdsad_info->datacount++; - if(mdsad_info->datacount < MDSAD_RAW_LEN) - sdata.raw[mdsad_info->datacount] = Addr & 0xFF; - - if(mdsad_info->datacount == (MDSAD_RAW_LEN - 1)) { - sim_debug(WR_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " Write Complete\n", PCX); - - if ((pDrive->uptr == NULL) || (pDrive->uptr->fileref == NULL)) { - sim_debug(WR_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " Drive: %d not attached - write ignored.\n", PCX, mdsad_info->orders.ds); - return 0x00; - } - if(mdsad_dev.dctrl & WR_DATA_DETAIL_MSG) - showdata(FALSE); - switch((pDrive->uptr)->u3) - { - case IMAGE_TYPE_DSK: - if(pDrive->uptr->fileref == NULL) { - printf(".fileref is NULL!" NLP); - } else { - sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); - sim_fwrite(sdata.u.data, 1, MDSAD_SECTOR_LEN, - (pDrive->uptr)->fileref); - } - break; - case IMAGE_TYPE_CPT: - printf("%s: CPT Format not supported" NLP, __FUNCTION__); - break; - default: - printf("%s: Unknown image Format" NLP, __FUNCTION__); - break; - } - } - break; - } - case MDSAD_CTLR_ORDERS: - mdsad_info->orders.dd = (Addr & 0x80) >> 7; - mdsad_info->orders.ss = (Addr & 0x40) >> 6; - mdsad_info->orders.dp = (Addr & 0x20) >> 5; - mdsad_info->orders.st = (Addr & 0x10) >> 4; - mdsad_info->orders.ds = (Addr & 0x0F); - - ds = mdsad_info->orders.ds; - switch(mdsad_info->orders.ds) { - case 0: - case 1: - mdsad_info->orders.ds = 0; - break; - case 2: - mdsad_info->orders.ds = 1; - break; - case 4: - mdsad_info->orders.ds = 2; - break; - case 8: - mdsad_info->orders.ds = 3; - break; - } - - if(mdsad_info->orders.ds != (mdsad_info->orders.ds & 0x03)) { - sim_debug(ERROR_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " Controller Orders update drive %x\n", PCX, mdsad_info->orders.ds); - mdsad_info->orders.ds &= 0x03; - } - sim_debug(ORDERS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " Controller Orders: Drive=%x[%x], DD=%d, SS=%d, DP=%d, ST=%d\n", - PCX, mdsad_info->orders.ds, ds, mdsad_info->orders.dd, - mdsad_info->orders.ss, mdsad_info->orders.dp, mdsad_info->orders.st); - - /* use latest selected drive */ - pDrive = &mdsad_info->drive[mdsad_info->orders.ds]; - - if(mdsad_info->orders.st == 1) { - if(mdsad_info->orders.dp == 0) { - sim_debug(SEEK_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " Step out: Track=%d%s\n", PCX, pDrive->track, - pDrive->track == 0 ? "[Warn: already at 0]" : ""); - if(pDrive->track > 0) /* anything to do? */ - pDrive->track--; - } else { - sim_debug(SEEK_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " Step in: Track=%d%s\n", PCX, pDrive->track, - pDrive->track == (MDSAD_TRACKS - 1) ? "[Warn: already at highest track]" : ""); - if(pDrive->track < (MDSAD_TRACKS - 1)) /* anything to do? */ - pDrive->track++; - } - } - /* always update t0 */ - mdsad_info->b_status.t0 = (pDrive->track == 0); - break; - case MDSAD_CTLR_COMMAND: -/* sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " DM=%x\n", PCX, (Addr & 0xF0) >> 4); */ - switch(Addr & 0x0F) { - case MDSAD_CMD_MOTORS_ON: - sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " CMD=Motors On\n", PCX); - mdsad_info->com_status.mo = 1; /* Turn motors on */ - break; - - case MDSAD_CMD_NOP: - pDrive->sector_wait_count++; - switch(pDrive->sector_wait_count) { - case 10: - { - mdsad_info->com_status.sf = 1; - mdsad_info->a_status.wi = 0; - mdsad_info->a_status.re = 0; - mdsad_info->a_status.bd = 0; - pDrive->sector_wait_count = 0; - pDrive->sector++; - if(pDrive->sector >= MDSAD_SECTORS_PER_TRACK) { - pDrive->sector = 0; - mdsad_info->com_status.ix = 1; - } else { - mdsad_info->com_status.ix = 0; - } - break; - } - case 2: - mdsad_info->a_status.wi = 1; - break; - case 3: - mdsad_info->a_status.re = 1; - mdsad_info->a_status.bd = 1; - break; - default: - break; - } - break; - case MDSAD_CMD_RESET_SF: - sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " CMD=Reset Sector Flag\n", PCX); - mdsad_info->com_status.sf = 0; - mdsad_info->datacount = 0; - break; - case MDSAD_CMD_INTR_DIS: - sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " CMD=Disarm Interrupt\n", PCX); - mdsad_info->int_enable = 0; - break; - case MDSAD_CMD_INTR_ARM: - sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " CMD=Arm Interrupt\n", PCX); - mdsad_info->int_enable = 1; - break; - case MDSAD_CMD_SET_BODY: - sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " CMD=Set Body (Diagnostic)\n", PCX); - break; - case MDSAD_CMD_BEGIN_WR: - sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " CMD=Begin Write\n", PCX); - break; - case MDSAD_CMD_RESET: - sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " CMD=Reset Controller\n", PCX); - mdsad_info->com_status.mo = 0; /* Turn motors off */ - break; - default: - sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " Unsupported CMD=0x%x\n", PCX, Addr & 0x0F); - break; - } - - /* Always Double-Density for now... */ - mdsad_info->com_status.dd = 1; - - cData = (mdsad_info->com_status.sf & 1) << 7; - cData |= (mdsad_info->com_status.ix & 1) << 6; - cData |= (mdsad_info->com_status.dd & 1) << 5; - cData |= (mdsad_info->com_status.mo & 1) << 4; - - mdsad_info->c_status.sc = pDrive->sector; - - switch( (Addr & 0xF0) >> 4) { - case MDSAD_A_STATUS: /* A-STATUS */ - cData |= (mdsad_info->a_status.wi & 1) << 3; - cData |= (mdsad_info->a_status.re & 1) << 2; - cData |= (mdsad_info->a_status.sp & 1) << 1; - cData |= (mdsad_info->a_status.bd & 1); - sim_debug(STATUS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " A-Status = <%s %s %s %s %s %s %s %s>\n", - PCX, - cData & MDSAD_A_SF ? "SF" : " ", - cData & MDSAD_A_IX ? "IX" : " ", - cData & MDSAD_A_DD ? "DD" : " ", - cData & MDSAD_A_MO ? "MO" : " ", - cData & MDSAD_A_WI ? "WI" : " ", - cData & MDSAD_A_RE ? "RE" : " ", - cData & MDSAD_A_SP ? "SP" : " ", - cData & MDSAD_A_BD ? "BD" : " "); - break; - case MDSAD_B_STATUS: /* B-STATUS */ - cData |= (mdsad_info->b_status.wr & 1) << 3; - cData |= (mdsad_info->b_status.sp & 1) << 2; - cData |= (mdsad_info->b_status.wp & 1) << 1; - cData |= (mdsad_info->b_status.t0 & 1); - sim_debug(STATUS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " B-Status = <%s %s %s %s %s %s %s %s>\n", - PCX, - cData & MDSAD_B_SF ? "SF" : " ", - cData & MDSAD_B_IX ? "IX" : " ", - cData & MDSAD_B_DD ? "DD" : " ", - cData & MDSAD_B_MO ? "MO" : " ", - cData & MDSAD_B_WR ? "WR" : " ", - cData & MDSAD_B_SP ? "SP" : " ", - cData & MDSAD_B_WP ? "WP" : " ", - cData & MDSAD_B_T0 ? "T0" : " "); - break; - case MDSAD_C_STATUS: /* C-STATUS */ - cData |= (mdsad_info->c_status.sc & 0xF); - sim_debug(STATUS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " C-Status = <%s %s %s %s %i>\n", - PCX, - cData & MDSAD_C_SF ? "SF" : " ", - cData & MDSAD_C_IX ? "IX" : " ", - cData & MDSAD_C_DD ? "DD" : " ", - cData & MDSAD_C_MO ? "MO" : " ", - cData & MDSAD_C_SC); - break; - case MDSAD_READ_DATA: /* READ DATA */ - { - if(mdsad_info->datacount == 0) { - sim_debug(RD_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " READ Start: Drive: %d, Track=%d, Head=%d, Sector=%d\n", - PCX, - mdsad_info->orders.ds, - pDrive->track, - mdsad_info->orders.ss, - pDrive->sector); - - checksum = 0; - - sec_offset = calculate_mdsad_sec_offset(pDrive->track, - mdsad_info->orders.ss, - pDrive->sector); - - if ((pDrive->uptr == NULL) || - (pDrive->uptr->fileref == NULL)) { - sim_debug(RD_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " Drive: %d not attached - read ignored.\n", - PCX, mdsad_info->orders.ds); - return 0xe5; - } - - switch((pDrive->uptr)->u3) - { - case IMAGE_TYPE_DSK: - if(pDrive->uptr->fileref == NULL) { - printf(".fileref is NULL!" NLP); - } else { - sim_fseek((pDrive->uptr)->fileref, - sec_offset, SEEK_SET); - rtn = sim_fread(&sdata.u.data[0], 1, MDSAD_SECTOR_LEN, - (pDrive->uptr)->fileref); - if (rtn != MDSAD_SECTOR_LEN) { - sim_debug(ERROR_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " READ: sim_fread error.\n", PCX); - } - } - break; - case IMAGE_TYPE_CPT: - printf("%s: CPT Format not supported" - NLP, __FUNCTION__); - break; - default: - printf("%s: Unknown image Format" - NLP, __FUNCTION__); - break; - } - if(mdsad_dev.dctrl & RD_DATA_DETAIL_MSG) - showdata(TRUE); - } - - if(mdsad_info->datacount < MDSAD_SECTOR_LEN) { - cData = sdata.u.data[mdsad_info->datacount]; - - /* Exclusive OR */ - checksum ^= cData; - /* Rotate Left Circular */ - checksum = ((checksum << 1) | ((checksum & 0x80) != 0)) & 0xff; - - DBG_PRINT(("MDSAD: " ADDRESS_FORMAT - " READ-DATA[offset:%06x+%03x]=%02x" NLP, - PCX, sec_offset, mdsad_info->datacount, cData)); - } else { /* checksum */ - cData = checksum; - sim_debug(RD_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT - " READ-DATA: Checksum is: 0x%02x\n", - PCX, cData); - } - - mdsad_info->datacount++; - break; - } - default: - DBG_PRINT(("MDSAD: " ADDRESS_FORMAT - " Invalid DM=%x" NLP, PCX, Addr & 0xF)); - break; - } - - break; - } - return (cData); -} diff --git a/AltairZ80/s100_scp300f.c b/AltairZ80/s100_scp300f.c deleted file mode 100644 index 38d7c1fb..00000000 --- a/AltairZ80/s100_scp300f.c +++ /dev/null @@ -1,450 +0,0 @@ -/************************************************************************* - * * - * $Id: s100_scp300f.c 1940 2008-06-13 05:28:57Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Seattle Computer Products SCP300F Support Board module for SIMH. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/* #define DBG_MSG */ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define PIO_MSG (1 << 1) -#define UART_MSG (1 << 2) -#define RTC_MSG (1 << 3) -#define ROM_MSG (1 << 5) -#define VERBOSE_MSG (1 << 7) -#define IRQ_MSG (1 << 8) - -#define SCP300F_MAX_DRIVES 1 -#define SCP300F_ROM_SIZE (2048) -#define SCP300F_ADDR_MASK (SCP300F_ROM_SIZE - 1) - -#define SCP300F_IO_SIZE (16) -#define SCP300F_IO_MASK (SCP300F_IO_SIZE - 1) - -#define UNIT_V_SCP300F_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_SCP300F_VERBOSE (1 << UNIT_V_SCP300F_VERBOSE) - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint8 *ram; - uint8 *rom; - uint8 rom_enabled; -} SCP300F_INFO; - -static SCP300F_INFO scp300f_info_data = { { 0xFF800, SCP300F_ROM_SIZE, 0xF0, SCP300F_IO_SIZE } }; -static SCP300F_INFO *scp300f_info = &scp300f_info_data; - -extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern uint32 PCX; -extern int32 find_unit_index (UNIT *uptr); - -static t_stat scp300f_reset(DEVICE *scp300f_dev); - -static uint8 SCP300F_Read(const uint32 Addr); -static uint8 SCP300F_Write(const uint32 Addr, uint8 cData); - -static int32 scp300fdev(const int32 port, const int32 io, const int32 data); -static int32 scp300f_mem(const int32 port, const int32 io, const int32 data); - -static int32 scp300f_sr = 0x00; /* Sense Switch Register, 0=Monitor prompt, 1=disk boot */ - -static UNIT scp300f_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE, 0) } -}; - -static REG scp300f_reg[] = { - { HRDATA (SR, scp300f_sr, 8), }, - { NULL } -}; - -static MTAB scp300f_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - /* quiet, no warning messages */ - { UNIT_SCP300F_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_SCP300F_VERBOSE, UNIT_SCP300F_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB scp300f_dt[] = { - { "ERROR", ERROR_MSG }, - { "PIO", PIO_MSG }, - { "UART", UART_MSG }, - { "RTC", RTC_MSG }, - { "ROM", ROM_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { "IRQ", IRQ_MSG }, - { NULL, 0 } -}; - - -DEVICE scp300f_dev = { - "SCP300F", scp300f_unit, scp300f_reg, scp300f_mod, - SCP300F_MAX_DRIVES, 10, 31, 1, SCP300F_MAX_DRIVES, SCP300F_MAX_DRIVES, - NULL, NULL, &scp300f_reset, - NULL, NULL, NULL, - &scp300f_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - scp300f_dt, NULL, "SCP Support Board SCP300F" -}; - -/* Reset routine */ -static t_stat scp300f_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - sim_debug(VERBOSE_MSG, &scp300f_dev, "SCP300F: Reset.\n"); - - if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &scp300fdev, TRUE); - sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &scp300f_mem, TRUE); - } else { - /* Connect SCP300F at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &scp300fdev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - /* Connect SCP300F Memory (512K RAM, 1MB FLASH) */ - if(sim_map_resource(pnp->mem_base, pnp->mem_size, RESOURCE_TYPE_MEMORY, &scp300f_mem, FALSE) != 0) { - printf("%s: error mapping MEM resource at 0x%04x\n", __FUNCTION__, pnp->mem_base); - return SCPE_ARG; - } - - /* Re-enable ROM */ - scp300f_info->rom_enabled = 1; - } - return SCPE_OK; -} - - -static uint8 scp300f_ram[SCP300F_ROM_SIZE]; - -/* ; Seattle Computer Products 8086 Monitor version 1.5 3-19-82. - * ; by Tim Paterson - * ; This software is not copyrighted. - * - * This was assembled from source (MON.ASM) using 86DOS ASM.COM running under Windows XP. - * It is configured for a Cromemco 16FDC disk controller. - */ -static uint8 scp300f_rom[SCP300F_ROM_SIZE] = { - 0xFC, 0x33, 0xC0, 0x8E, 0xD0, 0x8E, 0xD8, 0x8E, 0xC0, 0xBF, 0x9C, 0x01, 0xB9, 0x0E, 0x00, 0xF3, - 0xAB, 0x80, 0x0E, 0xB7, 0x01, 0x02, 0xB1, 0x04, 0xB0, 0x40, 0xBF, 0xAC, 0x01, 0xF3, 0xAB, 0xC6, - 0x06, 0xA5, 0x01, 0x0C, 0xBC, 0x9C, 0x01, 0xB0, 0x17, 0xE6, 0xF5, 0xB0, 0xF3, 0xE6, 0xF4, 0xB8, - 0x84, 0x05, 0xE7, 0xF4, 0xBE, 0x33, 0x07, 0xBA, 0xF0, 0x00, 0x2E, 0xAC, 0x8A, 0xC8, 0xE3, 0x05, - 0x2E, 0xAC, 0xEE, 0xE2, 0xFB, 0x42, 0x80, 0xFA, 0xF8, 0x75, 0xEF, 0xE8, 0x19, 0x00, 0xBE, 0xF5, - 0x07, 0xB8, 0x23, 0xE8, 0xE7, 0xF4, 0xB0, 0x0D, 0xE6, 0xF5, 0x2E, 0xAD, 0xE6, 0xF4, 0x8A, 0xC4, - 0xE6, 0xF4, 0xE8, 0x02, 0x00, 0xEB, 0xF3, 0xE8, 0x98, 0x00, 0xE8, 0x95, 0x00, 0x3C, 0x0D, 0x74, - 0x01, 0xC3, 0xBF, 0x18, 0x01, 0xC6, 0x05, 0x0D, 0xE4, 0xFF, 0xA8, 0x01, 0x74, 0x03, 0xE9, 0xF5, - 0x06, 0xBE, 0x51, 0x07, 0xE8, 0x8B, 0x00, 0xFC, 0x33, 0xC0, 0x8E, 0xD8, 0x8E, 0xC0, 0xBC, 0x9C, - 0x01, 0xC7, 0x06, 0x64, 0x00, 0xBB, 0x06, 0x8C, 0x0E, 0x66, 0x00, 0xB0, 0x3E, 0xE8, 0xC8, 0x00, - 0xE8, 0x1E, 0x00, 0xE8, 0x7F, 0x00, 0x74, 0xDF, 0x8A, 0x05, 0x2C, 0x42, 0x72, 0x10, 0x3C, 0x13, - 0x73, 0x0C, 0x47, 0xD0, 0xE0, 0x98, 0x93, 0x2E, 0xFF, 0x97, 0x7D, 0x01, 0xEB, 0xC9, 0xE9, 0xA8, - 0x02, 0xBF, 0x18, 0x01, 0x33, 0xC9, 0xE8, 0x39, 0x00, 0x3C, 0x20, 0x72, 0x1B, 0x3C, 0x7F, 0x74, - 0x0E, 0xE8, 0x94, 0x00, 0x3C, 0x40, 0x74, 0x25, 0xAA, 0x41, 0x83, 0xF9, 0x50, 0x76, 0xE7, 0xE3, - 0xE5, 0x4F, 0x49, 0xE8, 0x29, 0x00, 0xEB, 0xDE, 0x3C, 0x08, 0x74, 0xF3, 0x3C, 0x0D, 0x75, 0xD6, - 0xAA, 0xBF, 0x18, 0x01, 0xB0, 0x0D, 0xE8, 0x6F, 0x00, 0xB0, 0x0A, 0xEB, 0x6B, 0xE8, 0xF4, 0xFF, - 0xEB, 0x85, 0xFA, 0xE4, 0xF7, 0xA8, 0x02, 0x74, 0xF9, 0xE4, 0xF6, 0x24, 0x7F, 0xFB, 0xC3, 0xBE, - 0x73, 0x07, 0x2E, 0xAC, 0xE8, 0x51, 0x00, 0xD0, 0xE0, 0x73, 0xF7, 0xC3, 0xE8, 0x06, 0x00, 0x82, - 0x3D, 0x2C, 0x75, 0x0A, 0x47, 0xB0, 0x20, 0x51, 0xB1, 0xFF, 0xF3, 0xAE, 0x4F, 0x59, 0x82, 0x3D, - 0x0D, 0xC3, 0x8C, 0xDA, 0xB4, 0x00, 0xE8, 0x78, 0x00, 0x03, 0xD6, 0xEB, 0x09, 0x8C, 0xC2, 0xB4, - 0x00, 0xE8, 0x6D, 0x00, 0x03, 0xD7, 0x82, 0xD4, 0x00, 0xE8, 0x12, 0x00, 0x8A, 0xC6, 0xE8, 0x02, - 0x00, 0x8A, 0xC2, 0x8A, 0xE0, 0x51, 0xB1, 0x04, 0xD2, 0xE8, 0x59, 0xE8, 0x02, 0x00, 0x8A, 0xC4, - 0x24, 0x0F, 0x04, 0x90, 0x27, 0x14, 0x40, 0x27, 0x50, 0xE4, 0xF7, 0x24, 0x01, 0x74, 0xFA, 0x58, - 0xE6, 0xF6, 0xC3, 0xB0, 0x20, 0xEB, 0xF1, 0xE8, 0xF9, 0xFF, 0xE2, 0xFB, 0xC3, 0x76, 0x07, 0x68, - 0x03, 0x0D, 0x02, 0x88, 0x03, 0x97, 0x02, 0x6A, 0x06, 0x68, 0x03, 0x4C, 0x06, 0x68, 0x03, 0x68, - 0x03, 0x68, 0x03, 0x6A, 0x02, 0x68, 0x03, 0x59, 0x06, 0x68, 0x03, 0x68, 0x03, 0x2F, 0x04, 0xBA, - 0x02, 0x6A, 0x05, 0x8A, 0xC2, 0x24, 0x0F, 0xE8, 0x07, 0x00, 0x8A, 0xD0, 0x8A, 0xC6, 0x32, 0xF6, - 0xC3, 0xD1, 0xE2, 0xD0, 0xD4, 0xD1, 0xE2, 0xD0, 0xD4, 0xD1, 0xE2, 0xD0, 0xD4, 0xD1, 0xE2, 0xD0, - 0xD4, 0xC3, 0xB9, 0x05, 0x00, 0xE8, 0x22, 0x01, 0x50, 0x52, 0xE8, 0x4F, 0xFF, 0x82, 0x3D, 0x4C, - 0x74, 0x1C, 0xBA, 0x80, 0x00, 0xE8, 0x30, 0x01, 0x72, 0x1B, 0xB9, 0x05, 0x00, 0xE8, 0x0A, 0x01, - 0x8B, 0xCA, 0x5A, 0x5B, 0x2B, 0xCA, 0x1A, 0xE7, 0x75, 0x1D, 0x93, 0x41, 0xEB, 0x0B, 0x47, 0xB9, - 0x04, 0x00, 0xE8, 0xF5, 0x00, 0x8B, 0xCA, 0x5A, 0x58, 0x8B, 0xDA, 0x81, 0xE3, 0x0F, 0x00, 0xE3, - 0x04, 0x03, 0xD9, 0x73, 0x9E, 0x74, 0x9C, 0xB8, 0x52, 0x47, 0xE9, 0x1F, 0x03, 0xE8, 0xB2, 0xFF, - 0x50, 0xE8, 0x4E, 0x01, 0x1F, 0x8B, 0xF2, 0xE8, 0x18, 0xFF, 0x56, 0xE8, 0x55, 0xFF, 0xAC, 0xE8, - 0x31, 0xFF, 0x5A, 0x49, 0x74, 0x17, 0x8B, 0xC6, 0xA8, 0x0F, 0x74, 0x0C, 0x52, 0xA8, 0x07, 0x75, - 0xEA, 0xB0, 0x2D, 0xE8, 0x32, 0xFF, 0xEB, 0xE6, 0xE8, 0x02, 0x00, 0xEB, 0xDA, 0x51, 0x8B, 0xC6, - 0x8B, 0xF2, 0x2B, 0xC2, 0x8B, 0xD8, 0xD1, 0xE0, 0x03, 0xC3, 0xB9, 0x33, 0x00, 0x2B, 0xC8, 0xE8, - 0x25, 0xFF, 0x8B, 0xCB, 0xAC, 0x24, 0x7F, 0x3C, 0x7F, 0x74, 0x04, 0x3C, 0x20, 0x73, 0x02, 0xB0, - 0x2E, 0xE8, 0x04, 0xFF, 0xE2, 0xEE, 0x59, 0xE9, 0x8A, 0xFE, 0xE8, 0x55, 0xFF, 0x51, 0x50, 0x8B, - 0xF2, 0xB9, 0x05, 0x00, 0xE8, 0x73, 0x00, 0xE8, 0xE8, 0x00, 0xE8, 0x26, 0xFF, 0x8B, 0xFA, 0x5B, - 0x8E, 0xDB, 0x8E, 0xC0, 0x59, 0x3B, 0xFE, 0x1B, 0xC3, 0x72, 0x07, 0x49, 0x03, 0xF1, 0x03, 0xF9, - 0xFD, 0x41, 0xA4, 0x49, 0xF3, 0xA4, 0xC3, 0xE8, 0x28, 0xFF, 0x51, 0x50, 0x52, 0xE8, 0xB4, 0x00, - 0x5F, 0x07, 0x59, 0x3B, 0xD9, 0xBE, 0x18, 0x01, 0xE3, 0x02, 0x73, 0xE6, 0x2B, 0xCB, 0x87, 0xD9, - 0x57, 0xF3, 0xA4, 0x5E, 0x8B, 0xCB, 0x06, 0x1F, 0xEB, 0xD8, 0xE8, 0x05, 0xFF, 0x51, 0x50, 0x52, - 0xE8, 0x91, 0x00, 0x4B, 0x5F, 0x07, 0x59, 0x2B, 0xCB, 0xBE, 0x18, 0x01, 0xAC, 0xAE, 0xE0, 0xFD, - 0x75, 0xC4, 0x53, 0x87, 0xCB, 0x57, 0xF3, 0xA6, 0x8B, 0xCB, 0x5F, 0x5B, 0x75, 0x08, 0x4F, 0xE8, - 0x5B, 0xFE, 0x47, 0xE8, 0x0E, 0xFE, 0xE3, 0xAE, 0xEB, 0xDF, 0xE8, 0x2F, 0xFE, 0x33, 0xD2, 0x8A, - 0xE6, 0xE8, 0x14, 0x00, 0x72, 0x73, 0x8A, 0xD0, 0x47, 0x49, 0xE8, 0x0B, 0x00, 0x72, 0x97, 0xE3, - 0x68, 0xE8, 0xAD, 0xFE, 0x0A, 0xD0, 0xEB, 0xF0, 0x8A, 0x05, 0x2C, 0x30, 0x72, 0x88, 0x3C, 0x0A, - 0xF5, 0x73, 0x83, 0x2C, 0x07, 0x3C, 0x0A, 0x72, 0x03, 0x3C, 0x10, 0xF5, 0xC3, 0xE8, 0xFC, 0xFD, - 0xE8, 0xE5, 0xFF, 0x72, 0x0B, 0xB9, 0x02, 0x00, 0xE8, 0xBF, 0xFF, 0x88, 0x17, 0x43, 0xF8, 0xC3, - 0x8A, 0x05, 0x3C, 0x27, 0x74, 0x06, 0x3C, 0x22, 0x74, 0x02, 0xF9, 0xC3, 0x8A, 0xE0, 0x47, 0x8A, - 0x05, 0x47, 0x3C, 0x0D, 0x74, 0x23, 0x3A, 0xC4, 0x75, 0x05, 0x3A, 0x25, 0x75, 0xE0, 0x47, 0x88, - 0x07, 0x43, 0xEB, 0xEB, 0xBB, 0x18, 0x01, 0xE8, 0xC3, 0xFF, 0x73, 0xFB, 0x81, 0xEB, 0x18, 0x01, - 0x74, 0x07, 0xE8, 0xC0, 0xFD, 0x75, 0x02, 0xC3, 0x4F, 0x81, 0xEF, 0x17, 0x01, 0x8B, 0xCF, 0xE8, - 0x05, 0xFE, 0xBE, 0x6A, 0x07, 0xE8, 0x9A, 0xFD, 0xE9, 0x0C, 0xFD, 0xE8, 0xD6, 0xFF, 0x5F, 0x07, - 0xBE, 0x18, 0x01, 0x8B, 0xCB, 0xF3, 0xA4, 0xC3, 0xB9, 0x05, 0x00, 0xE8, 0x5C, 0xFF, 0xE8, 0x12, - 0xFE, 0x82, 0xEC, 0x08, 0x80, 0xC6, 0x80, 0x50, 0x52, 0xE8, 0x89, 0xFD, 0x75, 0xDD, 0x5F, 0x07, - 0xE8, 0x9A, 0xFD, 0xE8, 0xCD, 0xFD, 0x26, 0x8A, 0x05, 0xE8, 0xA7, 0xFD, 0xB0, 0x2E, 0xE8, 0xB7, - 0xFD, 0xB9, 0x02, 0x00, 0xBA, 0x00, 0x00, 0xE8, 0x48, 0xFD, 0x8A, 0xE0, 0xE8, 0x4B, 0xFF, 0x86, - 0xE0, 0x72, 0x0C, 0xE8, 0xA2, 0xFD, 0x8A, 0xF2, 0x8A, 0xD4, 0xE2, 0xEB, 0xE8, 0x33, 0xFD, 0x3C, - 0x08, 0x74, 0x19, 0x3C, 0x7F, 0x74, 0x15, 0x3C, 0x2D, 0x74, 0x4D, 0x3C, 0x0D, 0x74, 0x2F, 0x3C, - 0x20, 0x74, 0x31, 0xB0, 0x07, 0xE8, 0x80, 0xFD, 0xE3, 0xE2, 0xEB, 0xCB, 0x82, 0xF9, 0x02, 0x74, - 0xC6, 0xFE, 0xC1, 0x8A, 0xD6, 0x8A, 0xF5, 0xE8, 0x15, 0xFD, 0xEB, 0xBB, 0x82, 0xF9, 0x02, 0x74, - 0x0B, 0x51, 0xB1, 0x04, 0xD2, 0xE6, 0x59, 0x0A, 0xD6, 0x26, 0x88, 0x15, 0x47, 0xC3, 0xE8, 0xEB, - 0xFF, 0xE9, 0xE0, 0xFC, 0xE8, 0xE5, 0xFF, 0x41, 0x41, 0xE8, 0x5B, 0xFD, 0x8B, 0xC7, 0x24, 0x07, - 0x75, 0x84, 0xE8, 0xCF, 0xFC, 0xE9, 0x78, 0xFF, 0xE8, 0xD1, 0xFF, 0x4F, 0x4F, 0xEB, 0xF3, 0xE8, - 0xEA, 0xFC, 0x74, 0x62, 0x8A, 0x15, 0x47, 0x8A, 0x35, 0x82, 0xFE, 0x0D, 0x74, 0x76, 0x47, 0xE8, - 0x20, 0xFF, 0x82, 0xFE, 0x20, 0x74, 0x6D, 0xBF, 0xD7, 0x06, 0x92, 0x0E, 0x07, 0xB9, 0x0E, 0x00, - 0xF2, 0xAF, 0x75, 0x3C, 0x0B, 0xC9, 0x75, 0x06, 0x4F, 0x4F, 0x2E, 0x8B, 0x45, 0xFE, 0xE8, 0x07, - 0xFD, 0x8A, 0xC4, 0xE8, 0x02, 0xFD, 0xE8, 0x0A, 0xFD, 0x1E, 0x07, 0x8D, 0x9D, 0xC3, 0xFA, 0x8B, - 0x17, 0xE8, 0xD8, 0xFC, 0xE8, 0x7D, 0xFC, 0xB0, 0x3A, 0xE8, 0xEC, 0xFC, 0xE8, 0x42, 0xFC, 0xE8, - 0xA3, 0xFC, 0x74, 0x0B, 0xB9, 0x04, 0x00, 0xE8, 0x63, 0xFE, 0xE8, 0xD5, 0xFE, 0x89, 0x17, 0xC3, - 0xB8, 0x42, 0x52, 0xE9, 0x96, 0x00, 0xBE, 0xD7, 0x06, 0xBB, 0x9C, 0x01, 0xB9, 0x08, 0x00, 0xE8, - 0x65, 0x00, 0xE8, 0x4F, 0xFC, 0xB9, 0x05, 0x00, 0xE8, 0x5C, 0x00, 0xE8, 0xC5, 0xFC, 0xE8, 0x93, - 0x00, 0xE9, 0x40, 0xFC, 0x82, 0xFA, 0x46, 0x75, 0xD7, 0xE8, 0x88, 0x00, 0xB0, 0x2D, 0xE8, 0xA7, - 0xFC, 0xE8, 0xFD, 0xFB, 0xE8, 0x5E, 0xFC, 0x33, 0xDB, 0x8B, 0x16, 0xB6, 0x01, 0x8B, 0xF7, 0xAD, - 0x3C, 0x0D, 0x74, 0x66, 0x82, 0xFC, 0x0D, 0x74, 0x66, 0xBF, 0xF3, 0x06, 0xB9, 0x20, 0x00, 0x0E, - 0x07, 0xF2, 0xAF, 0x75, 0x5A, 0x8A, 0xE9, 0x80, 0xE1, 0x0F, 0xB8, 0x01, 0x00, 0xD3, 0xC0, 0x85, - 0xC3, 0x75, 0x33, 0x0B, 0xD8, 0x0B, 0xD0, 0xF6, 0xC5, 0x10, 0x75, 0x02, 0x33, 0xD0, 0x8B, 0xFE, - 0x1E, 0x07, 0xE8, 0x17, 0xFC, 0xEB, 0xC6, 0x2E, 0xAD, 0xE8, 0x5C, 0xFC, 0x8A, 0xC4, 0xE8, 0x57, - 0xFC, 0xB0, 0x3D, 0xE8, 0x52, 0xFC, 0x8B, 0x17, 0x43, 0x43, 0xE8, 0x2F, 0xFC, 0xE8, 0x53, 0xFC, - 0xE8, 0x50, 0xFC, 0xE2, 0xE2, 0xC3, 0xB8, 0x44, 0x46, 0xE8, 0x0E, 0x00, 0xE8, 0x39, 0xFC, 0x8A, - 0xC4, 0xE8, 0x34, 0xFC, 0xBE, 0x6B, 0x07, 0xE9, 0x3B, 0xFE, 0x89, 0x16, 0xB6, 0x01, 0xC3, 0xB8, - 0x42, 0x46, 0xEB, 0xE5, 0xBE, 0xF3, 0x06, 0xB9, 0x10, 0x00, 0x8B, 0x16, 0xB6, 0x01, 0x2E, 0xAD, - 0xD1, 0xE2, 0x72, 0x04, 0x2E, 0x8B, 0x44, 0x1E, 0x0B, 0xC0, 0x74, 0x0B, 0xE8, 0x09, 0xFC, 0x8A, - 0xC4, 0xE8, 0x04, 0xFC, 0xE8, 0x0C, 0xFC, 0xE2, 0xE5, 0xC3, 0xE8, 0xAF, 0xFB, 0xE8, 0x98, 0xFD, - 0xBA, 0x01, 0x00, 0x72, 0x06, 0xB9, 0x04, 0x00, 0xE8, 0x6F, 0xFD, 0x89, 0x16, 0x02, 0x01, 0xE8, - 0xE0, 0xFD, 0xC7, 0x06, 0x00, 0x01, 0x00, 0x00, 0x80, 0x0E, 0xB7, 0x01, 0x01, 0xC7, 0x06, 0x0C, - 0x00, 0xD1, 0x05, 0x8C, 0x0E, 0x0E, 0x00, 0xC7, 0x06, 0x04, 0x00, 0xD8, 0x05, 0x8C, 0x0E, 0x06, - 0x00, 0xFA, 0xC7, 0x06, 0x64, 0x00, 0xD8, 0x05, 0x8C, 0x0E, 0x66, 0x00, 0xBC, 0x9C, 0x01, 0x58, - 0x5B, 0x59, 0x5A, 0x5D, 0x5D, 0x5E, 0x5F, 0x07, 0x07, 0x17, 0x8B, 0x26, 0xA4, 0x01, 0xFF, 0x36, - 0xB6, 0x01, 0xFF, 0x36, 0xB2, 0x01, 0xFF, 0x36, 0xB4, 0x01, 0x8E, 0x1E, 0xAC, 0x01, 0xCF, 0xEB, - 0xB1, 0x87, 0xEC, 0xFF, 0x4E, 0x00, 0x87, 0xEC, 0x2E, 0x89, 0x26, 0xA4, 0x09, 0x2E, 0x8C, 0x16, - 0xB0, 0x09, 0x33, 0xE4, 0x8E, 0xD4, 0xBC, 0xB0, 0x01, 0x06, 0x1E, 0x57, 0x56, 0x55, 0x4C, 0x4C, - 0x52, 0x51, 0x53, 0x50, 0x16, 0x1F, 0x8B, 0x26, 0xA4, 0x01, 0x8E, 0x16, 0xB0, 0x01, 0x8F, 0x06, - 0xB4, 0x01, 0x8F, 0x06, 0xB2, 0x01, 0x58, 0x80, 0xE4, 0xFE, 0xA3, 0xB6, 0x01, 0x89, 0x26, 0xA4, - 0x01, 0x1E, 0x07, 0x1E, 0x17, 0xBC, 0x9C, 0x01, 0xC7, 0x06, 0x64, 0x00, 0xBB, 0x06, 0xB0, 0x20, - 0xE6, 0xF2, 0xFB, 0xFC, 0xE8, 0xCD, 0xFA, 0xE8, 0x6C, 0xFE, 0xFF, 0x0E, 0x02, 0x01, 0x75, 0x9F, - 0xBE, 0x04, 0x01, 0x8B, 0x0E, 0x00, 0x01, 0xE3, 0x10, 0x8B, 0x54, 0x14, 0xAD, 0x50, 0xE8, 0x62, - 0xFB, 0x8E, 0xC0, 0x8B, 0xFA, 0x58, 0xAA, 0xE2, 0xF0, 0xE9, 0x3B, 0xFA, 0xB9, 0x04, 0x00, 0xE8, - 0x98, 0xFC, 0xEC, 0xE8, 0xFD, 0xFA, 0xE9, 0x9B, 0xFA, 0xB9, 0x04, 0x00, 0xE8, 0x8B, 0xFC, 0x52, - 0xB9, 0x02, 0x00, 0xE8, 0x84, 0xFC, 0x92, 0x5A, 0xEE, 0xC3, 0xBB, 0x18, 0x01, 0x33, 0xF6, 0xE8, - 0xAA, 0xFA, 0x74, 0x19, 0xB9, 0x05, 0x00, 0xE8, 0x70, 0xFC, 0x89, 0x17, 0x88, 0x67, 0xED, 0x43, - 0x43, 0x46, 0x83, 0xFE, 0x0B, 0x75, 0xE8, 0xB8, 0x42, 0x50, 0xE9, 0x9F, 0xFE, 0x89, 0x36, 0x00, - 0x01, 0xE8, 0xCE, 0xFC, 0x8B, 0xCE, 0xE3, 0x1A, 0xBE, 0x04, 0x01, 0x8B, 0x54, 0x14, 0xAD, 0xE8, - 0x01, 0xFB, 0x8E, 0xD8, 0x8B, 0xFA, 0x8A, 0x05, 0xC6, 0x05, 0xCC, 0x06, 0x1F, 0x88, 0x44, 0xFE, - 0xE2, 0xE9, 0xC7, 0x06, 0x02, 0x01, 0x01, 0x00, 0xE9, 0xD2, 0xFE, 0x50, 0xB0, 0x20, 0xE6, 0xF2, - 0xE4, 0xF6, 0x24, 0x7F, 0x3C, 0x13, 0x75, 0x03, 0xE8, 0x37, 0xFA, 0x3C, 0x03, 0x74, 0x02, 0x58, - 0xCF, 0xE8, 0x20, 0xFA, 0xE9, 0xB0, 0xF9, 0x41, 0x58, 0x42, 0x58, 0x43, 0x58, 0x44, 0x58, 0x53, - 0x50, 0x42, 0x50, 0x53, 0x49, 0x44, 0x49, 0x44, 0x53, 0x45, 0x53, 0x53, 0x53, 0x43, 0x53, 0x49, - 0x50, 0x50, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x56, 0x44, 0x4E, 0x45, - 0x49, 0x00, 0x00, 0x4E, 0x47, 0x5A, 0x52, 0x00, 0x00, 0x41, 0x43, 0x00, 0x00, 0x50, 0x45, 0x00, - 0x00, 0x43, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x56, 0x55, 0x50, 0x44, - 0x49, 0x00, 0x00, 0x50, 0x4C, 0x4E, 0x5A, 0x00, 0x00, 0x4E, 0x41, 0x00, 0x00, 0x50, 0x4F, 0x00, - 0x00, 0x4E, 0x43, 0x01, 0x19, 0x04, 0x10, 0x02, 0x0F, 0xFD, 0x01, 0x19, 0x04, 0x18, 0x01, 0x0B, - 0xFD, 0x06, 0x63, 0x0B, 0x07, 0x00, 0x06, 0x00, 0x02, 0x70, 0x05, 0x00, 0x04, 0xB7, 0x77, 0xCE, - 0x37, 0x0D, 0x0A, 0x0A, 0x53, 0x43, 0x50, 0x20, 0x38, 0x30, 0x38, 0x36, 0x20, 0x4D, 0x6F, 0x6E, - 0x69, 0x74, 0x6F, 0x72, 0x20, 0x31, 0x2E, 0x35, 0x0D, 0x8A, 0x5E, 0x20, 0x45, 0x72, 0x72, 0x6F, - 0x72, 0x0D, 0x8A, 0x08, 0x20, 0x88, 0x57, 0xB0, 0x01, 0xE6, 0x02, 0xB0, 0x84, 0xE6, 0x00, 0xB0, - 0x7F, 0xE6, 0x04, 0xB6, 0x21, 0xB0, 0x30, 0xE6, 0x34, 0xB9, 0xC4, 0xAA, 0xD4, 0x0A, 0xD4, 0x0A, - 0xE2, 0xFA, 0xB0, 0xD0, 0xE6, 0x30, 0xD4, 0x0A, 0xD4, 0x0A, 0xD4, 0x0A, 0xD4, 0x0A, 0x80, 0xF6, - 0x10, 0x8A, 0xC6, 0xE6, 0x34, 0xBF, 0x00, 0x02, 0xB0, 0x0F, 0xE6, 0x30, 0xE4, 0x34, 0xD0, 0xC8, - 0x73, 0xFA, 0xE4, 0x30, 0x24, 0x98, 0x75, 0xDA, 0xB0, 0x01, 0xE6, 0x32, 0x8A, 0xC6, 0x0C, 0x80, - 0xE6, 0x34, 0xB2, 0x33, 0xB0, 0x8C, 0xE6, 0x30, 0xEB, 0x02, 0xEC, 0xAA, 0xE4, 0x34, 0xD0, 0xC8, - 0x73, 0xF8, 0xE4, 0x30, 0x24, 0x9C, 0x75, 0xBA, 0xC7, 0x06, 0xB2, 0x01, 0x00, 0x00, 0xC7, 0x06, - 0xB4, 0x01, 0x00, 0x02, 0x5F, 0xE9, 0x82, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x00, 0x00, 0x80, 0xFF, 0x0D, 0x00, 0x68, 0x00, 0xA0, 0x01, 0x40, 0x03, 0x78, 0x04, 0xFF -}; - - static int32 scp300f_mem(const int32 Addr, const int32 write, const int32 data) -{ -/* DBG_PRINT(("SCP300F: ROM %s, Addr %04x" NLP, write ? "WR" : "RD", Addr)); */ - if(write) { - if(scp300f_info->rom_enabled) - { - sim_debug(ROM_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " WR ROM[0x%05x]: Cannot write to ROM.\n", PCX, Addr); - } else { - } - return 0; - } else { - if(scp300f_info->rom_enabled) - { - return scp300f_rom[Addr & SCP300F_ADDR_MASK]; - } else { - return scp300f_ram[Addr & SCP300F_ADDR_MASK]; - } - } -} - -static int32 scp300fdev(const int32 port, const int32 io, const int32 data) -{ -/* DBG_PRINT(("SCP300F: IO %s, Port %02x\n", io ? "WR" : "RD", port)); */ - if(io) { - SCP300F_Write(port, data); - return 0; - } else { - return(SCP300F_Read(port)); - } -} - -#define SCP300F_MPIC_0 0x00 /* Master PIC */ -#define SCP300F_MPIC_1 0x01 /* Master PIC */ -#define SCP300F_SPIC_0 0x02 /* Slave PIC */ -#define SCP300F_SPIC_1 0x03 /* Slave PIC */ -#define SCP300F_9513_DATA 0x04 /* 9513 counter/timer Data Port */ -#define SCP300F_9513_STATUS 0x05 /* 9513 counter/timer Status/Control Port */ -#define SCP300F_UART_DATA 0x06 /* UART Data Register */ -#define SCP300F_UART_STATUS 0x07 /* UART Status */ - -#define SCP300F_PIO_DATA 0x0C /* PIO Data */ -#define SCP300F_PIO_STATUS 0x0D /* PIO Status */ -#define SCP300F_EPROM_DIS 0x0E /* EPROM Disable */ -#define SCP300F_SENSE_SW 0x0F /* Sense Switch */ - -extern int32 sio0d(const int32 port, const int32 io, const int32 data); -extern int32 sio0s(const int32 port, const int32 io, const int32 data); - -static uint8 SCP300F_Read(const uint32 Addr) -{ - uint8 cData = 0xFF; - - switch(Addr & SCP300F_IO_MASK) { - case SCP300F_MPIC_0: - case SCP300F_MPIC_1: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " Master 8259 DATA RD[%02x]: not implemented.\n", PCX, Addr); - break; - case SCP300F_SPIC_0: - case SCP300F_SPIC_1: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " Slave 8259 DATA RD[%02x]: not implemented.\n", PCX, Addr); - break; - case SCP300F_9513_DATA: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " 9513 DATA RD[%02x]: not implemented.\n", PCX, Addr); - break; - case SCP300F_9513_STATUS: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " 9513 STAT RD[%02x]: not implemented.\n", PCX, Addr); - break; - case SCP300F_UART_DATA: /* UART is handled by the 2SIO, if this gets called, then the 2SIO was not */ - case SCP300F_UART_STATUS: /* configured properly. */ - sim_debug(VERBOSE_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " RD[%02x]: UART not configured properly.\n", PCX, Addr); - break; - case SCP300F_PIO_DATA: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " PIO DATA RD[%02x]: not implemented.\n", PCX, Addr); - break; - case SCP300F_PIO_STATUS: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " PIO STATUS RD[%02x]: not implemented.\n", PCX, Addr); - break; - case SCP300F_EPROM_DIS: - sim_debug(ROM_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " EPROM DIS RD: EPROM Disabled.\n", PCX); - scp300f_info->rom_enabled = 0; - break; - case SCP300F_SENSE_SW: /* Sense Switch */ - cData = scp300f_sr; - sim_debug(VERBOSE_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " RD: Sense Switch=0x%02x\n", PCX, cData); - break; - default: - sim_debug(VERBOSE_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " RD[%02x]: not Implemented.\n", PCX, Addr); - break; - } - - return (cData); - -} - -static uint8 SCP300F_Write(const uint32 Addr, uint8 cData) -{ - - switch(Addr & SCP300F_IO_MASK) { - case SCP300F_MPIC_0: - case SCP300F_MPIC_1: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " Master 8259 DATA WR[%02x]=%02x: not implemented.\n", PCX, Addr, cData); - break; - case SCP300F_SPIC_0: - case SCP300F_SPIC_1: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " Slave 8259 DATA WR[%02x]=%02x: not implemented.\n", PCX, Addr, cData); - break; - case SCP300F_9513_DATA: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " 9513 DATA WR[%02x]=%02x: not implemented.\n", PCX, Addr, cData); - break; - case SCP300F_9513_STATUS: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " 9513 STAT WR[%02x]=%02x: not implemented.\n", PCX, Addr, cData); - break; - case SCP300F_UART_DATA: /* UART is handled by the 2SIO, if this gets called, then the 2SIO was not */ - case SCP300F_UART_STATUS: /* configured properly. */ - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " WR[%02x]: UART not configured properly.\n", PCX, Addr); - break; - case SCP300F_PIO_DATA: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " PIO DATA WR[%02x]=%02x: not implemented.\n", PCX, Addr, cData); - break; - case SCP300F_PIO_STATUS: - sim_debug(UART_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " WR[%02x]: Cannot write to PIO STATUS.\n", PCX, Addr); - break; - case SCP300F_EPROM_DIS: - sim_debug(ROM_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " EPROM DIS WR: EPROM Disabled.\n", PCX); - scp300f_info->rom_enabled = 0; - break; - case SCP300F_SENSE_SW: - sim_debug(VERBOSE_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " WR[%02x]: Cannot write to SR.\n", PCX, Addr); - break; - default: - sim_debug(VERBOSE_MSG, &scp300f_dev, "SCP300F: " ADDRESS_FORMAT " WR[0x%02x]=0x%02x: not Implemented.\n", PCX, Addr, cData); - break; - } - - return(0); -} - diff --git a/AltairZ80/s100_selchan.c b/AltairZ80/s100_selchan.c deleted file mode 100644 index 926a1b6f..00000000 --- a/AltairZ80/s100_selchan.c +++ /dev/null @@ -1,209 +0,0 @@ -/************************************************************************* - * * - * $Id: s100_selchan.c 1995 2008-07-15 03:59:13Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * CompuPro Selector Channel module for SIMH. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/*#define DBG_MSG */ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define VERBOSE_MSG (1 << 1) -#define DMA_MSG (1 << 2) - -#define SELCHAN_MAX_DRIVES 1 - -#define UNIT_V_SELCHAN_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_SELCHAN_VERBOSE (1 << UNIT_V_SELCHAN_VERBOSE) - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint32 selchan; /* Selector Channel Register */ - uint32 dma_addr; /* DMA Transfer Address */ - uint32 dma_mode; /* DMA Mode register */ - uint8 reg_cnt; /* Counter for selchan register */ -} SELCHAN_INFO; - -static SELCHAN_INFO selchan_info_data = { { 0x0, 0, 0xF0, 1 } }; -static SELCHAN_INFO *selchan_info = &selchan_info_data; -int32 selchan_dma(uint8 *buf, uint32 len); - -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern uint32 PCX; - -/* These are needed for DMA. */ -extern void PutByteDMA(const uint32 Addr, const uint32 Value); -extern uint8 GetByteDMA(const uint32 Addr); - -static t_stat selchan_reset(DEVICE *selchan_dev); - -static int32 selchandev(const int32 port, const int32 io, const int32 data); - - -static UNIT selchan_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ROABLE, 0) } -}; - -static REG selchan_reg[] = { - { HRDATA (DMA_MODE, selchan_info_data.dma_mode, 8), }, - { HRDATA (DMA_ADDR, selchan_info_data.dma_addr, 24), }, - { NULL } -}; - -static MTAB selchan_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - /* quiet, no warning messages */ - { UNIT_SELCHAN_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_SELCHAN_VERBOSE, UNIT_SELCHAN_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB selchan_dt[] = { - { "ERROR", ERROR_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { "DMA", DMA_MSG }, - { NULL, 0 } -}; - -DEVICE selchan_dev = { - "SELCHAN", selchan_unit, selchan_reg, selchan_mod, - SELCHAN_MAX_DRIVES, 10, 31, 1, SELCHAN_MAX_DRIVES, SELCHAN_MAX_DRIVES, - NULL, NULL, &selchan_reset, - NULL, NULL, NULL, - &selchan_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - selchan_dt, NULL, "Compupro Selector Channel SELCHAN" -}; - -/* Reset routine */ -static t_stat selchan_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &selchandev, TRUE); - } else { - /* Connect SELCHAN at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &selchandev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - return SCPE_OK; -} - -#define SELCHAN_MODE_WRITE 0x80 /* Selector Channel Memory or I/O Write */ -#define SELCHAN_MODE_IO 0x40 /* Set if I/O Access, otherwise memory */ -#define SELCHAN_MODE_CNT_UP 0x20 /* Set = DMA Address Count Up, otherwise down. (Mem only */ -#define SELCHAN_MODE_WAIT 0x10 /* Insert one wait state. */ -#define SELCHAN_MODE_DMA_MASK 0x0F /* Mask for DMA Priority field */ - -static int32 selchandev(const int32 port, const int32 io, const int32 data) -{ - DBG_PRINT(("SELCHAN: IO %s, Port %02x" NLP, io ? "WR" : "RD", port)); - if(io) { - selchan_info->selchan <<= 8; - selchan_info->selchan &= 0xFFFFFF00; - selchan_info->selchan |= data; - - selchan_info->dma_addr = (selchan_info->selchan & 0xFFFFF00) >> 8; - selchan_info->dma_mode = (selchan_info->selchan & 0xFF); - - selchan_info->reg_cnt ++; - - if(selchan_info->reg_cnt == 4) { - sim_debug(VERBOSE_MSG, &selchan_dev, "SELCHAN: " ADDRESS_FORMAT " DMA=0x%06x, Mode=0x%02x (%s, %s, %s)\n", PCX, selchan_info->dma_addr, selchan_info->dma_mode, selchan_info->dma_mode & SELCHAN_MODE_WRITE ? "WR" : "RD", selchan_info->dma_mode & SELCHAN_MODE_IO ? "I/O" : "MEM", selchan_info->dma_mode & SELCHAN_MODE_IO ? "FIX" : selchan_info->dma_mode & SELCHAN_MODE_CNT_UP ? "INC" : "DEC"); - } - - return 0; - } else { - sim_debug(VERBOSE_MSG, &selchan_dev, "SELCHAN: " ADDRESS_FORMAT " Reset\n", PCX); - selchan_info->reg_cnt = 0; - return(0xFF); - } -} - -int32 selchan_dma(uint8 *buf, uint32 len) -{ - uint32 i; - - if(selchan_info->reg_cnt != 4) { - printf("SELCHAN: " ADDRESS_FORMAT " Programming error: selector channel disabled." NLP, - PCX); - return (-1); - } - - if(selchan_info->dma_mode & SELCHAN_MODE_IO) - { - printf("SELCHAN: " ADDRESS_FORMAT " I/O Not supported" NLP, PCX); - return (-1); - } else { - sim_debug(DMA_MSG, &selchan_dev, "SELCHAN: " ADDRESS_FORMAT " DMA %s Transfer, len=%d\n", PCX, (selchan_info->dma_mode & SELCHAN_MODE_WRITE) ? "WR" : "RD", len); - for(i=0;idma_mode & SELCHAN_MODE_WRITE) { - PutByteDMA(selchan_info->dma_addr + i, buf[i]); - } else { - buf[i] = GetByteDMA(selchan_info->dma_addr + i); - } - } - - if(selchan_info->dma_mode & SELCHAN_MODE_CNT_UP) { - selchan_info->dma_addr += i; - } else { - selchan_info->dma_addr -= i; - } - } - - return(0); -} diff --git a/AltairZ80/s100_ss1.c b/AltairZ80/s100_ss1.c deleted file mode 100644 index 95184c05..00000000 --- a/AltairZ80/s100_ss1.c +++ /dev/null @@ -1,664 +0,0 @@ -/************************************************************************* - * * - * $Id: s100_ss1.c 1997 2008-07-18 05:29:52Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * CompuPro System Support 1 module for SIMH. * - * Note this does not include the Boot ROM on the System Support 1 Card * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/*#define DBG_MSG */ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#include - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define TRACE_MSG (1 << 1) -#define PIC_MSG (1 << 2) -#define TC_MSG (1 << 3) -#define RTC_MSG (1 << 4) -#define MATH_MSG (1 << 5) -#define UART_MSG (1 << 6) -#define IRQ_MSG (1 << 7) - -#define SS1_MAX_TIMERS 3 - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ -} SS1_INFO; - -static SS1_INFO ss1_info_data = { { 0x0, 0, 0x50, 16 } }; - -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern uint32 PCX; - -static t_stat ss1_reset(DEVICE *ss1_dev); -static t_stat ss1_svc (UNIT *uptr); -static uint8 SS1_Read(const uint32 Addr); -static uint8 SS1_Write(const uint32 Addr, uint8 cData); -static int32 ss1dev(const int32 port, const int32 io, const int32 data); -void raise_ss1_interrupt(uint8 isr_index); - -/* SS1 Interrupt Controller notes: - * - * Msster 8259: - * IRQ0 = VI0 - * IRQ1 = VI1 - DISK3 Interrupt - * IRQ2 = VI2 - IF3 Rx Interrupt - * IRQ3 = VI3 - IF3 Tx Interrupt - * IRQ4 = VI4 - DISK1A - * IRQ5 = VI5 - ? - * IRQ6 = VI6 - * - * - * Slave 8259: - * IRQ0 = VI7 0x48 - * IRQ1 = Timer0 0x49 - * IRQ2 = Timer1 0x4A - * IRQ3 = Timer2 0x4B - * IRQ4 = 9511 SVRQ 0x4C - * IRQ5 = 9511 END 0x4D - * IRQ6 = 2651 TxRDY 0x4E - * IRQ7 = 2651 RxRDY 0x4F - */ -#define MASTER_PIC 0 -#define SLAVE_PIC 1 - -#define VI0_IRQ_OFFSET 0 -#define VI1_IRQ_OFFSET 1 -#define VI2_IRQ_OFFSET 2 -#define VI3_IRQ_OFFSET 3 -#define VI4_IRQ_OFFSET 4 -#define VI5_IRQ_OFFSET 5 -#define VI6_IRQ_OFFSET 6 -#define VI7_IRQ_OFFSET 0 -#define TC0_IRQ_OFFSET 1 -#define TC1_IRQ_OFFSET 2 -#define TC2_IRQ_OFFSET 3 -#define MSVRQ_IRQ_OFFSET 4 -#define MEND_IRQ_OFFSET 5 -#define TXRDY_IRQ_OFFSET 6 -#define RXRDY_IRQ_OFFSET 7 - -typedef struct { - uint8 config_cnt; - uint8 ICW[5]; - uint8 IMR; /* OCW1 = IMR */ - uint8 OCW2; - uint8 OCW3; - uint8 IRR; - uint8 ISR; -} I8259_REGS; - -I8259_REGS ss1_pic[2]; - -/* SS1 Timer notes: - * - * T0, T1, T2 inputs connected to 2MHz clock on SS1 - * T0 IRQ connected to Slave IRQ 1 - * T1 IRQ connected to Slave IRQ 2 - * T2 IRQ connected to Slave IRQ 3 - */ -typedef struct { - uint16 count[3]; /* Current counter value for each timer. */ - uint8 mode[3]; /* Current mode of each timer. */ - uint8 bcd[3]; - uint8 rl[3]; - uint8 CTL; -} I8253_REGS; - -I8253_REGS ss1_tc[1]; - -#define I8253_CTL_SC_MASK 0xC0 -#define I8253_CTL_RL_MASK 0x30 -#define I8253_CTL_MODE_MASK 0x0E -#define I8253_CTL_BCD 0x01 - -typedef struct { - uint8 digit_sel; - uint8 flags; -} RTC_REGS; - -RTC_REGS ss1_rtc[1]; - -static UNIT ss1_unit[] = { - { UDATA (&ss1_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) }, - { UDATA (&ss1_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) }, - { UDATA (&ss1_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) }, - { UDATA (&ss1_svc, UNIT_FIX | UNIT_DISABLE | UNIT_ROABLE, 0) } -}; - -static REG ss1_reg[] = { - { HRDATA (MPIC_IMR, ss1_pic[MASTER_PIC].IMR, 8), }, - { HRDATA (MPIC_IRR, ss1_pic[MASTER_PIC].IRR, 8), }, - { HRDATA (MPIC_ISR, ss1_pic[MASTER_PIC].ISR, 8), }, - { HRDATA (MPIC_OCW2, ss1_pic[MASTER_PIC].OCW2, 8), }, - { HRDATA (MPIC_OCW3, ss1_pic[MASTER_PIC].OCW3, 8), }, - - { HRDATA (SPIC_IMR, ss1_pic[SLAVE_PIC].IMR, 8), }, - { HRDATA (SPIC_IRR, ss1_pic[SLAVE_PIC].IRR, 8), }, - { HRDATA (SPIC_ISR, ss1_pic[SLAVE_PIC].ISR, 8), }, - { HRDATA (SPIC_OCW2, ss1_pic[SLAVE_PIC].OCW2, 8), }, - { HRDATA (SPIC_OCW3, ss1_pic[SLAVE_PIC].OCW3, 8), }, - - { HRDATA (T0_MODE, ss1_tc[0].mode, 3), }, - { HRDATA (T0_COUNT, ss1_tc[0].count, 16), }, - { HRDATA (T1_MODE, ss1_tc[1].mode, 3), }, - { HRDATA (T1_COUNT, ss1_tc[1].count, 16), }, - { HRDATA (T2_MODE, ss1_tc[2].mode, 3), }, - { HRDATA (T2_COUNT, ss1_tc[2].count, 16), }, - - { HRDATA (RTC_DIGIT, ss1_rtc[0].digit_sel, 4), }, - { HRDATA (RTC_FLAGS, ss1_rtc[0].flags, 4), }, - - { NULL } -}; - -static MTAB ss1_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB ss1_dt[] = { - { "ERROR", ERROR_MSG }, - { "TRACE", TRACE_MSG }, - { "PIC", PIC_MSG }, - { "TC", TC_MSG }, - { "RTC", RTC_MSG }, - { "MATH", MATH_MSG }, - { "UART", UART_MSG }, - { "IRQ", IRQ_MSG }, - { NULL, 0 } -}; - -DEVICE ss1_dev = { - "SS1", ss1_unit, ss1_reg, ss1_mod, - SS1_MAX_TIMERS, 10, 31, 1, SS1_MAX_TIMERS, SS1_MAX_TIMERS, - NULL, NULL, &ss1_reset, - NULL, NULL, NULL, - &ss1_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - ss1_dt, NULL, "Compupro System Support 1 SS1" -}; - -/* Reset routine */ -static t_stat ss1_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &ss1dev, TRUE); - } else { - /* Connect SS1 at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &ss1dev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } else { - DBG_PRINT(("SS1: Mapped I/O resource at 0x%04x, len=%d\n", pnp->io_base, pnp->io_size)); - ss1_unit[0].u4 = 0; - ss1_unit[1].u4 = 1; - ss1_unit[2].u4 = 2; - ss1_unit[3].u4 = 3; - ss1_pic[MASTER_PIC].IMR = 0xFF; - ss1_pic[SLAVE_PIC].IMR = 0xFF; - } - } - return SCPE_OK; -} - -static int32 ss1dev(const int32 port, const int32 io, const int32 data) -{ - DBG_PRINT(("SS1: IO %s, Port %02x\n", io ? "WR" : "RD", port)); - if(io) { - SS1_Write(port, data); - return 0; - } else { - return(SS1_Read(port)); - } -} - -#define SS1_M8259_L 0x00 -#define SS1_M8259_H 0x01 -#define SS1_S8259_L 0x02 -#define SS1_S8259_H 0x03 -#define SS1_8253_TC0 0x04 -#define SS1_8253_TC1 0x05 -#define SS1_8253_TC2 0x06 -#define SS1_8253_CTL 0x07 -#define SS1_9511A_DATA 0x08 -#define SS1_9511A_CMD 0x09 -#define SS1_RTC_CMD 0x0A -#define SS1_RTC_DATA 0x0B -#define SS1_UART_DATA 0x0C -#define SS1_UART_STAT 0x0D -#define SS1_UART_MODE 0x0E -#define SS1_UART_CMD 0x0F - -extern int32 sio0d(const int32 port, const int32 io, const int32 data); -extern int32 sio0s(const int32 port, const int32 io, const int32 data); - -static struct tm currentTime; -static int32 toBCD(const int32 x); - -static uint8 SS1_Read(const uint32 Addr) -{ - uint8 cData = 0x00; - - uint8 sel_pic = MASTER_PIC; - uint8 sel_tc = 0; - time_t now; - - switch(Addr & 0x0F) { - case SS1_S8259_L: - sel_pic = SLAVE_PIC; - case SS1_M8259_L: - if((ss1_pic[sel_pic].OCW3 & 0x03) == 0x03) { - cData = ss1_pic[sel_pic].ISR; - sim_debug(PIC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " RD: %s PIC ISR=0x%02x.\n", PCX, (sel_pic ? "Slave " : "Master"), cData); - } else if((ss1_pic[sel_pic].OCW3 & 0x03) == 0x02) { - cData = ss1_pic[sel_pic].IRR; - sim_debug(PIC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " RD: %s PIC IRR=0x%02x.\n", PCX, (sel_pic ? "Slave " : "Master"), cData); - } else { - cData = 0xFF; - } - break; - case SS1_S8259_H: - sel_pic = SLAVE_PIC; - case SS1_M8259_H: - cData = ss1_pic[sel_pic].IMR; - sim_debug(PIC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " RD: %s PIC IMR=0x%02x.\n", PCX, (sel_pic ? "Slave " : "Master"), cData); - ss1_pic[sel_pic].IMR = cData; - break; - case SS1_8253_CTL: - cData = ss1_tc[0].CTL; - sim_debug(TC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " RD: TC CTL=0x%02x.\n", PCX, cData); - break; - case SS1_8253_TC2: - sel_tc++; - case SS1_8253_TC1: - sel_tc++; - case SS1_8253_TC0: - sim_debug(TC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " RD: TC [%d]=0x%02x.\n", PCX, sel_tc, cData); - break; - case SS1_9511A_DATA: - case SS1_9511A_CMD: - sim_debug(MATH_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " RD: Math Coprocessor not Implemented.\n", PCX); - break; - case SS1_RTC_CMD: - cData = 0xFF; - sim_debug(RTC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " RD: RTC Cmd=0x%02x.\n", PCX, cData); - break; - case SS1_RTC_DATA: - time(&now); - currentTime = *localtime(&now); - - switch(ss1_rtc[0].digit_sel) { - case 0: - cData = toBCD(currentTime.tm_sec) & 0xF; - break; - case 1: - cData = (toBCD(currentTime.tm_sec) >> 4) & 0xF; - break; - case 2: - cData = toBCD(currentTime.tm_min) & 0xF; - break; - case 3: - cData = (toBCD(currentTime.tm_min) >> 4) & 0xF; - break; - case 4: - cData = toBCD(currentTime.tm_hour) & 0xF; - break; - case 5: - cData = (toBCD(currentTime.tm_hour) >> 4) & 0x3; - cData |= 0x08; /* Set to 24-hour format */ - break; - case 6: - cData = toBCD(currentTime.tm_wday) & 0xF; - break; - case 7: - cData = toBCD(currentTime.tm_mday) & 0xF; - break; - case 8: - cData = (toBCD(currentTime.tm_mday) >> 4) & 0xF; - break; - case 9: - cData = toBCD(currentTime.tm_mon+1) & 0xF; - break; - case 10: - cData = (toBCD(currentTime.tm_mon+1) >> 4) & 0xF; - break; - case 11: - cData = toBCD(currentTime.tm_year-22) & 0xF; - break; - case 12: - cData = (toBCD(currentTime.tm_year-22) >> 4) & 0xF; - break; - default: - cData = 0; - break; - } - sim_debug(RTC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " RD: RTC Data[%x]=0x%02x.\n", PCX, ss1_rtc[0].digit_sel, cData); - - break; - case SS1_UART_DATA: - cData = sio0d(Addr, 0, 0); - sim_debug(UART_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " RD: UART Data=0x%02x.\n", PCX, cData); - break; - case SS1_UART_STAT: - cData = sio0s(Addr, 0, 0); - sim_debug(UART_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " RD: UART Stat=0x%02x.\n", PCX, cData); - break; - case SS1_UART_MODE: - case SS1_UART_CMD: - sim_debug(UART_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " RD: UART not Implemented.\n", PCX); - break; - } - - return (cData); - -} - -uint16 newcount = 0; -uint8 bc; - -static void generate_ss1_interrupt(void); - -static uint8 SS1_Write(const uint32 Addr, uint8 cData) -{ - - uint8 sel_pic = MASTER_PIC; - uint8 sel_tc = 0; - uint8 sel_timer = 0; - - switch(Addr & 0x0F) { - case SS1_S8259_L: - sel_pic = SLAVE_PIC; - case SS1_M8259_L: - if(cData & 0x10) { - sim_debug(PIC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " WR: %s PIC ICW1=0x%02x.\n", PCX, (sel_pic ? "Slave " : "Master"), cData); - ss1_pic[sel_pic].ICW[1] = cData; - ss1_pic[sel_pic].config_cnt=1; - } else { - if(cData & 0x08) { /* OCW3 */ - sim_debug(PIC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " WR: %s PIC OCW3=0x%02x.\n", PCX, (sel_pic ? "Slave " : "Master"), cData); - ss1_pic[sel_pic].OCW3 = cData; - } else { /* OCW2 */ - sim_debug(PIC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " WR: %s PIC OCW2=0x%02x.\n", PCX, (sel_pic ? "Slave " : "Master"), cData); - ss1_pic[sel_pic].OCW2 = cData; - } - } - break; - case SS1_S8259_H: - sel_pic = SLAVE_PIC; - case SS1_M8259_H: - if(ss1_pic[sel_pic].config_cnt == 0) { - sim_debug(PIC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT " WR: %s PIC IMR=0x%02x.\n", PCX, (sel_pic ? "Slave " : "Master"), cData); - ss1_pic[sel_pic].IMR = cData; - generate_ss1_interrupt(); - } else { - ss1_pic[sel_pic].config_cnt++; - sim_debug(PIC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT " WR: %s PIC ICW%d=0x%02x.\n", PCX, (sel_pic ? "Slave " : "Master"), ss1_pic[sel_pic].config_cnt, cData); - ss1_pic[sel_pic].ICW[ss1_pic[sel_pic].config_cnt] = cData; - - ss1_unit[0].u3 = ss1_pic[SLAVE_PIC].ICW[2]+TC0_IRQ_OFFSET; - ss1_unit[1].u3 = ss1_pic[SLAVE_PIC].ICW[2]+TC1_IRQ_OFFSET; - ss1_unit[2].u3 = ss1_pic[SLAVE_PIC].ICW[2]+TC2_IRQ_OFFSET; - - if(ss1_pic[sel_pic].config_cnt == 4) { - ss1_pic[sel_pic].config_cnt = 0; - } - } - break; - case SS1_8253_CTL: - ss1_tc[0].CTL = cData; - sel_timer = (ss1_tc[0].CTL & I8253_CTL_SC_MASK) >> 6; - sim_debug(TC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " WR: TC CTL=0x%02x.\n", - PCX, ss1_tc[0].CTL); - if(ss1_tc[0].CTL & I8253_CTL_BCD) { - sim_debug(ERROR_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " Timer %d: BCD Mode not supported: TC CTL=0x%02x.\n", - PCX, sel_timer, ss1_tc[0].CTL); - } - ss1_tc[0].bcd[sel_timer] = (ss1_tc[0].CTL & I8253_CTL_BCD); - ss1_tc[0].mode[sel_timer] = (ss1_tc[0].CTL & I8253_CTL_MODE_MASK) >> 1; - ss1_tc[0].rl[sel_timer] = (ss1_tc[0].CTL & I8253_CTL_RL_MASK) >> 4; - sim_debug(TRACE_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " Timer %d: Mode: %d, RL=%d, %s.\n", - PCX, sel_timer, ss1_tc[0].mode[sel_timer], - ss1_tc[0].rl[sel_timer], - ss1_tc[0].bcd[sel_timer] ? "BCD" : "Binary"); - newcount = 0; - bc=0; - break; - case SS1_8253_TC2: - sel_tc++; - case SS1_8253_TC1: - sel_tc++; - case SS1_8253_TC0: - if(ss1_tc[0].rl[sel_timer] == 3) { - if(bc==0) { - newcount = cData; - } - if(bc==1) { - newcount |= (cData << 8); - sim_activate(&ss1_unit[sel_tc], newcount); - } - bc++; - } - - if(ss1_tc[0].rl[sel_timer] == 2) { - newcount = (cData << 8); - sim_activate(&ss1_unit[sel_tc], newcount); - } - - sim_debug(TC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " WR: TC [%d]=0x%02x.\n", PCX, sel_tc, cData); - if(sel_tc == 0) { - } - break; - case SS1_9511A_DATA: - case SS1_9511A_CMD: - sim_debug(TRACE_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " WR: Math Coprocessor not Implemented.\n", PCX); - break; - case SS1_RTC_CMD: - ss1_rtc[0].digit_sel = cData & 0x0F; - ss1_rtc[0].flags = (cData >> 4) & 0x0F; - sim_debug(RTC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " WR: RTC Cmd=0x%02x (%s%s%s SEL=%x)\n", - PCX, cData, - ss1_rtc[0].flags & 0x4 ? "HOLD " :"", - ss1_rtc[0].flags & 0x2 ? "WR" :"", - ss1_rtc[0].flags & 0x1 ? "RD" :"", - ss1_rtc[0].digit_sel); - break; - case SS1_RTC_DATA: - sim_debug(RTC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " WR: RTC Data=0x%02x\n", PCX, cData); - break; - case SS1_UART_DATA: - sim_debug(UART_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " WR: UART Data=0x%02x.\n", PCX, cData); - sio0d(Addr, 1, cData); - break; - case SS1_UART_STAT: - sim_debug(UART_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " WR: UART Stat=0x%02x.\n", PCX, cData); - sio0s(Addr, 1, cData); - break; - case SS1_UART_MODE: - case SS1_UART_CMD: - sim_debug(TRACE_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT - " WR: UART not Implemented.\n", PCX); - break; - } - - return(0); -} - -void raise_ss1_interrupt(uint8 isr_index) -{ - uint8 irq_bit; - if(isr_index < 7) { /* VI0-6 on master PIC */ - irq_bit = (1 << isr_index); - ss1_pic[MASTER_PIC].ISR |= irq_bit; - generate_ss1_interrupt(); - } else { /* VI7 is on slave PIC */ - ss1_pic[SLAVE_PIC].ISR |= 1; - generate_ss1_interrupt(); - } -} -extern void cpu_raise_interrupt(uint32 irq); - -static void generate_ss1_interrupt(void) -{ - uint8 irq, irq_pend, irq_index = 0, irq_bit = 0; - - uint8 pic; - - for(pic=MASTER_PIC;pic<=SLAVE_PIC;pic++) { - irq_pend = (~ss1_pic[pic].IMR) & ss1_pic[pic].ISR; - - while(irq_pend) { - - irq_bit = irq_pend & 1; - if(irq_bit) { - ss1_pic[pic].IRR |= (irq_bit << irq_index); - irq = ss1_pic[pic].ICW[2]+irq_index; - sim_debug(IRQ_MSG, &ss1_dev, "Handling interrupt on %s PIC: IMR=0x%02x, ISR=0x%02x, IRR=0x%02x, index=%d\n", pic ? "SLAVE" : "MASTER", ss1_pic[pic].IMR, ss1_pic[pic].ISR, ss1_pic[pic].IRR, irq_index); - cpu_raise_interrupt(irq); - ss1_pic[pic].IRR &= ~(irq_bit << irq_index); - ss1_pic[pic].ISR &= ~(irq_bit << irq_index); - if(irq_pend & 0x7E) { -/* sim_debug(IRQ_MSG, &ss1_dev, "Requeue interrupt on %s PIC: IMR=0x%02x, ISR=0x%02x, IRR=0x%02x, index=%d\n", pic ? "SLAVE" : "MASTER", ss1_pic[pic].IMR, ss1_pic[pic].ISR, ss1_pic[pic].IRR, irq_index); -*/ - sim_activate(&ss1_unit[3], 1000); /* requeue, because more interrupts are pending. */ - } - break; - } else { - irq_index++; - irq_pend = irq_pend >> 1; - } - } - } -} - - -/* Unit service routine */ -/* Unit 0-2 = Timer0-2, Unit3=ISR queue */ -static t_stat ss1_svc (UNIT *uptr) -{ - uint8 cData; - uint8 irq_bit = 0; - - /* Handle SS1 UART Rx interrupts here. */ - cData = sio0s(0x5D, 0, 0); - if(cData & 2) { /* && ((ss1_pic[SLAVE_PIC].IMR & 0x80) == 0)) { */ - ss1_pic[SLAVE_PIC].ISR |= 0x80; - generate_ss1_interrupt(); - sim_activate(uptr, 1000); /* requeue, because we still need to handle the timer interrupt. */ - } else if((cData & 1) && ((ss1_pic[SLAVE_PIC].IMR & 0x40) == 0)) { - sim_debug(IRQ_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT " Calling UART Tx ISR.\n", PCX); - ss1_pic[SLAVE_PIC].ISR |= 0x40; - generate_ss1_interrupt(); - sim_activate(uptr, 1000); /* requeue, because we still need to handle the timer interrupt. */ - } else if (uptr->u4 == 0x3) { /* ISR was requeued because additional interrupts were pending. */ - generate_ss1_interrupt(); - } else { - switch(uptr->u4) { - case 0: - irq_bit = 2; - break; - case 1: - irq_bit = 4; - break; - case 2: - irq_bit = 8; - break; - } - if(ss1_tc[0].mode[uptr->u4] == 0x0) { - sim_debug(TC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT " Calling Timer%d ISR.\n", PCX, uptr->u4); - ss1_pic[SLAVE_PIC].ISR |= irq_bit; - generate_ss1_interrupt(); - } - if(ss1_tc[0].mode[uptr->u4] == 0x3) { - sim_debug(TC_MSG, &ss1_dev, "SS1: " ADDRESS_FORMAT " Calling Timer%d ISR.\n", PCX, uptr->u4); - ss1_pic[SLAVE_PIC].ISR |= irq_bit; - generate_ss1_interrupt(); - sim_debug(TC_MSG, &ss1_dev, "Timer %d, mode %d, reloading\n", uptr->u4, ss1_tc[0].mode[uptr->u4]); - sim_activate(uptr, 33280); - } - } - - sim_activate(&ss1_unit[3], 1000000); // requeue, because more interrupts are pending. - - return SCPE_OK; -} - -static int32 toBCD(const int32 x) { - return (x / 10) * 16 + (x % 10); -} - diff --git a/AltairZ80/sim_imd.c b/AltairZ80/sim_imd.c deleted file mode 100644 index b9884b25..00000000 --- a/AltairZ80/sim_imd.c +++ /dev/null @@ -1,802 +0,0 @@ -/************************************************************************* - * * - * $Id: sim_imd.c 1999 2008-07-22 04:25:28Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * ImageDisk (IMD) Disk Image File access module for SIMH. * - * see: http://www.classiccmp.org/dunfield/img/index.htm * - * for details on the ImageDisk format and other utilities. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/* Change log: - - 06-Aug-2008, Tony Nicholson, Add support for logical Head and - Cylinder maps in the .IMD image file (AGN) -*/ - -#include "sim_defs.h" -#include "sim_imd.h" -#include -#ifdef _WIN32 -#include /* for _chsize() */ -#else -#include -#endif -/* #define DBG_MSG */ - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* use NLP for new line printing while the simulation is running */ -#if defined (__linux) || defined(__NetBSD__) || defined (__OpenBSD__) || defined (__FreeBSD__) || defined (__APPLE__) -#define UNIX_PLATFORM 1 -#else -#define UNIX_PLATFORM 0 -#endif - -#if UNIX_PLATFORM -#define NLP "\r\n" -#else -#define NLP "\n" -#endif - -#if (defined (__MWERKS__) && defined (macintosh)) || defined(__DECC) -#define __FUNCTION__ __FILE__ -#endif - -static t_stat commentParse(DISK_INFO *myDisk, uint8 comment[], uint32 buffLen); -static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose); -static t_stat diskFormat(DISK_INFO *myDisk); - -/* Open an existing IMD disk image. It will be opened and parsed, and after this - * call, will be ready for sector read/write. The result is the corresponding - * DISK_INFO or NULL if an error occurred. - */ -DISK_INFO *diskOpen(FILE *fileref, uint32 isVerbose) -{ - DISK_INFO *myDisk = NULL; - - myDisk = (DISK_INFO *)malloc(sizeof(DISK_INFO)); - myDisk->file = fileref; - - if (diskParse(myDisk, isVerbose) != SCPE_OK) { - free(myDisk); - myDisk = NULL; - } - - return myDisk; -} - -/* Scans the IMD file for the comment string, and returns it in comment buffer. - * After this function returns, the file pointer is placed after the comment and - * the 0x1A "EOF" marker. - * - * The comment parameter is optional, and if NULL, then the ocmment will not - * be extracted from the IMD file, but the file position will still be advanced - * to the end of the comment. - */ -static t_stat commentParse(DISK_INFO *myDisk, uint8 comment[], uint32 buffLen) -{ - uint8 cData; - uint32 commentLen = 0; - - /* rewind to the beginning of the file. */ - rewind(myDisk->file); - cData = fgetc(myDisk->file); - while ((!feof(myDisk->file)) && (cData != 0x1a)) { - if ((comment != NULL) && (commentLen < buffLen)) { - comment[commentLen++] = cData; - } - cData = fgetc(myDisk->file); - } - if (comment != NULL) { - if (commentLen == buffLen) - commentLen--; - comment[commentLen] = 0; - } - return SCPE_OK; -} - -static uint32 headerOk(IMD_HEADER imd) { - return (imd.cyl < MAX_CYL) && (imd.head < MAX_HEAD); -} - -/* Parse an IMD image. This sets up sim_imd to be able to do sector read/write and - * track write. - */ -static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose) -{ - uint8 comment[256]; - uint8 sectorMap[256]; - uint8 sectorHeadMap[256]; - uint8 sectorCylMap[256]; - uint32 sectorSize, sectorHeadwithFlags, sectRecordType; - uint32 i; - uint8 start_sect; - - uint32 TotalSectorCount = 0; - IMD_HEADER imd; - - if(myDisk == NULL) { - return (SCPE_OPENERR); - } - - memset(myDisk->track, 0, (sizeof(TRACK_INFO)*MAX_CYL*MAX_HEAD)); - - if (commentParse(myDisk, comment, sizeof(comment)) != SCPE_OK) { - return (SCPE_OPENERR); - } - - if(isVerbose) - printf("%s" NLP, comment); - - myDisk->nsides = 1; - myDisk->ntracks = 0; - myDisk->flags = 0; /* Make sure all flags are clear. */ - - if(feof(myDisk->file)) { - printf("SIM_IMD: Disk image is blank, it must be formatted." NLP); - return (SCPE_OPENERR); - } - - do { - DBG_PRINT(("start of track %d at file offset %ld" NLP, myDisk->ntracks, ftell(myDisk->file))); - - sim_fread(&imd, 1, 5, myDisk->file); - if (feof(myDisk->file)) - break; - sectorSize = 128 << imd.sectsize; - sectorHeadwithFlags = imd.head; /*AGN save the head and flags */ - imd.head &= 1 ; /*AGN mask out flag bits to head 0 or 1 */ - - DBG_PRINT(("Track %d:" NLP, myDisk->ntracks)); - DBG_PRINT(("\tMode=%d, Cyl=%d, Head=%d(%d), #sectors=%d, sectsize=%d (%d bytes)" NLP, imd.mode, imd.cyl, sectorHeadwithFlags, imd.head, imd.nsects, imd.sectsize, sectorSize)); - - if (!headerOk(imd)) { - printf("SIM_IMD: Corrupt header." NLP); - return (SCPE_OPENERR); - } - - if((imd.head + 1) > myDisk->nsides) { - myDisk->nsides = imd.head + 1; - } - - myDisk->track[imd.cyl][imd.head].mode = imd.mode; - myDisk->track[imd.cyl][imd.head].nsects = imd.nsects; - myDisk->track[imd.cyl][imd.head].sectsize = sectorSize; - - if (sim_fread(sectorMap, 1, imd.nsects, myDisk->file) != imd.nsects) { - printf("SIM_IMD: Corrupt file [Sector Map]." NLP); - return (SCPE_OPENERR); - } - myDisk->track[imd.cyl][imd.head].start_sector = imd.nsects; - DBG_PRINT(("\tSector Map: ")); - for(i=0;itrack[imd.cyl][imd.head].start_sector) { - myDisk->track[imd.cyl][imd.head].start_sector = sectorMap[i]; - } - } - DBG_PRINT((", Start Sector=%d", myDisk->track[imd.cyl][imd.head].start_sector)); - - if(sectorHeadwithFlags & IMD_FLAG_SECT_HEAD_MAP) { - if (sim_fread(sectorHeadMap, 1, imd.nsects, myDisk->file) != imd.nsects) { - printf("SIM_IMD: Corrupt file [Sector Head Map]." NLP); - return (SCPE_OPENERR); - } - DBG_PRINT(("\tSector Head Map: ")); - for(i=0;ifile) != imd.nsects) { - printf("SIM_IMD: Corrupt file [Sector Cyl Map]." NLP); - return (SCPE_OPENERR); - } - DBG_PRINT(("\tSector Cyl Map: ")); - for(i=0;ifile))); - - /* Build the table with location 0 being the start sector. */ - start_sect = myDisk->track[imd.cyl][imd.head].start_sector; - - /* Now read each sector */ - for(i=0;ifile); - /* AGN Logical head mapping */ - myDisk->track[imd.cyl][imd.head].logicalHead[i] = sectorHeadMap[i]; - /* AGN Logical cylinder mapping */ - myDisk->track[imd.cyl][imd.head].logicalCyl[i] = sectorCylMap[i]; - switch(sectRecordType) { - case SECT_RECORD_UNAVAILABLE: /* Data could not be read from the original media */ - if (sectorMap[i]-start_sect < MAX_SPT) - myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = 0xBADBAD; - else { - printf("SIM_IMD: ERROR: Illegal sector offset %d" NLP, sectorMap[i]-start_sect); - return (SCPE_OPENERR); - } - break; - case SECT_RECORD_NORM: /* Normal Data */ - case SECT_RECORD_NORM_DAM: /* Normal Data with deleted address mark */ - case SECT_RECORD_NORM_ERR: /* Normal Data with read error */ - case SECT_RECORD_NORM_DAM_ERR: /* Normal Data with deleted address mark with read error */ -/* DBG_PRINT(("Uncompressed Data" NLP)); */ - if (sectorMap[i]-start_sect < MAX_SPT) { - myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = ftell(myDisk->file); - sim_fseek(myDisk->file, sectorSize, SEEK_CUR); - } - else { - printf("SIM_IMD: ERROR: Illegal sector offset %d" NLP, sectorMap[i]-start_sect); - return (SCPE_OPENERR); - } - break; - case SECT_RECORD_NORM_COMP: /* Compressed Normal Data */ - case SECT_RECORD_NORM_DAM_COMP: /* Compressed Normal Data with deleted address mark */ - case SECT_RECORD_NORM_COMP_ERR: /* Compressed Normal Data */ - case SECT_RECORD_NORM_DAM_COMP_ERR: /* Compressed Normal Data with deleted address mark */ - if (sectorMap[i]-start_sect < MAX_SPT) { - myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = ftell(myDisk->file); - myDisk->flags |= FD_FLAG_WRITELOCK; /* Write-protect the disk if any sectors are compressed. */ -#ifdef VERBOSE_DEBUG - DBG_PRINT(("Compressed Data = 0x%02x" NLP, fgetc(myDisk->file))); -#else - fgetc(myDisk->file); -#endif - } - else { - printf("SIM_IMD: ERROR: Illegal sector offset %d" NLP, sectorMap[i]-start_sect); - return (SCPE_OPENERR); - } - break; - default: - printf("SIM_IMD: ERROR: unrecognized sector record type %d" NLP, sectRecordType); - return (SCPE_OPENERR); - break; - } - DBG_PRINT((NLP)); - } - - myDisk->ntracks++; - } while (!feof(myDisk->file)); - - DBG_PRINT(("Processed %d sectors" NLP, TotalSectorCount)); - -#ifdef VERBOSE_DEBUG - for(i=0;intracks;i++) { - DBG_PRINT(("Track %02d: ", i)); - for(j=0;jtrack[i][0].sectorOffsetMap[j])); - } - DBG_PRINT((NLP)); - } -#endif - if(myDisk->flags & FD_FLAG_WRITELOCK) { - printf("Disk write-protected because the image contains compressed sectors. Use IMDU to uncompress." NLP); - } - - return SCPE_OK; -} - -/* - * This function closes the IMD image. After closing, the sector read/write operations are not - * possible. - * - * The IMD file is not actually closed, we leave that to SIMH. - */ -t_stat diskClose(DISK_INFO **myDisk) -{ - if(*myDisk == NULL) - return SCPE_OPENERR; - free(*myDisk); - *myDisk = NULL; - return SCPE_OK; -} - -#define MAX_COMMENT_LEN 256 - -/* - * Create an ImageDisk (IMD) file. This function just creates the comment header, and allows - * the user to enter a comment. After the IMD is created, it must be formatted with a format - * program on the simulated operating system, ie CP/M, CDOS, 86-DOS. - * - * If the IMD file already exists, the user will be given the option of overwriting it. - */ -t_stat diskCreate(FILE *fileref, char *ctlr_comment) -{ - DISK_INFO *myDisk = NULL; - char *comment; - char *curptr; - char *result; - uint8 answer; - int32 len, remaining; - - if(fileref == NULL) { - return (SCPE_OPENERR); - } - - if(sim_fsize(fileref) != 0) { - printf("SIM_IMD: Disk image already has data, do you want to overwrite it? "); - answer = getchar(); - - if((answer != 'y') && (answer != 'Y')) { - return (SCPE_OPENERR); - } - } - - if((curptr = comment = calloc(1, MAX_COMMENT_LEN)) == 0) { - printf("Memory allocation failure.\n"); - return (SCPE_MEM); - } - - printf("SIM_IMD: Enter a comment for this disk.\n" - "SIM_IMD: Terminate with a '.' on an otherwise blank line.\n"); - remaining = MAX_COMMENT_LEN; - do { - printf("IMD> "); - result = fgets(curptr, remaining - 3, stdin); - if ((result == NULL) || (strcmp(curptr, ".\n") == 0)) { - remaining = 0; - } else { - len = strlen(curptr) - 1; - if (curptr[len] != '\n') - len++; - remaining -= len; - curptr += len; - *curptr++ = 0x0d; - *curptr++ = 0x0a; - } - } while (remaining > 4); - *curptr = 0x00; - - /* rewind to the beginning of the file. */ - rewind(fileref); - - /* Erase the contents of the IMD file in case we are overwriting an existing image. */ -#ifdef _WIN32 /* This might work under UNIX and/or VMS since this POSIX, but I haven't tried it. */ - _chsize(_fileno(fileref), ftell (fileref)); -#else - if (ftruncate(fileno(fileref), ftell (fileref)) == -1) { - printf("SIM_IMD: Error overwriting disk image.\n"); - return(SCPE_OPENERR); - } -#endif - - fprintf(fileref, "IMD SIMH %s %s\n", __DATE__, __TIME__); - fputs(comment, fileref); - free(comment); - fprintf(fileref, "\n\n$Id: sim_imd.c 1999 2008-07-22 04:25:28Z hharte $\n"); - fprintf(fileref, "%s\n", ctlr_comment); - fputc(0x1A, fileref); /* EOF marker for IMD comment. */ - fflush(fileref); - - if((myDisk = diskOpen(fileref, 0)) == NULL) { - printf("SIM_IMD: Error opening disk for format.\n"); - return(SCPE_OPENERR); - } - - if(diskFormat(myDisk) != SCPE_OK) { - printf("SIM_IMD: error formatting disk.\n"); - } - - return diskClose(&myDisk); -} - - -t_stat diskFormat(DISK_INFO *myDisk) -{ - uint8 i; - uint8 sector_map[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}; - uint32 flags; - - printf("SIM_IMD: Formatting disk in IBM 3740 SS/SD Format.\n"); - - for(i=0;i<77;i++) { - if((trackWrite(myDisk, i, 0, 26, 128, sector_map, IMD_MODE_500K_FM, 0xE5, &flags)) != 0) { - printf("SIM_IMD: Error formatting track %d\n", i); - return SCPE_IOERR; - } else { - putchar('.'); - } - } - - printf("\nSIM_IMD: Format Complete.\n"); - - return SCPE_OK; -} - -uint32 imdGetSides(DISK_INFO *myDisk) -{ - if(myDisk != NULL) { - return(myDisk->nsides); - } - - return (0); -} - -uint32 imdIsWriteLocked(DISK_INFO *myDisk) -{ - if(myDisk != NULL) { - return((myDisk->flags & FD_FLAG_WRITELOCK) ? 1 : 0); - } - - return (0); -} - -/* Check that the given track/sector exists on the disk */ -t_stat sectSeek(DISK_INFO *myDisk, - uint32 Cyl, - uint32 Head) -{ - if(Cyl >= myDisk->ntracks) { - return(SCPE_IOERR); - } - - if(Head >= myDisk->nsides) { - return(SCPE_IOERR); - } - - if(myDisk->track[Cyl][Head].nsects == 0) { - DBG_PRINT(("%s: invalid track/head" NLP, __FUNCTION__)); - return(SCPE_IOERR); - } - - return(SCPE_OK); -} - -/* Read a sector from an IMD image. */ -t_stat sectRead(DISK_INFO *myDisk, - uint32 Cyl, - uint32 Head, - uint32 Sector, - uint8 *buf, - uint32 buflen, - uint32 *flags, - uint32 *readlen) -{ - uint32 sectorFileOffset; - uint8 sectRecordType; - uint8 start_sect; - *readlen = 0; - *flags = 0; - - /* Check parameters */ - if(myDisk == NULL) { - *flags |= IMD_DISK_IO_ERROR_GENERAL; - return(SCPE_IOERR); - } - - if(sectSeek(myDisk, Cyl, Head) != SCPE_OK) { - *flags |= IMD_DISK_IO_ERROR_GENERAL; - return(SCPE_IOERR); - } - - if(Sector > myDisk->track[Cyl][Head].nsects) { - DBG_PRINT(("%s: invalid sector" NLP, __FUNCTION__)); - *flags |= IMD_DISK_IO_ERROR_GENERAL; - return(SCPE_IOERR); - } - - if(buflen < myDisk->track[Cyl][Head].sectsize) { - printf("%s: Reading C:%d/H:%d/S:%d, len=%d: user buffer too short, need %d" NLP, __FUNCTION__, Cyl, Head, Sector, buflen, myDisk->track[Cyl][Head].sectsize); - *flags |= IMD_DISK_IO_ERROR_GENERAL; - return(SCPE_IOERR); - } - - start_sect = myDisk->track[Cyl][Head].start_sector; - - sectorFileOffset = myDisk->track[Cyl][Head].sectorOffsetMap[Sector-start_sect]; - - DBG_PRINT(("Reading C:%d/H:%d/S:%d, len=%d, offset=0x%08x" NLP, Cyl, Head, Sector, buflen, sectorFileOffset)); - - sim_fseek(myDisk->file, sectorFileOffset-1, 0); - - sectRecordType = fgetc(myDisk->file); - switch(sectRecordType) { - case SECT_RECORD_UNAVAILABLE: /* Data could not be read from the original media */ - *flags |= IMD_DISK_IO_ERROR_GENERAL; - break; - case SECT_RECORD_NORM_ERR: /* Normal Data with read error */ - case SECT_RECORD_NORM_DAM_ERR: /* Normal Data with deleted address mark with read error */ - *flags |= IMD_DISK_IO_ERROR_CRC; - case SECT_RECORD_NORM: /* Normal Data */ - case SECT_RECORD_NORM_DAM: /* Normal Data with deleted address mark */ - -/* DBG_PRINT(("Uncompressed Data" NLP)); */ - if (sim_fread(buf, 1, myDisk->track[Cyl][Head].sectsize, myDisk->file) != myDisk->track[Cyl][Head].sectsize) { - printf("SIM_IMD[%s]: sim_fread error for SECT_RECORD_NORM_DAM." NLP, __FUNCTION__); - } - *readlen = myDisk->track[Cyl][Head].sectsize; - break; - case SECT_RECORD_NORM_COMP_ERR: /* Compressed Normal Data */ - case SECT_RECORD_NORM_DAM_COMP_ERR: /* Compressed Normal Data with deleted address mark */ - *flags |= IMD_DISK_IO_ERROR_CRC; - case SECT_RECORD_NORM_COMP: /* Compressed Normal Data */ - case SECT_RECORD_NORM_DAM_COMP: /* Compressed Normal Data with deleted address mark */ -/* DBG_PRINT(("Compressed Data" NLP)); */ - memset(buf, fgetc(myDisk->file), myDisk->track[Cyl][Head].sectsize); - *readlen = myDisk->track[Cyl][Head].sectsize; - *flags |= IMD_DISK_IO_COMPRESSED; - break; - default: - printf("ERROR: unrecognized sector record type %d" NLP, sectRecordType); - break; - } - - /* Set flags for deleted address mark. */ - switch(sectRecordType) { - case SECT_RECORD_NORM_DAM: /* Normal Data with deleted address mark */ - case SECT_RECORD_NORM_DAM_ERR: /* Normal Data with deleted address mark with read error */ - case SECT_RECORD_NORM_DAM_COMP: /* Compressed Normal Data with deleted address mark */ - case SECT_RECORD_NORM_DAM_COMP_ERR: /* Compressed Normal Data with deleted address mark */ - *flags |= IMD_DISK_IO_DELETED_ADDR_MARK; - default: - break; - } - - return(SCPE_OK); -} - -/* Write a sector to an IMD image. */ -t_stat sectWrite(DISK_INFO *myDisk, - uint32 Cyl, - uint32 Head, - uint32 Sector, - uint8 *buf, - uint32 buflen, - uint32 *flags, - uint32 *writelen) -{ - uint32 sectorFileOffset; - uint8 sectRecordType; - uint8 start_sect; - *writelen = 0; - - DBG_PRINT(("Writing C:%d/H:%d/S:%d, len=%d" NLP, Cyl, Head, Sector, buflen)); - - /* Check parameters */ - if(myDisk == NULL) { - *flags = IMD_DISK_IO_ERROR_GENERAL; - return(SCPE_IOERR); - } - - if(sectSeek(myDisk, Cyl, Head) != 0) { - *flags = IMD_DISK_IO_ERROR_GENERAL; - return(SCPE_IOERR); - } - - if(Sector > myDisk->track[Cyl][Head].nsects) { - DBG_PRINT(("%s: invalid sector" NLP, __FUNCTION__)); - *flags = IMD_DISK_IO_ERROR_GENERAL; - return(SCPE_IOERR); - } - - if(myDisk->flags & FD_FLAG_WRITELOCK) { - printf("Disk write-protected because the image contains compressed sectors. Use IMDU to uncompress." NLP); - *flags = IMD_DISK_IO_ERROR_WPROT; - return(SCPE_IOERR); - } - - if(buflen < myDisk->track[Cyl][Head].sectsize) { - printf("%s: user buffer too short [buflen %i < sectsize %i]" NLP, - __FUNCTION__, buflen, myDisk->track[Cyl][Head].sectsize); - *flags = IMD_DISK_IO_ERROR_GENERAL; - return(SCPE_IOERR); - } - - start_sect = myDisk->track[Cyl][Head].start_sector; - - sectorFileOffset = myDisk->track[Cyl][Head].sectorOffsetMap[Sector-start_sect]; - - sim_fseek(myDisk->file, sectorFileOffset-1, 0); - - if (*flags & IMD_DISK_IO_ERROR_GENERAL) { - sectRecordType = SECT_RECORD_UNAVAILABLE; - } else if (*flags & IMD_DISK_IO_ERROR_CRC) { - if (*flags & IMD_DISK_IO_DELETED_ADDR_MARK) - sectRecordType = SECT_RECORD_NORM_DAM_ERR; - else - sectRecordType = SECT_RECORD_NORM_ERR; - } else { - if (*flags & IMD_DISK_IO_DELETED_ADDR_MARK) - sectRecordType = SECT_RECORD_NORM_DAM; - else - sectRecordType = SECT_RECORD_NORM; - } - - fputc(sectRecordType, myDisk->file); - sim_fwrite(buf, 1, myDisk->track[Cyl][Head].sectsize, myDisk->file); - *writelen = myDisk->track[Cyl][Head].sectsize; - - return(SCPE_OK); -} - -/* Format an entire track. The new track to be formatted must be after any existing tracks on - * the disk. - * - * This routine should be enhanced to re-format an existing track to the same format (this - * does not involve changing the disk image size.) - * - * Any existing data on the disk image will be destroyed when Track 0, Head 0 is formatted. - * At that time, the IMD file is truncated. So for the trackWrite to be used to sucessfully - * format a disk image, then format program must format tracks starting with Cyl 0, Head 0, - * and proceed sequentially through all tracks/heads on the disk. - * - * Format programs that are known to work include: - * Cromemco CDOS "INIT.COM" - * ADC Super-Six (CP/M-80) "FMT8.COM" - * 86-DOS "INIT.COM" - * - */ -t_stat trackWrite(DISK_INFO *myDisk, - uint32 Cyl, - uint32 Head, - uint32 numSectors, - uint32 sectorLen, - uint8 *sectorMap, - uint8 mode, - uint8 fillbyte, - uint32 *flags) -{ - FILE *fileref; - IMD_HEADER track_header; - uint8 *sectorData; - unsigned long i; - unsigned long dataLen; - - *flags = 0; - - /* Check parameters */ - if(myDisk == NULL) { - *flags |= IMD_DISK_IO_ERROR_GENERAL; - return(SCPE_IOERR); - } - - if(myDisk->flags & FD_FLAG_WRITELOCK) { - printf("Disk write-protected, cannot format tracks." NLP); - *flags |= IMD_DISK_IO_ERROR_WPROT; - return(SCPE_IOERR); - } - - fileref = myDisk->file; - - DBG_PRINT(("Formatting C:%d/H:%d/N:%d, len=%d, Fill=0x%02x" NLP, Cyl, Head, numSectors, sectorLen, fillbyte)); - - /* Truncate the IMD file when formatting Cyl 0, Head 0 */ - if((Cyl == 0) && (Head == 0)) - { - /* Skip over IMD comment field. */ - commentParse(myDisk, NULL, 0); - - /* Truncate the IMD file after the comment field. */ -#ifdef _WIN32 /* This might work under UNIX and/or VMS since this POSIX, but I haven't tried it. */ - _chsize(_fileno(fileref), ftell (fileref)); -#else - if (ftruncate(fileno(fileref), ftell (fileref)) == -1) { - printf("Disk truncation failed." NLP); - *flags |= IMD_DISK_IO_ERROR_GENERAL; - return(SCPE_IOERR); - } -#endif - /* Flush and re-parse the IMD file. */ - fflush(fileref); - diskParse(myDisk, 0); - } - - /* Check to make sure the Cyl / Head is not already formatted. */ - if(sectSeek(myDisk, Cyl, Head) == 0) { - printf("SIM_IMD: ERROR: Not Formatting C:%d/H:%d, track already exists." NLP, Cyl, Head); - *flags |= IMD_DISK_IO_ERROR_GENERAL; - return(SCPE_IOERR); - } - - track_header.mode = mode; - track_header.cyl = Cyl; - track_header.head = Head; - track_header.nsects = numSectors; - track_header.sectsize = sectorLen; - - /* Forward to end of the file, write track header and sector map. */ - sim_fseek(myDisk->file, 0, SEEK_END); - sim_fwrite(&track_header, 1, sizeof(IMD_HEADER), fileref); - sim_fwrite(sectorMap, 1, numSectors, fileref); - - /* Compute data length, and fill a sector buffer with the - * sector record type as the first byte, and fill the sector - * data with the fillbyte. - */ - dataLen = (128 << sectorLen)+1; - sectorData = malloc(dataLen); - memset(sectorData, fillbyte, dataLen); - sectorData[0] = SECT_RECORD_NORM; - - /* For each sector on the track, write the record type and sector data. */ - for(i=0;ifileref) == NULL) - uptr->u3 = IMAGE_TYPE_DSK; - else if (strncmp(header, "IMD", 3) == 0) - uptr->u3 = IMAGE_TYPE_IMD; - else if(strncmp(header, "CPT", 3) == 0) { - printf("CPT images not yet supported.\n"); - uptr->u3 = IMAGE_TYPE_CPT; - result = SCPE_OPENERR; - } - else - uptr->u3 = IMAGE_TYPE_DSK; - return result; -} - diff --git a/AltairZ80/sim_imd.h b/AltairZ80/sim_imd.h deleted file mode 100644 index b6989111..00000000 --- a/AltairZ80/sim_imd.h +++ /dev/null @@ -1,128 +0,0 @@ -/************************************************************************* - * * - * $Id: sim_imd.h 1987 2008-07-08 03:25:57Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * ImageDisk Disk Image File access module for SIMH, definitions. * - * See: http://www.classiccmp.org/dunfield/img/index.htm * - * for details on the ImageDisk format and other utilities. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -typedef struct { - uint8 mode; - uint8 cyl; - uint8 head; - uint8 nsects; - uint8 sectsize; -} IMD_HEADER; - - -#define IMD_FLAG_SECT_HEAD_MAP (1 << 6) -#define IMD_FLAG_SECT_CYL_MAP (1 << 7) - -#define SECT_RECORD_UNAVAILABLE 0 /* Data could not be read from the original media */ -#define SECT_RECORD_NORM 1 /* Normal Data */ -#define SECT_RECORD_NORM_COMP 2 /* Compressed Normal Data */ -#define SECT_RECORD_NORM_DAM 3 /* Normal Data with deleted address mark */ -#define SECT_RECORD_NORM_DAM_COMP 4 /* Compressed Normal Data with deleted address mark */ -#define SECT_RECORD_NORM_ERR 5 /* Normal Data */ -#define SECT_RECORD_NORM_COMP_ERR 6 /* Compressed Normal Data */ -#define SECT_RECORD_NORM_DAM_ERR 7 /* Normal Data with deleted address mark */ -#define SECT_RECORD_NORM_DAM_COMP_ERR 8 /* Compressed Normal Data with deleted address mark */ - -#define MAX_CYL 80 -#define MAX_HEAD 2 -#define MAX_SPT 26 - -#define FD_FLAG_WRITELOCK 1 - -#define IMD_DISK_IO_ERROR_GENERAL (1 << 0) /* General data error. */ -#define IMD_DISK_IO_ERROR_CRC (1 << 1) /* Data read/written, but got a CRC error. */ -#define IMD_DISK_IO_DELETED_ADDR_MARK (1 << 2) /* Sector had a deleted address mark */ -#define IMD_DISK_IO_COMPRESSED (1 << 3) /* Sector is compressed in the IMD file (Read Only) */ -#define IMD_DISK_IO_ERROR_WPROT (1 << 4) /* Disk is write protected */ - -#define IMD_MODE_500K_FM 0 -#define IMD_MODE_300K_FM 1 -#define IMD_MODE_250K_FM 2 -#define IMD_MODE_500K_MFM 3 -#define IMD_MODE_300K_MFM 4 -#define IMD_MODE_250K_MFM 5 - -#define IMD_MODE_FM(x) (x <= IMD_MODE_250K_FM) -#define IMD_MODE_MFM(x) (x >= IMD_MODE_500K_MFM) - -#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */ -#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */ -#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */ - -typedef struct { - uint8 mode; - uint8 nsects; - uint32 sectsize; - uint32 sectorOffsetMap[MAX_SPT]; - uint8 start_sector; - uint8 logicalHead[MAX_SPT]; - uint8 logicalCyl[MAX_SPT]; -} TRACK_INFO; - -typedef struct { - FILE *file; - uint32 ntracks; - uint8 nsides; - uint8 flags; - TRACK_INFO track[MAX_CYL][MAX_HEAD]; -} DISK_INFO; - -extern DISK_INFO *diskOpen(FILE *fileref, uint32 isVerbose); -extern t_stat diskClose(DISK_INFO **myDisk); -extern t_stat diskCreate(FILE *fileref, char *ctlr_comment); -extern uint32 imdGetSides(DISK_INFO *myDisk); -extern uint32 imdIsWriteLocked(DISK_INFO *myDisk); - -extern t_stat sectSeek(DISK_INFO *myDisk, uint32 Cyl, uint32 Head); -extern t_stat sectRead(DISK_INFO *myDisk, uint32 Cyl, uint32 Head, uint32 Sector, uint8 *buf, uint32 buflen, uint32 *flags, uint32 *readlen); -extern t_stat sectWrite(DISK_INFO *myDisk, uint32 Cyl, uint32 Head, uint32 Sector, uint8 *buf, uint32 buflen, uint32 *flags, uint32 *writelen); -extern t_stat trackWrite(DISK_INFO *myDisk, - uint32 Cyl, - uint32 Head, - uint32 numSectors, - uint32 sectorLen, - uint8 *sectorMap, - uint8 mode, - uint8 fillbyte, - uint32 *flags); -extern t_stat assignDiskType(UNIT *uptr); diff --git a/AltairZ80/vfdhd.c b/AltairZ80/vfdhd.c deleted file mode 100644 index a8879cb0..00000000 --- a/AltairZ80/vfdhd.c +++ /dev/null @@ -1,658 +0,0 @@ -/************************************************************************* - * * - * $Id: vfdhd.c 1995 2008-07-15 03:59:13Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Micropolis FDC module for SIMH * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/*#define DBG_MSG */ -#define USE_VGI /* Use 275-byte VGI-format sectors (includes all metadata) */ - -#include "altairz80_defs.h" - -#if defined (_WIN32) -#include -#endif - -#include "sim_imd.h" - -/* #define DBG_MSG */ - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define STATUS_MSG (1 << 5) -#define ORDERS_MSG (1 << 7) - -static void VFDHD_Command(void); - -#define VFDHD_MAX_DRIVES 4 - -#define VFDHD_SECTOR_LEN 275 -#define VFDHD_RAW_LEN (40 + VFDHD_SECTOR_LEN + 128) - -typedef union { - struct { - uint8 preamble[40]; /* Hard disk uses 30 bytes of preamble, floppy uses 40. */ - uint8 sync; - uint8 header[2]; - uint8 unused[10]; - uint8 data[256]; - uint8 checksum; - uint8 ecc[4]; - uint8 ecc_valid; /* 0xAA indicates ECC is being used. */ - uint8 postamble[128]; - } u; - uint8 raw[VFDHD_RAW_LEN]; - -} SECTOR_FORMAT; - -typedef struct { - UNIT *uptr; - DISK_INFO *imd; - uint16 ntracks; /* number of tracks */ - uint8 nheads; /* number of heads */ - uint8 nspt; /* number of sectors per track */ - uint8 npre_len; /* preamble length */ - uint32 sectsize; /* sector size, not including pre/postamble */ - uint16 track; - uint8 wp; /* Disk write protected */ - uint8 ready; /* Drive is ready */ - uint8 write_fault; - uint8 seek_complete; - uint8 sync_lost; - uint32 sector_wait_count; -} VFDHD_DRIVE_INFO; - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint8 xfr_flag; /* Indicates controller is ready to send/receive data */ - uint8 sel_drive; /* Currently selected drive */ - uint8 selected; /* 1 if drive is selected */ - uint8 track0; /* Set it selected drive is on track 0 */ - uint8 head; /* Currently selected head */ - uint8 wr_latch; /* Write enable latch */ - uint8 int_enable; /* Interrupt Enable */ - uint32 datacount; /* Number of data bytes transferred from controller for current sector */ - uint8 step; - uint8 direction; - uint8 rwc; - uint8 sector; - uint8 read; - uint8 ecc_enable; - uint8 precomp; - uint8 floppy_sel; - uint8 controller_busy; - uint8 motor_on; - uint8 hdsk_type; - VFDHD_DRIVE_INFO drive[VFDHD_MAX_DRIVES]; -} VFDHD_INFO; - -static VFDHD_INFO vfdhd_info_data = { { 0x0, 0, 0xC0, 4 } }; -static VFDHD_INFO *vfdhd_info = &vfdhd_info_data; - -static SECTOR_FORMAT sdata; -extern uint32 PCX; -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); - -#define UNIT_V_VFDHD_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_VFDHD_WLK (1 << UNIT_V_VFDHD_WLK) -#define UNIT_V_VFDHD_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_VFDHD_VERBOSE (1 << UNIT_V_VFDHD_VERBOSE) -#define VFDHD_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ - -static t_stat vfdhd_reset(DEVICE *vfdhd_dev); -static t_stat vfdhd_attach(UNIT *uptr, char *cptr); -static t_stat vfdhd_detach(UNIT *uptr); - -static int32 vfdhddev(const int32 port, const int32 io, const int32 data); - -static uint8 VFDHD_Read(const uint32 Addr); -static uint8 VFDHD_Write(const uint32 Addr, uint8 cData); - -static int32 hdSize = 5; - -static UNIT vfdhd_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, VFDHD_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, VFDHD_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, VFDHD_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, VFDHD_CAPACITY) } -}; - -static REG vfdhd_reg[] = { - { DRDATA (HDSIZE, hdSize, 10), }, - { NULL } -}; - -static MTAB vfdhd_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_VFDHD_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_VFDHD_WLK, UNIT_VFDHD_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_VFDHD_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_VFDHD_VERBOSE, UNIT_VFDHD_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB vfdhd_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "CMD", CMD_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "STATUS", STATUS_MSG }, - { "ORDERS", ORDERS_MSG }, - { NULL, 0 } -}; - -DEVICE vfdhd_dev = { - "VFDHD", vfdhd_unit, vfdhd_reg, vfdhd_mod, - VFDHD_MAX_DRIVES, 10, 31, 1, VFDHD_MAX_DRIVES, VFDHD_MAX_DRIVES, - NULL, NULL, &vfdhd_reset, - NULL, &vfdhd_attach, &vfdhd_detach, - &vfdhd_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - vfdhd_dt, NULL, "Vector Graphic FD-HD Controller VFDHD" -}; - -/* Reset routine */ -static t_stat vfdhd_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &vfdhddev, TRUE); - } else { - /* Connect MFDC at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &vfdhddev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - return SCPE_OK; -} - - -/* Attach routine */ -static t_stat vfdhd_attach(UNIT *uptr, char *cptr) -{ - t_stat r; - unsigned int i = 0; - - r = attach_unit(uptr, cptr); /* attach unit */ - if ( r != SCPE_OK) /* error? */ - return r; - - /* Determine length of this disk */ - uptr->capac = sim_fsize(uptr->fileref); - - for(i = 0; i < VFDHD_MAX_DRIVES; i++) { - vfdhd_info->drive[i].uptr = &vfdhd_dev.units[i]; - } - - for(i = 0; i < VFDHD_MAX_DRIVES; i++) { - if(vfdhd_dev.units[i].fileref == uptr->fileref) { - break; - } - } - - if(uptr->capac > 0) { - r = assignDiskType(uptr); - if (r != SCPE_OK) { - vfdhd_detach(uptr); - return r; - } - } else { - /* creating file, must be DSK format. */ - uptr->u3 = IMAGE_TYPE_DSK; - } - - if (uptr->flags & UNIT_VFDHD_VERBOSE) - printf("VFDHD%d: attached to '%s', type=%s, len=%d\n", i, cptr, - uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", - uptr->capac); - - if(uptr->u3 == IMAGE_TYPE_IMD) { - if(uptr->capac < 318000) { - printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n"); - vfdhd_detach(uptr); - return SCPE_OPENERR; - } - - if (uptr->flags & UNIT_VFDHD_VERBOSE) - printf("--------------------------------------------------------\n"); - vfdhd_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_VFDHD_VERBOSE)); - if (uptr->flags & UNIT_VFDHD_VERBOSE) - printf("\n"); - } else { - vfdhd_info->drive[i].imd = NULL; - } - - if(i>0) { /* Floppy Disk, Unit 1-3 */ - vfdhd_info->drive[i].ntracks = 77; /* number of tracks */ - vfdhd_info->drive[i].nheads = 2; /* number of heads */ - vfdhd_info->drive[i].nspt = 16; /* number of sectors per track */ - vfdhd_info->drive[i].npre_len = 40; /* preamble length */ - vfdhd_info->drive[i].sectsize = VFDHD_SECTOR_LEN; /* sector size, not including pre/postamble */ - } else { /* Hard Disk, Unit 0 */ - if(hdSize == 10) { - vfdhd_info->drive[i].ntracks = 153; /* number of tracks */ - vfdhd_info->drive[i].nheads = 6; /* number of heads */ - vfdhd_info->hdsk_type = 1; - printf("10MB\n"); - } else if (hdSize == 5) { - vfdhd_info->drive[i].ntracks = 153; /* number of tracks */ - vfdhd_info->drive[i].nheads = 4; /* number of heads */ - vfdhd_info->hdsk_type = 0; - printf("5MB\n"); - } else { - vfdhd_info->drive[i].ntracks = 512; /* number of tracks */ - vfdhd_info->drive[i].nheads = 8; /* number of heads */ - vfdhd_info->hdsk_type = 1; - printf("32MB\n"); - } - - vfdhd_info->drive[i].nheads = 4; /* number of heads */ - vfdhd_info->drive[i].nspt = 32; /* number of sectors per track */ - vfdhd_info->drive[i].npre_len = 30; /* preamble length */ - vfdhd_info->drive[i].sectsize = VFDHD_SECTOR_LEN; /* sector size, not including pre/postamble */ - vfdhd_info->drive[i].ready = 1; - vfdhd_info->drive[i].seek_complete = 1; - vfdhd_info->drive[i].sync_lost = 1; /* Active LOW */ - } - - vfdhd_info->motor_on = 1; - return SCPE_OK; -} - - -/* Detach routine */ -static t_stat vfdhd_detach(UNIT *uptr) -{ - t_stat r; - int8 i; - - for(i = 0; i < VFDHD_MAX_DRIVES; i++) { - if(vfdhd_dev.units[i].fileref == uptr->fileref) { - break; - } - } - - DBG_PRINT(("Detach VFDHD%d\n", i)); - r = diskClose(&vfdhd_info->drive[i].imd); - if (r != SCPE_OK) - return r; - - r = detach_unit(uptr); /* detach unit */ - if (r != SCPE_OK) - return r; - - return SCPE_OK; -} - - -static uint8 cy; -static uint8 adc(uint8 sum, uint8 a1) -{ - uint32 total; - - total = sum + a1 + cy; - - if(total > 0xFF) { - cy = 1; - } else { - cy = 0; - } - - return(total & 0xFF); -} - -static int32 vfdhddev(const int32 port, const int32 io, const int32 data) -{ - DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " IO %s, Port %02x" NLP, PCX, io ? "WR" : "RD", port)); - if(io) { - VFDHD_Write(port, data); - return 0; - } else { - return(VFDHD_Read(port)); - } -} - -#define FDHD_CTRL_STATUS0 0 /* R=Status Port 0, W=Control Port 0 */ -#define FDHD_CTRL_STATUS1 1 /* R=Status Port 1, W=Control Port 0 */ -#define FDHD_DATA 2 /* R/W=Data Port */ -#define FDHD_RESET_START 3 /* R=RESET, W=START */ - -static uint8 VFDHD_Read(const uint32 Addr) -{ - uint8 cData; - VFDHD_DRIVE_INFO *pDrive; - - pDrive = &vfdhd_info->drive[vfdhd_info->sel_drive]; - - cData = 0x00; - - switch(Addr & 0x3) { - case FDHD_CTRL_STATUS0: - cData = (pDrive->wp & 1); /* [0] Write Protect (FD) */ - cData |= (pDrive->ready & 1) << 1; /* [1] Drive ready (HD) */ - cData |= (pDrive->track == 0) ? 0x04 : 0; /* [2] TK0 (FD/HD) */ - cData |= (pDrive->write_fault & 1) << 3; /* [3] Write Fault (HD) */ - cData |= (pDrive->seek_complete & 1) << 4; /* [4] Seek Complete (HD) */ - cData |= (pDrive->sync_lost & 1) << 5; /* [5] Loss of Sync (HD) */ - cData |= 0xC0; /* [7:6] Reserved (pulled up) */ - sim_debug(STATUS_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " RD S0 = 0x%02x\n", PCX, cData); - break; - case FDHD_CTRL_STATUS1: - vfdhd_info->floppy_sel = (vfdhd_info->sel_drive == 0) ? 0 : 1; - cData = (vfdhd_info->floppy_sel & 0x1); /* [0] Floppy Selected */ - cData |= (vfdhd_info->controller_busy & 0x1) << 1; /* [1] Controller busy */ - cData |= (vfdhd_info->motor_on & 0x1) << 2; /* [2] Motor On (FD) */ - cData |= (vfdhd_info->hdsk_type & 0x1) << 3; /* [3] Hard Disk Type (0=5MB, 1=10MB) */ - cData |= 0xF0; /* [7:4] Reserved (pulled up) */ - if(vfdhd_info->sel_drive == 0) { -/* cData &= 0xF0; */ - } - - vfdhd_info->controller_busy = 0; - - sim_debug(STATUS_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " RD S1 = 0x%02x\n", PCX, cData); - break; - case FDHD_DATA: -/* DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " RD Data" NLP, PCX)); */ - if(vfdhd_info->datacount+40 >= VFDHD_RAW_LEN) { - sim_debug(ERROR_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " Illegal data count %d.\n", PCX, vfdhd_info->datacount); - vfdhd_info->datacount = 0; - } - cData = sdata.raw[vfdhd_info->datacount+40]; - - vfdhd_info->datacount++; - -/* DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " RD Data Sector %d[%03d]: 0x%02x" NLP, PCX, pDrive->sector, vfdhd_info->datacount, cData)); */ - break; - case FDHD_RESET_START: /* Reset */ - sim_debug(CMD_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " Reset\n", PCX); - vfdhd_info->datacount = 0; - cData = 0xFF; /* Return High-Z data */ - break; - } - - return (cData); -} - -static uint8 VFDHD_Write(const uint32 Addr, uint8 cData) -{ - VFDHD_DRIVE_INFO *pDrive; - - pDrive = &vfdhd_info->drive[vfdhd_info->sel_drive]; - - switch(Addr & 0x3) { - case FDHD_CTRL_STATUS0: - vfdhd_info->sel_drive = cData & 0x03; - vfdhd_info->head = (cData >> 2) & 0x7; - vfdhd_info->step = (cData >> 5) & 1; - vfdhd_info->direction = (cData >> 6) & 1; - vfdhd_info->rwc = (cData >> 7) & 1; - - sim_debug(WR_DATA_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " WR C0=%02x: sel_drive=%d, head=%d, step=%d, dir=%d, rwc=%d\n", PCX, cData, vfdhd_info->sel_drive, vfdhd_info->head, vfdhd_info->step, vfdhd_info->direction, vfdhd_info->rwc); - - if(vfdhd_info->step == 1) { - if(vfdhd_info->direction == 1) { /* Step IN */ - pDrive->track++; - } else { /* Step OUT */ - if(pDrive->track != 0) { - pDrive->track--; - } - } - sim_debug(SEEK_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " Drive %d on track %d\n", PCX, vfdhd_info->sel_drive, pDrive->track); - } - - break; - case FDHD_CTRL_STATUS1: - vfdhd_info->sector = (cData & 0x1f); - vfdhd_info->read = (cData >> 5) & 1; - vfdhd_info->ecc_enable = (cData >> 6) & 1; - vfdhd_info->precomp = (cData >> 7) & 1; - if(cData == 0xFF) { - sim_debug(SEEK_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " Home Disk %d\n", PCX, vfdhd_info->sel_drive); - pDrive->track = 0; - } - DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " WR C1=%02x: sector=%d, read=%d, ecc_en=%d, precomp=%d" NLP, - PCX, - cData, - vfdhd_info->sector, - vfdhd_info->read, - vfdhd_info->ecc_enable, - vfdhd_info->precomp)); - break; - case FDHD_DATA: /* Data Port */ - DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " WR Data" NLP, PCX)); -#ifdef USE_VGI - if(vfdhd_info->sel_drive > 0) { /* Floppy */ - if(vfdhd_info->datacount >= VFDHD_RAW_LEN) { - sim_debug(ERROR_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " Illegal data count %d.\n", PCX, vfdhd_info->datacount); - vfdhd_info->datacount = 0; - } - sdata.raw[vfdhd_info->datacount] = cData; - } else { /* Hard */ - if(vfdhd_info->datacount+10 >= VFDHD_RAW_LEN) { - sim_debug(ERROR_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " Illegal data count %d.\n", PCX, vfdhd_info->datacount); - vfdhd_info->datacount = 0; - } - sdata.raw[vfdhd_info->datacount+10] = cData; - } -#else - if((vfdhd_info->datacount-13 >= VFDHD_RAW_LEN) || (vfdhd_info->datacount < 13)) { - sim_debug(ERROR_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " Illegal data count %d.\n", PCX, vfdhd_info->datacount); - vfdhd_info->datacount = 13; - } - sdata.u.data[vfdhd_info->datacount-13] = cData; -#endif /* USE_VGI */ - - vfdhd_info->datacount ++; - - break; - case FDHD_RESET_START: - sim_debug(CMD_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " Start Command\n", PCX); - VFDHD_Command(); - break; - } - - cData = 0x00; - - return (cData); -} - -static void VFDHD_Command(void) -{ - VFDHD_DRIVE_INFO *pDrive; - - uint32 bytesPerTrack; - uint32 bytesPerHead; - - uint32 sec_offset; - uint32 flags; - int32 rtn; - - pDrive = &(vfdhd_info->drive[vfdhd_info->sel_drive]); - - bytesPerTrack = pDrive->sectsize * pDrive->nspt; - bytesPerHead = bytesPerTrack * pDrive->ntracks; - - sec_offset = (pDrive->track * bytesPerTrack) + \ - (vfdhd_info->head * bytesPerHead) + \ - (vfdhd_info->sector * pDrive->sectsize); - - vfdhd_info->controller_busy = 1; - - if(vfdhd_info->read == 1) { /* Perform a Read operation */ - unsigned int i, checksum; - uint32 readlen; - - sim_debug(RD_DATA_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " RD: Drive=%d, Track=%d, Head=%d, Sector=%d\n", PCX, vfdhd_info->sel_drive, pDrive->track, vfdhd_info->head, vfdhd_info->sector); - - /* Clear out unused portion of sector. */ - memset(&sdata.u.unused[0], 0x00, 10); - - sdata.u.sync = 0xFF; - sdata.u.header[0] = pDrive->track & 0xFF; - sdata.u.header[1] = vfdhd_info->sector; - - switch((pDrive->uptr)->u3) - { - case IMAGE_TYPE_IMD: - if(pDrive->imd == NULL) { - printf(".imd is NULL!" NLP); - } - printf("%s: Read: imd=%p" NLP, __FUNCTION__, pDrive->imd); - sectRead(pDrive->imd, - pDrive->track, - vfdhd_info->head, - vfdhd_info->sector, - sdata.u.data, - 256, - &flags, - &readlen); - - adc(0,0); /* clear Carry bit */ - checksum = 0; - - /* Checksum everything except the sync byte */ - for(i=1;i<269;i++) { - checksum = adc(checksum, sdata.raw[i+40]); - } - - sdata.u.checksum = checksum & 0xFF; - sdata.u.ecc_valid = 0xAA; - break; - case IMAGE_TYPE_DSK: - if(pDrive->uptr->fileref == NULL) { - printf(".fileref is NULL!" NLP); - } else { - sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); - rtn = sim_fread(&sdata.u.sync, 1, 274, /*VFDHD_SECTOR_LEN,*/ (pDrive->uptr)->fileref); - if (rtn != 274) { - sim_debug(ERROR_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " READ: sim_fread error.\n", PCX); - } - - memset(&sdata.u.preamble, 0, 40); - memset(&sdata.u.ecc, 0, 5); /* Clear out the ECC and ECC Valid bytes */ - sdata.u.ecc_valid = 0xAA; - for(vfdhd_info->datacount = 0; sdata.raw[vfdhd_info->datacount] == 0x00; vfdhd_info->datacount++) { - } - - DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " READ: Sync found at offset %d" NLP, PCX, vfdhd_info->datacount)); - - } - break; - case IMAGE_TYPE_CPT: - printf("%s: CPT Format not supported" NLP, __FUNCTION__); - break; - default: - printf("%s: Unknown image Format" NLP, __FUNCTION__); - break; - } - - } else { /* Perform a Write operation */ - uint32 writelen; - - sim_debug(WR_DATA_MSG, &vfdhd_dev, "VFDHD: " ADDRESS_FORMAT " WR: Drive=%d, Track=%d, Head=%d, Sector=%d\n", PCX, vfdhd_info->sel_drive, pDrive->track, vfdhd_info->head, vfdhd_info->sector); - -#ifdef USE_VGI -#else - int data_index = vfdhd_info->datacount - 13; - - sec_offset = (pDrive->track * 4096) + \ - (vfdhd_info->head * 315392) + \ - (vfdhd_info->sector * 256); -#endif /* USE_VGI */ - - switch((pDrive->uptr)->u3) - { - case IMAGE_TYPE_IMD: - if(pDrive->imd == NULL) { - printf(".imd is NULL!" NLP); - } - sectWrite(pDrive->imd, - pDrive->track, - vfdhd_info->head, - vfdhd_info->sector, - sdata.u.data, - 256, - &flags, - &writelen); - break; - case IMAGE_TYPE_DSK: - if(pDrive->uptr->fileref == NULL) { - printf(".fileref is NULL!" NLP); - } else { - DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " WR drive=%d, track=%d, head=%d, sector=%d" NLP, - PCX, - vfdhd_info->sel_drive, - pDrive->track, - vfdhd_info->head, - vfdhd_info->sector)); - sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); -#ifdef USE_VGI - sim_fwrite(&sdata.u.sync, 1, VFDHD_SECTOR_LEN, (pDrive->uptr)->fileref); -#else - sim_fwrite(sdata.u.data, 1, 256, (pDrive->uptr)->fileref); -#endif /* USE_VGI */ - } - break; - case IMAGE_TYPE_CPT: - printf("%s: CPT Format not supported" NLP, __FUNCTION__); - break; - default: - printf("%s: Unknown image Format" NLP, __FUNCTION__); - break; - } - } -} diff --git a/AltairZ80/vfdhd.h b/AltairZ80/vfdhd.h deleted file mode 100644 index 7b5052c2..00000000 --- a/AltairZ80/vfdhd.h +++ /dev/null @@ -1,43 +0,0 @@ -/************************************************************************* - * * - * $Id: vfdhd.h 1694 2007-12-14 05:23:11Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Micropolis FDC module for SIMH definitions * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -extern int32 mfdhd_dev(const int32 port, const int32 io, const int32 data); - diff --git a/AltairZ80/wd179x.c b/AltairZ80/wd179x.c deleted file mode 100644 index 589877df..00000000 --- a/AltairZ80/wd179x.c +++ /dev/null @@ -1,1138 +0,0 @@ -/************************************************************************* - * * - * $Id: wd179x.c 1999 2008-07-22 04:25:28Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Generic WD179X Disk Controller module for SIMH. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -/*#define DBG_MSG */ - -#include "altairz80_defs.h" -#include - -#if defined (_WIN32) -#include -#endif - -#include "sim_imd.h" -#include "wd179x.h" - -#ifdef DBG_MSG -#define DBG_PRINT(args) printf args -#else -#define DBG_PRINT(args) -#endif - -#define CROMFDC_SIM_100US 291 /* Number of "ticks" in 100uS, where does this come from? */ -#define CROMFDC_8IN_ROT (167 * CROMFDC_SIM_100US) -#define CROMFDC_5IN_ROT (200 * CROMFDC_SIM_100US) - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define CMD_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define STATUS_MSG (1 << 5) -#define FMT_MSG (1 << 6) -#define VERBOSE_MSG (1 << 7) - -#define WD179X_MAX_DRIVES 4 -#define WD179X_SECTOR_LEN 8192 -/* 2^(7 + WD179X_MAX_SEC_LEN) == WD179X_SECTOR_LEN */ -#define WD179X_MAX_SEC_LEN 6 -#define WD179X_MAX_SECTOR 26 - -#define CMD_PHASE 0 -#define EXEC_PHASE 1 -#define DATA_PHASE 2 - -/* Status Bits for Type I Commands */ -#define WD179X_STAT_NOT_READY (1 << 7) -#define WD179X_STAT_WPROT (1 << 6) -#define WD179X_STAT_HLD (1 << 5) -#define WD179X_STAT_SEEK_ERROR (1 << 4) -#define WD179X_STAT_CRC_ERROR (1 << 3) -#define WD179X_STAT_TRACK0 (1 << 2) -#define WD179X_STAT_INDEX (1 << 1) -#define WD179X_STAT_BUSY (1 << 0) - -/* Status Bits for Type II, III Commands */ -/*#define WD179X_STAT_NOT_READY (1 << 7) */ -/*#define WD179X_STAT_WPROT (1 << 6) */ -#define WD179X_STAT_REC_TYPE (1 << 5) /* Also Write Fault */ -#define WD179X_STAT_NOT_FOUND (1 << 4) -/*#define WD179X_STAT_CRC_ERROR (1 << 3) */ -#define WD179X_STAT_LOST_DATA (1 << 2) -#define WD179X_STAT_DRQ (1 << 1) -/*#define WD179X_STAT_BUSY (1 << 0) */ - -typedef union { - uint8 raw[WD179X_SECTOR_LEN]; -} SECTOR_FORMAT; - -typedef struct { - UNIT *uptr; - DISK_INFO *imd; - uint8 ntracks; /* number of tracks */ - uint8 nheads; /* number of heads */ - uint32 sectsize; /* sector size, not including pre/postamble */ - uint8 track; /* Current Track */ - uint8 ready; /* Is drive ready? */ -} WD179X_DRIVE_INFO; - -typedef struct { - PNP_INFO pnp; /* Plug-n-Play Information */ - uint8 intrq; /* WD179X Interrupt Request Output (EOJ) */ - uint8 hld; /* WD179X Head Load Output */ - uint8 drq; /* WD179X DMA Request Output */ - uint8 ddens; /* WD179X Double-Density Input */ - uint8 fdc_head; /* H Head Number */ - uint8 sel_drive; /* Currently selected drive */ - uint8 drivetype; /* 8 or 5 depending on disk type. */ - uint8 fdc_status; /* WD179X Status Register */ - uint8 verify; /* WD179X Type 1 command Verify flag */ - uint8 fdc_data; /* WD179X Data Register */ - uint8 fdc_read; /* TRUE when reading */ - uint8 fdc_write; /* TRUE when writing */ - uint8 fdc_write_track; /* TRUE when writing an entire track */ - uint8 fdc_fmt_state; /* Format track statemachine state */ - uint8 fdc_gap[4]; /* Gap I - Gap IV lengths */ - uint8 fdc_fmt_sector_count; /* sector count for format track */ - uint8 fdc_sectormap[WD179X_MAX_SECTOR]; /* Physical to logical sector map */ - uint8 fdc_header_index; /* Index into header */ - uint8 fdc_read_addr; /* TRUE when READ ADDRESS command is in progress */ - uint8 fdc_multiple; /* TRUE for multi-sector read/write */ - uint16 fdc_datacount; /* Read or Write data remaining transfer length */ - uint16 fdc_dataindex; /* index of current byte in sector data */ - uint8 index_pulse_wait; /* TRUE if waiting for interrupt on next index pulse. */ - uint8 fdc_sector; /* R Record (Sector) */ - uint8 fdc_sec_len; /* N Sector Length */ - int8 step_dir; - uint8 cmdtype; /* Type of current/former command */ - WD179X_DRIVE_INFO drive[WD179X_MAX_DRIVES]; -} WD179X_INFO; - -static SECTOR_FORMAT sdata; -extern uint32 PCX; -extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), uint8 unmap); -extern int32 find_unit_index (UNIT *uptr); - -t_stat wd179x_svc (UNIT *uptr); - -/* These are needed for DMA. PIO Mode has not been implemented yet. */ -extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); -extern uint8 GetBYTEWrapper(const uint32 Addr); - -#define UNIT_V_WD179X_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_WD179X_WLK (1 << UNIT_V_WD179X_WLK) -#define UNIT_V_WD179X_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_WD179X_VERBOSE (1 << UNIT_V_WD179X_VERBOSE) -#define WD179X_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ -#define WD179X_CAPACITY_SSSD (77*1*26*128) /* Single-sided Single Density IBM Diskette1 */ - -/* Write Track (format) Statemachine states */ -#define FMT_GAP1 1 -#define FMT_GAP2 2 -#define FMT_GAP3 3 -#define FMT_GAP4 4 -#define FMT_HEADER 5 -#define FMT_DATA 6 - -/* WD179X Commands */ -#define WD179X_RESTORE 0x00 /* Type I */ -#define WD179X_SEEK 0x10 /* Type I */ -#define WD179X_STEP 0x20 /* Type I */ -#define WD179X_STEP_U 0x30 /* Type I */ -#define WD179X_STEP_IN 0x40 /* Type I */ -#define WD179X_STEP_IN_U 0x50 /* Type I */ -#define WD179X_STEP_OUT 0x60 /* Type I */ -#define WD179X_STEP_OUT_U 0x70 /* Type I */ -#define WD179X_READ_REC 0x80 /* Type II */ -#define WD179X_READ_RECS 0x90 /* Type II */ -#define WD179X_WRITE_REC 0xA0 /* Type II */ -#define WD179X_WRITE_RECS 0xB0 /* Type II */ -#define WD179X_READ_ADDR 0xC0 /* Type III */ -#define WD179X_FORCE_INTR 0xD0 /* Type IV */ -#define WD179X_READ_TRACK 0xE0 /* Type III */ -#define WD179X_WRITE_TRACK 0xF0 /* Type III */ - -static int32 wd179xdev(const int32 port, const int32 io, const int32 data); -static t_stat wd179x_reset(DEVICE *dptr); -uint8 floorlog2(unsigned int n); - -WD179X_INFO wd179x_info_data = { { 0x0, 0, 0x30, 4 } }; -WD179X_INFO *wd179x_info = &wd179x_info_data; -WD179X_INFO_PUB *wd179x_infop = (WD179X_INFO_PUB *)&wd179x_info_data; - -static UNIT wd179x_unit[] = { - { UDATA (&wd179x_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, WD179X_CAPACITY), 58200 }, - { UDATA (&wd179x_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, WD179X_CAPACITY), 58200 }, - { UDATA (&wd179x_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, WD179X_CAPACITY), 58200 }, - { UDATA (&wd179x_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, WD179X_CAPACITY), 58200 } -}; - -static MTAB wd179x_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, - { UNIT_WD179X_WLK, 0, "WRTENB", "WRTENB", NULL }, - { UNIT_WD179X_WLK, UNIT_WD179X_WLK, "WRTLCK", "WRTLCK", NULL }, - /* quiet, no warning messages */ - { UNIT_WD179X_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_WD179X_VERBOSE, UNIT_WD179X_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB wd179x_dt[] = { - { "ERROR", ERROR_MSG }, - { "SEEK", SEEK_MSG }, - { "CMD", CMD_MSG }, - { "RDDATA", RD_DATA_MSG }, - { "WRDATA", WR_DATA_MSG }, - { "STATUS", STATUS_MSG }, - { "FMT", FMT_MSG }, - { "VERBOSE",VERBOSE_MSG }, - { NULL, 0 } -}; - -DEVICE wd179x_dev = { - "WD179X", wd179x_unit, NULL, wd179x_mod, - WD179X_MAX_DRIVES, 10, 31, 1, WD179X_MAX_DRIVES, WD179X_MAX_DRIVES, - NULL, NULL, &wd179x_reset, - NULL, &wd179x_attach, &wd179x_detach, - &wd179x_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - wd179x_dt, NULL, "Western Digital FDC Core WD179X" -}; - -/* Unit service routine */ -/* Used to generate INDEX pulses in response to a FORCE_INTR command */ -t_stat wd179x_svc (UNIT *uptr) -{ - - if(wd179x_info->index_pulse_wait == TRUE) { - wd179x_info->index_pulse_wait = FALSE; - wd179x_info->intrq = 1; - } - - return SCPE_OK; -} - - -/* Reset routine */ -static t_stat wd179x_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &wd179xdev, TRUE); - } else { - /* Connect I/O Ports at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &wd179xdev, FALSE) != 0) { - printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - return SCPE_OK; -} - -void wd179x_external_restore(void) -{ - WD179X_DRIVE_INFO *pDrive; - - if(wd179x_info->sel_drive >= WD179X_MAX_DRIVES) { - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " Illegal drive selected, cannot restore.\n", PCX); - return; - } - - pDrive = &wd179x_info->drive[wd179x_info->sel_drive]; - - if(pDrive->uptr == NULL) { - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " No drive selected, cannot restore.\n", PCX); - return; - } - - sim_debug(SEEK_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " External Restore drive to track 0\n", wd179x_info->sel_drive, PCX); - - pDrive->track = 0; - -} - -/* Attach routine */ -t_stat wd179x_attach(UNIT *uptr, char *cptr) -{ - char header[4]; - t_stat r; - int32 i = 0; - - r = attach_unit(uptr, cptr); /* attach unit */ - if ( r != SCPE_OK) /* error? */ - return r; - - /* Determine length of this disk */ - uptr->capac = sim_fsize(uptr->fileref); - - i = find_unit_index(uptr); - - if (i == -1) { - return (SCPE_IERR); - } - - DBG_PRINT(("Attach WD179X%d\n", i)); - wd179x_info->drive[i].uptr = uptr; - - /* Default to drive not ready */ - wd179x_info->drive[i].ready = 0; - - if(uptr->capac > 0) { - char *rtn = fgets(header, 4, uptr->fileref); - if ((rtn != NULL) && strncmp(header, "IMD", 3)) { - printf("WD179X: Only IMD disk images are supported\n"); - wd179x_info->drive[i].uptr = NULL; - return SCPE_OPENERR; - } - } else { - /* create a disk image file in IMD format. */ - if (diskCreate(uptr->fileref, "$Id: wd179x.c 1999 2008-07-22 04:25:28Z hharte $") != SCPE_OK) { - printf("WD179X: Failed to create IMD disk.\n"); - wd179x_info->drive[i].uptr = NULL; - return SCPE_OPENERR; - } - uptr->capac = sim_fsize(uptr->fileref); - } - - uptr->u3 = IMAGE_TYPE_IMD; - - if (uptr->flags & UNIT_WD179X_VERBOSE) - printf("WD179X%d: attached to '%s', type=%s, len=%d\n", i, cptr, - uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", - uptr->capac); - - if(uptr->u3 == IMAGE_TYPE_IMD) { - if (uptr->flags & UNIT_WD179X_VERBOSE) - printf("--------------------------------------------------------\n"); - wd179x_info->drive[i].imd = diskOpen(uptr->fileref, uptr->flags & UNIT_WD179X_VERBOSE); - if (uptr->flags & UNIT_WD179X_VERBOSE) - printf("\n"); - if (wd179x_info->drive[i].imd == NULL) { - printf("WD179X: IMD disk corrupt.\n"); - wd179x_info->drive[i].uptr = NULL; - return SCPE_OPENERR; - } - - /* Write-protect the unit if IMD think's it's writelocked. */ - if(imdIsWriteLocked(wd179x_info->drive[i].imd)) { - uptr->flags |= UNIT_WD179X_WLK; - } - - wd179x_info->drive[i].ready = 1; - } else { - wd179x_info->drive[i].imd = NULL; - } - - wd179x_info->fdc_sec_len = 0; /* 128 byte sectors, fixme */ - wd179x_info->sel_drive = 0; - - return SCPE_OK; -} - - -/* Detach routine */ -t_stat wd179x_detach(UNIT *uptr) -{ - t_stat r; - int8 i; - - i = find_unit_index(uptr); - - if (i == -1) { - return SCPE_IERR; - } - - DBG_PRINT(("Detach WD179X%d\n", i)); - r = diskClose(&wd179x_info->drive[i].imd); - wd179x_info->drive[i].ready = 0; - if (r != SCPE_OK) - return r; - - r = detach_unit(uptr); /* detach unit */ - if (r != SCPE_OK) - return r; - - return SCPE_OK; -} - - -static int32 wd179xdev(const int32 port, const int32 io, const int32 data) -{ - DBG_PRINT(("WD179X: " ADDRESS_FORMAT " %s, Port 0x%02x Data 0x%02x" NLP, - PCX, io ? "OUT" : " IN", port, data)); - if(io) { - WD179X_Write(port, data); - return 0; - } else { - return(WD179X_Read(port)); - } -} - -uint8 floorlog2(unsigned int n) -{ - /* Compute log2(n) */ - uint8 r = 0; - if (n >= 1<<16) { - n >>=16; - r += 16; - } - if (n >= 1<< 8) { - n >>= 8; - r += 8; - } - if (n >= 1<< 4) { - n >>= 4; - r += 4; - } - if (n >= 1<< 2) { - n >>= 2; - r += 2; - } - if (n >= 1<< 1) { - r += 1; - } - return ((n == 0) ? (0xFF) : r); /* 0xFF is error return value */ -} - -uint8 WD179X_Read(const uint32 Addr) -{ - uint8 cData; - WD179X_DRIVE_INFO *pDrive; - uint32 flags = 0; - uint32 readlen; - int status; - - if(wd179x_info->sel_drive >= WD179X_MAX_DRIVES) { - return 0xFF; - } - - pDrive = &wd179x_info->drive[wd179x_info->sel_drive]; - - if(pDrive->uptr == NULL) { - return 0xFF; - } - - cData = 0x00; - - switch(Addr & 0x3) { - case WD179X_STATUS: - /* Fix up status based on Command Type */ - if((wd179x_info->cmdtype == 1) || (wd179x_info->cmdtype == 4)) { - wd179x_info->fdc_status ^= WD179X_STAT_INDEX; /* Generate Index pulses */ - wd179x_info->fdc_status &= ~WD179X_STAT_TRACK0; - wd179x_info->fdc_status |= (pDrive->track == 0) ? WD179X_STAT_TRACK0 : 0; - } else if(wd179x_info->cmdtype == 4) { - } - else { - wd179x_info->fdc_status &= ~WD179X_STAT_INDEX; /* Mask index pulses */ - wd179x_info->fdc_status |= (wd179x_info->drq) ? WD179X_STAT_DRQ : 0; - } - cData = (pDrive->ready == 0) ? WD179X_STAT_NOT_READY : 0; - cData |= wd179x_info->fdc_status; /* Status Register */ - sim_debug(STATUS_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " RD STATUS = 0x%02x\n", PCX, cData); - wd179x_info->intrq = 0; - break; - case WD179X_TRACK: - cData = pDrive->track; - sim_debug(STATUS_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " RD TRACK = 0x%02x\n", PCX, cData); - break; - case WD179X_SECTOR: - cData = wd179x_info->fdc_sector; - sim_debug(STATUS_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " RD SECT = 0x%02x\n", PCX, cData); - break; - case WD179X_DATA: - cData = 0xFF; /* Return High-Z data */ - if(wd179x_info->fdc_read == TRUE) { - if(wd179x_info->fdc_dataindex < wd179x_info->fdc_datacount) { - cData = sdata.raw[wd179x_info->fdc_dataindex]; - if(wd179x_info->fdc_read_addr == TRUE) { - sim_debug(STATUS_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " READ_ADDR[%d] = 0x%02x\n", - wd179x_info->sel_drive, PCX, - wd179x_info->fdc_dataindex, cData); - } - - wd179x_info->fdc_dataindex++; - if(wd179x_info->fdc_dataindex == wd179x_info->fdc_datacount) { - if(wd179x_info->fdc_multiple == FALSE) { - wd179x_info->fdc_status &= ~(WD179X_STAT_DRQ | WD179X_STAT_BUSY); /* Clear DRQ, BUSY */ - wd179x_info->drq = 0; - wd179x_info->intrq = 1; - wd179x_info->fdc_read = FALSE; - wd179x_info->fdc_read_addr = FALSE; - } else { - - /* Compute Sector Size */ - wd179x_info->fdc_sec_len = floorlog2( - pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].sectsize) - 7; - if(wd179x_info->fdc_sec_len > WD179X_MAX_SEC_LEN) { /* Error calculating N or N too large */ - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT " Invalid sector size!\n", wd179x_info->sel_drive, PCX); - wd179x_info->fdc_sec_len = 0; - return cData; - } - assert(wd179x_info->fdc_sec_len >= 0); // convince static analyzer that << is ok - wd179x_info->fdc_sector ++; - sim_debug(RD_DATA_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT " MULTI_READ_REC, T:%d/S:%d/N:%d, %s, len=%d\n", wd179x_info->sel_drive, PCX, pDrive->track, wd179x_info->fdc_head, wd179x_info->fdc_sector, wd179x_info->ddens ? "DD" : "SD", 128 << wd179x_info->fdc_sec_len); - - status = sectRead(pDrive->imd, - pDrive->track, - wd179x_info->fdc_head, - wd179x_info->fdc_sector, - sdata.raw, - 128 << wd179x_info->fdc_sec_len, - &flags, - &readlen); - - if(status == SCPE_OK) { - wd179x_info->fdc_status = (WD179X_STAT_DRQ | WD179X_STAT_BUSY); /* Set DRQ, BUSY */ - wd179x_info->drq = 1; - wd179x_info->intrq = 0; - wd179x_info->fdc_datacount = 128 << wd179x_info->fdc_sec_len; - wd179x_info->fdc_dataindex = 0; - wd179x_info->fdc_read = TRUE; - wd179x_info->fdc_read_addr = FALSE; - } else { - wd179x_info->fdc_status = 0; /* Clear DRQ, BUSY */ - wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; - wd179x_info->drq = 0; - wd179x_info->intrq = 1; - wd179x_info->fdc_read = FALSE; - wd179x_info->fdc_read_addr = FALSE; - } - } - } - } - } - break; - } - - return (cData); -} - -/* - * Command processing happens in three stages: - * 1. Flags and initial conditions are set up based on the Type of the command. - * 2. The execution phase takes place. - * 3. Status is updated based on the Type and outcome of the command execution. - * - * See the WD179x-02 Datasheet available on www.hartetechnologies.com/manuals/ - * - */ -static uint8 Do1793Command(uint8 cCommand) -{ - uint8 result = 0; - WD179X_DRIVE_INFO *pDrive; - uint32 flags = 0; - uint32 readlen; - int status; - - if(wd179x_info->sel_drive >= WD179X_MAX_DRIVES) { - return 0xFF; - } - - pDrive = &wd179x_info->drive[wd179x_info->sel_drive]; - - if(pDrive->uptr == NULL) { - return 0xFF; - } - - if(wd179x_info->fdc_status & WD179X_STAT_BUSY) { - if(((cCommand & 0xF0) != WD179X_FORCE_INTR)) { /* && ((cCommand & 0xF0) != WD179X_RESTORE)) { */ - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " ERROR: Command 0x%02x ignored because controller is BUSY\n\n", - wd179x_info->sel_drive, PCX, cCommand); - } - return 0xFF; - } - - wd179x_info->fdc_status &= ~WD179X_STAT_NOT_READY; - - /* Extract Type-specific command flags, and set initial conditions */ - switch(cCommand & 0xF0) { - /* Type I Commands */ - case WD179X_RESTORE: - case WD179X_SEEK: - case WD179X_STEP: - case WD179X_STEP_U: - case WD179X_STEP_IN: - case WD179X_STEP_IN_U: - case WD179X_STEP_OUT: - case WD179X_STEP_OUT_U: - wd179x_info->cmdtype = 1; - wd179x_info->fdc_status |= WD179X_STAT_BUSY; /* Set BUSY */ - wd179x_info->fdc_status &= ~(WD179X_STAT_CRC_ERROR | WD179X_STAT_SEEK_ERROR | WD179X_STAT_DRQ); - wd179x_info->intrq = 0; - wd179x_info->hld = cCommand & 0x08; - wd179x_info->verify = cCommand & 0x04; - break; - /* Type II Commands */ - case WD179X_READ_REC: - case WD179X_READ_RECS: - case WD179X_WRITE_REC: - case WD179X_WRITE_RECS: - wd179x_info->cmdtype = 2; - wd179x_info->fdc_status = WD179X_STAT_BUSY; /* Set BUSY, clear all others */ - wd179x_info->intrq = 0; - wd179x_info->hld = 1; /* Load the head immediately, E Flag not checked. */ - break; - /* Type III Commands */ - case WD179X_READ_ADDR: - case WD179X_READ_TRACK: - case WD179X_WRITE_TRACK: - wd179x_info->cmdtype = 3; - break; - /* Type IV Commands */ - case WD179X_FORCE_INTR: - wd179x_info->cmdtype = 4; - break; - default: - wd179x_info->cmdtype = 0; - break; - } - - switch(cCommand & 0xF0) { - /* Type I Commands */ - case WD179X_RESTORE: - sim_debug(CMD_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=RESTORE %s\n", wd179x_info->sel_drive, PCX, - wd179x_info->verify ? "[VERIFY]" : ""); - pDrive->track = 0; - wd179x_info->intrq = 1; - break; - case WD179X_SEEK: - sim_debug(SEEK_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=SEEK, track=%d, new=%d\n", wd179x_info->sel_drive, - PCX, pDrive->track, wd179x_info->fdc_data); - pDrive->track = wd179x_info->fdc_data; - break; - case WD179X_STEP: - sim_debug(SEEK_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=STEP\n", wd179x_info->sel_drive, PCX); - break; - case WD179X_STEP_U: - sim_debug(SEEK_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=STEP_U dir=%d\n", wd179x_info->sel_drive, - PCX, wd179x_info->step_dir); - if(wd179x_info->step_dir == 1) { - if (pDrive->track < 255) - pDrive->track++; - } else if (wd179x_info->step_dir == -1) { - if (pDrive->track > 0) - pDrive->track--; - } else { - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " ERROR: undefined direction for STEP\n", - wd179x_info->sel_drive, PCX); - } - break; - case WD179X_STEP_IN: - sim_debug(SEEK_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=STEP_IN\n", wd179x_info->sel_drive, PCX); - break; - case WD179X_STEP_IN_U: - if (pDrive->track < 255) - pDrive->track++; - wd179x_info->step_dir = 1; - sim_debug(SEEK_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=STEP_IN_U, Track=%d\n", wd179x_info->sel_drive, - PCX, pDrive->track); - break; - case WD179X_STEP_OUT: - sim_debug(SEEK_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=STEP_OUT\n", wd179x_info->sel_drive, PCX); - break; - case WD179X_STEP_OUT_U: - sim_debug(SEEK_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=STEP_OUT_U\n", wd179x_info->sel_drive, PCX); - if (pDrive->track > 0) - pDrive->track--; - wd179x_info->step_dir = -1; - break; - /* Type II Commands */ - case WD179X_READ_REC: - case WD179X_READ_RECS: - /* Compute Sector Size */ - wd179x_info->fdc_sec_len = floorlog2( - pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].sectsize) - 7; - if(wd179x_info->fdc_sec_len > WD179X_MAX_SEC_LEN) { /* Error calculating N or N too large */ - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " Invalid sector size!\n", wd179x_info->sel_drive, PCX); - wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; /* Sector not found */ - wd179x_info->fdc_status &= ~WD179X_STAT_BUSY; - wd179x_info->intrq = 1; - wd179x_info->drq = 0; - wd179x_info->fdc_sec_len = 0; - return 0xFF; - }; - assert(wd179x_info->fdc_sec_len >= 0); // convince static analyzer that << is ok - - wd179x_info->fdc_multiple = (cCommand & 0x10) ? TRUE : FALSE; - sim_debug(RD_DATA_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=READ_REC, T:%d/S:%d/N:%d, %s, %s len=%d\n", - wd179x_info->sel_drive, PCX, pDrive->track, - wd179x_info->fdc_head, wd179x_info->fdc_sector, - wd179x_info->fdc_multiple ? "Multiple" : "Single", - wd179x_info->ddens ? "DD" : "SD", 128 << wd179x_info->fdc_sec_len); - - if(IMD_MODE_MFM(pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].mode) != (wd179x_info->ddens)) { - wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; /* Sector not found */ - wd179x_info->fdc_status &= ~WD179X_STAT_BUSY; - wd179x_info->intrq = 1; - wd179x_info->drq = 0; - } else { - - status = sectRead(pDrive->imd, - pDrive->track, - wd179x_info->fdc_head, - wd179x_info->fdc_sector, - sdata.raw, - 128 << wd179x_info->fdc_sec_len, - &flags, - &readlen); - - if(status == SCPE_OK) { - wd179x_info->fdc_status |= (WD179X_STAT_DRQ); /* Set DRQ */ - wd179x_info->drq = 1; - wd179x_info->fdc_datacount = 128 << wd179x_info->fdc_sec_len; - wd179x_info->fdc_dataindex = 0; - wd179x_info->fdc_write = FALSE; - wd179x_info->fdc_write_track = FALSE; - wd179x_info->fdc_read = TRUE; - wd179x_info->fdc_read_addr = FALSE; - } else { - wd179x_info->fdc_status = 0; /* Clear DRQ, BUSY */ - wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; - wd179x_info->fdc_status &= ~WD179X_STAT_BUSY; - wd179x_info->drq = 0; - wd179x_info->intrq = 1; - wd179x_info->fdc_read = FALSE; - wd179x_info->fdc_read_addr = FALSE; - } - } - break; - case WD179X_WRITE_RECS: - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " Error: WRITE_RECS not implemented.\n", wd179x_info->sel_drive, PCX); - break; - case WD179X_WRITE_REC: - /* Compute Sector Size */ - wd179x_info->fdc_sec_len = floorlog2( - pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].sectsize) - 7; - if(wd179x_info->fdc_sec_len > WD179X_MAX_SEC_LEN) { /* Error calculating N or N too large */ - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " Invalid sector size!\n", wd179x_info->sel_drive, PCX); - wd179x_info->fdc_sec_len = 0; - } - - sim_debug(WR_DATA_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=WRITE_REC, T:%d/S:%d/N:%d, %s.\n", wd179x_info->sel_drive, PCX, pDrive->track, wd179x_info->fdc_head, wd179x_info->fdc_sector, (cCommand & 0x10) ? "Multiple" : "Single"); - wd179x_info->fdc_status |= (WD179X_STAT_DRQ); /* Set DRQ */ - wd179x_info->drq = 1; - wd179x_info->fdc_datacount = 128 << wd179x_info->fdc_sec_len; - wd179x_info->fdc_dataindex = 0; - wd179x_info->fdc_write = TRUE; - wd179x_info->fdc_write_track = FALSE; - wd179x_info->fdc_read = FALSE; - wd179x_info->fdc_read_addr = FALSE; - - sdata.raw[wd179x_info->fdc_dataindex] = wd179x_info->fdc_data; - break; - /* Type III Commands */ - case WD179X_READ_ADDR: - sim_debug(RD_DATA_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=READ_ADDR, T:%d/S:%d, %s\n", wd179x_info->sel_drive, - PCX, pDrive->track, wd179x_info->fdc_head, wd179x_info->ddens ? "DD" : "SD"); - - /* For some reason 86-DOS tries to use this track, force it to 0. Need to investigate this more. */ - if (pDrive->track == 0xFF) - pDrive->track=0; - - /* Compute Sector Size */ - wd179x_info->fdc_sec_len = floorlog2( - pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].sectsize) - 7; - if(wd179x_info->fdc_sec_len > WD179X_MAX_SEC_LEN) { /* Error calculating N or N too large */ - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " Invalid sector size!\n", wd179x_info->sel_drive, PCX); - wd179x_info->fdc_sec_len = 0; - } - - if(IMD_MODE_MFM(pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].mode) != (wd179x_info->ddens)) { - wd179x_info->fdc_status = WD179X_STAT_NOT_FOUND; /* Sector not found */ - wd179x_info->intrq = 1; - } else { - wd179x_info->fdc_status = (WD179X_STAT_DRQ | WD179X_STAT_BUSY); /* Set DRQ, BUSY */ - wd179x_info->drq = 1; - wd179x_info->fdc_datacount = 6; - wd179x_info->fdc_dataindex = 0; - wd179x_info->fdc_read = TRUE; - wd179x_info->fdc_read_addr = TRUE; - - sdata.raw[0] = pDrive->track; - sdata.raw[1] = wd179x_info->fdc_head; - sdata.raw[2] = wd179x_info->fdc_sector; - sdata.raw[3] = wd179x_info->fdc_sec_len; - sdata.raw[4] = 0xAA; /* CRC1 */ - sdata.raw[5] = 0x55; /* CRC2 */ - - wd179x_info->fdc_sector = pDrive->track; - wd179x_info->fdc_status &= ~(WD179X_STAT_BUSY); /* Clear BUSY */ - wd179x_info->intrq = 1; - } - break; - case WD179X_READ_TRACK: - sim_debug(RD_DATA_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=READ_TRACK\n", wd179x_info->sel_drive, PCX); - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " Error: READ_TRACK not implemented.\n", wd179x_info->sel_drive, PCX); - break; - case WD179X_WRITE_TRACK: - sim_debug(WR_DATA_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=WRITE_TRACK\n", wd179x_info->sel_drive, PCX); - sim_debug(FMT_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=WRITE_TRACK, T:%d/S:%d.\n", wd179x_info->sel_drive, - PCX, pDrive->track, wd179x_info->fdc_head); - wd179x_info->fdc_status |= (WD179X_STAT_DRQ); /* Set DRQ */ - wd179x_info->drq = 1; - wd179x_info->fdc_datacount = 128 << wd179x_info->fdc_sec_len; - wd179x_info->fdc_dataindex = 0; - wd179x_info->fdc_write = FALSE; - wd179x_info->fdc_write_track = TRUE; - wd179x_info->fdc_read = FALSE; - wd179x_info->fdc_read_addr = FALSE; - wd179x_info->fdc_fmt_state = FMT_GAP1; /* TRUE when writing an entire track */ - wd179x_info->fdc_fmt_sector_count = 0; - - break; - /* Type IV Commands */ - case WD179X_FORCE_INTR: - sim_debug(CMD_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " CMD=FORCE_INTR\n", wd179x_info->sel_drive, PCX); - if((cCommand & 0x0F) == 0) { /* I0-I3 == 0, no intr, but clear BUSY and terminate command */ - wd179x_info->fdc_status &= ~(WD179X_STAT_DRQ | WD179X_STAT_BUSY); /* Clear DRQ, BUSY */ - wd179x_info->drq = 0; - wd179x_info->fdc_write = FALSE; - wd179x_info->fdc_read = FALSE; - wd179x_info->fdc_write_track = FALSE; - wd179x_info->fdc_read_addr = FALSE; - wd179x_info->fdc_datacount = 0; - wd179x_info->fdc_dataindex = 0; - } else { - if(wd179x_info->fdc_status & WD179X_STAT_BUSY) { /* Force Interrupt when command is pending */ - } else { /* Command not pending, clear status */ - wd179x_info->fdc_status = 0; - } - - if(cCommand & 0x04) { - wd179x_info->index_pulse_wait = TRUE; - if(wd179x_info->sel_drive < WD179X_MAX_DRIVES) { - sim_activate (wd179x_unit, ((wd179x_info->drive[wd179x_info->sel_drive].imd->ntracks % 77) == 0) ? CROMFDC_8IN_ROT : CROMFDC_5IN_ROT); /* Generate INDEX pulse */ -/* printf("Drive %d Num tracks=%d\n", wd179x_info->sel_drive, wd179x_info->drive[wd179x_info->sel_drive].imd->ntracks); */ - } - } else { - wd179x_info->intrq = 1; - } - wd179x_info->fdc_status &= ~(WD179X_STAT_BUSY); /* Clear BUSY */ - } - break; - default: - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " ERROR: Unknown command 0x%02x.\n\n", wd179x_info->sel_drive, PCX, cCommand); - break; - } - - /* Post processing of Type-specific command */ - switch(cCommand & 0xF0) { - /* Type I Commands */ - case WD179X_RESTORE: - case WD179X_SEEK: - case WD179X_STEP: - case WD179X_STEP_U: - case WD179X_STEP_IN: - case WD179X_STEP_IN_U: - case WD179X_STEP_OUT: - case WD179X_STEP_OUT_U: - if(wd179x_info->verify) { /* Verify the selected track/head is ok. */ - sim_debug(SEEK_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " Verify ", wd179x_info->sel_drive, PCX); - if(sectSeek(pDrive->imd, pDrive->track, wd179x_info->fdc_head) != SCPE_OK) { - sim_debug(SEEK_MSG, &wd179x_dev, "FAILED\n"); - wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; - } else if(IMD_MODE_MFM(pDrive->imd->track[pDrive->track][wd179x_info->fdc_head].mode) != (wd179x_info->ddens)) { - wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; /* Sector not found */ - sim_debug(SEEK_MSG, &wd179x_dev, "NOT FOUND\n"); - } else { - sim_debug(SEEK_MSG, &wd179x_dev, "Ok\n"); - } - } - - if(pDrive->track == 0) { - wd179x_info->fdc_status |= WD179X_STAT_TRACK0; - } else { - wd179x_info->fdc_status &= ~(WD179X_STAT_TRACK0); - } - - wd179x_info->fdc_status &= ~(WD179X_STAT_BUSY); /* Clear BUSY */ - wd179x_info->intrq = 1; - break; - /* Type II Commands */ - case WD179X_READ_REC: - case WD179X_READ_RECS: - case WD179X_WRITE_REC: - case WD179X_WRITE_RECS: - /* Type III Commands */ - case WD179X_READ_ADDR: - case WD179X_READ_TRACK: - case WD179X_WRITE_TRACK: - /* Type IV Commands */ - case WD179X_FORCE_INTR: - default: - break; - } - - - return result; -} - -/* Maximum number of sectors per track for format */ -uint8 max_sectors_per_track[2][7] = { - /* 128, 256, 512, 1024, 2048, 4096, 8192 */ - { 26, 15, 8, 4, 2, 1, 0 }, /* Single-density table */ - { 26, 26, 15, 8, 4, 2, 1 } /* Double-density table */ -}; - -uint8 WD179X_Write(const uint32 Addr, uint8 cData) -{ - WD179X_DRIVE_INFO *pDrive; -/* uint8 disk_read = 0; */ - uint32 flags = 0; - uint32 writelen; - - if(wd179x_info->sel_drive >= WD179X_MAX_DRIVES) { - return 0xFF; - } - - pDrive = &wd179x_info->drive[wd179x_info->sel_drive]; - - if(pDrive->uptr == NULL) { - return 0xFF; - } - - switch(Addr & 0x3) { - case WD179X_STATUS: - sim_debug(STATUS_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " WR CMD = 0x%02x\n", PCX, cData); - wd179x_info->fdc_read = FALSE; - wd179x_info->fdc_write = FALSE; - wd179x_info->fdc_write_track = FALSE; - wd179x_info->fdc_datacount = 0; - wd179x_info->fdc_dataindex = 0; - - Do1793Command(cData); - break; - case WD179X_TRACK: - sim_debug(STATUS_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " WR TRACK = 0x%02x\n", PCX, cData); - pDrive->track = cData; - break; - case WD179X_SECTOR: /* Sector Register */ - sim_debug(STATUS_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " WR SECT = 0x%02x\n", PCX, cData); - wd179x_info->fdc_sector = cData; - break; - case WD179X_DATA: - sim_debug(STATUS_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " WR DATA = 0x%02x\n", PCX, cData); - if(wd179x_info->fdc_write == TRUE) { - if(wd179x_info->fdc_dataindex < wd179x_info->fdc_datacount) { - sdata.raw[wd179x_info->fdc_dataindex] = cData; - - wd179x_info->fdc_dataindex++; - if(wd179x_info->fdc_dataindex == wd179x_info->fdc_datacount) { - wd179x_info->fdc_status &= ~(WD179X_STAT_DRQ | WD179X_STAT_BUSY); /* Clear DRQ, BUSY */ - wd179x_info->drq = 0; - wd179x_info->intrq = 1; - - sim_debug(WR_DATA_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " Writing sector, T:%d/S:%d/N:%d, Len=%d\n", wd179x_info->sel_drive, PCX, pDrive->track, wd179x_info->fdc_head, wd179x_info->fdc_sector, 128 << wd179x_info->fdc_sec_len); - - sectWrite(pDrive->imd, - pDrive->track, - wd179x_info->fdc_head, - wd179x_info->fdc_sector, - sdata.raw, - 128 << wd179x_info->fdc_sec_len, - &flags, - &writelen); - - wd179x_info->fdc_write = FALSE; - } - } - } - - if(wd179x_info->fdc_write_track == TRUE) { - if(wd179x_info->fdc_fmt_state == FMT_GAP1) { - if(cData != 0xFC) { - wd179x_info->fdc_gap[0]++; - } else { - sim_debug(VERBOSE_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " FMT GAP1 Length = %d\n", PCX, wd179x_info->fdc_gap[0]); - wd179x_info->fdc_gap[1] = 0; - wd179x_info->fdc_fmt_state = FMT_GAP2; - } - } else if(wd179x_info->fdc_fmt_state == FMT_GAP2) { - if(cData != 0xFE) { - wd179x_info->fdc_gap[1]++; - } else { - sim_debug(VERBOSE_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " FMT GAP2 Length = %d\n", PCX, wd179x_info->fdc_gap[1]); - wd179x_info->fdc_gap[2] = 0; - wd179x_info->fdc_fmt_state = FMT_HEADER; - wd179x_info->fdc_header_index = 0; - } - } else if(wd179x_info->fdc_fmt_state == FMT_HEADER) { - if(wd179x_info->fdc_header_index == 5) { - wd179x_info->fdc_gap[2] = 0; - wd179x_info->fdc_fmt_state = FMT_GAP3; - } else { - sim_debug(VERBOSE_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " HEADER[%d]=%02x\n", PCX, wd179x_info->fdc_header_index, cData); - switch(wd179x_info->fdc_header_index) { - case 0: - pDrive->track = cData; - break; - case 1: - wd179x_info->fdc_head = cData; - break; - case 2: - wd179x_info->fdc_sector = cData; - break; - case 3: - if(cData != 0x00) { - } - break; - case 4: - if(cData != 0xF7) { - } - break; - } - wd179x_info->fdc_header_index++; - } - } else if(wd179x_info->fdc_fmt_state == FMT_GAP3) { - if(cData != 0xFB) { - wd179x_info->fdc_gap[2]++; - } else { - sim_debug(VERBOSE_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " FMT GAP3 Length = %d\n", PCX, wd179x_info->fdc_gap[2]); - wd179x_info->fdc_fmt_state = FMT_DATA; - wd179x_info->fdc_dataindex = 0; - } - } else if(wd179x_info->fdc_fmt_state == FMT_DATA) { /* data bytes */ - if(cData != 0xF7) { - sdata.raw[wd179x_info->fdc_dataindex] = cData; - wd179x_info->fdc_dataindex++; - } else { - wd179x_info->fdc_sec_len = floorlog2(wd179x_info->fdc_dataindex) - 7; - if(wd179x_info->fdc_sec_len > WD179X_MAX_SEC_LEN) { /* Error calculating N or N too large */ - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT - " Invalid sector size!\n", wd179x_info->sel_drive, PCX); - wd179x_info->fdc_sec_len = 0; - } - if(wd179x_info->fdc_fmt_sector_count >= WD179X_MAX_SECTOR) { - sim_debug(ERROR_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " Illegal sector count\n", PCX); - wd179x_info->fdc_fmt_sector_count = 0; - } - wd179x_info->fdc_sectormap[wd179x_info->fdc_fmt_sector_count] = wd179x_info->fdc_sector; - wd179x_info->fdc_fmt_sector_count++; - sim_debug(VERBOSE_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " FMT Data Length = %d\n", PCX, wd179x_info->fdc_dataindex); - - sim_debug(FMT_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT - " FORMAT T:%d/H:%d/N:%d=%d/L=%d[%d] Fill=0x%02x\n", PCX, - pDrive->track, wd179x_info->fdc_head, - wd179x_info->fdc_fmt_sector_count, - wd179x_info->fdc_sectormap[wd179x_info->fdc_fmt_sector_count], - wd179x_info->fdc_dataindex, wd179x_info->fdc_sec_len, sdata.raw[0]); - - wd179x_info->fdc_gap[1] = 0; - wd179x_info->fdc_fmt_state = FMT_GAP2; - - if(wd179x_info->fdc_fmt_sector_count == max_sectors_per_track[wd179x_info->ddens & 1][wd179x_info->fdc_sec_len]) { - trackWrite(pDrive->imd, - pDrive->track, - wd179x_info->fdc_head, - wd179x_info->fdc_fmt_sector_count, - wd179x_info->fdc_sec_len, - wd179x_info->fdc_sectormap, - wd179x_info->ddens ? 3 : 0, /* data mode */ - sdata.raw[0], - &flags); - - wd179x_info->fdc_status &= ~(WD179X_STAT_BUSY | WD179X_STAT_LOST_DATA); /* Clear BUSY, LOST_DATA */ - wd179x_info->drq = 0; - wd179x_info->intrq = 1; - - /* Recalculate disk size */ - pDrive->uptr->capac = sim_fsize(pDrive->uptr->fileref); - } - } - } - } - - wd179x_info->fdc_data = cData; - break; - } - - return 0; -} - diff --git a/AltairZ80/wd179x.h b/AltairZ80/wd179x.h deleted file mode 100644 index 1ac1f19f..00000000 --- a/AltairZ80/wd179x.h +++ /dev/null @@ -1,67 +0,0 @@ -/************************************************************************* - * * - * $Id: wd179x.h 1907 2008-05-21 07:04:17Z hharte $ * - * * - * Copyright (c) 2007-2008 Howard M. Harte. * - * http://www.hartetec.com * - * * - * 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 HOWARD M. HARTE 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 Howard M. Harte shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * Howard M. Harte. * - * * - * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. * - * * - * Module Description: * - * Generic Intel 8272 Disk Controller module for SIMH. * - * * - * Environment: * - * User mode only * - * * - *************************************************************************/ - -extern t_stat wd179x_attach(UNIT *uptr, char *cptr); -extern t_stat wd179x_detach(UNIT *uptr); -extern uint8 WD179X_Set_DMA(const uint32 dma_addr); -extern uint8 WD179X_Read(const uint32 Addr); -extern uint8 WD179X_Write(const uint32 Addr, uint8 cData); - -extern void wd179x_external_restore(void); - -#define WD179X_FDC_MSR 0 /* R=FDC Main Status Register, W=Drive Select Register */ -#define WD179X_FDC_DATA 1 /* R/W FDC Data Register */ - -#define WD179X_STATUS 0 -#define WD179X_TRACK 1 -#define WD179X_SECTOR 2 -#define WD179X_DATA 3 - -typedef struct { - PNP_INFO pnp; /* Plug-n-Play Information */ - uint8 intrq; /* WD179X Interrupt Request Output (EOJ) */ - uint8 hld; /* WD179X Head Load Output */ - uint8 drq; /* WD179X DMA Request Output */ - uint8 ddens; /* WD179X Double-Density Input */ - uint8 fdc_head; /* H Head Number */ - uint8 sel_drive; /* Currently selected drive */ - uint8 drivetype; /* 8 or 5 depending on disk type. */ -} WD179X_INFO_PUB; diff --git a/Ibm1130/1130consoleblank.bmp b/Ibm1130/1130consoleblank.bmp deleted file mode 100644 index 4b989529..00000000 Binary files a/Ibm1130/1130consoleblank.bmp and /dev/null differ diff --git a/Ibm1130/1132empty.bmp b/Ibm1130/1132empty.bmp deleted file mode 100644 index 3ccc082c..00000000 Binary files a/Ibm1130/1132empty.bmp and /dev/null differ diff --git a/Ibm1130/1132full.bmp b/Ibm1130/1132full.bmp deleted file mode 100644 index 4705d1b6..00000000 Binary files a/Ibm1130/1132full.bmp and /dev/null differ diff --git a/Ibm1130/1442empty.bmp b/Ibm1130/1442empty.bmp deleted file mode 100644 index 8b9f667b..00000000 Binary files a/Ibm1130/1442empty.bmp and /dev/null differ diff --git a/Ibm1130/1442eof.bmp b/Ibm1130/1442eof.bmp deleted file mode 100644 index 2bf679a9..00000000 Binary files a/Ibm1130/1442eof.bmp and /dev/null differ diff --git a/Ibm1130/1442full.bmp b/Ibm1130/1442full.bmp deleted file mode 100644 index e6ba0c5b..00000000 Binary files a/Ibm1130/1442full.bmp and /dev/null differ diff --git a/Ibm1130/1442middle.bmp b/Ibm1130/1442middle.bmp deleted file mode 100644 index af45289f..00000000 Binary files a/Ibm1130/1442middle.bmp and /dev/null differ diff --git a/Ibm1130/HAND.CUR b/Ibm1130/HAND.CUR deleted file mode 100644 index eb0796dd..00000000 Binary files a/Ibm1130/HAND.CUR and /dev/null differ diff --git a/Ibm1130/dmsr2v12phases.h b/Ibm1130/dmsr2v12phases.h deleted file mode 100644 index 47fbb2d9..00000000 --- a/Ibm1130/dmsr2v12phases.h +++ /dev/null @@ -1,171 +0,0 @@ -0x01, "DUP - COMMON SUBROUTINES", -0x02, "DUP - CTRL RECORD PROCESSOR", -0x03, "DUP - STORE PHASE", -0x04, "DUP - *FILES, *LOCAL, *NOCAL PHASE", -0x05, "DUP - DUMP PHASE", -0x06, "DUP - DUMP LET/FLET PHASE", -0x07, "DUP - DELETE PHASE", -0x08, "DUP - DEFINE PHASE", -0x09, "DUP - EXIT PHASE", -0x0A, "DUP - CARD I/O INTERFACE", -0x0B, "DUP - KEYBOARD INPUT INTERFACE", -0x0C, "DUP - PAPER TAPE I/O INTERFACE", -0x0D, "DUP - SAVED UPCOR PHASE", -0x0E, "DUP - PRINCIPAL I/O DUMMY PHASE", -0x0F, "DUP - PRINCIPAL I/O (W/O KB) DUMMY PHASE", -0x10, "DUP - PAPER TAPE I/O DUMMY PHASE", -0x11, "DUP - MOVE DCI PROGRAMS TO UA OR FXA", -0x12, "DUP - EXIT TO MODIF DUMMY PHASE", - -0x1F, "FOR - INPUT PHASE", -0x20, "FOR - CLASSIFIERPHASE", -0x21, "FOR - CHECK ORDER/ST NO PHASE", -0x22, "FOR - COMMON SUBR OR FUNCTION PHASE", -0x23, "FOR - DIMENSION/REAL/INTEGER PHASE", -0x24, "FOR - REAL CONSTANT PHASE", -0x25, "FOR - DEFINE FILE, CALL LINK/EXIT PHASE", -0x26, "FOR - VARIABLE, STMT FUNC PHASE", -0x27, "FOR - DATA STATEMENT PHASE", -0x28, "FOR - FORMAT STATEMENT PHASE", -0x29, "FOR - SUBTRACT DECOMPOSITION PHASE", -0x2A, "FOR - ASCAN I PHASE", -0x2B, "FOR - ASCAN II PHASE", -0x2C, "FOR - DO/CONTINUE/ETC PHASE", -0x2D, "FOR - SUBSCRIPT OPTIMIZATION PHASE", -0x2E, "FOR - SCAN PHASE", -0x2F, "FOR - EXPANDER I PHASE", -0x30, "FOR - EXPANDER II PHASE", -0x31, "FOR - DATA ALLOCATION PHASE", -0x32, "FOR - COMPILATION ERROR PHASE", -0x33, "FOR - STATEMENT ALLOCATION PHASE", -0x34, "FOR - LIST STATEMENT PHASE", -0x35, "FOR - LIST SYMBOL TABLE PHASE", -0x36, "FOR - LIST CONSTANTS PHASE", -0x37, "FOR - OUTPUT I PHASE", -0x38, "FOR - OUTPUT II PHASE", -0x39, "FOR - RECOVERY/EXIT PHASE", - -0X51, "COBOL 51", -0X52, "COBOL 52", -0X53, "COBOL 53", -0X54, "COBOL 54", -0X55, "COBOL 55", -0X56, "COBOL 56", -0X57, "COBOL 57", -0X58, "COBOL 58", -0X59, "COBOL 59", -0X5A, "COBOL 5A", -0X5B, "COBOL 5B", -0X5C, "COBOL 5C", - -0X6E, "SUP PHASE 1 - MONITOR CONTROL RECORD ANALYZER", -0x6F, "SUP PHASE 2 - JOB PROCESSING", -0x70, "SUP PHASE 3 - DELETE TEMPORARY LET", -0x71, "SUP PHASE 4 - XEQ PROCESSING", -0x72, "SUP PHASE 5 - SUPV CONTROL REC PROCESSING", -0X73, "SYSTEM DUMP-CORE-TO-PRINTER", -0X74, "AUXILIARY SUPERVISOR", -0X78, "CORE LOAD BUILDER, PHASE 1", -0x79, "CORE LOAD BUILDER, PHASE 2", -0x7A, "CORE LOAD BUILDER, PHASE 3", -0x7B, "CORE LOAD BUILDER, PHASE 4", -0x7C, "CORE LOAD BUILDER, PHASE 5", -0x7D, "CORE LOAD BUILDER, PHASE 6", -0x7E, "CORE LOAD BUILDER, PHASE 7", -0x7F, "CORE LOAD BUILDER, PHASE 8", -0x80, "CORE LOAD BUILDER, PHASE 9", -0x81, "CORE LOAD BUILDER, PHASE 10", -0x82, "CORE LOAD BUILDER, PHASE 11", -0x83, "CORE LOAD BUILDER, PHASE 12", -0x84, "CORE LOAD BUILDER, PHASE 13", - -0X8C, "SYS 1403 READER", -0x8D, "SYS 1132 PRINTER", -0x8E, "SYS CONSOLE PRINTER", -0x8F, "SYS 2501/1442 READER", -0x90, "SYS 1442/1442 READER", -0x91, "SYS 1134/1055 PAPER TAPE IO", -0x92, "SYS KEYBOARD", -0x93, "SYS 2501/1442 CONVERSION", -0x94, "SYS 1134/1055 CONVERSION", -0x95, "SYS KEYBOARD CONVERSION", -0x96, "DISKZ", -0x97, "SYS DISK1", -0x98, "SYS DISKN", - -0xA0, "CIL CORE IMAGE LOADER - PHASE 1", -0xA1, "CIL CORE IMAGE LOADER - PHASE 2", - -0XB0, "RPG B0", -0XB1, "RPG B1", -0XB2, "RPG B2", -0XB3, "RPG B3", -0XB4, "RPG B4", -0XB5, "RPG B5", -0XB6, "RPG B6", -0XB7, "RPG B7", -0XB8, "RPG B8", -0XB9, "RPG B9", -0XBA, "RPG BA", -0XBB, "RPG BB", -0XBC, "RPG BC", -0XBD, "RPG BD", -0XBE, "RPG BE", -0XBF, "RPG BF", -0XC0, "RPG C0", -0XC1, "RPG C1", -0XC2, "RPG C2", -0XC3, "RPG C3", -0XC4, "RPG C4", -0XC5, "RPG C5", -0XC6, "RPG C6", -0XC7, "RPG C7", -0XC8, "RPG C8", -0XC9, "RPG C9", -0XCA, "RPG CA", -0XCB, "RPG CB", -0XCC, "RPG CC", - -0XCD, "DUP PART 2 - CTRL", -0XCE, "DUP PART 2 - MACRO UPDATE", - -0XCF, "ASM INITIALIZATION PHASE", -0xD0, "ASM CARD CONVERSION PHASE", -0xD1, "ASM DSF OUTPUT PHASE", -0xD2, "ASM INTERMEDIATE INPUT PHASE", -0xD3, "ASM END STATEMENT PHASE", -0xD4, "ASM ASSEMBLY ERROR PHASE", -0xD5, "ASM CONTROL CARDS I", -0xD6, "ASM CONTROL CARDS 2", -0xD7, "ASM DUMMY SYST SYMBOL TBL", -0xD8, "ASM SYMBOL TABLE OPTIONS PHASE", -0xD9, "ASM EXIT PHASE", -0xDA, "ASM PROG HEADER MNEMONICS PH", -0xDB, "ASM FILE STATEMENT PHASE", -0xDC, "ASM COMMON SUBROUTINES,ASCOM", -0xE4, "ASM INTERMEDIATE I/O", -0xE5, "ASM SYMBOL TABLE OVERFLOW", -0xDD, "ASM PROG CONTROL MNEMONICS PH", -0xDE, "ASM IMPERATIVE STATEMENTS PH", -0xDF, "ASM DECML,XFLC PROCESSING PH", -0xE0, "ASM DECIMAL CONVERSION PH", -0xE1, "ASM PROG LINKAGE PHASE", -0xE2, "ASM DMES PROCESSING PHASE", -0xE3, "ASM PUNCH CONVERSION PHASE", -0xE6, "ASM GRAPHIC ORDER PHASE", -0xE8, "ASM CONTROL CARDS III", -0xE9, "ASM MACRO PH 1 - SPECIAL OP AND PREPROCESSI", -0xEA, "MACRO PHASE 1A - SPECIAL PSEUDO OPS", -0xEB, "MACRO PHASE 1B - CONDITIONAL ASM PSEUDO OPS", -0xEC, "ASM MACRO PHASE 2 - MACRO DEFINITION", -0xED, "MACRO PHASE 2A - MACRO DEFINITION", -0xEE, "MACRO PHASE 2B - MACRO DEFINITION", -0xEF, "MACRO PHASE 3 - MACRO EXPANSION", -0xF0, "MACRO PHASE 3A - MACRO EXPANSION", -0xF1, "MACRO PHASE 3B - MACRO EXPANSION", -0xE7, "ASM DIVISION OPERATOR", -0xF2, "ASM CROSS-REFERENCE PART I", -0xF3, "ASM CROSS-REFERENCE PART 2A", -0xF4, "ASM CROSS-REFERENCE PART 2B", -0xF5, "ASM CROSS-REFERENCE PART 2C", -0xF6, "ASM CROSS-REFERENCE PART III", diff --git a/Ibm1130/dmsr2v12slet.h b/Ibm1130/dmsr2v12slet.h deleted file mode 100644 index 7d00676b..00000000 --- a/Ibm1130/dmsr2v12slet.h +++ /dev/null @@ -1,129 +0,0 @@ -/* DMS R2V12 SLET without RPG, for debugging only */ - -0x0001, 0x7c50, 0x032f, 0x0008, -0x0002, 0x11de, 0x05a2, 0x000b, -0x0003, 0x21de, 0x05a2, 0x0010, -0x0004, 0x01de, 0x03c0, 0x0015, -0x0005, 0x41de, 0x0550, 0x0018, -0x0006, 0x01de, 0x03c0, 0x001d, -0x0007, 0x01de, 0x05a2, 0x0020, -0x0008, 0x01de, 0x05a2, 0x0025, -0x0009, 0x01de, 0x0500, 0x002a, -0x000a, 0x7a06, 0x00db, 0x002e, -0x000b, 0x7a06, 0x0035, 0x002f, -0x000c, 0x7a06, 0x00d8, 0x0030, -0x000d, 0x7782, 0x087c, 0x0031, -0x000e, 0x7a06, 0x0248, 0x0038, -0x000f, 0x7a06, 0x0248, 0x003a, -0x0010, 0x7a06, 0x0248, 0x003c, -0x0011, 0x01de, 0x0280, 0x003e, -0x0012, 0x0e6e, 0x0140, 0x0040, -0x001f, 0x760c, 0x09f1, 0x0041, -0x0020, 0x7a34, 0x0500, 0x0049, -0x0021, 0x7a34, 0x0280, 0x004d, -0x0022, 0x7a34, 0x03c0, 0x004f, -0x0023, 0x7a34, 0x0500, 0x0052, -0x0024, 0x7a34, 0x03c0, 0x0056, -0x0025, 0x7a34, 0x0280, 0x0059, -0x0026, 0x7a34, 0x0500, 0x005b, -0x0027, 0x7a34, 0x03f0, 0x005f, -0x0028, 0x7a34, 0x03c0, 0x0063, -0x0029, 0x7a34, 0x03c0, 0x0066, -0x002a, 0x7a34, 0x03c0, 0x0069, -0x002b, 0x7a34, 0x03c0, 0x006c, -0x002c, 0x7a34, 0x0500, 0x006f, -0x002d, 0x7a34, 0x0500, 0x0073, -0x002e, 0x7a34, 0x0500, 0x0077, -0x002f, 0x7a34, 0x0500, 0x007b, -0x0030, 0x7a34, 0x0500, 0x007f, -0x0031, 0x7a34, 0x0404, 0x0083, -0x0032, 0x7a34, 0x03c0, 0x0087, -0x0033, 0x7a34, 0x03c0, 0x008a, -0x0034, 0x7a34, 0x0280, 0x008d, -0x0035, 0x7a34, 0x03c0, 0x008f, -0x0036, 0x7a34, 0x03c0, 0x0092, -0x0037, 0x7a34, 0x0500, 0x0095, -0x0038, 0x7b96, 0x03c0, 0x0099, -0x0039, 0x766e, 0x013e, 0x009c, -0x006e, 0x04fe, 0x02fe, 0x009d, -0x006f, 0x07fe, 0x052b, 0x00a0, -0x0070, 0x07fe, 0x0280, 0x00a5, -0x0071, 0x07fe, 0x0280, 0x00a7, -0x0072, 0x07fe, 0x03ea, 0x00a9, -0x0073, 0x0506, 0x04f8, 0x00ad, -0x0074, 0x0400, 0x0189, 0x00b1, -0x0078, 0x01e0, 0x0782, 0x00b3, -0x0079, 0x05bc, 0x04dd, 0x00ba, -0x007a, 0x08b6, 0x01e8, 0x00be, -0x007b, 0x08b6, 0x01e8, 0x00c0, -0x007c, 0x08b6, 0x01e8, 0x00c2, -0x007d, 0x08b6, 0x01e8, 0x00c4, -0x007e, 0x0aa0, 0x0140, 0x00c6, -0x007f, 0x0aa0, 0x0140, 0x00c7, -0x0080, 0x0aa0, 0x0140, 0x00c8, -0x0081, 0x0aa0, 0x0140, 0x00c9, -0x0082, 0x0be2, 0x0140, 0x00ca, -0x0083, 0x08b6, 0x01e8, 0x00cb, -0x0084, 0x0aa0, 0x0140, 0x00cd, -0x008c, 0x0000, 0x0134, 0x80ceU, -0x008d, 0x0000, 0x0113, 0x00cf, -0x008e, 0x0000, 0x011f, 0x00d0, -0x008f, 0x0000, 0x009c, 0x80d1U, -0x0090, 0x0000, 0x00ab, 0x00d2, -0x0091, 0x0000, 0x016c, 0x80d3U, -0x0092, 0x0000, 0x0174, 0x00d5, -0x0093, 0x0000, 0x00b9, 0x00d7, -0x0094, 0x0000, 0x0003, 0x80d8U, -0x0095, 0x0000, 0x0003, 0x00d9, -0x0096, 0x00f0, 0x00ec, 0x00da, -0x0097, 0x00f0, 0x01a2, 0x00db, -0x0098, 0x00f0, 0x02b0, 0x00dd, -0x0099, 0x0000, 0x0113, 0x00cf, -0x009a, 0x0000, 0x00ab, 0x00d2, -0x009b, 0x0000, 0x00ab, 0x00d2, -0x009c, 0x0000, 0x00b9, 0x00d7, -0x009d, 0x0000, 0x00b9, 0x00d7, -0x00a0, 0x0000, 0x016c, 0x00e0, -0x00a1, 0x0000, 0x01c0, 0x00e2, -0x00cd, 0x11de, 0x0280, 0x00e4, -0x00ce, 0x01de, 0x11df, 0x00e6, -0x00cf, 0x01e0, 0x026b, 0x00f5, -0x00d0, 0x01e8, 0x00bb, 0x00f7, -0x00d1, 0x01e8, 0x005f, 0x00f8, -0x00d2, 0x01e8, 0x005f, 0x00f9, -0x00d3, 0x0280, 0x01d5, 0x00fa, -0x00d4, 0x0ad0, 0x0145, 0x00fc, -0x00d5, 0x0280, 0x01d6, 0x00fe, -0x00d6, 0x0280, 0x0113, 0x0100, -0x00d7, 0x0000, 0x0130, 0x0101, -0x00d8, 0x07a8, 0x0254, 0x0102, -0x00d9, 0x0280, 0x01d7, 0x0104, -0x00da, 0x0280, 0x01a0, 0x0106, -0x00db, 0x0282, 0x00a3, 0x0108, -0x00dc, 0x0458, 0x05a7, 0x0109, -0x00dd, 0x0280, 0x01d5, 0x010e, -0x00de, 0x0280, 0x01d6, 0x0110, -0x00df, 0x0280, 0x017c, 0x0112, -0x00e0, 0x0282, 0x0127, 0x0114, -0x00e1, 0x0280, 0x0196, 0x0115, -0x00e2, 0x0280, 0x01d8, 0x0117, -0x00e3, 0x0280, 0x0099, 0x0119, -0x00e4, 0x098a, 0x005f, 0x011a, -0x00e5, 0x098a, 0x0062, 0x011b, -0x00e6, 0x0eca, 0x03c1, 0x011c, -0x00e7, 0x0280, 0x00b8, 0x0120, -0x00e8, 0x0280, 0x017f, 0x0121, -0x00e9, 0x0280, 0x01d6, 0x0123, -0x00ea, 0x0280, 0x01d9, 0x0125, -0x00eb, 0x0280, 0x01d9, 0x0127, -0x00ec, 0x0280, 0x01ca, 0x0129, -0x00ed, 0x0280, 0x01c2, 0x012b, -0x00ee, 0x05dc, 0x0158, 0x012d, -0x00ef, 0x07ac, 0x0051, 0x012f, -0x00f0, 0x0280, 0x01af, 0x0130, -0x00f1, 0x12f4, 0x027f, 0x0132, -0x00f2, 0x0280, 0x01c7, 0x0134, -0x00f3, 0x07a8, 0x0052, 0x0136, -0x00f4, 0x0924, 0x005b, 0x0137, -0x00f5, 0x0886, 0x003d, 0x0138, -0x00f6, 0x0eca, 0x03b2, 0x0139, diff --git a/Ibm1130/ibm1130.mak b/Ibm1130/ibm1130.mak deleted file mode 100644 index 4651d698..00000000 --- a/Ibm1130/ibm1130.mak +++ /dev/null @@ -1,435 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "ibm1130.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/ibm1130.exe $(OUTDIR)/ibm1130.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /I "c:\pdp11\supnik" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /I "c:\pdp11\supnik" /D "NDEBUG" /D "WIN32" /D\ - "_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR$(INTDIR)/ /Fp$(OUTDIR)/"ibm1130.pch"\ - /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -RSC_PROJ=/l 0x409 /fo$(INTDIR)/"ibm1130.res" /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"ibm1130.bsc" -BSC32_SBRS= \ - $(INTDIR)/ibm1130_cpu.sbr \ - $(INTDIR)/ibm1130_sys.sbr \ - $(INTDIR)/ibm1130_cr.sbr \ - $(INTDIR)/ibm1130_stddev.sbr \ - $(INTDIR)/ibm1130_disk.sbr \ - $(INTDIR)/ibm1130_gdu.sbr \ - $(INTDIR)/ibm1130_gui.sbr \ - $(INTDIR)/ibm1130_prt.sbr \ - $(INTDIR)/scp.sbr \ - $(INTDIR)/sim_tmxr.sbr \ - $(INTDIR)/sim_sock.sbr \ - $(INTDIR)/ibm1130_fmt.sbr \ - $(INTDIR)/sim_console.sbr \ - $(INTDIR)/sim_fio.sbr \ - $(INTDIR)/sim_timer.sbr \ - $(INTDIR)/ibm1130_ptrp.sbr - -$(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib wsock32.lib shell32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib\ - wsock32.lib shell32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\ - /PDB:$(OUTDIR)/"ibm1130.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/ibm1130_cpu.obj \ - $(INTDIR)/ibm1130_sys.obj \ - $(INTDIR)/ibm1130_cr.obj \ - $(INTDIR)/ibm1130_stddev.obj \ - $(INTDIR)/ibm1130.res \ - $(INTDIR)/ibm1130_disk.obj \ - $(INTDIR)/ibm1130_gdu.obj \ - $(INTDIR)/ibm1130_gui.obj \ - $(INTDIR)/ibm1130_prt.obj \ - $(INTDIR)/scp.obj \ - $(INTDIR)/sim_tmxr.obj \ - $(INTDIR)/sim_sock.obj \ - $(INTDIR)/ibm1130_fmt.obj \ - $(INTDIR)/sim_console.obj \ - $(INTDIR)/sim_fio.obj \ - $(INTDIR)/sim_timer.obj \ - $(INTDIR)/ibm1130_ptrp.obj - -$(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/ibm1130.exe $(OUTDIR)/ibm1130.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /I "c:\pdp11\supnik" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /I "c:\pdp11\supnik" /D "_DEBUG" /D\ - "WIN32" /D "_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR$(INTDIR)/\ - /Fp$(OUTDIR)/"ibm1130.pch" /Fo$(INTDIR)/ /Fd$(OUTDIR)/"ibm1130.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -RSC_PROJ=/l 0x409 /fo$(INTDIR)/"ibm1130.res" /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"ibm1130.bsc" -BSC32_SBRS= \ - $(INTDIR)/ibm1130_cpu.sbr \ - $(INTDIR)/ibm1130_sys.sbr \ - $(INTDIR)/ibm1130_cr.sbr \ - $(INTDIR)/ibm1130_stddev.sbr \ - $(INTDIR)/ibm1130_disk.sbr \ - $(INTDIR)/ibm1130_gdu.sbr \ - $(INTDIR)/ibm1130_gui.sbr \ - $(INTDIR)/ibm1130_prt.sbr \ - $(INTDIR)/scp.sbr \ - $(INTDIR)/sim_tmxr.sbr \ - $(INTDIR)/sim_sock.sbr \ - $(INTDIR)/ibm1130_fmt.sbr \ - $(INTDIR)/sim_console.sbr \ - $(INTDIR)/sim_fio.sbr \ - $(INTDIR)/sim_timer.sbr \ - $(INTDIR)/ibm1130_ptrp.sbr - -$(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib wsock32.lib shell32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# SUBTRACT LINK32 /MAP -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib\ - wsock32.lib shell32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\ - /PDB:$(OUTDIR)/"ibm1130.pdb" /DEBUG /MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/ibm1130_cpu.obj \ - $(INTDIR)/ibm1130_sys.obj \ - $(INTDIR)/ibm1130_cr.obj \ - $(INTDIR)/ibm1130_stddev.obj \ - $(INTDIR)/ibm1130.res \ - $(INTDIR)/ibm1130_disk.obj \ - $(INTDIR)/ibm1130_gdu.obj \ - $(INTDIR)/ibm1130_gui.obj \ - $(INTDIR)/ibm1130_prt.obj \ - $(INTDIR)/scp.obj \ - $(INTDIR)/sim_tmxr.obj \ - $(INTDIR)/sim_sock.obj \ - $(INTDIR)/ibm1130_fmt.obj \ - $(INTDIR)/sim_console.obj \ - $(INTDIR)/sim_fio.obj \ - $(INTDIR)/sim_timer.obj \ - $(INTDIR)/ibm1130_ptrp.obj - -$(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_cpu.c -DEP_IBM11=\ - .\ibm1130_defs.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_cpu.obj : $(SOURCE) $(DEP_IBM11) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_sys.c -DEP_IBM113=\ - .\ibm1130_defs.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_sys.obj : $(SOURCE) $(DEP_IBM113) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_cr.c -DEP_IBM1130=\ - .\ibm1130_defs.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_cr.obj : $(SOURCE) $(DEP_IBM1130) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_stddev.c -DEP_IBM1130_=\ - .\ibm1130_defs.h\ - .\ibm1130_conout.h\ - .\ibm1130_conin.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_stddev.obj : $(SOURCE) $(DEP_IBM1130_) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130.rc -DEP_IBM1130_R=\ - .\1130consoleblank.bmp\ - .\hand.cur - -$(INTDIR)/ibm1130.res : $(SOURCE) $(DEP_IBM1130_R) $(INTDIR) - $(RSC) $(RSC_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_disk.c -DEP_IBM1130_D=\ - .\ibm1130_defs.h\ - .\dmsr2v12phases.h\ - .\dmsr2v12slet.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_disk.obj : $(SOURCE) $(DEP_IBM1130_D) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_gdu.c -DEP_IBM1130_G=\ - .\ibm1130_defs.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_gdu.obj : $(SOURCE) $(DEP_IBM1130_G) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_gui.c -DEP_IBM1130_GU=\ - .\ibm1130_defs.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_gui.obj : $(SOURCE) $(DEP_IBM1130_GU) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_prt.c -DEP_IBM1130_P=\ - .\ibm1130_defs.h\ - .\ibm1130_prtwheel.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_prt.obj : $(SOURCE) $(DEP_IBM1130_P) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=\pdp11\supnik\scp.c -DEP_SCP_C=\ - ..\sim_defs.h\ - \pdp11\supnik\sim_rev.h\ - \pdp11\supnik\sim_sock.h\ - \pdp11\supnik\sim_tmxr.h\ - \MSVC20\INCLUDE\sys\TYPES.H - -$(INTDIR)/scp.obj : $(SOURCE) $(DEP_SCP_C) $(INTDIR) - $(CPP) $(CPP_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=\pdp11\supnik\sim_tmxr.c -DEP_SIM_T=\ - ..\sim_defs.h\ - \pdp11\supnik\sim_sock.h\ - \pdp11\supnik\sim_tmxr.h\ - \MSVC20\INCLUDE\sys\TYPES.H - -$(INTDIR)/sim_tmxr.obj : $(SOURCE) $(DEP_SIM_T) $(INTDIR) - $(CPP) $(CPP_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=\pdp11\supnik\sim_sock.c -DEP_SIM_S=\ - ..\sim_defs.h\ - \pdp11\supnik\sim_sock.h\ - \MSVC20\INCLUDE\sys\TYPES.H - -$(INTDIR)/sim_sock.obj : $(SOURCE) $(DEP_SIM_S) $(INTDIR) - $(CPP) $(CPP_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_fmt.c - -$(INTDIR)/ibm1130_fmt.obj : $(SOURCE) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=\pdp11\supnik\sim_console.c -DEP_SIM_C=\ - ..\sim_defs.h\ - \pdp11\supnik\sim_sock.h\ - \pdp11\supnik\sim_tmxr.h\ - \pdp11\supnik\scp.h\ - \pdp11\supnik\sim_console.h\ - \pdp11\supnik\sim_timer.h\ - \pdp11\supnik\sim_fio.h\ - D:\PROGRA~1\MICROS~1\INCLUDE\WinSock2.h\ - \MSVC20\INCLUDE\sys\TYPES.H\ - D:\PROGRA~1\MICROS~1\INCLUDE\Qos.h\ - D:\WINDDK\2600\inc\wxp\guiddef.h - -$(INTDIR)/sim_console.obj : $(SOURCE) $(DEP_SIM_C) $(INTDIR) - $(CPP) $(CPP_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=\pdp11\supnik\sim_fio.c -DEP_SIM_F=\ - ..\sim_defs.h\ - D:\PROGRA~1\MICROS~1\INCLUDE\BaseTsd.h\ - \pdp11\supnik\scp.h\ - \pdp11\supnik\sim_console.h\ - \pdp11\supnik\sim_timer.h\ - \pdp11\supnik\sim_fio.h - -$(INTDIR)/sim_fio.obj : $(SOURCE) $(DEP_SIM_F) $(INTDIR) - $(CPP) $(CPP_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=\pdp11\supnik\sim_timer.c -DEP_SIM_TI=\ - ..\sim_defs.h\ - D:\PROGRA~1\MICROS~1\INCLUDE\BaseTsd.h\ - \pdp11\supnik\scp.h\ - \pdp11\supnik\sim_console.h\ - \pdp11\supnik\sim_timer.h\ - \pdp11\supnik\sim_fio.h - -$(INTDIR)/sim_timer.obj : $(SOURCE) $(DEP_SIM_TI) $(INTDIR) - $(CPP) $(CPP_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_ptrp.c - -$(INTDIR)/ibm1130_ptrp.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/ibm1130.rc b/Ibm1130/ibm1130.rc deleted file mode 100644 index 47a56a67..00000000 --- a/Ibm1130/ibm1130.rc +++ /dev/null @@ -1,72 +0,0 @@ -//Microsoft Visual C++ generated resource script. -// -#include "ibm1130res.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "ibm1130res.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include \r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -///////////////////////////////////////////////////////////////////////////// -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Bitmap -// - -IDB_CONSOLE BITMAP MOVEABLE PURE "1130consoleblank.bmp" -FULL_1442 BITMAP MOVEABLE PURE "1442full.bmp" -EOF_1442 BITMAP MOVEABLE PURE "1442eof.bmp" -EMPTY_1442 BITMAP MOVEABLE PURE "1442empty.bmp" -MIDDLE_1442 BITMAP MOVEABLE PURE "1442middle.bmp" -FULL_1132 BITMAP MOVEABLE PURE "1132full.bmp" -EMPTY_1132 BITMAP MOVEABLE PURE "1132empty.bmp" - -///////////////////////////////////////////////////////////////////////////// -// -// Cursor -// - -IDC_MYHAND CURSOR DISCARDABLE "HAND.CUR" - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/Ibm1130/ibm1130_conin.h b/Ibm1130/ibm1130_conin.h deleted file mode 100644 index a142e865..00000000 --- a/Ibm1130/ibm1130_conin.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -/* - * 03 ctrl-C => Program stop (not handled here) - * 05 ctrl-E => Simulator stop (not handled here) - * 08 ctrl-H => Backspace - * 0D ctrl-M (Enter) => EOF - * 11 ctrl-Q => Interrupt request (not handled here) - * 12 ctrl-R => "cent" (R because that's where cent is on the 1130 keyboard) - * 15 ctrl-U => Erase Field - * 7E ~ => "not" - * FF Del => Backspace again - */ - -static uint16 ascii_to_conin[] = /* ASCII to ((hollerith << 4) | special key flags) */ -{ - /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */ - /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0,0x0004, 0, 0, 0, 0,0x0008, 0, 0, - /* 10 */ 0, 0,0x8820, 0, 0,0x0002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 20 */ 0x0001,0x4820,0x0060,0x0420,0x4420,0x2220,0x8000,0x0120,0x8120,0x4120,0x4220,0x80a0,0x2420,0x4000,0x8420,0x3000, - /* 30 */ 0x2000,0x1000,0x0800,0x0400,0x0200,0x0100,0x0080,0x0040,0x0020,0x0010,0x0820,0x40a0,0x8220,0x00a0,0x20a0,0x2060, - /* 40 */ 0x0220,0x9000,0x8800,0x8400,0x8200,0x8100,0x8080,0x8040,0x8020,0x8010,0x5000,0x4800,0x4400,0x4200,0x4100,0x4080, - /* 50 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010, 0, 0, 0, 0,0x2120, - /* 60 */ 0,0x9000,0x8800,0x8400,0x8200,0x8100,0x8080,0x8040,0x8020,0x8010,0x5000,0x4800,0x4400,0x4200,0x4100,0x4080, - /* 70 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010, 0,0xB060, 0, 0,0x0004, - /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* a0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* b0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* c0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* d0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* e0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* f0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x0004, -}; diff --git a/Ibm1130/ibm1130_conout.h b/Ibm1130/ibm1130_conout.h deleted file mode 100644 index 478e005d..00000000 --- a/Ibm1130/ibm1130_conout.h +++ /dev/null @@ -1,58 +0,0 @@ -/* IBM1130 CONSOLE OUTPUT TO ASCII CONVERSION TABLE - * - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -#define _0_ '\0' - -#define CENT_ '\xA2' /* cent and not: standard DOS mapping */ -#define NOT_ '\xAC' -#define IGNR_ '\xFF' -#define CRLF_ '\r' - -#define COUT_IS_CTRL 0x01 /* conout characters with bit 1 set are controls: */ - -#define COUT_CTRL_BLACK 0x04 /* none or one of these bits */ -#define COUT_CTRL_RED 0x08 - -#define COUT_CTRL_LINEFEED 0x02 /* plus none or one of these bits */ -#define COUT_CTRL_BACKSPACE 0x10 -#define COUT_CTRL_SPACE 0x20 -#define COUT_CTRL_TAB 0x40 -#define COUT_CTRL_RETURN 0x80 - -#ifdef _MSC_VER -# pragma warning(disable:4245) /* enable int->char demotion warning caused by characters with high-bit set */ -#endif - -static unsigned char conout_to_ascii[] = /* console output code to ASCII */ -{ - /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */ - /* 00 */ '.', IGNR_,CENT_, '\n', '@', IGNR_,'%', _0_, _0_, IGNR_,_0_, _0_, _0_, _0_, _0_, _0_, - /* 10 */ 'F', '\b', 'f', _0_, 'G', _0_, 'g', _0_, 'B', _0_, 'b', _0_, 'C', _0_, 'c', _0_, - /* 20 */ 'I', ' ', 'i', _0_, 'H', _0_, 'h', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 30 */ 'D', _0_, 'd', _0_, 'E', _0_, 'e', _0_, _0_, _0_, _0_, _0_, 'A', _0_, 'a', _0_, - /* 40 */ '$', '\t', '!', _0_, '&', _0_, '>', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 50 */ 'O', _0_, 'o', _0_, 'P', _0_, 'o', _0_, 'K', _0_, 'k', _0_, 'L', _0_, 'l', _0_, - /* 60 */ 'R', _0_, 'r', _0_, 'Q', _0_, 'q', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 70 */ 'M', _0_, 'm', _0_, 'N', _0_, 'n', _0_, _0_, _0_, _0_, _0_, 'J', _0_, 'j', _0_, - /* 80 */ ',', CRLF_, ':', _0_, '-', _0_, '?', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 90 */ 'W', _0_, 'w', _0_, 'X', _0_, 'x', _0_, 'S', _0_, 's', _0_, 'T', _0_, 't', _0_, - /* A0 */ 'Z', _0_, 'z', _0_, 'Y', _0_, 'y', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* B0 */ 'U', _0_, 'u', _0_, 'V', _0_, 'v', _0_, _0_, _0_, _0_, _0_, '/', _0_, '_', _0_, - /* C0 */ '#', _0_, '=', _0_, '0', _0_, '|', _0_, _0_, _0_, _0_, _0_, 'J', _0_, 'j', _0_, - /* D0 */ '6', _0_, ';', _0_, '7', _0_, '*', _0_, '2', _0_, '+', _0_, '3', _0_, '<', _0_, - /* E0 */ '9', _0_, '"', _0_, '8', _0_, '\'', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* F0 */ '4', _0_, NOT_, _0_, '5', _0_, ')', _0_, _0_, _0_, _0_, _0_, '1', _0_, '(', _0_, -}; - -#ifdef _MSC_VER -# pragma warning(default:4245) /* enable int->char demotion warning */ -#endif diff --git a/Ibm1130/ibm1130_cpu.c b/Ibm1130/ibm1130_cpu.c deleted file mode 100644 index d35bbcbd..00000000 --- a/Ibm1130/ibm1130_cpu.c +++ /dev/null @@ -1,1883 +0,0 @@ -/* ibm1130_cpu.c: IBM 1130 CPU simulator - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - - 25-Jun-01 BLK Written - 10-May-02 BLK Fixed bug in MDX instruction - 27-Mar-02 BLK Made BOSC work even in short form - 16-Aug-02 BLK Fixed bug in multiply instruction; didn't work with negative values - 18-Mar-03 BLK Fixed bug in divide instruction; didn't work with negative values - 23-Jul-03 BLK Prevented tti polling in CGI mode - 24-Nov-03 BLK Fixed carry bit error in subtract and subtract double, found by Bob Flanders - 20-Oct-04 BLK Changed "(unsigned int32)" to "(uint32)" to accomodate improved definitions of simh types - Also commented out my echo command as it's now a standard simh command - 27-Nov-05 BLK Added Arithmetic Factor Register support per Carl Claunch (GUI only) - 06-Dec-06 BLK Moved CGI stuff out of ibm1130_cpu.c - ->> To do: verify actual operands stored in ARF, need to get this from state diagrams in the schematic set - Also: determine how many bits are actually stored in the IAR in a real 1130, by forcing wraparound - and storing the IAR. - - IBM 1800 support is just beginning. Mode set is done (SET CPU 1800 or SET CPU 1130). - Index registers are handled (1800 has real registers, 1130 uses core locations 1, 2 and 3 -- - but does the 1800 make its hardware index registers appear in the address space?) - Need to add: memory protect feature, more interrupt levels, GUI mods, IO device mods, timers, watchdog. - Memory protect was interesting -- they borrowed one of the two parity bits. XIO(0) on 1800 is used for - interval timers, console data switches, console sense/program select/CE switches, interrupt mask register, - programmed interrupt, console interrupt and operations monitor (watchdog) - very interesting stuff. - - The register state for the IBM 1130 CPU is: - - IAR instruction address register - ACC accumulator - EXT accumulator extension - Oflow overflow bit - Carry carry bit - CES console entry switches - ipl current interrupt level, -1 = non interrupt - iplpending bitmap of pending interrupts - wait_state current CPU state: running or waiting - DSW console run/stop switch device status word - RUNMODE processor step/run mode (may also imply IntRun) - BREAK breakpoint address - WRU simulator-break character - IntRun Int Run flag (causes level 5 interrupt after every instruction) - ILSW0..5 interrupt level status words - XR1, 2, 3 for IBM 1800 only, index registers 1, 2, and 3 - - The SAR (storage address register) and SBR (storage buffer register) are updated - but not saved in the CPU state; they matter only to the GUI. - - Interrupt handling: interrupts occur when any device on any level has an - active interrupt. XIO commands can clear specific IRQ bits. When this - happens, we have to evaluate all devices on the same IRQ level for remaining - indicators. The flag int_req is set with a bit corresponding to the IRQ level - when any interrupt indicator is activated. - - The 1130 console has a switch that controls several run modes: SS (single processor - step), SCLK (single clock step), SINST (single instruction step), INT_RUN - (IRQ 5 after each non interrupt-handler instruction) and RUN (normal operation). - This simulator does not implement SS and SCLK. The simulator GUI console handles - SINST, so we only have to worry about INT_RUN. The console command SET CPU IntRun sets - the tmode (trace mode) flag; this causes a level 5 interrupt after each - instruction. - - The IBM 1130 instruction formats are - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | opcode | F| T | | general format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | opcode | 0| T | DISPLACEMENT | short instruction - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | opcode | 1| T | I| MODIFIER | long instruction - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | ADDRESS | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - opcode in MSBits - - F = format. 0 = short (1 word), 1 = long (2 word) instruction - - T = Tag 00 = no index register (e.g. IAR relative) - 01 = use index register 1 (e.g. core address 1 = M[1]) - 02 = use index register 2 (e.g. core address 2 = M[2]) - 03 = use index register 3 (e.g. core address 3 = M[3]) - - DISPLACEMENT = two's complement (must be sign-extended) - - I = Indirect - - Note that IAR = instruction address+1 when instruction is being decoded. - - In normal addressing mode, effective address (EA) is computed as follows: - - F = 0 T = 0 EA = IAR + DISPLACEMENT - 0 1 IAR + DISPLACEMENT + M[1] - 0 2 IAR + DISPLACEMENT + M[2] - 0 3 IAR + DISPLACEMENT + M[3] - - F = 1 T = 0 I = 0 EA = ADDRESS - 1 1 0 ADDRESS + M[1] - 1 2 0 ADDRESS + M[2] - 1 3 0 ADDRESS + M[3] - 1 0 1 M[ADDRESS] - 1 1 1 M[ADDRESS + M[1]] - 1 2 1 M[ADDRESS + M[2]] - 1 3 1 M[ADDRESS + M[3]] - - Loads or stores are then made to/from MEM[EA]. Some instructions have special - weird addressing modes. Simulator code precomputes standard addressing for - all instructions though it's not always used. - - General notes: - - Adding I/O devices requires modifications to three modules: - - ibm1130_defs.h add interrupt request definitions - ibm1130_cpu.c add XIO command linkages - ibm1130_sys.c add to sim_devices array -*/ - -/* ------------------------------------------------------------------------ - * Definitions - * ------------------------------------------------------------------------ */ - -#include - -#include "ibm1130_defs.h" - -#define save_ibkpt (cpu_unit.u3) /* will be SAVEd */ - -#define UPDATE_BY_TIMER -#define ENABLE_BACKTRACE -/* #define USE_MY_ECHO_CMD */ /* simh now has echo command built in */ -#define ENABLE_1800_SUPPORT /* define to enable support for 1800 CPU simulation mode */ - -static void cgi_start(void); -static void cgi_stop(t_stat reason); -static int simh_status_to_stopcode (int status); - -/* hook pointers from scp.c */ -void (*sim_vm_init) (void) = &sim_init; -extern char* (*sim_vm_read) (char *ptr, int32 size, FILE *stream); -extern void (*sim_vm_post) (t_bool from_scp); -extern CTAB *sim_vm_cmd; - -/* space to store extra simulator-specific commands */ -#define MAX_EXTRA_COMMANDS 10 -CTAB x_cmds[MAX_EXTRA_COMMANDS]; - -#ifdef _WIN32 -# define CRLF "\r\n" -#else -# define CRLF "\n" -#endif - -/* ------------------------------------------------------------------------ - * initializers for globals - * ------------------------------------------------------------------------ */ - -#define SIGN_BIT(v) ((v) & 0x8000) -#define DWSIGN_BIT(v) ((v) & 0x80000000) - -uint16 M[MAXMEMSIZE]; /* core memory, up to 32Kwords (note: don't even think about trying 64K) */ -uint16 ILSW[6] = {0,0,0,0,0,0}; /* interrupt level status words */ -uint16 XR[3] = {0,0,0}; /* IBM 1800 index registers */ -int32 IAR; /* instruction address register */ -int32 prev_IAR; /* instruction address register at start of current instruction */ -int32 SAR, SBR; /* storage address/buffer registers */ -int32 OP, TAG, CCC; /* instruction decoded pieces */ -int32 CES; /* console entry switches */ -int32 ACC, EXT; /* accumulator and extension */ -int32 ARF; /* arithmetic factor, a non-addressable internal CPU register */ -int32 RUNMODE; /* processor run/step mode */ -int32 ipl = -1; /* current interrupt level (-1 = not handling irq) */ -int32 iplpending = 0; /* interrupted IPL's */ -int32 tbit = 0; /* trace flag (causes level 5 IRQ after each instr) */ -int32 V = 0, C = 0; /* condition codes */ -int32 wait_state = 0; /* wait state (waiting for an IRQ) */ -int32 wait_lamp = TRUE; /* alternate indicator to light the wait lamp on the GUI */ -int32 int_req = 0; /* sum of interrupt request levels active */ -int32 int_lamps = 0; /* accumulated version of int_req - gives lamp persistence */ -int32 int_mask; /* current active interrupt mask (ipl sensitive) */ -int32 mem_mask; /* mask for memory address bits based on current memory size */ -int32 cpu_dsw = 0; /* CPU device status word */ -int32 ibkpt_addr = -1; /* breakpoint addr */ -t_bool sim_gui = TRUE; /* enable gui */ -t_bool running = FALSE; /* TRUE if CPU is running */ -t_bool power = TRUE; /* TRUE if CPU power is on */ -t_bool cgi = FALSE; /* TRUE if we are running as a CGI program */ -t_bool cgiwritable = FALSE; /* TRUE if we can write the disk images back to the image file in CGI mode */ -t_bool is_1800 = FALSE; /* TRUE if we are simulating an IBM 1800 processor */ -t_stat reason; /* CPU execution loop control */ - -static int32 int_masks[6] = { - 0x00, 0x20, 0x30, 0x38, 0x3C, 0x3E /* IPL 0 is highest prio (sees no other interrupts) */ -}; - -/* ------------------------------------------------------------------------ - * Function declarations - * ------------------------------------------------------------------------ */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_svc (UNIT *uptr); -t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc); -t_stat cpu_set_type (UNIT *uptr, int32 value, char *cptr, void *desc); -void calc_ints (void); - -extern t_stat ts_wr (int32 data, int32 addr, int32 access); -extern t_stat detach_cmd (int32 flags, char *cptr); -extern UNIT cr_unit; -extern int32 sim_switches; - -#ifdef ENABLE_BACKTRACE - static void archive_backtrace(char *inst); - static void reset_backtrace (void); - static void show_backtrace (int nshow); - static t_stat backtrace_cmd (int32 flag, char *cptr); -#else - #define archive_backtrace(inst) - #define reset_backtrace() - #define show_backtrace(ntrace) -#endif - -#ifdef GUI_SUPPORT -# define ARFSET(v) ARF = (v) & 0xFFFF /* set Arithmetic Factor Register (used for display purposes only) */ -#else -# define ARFSET(v) /* without GUI, no need for setting ARF */ -#endif - -static void init_console_window (void); -static void destroy_console_window (void); -static t_stat view_cmd (int32 flag, char *cptr); -static t_stat cpu_attach (UNIT *uptr, char *cptr); -static t_bool bsctest (int32 DSPLC, t_bool reset_V); -static void exit_irq (void); -static void trace_instruction (void); - -/* ------------------------------------------------------------------------ - * CPU data structures: - * cpu_dev CPU device descriptor - * cpu_unit CPU unit descriptor - * cpu_reg CPU register list - * cpu_mod CPU modifier list - * - * The CPU is attachable; attaching a file to it write a log of instructions - * and registers - * ------------------------------------------------------------------------ */ - -#define UNIT_MSIZE (1 << (UNIT_V_UF + 7)) /* flag for memory size setting */ -#define UNIT_1800 (1 << (UNIT_V_UF + 0)) /* flag for 1800 mode */ - -UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX | UNIT_BINK | UNIT_ATTABLE | UNIT_SEQ, INIMEMSIZE) }; - -REG cpu_reg[] = { - { HRDATA (IAR, IAR, 32) }, - { HRDATA (ACC, ACC, 32) }, - { HRDATA (EXT, EXT, 32) }, - { FLDATA (Oflow, V, 1) }, - { FLDATA (Carry, C, 1) }, - { HRDATA (CES, CES, 32) }, - { HRDATA (ipl, ipl, 32), REG_RO }, - { HRDATA (iplpending, iplpending, 32), REG_RO }, - { HRDATA (wait_state, wait_state, 32)}, - { HRDATA (DSW, cpu_dsw, 32), REG_RO }, - { HRDATA (RUNMODE, RUNMODE, 32) }, - { HRDATA (BREAK, ibkpt_addr, 32) }, - { ORDATA (WRU, sim_int_char, 8) }, - { FLDATA (IntRun, tbit, 1) }, - - { HRDATA (ILSW0, ILSW[0], 32), REG_RO }, - { HRDATA (ILSW1, ILSW[1], 32), REG_RO }, - { HRDATA (ILSW2, ILSW[2], 32), REG_RO }, - { HRDATA (ILSW3, ILSW[3], 32), REG_RO }, - { HRDATA (ILSW4, ILSW[4], 32), REG_RO }, - { HRDATA (ILSW5, ILSW[5], 32), REG_RO }, - -#ifdef ENABLE_1800_SUPPORT - { HRDATA (IS_1800, is_1800, 32), REG_RO|REG_HIDDEN}, /* is_1800 flag is part of state, but hidden */ - { HRDATA (XR1, XR[0], 16), REG_RO|REG_HIDDEN}, /* index registers are unhidden if CPU set to 1800 mode */ - { HRDATA (XR2, XR[1], 16), REG_RO|REG_HIDDEN}, - { HRDATA (XR3, XR[2], 16), REG_RO|REG_HIDDEN}, -#endif - - { HRDATA (ARF, ARF, 32) }, - { NULL} -}; - -MTAB cpu_mod[] = { - { UNIT_MSIZE, 4096, NULL, "4KW", &cpu_set_size}, - { UNIT_MSIZE, 8192, NULL, "8KW", &cpu_set_size}, - { UNIT_MSIZE, 16384, NULL, "16KW", &cpu_set_size}, - { UNIT_MSIZE, 32768, NULL, "32KW", &cpu_set_size}, -#ifdef ENABLE_1800_SUPPORT - { UNIT_1800, 0, "1130", "1130", &cpu_set_type}, - { UNIT_1800, UNIT_1800, "1800", "1800", &cpu_set_type}, -#endif - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 16, 1, 16, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, cpu_attach, NULL}; /* attaching to CPU creates cpu log file */ - -/* ------------------------------------------------------------------------ - * Memory read/write -- save SAR and SBR on the way in and out - * - * (It can be helpful to set breakpoints on a = 1, 2, or 3 in these routines - * to detect attempts to read/set index registers using normal memory addessing. - * APL\1130 does this in some places, I think these are why it had to be modified - * to run on the 1800. Of course not all read/write to 1, 2 or implies an attempt - * to read/set and index register -- they could using the address in the normal way). - * ------------------------------------------------------------------------ */ - -int32 ReadW (int32 a) -{ - SAR = a; - SBR = (int32) M[(a) & mem_mask]; - return SBR; -} - -void WriteW (int32 a, int32 d) -{ - SAR = a; - SBR = d; - M[a & mem_mask] = (int16) d; -} - -/* ------------------------------------------------------------------------ - * read and write index registers. On the 1130, they're in core addresses 1, 2, 3. - * on the 1800, they're separate registers - * ------------------------------------------------------------------------ */ - -static uint16 ReadIndex (int32 tag) -{ -#ifdef ENABLE_1800_SUPPORT - if (is_1800) - return XR[tag-1]; /* 1800: fetch from register */ -#endif - - SAR = tag; /* 1130: ordinary read from memory (like ReadW) */ - SBR = (int32) M[(tag) & mem_mask]; - return SBR; -} - -static void WriteIndex (int32 tag, int32 d) -{ -#ifdef ENABLE_1800_SUPPORT - if (is_1800) { - XR[tag-1] = d; /* 1800: store in register */ - return; - } -#endif - - SAR = tag; /* 1130: ordinary write to memory (same as WriteW) */ - SBR = d; - M[tag & mem_mask] = (int16) d; -} - -/* ------------------------------------------------------------------------ - * upcase - force a string to uppercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *upcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'a' && *s <= 'z') - *s -= 32; - } - - return str; -} - -/* ------------------------------------------------------------------------ - * calc_ints - set appropriate bits in int_req if any interrupts are pending on given levels - * - * int_req: - * bit 5 4 3 2 1 0 - * \ \ \ \ \ \ - * \ \ \ \ \ interrupt level 5 pending (lowest priority) - * \ . . . - * interrupt level 0 pending (highest priority) - * - * int_mask is set according to current interrupt level (ipl) - * - * 0 0 0 0 0 0 ipl = 0 (currently servicing highest priority interrupt) - * 1 0 0 0 0 0 1 - * 1 1 0 0 0 0 2 - * 1 1 1 0 0 0 3 - * 1 1 1 1 0 0 4 - * 1 1 1 1 1 0 5 (currently servicing lowest priority interrupt) - * 1 1 1 1 1 1 -1 (not servicing an interrupt) - * ------------------------------------------------------------------------ */ - -void calc_ints (void) -{ - register int i; - register int32 newbits = 0; - - GUI_BEGIN_CRITICAL_SECTION /* using critical section here so we don't mislead the GUI thread */ - - for (i = 6; --i >= 0; ) { - newbits >>= 1; - if (ILSW[i]) - newbits |= 0x20; - } - - int_req = newbits; - int_lamps |= int_req; - int_mask = (ipl < 0) ? 0xFFFF : int_masks[ipl]; /* be sure this is set correctly */ - - GUI_END_CRITICAL_SECTION -} - -/* ------------------------------------------------------------------------ - * instruction processor - * ------------------------------------------------------------------------ */ - -#define INCREMENT_IAR IAR = (IAR + 1) & mem_mask -#define DECREMENT_IAR IAR = (IAR - 1) & mem_mask - -void bail (char *msg) -{ - printf("%s\n", msg); - exit(1); -} - -static void weirdop (char *msg, int offset) -{ - printf("Weird opcode: %s at %04x\n", msg, IAR+offset); -} - -static char *xio_devs[] = { - "0?", "console", "1142card", "1134papertape", - "dsk0", "1627plot", "1132print", "switches", - "1231omr", "2501card", "comm", "b?", - "sys7", "d?", "e?", "f?", - "10?", "dsk1", "dsk2", "dsk3", - "dsk4", "dsk5", "dsk6", "dsk7+", - "18?", "2250disp", "2741attachment", "1b", - "1c?", "1d?", "1e?", "1f?" -}; - -static char *xio_funcs[] = { - "0?", "write", "read", "sense_irq", - "control", "initw", "initr", "sense" -}; - -t_stat sim_instr (void) -{ - extern int32 sim_interval; - extern UNIT *sim_clock_queue; - int32 i, eaddr, INDIR, IR, F, DSPLC, word2, oldval, newval, src, src2, dst, abit, xbit; - int32 iocc_addr, iocc_op, iocc_dev, iocc_func, iocc_mod; - char msg[50]; - int cwincount = 0, status; - static long ninstr = 0; - static char *intlabel[] = {"INT0","INT1","INT2","INT3","INT4","INT5"}; - - if (cgi) /* give CGI hook function a chance to do something */ - cgi_start(); - - if (running) /* this is definitely not reentrant */ - return -1; - - if (! power) /* this matters only to the GUI */ - return STOP_POWER_OFF; - - running = TRUE; - - mem_mask = MEMSIZE - 1; /* set other useful variables */ - calc_ints(); - - /* Main instruction fetch/decode loop */ - - reason = 0; - wait_lamp = 0; /* release lock on wait lamp */ - -#ifdef GUI_SUPPORT - update_gui(TRUE); - gui_run(TRUE); -#endif - - while (reason == 0) { - IAR &= mem_mask; - -#ifdef GUI_SUPPORT -#ifndef UPDATE_BY_TIMER -#if (UPDATE_INTERVAL > 0) - if (--cwincount <= 0) { - update_gui(FALSE); /* update console lamps only every so many instructions */ - cwincount = UPDATE_INTERVAL + (rand() % MIN(UPDATE_INTERVAL, 32)); - } -#else - update_gui(FALSE); -#endif /* ifdef UPDATE_INTERVAL */ -#endif /* ifndef UPDATE_BY_TIMER */ -#endif /* ifdef GUI_SUPPORT */ - - if (sim_interval <= 0) { /* any events timed out? */ - if (sim_clock_queue != NULL) { - if ((status = sim_process_event()) != 0) - reason = simh_status_to_stopcode(status); - - calc_ints(); - continue; - } - } - - if (int_req & int_mask) { /* any pending interrupts? */ - for (i = 0; i <= 5; i++) /* find highest pending interrupt */ - if ((int_req & int_mask) & (0x20 >> i)) - break; - - if (i >= 6) { /* nothing to do? */ - calc_ints(); /* weird. recalculate */ - continue; /* back to fetch */ - } - - GUI_BEGIN_CRITICAL_SECTION - - if (ipl >= 0) /* save previous IPL in bit stack */ - iplpending |= (0x20 >> ipl); - - ipl = i; /* set new interrupt level */ - int_mask = int_masks[i]; /* set appropriate mask */ - - GUI_END_CRITICAL_SECTION - - wait_state = 0; /* exit wait state */ - eaddr = ReadW(8+i); /* get IRQ vector */ - archive_backtrace(intlabel[i]); - WriteW(eaddr, IAR); /* save IAR */ - IAR = (eaddr+1) & mem_mask; /* go to next address */ - continue; /* now continue processing */ - } /* end if int_req */ - - if (wait_state) { /* waiting? */ - sim_interval = 0; /* run the clock out */ - - if (sim_qcount() <= (cgi ? 0 : 1)) { /* one routine queued? we're waiting for keyboard only */ - if (keyboard_is_busy()) { /* we are actually waiting for a keystroke */ - if ((status = sim_process_event()) != SCPE_OK) /* get it with wait_state still set */ - reason = simh_status_to_stopcode(status); - } - else { /* CPU is not expecting a keystroke (keyboard interrupt) */ - if (wait_state == WAIT_OP) - reason = STOP_WAIT; /* end the simulation */ - else - reason = STOP_INVALID_INSTR; - } - } - - if (gdu_active()) /* but don't stop simulator if 2250 GDU is running */ - reason = 0; - - continue; - } - - if (IAR == ibkpt_addr) { /* simulator breakpoint? */ - save_ibkpt = ibkpt_addr; /* save bkpt */ - ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */ - sim_activate(&cpu_unit, 1); /* sched re-enable after next instruction */ - reason = STOP_IBKPT; /* stop simulation */ - cwincount = 0; - continue; - } - - ninstr++; - if (cpu_unit.flags & UNIT_ATT) - trace_instruction(); /* log CPU details if logging is enabled */ - - prev_IAR = IAR; /* save IAR before incrementing it */ - - IR = ReadW(IAR); /* fetch 1st word of instruction */ - INCREMENT_IAR; - sim_interval = sim_interval - 1; /* this constitutes one tick of the simulation clock */ - - OP = (IR >> 11) & 0x1F; /* opcode */ - F = IR & 0x0400; /* format bit: 1 = long instr */ - TAG = IR & 0x0300; /* tag bits: index reg x */ - if (TAG) - TAG >>= 8; - - /* here I compute the usual effective address on the assumption that the instruction will need it. Some don't. */ - - if (F) { /* long instruction, ASSUME it's valid (have to decrement IAR if not) */ - INDIR = IR & 0x0080; /* indirect bit */ - DSPLC = IR & 0x007F; /* displacement or modifier */ - if (DSPLC & 0x0040) - DSPLC |= ~ 0x7F; /* sign extend */ - - word2 = ReadW(IAR); /* get reference address */ - INCREMENT_IAR; /* bump the instruction address register */ - - eaddr = word2; /* assume standard addressing & compute effective address */ - if (TAG) /* if indexed */ - eaddr += ReadIndex(TAG); /* add index register value */ - if (INDIR) /* if indirect addressing */ - eaddr = ReadW(eaddr); /* pick up referenced address */ - } - else { /* short instruction, use displacement */ - INDIR = 0; /* never indirect */ - DSPLC = IR & 0x00FF; /* get displacement */ - if (DSPLC & 0x0080) - DSPLC |= ~ 0xFF; - - if (TAG) /* if indexed */ - eaddr = ReadIndex(TAG) + DSPLC; /* add index register value */ - else - eaddr = IAR + DSPLC; /* otherwise relative to IAR after fetch */ - } - - switch (OP) { /* decode instruction */ - case 0x01: /* --- XIO --- */ - iocc_addr = ReadW(eaddr); /* get IOCC packet */ - iocc_op = ReadW(eaddr|1); /* note 'or' not plus, address must be even for proper operation */ - - iocc_dev = (iocc_op >> 11) & 0x001F; - iocc_func = (iocc_op >> 8) & 0x0007; - iocc_mod = iocc_op & 0x00FF; - - if (cpu_unit.flags & UNIT_ATT) - trace_io("* XIO %s %s mod %02x addr %04x", xio_funcs[iocc_func], xio_devs[iocc_dev], iocc_mod, iocc_addr); - -/* fprintf(stderr, "* XIO %s %s mod %02x addr %04x\n", xio_funcs[iocc_func], xio_devs[iocc_dev], iocc_mod, iocc_addr); */ - - ACC = 0; /* ACC is destroyed, and default XIO_SENSE_DEV result is 0 */ - - switch (iocc_func) { - case XIO_UNUSED: - sprintf(msg, "Unknown op %x on device %02x", iocc_func, iocc_dev); - xio_error(msg); - break; - - case XIO_SENSE_IRQ: /* examine current Interrupt Level Status Word */ - ACC = (ipl >= 0) ? ILSW[ipl] : 0; - break; - - default: /* perform device-specific operation */ - switch (iocc_dev) { - case 0x01: /* console keyboard and printer */ - xio_1131_console(iocc_addr, iocc_func, iocc_mod); - break; - case 0x02: /* 1142 card reader/punch */ - xio_1142_card(iocc_addr, iocc_func, iocc_mod); - break; - case 0x03: /* 1134 paper tape reader/punch */ - xio_1134_papertape(iocc_addr, iocc_func, iocc_mod); - break; - case 0x04: /* CPU disk storage */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 0); - break; - case 0x05: /* 1627 plotter */ - xio_1627_plotter(iocc_addr, iocc_func, iocc_mod); - break; - case 0x06: /* 1132 Printer */ - xio_1132_printer(iocc_addr, iocc_func, iocc_mod); - break; - case 0x07: /* console switches, stop key, run mode */ - xio_1131_switches(iocc_addr, iocc_func, iocc_mod); - break; - case 0x08: /* 1231 optical mark reader */ - xio_1231_optical(iocc_addr, iocc_func, iocc_mod); - break; - case 0x09: /* 2501 card reader */ - xio_2501_card(iocc_addr, iocc_func, iocc_mod); - break; - case 0x0a: /* synchronous comm adapter */ - xio_sca(iocc_addr, iocc_func, iocc_mod); - break; - case 0x0c: /* IBM System/7 interprocessor link */ - xio_system7(iocc_addr, iocc_func, iocc_mod); - break; - case 0x11: /* 2310 Disk Storage, Drive 1, or 2311 Disk Storage Drive. Drive 1, Disk 1 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 1); - break; - case 0x12: /* 2310 Disk Storage, Drive 2, or 2311 Disk Storage Drive. Drive 1, Disk 2 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 2); - break; - case 0x13: /* 2310 Disk Storage, Drive 3, or 2311 Disk Storage Drive. Drive 1, Disk 3 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 3); - break; - case 0x14: /* 2310 Disk Storage, Drive 4, or 2311 Disk Storage Drive. Drive 1, Disk 4 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 4); - break; - case 0x15: /* 1403 Printer */ - xio_1403_printer(iocc_addr, iocc_func, iocc_mod); - break; - case 0x16: /* 2311 Disk Storage Drive. Drive 1, Disk 5 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, -1); - break; - case 0x17: /* 2311 Disk Storage Drive, Drive 2, Disk 1 through 5 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, -1); - break; - case 0x19: /* 2250 Display Unit */ - xio_2250_display(iocc_addr, iocc_func, iocc_mod); - break; - case 0x1a: /* 2741 Attachment (nonstandard serial interface used by APL\1130 */ - xio_t2741_terminal(iocc_addr, iocc_func, iocc_mod); - break; - default: - sprintf(msg, "unknown device %02x", iocc_dev); - xio_error(msg); - break; - } - } - - calc_ints(); /* after every XIO, reset int_mask just in case */ - break; - - case 0x02: /* --- SLA,SLT,SLC,SLCA,NOP - Shift Left family --- */ - if (F) { - weirdop("Long Left Shift", -2); - DECREMENT_IAR; - } - - CCC = ((TAG == 0) ? DSPLC : ReadIndex(TAG)) & 0x003F; - ARFSET(CCC); - if (CCC == 0) - break; /* shift of zero is a NOP */ - - switch (IR & 0x00C0) { - case 0x0040: /* SLCA */ - if (TAG) { - while (CCC > 0 && (ACC & 0x8000) == 0) { - ACC <<= 1; - CCC--; - } - C = (CCC != 0); - WriteIndex(TAG, (ReadIndex(TAG) & 0xFF00) | CCC); /* put low 6 bits back into index register and zero bits 8 and 9 */ - break; - } - /* if TAG == 0, fall through and treat like normal shift SLA */ - - case 0x0000: /* SLA */ - while (CCC > 0) { - C = (ACC & 0x8000); - ACC = (ACC << 1) & 0xFFFF; - CCC--; - } - break; - - case 0x00C0: /* SLC */ - if (TAG) { - while (CCC > 0 && (ACC & 0x8000) == 0) { - abit = (EXT & 0x8000) >> 15; - ACC = ((ACC << 1) & 0xFFFF) | abit; - EXT = (EXT << 1); - CCC--; - } - C = (CCC != 0); - WriteIndex(TAG, ReadIndex(TAG) & 0xFF00 | CCC); /* put 6 bits back into low byte of index register */ - break; - } - /* if TAG == 0, fall through and treat like normal shift SLT */ - - case 0x0080: /* SLT */ - while (CCC > 0) { - C = (ACC & 0x8000); - abit = (EXT & 0x8000) >> 15; - ACC = ((ACC << 1) & 0xFFFF) | abit; - EXT = (EXT << 1) & 0xFFFF; - CCC--; - } - break; - - default: - bail("SLA switch, can't happen"); - break; - } - break; - - case 0x03: /* --- SRA, SRT, RTE - Shift Right family --- */ - if (F) { - weirdop("Long Right Shift", -2); - DECREMENT_IAR; - } - - CCC = ((TAG == 0) ? DSPLC : ReadIndex(TAG)) & 0x3F; - ARFSET(CCC); - if (CCC == 0) - break; /* NOP */ - - switch (IR & 0x00C0) { - case 0x0000: /* SRA */ - ACC = (CCC < 16) ? ((ACC & 0xFFFF) >> CCC) : 0; - CCC = 0; - break; - - case 0x0040: /* invalid */ - wait_state = WAIT_INVALID_OP; - break; - - case 0x0080: /* SRT */ - while (CCC > 0) { - xbit = (ACC & 0x0001) << 15; - abit = (ACC & 0x8000); - ACC = (ACC >> 1) & 0x7FFF | abit; - EXT = (EXT >> 1) & 0x7FFF | xbit; - CCC--; - } - break; - - case 0x00C0: /* RTE */ - while (CCC > 0) { - abit = (EXT & 0x0001) << 15; - xbit = (ACC & 0x0001) << 15; - ACC = (ACC >> 1) & 0x7FFF | abit; - EXT = (EXT >> 1) & 0x7FFF | xbit; - CCC--; - } - break; - - default: - bail("SRA switch, can't happen"); - break; - } - break; - - case 0x04: /* --- LDS - Load Status --- */ - if (F) { /* never fetches second word? */ - weirdop("Long LDS", -2); - DECREMENT_IAR; - } - - V = (DSPLC & 1); - C = (DSPLC & 2) >> 1; - break; - - case 0x05: /* --- STS - Store Status --- */ - newval = ReadW(eaddr) & 0xFF00; - if (C) - newval |= 2; - if (V) - newval |= 1; - - WriteW(eaddr, newval); - C = V = 0; /* clear flags after storing */ - break; - - case 0x06: /* --- WAIT --- */ - wait_state = WAIT_OP; - if (F) { /* what happens if we use long format? */ - weirdop("Long WAIT", -2); - DECREMENT_IAR; /* assume it wouldn't have fetched 2nd word? */ - } - break; - - case 0x08: /* --- BSI - Branch and store IAR --- */ - if (F) { - if (bsctest(IR, F)) /* do standard BSC long format testing */ - break; /* if any condition is true, do nothing */ - } - WriteW(eaddr, IAR); /* do subroutine call */ - archive_backtrace("BSI"); /* save info in back-trace buffer */ - IAR = (eaddr + 1) & mem_mask; - break; - - case 0x09: /* --- BSC - Branch and skip on Condition --- */ - if (F) { - if (bsctest(IR, F)) /* long format; any indicator cancels branch */ - break; - - archive_backtrace((DSPLC & 0x40) ? "BOSC" : "BSC"); /* save info in back-trace buffer */ - IAR = eaddr; /* no indicator means branch taken */ - } - else { /* short format: skip if any indicator hits */ - if (bsctest(IR, F)) { - archive_backtrace((DSPLC & 0x40) ? "BOSC" : "BSC"); /* save info in back-trace buffer */ - INCREMENT_IAR; - } - } -/* 27Mar02: moved this test out of the (F) condition; BOSC works even in the - * short form. The displacement field in this instruction is always the set of - * condition bits, and the interrupt clear bit doesn't collide. */ - - if (DSPLC & 0x40) { /* BOSC = exit from interrupt handler */ - exit_irq(); - cwincount = 0; - } - break; - - case 0x0c: /* --- LDX - Load Index --- */ - if (F) - eaddr = (INDIR) ? ReadW(word2) : word2; - else - eaddr = DSPLC; - - if (TAG) - WriteIndex(TAG, eaddr); - else { - archive_backtrace("LDX"); /* save info in back-trace buffer */ - IAR = eaddr; /* what happens in short form? can onlyjump to low addresses? */ - } - break; - - case 0x0d: /* --- STX - Store Index --- */ - if (F) { /* compute EA without any indexing */ - eaddr = (INDIR) ? ReadW(word2) : word2; - } - else { - eaddr = IAR + DSPLC; - } - WriteW(eaddr, TAG ? ReadIndex(TAG) : IAR); - break; - - case 0x0e: /* --- MDX - Modify Index and Skip --- */ - if (F) { /* long format: adjust memory location */ - if (TAG) { - oldval = ReadIndex(TAG); /* add word2 to index */ - newval = oldval + (INDIR ? ReadW(word2) : word2); - WriteIndex(TAG, newval); - } - else { - oldval = ReadW(word2); - DSPLC = IR & 0x00FF; /* use extended displacement (no INDIR bit, it's is part of displacement in this op) */ - if (DSPLC & 0x0080) - DSPLC |= ~ 0xFF; - newval = oldval + DSPLC; /* add modifier to @word2 */ - WriteW(word2, newval); - } - } - else { /* short format: adust IAR or index */ - if (TAG) { - oldval = ReadIndex(TAG); /* add displacement to index */ - newval = oldval + DSPLC; - WriteIndex(TAG, newval); - } - else { - oldval = IAR; /* add displacement to IAR */ - newval = IAR + DSPLC; - archive_backtrace("MDX"); - IAR = newval & mem_mask; - } - } - - if ((F || TAG) && (((newval & 0xFFFF) == 0) || ((oldval & 0x8000) != (newval & 0x8000)))) { - archive_backtrace("SKP"); - INCREMENT_IAR; /* skip if index sign change or zero */ - } - break; - - case 0x10: /* --- A - Add --- */ - /* in adds and subtracts, carry is set or cleared, overflow is set only */ - src = ReadW(eaddr); - ARFSET(src); - src2 = ACC; - ACC = (ACC + src) & 0xFFFF; - - C = ACC < src; - if (! V) - V = SIGN_BIT((~src ^ src2) & (src ^ ACC)); - break; - - case 0x11: /* --- AD - Add Double --- */ - src = ((ACC << 16) | (EXT & 0xFFFF)); - ARFSET(EXT); - src2 = (ReadW(eaddr) << 16) + ReadW(eaddr|1); - dst = src + src2; - ACC = (dst >> 16) & 0xFFFF; - EXT = dst & 0xFFFF; - - C = (uint32) dst < (uint32) src; - if (! V) - V = DWSIGN_BIT((~src ^ src2) & (src ^ dst)); - break; - - case 0x12: /* --- S - Subtract --- */ - src = ACC; - ARFSET(src); - src2 = ReadW(eaddr); - ACC = (ACC-src2) & 0xFFFF; - - C = src < src2; - if (! V) - V = SIGN_BIT((src ^ src2) & (src ^ ACC)); - break; - - case 0x13: /* --- SD - Subtract Double --- */ - src = ((ACC << 16) | (EXT & 0xFFFF)); - ARFSET(EXT); - src2 = (ReadW(eaddr) << 16) + ReadW(eaddr|1); - dst = src - src2; - ACC = (dst >> 16) & 0xFFFF; - EXT = dst & 0xFFFF; - - C = (uint32) src < (uint32) src2; - if (! V) - V = DWSIGN_BIT((src ^ src2) & (src ^ dst)); - break; - - case 0x14: /* --- M - Multiply --- */ - if ((src = ACC & 0xFFFF) & 0x8000) /* sign extend the values */ - src |= ~0xFFFF; - if ((src2 = ReadW(eaddr)) & 0x8000) - src2 |= ~0xFFFF; - - ARFSET(src2); - dst = src * src2; - ACC = (dst >> 16) & 0xFFFF; /* split the results */ - EXT = dst & 0xFFFF; - break; - - case 0x15: /* --- D - Divide --- */ - src = ((ACC << 16) | (EXT & 0xFFFF)); - if ((src2 = ReadW(eaddr)) & 0x8000) - src2 |= ~0xFFFF; /* oops: sign extend was missing, fixed 18Mar03 */ - - ARFSET(src2); - - if (src2 == 0) - V = 1; /* divide by zero just sets overflow, ACC & EXT are undefined */ - else { - ACC = (src / src2) & 0xFFFF; - EXT = (src % src2) & 0xFFFF; - } - break; - - case 0x18: /* --- LD - Load ACC --- */ - ACC = ReadW(eaddr); - break; - - case 0x19: /* --- LDD - Load Double --- */ - ACC = ReadW(eaddr); - EXT = ReadW(eaddr|1); /* notice address is |1 not +1 */ - break; - - case 0x1a: /* --- STO - Store ACC --- */ - WriteW(eaddr, ACC); - break; - - case 0x1b: /* --- STD - Store Double --- */ - WriteW(eaddr|1, EXT); - WriteW(eaddr, ACC); /* order is important: if odd addr, only ACC is stored */ - break; - - case 0x1c: /* --- AND - Logical AND --- */ - src = ReadW(eaddr); - ARFSET(src); - ACC &= src; - break; - - case 0x1d: /* --- OR - Logical OR --- */ - src = ReadW(eaddr); - ARFSET(src); - ACC |= src; - break; - - case 0x1e: /* --- EOR - Logical Excl OR --- */ - src = ReadW(eaddr); - ARFSET(src); - ACC ^= src; - break; - - case 0x16: - case 0x17: -#ifdef ENABLE_1800_SUPPORT - if (is_1800) { - if (OP == 0x16) { /* --- CMP - Compare --- */ - src = ACC; /* like subtract but result isn't stored */ - src2 = ReadW(eaddr); - dst = (ACC-src2) & 0xFFFF; - C = src < src2; - - if (dst & 0x8000) /* if ACC < operand, skip 1 instruction */ - IAR = IAR+1; - else if ((dst & 0xFFFF) == 0) /* if ACC == operand, skip 2 instructions */ - IAR = IAR+2; - } - else { /* --- DCMP - Compare Double --- */ - src = ((ACC << 16) | (EXT & 0xFFFF)); - src2 = (ReadW(eaddr) << 16) + ReadW(eaddr|1); - dst = src - src2; - C = (uint32) src < (uint32) src2; - - if (dst & 0x80000000) /* if ACC_EXT < operand, skip 1 instruction */ - IAR = IAR+1; - else if (dst == 0) /* if ACC_EXT == operand, skip 2 instructions */ - IAR = IAR+2; - } - - break; /* these are legal instructions on the 1800 */ - } -#endif - /* 1130: these are not legal instructions, fall through */ - - default: -/* all invalid instructions act like waits */ -/* case 0x00: */ -/* case 0x07: */ -/* case 0x0a: */ -/* case 0x0b: */ -/* case 0x0e: */ -/* case 0x0f: */ -/* case 0x1f: */ - wait_state = WAIT_INVALID_OP; - if (F) - DECREMENT_IAR; /* assume it wouldn't have fetched 2nd word? */ - - break; - } /* end instruction decode switch */ - - if (RUNMODE != MODE_RUN && RUNMODE != MODE_INT_RUN) - reason = STOP_WAIT; - - if (tbit && (ipl < 0)) { /* if INT_RUN mode, set IRQ5 after this instr */ - GUI_BEGIN_CRITICAL_SECTION - SETBIT(cpu_dsw, CPU_DSW_INT_RUN); - SETBIT(ILSW[5], ILSW_5_INT_RUN_PROGRAM_STOP); - int_req |= INT_REQ_5; - GUI_END_CRITICAL_SECTION - } - } /* end main loop */ - -#ifdef GUI_SUPPORT - gui_run(FALSE); -#endif - - running = FALSE; - int_lamps = 0; /* display only currently active interrupts while halted */ - - if (reason == STOP_WAIT || reason == STOP_INVALID_INSTR) { - wait_state = 0; /* on resume, don't wait */ - wait_lamp = TRUE; /* but keep the lamp lit on the GUI */ - - CLRBIT(cpu_dsw, CPU_DSW_PROGRAM_STOP); /* and on resume, reset program start bit */ - if ((cpu_dsw & CPU_DSW_PROGRAM_STOP) == 0) - CLRBIT(ILSW[5], ILSW_5_INT_RUN_PROGRAM_STOP); - } - - if (cgi) /* give CGI hook function a chance to do something */ - cgi_stop(reason); - - return reason; -} - -/* - * simh_status_to_stopcode - convert a SCPE_xxx value from sim_process_event into a STOP_xxx code - */ - -static int simh_status_to_stopcode (int status) -{ - return (status == SCPE_BREAK) ? STOP_BREAK : - (status == SCPE_STOP) ? STOP_IMMEDIATE : - (status == SCPE_STEP) ? STOP_STEP : STOP_OTHER; -} - -/* ------------------------------------------------------------------------ - * bsctest - perform standard set of condition tests. We return TRUE if any - * of the condition bits specified in DSPLC test positive, FALSE if none are true. - * If reset_V is TRUE, we reset the oVerflow flag after testing it. - * ------------------------------------------------------------------------ */ - -static t_bool bsctest (int32 DSPLC, t_bool reset_V) -{ - if (DSPLC & 0x01) { /* Overflow off (note inverted sense) */ - if (! V) - return TRUE; - else if (reset_V) /* reset after testing */ - V = 0; - } - - if (DSPLC & 0x02) { /* Carry off (note inverted sense) */ - if (! C) - return TRUE; - } - - if (DSPLC & 0x04) /* Even */ - if ((ACC & 1) == 0) - return TRUE; - - if (DSPLC & 0x08) /* Positive */ - if ((ACC & 0x8000) == 0 && ACC != 0) - return TRUE; - - if (DSPLC & 0x10) /* Negative */ - if (ACC & 0x8000) - return TRUE; - - if (DSPLC & 0x20) /* Zero */ - if ((ACC & 0xFFFF) == 0) - return TRUE; - - return FALSE; -} - -/* ------------------------------------------------------------------------ - * exit_irq - pop interrupt stack as part of return from subroutine (BOSC) - * ------------------------------------------------------------------------ */ - -static void exit_irq (void) -{ - int i, bit; - - GUI_BEGIN_CRITICAL_SECTION - - if (ipl == 5 && tbit) { /* if we are exiting an INT_RUN interrupt, clear it for the next instruction */ - CLRBIT(cpu_dsw, CPU_DSW_INT_RUN); - if ((cpu_dsw & CPU_DSW_PROGRAM_STOP) == 0) - CLRBIT(ILSW[5], ILSW_5_INT_RUN_PROGRAM_STOP); - } - - ipl = -1; /* default: return to main processor level */ - int_mask = 0xFFFF; - - if (iplpending) { /* restore previous interrupt status */ - for (i = 0, bit = 0x20; i < 6; i++, bit >>= 1) { - if (iplpending & bit) { - iplpending &= ~bit; - ipl = i; - int_mask = int_masks[i]; - break; - } - } - } - GUI_END_CRITICAL_SECTION - - calc_ints(); /* recompute pending interrupt mask */ -} /* because we probably cleared some ILSW bits before this instruction */ - -/* let a device halt the simulation */ - -void break_simulation (t_stat stopreason) -{ - reason = stopreason; -} - -/* ------------------------------------------------------------------------ - * SIMH required routines - * ------------------------------------------------------------------------ */ - -/* ------------------------------------------------------------------------ - * Reset routine - * ------------------------------------------------------------------------ */ - -t_stat cpu_reset (DEVICE *dptr) -{ - wait_state = 0; /* cancel wait */ - wait_lamp = TRUE; /* but keep the wait lamp lit on the GUI */ - - if (cpu_unit.flags & UNIT_ATT) { /* record reset in CPU log */ - fseek(cpu_unit.fileref, 0, SEEK_END); - fprintf(cpu_unit.fileref, "---RESET---" CRLF); - } - - GUI_BEGIN_CRITICAL_SECTION - - CLRBIT(cpu_dsw, CPU_DSW_PROGRAM_STOP|CPU_DSW_INT_RUN); - CLRBIT(ILSW[5], ILSW_5_INT_RUN_PROGRAM_STOP); - - reset_backtrace(); - - ipl = -1; - int_mask = 0xFFFF; - int_req = 0; /* hmmm, it SHOULD reset the int req, right? */ - int_lamps = 0; - iplpending = 0; - memset(ILSW, 0, sizeof(ILSW)); - - cpu_dsw = 0; /* clear int req and prot stop bits */ - tbit = 0; /* cancel INT_RUN mode */ - - C = V = 0; /* clear processor flags */ - IAR = SAR = SBR = 0; /* clear IAR and other registers */ - ACC = EXT = OP = TAG = CCC = C = V = 0; - - mem_mask = MEMSIZE - 1; /* wraparound mask */ - - GUI_END_CRITICAL_SECTION - - return cpu_svc(&cpu_unit); /* reset breakpoint */ -} - -/* ------------------------------------------------------------------------ - * Memory examine - * ------------------------------------------------------------------------ */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ - if (vptr == NULL) return SCPE_ARG; - - /* check this out -- save command hits it in weird way */ - /* I wish I remembered what I meant when I wrote that */ - if (addr < MEMSIZE) { - *vptr = M[addr] & 0xFFFF; - return SCPE_OK; - } - return SCPE_NXM; -} - -/* ------------------------------------------------------------------------ - * Memory deposit - * ------------------------------------------------------------------------ */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ - if (addr < MEMSIZE) { - M[addr] = (uint16) (val & 0xFFFF); - return SCPE_OK; - } - return SCPE_NXM; -} - -/* ------------------------------------------------------------------------ - * Breakpoint service - * ------------------------------------------------------------------------ */ - -t_stat cpu_svc (UNIT *uptr) -{ - if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) - ibkpt_addr = save_ibkpt; - - save_ibkpt = -1; - return SCPE_OK; -} - -/* ------------------------------------------------------------------------ - * Memory allocation - * ------------------------------------------------------------------------ */ - -t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc) -{ - t_bool used; - int32 i; - - if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 0xFFF) != 0)) - return SCPE_ARG; - - for (i = value, used = FALSE; i < (int32) MEMSIZE; i++) { - if (M[i] != 0) { - used = TRUE; - break; - } - } - - if (used && ! get_yn ("Really truncate memory [N]?", FALSE)) - return SCPE_OK; - - for (i = MEMSIZE; i < value; i++) /* clear expanded area */ - M[i] = 0; - - MEMSIZE = value; - mem_mask = MEMSIZE - 1; - - return SCPE_OK; -} - -/* processor type */ - -t_stat cpu_set_type (UNIT *uptr, int32 value, char *cptr, void *desc) -{ - REG *r; - - is_1800 = (value & UNIT_1800) != 0; /* set is_1800 mode flag */ - - for (r = cpu_reg; r->name != NULL; r++) { /* unhide or hide 1800-specific registers & state */ - if (strnicmp(r->name, "XR", 2) == 0) { - if (value & UNIT_1800) - CLRBIT(r->flags, REG_HIDDEN|REG_RO); - else - SETBIT(r->flags, REG_HIDDEN|REG_RO); - } - } - - return SCPE_OK; -} - -/* ------------------------------------------------------------------------ - * IO function for console switches - * ------------------------------------------------------------------------ */ - -void xio_1131_switches (int32 addr, int32 func, int32 modify) -{ - char msg[80]; - - switch (func) { - case XIO_READ: - WriteW(addr, CES); - break; - - case XIO_SENSE_DEV: - ACC = cpu_dsw; - break; - - default: - sprintf(msg, "Invalid console switch function %x", func); - xio_error(msg); - } -} - -/* ------------------------------------------------------------------------ - * Illegal IO operation. Not yet sure what the actual CPU does in this case - * ------------------------------------------------------------------------ */ - -void xio_error (char *msg) -{ - printf("*** XIO error at %04x: %s\n", prev_IAR, msg); - if (cgi) /* if this happens in CGI mode, probably best to halt */ - break_simulation(STOP_CRASH); -} - -/* ------------------------------------------------------------------------ - * register_cmd - add a command to the extensible command table - * ------------------------------------------------------------------------ */ - -t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help) -{ - int i; - - for (i = 0; i < MAX_EXTRA_COMMANDS; i++) { /* find end of command table */ - if (x_cmds[i].action == action) - return SCPE_OK; /* command is already there, just return */ - if (x_cmds[i].name == NULL) - break; - } - - if (i >= (MAX_EXTRA_COMMANDS-1)) { /* no more room (we need room for the NULL) */ - fprintf(stderr, "The command table is full - rebuild the simulator with more free slots\n"); - return SCPE_ARG; - } - - x_cmds[i].action = action; /* add new command */ - x_cmds[i].name = name; - x_cmds[i].arg = arg; - x_cmds[i].help = help; - - i++; - x_cmds[i].action = NULL; /* move the NULL terminator */ - x_cmds[i].name = NULL; - - return SCPE_OK; -} - -#ifdef USE_MY_ECHO_CMD -/* ------------------------------------------------------------------------ - * echo_cmd - just echo the command line - * ------------------------------------------------------------------------ */ - -static t_stat echo_cmd (int flag, char *cptr) -{ - printf("%s\n", cptr); - return SCPE_OK; -} -#endif - -/* ------------------------------------------------------------------------ - * sim_init - initialize simulator upon startup of scp, before reset - * ------------------------------------------------------------------------ */ - -void sim_init (void) -{ - sim_gui = ! (sim_switches & SWMASK('G')); /* -g means no GUI */ - - sim_vm_cmd = x_cmds; /* provide list of additional commands */ - -#ifdef GUI_SUPPORT - /* set hook routines for GUI command processing */ - if (sim_gui) { - sim_vm_read = &read_cmdline; - sim_vm_post = &update_gui; - } -#endif - -#ifdef ENABLE_BACKTRACE - /* add the BACKTRACE command */ - register_cmd("BACKTRACE", &backtrace_cmd, 0, "ba{cktrace} {n} list last n branches/skips/interrupts\n"); -#endif - - register_cmd("VIEW", &view_cmd, 0, "v{iew} filename view a text file with notepad\n"); - -#ifdef USE_MY_ECHO_CMD - register_cmd("ECHO", &echo_cmd, 0, "echo args... echo arguments passed to command\n"); -#endif -} - -/* ------------------------------------------------------------------------ - * archive_backtrace - record a jump, skip, branch or whatever - * ------------------------------------------------------------------------ */ - -#ifdef ENABLE_BACKTRACE - -#define MAXARCHIVE 16 - -static struct tag_arch { - int iar; - char *inst; -} arch[MAXARCHIVE]; -int narchived = 0, archind = 0; - -static void archive_backtrace (char *inst) -{ - static int prevind; - - if (narchived < MAXARCHIVE) - narchived++; - - if (narchived > 0 && arch[prevind].iar == prev_IAR) - return; - - arch[archind].iar = prev_IAR; - arch[archind].inst = inst; - - prevind = archind; - archind = (archind+1) % MAXARCHIVE; -} - -static void reset_backtrace (void) -{ - narchived = 0; - archind = 0; -} - -void void_backtrace (int afrom, int ato) -{ - int i; - - afrom &= mem_mask; - ato &= mem_mask; - - for (i = 0; i < narchived; i++) - if (arch[i].iar >= afrom && arch[i].iar <= ato) - arch[i].inst = "OVERWRITTEN"; -} - -static void show_backtrace (int nshow) -{ - int n = narchived, i = archind; - - if (n > nshow) n = nshow; - - while (--n >= 0) { - i = (i > 0) ? (i-1) : (MAXARCHIVE-1); - printf("from %04x (%s) ", arch[i].iar, arch[i].inst); - } - - if (narchived) - putchar('\n'); -} - -static t_stat backtrace_cmd (int32 flag, char *cptr) -{ - int n; - - if ((n = atoi(cptr)) <= 0) - n = 6; - - show_backtrace(n); - return SCPE_OK; -} -#else - -/* stub this for the disk routine */ - -void void_backtrace (int afrom, int ato) -{ -} - -#endif - -/************************************************************************************* - * CPU log routines -- attaching a file to the CPU creates a trace of instructions and register values - * - * Syntax is WEIRD: - * - * attach cpu logfile log instructions and registers to file "logfile" - * attach -f cpu cpu.log log instructions, registers and floating point acc - * attach -m cpu mapfile logfile read addresses from "mapfile", log instructions to "logfile" - * attach -f -m cpu mapfile logfile same and log floating point stuff too - * - * mapfile if specified is a list of symbols and addresses of the form: - * symbol hexval - * - * e.g. - * FSIN 082E - * FARC 09D4 - * FMPY 09A4 - * NORM 0976 - * XMDS 095A - * START 021A - * - * These values are easily obtained from a load map created by - * XEQ L - * - * The log output is of the form - * - * IAR ACC EXT (flt) XR1 XR2 XR3 CVI FAC OPERATION - * --------------- ---- ---- -------- ---- ---- ---- --- ------------- ----------------------- - * 002a 002a 1234 5381 0.14222 00b3 0236 3f7e CV 1.04720e+000 4c80 BSC I ,0028 - * 081d PAUSE+000d 1234 5381 0.14222 00b3 0236 3f7e CV 1.04720e+000 7400 MDM L 00f0,0 (0) - * 0820 PAUSE+0010 1234 5381 0.14222 00b3 0236 3f7e CV 1.04720e+000 7201 MDX 2 0001 - * 0821 PAUSE+0011 1234 5381 0.14222 00b3 0237 3f7e CV 1.04720e+000 6a03 STX 2 0003 - * 0822 PAUSE+0012 1234 5381 0.14222 00b3 0237 3f7e CV 1.04720e+000 6600 LDX L2 0231 - * 0824 PAUSE+0014 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4c00 BSC L ,0237 - * 0237 START+001d 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4480 BSI I ,3fff - * 082f FSIN +0001 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4356 BSI 3 0056 - * 3fd5 ILS01+35dd 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4c00 BSC L ,08de - * - * IAR - instruction address register value, optionally including symbol and offset - * ACC - accumulator - * EXT - extension - * flt - ACC+EXT interpreted as the mantissa of a floating pt number (value 0.5 -> 1) - * XR* - index registers - * CVI - carry, overflow and interrupt indicators - * FAC - floating point accumulator (exponent at 125+XR3, mantissa at 126+XR3 and 127+XR3) - * OP - opcode value and crude disassembly - * - * flt and FAC are displayed only when the -f flag is specified in the attach command - * The label and offset and displayed only when the -m flag is specified in the attach command - * - * The register values shown are the values BEFORE the instruction is executed. - *************************************************************************************/ - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw); - -typedef struct tag_symentry { - struct tag_symentry *next; - int addr; - char sym[6]; -} SYMENTRY, *PSYMENTRY; - -static PSYMENTRY syms = NULL; -static t_bool new_log, log_fac; - -static t_stat cpu_attach (UNIT *uptr, char *cptr) -{ - char mapfile[200], buf[200], sym[100]; - int addr; - PSYMENTRY n, prv, s; - FILE *fd; - - remove(cptr); /* delete old log file, if present */ - new_log = TRUE; - log_fac = sim_switches & SWMASK ('F'); /* display the FAC and the ACC/EXT as fixed point. */ - - for (s = syms; s != NULL; s = n) { /* free any old map entries */ - n = s->next; - free(s); - } - syms = NULL; - - if (sim_switches & SWMASK('M')) { /* use a map file to display relative addresses */ - cptr = get_glyph(cptr, mapfile, 0); - if (! *mapfile) { - printf("/m must be followed by a filename\n"); - return SCPE_ARG; - } - if ((fd = fopen(mapfile, "r")) == NULL) { - perror(mapfile); - return SCPE_OPENERR; - } - - while (fgets(buf, sizeof(buf), fd) != NULL) { /* read symbols & addresses, link in descending address order */ - if (sscanf(buf, "%s %x", sym, &addr) != 2) - continue; - if (*buf == ';') - continue; - - for (prv = NULL, s = syms; s != NULL; prv = s, s = s->next) { - if (s->addr < addr) - break; - } - - if ((n = malloc(sizeof(SYMENTRY))) == NULL) { - printf("out of memory reading map!\n"); - break; - } - - sym[5] = '\0'; - strcpy(n->sym, sym); - upcase(n->sym); - n->addr = addr; - - if (prv == NULL) { - n->next = syms; - syms = n; - } - else { - n->next = prv->next; - prv ->next = n; - } - } - fclose(fd); - } - - return attach_unit(uptr, quotefix(cptr)); /* fix quotes in filenames & attach */ -} - -static void trace_instruction (void) -{ - t_value v[2]; - float fac; - short exp; - int addr; - PSYMENTRY s; - long mant, sign; - char facstr[20], fltstr[20]; - - if ((cpu_unit.flags & UNIT_ATT) == 0) - return; - - if (new_log) { - fseek(cpu_unit.fileref, 0, SEEK_END); - new_log = FALSE; - - fprintf(cpu_unit.fileref, " IAR%s ACC EXT %s XR1 XR2 XR3 CVI %sOPERATION" CRLF, - syms ? " " : "", log_fac ? " (flt) " : "", log_fac ? " FAC " : ""); - fprintf(cpu_unit.fileref, "----%s ---- ---- %s---- ---- ---- --- %s-----------------------" CRLF, - syms ? "-----------" : "", log_fac ? "-------- " : "", log_fac ? "------------- " : ""); - } - - if (! log_fac) - facstr[0] = fltstr[0] = '\0'; - else { - mant = ((ACC & 0xFFFF) << 16) | (EXT & 0xFFFF); - if (mant == 0x80000000) { - sign = TRUE; - fac = 1.f; - } - else { - if ((sign = mant & 0x80000000) != 0) - mant = -mant; - fac = (float) mant * ((float) 1./ (float) (unsigned long) 0x80000000); - } - sprintf(fltstr, "%c%.5f ", sign ? '-' : ' ', fac); - - if (BETWEEN(M[3], 0x300, MEMSIZE-128)) { - exp = (short) ((M[M[3]+125] & 0xFF) - 128); - mant = (M[M[3]+126] << 8) | ((M[M[3]+127] >> 8) & 0xFF); - if ((sign = (mant & 0x00800000)) != 0) - mant = (-mant) & 0x00FFFFFF; - - fac = (float) mant * ((float) 1. / (float) 0x00800000); - - if (exp > 30) { - fac *= (float) (1 << 30); - exp -= 30; - while (exp > 0) - fac *= 2; - } - else if (exp > 0) - fac *= (float) (1 << exp); - else if (exp < -30) { - fac /= (float) (1 << 30); - exp += 30; - while (exp < 0) - fac /= 2; - } - else if (exp < 0) - fac /= (float) (1 << -exp); - - sprintf(facstr, "%c%.5e ", sign ? '-' : ' ', fac); - } - else - strcpy(facstr, " "); - } - - addr = IAR & 0xFFFF; - fprintf(cpu_unit.fileref, "%04x ", addr); - - if (syms) { - for (s = syms; s != NULL; s = s->next) - if (s->addr <= addr) - break; - - if (s == NULL) - fprintf(cpu_unit.fileref, " %04x ", addr); - else - fprintf(cpu_unit.fileref, "%-5s+%04x ", s->sym, addr - s->addr); - } - - fprintf(cpu_unit.fileref, "%04x %04x %s%04x %04x %04x %c%c%c %s", - ACC & 0xFFFF, EXT & 0xFFFF, fltstr, M[1] & 0xFFFF, M[2] & 0xFFFF, M[3] & 0xFFFF, - C ? 'C' : ' ', V ? 'V' : ' ', (ipl < 0) ? ' ' : (ipl+'0'), facstr); - - v[0] = M[ IAR & mem_mask]; - v[1] = M[(IAR+1) & mem_mask]; - fprint_sym(cpu_unit.fileref, IAR & mem_mask, v, NULL, SWMASK('M')); /* disassemble instruction */ - - fputs(CRLF, cpu_unit.fileref); -} - -void trace_io (char *fmt, ...) -{ - va_list args; - - if ((cpu_unit.flags & UNIT_ATT) == 0) - return; - - va_start(args, fmt); /* get pointer to argument list */ - vfprintf(cpu_unit.fileref, fmt, args); /* write errors to cpu log file */ - va_end(args); - - fputs(CRLF, cpu_unit.fileref); -} - -void trace_both (char *fmt, ...) -{ - va_list args; - - if (cpu_unit.flags & UNIT_ATT) { - va_start(args, fmt); /* get pointer to argument list */ - vfprintf(cpu_unit.fileref, fmt, args); - va_end(args); - fputs(CRLF, cpu_unit.fileref); - } - - va_start(args, fmt); /* get pointer to argument list */ - vfprintf(stdout, fmt, args); - va_end(args); - putchar('\n'); -} - -/* debugging */ - -void debug_print (char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vprintf(fmt, args); - if (cpu_unit.flags & UNIT_ATT) - vfprintf(cpu_unit.fileref, fmt, args); - va_end(args); - - if (strchr(fmt, '\n') == NULL) { /* be sure to emit a newline */ - putchar('\n'); - if (cpu_unit.flags & UNIT_ATT) - putc('\n', cpu_unit.fileref); - } -} - -#ifdef _WIN32 -#include -#endif - -/* view_cmd - let user view and/or edit a file (e.g. a printer output file, script, or source deck) */ - -static t_stat view_cmd (int32 flag, char *cptr) -{ -#ifdef _WIN32 - char cmdline[256]; - - sprintf(cmdline, "notepad %s", cptr); - WinExec(cmdline, SW_SHOWNORMAL); -#endif - return SCPE_OK; -} - -/* web server version - hooks for CGI mode. These function pointer can be set by the CGI version's main() routine */ - -void (*cgi_start_hook)(void) = NULL; /* these can be defined by a CGI wrapper to do things on start and stop of simulation */ -void (*cgi_end_hook)(void) = NULL; - -static void cgi_start (void) -{ - if (cgi_start_hook != NULL) - (*cgi_start_hook)(); -} - -static void cgi_stop (t_stat reason) -{ - if (cgi_end_hook != NULL) - (*cgi_end_hook)(); -} diff --git a/Ibm1130/ibm1130_cr.c b/Ibm1130/ibm1130_cr.c deleted file mode 100644 index 62230842..00000000 --- a/Ibm1130/ibm1130_cr.c +++ /dev/null @@ -1,2636 +0,0 @@ -#include "ibm1130_defs.h" -#include "ibm1130_fmt.h" - -#ifdef _WIN32 -# include /* Microsoft puts definition of mktemp into io.h rather than stdlib.h */ -#endif - -/* ibm1130_cr.c: IBM 1130 1442 Card Reader simulator - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - - * Update 2006-01-23 More fixes, in call to mktemp and in 2501 support, also thanks - to Carl Claunch. - - * Update 2006-01-03 Fixed bug found by Carl Claunch: feed function does not - cause an operation complete interrupt. Standard DMS routines were not - sensitive to this but DUP uses its own interrupt handler, and this - is why DUP would hang at end of deck. - - * Update 2005-05-19 Added support for 2501 reader - - * Update 2004-11-08 Merged in correct physical card reader code - - * Update 2004-11-02: Added -s to boot command: don't touch console switches. - - * Update 2004-06-05: Removed "feedcycle" from cr_reset. Reset should not touch the card reader. - - * Update 2004-04-12: Changed ascii field of CPCODE to unsigned char, caught a couple - other potential problems with signed characters used as subscript indexes. - - * Update 2003-11-25: Physical card reader support working, may not be perfect. - Changed magic filename for stdin to "(stdin)". - - * Update 2003-07-23: Added autodetect for card decks (029 vs binary), - made this the default. - - * Update 2003-06-21: Fixed bug in XIO_SENSE: op_complete and response - bits were being cleared before the DSW was saved in ACC. Somehow DMS - worked with this, but APL didn't. - - * Update 2002-02-29: Added deck-list option. - - * Update 2003-02-08: Fixed error in declaration of array list_save, pointed - out by Ray Comas. - -* ----------------------------------------------------------------------- -* USAGE NOTES -* ----------------------------------------------------------------------- - -* Attach switches: - - The ATTACH CR command accepts several command-line switches - - -q quiet mode, the simulator will not print the name of each file it opens - while processing deck files (which are discussed below). For example, - - ATTACH -q @deckfile - - -l makes the simulator convert lower case letters in text decks - to the IBM lower-case Hollerith character codes. Normally, the simulator - converts lower case input to the uppercase Hollerith character codes. - (Lowercase codes are used in APL\1130 save decks). - - -d prints a lot of simulator debugging information - - -f converts tabs in an ascii file to spaces according to Fortran column conventions - -a converts tabs in an ascii file to spaces according to 1130 Assembler column conventions - -t converts tabs in an ascii file to spaces, with tab settings every 8 columns - (See below for a discussion of tab formatting) - - -p means that filename is a COM port connected to a physical card reader using - the CARDREAD interface (see http://ibm1130.org/sim/downloads) - - The ATTACH CP command accepts the -d switch. - -* Deck lists - If you issue an attach command and specify the filename as - "@filename", the file is interpreted as a list of filenames to - be read in sequence; the effect is that the reader sees the concatenation - of all of the files listed. The simulator "reset" does NOT rewind the deck list. - - Filenames may be quoted if they contain spaces. - - The strings %1, %2, etc, if they appear, are replaced with arguments passed - on the attach command line after the name of the deckfile. These can be the - arguments to ibm1130, or to the "do" command if a "do" script is executing, if the - attach command is constructed this way: - - attach @deckfile %1 %2 %3 - - This will pass the ibm1130 or do script arguments to attach, which will make - them available in the deckfile. Then, for instance the line - - %1.for - - would be substituted accordingly. - - Blank lines and lines starting with ; # or * are ignored as comments. - - Filenames may be followed by whitespace and one or more mode options: - The mode options are: - - b forces interpration as raw binary - a forces conversion from ascii to 029 coding, tabs are left alone - af forces 029 ascii conversion, and interprets tabs in Fortran mode - aa forces 029 ascii conversion, and interprets tabs in 1130 Assembler mode - at forces 029 ascii conversion, and interprets tabs with settings every 8 spaces - - If "a" or "b" mode is not specified, the device mode setting is used. In this case, - if the mode is "auto", the simulator will select binary or 029 by inspecting each - file in turn. - - If a tab mode is not specified, tabs are left unmolested (and are treated as invalid characters) - - Example: - - attach cr @decklist - - reads filenames from file "decklist," which might contain: - - file01.for xf - file02.dat a - file03 bin b - file04 bin - - ('a' means 029, so, if you need 026 coding, specify the - device default as the correct 026 code and omit the 'a' on the text files lines). - - Literal text cards can be entered in deck files by preceding an input - line with an exclamation point. For example, - - !// JOB - !// FOR - program.for - !// XEQ - program.dat - - looks like two literal supervisor control cards, followed by the contents - of file program.for, followed by an // XEQ card, followed by the contents - of file program.dat. - - %n tokens are not replaced in literal cards. - - The line - - !BREAK - - has a special meaning: when read from a deck file, it stops the - emulator as if "IMMEDIATE STOP" was pressed. This returns control to - the command interpreter or to the current DO command script. - -* Card image format. - Card files can be ascii text or binary. There are several ASCII modes: - CODE_029, CODE_26F, etc, corresponding to different code sets. - Punch and reader modes can be set independently using - - set cr binary set cp binary * - set cr 029 set cp 029 - set cr 026f set cp 026f - set cr 026c set cp 026c - set cr auto * - - (* = default mode) - - In "auto" mode, the card reader will examine the first 160 bytes of - the deck and guess whether the card is binary or 029 text encoded. - When a deck file is used with auto mode, the simulator guesses for - each file named in the deck file. - -* Tab formatting. The attach command and deckfile entries can indicate - that tabs are to be converted to spaces, to help let you write free-form - source files. There are three tab conversion modes, which are set - with the attach command or in a decklist, as discussed earlier - - Fortran mode: - Input lines of the form - - [label]statement - - or - - [label]+continuation - - (where + is any nonalphabetic character) are rearranged in the - appropriate manner: - - 1 2 - 12345678901234567890... - ------------------------ - label statement - label+continuation - - However, you must take care that you don't end up with statement text after column 72. - - Input lines with * or C in column 1 (comments and directives) and lines without tabs - are left alone. - - (The ! escape is not used before Fortran directives as before Assembler directives) - - Assembler mode: - Input lines of the form - - [label][opcode][tag][L][argument] - - are rearranged so that the input fields are placed in the appropriate columns - - The label must start on the first character of the line. If there is no label, - the first character(s) before the opcode must be whitespace. Following the opcode, there - MUST be a tab character, followed by the format and tag. Following the format and tag - may be exactly one whitespace character, and then starts the argument. - - Input lines with * in column 1 and blank lines are turned into Assembler comments, - with the * in the Opcode field. - - Assembler directive lines at the beginning of the deck must be preceded by - ! to indicate that they are not comments. For example, - - !*LIST - * This is a comment - - Plain Tab mode: - Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide, - as is standard for vi, notepad, etc. - -* CGI mode note: The command - - attach cr (stdin) - - will attach the card reader to stdin. However, this is not compatible - with the default encoding autodetect feature, so the command must be - preceded with - - set cr 029 - -* ----------------------------------------------------------------------- -* PROGRAMMING NOTES -* ----------------------------------------------------------------------- - -NOTE - there is a problem with this code. The Device Status Word (DSW) is -computed from current conditions when requested by an XIO load status -command; the value of DSW available to the simulator's examine & save -commands may NOT be accurate. This should probably be fixed. (I think there's -a way to have the expression evaluator call a routine? That would be one -way to solve the problem, the other is to keep DSW up-to-date all the time). - - The 1442 card read/punch has several cycles: - - feed cycle: moves card from hopper to read station - card from read station to punch station - card from punch station to stacker - - read or punch: operates on card at read or punch station (but not both). - - The simulator requires input cards to be read from the file attached - to the card reader unit. A feed cycle reads one line (text mode) or - 160 bytes (binary mode) from the input file to the read station buffer, - copies the read station buffer to the punch station buffer, and if - the punch unit is attached to a file, writes the punch station buffer to - the output file. - - The read and punch cycles operate on the appropriate card buffer. - - Detaching the card punch flushes the punch station buffer if necessary. - - As does the 1442, a read or punch cycle w/o a feed cycle causes a - feed cycle first. - - A feed cycle on an empty deck (reader unattaced or at EOF) clears - the appropriate buffer, so you can punch w/o attaching a deck to - the card reader. - - (Note: Carl Claunch determined by examining DUP code that a feed cycle - does not cause an operation complete interrupt). - --- -- this may need changing depending on how things work in hardware. TBD. -|| A read cycle on an empty deck causes an error. -|| Hmmm -- what takes the place of the Start button on --- the card reader? - - Binary format is stored using fxwrite of short ints, in this format: - - 1 1 - 2 2 0 1 2 3 4 5 6 7 8 9 - * * * * * * * * * * * * 0 0 0 0 - - MSB LSB - byte 0 [ 6] [ 7] [ 8] [ 9] 0 0 0 0 - byte 1 [12] [11] [ 0] [ 1] [ 2] [ 3] [ 4] [ 5] - - This means we can read words (little endian) and get this in memory: - - 12 11 0 1 2 3 4 5 6 7 8 9 - - - - - - which is what the 1130 sees. - - ASCII can be read in blocks of 80 characters but can be terminated by newline prematurely. - - Booting: card reader IPL loads 80 columns (1 card) into memory starting - at location 0 in a split fashion: - - ________________ _ _ _ - / - 12 | - 11 | - 0 | - 1 | - 2 | - 3 | Punched card - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | - +------------------ - - - - - 12 11 0 1 2 3 4 5 6 7 8 9 <- columns of cold start card - | | | | | 0 0 0 / \ | | | | | | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15| - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | OPCODE | F| Tag | DISPLACEMENT | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The zeros mean that all IPL instructions are short form, - nonindexed. The 3 column is repeated in bits 8 and 9 so - it's a sign bit. - - Boot command on a binary deck does this. Boot on an unattached - reader loads one of the built-in boot card images. Boot with an ASCII - deck isn't allowed. -*/ - -#define READ_DELAY 35 /* see how small a number we can get away with */ -#define PUNCH_DELAY 35 -#define FEED_DELAY 25 -#define READ_2501_DELAY 500 - -/* umm, this is a weird little future project of mine. */ - -#define ENABLE_PHYSICAL_CARD_READER_SUPPORT - -extern int32 sim_switches; -extern UNIT cpu_unit; - -static t_stat cr_svc (UNIT *uptr); -static t_stat cr_reset (DEVICE *dptr); -static t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc); -static t_stat cr_attach (UNIT *uptr, char *cptr); -static int32 guess_cr_code (void); -static void feedcycle (t_bool load, t_bool punching); - -static t_stat cp_reset (DEVICE *dptr); -static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc); -static t_stat cp_attach (UNIT *uptr, char *cptr); -static t_stat cp_detach (UNIT *uptr); - -static int16 cr_dsw = 0; /* device status word */ -static int32 cr_wait = READ_DELAY; /* read per-column wait */ -static int32 cr_wait2501 = READ_2501_DELAY; /* read card wait for 2501 reader */ -static int32 cf_wait = PUNCH_DELAY; /* punch per-column wait */ -static int32 cp_wait = FEED_DELAY; /* feed op wait */ -static int32 cr_count= 0; /* read and punch card count */ -static int32 cp_count= 0; -static int32 cr_addr = 0; /* 2501 reader transfer address */ -static int32 cr_cols = 0; /* 2501 reader column count */ - -#define UNIT_V_OPERATION (UNIT_V_UF + 0) /* operation in progress */ -#define UNIT_V_CODE (UNIT_V_UF + 2) /* three bits */ -#define UNIT_V_CR_EMPTY (UNIT_V_UF + 5) /* NOTE: THIS MUST BE SET IN ibm1130_gui.c too */ -#define UNIT_V_SCRATCH (UNIT_V_UF + 6) -#define UNIT_V_QUIET (UNIT_V_UF + 7) -#define UNIT_V_DEBUG (UNIT_V_UF + 8) -#define UNIT_V_PHYSICAL (UNIT_V_UF + 9) /* NOTE: THIS MUST BE SET IN ibm1130_gui.c too */ -#define UNIT_V_LASTPUNCH (UNIT_V_UF + 10) /* used in unit_cp only */ -#define UNIT_V_LOWERCASE (UNIT_V_UF + 10) /* used in unit_cr only */ -#define UNIT_V_ACTCODE (UNIT_V_UF + 11) /* used in unit_cr only, 3 bits */ -#define UNIT_V_2501 (UNIT_V_UF + 14) - -#define UNIT_OP (3u << UNIT_V_OPERATION) /* two bits */ -#define UNIT_CODE (7u << UNIT_V_CODE) /* three bits */ -#define UNIT_CR_EMPTY (1u << UNIT_V_CR_EMPTY) -#define UNIT_SCRATCH (1u << UNIT_V_SCRATCH) /* temp file */ -#define UNIT_QUIET (1u << UNIT_V_QUIET) -#define UNIT_DEBUG (1u << UNIT_V_DEBUG) -#define UNIT_PHYSICAL (1u << UNIT_V_PHYSICAL) -#define UNIT_LASTPUNCH (1u << UNIT_V_LASTPUNCH) -#define UNIT_LOWERCASE (1u << UNIT_V_LOWERCASE) /* permit lowercase input (needed for APL) */ -#define UNIT_ACTCODE (7u << UNIT_V_ACTCODE) -#define UNIT_2501 (1u << UNIT_V_2501) - -#define OP_IDLE (0u << UNIT_V_OPERATION) -#define OP_READING (1u << UNIT_V_OPERATION) -#define OP_PUNCHING (2u << UNIT_V_OPERATION) -#define OP_FEEDING (3u << UNIT_V_OPERATION) - -#define SET_OP(op) {cr_unit.flags &= ~UNIT_OP; cr_unit.flags |= (op);} -#define CURRENT_OP (cr_unit.flags & UNIT_OP) - -#define CODE_AUTO (0u << UNIT_V_CODE) -#define CODE_029 (1u << UNIT_V_CODE) -#define CODE_026F (2u << UNIT_V_CODE) -#define CODE_026C (3u << UNIT_V_CODE) -#define CODE_BINARY (4u << UNIT_V_CODE) - -#define GET_CODE(un) (un.flags & UNIT_CODE) -#define SET_CODE(un,cd) {un.flags &= ~UNIT_CODE; un.flags |= (cd);} - -#define ACTCODE_029 (CODE_029 << (UNIT_V_ACTCODE-UNIT_V_CODE)) /* these are used ONLY in MTAB. Elsewhere */ -#define ACTCODE_026F (CODE_026F << (UNIT_V_ACTCODE-UNIT_V_CODE)) /* we use values CODE_xxx with macros */ -#define ACTCODE_026C (CODE_026C << (UNIT_V_ACTCODE-UNIT_V_CODE)) /* GET_ACTCODE and SET_ACTCODE. */ -#define ACTCODE_BINARY (CODE_BINARY << (UNIT_V_ACTCODE-UNIT_V_CODE)) - - /* get/set macros for actual-code field, these use values like CODE_029 meant for the UNIT_CODE field */ -#define GET_ACTCODE(un) ((un.flags & UNIT_ACTCODE) >> (UNIT_V_ACTCODE-UNIT_V_CODE)) -#define SET_ACTCODE(un,cd) {un.flags &= ~UNIT_ACTCODE; un.flags |= (cd) << (UNIT_V_ACTCODE-UNIT_V_CODE);} - -#define COLUMN u4 /* column field in unit record */ - -UNIT cr_unit = { UDATA (&cr_svc, UNIT_ATTABLE|UNIT_ROABLE|UNIT_CR_EMPTY, 0) }; -UNIT cp_unit = { UDATA (NULL, UNIT_ATTABLE, 0) }; - -MTAB cr_mod[] = { - { UNIT_CODE, CODE_029, "029", "029", &cr_set_code}, - { UNIT_CODE, CODE_026F, "026F", "026F", &cr_set_code}, - { UNIT_CODE, CODE_026C, "026C", "026C", &cr_set_code}, - { UNIT_CODE, CODE_BINARY, "BINARY", "BINARY", &cr_set_code}, - { UNIT_CODE, CODE_AUTO, "AUTO", "AUTO", &cr_set_code}, - { UNIT_ACTCODE, ACTCODE_029, "(029)", NULL, NULL}, /* display-only, shows current mode */ - { UNIT_ACTCODE, ACTCODE_026F, "(026F)", NULL, NULL}, - { UNIT_ACTCODE, ACTCODE_026C, "(026C)", NULL, NULL}, - { UNIT_ACTCODE, ACTCODE_BINARY, "(BINARY)", NULL, NULL}, - { UNIT_2501, 0, "1442", "1442", NULL}, - { UNIT_2501, UNIT_2501, "2501", "2501", NULL}, - { 0 } }; - -MTAB cp_mod[] = { - { UNIT_CODE, CODE_029, "029", "029", &cp_set_code}, - { UNIT_CODE, CODE_026F, "026F", "026F", &cp_set_code}, - { UNIT_CODE, CODE_026C, "026C", "026C", &cp_set_code}, - { UNIT_CODE, CODE_BINARY, "BINARY", "BINARY", &cp_set_code}, - { 0 } }; - -REG cr_reg[] = { - { HRDATA (CRDSW, cr_dsw, 16) }, /* device status word */ - { DRDATA (CRTIME, cr_wait, 24), PV_LEFT }, /* operation wait for 1442 column read*/ - { DRDATA (2501TIME, cr_wait2501, 24), PV_LEFT }, /* operation wait for 2501 whole card read*/ - { DRDATA (CFTIME, cf_wait, 24), PV_LEFT }, /* operation wait */ - { DRDATA (CRCOUNT, cr_count, 32),PV_LEFT }, /* number of cards read since last attach cmd */ - { HRDATA (CRADDR, cr_addr, 32) }, /* 2501 reader transfer address */ - { HRDATA (CRCOLS, cr_cols, 32) }, /* 2501 reader column count */ - { NULL } }; - -REG cp_reg[] = { - { DRDATA (CPTIME, cp_wait, 24), PV_LEFT }, /* operation wait */ - { DRDATA (CPCOUNT, cp_count, 32),PV_LEFT }, /* number of cards punched since last attach cmd */ - { NULL } }; - -DEVICE cr_dev = { - "CR", &cr_unit, cr_reg, cr_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, cr_reset, - cr_boot, cr_attach, cr_detach}; - -DEVICE cp_dev = { - "CP", &cp_unit, cp_reg, cp_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, cp_reset, - NULL, cp_attach, cp_detach}; - -#define CR_DSW_1442_READ_RESPONSE 0x8000 /* device status word bits */ -#define CR_DSW_1442_PUNCH_RESPONSE 0x4000 -#define CR_DSW_1442_ERROR_CHECK 0x2000 -#define CR_DSW_1442_LAST_CARD 0x1000 -#define CR_DSW_1442_OP_COMPLETE 0x0800 -#define CR_DSW_1442_FEED_CHECK 0x0100 -#define CR_DSW_1442_BUSY 0x0002 -#define CR_DSW_1442_NOT_READY 0x0001 - -#define CR_DSW_2501_ERROR_CHECK 0x2000 /* DSW for 2501 reader */ -#define CR_DSW_2501_LAST_CARD 0x1000 -#define CR_DSW_2501_OP_COMPLETE 0x0800 -#define CR_DSW_2501_BUSY 0x0002 -#define CR_DSW_2501_NOT_READY 0x0001 - -typedef struct { - uint16 hollerith; - unsigned char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', /* + in 026 Fortran */ - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', /* = in 026 Fortran */ - 0x0220, '@', /* ' in 026 Fortran */ - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, (unsigned char) '\xA2', /* cent, in MS-DOS encoding (this is in guess_cr_code as well) */ - 0x8420, '.', - 0x8220, '<', /* ) in 026 Fortran */ - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, (unsigned char) '\xAC', /* not, in MS-DOS encoding (this is in guess_cr_code as well) */ - 0x2420, ',', - 0x2220, '%', /* ( in 026 Fortran */ - 0x2120, '_', - 0x20A0, '>', - 0xB000, 'a', - 0xA800, 'b', - 0xA400, 'c', - 0xA200, 'd', - 0xA100, 'e', - 0xA080, 'f', - 0xA040, 'g', - 0xA020, 'h', - 0xA010, 'i', - 0xD000, 'j', - 0xC800, 'k', - 0xC400, 'l', - 0xC200, 'm', - 0xC100, 'n', - 0xC080, 'o', - 0xC040, 'p', - 0xC020, 'q', - 0xC010, 'r', - 0x6800, 's', - 0x6400, 't', - 0x6200, 'u', - 0x6100, 'v', - 0x6080, 'w', - 0x6040, 'x', - 0x6020, 'y', - 0x6010, 'z', /* these odd punch codes are used by APL: */ - 0x1010, '\001', /* no corresponding ASCII using ^A */ - 0x0810, '\002', /* SYN using ^B */ - 0x0410, '\003', /* no corresponding ASCII using ^C */ - 0x0210, '\004', /* PUNCH ON using ^D */ - 0x0110, '\005', /* READER STOP using ^E */ - 0x0090, '\006', /* UPPER CASE using ^F */ - 0x0050, '\013', /* EOT using ^K */ - 0x0030, '\016', /* no corresponding ASCII using ^N */ - 0x1030, '\017', /* no corresponding ASCII using ^O */ - 0x0830, '\020', /* no corresponding ASCII using ^P */ -}; - -static CPCODE cardcode_026F[] = /* 026 fortran */ -{ - 0x0000, ' ', - 0x8000, '+', - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0420, '=', - 0x0220, '\'', - 0x8420, '.', - 0x8220, ')', - 0x4420, '$', - 0x4220, '*', - 0x2420, ',', - 0x2220, '(', -}; - -static CPCODE cardcode_026C[] = /* 026 commercial */ -{ - 0x0000, ' ', - 0x8000, '+', - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0420, '=', - 0x0220, '\'', - 0x8420, '.', - 0x8220, ')', - 0x4420, '$', - 0x4220, '*', - 0x2420, ',', - 0x2220, '(', -}; - -extern int cgi; -extern void sub_args (char *instr, char *tmpbuf, int32 maxstr, int32 nargs, char *arg[]); - -static int16 ascii_to_card[256]; - -static CPCODE *cardcode; -static int ncardcode; -static FILE *deckfile = NULL; -static char tempfile[128]; -static int any_punched = 0; - -#define MAXARGLEN 80 /* max length of a saved attach command argument */ -#define MAXARGS 10 /* max number of arguments to save */ -static char list_save[MAXARGS][MAXARGLEN], *list_arg[MAXARGLEN]; -static int list_nargs = 0; -static char* (*tab_proc)(char*) = NULL; /* tab reformatting routine */ - -static uint16 punchstation[80]; -static uint16 readstation[80]; -static enum {STATION_EMPTY, STATION_LOADED, STATION_READ, STATION_PUNCHED} punchstate = STATION_EMPTY, readstate = STATION_EMPTY; - -static t_bool nextdeck (void); -static void checkdeck (void); - -static t_stat pcr_attach(UNIT *uptr, char *devname); -static t_stat pcr_detach(UNIT *uptr); -static t_stat pcr_svc(UNIT *uptr); -static void pcr_xio_sense(int modify); -static void pcr_xio_feedcycle(void); -static void pcr_xio_startread(void); -static void pcr_reset(void); - -/* lookup_codetable - use code flag setting to get code table pointer and length */ - -static t_bool lookup_codetable (int32 match, CPCODE **pcode, int *pncode) -{ - switch (match) { - case CODE_029: - *pcode = cardcode_029; - *pncode = sizeof(cardcode_029) / sizeof(CPCODE); - break; - - case CODE_026F: - *pcode = cardcode_026F; - *pncode = sizeof(cardcode_026F) / sizeof(CPCODE); - break; - - case CODE_026C: - *pcode = cardcode_026C; - *pncode = sizeof(cardcode_026C) / sizeof(CPCODE); - break; - - case CODE_BINARY: - *pcode = NULL; - *pncode = 0; - break; - - default: - printf("Eek! Undefined code table index"); - return FALSE; - } - return TRUE; -} - -t_stat set_active_cr_code (int match) -{ - CPCODE *code; - int i, ncode; - - SET_ACTCODE(cr_unit, match); - - if (! lookup_codetable(match, &code, &ncode)) - return SCPE_ARG; - - memset(ascii_to_card, 0, sizeof(ascii_to_card)); - - for (i = 0; i < ncode; i++) /* set ascii to card code table */ - ascii_to_card[code[i].ascii] = code[i].hollerith; - - return SCPE_OK; -} - -static t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc) -{ - if (match == CODE_AUTO) - match = guess_cr_code(); - - return set_active_cr_code(match); -} - -static int32 guess_cr_code (void) -{ - int i; - long filepos; - int32 guess; - union { - uint16 w[80]; /* one card image, viewed as 80 short words */ - char c[160]; /* same, viewed as 160 characters */ - } line; - - /* here, we can see if the attached file is binary or ascii and auto-set the - * mode. If we the file is a binary deck, we should be able to read a record of 80 short - * words, and the low 4 bits of each word must be zero. If the file was an ascii deck, - * then these low 4 bits are the low 4 bits of every other character in the first 160 - * chararacters of the file. They would all only be 0 if all of these characters were - * in the following set: {NUL ^P space 0 @ P ` p} . It seems very unlikely that - * this would happen, as even if the deck consisted of untrimmed card images and - * the first two lines were blank, the 81'st character would be a newline, and it would - * appear at one of the every-other characters seen on little-endian machines, anyway. - * So: if the code mode is AUTO, we can use this test and select either BINARY or 029. - * Might as well also check for the all-blanks and newlines case in case this is a - * big-endian machine. - */ - - - guess = CODE_029; /* assume ASCII, 029 */ - - if ((cr_unit.flags & UNIT_ATT) && (cr_unit.fileref != NULL)) { - filepos = ftell(cr_unit.fileref); /* remember current position in file */ - fseek(cr_unit.fileref, 0, SEEK_SET); /* go to first record of file */ - /* read card image; if file too short, leave guess set to 029 */ - if (fxread(line.w, sizeof(line.w[0]), 80, cr_unit.fileref) == 80) { - guess = CODE_BINARY; /* we got a card image, assume binary */ - - for (i = 0; i < 80; i++) { /* make sure low bits are zeroes, which our binary card format promises */ - if (line.w[i] & 0x000F) { - guess = CODE_029; /* low bits set, must be ascii text */ - break; - } - } - - if (guess == CODE_BINARY) { /* if we saw no low bits, it could have been all spaces. */ - guess = CODE_029; /* so now assume file is text */ - for (i = 0; i < 160; i++) { /* ensure all 160 characters are 7-bit ASCII (or not or cent) */ - /* 3.0-3, changed test for > 0x7f to & 0x80 */ - if ((strchr("\r\n\t\xA2\xAC", line.c[i]) == NULL) && ((line.c[i] < ' ') || (line.c[i] & 0x80))) { - guess = CODE_BINARY; /* oops, null or weird character, it's binary after all */ - break; - } - } - } - } - - fseek(cr_unit.fileref, filepos, SEEK_SET); /* return to original position */ - } - - return guess; -} - -static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc) -{ - CPCODE *code; - int ncode; - - if (! lookup_codetable(match, &code, &ncode)) - return SCPE_ARG; - - cardcode = code; /* save code table for punch output */ - ncardcode = ncode; - - return SCPE_OK; -} - -t_stat load_cr_boot (int drvno, int switches) -{ - int i; - char *name, msg[80]; - t_bool expand; - uint16 word, *boot; - static uint16 dms_boot_data[] = { /* DMSV2M12, already expanded to 16 bits */ - 0xc80a, 0x18c2, 0xd008, 0xc019, 0x8007, 0xd017, 0xc033, 0x100a, - 0xd031, 0x7015, 0x000c, 0xe800, 0x0020, 0x08f8, 0x4828, 0x7035, - 0x70fa, 0x4814, 0xf026, 0x2000, 0x8800, 0x9000, 0x9800, 0xa000, - 0xb000, 0xb800, 0xb810, 0xb820, 0xb830, 0xb820, 0x3000, 0x08ea, - 0xc0eb, 0x4828, 0x70fb, 0x9027, 0x4830, 0x70f8, 0x8001, 0xd000, - 0xc0f4, 0xd0d9, 0xc01d, 0x1804, 0xe8d6, 0xd0d9, 0xc8e3, 0x18d3, - 0xd017, 0x18c4, 0xd0d8, 0x9016, 0xd815, 0x90db, 0xe8cc, 0xd0ef, - 0xc016, 0x1807, 0x0035, 0x00d0, 0xc008, 0x1803, 0xe8c4, 0xd00f, - 0x080d, 0x08c4, 0x1003, 0x4810, 0x70d9, 0x3000, 0x08df, 0x3000, - 0x7010, 0x00d1, 0x0028, 0x000a, 0x70f3, 0x0000, 0x00d0, 0xa0c0 - }; - static uint16 apl_boot_data[] = { /* APLIPL, already expanded */ - 0x7021, 0x3000, 0x7038, 0xa0c0, 0x0002, 0x4808, 0x0003, 0x0026, - 0x0001, 0x0001, 0x000c, 0x0000, 0x0000, 0x0800, 0x48f8, 0x0027, - 0x7002, 0x08f2, 0x3800, 0xe0fe, 0x18cc, 0x100e, 0x10c1, 0x4802, - 0x7007, 0x4828, 0x7005, 0x4804, 0x7001, 0x70f3, 0x08e7, 0x70e1, - 0x08ed, 0x70f1, 0xc0e0, 0x1807, 0xd0de, 0xc0df, 0x1801, 0xd0dd, - 0x800d, 0xd00c, 0xc0e3, 0x1005, 0xe80a, 0xd009, 0xc0d8, 0x1008, - 0xd0d6, 0xc0dd, 0x1008, 0x80d4, 0xd0da, 0x1000, 0xb000, 0x00f6, - 0x70e7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x9000, 0x4004, 0x40c0, 0x8001, 0x4004, 0x40c0, 0x0000, 0x0000 }; - static uint16 aplp_boot_data[] = { /* APLIPL Privileged, already expanded */ - 0x7021, 0x3000, 0x7038, 0xa0c0, 0x0002, 0x4808, 0x0003, 0x0026, - 0x0001, 0x0001, 0x000c, 0x0000, 0x0000, 0x0800, 0x48f8, 0x0027, - 0x7002, 0x08f2, 0x3800, 0xe0fe, 0x18cc, 0x100e, 0x10c1, 0x4802, - 0x7007, 0x4828, 0x7005, 0x4804, 0x7001, 0x70f3, 0x08e7, 0x70e1, - 0x08ed, 0x70f1, 0xc0e0, 0x1807, 0xd0de, 0xc0df, 0x1801, 0xd0dd, - 0x800d, 0xd00c, 0xc0e3, 0x1005, 0xe80a, 0xd009, 0xc0d8, 0x1008, - 0xd0d6, 0xc0dd, 0x1008, 0x80d4, 0xd0da, 0x1002, 0xb000, 0x00f6, - 0x70e7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x9000, 0x4004, 0x40c0, 0x8001, 0x4004, 0x40c0, 0x4004, 0x4001 - }; - - if ((switches & SWMASK('A')) && (switches & SWMASK('P'))) { - boot = aplp_boot_data; - name = "APL\\1130 Privileged"; - expand = FALSE; - } - else if (switches & SWMASK('A')) { - boot = apl_boot_data; - name = "APL\\1130"; - expand = FALSE; - } - else { - boot = dms_boot_data; - name = "DMS V2M12"; - expand = FALSE; - } - - if (drvno >= 0 && ! (switches & SWMASK('S'))) /* if specified, set toggle switches to disk drive no */ - CES = drvno; /* so BOOT DSK1 will work correctly (DMS boot uses this) */ - /* but do not touch switches if -S was specified */ - - IAR = 0; /* clear IAR */ - - for (i = 0; i < 80; i++) { /* store the boot image to core words 0..79 */ - word = boot[i]; /* expanding the 12-bit card data to 16 bits if not already expanded */ - if (expand) - word = (word & 0xF800) | ((word & 0x0400) ? 0x00C0 : 0x0000) | ((word & 0x03F0) >> 4); - - WriteW(i, word); - } - /* quiet switch or CGI mode inhibit the boot remark */ - if (((switches & SWMASK('Q')) == 0) && ! cgi) { /* 3.0-3, parenthesized & operation, per lint check */ - sprintf(msg, "Loaded %s cold start card\n", name); - -#ifdef GUI_SUPPORT - remark_cmd(msg); -#else - printf("%s", msg); -#endif - } - - return SCPE_OK; -} - -t_stat cr_boot (int32 unitno, DEVICE *dptr) -{ - t_stat rval; - int i; - - if ((rval = reset_all(0)) != SCPE_OK) - return rval; - - if (! (cr_unit.flags & UNIT_ATT)) /* no deck; load standard boot anyway */ - return load_cr_boot(-1, 0); - - if (GET_ACTCODE(cr_unit) != CODE_BINARY) { - printf("Can only boot from card reader when set to BINARY mode"); - return SCPE_IOERR; - } - - if (cr_unit.fileref == NULL) /* this will happen if no file in deck file can be opened */ - return SCPE_IOERR; - - feedcycle(TRUE, FALSE); - -/* if (fxread(buf, sizeof(buf[0]), 80, cr_unit.fileref) != 80) */ -/* return SCPE_IOERR; */ - - IAR = 0; /* Program Load sets IAR = 0 */ - - for (i = 0; i < 80; i++) /* shift 12 bits into 16 */ - WriteW(i, (readstation[i] & 0xF800) | ((readstation[i] & 0x0400) ? 0x00C0 : 0x0000) | ((readstation[i] & 0x03F0) >> 4)); - - return SCPE_OK; -} - -char card_to_ascii (uint16 hol) -{ - int i; - - for (i = 0; i < ncardcode; i++) - if (cardcode[i].hollerith == hol) - return (char) cardcode[i].ascii; - - return '?'; -} - -/* hollerith_to_ascii - provide a generic conversion for simulator debugging */ - -char hollerith_to_ascii (uint16 hol) -{ - int i; - - for (i = 0; i < ncardcode; i++) - if (cardcode_029[i].hollerith == hol) - return (char) cardcode[i].ascii; - - return ' '; -} - -/* feedcycle - move cards to next station */ - -static void feedcycle (t_bool load, t_bool punching) -{ - char buf[84], *x, *result; - int i, nread, nwrite, ch; - - /* write punched card if punch is attached to a file */ - if (cp_unit.flags & UNIT_ATT) { - if (any_punched && punchstate != STATION_EMPTY) { - if (GET_CODE(cp_unit) == CODE_BINARY) { - fxwrite(punchstation, sizeof(punchstation[0]), 80, cp_unit.fileref); - } - else { - for (i = 80; --i >= 0; ) { /* find last nonblank column */ - if (punchstation[i] != 0) - break; - } - - /* i is now index of last character to output or -1 if all blank */ - - for (nwrite = 0; nwrite <= i; nwrite++) { /* convert characters */ - buf[nwrite] = card_to_ascii(punchstation[nwrite]); - } - - /* nwrite is now number of characters to output */ - -#ifdef WIN32 - buf[nwrite++] = '\r'; /* add CR before NL for microsoft */ -#endif - buf[nwrite++] = '\n'; /* append newline */ - fxwrite(buf, sizeof(char), nwrite, cp_unit.fileref); - } - } - - cp_count++; - } - - if (! load) /* all we wanted to do was flush the punch */ - return; - - /* slide cards from reader to punch. If we know we're punching, - * generate a blank card in any case. Otherwise, it should take two feed - * cycles to get a read card from the hopper to punch station. Also when - * the reader is a 2501, we assume the 1442 is a punch only */ - - if (readstate == STATION_EMPTY || (cr_unit.flags & UNIT_2501)) { - if (punching) { - memset(punchstation, 0, sizeof(punchstation)); - punchstate = STATION_LOADED; - } - else - punchstate = STATION_EMPTY; - } - else { - memcpy(punchstation, readstation, sizeof(punchstation)); - punchstate = STATION_LOADED; - } - - /* load card into read station */ - -again: /* jump here if we've loaded a new deck after emptying the previous one */ - - if (cr_unit.flags & UNIT_ATT) { - - memset(readstation, 0, sizeof(readstation)); /* blank out the card image */ - - if (cr_unit.fileref == NULL) - nread = 0; - - else if (GET_ACTCODE(cr_unit) == CODE_BINARY) /* binary read is straightforward */ - nread = fxread(readstation, sizeof(readstation[0]), 80, cr_unit.fileref); - - else if (fgets(buf, sizeof(buf), cr_unit.fileref) == NULL) /* read up to 80 chars */ - nread = 0; /* hmm, end of file */ - - else { /* check for CRLF or newline */ - if ((x = strchr(buf, '\r')) == NULL) - x = strchr(buf, '\n'); - - if (x == NULL) { /* there were no delimiters, burn rest of line */ - while ((ch = getc(cr_unit.fileref)) != EOF) { /* get character */ - if (ch == '\n') /* newline, done */ - break; - - if (ch == '\r') { /* CR, try to take newline too */ - ch = getc(cr_unit.fileref); - if (ch != EOF && ch != '\n') /* hmm, put it back */ - ungetc(ch, cr_unit.fileref); - - break; - } - } - if ((nread = strlen(buf)) > 80) /* use the line as read, at most 80 characters */ - nread = 80; - } - else - nread = x-buf; /* reduce length of string */ - - if (! (cr_unit.flags & UNIT_LOWERCASE)) - upcase(buf); /* force uppercase */ - - if (tab_proc != NULL) { /* apply tab editing, if specified */ - buf[nread] = '\0'; /* .. be sure string is terminated */ - result = (*tab_proc)(buf); /* .. convert tabs spaces */ - nread = strlen(result); /* .. set new read length */ - } - else - result = buf; - - for (i = 0; i < nread; i++) /* convert ascii to punch code */ - readstation[i] = ascii_to_card[(unsigned char) result[i]]; - - nread = 80; /* even if line was blank consider it present */ - } - - if (nread <= 0) { /* set hopper flag accordingly */ - if (deckfile != NULL && nextdeck()) - goto again; - - if (punching) /* pretend we loaded a blank card */ - nread = 80; - } - - if (nread == 0) { - SETBIT(cr_unit.flags, UNIT_CR_EMPTY); - readstate = STATION_EMPTY; - cr_count = -1; /* nix the card counter */ - } - else { - CLRBIT(cr_unit.flags, UNIT_CR_EMPTY); - readstate = STATION_LOADED; - cr_count++; - cr_unit.pos++; - } - } -/* else */ -/* readstate = STATION_EMPTY; */ - - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - cp_unit.COLUMN = -1; -} - -#ifdef NO_USE_FOR_THIS_CURRENTLY - -/* this routine should probably be hooked up to the GUI somehow */ - -/* NPRO - nonprocess runout, flushes out the reader/punch */ - -static void npro (void) -{ - if (cr_unit.flags & UNIT_ATT) - fseek(cr_unit.fileref, 0, SEEK_END); /* push reader to EOF */ - if (deckfile != NULL) - fseek(deckfile, 0, SEEK_END); /* skip to end of deck list */ - - cr_count = -1; /* nix the card counter */ - - if (punchstate == STATION_PUNCHED) - feedcycle(FALSE, FALSE); /* flush out card just punched */ - - readstate = punchstate = STATION_EMPTY; - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - cp_unit.COLUMN = -1; - SETBIT(cr_unit.flags, UNIT_CR_EMPTY); /* set hopper empty */ -} - -#endif - -/* skipbl - skip leading whitespace in a string */ - -static char * skipbl (char *str) -{ - while (*str && *str <= ' ') - str++; - - return str; -} - -static char * trim (char *str) -{ - char *s, *lastnb; - - for (lastnb = str-1, s = str; *s; s++) /* point to last nonblank characteter in string */ - if (*s > ' ') - lastnb = s; - - lastnb[1] = '\0'; /* clip just after it */ - - return str; -} - -/* alltrim - remove all leading and trailing whitespace from a string */ - -static char * alltrim (char *str) -{ - char *s, *lastnb; - - if ((s = skipbl(str)) != str) /* slide down over leading whitespace */ - strcpy(str, s); - - for (lastnb = str-1, s = str; *s; s++) /* point to last nonblank characteter in string */ - if (*s > ' ') - lastnb = s; - - lastnb[1] = '\0'; /* clip just after it */ - - return str; -} - -/* checkdeck - set hopper empty status based on condition of current reader file */ - -static void checkdeck (void) -{ - t_bool empty; - - if (cr_unit.fileref == NULL) { /* there is no open file */ - empty = TRUE; - } - else { - fseek(cr_unit.fileref, 0, SEEK_END); /* seek to end of file */ - empty = ftell(cr_unit.fileref) <= 0; /* file is empty if there was nothing in it*/ - cr_count = 0; /* reset card counter */ - cr_unit.pos = 0; - fseek(cr_unit.fileref, 0, SEEK_SET); /* rewind deck */ - } - - if (empty) { - SETBIT(cr_unit.flags, UNIT_CR_EMPTY); - if (cr_unit.fileref != NULL) /* real file but it's empty, hmmm, try another */ - nextdeck(); - } - else { - CLRBIT(cr_unit.flags, UNIT_CR_EMPTY); - } -} - -/* nextdeck - attempt to load a new file from the deck list into the hopper */ - -static t_bool nextdeck (void) -{ - char buf[200], tmpbuf[200], *fname, *c, quote, *mode; - int code; - long fpos; - - cr_count = 0; /* clear read count */ - cr_unit.pos = 0; - - if (deckfile == NULL) /* we can't help */ - return FALSE; - - code = GET_CODE(cr_unit); /* default code as set */ - - if (cr_unit.fileref != NULL) { /* this pulls the rug out from under scp */ - fclose(cr_unit.fileref); /* since the attach flag is still set. be careful! */ - cr_unit.fileref = NULL; - - if (cr_unit.flags & UNIT_SCRATCH) { - remove(tempfile); - CLRBIT(cr_unit.flags, UNIT_SCRATCH); - } - } - - for (;;) { /* get a filename */ - tab_proc = NULL; /* default: no tab editing */ - - if (fgets(buf, sizeof(buf), deckfile) == NULL) - break; /* oops, no more names */ - - alltrim(buf); /* remove leading and trailing spaces */ - - if (! *buf) - continue; /* empty line */ - - if (*buf == '#' || *buf == '*' || *buf == ';') - continue; /* comment */ - - if (strnicmp(buf, "!BREAK", 6) == 0) { /* stop the simulation */ - break_simulation(STOP_DECK_BREAK); - continue; - } - - if (buf[0] == '!') { /* literal text line, make a temporary file */ - -#if defined (__GNUC__) && !defined (_WIN32) /* GCC complains about mktemp & always provides mkstemp */ - - if (*tempfile == '\0') { /* first time, open guaranteed-unique file */ - int fh; - - strcpy(tempfile, "tempXXXXXX"); /* get modifiable copy of name template */ - - if ((fh = mkstemp(tempfile)) == -1) { /* open file. Actual name is set by side effect */ - printf("Cannot create temporary deck file\n"); - break_simulation(STOP_DECK_BREAK); - return 0; - } - /* get FILE * from the file handle */ - if ((cr_unit.fileref = fdopen(fh, "w+b")) == NULL) { - printf("Cannot use temporary deck file %s\n", tempfile); - break_simulation(STOP_DECK_BREAK); - return 0; - } - } - else { /* on later opens, just reuse the old name */ - if ((cr_unit.fileref = fopen(tempfile, "w+b")) == NULL) { - printf("Cannot create temporary file %s\n", tempfile); - break_simulation(STOP_DECK_BREAK); - return 0; - } - } -#else /* ANSI standard C always provides mktemp */ - - if (*tempfile == '\0') { /* first time, construct unique name */ - strcpy(tempfile, "tempXXXXXX"); /* make a modifiable copy of the template */ - if (mktemp(tempfile) == NULL) { - printf("Cannot create temporary card file name\n"); - break_simulation(STOP_DECK_BREAK); - return 0; - } - } - /* (re)create file */ - if ((cr_unit.fileref = fopen(tempfile, "w+b")) == NULL) { - printf("Cannot create temporary file %s\n", tempfile); - break_simulation(STOP_DECK_BREAK); - return 0; - } -#endif - - SETBIT(cr_unit.flags, UNIT_SCRATCH); - - for (;;) { /* store literal cards into temporary file */ - upcase(buf+1); - fputs(buf+1, cr_unit.fileref); - putc('\n', cr_unit.fileref); - - if (cpu_unit.flags & UNIT_ATT) - trace_io("(Literal card %s\n)", buf+1); - if (! (cr_unit.flags & UNIT_QUIET)) - printf( "(Literal card %s)\n", buf+1); - - fpos = ftell(deckfile); - if (fgets(buf, sizeof(buf), deckfile) == NULL) - break; /* oops, end of file */ - if (buf[0] != '!' || strnicmp(buf, "!BREAK", 6) == 0) - break; - alltrim(buf); - } - fseek(deckfile, fpos, SEEK_SET); /* restore deck file to just before non-literal card */ - - fseek(cr_unit.fileref, 0, SEEK_SET); /* rewind scratch file for reading */ - code = CODE_029; /* assume literal cards use keycode 029 */ - break; - } - - sub_args(buf, tmpbuf, sizeof(buf), list_nargs, list_arg); /* substitute in stuff from the attach command line */ - - c = buf; /* pick filename from string */ - - while (*c && *c <= ' ') /* skip leading blanks (there could be some now after subsitution) */ - c++; - - fname = c; /* remember start */ - - if (*c == '\'' || *c == '"') { /* quoted string */ - quote = *c++; /* remember the quote type */ - fname++; /* skip the quote */ - while (*c && (*c != quote)) - c++; /* skip to end of quote */ - } - else { /* not quoted; look for terminating whitespace */ - while (*c && (*c > ' ')) - c++; - } - - if (*c) - *c++ = 0; /* term arg at space or closing quote & move to next character */ - - if (! *fname) /* blank line, no filename */ - continue; - - if ((cr_unit.fileref = fopen(fname, "rb")) == NULL) { - printf("File '%s' specified in deck file '%s' cannot be opened\n", fname, cr_unit.filename+1); - continue; - } - - mode = c = skipbl(c); /* skip to next token, which would be mode, if present */ - - switch (*c) { - case 'b': - case 'B': - code = CODE_BINARY; /* force code */ - c++; /* accept mode character by moving past it */ - break; - - case 'a': - case 'A': - code = CODE_029; - c++; - - switch (*c) { /* is ascii mode followed by another character? */ - case 'F': - case 'f': - tab_proc = EditToFortran; - c++; - break; - - case 'A': - case 'a': - tab_proc = EditToAsm; - c++; - break; - - case 't': - case 'T': - tab_proc = EditToWhitespace; - c++; - break; - } - } - - if (code == CODE_AUTO) /* otherwise if mode is auto, guess it, otherwise use default */ - code = guess_cr_code(); - - if (cpu_unit.flags & UNIT_ATT) - trace_io("(Opened %s deck %s%s)\n", (code == CODE_BINARY) ? "binary" : "text", fname, tab_proc ? (*tab_proc)(NULL) : ""); - - if (! (cr_unit.flags & UNIT_QUIET)) - printf( "(Opened %s deck %s%s)\n", (code == CODE_BINARY) ? "binary" : "text", fname, tab_proc ? (*tab_proc)(NULL) : ""); - - break; - } - - checkdeck(); - - if (code != CODE_AUTO) /* if code was determined, set it */ - set_active_cr_code(code); /* (it may be left at CODE_AUTO when deckfile is exhausted */ - - return (cr_unit.flags & UNIT_CR_EMPTY) == 0;/* return TRUE if a deck has been loaded */ -} - -static t_stat cr_reset (DEVICE *dptr) -{ - if (GET_ACTCODE(cr_unit) == CODE_AUTO) - SET_ACTCODE(cr_unit, CODE_029); /* if actual code is not yet set, select 029 for now*/ - - cr_set_code(&cr_unit, GET_ACTCODE(cr_unit), NULL, NULL); /* reset to specified code table */ - - readstate = STATION_EMPTY; - - cr_dsw = 0; - sim_cancel(&cr_unit); /* cancel any pending ops */ - calc_ints(); - - SET_OP(OP_IDLE); - - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_reset(); - return SCPE_OK; - } - - return SCPE_OK; -} - -static t_stat cp_reset (DEVICE *dptr) -{ - if (GET_CODE(cp_unit) == CODE_AUTO) - SET_CODE(cp_unit, CODE_BINARY); /* punch is never in auto mode; turn it to binary on startup */ - - cp_set_code(&cp_unit, GET_CODE(cp_unit), NULL, NULL); - punchstate = STATION_EMPTY; - - cp_unit.COLUMN = -1; - return SCPE_OK; -} - -t_stat cr_rewind (void) -{ - if ((cr_unit.flags & UNIT_ATT) == 0) - return SCPE_UNATT; - - if (deckfile) { - fseek(deckfile, 0, SEEK_SET); - nextdeck(); - } - else { - fseek(cr_unit.fileref, 0, SEEK_SET); - checkdeck(); - cr_set_code(&cr_unit, GET_CODE(cr_unit), NULL, NULL); - } - - cr_unit.pos = 0; - - /* there is a read pending. Pull the card in to make it go */ - if (CURRENT_OP == OP_READING || CURRENT_OP == OP_PUNCHING || CURRENT_OP == OP_FEEDING) - feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); - - return SCPE_OK; -} - -static t_stat cr_attach (UNIT *uptr, char *cptr) -{ - t_stat rval; - t_bool use_decklist; - char *c, *arg, quote; - - cr_detach(uptr); /* detach file and possibly deck file */ - - CLRBIT(uptr->flags, UNIT_SCRATCH|UNIT_QUIET|UNIT_DEBUG|UNIT_PHYSICAL|UNIT_LOWERCASE); /* set options */ - - tab_proc = NULL; - use_decklist = FALSE; - - if (sim_switches & SWMASK('D')) SETBIT(uptr->flags, UNIT_DEBUG); - if (sim_switches & SWMASK('Q')) SETBIT(uptr->flags, UNIT_QUIET); - if (sim_switches & SWMASK('L')) SETBIT(uptr->flags, UNIT_LOWERCASE); - - if (sim_switches & SWMASK('F')) tab_proc = EditToFortran; - if (sim_switches & SWMASK('A')) tab_proc = EditToAsm; - if (sim_switches & SWMASK('T')) tab_proc = EditToWhitespace; - - /* user can specify multiple names on the CR attach command if using a deck file. The deck file - * can contain %n tokens to pickup the additional name(s). */ - - c = cptr; /* extract arguments */ - for (list_nargs = 0; list_nargs < MAXARGS; list_nargs++) { - while (*c && (*c <= ' ')) /* skip blanks */ - c++; - - if (! *c) - break; /* all done */ - - if (list_nargs == 0 && *c == '@') { /* @ might occur before a quoted name; check first */ - c++; - use_decklist = TRUE; - } - - if (*c == '\'' || *c == '"') { /* quoted string */ - quote = *c++; - arg = c; /* save start */ - while (*c && (*c != quote)) - c++; - } - else { - arg = c; /* save start */ - while (*c && (*c > ' ')) - c++; - } - - if (*c) - *c++ = 0; /* term arg at space or closing quote */ - - list_arg[list_nargs] = list_save[list_nargs]; /* set pointer to permanent storage location */ - strncpy(list_arg[list_nargs], arg, MAXARGLEN); /* store copy */ - } - - if (list_nargs <= 0) /* need at least 1 */ - return SCPE_2FARG; - - cr_count = 0; /* reset card counter */ - - cptr = list_arg[0]; /* filename is first argument */ - if (*cptr == '@') { /* @ might also occur inside a quoted name; check afterwards too */ - use_decklist = TRUE; - cptr++; - } - - else if (sim_switches & SWMASK('P')) { /* open physical card reader device */ - return pcr_attach(uptr, cptr); - } - - if (list_nargs > 1 && ! use_decklist) /* if not using deck file, there should have been only one name */ - return SCPE_2MARG; - - if (strcmp(cptr, "(stdin)") == 0 && ! use_decklist) { /* standard input */ - if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ - uptr->filename = calloc(CBUFSIZE, sizeof(char)); - strcpy(uptr->filename, "(stdin)"); - uptr->fileref = stdin; - SETBIT(uptr->flags, UNIT_ATT); - uptr->pos = 0; - } - else if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) { - return rval; - } - - if (use_decklist) { /* if we skipped the '@', store the actually-specified name */ - uptr->filename[0] = '@'; - strncpy(uptr->filename+1, cptr, CBUFSIZE-1); - - deckfile = cr_unit.fileref; /* save the deck file stream in our local variable */ - cr_unit.fileref = NULL; - nextdeck(); - } - else { - checkdeck(); - cr_set_code(&cr_unit, GET_CODE(cr_unit), NULL, NULL); - } - - /* there is a read pending. Pull the card in to make it go */ - if (CURRENT_OP == OP_READING || CURRENT_OP == OP_PUNCHING || CURRENT_OP == OP_FEEDING) - feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); - - return SCPE_OK; -} - -t_stat cr_detach (UNIT *uptr) -{ - t_stat rval; - - cr_count = 0; /* clear read count */ - - if (cr_unit.flags & UNIT_PHYSICAL) - return pcr_detach(uptr); - - if (cr_unit.flags & UNIT_ATT && deckfile != NULL) { - if (cr_unit.fileref != NULL) /* close the active card deck */ - fclose(cr_unit.fileref); - - if (cr_unit.flags & UNIT_SCRATCH) { - remove(tempfile); - CLRBIT(cr_unit.flags, UNIT_SCRATCH); - } - - cr_unit.fileref = deckfile; /* give scp a file to close */ - } - - if (uptr->fileref == stdin) { - CLRBIT(uptr->flags, UNIT_ATT); - free(uptr->filename); - uptr->filename = NULL; - uptr->fileref = NULL; - rval = SCPE_OK; - } - else - rval = detach_unit(uptr); - - return rval; -} - -static t_stat cp_attach (UNIT *uptr, char *cptr) -{ - /* if -d is specified turn on debugging (bit is in card reader UNIT) */ - if (sim_switches & SWMASK('D')) SETBIT(cr_unit.flags, UNIT_DEBUG); - - return attach_unit(uptr, quotefix(cptr)); /* fix quotes in filenames & attach */ -} - -static t_stat cp_detach (UNIT *uptr) -{ - if (cp_unit.flags & UNIT_ATT) - if (punchstate == STATION_PUNCHED) - feedcycle(FALSE, FALSE); /* flush out card just punched */ - - any_punched = 0; /* reset punch detected */ - cp_count = 0; /* clear punch count */ - - return detach_unit(uptr); -} - -static void op_done (UNIT *u, t_bool issue_intr) -{ - if (u->flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Op Complete, card %d", cr_count); - - SET_OP(OP_IDLE); - - if (u->flags & UNIT_2501) /* we use u-> not cr_unit. because PUNCH is always a 1442 */ - CLRBIT(cr_dsw, CR_DSW_2501_BUSY); - else - CLRBIT(cr_dsw, CR_DSW_1442_BUSY); /* this is trickier. 1442 cr and cp share a dsw */ - - if (issue_intr) { /* issue op-complete interrupt for read and punch ops but not feed */ - if (u->flags & UNIT_2501) { - SETBIT(cr_dsw, CR_DSW_2501_OP_COMPLETE); - SETBIT(ILSW[4], ILSW_4_2501_CARD); - } - else { - SETBIT(cr_dsw, CR_DSW_1442_OP_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1442_CARD); - } - calc_ints(); - } -} - -static t_stat cr_svc (UNIT *uptr) -{ - int i; - - if (uptr->flags & UNIT_PHYSICAL) - return pcr_svc(uptr); - - switch (CURRENT_OP) { - case OP_IDLE: - break; - - case OP_FEEDING: - op_done(&cr_unit, FALSE); - break; - - case OP_READING: - if (readstate == STATION_EMPTY) { /* read active but no cards? hang */ - sim_activate(&cr_unit, cf_wait); - break; - } - - if (cr_unit.flags & UNIT_2501) { /* 2501 transfers entire card then interrupts */ - for (i = 0; i < cr_cols; i++) /* (we wait until end of delay time before transferring data) */ - M[(cr_addr + i) & mem_mask] = readstation[i]; - - readstate = STATION_READ; - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Op Complete, card %d", cr_count); - - op_done(&cr_unit, TRUE); - } - else if (++cr_unit.COLUMN < 80) { /* 1442 interrupts on each column... */ - SETBIT(cr_dsw, CR_DSW_1442_READ_RESPONSE); - SETBIT(ILSW[0], ILSW_0_1442_CARD); - calc_ints(); - sim_activate(&cr_unit, cr_wait); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Read Response %d : %d", cr_count, cr_unit.COLUMN+1); - } - else { /* ... then issues op-complete */ - readstate = STATION_READ; - op_done(&cr_unit, TRUE); - } - break; - - case OP_PUNCHING: - if (punchstate == STATION_EMPTY) { /* punch active but no cards? hang */ - sim_activate(&cr_unit, cf_wait); - break; - } - - if (cp_unit.flags & UNIT_LASTPUNCH) { - punchstate = STATION_PUNCHED; - op_done(&cp_unit, TRUE); - } - else if (++cp_unit.COLUMN < 80) { - SETBIT(cr_dsw, CR_DSW_1442_PUNCH_RESPONSE); - SETBIT(ILSW[0], ILSW_0_1442_CARD); - calc_ints(); - sim_activate(&cr_unit, cp_wait); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Punch Response"); - } - else { - punchstate = STATION_PUNCHED; - op_done(&cp_unit, TRUE); - } - break; - } - - return SCPE_OK; -} - -void xio_2501_card (int32 addr, int32 func, int32 modify) -{ - char msg[80]; - int ch; - t_bool lastcard; - -/* it would be nice for simulated reader to be able to use 2501 mode -- much more - * efficient. Using the 1403 printer and 2501 reader speeds things up quite considerably. */ - - switch (func) { - case XIO_SENSE_DEV: - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_xio_sense(modify); - break; - } - -// the following part is questionable -- the 2501 might need to be more picky about setting -// the LAST_CARD bit... - - if ((cr_unit.flags & UNIT_ATT) == 0) - lastcard = TRUE; /* if nothing to read, hopper's empty */ - else if (readstate == STATION_LOADED) - lastcard = FALSE; - else if (cr_unit.fileref == NULL) - lastcard = TRUE; - else if ((ch = getc(cr_unit.fileref)) != EOF) { - ungetc(ch, cr_unit.fileref); /* put character back; hopper's not empty */ - lastcard = FALSE; - } - else if (deckfile != NULL && nextdeck()) - lastcard = FALSE; - else - lastcard = TRUE; /* there is nothing left to read for a next card */ - - CLRBIT(cr_dsw, CR_DSW_2501_LAST_CARD|CR_DSW_2501_BUSY|CR_DSW_2501_NOT_READY); - - if (lastcard) - SETBIT(cr_dsw, CR_DSW_2501_LAST_CARD|CR_DSW_2501_NOT_READY); - // don't clear it here -- modify bit must be set before last card can be cleared - - if (CURRENT_OP != OP_IDLE) - SETBIT(cr_dsw, CR_DSW_2501_BUSY|CR_DSW_2501_NOT_READY); - - ACC = cr_dsw; /* return the DSW */ - - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Sense %04x%s", cr_dsw & 0xFFFF, (modify & 1) ? " RESET" : ""); - - if (modify & 0x01) { /* reset interrupts */ -// if (! lastcard) /* (lastcard is reset only when modify bit is set) */ - CLRBIT(cr_dsw, CR_DSW_2501_LAST_CARD); - CLRBIT(cr_dsw, CR_DSW_2501_OP_COMPLETE); - CLRBIT(ILSW[4], ILSW_4_2501_CARD); - } - break; - - case XIO_INITR: - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Start read"); - - cr_unit.COLUMN = -1; - - cr_cols = M[addr & mem_mask]; /* save column count and transfer address */ - cr_addr = addr+1; - - if ((cr_cols < 0) || (cr_cols > 80)) /* this is questionable -- what would hardware do? */ - cr_cols = 80; - - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_xio_startread(); - break; - } - - if (readstate != STATION_LOADED) - feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); - - SET_OP(OP_READING); - sim_cancel(&cr_unit); - sim_activate(&cr_unit, cr_wait2501); - break; - - default: - sprintf(msg, "Invalid 2501 XIO function %x", func); - xio_error(msg); - break; - } -} - -void xio_1142_card (int32 addr, int32 func, int32 modify) -{ - char msg[80]; - int ch; - uint16 wd; - t_bool lastcard; - - switch (func) { - case XIO_SENSE_DEV: - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_xio_sense(modify); - break; - } - -/* glunk - * have to separate out what status is 1442 is punch only and 2501 is the reader */ - - if (cp_unit.flags & UNIT_ATT) - lastcard = FALSE; /* if punch file is open, assume infinite blank cards in reader */ - else if ((cr_unit.flags & UNIT_ATT) == 0) - lastcard = TRUE; /* if nothing to read, hopper's empty */ - else if (readstate == STATION_LOADED) - lastcard = FALSE; - else if (cr_unit.fileref == NULL) - lastcard = TRUE; - else if ((ch = getc(cr_unit.fileref)) != EOF) { - ungetc(ch, cr_unit.fileref); /* put character back; hopper's not empty */ - lastcard = FALSE; - } - else if (deckfile != NULL && nextdeck()) - lastcard = FALSE; - else - lastcard = TRUE; /* there is nothing left to read for a next card */ - - CLRBIT(cr_dsw, CR_DSW_1442_LAST_CARD | CR_DSW_1442_BUSY | CR_DSW_1442_NOT_READY); - - if (lastcard) - SETBIT(cr_dsw, CR_DSW_1442_LAST_CARD); - - if (CURRENT_OP != OP_IDLE) - SETBIT(cr_dsw, CR_DSW_1442_BUSY | CR_DSW_1442_NOT_READY); - else if (readstate == STATION_EMPTY && punchstate == STATION_EMPTY && lastcard) - SETBIT(cr_dsw, CR_DSW_1442_NOT_READY); - - ACC = cr_dsw; /* return the DSW */ - - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Sense %04x%s%s", cr_dsw & 0xFFFF, (modify & 1) ? " RESET0" : "", (modify & 2) ? " RESET4" : ""); - - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(cr_dsw, CR_DSW_1442_READ_RESPONSE | CR_DSW_1442_PUNCH_RESPONSE); - CLRBIT(ILSW[0], ILSW_0_1442_CARD); - } - - if (modify & 0x02) { - CLRBIT(cr_dsw, CR_DSW_1442_OP_COMPLETE); - CLRBIT(ILSW[4], ILSW_4_1442_CARD); - } - break; - - case XIO_READ: /* get card data into word pointed to in IOCC packet */ - if (cr_unit.flags & OP_READING) { - if (cr_unit.COLUMN < 0) { - xio_error("1442: Premature read!"); - } - else if (cr_unit.COLUMN < 80) { - WriteW(addr, readstation[cr_unit.COLUMN]); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Read %03x", (readstation[cr_unit.COLUMN] >> 4)); - } - else if (cr_unit.COLUMN == 80) { - xio_error("1442: Read past column 80!"); - cr_unit.COLUMN++; /* don't report it again */ - } - } - else { -/* don't complain: APL\1130 issues both reads and writes on every interrupt - * (probably to keep the code small). Apparently it's just ignored if corresponding - * control didn't initiate a read cycle. - * xio_error("1442: Read when not in a read cycle!"); */ - } - break; - - case XIO_WRITE: - if (cr_unit.flags & OP_PUNCHING) { - if (cp_unit.COLUMN < 0) { - xio_error("1442: Premature write!"); - } - else if (cp_unit.flags & UNIT_LASTPUNCH) { - xio_error("1442: Punch past last-punch column!"); - cp_unit.COLUMN = 81; - } - else if (cp_unit.COLUMN < 80) { - wd = (uint16) ReadW(addr); /* store one word to punch buffer */ - punchstation[cp_unit.COLUMN] = wd & 0xFFF0; - if (wd & 0x0008) /* mark this as last column to be punched */ - SETBIT(cp_unit.flags, UNIT_LASTPUNCH); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Punch %03x%s", (wd >> 4) & 0xFFF, (wd & 8) ? " LAST" : ""); - } - else if (cp_unit.COLUMN == 80) { - xio_error("1442: Punch past column 80!"); - cp_unit.COLUMN++; /* don't report it again */ - } - } - else { -/* don't complain: APL\1130 issues both reads and writes on every interrupt - * (probably to keep the code small). Apparently it's just ignored if corresponding - * control didn't initiate a punch cycle. - * xio_error("1442: Write when not in a punch cycle!"); */ - } - break; - - case XIO_CONTROL: - switch (modify & 7) { - case 1: /* start punch */ - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Start Punch"); - if (punchstate != STATION_LOADED) - feedcycle(TRUE, TRUE); - - SET_OP(OP_PUNCHING); - cp_unit.COLUMN = -1; - - CLRBIT(cp_unit.flags, UNIT_LASTPUNCH); - - any_punched = 1; /* we've started punching, so enable writing to output deck file */ - - sim_cancel(&cr_unit); - sim_activate(&cr_unit, cp_wait); - break; - - case 2: /* feed cycle */ - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Feed"); - - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_xio_feedcycle(); - break; - } - - feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); - - SET_OP(OP_FEEDING); - sim_cancel(&cr_unit); - sim_activate(&cr_unit, cf_wait); - break; - - case 4: /* start read */ - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Start read"); - - cr_unit.COLUMN = -1; - - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_xio_startread(); - break; - } - - if (readstate != STATION_LOADED) - feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); - - SET_OP(OP_READING); - sim_cancel(&cr_unit); - sim_activate(&cr_unit, cr_wait); - break; - - case 0: - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR NOP"); - break; - - default: - sprintf(msg, "1442: Multiple operations in XIO_CONTROL: %x", modify); - xio_error(msg); - return; - } - - break; - - default: - sprintf(msg, "Invalid 1442 XIO function %x", func); - xio_error(msg); - break; - } -} - -#if ! (defined(ENABLE_PHYSICAL_CARD_READER_SUPPORT) && defined(WIN32)) - - /* stub out the physical card reader routines */ - - static t_stat pcr_attach (UNIT *uptr, char *devname) {return SCPE_ARG;} - static t_stat pcr_detach (UNIT *uptr) {return detach_unit(uptr);} - static t_stat pcr_svc (UNIT *uptr) {return SCPE_OK;} - static void pcr_xio_sense (int modify) {} - static void pcr_xio_feedcycle (void) {} - static void pcr_xio_startread (void) {} - static void pcr_reset (void) {} - -#else - -/* - * This code supports a physical card reader interface I built. Interface schematic - * and documentation can be downloaded from http://ibm1130.org/sim/downloads/cardread.zip - */ - -#include - -#define PCR_STATUS_READY 1 /* bits in interface reply byte */ -#define PCR_STATUS_ERROR 2 -#define PCR_STATUS_HEMPTY 4 -#define PCR_STATUS_EOF 8 -#define PCR_STATUS_PICKING 16 - -#define PCR_STATUS_MSEC 150 /* when idle, get status every 150 msec */ - -typedef enum { - PCR_STATE_IDLE, /* nothing expected from the interface */ - PCR_STATE_WAIT_CMD_RESPONSE, /* waiting for response from any command other than P */ - PCR_STATE_WAIT_PICK_CMD_RESPONSE, /* waiting for response from P command */ - PCR_STATE_WAIT_DATA_START, /* waiting for introduction to data from P command */ - PCR_STATE_WAIT_DATA, /* waiting for data from P command */ - PCR_STATE_WAIT_PICK_FINAL_RESPONSE, /* waiting for status byte after last of the card data */ - PCR_STATE_CLOSED -} PCR_STATE; - -static void pcr_cmd (char cmd); -static DWORD CALLBACK pcr_thread (LPVOID arg); -static BOOL pcr_handle_status_byte (int nrcvd); -static void pcr_trigger_interrupt_0(void); -static void begin_pcr_critical_section (void); -static void end_pcr_critical_section (void); -static void pcr_set_dsw_from_status (BOOL post_pick); -static t_stat pcr_open_controller (char *devname); - -static PCR_STATE pcr_state = PCR_STATE_CLOSED; /* current state of connection to physical card reader interface */ -static char pcr_status = 0; /* last status byte received from the interface */ -static int pcr_nleft; /* number of bytes still expected from pick command */ -static int pcr_nready; /* number of bytes waiting in the input buffer for simulator to read */ -static BOOL pcr_done; -static HANDLE hpcr = INVALID_HANDLE_VALUE; -static HANDLE hPickEvent = INVALID_HANDLE_VALUE; -static HANDLE hResetEvent = INVALID_HANDLE_VALUE; -static OVERLAPPED ovRd, ovWr; /* overlapped IO structures for reading from, writing to device */ -static int nwaits; /* number of timeouts waiting for response from interface */ -static char response_byte; /* buffer to receive command/status response byte from overlapped read */ -static char lastcmd = '?'; - -/* pcr_attach - perform attach function to physical card reader */ - -static t_stat pcr_attach (UNIT *uptr, char *devname) -{ - DWORD thread_id; - t_stat rval; - - pcr_state = PCR_STATE_CLOSED; - sim_cancel(uptr); - cr_unit.COLUMN = -1; /* device is not currently cycling */ - - if ((rval = pcr_open_controller(devname)) != SCPE_OK) - return rval; - - if (hPickEvent == INVALID_HANDLE_VALUE) - hPickEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - - if (hResetEvent == INVALID_HANDLE_VALUE) - hResetEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - - pcr_status = PCR_STATUS_HEMPTY; /* set default status: offline, no cards */ - pcr_state = PCR_STATE_IDLE; - pcr_done = FALSE; - cr_dsw = CR_DSW_1442_LAST_CARD | CR_DSW_1442_NOT_READY; - - set_active_cr_code(CODE_BINARY); /* force binary mode */ - - if (CreateThread(NULL, 0, pcr_thread, NULL, 0, &thread_id) == NULL) { - pcr_state = PCR_STATE_CLOSED; - CloseHandle(hpcr); - hpcr = INVALID_HANDLE_VALUE; - printf("Error creating card reader thread\n"); - return SCPE_IERR; - } - - SETBIT(uptr->flags, UNIT_PHYSICAL|UNIT_ATT); /* mark device as attached */ - uptr->filename = malloc(strlen(devname)+1); - strcpy(uptr->filename, devname); - - return SCPE_OK; -} - -/* pcr_open_controller - open the USB device's virtual COM port and configure the interface */ - -static t_stat pcr_open_controller (char *devname) -{ - DCB dcb; - COMMTIMEOUTS cto; - DWORD nerr; - - if (hpcr != INVALID_HANDLE_VALUE) - return SCPE_OK; - /* open the COM port */ - hpcr = CreateFile(devname, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (hpcr == INVALID_HANDLE_VALUE) - return SCPE_OPENERR; - - memset(&dcb, 0, sizeof(dcb)); /* set communications parameters */ - - dcb.DCBlength = sizeof(DCB); - dcb.BaudRate = CBR_115200; /* for the USB virtual com port, baud rate is irrelevant */ - dcb.fBinary = 1; - dcb.fParity = 0; - dcb.fOutxCtsFlow = 0; - dcb.fOutxDsrFlow = 0; - dcb.fDtrControl = DTR_CONTROL_ENABLE; - dcb.fDsrSensitivity = FALSE; - dcb.fTXContinueOnXoff = 0; - dcb.fOutX = 0; - dcb.fInX = 0; - dcb.fErrorChar = 0; - dcb.fNull = 0; - dcb.fRtsControl = RTS_CONTROL_ENABLE; - dcb.fAbortOnError = 0; - dcb.XonLim = 0; - dcb.XoffLim = 0; - dcb.ByteSize = 8; - dcb.Parity = NOPARITY; - dcb.StopBits = ONESTOPBIT; - dcb.XonChar = 0; - dcb.XoffChar = 0; - dcb.ErrorChar = 0; - dcb.EofChar = 0; - dcb.EvtChar = 0; - - if (! SetCommState(hpcr, &dcb)) { - CloseHandle(hpcr); - hpcr = INVALID_HANDLE_VALUE; - printf("Call to SetCommState failed\n"); - return SCPE_OPENERR; - } - - cto.ReadIntervalTimeout = 100; /* stop if 100 msec elapses between two received bytes */ - cto.ReadTotalTimeoutMultiplier = 0; /* no length sensitivity */ - cto.ReadTotalTimeoutConstant = 400; /* allow 400 msec for a read (reset command can take a while) */ - - cto.WriteTotalTimeoutMultiplier = 0; - cto.WriteTotalTimeoutConstant = 200; /* allow 200 msec for a write */ - - if (! SetCommTimeouts(hpcr, &cto)) { - CloseHandle(hpcr); - hpcr = INVALID_HANDLE_VALUE; - printf("Call to SetCommTimeouts failed\n"); - return SCPE_OPENERR; - } - - PurgeComm(hpcr, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); - ClearCommError(hpcr, &nerr, NULL); - - return SCPE_OK; -} - -/* pcr_detach - detach physical reader from CR device */ - -static t_stat pcr_detach (UNIT *uptr) -{ - if (cr_unit.flags & UNIT_ATT) { - CloseHandle(hpcr); /* close the COM port (this will lead to the thread closing) */ - hpcr = INVALID_HANDLE_VALUE; - pcr_state = PCR_STATE_CLOSED; - - free(uptr->filename); /* release the name copy */ - uptr->filename = NULL; - } - - CLRBIT(cr_unit.flags, UNIT_PHYSICAL|UNIT_ATT); /* drop the attach and physical bits */ - return SCPE_OK; -} - -/* pcr_xio_sense - perform XIO sense function on physical card reader */ - -static void pcr_xio_sense (int modify) -{ - if (modify & 0x01) { /* reset simulated interrupts */ - CLRBIT(cr_dsw, CR_DSW_1442_READ_RESPONSE | CR_DSW_1442_PUNCH_RESPONSE); - CLRBIT(ILSW[0], ILSW_0_1442_CARD); - } - - if (modify & 0x02) { - CLRBIT(cr_dsw, CR_DSW_1442_OP_COMPLETE); - CLRBIT(ILSW[4], ILSW_4_1442_CARD); - } - - ACC = cr_dsw; /* DSW was set in real-time, just return the DSW */ - - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Sense %04x%s%s", cr_dsw, (modify & 1) ? " RESET0" : "", (modify & 2) ? " RESET4" : ""); -} - -/* report_error - issue detailed report of Windows IO error */ - -static void report_error (char *msg, DWORD err) -{ - char *lpMessageBuffer = NULL; - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* The user default language */ - (LPTSTR) &lpMessageBuffer, - 0, - NULL ); - - printf("GetOverlappedResult failed, %s, %s\n", - msg, lpMessageBuffer); - - LocalFree(lpMessageBuffer); -} - -/* pcr_thread - thread to handle card reader interface communications */ - -static DWORD CALLBACK pcr_thread (LPVOID arg) -{ - DWORD event; - long nrcvd, nread, nwritten; - HANDLE objs[4]; - BOOL pick_queued = FALSE, reset_queued = FALSE; - - nwaits = 0; - - ZeroMemory(&ovRd, sizeof(ovRd)); - ZeroMemory(&ovWr, sizeof(ovWr)); - ovRd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* create an event for async IO reads */ - ovWr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* create an event for async IO writes */ - - objs[0] = ovRd.hEvent; - objs[1] = ovWr.hEvent; - objs[2] = hResetEvent; - objs[3] = hPickEvent; - - while (hpcr != INVALID_HANDLE_VALUE) { - if (pcr_state == PCR_STATE_IDLE) { - if (pick_queued) { - pcr_cmd('P'); - pick_queued = FALSE; - pcr_done = FALSE; - pcr_state = PCR_STATE_WAIT_PICK_CMD_RESPONSE; - } - else if (reset_queued) { - pcr_cmd('X'); - reset_queued = FALSE; - pcr_state = PCR_STATE_WAIT_CMD_RESPONSE; - } - } - - event = WaitForMultipleObjects(4, objs, FALSE, PCR_STATUS_MSEC); - - switch (event) { - case WAIT_OBJECT_0+0: /* read complete */ - ResetEvent(ovRd.hEvent); - if (! GetOverlappedResult(hpcr, &ovRd, &nrcvd, TRUE)) - report_error("PCR_Read", GetLastError()); - else if (cr_unit.flags & UNIT_DEBUG) - printf("PCR_Read: event, %d rcvd\n", nrcvd); - break; - - case WAIT_OBJECT_0+1: /* write complete */ - nwritten = 0; - ResetEvent(ovWr.hEvent); - if (! GetOverlappedResult(hpcr, &ovWr, &nwritten, TRUE)) - report_error("PCR_Write", GetLastError()); - else if (cr_unit.flags & UNIT_DEBUG) - printf("PCR_Write: event, %d sent\n", nwritten); - continue; - - case WAIT_OBJECT_0+2: /* reset request from simulator */ - reset_queued = TRUE; - pick_queued = FALSE; - continue; - - case WAIT_OBJECT_0+3: /* pick request from simulator */ - pick_queued = TRUE; - continue; - - case WAIT_TIMEOUT: - if (pcr_state == PCR_STATE_IDLE) { - pcr_state = PCR_STATE_WAIT_CMD_RESPONSE; - ovRd.Offset = ovRd.OffsetHigh = 0; - pcr_cmd('S'); - } - else if (pcr_state == PCR_STATE_WAIT_CMD_RESPONSE && ++nwaits >= 6) { - printf("Requesting status again!\n"); - ovRd.Offset = ovRd.OffsetHigh = 0; - pcr_cmd('S'); - } - continue; - - default: - printf("Unexpected pcr_wait result %08lx", event); - continue; - } - - /* We only get here if read event occurred */ - - switch (pcr_state) { - case PCR_STATE_IDLE: /* nothing expected from the interface */ - PurgeComm(hpcr, PURGE_RXCLEAR|PURGE_RXABORT); - break; - - case PCR_STATE_WAIT_CMD_RESPONSE: /* waiting for response from any command other than P */ - if (pcr_handle_status_byte(nrcvd)) - pcr_state = PCR_STATE_IDLE; - break; - - case PCR_STATE_WAIT_PICK_CMD_RESPONSE: /* waiting for response from P command */ - if (pcr_handle_status_byte(nrcvd)) { - pcr_cmd('\0'); /* queue a response read */ - pcr_state = PCR_STATE_WAIT_DATA_START; - } - break; - - case PCR_STATE_WAIT_DATA_START: /* waiting for leadin character from P command (= or !) */ - if (nrcvd <= 0) { /* (this could take an indefinite amount of time) */ - if (cr_unit.flags & UNIT_DEBUG) - printf("PCR: NO RESP YET\n"); - - continue; /* reader is not ready */ - } - - if (cr_unit.flags & UNIT_DEBUG) /* (this could take an indefinite amount of time) */ - printf("PCR: GOT %c\n", response_byte); - - switch (response_byte) { - case '=': /* = means pick in progress, 160 bytes of data will be coming */ - pcr_state = PCR_STATE_WAIT_DATA; - ovRd.Offset = ovRd.OffsetHigh = 0; - nread = 20; /* initiate a read */ - ReadFile(hpcr, ((char *) readstation), nread, &nrcvd, &ovRd); - break; - - case '!': /* ! means pick has been canceled, status will be coming next */ - pcr_state = PCR_STATE_WAIT_CMD_RESPONSE; - pcr_cmd('\0'); /* initiate read */ - break; - - default: /* anything else is a datacomm error, or something */ - /* indicate read check or something */ -/* pcr_state = PCR_STATE_IDLE; */ - break; - } - break; - - case PCR_STATE_WAIT_DATA: /* waiting for data from P command */ - if (cr_unit.flags & UNIT_DEBUG) - printf((nrcvd <= 0) ? "PCR: NO RESP!\n" : "PCR: GOT %d BYTES\n", nrcvd); - - if (nrcvd > 0) { - pcr_nleft -= nrcvd; - - begin_pcr_critical_section(); - pcr_nready += nrcvd; - end_pcr_critical_section(); - } - - if (pcr_nleft > 0) { - ovRd.Offset = ovRd.OffsetHigh = 0; - nread = min(pcr_nleft, 20); - ReadFile(hpcr, ((char *) readstation)+160-pcr_nleft, nread, &nrcvd, &ovRd); - } - else { - pcr_state = PCR_STATE_WAIT_PICK_FINAL_RESPONSE; - pcr_cmd('\0'); /* queue read */ - } - break; - - case PCR_STATE_WAIT_PICK_FINAL_RESPONSE: /* waiting for status byte after last of the card data */ - if (pcr_handle_status_byte(nrcvd)) { - readstate = STATION_READ; - pcr_state = PCR_STATE_IDLE; - pcr_done = TRUE; - } - break; - } - } - - CloseHandle(ovRd.hEvent); - CloseHandle(ovWr.hEvent); - - return 0; -} - -/* pcr_cmd - issue command byte to interface. Read of response byte is queued */ - -static void pcr_cmd (char cmd) -{ - long nwritten, nrcvd; - int status; - - if (cmd != '\0') { - if (cr_unit.flags & UNIT_DEBUG /* && (cmd != 'S' || cmd != lastcmd) */) - printf("PCR: SENT %c\n", cmd); - - lastcmd = cmd; - - ResetEvent(ovWr.hEvent); - ovWr.Offset = ovWr.OffsetHigh = 0; - status = WriteFile(hpcr, &cmd, 1, &nwritten, &ovWr); - if (status == 0 && GetLastError() != ERROR_IO_PENDING) - printf("Error initiating write in pcr_cmd\n"); - } - - ovRd.Offset = ovRd.OffsetHigh = 0; - status = ReadFile(hpcr, &response_byte, 1, &nrcvd, &ovRd); /* if no bytes ready, just return -- a later wait-event will catch it */ - if (status == 0 && GetLastError() != ERROR_IO_PENDING) - printf("Error initiating read in pcr_cmd\n"); - -/* if (cr_unit.flags & UNIT_DEBUG) - * if (nrcvd == 0) - * printf("PCR: NO RESPONSE\n"); - * else - * printf("PCR: RESPONSE %c\n", response_byte); */ - - nwaits = 0; -} - -/* pcr_handle_status_byte - handle completion of read of response byte */ - -static BOOL pcr_handle_status_byte (int nrcvd) -{ - static char prev_status = '?'; - BOOL show; - - if (nrcvd <= 0) - return FALSE; - - pcr_status = response_byte; /* save new status */ - - show = lastcmd != 'S' || pcr_status != prev_status; - - if ((cr_unit.flags & UNIT_DEBUG) && show) { - printf("PCR: status %c\n", pcr_status); - prev_status = pcr_status; - } - - pcr_set_dsw_from_status(FALSE); - - return TRUE; -} - -/* pcr_set_dsw_from_status - construct device status word from current physical reader status */ - -static void pcr_set_dsw_from_status (BOOL post_pick) -{ - /* set 1130 status word bits */ - CLRBIT(cr_dsw, CR_DSW_1442_LAST_CARD | CR_DSW_1442_BUSY | CR_DSW_1442_NOT_READY | CR_DSW_1442_ERROR_CHECK); - - if (pcr_status & PCR_STATUS_HEMPTY) - SETBIT(cr_dsw, CR_DSW_1442_LAST_CARD | CR_DSW_1442_NOT_READY); - - if (pcr_status & PCR_STATUS_ERROR) - SETBIT(cr_dsw, CR_DSW_1442_ERROR_CHECK); - - /* we have a problem -- ready doesn't come back up right away after a pick. */ - /* I think I'll fudge this and not set NOT_READY immediately after a pick */ - - if ((! post_pick) && ! (pcr_status & PCR_STATUS_READY)) - SETBIT(cr_dsw, CR_DSW_1442_NOT_READY); - - if (CURRENT_OP != OP_IDLE) - SETBIT(cr_dsw, CR_DSW_1442_BUSY | CR_DSW_1442_NOT_READY); -} - -static void pcr_xio_feedcycle (void) -{ - SET_OP(OP_FEEDING); - cr_unit.COLUMN = -1; - SetEvent(hPickEvent); - sim_activate(&cr_unit, cr_wait); /* keep checking frequently */ -} - -static void pcr_xio_startread (void) -{ - SET_OP(OP_READING); - cr_unit.COLUMN = -1; - pcr_nleft = 160; - pcr_nready = 0; - SetEvent(hPickEvent); - sim_activate(&cr_unit, cr_wait); /* keep checking frequently */ -} - -static void pcr_reset (void) -{ - pcr_status = PCR_STATUS_HEMPTY; /* set default status: offline, no cards */ - pcr_state = PCR_STATE_IDLE; - cr_dsw = CR_DSW_1442_LAST_CARD | CR_DSW_1442_NOT_READY; - - sim_cancel(&cr_unit); - - SetEvent(hResetEvent); -} - -/* pcr_trigger_interrupt_0 - simulate a read response interrupt so OS will read queued column data */ - -static void pcr_trigger_interrupt_0 (void) -{ - if (++cr_unit.COLUMN < 80) { - SETBIT(cr_dsw, CR_DSW_1442_READ_RESPONSE); - SETBIT(ILSW[0], ILSW_0_1442_CARD); - calc_ints(); - - begin_pcr_critical_section(); - pcr_nready -= 2; - end_pcr_critical_section(); - - if (cr_unit.flags & UNIT_DEBUG) - printf("SET IRQ0 col %d\n", cr_unit.COLUMN+1); - } -} - -static t_stat pcr_svc (UNIT *uptr) -{ - switch (CURRENT_OP) { - case OP_IDLE: - break; - - case OP_READING: - if (pcr_nready >= 2) { /* if there is a whole column buffered, simulate column interrupt/* pcr_trigger_interrupt_0 - simulate a read response interrupt so OS will read queued column data */ - - pcr_trigger_interrupt_0(); - sim_activate(&cr_unit, cr_wait); /* keep checking frequently */ - } - else if (pcr_done) { - pcr_done = FALSE; - cr_count++; - op_done(&cr_unit, TRUE); - pcr_set_dsw_from_status(TRUE); - } - else - sim_activate(&cr_unit, cr_wait); /* keep checking frequently */ - break; - - case OP_FEEDING: - if (pcr_done) { - cr_count++; - op_done(&cr_unit, FALSE); - pcr_set_dsw_from_status(TRUE); - } - else - sim_activate(&cr_unit, cr_wait); /* keep checking frequently */ - - break; - - case OP_PUNCHING: - return cr_svc(uptr); - } - - return SCPE_OK; -} - -static CRITICAL_SECTION pcr_critsect; - -static void begin_pcr_critical_section (void) -{ - static BOOL mustinit = TRUE; - - if (mustinit) { - InitializeCriticalSection(&pcr_critsect); - mustinit = FALSE; - } - - EnterCriticalSection(&pcr_critsect); -} - -static void end_pcr_critical_section (void) -{ - LeaveCriticalSection(&pcr_critsect); -} - -#endif - diff --git a/Ibm1130/ibm1130_defs.h b/Ibm1130/ibm1130_defs.h deleted file mode 100644 index c25e2153..00000000 --- a/Ibm1130/ibm1130_defs.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -/* ibm1130_defs.h: IBM-1130 simulator definitions - */ - -#include "sim_defs.h" /* main SIMH defns (include path should include .., or make a copy) */ -#include "sim_console.h" /* more SIMH defns (include path should include .., or make a copy) */ - -#include -#include -#include - -#if defined(VMS) - # include /* to pick up 'unlink' */ -#endif - -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#ifndef _WIN32 - int strnicmp (const char *a, const char *b, size_t n); - int strcmpi (const char *a, const char *b); -#endif - -/* #define GUI_SUPPORT uncomment to compile the GUI extensions. It's defined in the windows ibm1130.mak makefile */ - -/* ------------------------------------------------------------------------ */ -/* Architectural constants */ - -#define MAXMEMSIZE (32768) /* 32Kwords */ -#define INIMEMSIZE (16384) /* 16Kwords */ -#define MEMSIZE (cpu_unit.capac) - -#define ILL_ADR_FLAG 0x40000000 /* an impossible 1130 address */ - -/* ------------------------------------------------------------------------ */ -/* Global state */ - -extern int cgi; /* TRUE if we are running as a CGI program */ -extern int cgiwritable; /* TRUE if we can write the disk images back to the image file in CGI mode */ -extern t_bool sim_gui; - -extern uint16 M[]; /* core memory, up to 32Kwords (note: don't even think about trying 64K) */ -extern uint16 ILSW[]; /* interrupt level status words */ -extern int32 IAR; /* instruction address register */ -extern int32 prev_IAR; /* instruction address register at start of current instruction */ -extern int32 SAR, SBR; /* storage address/buffer registers */ -extern int32 OP, TAG, CCC; /* instruction decoded pieces */ -extern int32 CES; /* console entry switches */ -extern int32 ACC, EXT; /* accumulator and extension */ -extern int32 ARF; /* arithmetic factor register, a nonaddressable internal CPU register */ -extern int32 RUNMODE; /* processor run/step mode */ -extern int32 ipl; /* current interrupt level (-1 = not handling irq) */ -extern int32 iplpending; /* interrupted IPL's */ -extern int32 tbit; /* trace flag (causes level 5 IRQ after each instr) */ -extern int32 V, C; /* condition codes */ -extern int32 wait_state; /* wait state (waiting for an IRQ) */ -extern int32 wait_lamp; /* alternate indicator to light the wait lamp on the GUI */ -extern int32 int_req; /* sum of interrupt request levels active */ -extern int32 int_lamps; /* accumulated version of int_req - gives lamp persistence */ -extern int32 int_mask; /* current active interrupt mask (ipl sensitive) */ -extern int32 mem_mask; -extern int32 cpu_dsw; /* CPU device status word */ -extern int32 sim_int_char; /* interrupt character */ -extern int32 con_dsw; /* has program stop and int run bits */ -extern t_bool running; -extern t_bool power; -extern t_bool cgi; /* TRUE if we are running as a CGI program */ -extern t_bool cgiwritable; /* TRUE if we can write to the disk image file in CGI mode */ -extern t_stat reason; /* CPU execution loop control */ - -#define WAIT_OP 1 /* wait state causes: wait instruction, invalid instruction*/ -#define WAIT_INVALID_OP 2 - -#define MODE_SS 3 /* RUNMODE values. SS and SMC are not implemented in this simulator */ -#define MODE_SMC 2 -#define MODE_INT_RUN 1 -#define MODE_RUN 0 -#define MODE_SI -1 -#define MODE_DISP -2 -#define MODE_LOAD -3 - -/* ------------------------------------------------------------------------ */ -/* debugging */ -/* ------------------------------------------------------------------------ */ - -#define ENABLE_DEBUG_PRINT -#define ENABLE_DEBUG_TO_LOG - -#ifdef ENABLE_DEBUG_PRINT -# define DEBUG_PRINT debug_print -#else -# ifdef ENABLE_DEBUG_TO_LOG -# define DEBUG_PRINT trace_io -# else -# define DEBUG_PRINT if (0) debug_print -# endif -#endif - -void debug_print(char *fmt, ...); - -/* ------------------------------------------------------------------------ */ -/* memory IO routines */ - -int32 ReadW (int32 a); -void WriteW (int32 a, int32 d); - -/* ------------------------------------------------------------------------ */ -/* handy macros */ - -#define CLRBIT(v,b) ((v) &= ~(b)) -#define SETBIT(v,b) ((v) |= (b)) -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) - -/* ------------------------------------------------------------------------ */ -/* Simulator stop codes */ - -#define STOP_WAIT 1 /* wait, no events */ -#define STOP_INVALID_INSTR 2 /* bad instruction */ -#define STOP_IBKPT 3 /* simulator breakpoint */ -#define STOP_INCOMPLETE 4 /* simulator coding not complete here */ -#define STOP_POWER_OFF 5 /* no power */ -#define STOP_DECK_BREAK 6 /* !BREAK in deck file */ -#define STOP_PHASE_BREAK 7 /* phase load break */ -#define STOP_CRASH 8 /* program has crashed badly */ -#define STOP_TIMED_OUT 9 /* simulation time limit exceeded */ -#define STOP_IMMEDIATE 10 /* simulator stop key pressed (immediate stop) */ -#define STOP_BREAK 11 /* simulator break key pressed */ -#define STOP_STEP 12 /* step count expired */ -#define STOP_OTHER 13 /* other reason, probably error returned by sim_process_event() */ - -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ - -#define INT_REQ_5 0x01 /* bits for interrupt levels (ipl, iplpending, int_req, int_mask) */ -#define INT_REQ_4 0x02 -#define INT_REQ_3 0x04 -#define INT_REQ_2 0x08 -#define INT_REQ_1 0x10 -#define INT_REQ_0 0x20 - -#define XIO_UNUSED 0x00 /* XIO commands */ -#define XIO_WRITE 0x01 -#define XIO_READ 0x02 -#define XIO_SENSE_IRQ 0x03 -#define XIO_CONTROL 0x04 -#define XIO_INITW 0x05 -#define XIO_INITR 0x06 -#define XIO_SENSE_DEV 0x07 - -#define XIO_FAILED 0x20 /* fake function to record error */ - -/* ILSW bits - set by appropriate device whenever an interrupt is outstanding */ - -#define ILSW_0_1442_CARD 0x8000 /* ILSW 0 is not really defined on the 1130 */ - -#define ILSW_1_1132_PRINTER 0x8000 /* had these backwards! */ -#define ILSW_1_SCA 0x4000 - -#define ILSW_2_1131_DISK 0x8000 - -#define ILSW_2_2310_DRV_1 0x4000 -#define ILSW_2_2310_DRV_2 0x2000 -#define ILSW_2_2310_DRV_3 0x1000 -#define ILSW_2_2310_DRV_4 0x0800 /* can have 2310 or 2311 */ - -#define ILSW_2_2311_DRV_1_DISK_1 0x4000 -#define ILSW_2_2311_DRV_1_DISK_2 0x2000 -#define ILSW_2_2311_DRV_1_DISK_3 0x1000 -#define ILSW_2_2311_DRV_1_DISK_4 0x0800 - -#define ILSW_2_2311_DRV_1_DISK_5 0x0400 -#define ILSW_2_2311_DRV_2_DISK_1 0x0200 -#define ILSW_2_2311_DRV_2_DISK_2 0x0100 -#define ILSW_2_2311_DRV_2_DISK_3 0x0080 -#define ILSW_2_2311_DRV_2_DISK_4 0x0040 -#define ILSW_2_2311_DRV_2_DISK_5 0x0020 - -#define ILSW_2_SAC_BIT_11 0x0010 -#define ILSW_2_SAC_BIT_12 0x0008 -#define ILSW_2_SAC_BIT_13 0x0004 -#define ILSW_2_SAC_BIT_14 0x0002 -#define ILSW_2_SAC_BIT_15 0x0001 - -#define ILSW_3_1627_PLOTTER 0x8000 -#define ILSW_3_SAC_BIT_01 0x4000 -#define ILSW_3_SAC_BIT_02 0x2000 -#define ILSW_3_SAC_BIT_03 0x1000 -#define ILSW_3_2250_DISPLAY 0x0800 -#define ILSW_3_SYSTEM7 0x0800 -#define ILSW_3_SAC_BIT_05 0x0400 -#define ILSW_3_SAC_BIT_06 0x0200 -#define ILSW_3_SAC_BIT_07 0x0100 -#define ILSW_3_SAC_BIT_08 0x0080 -#define ILSW_3_SAC_BIT_09 0x0040 -#define ILSW_3_SAC_BIT_10 0x0020 -#define ILSW_3_SAC_BIT_11 0x0010 -#define ILSW_3_SAC_BIT_12 0x0008 -#define ILSW_3_SAC_BIT_13 0x0004 -#define ILSW_3_SAC_BIT_14 0x0002 -#define ILSW_3_SAC_BIT_15 0x0001 - -#define ILSW_4_1134_TAPE 0x8000 -#define ILSW_4_1055_TAPE 0x8000 -#define ILSW_4_CONSOLE 0x4000 -#define ILSW_4_1442_CARD 0x2000 -#define ILSW_4_2501_CARD 0x1000 -#define ILSW_4_1403_PRINTER 0x0800 -#define ILSW_4_1231_MARK 0x0400 -#define ILSW_4_SAC_BIT_06 0x0200 -#define ILSW_4_SAC_BIT_07 0x0100 -#define ILSW_4_SAC_BIT_08 0x0080 -#define ILSW_4_SAC_BIT_09 0x0040 -#define ILSW_4_SAC_BIT_10 0x0020 -#define ILSW_4_SAC_BIT_11 0x0010 -#define ILSW_4_T2741_TERMINAL 0x0010 /* APL\1130 nonstandard serial interface uses this bit */ -#define ILSW_4_SAC_BIT_12 0x0008 -#define ILSW_4_SAC_BIT_13 0x0004 -#define ILSW_4_SAC_BIT_14 0x0002 -#define ILSW_4_SAC_BIT_15 0x0001 - -#define ILSW_5_INT_RUN_PROGRAM_STOP 0x8000 /* this replaces both ILSW_5_INT_RUN and ILSW_5_PROGRAM_STOP */ -#define ILSW_5_SAC_BIT_01 0x4000 -#define ILSW_5_SAC_BIT_02 0x2000 -#define ILSW_5_SAC_BIT_03 0x1000 -#define ILSW_5_SAC_BIT_04 0x0800 -#define ILSW_5_SAC_BIT_05 0x0400 -#define ILSW_5_SAC_BIT_06 0x0200 -#define ILSW_5_SAC_BIT_07 0x0100 -#define ILSW_5_SAC_BIT_08 0x0080 -#define ILSW_5_SAC_BIT_09 0x0040 -#define ILSW_5_SAC_BIT_10 0x0020 -#define ILSW_5_SAC_BIT_11 0x0010 -#define ILSW_5_SAC_BIT_12 0x0008 -#define ILSW_5_SAC_BIT_13 0x0004 -#define ILSW_5_SAC_BIT_14 0x0002 -#define ILSW_5_SAC_BIT_15 0x0001 - -/* CPU DSW bits */ - -#define CPU_DSW_PROGRAM_STOP 0x8000 -#define CPU_DSW_INT_RUN 0x4000 - -/* prototypes: xio handlers */ - -void xio_1131_console (int32 addr, int32 func, int32 modify); /* console keyboard and printer */ -void xio_1142_card (int32 addr, int32 func, int32 modify); /* standard card reader/punch */ -void xio_1134_papertape (int32 addr, int32 func, int32 modify); /* paper tape reader/punch */ -void xio_disk (int32 addr, int32 func, int32 modify, int drv); /* internal CPU disk */ -void xio_1627_plotter (int32 addr, int32 func, int32 modify); /* XY plotter */ -void xio_1132_printer (int32 addr, int32 func, int32 modify); /* standard line printer */ -void xio_1131_switches (int32 addr, int32 func, int32 modify); /* console buttons & switches */ -void xio_1231_optical (int32 addr, int32 func, int32 modify); /* optical mark page reader */ -void xio_2501_card (int32 addr, int32 func, int32 modify); /* alternate high-speed card reader */ -void xio_sca (int32 addr, int32 func, int32 modify); /* synchronous communications adapter */ -void xio_system7 (int32 addr, int32 func, int32 modify); /* system/7 interprocessor IO link */ -void xio_1403_printer (int32 addr, int32 func, int32 modify); /* alternate high-speed printer */ -void xio_2250_display (int32 addr, int32 func, int32 modify); /* vector display processor */ -void xio_t2741_terminal (int32 addr, int32 func, int32 modify); /* IO selectric via nonstandard serial interface for APL */ -void xio_error (char *msg); - -void bail (char *msg); -t_stat load_cr_boot (int drv, int switches); -t_stat cr_boot (int32 unitno, DEVICE *dptr); -t_stat cr_rewind (void); -t_stat cr_detach (UNIT *uptr); -void calc_ints (void); /* recalculate interrupt bitmask */ -void trace_io (char *fmt, ...); /* debugging printout */ -void trace_both (char *fmt, ...); /* debugging printout */ -t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help); -void scp_panic (char *msg); /* bail out of simulator */ -char *upcase(char *str); -void break_simulation (t_stat reason); /* let a device halt the simulation */ -char hollerith_to_ascii (uint16 hol); /* for debugging use only */ -t_bool gdu_active (void); -void remark_cmd (char *remark); -void stuff_cmd (char *cmd); -t_bool stuff_and_wait (char *cmd, int timeout, int delay); -void update_gui (t_bool force); -void sim_init (void); -t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help); -t_stat basic_attach (UNIT *uptr, char *cptr); -char * quotefix (char * cptr); - -/* GUI interface routines */ -t_bool keyboard_is_busy (void); -void forms_check (int set); /* device notification to console lamp display */ -void print_check (int set); -void keyboard_selected (int select); -void disk_ready (int ready); -void disk_unlocked (int unlocked); -void gui_run(int running); -char *read_cmdline (char *ptr, int size, FILE *stream); - -#ifdef GUI_SUPPORT -# define GUI_BEGIN_CRITICAL_SECTION begin_critical_section(); -# define GUI_END_CRITICAL_SECTION end_critical_section(); - void begin_critical_section (void); - void end_critical_section (void); -#else -# define GUI_BEGIN_CRITICAL_SECTION -# define GUI_END_CRITICAL_SECTION -#endif diff --git a/Ibm1130/ibm1130_disk.c b/Ibm1130/ibm1130_disk.c deleted file mode 100644 index 4b776470..00000000 --- a/Ibm1130/ibm1130_disk.c +++ /dev/null @@ -1,889 +0,0 @@ -/* ibm1130_disk.c: IBM 1130 disk IO simulator - -NOTE - there is a problem with this code. The Device Status Word (DSW) is -computed from current conditions when requested by an XIO load status -command; the value of DSW available to the simulator's examine & save -commands may NOT be accurate. This should probably be fixed. - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * Revision History - * 05-dec-06 Added cgiwritable mode - * - * 19-Dec-05 We no longer issue an operation complete interrupt if an INITR, INITW - * or CONTROL operation is attemped on a drive that is not online. DATA_ERROR - * is now only indicated in the DSW when - * - * 02-Nov-04 Addes -s option to boot to leave switches alone. - * 15-jun-03 moved actual read on XIO read to end of time interval, - * as the APL boot card required 2 instructions to run between the - * time read was initiated and the time the data was read (a jump and a wait) - * - * 01-sep-02 corrected treatment of -m and -r flags in dsk_attach - * in cgi mode, so that file is opened readonly but emulated - * disk is writable. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#include "ibm1130_defs.h" -#include "memory.h" - -#define TRACE_DMS_IO /* define to enable debug of DMS phase IO */ - -#ifdef TRACE_DMS_IO -extern int32 sim_switches; -extern int32 sim_quiet; -static int trace_dms = 0; -static void tracesector (int iswrite, int nwords, int addr, int sector); -static t_stat where_cmd (int32 flag, char *ptr); -static t_stat phdebug_cmd (int32 flag, char *ptr); -static t_stat fdump_cmd (int32 flags, char *cptr); -static void enable_dms_tracing (int newsetting); -#endif - -/* Constants */ - -#define DSK_NUMWD 321 /* words/sector */ -#define DSK_NUMSC 4 /* sectors/surface */ -#define DSK_NUMSF 2 /* surfaces/cylinder */ -#define DSK_NUMCY 203 /* cylinders/drive */ -#define DSK_NUMTR (DSK_NUMCY * DSK_NUMSF) /* tracks/drive */ -#define DSK_NUMDR 5 /* drives/controller */ -#define DSK_SIZE (DSK_NUMCY * DSK_NUMSF * DSK_NUMSC * DSK_NUMWD) /* words/drive */ - -#define UNIT_V_RONLY (UNIT_V_UF + 0) /* hwre write lock */ -#define UNIT_V_OPERR (UNIT_V_UF + 1) /* operation error flag */ -#define UNIT_V_HARDERR (UNIT_V_UF + 2) /* hard error flag (reset on power down) */ -#define UNIT_RONLY (1u << UNIT_V_RONLY) -#define UNIT_OPERR (1u << UNIT_V_OPERR) -#define UNIT_HARDERR (1u << UNIT_V_HARDERR) - -#define MEM_MAPPED(uptr) (uptr->flags & UNIT_BUF) /* disk buffered in memory */ - -#define IO_NONE 0 /* last operation, used to ensure fseek between read and write */ -#define IO_READ 1 -#define IO_WRITE 2 - -#define DSK_DSW_DATA_ERROR 0x8000 /* device status word bits */ -#define DSK_DSW_OP_COMPLETE 0x4000 -#define DSK_DSW_NOT_READY 0x2000 -#define DSK_DSW_DISK_BUSY 0x1000 -#define DSK_DSW_CARRIAGE_HOME 0x0800 -#define DSK_DSW_SECTOR_MASK 0x0003 - - /* device status words */ -static int16 dsk_dsw[DSK_NUMDR] = {DSK_DSW_NOT_READY, DSK_DSW_NOT_READY, DSK_DSW_NOT_READY, DSK_DSW_NOT_READY, DSK_DSW_NOT_READY}; -static int16 dsk_sec[DSK_NUMDR] = {0}; /* next-sector-up */ -static char dsk_lastio[DSK_NUMDR]; /* last stdio operation: IO_READ or IO_WRITE */ -int32 dsk_swait = 50; /* seek time -- see how short a delay we can get away with */ -int32 dsk_rwait = 50; /* rotate time */ -static t_bool raw_disk_debug = FALSE; - -static t_stat dsk_svc (UNIT *uptr); -static t_stat dsk_reset (DEVICE *dptr); -static t_stat dsk_attach (UNIT *uptr, char *cptr); -static t_stat dsk_detach (UNIT *uptr); -static t_stat dsk_boot (int32 unitno, DEVICE *dptr); - -static void diskfail (UNIT *uptr, int dswflag, int unitflag, t_bool do_interrupt); - -/* DSK data structures - - dsk_dev disk device descriptor - dsk_unit unit descriptor - dsk_reg register list -*/ - -UNIT dsk_unit[] = { - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) } -}; - -#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* current function */ - -REG dsk_reg[] = { - { HRDATA (DSKDSW0, dsk_dsw[0], 16) }, - { HRDATA (DSKDSW1, dsk_dsw[1], 16) }, - { HRDATA (DSKDSW2, dsk_dsw[2], 16) }, - { HRDATA (DSKDSW3, dsk_dsw[3], 16) }, - { HRDATA (DSKDSW4, dsk_dsw[4], 16) }, - { DRDATA (STIME, dsk_swait, 24), PV_LEFT }, - { DRDATA (RTIME, dsk_rwait, 24), PV_LEFT }, - { NULL } }; - -MTAB dsk_mod[] = { - { UNIT_RONLY, 0, "write enabled", "ENABLED", NULL }, - { UNIT_RONLY, UNIT_RONLY, "write locked", "LOCKED", NULL }, - { 0 } }; - -DEVICE dsk_dev = { - "DSK", dsk_unit, dsk_reg, dsk_mod, - DSK_NUMDR, 16, 16, 1, 16, 16, - NULL, NULL, &dsk_reset, - dsk_boot, dsk_attach, dsk_detach}; - -static int32 dsk_ilswbit[DSK_NUMDR] = { /* interrupt level status word bits for the drives */ - ILSW_2_1131_DISK, - ILSW_2_2310_DRV_1, - ILSW_2_2310_DRV_2, - ILSW_2_2310_DRV_3, - ILSW_2_2310_DRV_4, -}; - -static int32 dsk_ilswlevel[DSK_NUMDR] = -{ - 2, /* interrupt levels for the drives */ - 2, 2, 2, 2 -}; - -typedef enum {DSK_FUNC_IDLE, DSK_FUNC_READ, DSK_FUNC_VERIFY, DSK_FUNC_WRITE, DSK_FUNC_SEEK, DSK_FUNC_FAILED} DSK_FUNC; - -static struct tag_dsk_action { /* stores data needed for pending IO activity */ - int32 io_address; - uint32 io_filepos; - int io_nwords; - int io_sector; -} dsk_action[DSK_NUMDR]; - -/* xio_disk - XIO command interpreter for the disk drives */ -/* - * device status word: - * - * 0 data error, occurs when: - * 1. A modulo 4 error is detected during a read, read-check, or write operation. - * 2. The disk storage is in a read or write mode at the leading edge of a sector pulse. - * 3. A seek-incomplete signal is received from the 2311. - * 4. A write select error has occurred in the disk storage drive. - * 5. The power unsafe latch is set in the attachment. - * Conditions 1, 2, and 3 are turned off by a sense device command with modifier bit 15 - * set to 1. Conditions 4 and 5 are turned off by powering the drive off and back on. - * 1 operation complete - * 2 not ready, occurs when disk not ready or busy or disabled or off-line or - * power unsafe latch set. Also included in the disk not ready is the write select error, - * which can be a result of power unsafe or write select. - * 3 disk busy - * 4 carriage home (on cyl 0) - * 15-16: number of next sector spinning into position. - */ - -extern void void_backtrace (int afrom, int ato); - -void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv) -{ - int i, rev, nsteps, newcyl, sec, nwords; - uint32 newpos; /* changed from t_addr to uint32 in anticipation of simh 64-bit development */ - char msg[80]; - UNIT *uptr = dsk_unit+drv; - int16 buf[DSK_NUMWD]; - - if (! BETWEEN(drv, 0, DSK_NUMDR-1)) { /* hmmm, invalid drive */ - if (func != XIO_SENSE_DEV) { /* tried to use it, too */ - /* just do nothing, as if the controller isn't there. NAMCRA at N0116300 tests for drives by attempting reads - sprintf(msg, "Op %x on invalid drive number %d", func, drv); - xio_error(msg); - */ - } - return; - } - - CLRBIT(uptr->flags, UNIT_OPERR); /* clear pending error flag from previous op, if any */ - - switch (func) { - case XIO_INITR: - if (! IS_ONLINE(uptr)) { /* disk is offline */ - diskfail(uptr, 0, 0, FALSE); - break; - } - - sim_cancel(uptr); /* cancel any pending ops */ - dsk_dsw[drv] |= DSK_DSW_DISK_BUSY; /* and mark the disk as busy */ - - nwords = M[iocc_addr++ & mem_mask]; /* get word count w/o upsetting SAR/SBR */ - - if (nwords == 0) /* this is bad -- on real 1130, this locks up disk controller ! */ - break; - - if (! BETWEEN(nwords, 1, DSK_NUMWD)) { /* count bad */ - SETBIT(uptr->flags, UNIT_OPERR); /* set data error DSW bit when op complete */ - nwords = DSK_NUMWD; /* limit xfer to proper sector size */ - } - - sec = modify & 0x07; /* get sector on cylinder */ - - if ((modify & 0x0080) == 0) { /* it's a real read if it's not a read check */ - /* ah. We have a problem. The APL boot card counts on there being time for at least one - * more instruction to execute between the XIO read and the time the data starts loading - * into core. So, we have to defer the actual read operation a bit. Might as well wait - * until it's time to issue the operation complete interrupt. This means saving the - * IO information, then performing the actual read in dsk_svc. - */ - - newpos = (uptr->CYL*DSK_NUMSC*DSK_NUMSF + sec)*2*DSK_NUMWD; - - dsk_action[drv].io_address = iocc_addr; - dsk_action[drv].io_nwords = nwords; - dsk_action[drv].io_sector = sec; - dsk_action[drv].io_filepos = newpos; - - uptr->FUNC = DSK_FUNC_READ; - } - else { - trace_io("* DSK%d verify %d.%d (%x)", drv, uptr->CYL, sec, uptr->CYL*8 + sec); - - if (raw_disk_debug) - printf("* DSK%d verify %d.%d (%x)", drv, uptr->CYL, sec, uptr->CYL*8 + sec); - - uptr->FUNC = DSK_FUNC_VERIFY; - } - - sim_activate(uptr, dsk_rwait); - break; - - case XIO_INITW: - if (! IS_ONLINE(uptr)) { /* disk is offline */ - diskfail(uptr, 0, 0, FALSE); - break; - } - - if (uptr->flags & UNIT_RONLY) { /* oops, write to RO disk? permanent error until disk is powered off/on */ - diskfail(uptr, DSK_DSW_DATA_ERROR, UNIT_HARDERR, FALSE); - break; - } - - sim_cancel(uptr); /* cancel any pending ops */ - dsk_dsw[drv] |= DSK_DSW_DISK_BUSY; /* and mark drive as busy */ - - nwords = M[iocc_addr++ & mem_mask]; /* get word count w/o upsetting SAR/SBR */ - - if (nwords == 0) /* this is bad -- locks up disk controller ! */ - break; - - if (! BETWEEN(nwords, 1, DSK_NUMWD)) { /* count bad */ - SETBIT(uptr->flags, UNIT_OPERR); /* set data error DSW bit when op complete */ - nwords = DSK_NUMWD; /* limit xfer to proper sector size */ - } - - sec = modify & 0x07; /* get sector on cylinder */ - newpos = (uptr->CYL*DSK_NUMSC*DSK_NUMSF + sec)*2*DSK_NUMWD; - - trace_io("* DSK%d wrote %d words from M[%04x-%04x] to %d.%d (%x, %x)", drv, nwords, iocc_addr & mem_mask, (iocc_addr + nwords - 1) & mem_mask, uptr->CYL, sec, uptr->CYL*8 + sec, newpos); - - if (raw_disk_debug) - printf("* DSK%d XIO @ %04x wrote %d words from M[%04x-%04x] to %d.%d (%x, %x)\n", drv, prev_IAR, nwords, iocc_addr & mem_mask, (iocc_addr + nwords - 1) & mem_mask, uptr->CYL, sec, uptr->CYL*8 + sec, newpos); - -#ifdef TRACE_DMS_IO - if (trace_dms) - tracesector(1, nwords, iocc_addr & mem_mask, uptr->CYL*8 + sec); -#endif - for (i = 0; i < nwords; i++) - buf[i] = M[iocc_addr++ & mem_mask]; - - for (; i < DSK_NUMWD; i++) /* rest of sector gets zeroed */ - buf[i] = 0; - - i = uptr->CYL*8 + sec; - if (buf[0] != i) - printf("*DSK writing bad sector#\n"); - - if (MEM_MAPPED(uptr)) { - memcpy((char *) uptr->filebuf + newpos, buf, 2*DSK_NUMWD); - uptr->hwmark = newpos + 2*DSK_NUMWD; - } - else { - if (uptr->pos != newpos || dsk_lastio[drv] != IO_WRITE) { - fseek(uptr->fileref, newpos, SEEK_SET); - dsk_lastio[drv] = IO_WRITE; - } - - fxwrite(buf, 2, DSK_NUMWD, uptr->fileref); - uptr->pos = newpos + 2*DSK_NUMWD; - } - - uptr->FUNC = DSK_FUNC_WRITE; - sim_activate(uptr, dsk_rwait); - break; - - case XIO_CONTROL: /* step fwd/rev */ - if (! IS_ONLINE(uptr)) { - diskfail(uptr, 0, 0, FALSE); - break; - } - - sim_cancel(uptr); - - rev = modify & 4; - nsteps = iocc_addr & 0x00FF; - if (nsteps == 0) /* 0 steps does not cause op complete interrupt */ - break; - - newcyl = uptr->CYL + (rev ? (-nsteps) : nsteps); - if (newcyl < 0) - newcyl = 0; - else if (newcyl >= DSK_NUMCY) - newcyl = DSK_NUMCY-1; - - uptr->FUNC = DSK_FUNC_SEEK; - uptr->CYL = newcyl; - sim_activate(uptr, dsk_swait); /* schedule interrupt */ - - dsk_dsw[drv] |= DSK_DSW_DISK_BUSY; - trace_io("* DSK%d at cyl %d", drv, newcyl); - break; - - case XIO_SENSE_DEV: - CLRBIT(dsk_dsw[drv], DSK_DSW_CARRIAGE_HOME|DSK_DSW_NOT_READY); - - if ((uptr->flags & UNIT_HARDERR) || (dsk_dsw[drv] & DSK_DSW_DISK_BUSY) || ! IS_ONLINE(uptr)) - SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY); - else if (uptr->CYL <= 0) { - SETBIT(dsk_dsw[drv], DSK_DSW_CARRIAGE_HOME); - uptr->CYL = 0; - } - - dsk_sec[drv] = (int16) ((dsk_sec[drv] + 1) % 4); /* advance the "next sector" count every time */ - ACC = dsk_dsw[drv] | dsk_sec[drv]; - - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(dsk_dsw[drv], DSK_DSW_OP_COMPLETE|DSK_DSW_DATA_ERROR); - CLRBIT(ILSW[dsk_ilswlevel[drv]], dsk_ilswbit[drv]); - } - break; - - default: - sprintf(msg, "Invalid disk XIO function %x", func); - xio_error(msg); - } -} - -/* diskfail - schedule an operation complete that sets the error bit */ - -static void diskfail (UNIT *uptr, int dswflag, int unitflag, t_bool do_interrupt) -{ - int drv = uptr - dsk_unit; - - sim_cancel(uptr); /* cancel any pending ops */ - SETBIT(dsk_dsw[drv], dswflag); /* set any specified DSW bits */ - SETBIT(uptr->flags, unitflag); /* set any specified unit flag bits */ - uptr->FUNC = DSK_FUNC_FAILED; /* tell svc routine why it failed */ - - if (do_interrupt) - sim_activate(uptr, 1); /* schedule an immediate op complete interrupt */ -} - -t_stat dsk_svc (UNIT *uptr) -{ - int drv = uptr - dsk_unit, i, nwords, sec; - int16 buf[DSK_NUMWD]; - uint32 newpos; /* changed from t_addr to uint32 in anticipation of simh 64-bit development */ - int32 iocc_addr; - - if (uptr->FUNC == DSK_FUNC_IDLE) /* service function called with no activity? not good, but ignore */ - return SCPE_OK; - - CLRBIT(dsk_dsw[drv], DSK_DSW_DISK_BUSY); /* activate operation complete interrupt */ - SETBIT(dsk_dsw[drv], DSK_DSW_OP_COMPLETE); - - if (uptr->flags & (UNIT_OPERR|UNIT_HARDERR)) { /* word count error or data error */ - SETBIT(dsk_dsw[drv], DSK_DSW_DATA_ERROR); - CLRBIT(uptr->flags, UNIT_OPERR); /* soft error is one time occurrence; don't clear hard error */ - } - /* schedule interrupt */ - SETBIT(ILSW[dsk_ilswlevel[drv]], dsk_ilswbit[drv]); - - switch (uptr->FUNC) { /* take care of business */ - case DSK_FUNC_IDLE: - case DSK_FUNC_VERIFY: - case DSK_FUNC_WRITE: - case DSK_FUNC_SEEK: - case DSK_FUNC_FAILED: - break; - - case DSK_FUNC_READ: /* actually read the data into core */ - iocc_addr = dsk_action[drv].io_address; /* recover saved parameters */ - nwords = dsk_action[drv].io_nwords; - newpos = dsk_action[drv].io_filepos; - sec = dsk_action[drv].io_sector; - - if (MEM_MAPPED(uptr)) { - memcpy(buf, (char *) uptr->filebuf + newpos, 2*DSK_NUMWD); - } - else { - if (uptr->pos != newpos || dsk_lastio[drv] != IO_READ) { - fseek(uptr->fileref, newpos, SEEK_SET); - dsk_lastio[drv] = IO_READ; - uptr->pos = newpos; - } - fxread(buf, 2, DSK_NUMWD, uptr->fileref); /* read whole sector so we're in position for next read */ - uptr->pos = newpos + 2*DSK_NUMWD; - } - - void_backtrace(iocc_addr, iocc_addr + nwords - 1); /* mark prev instruction as altered */ - - trace_io("* DSK%d read %d words from %d.%d (%x, %x) to M[%04x-%04x]", drv, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask, - (iocc_addr + nwords - 1) & mem_mask); - - /* this will help debug the monitor by letting me watch phase loading */ - if (raw_disk_debug) - printf("* DSK%d XIO @ %04x read %d words from %d.%d (%x, %x) to M[%04x-%04x]\n", drv, prev_IAR, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask, - (iocc_addr + nwords - 1) & mem_mask); - - i = uptr->CYL*8 + sec; - if (buf[0] != i) - printf("*DSK read bad sector #\n"); - - for (i = 0; i < nwords; i++) - M[(iocc_addr+i) & mem_mask] = buf[i]; - -#ifdef TRACE_DMS_IO - if (trace_dms) - tracesector(0, nwords, iocc_addr & mem_mask, uptr->CYL*8 + sec); -#endif - break; - - default: - fprintf(stderr, "Unexpected FUNC %x in dsk_svc(%d)\n", uptr->FUNC, drv); - break; - - } - - uptr->FUNC = DSK_FUNC_IDLE; /* we're done with this operation */ - - return SCPE_OK; -} - -t_stat dsk_reset (DEVICE *dptr) -{ - int drv; - UNIT *uptr; - -#ifdef TRACE_DMS_IO - /* add the WHERE command. It finds the phase that was loaded at given address and indicates */ - /* the offset in the phase */ - register_cmd("WHERE", &where_cmd, 0, "w{here} address find phase and offset of an address\n"); - register_cmd("PHDEBUG", &phdebug_cmd, 0, "ph{debug} off|phlo phhi break on phase load\n"); - register_cmd("FDUMP", &fdump_cmd, 0, NULL); -#endif - - for (drv = 0, uptr = dsk_dev.units; drv < DSK_NUMDR; drv++, uptr++) { - sim_cancel(uptr); - - CLRBIT(ILSW[2], dsk_ilswbit[drv]); - CLRBIT(uptr->flags, UNIT_OPERR|UNIT_HARDERR); - - uptr->CYL = 0; - uptr->FUNC = DSK_FUNC_IDLE; - dsk_dsw[drv] = (int16) ((uptr->flags & UNIT_ATT) ? DSK_DSW_CARRIAGE_HOME : 0); - } - - calc_ints(); - - return SCPE_OK; -} - -static t_stat dsk_attach (UNIT *uptr, char *cptr) -{ - int drv = uptr - dsk_unit; - t_stat rval; - - sim_cancel(uptr); /* cancel current IO */ - dsk_lastio[drv] = IO_NONE; - - if (uptr->flags & UNIT_ATT) /* dismount current disk */ - if ((rval = dsk_detach(uptr)) != SCPE_OK) - return rval; - - uptr->CYL = 0; /* reset the device */ - uptr->FUNC = DSK_FUNC_IDLE; - dsk_dsw[drv] = DSK_DSW_CARRIAGE_HOME; - - CLRBIT(uptr->flags, UNIT_RO|UNIT_ROABLE|UNIT_BUFABLE|UNIT_BUF|UNIT_RONLY|UNIT_OPERR|UNIT_HARDERR); - CLRBIT(ILSW[2], dsk_ilswbit[drv]); - calc_ints(); - - if (sim_switches & SWMASK('M')) /* if memory mode (e.g. for CGI), buffer the file */ - SETBIT(uptr->flags, UNIT_BUFABLE|UNIT_MUSTBUF); - - if (sim_switches & SWMASK('R')) /* read lock mode */ - SETBIT(uptr->flags, UNIT_RO|UNIT_ROABLE|UNIT_RONLY); - - if (cgi && (sim_switches & SWMASK('M')) && ! cgiwritable) { /* if cgi and memory mode, but writable option not specified */ - sim_switches |= SWMASK('R'); /* have attach_unit open file in readonly mode */ - SETBIT(uptr->flags, UNIT_ROABLE); /* but don't set the UNIT_RONLY flag so DMS can write to the buffered image */ - } - - if ((rval = attach_unit(uptr, quotefix(cptr))) != SCPE_OK) { /* mount new disk */ - SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY); - return rval; - } - - if (drv == 0) { - disk_ready(TRUE); - disk_unlocked(FALSE); - } - - enable_dms_tracing(sim_switches & SWMASK('D')); - raw_disk_debug = sim_switches & SWMASK('G'); - - return SCPE_OK; -} - -static t_stat dsk_detach (UNIT *uptr) -{ - t_stat rval; - int drv = uptr - dsk_unit; - - sim_cancel(uptr); - - if ((rval = detach_unit(uptr)) != SCPE_OK) - return rval; - - CLRBIT(ILSW[2], dsk_ilswbit[drv]); - CLRBIT(uptr->flags, UNIT_OPERR|UNIT_HARDERR); - calc_ints(); - - uptr->CYL = 0; - uptr->FUNC = DSK_FUNC_IDLE; - dsk_dsw[drv] = DSK_DSW_NOT_READY; - - if (drv == 0) { - disk_unlocked(TRUE); - disk_ready(FALSE); - } - - return SCPE_OK; -} - -/* boot routine - if they type BOOT DSK, load the standard boot card. */ - -static t_stat dsk_boot (int32 unitno, DEVICE *dptr) -{ - t_stat rval; - - if ((rval = reset_all(0)) != SCPE_OK) - return rval; - - return load_cr_boot(unitno, sim_switches); -} - -#ifdef TRACE_DMS_IO - -static struct { - int phid; - char *name; -} phase[] = { -# include "dmsr2v12phases.h" - 0xFFFF, "" -}; - -#pragma pack(2) -#define MAXSLET ((3*320)/4) -struct tag_slet { - int16 phid; - int16 addr; - int16 nwords; - int16 sector; -} slet[MAXSLET] = { -# include "dmsr2v12slet.h" /* without RPG, use this info until overwritten by actual data from disk */ -}; - -#pragma pack() - -#define MAXMSEG 100 -struct tag_mseg { - char *name; - int addr, offset, len, phid; -} mseg[MAXMSEG]; -int nseg = 0; - -static void enable_dms_tracing (int newsetting) -{ - nseg = 0; /* clear the segment map */ - - if ((newsetting && trace_dms) || ! (newsetting || trace_dms)) - return; - - trace_dms = newsetting; - if (! sim_quiet) - printf("DMS disk tracing is now %sabled\n", trace_dms ? "en" : "dis"); -} - -char * saywhere (int addr) -{ - int i; - static char buf[150]; - - for (i = 0; i < nseg; i++) { - if (addr >= mseg[i].addr && addr < (mseg[i].addr+mseg[i].len)) { - sprintf(buf, "/%04x = /%04x + /%x in ", addr, mseg[i].addr - mseg[i].offset, addr-mseg[i].addr + mseg[i].offset); - if (mseg[i].phid > 0) - sprintf(buf+strlen(buf), "phase %02x (%s)", mseg[i].phid, mseg[i].name); - else - sprintf(buf+strlen(buf), "%s", mseg[i].name); - - return buf; - } - } - return NULL; -} - -static int phdebug_lo = -1, phdebug_hi = -1; - -static t_stat phdebug_cmd (int32 flag, char *ptr) -{ - int val1, val2; - - if (strcmpi(ptr, "off") == 0) - phdebug_lo = phdebug_hi = -1; - else { - switch(sscanf(ptr, "%x%x", &val1, &val2)) { - case 1: - phdebug_lo = phdebug_hi = val1; - enable_dms_tracing(TRUE); - break; - - case 2: - phdebug_lo = val1; - phdebug_hi = val2; - enable_dms_tracing(TRUE); - break; - - default: - printf("Usage: phdebug off | phdebug phfrom [phto]\n"); - break; - } - } - return SCPE_OK; -} - -static t_stat where_cmd (int32 flag, char *ptr) -{ - int addr; - char *where; - - if (! trace_dms) { - printf("Tracing is disabled. To enable, attach disk with -d switch\n"); - return SCPE_OK; - } - - if (sscanf(ptr, "%x", &addr) != 1) - return SCPE_ARG; - - if ((where = saywhere(addr)) == NULL) - printf("/%04x not found\n", addr); - else - printf("%s\n", where); - - return SCPE_OK; -} - -/* savesector - save info on a sector just read. THIS IS NOT YET TESTED */ - -static void addseg (int i) -{ - if (! trace_dms) - return; - - if (nseg >= MAXMSEG) { - printf("(Memory map full, disabling tracing)\n"); - trace_dms = 0; - nseg = -1; - return; - } - memcpy(mseg+i+1, mseg+i, (nseg-i)*sizeof(mseg[0])); - nseg++; -} - -static void delseg (int i) -{ - if (! trace_dms) - return; - - if (nseg > 0) { - nseg--; - memcpy(mseg+i, mseg+i+1, (nseg-i)*sizeof(mseg[0])); - } -} - -static void savesector (int addr, int offset, int len, int phid, char *name) -{ - int i; - - if (! trace_dms) - return; - - addr++; /* first word is sector address, so account for that */ - len--; - - for (i = 0; i < nseg; i++) { - if (addr >= (mseg[i].addr+mseg[i].len)) /* entirely after this entry */ - continue; - - if (mseg[i].addr < addr) { /* old one starts before this. split it */ - addseg(i); - mseg[i].len = addr-mseg[i].addr; - i++; - mseg[i].addr = addr; - mseg[i].len -= mseg[i-1].len; - } - - break; - } - - addseg(i); /* add new segment. Old one ends up after this */ - - if (i >= MAXMSEG) - return; - - mseg[i].addr = addr; - mseg[i].offset = offset; - mseg[i].phid = phid; - mseg[i].len = len; - mseg[i].name = name; - - i++; /* delete any segments completely covered */ - - while (i < nseg && (mseg[i].addr+mseg[i].len) <= (addr+len)) - delseg(i); - - if (i < nseg && mseg[i].addr < (addr+len)) { /* old one extends past this. Retain the end */ - mseg[i].len = (mseg[i].addr+mseg[i].len) - (addr+len); - mseg[i].addr = addr+len; - } -} - -static void tracesector (int iswrite, int nwords, int addr, int sector) -{ - int i, phid = 0, offset = 0; - char *name = NULL; - - if (nwords < 3 || ! trace_dms) - return; - - switch (sector) { /* explicitly known sector name */ - case 0: name = "ID/COLD START"; break; - case 1: name = "DCOM"; break; - case 2: name = "RESIDENT IMAGE"; break; - case 3: - case 4: - case 5: name = "SLET"; /* save just-read or written SLET info */ - memmove(&slet[(320/4)*(sector-3)], &M[addr+1], nwords*2); - break; - case 6: name = "RELOAD TABLE"; break; - case 7: name = "PAGE HEADER"; break; - } - - printf("* %04x: %3d /%04x %c %3d.%d ", - prev_IAR, nwords, addr, iswrite ? 'W' : 'R', sector/8, sector%8); - - if (name == NULL) { /* look up sector in SLET */ - for (i = 0; i < MAXSLET; i++) { - if (slet[i].phid == 0) /* not found */ - goto done; - else if (slet[i].sector > sector) { - if (--i >= 0) { - if (sector >= slet[i].sector && sector <= (slet[i].sector + slet[i].nwords/320)) { - phid = slet[i].phid; - offset = (sector-slet[i].sector)*320; - break; - } - } - goto done; - } - if (slet[i].sector == sector) { - phid = slet[i].phid; /* we found the starting sector */ - break; - } - } - - if (i >= MAXSLET) /* was not found */ - goto done; - - name = "?"; - for (i = sizeof(phase)/sizeof(phase[0]); --i >= 0; ) { - if (phase[i].phid == phid) { /* look up name */ - name = phase[i].name; - break; - } - } - printf("%02x %s", phid, name); - } - else - printf("%s", name); - -done: - putchar('\n'); - - if (phid >= phdebug_lo && phid <= phdebug_hi && offset == 0) - break_simulation(STOP_PHASE_BREAK); /* break on read of first sector of indicated phases */ - - if (name != NULL && *name != '?' && ! iswrite) - savesector(addr, offset, nwords, phid, name); -} - -static t_stat fdump_cmd (int32 flags, char *cptr) -{ - int addr = 0x7a24; /* address of next statement */ - int sofst = 0x7a26, symaddr; - int cword, nwords, stype, has_stnum, strel = 1, laststno = 0; - - addr = M[addr & mem_mask] & mem_mask; /* get address of first statement */ - sofst = M[sofst & mem_mask] & mem_mask ; /* get address of symbol table */ - - for (;;) { - cword = M[addr]; - nwords = (cword >> 2) & 0x01FF; - stype = (cword >> 1) & 0x7C00; - has_stnum = (cword & 1); - - if (has_stnum) { - laststno++; - strel = 0; - } - - printf("/%04x [%4d +%3d] %3d - %04x", addr, laststno, strel, nwords, stype); - - if (has_stnum) { - addr++; - nwords--; - symaddr = sofst - (M[addr] & 0x7FF)*3 + 3; - printf(" [%04x %04x %04x]", M[symaddr], M[symaddr+1], M[symaddr+2]); - } - - if (stype == 0x5000) { /* error record */ - printf(" (err %d)", M[addr+1]); - } - - if (stype == 0x0800) - break; - - addr += nwords; - putchar('\n'); - - if (nwords == 0) { - printf("0 words?\n"); - break; - } - strel++; - } - - printf("\nEnd found at /%04x, EOFS = /%04x\n", addr, M[0x7a25 & mem_mask]); - return SCPE_OK; -} - -#endif /* TRACE_DMS_IO */ diff --git a/Ibm1130/ibm1130_fmt.c b/Ibm1130/ibm1130_fmt.c deleted file mode 100644 index 8178de89..00000000 --- a/Ibm1130/ibm1130_fmt.c +++ /dev/null @@ -1,313 +0,0 @@ -/********************************************************************************************* - * ibm1130_fmt.c : interpret tabs in 1130 Assembler or Fortran source - * Bob Flanders - * ------------------------------------------------------------------------------------------- - * - * These routines are used by ibm1130_cr.c when the user has indicated - * that the input text is formatted with tabs. Input lines are edited - * into the appropriate column format. Three edit modes are recognized: - * - * Assembler mode: - * Input lines of the form - * - * [label][opcode][tag][L][argument] - * - * are rearranged so that the input fields are placed in the appropriate columns - * - * The label must start on the first character of the line. If there is no label, - * the first character(s) before the opcode must be whitespace. Following the opcode, there - * MUST be a tab character, followed by the format and tag. Following the format and tag - * may be exactly one whitespace character, and then starts the argument. - * - * Input lines with * in column 1 and blank lines are turned into Assembler comments, - * with the * in the Opcode field. - * - * Assembler directive lines at the beginning of the deck must be preceded by - * ! to indicate that they are not comments. For example, - * - * !*LIST - * * This is a comment - * - * Fortran mode: - * Input lines of the form - * - * [label]statement - * - * or - * - * [label]Xcontinuation - * - * where X is a non alphabetic contination character are rearranged in the - * appropriate manner: - * - * 1 2 - * 12345678901234567890... - * ------------------------ - * label statement - * labelXcontinuation - * - * However, you must take care that you don't end up with statement text after column 72. - * - * Input lines with * or C in column 1 are left alone (comments and directives) - * - * (The ! escape is not used before Fortran directives as before Assembler directives) - * - * Tab mode: - * Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide, - * as is standard for vi, notepad, etc. - *********************************************************************************************/ - -#include -#include -#include -#include -#include -#include "ibm1130_fmt.h" - -#define MAXLINE 81 /* maximum output line size */ -#define WORKSZ 256 /* size for tab work area */ -#define TAGOFFSET 12 /* offset for tag field */ -#define FMTOFFSET 11 /* offset for format field */ - -#define MIN(a,b) ((a < b) ? a : b) -#define AMSG " with Assembler Reformat" -#define FMSG " with FORTRAN Reformat" -#define AFORMAT "%20.20s%-60.60s"," " -#define ACOMMENTFMT "%20.20s%-60.60s"," " -#define ABLANKLINE "%20.20s*"," " -#define FFORMAT "%-5.5s %-74.74s" -#define FCONTFMT "%-5.5s%-75.75s" - -char gszLabel[6]; /* work area for label */ -char gszArg[MAXLINE]; /* .. argument */ -char gszOutput[MAXLINE]; /* .. output */ -short gaiAsmTabs[] = {7,12,15,20,25,30,35,40,45,52,0};/* tab stops for assembler */ - -short gaiPlainTabs[] = {9, 17, 25, 33, 41, 49, 57, 65, 73, 0};/* tab stops for just plain tabs */ - -/* - * helper routines - */ - -/************************************************* - * ExpandTabs: Expand tabs to spaces - */ - -char* ExpandTabs(char* p_szInbuf, /* expand tabs .. input buffer */ - char* p_szOutbuf, /* .. output buffer */ - short* p_aiTabs) /* .. array of tab stops (1 based) -- 0 end of array */ -{ -short iI, /* input position */ - iO, /* output position */ - iT; /* next tab stop */ - -char cX; /* character to test */ - - iI = 0; /* init input position */ - iO = 0; /* init output position */ - iT = 0; /* init tab stop */ - - while ((cX = *(p_szInbuf + iI)) != 0) /* while there are characters */ - { - if (cX == '\t') /* q. tab character? */ - { /* a. yes .. */ - while ((p_aiTabs[iT] <= iO + 1) /* search for next valid stop .. */ - && (p_aiTabs[iT] != 0)) /* .. or end of table */ - iT++; /* .. go to next tab */ - - if (p_aiTabs[iT] != 0) /* q. end of tab array? */ - { /* a. no .. */ - while (iO < (p_aiTabs[iT] - 1)) /* fill to tab with blanks */ - *(p_szOutbuf + iO++) = ' '; /* .. put in a blank */ - - } - else /* Otherwise ... */ - *(p_szOutbuf + iO++) = ' '; /* .. Translate to blank */ - } - else /* Otherwise .. not tab */ - *(p_szOutbuf + iO++) = cX; /* .. save the input char */ - - iI++; /* next input character */ - } - - *(p_szOutbuf + iO) = 0; /* end the string.. */ - return p_szOutbuf; /* .. return output area addr */ -} - -/************************************************* - * extract next token, modify pointer - */ - -char* GetToken(char* p_szOut, /* output location */ - int p_iLen, /* max output length */ - char**p_pszToken) /* pointer to input token */ -{ -int iI; /* work integer */ -char* pszX; /* work pointer */ - - pszX = *p_pszToken; /* get pointer to token */ - - for (iI = 0; *(pszX + iI) && (!isspace(*(pszX + iI)));) /* while not whitespace & not end */ - iI++; /* .. count token length */ - - memset(p_szOut, 0, p_iLen); /* zero out output area */ - - if (iI > 0) /* q. any chars? */ - strncpy(p_szOut, *p_pszToken, MIN(iI, p_iLen-1)); /* a. yes.. copy max of p_iLen-1 */ - - *p_pszToken += iI; /* point beyond token */ - return p_szOut; /* .. return token pointer */ -} - -/************************************************* - * EditToAsm - convert tab-formatted text line to 1130 Assembler format - */ - -char *EditToAsm (char* p_pszEdit) /* convert line to 1130 assembler */ -{ -char pszLine[MAXLINE]; /* source line */ -char pszWork[WORKSZ]; /* work buffer */ -char acTFWrk[2]; /* tag/format work area */ -size_t iI; /* work integer */ - - if (p_pszEdit == NULL) /* q. null request? */ - return AMSG; /* a. yes .. return display message */ - - if (*p_pszEdit == '!') /* leave lines starting with ! alone */ - return EditToWhitespace(p_pszEdit+1); - - if (*p_pszEdit == '*') /* q. comment line? */ - { /* a. yes.. */ - strncpy(pszWork, EditToWhitespace(p_pszEdit), MAXLINE); /* .. convert any tabs */ - sprintf(gszOutput, ACOMMENTFMT, pszWork); /* .. put the comment out there in the opcode column */ - return gszOutput; /* .. and return it */ - } - - strncpy(pszLine, p_pszEdit, MAXLINE-1); /* copy the line local */ - - ExpandTabs(pszLine, pszWork, gaiAsmTabs); /* expand the tabs */ - strncpy(pszLine, pszWork, MAXLINE-1); /* copy the line back */ - - for (iI = strlen(pszLine); iI--;) /* trim trailing whitespace */ - { - if (*(pszLine + iI) <= ' ') /* q. space or less? */ - *(pszLine + iI) = 0; /* a. yes .. remove it */ - else /* otherwise */ - break; /* .. done. Leave loop. */ - } - - if (strlen(pszLine) == 0) /* q. blank line? */ - { /* a. yes .. Assembler abhors these so */ - sprintf(gszOutput, ABLANKLINE); /* format as comment statement */ - return gszOutput; /* .. and return it */ - } - - - /* TODO: Add code to process a strip switch - * comment? - */ - - if (strlen(pszLine) > (TAGOFFSET + 1)) /* q. line long enough? */ - { /* a. yes.. reorder tag/format */ - memcpy(acTFWrk, pszLine + FMTOFFSET, 2); /* get tag/format */ - memset((pszLine + FMTOFFSET), ' ', 2); /* .. blank 'em out */ - - for (iI = 0; iI < 2; iI ++) - if (isalpha(acTFWrk[iI])) /* q. alpha char? */ - *(pszLine + FMTOFFSET) = acTFWrk[iI]; /* a. yes .. make it format */ - else if (isdigit(acTFWrk[iI])) /* q. digit? */ - *(pszLine + TAGOFFSET) = acTFWrk[iI]; /* a. yes .. make it the tag */ - } - - sprintf(gszOutput, AFORMAT, pszLine); /* format the line */ - - return gszOutput; /* return formatted line */ -} - -/************************************************* - * EditToFortran - convert tab-formatted input text line to FORTRAN format - * (a la DEC Fortran) - */ - -char *EditToFortran(char* p_pszEdit) /* convert line to 1130 assembler */ -{ -char pszLine[MAXLINE]; /* source line */ -char* pszWork; /* work pointer */ -size_t iI; /* work integer */ -int bContinue; /* true if continue */ - - if (p_pszEdit == NULL) /* q. null request? */ - return FMSG; /* a. yes .. return display message */ - - if (strchr(p_pszEdit, '\t') == NULL) /* q. no tab in the line? */ - return p_pszEdit; /* a. nope, return line as is, assume it's formatted correctly */ - - if (*p_pszEdit == 'C' || *p_pszEdit == '*' || *p_pszEdit == '\0') /* q. comment or directive or blank line? */ - { /* a. yes.. don't restructure */ - return EditToWhitespace(p_pszEdit); - } - - strncpy(pszLine, p_pszEdit, MAXLINE-1); /* copy the line local */ - - for (iI = strlen(pszLine); iI--;) /* trim trailing whitespace */ - { - if (*(pszLine + iI) <= ' ') /* q. space or less? */ - *(pszLine + iI) = 0; /* a. yes .. remove it */ - else /* otherwise */ - break; /* .. done. Leave loop. */ - } - - /* - * TODO: Add code to process a strip switch - * comment? - */ - - pszWork = (char*) pszLine; /* set pointer to line */ - GetToken(gszLabel, 6, &pszWork); /* get the line, if any. */ - - pszWork++; /* skip tab/whitespace */ - - /* continuation... */ - bContinue = ((isdigit(*pszWork) && (*pszWork != '0')) /* if first char non-zero digit */ - || (!isspace(*pszWork) && !isalpha(*pszWork))); /* .. or non-alpha non-blank */ - - memset(gszArg, 0, MAXLINE); /* .. and arguments */ - - strncpy(gszArg, pszWork, 75); /* copy rest to argument */ - - sprintf(gszOutput, (bContinue) ? FCONTFMT : FFORMAT, /* format the line */ - gszLabel, /* .. statement # */ - gszArg); /* .. code */ - - return gszOutput; /* return formatted line */ -} - -/************************************************* - * EditToWhitespace - expand tabs at 8 space intervals. - */ - -char* EditToWhitespace(char *p_pszEdit) -{ -int iI; /* work integer */ -char pszLine[MAXLINE]; /* source line */ -char pszWork[WORKSZ]; /* work buffer */ - - if (p_pszEdit == NULL) /* q. null request? */ - return AMSG; /* a. yes .. return display message */ - - strncpy(pszLine, p_pszEdit, MAXLINE-1); /* copy the line local */ - - ExpandTabs(pszLine, pszWork, gaiPlainTabs); /* expand the tabs */ - strncpy(gszOutput, pszWork, MAXLINE-1); /* copy the line back */ - - for (iI = strlen(gszOutput); iI--;) /* look at each character */ - { - if (*(gszOutput + iI) <= ' ') /* q. space or less? */ - *(gszOutput + iI) = 0; /* a. yes .. remove it */ - else /* otherwise */ - break; /* .. done. Leave loop. */ - } - - - return gszOutput; /* ... return buffer */ -} diff --git a/Ibm1130/ibm1130_fmt.h b/Ibm1130/ibm1130_fmt.h deleted file mode 100644 index 7232560b..00000000 --- a/Ibm1130/ibm1130_fmt.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * (C) Copyright 2003, Bob Flander. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to bob@jftr.com - */ - -/* ibm1130_asm.h: definition of routines in ibm1130_asm.c - */ - -char* EditToAsm(char*); /* convert edit format to 1130 assembler format */ -char* EditToFortran(char*); /* convert edit format to Fortran format */ -char* EditToWhitespace(char*); /* clean white space, tabstops every 8 positions */ diff --git a/Ibm1130/ibm1130_gdu.c b/Ibm1130/ibm1130_gdu.c deleted file mode 100644 index 86d32c45..00000000 --- a/Ibm1130/ibm1130_gdu.c +++ /dev/null @@ -1,1128 +0,0 @@ -#include "ibm1130_defs.h" - -/* ibm1130_gdu.c: IBM 1130 2250 Graphical Display Unit - - (Under construction) - stuff to fix: - "store revert" might be backwards? - alpha keyboard is not implemented - pushbuttons are not implemented - there is something about interrupts being deferred during a subroutine transition? - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#define BLIT_MODE /* define for better performance, undefine when debugging generate_image() */ -/* #define DEBUG_LIGHTPEN */ /* define to debug light-pen sensing */ - -#define DEFAULT_GDU_RATE 20 /* default frame rate */ -#define DEFAULT_PEN_THRESHOLD 3 /* default looseness of light-pen hit */ -#define INDWIDTH 32 /* width of an indicator (there are two columns of these) */ -#define INITSIZE 512 /* initial window size */ - -#define GDU_DSW_ORDER_CONTROLLED_INTERRUPT 0x8000 -#define GDU_DSW_KEYBOARD_INTERUPT 0x4000 -#define GDU_DSW_DETECT_INTERRUPT 0x2000 -#define GDU_DSW_CYCLE_STEAL_CHECK 0x1000 -#define GDU_DSW_DETECT_STATUS 0x0800 -#define GDU_DSW_LIGHT_PEN_SWITCH 0x0100 -#define GDU_DSW_BUSY 0x0080 -#define GDU_DSW_CHARACTER_MODE 0x0040 -#define GDU_DSW_POINT_MODE 0x0020 -#define GDU_DSW_ADDR_DISP 0x0003 - -#define GDU_FKEY_DATA_AVAILABLE 0x8000 -#define GDU_FKEY_KEY_CODE 0x1F00 -#define GDU_FKEY_OVERLAY_CODE 0x00FF - -#define GDU_AKEY_DATA_AVAILABLE 0x8000 -#define GDU_AKEY_END 0x1000 -#define GDU_AKEY_CANCEL 0x0800 -#define GDU_AKEY_ADVANCE 0x0400 -#define GDU_AKEY_BACKSPACE 0x0200 -#define GDU_AKEY_JUMP 0x0100 -#define GDU_AKEY_KEY_CODE 0x00FF - -/* -------------------------------------------------------------------------------------- */ - -#define UNIT_V_DISPLAYED (UNIT_V_UF + 0) -#define UNIT_V_DETECTS_ENABLED (UNIT_V_UF + 1) -#define UNIT_V_INTERRUPTS_DEFERRED (UNIT_V_UF + 2) -#define UNIT_V_LARGE_CHARS (UNIT_V_UF + 3) - -#define UNIT_DISPLAYED (1u << UNIT_V_DISPLAYED) /* display windows is up */ -#define UNIT_DETECTS_ENABLED (1u << UNIT_V_DETECTS_ENABLED) /* light pen detects are enabled */ -#define UNIT_INTERRUPTS_DEFERRED (1u << UNIT_V_INTERRUPTS_DEFERRED) /* light pen interrupts are deferred */ -#define UNIT_LARGE_CHARS (1u << UNIT_V_LARGE_CHARS) /* large character mode */ - -static t_stat gdu_reset (DEVICE *dptr); - -static int16 gdu_dsw = 1; /* device status word */ -static int16 gdu_ar = 0; /* address register */ -static int16 gdu_x = 0; /* X deflection */ -static int16 gdu_y = 0; /* Y deflection */ -static int16 gdu_fkey = 0; /* function keyboard register */ -static int16 gdu_akey = 0; /* alphanumeric keyboard register */ -static int16 gdu_revert = 0; /* revert address register */ -static int32 gdu_indicators = 0; /* programmed indicator lamps */ -static int32 gdu_threshold = DEFAULT_PEN_THRESHOLD; /* mouse must be within 3/1024 of line to be a hit */ -static int32 gdu_rate = DEFAULT_GDU_RATE; /* refresh rate. 0 = default */ - -UNIT gdu_unit = { UDATA (NULL, 0, 0) }; - -REG gdu_reg[] = { - { HRDATA (GDUDSW, gdu_dsw, 16) }, /* device status word */ - { HRDATA (GDUAR, gdu_ar, 16) }, /* address register */ - { HRDATA (GDUXREG, gdu_x, 16) }, /* X deflection register */ - { HRDATA (GDUYREG, gdu_y, 16) }, /* Y deflection register */ - { HRDATA (GDUFKEY, gdu_fkey, 16) }, /* function keyboard register */ - { HRDATA (GDUAKEY, gdu_akey, 16) }, /* alphanumeric keyboard register */ - { HRDATA (GDUREVERT,gdu_revert, 16) }, /* revert address register */ - { HRDATA (GDUAKEY, gdu_indicators, 32) }, /* programmed indicators */ - { DRDATA (GDUTHRESH,gdu_threshold, 32) }, /* mouse closeness threshhold */ - { DRDATA (GDURATE, gdu_rate, 32) }, /* refresh rate in frames/sec */ - { NULL } }; - -DEVICE gdu_dev = { - "GDU", &gdu_unit, gdu_reg, NULL, - 1, 16, 16, 1, 16, 16, - NULL, NULL, gdu_reset, - NULL, NULL, NULL}; - -/* -------------------------------------------------------------------------------------- */ - -#ifndef GUI_SUPPORT - -static t_stat gdu_reset (DEVICE *dptr) -{ - return SCPE_OK; -} - -void xio_2250_display (int32 addr, int32 func, int32 modify) -{ - /* ignore commands if device is nonexistent */ -} - -t_bool gdu_active (void) -{ - return 0; -} - -/* -------------------------------------------------------------------------------------- */ -#else /* GUI_SUPPORT defined */ - -/******* PLATFORM INDEPENDENT CODE ********************************************************/ - -static int32 gdu_instaddr; // address of first word of instruction -static int xmouse, ymouse, lpen_dist, lpen_dist2; // current mouse pointer, scaled closeness threshhold, same squared -static double sfactor; // current scaling factor -static t_bool last_abs = TRUE; // last positioning instruction was absolute -static t_bool mouse_present = FALSE; // mouse is/is not in the window -static void clear_interrupts (void); -static void set_indicators (int32 new_inds); -static void start_regeneration (void); -static void halt_regeneration (void); -static void draw_characters (void); -static void notify_window_closed (void); - -// routines that must be implemented per-platform - -static void DrawLine(int x0, int y0, int x1, int y1); -static void DrawPoint(int x, int y); -static void CheckGDUKeyboard(void); -static t_bool CreateGDUWindow(void); -static void StartGDUUpdates(void); -static void StopGDUUpdates(void); -static void GetMouseCoordinates(void); -static void UpdateGDUIndicators(void); -static void ShowPenHit (int x, int y); -static void EraseGDUScreen (void); - -/* -------------------------------------------------------------------------------------- */ - -void xio_2250_display (int32 addr, int32 func, int32 modify) -{ - switch (func) { - case XIO_SENSE_DEV: - ACC = (gdu_dsw & GDU_DSW_BUSY) ? GDU_DSW_BUSY : gdu_dsw; - if (modify & 1) - clear_interrupts(); - break; - - case XIO_READ: /* store status data into word pointed to by IOCC packet */ - if (gdu_dsw & GDU_DSW_BUSY) /* not permitted while device is busy */ - break; - - WriteW(addr, gdu_ar); /* save status information */ - WriteW(addr+1, gdu_dsw); - WriteW(addr+2, gdu_x & 0x7FF); - WriteW(addr+3, gdu_y & 0x7FF); - WriteW(addr+4, gdu_fkey); - WriteW(addr+5, gdu_akey); - gdu_ar = (int16) (addr+6); /* this alters the channel address register? */ - - clear_interrupts(); /* read status clears the interrupts */ - break; - - case XIO_WRITE: - if (gdu_dsw & GDU_DSW_BUSY) /* treated as no-op if display is busy */ - break; - - if (modify & 0x80) { /* bit 8 on means set indicators, 0 means start regeneration */ - set_indicators((ReadW(addr) << 16) | ReadW(addr+1)); - } - else { - gdu_ar = (int16) addr; - gdu_fkey = 0; - gdu_akey = 0; - clear_interrupts(); - start_regeneration(); - } - break; - - case XIO_CONTROL: - if (modify & 0x80) { /* bit 8 on means reset, off is no-op */ - gdu_reset(&gdu_dev); - set_indicators((addr << 16) | addr); - } - break; - - default: /* all other commands are no-ops */ - break; - } -} - -static t_stat gdu_reset (DEVICE *dptr) -{ - halt_regeneration(); - clear_interrupts(); - set_indicators(0); - gdu_x = gdu_y = 512; - CLRBIT(gdu_unit.flags, UNIT_INTERRUPTS_DEFERRED | UNIT_DETECTS_ENABLED | UNIT_LARGE_CHARS); - gdu_dsw = 1; - return SCPE_OK; -} - -static void clear_interrupts (void) -{ - CLRBIT(gdu_dsw, GDU_DSW_ORDER_CONTROLLED_INTERRUPT | GDU_DSW_KEYBOARD_INTERUPT | GDU_DSW_DETECT_INTERRUPT); - CLRBIT(ILSW[3], ILSW_3_2250_DISPLAY); - calc_ints(); -} - -static void gdu_interrupt (int32 dswbit) -{ - SETBIT(gdu_dsw, dswbit); - SETBIT(ILSW[3], ILSW_3_2250_DISPLAY); - calc_ints(); - halt_regeneration(); -} - -static void set_indicators (int32 new_inds) -{ - gdu_indicators = new_inds; - if (gdu_unit.flags & UNIT_DISPLAYED) - UpdateGDUIndicators(); -} - -static void start_regeneration (void) -{ - SETBIT(gdu_dsw, GDU_DSW_BUSY); - - if ((gdu_unit.flags & UNIT_DISPLAYED) == 0) { - if (! CreateGDUWindow()) - return; - - SETBIT(gdu_unit.flags, UNIT_DISPLAYED); - } - - StartGDUUpdates(); -} - -static void halt_regeneration (void) -{ - // halt_regeneration gets called at end of every refresh interation, so it should NOT black out the - // screen -- this is why it was flickering so badly. The lower level code (called on a timer) - // should check to see if GDU_DSW_BUSY is clear, and if it it still zero after several msec, - // only then should it black out the screen and call StopGDUUpdates. - if (gdu_dsw & GDU_DSW_BUSY) { -// StopGDUUpdates(); // let lower level code discover this during next refresh - CLRBIT(gdu_dsw, GDU_DSW_BUSY); - } -// EraseGDUScreen(); // let cessation of regeneration erase it (eventually) -} - -static void notify_window_closed (void) -{ - if (gdu_dsw & GDU_DSW_BUSY) { - StopGDUUpdates(); - CLRBIT(gdu_dsw, GDU_DSW_BUSY); - } - - CLRBIT(gdu_unit.flags, UNIT_DISPLAYED); - - gdu_reset(&gdu_dev); -} - -static int32 read_gduword (void) -{ - int32 w; - - w = M[gdu_ar++ & mem_mask]; - gdu_dsw = (int16) ((gdu_dsw & ~GDU_DSW_ADDR_DISP) | ((gdu_ar - gdu_instaddr) & GDU_DSW_ADDR_DISP)); - - return w; -} - -#define DIST2(x0,y0,x1,y1) (((x1)-(x0))*((x1)-(x0))+((y1)-(y0))*((y1)-(y0))) - -static void draw (int32 newx, int32 newy, t_bool beam) -{ - int xmin, xmax, ymin, ymax, xd, yd; - double s; - int hit = FALSE; - - if (beam) { - if (gdu_dsw & GDU_DSW_POINT_MODE) { - DrawPoint(newx, newy); - -#ifdef DEBUG_LIGHTPEN - if (DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; -#else - if (gdu_unit.flags & UNIT_DETECTS_ENABLED && mouse_present) - if (DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; -#endif - } - else { - DrawLine(gdu_x, gdu_y, newx, newy); - - // calculate proximity of light pen to the line -#ifndef DEBUG_LIGHTPEN - if (gdu_unit.flags & UNIT_DETECTS_ENABLED && mouse_present) { -#endif - if (gdu_x <= newx) - xmin = gdu_x, xmax = newx; - else - xmin = newx, xmax = gdu_x; - - if (gdu_y <= newy) - ymin = gdu_y, ymax = newy; - else - ymin = newy, ymax = gdu_y; - - if (newx == gdu_x) { - // line is vertical. Nearest point is an endpoint if the mouse is above or - // below the line segment, otherwise the segment point at the same y as the mouse - xd = gdu_x; - yd = (ymouse <= ymin) ? ymin : (ymouse >= ymax) ? ymax : ymouse; - - if (DIST2(xd, yd, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; - } - else if (newy == gdu_y) { - // line is horizontal. Nearest point is an endpoint if the mouse is to the left or - // the right of the line segment, otherwise the segment point at the same x as the mouse - xd = (xmouse <= xmin) ? xmin : (xmouse >= xmax) ? xmax : xmouse; - yd = gdu_y; - - if (DIST2(xd, yd, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; - } - else { - // line is diagonal. See if the mouse is inside the box lpen_dist wider than the line segment's bounding rectangle - if (xmouse >= (xmin-lpen_dist) && xmouse <= (xmax+lpen_dist) && ymouse >= (ymin-lpen_dist) || ymouse <= (ymax+lpen_dist)) { - // compute the point at the intersection of the line through the line segment and the normal - // to that line through the mouse. This is the point on the line through the line segment - // nearest the mouse - - s = (double)(newy - gdu_y) / (double)(newx - gdu_x); // slope of line segment - xd = (int) ((ymouse + xmouse/s - gdu_y + s*gdu_x) / (s + 1./s) + 0.5); - - // if intersection is beyond either end of the line segment, the nearest point to the - // mouse is nearest segment end, otherwise it's the computed intersection point - if (xd < xmin || xd > xmax) { -#ifdef DEBUG_LIGHTPEN - // if it's a hit, set xd and yd so we can display the hit - if (DIST2(gdu_x, gdu_y, xmouse, ymouse) <= lpen_dist2) { - hit = TRUE; - xd = gdu_x; - yd = gdu_y; - } - else if (DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) { - hit = TRUE; - xd = newx; - yd = newy; - } -#else - if (DIST2(gdu_x, gdu_y, xmouse, ymouse) <= lpen_dist2 || DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; -#endif - } - else { - yd = (int) (gdu_y + s*(xd - gdu_x) + 0.5); - if (DIST2(xd, yd, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; - } - } - } -#ifndef DEBUG_LIGHTPEN - } -#endif - } - } - - if (hit) { -#ifdef DEBUG_LIGHTPEN - ShowPenHit(xd, yd); - if (gdu_unit.flags & UNIT_DETECTS_ENABLED && mouse_present) - SETBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); -#else - SETBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); -#endif - } - - gdu_x = (int16) newx; - gdu_y = (int16) newy; -} - -static void generate_image (void) -{ - int32 instr, new_addr, newx, newy; - t_bool run = TRUE, accept; - - if (! (gdu_dsw & GDU_DSW_BUSY)) - return; - - GetMouseCoordinates(); - - lpen_dist = (int) (gdu_threshold/sfactor + 0.5); // mouse-to-line threshhold at current scaling factor - lpen_dist2 = lpen_dist * lpen_dist; - - while (run) { - if ((gdu_dsw & GDU_DSW_DETECT_STATUS) && ! (gdu_unit.flags & UNIT_INTERRUPTS_DEFERRED)) { - CLRBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); // clear when interrupt is activated - gdu_interrupt(GDU_DSW_DETECT_INTERRUPT); - run = FALSE; - break; - } - - gdu_instaddr = gdu_ar; // remember address of GDU instruction - instr = read_gduword(); // fetch instruction (and we really are cycle stealing here!) - - switch ((instr >> 12) & 0xF) { // decode instruction - case 0: // short branch - case 1: - gdu_revert = gdu_ar; // save revert address & get new address - gdu_ar = (int16) (read_gduword() & 0x1FFF); - if (gdu_dsw & GDU_DSW_CHARACTER_MODE) { - draw_characters(); // in character mode this means we are at character data - gdu_ar = gdu_revert; - } - break; - - case 2: // long branch/interrupt - new_addr = read_gduword(); // get next word - accept = ((instr & 1) ? (gdu_dsw & GDU_DSW_LIGHT_PEN_SWITCH) : TRUE) && ((instr & 2) ? (gdu_dsw & GDU_DSW_DETECT_STATUS) : TRUE); - - if (instr & 2) // clear after testing - CLRBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); - - if (instr & 0x0400) // NOP - accept = FALSE; - - if (accept) { - if (instr & 0x0800) { // branch - gdu_revert = gdu_ar; - - if (instr & 0x0080) // indirect - new_addr = M[new_addr & mem_mask]; - - gdu_ar = (int16) new_addr; - - if (gdu_dsw & GDU_DSW_CHARACTER_MODE) { - draw_characters(); - gdu_ar = gdu_revert; - } - } - else { // interrupt - gdu_interrupt(GDU_DSW_ORDER_CONTROLLED_INTERRUPT); - run = FALSE; - } - } - break; - - case 3: // control instructions - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - - switch ((instr >> 8) & 0xF) { - case 1: // set pen mode - if ((instr & 0xC) == 8) - SETBIT(gdu_unit.flags, UNIT_DETECTS_ENABLED); - else if ((instr & 0xC) == 4) - CLRBIT(gdu_unit.flags, UNIT_DETECTS_ENABLED); - - if ((instr & 0x3) == 2) - SETBIT(gdu_unit.flags, UNIT_INTERRUPTS_DEFERRED); - else if ((instr & 0x3) == 1) - CLRBIT(gdu_unit.flags, UNIT_INTERRUPTS_DEFERRED); - break; - - case 2: // set graphic mode - if (instr & 1) - SETBIT(gdu_dsw, GDU_DSW_POINT_MODE); - else - CLRBIT(gdu_dsw, GDU_DSW_POINT_MODE); - break; - - case 3: // set character mode - SETBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - if (instr & 1) - SETBIT(gdu_unit.flags, UNIT_LARGE_CHARS); - else - CLRBIT(gdu_unit.flags, UNIT_LARGE_CHARS); - break; - - case 4: // start timer - run = FALSE; // (which, for us, means stop processing until next timer message) - CheckGDUKeyboard(); - break; - - case 5: // store revert - M[gdu_ar & mem_mask] = gdu_revert; - read_gduword(); // skip to next address - break; - - case 6: // revert - gdu_ar = gdu_revert; - break; - - default: // all others treated as no-ops - break; - } - break; - - case 4: // long absolute - case 5: - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - newx = instr & 0x3FF; - newy = read_gduword() & 0x3FF; - draw(newx, newy, instr & 0x1000); - last_abs = TRUE; - break; - - case 6: // short absolute - case 7: - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - newx = gdu_x; - newy = gdu_y; - if (instr & 0x0800) - newy = instr & 0x3FF; - else - newx = instr & 0x3FF; - draw(newx, newy, instr & 0x1000); - last_abs = TRUE; - break; - - default: // high bit set - it's a relative instruction - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - newx = (instr >> 8) & 0x3F; - newy = instr & 0x3F; - - if (instr & 0x4000) // sign extend x - values are in 2's complement - newx |= -1 & ~0x3F; // although documentation doesn't make that clear - - if (instr & 0x0040) // sign extend y - newy |= -1 & ~0x3F; - - newx = gdu_x + newx; - newy = gdu_y + newy; - draw(newx, newy, instr & 0x0080); - last_abs = FALSE; - break; - } - } -} - -static struct charinfo { // character mode scaling info: - int dx, dy; // character and line spacing - double sx, sy; // scaling factors: character units to screen units - int xoff, yoff; // x and y offset to lower left corner of character - int suby; // subscript/superscript offset -} cx[2] = { - {14, 20, 1.7, 2.0, -6, -7, 6}, // regular - {21, 30, 2.5, 3.0, -9, -11, 9} // large -}; - -static void draw_characters (void) -{ - int32 w, x0, y0, x1, y1, yoff = 0, ninstr = 0; - t_bool dospace, didstroke = FALSE; - struct charinfo *ci; - - ci = &cx[(gdu_unit.flags & UNIT_LARGE_CHARS) ? 1 : 0]; - x0 = gdu_x + ci->xoff; // starting position - y0 = gdu_y + ci->yoff; - - do { - if (++ninstr > 29) { // too many control words - gdu_interrupt(GDU_DSW_CYCLE_STEAL_CHECK); - return; - } - - dospace = TRUE; - w = M[gdu_ar++ & mem_mask]; // get next stroke or control word - - x1 = (w >> 12) & 7; - y1 = (w >> 8) & 7; - - if (x1 == 7) { // this is a character control word - dospace = FALSE; // inhibit character spacing - - switch (y1) { - case 1: // subscript - if (yoff == 0) // (ignored if superscript is in effect) - yoff = -ci->suby; - break; - -// case 2: // no-op or null (nothing to do) -// default: // all unknowns are no-ops -// break; - - case 4: // superscript - yoff = ci->suby; - break; - - case 7: // new line - gdu_x = 0; - gdu_y -= (int16) ci->dy; - if (gdu_y < 0 && last_abs) - gdu_y = (int16) (1024 - ci->dy); // this is a guess - break; - } - } - else { // this is stroke data -- extract two strokes - x1 = gdu_x + (int) (x1*ci->sx + 0.5); - y1 = gdu_y + (int) ((y1+yoff)*ci->sy + 0.5); - - if (w & 0x0800) { - didstroke = TRUE; - DrawLine(x0, y0, x1, y1); - } - - x0 = (w >> 4) & 7; - y0 = w & 7; - - x0 = gdu_x + (int) (x0*ci->sx + 0.5); - y0 = gdu_y + (int) ((y0+yoff)*ci->sy + 0.5); - - if (w & 0x0008) { - didstroke = TRUE; - DrawLine(x1, y1, x0, y0); - } - } - - if (dospace) { - gdu_x += ci->dx; - if (gdu_x > 1023 && last_abs) { // line wrap - gdu_x = 0; - gdu_y -= (int16) ci->dy; - } - } - } while ((w & 0x0080) == 0); // repeat until we hit revert bit - - if (didstroke && mouse_present && (gdu_unit.flags & UNIT_DETECTS_ENABLED)) { - if (xmouse >= (gdu_x - ci->xoff/2) && xmouse <= (gdu_x + ci->xoff/2) && - ymouse >= (gdu_y - ci->yoff/2) && ymouse <= (gdu_y + ci->yoff/2)) - SETBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); - } -} - -/******* PLATFORM SPECIFIC CODE ***********************************************************/ - -#ifdef _WIN32 - -#include -#include - -#define APPCLASS "IBM2250GDU" // window class name - -#define RGB_GREEN RGB(0,255,0) // handy colors -#define RGB_RED RGB(255,0,0) - -static HINSTANCE hInstance; -static HWND hwGDU = NULL; -static HDC hdcGDU = NULL; -static HBITMAP hBmp = NULL; -static int curwid = 0; -static int curht = 0; -static BOOL wcInited = FALSE; -static DWORD GDUPumpID = 0; -static HANDLE hGDUPump = INVALID_HANDLE_VALUE; -static HPEN hGreenPen = NULL; -static HBRUSH hRedBrush = NULL; -#ifdef DEBUG_LIGHTPEN -static HPEN hRedPen = NULL; -#endif -static HBRUSH hGrayBrush, hDarkBrush; -static HPEN hBlackPen; -static int halted = 0; // number of time intervals that GDU has been halted w/o a regeneration -static LRESULT APIENTRY GDUWndProc (HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam); -static DWORD WINAPI GDUPump (LPVOID arg); - -static void destroy_GDU_window (void) -{ - if (hwGDU != NULL) - SendMessage(hwGDU, WM_CLOSE, 0, 0); // cross thread call is OK - - if (hGDUPump != INVALID_HANDLE_VALUE) { // this is not the most graceful way to do it - TerminateThread(hGDUPump, 0); - hGDUPump = INVALID_HANDLE_VALUE; - GDUPumpID = 0; - hwGDU = NULL; - } - - if (hdcGDU != NULL) { - DeleteDC(hdcGDU); - hdcGDU = NULL; - } - - if (hBmp != NULL) { - DeleteObject(hBmp); - hBmp = NULL; - } - - if (hGreenPen != NULL) { - DeleteObject(hGreenPen); - hGreenPen = NULL; - } - - if (hRedBrush != NULL) { - DeleteObject(hRedBrush); - hRedBrush = NULL; - } - -#ifdef DEBUG_LIGHTPEN - if (hRedPen != NULL) { - DeleteObject(hRedPen); - hRedPen = NULL; - } -#endif -} - -static t_bool CreateGDUWindow (void) -{ - static BOOL did_atexit = FALSE; - - hInstance = GetModuleHandle(NULL); - - if (hGDUPump == INVALID_HANDLE_VALUE) - hGDUPump = CreateThread(NULL, 0, GDUPump, 0, 0, &GDUPumpID); - - if (! did_atexit) { - atexit(destroy_GDU_window); - did_atexit = TRUE; - } - - return TRUE; -} - -// windows message handlers ---------------------------------------------------- - -// close the window - -static void gdu_WM_CLOSE (HWND hWnd) -{ - DestroyWindow(hWnd); -} - -// the window is being destroyed - -static void gdu_WM_DESTROY (HWND hWnd) -{ - notify_window_closed(); - hwGDU = NULL; -} - -// adjust the min and max resizing boundaries - -static void gdu_WM_GETMINMAXINFO (HWND hWnd, LPMINMAXINFO mm) -{ - mm->ptMinTrackSize.x = 100 + 2*INDWIDTH; - mm->ptMinTrackSize.y = 100; -} - -static void PaintImage (HDC hDC, BOOL draw_indicators) -{ - HPEN hOldPen; - RECT r; - int wid, ht, x, y, dy, i, j, ycirc; - unsigned long bit; - - GetClientRect(hwGDU, &r); - wid = r.right+1 - 2*INDWIDTH; - ht = r.bottom+1; - sfactor = (double) MIN(wid,ht) / 1024.; - - if (gdu_dsw & GDU_DSW_BUSY) { -#ifdef BLIT_MODE - // if compiled for BLIT_MODE, draw the image into a memory display context, then - // blit the new image over window. This eliminates the flicker that a normal erase-and- - // repaint would cause. - - if (wid != curwid || ht != curht) { // dimensions have changed, discard old memory display context - if (hdcGDU != NULL) { - DeleteDC(hdcGDU); - hdcGDU = NULL; - } - curwid = wid; - curht = ht; - } - - if (hdcGDU == NULL) { // allocate memory display context & select a bitmap into it - hdcGDU = CreateCompatibleDC(hDC); - if (hBmp != NULL) - DeleteObject(hBmp); - hBmp = CreateCompatibleBitmap(hDC, wid, ht); - SelectObject(hdcGDU, hBmp); - } - - PatBlt(hdcGDU, 0, 0, wid, ht, BLACKNESS); // start with a black screen - - hOldPen = SelectObject(hdcGDU, hGreenPen); - - SetMapMode(hdcGDU, MM_ANISOTROPIC); - SetWindowExtEx(hdcGDU, 1024, -1024, NULL); - SetViewportExtEx(hdcGDU, wid, ht, NULL); - SetWindowOrgEx(hdcGDU, 0, 1023, NULL); - - generate_image(); // run the display program to paint the image into the memory context - - SetWindowExtEx(hdcGDU, wid, ht, NULL); // undo the scaling so the blit isn't distorted - SetViewportExtEx(hdcGDU, wid, ht, NULL); - SetWindowOrgEx(hdcGDU, 0, 0, NULL); - BitBlt(hDC, 0, 0, wid, ht, hdcGDU, 0, 0, SRCCOPY); // blit the new image over the old - - SelectObject(hdcGDU, hOldPen); -#else - // for testing purposes -- draw the image directly onto the screen. - // Compile this way when you want to single-step through the image drawing routine, - // so you can see the draws occur. - hdcGDU = hDC; - hOldPen = SelectObject(hdcGDU, hGreenPen); - - SetMapMode(hdcGDU, MM_ANISOTROPIC); - SetWindowExtEx(hdcGDU, 1024, -1024, NULL); - SetViewportExtEx(hdcGDU, wid, ht, NULL); - SetWindowOrgEx(hdcGDU, 0, 1023, NULL); - - generate_image(); - - SelectObject(hdcGDU, hOldPen); - hdcGDU = NULL; -#endif - } - - if (draw_indicators) { - x = r.right-2*INDWIDTH+1; - dy = ht / 16; - ycirc = MIN(dy-2, 8); - - r.left = x; - FillRect(hDC, &r, hGrayBrush); - SelectObject(hDC, hBlackPen); - - bit = 0x80000000L; - for (i = 0; i < 2; i++) { - MoveToEx(hDC, x, 0, NULL); - LineTo(hDC, x, r.bottom); - y = 0; - for (j = 0; j < 16; j++) { - MoveToEx(hDC, x, y, NULL); - LineTo(hDC, x+INDWIDTH, y); - - SelectObject(hDC, (gdu_indicators & bit) ? hRedBrush : hDarkBrush); - Pie(hDC, x+1, y+1, x+1+ycirc, y+1+ycirc, x+1, y+1, x+1, y+1); - - y += dy; - bit >>= 1; - } - x += INDWIDTH; - } - } -} - -// repaint the window - -static void gdu_WM_PAINT (HWND hWnd) -{ - PAINTSTRUCT ps; - HDC hDC; - // code for display - hDC = BeginPaint(hWnd, &ps); - PaintImage(hDC, TRUE); - EndPaint(hWnd, &ps); -} - -// the window has been resized - -static void gdu_WM_SIZE (HWND hWnd, UINT state, int cx, int cy) -{ - InvalidateRect(hWnd, NULL, TRUE); -} - -// tweak the sizing rectangle during a resize to guarantee a square window - -static void gdu_WM_SIZING (HWND hWnd, WPARAM fwSide, LPRECT r) -{ - switch (fwSide) { - case WMSZ_LEFT: - case WMSZ_RIGHT: - case WMSZ_BOTTOMLEFT: - case WMSZ_BOTTOMRIGHT: - r->bottom = r->right - r->left - 2*INDWIDTH + r->top; - break; - - case WMSZ_TOP: - case WMSZ_BOTTOM: - case WMSZ_TOPRIGHT: - r->right = r->bottom - r->top + r->left + 2*INDWIDTH; - break; - - case WMSZ_TOPLEFT: - r->left = r->top - r->bottom + r->right - 2*INDWIDTH; - break; - } -} - -// the refresh timer has gone off - -static void gdu_WM_TIMER (HWND hWnd, UINT id) -{ - HDC hDC; - - if (running) { // if CPU is running, update picture - if ((gdu_dsw & GDU_DSW_BUSY) == 0) { // regeneration is not to occur - if (++halted >= 4) { // stop the timer if four timer intervals go by with the display halted - EraseGDUScreen(); // screen goes black due to cessation of refreshing - StopGDUUpdates(); // might as well kill the timer - return; - } - } - else - halted = 0; - -#ifdef BLIT_MODE - hDC = GetDC(hWnd); // blit the new image right over the old - PaintImage(hDC, FALSE); - ReleaseDC(hWnd, hDC); -#else - InvalidateRect(hWnd, NULL, TRUE); // repaint -#endif - } -} - -// window procedure ------------------------------------------------------------ - -#define HANDLE(msg) case msg: return HANDLE_##msg(hWnd, wParam, lParam, gdu_##msg); - -#ifndef HANDLE_WM_SIZING -// void Cls_OnSizing(HWND hwnd, UINT fwSide, LPRECT r) -# define HANDLE_WM_SIZING(hwnd, wParam, lParam, fn) \ - ((fn)((hwnd), (UINT)(wParam), (LPRECT)(lParam)), 0L) -#endif - -static LRESULT APIENTRY GDUWndProc (HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) -{ - switch (iMessage) { - HANDLE(WM_CLOSE); - HANDLE(WM_GETMINMAXINFO); - HANDLE(WM_DESTROY); - HANDLE(WM_PAINT); - HANDLE(WM_SIZE); - HANDLE(WM_SIZING); - HANDLE(WM_TIMER); - default: // any message we don't process - return DefWindowProc(hWnd, iMessage, wParam, lParam); - } - return 0L; -} - -// graphic calls ---------------------------------------------------------------- - -static void DrawLine (int x0, int y0, int x1, int y1) -{ - MoveToEx(hdcGDU, x0, y0, NULL); - LineTo(hdcGDU, x1, y1); -} - -static void DrawPoint (int x, int y) -{ - SetPixel(hdcGDU, x, y, RGB_GREEN); -} - -static void UpdateGDUIndicators(void) -{ - if (hwGDU != NULL) - InvalidateRect(hwGDU, NULL, FALSE); // no need to erase the background -- the draw routine fully paints the indicator -} - -static void CheckGDUKeyboard (void) -{ -} - -static UINT idTimer = 0; - -static void StartGDUUpdates (void) -{ - int msec; - - if (idTimer == 0) { - msec = (gdu_rate == 0) ? (1000 / DEFAULT_GDU_RATE) : 1000/gdu_rate; - idTimer = SetTimer(hwGDU, 1, msec, NULL); - } - halted = 0; -} - -static void StopGDUUpdates (void) -{ - if (idTimer != 0) { - KillTimer(hwGDU, 1); - idTimer = 0; - halted = 10000; - } -} - -static void GetMouseCoordinates() -{ - POINT p; - RECT r; - - GetCursorPos(&p); - GetClientRect(hwGDU, &r); - if (! ScreenToClient(hwGDU, &p)) { - xmouse = ymouse = -2000; - mouse_present = FALSE; - return; - } - - if (p.x < r.left || p.x >= r.right || p.y < r.top || p.y > r.bottom) { - mouse_present = FALSE; - return; - } - - // convert mouse coordinates to scaled coordinates - - xmouse = (int) (1024./(r.right+1.-2*INDWIDTH)*p.x + 0.5); - ymouse = 1023 - (int) (1024./(r.bottom+1.)*p.y + 0.5); - mouse_present = TRUE; -} - -t_bool gdu_active (void) -{ - return gdu_dsw & GDU_DSW_BUSY; -} - -static void EraseGDUScreen (void) -{ - if (hwGDU != NULL) /* redraw screen. it will be blank if GDU is not running */ - InvalidateRect(hwGDU, NULL, TRUE); -} - -/* GDUPump - thread responsible for creating and displaying the graphics window */ - -static DWORD WINAPI GDUPump (LPVOID arg) -{ - MSG msg; - WNDCLASS wc; - - if (! wcInited) { /* register Window class */ - memset(&wc, 0, sizeof(wc)); - wc.style = CS_NOCLOSE; - wc.lpfnWndProc = GDUWndProc; - wc.hInstance = hInstance; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = GetStockObject(BLACK_BRUSH); - wc.lpszClassName = APPCLASS; - - if (! RegisterClass(&wc)) { - GDUPumpID = 0; - return 0; - } - - wcInited = TRUE; - } - - if (hGreenPen == NULL) - hGreenPen = CreatePen(PS_SOLID, 1, RGB_GREEN); - -#ifdef DEBUG_LIGHTPEN - if (hRedPen == NULL) - hRedPen = CreatePen(PS_SOLID, 1, RGB_RED); -#endif - - if (hRedBrush == NULL) - hRedBrush = CreateSolidBrush(RGB_RED); - - hGrayBrush = GetStockObject(GRAY_BRUSH); - hDarkBrush = GetStockObject(DKGRAY_BRUSH); - hBlackPen = GetStockObject(BLACK_PEN); - - if (hwGDU == NULL) { /* create window */ - hwGDU = CreateWindow(APPCLASS, - "2250 Display", - WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, - CW_USEDEFAULT, CW_USEDEFAULT, // initial x, y position - INITSIZE+2*INDWIDTH, INITSIZE, // initial width and height - NULL, // parent window handle - NULL, // use class menu - hInstance, // program instance handle - NULL); // create parameters - - if (hwGDU == NULL) { - GDUPumpID = 0; - return 0; - } - } - - ShowWindow(hwGDU, SW_SHOWNOACTIVATE); /* display it */ - UpdateWindow(hwGDU); - - while (GetMessage(&msg, hwGDU, 0, 0)) { /* message pump - this basically loops forevermore */ - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - if (hwGDU != NULL) { - DestroyWindow(hwGDU); /* but if a quit message got posted, clean up */ - hwGDU = NULL; - } - - GDUPumpID = 0; - return 0; -} - -#ifdef DEBUG_LIGHTPEN -static void ShowPenHit (int x, int y) -{ - HPEN hOldPen; - - hOldPen = SelectObject(hdcGDU, hRedPen); - DrawLine(x-10, y-10, x+10, y+10); - DrawLine(x-10, y+10, x+10, y-10); - SelectObject(hdcGDU, hOldPen); -} -#endif - -#endif // _WIN32 defined -#endif // GUI_SUPPORT defined diff --git a/Ibm1130/ibm1130_gui.c b/Ibm1130/ibm1130_gui.c deleted file mode 100644 index 765c2214..00000000 --- a/Ibm1130/ibm1130_gui.c +++ /dev/null @@ -1,1657 +0,0 @@ -/* ibm1130_gui.c: IBM 1130 CPU simulator Console Display - * - * Based on the SIMH package written by Robert M Supnik - * - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - * - * 30-Dec-05 BLK Fixed mask for IAR and SAR register display and added display - * of Arithmetic Factor, per Carl Claunch. - * - * 09-Apr-04 BLK Changed code to use stock windows cursor IDC_HAND if available - * - * 02-Dec-02 BLK Changed display, added printer and card reader icons - * Added drag and drop support for scripts and card decks - * Added support for physical card reader and printer (hides icons) - * - * 17-May-02 BLK Pulled out of ibm1130_cpu.c - */ - -/* ------------------------------------------------------------------------ - * Definitions - * ------------------------------------------------------------------------ */ - -#include -#include - -#include "ibm1130_defs.h" -#include "ibm1130res.h" - -#define UPDATE_BY_TIMER - -#ifdef UPDATE_BY_TIMER -# define UPDATE_INTERVAL 20 /* set to desired number of updates/second */ -#else -# define UPDATE_INTERVAL 5000 /* GUI: set to 100000/f where f = desired updates/second of 1130 time */ -#endif - -#define UNIT_V_CR_EMPTY (UNIT_V_UF + 5) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_cr.c */ -#define UNIT_CR_EMPTY (1u << UNIT_V_CR_EMPTY) -#define UNIT_V_PHYSICAL (UNIT_V_UF + 9) -#define UNIT_PHYSICAL (1u << UNIT_V_PHYSICAL) - -#define UNIT_V_PHYSICAL_PTR (UNIT_V_UF + 10) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_prt.c */ -#define UNIT_PHYSICAL_PTR (1u << UNIT_V_PHYSICAL_PTR) - -/* I think I had it wrong; Program Load actually does start the processor after - * reading in the card? - */ - -#define PROGRAM_LOAD_STARTS_CPU - -/* ------------------------------------------------------------------------ - * Function declarations - * ------------------------------------------------------------------------ */ - -t_stat console_reset (DEVICE *dptr); - -/* ------------------------------------------------------------------------ - * Console display - on Windows builds (only) this code displays the 1130 console - * and toggle switches. It really enhances the experience. - * - * Currently, when the IPS throttle is nonzero, I update the display after every - * UPDATE_INTERVAL instructions, plus or minus a random amount to avoid aliased - * sampling in loops. When UPDATE_INTERVAL is defined as zero, we update every - * instruction no matter what the throttle. This makes the simulator too slow - * but it's cool and helpful during development. - * ------------------------------------------------------------------------ */ - -#define UNIT_V_DISPLAY (UNIT_V_UF + 0) -#define UNIT_DISPLAY (1u << UNIT_V_DISPLAY) - -MTAB console_mod[] = { - { UNIT_DISPLAY, 0, "off", "OFF", NULL }, - { UNIT_DISPLAY, UNIT_DISPLAY, "on", "ON", NULL }, - { 0 } -}; - -UNIT console_unit = {UDATA (NULL, UNIT_DISABLE|UNIT_DISPLAY, 0) }; - -DEVICE console_dev = { - "GUI", &console_unit, NULL, console_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, console_reset, - NULL, NULL, NULL -}; - -/* reset for the "console" display device */ - -extern char *read_line (char *cptr, int size, FILE *stream); -extern FILE *sim_log; -extern DEVICE *find_unit (char *cptr, UNIT **uptr); - -extern UNIT cr_unit; /* pointers to 1442 and 1132 (1403) printers */ -extern UNIT prt_unit; - -#ifndef GUI_SUPPORT - void update_gui (int force) {} /* stubs for non-GUI builds */ - void forms_check (int set) {} - void print_check (int set) {} - void keyboard_select (int select) {} - void keyboard_selected (int select) {} - void disk_ready (int ready) {} - void disk_unlocked (int unlocked) {} - void gui_run (int running) {} - static void init_console_window (void) {} - static void destroy_console_window (void) {} - - t_stat console_reset (DEVICE *dptr) {return SCPE_OK;} - void stuff_cmd (char *cmd) {} - t_bool stuff_and_wait (char *cmd, int timeout, int delay) {return FALSE;} - char *read_cmdline (char *ptr, int size, FILE *stream) {return read_line(ptr, size, stream);} - void remark_cmd (char *remark) {printf("%s\n", remark); if (sim_log) fprintf(sim_log, "%s\n", remark);} -#else - -t_stat console_reset (DEVICE *dptr) -{ - if (! sim_gui) { - SETBIT(console_unit.flags, UNIT_DIS); /* disable the GUI */ - CLRBIT(console_unit.flags, UNIT_DISPLAY); /* turn the GUI off */ - } - - update_gui(FALSE); - return SCPE_OK; -} - -/* scp_panic - report fatal internal programming error */ - -void scp_panic (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -#ifdef _WIN32 - /* only _WIN32 is defined right now */ - -#include - -#define BUTTON_WIDTH 90 -#define BUTTON_HEIGHT 50 - -#define IDC_KEYBOARD_SELECT 0 -#define IDC_DISK_UNLOCK 1 -#define IDC_RUN 2 -#define IDC_PARITY_CHECK 3 -#define IDC_UNUSED 4 -#define IDC_FILE_READY 5 -#define IDC_FORMS_CHECK 6 -#define IDC_POWER_ON 7 -#define IDC_POWER 8 -#define IDC_PROGRAM_START 9 -#define IDC_PROGRAM_STOP 10 -#define IDC_LOAD_IAR 11 -#define IDC_KEYBOARD 12 -#define IDC_IMM_STOP 13 -#define IDC_RESET 14 -#define IDC_PROGRAM_LOAD 15 - -#define IDC_TEAR 16 /* standard button */ -#define IDC_1442 17 /* device images */ -#define IDC_1132 18 - -#define LAMPTIME 500 /* 500 msec delay on updating */ -#define FLASH_TIMER_ID 1 -#define UPDATE_TIMER_ID 2 - -#define RUNSWITCH_X 689 /* center of the run mode switch dial */ -#define RUNSWITCH_Y 107 -#define TOGGLES_X 122 /* left edge of series of toggle switches */ - -#define TXTBOX_X 200 /* text labels showing attached devices */ -#define TXTBOX_Y 300 -#define TXTBOX_WIDTH 195 -#define TXTBOX_HEIGHT 12 - -static BOOL class_defined = FALSE; -static HWND hConsoleWnd = NULL; -static HBITMAP hBitmap = NULL; -static HFONT hFont = NULL; -static HFONT hBtnFont = NULL; -static HFONT hTinyFont = NULL; -static HBRUSH hbLampOut = NULL; -static HBRUSH hbWhite = NULL; -static HBRUSH hbBlack = NULL; -static HBRUSH hbGray = NULL; -static HPEN hSwitchPen = NULL; -static HPEN hWhitePen = NULL; -static HPEN hBlackPen = NULL; -static HPEN hLtGreyPen = NULL; -static HPEN hGreyPen = NULL; -static HPEN hDkGreyPen = NULL; -static int hUpdateTimer = 0; -static int hFlashTimer = 0; - -static HCURSOR hcArrow = NULL; -static HCURSOR hcHand = NULL; -static HINSTANCE hInstance; -static HDC hCDC = NULL; -static char szConsoleClassName[] = "1130CONSOLE"; -static DWORD PumpID = 0; -static HANDLE hPump = INVALID_HANDLE_VALUE; -static int bmwid, bmht; -static HANDLE hbm1442_full, hbm1442_empty, hbm1442_eof, hbm1442_middle; -static HANDLE hbm1132_full, hbm1132_empty; - -static struct tag_btn { - int x, y, wx, wy; - char *txt; - BOOL pushable, state; - COLORREF clr; - HBRUSH hbrLit, hbrDark; - HWND hBtn; - BOOL subclassed; - -} btn[] = { - 0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "KEYBOARD\nSELECT", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE, - 0, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "DISK\nUNLOCK", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, TRUE, - 0, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "RUN", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE, - 0, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "PARITY\nCHECK", FALSE, FALSE, RGB(255,0,0), NULL, NULL, NULL, TRUE, - - 1, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE, - 1, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "FILE\nREADY", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE, - 1, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "FORMS\nCHECK", FALSE, FALSE, RGB(255,255,0), NULL, NULL, NULL, TRUE, - 1, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "POWER\nON", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, TRUE, - - 2, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "POWER", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE, - 2, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "PROGRAM\nSTART", TRUE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE, - 2, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "PROGRAM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, TRUE, - 2, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "LOAD\nIAR", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, TRUE, - - 3, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "KEYBOARD", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE, - 3, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "IMM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, TRUE, - 3, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "CHECK\nRESET", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, TRUE, - 3, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "PROGRAM\nLOAD", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, TRUE, - - TXTBOX_X+40, TXTBOX_Y+25, 35, 12, "Tear", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE, - 635, 238, 110, 110, "EMPTY_1442", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE, - 635, 366, 110, 110, "EMPTY_1132", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE, -}; -#define NBUTTONS (sizeof(btn) / sizeof(btn[0])) - -#define STATE_1442_EMPTY 0 /* no cards (no file attached) */ -#define STATE_1442_FULL 1 /* cards in hopper (file attached at BOF) */ -#define STATE_1442_MIDDLE 2 /* cards in hopper and stacker (file attached, neither EOF nor BOF) */ -#define STATE_1442_EOF 3 /* cards in stacker (file attached, at EOF) */ -#define STATE_1442_HIDDEN 4 /* simulator is attached to physical card reader */ - -#define STATE_1132_EMPTY 0 /* no paper hanging out of printer */ -#define STATE_1132_FULL 1 /* paper hanging out of printer */ -#define STATE_1132_HIDDEN 2 /* printer is attached to physical printer */ - -static struct tag_txtbox { - int x, y; - char *txt; - char *unitname; - int idctrl; -} txtbox[] = { - TXTBOX_X, TXTBOX_Y, "Card Reader", "CR", -1, - TXTBOX_X, TXTBOX_Y+ 25, "Printer", "PRT", IDC_1132, - TXTBOX_X, TXTBOX_Y+ 50, "Disk 1", "DSK0", -1, - TXTBOX_X, TXTBOX_Y+ 75, "Disk 2", "DSK1", -1, - TXTBOX_X, TXTBOX_Y+100, "Disk 3", "DSK2", -1, - TXTBOX_X, TXTBOX_Y+125, "Disk 4", "DSK3", -1, - TXTBOX_X, TXTBOX_Y+150, "Disk 5", "DSK4", -1, -}; -#define NTXTBOXES (sizeof(txtbox) / sizeof(txtbox[0])) - -#define TXTBOX_BOTTOM (TXTBOX_Y+150) - -static void init_console_window (void); -static void destroy_console_window (void); -LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -static DWORD WINAPI Pump (LPVOID arg); -static void accept_dropped_file (HANDLE hDrop); -static void tear_printer (void); - -#define NIXOBJECT(hObj) if (hObj != NULL) {DeleteObject(hObj); hObj = NULL;} - -/* ------------------------------------------------------------------------ - * init_console_window - display the 1130 console. Actually just creates a thread - * to run the Pump routine which does the actual work. - * ------------------------------------------------------------------------ */ - -static void init_console_window (void) -{ - static BOOL did_atexit = FALSE; - - if (hConsoleWnd != NULL) - return; - - if (PumpID == 0) - hPump = CreateThread(NULL, 0, Pump, 0, 0, &PumpID); - - if (! did_atexit) { - atexit(destroy_console_window); - did_atexit = TRUE; - } -} - -/* ------------------------------------------------------------------------ - * destroy_console_window - delete GDI objects. - * ------------------------------------------------------------------------ */ - -static void destroy_console_window (void) -{ - int i; - - if (hConsoleWnd != NULL) - SendMessage(hConsoleWnd, WM_CLOSE, 0, 0); /* cross thread call is OK */ - - if (hPump != INVALID_HANDLE_VALUE) { /* this is not the most graceful way to do it */ - TerminateThread(hPump, 0); - hPump = INVALID_HANDLE_VALUE; - PumpID = 0; - hConsoleWnd = NULL; - } - if (hCDC != NULL) { - DeleteDC(hCDC); - hCDC = NULL; - } - - NIXOBJECT(hBitmap) - NIXOBJECT(hbLampOut) - NIXOBJECT(hFont) - NIXOBJECT(hBtnFont); - NIXOBJECT(hTinyFont); - NIXOBJECT(hcHand) - NIXOBJECT(hSwitchPen) - NIXOBJECT(hLtGreyPen) - NIXOBJECT(hGreyPen) - NIXOBJECT(hDkGreyPen) - - for (i = 0; i < NBUTTONS; i++) { - NIXOBJECT(btn[i].hbrLit); - NIXOBJECT(btn[i].hbrDark); - } - -/* if (class_defined) { - UnregisterClass(hInstance, szConsoleClassName); - class_defined = FALSE; - } -*/ -} - -/* ------------------------------------------------------------------------ - * these variables hold the displayed versions of the system registers - * ------------------------------------------------------------------------ */ - -static int shown_iar = 0, shown_sar = 0, shown_sbr = 0, shown_afr = 0, shown_acc = 0, shown_ext = 0; -static int shown_op = 0, shown_tag = 0, shown_irq = 0, shown_ccc = 0, shown_cnd = 0, shown_wait = 0; -static int shown_ces = 0, shown_arf = 0, shown_runmode = MODE_RUN; -static int CND; - -/* ------------------------------------------------------------------------ - * RedrawRegion - mark a region for redrawing without background erase - * ------------------------------------------------------------------------ */ - -static void RedrawRegion (HWND hWnd, int left, int top, int right, int bottom) -{ - RECT r; - - r.left = left; - r.top = top; - r.right = right; - r.bottom = bottom; - - InvalidateRect(hWnd, &r, FALSE); -} - -/* ------------------------------------------------------------------------ - * RepaintRegion - mark a region for redrawing with background erase - * ------------------------------------------------------------------------ */ - -static void RepaintRegion (HWND hWnd, int left, int top, int right, int bottom) -{ - RECT r; - - r.left = left; - r.top = top; - r.right = right; - r.bottom = bottom; - - InvalidateRect(hWnd, &r, TRUE); -} - -/* ------------------------------------------------------------------------ - * update_gui - sees if anything on the console display has changed, and invalidates - * the changed regions. Then it calls UpdateWindow to force an immediate repaint. This - * function (update_gui) should probably not be called every time through the main - * instruction loop but it should be called at least whenever wait_state or int_req change, and then - * every so many instructions. It's also called after every simh command so manual changes are - * reflected instantly. - * ------------------------------------------------------------------------ */ - -void update_gui (BOOL force) -{ - int i; - BOOL state; - static int in_here = FALSE; - static int32 displayed = 0; - RECT xin; - - if ((int32)(console_unit.flags & UNIT_DISPLAY) != displayed) { /* setting has changed */ - displayed = console_unit.flags & UNIT_DISPLAY; - if (displayed) - init_console_window(); - else - destroy_console_window(); - } - - if (hConsoleWnd == NULL) - return; - - GUI_BEGIN_CRITICAL_SECTION /* only one thread at a time, please */ - if (in_here) { - GUI_END_CRITICAL_SECTION - return; - } - in_here = TRUE; - GUI_END_CRITICAL_SECTION - - CND = 0; /* combine carry and V as two bits */ - if (C) - CND |= 2; - if (V) - CND |= 1; - - int_lamps |= int_req; - if (ipl >= 0) - int_lamps |= (0x20 >> ipl); - - if (RUNMODE == MODE_LOAD) - SBR = CES; /* in load mode, SBR follows the console switches */ - - if (IAR != shown_iar) - {shown_iar = IAR; RedrawRegion(hConsoleWnd, 75, 8, 364, 32);} /* lamps: don't bother erasing bkgnd */ - if (SAR != shown_sar) - {shown_sar = SAR; RedrawRegion(hConsoleWnd, 75, 42, 364, 65);} - if (ARF != shown_arf) - {shown_arf = ARF; RedrawRegion(hConsoleWnd, 75, 114, 364, 136);} - if (ACC != shown_acc) - {shown_acc = ACC; RedrawRegion(hConsoleWnd, 75, 141, 364, 164);} - if (EXT != shown_ext) - {shown_ext = EXT; RedrawRegion(hConsoleWnd, 75, 174, 364, 197);} - if (SBR != shown_sbr) - {shown_sbr = SBR; RedrawRegion(hConsoleWnd, 75, 77, 364, 97);} - if (OP != shown_op) - {shown_op = OP; RedrawRegion(hConsoleWnd, 501, 8, 595, 32);} - if (TAG != shown_tag) - {shown_tag = TAG; RedrawRegion(hConsoleWnd, 501, 77, 595, 97);} - - if (int_lamps != shown_irq) - {shown_irq = int_lamps; RedrawRegion(hConsoleWnd, 501, 108, 595, 130);} - - if (CCC != shown_ccc) - {shown_ccc = CCC; RedrawRegion(hConsoleWnd, 501, 141, 595, 164);} - if (CND != shown_cnd) - {shown_cnd = CND; RedrawRegion(hConsoleWnd, 501, 174, 595, 197);} - if ((wait_state|wait_lamp) != shown_wait) - {shown_wait= (wait_state|wait_lamp); RedrawRegion(hConsoleWnd, 380, 77, 414, 97);} - if (CES != shown_ces) - {shown_ces = CES; RepaintRegion(hConsoleWnd, TOGGLES_X-7, 230, TOGGLES_X+360, 275);} /* console entry sw: do erase bkgnd */ - if (RUNMODE != shown_runmode) - {shown_runmode = RUNMODE;RepaintRegion(hConsoleWnd, RUNSWITCH_X-50, RUNSWITCH_Y-50, RUNSWITCH_X+50, RUNSWITCH_Y+50);} - - int_lamps = 0; - - /* this loop works with lamp buttons that are calculated on-the-fly only */ - for (i = 0; i < NBUTTONS; i++) { - if (btn[i].pushable) - continue; - - switch (i) { - case IDC_RUN: - state = hFlashTimer || (running && ! wait_state); - break; - -/* this button is always off - case IDC_PARITY_CHECK -*/ - -/* these buttons are enabled/disabled directly - case IDC_POWER_ON: - case IDC_FILE_READY: - case IDC_FORMS_CHECK: - case IDC_KEYBOARD_SELECT: - case IDC_DISK_UNLOCK: -*/ - default: - continue; - } - - if (state != btn[i].state) { /* state has changed */ - EnableWindow(btn[i].hBtn, state); - btn[i].state = state; - } - } - - if (force) { /* if force flag is set, update text region */ - SetRect(&xin, TXTBOX_X, TXTBOX_Y, TXTBOX_X+TXTBOX_WIDTH, TXTBOX_BOTTOM+2*TXTBOX_HEIGHT); - InvalidateRect(hConsoleWnd, &xin, TRUE); - } - - state = ((cr_unit.flags & UNIT_ATT) == 0) ? STATE_1442_EMPTY : - (cr_unit.flags & UNIT_PHYSICAL) ? STATE_1442_HIDDEN : - (cr_unit.flags & UNIT_CR_EMPTY) ? STATE_1442_EOF : - cr_unit.pos ? STATE_1442_MIDDLE : - STATE_1442_FULL; - - if (state != btn[IDC_1442].state) { - if (state == STATE_1442_HIDDEN) - ShowWindow(btn[IDC_1442].hBtn, SW_HIDE); - else { - if (btn[IDC_1442].state == STATE_1442_HIDDEN) - ShowWindow(btn[IDC_1442].hBtn, SW_SHOWNA); - - SendMessage(btn[IDC_1442].hBtn, STM_SETIMAGE, IMAGE_BITMAP, - (LPARAM) ( - (state == STATE_1442_FULL) ? hbm1442_full : - (state == STATE_1442_MIDDLE) ? hbm1442_middle : - (state == STATE_1442_EOF) ? hbm1442_eof : - hbm1442_empty)); - } - - btn[IDC_1442].state = state; - } - - state = ((prt_unit.flags & UNIT_ATT) == 0) ? STATE_1132_EMPTY : - (prt_unit.flags & UNIT_PHYSICAL_PTR) ? STATE_1132_HIDDEN : - prt_unit.pos ? STATE_1132_FULL : - STATE_1132_EMPTY; - - if (state != btn[IDC_1132].state) { - if (state == STATE_1132_HIDDEN) - ShowWindow(btn[IDC_1132].hBtn, SW_HIDE); - else { - if (btn[IDC_1132].state == STATE_1132_HIDDEN) - ShowWindow(btn[IDC_1132].hBtn, SW_SHOWNA); - - SendMessage(btn[IDC_1132].hBtn, STM_SETIMAGE, IMAGE_BITMAP, - (LPARAM) ( - (state == STATE_1132_FULL) ? hbm1132_full : hbm1132_empty)); - } - - btn[IDC_1132].state = state; - } - - in_here = FALSE; -} - -WNDPROC oldButtonProc = NULL; - -/* ------------------------------------------------------------------------ - * ------------------------------------------------------------------------ */ - -LRESULT CALLBACK ButtonProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - int i; - - i = GetWindowLong(hWnd, GWL_ID); - - if (! btn[i].pushable) { - if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_LBUTTONDBLCLK) - return 0; - - if (uMsg == WM_CHAR) - if ((TCHAR) wParam == ' ') - return 0; - } - - return CallWindowProc(oldButtonProc, hWnd, uMsg, wParam, lParam); -} - -/* ------------------------------------------------------------------------ - * ------------------------------------------------------------------------ */ - -static int occurs (char *txt, char ch) -{ - int count = 0; - - while (*txt) - if (*txt++ == ch) - count++; - - return count; -} - -/* ------------------------------------------------------------------------ - * turns out to get properly colored buttons you have to paint them yourself. Sheesh. - * On the plus side, this lets do a better job of aligning the button text than - * the button would by itself. - * ------------------------------------------------------------------------ */ - -void PaintButton (LPDRAWITEMSTRUCT dis) -{ - int i = dis->CtlID, nc, nlines, x, y, dy; - BOOL down = dis->itemState & ODS_SELECTED; - HPEN hOldPen; - HFONT hOldFont; - UINT oldAlign; - COLORREF oldBk; - char *txt, *tstart; - - if (! BETWEEN(i, 0, NBUTTONS-1)) - return; - - if (! btn[i].subclassed) - return; - - FillRect(dis->hDC, &dis->rcItem, ((btn[i].pushable || power) && IsWindowEnabled(btn[i].hBtn)) ? btn[i].hbrLit : btn[i].hbrDark); - - if (! btn[i].pushable) { - hOldPen = SelectObject(dis->hDC, hBlackPen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.top, NULL); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top); - } - else if (down) { - /* do the three-D thing */ - hOldPen = SelectObject(dis->hDC, hDkGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-2, NULL); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hWhitePen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-1, NULL); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left+1, dis->rcItem.bottom-3, NULL); - LineTo(dis->hDC, dis->rcItem.left+1, dis->rcItem.top+1); - LineTo(dis->hDC, dis->rcItem.right-3, dis->rcItem.top+1); - } - else { - hOldPen = SelectObject(dis->hDC, hWhitePen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-2, NULL); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hDkGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-1, NULL); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left+1, dis->rcItem.bottom-2, NULL); - LineTo(dis->hDC, dis->rcItem.right-2, dis->rcItem.bottom-2); - LineTo(dis->hDC, dis->rcItem.right-2, dis->rcItem.top+1); - } - - SelectObject(dis->hDC, hOldPen); - - hOldFont = SelectObject(dis->hDC, hBtnFont); - oldAlign = SetTextAlign(dis->hDC, TA_CENTER|TA_TOP); - oldBk = SetBkMode(dis->hDC, TRANSPARENT); - - txt = btn[i].txt; - nlines = occurs(txt, '\n')+1; - x = (dis->rcItem.left + dis->rcItem.right) / 2; - y = (dis->rcItem.top + dis->rcItem.bottom) / 2; - - dy = 14; - y = y - (nlines*dy)/2; - - if (down) { - x += 1; - y += 1; - } - - for (;;) { - for (nc = 0, tstart = txt; *txt && *txt != '\n'; txt++, nc++) - ; - - TextOut(dis->hDC, x, y, tstart, nc); - - if (*txt == '\0') - break; - - txt++; - y += dy; - } - - SetTextAlign(dis->hDC, oldAlign); - SetBkMode(dis->hDC, oldBk); - SelectObject(dis->hDC, hOldFont); -} - -/* ------------------------------------------------------------------------ - * ------------------------------------------------------------------------ */ - -HWND CreateSubclassedButton (HWND hwParent, int i) -{ - HWND hBtn; - int x, y; - int r, g, b; - - y = bmht - (4*BUTTON_HEIGHT) + BUTTON_HEIGHT * btn[i].y; - x = (btn[i].x < 2) ? (btn[i].x*BUTTON_WIDTH) : (598 - (4-btn[i].x)*BUTTON_WIDTH); - - if ((hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER|BS_MULTILINE|BS_OWNERDRAW, - x, y, BUTTON_WIDTH, BUTTON_HEIGHT, hwParent, (HMENU) i, hInstance, NULL)) == NULL) - return NULL; - - btn[i].hBtn = hBtn; - - if (oldButtonProc == NULL) - oldButtonProc = (WNDPROC) GetWindowLong(hBtn, GWL_WNDPROC); - - btn[i].hbrLit = CreateSolidBrush(btn[i].clr); - - if (! btn[i].pushable) { - r = GetRValue(btn[i].clr) / 4; - g = GetGValue(btn[i].clr) / 4; - b = GetBValue(btn[i].clr) / 4; - - btn[i].hbrDark = CreateSolidBrush(RGB(r,g,b)); - EnableWindow(hBtn, FALSE); - } - - SetWindowLong(hBtn, GWL_WNDPROC, (LONG) ButtonProc); - return hBtn; -} - -/* ------------------------------------------------------------------------ - * Pump - thread that takes care of the console window. It has to be a separate thread so that it gets - * execution time even when the simulator is compute-bound or IO-blocked. This routine creates the window - * and runs a standard Windows message pump. The window function does the actual display work. - * ------------------------------------------------------------------------ */ - -static DWORD WINAPI Pump (LPVOID arg) -{ - MSG msg; - int wx, wy, i; - RECT r, ra; - BITMAP bm; - WNDCLASS cd; - HDC hDC; - HWND hActWnd; - - hActWnd = GetForegroundWindow(); - - if (! class_defined) { /* register Window class */ - hInstance = GetModuleHandle(NULL); - - memset(&cd, 0, sizeof(cd)); - cd.style = CS_NOCLOSE; - cd.lpfnWndProc = ConsoleWndProc; - cd.cbClsExtra = 0; - cd.cbWndExtra = 0; - cd.hInstance = hInstance; - cd.hIcon = NULL; - cd.hCursor = hcArrow; - cd.hbrBackground = NULL; - cd.lpszMenuName = NULL; - cd.lpszClassName = szConsoleClassName; - - if (! RegisterClass(&cd)) { - PumpID = 0; - return 0; - } - - class_defined = TRUE; - } - - hbWhite = GetStockObject(WHITE_BRUSH); /* create or fetch useful GDI objects */ - hbBlack = GetStockObject(BLACK_BRUSH); /* create or fetch useful GDI objects */ - hbGray = GetStockObject(GRAY_BRUSH); - hSwitchPen = CreatePen(PS_SOLID, 5, RGB(255,255,255)); - - hWhitePen = GetStockObject(WHITE_PEN); - hBlackPen = GetStockObject(BLACK_PEN); - hLtGreyPen = CreatePen(PS_SOLID, 1, RGB(190,190,190)); - hGreyPen = CreatePen(PS_SOLID, 1, RGB(128,128,128)); - hDkGreyPen = CreatePen(PS_SOLID, 1, RGB(64,64,64)); - - hcArrow = LoadCursor(NULL, IDC_ARROW); -#ifdef IDC_HAND - hcHand = LoadCursor(NULL, IDC_HAND); /* use stock object provided by Windows */ - if (hcHand == NULL) - hcHand = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_MYHAND)); -#else - hcHand = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_MYHAND)); -#endif - - if (hBitmap == NULL) - hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_CONSOLE)); - if (hbLampOut == NULL) - hbLampOut = CreateSolidBrush(RGB(50,50,50)); - if (hFont == NULL) - hFont = CreateFont(-10, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FIXED_PITCH, FF_SWISS, "Arial"); - if (hBtnFont == NULL) - hBtnFont = CreateFont(-12, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FIXED_PITCH, FF_SWISS, "Arial"); - if (hTinyFont == NULL) - hTinyFont = CreateFont(-10, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FIXED_PITCH, FF_SWISS, "Arial"); - - if (hConsoleWnd == NULL) { /* create window */ - if ((hConsoleWnd = CreateWindow(szConsoleClassName, "IBM 1130", WS_OVERLAPPED|WS_CLIPCHILDREN, 0, 0, 200, 200, NULL, NULL, hInstance, NULL)) == NULL) { - PumpID = 0; - return 0; - } - - DragAcceptFiles(hConsoleWnd, TRUE); /* let it accept dragged files (scripts) */ - } - - GetObject(hBitmap, sizeof(bm), &bm); /* get bitmap size */ - bmwid = bm.bmWidth; - bmht = bm.bmHeight; - - for (i = 0; i < NBUTTONS; i++) { - if (! btn[i].subclassed) - continue; - - CreateSubclassedButton(hConsoleWnd, i); - if (! btn[i].pushable) - EnableWindow(btn[i].hBtn, btn[i].state); - } - -/* This isn't needed anymore, now that we have the big printer icon -- it acts like a button now - * i = IDC_TEAR; - * btn[i].hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER, - * btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL); - * - * SendMessage(btn[i].hBtn, WM_SETFONT, (WPARAM) hTinyFont, TRUE); - */ - - hbm1442_full = LoadBitmap(hInstance, "FULL_1442"); - hbm1442_empty = LoadBitmap(hInstance, "EMPTY_1442"); - hbm1442_eof = LoadBitmap(hInstance, "EOF_1442"); - hbm1442_middle = LoadBitmap(hInstance, "MIDDLE_1442"); - hbm1132_full = LoadBitmap(hInstance, "FULL_1132"); - hbm1132_empty = LoadBitmap(hInstance, "EMPTY_1132"); - - i = IDC_1442; - - btn[i].hBtn = CreateWindow("STATIC", btn[i].txt, WS_CHILD|WS_VISIBLE|SS_BITMAP|SS_SUNKEN|WS_BORDER|SS_REALSIZEIMAGE|SS_NOTIFY, - btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL); - btn[i].state = STATE_1442_EMPTY; - - wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1442_empty); - - i = IDC_1132; - - btn[i].hBtn = CreateWindow("STATIC", btn[i].txt, WS_CHILD|WS_VISIBLE|SS_BITMAP|SS_SUNKEN|WS_BORDER|SS_REALSIZEIMAGE|SS_NOTIFY, - btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL); - btn[i].state = FALSE; - - wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1132_empty); - - GetWindowRect(hConsoleWnd, &r); /* get window size as created */ - wx = r.right - r.left + 1; - wy = r.bottom - r.top + 1; - - if (hCDC == NULL) { /* get a memory DC and select the bitmap into ti */ - hDC = GetDC(hConsoleWnd); - hCDC = CreateCompatibleDC(hDC); - SelectObject(hCDC, hBitmap); - ReleaseDC(hConsoleWnd, hDC); - } - - GetClientRect(hConsoleWnd, &r); - wx = (wx - r.right - 1) + bmwid; /* compute new desired size based on how client area came out */ - wy = (wy - r.bottom - 1) + bmht; - MoveWindow(hConsoleWnd, 0, 0, wx, wy, FALSE); /* resize window */ - - ShowWindow(hConsoleWnd, SW_SHOWNOACTIVATE); /* display it */ - UpdateWindow(hConsoleWnd); - - if (hActWnd != NULL) { /* bring console (sim) window back to top */ - GetWindowRect(hConsoleWnd, &r); - ShowWindow(hActWnd, SW_NORMAL); /* and move it just below the display window */ - SetWindowPos(hActWnd, HWND_TOP, 0, r.bottom, 0, 0, SWP_NOSIZE); - GetWindowRect(hActWnd, &ra); - if (ra.bottom >= GetSystemMetrics(SM_CYSCREEN)) { /* resize if it goes of bottom of screen */ - ra.bottom = GetSystemMetrics(SM_CYSCREEN) - 1; - SetWindowPos(hActWnd, 0, 0, 0, ra.right-ra.left+1, ra.bottom-ra.top+1, SWP_NOZORDER|SWP_NOMOVE); - } - } - - if (running) /* if simulator is already running, start update timer */ - gui_run(TRUE); - - while (GetMessage(&msg, hConsoleWnd, 0, 0)) { /* message pump - this basically loops forevermore */ - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - if (hConsoleWnd != NULL) { - DragAcceptFiles(hConsoleWnd, FALSE); /* unregister as drag/drop target */ - DestroyWindow(hConsoleWnd); /* but if a quit message got posted, clean up */ - hConsoleWnd = NULL; - } - - PumpID = 0; - return 0; -} - -/* ------------------------------------------------------------------------ - * DrawBits - starting at position (x,y), draw lamps for nbits bits of word 'bits', looking only at masked bits - * ------------------------------------------------------------------------ */ - -static void DrawBits (HDC hDC, int x, int y, int bits, int nbits, int mask, char *syms) -{ - int i, b = 0x0001 << (nbits-1); - - for (i = 0; i < nbits; i++, b >>= 1) { - if (mask & b) { /* select white or black lettering then write 2 chars */ - SetTextColor(hDC, (b & bits && power) ? RGB(255,255,255) : RGB(0,0,0)); - TextOut(hDC, x, y, syms, 2); - } - syms += 2; /* go to next symbol pair */ - - if (i < 10) - x += 15; /* step between lamps */ - else - x += 19; - - if (x < 500) { - if (b & 0x1110) - x += 10; /* step over nibble divisions on left side */ - else if (b & 0x0001) - x += 9; - } - } -} - -/* ------------------------------------------------------------------------ - * DrawToggles - display the console sense switches - * ------------------------------------------------------------------------ */ - - -static void DrawToggles (HDC hDC, int bits) -{ - int b, x; - - for (b = 0x8000, x = TOGGLES_X; b != 0; b >>= 1) { - if (shown_ces & b) { /* up */ - SelectObject(hDC, hbWhite); - Rectangle(hDC, x, 232, x+9, 240); - SelectObject(hDC, hbGray); - Rectangle(hDC, x, 239, x+9, 255); - } - else { /* down */ - SelectObject(hDC, hbWhite); - Rectangle(hDC, x, 263, x+9, 271); - SelectObject(hDC, hbGray); - Rectangle(hDC, x, 248, x+9, 264); - } - - x += (b & 0x1111) ? 31 : 21; - } -} - -/* ------------------------------------------------------------------------ - * DrawRunmode - draw the run mode rotary switch's little tip - * ------------------------------------------------------------------------ */ - -void DrawRunmode (HDC hDC, int mode) -{ - double angle = (mode*45. + 90.) * 3.1415926 / 180.; /* convert mode position to angle in radians */ - double ca, sa; /* sine and cosine */ - int x0, y0, x1, y1; - HPEN hOldPen; - - ca = cos(angle); - sa = sin(angle); - - x0 = RUNSWITCH_X + (int) (20.*ca + 0.5); /* inner radius */ - y0 = RUNSWITCH_Y - (int) (20.*sa + 0.5); - x1 = RUNSWITCH_X + (int) (25.*ca + 0.5); /* outer radius */ - y1 = RUNSWITCH_Y - (int) (25.*sa + 0.5); - - hOldPen = SelectObject(hDC, hSwitchPen); - - MoveToEx(hDC, x0, y0, NULL); - LineTo(hDC, x1, y1); - - SelectObject(hDC, hOldPen); -} - -/* ------------------------------------------------------------------------ - * HandleClick - handle mouse clicks on the console window. Now we just - * look at the console sense switches. Actual says this is a real click, rather - * than a mouse-region test. Return value TRUE means the cursor is over a hotspot. - * ------------------------------------------------------------------------ */ - -static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual, BOOL rightclick) -{ - int b, x, r, ang, i; - - for (b = 0x8000, x = TOGGLES_X; b != 0; b >>= 1) { - if (BETWEEN(xh, x-3, x+8+3) && BETWEEN(yh, 230, 275)) { - if (actual) { - CES ^= b; /* a hit. Invert the bit and redisplay */ - update_gui(TRUE); - } - return TRUE; - } - x += (b & 0x1111) ? 31 : 21; - } - - if (BETWEEN(xh, RUNSWITCH_X-50, RUNSWITCH_X+50) && BETWEEN(yh, RUNSWITCH_Y-50, RUNSWITCH_Y+50)) { /* hit near rotary switch */ - ang = (int) (atan2(RUNSWITCH_X-xh, RUNSWITCH_Y-yh)*180./3.1415926); /* this does implicit 90 deg rotation by the way */ - r = (int) sqrt((xh-RUNSWITCH_X)*(xh-RUNSWITCH_X)+(yh-RUNSWITCH_Y)*(yh-RUNSWITCH_Y)); - if (r > 12) { - for (i = MODE_LOAD; i <= MODE_INT_RUN; i++) { - if (BETWEEN(ang, i*45-12, i*45+12)) { - if (actual) { - RUNMODE = i; - update_gui(TRUE); - } - return TRUE; - } - } - - } - } - - return FALSE; -} - -/* ------------------------------------------------------------------------ - * DrawConsole - refresh the console display. (This routine could be sped up by intersecting - * the various components' bounding rectangles with the repaint rectangle. The bounding rects - * could be put into an array and used both here and in the refresh routine). - * - * RedrawRegion -> force repaint w/o background redraw. used for lamps which are drawn in the same place in either state - * RepaintRegion-> repaint with background redraw. Used for toggles which change position. - * ------------------------------------------------------------------------ */ - -static void DrawConsole (HDC hDC, PAINTSTRUCT *ps) -{ - static char digits[] = " 0 1 2 3 4 5 6 7 8 9101112131415"; - static char cccs[] = "3216 8 4 2 1"; - static char cnds[] = " C V"; - static char waits[] = " W"; - HFONT hOldFont, hOldBrush; - RECT xout, xin; - int i, n; - DEVICE *dptr; - UNIT *uptr; - t_bool enab; - char nametemp[50], *dispname; - - hOldFont = SelectObject(hDC, hFont); /* use that tiny font */ - hOldBrush = SelectObject(hDC, hbWhite); - - SetBkMode(hDC, TRANSPARENT); /* overlay letters w/o changing background */ - - DrawBits(hDC, 76, 15, shown_iar, 16, mem_mask, digits); /* register holds only 15 bits */ - DrawBits(hDC, 76, 48, shown_sar, 16, mem_mask, digits); /* but let's display only used bits */ - DrawBits(hDC, 76, 81, shown_sbr, 16, 0xFFFF, digits); - DrawBits(hDC, 76, 114, shown_arf, 16, 0xFFFF, digits); - DrawBits(hDC, 76, 147, shown_acc, 16, 0xFFFF, digits); - DrawBits(hDC, 76, 180, shown_ext, 16, 0xFFFF, digits); - - DrawBits(hDC, 506, 15, shown_op, 5, 0x001F, digits); - DrawBits(hDC, 506, 81, shown_tag, 4, 0x0007, digits); - DrawBits(hDC, 506, 114, shown_irq, 6, 0x003F, digits); - DrawBits(hDC, 506, 147, shown_ccc, 6, 0x003F, cccs); - DrawBits(hDC, 506, 180, shown_cnd, 2, 0x0003, cnds); - - DrawBits(hDC, 390, 81, shown_wait?1:0,1, 0x0001, waits); - - DrawToggles(hDC, shown_ces); - - DrawRunmode(hDC, shown_runmode); - - SelectObject(hDC, hOldFont); - SelectObject(hDC, hOldBrush); - - SetBkColor(hDC, RGB(0,0,0)); - - SetRect(&xin, TXTBOX_X, TXTBOX_Y, TXTBOX_X+TXTBOX_WIDTH, TXTBOX_BOTTOM+TXTBOX_HEIGHT); - if (IntersectRect(&xout, &xin, &ps->rcPaint)) { - hOldFont = SelectObject(hDC, hTinyFont); - - for (i = 0; i < NTXTBOXES; i++) { - enab = FALSE; - - dptr = find_unit(txtbox[i].unitname, &uptr); - if (dptr != NULL && uptr != NULL) { - if (uptr->flags & UNIT_DIS) { - SetTextColor(hDC, RGB(128,0,0)); - } - else if (uptr->flags & UNIT_ATT) { - SetTextColor(hDC, RGB(0,0,255)); - if ((n = strlen(uptr->filename)) > 30) { - strcpy(nametemp, "..."); - strcpy(nametemp+3, uptr->filename+n-30); - dispname = nametemp; - } - else - dispname = uptr->filename; - - TextOut(hDC, txtbox[i].x+25, txtbox[i].y+TXTBOX_HEIGHT, dispname, strlen(dispname)); - SetTextColor(hDC, RGB(255,255,255)); - enab = TRUE; - } - else { - SetTextColor(hDC, RGB(128,128,128)); - } - TextOut(hDC, txtbox[i].x, txtbox[i].y, txtbox[i].txt, strlen(txtbox[i].txt)); - } - - if (txtbox[i].idctrl >= 0) - EnableWindow(btn[txtbox[i].idctrl].hBtn, enab); - } - - SelectObject(hDC, hOldFont); - } -} - -/* ------------------------------------------------------------------------ - * Handles button presses. Remember that this occurs in the context of - * the Pump thread, not the simulator thread. - * ------------------------------------------------------------------------ */ - -void flash_run (void) -{ - EnableWindow(btn[IDC_RUN].hBtn, TRUE); /* enable the run lamp */ - - if (hFlashTimer != 0) - KillTimer(hConsoleWnd, FLASH_TIMER_ID); /* (re)schedule lamp update */ - - hFlashTimer = SetTimer(hConsoleWnd, FLASH_TIMER_ID, LAMPTIME, NULL); -} - -void gui_run (int running) -{ - if (running && hUpdateTimer == 0 && hConsoleWnd != NULL) { - hUpdateTimer = SetTimer(hConsoleWnd, UPDATE_TIMER_ID, 1000/UPDATE_INTERVAL, NULL); - } - else if (hUpdateTimer != 0 && ! running) { - KillTimer(hConsoleWnd, UPDATE_TIMER_ID); - hUpdateTimer = 0; - } - flash_run(); /* keep run lamp active for a while after we stop running */ -} - -void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl) -{ - int i; - - switch (idCtl) { - case IDC_POWER: /* toggle system power */ - power = ! power; - reset_all(0); - if (running && ! power) { /* turning off */ - reason = STOP_POWER_OFF; - /* wait for execution thread to exit */ -/* this prevents message pump from running, which unfortunately locks up - * the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp - * while (running) - * Sleep(10); - */ - } - - btn[IDC_POWER_ON].state = power; - EnableWindow(btn[IDC_POWER_ON].hBtn, power); - - for (i = 0; i < NBUTTONS; i++) /* repaint all of the lamps */ - if (! btn[i].pushable) - InvalidateRect(btn[i].hBtn, NULL, TRUE); - - break; - - case IDC_PROGRAM_START: /* begin execution */ - if (! running) { - switch (RUNMODE) { - case MODE_INT_RUN: - case MODE_RUN: - case MODE_SI: - stuff_cmd("cont"); - break; - - case MODE_DISP: /* display core and advance IAR */ - ReadW(IAR); - IAR = IAR+1; - flash_run(); /* illuminate run lamp for .5 sec */ - break; - - case MODE_LOAD: /* store to core and advance IAR */ - WriteW(IAR, CES); - IAR = IAR+1; - flash_run(); - break; - } - } - break; - - case IDC_PROGRAM_STOP: - if (running) { /* potential race condition here */ - GUI_BEGIN_CRITICAL_SECTION - SETBIT(con_dsw, CPU_DSW_PROGRAM_STOP); - SETBIT(ILSW[5], ILSW_5_INT_RUN_PROGRAM_STOP); - int_req |= INT_REQ_5; /* note: calc_ints() is not needed in this case */ - int_lamps |= INT_REQ_5; - GUI_END_CRITICAL_SECTION - } - break; - - case IDC_LOAD_IAR: - if (! running) { - IAR = CES & mem_mask; /* set IAR from console entry switches */ - } - break; - - case IDC_KEYBOARD: /* toggle between console/keyboard mode */ - break; - - case IDC_IMM_STOP: - if (running) { - reason = STOP_IMMEDIATE; /* terminate execution without setting wait_mode */ - /* wait for execution thread to exit */ -/* this prevents message pump from running, which unfortunately locks up - * the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp - * while (running) - * Sleep(10); - */ - } - break; - - case IDC_RESET: - if (! running) { /* check-reset is disabled while running */ - reset_all(0); - forms_check(0); /* clear forms-check status */ - print_check(0); - } - break; - - case IDC_PROGRAM_LOAD: - if (! running) { /* if card reader is attached to a file, do cold start read of one card */ - IAR = 0; /* reset IAR */ -#ifdef PROGRAM_LOAD_STARTS_CPU - stuff_cmd("boot cr"); -#else - if (cr_boot(0, NULL) != SCPE_OK) /* load boot card */ - remark_cmd("IPL failed"); -#endif - } - break; - - case IDC_TEAR: /* "tear off printer output" */ - case IDC_1132: /* do same if they click on the printer icon */ - if (btn[IDC_1132].state && (wNotify == STN_CLICKED || wNotify == STN_DBLCLK)) - tear_printer(); - break; - - case IDC_1442: - if (btn[IDC_1442].state == STATE_1442_FULL || wNotify == STN_DBLCLK) - stuff_cmd("detach cr"); - else if (btn[IDC_1442].state != STATE_1442_EMPTY && wNotify == STN_CLICKED) { - cr_rewind(); - update_gui(TRUE); - } - break; - } - - update_gui(FALSE); -} - -/* ------------------------------------------------------------------------ - * ConsoleWndProc - window process for the console display - * ------------------------------------------------------------------------ */ - -LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - HDC hDC; - PAINTSTRUCT ps; - POINT p; - RECT clip, xsect, rbmp; - int i; - - switch (uMsg) { - case WM_CLOSE: - DestroyWindow(hWnd); - break; - - case WM_DESTROY: - gui_run(FALSE); - hConsoleWnd = NULL; - break; - - case WM_ERASEBKGND: - hDC = (HDC) wParam; - GetClipBox(hDC, &clip); - SetRect(&rbmp, 0, 0, bmwid, bmht); - if (IntersectRect(&xsect, &clip, &rbmp)) - BitBlt(hDC, xsect.left, xsect.top, xsect.right-xsect.left+1, xsect.bottom-xsect.top+1, hCDC, xsect.left, xsect.top, SRCCOPY); - return TRUE; /* let Paint do this so we know what the update region is (ps.rcPaint) */ - - case WM_PAINT: - hDC = BeginPaint(hWnd, &ps); - DrawConsole(hDC, &ps); - EndPaint(hWnd, &ps); - break; - - case WM_COMMAND: /* button click */ - HandleCommand(hWnd, HIWORD(wParam), LOWORD(wParam), (HWND) lParam); - break; - - case WM_CTLCOLOREDIT: /* text color for edit controls */ - SetBkColor((HDC) wParam, RGB(0,0,0)); - SetTextColor((HDC) wParam, RGB(255,255,255)); - break; - - case WM_DRAWITEM: - PaintButton((LPDRAWITEMSTRUCT) lParam); - break; - - case WM_SETCURSOR: - GetCursorPos(&p); - ScreenToClient(hWnd, &p); - SetCursor(HandleClick(hWnd, p.x, p.y, FALSE, FALSE) ? hcHand : hcArrow); - return TRUE; - - case WM_LBUTTONDOWN: - HandleClick(hWnd, LOWORD(lParam), HIWORD(lParam), TRUE, FALSE); - break; - - case WM_RBUTTONDOWN: - HandleClick(hWnd, LOWORD(lParam), HIWORD(lParam), TRUE, TRUE); - break; - - case WM_CTLCOLORBTN: - i = GetWindowLong((HWND) lParam, GWL_ID); - if (BETWEEN(i, 0, NBUTTONS-1)) - return (LRESULT) (power && IsWindowEnabled((HWND) lParam) ? btn[i].hbrLit : btn[i].hbrDark); - - case WM_TIMER: - if (wParam == FLASH_TIMER_ID && hFlashTimer != 0) { - KillTimer(hWnd, FLASH_TIMER_ID); - hFlashTimer = 0; - } - update_gui(FALSE); - break; - - case WM_DROPFILES: - accept_dropped_file((HANDLE) wParam); /* console window - dragged file is a script or card deck */ - break; - - default: - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } - - return 0; -} - -enum {PRINTER_OK = 0, FORMS_CHECK = 1, PRINT_CHECK = 2, BOTH_CHECK = 3} printerstatus = PRINTER_OK; - -void forms_check (int set) -{ - COLORREF oldcolor = btn[IDC_FORMS_CHECK].clr; - - if (set) - SETBIT(printerstatus, FORMS_CHECK); - else - CLRBIT(printerstatus, FORMS_CHECK); - - btn[IDC_FORMS_CHECK].clr = (printerstatus & PRINT_CHECK) ? RGB(255,0,0) : RGB(255,255,0); - - btn[IDC_FORMS_CHECK].state = printerstatus; - - if (btn[IDC_FORMS_CHECK].hBtn != NULL) { - EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus); - - if (btn[IDC_FORMS_CHECK].clr != oldcolor) - InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); /* change color in any case */ - } -} - -void print_check (int set) -{ - COLORREF oldcolor = btn[IDC_FORMS_CHECK].clr; - - if (set) - SETBIT(printerstatus, PRINT_CHECK); - else - CLRBIT(printerstatus, PRINT_CHECK); - - btn[IDC_FORMS_CHECK].clr = (printerstatus & PRINT_CHECK) ? RGB(255,0,0) : RGB(255,255,0); - - btn[IDC_FORMS_CHECK].state = printerstatus; - - if (btn[IDC_FORMS_CHECK].hBtn != NULL) { - EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus); - - if (btn[IDC_FORMS_CHECK].clr != oldcolor) - InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); /* change color in any case */ - } -} - -void keyboard_selected (int select) -{ - btn[IDC_KEYBOARD_SELECT].state = select; - - if (btn[IDC_KEYBOARD_SELECT].hBtn != NULL) - EnableWindow(btn[IDC_KEYBOARD_SELECT].hBtn, select); -} - -void disk_ready (int ready) -{ - btn[IDC_FILE_READY].state = ready; - - if (btn[IDC_FILE_READY].hBtn != NULL) - EnableWindow(btn[IDC_FILE_READY].hBtn, ready); -} - -void disk_unlocked (int unlocked) -{ - btn[IDC_DISK_UNLOCK].state = unlocked; - - if (btn[IDC_DISK_UNLOCK].hBtn != NULL) - EnableWindow(btn[IDC_DISK_UNLOCK].hBtn, unlocked); -} - -static void accept_dropped_file (HANDLE hDrop) -{ - int nfiles; - char fname[MAX_PATH], cmd[MAX_PATH+50], *deckfile; - BOOL cardreader; - POINT pt; - HWND hWndDrop; - - nfiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); /* get file count, */ - DragQueryFile(hDrop, 0, fname, sizeof(fname)); /* get first filename */ - DragQueryPoint(hDrop, &pt); /* get location of drop */ - DragFinish(hDrop); - - if (nfiles <= 0) /* hmm, this seems unlikely to occur, but better check */ - return; - - if (running) { /* can only accept a drop while processor is stopped */ - MessageBeep(0); - return; - } - - if ((hWndDrop = ChildWindowFromPoint(hConsoleWnd, pt)) == btn[IDC_1442].hBtn) - cardreader = TRUE; /* file was dropped onto 1442 card reader */ - else if (hWndDrop == NULL || hWndDrop == hConsoleWnd) - cardreader = FALSE; /* file was dropped onto console window, not a button */ - else { - MessageBeep(0); /* file was dropped onto another button */ - return; - } - - if (nfiles > 1) { /* oops, we wouldn't know what order to read them in */ - MessageBox(hConsoleWnd, "You may only drop one file at a time", "", MB_OK); - return; - } - - /* if shift key is down, prepend @ to name (make it a deck file) */ - deckfile = ((GetKeyState(VK_SHIFT) & 0x8000) && cardreader) ? "@" : ""; - - sprintf(cmd, "%s \"%s%s\"", cardreader ? "attach cr" : "do", deckfile, fname); - stuff_cmd(cmd); -} - -static void tear_printer (void) -{ - char cmd[MAX_PATH+100], filename[MAX_PATH]; - - if ((prt_unit.flags & UNIT_ATT) == 0) - return; - - strcpy(filename, prt_unit.filename); /* save current attached filename */ - - if (! stuff_and_wait("detach prt", 1000, 0)) /* detach it */ - return; - - sprintf(cmd, "view \"%s\"", filename); /* spawn notepad to view it */ - if (! stuff_and_wait(cmd, 3000, 500)) - return; - - remove(filename); /* delete the file */ - - sprintf(cmd, "attach prt \"%s\"", filename); /* reattach */ - stuff_cmd(cmd); -} - -#ifdef XXX - if ((hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER|BS_MULTILINE|BS_OWNERDRAW, - x, y, BUTTON_WIDTH, BUTTON_HEIGHT, hwParent, (HMENU) i, hInstance, NULL)) == NULL) - return NULL; - -#endif - -CRITICAL_SECTION critsect; - -void begin_critical_section (void) -{ - static BOOL mustinit = TRUE; - - if (mustinit) { - InitializeCriticalSection(&critsect); - mustinit = FALSE; - } - - EnterCriticalSection(&critsect); -} - -void end_critical_section (void) -{ - LeaveCriticalSection(&critsect); -} - -#ifndef MIN -# define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#endif - -/* win32 - use a separate thread to read command lines so the GUI - * can insert commands as well */ - -static HANDLE hCmdThread = NULL; -static DWORD iCmdThreadID = 0; -static HANDLE hCmdReadEvent = NULL; -static HANDLE hCmdReadyEvent = NULL; -static BOOL scp_stuffed = FALSE, scp_reading = FALSE; -static char cmdbuffer[256]; - -/* CmdThread - separate thread to read commands from stdin upon request */ - -static DWORD WINAPI CmdThread (LPVOID arg) -{ - for (;;) { - WaitForSingleObject(hCmdReadEvent, INFINITE); /* wait for request */ - read_line(cmdbuffer, sizeof(cmdbuffer), stdin); /* read one line */ - scp_stuffed = FALSE; /* say how we got it */ - scp_reading = FALSE; - SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */ - } - return 0; -} - -char *read_cmdline (char *ptr, int size, FILE *stream) -{ - char *cptr; - - if (hCmdThread == NULL) { /* set up command-reading thread */ - if ((hCmdReadEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) - scp_panic("Can't create command line read event"); - - if ((hCmdReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) - scp_panic("Can't create command line ready event"); - /* start up the command thread */ - if ((hCmdThread = CreateThread(NULL, 0, CmdThread, NULL, 0, &iCmdThreadID)) == NULL) - scp_panic("Unable to create command line reading thread"); - } - - scp_reading = TRUE; - - SetEvent(hCmdReadEvent); /* let read thread get one line */ - WaitForSingleObject(hCmdReadyEvent, INFINITE); /* wait for read thread or GUI to respond */ - strncpy(ptr, cmdbuffer, MIN(size, sizeof(cmdbuffer))); /* copy line to caller's buffer */ - - for (cptr = ptr; isspace(*cptr); cptr++) /* absorb spaces */ - ; - - if (scp_stuffed) { /* stuffed command needs to be echoed */ - printf("%s\n", cptr); - if (sim_log) fprintf(sim_log, "%s\n", cptr); - } - - return cptr; -} - -/* stuff_cmd - force a command into the read_cmdline output buffer. Called asynchronously by GUI */ - -void stuff_cmd (char *cmd) -{ - strcpy(cmdbuffer, cmd); /* save the string */ - scp_stuffed = TRUE; /* note where it came from */ - scp_reading = FALSE; - ResetEvent(hCmdReadEvent); /* clear read request event */ - SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */ -} - -/* my_yield - process GUI messages. It's not apparent why stuff_and_wait would block, - * since it sleeps in the GUI thread while scp runs in the main thread. However, - * at the end of every command scp calls update_gui, which can result in messages - * being sent to the GUI thread. So, the GUI thread has to process messages while - * stuff_and_wait is waiting. - */ -static void my_yield (void) -{ - MSG msg; - /* multitask */ - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } -} - -/* stuff_and_wait -- stuff a command and wait for the emulator to process the command - * and come back to prompt for another - */ - -t_bool stuff_and_wait (char *cmd, int timeout, int delay) -{ - scp_reading = FALSE; - - stuff_cmd(cmd); - - while (! scp_reading) { - if (timeout < 0) - return FALSE; - - my_yield(); - if (scp_reading) - break; - - Sleep(50); - if (timeout) - if ((timeout -= 50) <= 0) - timeout = -1; - - my_yield(); - } - - if (delay) - Sleep(delay); - - return TRUE; -} - -/* remark_cmd - print a remark from inside a command processor. This routine takes - * into account the possiblity that the command might have been stuffed, in which - * case the sim> prompt needs to be reprinted. - */ - -void remark_cmd (char *remark) -{ - if (scp_reading) { - putchar('\n'); - if (sim_log) putc('\n', sim_log); - } - - printf("%s\n", remark); - if (sim_log) fprintf(sim_log, "%s\n", remark); - - if (scp_reading) { - printf("sim> "); - if (sim_log) fprintf(sim_log, "sim> "); - } -} - -#endif /* _WIN32 defined */ -#endif /* GUI_SUPPORT defined */ diff --git a/Ibm1130/ibm1130_plot.c b/Ibm1130/ibm1130_plot.c deleted file mode 100644 index 02344a3c..00000000 --- a/Ibm1130/ibm1130_plot.c +++ /dev/null @@ -1,634 +0,0 @@ -/* ibm1130_plot.c: IBM 1130 1627 plotter emulation - - Based on the SIMH simulator package written by Robert M Supnik - - Brian Knittel - Revision History - - 2004.10.22 - Written. - 2006.1.2 - Rewritten as plotter routine by Carl V Claunch - - * (C) Copyright 2004, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#include "ibm1130_defs.h" - -#ifndef ENABLE_PLOT_SUPPORT - - DEVICE plot_dev = { - "PLOT", NULL, NULL, NULL, - 0, 16, 16, 1, 16, 16, - NULL, NULL, NULL, - NULL, NULL, NULL}; - - void xio_1627_plotter (int32 addr, int32 func, int32 modify) - { - /* silently eat any plotter commands */ - } - -#else - -#include "gd.h" - -/*************************************************************************************** - * 1627 model 1 plotter (based on Calcomp 535 which was sold as IBM 1627) - * - * - 11" wide carriage, addressible in .01" steps - * - continous sheet paper up to 120' in length - * - sheet moveable in .01" steps, either direction - * - switchable pen, in various colors and line widths - * - * Simulator implementation will create a JPEG image corresponding to a - * landscape mode sheet of paper, the width of the carriage at 11". - * A diagram of more than 8" of paper travel will span printed pages - * in landscape mode. - * - * When an 'att plot' command is issued a file is created based on the - * default or currently set values of paper length, starting - * position of the pen in both X and Y axes, pen color and pen width. - * Based on the number of logical pages of paper, the command will create - * the proper size canvas internally and create the output JPEG file. - * - * When a 'det plot' command is issued, the plotter image will be converted - * into the file that was specified during the attach process. The - * image is not viewable until this point, unless an examine plot is - * issued which will dump the current state of the paper into the file. - * - * The 'set plot' command can set pen width, paper length, pen color, - * current carriage X and Y coordinates. Paper length can be set - * to alter the default of 800 (8"); changes are ignored until - * the next 'attach' command. The current carriage x and y positions - * can be set at any time and will go into effect immediately, just - * as the pen color and pen width can be altered on the fly. - * - * NOTE: requires gd library and definition of ENABLE_PLOT_SUPPORT in makefile or Visual C configuration - * gd is not included in the main simh and ibm1130.org distributions at the present time. - ***************************************************************************************/ - -#define PLOT1627_DSW_OP_COMPLETE 0x8000 -#define PLOT1627_DSW_BUSY 0x0200 -#define PLOT1627_DSW_NOT_READY 0x0100 - -#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) -#define IS_DEBUG ((plot_unit->flags & UNIT_DEBUG) == UNIT_DEBUG) -#define IS_PENDOWN ((plot_unit->flags & UNIT_PEN) == UNIT_PEN) - -static t_stat plot_svc (UNIT *uptr); /* activity routine */ -static t_stat plot_reset (DEVICE *dptr); /* reset of 1130 */ -static t_stat plot_attach (UNIT *uptr, char *cptr); /* attach, loads plotter */ -static t_stat plot_detach (UNIT *uptr); /* detach and save image */ -static t_stat plot_examine (UNIT *uptr); /* update file with current canvas */ -static t_stat plot_set_length (UNIT *uptr, int32 val, char * ptr, void *desc); /* set paper length */ -static t_stat plot_set_pos (UNIT *uptr, int32 val, char * ptr, void *desc); /* reset current X/Y position */ -static t_stat plot_show_vals(FILE *fp, UNIT *uptr, int32 val, void *descrip); /* print x, y and length */ -static t_stat plot_show_nl(FILE *fp, UNIT *uptr, int32 val, void *descrip); /* overcome wacky simh behavior */ -static void update_pen(void); /* will ensure pen action is correct when changes made */ -static t_stat plot_validate_change (UNIT *uptr, int32 val, char * ptr, void *desc); /* when set command issued */ -static void process_cmd(void); /* does actual drawing for plotter */ - -extern int32 sim_switches; /* switches set on simh command */ -static int16 plot_dsw = 0; /* device status word */ -static int16 plot_cmd = 0; /* the command to process */ -static int32 plot_wait = 1000; /* plotter movement wait */ -static int32 plot_xpos = 0; /* current X position */ -static int32 plot_xmax = 799; /* end of paper */ -static int32 plot_ypos = 0; /* current Y position */ -static int32 plot_ymax = 1099; /* right edge of carriage */ - -#define PEN_DOWN 0x80000000 -#define PEN_UP 0x00000000 -static int32 plot_pen = PEN_UP; /* current pen position */ - -static int black_pen; /* holds color black */ -static int blue_pen; /* holds color blue */ -static int red_pen; /* holds color red */ -static int green_pen; /* holds color green */ -static int yellow_pen; /* holds yellow color */ -static int purple_pen; /* holds color purple */ -static int ltgrey_pen; /* holds light grey */ -static int grey_pen; /* holds grey */ -static int white_background; /* holds white of paper roll */ -static int plot_pwidth; /* set and display variable */ -static int plot_pcolor; /* set and display variable */ -static int need_update = 0; /* flag to force and update_pen() */ -static gdImagePtr image; /* pointer to our canvas */ - -#define UNIT_V_COLOR (UNIT_V_UF + 0) /* color of selected pen - 3 bits */ -#define UNIT_V_WIDTH (UNIT_V_UF + 3) /* width of pen - two bits */ -#define UNIT_V_NOOP (UNIT_V_UF + 5) /* dummy for set/show commands */ -#define UNIT_V_DEBUG (UNIT_V_UF + 6) /* for -d switch on attach command */ -#define UNIT_V_PEN (UNIT_V_UF + 7) /* track pen state */ - -#define UNIT_WIDTH (3u << UNIT_V_WIDTH) /* two bits */ -#define UNIT_COLOR (7u << UNIT_V_COLOR) /* three bits */ -#define UNIT_NOOP (1u << UNIT_V_NOOP) /* dummy for set/show */ -#define UNIT_DEBUG (1u << UNIT_V_DEBUG) /* shows debug mode on */ -#define UNIT_PEN (1u << UNIT_V_PEN) /* the pen state bit */ - -#define PEN_BLACK (0u << UNIT_V_COLOR) -#define PEN_RED (1u << UNIT_V_COLOR) -#define PEN_BLUE (2u << UNIT_V_COLOR) -#define PEN_GREEN (3u << UNIT_V_COLOR) -#define PEN_YELLOW (4u << UNIT_V_COLOR) -#define PEN_PURPLE (5u << UNIT_V_COLOR) -#define PEN_LTGREY (6u << UNIT_V_COLOR) -#define PEN_GREY (7u << UNIT_V_COLOR) - -#define SET_COLOR(op) {plot_unit[0].flags &= ~UNIT_COLOR; plot_unit[0].flags |= (op);} -#define GET_COLOR (plot_unit[0].flags & UNIT_COLOR) - -#define BLACK 0,0,0 -#define BLUE 0,0,255 -#define RED 255,0,0 -#define GREEN 0,255,0 -#define YELLOW 200,200,0 -#define PURPLE 150,0,150 -#define LTGREY 200,200,200 -#define GREY 120,120,120 -#define WHITE 255,255,255 - -#define PEN_SINGLE (0u << UNIT_V_WIDTH) -#define PEN_DOUBLE (1u << UNIT_V_WIDTH) -#define PEN_TRIPLE (2u << UNIT_V_WIDTH) -#define PEN_QUAD (3u << UNIT_V_WIDTH) - -#define GET_WIDTH() (plot_unit[0].flags & UNIT_WIDTH) -#define SET_WIDTH(cd) {plot_unit[0].flags &= ~UNIT_WIDTH; un.flags |= (cd);} - -UNIT plot_unit[] = { - { UDATA (&plot_svc, UNIT_ATTABLE, 0) }, -}; - -REG plot_reg[] = { - { HRDATA (DSW, plot_dsw, 16) }, /* device status word */ - { DRDATA (WTIME, plot_wait, 24), PV_LEFT }, /* plotter movement wait */ - { DRDATA (Xpos, plot_xpos, 32), PV_LEFT }, /* Current X Position*/ - { DRDATA (Ypos, plot_ypos, 32), PV_LEFT }, /* Current Y Position*/ - { FLDATA (PenDown, plot_pen, 0)}, /* Current pen position - 1 = down */ - { DRDATA (PaperSize, plot_xmax, 32), PV_LEFT }, /* Length of paper in inches */ - { NULL } }; - -MTAB plot_mod[] = { - { UNIT_COLOR, PEN_BLACK, "black", "BLACK", &plot_validate_change}, - { UNIT_COLOR, PEN_RED, "red", "RED", &plot_validate_change}, - { UNIT_COLOR, PEN_BLUE, "blue", "BLUE", &plot_validate_change}, - { UNIT_COLOR, PEN_GREEN, "green", "GREEN", &plot_validate_change}, - { UNIT_COLOR, PEN_YELLOW, "yellow", "YELLOW", &plot_validate_change}, - { UNIT_COLOR, PEN_PURPLE, "purple", "PURPLE", &plot_validate_change}, - { UNIT_COLOR, PEN_LTGREY, "ltgrey", "LTGREY", &plot_validate_change}, - { UNIT_COLOR, PEN_GREY, "grey", "GREY", &plot_validate_change}, - { UNIT_WIDTH, PEN_SINGLE, "1.0", "1.0", &plot_validate_change}, - { UNIT_WIDTH, PEN_DOUBLE, "2.0", "2.0", &plot_validate_change}, - { UNIT_WIDTH, PEN_TRIPLE, "3.0", "3.0", &plot_validate_change}, - { UNIT_WIDTH, PEN_QUAD, "4.0", "4.0", &plot_validate_change}, - { UNIT_PEN, UNIT_PEN, "pendown", "PENDOWN", &plot_validate_change}, - { UNIT_PEN, 0, "penup", "PENUP", &plot_validate_change}, - /* below is dummy entry to trigger the show routine and print extended values */ - { UNIT_NOOP, 0, "", NULL, NULL, &plot_show_vals}, - /* extended entries must allow parm for both unit and dev, but - * then they will print the value twice for a 'show plot' command - * therefore they are set to not display unless explicity requested - * and the special dummy NOOP entry will cause the print of these values */ - { MTAB_XTD | MTAB_VAL | MTAB_VUN | MTAB_VDV | MTAB_NMO, 2, - "length", "LENGTH", &plot_set_length, &plot_show_nl, &plot_reg[5]}, - { MTAB_XTD | MTAB_VAL | MTAB_VDV | MTAB_VUN | MTAB_NMO, 0, - "Xpos", "XPOS", &plot_set_pos, &plot_show_nl, &plot_reg[2]}, - { MTAB_XTD | MTAB_VAL | MTAB_VDV | MTAB_VUN | MTAB_NMO, 1, - "Ypos", "YPOS", &plot_set_pos, &plot_show_nl, &plot_reg[3]}, - { 0 } }; - -DEVICE plot_dev = { - "PLOT", plot_unit, plot_reg, plot_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, plot_reset, - NULL, plot_attach, plot_detach}; - -/* xio_1627_plotter - XIO command interpreter for the 1627 plotter model 1 */ - -void xio_1627_plotter (iocc_addr, iocc_func, iocc_mod) -{ - char msg[80]; - - if (! IS_ONLINE(plot_unit) ) { - SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* set not ready */ - if (IS_DEBUG) printf("Plotter has no paper, ignored\n"); - return; /* and ignore */ - } - - switch (iocc_func) { - case XIO_READ: /* read XIO */ - xio_error("Read XIO not supported by 1627 plotter"); - break; - - case XIO_WRITE: /* write: do one plotter operation */ - if ((plot_dsw & PLOT1627_DSW_NOT_READY)) { - if (IS_DEBUG) printf("Wrote to non-ready Plotter\n"); - break; - } - plot_cmd = (uint16) ( M[iocc_addr & mem_mask] >> 10 ); /* pick up command */ - process_cmd(); /* interpret command */ - sim_activate(plot_unit, plot_wait); /* schedule interrupt */ - SETBIT(plot_dsw, PLOT1627_DSW_BUSY); /* mark it busy */ - break; - - case XIO_SENSE_DEV: /* sense device status */ - ACC = plot_dsw; /* get current status */ - if (iocc_mod & 0x01) { /* reset interrupts */ - CLRBIT(plot_dsw, PLOT1627_DSW_OP_COMPLETE); - CLRBIT(ILSW[3], ILSW_3_1627_PLOTTER); - } - break; - - case XIO_CONTROL: /* control XIO */ - xio_error("Control XIO not supported by 1627 plotter"); - break; - - default: - sprintf(msg, "Invalid 1627 Plotter XIO function %x", iocc_func); - xio_error(msg); - } - return; -} - -// plot_svc - 1627 plotter operation complete - -static t_stat plot_svc (UNIT *uptr) -{ - CLRBIT(plot_dsw, PLOT1627_DSW_BUSY); /* clear reader busy flag */ - - SETBIT(plot_dsw, PLOT1627_DSW_OP_COMPLETE); /* indicate read complete */ - - SETBIT(ILSW[3], ILSW_3_1627_PLOTTER); /* initiate interrupt */ - calc_ints(); - - return SCPE_OK; -} - -/* plot_reset - reset emulated plotter */ - -static t_stat plot_reset (DEVICE *dptr) -{ - char * buf; - int32 size; - - sim_cancel(plot_unit); - - CLRBIT(plot_dsw, PLOT1627_DSW_BUSY | PLOT1627_DSW_OP_COMPLETE); - - if (IS_DEBUG) printf("reset routine for Plotter\n"); - - CLRBIT(ILSW[3], ILSW_3_1627_PLOTTER); - calc_ints(); - - return SCPE_OK; -} - - -/* plot_attach - attach file to simulated plotter */ - -static t_stat plot_attach (UNIT *uptr, char *cptr) -{ - t_stat result; - - CLRBIT(uptr->flags, UNIT_DEBUG); - if (sim_switches & SWMASK('D')) SETBIT(uptr->flags, UNIT_DEBUG); - - /* get the output file by using regular attach routine */ - result = attach_unit(uptr, cptr); - - if (result != SCPE_OK) { - if (IS_DEBUG) printf("problem attaching file\n"); - return result; - } - - SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* assume failure */ - - /* set up our canvas at the desired size */ - image = gdImageCreate(plot_ymax+1,plot_xmax+1); /* create our canvas */ - if (image == NULL) { - if (IS_DEBUG) printf("problem creating image canvas\n"); - return SCPE_MEM; - } - - /* set up the basic colors after image created */ - white_background = gdImageColorAllocate(image,WHITE); /* white is background */ - black_pen = gdImageColorAllocate(image,BLACK); /* load up black color */ - blue_pen = gdImageColorAllocate(image,BLUE); /* load up blue color */ - red_pen = gdImageColorAllocate(image,RED); /* load up red color */ - green_pen = gdImageColorAllocate(image,GREEN); /* load up green color */ - yellow_pen = gdImageColorAllocate(image,YELLOW); /* load up yellow color */ - purple_pen = gdImageColorAllocate(image,PURPLE); /* load up purple color */ - ltgrey_pen = gdImageColorAllocate(image,LTGREY); /* load up light grey color */ - grey_pen = gdImageColorAllocate(image,GREY); /* load up grey color */ - - if ( (white_background == -1) || (black_pen == -1) || - (red_pen == -1) || (blue_pen == -1) || (green_pen == -1) || - (purple_pen == -1) || (ltgrey_pen == -1) || (grey_pen == -1) ) { - if (IS_DEBUG) printf("problem allocating pen colors\n"); - return SCPE_MEM; - } - - CLRBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* we're in business */ - - update_pen(); /* routine to ensure pen is okay */ - - return SCPE_OK; -} - -/* pen updating routine, called at attach and whenever we reset the values */ - -void update_pen (void) -{ - int color; - int width; - - if (!IS_ONLINE(plot_unit)) return; /* only do this if attached */ - - /* pick up latest color as active pen */ - color = GET_COLOR; - switch (color) { - case PEN_BLACK: - plot_pcolor = black_pen; - break; - - case PEN_RED: - plot_pcolor = red_pen; - break; - - case PEN_BLUE: - plot_pcolor = blue_pen; - break; - - case PEN_GREEN: - plot_pcolor = green_pen; - break; - - case PEN_YELLOW: - plot_pcolor = yellow_pen; - break; - - case PEN_PURPLE: - plot_pcolor = purple_pen; - break; - - case PEN_LTGREY: - plot_pcolor = ltgrey_pen; - break; - - case PEN_GREY: - plot_pcolor = grey_pen; - break; - - default: - if (IS_DEBUG) printf("invalid pen color state\n"); - plot_pcolor = black_pen; - break; - } - - /* set up anti-aliasing for the line */ - gdImageSetAntiAliased(image, plot_pcolor); - - /* pick up latest width for pen */ - width = GET_WIDTH(); - switch (width) { - case PEN_SINGLE: - plot_pwidth = 1; - gdImageSetThickness(image, 1); - break; - - case PEN_TRIPLE: - plot_pwidth = 3; - gdImageSetThickness(image, 3); - break; - - case PEN_DOUBLE: - plot_pwidth = 2; - gdImageSetThickness(image, 2); - break; - - case PEN_QUAD: - plot_pwidth = 4; - gdImageSetThickness(image, 4); - break; - - default: - if (IS_DEBUG) printf("invalid pen width\n"); - plot_pwidth = 1; - gdImageSetThickness(image, 1); - break; - } - - /* now ensure the pen state is accurate */ - plot_pen = IS_PENDOWN ? PEN_DOWN : PEN_UP; - return; -} - -/* plot_detach - detach file from simulated plotter */ -static t_stat plot_detach (UNIT *uptr) -{ - char * buf; - int32 size; - FILE * fp; - int32 result; - - SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY); - - /* copy images to files, close files, set device to detached, free gd memory */ - - buf = gdImageGifPtr(image,&size); - if (! buf) { - if (IS_DEBUG) printf("failure creating GIF in-memory\n"); - return SCPE_MEM; - } - - fp = uptr->fileref; /* get file attached to unit */ - - if (! fseek(fp,0,SEEK_SET)) { /* first we reset to begin of file */ - if (IS_DEBUG) printf("wrote out GIF to file\n"); - result = fwrite(buf,1,size,fp); /* write out our image to the file */ - } - - gdFree(buf); /* free up the memory of GIF format */ - gdImageDestroy(image); /* free up the canvas memory */ - - if (result != size) { /* some problem writing it */ - if (IS_DEBUG) printf("error in write of image file\n"); - return SCPE_IOERR; - } - - return detach_unit(uptr); /* have simh close the file */ -} - -/* process_cmd - implement the drawing actions of the plotter */ - -static void process_cmd (void) -{ - int32 oldx, oldy; - - /* first see if we set any changes to pen or position, do an update */ - if (need_update) { - update_pen(); - need_update = 0; - } - - /* will move pen one step or flip pen up or down */ - oldx = plot_xpos; - oldy = plot_ypos; - - switch (plot_cmd) { - case 1: /* raise pen command */ - plot_pen = PEN_UP; - plot_unit->flags = plot_unit->flags & (~UNIT_PEN); - return; - break; - - case 2: /* +Y command */ - plot_ypos = plot_ypos + 1; - break; - - case 4: /* -Y command */ - plot_ypos = plot_ypos - 1; - break; - - case 8: /* -X command */ - plot_xpos = plot_xpos - 1; - break; - - case 10: /* -X +Y command */ - plot_xpos = plot_xpos - 1; - plot_ypos = plot_ypos + 1; - break; - - case 12: /* -X -Y command */ - plot_xpos = plot_xpos - 1; - plot_ypos = plot_ypos - 1; - break; - - case 16: /* +X command */ - plot_xpos = plot_xpos + 1; - break; - - case 18: /* +X +Y command */ - plot_xpos = plot_xpos + 1; - plot_ypos = plot_ypos + 1; - break; - - case 20: /* +X -Y pen command */ - plot_xpos = plot_xpos + 1; - plot_ypos = plot_ypos - 1; - break; - - case 32: /* lower pen command */ - plot_pen = PEN_DOWN; - plot_unit->flags = plot_unit->flags | UNIT_PEN; - return; - break; - - default: - if (IS_DEBUG) printf("invalid plotter command\n"); - return; - break; - } - - /* check to see if carriage has moved off any edge */ - if ((plot_xpos > (plot_xmax+1)) || (plot_ypos > (plot_ymax+1)) || - (plot_xpos < 0) || (plot_ypos < 0)) { - /* if so, ignore as 1627 has no way of signalling error */ - if (IS_DEBUG) printf( - "attempted to move carriage off paper edge %d %d for command %d\n", - plot_xpos,plot_ypos,plot_cmd); - return; - } - - /* only draw a line if the pen was down during the movement command */ - if (plot_pen) { - gdImageLine(image, plot_ymax-plot_ypos, plot_xmax-plot_xpos, plot_ymax-oldy, plot_xmax-oldx, gdAntiAliased); - /* semantics are 0,0 point is lower right */ - } - - return; -} - -/* plot_set_length - validate and store the length of the paper */ - -static t_stat plot_set_length (UNIT *uptr, int32 set, char *ptr, void *desc) -{ - char *cptr; - int32 val; - -#define LONGEST_ROLL 1440000 /* longest is 120', 14400", 1,440,000 .01"s */ - - val = strtotv (ptr, &cptr, (uint32) 10); /* sim routine to get value */ - if ((val < 1) | (val >= LONGEST_ROLL)) { /* check valid range */ - if (IS_DEBUG) printf("setting paper more than 120' or less than 1 inch\n"); - return SCPE_ARG; - } - - /* origin zero drawing, reduce by 1 but show command will fudge by adding it back */ - *((int32 *)((REG *) desc)->loc) = val - 1; - - return SCPE_OK; -} - -/* plot_set_pos - validate and store the new position of the carriage */ - -static t_stat plot_set_pos (UNIT *uptr, int32 set, char *ptr, void *desc) -{ - char *cptr; - int32 val; - int32 max; - - max = (set == 1) ? plot_ymax : plot_xmax; - val = strtotv (ptr, &cptr, (uint32) 10); - if ((val < 0) | (val > max)) { - if (IS_DEBUG) printf("error moving carriage off paper edge\n"); - return SCPE_ARG; - } - - *((int32 *)((REG *) desc)->loc) = val; - - return SCPE_OK; -} - -/* routine to display the paper length and carriage position - * cannot use regular simh routine because it prints values twice, - * once for device and once for unit - */ - -static t_stat plot_show_vals (FILE *fp, UNIT *uptr, int32 val, void *descrip) -{ - fprintf(fp, "length=%d, Xpos=%d, Ypos=%d",plot_xmax+1, plot_xpos,plot_ypos); - return SCPE_OK; -} - -/* routine to add a terminating NL character when 'show plot length' - * or equivalent for xpos or ypos is issued, as simh will not append for us */ - -static t_stat plot_show_nl(FILE *fp, UNIT *uptr, int32 val, void *descrip) -{ - int32 disp; - char *label; - - disp = (val == 2) ? plot_xmax + 1 : ((val == 1) ? plot_ypos : plot_xpos); - label = (val == 2) ? "length=" : ((val == 1) ? "Ypos=" : "Xpos="); - - fprintf(fp, "%s%d\n", label, disp); - return SCPE_OK; -} - -/* plot_validate_change - force the update_pen routine to be called after user changes pen setting */ - -static t_stat plot_validate_change (UNIT *uptr, int32 set, char *ptr, void *desc) -{ - need_update = 1; - return SCPE_OK; -} - -#endif /* ENABLE_PLOT_SUPPORT */ diff --git a/Ibm1130/ibm1130_prt.c b/Ibm1130/ibm1130_prt.c deleted file mode 100644 index 90103b8f..00000000 --- a/Ibm1130/ibm1130_prt.c +++ /dev/null @@ -1,819 +0,0 @@ -/* ibm1130_prt.c: IBM 1130 line printer emulation - - Based on the SIMH simulator package written by Robert M Supnik - - Brian Knittel - Revision History - - 2006.12.06 - Moved CGI stuff out of this routine into cgi1130 main() module. - - 2006.07.06 - Made 1403 printer 132 columns wide, was 120 previously - - 2006.01.03 - Fixed bug in prt_attach, found and fixed by Carl Claunch. Detach followed - by reattach of 1403-mode printer left device permanently not-ready. - - 2004.11.08 - HACK for demo mode: in physical (-p) mode, multiple consecutive formfeeds are suppressed. - This lets us do a formfeed at the end of a job to kick the last page out - without getting another blank page at the beginning of the next job. - - 2003.12.02 - Added -p option for physical line printer output (flushes - output buffer after each line). When using a physical printer on - Windows, be sure to set printer to "send output directly to printer" - to disable spooling, otherwise nothing appears until printer is - detatched. - - 2003.11.25 - Changed magic filename for standard output to "(stdout)". - - 2002.09.13 - Added 1403 support. New file, taken from part of ibm1130_stddev.c - - Note: The 1403 is much faster, even in emulation, because it takes much - less CPU power to run it. DMS doesn't use the WAIT command when waiting for - printer operations to complete, so it ends up burning LOTS of cpu cycles. - The 1403 printer doesn't require as many. HOWEVER: DMS must be loaded for the 1403, - and Fortran IOCS control cards must specify it. - - The 1132 is still the default printer. - - As written, we can't have two printers. - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#include "ibm1130_defs.h" -#include /* needed for atexit, for cgi mode */ - -/*************************************************************************************** - * 1132 PRINTER - ***************************************************************************************/ - -#define PRT1132_DSW_READ_EMITTER_RESPONSE 0x8000 -#define PRT1132_DSW_SKIP_RESPONSE 0x4000 -#define PRT1132_DSW_SPACE_RESPONSE 0x2000 -#define PRT1132_DSW_CARRIAGE_BUSY 0x1000 -#define PRT1132_DSW_PRINT_SCAN_CHECK 0x0800 -#define PRT1132_DSW_NOT_READY 0x0400 -#define PRT1132_DSW_PRINTER_BUSY 0x0200 - -#define PRT1132_DSW_CHANNEL_MASK 0x00FF /* 1132 printer DSW bits */ -#define PRT1132_DSW_CHANNEL_1 0x0080 -#define PRT1132_DSW_CHANNEL_2 0x0040 -#define PRT1132_DSW_CHANNEL_3 0x0020 -#define PRT1132_DSW_CHANNEL_4 0x0010 -#define PRT1132_DSW_CHANNEL_5 0x0008 -#define PRT1132_DSW_CHANNEL_6 0x0004 -#define PRT1132_DSW_CHANNEL_9 0x0002 -#define PRT1132_DSW_CHANNEL_12 0x0001 - -#define PRT1403_DSW_PARITY_CHECK 0x8000 /* 1403 printer DSW bits */ -#define PRT1403_DSW_TRANSFER_COMPLETE 0x4000 -#define PRT1403_DSW_PRINT_COMPLETE 0x2000 -#define PRT1403_DSW_CARRIAGE_COMPLETE 0x1000 -#define PRT1403_DSW_RING_CHECK 0x0400 -#define PRT1403_DSW_SYNC_CHECK 0x0200 -#define PRT1403_DSW_CH9 0x0010 -#define PRT1403_DSW_CH12 0x0008 -#define PRT1403_DSW_CARRIAGE_BUSY 0x0004 -#define PRT1403_DSW_PRINTER_BUSY 0x0002 -#define PRT1403_DSW_NOT_READY 0x0001 - -#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) - -static t_stat prt1132_svc(UNIT *uptr); -static t_stat prt1403_svc(UNIT *uptr); -static t_stat prt_svc (UNIT *uptr); -static t_stat prt_reset (DEVICE *dptr); -static t_stat prt_attach (UNIT *uptr, char *cptr); -static t_stat prt_detach (UNIT *uptr); - -static int16 PRT_DSW = 0; /* device status word */ -static int32 prt_swait = 500; /* line skip wait */ -static int32 prt_cwait = 1250; /* character rotation wait */ -static int32 prt_fwait = 100; /* fast wait, for 1403 operations */ -static int32 prt_twait = 50; /* transfer wait, for 1403 operations */ -#define SKIPTARGET (uptr->u4) /* target for skip operation */ - -static t_bool formfed = FALSE; /* last line printed was a formfeed */ - -#define UNIT_V_FORMCHECK (UNIT_V_UF + 0) /* out of paper error */ -#define UNIT_V_DATACHECK (UNIT_V_UF + 1) /* printer overrun error */ -#define UNIT_V_SKIPPING (UNIT_V_UF + 2) /* printer skipping */ -#define UNIT_V_SPACING (UNIT_V_UF + 3) /* printer is spacing */ -#define UNIT_V_PRINTING (UNIT_V_UF + 4) /* printer printing */ -#define UNIT_V_TRANSFERRING (UNIT_V_UF + 5) /* unit is transferring print buffer (1403 only) */ -#define UNIT_V_1403 (UNIT_V_UF + 6) /* printer model is 1403 rather than 1132 */ -#define UNIT_V_PARITYCHECK (UNIT_V_UF + 7) /* error flags for 1403 */ -#define UNIT_V_RINGCHECK (UNIT_V_UF + 8) -#define UNIT_V_SYNCCHECK (UNIT_V_UF + 9) -#define UNIT_V_PHYSICAL_PTR (UNIT_V_UF + 10) /* this appears in ibm1130_gui as well */ - -#define UNIT_FORMCHECK (1u << UNIT_V_FORMCHECK) -#define UNIT_DATACHECK (1u << UNIT_V_DATACHECK) -#define UNIT_SKIPPING (1u << UNIT_V_SKIPPING) -#define UNIT_SPACING (1u << UNIT_V_SPACING) -#define UNIT_PRINTING (1u << UNIT_V_PRINTING) -#define UNIT_TRANSFERRING (1u << UNIT_V_TRANSFERRING) -#define UNIT_1403 (1u << UNIT_V_1403) -#define UNIT_PARITYCHECK (1u << UNIT_V_PARITYCHECK) -#define UNIT_RINGCHECK (1u << UNIT_V_RINGCHECK) -#define UNIT_SYNCCHECK (1u << UNIT_V_SYNCCHECK) -#define UNIT_PHYSICAL_PTR (1u << UNIT_V_PHYSICAL_PTR) - -UNIT prt_unit[] = { - { UDATA (&prt_svc, UNIT_ATTABLE, 0) }, -}; - -#define IS_1403(uptr) (uptr->flags & UNIT_1403) /* model test */ -#define IS_1132(uptr) ((uptr->flags & UNIT_1403) == 0) /* model test */ -#define IS_PHYSICAL(uptr) (uptr->flags & UNIT_PHYSICAL_PTR) - -/* Parameter in the unit descriptor (1132 printer) */ - -#define CMD_NONE 0 -#define CMD_SPACE 1 -#define CMD_SKIP 2 -#define CMD_PRINT 3 - -REG prt_reg[] = { - { HRDATA (PRTDSW, PRT_DSW, 16) }, /* device status word */ - { DRDATA (STIME, prt_swait, 24), PV_LEFT }, /* line skip wait */ - { DRDATA (CTIME, prt_cwait, 24), PV_LEFT }, /* character rotation wait */ - { DRDATA (FTIME, prt_fwait, 24), PV_LEFT }, /* 1403 fast wait */ - { DRDATA (TTIME, prt_twait, 24), PV_LEFT }, /* 1403 transfer wait */ - { NULL } }; - -MTAB prt_mod[] = { - { UNIT_1403, 0, "1132", "1132", NULL }, /* model option */ - { UNIT_1403, UNIT_1403, "1403", "1403", NULL }, - { 0 } }; - -DEVICE prt_dev = { - "PRT", prt_unit, prt_reg, prt_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, &prt_reset, - NULL, prt_attach, prt_detach}; - -#define MAX_COLUMNS 120 -#define MAX_OVPRINT 20 -#define PRT1132_COLUMNS 120 -#define PRT1403_COLUMNS 120 /* the 1130's version of the 1403 printed in 120 columns only (see Functional Characteristics) */ - -static char prtbuf[MAX_COLUMNS*MAX_OVPRINT]; -static int nprint[MAX_COLUMNS], ncol[MAX_OVPRINT], maxnp; -static int prt_nchar, prt_row; /* current printwheel position, current page row */ -static int prt_nnl; /* number of queued newlines */ - -#define CC_CHANNEL_1 0x0800 /* carriage control tape punch values */ -#define CC_CHANNEL_2 0x0400 -#define CC_CHANNEL_3 0x0200 -#define CC_CHANNEL_4 0x0100 -#define CC_CHANNEL_5 0x0080 -#define CC_CHANNEL_6 0x0040 /* 7, 8, 10 and 11 are not used on 1132 printer */ -#define CC_CHANNEL_7 0x0020 -#define CC_CHANNEL_8 0x0010 -#define CC_CHANNEL_9 0x0008 -#define CC_CHANNEL_10 0x0004 -#define CC_CHANNEL_11 0x0002 -#define CC_CHANNEL_12 0x0001 - -#define CC_1403_BITS 0x0FFF /* all bits for 1403, most for 1132 */ -#define CC_1132_BITS (CC_1403_BITS & ~(CC_CHANNEL_7|CC_CHANNEL_8|CC_CHANNEL_10|CC_CHANNEL_11)) - -#define PRT_PAGELENGTH 66 - -static int cctape[PRT_PAGELENGTH]; /* standard carriage control tape */ - -static struct tag_ccpunches { /* list of rows and punches on tape */ - int row, channels; -} -ccpunches[] = { - 2, CC_CHANNEL_1, /* channel 1 = top of form */ - 62, CC_CHANNEL_12 /* channel 12 = bottom of form */ -}, -cccgi[] = { - 2, CC_CHANNEL_1 /* channel 1 = top of form; no bottom of form */ -}; - -#include "ibm1130_prtwheel.h" - -extern int32 sim_switches; - -/* cc_format_1132 and cc_format_1403 - turn cctape bits into proper format for DSW or status read */ - -static int cc_format_1132 (int bits) -{ - return ((bits & (CC_CHANNEL_1|CC_CHANNEL_2|CC_CHANNEL_3|CC_CHANNEL_4|CC_CHANNEL_5|CC_CHANNEL_6)) >> 4) | - ((bits & CC_CHANNEL_9) >> 3) | - (bits & CC_CHANNEL_12); -} - -#define cc_format_1403(bits) (bits) - -/* reset_prt_line - clear the print line following paper advancement */ - -static void reset_prt_line (void) -{ - memset(nprint, 0, sizeof(nprint)); - memset(ncol, 0, sizeof(ncol)); - maxnp = 0; -} - -/* save_1132_prt_line - fire hammers for character 'ch' */ - -static t_bool save_1132_prt_line (int ch) -{ - int i, r, addr = 32; - int32 mask = 0, wd = 0; - - for (i = 0; i < PRT1132_COLUMNS; i++) { - if (mask == 0) { /* fetch next word from memory */ - mask = 0x8000; - wd = M[addr++]; - } - - if (wd & mask) { /* hammer is to fire in this column */ - if ((r = nprint[i]) < MAX_OVPRINT) { - if (ncol[r] <= i) { /* we haven't moved this far yet */ - if (ncol[r] == 0) /* first char in this row? */ - memset(prtbuf+r*MAX_COLUMNS, ' ', PRT1132_COLUMNS); /* blank out the new row */ - ncol[r] = i+1; /* remember new row length */ - } - prtbuf[r*MAX_COLUMNS + i] = (char) ch; /* save the character */ - - nprint[i]++; /* remember max overprintings for this column */ - maxnp = MAX(maxnp, nprint[i]); - } - } - - mask >>= 1; /* prepare to examine next bit */ - } - - return wd & 1; /* return TRUE if the last word has lsb set, which means all bits had been set */ -} - -/* write_line - write collected line to output file. No need to trim spaces as the hammers - * are never fired for them, so ncol[r] is the last printed position on each line. - */ - -static void newpage (FILE *fd, t_bool physical_printer) -{ - if (cgi) - fputs("
\n", fd); - else if (! formfed) { - putc('\f', fd); - if (physical_printer) { - fflush(fd); /* send the ff out to the printer immediately */ - formfed = TRUE; /* hack: inhibit consecutive ff's */ - } - } -} - -static void flush_prt_line (FILE *fd, int spacemode, t_bool physical_printer) -{ - int r; - - if (! (spacemode || maxnp)) /* nothing to do */ - return; - - prt_row = (prt_row+1) % PRT_PAGELENGTH; /* NEXT line */ - - if (spacemode && ! maxnp) { /* spacing only */ - if (prt_row == 0 && prt_nnl) { -#ifdef _WIN32 - if (! cgi) - putc('\r', fd); /* DOS/Windows: end with cr/lf */ -#endif - putc('\n', fd); /* otherwise end with lf */ - if (spacemode & UNIT_SKIPPING) /* add formfeed if we crossed page boundary while skipping */ - newpage(fd, physical_printer); - - prt_nnl = 0; - } - else { - prt_nnl++; - formfed = FALSE; - } - - prt_unit->pos++; /* note something written */ - return; - } - - if (prt_nnl) { /* there are queued newlines */ - while (prt_nnl > 0) { /* spit out queued newlines */ -#ifdef _WIN32 - if (! cgi) - putc('\r', fd); /* DOS/Windows: end with cr/lf */ -#endif - putc('\n', fd); /* otherwise end with lf */ - prt_nnl--; - } - } - - for (r = 0; r < maxnp; r++) { - if (r > 0) - putc('\r', fd); /* carriage return between overprinted lines */ - - fxwrite(&prtbuf[r*MAX_COLUMNS], 1, ncol[r], fd); - } - - reset_prt_line(); - - prt_unit->pos++; /* note something written */ - prt_nnl++; /* queue a newline */ - - if (physical_printer) /* if physical printer, send buffered output to device */ - fflush(fd); - - formfed = FALSE; /* note that something is now on the page */ -} - -/* 1132 printer commands */ - -#define PRT_CMD_START_PRINTER 0x0080 -#define PRT_CMD_STOP_PRINTER 0x0040 -#define PRT_CMD_START_CARRIAGE 0x0004 -#define PRT_CMD_STOP_CARRIAGE 0x0002 -#define PRT_CMD_SPACE 0x0001 - -#define PRT_CMD_MASK 0x00C7 - -extern char * saywhere (int addr); - -static void mytrace (int start, char *what) -{ - char *where; - - if ((where = saywhere(prev_IAR)) == NULL) where = "?"; - trace_io("%s %s at %04x: %s\n", start ? "start" : "stop", what, prev_IAR, where); -} - -/* xio_1132_printer - XIO command interpreter for the 1132 printer */ - -void xio_1132_printer (int32 iocc_addr, int32 func, int32 modify) -{ - char msg[80]; - UNIT *uptr = &prt_unit[0]; - - switch (func) { - case XIO_READ: - M[iocc_addr & mem_mask] = codewheel1132[prt_nchar].ebcdic << 8; - - if ((uptr->flags & UNIT_PRINTING) == 0) /* if we're not printing, advance this after every test */ - prt_nchar = (prt_nchar + 1) % WHEELCHARS_1132; - break; - - case XIO_SENSE_DEV: - ACC = PRT_DSW; - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(PRT_DSW, PRT1132_DSW_READ_EMITTER_RESPONSE | PRT1132_DSW_SKIP_RESPONSE | PRT1132_DSW_SPACE_RESPONSE); - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - } - break; - - case XIO_CONTROL: - if (modify & PRT_CMD_START_PRINTER) { - SETBIT(uptr->flags, UNIT_PRINTING); -/* mytrace(1, "printing"); */ - } - - if (modify & PRT_CMD_STOP_PRINTER) { - CLRBIT(uptr->flags, UNIT_PRINTING); -/* mytrace(0, "printing"); */ - } - - if (modify & PRT_CMD_START_CARRIAGE) { - SETBIT(uptr->flags, UNIT_SKIPPING); -/* mytrace(1, "skipping"); */ - } - - if (modify & PRT_CMD_STOP_CARRIAGE) { - CLRBIT(uptr->flags, UNIT_SKIPPING); -/* mytrace(0, "skipping"); */ - } - - if (modify & PRT_CMD_SPACE) { - SETBIT(uptr->flags, UNIT_SPACING); -/* mytrace(1, "space"); */ - } - - sim_cancel(uptr); - if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING)) { /* busy bits = doing something */ - SETBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - sim_activate(uptr, prt_cwait); - } - else - CLRBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - - if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING)) - SETBIT(PRT_DSW, PRT1132_DSW_CARRIAGE_BUSY); - else - CLRBIT(PRT_DSW, PRT1132_DSW_CARRIAGE_BUSY); - - if ((uptr->flags & (UNIT_SKIPPING|UNIT_SPACING)) == (UNIT_SKIPPING|UNIT_SPACING)) { - sprintf(msg, "1132 printer skip and space at same time?"); - xio_error(msg); - } - break; - - default: - sprintf(msg, "Invalid 1132 printer XIO function %x", func); - xio_error(msg); - } -} - -#define SET_ACTION(u,a) {(u)->flags &= ~(UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING|UNIT_TRANSFERRING); (u)->flags |= a;} - -static t_stat prt_svc (UNIT *uptr) -{ - return IS_1403(uptr) ? prt1403_svc(uptr) : prt1132_svc(uptr); -} - -/* prt1132_svc - emulated timeout for 1132 operation */ - -static t_stat prt1132_svc (UNIT *uptr) -{ - if (PRT_DSW & PRT1132_DSW_NOT_READY) { /* cancel operation if printer went offline */ - SETBIT(uptr->flags, UNIT_FORMCHECK); - SET_ACTION(uptr, 0); - forms_check(TRUE); /* and turn on forms check lamp */ - return SCPE_OK; - } - - if (uptr->flags & UNIT_SPACING) { - flush_prt_line(uptr->fileref, UNIT_SPACING, IS_PHYSICAL(uptr)); - - CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK|PRT1132_DSW_PRINTER_BUSY|PRT1132_DSW_CARRIAGE_BUSY); - SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]) | PRT1132_DSW_SPACE_RESPONSE); - SETBIT(ILSW[1], ILSW_1_1132_PRINTER); - CLRBIT(uptr->flags, UNIT_SPACING); /* done with this */ - calc_ints(); - } - - if (uptr->flags & UNIT_SKIPPING) { - do { - flush_prt_line(uptr->fileref, UNIT_SKIPPING, IS_PHYSICAL(uptr)); - CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK); - SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row])); - } while ((cctape[prt_row] & CC_1132_BITS) == 0); /* slew directly to a cc tape punch */ - - SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]) | PRT1132_DSW_SKIP_RESPONSE); - SETBIT(ILSW[1], ILSW_1_1132_PRINTER); - calc_ints(); - } - - if (uptr->flags & UNIT_PRINTING) { - if (! save_1132_prt_line(codewheel1132[prt_nchar].ascii)) { /* save previous printed line */ - SETBIT(uptr->flags, UNIT_DATACHECK); /* buffer wasn't set in time */ - SET_ACTION(uptr, 0); - print_check(TRUE); /* and turn on forms check lamp */ - return SCPE_OK; - } - - prt_nchar = (prt_nchar + 1) % WHEELCHARS_1132; /* advance print drum */ - - SETBIT(PRT_DSW, PRT1132_DSW_READ_EMITTER_RESPONSE); /* issue interrupt to tell printer to set buffer */ - SETBIT(ILSW[1], ILSW_1_1132_PRINTER); /* we'll save the printed stuff just before next emitter response (later than on real 1130) */ - calc_ints(); - } - - if (uptr->flags & (UNIT_SPACING|UNIT_SKIPPING|UNIT_PRINTING)) { /* still doing something */ - SETBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - sim_activate(uptr, prt_cwait); - } - else - CLRBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - - return SCPE_OK; -} - -void save_1403_prt_line (int32 addr) -{ - int i, j, r, ch, even = TRUE; - unsigned char ebcdic; - int32 wd; - - for (i = 0; i < PRT1403_COLUMNS; i++) { - if (even) { /* fetch next word from memory */ - wd = M[addr++]; - ebcdic = (unsigned char) ((wd >> 8) & 0x7F); - even = FALSE; - } - else { - ebcdic = (unsigned char) (wd & 0x7F); /* use low byte of previously fetched word */ - even = TRUE; - } - - ch = ' '; /* translate ebcdic to ascii. Don't bother checking for parity errors */ - for (j = 0; j < WHEELCHARS_1403; j++) { - if (codewheel1403[j].ebcdic == ebcdic) { - ch = codewheel1403[j].ascii; - break; - } - } - - if (ch > ' ') { - if ((r = nprint[i]) < MAX_OVPRINT) { - if (ncol[r] <= i) { /* we haven't moved this far yet */ - if (ncol[r] == 0) /* first char in this row? */ - memset(prtbuf+r*MAX_COLUMNS, ' ', PRT1403_COLUMNS); /* blank out the new row */ - ncol[r] = i+1; /* remember new row length */ - } - prtbuf[r*MAX_COLUMNS + i] = (char) ch; /* save the character */ - - nprint[i]++; /* remember max overprintings for this column */ - maxnp = MAX(maxnp, nprint[i]); - } - } - } -} - -void xio_1403_printer (int32 iocc_addr, int32 func, int32 modify) -{ - UNIT *uptr = &prt_unit[0]; - - switch (func) { - case XIO_INITW: /* print a line */ - save_1403_prt_line(iocc_addr); /* put formatted line into our print buffer */ - - SETBIT(uptr->flags, UNIT_TRANSFERRING); /* schedule transfer complete interrupt */ - SETBIT(PRT_DSW, PRT1403_DSW_PRINTER_BUSY); - sim_activate(uptr, prt_twait); - break; - - case XIO_CONTROL: /* initiate single space */ - if (uptr->flags & UNIT_SKIPPING) { - xio_error("1403 printer skip and space at same time?"); - } - else { - SETBIT(uptr->flags, UNIT_SPACING); - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - sim_activate(uptr, prt_fwait); - } - break; - - case XIO_WRITE: /* initiate skip */ - if (uptr->flags & UNIT_SPACING) { - xio_error("1403 printer skip and space at same time?"); - } - else { - SETBIT(uptr->flags, UNIT_SKIPPING); - SKIPTARGET = ReadW(iocc_addr) & CC_1403_BITS; /* get CC bits that we're to match */ - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - sim_activate(uptr, prt_fwait); - } - break; - - case XIO_SENSE_DEV: /* get device status word */ - ACC = PRT_DSW; - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(PRT_DSW, PRT1403_DSW_PARITY_CHECK | PRT1403_DSW_TRANSFER_COMPLETE | - PRT1403_DSW_PRINT_COMPLETE | PRT1403_DSW_CARRIAGE_COMPLETE | - PRT1403_DSW_RING_CHECK | PRT1403_DSW_SYNC_CHECK); - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - break; - } -} - -static t_stat prt1403_svc(UNIT *uptr) -{ - if (PRT_DSW & PRT1403_DSW_NOT_READY) { /* cancel operation if printer went offline */ - SET_ACTION(uptr, 0); - forms_check(TRUE); /* and turn on forms check lamp */ - } - else if (uptr->flags & UNIT_TRANSFERRING) { /* end of transfer */ - CLRBIT(uptr->flags, UNIT_TRANSFERRING); - SETBIT(uptr->flags, UNIT_PRINTING); /* schedule "print complete" */ - - SETBIT(PRT_DSW, PRT1403_DSW_TRANSFER_COMPLETE); /* issue transfer complete interrupt */ - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - else if (uptr->flags & UNIT_PRINTING) { - CLRBIT(uptr->flags, UNIT_PRINTING); - CLRBIT(PRT_DSW, PRT1403_DSW_PRINTER_BUSY); - - SETBIT(PRT_DSW, PRT1403_DSW_PRINT_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); /* issue print complete interrupt */ - } - else if (uptr->flags & UNIT_SKIPPING) { - do { /* find line with exact match of tape punches */ - flush_prt_line(uptr->fileref, UNIT_SKIPPING, IS_PHYSICAL(uptr)); - } while (cctape[prt_row] != SKIPTARGET); /* slew directly to requested cc tape punch */ - - CLRBIT(uptr->flags, UNIT_SKIPPING); /* done with this */ - CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - else if (uptr->flags & UNIT_SPACING) { - flush_prt_line(uptr->fileref, UNIT_SPACING, IS_PHYSICAL(uptr)); - - CLRBIT(uptr->flags, UNIT_SPACING); /* done with this */ - CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - - if (uptr->flags & (UNIT_PRINTING|UNIT_SKIPPING|UNIT_SPACING|UNIT_TRANSFERRING)) - sim_activate(uptr, prt_fwait); - - CLRBIT(PRT_DSW, PRT1403_DSW_CH9|PRT1403_DSW_CH12); /* set the two CC bits in the DSW */ - if (cctape[prt_row] & CC_CHANNEL_9) - SETBIT(PRT_DSW, PRT1403_DSW_CH9); - if (cctape[prt_row] & CC_CHANNEL_12) - SETBIT(PRT_DSW, PRT1403_DSW_CH12); - - calc_ints(); - return SCPE_OK; -} - -/* delete_cmd - SCP command to delete a file */ - -static t_stat delete_cmd (int32 flag, char *cptr) -{ - char gbuf[CBUFSIZE]; - int status; - - cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ - if (*gbuf == 0) return SCPE_2FARG; - if (*cptr != 0) return SCPE_2MARG; /* now eol? */ - - status = remove(gbuf); /* delete the file */ - - if (status != 0 && errno != ENOENT) /* print message if failed and file exists */ - perror(gbuf); - - return SCPE_OK; -} - -/* prt_reset - reset emulated printer */ - -static t_stat prt_reset (DEVICE *dptr) -{ - UNIT *uptr = &prt_unit[0]; - int i; - -/* add a DELETE filename command so we can be sure to have clean listings */ - register_cmd("DELETE", &delete_cmd, 0, "del{ete} filename remove file\n"); - - sim_cancel(uptr); - - memset(cctape, 0, sizeof(cctape)); /* copy punch list into carriage control tape image */ - - if (cgi) { - for (i = 0; i < (sizeof(cccgi)/sizeof(cccgi[0])); i++) - cctape[cccgi[i].row-1] |= cccgi[i].channels; - } - else - for (i = 0; i < (sizeof(ccpunches)/sizeof(ccpunches[0])); i++) - cctape[ccpunches[i].row-1] |= ccpunches[i].channels; - - prt_nchar = 0; - prt_row = 0; - prt_nnl = 0; - - CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK|UNIT_PRINTING|UNIT_SPACING|UNIT_SKIPPING| - UNIT_TRANSFERRING|UNIT_PARITYCHECK|UNIT_RINGCHECK|UNIT_SYNCCHECK); - - if (IS_1132(uptr)) { - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - PRT_DSW = cc_format_1132(cctape[prt_row]); - if (! IS_ONLINE(uptr)) - SETBIT(PRT_DSW, PRT1132_DSW_NOT_READY); - } - else { - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - PRT_DSW = 0; - if (cctape[prt_row] & CC_CHANNEL_9) - SETBIT(PRT_DSW, PRT1403_DSW_CH9); - if (cctape[prt_row] & CC_CHANNEL_12) - SETBIT(PRT_DSW, PRT1403_DSW_CH12); - if (! IS_ONLINE(uptr)) - SETBIT(PRT_DSW, PRT1403_DSW_NOT_READY); - } - - SET_ACTION(uptr, 0); - calc_ints(); - reset_prt_line(); - - forms_check(FALSE); - return SCPE_OK; -} - -static t_stat prt_attach (UNIT *uptr, char *cptr) -{ - t_stat rval; - /* assume failure */ - SETBIT(PRT_DSW, IS_1132(uptr) ? PRT1132_DSW_NOT_READY : PRT1403_DSW_NOT_READY); - formfed = FALSE; - - if (uptr->flags & UNIT_ATT) { - if ((rval = prt_detach(uptr)) != SCPE_OK) { - return rval; - } - } - - if (sim_switches & SWMASK('P')) /* set physical (unbuffered) printer flag */ - SETBIT(uptr->flags, UNIT_PHYSICAL_PTR); - else - CLRBIT(uptr->flags, UNIT_PHYSICAL_PTR); - - sim_cancel(uptr); - - if (strcmp(cptr, "(stdout)") == 0) { /* connect printer to stdout */ - if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ - uptr->filename = calloc(CBUFSIZE, sizeof(char)); - strcpy(uptr->filename, "(stdout)"); - uptr->fileref = stdout; - SETBIT(uptr->flags, UNIT_ATT); - uptr->pos = 0; - } - else { - if ((rval = attach_unit(uptr, quotefix(cptr))) != SCPE_OK) - return rval; - } - - fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */ - uptr->pos = ftell(uptr->fileref); - - if (IS_1132(uptr)) { - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK); - } - else { - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - CLRBIT(uptr->flags, UNIT_PARITYCHECK|UNIT_RINGCHECK|UNIT_SYNCCHECK); - } - - SET_ACTION(uptr, 0); - calc_ints(); - - prt_nchar = 0; - prt_nnl = 0; - prt_row = 0; - reset_prt_line(); - - if (IS_1132(uptr)) { - PRT_DSW = (PRT_DSW & ~PRT1132_DSW_CHANNEL_MASK) | cc_format_1132(cctape[prt_row]); - - if (IS_ONLINE(uptr)) - CLRBIT(PRT_DSW, PRT1132_DSW_NOT_READY); - } - else { - CLRBIT(PRT_DSW, PRT1403_DSW_CH9 | PRT1403_DSW_CH12); - if (cctape[prt_row] & CC_CHANNEL_9) - SETBIT(PRT_DSW, PRT1403_DSW_CH9); - if (cctape[prt_row] & CC_CHANNEL_12) - SETBIT(PRT_DSW, PRT1403_DSW_CH12); - - if (IS_ONLINE(uptr)) - CLRBIT(PRT_DSW, PRT1403_DSW_NOT_READY); /* fixed by Carl Claunch */ - } - - forms_check(FALSE); - - return SCPE_OK; -} - -static t_stat prt_detach (UNIT *uptr) -{ - t_stat rval; - - if (uptr->flags & UNIT_ATT) - flush_prt_line(uptr->fileref, TRUE, TRUE); - - if (uptr->fileref == stdout) { - CLRBIT(uptr->flags, UNIT_ATT); - free(uptr->filename); - uptr->filename = NULL; - } - else if ((rval = detach_unit(uptr)) != SCPE_OK) - return rval; - - sim_cancel(uptr); - - if (IS_1132(uptr)) { - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK); - SETBIT(PRT_DSW, PRT1132_DSW_NOT_READY); - } - else { - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - SETBIT(PRT_DSW, PRT1403_DSW_NOT_READY); - } - SET_ACTION(uptr, 0); - - calc_ints(); - - forms_check(FALSE); - return SCPE_OK; -} - diff --git a/Ibm1130/ibm1130_prtwheel.h b/Ibm1130/ibm1130_prtwheel.h deleted file mode 100644 index c39c1e59..00000000 --- a/Ibm1130/ibm1130_prtwheel.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -struct tag_codewheel { - unsigned char ascii; - unsigned char ebcdic; -}; - -static struct tag_codewheel codewheel1132[] = -{ /* characters and EBCDIC codes in printwheel order */ - 'A', 0xC1, - 'B', 0xC2, - 'C', 0xC3, - 'D', 0xC4, - 'F', 0xC6, - 'H', 0xC8, - 'I', 0xC9, - 'S', 0xE2, - 'T', 0xE3, - 'U', 0xE4, - 'V', 0xE5, - '1', 0xF1, - '2', 0xF2, - '3', 0xF3, - '4', 0xF4, - '5', 0xF5, - '6', 0xF6, - '7', 0xF7, - '8', 0xF8, - '9', 0xF9, - '0', 0xF0, - '=', 0x7E, - '$', 0x5B, - '.', 0x4B, - '\'', 0x7D, - ',', 0x6B, - ')', 0x5D, - '-', 0x60, - '(', 0x4D, - '+', 0x4E, - '/', 0x61, - '*', 0x5C, - '&', 0x50, - 'J', 0xD1, - 'K', 0xD2, - 'L', 0xD3, - 'M', 0xD4, - 'N', 0xD5, - 'O', 0xD6, - 'P', 0xD7, - 'Q', 0xD8, - 'R', 0xD9, - 'E', 0xC5, - 'G', 0xC7, - 'W', 0xE6, - 'X', 0xE7, - 'Y', 0xE8, - 'Z', 0xE9, -}; - -#define WHEELCHARS_1132 (sizeof(codewheel1132)/sizeof(codewheel1132[0])) - -static struct tag_codewheel codewheel1403[] = -{ - 'A', 0x64, - 'B', 0x25, - 'C', 0x26, - 'D', 0x67, - 'E', 0x68, - 'F', 0x29, - 'G', 0x2A, - 'H', 0x6B, - 'I', 0x2C, - 'J', 0x58, - 'K', 0x19, - 'L', 0x1A, - 'M', 0x5B, - 'N', 0x1C, - 'O', 0x5D, - 'P', 0x5E, - 'Q', 0x1F, - 'R', 0x20, - 'S', 0x0D, - 'T', 0x0E, - 'U', 0x4F, - 'V', 0x10, - 'W', 0x51, - 'X', 0x52, - 'Y', 0x13, - 'Z', 0x54, - '0', 0x49, - '1', 0x40, - '2', 0x01, - '3', 0x02, - '4', 0x43, - '5', 0x04, - '6', 0x45, - '7', 0x46, - '8', 0x07, - '9', 0x08, - ' ', 0x7F, - '.', 0x6E, - '(', 0x57, - '+', 0x6D, - '&', 0x15, - '$', 0x62, - '*', 0x23, - ')', 0x2F, - '-', 0x61, - '/', 0x4C, - ',', 0x16, - '\'', 0x0B, - '=', 0x4A, -}; - -#define WHEELCHARS_1403 (sizeof(codewheel1403)/sizeof(codewheel1403[0])) - - diff --git a/Ibm1130/ibm1130_ptrp.c b/Ibm1130/ibm1130_ptrp.c deleted file mode 100644 index c24a27d4..00000000 --- a/Ibm1130/ibm1130_ptrp.c +++ /dev/null @@ -1,309 +0,0 @@ -/* ibm1130_ptrp.c: IBM 1130 paper tape reader/punch emulation - - Based on the SIMH simulator package written by Robert M Supnik - - Brian Knittel - Revision History - - 2004.10.22 - Written. - - * (C) Copyright 2004, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#include "ibm1130_defs.h" - -/*************************************************************************************** - * 1134 Paper Tape Reader device PTR - * 1055 Paper Tape Punch device PTP (shares DSW with PTR) - ***************************************************************************************/ - -#define PTR1134_DSW_READER_RESPONSE 0x4000 -#define PTR1134_DSW_PUNCH_RESPONSE 0x1000 -#define PTR1134_DSW_READER_BUSY 0x0800 -#define PTR1134_DSW_READER_NOT_READY 0x0400 -#define PTR1134_DSW_PUNCH_BUSY 0x0200 -#define PTR1134_DSW_PUNCH_NOT_READY 0x0100 - -#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) - -static t_stat ptr_svc (UNIT *uptr); -static t_stat ptr_reset (DEVICE *dptr); -static t_stat ptr_attach (UNIT *uptr, char *cptr); -static t_stat ptr_detach (UNIT *uptr); -static t_stat ptr_boot (int32 unitno, DEVICE *dptr); -static t_stat ptp_svc (UNIT *uptr); -static t_stat ptp_reset (DEVICE *dptr); -static t_stat ptp_attach (UNIT *uptr, char *cptr); -static t_stat ptp_detach (UNIT *uptr); - -static int16 ptr_dsw = 0; /* device status word */ -static int32 ptr_wait = 1000; /* character read wait */ -static uint8 ptr_char = 0; /* last character read */ -static int32 ptp_wait = 1000; /* character punch wait */ - -UNIT ptr_unit[1] = { - { UDATA (&ptr_svc, UNIT_ATTABLE, 0) }, -}; - -REG ptr_reg[] = { - { HRDATA (DSW, ptr_dsw, 16) }, /* device status word */ - { DRDATA (WTIME, ptr_wait, 24), PV_LEFT }, /* character read wait */ - { DRDATA (LASTCHAR, ptr_char, 8), PV_LEFT }, /* last character read */ - { NULL } }; - -DEVICE ptr_dev = { - "PTR", ptr_unit, ptr_reg, NULL, - 1, 16, 16, 1, 16, 16, - NULL, NULL, ptr_reset, - ptr_boot, ptr_attach, ptr_detach}; - -UNIT ptp_unit[1] = { - { UDATA (&ptp_svc, UNIT_ATTABLE, 0) }, -}; - -REG ptp_reg[] = { - { HRDATA (DSW, ptr_dsw, 16) }, /* device status word (this is the same as the reader's!) */ - { DRDATA (WTIME, ptp_wait, 24), PV_LEFT }, /* character punch wait */ - { NULL } }; - -DEVICE ptp_dev = { - "PTP", ptp_unit, ptp_reg, NULL, - 1, 16, 16, 1, 16, 16, - NULL, NULL, ptp_reset, - NULL, ptp_attach, ptp_detach}; - -/* xio_1134_papertape - XIO command interpreter for the 1134 paper tape reader and 1055 paper tape punch */ - -void xio_1134_papertape (int32 iocc_addr, int32 iocc_func, int32 iocc_mod) -{ - char msg[80]; - - switch (iocc_func) { - case XIO_READ: /* read: return last character read */ - M[iocc_addr & mem_mask] = (uint16) (ptr_char << 8); - break; - - case XIO_WRITE: /* write: initiate punch operation */ - if ((ptr_dsw & PTR1134_DSW_PUNCH_NOT_READY) == 0 && IS_ONLINE(ptp_unit)) { - putc((M[iocc_addr & mem_mask] >> 8) & 0xFF, ptp_unit->fileref); - ptp_unit->pos++; - } - sim_activate(ptp_unit, ptp_wait); /* schedule interrupt */ - SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY | PTR1134_DSW_PUNCH_BUSY); - break; - - case XIO_SENSE_DEV: /* sense device status */ - ACC = ptr_dsw; - if (iocc_mod & 0x01) { /* reset interrupts */ - CLRBIT(ptr_dsw, PTR1134_DSW_READER_RESPONSE | PTR1134_DSW_PUNCH_RESPONSE); - CLRBIT(ILSW[4], ILSW_4_1134_TAPE); - } - break; - - case XIO_CONTROL: /* control: initiate character read */ - sim_activate(ptr_unit, ptr_wait); /* schedule interrupt */ - SETBIT(ptr_dsw, PTR1134_DSW_READER_BUSY | PTR1134_DSW_READER_NOT_READY); - break; - - default: - sprintf(msg, "Invalid 1134 reader/1055 punch XIO function %x", iocc_func); - xio_error(msg); - } -} - -/* ptr_svc - emulated timeout - 1134 read operation complete */ - -static t_stat ptr_svc (UNIT *uptr) -{ - CLRBIT(ptr_dsw, PTR1134_DSW_READER_BUSY); /* clear reader busy flag */ - SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* assume at end of file */ - - if (IS_ONLINE(uptr)) { /* fetch character from file */ - ptr_char = getc(uptr->fileref); - uptr->pos++; - - if (! feof(uptr->fileref)) /* there's more left */ - CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); - } - - SETBIT(ptr_dsw, PTR1134_DSW_READER_RESPONSE); /* indicate read complete */ - - SETBIT(ILSW[4], ILSW_4_1134_TAPE); /* initiate interrupt */ - calc_ints(); - - return SCPE_OK; -} - -/* ptp_svc - emulated timeout -- 1055 punch operation complete */ - -static t_stat ptp_svc (UNIT *uptr) -{ - CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_BUSY); /* clear punch busy flag */ - - if (IS_ONLINE(uptr)) /* update punch ready status */ - CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); - else - SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); - - SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_RESPONSE); /* indicate punch complete */ - - SETBIT(ILSW[4], ILSW_4_1134_TAPE); /* initiate interrupt */ - calc_ints(); - - return SCPE_OK; -} - -/* ptr_reset - reset emulated paper tape reader */ - -static t_stat ptr_reset (DEVICE *dptr) -{ - sim_cancel(ptr_unit); - - CLRBIT(ptr_dsw, PTR1134_DSW_READER_BUSY | PTR1134_DSW_READER_RESPONSE); - SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); - - if (IS_ONLINE(ptr_unit) && ! feof(ptr_unit->fileref)) - CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); - - if ((ptr_dsw & PTR1134_DSW_PUNCH_RESPONSE) == 0) { /* punch isn't interrupting either */ - CLRBIT(ILSW[4], ILSW_4_1134_TAPE); - calc_ints(); - } - - return SCPE_OK; -} - -/* ptp_reset - reset emulated paper tape punch */ - -static t_stat ptp_reset (DEVICE *dptr) -{ - sim_cancel(ptp_unit); - - CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_BUSY | PTR1134_DSW_PUNCH_RESPONSE); - SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); - - if (IS_ONLINE(ptp_unit)) - CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); - - if ((ptr_dsw & PTR1134_DSW_READER_RESPONSE) == 0) { /* reader isn't interrupting either */ - CLRBIT(ILSW[4], ILSW_4_1134_TAPE); - calc_ints(); - } - - return SCPE_OK; -} - -/* ptr_attach - attach file to simulated paper tape reader */ - -static t_stat ptr_attach (UNIT *uptr, char *cptr) -{ - t_stat rval; - - SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* assume failure */ - - if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) /* use standard attach */ - return rval; - - if ((ptr_dsw & PTR1134_DSW_READER_BUSY) == 0 && ! feof(uptr->fileref)) - CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* we're in business */ - - return SCPE_OK; -} - -/* ptr_attach - detach file from simulated paper tape reader */ - -static t_stat ptr_detach (UNIT *uptr) -{ - SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); - - return detach_unit(uptr); -} - -/* ptr_attach - perform paper tape initial program load */ - -static t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ - int ch, nch, val, addr; - t_bool leader = TRUE, start = FALSE; - t_stat rval; - - addr = 0; - nch = 0; - val = 0; - - for (;;) { - if ((ch = getc(ptr_unit->fileref)) == EOF) { - printf("EOF on paper tape without finding Channel 5 end-of-load mark\n"); - break; - } - - if (leader) { - if ((ch & 0x7F) == 0x7F) /* ignore leading rubouts or "delete" characters */ - continue; - - leader = FALSE; /* after first nonrubout, any punch in channel 5 terminates load */ - } - - /* this is untested -- not sure of actual byte ordering */ - - val = (val << 4) | (ch & 0x0F); /* get next nybble */ - - if (++nch == 4) { /* if we now have four nybbles, store the word */ - M[addr & mem_mask] = (uint16) val; - - addr++; /* prepare for next word */ - nch = 0; - val = 0; - } - - if (ch & 0x10) { /* channel 5 punch terminates load */ - start = TRUE; - break; - } - } - - if (! start) /* if we didn't get a valid load, report EOF error */ - return SCPE_EOF; - - if ((rval = reset_all(0)) != SCPE_OK) /* force a reset */ - return rval; - - IAR = 0; /* start running at address 0 */ - return SCPE_OK; -} - -/* ptp_attach - attach file to simulated paper tape punch */ - -static t_stat ptp_attach (UNIT *uptr, char *cptr) -{ - t_stat rval; - - SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); /* assume failure */ - - if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) /* use standard attach */ - return rval; - - fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */ - uptr->pos = ftell(uptr->fileref); - - if ((ptr_dsw & PTR1134_DSW_PUNCH_BUSY) == 0) - CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); /* we're in business */ - - return SCPE_OK; -} - -/* ptp_detach - detach file from simulated paper tape punch */ - -static t_stat ptp_detach (UNIT *uptr) -{ - SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); - - return detach_unit(uptr); -} diff --git a/Ibm1130/ibm1130_sca.c b/Ibm1130/ibm1130_sca.c deleted file mode 100644 index b0e8e293..00000000 --- a/Ibm1130/ibm1130_sca.c +++ /dev/null @@ -1,1165 +0,0 @@ -/* ibm1130_sca.c: IBM 1130 synchronous communications adapter emulation - - Based on the SIMH simulator package written by Robert M Supnik - - Brian Knittel - Revision History - - 2005.03.08 - Started - - * (C) Copyright 2005-2010, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -/****************************************************************************************************************** - * NOTES: - * This module sends raw bisync data over a standard TCP port. It's meant to be - * used with the emulated 2703 device in Hercules. - * - * Attach command: - * - * to establish an outgoing connection: - * - * attach sca host connect to named host on default port (initial default port is 2703); or - * attach sca host:### connect to named host on port ###. ### is also set as new default port number. - * >> The simulator waits until the connection is established - * - * or to set up for incoming connections: - * - * attach sca -l dummy listen for a connection on default port (initially 2703); Nonnumeric "dummy" argument is ignored; or - * attach sca -l ### listen for a connection on the port ###. ### is also set as the new default port - * >> The simulator proceeds. When another simulator connects, the READY bit is set in the DSW. - * - * If the SCA's autoanswer-enable bit has been set, an incoming connection causes an interrupt (untested) - * Configuration commands: - * - * set sca bsc set bisync mode (default) - * set sca str set synchronous transmit/recieve mode (NOT IMPLEMENTED) - * - * set sca ### set simulated baud rate to ###, where ### is 600, 1200, 2000, 2400 or 4800 (4800 is default) - * - * set sca half set simulated half-duplex mode - * set sca full set simulated full-duplex mode (note: 1130's SCA can't actually send and receive at the same time!) - * - * deposit sca keepalive ### send SYN packets every ### msec when suppressing SYN's, default is 0 (no keepalives) - * - * STR/BSC mode is selected by a toggle switch on the 1130, with the SET SCA BSC or SET SET STR command here. - * Testable with in_bsc_mode() or in_str_mode() in this module. If necessary, the SET command can be configured - * to call a routine when the mode is changed; or, we can just required the user to reboot the simulated 1130 - * when switching modes. - * - * STR MODE IS NOT IMPLEMENTED! - * - * The SCA adapter appears to know nothing of the protocols used by STR and BSC. It does handle the sync/idle - * character specially, and between BSC and STR mode the timers are used differently. Also in STR mode it - * can be set to a sychronization mode where it sends SYN's without program intervention. - * - * See definition of SCA_STATE for defintion of simulator states. - * - * Rather than trying to simulate the actual baud rates, we try to keep the character service interrupts - * coming at about the same number of instruction intervals -- thus existing 1130 code should work correctly - * but the effective data transfer rate will be much higher. The "timers" however are written to run on real wall clock - * time, This may or may not work. If necessary they could be set to time out based on the number of calls to sca_svc - * which occurs once per character send/receive time; For example, at 4800 baud and an 8 bit frame, we get - * 600 characters/second, so the 3 second timer would expire in 1800 sca_svc calls. Well, that's something to - * think about. - * - * To void blowing zillions of SYN characters across the network when the system is running but idle, we suppress - * them. If 100 consecutive SYN's are sent, we flush the output buffer and stop sending SYN's - * until some other character is sent, OR the line is turned around (e.g. INITR, INITW or an end-operation - * CONTROL is issued), or the number of msec set by DEPOSIT SCS KEEPALIVE has passed, if a value has - * been set. By default no keepalives are sent. - * - * Timer operations are not debugged. First, do timers automatically reset and re-interrupt if - * left alone after they timeout the first time? Does XIO_SENSE_DEV really restart all running timers? - * Does it touch the timer trigger (program timer?) How do 3 and 1.25 second timers really work - * in BSC mode? Hard to tell from the FC manual. - ******************************************************************************************************************/ - -#include "ibm1130_defs.h" -#include "sim_sock.h" /* include path must include main simh directory */ -#include -#ifndef INADDR_NONE -#define INADDR_NONE ((unsigned long)-1) -#endif - -#define DEBUG_SCA_FLUSH 0x0001 /* debugging options */ -#define DEBUG_SCA_TRANSMIT 0x0002 -#define DEBUG_SCA_CHECK_INDATA 0x0004 -#define DEBUG_SCA_RECEIVE_SYNC 0x0008 -#define DEBUG_SCA_RECEIVE_DATA 0x0010 -#define DEBUG_SCA_XIO_READ 0x0020 -#define DEBUG_SCA_XIO_WRITE 0x0040 -#define DEBUG_SCA_XIO_CONTROL 0x0080 -#define DEBUG_SCA_XIO_INITW 0x0100 -#define DEBUG_SCA_XIO_INITR 0x0200 -#define DEBUG_SCA_XIO_SENSE_DEV 0x0400 -#define DEBUG_SCA_TIMERS 0x0800 -#define DEBUG_SCA_ALL 0xFFFF - -/* #define DEBUG_SCA (DEBUG_SCA_TIMERS|DEBUG_SCA_FLUSH|DEBUG_SCA_TRANSMIT|DEBUG_SCA_CHECK_INDATA|DEBUG_SCA_RECEIVE_SYNC|DEBUG_SCA_RECEIVE_DATA|DEBUG_SCA_XIO_INITR|DEBUG_SCA_XIO_INITW) */ -#define DEBUG_SCA (DEBUG_SCA_TIMERS|DEBUG_SCA_FLUSH|DEBUG_SCA_CHECK_INDATA|DEBUG_SCA_XIO_INITR|DEBUG_SCA_XIO_INITW) - -#define SCA_DEFAULT_PORT 2703 /* default socket, This is the number of the IBM 360's BSC device */ - -#define MAX_SYNS 100 /* number of consecutive syn's after which we stop buffering them */ - -/*************************************************************************************** - * SCA - ***************************************************************************************/ - -#define SCA_DSW_READ_RESPONSE 0x8000 /* receive buffer full interrupt */ -#define SCA_DSW_WRITE_RESPONSE 0x4000 /* transmitter buffer empty interrupt */ -#define SCA_DSW_CHECK 0x2000 /* data overrun or character gap error */ -#define SCA_DSW_TIMEOUT 0x1000 /* timer interrupt, mode specific */ -#define SCA_DSW_AUTOANSWER_REQUEST 0x0800 /* dataset is ringing and autoanswer is enabled */ -#define SCA_DSW_BUSY 0x0400 /* adapter is in either receive or transmit mode */ -#define SCA_DSW_AUTOANSWER_ENABLED 0x0200 /* 1 when autoanswer mode has been enabled */ -#define SCA_DSW_READY 0x0100 /* Carrier detect? Connected and ready to rcv, xmit or sync */ -#define SCA_DSW_RECEIVE_RUN 0x0080 /* used in two-wire half-duplex STR mode only. "Slave" mode (?) */ - -#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) - -typedef enum { /* ms m = mode (0 = idle, 1 = send, 2 = receive), s = substate */ - SCA_STATE_IDLE = 0x00, /* nothing happening */ - SCA_STATE_TURN_SEND = 0x10, /* line turning around to the send state */ - SCA_STATE_SEND_SYNC = 0x11, /* sca is sending syncs */ - SCA_STATE_SEND1 = 0x12, /* have issued write response, waiting for write command */ - SCA_STATE_SEND2 = 0x13, /* write command issued, "sending" byte */ - SCA_STATE_TURN_RECEIVE = 0x20, /* line turnaround to the receive state */ - SCA_STATE_RECEIVE_SYNC = 0x21, /* sca is receiving syncs */ - SCA_STATE_RECEIVE_SYNC2 = 0x22, /* bsc mode, waiting for 2nd SYN */ - SCA_STATE_RECEIVE_SYNC3 = 0x23, /* bsc mode, waiting for 1st non-SYN */ - SCA_STATE_RECEIVE1 = 0x24, /* "receiving" a byte */ - SCA_STATE_RECEIVE2 = 0x25, /* read response issued, "receiving" next byte */ -} SCA_STATE; - -#define in_send_state() (sca_state & 0x10) -#define in_receive_state() (sca_state & 0x20) - -static t_stat sca_svc (UNIT *uptr); /* prototypes */ -static t_stat sca_reset (DEVICE *dptr); -static t_stat sca_attach (UNIT *uptr, char *cptr); -static t_stat sca_detach (UNIT *uptr); -static void sca_start_timer (int n, int msec_now); -static void sca_halt_timer (int n); -static void sca_toggle_timer (int n, int msec_now); - /* timer states, chosen so any_timer_running can be calculated by oring states of all 3 timers */ -typedef enum {SCA_TIMER_INACTIVE = 0, SCA_TIMER_RUNNING = 1, SCA_TIMER_INHIBITED = 2, SCA_TIMER_TIMEDOUT = 4} SCA_TIMER_STATE; - -#define TIMER_3S 0 /* 3 second timer index into sca_timer_xxx arrays */ -#define TIMER_125S 1 /* 1.25 second timer */ -#define TIMER_035S 2 /* 0.35 second timer */ - -static uint16 sca_dsw = 0; /* device status word */ -static uint32 sca_cwait = 275; /* inter-character wait */ -static uint32 sca_iwait = 2750; /* idle wait */ -static uint32 sca_state = SCA_STATE_IDLE; -static uint8 sichar = 0; /* sync/idle character */ -static uint8 rcvd_char = 0; /* most recently received character */ -static uint8 sca_frame = 8; -static uint16 sca_port = SCA_DEFAULT_PORT; /* listening port number */ -static int32 sca_keepalive = 0; /* keepalive SYN packet period in msec, default = 0 (disabled) */ -static SCA_TIMER_STATE sca_timer_state[3]; /* current timer state */ -static int sca_timer_endtime[3]; /* clocktime when timeout is to occur if state is RUNNING */ -static int sca_timer_timeleft[3]; /* time left in msec if state is INHIBITED */ -static t_bool any_timer_running = FALSE; /* TRUE if at least one timer is running */ -static int sca_timer_msec[3] = {3000, 1250, 350}; /* timebase in msec for the three timers: 3 sec, 1.25 sec, 0.35 sec */ -static t_bool sca_timer_trigger; /* if TRUE, the "timer trigger" is set, the 0.35s timer is running and the 3 sec and 1.25 sec timers are inhibited */ -static int sca_nsyns = 0; /* number of consecutively sent SYN's */ -static int idles_since_last_write = 0; /* used to detect when software has ceased sending data */ -static SOCKET sca_lsock = INVALID_SOCKET; -static SOCKET sca_sock = INVALID_SOCKET; - -#define SCA_SENDBUF_SIZE 145 /* maximum number of bytes to buffer for transmission */ -#define SCA_RCVBUF_SIZE 256 /* max number of bytes to read from socket at a time */ -#define SCA_SEND_THRESHHOLD 140 /* number of bytes to buffer before initiating packet send */ -#define SCA_IDLE_THRESHHOLD 3 /* maximum number of unintentional idles to buffer before initiating send */ - -static uint8 sca_sendbuf[SCA_SENDBUF_SIZE]; /* bytes pending to write to socket */ -static uint8 sca_rcvbuf[SCA_RCVBUF_SIZE]; /* bytes received from socket, to be given to SCA */ -static int sca_n2send = 0; /* number of bytes queued for transmission */ -static int sca_nrcvd = 0; /* number of received bytes in buffer */ -static int sca_rcvptr = 0; /* index of next byte to take from rcvbuf */ - -#define UNIT_V_BISYNC (UNIT_V_UF + 0) /* BSC (bisync) mode */ -#define UNIT_V_BAUD (UNIT_V_UF + 1) /* 3 bits for baud rate encoding */ -#define UNIT_V_FULLDUPLEX (UNIT_V_UF + 4) -#define UNIT_V_AUTOANSWER (UNIT_V_UF + 5) -#define UNIT_V_LISTEN (UNIT_V_UF + 6) /* listen socket mode */ - -#define UNIT_BISYNC (1u << UNIT_V_BISYNC) -#define UNIT_BAUDMASK (7u << UNIT_V_BAUD) -#define UNIT_BAUD600 (0u << UNIT_V_BAUD) -#define UNIT_BAUD1200 (1u << UNIT_V_BAUD) -#define UNIT_BAUD2000 (2u << UNIT_V_BAUD) -#define UNIT_BAUD2400 (3u << UNIT_V_BAUD) -#define UNIT_BAUD4800 (4u << UNIT_V_BAUD) -#define UNIT_FULLDUPLEX (1u << UNIT_V_FULLDUPLEX) -#define UNIT_AUTOANSWER (1u << UNIT_V_AUTOANSWER) -#define UNIT_LISTEN (1u << UNIT_V_LISTEN) - -extern int sim_switches; /* variable that gets bits set for -x switches on command lines */ - -t_stat sca_set_baud (UNIT *uptr, int32 value, char *cptr, void *desc); - -UNIT sca_unit = { /* default settings */ - UDATA (sca_svc, UNIT_ATTABLE|UNIT_BISYNC|UNIT_BAUD4800|UNIT_FULLDUPLEX, 0), -}; - -REG sca_reg[] = { /* DEVICE STATE/SETTABLE PARAMETERS: */ - { HRDATA (SCADSW, sca_dsw, 16) }, /* device status word */ - { DRDATA (SICHAR, sichar, 8), PV_LEFT }, /* sync/idle character */ - { DRDATA (RCVDCHAR, rcvd_char, 8), PV_LEFT }, /* most recently received character */ - { DRDATA (FRAME, sca_frame, 8), PV_LEFT }, /* frame bits (6, 7 or 8) */ - { DRDATA (SCASTATE, sca_state, 32), PV_LEFT }, /* current state */ - { DRDATA (CTIME, sca_cwait, 32), PV_LEFT }, /* inter-character wait */ - { DRDATA (ITIME, sca_iwait, 32), PV_LEFT }, /* idle wait (polling interval for socket connects) */ - { DRDATA (SCASOCKET, sca_port, 16), PV_LEFT }, /* listening port number */ - { DRDATA (KEEPALIVE, sca_keepalive, 32), PV_LEFT }, /* keepalive packet period in msec */ - { NULL } }; - -MTAB sca_mod[] = { /* DEVICE OPTIONS */ - { UNIT_BISYNC, 0, "STR", "STR", NULL }, /* mode option */ - { UNIT_BISYNC, UNIT_BISYNC, "BSC", "BSC", NULL }, - { UNIT_BAUDMASK, UNIT_BAUD600, "600", "600", sca_set_baud }, /* data rate option */ - { UNIT_BAUDMASK, UNIT_BAUD1200, "1200", "1200", sca_set_baud }, - { UNIT_BAUDMASK, UNIT_BAUD2000, "2000", "2000", sca_set_baud }, - { UNIT_BAUDMASK, UNIT_BAUD2400, "2400", "2400", sca_set_baud }, - { UNIT_BAUDMASK, UNIT_BAUD4800, "4800", "4800", sca_set_baud }, - { UNIT_FULLDUPLEX, 0, "HALF", "HALF", NULL }, /* duplex option (does this matter?) */ - { UNIT_FULLDUPLEX, UNIT_FULLDUPLEX, "FULL", "FULL", NULL }, - { 0 } }; - -DEVICE sca_dev = { - "SCA", &sca_unit, sca_reg, sca_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, sca_reset, - NULL, sca_attach, sca_detach -}; - -/********************************************************************************************* - * sca_set_baud - set baud rate handler (SET SCA.BAUD nnn) - *********************************************************************************************/ - -t_stat sca_set_baud (UNIT *uptr, int32 value, char *cptr, void *desc) -{ - uint32 newbits; - - switch (value) { - case 600: newbits = UNIT_BAUD600; break; - case 1200: newbits = UNIT_BAUD1200; break; - case 2000: newbits = UNIT_BAUD2000; break; - case 2400: newbits = UNIT_BAUD2400; break; - case 4800: newbits = UNIT_BAUD4800; break; - default: return SCPE_ARG; - } - - CLRBIT(sca_unit.flags, UNIT_BAUDMASK); - SETBIT(sca_unit.flags, newbits); - - sca_cwait = 1320000 / value; /* intercharacter wait time in instructions (roughly) */ - - return SCPE_OK; -} - -/********************************************************************************************* - * HANDY MACROS - *********************************************************************************************/ - -#define in_bsc_mode() (sca_unit.flags & UNIT_BISYNC) /* TRUE if user selected BSC mode */ -#define in_str_mode() ((sca_unit.flags & UNIT_BISYNC) == 0) /* TRUE if user selected STR mode */ - -/********************************************************************************************* - * mstring - allocate a copy of a string - *********************************************************************************************/ - -char *mstring (char *str) -{ - int len; - char *m; - - len = strlen(str)+1; - if ((m = malloc(len)) == NULL) { - printf("Out of memory!"); - return "?"; /* this will of course cause trouble if it's subsequently freed */ - } - strcpy(m, str); - return m; -} - -/********************************************************************************************* - * sca_socket_error - call when there is an error reading from or writing to socket - *********************************************************************************************/ - -static void sca_socket_error (void) -{ - char name[100]; - - /* print diagnostic? */ - printf("SCA socket error, closing connection\n"); - - /* tell 1130 that connection was lost */ - CLRBIT(sca_dsw, SCA_DSW_READY); - - if (sca_sock != INVALID_SOCKET) { - /* close socket, prepare to listen again if in listen mode. It's a "master" socket if it was an outgoing connection */ - sim_close_sock(sca_sock, (sca_unit.flags & UNIT_LISTEN) == 0); - sca_sock = INVALID_SOCKET; - - if (sca_unit.filename != NULL) /* reset filename string in unit record */ - free(sca_unit.filename); - - if (sca_unit.flags & UNIT_LISTEN) { - sprintf(name, "(Listening on port %d)", sca_port); - sca_unit.filename = mstring(name); - printf("%s\n", name); - } - else - sca_unit.filename = mstring("(connection failed)"); - } - - /* clear buffers */ - sca_nrcvd = sca_rcvptr = sca_n2send = sca_nsyns = 0; -} - -/********************************************************************************************* - * sca_transmit_byte, sca_flush - send data buffering mechanism - *********************************************************************************************/ - -static void sca_flush (void) -{ - int nbytes; - - if (sca_n2send > 0) { -#if (DEBUG_SCA & DEBUG_SCA_FLUSH) - printf("* SCA_FLUSH %d byte%s\n", sca_n2send, (sca_n2send == 1) ? "" : "s"); -#endif - - if (sca_sock != INVALID_SOCKET) { - nbytes = sim_write_sock(sca_sock, (char *) sca_sendbuf, sca_n2send); - - if (nbytes == SOCKET_ERROR) - sca_socket_error(); - else if (nbytes != sca_n2send) - printf("SOCKET BLOCKED -- NEED TO REWRITE IBM1130_SCA.C"); - - /* I'm going to assume that SCA communications on the 1130 will consist entirely */ - /* of back and forth exchanges of short records, and so we should never stuff the pipe so full that */ - /* it blocks. If it does ever block, we'll have to come up with an asychronous buffering mechanism. */ - } - - sca_n2send = 0; /* mark buffer cleared */ - } -} - -/********************************************************************************************* - * sca_transmit_byte - buffer a byte to be send to the socket - *********************************************************************************************/ - -static void sca_transmit_byte (uint8 b) -{ - uint32 curtime; - static uint32 last_syn_time, next_syn_time; - -#if (DEBUG_SCA & DEBUG_SCA_TRANSMIT) - printf("* SCA_TRANSMIT: %02x\n", b); -#endif - - /* write a byte to the socket. Let's assume an 8 bit frame in all cases. - * We buffer them up, then send the packet when (a) it fills up to a certain point - * and/or (b) some time has passed? We handle (b) by: - * checking in sva_svc if several sca_svc calls are made w/o any XIO_WRITES, and - * flushing send buffer on line turnaround, timeouts, or any other significant state change - */ - - /* on socket error, call sca_socket_error(); */ - - if (b == sichar) { - if (sca_nsyns >= MAX_SYNS) { /* we're suppressing SYN's */ - if (sca_keepalive > 0) { /* we're sending keepalives, though... check to see if it's time */ - curtime = sim_os_msec(); - if (curtime >= next_syn_time || curtime < last_syn_time) { /* check for < last_syn_time because sim_os_msec() can wrap when OS has been running a long time */ - sca_sendbuf[sca_n2send++] = b; - sca_sendbuf[sca_n2send++] = b; /* send 2 of them */ - sca_flush(); - last_syn_time = curtime; - next_syn_time = last_syn_time + sca_keepalive; - } - } - return; - } - - if (++sca_nsyns == MAX_SYNS) { /* we've sent a bunch of SYN's, time to stop sending them */ - sca_sendbuf[sca_n2send] = b; /* send last one */ - sca_flush(); - last_syn_time = sim_os_msec(); /* remember time, and note time to send next one */ - next_syn_time = last_syn_time + sca_keepalive; - return; - } - } - else - sca_nsyns = 0; - - sca_sendbuf[sca_n2send] = b; /* store character */ - - if (++sca_n2send >= SCA_SEND_THRESHHOLD) - sca_flush(); /* buffer is full, send it immediately */ -} - -/********************************************************************************************* - * sca_interrupt (utility routine) - set a bit in the device status word and initiate an interrupt - *********************************************************************************************/ - -static void sca_interrupt (int bit) -{ - sca_dsw |= bit; /* set device status word bit(s) */ - SETBIT(ILSW[1], ILSW_1_SCA); /* set interrupt level status word bit */ - - calc_ints(); /* udpate simulator interrupt status (not really needed if within xio handler, since ibm1130_cpu calls it after xio handler) */ -} - -/********************************************************************************************* - * sca_reset - reset the SCA device - *********************************************************************************************/ - -static t_stat sca_reset (DEVICE *dptr) -{ - /* flush any pending data */ - sca_flush(); - sca_nrcvd = sca_rcvptr = sca_n2send = sca_nsyns = 0; - - /* reset sca activity */ - sca_state = SCA_STATE_IDLE; - CLRBIT(sca_dsw, SCA_DSW_BUSY | SCA_DSW_AUTOANSWER_ENABLED | SCA_DSW_RECEIVE_RUN | SCA_DSW_READ_RESPONSE | SCA_DSW_WRITE_RESPONSE | SCA_DSW_CHECK | SCA_DSW_TIMEOUT | SCA_DSW_AUTOANSWER_REQUEST); - sca_timer_state[0] = sca_timer_state[1] = sca_timer_state[2] = SCA_TIMER_INACTIVE; - any_timer_running = FALSE; - sca_timer_trigger = FALSE; - - if (sca_unit.flags & UNIT_ATT) /* if unit is attached (or listening) */ - sim_activate(&sca_unit, sca_iwait); /* poll for service. Must do this here as BOOT clears activity queue before resetting all devices */ - - return SCPE_OK; -} - -/********************************************************************************************* - * sca_attach - attach the SCA device - *********************************************************************************************/ - -static t_stat sca_attach (UNIT *uptr, char *cptr) -{ - t_bool do_listen; - char *colon; - uint32 ipaddr; - int32 port; - struct hostent *he; - char name[256]; - static SOCKET sdummy = INVALID_SOCKET; - fd_set wr_set, err_set; - - do_listen = sim_switches & SWMASK('L'); /* -l means listen mode */ - - if (sca_unit.flags & UNIT_ATT) /* if already attached, detach */ - detach_unit(&sca_unit); - - if (do_listen) { /* if listen mode, string specifies socket number (only; otherwise it's a dummy argument) */ - if (isdigit(*cptr)) { /* if digits specified, extract port number */ - port = atoi(cptr); - if (port <= 0 || port > 65535) - return SCPE_ARG; - else - sca_port = port; - } - /* else if nondigits specified, ignore... but the command has to have something there otherwise the core scp */ - /* attach_cmd() routine complains "too few arguments". */ - - if ((sca_lsock = sim_master_sock(sca_port)) == INVALID_SOCKET) - return SCPE_OPENERR; - - SETBIT(sca_unit.flags, UNIT_LISTEN); /* note that we are listening, not yet connected */ - - sprintf(name, "(Listening on port %d)", sca_port); - sca_unit.filename = mstring(name); - printf("%s\n", name); - - } - else { - while (*cptr && *cptr <= ' ') - cptr++; - - if (! *cptr) - return SCPE_2FARG; - - if ((colon = strchr(cptr, ':')) != NULL) { - *colon++ = '\0'; /* clip hostname at colon */ - - port = atoi(colon); /* extract port number that follows it */ - if (port <= 0 || port > 65535) - return SCPE_ARG; - else - sca_port = port; - } - - if (sdummy == INVALID_SOCKET) - if ((sdummy = sim_create_sock()) == INVALID_SOCKET) /* create and keep a socket, to force initialization */ - return SCPE_IERR; /* of socket library (e.g on Win32 call WSAStartup), else gethostbyname fails */ - - if (get_ipaddr(cptr, &ipaddr, NULL) != SCPE_OK) { /* try to parse hostname as dotted decimal nnn.nnn.nnn.nnn */ - if ((he = gethostbyname(cptr)) == NULL) /* if not decimal, look up name through DNS */ - return SCPE_OPENERR; - - if ((ipaddr = * (unsigned long *) he->h_addr_list[0]) == INADDR_NONE) - return SCPE_OPENERR; - - ipaddr = ntohl(ipaddr); /* convert to host byte order; gethostbyname() gives us network order */ - } - - if ((sca_sock = sim_connect_sock(ipaddr, sca_port)) == INVALID_SOCKET) - return SCPE_OPENERR; - - /* sim_connect_sock() sets socket to nonblocking before initiating the connect, so - * the connect is pending when it returns. For outgoing connections, the attach command should wait - * until the connection succeeds or fails. We use "accept" to wait and find out which way it goes... - */ - - FD_ZERO(&wr_set); /* we are only interested in info for sca_sock */ - FD_ZERO(&err_set); - FD_SET(sca_sock, &wr_set); - FD_SET(sca_sock, &err_set); - - select(3, NULL, &wr_set, &err_set, NULL); /* wait for connection to complete or fail */ - - if (FD_ISSET(sca_sock, &wr_set)) { /* sca_sock appears in "writable" set -- connect completed */ - sprintf(name, "%s:%d", cptr, sca_port); - sca_unit.filename = mstring(name); - SETBIT(sca_dsw, SCA_DSW_READY); - } - else if (FD_ISSET(sca_sock, &err_set)) { /* sca_sock appears in "error" set -- connect failed */ - sim_close_sock(sca_sock, TRUE); - sca_sock = INVALID_SOCKET; - return SCPE_OPENERR; - } - else { /* if we get here my assumption about how select works is wrong */ - printf("SCA_SOCK NOT FOUND IN WR_SET -OR- ERR_SET, CODING IN IBM1130_SCA IS WRONG\n"); - sim_close_sock(sca_sock, TRUE); - sca_sock = INVALID_SOCKET; - return SCPE_OPENERR; - } - } - - /* set up socket connect or listen. on success, set UNIT_ATT. - * If listen mode, set UNIT_LISTEN. sca_svc will poll for connection - * If connect mode, set dsw SCA_DSW_READY to indicate connection is up - */ - - SETBIT(sca_unit.flags, UNIT_ATT); /* record successful socket binding */ - - sca_state = SCA_STATE_IDLE; - sim_activate(&sca_unit, sca_iwait); /* start polling for service */ - - sca_n2send = 0; /* clear buffers */ - sca_nrcvd = 0; - sca_rcvptr = 0; - sca_nsyns = 0; - - return SCPE_OK; -} - -/********************************************************************************************* - * sca_detach - detach the SCA device - *********************************************************************************************/ - -static t_stat sca_detach (UNIT *uptr) -{ - if ((sca_unit.flags & UNIT_ATT) == 0) - return SCPE_OK; - - sca_flush(); - - sca_state = SCA_STATE_IDLE; /* stop processing during service calls */ - sim_cancel(&sca_unit); /* stop polling for service */ - - CLRBIT(sca_dsw, SCA_DSW_READY); /* indicate offline */ - - if (sca_sock != INVALID_SOCKET) { /* close connected socket */ - sim_close_sock(sca_sock, (sca_unit.flags & UNIT_LISTEN) == 0); - sca_sock = INVALID_SOCKET; - } - if (sca_lsock != INVALID_SOCKET) { /* close listening socket */ - sim_close_sock(sca_lsock, TRUE); - sca_lsock = INVALID_SOCKET; - } - - free(sca_unit.filename); - sca_unit.filename = NULL; - - CLRBIT(sca_unit.flags, UNIT_ATT|UNIT_LISTEN); - - return SCPE_OK; -} - -/********************************************************************************************* - * sca_check_connect - see if an incoming socket connection has com - *********************************************************************************************/ - -static void sca_check_connect (void) -{ - uint32 ipaddr; - char name[100]; - - if ((sca_sock = sim_accept_conn(sca_lsock, &ipaddr)) == INVALID_SOCKET) - return; - - ipaddr = htonl(ipaddr); /* convert to network order so we can print it */ - - sprintf(name, "%d.%d.%d.%d", ipaddr & 0xFF, (ipaddr >> 8) & 0xFF, (ipaddr >> 16) & 0xFF, (ipaddr >> 24) & 0xFF); - - printf("(SCA connection from %s)\n", name); - - if (sca_unit.filename != NULL) - free(sca_unit.filename); - - sca_unit.filename = mstring(name); - - SETBIT(sca_dsw, SCA_DSW_READY); /* indicate active connection */ - - if (sca_dsw & SCA_DSW_AUTOANSWER_ENABLED) /* if autoanswer was enabled, I guess we should give them an interrupt. Untested. */ - sca_interrupt(SCA_DSW_AUTOANSWER_REQUEST); -} - -/********************************************************************************************* - * sca_check_indata - try to fill receive buffer from socket - *********************************************************************************************/ - -static void sca_check_indata (void) -{ - int nbytes; - - sca_rcvptr = 0; /* reset pointers and count */ - sca_nrcvd = 0; - -#ifdef FAKE_SCA - - nbytes = 5; /* FAKE: receive SYN SYN SYN SYN DLE ACK0 */ - sca_rcvbuf[0] = 0x32; - sca_rcvbuf[1] = 0x32; - sca_rcvbuf[2] = 0x32; - sca_rcvbuf[3] = 0x10; - sca_rcvbuf[4] = 0x70; - -#else - /* read socket; 0 is returned if no data is available */ - nbytes = sim_read_sock(sca_sock, (char *) sca_rcvbuf, SCA_RCVBUF_SIZE); - -#endif - - if (nbytes < 0) - sca_socket_error(); - else /* zero or more */ - sca_nrcvd = nbytes; - -#if (DEBUG_SCA & DEBUG_SCA_CHECK_INDATA) - if (sca_nrcvd > 0) - printf("* SCA_CHECK_INDATA %d byte%s\n", sca_nrcvd, (sca_nrcvd == 1) ? "" : "s"); -#endif -} - -/********************************************************************************************* - * sca_svc - handled scheduled event. This will presumably be scheduled frequently, and can check - * for incoming data, reasonableness of initiating a write interrupt, timeouts etc. - *********************************************************************************************/ - -static t_stat sca_svc (UNIT *uptr) -{ - t_bool timeout; - int msec_now; - int i; - - /* if not connected, and if in wait-for-connection mode, check for connection attempt */ - if ((sca_unit.flags & UNIT_LISTEN) && ! (sca_dsw & SCA_DSW_READY)) - sca_check_connect(); - - if (any_timer_running) { - msec_now = sim_os_msec(); - - timeout = FALSE; - for (i = 0; i < 3; i++) { - if (sca_timer_state[i] == SCA_TIMER_RUNNING && msec_now >= sca_timer_endtime[i]) { - timeout = TRUE; - sca_timer_state[i] = SCA_TIMER_TIMEDOUT; -#if (DEBUG_SCA & DEBUG_SCA_TIMERS) - printf("+ SCA_TIMER %d timed out\n", i); -#endif - - if (i == TIMER_035S && sca_timer_trigger) { - sca_timer_trigger = FALSE; /* uninhibit the other two timers */ - sca_toggle_timer(TIMER_3S, msec_now); - sca_toggle_timer(TIMER_125S, msec_now); - } - } - } - - if (timeout) - sca_interrupt(SCA_DSW_TIMEOUT); - - any_timer_running = (sca_timer_state[0]| sca_timer_state[1] | sca_timer_state[2]) & SCA_TIMER_RUNNING; - } - - if (sca_dsw & SCA_DSW_READY) { /* if connected */ - - /* if rcvd data buffer is empty, and if in one of the receive states, checÄk for arrival of received data */ - if (in_receive_state() && sca_rcvptr >= sca_nrcvd) - sca_check_indata(); - - switch (sca_state) { - case SCA_STATE_IDLE: - break; - - case SCA_STATE_TURN_SEND: - /* has enough time gone by yet? if so... */ - sca_state = SCA_STATE_SEND1; - sca_interrupt(SCA_DSW_WRITE_RESPONSE); - break; - - case SCA_STATE_SEND_SYNC: - sca_transmit_byte(sichar); - break; - - case SCA_STATE_SEND1: - sca_transmit_byte(sichar); /* character interval has passed with no character written? character gap check */ - sca_interrupt(SCA_DSW_CHECK); /* send an idle character (maybe? for socket IO maybe send nothing) and interrupt */ - - if (idles_since_last_write >= 0) { - if (++idles_since_last_write >= SCA_IDLE_THRESHHOLD) { - sca_flush(); - idles_since_last_write = -1; /* don't send a short packet again until real data gets written again */ - sca_nsyns = 0; /* resume sending syns if output starts up again */ - } - } - break; - - case SCA_STATE_SEND2: - sca_state = SCA_STATE_SEND1; /* character has been sent. Schedule another transmit */ - sca_interrupt(SCA_DSW_WRITE_RESPONSE); - break; - - case SCA_STATE_TURN_RECEIVE: - /* has enough time gone by yet? if so... */ - sca_state = SCA_STATE_RECEIVE_SYNC; /* assume a character is coming in */ - break; - - case SCA_STATE_RECEIVE_SYNC: - if (sca_rcvptr < sca_nrcvd) { - rcvd_char = sca_rcvbuf[sca_rcvptr++]; -#if (DEBUG_SCA & DEBUG_SCA_RECEIVE_SYNC) - printf("* SCA rcvd %02x %s\n", rcvd_char, (rcvd_char == sichar) ? "sync1" : "ignored"); -#endif - if (in_bsc_mode()) { - if (rcvd_char == sichar) /* count the SYN but don't interrupt */ - sca_state = SCA_STATE_RECEIVE_SYNC2; - } - } - break; - - case SCA_STATE_RECEIVE_SYNC2: - if (sca_rcvptr < sca_nrcvd) { - rcvd_char = sca_rcvbuf[sca_rcvptr++]; -#if (DEBUG_SCA & DEBUG_SCA_RECEIVE_SYNC) - printf("* SCA rcvd %02x %s\n", rcvd_char, (rcvd_char == sichar) ? "sync2" : "ignored"); -#endif - if (in_bsc_mode()) { - if (rcvd_char == sichar) /* count the SYN but don't interrupt */ - sca_state = SCA_STATE_RECEIVE_SYNC3; - } - } - break; - - case SCA_STATE_RECEIVE_SYNC3: - case SCA_STATE_RECEIVE1: - if (sca_rcvptr < sca_nrcvd) { - rcvd_char = sca_rcvbuf[sca_rcvptr++]; - - if (sca_state == SCA_STATE_RECEIVE_SYNC3 && rcvd_char == sichar) { - /* we're ready for data, but we're still seeing SYNs */ -#if (DEBUG_SCA & DEBUG_SCA_RECEIVE_SYNC) - printf("* SCA rcvd %02x extra sync\n", rcvd_char); -#endif - } - else { -#if (DEBUG_SCA & DEBUG_SCA_RECEIVE_DATA) - printf("* SCA rcvd %02x\n", rcvd_char); -#endif - sca_interrupt(SCA_DSW_READ_RESPONSE); - sca_state = SCA_STATE_RECEIVE2; - } - } - /* otherwise remain in state until data becomes available */ - break; - - case SCA_STATE_RECEIVE2: /* if we are still in this state when another service interval has passed */ - if (sca_rcvptr < sca_nrcvd) { - rcvd_char = sca_rcvbuf[sca_rcvptr++]; - - sca_interrupt(SCA_DSW_CHECK); /* overrun error */ - sca_state = SCA_STATE_RECEIVE1; /* another character will come soon */ - } - break; - - default: - printf("Simulator error: unknown state %d in sca_svc\n", sca_state); - sca_state = SCA_STATE_IDLE; - break; - } - } - /* schedule service again */ - sim_activate(&sca_unit, (sca_state == SCA_STATE_IDLE) ? sca_iwait : sca_cwait); - - return SCPE_OK; -} - -/********************************************************************************************* - * sca_toggle_timer - toggle a given timer's running/inhibited state for XIO_CONTROL - *********************************************************************************************/ - -static void sca_toggle_timer (int n, int msec_now) -{ - if (sca_timer_state[n] == SCA_TIMER_RUNNING && sca_timer_trigger) { - sca_timer_state[n] = SCA_TIMER_INHIBITED; - sca_timer_timeleft[n] = sca_timer_endtime[n] - msec_now; /* save time left */ -#if (DEBUG_SCA & DEBUG_SCA_TIMERS) - printf("+ SCA_TIMER %d inhibited\n", n); -#endif - } - else if (sca_timer_state[n] == SCA_TIMER_INHIBITED && ! sca_timer_trigger) { - sca_timer_state[n] = SCA_TIMER_RUNNING; - sca_timer_endtime[n] = sca_timer_timeleft[n] + msec_now; /* compute new endtime */ -#if (DEBUG_SCA & DEBUG_SCA_TIMERS) - printf("+ SCA_TIMER %d uninhibited\n", n); -#endif - } -} - -static void sca_start_timer (int n, int msec_now) -{ - sca_timer_state[n] = SCA_TIMER_RUNNING; - sca_timer_endtime[n] = sca_timer_msec[n] + msec_now; - any_timer_running = TRUE; -#if (DEBUG_SCA & DEBUG_SCA_TIMERS) - printf("+ SCA_TIMER %d started\n", n); -#endif -} - -static void sca_halt_timer (int n) -{ -#if (DEBUG_SCA & DEBUG_SCA_TIMERS) - if (sca_timer_state[n] != SCA_TIMER_INACTIVE) - printf("+ SCA_TIMER %d stopped\n", n); -#endif - - sca_timer_state[n] = SCA_TIMER_INACTIVE; -} - -/********************************************************************************************* - * sca_start_transmit - initiate transmit mode, from XIO_INITR or XIO_CONTROL (sync mode) - *********************************************************************************************/ - -void sca_start_transmit (int32 iocc_addr, int32 modify) -{ - sca_flush(); - sca_nsyns = 0; /* reset SYN suppression */ - - /* Address bits are used to reset DSW conditions. */ - - if (modify & 0x40) /* bit 9. If set, reset all conditions */ - iocc_addr = 0xD800; - - iocc_addr &= 0xD800; /* look at just bits 0, 1, 3 and 4 */ - if (iocc_addr) { /* if set, these bits clear DSW conditions */ - CLRBIT(sca_dsw, iocc_addr); - CLRBIT(ILSW[1], ILSW_1_SCA); /* and I assume clear the interrupt condition too? (Seems unlikely that INITW would */ - } /* be used in an interrupt service routine before SENSE, but who knows?) */ - - if (! in_send_state()) { - sca_state = SCA_STATE_TURN_SEND; /* begin line turnaround */ - } - else { - sca_state = SCA_STATE_SEND1; /* line is */ - sca_interrupt(SCA_DSW_WRITE_RESPONSE); - } - - SETBIT(sca_dsw, SCA_DSW_BUSY); /* SCA is now busy, in transmit mode */ - - sim_cancel(&sca_unit); - sim_activate(&sca_unit, sca_cwait); /* start polling frequently */ -} - -/********************************************************************************************* - * xio_sca - handle SCA XIO command - *********************************************************************************************/ - -void xio_sca (int32 iocc_addr, int32 func, int32 modify) -{ - char msg[80]; - int i, msec_now; - - switch (func) { - case XIO_READ: /* ***** XIO_READ - store last-received character to memory */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_READ) - printf("SCA RD addr %04x mod %02x rcvd_char %02x\n", iocc_addr, modify, rcvd_char); -#endif - if (modify & 0x03) { /* bits 14 and 15 */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_READ) - printf("(rd diag)\n"); -#endif - /* if either of low two modifier bits is set, reads diagnostic words. whatever that is */ - } - else { - WriteW(iocc_addr, rcvd_char << 8); /* always return last received character */ - - /* note: in read mode, read w/o interrupt (or two reads after an interrupt) causes a check - * so here we have to check the current state and possibly cause an interrupt - * Failure to have read before another arrives (overrun) also causes a check. - */ - - if (sca_state == SCA_STATE_RECEIVE2)/* XIO_READ should only be done (and only once) after a character interrupt */ - sca_state = SCA_STATE_RECEIVE1; /* assume another character is coming in -- wait for it */ - else - sca_interrupt(SCA_DSW_CHECK); - } - break; - - case XIO_WRITE: /* ***** XIO_WRITE - transfer character from memory to output shift register */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_WRITE) - printf("SCA WRT addr %04x (%04x) mod %02x\n", iocc_addr, M[iocc_addr & mem_mask], modify); -#endif - if (modify & 0x01) { /* bit 15 */ - /* clear audible alarm trigger */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_WRITE) - printf("(clr audible alarm trigger)\n"); -#endif - } - /* else? or can they all operate in parallel? */ - if (modify & 0x02) { /* bit 14 */ - /* set audible alarm trigger */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_WRITE) - printf("(set audible alarm trigger)\n"); -#endif - } - /* else? */ - if (modify & 0x04) { /* bit 13 */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_WRITE) - printf("(set SYN)\n"); -#endif - /* set sync/idle character */ - sichar = (uint8) (ReadW(iocc_addr) >> 8); - sca_nsyns = 0; /* reset SYN suppression */ - } - /* else? does presence of mod bit preclude sending a character? */ - if ((modify & 0x07) == 0) { /* no modifiers */ - /* transmit character -- - * note: in write mode, failure to write soon enough after a write response interrupt causes a check - * Also, writing w/o interrupt (or two writes after an interrupt) causes a check - * so again, here we have to check the state to be sure that a write is appropriate - * - * note that in this simulator, we transmit the character immediately on XIO_WRITE. Therefore, - * there is no need to delay an end-operation function (XIO_CONTROL bit 13) until after a character time - */ - - idles_since_last_write = 0; - - switch (sca_state) { - case SCA_STATE_SEND_SYNC: - case SCA_STATE_SEND1: - sca_transmit_byte((uint8) (M[iocc_addr & mem_mask] >> 8)); - sca_state = SCA_STATE_SEND2; - sim_cancel(&sca_unit); - sim_activate(&sca_unit, sca_cwait); /* schedule service after character write time */ - break; - - case SCA_STATE_SEND2: - sca_interrupt(SCA_DSW_CHECK); /* write issued while a character is in progress out? write overrun */ - break; - - case SCA_STATE_IDLE: /* wrong time to issue a write, incorrect sca state */ - default: - sca_flush(); - sca_interrupt(SCA_DSW_CHECK); /* ??? or does this just perform a line turnaround and start transmission? */ - break; - } - - } - break; - - case XIO_CONTROL: /* ***** XIO_CONTROL - manipulate interface state */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL) - printf("SCA CTL addr %04x mod %02x\n", iocc_addr, modify); -#endif - if (modify & 0x80) { /* bit 8 */ - /* enable auto answer */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL) - printf("(enable autoanswer)\n"); -#endif - SETBIT(sca_unit.flags, UNIT_AUTOANSWER); - SETBIT(sca_dsw, SCA_DSW_AUTOANSWER_ENABLED); - } - - if (modify & 0x40) { /* bit 9 */ - /* disable auto answer */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL) - printf("(disable autoanswer)\n"); -#endif - CLRBIT(sca_unit.flags, UNIT_AUTOANSWER); - CLRBIT(sca_dsw, SCA_DSW_AUTOANSWER_ENABLED); - } - - if (modify & 0x20) { /* bit 10 */ - /* toggle timers, inhibit->run or run->inhibit */ -#if (DEBUG_SCA & (DEBUG_SCA_XIO_CONTROL|DEBUG_SCA_TIMERS)) - printf("(toggle timers)\n"); -#endif - msec_now = sim_os_msec(); - - if (in_bsc_mode()) - sca_timer_trigger = ! sca_timer_trigger; /* toggle the timer trigger */ - if (sca_timer_trigger) /* if we've just set it, we're stopping the other timers and */ - sca_start_timer(TIMER_035S, msec_now); /* starting the 0.35 sec timer */ - else - sca_halt_timer(TIMER_035S); - - sca_toggle_timer(TIMER_3S, msec_now); /* toggle the 3 sec and 1.35 sec timers accordingly */ - sca_toggle_timer(TIMER_125S, msec_now); - - any_timer_running = (sca_timer_state[0]| sca_timer_state[1] | sca_timer_state[2]) & SCA_TIMER_RUNNING; - } - - if (modify & 0x10) { /* bit 11 */ - /* enable sync mode. See references to this in FC manual - * In STR mode only, sends a constant stream of SYN's without any CPU intervention - * In BSC mode, appears to start the 1.25 second timer and otherwise act like INITW? - */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL) - printf("(enable sync mode)\n"); -#endif - - if (in_bsc_mode()) { /* in bsc mode start the 1.25 second timer. not sure what resets it?!? */ - if (! in_send_state()) /* also may cause a line turnaround */ - sca_start_transmit(iocc_addr, 0); - - sca_start_timer(TIMER_125S, sim_os_msec()); - } - } - - if (modify & 0x08) { /* bit 12 */ - /* diagnostic mode. What does this do?!? */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL) - printf("(diag mode)\n"); -#endif - } - - if (modify & 0x04) { /* bit 13 */ - /* end operation (reset adapter. See references to this in FC manual). In transmit mode the real adapter delays this - * function until current character has been sent. We don't need to do that as the character got buffered for transmission - * immediately on XIO_WRITE. - */ - -#if (DEBUG_SCA & (DEBUG_SCA_XIO_CONTROL|DEBUG_SCA_XIO_INITR|DEBUG_SCA_XIO_INITW)) - printf("(end operation)\n"); -#endif - sca_state = SCA_STATE_IDLE; - sca_timer_state[0] = sca_timer_state[1] = sca_timer_state[2] = SCA_TIMER_INACTIVE; - any_timer_running = FALSE; - sca_timer_trigger = FALSE; - sca_nsyns = 0; /* reset SYN suppression */ - CLRBIT(sca_dsw, SCA_DSW_BUSY); - } - - if (modify & 0x02) { /* bit 14 */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL) - printf("(6 bit frame)\n"); -#endif - /* set six bit character frame. This is reset to 8 bits at every line turnaround */ - sca_frame = 6; - } - - if (modify & 0x01) { /* bit 15 */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_CONTROL) - printf("(7 bit frame)\n"); -#endif - /* set seven bit character frame. This is reset to 8 bits at every line turnaround */ - sca_frame = 7; - } - - sca_flush(); - break; - - case XIO_INITW: /* ***** XIO_INITW - put SCA in transmit mode */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_INITW) - printf("SCA INITW addr %04x mod %02x\n", iocc_addr, modify); -#endif - /* enter transmit mode. Causes line turnaround. Resets frame to 8 bits. */ - /* (may cause syncing, may involve a fixed timeout?) */ - sca_frame = 8; - sca_start_transmit(iocc_addr, modify); /* this code pulled out to a subroutine cuz transmit can be started from XIO_CONTROL too */ - break; - - case XIO_INITR: /* ***** XIO_INITR - put SCA in receive mode */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_INITR) - printf("SCA INITR addr %04x mod %02x\n", iocc_addr, modify); -#endif - sca_flush(); - - sca_nrcvd = sca_rcvptr = 0; /* discard any data previously read! */ - sca_nsyns = 0; /* reset SYN suppression */ - - /* enter receive mode. Causes line turnaround (e.g. resets to 8 bit frame). Modifier bits are used here too */ - /* (may cause syncing, may involve a fixed timeout?) */ - - sca_frame = 8; - if (! in_receive_state()) - sca_state = SCA_STATE_TURN_RECEIVE; /* begin line turnaround */ - else - sca_state = SCA_STATE_RECEIVE_SYNC; - - SETBIT(sca_dsw, SCA_DSW_BUSY); /* SCA is now busy, in receive mode */ - - if (in_bsc_mode()) /* in BSC mode, start the 3 second timer when we enter receive mode */ - sca_start_timer(TIMER_3S, sim_os_msec()); - - break; - - case XIO_SENSE_DEV: /* ***** XIO_SENSE_DEV - read device status word */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_SENSE_DEV) - printf("SCA SNS mod %02x dsw %04x\n", modify, sca_dsw); -#endif - ACC = sca_dsw; /* return DSW in accumulator */ - - if (modify & 0x01) { /* bit 15: reset interrupts */ -#if (DEBUG_SCA & DEBUG_SCA_XIO_SENSE_DEV) - printf("(reset interrupts)\n"); -#endif - CLRBIT(sca_dsw, SCA_DSW_READ_RESPONSE | SCA_DSW_WRITE_RESPONSE | SCA_DSW_CHECK | SCA_DSW_TIMEOUT | SCA_DSW_AUTOANSWER_REQUEST); - CLRBIT(ILSW[1], ILSW_1_SCA); - } - - if (modify & 0x02) { /* bit 14: restart running timers */ -#if (DEBUG_SCA & (DEBUG_SCA_XIO_SENSE_DEV|DEBUG_SCA_TIMERS)) - printf("(restart timers)\n"); -#endif - msec_now = sim_os_msec(); /* restart "any running timer?" All three, really? */ - for (i = 0; i < 3; i++) - if (sca_timer_state[i] == SCA_TIMER_RUNNING || sca_timer_state[i] == SCA_TIMER_TIMEDOUT) - sca_start_timer(i, msec_now); - } - break; - - default: - sprintf(msg, "Invalid SCA XIO function %x", func); - xio_error(msg); - } -} diff --git a/Ibm1130/ibm1130_stddev.c b/Ibm1130/ibm1130_stddev.c deleted file mode 100644 index d71d45b4..00000000 --- a/Ibm1130/ibm1130_stddev.c +++ /dev/null @@ -1,1319 +0,0 @@ -/* ibm1130_stddev.c: IBM 1130 standard I/O devices simulator - - Based on the SIMH simulator package written by Robert M Supnik - - Brian Knittel - - Revision History: - - 2004.10.22 - Removed stub for xio_1134_papertape as it's now a supported device - - 2003.11.23 - Fixed bug in new routine "quotefix" that made sim crash - for all non-Windows builds :( - - 2003.06.15 - added output translation code to accomodate APL font - added input translation feature to assist emulation of 1130 console keyboard for APL - changes to console input and output IO emulation, fixed bugs exposed by APL interpreter - - 2002.09.13 - pulled 1132 printer out of this file into ibm1130_prt.c - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - * - * Notes about overstrike mapping: - * The 1130 console printer used a Selectric typewriter element. The APL interpreter - * used overprinting to construct some APL symbols, for example, a round O overstruck] - * with | to get the greek phi. This doesn't accomodate a glass terminal! Instead, - * modern APL fonts have separate character codes for the complex characters. - * To have APL\1130 output appear correctly, we have to do three things: - * - * use simh's telnet feature to connect to the 1130 console stream - * have the telnet program use an APL font - * detect combinations of overstruck symbols, and generate the approrpiate alternate codes. - * - * There is a built-in table of font mappings and overstrike mappings, for the APLPLUS.TTF - * truetype font widely available on the Internet. An font descriptor file can be used - * to specify alternate mappings. - * - * The APL font codes and overstrike mapping can be enabled with the simh command - * - * set tto apl - * - * and disabled with - * - * set tto ascii (this is the default) - * - * APL also uses the red and black ribbon selection. The emulator will output - * ansi red/black foreground commands with the setting - * - * set tto ansi - * - * The codes can be disabled with - * - * set tto noansi (this is the default) - * - * Finally, when APL mode is active, the emulator does some input key translations - * to let the standard ASCII keyboard more closely match the physical layout of the - * 1130 console keyboard. The numeric and punctuation key don't have their - * traditional meaning under APL. The input mapping lets you use the APL keyboard - * layout shown in the APL documentation. - * - * The translations are: - * FROM - * ASCII Position on keyboard To 1130 Key APL interpretation - * ------------------------------------ -------------------------------- - * [ (key to right of P) \r Enter left arrow - * ; (1st key to right of L) \b Backspace [ - * ' (2nd key to right of L) ^U Erase Fld ] - * 2 (key above Q) @ @ up shift - * 3 (key above W) % % up right shift - * 4 (key above E) * * + - * 5 (key above R) < < multiply - * 8 (key above U) - - Return - * 9 (key above I) / / Backspace - * - (key above P) ^Q INT REQ ATTN - * Enter - - Return - * backsp / / Backspace - */ - -#include "ibm1130_defs.h" -#include - -/* #define DEBUG_CONSOLE */ - -/* ---------------------------------------------------------------------------- */ - -static void badio (char *dev) -{ -/* the real 1130 just ignores attempts to use uninstalled devices. They get tested - * at times, so it's best to just be quiet about this - * printf("%s I/O is not yet supported", dev); - */ -} - -void xio_1231_optical (int32 addr, int32 func, int32 modify) {badio("optical mark");} -void xio_system7 (int32 addr, int32 func, int32 modify) {badio("System 7");} - -/* ---------------------------------------------------------------------------- */ - -#define MAX_OUTPUT_COLUMNS 100 /* width of 1130 console printer */ -#define MAX_OS_CHARS 4 /* maximum number of overstruck characters that can be mapped */ -#define MAX_OS_MAPPINGS 100 /* maximum number of overstrike mappings */ - -typedef struct tag_os_map { /* os_map = overstrike mapping */ - int ch; /* ch = output character */ - int nin; /* nin = number of overstruck characters */ - unsigned char inlist[MAX_OS_CHARS]; /* inlist = overstruck ASCII characters, sorted. NOT NULL TERMINATED */ -} OS_MAP; - -extern UNIT *sim_clock_queue; -extern int cgi; - -static int32 tti_dsw = 0; /* device status words */ -static int32 tto_dsw = 0; - int32 con_dsw = 0; - -static unsigned char conout_map[256]; /* 1130 console code to ASCII translation. 0 = undefined, 0xFF = IGNR_ = no output */ -static unsigned char conin_map[256]; /* input mapping */ -static int curcol = 0; /* current typewriter element column, leftmost = 0 */ -static int maxcol = 0; /* highest curcol seen in this output line */ -static unsigned char black_ribbon[30]; /* output escape sequence for black ribbon shift */ -static unsigned char red_ribbon[30]; /* output escape sequence for red ribbon shift */ - -static OS_MAP os_buf[MAX_OUTPUT_COLUMNS]; /* current typewriter output line, holds character struck in each column */ -static OS_MAP os_map[MAX_OS_MAPPINGS]; /* overstrike mapping entries */ -static int n_os_mappings; /* number of overstrike mappings */ - -static t_stat tti_svc(UNIT *uptr); -static t_stat tto_svc(UNIT *uptr); -static t_stat tti_reset(DEVICE *dptr); -static t_stat tto_reset(DEVICE *dptr); - -static t_stat emit_conout_character(int ch); -static t_stat map_conout_character(int ch); -static void reset_mapping (void); -static void set_conout_mapping(int32 flags); -static t_stat validate_conout_mapping(UNIT *uptr, int32 match, char *cvptr, void *desc); -static void set_default_mapping(int32 flags); -static void finish_conout_mapping(int32 flags); -static void strsort (int n, unsigned char *s); /* sorts an array of n characters */ -static int os_map_comp (OS_MAP *a, OS_MAP *b); /* compares two mapping entries */ -static t_stat font_cmd(int32 flag, char *cptr); /* handles font command */ -static void read_map_file(FILE *fd); /* reads a font map file */ -static t_bool str_match(char *str, char *keyword); /* keyword/string comparison */ -static char * handle_map_ansi_definition(char **pc); /* input line parsers for map file sections */ -static char * handle_map_input_definition(char **pc); -static char * handle_map_output_definition(char **pc); -static char * handle_map_overstrike_definition(char **pc); - -extern t_stat sim_poll_kbd(void); -extern t_stat sim_wait_kbd(void); -extern t_stat sim_putchar(int32 out); - -#define UNIT_V_CSET (UNIT_V_UF + 0) /* user flag: character set */ -#define UNIT_V_LOCKED (UNIT_V_UF + 2) /* user flag: keyboard locked */ -#define UNIT_V_ANSI (UNIT_V_UF + 3) - -#define CSET_ASCII (0u << UNIT_V_CSET) -#define CSET_1130 (1u << UNIT_V_CSET) -#define CSET_APL (2u << UNIT_V_CSET) -#define CSET_MASK (3u << UNIT_V_CSET) -#define ENABLE_ANSI (1u << UNIT_V_ANSI) - -#define KEYBOARD_LOCKED (1u << UNIT_V_LOCKED) - -#define IRQ_KEY 0x11 /* ctrl-Q */ -#define PROGRAM_STOP_KEY 0x10 /* ctrl-P */ - -#include "ibm1130_conout.h" /* conout_to_ascii table */ -#include "ibm1130_conin.h" /* ascii_to_conin table */ - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list -*/ - -UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 16) }, - { ORDATA (DSW, tti_dsw, 16) }, - { DRDATA (POS, tti_unit.pos, 31), PV_LEFT }, - { DRDATA (STIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti_mod[] = { - { CSET_MASK, CSET_ASCII, "ASCII", "ASCII", NULL}, - { CSET_MASK, CSET_1130, "1130", "1130", NULL}, - { 0 } }; - -DEVICE tti_dev = { - "KEYBOARD", &tti_unit, tti_reg, tti_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, basic_attach, NULL }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - - /* 14-Nov-03 -- the wait time was SERIAL_OUT_WAIT, but recent versions of SIMH reduced - * this to 100, and wouldn't you know it, APL\1130 has about 120 instructions between the XIO WRITE - * to the console and the associated WAIT. - */ - -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), 200 }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 16) }, - { ORDATA (DSW, tto_dsw, 16) }, - { DRDATA (POS, tto_unit.pos, 31), PV_LEFT }, - { DRDATA (STIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { CSET_MASK, CSET_ASCII, "ASCII", "ASCII", validate_conout_mapping, NULL, NULL}, - { CSET_MASK, CSET_1130, "1130", "1130", validate_conout_mapping, NULL, NULL}, - { CSET_MASK, CSET_APL, "APL", "APL", validate_conout_mapping, NULL, NULL}, - { ENABLE_ANSI,0, "NOANSI", "NOANSI", NULL}, - { ENABLE_ANSI,ENABLE_ANSI, "ANSI", "ANSI", NULL}, - { 0 } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, tto_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, basic_attach, NULL }; - -/* Terminal input routines - - tti_svc process event (character ready) - tti_reset process reset - tto_svc process event (print character) - tto_reset process reset -*/ - -#define TT_DSW_PRINTER_RESPONSE 0x8000 -#define TT_DSW_KEYBOARD_RESPONSE 0x4000 -#define TT_DSW_INTERRUPT_REQUEST 0x2000 -#define TT_DSW_KEYBOARD_CONSOLE 0x1000 -#define TT_DSW_PRINTER_BUSY 0x0800 -#define TT_DSW_PRINTER_NOT_READY 0x0400 -#define TT_DSW_KEYBOARD_BUSY 0x0200 - -void xio_1131_console (int32 iocc_addr, int32 func, int32 modify) -{ - int ch; - char msg[80]; - - switch (func) { - case XIO_CONTROL: - SETBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* select and unlock the keyboard */ - keyboard_selected(TRUE); - CLRBIT(tti_unit.flags, KEYBOARD_LOCKED); - tti_unit.buf = 0; /* no key character yet */ - break; - - case XIO_READ: - WriteW(iocc_addr, tti_unit.buf); /* return keycode */ - CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* this ends selected mode */ - keyboard_selected(FALSE); - SETBIT(tti_unit.flags, KEYBOARD_LOCKED); /* keyboard is locked when not selected */ - tti_unit.buf = 0; /* subsequent reads will return zero */ - break; - - case XIO_WRITE: - ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */ - tto_unit.buf = emit_conout_character(ch); /* output character and save write status */ - -/* fprintf(stderr, "[CONOUT] %02x\n", ch); */ - - SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY); - sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */ - break; - - case XIO_SENSE_DEV: - ACC = tto_dsw | tti_dsw; - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE); - CLRBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); - CLRBIT(tti_dsw, TT_DSW_INTERRUPT_REQUEST); - CLRBIT(ILSW[4], ILSW_4_CONSOLE); - } - break; - - default: - sprintf(msg, "Invalid console XIO function %x", func); - xio_error(msg); - } - -/* fprintf(stderr, "After XIO %04x %04x\n", tti_dsw, tto_dsw); */ -} - -/* emit_conout_character - write character with 1130 console code 'ch' */ - -t_stat emit_conout_character (int ch) -{ - t_stat status; - -#ifdef DEBUG_CONSOLE - printf("{%02x}", ch); -#endif - - if ((tto_unit.flags & CSET_MASK) == CSET_1130) /* 1130 (binary) mode, write the raw 8-bit value */ - return sim_putchar(ch); - - if (ch & COUT_IS_CTRL) { - /* red/black shift can be combined with another control */ - /* if present, emit the color shift characters alone */ - - if (ch & COUT_CTRL_BLACK) { - if ((status = map_conout_character(COUT_IS_CTRL|COUT_CTRL_BLACK)) != SCPE_OK) - return status; - } - else if (ch & COUT_CTRL_RED) { - if ((status = map_conout_character(COUT_IS_CTRL|COUT_CTRL_RED)) != SCPE_OK) - return status; - } - - ch &= ~(COUT_CTRL_BLACK|COUT_CTRL_RED); /* remove the ribbon shift bits */ - - if (ch & ~COUT_IS_CTRL) { /* if another control remains, emit it */ - if ((status = map_conout_character(ch)) != SCPE_OK) - return status; - } - - return SCPE_OK; - } - - return map_conout_character(ch); -} - -static void Beep (void) /* notify user keyboard was locked or key was bad */ -{ - sim_putchar(7); -} - -/* tti_svc - keyboard polling (never stops) */ - -static t_stat tti_svc (UNIT *uptr) -{ - int32 temp; - - if (cgi) /* if running in CGI mode, no keyboard and no keyboard polling! */ - return SCPE_OK; - /* otherwise, so ^E can interrupt the simulator, */ - sim_activate(&tti_unit, tti_unit.wait); /* always continue polling keyboard */ - - assert(sim_clock_queue != NULL); - - temp = sim_poll_kbd(); - - if (temp < SCPE_KFLAG) - return temp; /* no char or error? */ - - temp &= 0xFF; /* remove SCPE_KFLAG */ - - if ((tti_unit.flags & CSET_MASK) == CSET_ASCII) - temp = conin_map[temp] & 0xFF; /* perform input translation */ - - if (temp == IRQ_KEY) { /* INT REQ (interrupt request) key */ - SETBIT(tti_dsw, TT_DSW_INTERRUPT_REQUEST); /* queue interrupt */ - SETBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - - CLRBIT(tti_unit.flags, KEYBOARD_LOCKED); /* keyboard restore, according to func. char. manual */ - -#ifdef DEBUG_CONSOLE - printf("[*IRQ*]"); -#endif - tti_unit.buf = 0; /* subsequent reads need to return 0 (required by APL\1130) */ - return SCPE_OK; - } - - if (temp == PROGRAM_STOP_KEY) { /* simulate the program stop button */ - SETBIT(con_dsw, CPU_DSW_PROGRAM_STOP); - SETBIT(ILSW[5], ILSW_5_INT_RUN_PROGRAM_STOP); - calc_ints(); - -#ifdef DEBUG_CONSOLE - printf("[*PSTOP*]"); -#endif - - return SCPE_OK; - } - - if ((tti_unit.flags & KEYBOARD_LOCKED) || ! (tti_dsw & TT_DSW_KEYBOARD_BUSY)) { - Beep(); - return SCPE_OK; - } - - if ((tti_unit.flags & CSET_MASK) == CSET_ASCII) - temp = ascii_to_conin[temp]; - - if (temp == 0) { /* ignore invalid characters */ - Beep(); - calc_ints(); - return SCPE_OK; - } - - tti_unit.buf = temp & 0xFFFE; /* save keystroke except last bit (not defined) */ - tti_unit.pos = tti_unit.pos + 1; /* but it lets us distinguish 0 from no punch ' ' */ - -#ifdef DEBUG_CONSOLE - printf("[%04x]", tti_unit.buf & 0xFFFF); -#endif - - SETBIT(tti_unit.flags, KEYBOARD_LOCKED); /* prevent further keystrokes */ - - SETBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); /* queue interrupt */ - SETBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - -/* fprintf(stderr, "TTI interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw); */ - - return SCPE_OK; -} - -static t_stat tti_reset (DEVICE *dptr) -{ - tti_unit.buf = 0; - tti_dsw = 0; - - CLRBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - keyboard_selected(FALSE); - - SETBIT(tti_unit.flags, KEYBOARD_LOCKED); - - if (cgi) - sim_cancel(&tti_unit); /* in cgi mode, never poll keyboard */ - else - sim_activate(&tti_unit, tti_unit.wait); /* otherwise, always poll keyboard */ - - return SCPE_OK; -} - -/* basic_attach - fix quotes in filename, then call standard unit attach routine */ - -t_stat basic_attach (UNIT *uptr, char *cptr) -{ - return attach_unit(uptr, quotefix(cptr)); /* fix quotes in filenames & attach */ -} - -/* quotefix - strip off quotes around filename, if present */ - -char * quotefix (char * cptr) -{ -#ifdef WIN32 /* do this only for Windows builds, for the time being */ - char *c; - int quote; - - if (*cptr == '"' || *cptr == '\'') { - quote = *cptr++; /* remember quote and skip over it */ - - for (c = cptr; *c && *c != quote; c++) - ; /* find closing quote, or end of string */ - - if (*c) /* terminate string at closing quote */ - *c = '\0'; - } - -#endif - return cptr; /* return pointer to cleaned-up name */ -} - -t_bool keyboard_is_busy (void) /* return TRUE if keyboard is not expecting a character */ -{ - return (tti_dsw & TT_DSW_KEYBOARD_BUSY); -} - -static t_stat tto_svc (UNIT *uptr) -{ - CLRBIT(tto_dsw, TT_DSW_PRINTER_BUSY); - SETBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE); - - SETBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - -/* fprintf(stderr, "TTO interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw); */ - - return (t_stat) tto_unit.buf; /* return status saved during output conversion */ -} - -static t_stat tto_reset (DEVICE *dptr) -{ - tto_unit.buf = 0; - tto_dsw = 0; - - CLRBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - - sim_cancel(&tto_unit); /* deactivate unit */ - - set_conout_mapping(tto_unit.flags); /* initialize the overstrike mappings */ - /* register the font-mapping command */ - register_cmd("FONT", font_cmd, 0, "font MAPFILE use font mapping definitions in MAPFILE\n"); - - return SCPE_OK; -} - -#ifdef _MSC_VER -# pragma warning(disable:4245) /* enable int->char demotion warning caused by characters with high-bit set */ -#endif - -static struct { /* default input mapping for APL */ - unsigned char in; - unsigned char out; -} conin_to_APL[] = -{ /* these map input keys to those in like positions on 1130 keyboard */ - '[', '\r', /* enter (EOF) is APL left arrow */ - ';', '\b', /* backspace is APL [ */ - '\'', '\x15', /* ctrl-U, erase field, is APL ]*/ - '2', '@', /* APL upshift */ - '3', '%', /* APL rightshift */ - '4', '*', /* APL + and - */ - '5', '<', /* APL x and divide */ - '8', '-', /* APL return */ - '9', '/', /* APL backspace */ - '-', IRQ_KEY, /* ctrl-q (INT REQ), APL ATTN */ - '\r', '-', /* APL return */ - '\b', '/' /* APL backspace */ -}; - -#define NCONIN_TO_APL (sizeof(conin_to_APL)/sizeof(conin_to_APL[0])) - -static struct { /* default output mapping for APLPLUS font */ - unsigned char in; - unsigned char out; -} conout_to_APL[] = -{ - '\x01', IGNR_, /* controls */ - '\x03', '\n', - '\x05', IGNR_, /* (black and red are handled by ansi sequences) */ - '\x09', IGNR_, - '\x11', '\b', - '\x21', ' ', - '\x41', '\t', - '\x81', CRLF_, - - '\xC4', '\x30', /* (if you're curious, order here is position on APL typeball) */ - '\xE4', '\x38', - '\xD4', '\x37', - '\xF4', '\x35', - '\xDC', '\x33', - '\xFC', '\x31', - '\xC2', '\x29', - '\xE2', '\x9F', - '\xD2', '\x89', - '\xF2', '\x88', - '\xDA', '\xAF', - '\xC6', '\x5E', - '\xE6', '\xAC', - '\xD6', '\x3E', - '\xF6', '\x3D', - '\xDE', '\x3C', - '\xFE', '\xA8', - '\xC0', '\x5D', - '\xE0', '\x39', - '\xD0', '\x36', - '\xF0', '\x34', - '\xD8', '\x32', - - '\x84', '\x84', - '\xA4', '\x59', - '\x94', '\x58', - '\xB4', '\x56', - '\x9C', '\x54', - '\xBC', '\x2F', - '\x82', '\x3B', - '\xA2', '\x9B', - '\x92', '\xBE', - '\xB2', '\x87', - '\x9A', '\x97', - '\x86', '\x85', - '\xA6', '\x86', - '\x96', '\x9C', - '\xB6', '\x9E', - '\x9E', '\x7E', - '\xBE', '\x5C', - '\x80', '\x2C', - '\xA0', '\x5A', - '\x90', '\x57', - '\xB0', '\x55', - '\x98', '\x53', - - '\x44', '\x2B', - '\x64', '\x51', - '\x54', '\x50', - '\x74', '\x4E', - '\x5C', '\x4C', - '\x7C', '\x4A', - '\x42', '\x28', - '\x62', '\xBD', - '\x52', '\xB1', - '\x72', '\x7C', - '\x5A', '\x27', - '\x46', '\x2D', - '\x66', '\x3F', - '\x56', '\x2A', - '\x76', '\x82', - '\x5E', '\x8C', - '\x7E', '\xB0', - '\x40', '\x5B', - '\x60', '\x52', - '\x50', '\x4F', - '\x70', '\x4D', - '\x58', '\x4B', - - '\x04', '\xD7', - '\x24', '\x48', - '\x14', '\x47', - '\x34', '\x45', - '\x1C', '\x43', - '\x3C', '\x41', - '\x02', '\x3A', - '\x22', '\xBC', - '\x12', '\x5F', - '\x32', '\x98', - '\x1A', '\x83', - '\x06', '\xF7', - '\x26', '\x91', - '\x16', '\x92', - '\x36', '\xB9', - '\x1E', '\x9D', - '\x3E', '\xB8', - '\x00', '\x2E', - '\x20', '\x49', - '\x10', '\x46', - '\x30', '\x44', - '\x18', '\x42', -}; - -#define NCONOUT_TO_APL (sizeof(conout_to_APL)/sizeof(conout_to_APL[0])) - -static OS_MAP default_os_map[] = /* overstrike mapping for APLPLUS font */ -{ - '\x8a', 2, "\x5e\x7e", - '\x8b', 2, "\x9f\x7e", - '\x8d', 2, "\x8c\x27", - '\x8e', 3, "\x8c\x2d\x3a", - '\x8f', 2, "\x91\x5f", - '\x90', 2, "\x92\x7e", - '\x93', 2, "\x91\x7c", - '\x94', 2, "\x92\x7c", - '\x95', 2, "\xb0\x82", - '\x96', 2, "\xb0\x83", - '\x99', 2, "\x2d\x5c", - '\x9a', 2, "\x2d\x2f", - '\xae', 2, "\x2c\x2d", - '\xb2', 2, "\xb1\x7c", - '\xb3', 2, "\xb1\x5c", - '\xb4', 2, "\xb1\x2d", - '\xb5', 2, "\xb1\x2a", - '\xba', 2, "\xb9\x5f", - '\xd0', 2, "\x30\x7e", - '\xd8', 2, "\x4f\x2f", - '\x21', 2, "\x27\x2e", - '\xa4', 2, "\xb0\xb1", /* map degree in circle to circle cross (APL uses this as character error symbol) */ - '\xf0', 2, "\xb0\xa8", - '\xfe', 2, "\x3a\xa8", -}; - -#ifdef _MSC_VER -# pragma warning(default:4245) /* enable int->char demotion warning */ -#endif - -/* os_map_comp - compare to OS_MAP entries */ - -static int os_map_comp (OS_MAP *a, OS_MAP *b) -{ - unsigned char *sa, *sb; - int i; - - if (a->nin > b->nin) - return +1; - - if (a->nin < b->nin) - return -1; - - sa = a->inlist; - sb = b->inlist; - - for (i = a->nin; --i >= 0;) { - if (*sa > *sb) - return +1; - - if (*sa < *sb) - return -1; - - sa++; - sb++; - } - - return 0; -} - -/* strsort - sorts the n characters of array 's' using insertion sort */ - -static void strsort (int n, unsigned char *s) -{ - unsigned char temp; - int i, big; - - while (--n > 0) { /* repeatedly */ - big = 0; /* find largest value of s[0]...s[n] */ - for (i = 1; i <= n; i++) - if (s[i] > s[big]) big = i; - - temp = s[n]; /* put largest value at end of array */ - s[n] = s[big]; - s[big] = temp; - } -} - -/* file format: - -[font XXX] font named XXX -OUT failure character -OUT IN single character mapping -OUT IN IN ... overstrike mapping - -*/ - -static void set_conout_mapping (int32 flags) -{ - curcol = 0; - maxcol = 0; - - /* set the default mappings. We may later override them with settings from an ini file */ - - set_default_mapping(flags); -} - -/* finish_conout_mapping - sort the finalized overstrike mapping */ - -static void finish_conout_mapping (int32 flags) -{ - int i, n, big; - OS_MAP temp; - - for (i = 0; i < n_os_mappings; i++) /* sort the inlist strings individually */ - strsort(os_map[i].nin, os_map[i].inlist); - - for (n = n_os_mappings; --n > 0; ) { /* then sort the os_map array itself with insertion sort */ - big = 0; /* find largest value of s[0]...s[n] */ - for (i = 1; i <= n; i++) - if (os_map_comp(os_map+i, os_map+big) > 0) big = i; - - if (big != n) { - temp = os_map[n]; /* put largest value at end of array */ - os_map[n] = os_map[big]; - os_map[big] = temp; - } - } -} - -/* validate_conout_mapping - called when set command gets a new value */ - -static t_stat validate_conout_mapping (UNIT *uptr, int32 match, char *cvptr, void *desc) -{ - set_conout_mapping(match); - return SCPE_OK; -} - -static void reset_mapping (void) -{ - int i; - - black_ribbon[0] = '\0'; /* erase the ribbon sequences */ - red_ribbon[0] = '\0'; - - memset(conout_map, 0, sizeof(conout_map)); /* erase output mapping */ - - n_os_mappings = 0; /* erase overstrike mapping */ - - for (i = (sizeof(conin_map)/sizeof(conin_map[0])); --i >= 0; ) - conin_map[i] = (unsigned char) i; /* default conin_map is identity map */ -} - -/* set_default_mapping - create standard font and overstrike map */ - -static void set_default_mapping (int32 flags) -{ - int i; - - reset_mapping(); - - strcpy((char *) black_ribbon, "\033[30m"); - strcpy((char *) red_ribbon, "\033[31m"); - - switch (flags & CSET_MASK) { - case CSET_1130: - break; - - case CSET_ASCII: - memcpy(conout_map, conout_to_ascii, sizeof(conout_to_ascii)); - break; - - case CSET_APL: - for (i = NCONOUT_TO_APL; --i >= 0; ) - conout_map[conout_to_APL[i].in] = conout_to_APL[i].out; - - for (i = NCONIN_TO_APL; --i >= 0; ) - conin_map[conin_to_APL[i].in] = conin_to_APL[i].out; - - memcpy(os_map, default_os_map, sizeof(default_os_map)); - n_os_mappings = (sizeof(default_os_map) / sizeof(default_os_map[0])); - break; - } - - finish_conout_mapping(flags); /* sort conout mapping if necessary */ -} - -/* sim_putstr - write a string to the console */ - -t_stat sim_putstr (char *s) -{ - t_stat status; - - while (*s) { - if ((status = sim_putchar(*s)) != SCPE_OK) - return status; - - s++; - } - - return SCPE_OK; -} - -/* map_conout_character - translate and write a single character */ - -static t_stat map_conout_character (int ch) -{ - t_stat status; - int i, cmp; - - if (ch == (COUT_IS_CTRL|COUT_CTRL_BLACK)) - return (tto_unit.flags & ENABLE_ANSI) ? sim_putstr((char *) black_ribbon) : SCPE_OK; - - if (ch == (COUT_IS_CTRL|COUT_CTRL_RED)) - return (tto_unit.flags & ENABLE_ANSI) ? sim_putstr((char *) red_ribbon) : SCPE_OK; - - if ((ch = conout_map[ch & 0xFF]) == 0) - ch = '?'; /* unknown character? print ? */ - - if (ch == '\n') { /* newline: reset overstrike buffer */ - curcol = 0; - maxcol = -1; - } - else if (ch == '\r') { /* carriage return: rewind to column 0 */ - curcol = 0; - maxcol = -1; /* assume it advances paper too */ - } - else if (ch == '\b') { /* backspace: back up one character */ - if (curcol > 0) - curcol--; - } - else if (n_os_mappings && ch != (unsigned char) IGNR_) { - if (curcol >= MAX_OUTPUT_COLUMNS) - map_conout_character('\x81'); /* precede with automatic carriage return/line feed, I guess */ - - if (curcol > maxcol) { /* first time in this column, no overstrike possible yet */ - os_buf[curcol].nin = 0; - maxcol = curcol; - } - - if (ch != ' ' && ch != 0) { /* (if it's not a blank or unknown) */ - os_buf[curcol].inlist[os_buf[curcol].nin] = (unsigned char) ch; - strsort(++os_buf[curcol].nin, os_buf[curcol].inlist); - } - - if (os_buf[curcol].nin == 0) /* if nothing but blanks seen, */ - ch = ' '; /* output is a blank */ - else if (os_buf[curcol].nin == 1) { /* if only one printing character seen, display it */ - ch = os_buf[curcol].inlist[0]; - } - else { /* otherwise look up mapping */ - ch = '?'; - - for (i = 0; i < n_os_mappings; i++) { - cmp = os_map_comp(&os_buf[curcol], &os_map[i]); - if (cmp == 0) { /* a hit */ - ch = os_map[i].ch; - break; - } - else if (cmp < 0) /* not found */ - break; - } - } - - if (curcol < MAX_OUTPUT_COLUMNS) /* this should now never happen, as we automatically return */ - curcol++; - } - - switch (ch) { - case IGNR_: - break; - - case CRLF_: - if (! cgi) { - if ((status = sim_putchar('\r')) != SCPE_OK) - return status; - - tto_unit.pos++; - } - - if ((status = sim_putchar('\n')) != SCPE_OK) - return status; - - tto_unit.pos++; /* hmm, why do we count these? */ - break; - - default: - if ((status = sim_putchar(ch)) != SCPE_OK) - return status; - - tto_unit.pos++; - break; - } - - return SCPE_OK; -} - -/* font_cmd - parse a font mapping file. Sets input and output translations */ - -static t_stat font_cmd (int32 flag, char *cptr) -{ - char *fname, quote; - FILE *fd; - - while (*cptr && (*cptr <= ' ')) cptr++; /* skip blanks */ - if (! *cptr) return SCPE_2FARG; /* argument missing */ - - fname = cptr; /* save start */ - if (*cptr == '\'' || *cptr == '"') { /* quoted string */ - quote = *cptr++; /* remember quote character */ - fname++; /* skip the quote */ - - while (*cptr && (*cptr != quote)) /* find closing quote */ - cptr++; - } - else { - while (*cptr && (*cptr > ' ')) /* find terminating blank */ - cptr++; - } - *cptr = '\0'; /* terminate name */ - - if ((fd = fopen(fname, "r")) == NULL) - return SCPE_OPENERR; - - reset_mapping(); /* remove all default mappings */ - - read_map_file(fd); - fclose(fd); - - finish_conout_mapping(tto_unit.flags); - return SCPE_OK; -} - -/* str_match - compare the string str to the keyword, case insensitive */ - -static t_bool str_match (char *str, char *keyword) -{ - char kch, sch; - - while (*keyword) { /* see if str matches the keyword... */ - kch = *keyword++; /* get pair of characters */ - sch = *str++; - - if (BETWEEN(kch, 'A', 'Z')) kch += 32; /* change upper to lower case */ - if (BETWEEN(sch, 'A', 'Z')) sch += 32; - - if (kch != sch) /* characters must match; if not, quit */ - return FALSE; - } - - return *str <= ' ' || *str == ';'; /* success if the input string ended or is in whitespace or comment */ -} - -/* read_map_file - process definition lines in opened mapping file */ - -static void read_map_file (FILE *fd) -{ - char str[256], *c, *errmsg; - int lineno = 0; - enum {SECT_UNDEFINED, SECT_DEFAULT, SECT_ANSI, SECT_INPUT, SECT_OUTPUT, SECT_OVERSTRIKE} - section = SECT_UNDEFINED; - - while (fgets(str, sizeof(str), fd) != NULL) { - ++lineno; /* count input lines */ - - if ((c = strchr(str, '\n')) != NULL) /* terminate at newline */ - *c = '\0'; - - for (c = str; *c && *c <= ' '; c++) /* skip blanks */ - ; - - if (c[0] == '\0' || c[0] == ';') /* ignore blank lines and lines starting with ; */ - continue; - - if (*c == '[') { - if (str_match(c, "[default]")) { /* check for section separators */ - set_default_mapping(tto_unit.flags); - section = SECT_UNDEFINED; - continue; - } - if (str_match(c, "[ansi]")) { - section = SECT_ANSI; - continue; - } - if (str_match(c, "[input]")) { - section = SECT_INPUT; - continue; - } - if (str_match(c, "[output]")) { - section = SECT_OUTPUT; - continue; - } - if (str_match(c, "[overstrike]")) { - section = SECT_OVERSTRIKE; - continue; - } - } - - switch (section) { /* if we get here, we have a definition line */ - case SECT_ANSI: - errmsg = handle_map_ansi_definition(&c); - break; - case SECT_INPUT: - errmsg = handle_map_input_definition(&c); - break; - case SECT_OUTPUT: - errmsg = handle_map_output_definition(&c); - break; - case SECT_OVERSTRIKE: - errmsg = handle_map_overstrike_definition(&c); - break; - default: - errmsg = "line occurs before valid [section]"; - break; - } - - if (errmsg == NULL) { /* if no other error detected, */ - while (*c && *c <= ' ') /* skip past any whitespace */ - c++; - - if (*c && *c != ';') /* if line doesn't end or run into a comment, complain */ - errmsg = "too much stuff on input line"; - } - - if (errmsg != NULL) { /* print error message and offending line */ - printf("* Warning: %s", errmsg); - - switch (section) { /* add section name if possible */ - case SECT_ANSI: errmsg = "ansi"; break; - case SECT_INPUT: errmsg = "input"; break; - case SECT_OUTPUT: errmsg = "output"; break; - case SECT_OVERSTRIKE: errmsg = "overstrike"; break; - default: errmsg = NULL; break; - } - if (errmsg != NULL) - printf(" in [%s] section", errmsg); - - printf(", line %d\n%s\n", lineno, str); - } - } -} - -/* get_num_char - read an octal or hex character specification of exactly 'ndigits' digits - * the input pointers is left pointing to the last character of the number, so that it - * may be incremented by the caller - */ - -static char * get_num_char (char **pc, unsigned char *out, int ndigits, int base, char *errmsg) -{ - int ch = 0, digit; - char *c = *pc; - - while (--ndigits >= 0) { /* collect specified number of digits */ - if (BETWEEN(*c, '0', '9')) - digit = *c - '0'; - else if (BETWEEN(*c, 'A', 'F')) - digit = *c - 'A' + 10; - else if (BETWEEN(*c, 'a', 'f')) - digit = *c - 'a' + 10; - else - digit = base; - - if (digit >= base) /* bad digit */ - return errmsg; - - ch = ch * base + digit; /* accumulate digit */ - c++; - } - - *out = (unsigned char) ch; /* return parsed character */ - *pc = c-1; /* make input pointer point to last character seen */ - return NULL; /* no error */ -} - -/* get_characters - read character specification(s) from input string pointed to - * by *pc. Results stored in outstr; up to nmax characters parsed. Actual number - * found returned in *nout. Returns NULL on success or error message if syntax - * error encountered. *pc is advanced to next whitespace or whatever followed input. - */ - -static char * get_characters (char **pc, unsigned char *outstr, int nmax, int *nout) -{ - char *c = *pc, *errstr; - unsigned char *out = outstr; - - while (*c && *c <= ' ') /* skip leading whitespace */ - c++; - - while (--nmax >= 0) { /* get up to maximum number of characters */ - if (*c == ';' || *c <= ' ') /* we ran into a comment, whitespace or end of string: we're done */ - break; - - if (*c == '\\') { /* backslash escape of some sort */ - switch (*++c) { - case 'b': /* backspace */ - case 'B': - *out++ = '\b'; - break; - - case 'e': /* ascii ESCAPE */ - case 'E': - *out++ = '\033'; - break; - - case 'f': /* formfeed */ - case 'F': - *out++ = '\f'; - break; - - case 'n': /* newline */ - case 'N': - *out++ = '\n'; - break; - - case 'r': /* return */ - case 'R': - *out++ = '\r'; - break; - - case 't': /* tab */ - case 'T': - *out++ = '\t'; - break; - - case 'x': /* hex specification */ - case 'X': - c++; - if ((errstr = get_num_char(&c, out, 2, 16, "bad hex character")) != NULL) - return errstr; - - out++; /* advance out pointer */ - break; - - default: /* anything else */ - if (BETWEEN(*c, '0', '7')) { /* octal specification */ - if ((errstr = get_num_char(&c, out, 3, 8, "bad octal character")) != NULL) - return errstr; - - out++; /* advance out pointer */ - } - else if (BETWEEN(*c, 'A', 'Z') || BETWEEN(*c, 'a', 'z')) - return "invalid \\ escape"; /* other \x letters are bad */ - else { - *out++ = (unsigned char) *c;/* otherwise, accept \x as literal character x */ - } - break; - } - } - else if (*c == '^') { /* control character */ - c++; - if (BETWEEN(*c, 'A', 'Z')) /* convert alpha, e.g. A -> 1 */ - *out++ = (unsigned char) (*c - 'A' + 1); - else if (BETWEEN(*c, 'a', 'z')) - *out++ = (unsigned char) (*c - 'z' + 1); - else /* non alpha is bad */ - return "invalid control letter"; - } - else if (str_match(c, "IGNORE")) { /* magic word: a character that will never be output */ - *out++ = (unsigned char) IGNR_; - c += 6; - } - else { - *out++ = (unsigned char) *c; /* save literal character */ - } - - c++; - } - - if (*c && *c != ';' && *c > ' ') /* we should be at end of string, whitespace or comment */ - return "too many characters specified"; - - *pc = c; /* save advanced pointer */ - *nout = out-outstr; /* save number of characters stored */ - - return NULL; /* no error */ -} - -/* handle_map_ansi_definition - process line in [ansi] section */ - -static char * handle_map_ansi_definition (char **pc) -{ - unsigned char *outstr; - char *errmsg; - int n; - - if (str_match(*pc, "black")) { /* find which string we're setting */ - outstr = black_ribbon; /* this is where we'll save the output string */ - *pc += 5; /* skip over the token */ - } - else if (str_match(*pc, "red")) { - outstr = red_ribbon; - *pc += 3; - } - else - return "invalid variable name"; - /* get list of characters */ - if ((errmsg = get_characters(pc, outstr, sizeof(black_ribbon)-1, &n)) != NULL) - return errmsg; - - outstr[n] = '\0'; /* null terminate the string */ - - return (n > 0) ? NULL : "missing output string"; /* NULL if OK, error msg if no characters */ -} - -/* handle_map_input_definition - process line in [input] section */ - -static char * handle_map_input_definition (char **pc) -{ - unsigned char cin, cout; - char *errmsg; - int n; - - if ((errmsg = get_characters(pc, &cin, 1, &n)) != NULL) /* get input character */ - return errmsg; - - if (n != 1) - return "missing input character"; - - if ((errmsg = get_characters(pc, &cout, 1, &n)) != NULL) /* get output character */ - return errmsg; - - if (n != 1) - return "missing output character"; - - conin_map[cin] = cout; /* set the mapping */ - return NULL; -} - -/* handle_map_output_definition - process line in [output] section */ - -static char * handle_map_output_definition (char **pc) -{ - unsigned char cin, cout; - char *errmsg; - int n; - - if ((errmsg = get_characters(pc, &cin, 1, &n)) != NULL) /* get input character */ - return errmsg; - - if (n != 1) - return "missing input character"; - - if ((errmsg = get_characters(pc, &cout, 1, &n)) != NULL) /* get output character */ - return errmsg; - - if (n != 1) - return "missing output character"; - - conout_map[cin] = cout; /* set the mapping */ - return NULL; -} - -/* handle_map_overstrike_definition - process line in [overstrike] section */ - -static char * handle_map_overstrike_definition (char **pc) -{ - unsigned char ch, inlist[MAX_OS_CHARS]; - char *errmsg; - int nin; - - if (n_os_mappings >= MAX_OS_MAPPINGS) /* os_map is full, no more room */ - return "too many overstrike mappings"; - /* get output character */ - if ((errmsg = get_characters(pc, &ch, 1, &nin)) != NULL) - return errmsg; - - if (nin != 1) - return "missing output character"; - /* get input list */ - if ((errmsg = get_characters(pc, inlist, MAX_OS_CHARS, &nin)) != NULL) - return errmsg; - - if (nin < 2) /* expect at least two characters overprinted */ - return "missing input list"; - - os_map[n_os_mappings].ch = ch; /* save in next os_map slot */ - os_map[n_os_mappings].nin = nin; - memmove(os_map[n_os_mappings].inlist, inlist, nin); - - n_os_mappings++; - return NULL; -} diff --git a/Ibm1130/ibm1130_sys.c b/Ibm1130/ibm1130_sys.c deleted file mode 100644 index 2fefc52c..00000000 --- a/Ibm1130/ibm1130_sys.c +++ /dev/null @@ -1,507 +0,0 @@ -/* ibm1130_sys.c: IBM 1130 simulator interface - - Based on PDP-11 simulator written by Robert M Supnik - - Revision History - 0.27 2005Mar08 - Added sca device - 0.26 2002Apr24 - Added !BREAK in card deck file to stop simulator - 0.25 2002Apr18 - Fixed some card reader problems. It starts the reader - properly if you attach a deck while it's waiting to a read. - 0.24 2002Mar27 - Fixed BOSC bug; BOSC works in short instructions too - 0.23 2002Feb26 - Added @decklist feature for ATTACH CR. - 0.22 2002Feb26 - Replaced "strupr" with "upcase" for compatibility. - 0.21 2002Feb25 - Some compiler compatibiity changes, couple of compiler-detected - bugs - 0.01 2001Jul31 - Derived from pdp11_sys.c, which carries this disclaimer: - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#include "ibm1130_defs.h" -#include -#include - -extern DEVICE cpu_dev, console_dev, dsk_dev, cr_dev, cp_dev, ptr_dev, ptp_dev, t2741_dev; -extern DEVICE tti_dev, tto_dev, prt_dev, log_dev, sca_dev; -extern DEVICE gdu_dev, console_dev, plot_dev; - -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern int32 saved_PC; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "IBM 1130"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &cpu_dev, /* the cpu */ - &dsk_dev, /* disk drive(s) */ - &cr_dev, /* card reader/punch */ - &cp_dev, - &tti_dev, /* console keyboard, selectric printer */ - &tto_dev, - &prt_dev, /* 1132 printer */ - &ptr_dev, /* 1134 paper tape reader */ - &ptp_dev, /* 1055 paper tape punch */ - &sca_dev, /* Synchronous communications adapter option */ - &console_dev, /* console display (windows GUI) */ - &gdu_dev, /* 2250 display */ - &t2741_dev, /* nonstandard serial interface used by APL\1130 */ - &plot_dev, /* plotter device, in ibm1130_plot.c */ - NULL -}; - -const char *sim_stop_messages[] = { - "Unknown error", - "Wait", - "Invalid command", - "Simulator breakpoint", - "Use of incomplete simulator function", - "Power off", - "!BREAK in card deck file", - "Phase load break", - "Program has run amok", - "Run time limit exceeded", - "Immediate Stop key requested", - "Simulator break key pressed", - "Simulator step count expired", - "Simulator IO error", -}; - -/* Loader. IPL is normally performed by card reader (boot command). This function - * loads hex data from a file for testing purposes. The format is: - * - * blank lines or lines starting with ; / or # are ignored as comments - * - * @XXXX set load addresss to hex value XXXX - * XXXX store hex word value XXXX at current load address and increment address - * ... - * =XXXX set IAR to hex value XXXX - * ZXXXX zero XXXX words and increment load address - * SXXXX set console entry switches to XXXX. This lets a program specify the - * default value for the toggle switches. - * - * Multiple @ and data sections may be entered. If more than one = or S value is specified - * the last one wins. - * - * Note: the load address @XXXX and data values XXXX can be followed by the letter - * R to indicate that the values are relocatable addresses. This is ignored in this loader, - * but the asm1130 cross assembler may put them there. - */ - -t_stat my_load (FILE *fileref, char *cptr, char *fnam) -{ - char line[150], *c; - int iaddr = -1, runaddr = -1, val, nwords; - - while (fgets(line, sizeof(line), fileref) != NULL) { - for (c = line; *c && *c <= ' '; c++) /* find first nonblank */ - ; - - if (*c == '\0' || *c == '#' || *c == '/' || *c == ';') - continue; /* empty line or comment */ - - if (*c == '@') { /* set load address */ - if (sscanf(c+1, "%x", &iaddr) != 1) - return SCPE_FMT; - } - else if (*c == '=') { - if (sscanf(c+1, "%x", &runaddr) != 1) - return SCPE_FMT; - } - else if (*c == 's' || *c == 'S') { - if (sscanf(c+1, "%x", &val) != 1) - return SCPE_FMT; - - CES = val & 0xFFFF; /*preload console entry switches */ - } - else if (*c == 'z' || *c == 'Z') { - if (sscanf(c+1, "%x", &nwords) != 1) - return SCPE_FMT; - - if (iaddr == -1) - return SCPE_FMT; - - while (--nwords >= 0) { - WriteW(iaddr, 0); - iaddr++; - } - } - else if (strchr("0123456789abcdefABCDEF", *c) != NULL) { - if (sscanf(c, "%x", &val) != 1) - return SCPE_FMT; - - if (iaddr == -1) - return SCPE_FMT; - - WriteW(iaddr, val); /*store data */ - iaddr++; - } - else - return SCPE_FMT; /*unexpected data */ - } - - if (runaddr != -1) - IAR = runaddr; - - return SCPE_OK; -} - -t_stat my_save (FILE *fileref, char *cptr, char *fnam) -{ - int iaddr, nzeroes = 0, nwords = (int) (MEMSIZE/2), val; - - fprintf(fileref, "=%04x\r\n", IAR); - fprintf(fileref, "@0000\r\n"); - for (iaddr = 0; iaddr < nwords; iaddr++) { - val = ReadW(iaddr); - if (val == 0) /*queue up zeroes */ - nzeroes++; - else { - if (nzeroes >= 4) { /*spit out a Z directive */ - fprintf(fileref, "Z%04x\r\n", nzeroes); - nzeroes = 0; - } - else { /*write queued zeroes literally */ - while (nzeroes > 0) { - fprintf(fileref, " 0000\r\n"); - nzeroes--; - } - } - fprintf(fileref, " %04x\r\n", val); - } - } - if (nzeroes >= 4) { /*emit any queued zeroes */ - fprintf(fileref, "Z%04x\r\n", nzeroes); - nzeroes = 0; - } - else { - while (nzeroes > 0) { - fprintf(fileref, " 0000\r\n"); - nzeroes--; - } - } - - return SCPE_OK; -} - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ - if (flag) - return my_save(fileref, cptr, fnam); - else - return my_load(fileref, cptr, fnam); -} - -/* Specifier decode - - Inputs: - *of = output stream - addr = current PC - spec = specifier - nval = next word - flag = TRUE if decoding for CPU - iflag = TRUE if decoding integer instruction - Outputs: - count = -number of extra words retired -*/ - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = values to decode - *uptr = pointer to unit - sw = switches - Outputs: - return = if >= 0, error code - if < 0, number of extra words retired -*/ - -static char *opcode[] = { - "?00 ", "XIO ", "SLA ", "SRA ", - "LDS ", "STS ", "WAIT", "?07 ", - "BSI ", "BSC ", "?0A ", "?0B ", - "LDX ", "STX ", "MDX ", "?0F ", - "A ", "AD ", "S ", "SD ", - "M ", "D ", "?16 ", "?17 ", - "LD ", "LDD ", "STO ", "STD ", - "AND ", "OR ", "EOR ", "?1F ", -}; - -static char relative[] = { /*true if short mode displacements are IAR relative */ - FALSE, TRUE, FALSE, FALSE, - FALSE, TRUE, FALSE, FALSE, - TRUE, FALSE, FALSE, FALSE, - TRUE, TRUE, TRUE, FALSE, - TRUE, TRUE, TRUE, TRUE, - TRUE, TRUE, FALSE, FALSE, - TRUE, TRUE, TRUE, TRUE, - TRUE, TRUE, TRUE, FALSE -}; - -static char *lsopcode[] = {"SLA ", "SLCA ", "SLT ", "SLC "}; -static char *rsopcode[] = {"SRA ", "?188 ", "SRT ", "RTE "}; -static char tagc[] = " 123"; - -static int ascii_to_ebcdic_table[128] = -{ - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, - - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -static int ebcdic_to_ascii (int ch) -{ - int j; - - for (j = 32; j < 128; j++) - if (ascii_to_ebcdic_table[j] == ch) - return j; - - return '?'; -} - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) -{ - int32 cflag, ch, OP, F, TAG, INDIR, DSPLC, IR, eaddr; - char *mnem, tst[12]; - - cflag = (uptr == NULL) || (uptr == &cpu_unit); - -/* if (sw & SWMASK ('A')) { // ASCII? not useful - fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); - return SCPE_OK; - } -*/ - - if (sw & SWMASK ('C')) /* character? not useful -- make it EBCDIC */ - sw |= SWMASK('E'); - - if (sw & SWMASK ('E')) { /* EBCDIC! */ - ch = ebcdic_to_ascii((val[0] >> 8) & 0xFF); /* take high byte first */ - fprintf (of, (ch < ' ')? "<%03o>": "%c", ch); - ch = ebcdic_to_ascii(val[0] & 0xFF); - fprintf (of, (ch < ' ')? "<%03o>": "%c", ch); - return SCPE_OK; - } - - if (sw & SWMASK ('H')) { /* HOLLERITH! now THIS is useful! */ - ch = hollerith_to_ascii((int16) val[0]); - fprintf (of, (ch < ' ')? "<%03o>": "%c", ch); - return SCPE_OK; - } - - if (! (sw & SWMASK ('M'))) - return SCPE_ARG; - - IR = val[0]; - OP = (IR >> 11) & 0x1F; /* opcode */ - F = IR & 0x0400; /* format bit: 1 = long instr */ - TAG = IR & 0x0300; /* tag bits: index reg select */ - if (TAG) - TAG >>= 8; - - if (F) { /* long instruction, ASSUME it's valid (have to decrement IAR if not) */ - INDIR = IR & 0x0080; /* indirect bit */ - DSPLC = IR & 0x007F; /* displacement or modifier */ - if (DSPLC & 0x0040) - DSPLC |= ~ 0x7F; /* sign extend */ - - eaddr = val[1]; /* get reference address */ - } - else { /* short instruction, use displacement */ - INDIR = 0; /* never indirect */ - DSPLC = IR & 0x00FF; /* get displacement */ - if (DSPLC & 0x0080) - DSPLC |= ~ 0xFF; - - eaddr = DSPLC; - if (relative[OP] && ! TAG) - eaddr += addr+1; /* turn displacement into address */ - } - - mnem = opcode[OP]; /* get mnemonic */ - if (OP == 0x02) { /* left shifts are special */ - mnem = lsopcode[(DSPLC >> 6) & 0x0003]; - DSPLC &= 0x003F; - eaddr = DSPLC; - } - else if (OP == 0x03) { /* right shifts too */ - mnem = rsopcode[(DSPLC >> 6) & 0x0003]; - DSPLC &= 0x003F; - eaddr = DSPLC; - } - else if ((OP == 0x08 && F)|| OP == 0x09) { /* BSI L and BSC any */ - if (OP == 0x09 && (IR & 0x40)) - mnem = "BOSC"; - - tst[0] = '\0'; - if (DSPLC & 0x20) strcat(tst, "Z"); - if (DSPLC & 0x10) strcat(tst, "-"); - if (DSPLC & 0x08) strcat(tst, "+"); - if (DSPLC & 0x04) strcat(tst, "E"); - if (DSPLC & 0x02) strcat(tst, "C"); - if (DSPLC & 0x01) strcat(tst, "O"); - - if (F) { - fprintf(of, "%04x %s %c%c %s,%04x ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], tst, eaddr & 0xFFFF); - return -1; - } - fprintf(of, "%04x %s %c%c %s ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], tst); - return SCPE_OK; - } - else if (OP == 0x0e && TAG == 0) { /* MDX with no tag => MDM or jump */ - if (F) { - fprintf(of, "%04x %s %c%c %04x,%x (%d) ", IR & 0xFFFF, "MDM ", (INDIR ? 'I' : 'L'), tagc[TAG], eaddr & 0xFFFF, DSPLC & 0xFFFF, DSPLC); - return -1; - } - mnem = "JMP "; - } - - fprintf(of, "%04x %s %c%c %04x ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], eaddr & 0xFFFF); - return F ? -1 : SCPE_OK; /* inform how many words we read */ -} - -int32 get_reg (char *cptr, const char *strings[], char mchar) -{ -return -1; -} - -/* Number or memory address - - Inputs: - *cptr = pointer to input string - *dptr = pointer to output displacement - *pflag = pointer to accumulating flags - Outputs: - cptr = pointer to next character in input string - NULL if parsing error - - Flags: 0 (no result), A_NUM (number), A_REL (relative) -*/ - -char *get_addr (char *cptr, int32 *dptr, int32 *pflag) -{ - return 0; -} - -/* Specifier decode - - Inputs: - *cptr = pointer to input string - addr = current PC - n1 = 0 if no extra word used - -1 if extra word used in prior decode - *sptr = pointer to output specifier - *dptr = pointer to output displacement - cflag = true if parsing for the CPU - iflag = true if integer specifier - Outputs: - status = = -1 extra word decoded - = 0 ok - = +1 error -*/ - -t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, t_value *dptr, - int32 cflag, int32 iflag) -{ - return -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 = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ - return SCPE_ARG; -} - -#ifndef _WIN32 - -int strnicmp (const char *a, const char *b, size_t n) -{ - int ca, cb; - - if (n == 0) return 0; /* zero length compare is equal */ - - for (;;) { - if ((ca = *a) == 0) /* get character, stop on null terminator */ - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') /* fold lowercase to uppercase */ - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) /* if different, return comparison */ - return ca; - - a++, b++; - - if (--n == 0) /* still equal after n characters? quit now */ - return 0; - } -} - -int strcmpi (const char *a, const char *b) -{ - int ca, cb; - - for (;;) { - if ((ca = *a) == 0) /* get character, stop on null terminator */ - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') /* fold lowercase to uppercase */ - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) /* if different, return comparison */ - return ca; - - a++, b++; - } -} - -#endif diff --git a/Ibm1130/ibm1130_t2741.c b/Ibm1130/ibm1130_t2741.c deleted file mode 100644 index 7ef37c35..00000000 --- a/Ibm1130/ibm1130_t2741.c +++ /dev/null @@ -1,388 +0,0 @@ -/*************************************************************************************** - * Nonstandard serial attachment for remote 2741 terminal (IO selectric) used by APL\1130 - * This implementation may be incomplete and/or incorrect - ***************************************************************************************/ - -#include "ibm1130_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" - -#define DEBUG_T2741 - -static TMLN t2741_ldsc = { 0 }; /* line descr for telnet attachment */ -static TMXR t2741_tmxr = { 1, 0, 0, &t2741_ldsc }; /* line mux for telnet attachment */ - -#define T2741_DSW_TRANSMIT_NOT_READY 0x4000 -#define T2741_DSW_READ_RESPONSE 0x1000 -#define T2741_DSW_READ_OVERRUN 0x0800 -#define T2741_DSW_ATTENTION 0x0010 - -#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) - -#define UNIT_V_PHYSICAL_TERM (UNIT_V_UF + 0) /* indicates not telnet but attachment to real terminal */ -#define UNIT_V_UPCASE (UNIT_V_UF + 1) /* indicates upshift performed */ -#define UNIT_V_SENDING (UNIT_V_UF + 2) /* indicates not telnet but attachment to real terminal */ -#define UNIT_V_RECEIVING (UNIT_V_UF + 3) /* indicates not telnet but attachment to real terminal */ - -#define UNIT_PHYSICAL_TERM (1u << UNIT_V_PHYSICAL_TERM) -#define UNIT_UPCASE (1u << UNIT_V_UPCASE) -#define UNIT_SENDING (1u << UNIT_V_SENDING) -#define UNIT_RECEIVING (1u << UNIT_V_RECEIVING) - -#define CODE_SHIFTUP 0x1C00 -#define CODE_SHIFTDOWN 0x7C00 -#define CODE_CIRCLEC 0x1F00 -#define CODE_CIRCLED 0x1600 -#define CODE_RETURN 0x5B00 -#define CODE_LINEFEED 0x3B00 -#define CODE_ATTENTION 0x0001 /* pseudocode, never really returned as a received character */ -#define CODE_UNKNOWN 0x0000 - -static t_stat t2741_svc (UNIT *uptr); -static t_stat t2741_reset (DEVICE *dptr); -static t_stat t2741_attach (UNIT *uptr, char *cptr); -static t_stat t2741_detach (UNIT *uptr); -static uint16 ascii_to_t2741 (int ascii); -static char * t2741_to_ascii (uint16 code); -static void set_transmit_notready (void); - -static uint16 t2741_dsw = T2741_DSW_TRANSMIT_NOT_READY; /* device status word */ -static uint32 t2741_swait = 200; /* character send wait */ -static uint32 t2741_rwait = 2000; /* character receive wait */ -static uint16 t2741_char = 0; /* last character received */ -static int overrun = FALSE; -static uint32 t2741_socket = 1130; - -UNIT t2741_unit[1] = { - { UDATA (&t2741_svc, UNIT_ATTABLE, 0) }, -}; - -REG t2741_reg[] = { - { HRDATA (DSW, t2741_dsw, 16) }, /* device status word */ - { DRDATA (RTIME, t2741_rwait, 24), PV_LEFT }, /* character receive wait */ - { DRDATA (STIME, t2741_swait, 24), PV_LEFT }, /* character send wait */ - { DRDATA (SOCKET, t2741_socket,16), PV_LEFT }, /* socket number */ - { HRDATA (LASTCHAR, t2741_char, 16), PV_LEFT }, /* last character read */ - { NULL } }; - -DEVICE t2741_dev = { - "T2741", t2741_unit, t2741_reg, NULL, - 1, 16, 16, 1, 16, 16, - NULL, NULL, t2741_reset, - NULL, t2741_attach, t2741_detach}; - -/* xio_t2741_terminal - XIO command interpreter for the terminal adapter */ - -void xio_t2741_terminal (int32 iocc_addr, int32 iocc_func, int32 iocc_mod) -{ - char msg[80]; - uint16 code; - - switch (iocc_func) { - case XIO_READ: /* read: return last character read */ - code = t2741_char & 0xFF00; - M[iocc_addr & mem_mask] = code; - overrun = FALSE; -#ifdef DEBUG_T2741 -/* trace_both("T2741 %04x READ %02x %s", prev_IAR, code >> 8, t2741_to_ascii(code)); */ -#endif - break; - - case XIO_WRITE: /* write: initiate character send */ - code = M[iocc_addr & mem_mask] & 0xFF00; -#ifdef DEBUG_T2741 - trace_both("T2741 %04x SEND %02x %s", prev_IAR, code >> 8, t2741_to_ascii(code)); -#endif - SETBIT(t2741_dsw, T2741_DSW_TRANSMIT_NOT_READY); - SETBIT(t2741_unit->flags, UNIT_SENDING); - - if (code == CODE_SHIFTUP) - SETBIT(t2741_unit->flags, UNIT_UPCASE); - else if (code == CODE_SHIFTDOWN) - CLRBIT(t2741_unit->flags, UNIT_UPCASE); - - sim_activate(t2741_unit, t2741_swait); /* schedule interrupt */ - break; - - case XIO_SENSE_DEV: /* sense device status */ - ACC = t2741_dsw; -#ifdef DEBUG_T2741 -/* trace_both("T2741 %04x SENS %04x%s", prev_IAR, t2741_dsw, (iocc_mod & 0x01) ? " reset" : ""); */ -#endif - if (iocc_mod & 0x01) { /* reset interrupts */ - CLRBIT(t2741_dsw, T2741_DSW_READ_RESPONSE); - CLRBIT(ILSW[4], ILSW_4_T2741_TERMINAL); - } - break; - - case XIO_CONTROL: /* control: do something to interface */ -#ifdef DEBUG_T2741 - trace_both("T2741 %04x CTRL %04x", prev_IAR, iocc_mod &0xFF); -#endif - SETBIT(t2741_unit->flags, UNIT_RECEIVING); /* set mode to receive mode */ - if (IS_ONLINE(t2741_unit) && (t2741_char != 0 || ! feof(t2741_unit->fileref))) { - sim_activate(t2741_unit, t2741_rwait); - t2741_char = (CODE_CIRCLED >> 8); /* first character received after turnaround is circled */ - } - break; - - default: - sprintf(msg, "Invalid T2741 XIO function %x", iocc_func); - xio_error(msg); - } -} - -static void set_transmit_notready (void) -{ - if (IS_ONLINE(t2741_unit) && ! (t2741_unit->flags & UNIT_SENDING)) - CLRBIT(t2741_dsw, T2741_DSW_TRANSMIT_NOT_READY); - else - SETBIT(t2741_dsw, T2741_DSW_TRANSMIT_NOT_READY); -} - -static t_stat t2741_svc (UNIT *uptr) -{ - int ch = EOF; - uint16 code; - - if (uptr->flags & UNIT_SENDING) { /* xmit: no interrupt, as far as I know. just clr busy bit */ - CLRBIT(uptr->flags, UNIT_SENDING); - set_transmit_notready(); - } - - if (uptr->flags & UNIT_RECEIVING) { /* rcv: fire interrupt */ - t2741_char <<= 8; - - if (t2741_char == 0) { /* there is no 2nd character from previous ascii input */ - if ((ch = getc(t2741_unit->fileref)) == EOF) - t2741_char = 0; - else { - if (ch == '\r') { /* if we get CR, jump to LF */ - if ((ch = getc(t2741_unit->fileref)) != '\n') { - ungetc(ch, t2741_unit->fileref); - ch = '\r'; - } - } - - if (ch == '\027') { - t2741_char = CODE_LINEFEED; /* attention key sends line feed character */ -#ifdef DEBUG_T2741 - trace_both("T2741 ---- ATTENTION"); -#endif - SETBIT(t2741_dsw, T2741_DSW_ATTENTION); /* no character returned ? */ - } - else { - t2741_char = ascii_to_t2741(ch); /* translate to 2741 code(s) */ - } - } - } - - code = t2741_char & 0xFF00; - - if (t2741_char != 0) { - if (overrun) /* previous character was not picked up! */ - SETBIT(t2741_dsw, T2741_DSW_READ_OVERRUN); - - SETBIT(t2741_dsw, T2741_DSW_READ_RESPONSE); - SETBIT(ILSW[4], ILSW_4_T2741_TERMINAL); /* issue interrupt */ - calc_ints(); - -#ifdef DEBUG_T2741 - trace_both("T2741 ---- RCVD %02x '%s' RDRESP%s%s", code >> 8, t2741_to_ascii(code), - (t2741_dsw & T2741_DSW_READ_OVERRUN) ? "|OVERRUN" : "", - (t2741_dsw & T2741_DSW_ATTENTION) ? "|ATTENTION" : ""); -#endif - - overrun = TRUE; /* arm overrun flag */ - } - - if (t2741_char == CODE_CIRCLEC) /* end of line (CIRCLEC after RETURN) auto downshifts */ - CLRBIT(t2741_unit->flags, UNIT_UPCASE); - - if (t2741_char == 0 || code == CODE_CIRCLEC) - CLRBIT(uptr->flags, UNIT_RECEIVING); /* on enter or EOF, stop typing */ - else - sim_activate(t2741_unit, t2741_rwait); /* schedule next character to arrive */ - } - - return SCPE_OK; -} - -static t_stat t2741_attach (UNIT *uptr, char *cptr) -{ - int rval; - - if ((rval = attach_unit(uptr, cptr)) == SCPE_OK) { /* use standard attach */ - t2741_char = 0; - overrun = FALSE; - - CLRBIT(t2741_unit->flags, UNIT_UPCASE); - - if ((t2741_unit->flags & UNIT_RECEIVING) && ! feof(t2741_unit->fileref)) - sim_activate(t2741_unit, t2741_rwait); /* schedule interrupt */ - } - - set_transmit_notready(); - - return rval; -} - -static t_stat t2741_detach (UNIT *uptr) -{ - t_stat rval; - - if (t2741_unit->flags & UNIT_RECEIVING) /* if receive was pending, cancel interrupt */ - sim_cancel(t2741_unit); - - t2741_char = 0; - overrun = FALSE; - - rval = detach_unit(uptr); /* use standard detach */ - - set_transmit_notready(); - - return rval; -} - -static t_stat t2741_reset (DEVICE *dptr) -{ - sim_cancel(t2741_unit); - - CLRBIT(t2741_unit->flags, UNIT_SENDING|UNIT_RECEIVING|UNIT_UPCASE); - - t2741_char = 0; - t2741_dsw = 0; - overrun = FALSE; - - set_transmit_notready(); - - CLRBIT(ILSW[4], ILSW_4_T2741_TERMINAL); - calc_ints(); - - return SCPE_OK; -} - -static struct tag_t2741_map { - int code; - int lcase, ucase; - t_bool shifts; -} t2741_map[] = { - {0x4F00, 'A', 'a', TRUE}, - {0x3700, 'B', 'b', TRUE}, - {0x2F00, 'C', 'c', TRUE}, - {0x2A00, 'D', 'd', TRUE}, - {0x2900, 'E', 'e', TRUE}, - {0x6700, 'F', '_', TRUE}, - {0x6200, 'G', 'g', TRUE}, - {0x3200, 'H', 'h', TRUE}, - {0x4C00, 'I', 'i', TRUE}, - {0x6100, 'J', 'j', TRUE}, - {0x2C00, 'K', '\'', TRUE}, - {0x3100, 'L', 'l', TRUE}, - {0x4300, 'M', '|', TRUE}, - {0x2500, 'N', 'n', TRUE}, - {0x5100, 'O', 'o', TRUE}, - {0x6800, 'P', '*', TRUE}, - {0x6D00, 'Q', '?', TRUE}, - {0x4A00, 'R', 'r', TRUE}, - {0x5200, 'S', 's', TRUE}, - {0x2000, 'T', '~', TRUE}, - {0x2600, 'U', 'u', TRUE}, - {0x4600, 'V', 'v', TRUE}, - {0x5700, 'W', 'w', TRUE}, - {0x2300, 'X', 'x', TRUE}, - {0x7300, 'Y', 'y', TRUE}, - {0x1500, 'Z', 'z', TRUE}, - {0x1300, '0', '&', TRUE}, - {0x0200, '1', '?', TRUE}, - {0x0400, '2', '?', TRUE}, - {0x0700, '3', '<', TRUE}, - {0x1000, '4', '?', TRUE}, - {0x0800, '5', '=', TRUE}, - {0x0D00, '6', '?', TRUE}, - {0x0B00, '7', '>', TRUE}, - {0x0E00, '8', '?', TRUE}, - {0x1600, '9', '|', TRUE}, - {0x7000, '/', '\\', TRUE}, - {0x7600, '+', '-', TRUE}, - {0x6400, '?', '?', TRUE}, - {0x4000, '<', '>', TRUE}, - {0x6B00, '[', '(', TRUE}, - {0x4900, ']', ')', TRUE}, - {0x6E00, ',', ';', TRUE}, - {0x4500, '.', ':', TRUE}, - {0x0100, ' ', 0, FALSE}, - {0x5B00, '\r', 0, FALSE}, - {0x3B00, '\n', 0, FALSE}, - {0x5D00, '\b', 0, FALSE}, - {0x5E00, '\t', 0, FALSE}, - {0x0001, '\027', 0, FALSE}, -}; - -static uint16 ascii_to_t2741 (int ascii) -{ - int i; - uint16 rval = 0; - - ascii &= 0xFF; - - if (ascii == '\n') /* turn newlines into returns + CIRCLED? */ - return CODE_RETURN | (CODE_CIRCLEC >> 8); - - for (i = sizeof(t2741_map)/sizeof(t2741_map[0]); --i >= 0; ) { - if (t2741_map[i].shifts) { - if (t2741_map[i].lcase == ascii) { - rval = t2741_map[i].code; - if (t2741_unit->flags & UNIT_UPCASE) { - CLRBIT(t2741_unit->flags, UNIT_UPCASE); - rval = CODE_SHIFTDOWN | (rval >> 8); - } - return rval; - } - if (t2741_map[i].ucase == ascii) { - rval = t2741_map[i].code; - if (! (t2741_unit->flags & UNIT_UPCASE)) { - SETBIT(t2741_unit->flags, UNIT_UPCASE); - rval = CODE_SHIFTUP | (rval >> 8); - } - return rval; - } - } - else if (t2741_map[i].lcase == ascii) - return t2741_map[i].code; - } - - return CODE_UNKNOWN; -} - -static char * t2741_to_ascii (uint16 code) -{ - int i; - static char string[2] = {'?', '\0'}; - - switch (code) { - case CODE_SHIFTUP: return "SHIFTUP"; - case CODE_SHIFTDOWN: return "SHIFTDN"; - case CODE_CIRCLEC: return "CIRCLEC"; - case CODE_CIRCLED: return "CIRCLED"; - } - - for (i = sizeof(t2741_map)/sizeof(t2741_map[0]); --i >= 0; ) { - if (t2741_map[i].code == code) { - if (t2741_map[i].shifts) { - string[0] = (t2741_unit->flags & UNIT_UPCASE) ? t2741_map[i].ucase : t2741_map[i].lcase; - return string; - } - switch (t2741_map[i].lcase) { - case ' ': return " "; - case '\r': return "RETURN"; - case '\n': return "LINEFEED"; - case '\b': return "BS"; - case '\t': return "IDLE"; - } - break; - } - } - - return "?"; -} diff --git a/Ibm1130/ibm1130res.h b/Ibm1130/ibm1130res.h deleted file mode 100644 index d84a46ee..00000000 --- a/Ibm1130/ibm1130res.h +++ /dev/null @@ -1,17 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by ibm1130.rc -// -#define IDB_CONSOLE 101 -#define IDC_MYHAND 102 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 103 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/Ibm1130/makefile b/Ibm1130/makefile deleted file mode 100644 index 647d0537..00000000 --- a/Ibm1130/makefile +++ /dev/null @@ -1,74 +0,0 @@ -# (This makefile is for operating systems other than Windows, -# or compilers other than Microsoft's. For MS builds, use the -# .mak files found in this directory and the utils directory). -# -# If you are building the emulator and utilities as part of -# the SIMH package, please: -# -# Be sure that you there are NO copies of scp.c, scp_tty.c, -# sim_sock.c, sim_tmxr.c, sim_rev.h, sim_defs.h, sim_sock.h and -# sim_tmxr.h in the ibm1130 subdirectory. Delete them if there -# are. -# -# Do not use this makefile with "make all" or "make ibm1130". -# Use the SIMH build files instead. -# -# If and when you download updates for this simulator from -# www.ibm1130.org, get ibm1130code.zip and ibm1130software.zip -# separately. -# -# If you have downloaded the emulator independently of SIMH (e.g, from -# www.ibm1130.org), please: -# -# Be sure that you DO have copies of scp.c, scp_tty.c, sim_sock.c, -# sim_tmxr.c, sim_rev.h, sim_defs.h, sim_sock.h and sim_tmxr.h -# in this folder. -# -# Use this file to make the emulator. -# -# If and when you download updates for this simulator from -# www.ibm1130.org, get ibm1130.zip. When you expand it, -# also expand ibm1130sofware.zip, which is inside. -# -# In either case, if you want to build DMS or work with assembly -# language programs outside of DMS, you'll want to make the utilities -# by cd'ing to the utils directory and running make there. - -# CC Command -# -# Note: -O2 is sometimes broken in GCC when setjump/longjump is being -# used. Try -O2 only with released simulators. -# -CC = gcc -O0 -lm -I . -#CC = gcc -O2 -g -lm -I . - - -# -# Common Libraries -# -BIN = -SIM = scp.c sim_console.c sim_fio.c sim_sock.c sim_timer.c sim_tmxr.c scp_tty.c -SIM_INC = scp.h sim_console.h sim_defs.h sim_fio.h sim_rev.h sim_sock.h sim_timer.h sim_tmxr.h - -# -# Emulator source files and compile time options -# - -ibm1130D = ./ -ibm1130 = ${ibm1130D}ibm1130_sys.c ${ibm1130D}ibm1130_cpu.c \ - ${ibm1130D}ibm1130_cr.c ${ibm1130D}ibm1130_disk.c \ - ${ibm1130D}ibm1130_stddev.c ${ibm1130D}ibm1130_gdu.c \ - ${ibm1130D}ibm1130_gui.c ${ibm1130D}ibm1130_prt.c \ - ${ibm1130D}ibm1130_ptrp.c ${ibm1130D}ibm1130_fmt.c - -ibm1130_INC = ibm1130res.h ibm1130_conin.h ibm1130_conout.h \ - ibm1130_defs.h ibm1130_prtwheel.h ibm1130_fmt.h \ - dmsr2v12phases.h dmsr2v12slet.h - -# -# Build the emulator -# - -${BIN}ibm1130 : ${ibm1130} ${SIM} ${ibm1130_INC} ${SIM_INC} - ${CC} ${ibm1130} ${SIM} -o $@ - diff --git a/Ibm1130/readme1130.txt b/Ibm1130/readme1130.txt deleted file mode 100644 index d2b5da29..00000000 --- a/Ibm1130/readme1130.txt +++ /dev/null @@ -1,189 +0,0 @@ -Here's the 1130 simulator as it stands now. - -Status: 22Jul2003 - - * Added support for APL\1130 output translations - and some bug fixes uncovered by APL. - -Status: 13Sep2002 - - * Added support for 1403 printer. It's MUCH faster - even in emulation. Not important for general use, - but it will help the CGI version a lot. - -Status: 16Aug2002 - - * Disk Monitor System R2V12 is available including the - Macro Assembler, Fortran Compiler and System Library. - - * There was a bug in the multiply instruction. This has - been fixed, and now the single precision trig functions - work correctly. - - * The card punch does not yet work correctly. - - * The card reader, punch and disk don't compute their device - status word until an XIO requests it; this is probably bad - as the "examine" command will show the wrong value. Doesn't - affect functioning of emulated software, though. - - * Documentation is a work in progress, see ibm1130.doc - in ibm1130software.zip. We hope to have it finished in - October. This is a Word document. Will distribute as a - PDF when it's finished. - - * Thanks to Oscar E Wyss (www.cosecans.ch) for - the DMS V12 source code listings and one card - programs, to Douglas W. Jones for the DMS V10, 11 and - 12 microfiche (which will end up scanned on IBM1130.org). - - * Thanks to Robert Alan Byer for adding the 1130 - to the simh makefiles & testing the builds on several - platforms. - - * For updated information about the 1130 and for - future 1130 OS and application software developments, - check www.ibm1130.org periodically. Sign up for the - mailing list to get updates as they occur! - - * Cross-assembler has been updated to handle card image input - correctly. The DMS sources seems to mix up @ and ' - as a leading symbol in labels, I have to find out why - this is. - -BUILD NOTES: if you download this simulator directly from -IBM1130.org, the makefile, source, and binaries are all in -the main directory. If you use the version from Bob Supnik's -SIMH distribution, the makefile is in the main simh -directory, and the SCP files used are Bob's. For a -Windows build, use the .mak file in the IBM1130 directory, -as this incorporates the GUI. - -Make the utilities in the utils directory if you want -to actually build and load DMS from scratch. Move the -executables to a common directory in your search path - -Brian Knittel -brian@ibm1130.org - --------------------------------------------------------------------------- -Some sample things to run: -(it's best to hit CHECK RESET or type "reset" between program runs!) - -* Run a Fortran Program - ibm1130 - do job roots - do job csort - -* List the monitor system disk's contents - ibm1130 - do job list - -* Look into the files "job", "roots.job" and "csort.job" and "list.job" - to see the actual input files - -* When the jobs have run (stop at 2A with 1000 in the - accumulator), detach the printer (det prt) and look at - the output file: for.lst or asm.lst. The supplied "job" - script displays the print output automatically on Windows - builds. - --------------------------------------------------------------------------- -Contents: - -There are several programs: - - ibm1130 the simulator - asm1130 cross assembler - bindump dumps contents of relocatable format object decks (xxx.bin) - checkdisk validates DMS disk format - diskview dumps contents of DMS disk directory - mkboot creates IPL and Core Image Format Decks from .bin - viewdeck displays contents of Hollerith-format binary decks - -Files in the software (sw) directory: - - actual 1130 software: - dms.dsk disk image file containing Disk Monitor System - zdcip.asm disk cartridge initialization program - zcrdumpc.asm a cold-start-mode one card memory dump program - dmsboot.asm source code for the DMS cold start loader - - contributed software: - onecard/* one-card programs from Oscar Wyss - --------------------------------------------------------------------------- -Status of the simulator: - -* There is a reasonably fun console GUI available for Windows builds, - as well as support for the 2250 graphical display. - -* The card reader emulator now supports deck files with literal cards and - breakpoints. The command "attach cr @filename" tells the simulator to - read data from the files named in the specified file. Input lines are of - the following form: - - filename a -- input file to be read as ascii text - filename b -- input file to be read as binary card images - !xyz... -- literal text xyz..., treated as a card - !break -- halts the simulator - #comment -- remarks - -* The do command may have arguments after the filename. These may be - interpolated in the script and in card reader deck files with %1, %2, etc - --------------------------------------------------------------------------- -sample usage --------------------------------------------------------------------------- - -ibm1130 - starts SIMH-based simulator. - Optional command line arguments: -q quiet mode, -g no GUI - - Enhancements: - - * Windows builds display a console window - - * CPU activity log - - the command "attach cpu file.log" will make the simulator - write a detailed log of CPU and IO activity, good for - debugging. Turn off with "detach cpu". - - * DO command [arg1 arg2...] - reads file 'filename' for SIMH commands. Lets you write - simh command files to be run from the prompt rather - than just the command line. In the do command file, %1 will - be replaced by the first command line argument, etc. This - applies to the script run from the ibm1130 command line too. - - * DELETE filename - deletes the named file - - * VIEW filename - displays the named file with "notepad." (Windows only). - --------------------------------------------------------------------------- -asm1130 -l program.asm - - compiles source file, creates simulator load - file (program.out) and listing file (program.lst) - - The cross assembler wants files either in strict column - layout matching the IBM spec, or, if tabs are present in the - source file, - - labelopcodeflagsoperand - - The output file is in the format used by the 1130 simulator's - load command. - --------------------------------------------------------------------------- - -Note: the DMS disk is built with the Windows batch file "mkdms.bat". - -Subnote: DMS cannot be built with the 1130's native assembler. - - --------------------------------------------------------------------------- -check www.ibm1130.org for updates... diff --git a/Ibm1130/readme_update.txt b/Ibm1130/readme_update.txt deleted file mode 100644 index 05a5ff91..00000000 --- a/Ibm1130/readme_update.txt +++ /dev/null @@ -1,60 +0,0 @@ -Version: 10 July 2003 - -History (partial): - -2003-11-15 Changed default value of TTO STIME to 200. It was - defined using a constant from sim_defs.h which was - changed from 10 to 100 at some point. APL\1130 has a - sychronization bug & hangs if the console output complete - interrupt occurs between the XIO SENSE and WAIT instructions. - This bug is hit frequently if the delay time is set to - 100 instructions. 10 worked reliably, but is really not realistic, - and 200 may not be adequate in all cases, but we'll try 200 for now. - -2003-11-00 Updated GUI to allow drag and drop to simulated card - reader, tear-off from simulated printer - -2003-07-10 Fixed disk and console terminal bugs uncovered by - APL\1130. Added APL keyboard and output font support - to enable use of APL\1130. APL will be released soon. - -2003-03-18 Fixed bug in asm1130 that produced an error message - with a (legal) offset of +127 in MDX instructions. - - Fixed sign bug in 1130 emulator divide instruction. - -Interim 1130 distribution: --------------------------------------------- - -folders: - . sources - winrel windows executables - windebug windows executables - utils accessory programs - utils\winrel windows executables - utils\windebug windows executables - sw working directory for DMS build & execution - sw\dmsR2V12 Disk Monitor System sources - -programs: - asm1130 cross assembler - bindump object deck dump tool, also used to sort decks by phase id - checkdisk DMS disk image check and dump - diskview work in progress, interpreted disk image dump - ibm1130 emulator - mkboot object deck to IPL and core image converter - viewdeck binary to hollerith deck viewer if needed to view phase ID cards and ident fields - -batch file: - mkdms.bat builds DMS objects and binary cards. Need a shell script version of this. - -IBM1130 simulator DO command scripts: - format format a disk image named DMS.DSK - loaddms format and install DMS onto the formatted DMS.DSK - for run a Fortran program - list list the disk contents - asm assemble a program - -ancillary files: - loaddms.deck list of files stacked into the card reader for loaddms - *.deck other sample deck files diff --git a/Ibm1130/utils/asm1130.c b/Ibm1130/utils/asm1130.c deleted file mode 100644 index 3cbc2f4c..00000000 --- a/Ibm1130/utils/asm1130.c +++ /dev/null @@ -1,4585 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -#define VERSION "ASM1130 CROSS ASSEMBLER V1.14" - -// --------------------------------------------------------------------------------- -// ASM1130 - IBM 1130 Cross Assembler -// -// Version -// 1.14 - 2004Oct22 - Fixed problem with BSS complaining about negative -// sizes. This may be a fundamental problem with my using -// 32-bit expressions, but for now, it appears that just -// truncating the BSS size to 16 bits is sufficient to build DMS. -// 1.13 - 2004Jun05 - Fixed sign extension of constants in expressions. Statements -// like LD /FFFF were being assembled incorrectly. -// 1.12 - 2004Jun04 - Made WAIT instruction take a displacement value. -// Doesn't affect operation, but these are used as indicators -// in the IBM one-card diagnostic programs. -// Also -- should mention that the .IPL directive was -// removed some time ago. To create bootable cards, -// use -b flag to create binary output, and post-process the -// binary output with program "mkboot" -// 1.11 - 2004May22 - Added CMP, DCM, and DECS instructions for 1800, -// thanks to Kevin Everets. -// 1.10 - 2003Dec08 - Fixed opcode value for XCH instruction, thanks to -// Roger Simpson. -// 1.09 - 2003Aug03 - Added fxwrite so asm will write little-endian files -// on all CPUs. -// 1.08 - 2003Mar18 - Fixed bug that complained about valid MDX displacement of +127 -// 1.07 - 2003Jan05 - Filenames are now left in lower case. SYMBOLS.SYS stays all upper case -// 1.06 - 2002May02 - Fixed bug in ebdic constants (data goes into low byte) -// First stab at adding ISS level # info, this is iffy -// 1.05 - 2002Apr24 - Made negative BSS size a warning not an error, as it -// it's looking like it happens twice in PTMASMBL. -// This version still doesn't do fixed point numbers and -// negative floats may be wrong. -// 1.04 - 2002Apr18 - Added binary (card loader format) output, removed -// interim IPL output formats and moved that to MKBOOT. -// Enhanced relocatable code handling. Added floating -// point constants, but don't know how to make fixed point -// constants yet. Made amenable to syntax variations found -// in the DMS sources. Doesn't properly handle ILS -// modules yet and ISS is probably wrong. -// 1.03 - 2002Apr10 - numerous fixes, began to add relative/absolute support -// 1.02 - 2002Feb26 - replaced "strupr" with "upcase" for compatibility -// 1.01 - 2002Feb25 - minor compiler compatibility changes -// 1.00 - 2002Feb01 - first release. Tested only under Win32. -// --------------------------------------------------------------------------------- -// -// Usage: -// asm1130 [-bvsx] [-o[file]] [-l[file]] [-rN.M] file... -// -// Description: -// -b binary output (.bin, relocatable absolute format) -// -v verbose -// -s print symbol table -// -x print cross references -// -o output file (default is name of first source file + extension .out or .bin) -// -l listing file (default is name of first source file + extension .lst) -// -y preload system symbol table SYMBOLS.SYS (from the current directory) -// -w write the system symbol table SYMBOLS.SYS in the current directory -// -W same as -w but don't prompt to confirm overwriting existing file -// -r set DMS release to release N version M, for sbrk cards -// -// Listing and symbol table output can be turned on by *LIST directives in the source, too -// Listing file default extension is .LST -// -// Input files can use strict IBM 1130 Assembler column format, or loose formatting -// with tabs, or any mix on a line-by-line basis. Input files default extension is .ASM. -// -// Strict specification is: -// -// label columns 1 - 5 -// opcode 7 - 10 -// tag 12 -// index 13 -// arguments 15 - 51 -// -// Loose, indicated by presence of ascii tab character(s): -// -// labelopcodeindex and format indicatorsarguments -// -// In both cases, the IBM convention that the arguments section ends with the -// first nonblank applies. This means that ".DC 1, 2, 3" assembles only the 1! -// -// Output file format is that used by the LOAD command in my 1130 -// simulator. Lines are any of the following. All values are in hex: -// -// @addr load address for subsequent words is addr -// Znwords Zero the next "nwords" and increment load address by nwords. -// =addr set IAR register to address addr (a convenience) -// value load value at load address and increment load address -// -// Output file default extension is .OUT or .BIN for binary assemblies -// -// Note: this version does not handle relative assembly, and so doesn't carry -// absolute/relative indication through expression calculation. -// -// Seems to work. Was able to assemble the resident monitor OK. -// >>> Look for "bug here" though, for things to check out. -// -// Notes: -// We assume that the computer on which the assembler runs uses ANSI floating point. -// Also, the assembly of floating point values may be incorrect on non-Intel -// architectures, this needs to be investigated. -// -// org_advanced tells whether * in an expression refers to the address AFTER the -// instruction (1 or 2 words, depending on length). This is the case for opcodes -// but not all directives. -// -// Revision History -// 16Apr02 1.03 Added sector break, relocation flag output -// 02Apr02 1.02 Fixed bug in BOSC: it CAN be a short instruction. -// Added directives for 1130 and 1800 IPL output formats -// Added conditional assembly directives -// --------------------------------------------------------------------------------- - -#include -#include -#include -#include -#include -#include -#include -#include "util_io.h" - -// ---------------------------------------------------------------1------------------ -// DEFINITIONS -// --------------------------------------------------------------------------------- - -// I have found some IBM source code where @ and ' seem interchangable (likely due to the -// use of 026 keypunches). -// Comment out this define to make @ and ' different in symbol names, keep to make equivalent - -#if defined(VMS) - # include /* to pick up 'unlink' */ -#endif - -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#ifndef _WIN32 - int strnicmp (char *a, char *b, int n); - int strcmpi (char *a, char *b); -#endif - -#define FIX_ATS - -#define DMSVERSION "V2M12" /* required 5 characters on sector break card col 67-71 */ - -#define DOLLAREXIT "/38" // hmmm, are these really fixed absolutely in all versions? -#define DOLLARDUMP "/3F" - -#define SYSTEM_TABLE "SYMBOLS.SYS" - -#define BOOL int -#define TRUE 1 -#define FALSE 0 - -#define ISTV 0x33 // magic number from DMS R2V12 monitorm symbol @ISTV - -#define MAXLITERALS 300 -#define MAXENTRIES 14 - -#define LINEFORMAT " %4ld | %s" -#define LEFT_MARGIN " |" - // XXXX XXXX XXXX XXXX XXXX XXXX - // org w1 w2 w3 w4 w5 - // XXXX 1111 2222 3333 4444 LLLL | - // 12345678901234567890123456789012 - -typedef enum {ABSOLUTE = 0, RELATIVE = 1, LIBF = 2, CALL = 3} RELOC; - -typedef struct tag_symbol { // symbol table entry: - char *name; // name of symbol - int value; // value (absolute) - int pass; // defined during pass # - int defined; // definition state, see #defines below - RELOC relative; // ABSOLUTE = absolute, RELATIVE = relative - struct tag_symbol *next; // next symbol in list - struct tag_xref *xrefs; // cross references -} SYMBOL, *PSYMBOL; - -#define S_UNDEFINED 0 // values of 'defined' -#define S_PROVISIONAL 1 // usually an expression with forward references -#define S_DEFINED 2 // ordering must be undef < prov < def - -typedef struct tag_xref { // cross reference entry - char *fname; // filename - int lno; // line number - BOOL definition; // true = definition, false = reference - struct tag_xref *next; // next reference -} XREF, *PXREF; - -typedef struct tag_expr { // expression result: absolute or relative - int value; - RELOC relative; -} EXPR; - -typedef enum {PROGTYPE_ABSOLUTE = 1, PROGTYPE_RELOCATABLE = 2, PROGTYPE_LIBF = 3, PROGTYPE_CALL = 4, - PROGTYPE_ISSLIBF = 5, PROGTYPE_ISSCALL = 6, PROGTYPE_ILS = 7} PROGTYPE; - -typedef enum {SUBTYPE_INCORE = 0, SUBTYPE_FORDISK = 1, SUBTYPE_ARITH = 2, - SUBTYPE_FORNONDISK = 3, SUBTYPE_FUNCTION=8} SUBTYPE; - -typedef enum {INTMODE_UNSPECIFIED = 0, INTMODE_MATCHREAL = 0x0080, INTMODE_ONEWORD = 0x0090} INTMODE; -typedef enum {REALMODE_UNSPECIFIED = 0, REALMODE_STANDARD = 0x0001, REALMODE_EXTENDED = 0x0002} REALMODE; - -#define OP_INDEXED 0x0300 // 1130 opcode modifier bits -#define OP_LONG 0x0400 -#define OP_INDIRECT 0x0080 - -typedef enum {OUTMODE_LOAD, OUTMODE_1130, OUTMODE_1800, OUTMODE_BINARY} OUTMODE; - -#ifdef _WIN32 -# define OUTWRITEMODE "wb" // write outfile in binary mode -# define ENDLINE "\r\n" // explictly write CR/LF -#else -# define OUTWRITEMODE "w" // use native mode -# define ENDLINE "\n" -#endif - -// --------------------------------------------------------------------------------- -// GLOBALS -// --------------------------------------------------------------------------------- - -// command line syntax -char *usestr = -"Usage: asm1130 [-bpsvwxy8] [-o[file]] [-l[file]] [-rN.M] file...\n\n" -"-b binary (relocatable format) output; default is simulator LOAD format\n" -"-p count passes required; no assembly output is created with this flag" -"-s add symbol table to listing\n" -"-v verbose mode\n" -"-w write system symbol table as SYMBOLS.SYS\n" -"-W same as -w but do not confirm overwriting previous file\n" -"-x add cross reference table to listing\n" -"-y preload system symbol table SYMBOLS.SYS\n" -"-o set output file; default is first input file + .out or .bin\n" -"-l create listing file; default is first input file + .lst\n" -"-r set dms version to VN RM for system SBRK cards\n" -"-8 enable IBM 1800 instructions"; // (alternately, rename or link executable to asm1800.exe) - -BOOL verbose = FALSE; // verbose mode flag -BOOL tabformat = FALSE; // TRUE if tabs were seen in the file -BOOL enable_1800 = FALSE; // TRUE if 1800 mode is enabled by flag or executable name -int pass; // current assembler pass (1 or 2) -char curfn[256]; // current input file name -char progname[8]; // base name of primary input file -char *outfn = NULL; // output file name -int lno; // current input file line number -BOOL preload = FALSE; // preload system symbol table -BOOL savetable = FALSE; // write system symbol table -BOOL saveprompt = TRUE; // prompt before overwriting -int nerrors = 0; // count of errors -int nwarnings = 0; // count of warnings -FILE *fin = NULL; // current input file -FILE *fout = NULL; // output file stream -OUTMODE outmode = OUTMODE_LOAD; // output file mode -int outcols = 0; // columns written in using card output -int maxiplcols = 80; -char cardid[9]; // characters used for IPL card ID -FILE *flist = NULL; // listing file stream -char *listfn = NULL; // listing filename -BOOL do_list = FALSE; // flag: create listing -BOOL passcount = FALSE; // flag: count passes only -BOOL list_on = TRUE; // listing is currently enabled -BOOL do_xref = FALSE; // cross reference listing -BOOL do_syms = FALSE; // symbol table listing -BOOL ended = FALSE; // end of current file -BOOL hasforward = FALSE; // true if there are any forward references -char listline[350]; // output listing line -BOOL line_error; // already saw an error on current line -RELOC relocate = RELATIVE; // relocatable assembly mode -BOOL assembled = FALSE; // true if any output has been generated -int nwout; // number of words written on current line -int org = 0; // output address (origin) -int org_advanced; // if TRUE, * means instruction addr+(value) during evaluation -int pta = -1; // program transfer address -BOOL cexpr = FALSE; // "C" expression syntax -PSYMBOL symbols = NULL; // the symbol table (linear search) -BOOL check_control = TRUE; // check for control cards -PROGTYPE progtype = PROGTYPE_RELOCATABLE; // program type -INTMODE intmode = INTMODE_UNSPECIFIED; // integer mode -REALMODE realmode = REALMODE_UNSPECIFIED; // real mode -int nintlevels = 0; // # of interrupt levels for ISS -int intlevel_primary = 0; // primary level for ISS and level for ILS -int intlevel_secondary = 0; // secondary level for ISS -int iss_number = 0; // ISS number -PSYMBOL entry[MAXENTRIES]; // entries for subroutines -int nentries = 0; -int ndefined_files = 0; - -struct lit { // accumulated literals waiting to be output - int value; // constant value - int tagno; // constant symbol tag number (e.g. _L001) - BOOL hex; // constant was expressed in hex - BOOL even; // constant was operand of a double-width instruction (e.g. AD) -} literal[MAXLITERALS]; - -int n_literals = 0, lit_tag = 0; -BOOL requires_even_address; // target of current instruction -BOOL dmes_saved; // odd character left over from dmes ending in ' -int dmes_savew; -char opfield[256]; // extracted operand field from source line -char dmsversion[12] = DMSVERSION; // version number for SBRK cards -const char whitespace[] = " \t"; // whitespace - -int ascii_to_ebcdic_table[128] = -{ -// - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, -// - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, -// spac ! " # $ % & ' ( ) * + , - . / - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, -// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, -// @ A B C D E F G H I J K L M N O - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, -// P Q R S T U V W X Y Z [ \ ] & _ - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, -// a b c d e f g h i j k l m n o - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, -// p q r s t u v w x y z { | } ~ - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -int ascii_to_1403_table[128] = -{ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f */ - 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x7f,0x7f,0x7f,0x62,0x7f,0x15,0x0b, 0x57,0x2f,0x23,0x6d,0x16,0x61,0x6e,0x4c, - 0x49,0x40,0x01,0x02,0x43,0x04,0x45,0x46, 0x07,0x08,0x7f,0x7f,0x7f,0x4a,0x7f,0x7f, - 0x7f,0x64,0x25,0x26,0x67,0x68,0x29,0x2a, 0x6b,0x2c,0x58,0x19,0x1a,0x5b,0x1c,0x5d, - 0x5e,0x1f,0x20,0x0d,0x0e,0x4f,0x10,0x51, 0x52,0x13,0x54,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x64,0x25,0x26,0x67,0x68,0x29,0x2a, 0x6b,0x2c,0x58,0x19,0x1a,0x5b,0x1c,0x5d, - 0x5e,0x1f,0x20,0x0d,0x0e,0x4f,0x10,0x51, 0x52,0x13,0x54,0x7f,0x7f,0x7f,0x7f,0x7f -}; - -#include "../ibm1130_conout.h" /* conout_to_ascii_table */ -#include "../ibm1130_prtwheel.h" /* 1132 printer printwheel data */ - -// --------------------------------------------------------------------------------- -// PROTOTYPES -// --------------------------------------------------------------------------------- - -void init (int argc, char **argv); -void bail (char *msg); -void flag (char *arg); -void proc (char *fname); -void startpass (int n); -void errprintf (char *fmt, ...); -void asm_error (char *fmt, ...); -void asm_warning (char *fmt, ...); -char *astring (char *str); -PSYMBOL lookup_symbol (char *name, BOOL define); -void add_xref (PSYMBOL s, BOOL definition); -int get_symbol (char *name); -void set_symbol (char *name, int value, int known, RELOC relative); -char * gtok (char **pc, char *tok); -char *skipbl (char *c); -void sym_list (void); -void xref_list (void); -void listhdr (void); -int getexpr (char *pc, BOOL undefined_ok, EXPR *expr); -void passreport (void); -void listout (BOOL reset); -void output_literals (BOOL eof); -char *upcase (char *str); -void prep_line (char *line); -int ascii_to_hollerith (int ch); -char *detab (char *str); -void preload_symbols (void); -void save_symbols (void); -void bincard_init (void); -void bincard_writecard (char *sbrk_text); -void bincard_writedata (void); -void bincard_flush (void); -void bincard_sbrk (char *line); -void bincard_setorg (int neworg); -void bincard_writew (int word, RELOC relative); -void bincard_endcard (void); -void handle_sbrk (char *line); -void bincard_typecard (void); -void namecode (unsigned short *words, char *tok); -int signextend (int v); - -// --------------------------------------------------------------------------------- -// main routine -// --------------------------------------------------------------------------------- - -int main (int argc, char **argv) -{ - int i, sawfile = FALSE; - - init(argc, argv); // initialize, process flags - - startpass(1); // first pass, process files - - for (i = 1; i < argc; i++) - if (*argv[i] != '-') - proc(argv[i]), sawfile = TRUE; - - if (! sawfile) // should have seen at least one file - bail(usestr); - - if (passcount) { - passreport(); - return 0; - } - - startpass(2); // second pass, process files again - - for (i = 1; i < argc; i++) - if (*argv[i] != '-') - proc(argv[i]); - - if (outmode == OUTMODE_LOAD) { - if (pta >= 0) // write start address to the load file - fprintf(fout, "=%04x" ENDLINE, pta & 0xFFFF); - } - else - bincard_endcard(); - - if (flist) { - if (nerrors || nwarnings) { // summarize (or summarise) - if (nerrors == 0) - fprintf(flist, "There %s ", (nwarnings == 1) ? "was" : "were"); - else - fprintf(flist, "\nThere %s %d error%s %s", - (nerrors == 1) ? "was" : "were", nerrors, (nerrors == 1) ? "" : "s", nwarnings ? "and " : ""); - - if (nwarnings > 0) - fprintf(flist, "%d warning%s ", nwarnings, (nwarnings == 1) ? "" : "s"); - - fprintf(flist, "in this assembly\n"); - } - else - fprintf(flist, "\nThere were no errors in this assembly\n"); - } - - if (flist) { // finish the listing - if (pta >= 0) - fprintf(flist, "\nProgram transfer address = %04x\n", pta); - - if (do_xref) - xref_list(); - else if (do_syms) - sym_list(); - } - - if (savetable) - save_symbols(); - - return 0; // all done -} - -// --------------------------------------------------------------------------------- -// init - initialize assembler, process command line flags -// --------------------------------------------------------------------------------- - -void init (int argc, char **argv) -{ - int i; - - enable_1800 = strstr(argv[0], "1800") != NULL; // if "1800" appears in the executable name, enable 1800 extensions - - for (i = 1; i < argc; i++) // process command line switches - if (*argv[i] == '-') - flag(argv[i]+1); -} - -// --------------------------------------------------------------------------------- -// flag - process one command line switch -// --------------------------------------------------------------------------------- - -void flag (char *arg) -{ - int major, minor; - - while (*arg) { - switch (*arg++) { - case 'o': // output (load) file name - if (! *arg) - bail(usestr); - outfn = arg; - return; - - case 'p': - passcount = TRUE; - break; - - case 'v': // mumble while running - verbose = TRUE; - break; - - case 'x': // print cross reference table - do_xref = TRUE; - break; - - case 's': // print symbol table - do_syms = TRUE; - break; - - case 'l': // listing file name - listfn = (* arg) ? arg : NULL; - do_list = TRUE; - return; - - case 'W': - saveprompt = FALSE; - // fall through - case 'w': - savetable = TRUE; - break; - - case 'y': - preload = TRUE; - break; - - case 'b': - outmode = OUTMODE_BINARY; - break; - - case '8': - enable_1800 = TRUE; - break; - - case 'r': - if (sscanf(arg, "%d.%d", &major, &minor) != 2) - bail(usestr); - sprintf(dmsversion, "V%01.1dM%02.2d", major, minor); - return; - - default: - bail(usestr); - break; - } - } -} - -// --------------------------------------------------------------------------------- -// bail - print error message on stderr (only) and exit -// --------------------------------------------------------------------------------- - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -// --------------------------------------------------------------------------------- -// errprintf - print error message to stderr -// --------------------------------------------------------------------------------- - -void errprintf (char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); // get pointer to argument list - - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) - - va_end(args); -} - -// --------------------------------------------------------------------------------- -// asm_error - report an error to listing file and to user's console -// --------------------------------------------------------------------------------- - -void asm_error (char *fmt, ...) -{ - va_list args; - - if (pass == 1) // only print on pass 2 - return; - - va_start(args, fmt); // get pointer to argument list - - fprintf(stderr, "E: %s (%d): ", curfn, lno); - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) - putc('\n', stderr); - - if (flist != NULL && list_on) { - listout(FALSE); - line_error = TRUE; - - fprintf(flist, "**** Error: "); - vfprintf(flist, fmt, args); // write errors to listing file - putc('\n', flist); - } - - nerrors++; - va_end(args); -} - -// --------------------------------------------------------------------------------- -// asm_warning - same but warnings are not counted -// --------------------------------------------------------------------------------- - -void asm_warning (char *fmt, ...) -{ - va_list args; - - if (pass == 1) // only print on pass 2 - return; - - va_start(args, fmt); // get pointer to argument list - - fprintf(stderr, "W: %s (%d): ", curfn, lno); - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) - putc('\n', stderr); - - if (flist != NULL && list_on) { - listout(FALSE); - line_error = TRUE; - - fprintf(flist, "**** Warning: "); - vfprintf(flist, fmt, args); // write errors to listing file - putc('\n', flist); - } - - nwarnings++; -} - -// --------------------------------------------------------------------------------- -// sym_list - print the symbol table -// --------------------------------------------------------------------------------- - -void sym_list (void) -{ - PSYMBOL s; - int n = 5; - - if (symbols == NULL || flist == NULL) - return; - - fprintf(flist, "\n=== SYMBOL TABLE ==============================================================\n"); - - for (s = symbols, n = 0; s != NULL; s = s->next) { - if (n >= 5) { - putc('\n', flist); - n = 0; - } - else if (n > 0) - fprintf(flist, " "); - - fprintf(flist, "%-6s ", s->name); - if (s->defined == S_DEFINED) - fprintf(flist, "%04x%s", s->value & 0xFFFF, s->relative ? "R" : " "); - else - fprintf(flist, "UUUU "); - - n++; - } - fprintf(flist, "\n"); -} - -// --------------------------------------------------------------------------------- -// passreport - report # of passes required for assembly on the 1130 -// --------------------------------------------------------------------------------- - -void passreport (void) -{ - PSYMBOL s; - - for (s = symbols; s != NULL; s = s->next) { - if (s->defined == S_UNDEFINED || s->defined == S_PROVISIONAL) { - printf("There are undefined symbols. Cannot determine pass requirement.\n"); - return; - } - } - - if (hasforward) - printf("There are forward references. Two passes are required.\n"); - else - printf("There are no forward references. Only one pass is required.\n"); -} - -// --------------------------------------------------------------------------------- -// xref_list - print the cross-reference table -// --------------------------------------------------------------------------------- - -void xref_list (void) -{ - int n = 0; - PXREF x; - PSYMBOL s; - - if (flist == NULL || symbols == NULL) - return; - - fprintf(flist, "\n=== CROSS REFERENCES ==========================================================\n"); - - if (symbols == NULL || flist == NULL) - return; - - fprintf(flist, "Name Val Defd Referenced\n"); - - for (s = symbols; s != NULL; s = s->next) { - fprintf(flist, "%-5s %04x%s", s->name, s->value & 0xFFFF, s->relative ? "R" : " "); - - for (x = s->xrefs; x != NULL; x = x->next) - if (x->definition) - break; - - if (x == NULL) - fprintf(flist, "----"); - else - fprintf(flist, " %4d", x->lno); - - for (n = 0, x = s->xrefs; x != NULL; x = x->next) { - if (x->definition) - continue; - - if (n >= 12) { - n = 0; - fprintf(flist, "\n "); - } - fprintf(flist, " %4d", x->lno); - n++; - } - putc('\n', flist); - } -} - -// --------------------------------------------------------------------------------- -// listhdr - print a banner header in the listing file. Since it's not paginated -// at this time, this is not used often. -// --------------------------------------------------------------------------------- - -void listhdr (void) -{ - time_t t; - - time(&t); - fprintf(flist, "%s -- %s -- %s\n", VERSION, dmsversion, ctime(&t)); -} - -// --------------------------------------------------------------------------------- -// astring - allocate a copy of a string -// --------------------------------------------------------------------------------- - -char *astring (char *str) -{ - static char *s = NULL; - - if (s != NULL) - if (strcmp(s, str) == 0) // if same as immediately previous allocation - return s; // return same pointer (why did I do this?) - - if ((s = malloc(strlen(str)+1)) == NULL) - bail("out of memory"); - - strcpy(s, str); - return s; -} - -// --------------------------------------------------------------------------------- -// lookup_symbol - get pointer to a symbol. -// If define is TRUE, creates and marks 'undefined' if not previously defined. -// --------------------------------------------------------------------------------- - -PSYMBOL lookup_symbol (char *name, BOOL define) -{ - PSYMBOL s, n, prv = NULL; - int c; - char *at; - - if (strlen(name) > 5) { // (sigh) - asm_error("Symbol '%s' is longer than 5 letters", name); - name[5] = '\0'; - } - -#ifdef FIX_ATS - while ((at = strchr(name, '@')) != NULL) - *at = '\''; -#endif - // search sorted list of symbols - for (s = symbols; s != NULL; prv = s, s = s->next) { - c = strcmpi(s->name, name); - if (c == 0) - return s; - if (c > 0) - break; - } - - if (! define) - return NULL; // not found - - if ((n = malloc(sizeof(SYMBOL))) == NULL) - bail("out of memory"); - - n->name = astring(name); // symbol was undefined -- add it now - n->value = 0; - n->defined = FALSE; - n->xrefs = NULL; - n->defined = FALSE; - - n->next = s; // link in alpha order - - if (prv == NULL) // we stopped before first item in list - symbols = n; - else - prv->next = n; // insert after item before place we stopped - - return n; -} - -// --------------------------------------------------------------------------------- -// add_xref - add a cross reference entry to a symbol -// --------------------------------------------------------------------------------- - -void add_xref (PSYMBOL s, BOOL definition) -{ - PXREF x, prv = NULL, n; - - if (pass == 1 || ! do_xref) // define only during 2nd pass and only if listing was requested - return; - - for (x = s->xrefs; x != NULL; prv = x, x = x->next) - if (strcmpi(x->fname, curfn) == 0 && x->lno == lno) - return; // ignore multiple refs on same line - - if ((n = malloc(sizeof(XREF))) == NULL) - bail("out of memory"); - - n->fname = astring(curfn); - n->lno = lno; - n->definition = definition; - - n->next = x; // link at end of existing list - - if (prv == NULL) - s->xrefs = n; - else - prv->next = n; -} - -// --------------------------------------------------------------------------------- -// get_symbol - get a symbol value, defining if necessary -// --------------------------------------------------------------------------------- - -int get_symbol (char *name) -{ - PSYMBOL s; - - s = lookup_symbol(name, TRUE); // lookup, define if necessary - - if (pass == 2) // should be defined by now - if (! s->defined) - asm_error("Symbol '%s' is undefined", name); - - add_xref(s, FALSE); // note the reference - - return s->value; -} - -// --------------------------------------------------------------------------------- -// set_symbol - set a symbol value. Known = TRUE means we really know the value; -// FALSE means we're calculating it with forward referenced values or something like -// that. -// --------------------------------------------------------------------------------- - -void set_symbol (char *name, int value, int known, RELOC relative) -{ - PSYMBOL s; - char *at; - - if (strlen(name) > 5) { - asm_error("Symbol '%s' is longer than 5 letters", name); - name[5] = '\0'; - } - -#ifdef FIX_ATS - while ((at = strchr(name, '@')) != NULL) - *at = '\''; -#endif - - s = lookup_symbol(name, TRUE); - - if (s->defined == S_DEFINED) // once defined, it should not change - if (s->value != value) - asm_error("Symbol '%s' %s", name, (s->pass == pass) ? "is multiply defined" : "changed between passes"); - - s->value = value; - s->relative = relative; - s->defined = known ? S_DEFINED : S_PROVISIONAL; - s->pass = pass; - - if (! known) - hasforward = TRUE; - - add_xref(s, TRUE); // record the place of definition -} - -// --------------------------------------------------------------------------------- -// skipbl - return pointer to first nonblank character in string s -// --------------------------------------------------------------------------------- - -char *skipbl (char *s) -{ - while (*s && *s <= ' ') - s++; - - return s; -} - -// --------------------------------------------------------------------------------- -// gtok - extracts a whitespace-delimited token from the string pointed to by *pc; -// stores the token into the buffer tok and returns pointer to same. Returns NULL -// when there are no tokens. Best to call repeatedly with a pointer to the source -// buffer, e.g. -// char *pbuf = buf; -// while (gtok(&pbuf, token) != NULL) ... -// --------------------------------------------------------------------------------- - -char * gtok (char **pc, char *tok) -{ - char *s = *pc, *otok = tok; - - while (*s && *s <= ' ') // skip blanks - s++; - - if (! *s) { // no tokens to be found - *tok = '\0'; - *pc = s; - return NULL; - } - - while (*s > ' ') // save nonblanks into 'tok' - *tok++ = *s++; - - *tok = '\0'; // terminate - *pc = s; // adjust caller's pointer - - return otok; // return pointer to token -} - -// listing format: -// -// ADDR CODE SOURCE -// 0000 0000 0000 0000 0000 | XXXXXXXXXXXXXXXXX - -// --------------------------------------------------------------------------------- -// trim - remove trailing whitespace from string s -// --------------------------------------------------------------------------------- - -char *trim (char *s) -{ - char *os = s, *nb; - - for (nb = s-1; *s; s++) - if (*s > ' ') - nb = s; - - nb[1] = '\0'; - return os; -} - -// --------------------------------------------------------------------------------- -// listout - emit current constructed output listing line held in "listline" and -// if "reset" is true, prepare listline for second and subsequent listing lines -// for a given input statement. -// --------------------------------------------------------------------------------- - -void listout (BOOL reset) -{ - if (flist && list_on && ! line_error) { - trim(listline); - fputs(listline, flist); - putc('\n', flist); - if (reset) - sprintf(listline, LEFT_MARGIN, org); - } -} - -// --------------------------------------------------------------------------------- -// storew - store a word in the output medium (hex or binary file). Most of the time -// writew is used. Advances the origin! -// --------------------------------------------------------------------------------- - -void storew (int word, RELOC relative) -{ - if (pass == 2) { // save in output (load) file. - switch (outmode) { - case OUTMODE_BINARY: - bincard_writew(word, relative); - break; - - case OUTMODE_LOAD: - fprintf(fout, " %04x%s" ENDLINE, word & 0xFFFF, - (relative == ABSOLUTE) ? "" : (relative == RELATIVE) ? "R" : - (relative == LIBF) ? "L" : (relative == CALL) ? "$" : "?"); - break; - - default: - bail("in storew, can't happen"); - } - } - - if (relative != LIBF) - org++; - - assembled = TRUE; // remember that we wrote something -} - -// --------------------------------------------------------------------------------- -// setw - store a word value in the current listing output line in position 'pos'. -// --------------------------------------------------------------------------------- - -void setw (int pos, int word, RELOC relative) -{ - char tok[10], *p; - int i; - - if (flist == NULL || ! list_on) - return; - - sprintf(tok, "%04x", word & 0xFFFF); - - for (i = 0, p = listline + 5*pos; i < 4; i++) - p[i] = tok[i]; - - if (relative == RELATIVE) - p[i] = 'R'; - else if (relative != ABSOLUTE) - p[i] = '*'; -} - -// --------------------------------------------------------------------------------- -// writew - emit an assembled word value. Words are also displayed in the listing file. -// if relative is true, a relocation entry should be recorded. -// --------------------------------------------------------------------------------- - -void writew (int word, RELOC relative) -{ // first, the listing stuff... - if (nwout == 0) { // on first output word, display address in column 0 - setw(0, org, FALSE); - } - else if (nwout >= 4) { // if 4 words have already been written, start new line - listout(TRUE); - nwout = 0; - } - - nwout++; - setw(nwout, word, relative); // display word in the listing line - - storew(word, relative); // write it to the output medium -} - -// --------------------------------------------------------------------------------- -// setorg - take note of new load address -// --------------------------------------------------------------------------------- - -void setorg (int neworg) -{ - if (pass == 2) { - setw(0, neworg, FALSE); // display in listing file in column 0 - - if (outmode == OUTMODE_LOAD) { // write new load address to the output file - fprintf(fout, "@%04x%s" ENDLINE, neworg & 0xFFFF, relocate ? "R" : ""); - } - else { - bincard_setorg(neworg); - } - } - - org = neworg; -} - -// --------------------------------------------------------------------------------- -// org_even - force load address to an even address -// --------------------------------------------------------------------------------- - -void org_even (void) -{ - if (org & 1) - setorg(org+1); -} - -// --------------------------------------------------------------------------------- -// tabtok - get the token in tab-delimited column number i, from source string c, -// saving in string 'tok'. If save is nonnull, we copy the entire remainder of -// the input string in buffer 'save' (in contrast to 'tok' which gets only the -// first whitespace delimited token). -// --------------------------------------------------------------------------------- - -void tabtok (char *c, char *tok, int i, char *save) -{ - *tok = '\0'; - - while (--i >= 0) { // skip to i'th tab-delimited field - if ((c = strchr(c, '\t')) == NULL) { - if (save) // was none - *save = '\0'; - return; - } - c++; - } - - while (*c == ' ') // skip leading blanks - c++; - - if (save != NULL) // save copy of entire remainder - strcpy(save, c); - - while (*c > ' ') { // take up to any whitespace - if (*c == '(') { // if we start with a paren, take all up to closing paren including spaces - while (*c && *c != ')') - *tok++ = *c++; - } - else if (*c == '.') { // period means literal character following - *tok++ = *c++; - if (*c) - *tok++ = *c++; - } - else - *tok++ = *c++; - } - - *tok = '\0'; -} - -// --------------------------------------------------------------------------------- -// coltok - extract a token from string c, saving to buffer tok, by examining -// columns ifrom through ito only. If save is nonnull, the entire remainder -// of the input from ifrom to the end is saved there. In this routine -// if condense is true, we save all nonwhite characters in the column range; -// not the usual thing. This helps us coalesce the format, tag, & index things -// nto one string for the simple minded parser. If condense is FALSE, we terminate -// on the first nonblank, except that if we start with a (, we take up to ) and -// then terminate on a space. -// -// ifrom and ito on entry are column numbers, not indices; we change that right away -// --------------------------------------------------------------------------------- - -void coltok (char *c, char *tok, int ifrom, int ito, BOOL condense, char *save) -{ - char *otok = tok; - int i; - - ifrom--; - ito--; - - for (i = 0; i < ifrom; i++) { - if (c[i] == '\0') { // line ended before this column - *tok = '\0'; - if (save) - *save = '\0'; - return; - } - } - - if (save) // save from ifrom on - strcpy(save, c+i); - - if (condense) { - for (; i <= ito; i++) { // save only nonwhite characters - if (c[i] > ' ') - *tok++ = c[i]; - } - } - else { - if (c[i] == ' ' && save != NULL)// if it starts with a space, it's empty - *save = '\0'; - - while (i <= ito) { // take up to any whitespace - if (c[i] <= ' ') - break; - else if (c[i] == '(') { // starts with paren? take to close paren - while (i <= ito && c[i]) { - if ((*tok++ = c[i++]) == ')') - break; - } - } - else if (c[i] == '.') { // period means literal character following - *tok++ = c[i++]; - if (i <= ito && c[i]) - *tok++ = c[i++]; - } - else - *tok++ = c[i++]; - } - } - - *tok = '\0'; - trim(otok); -} - -// --------------------------------------------------------------------------------- -// opcode table -// --------------------------------------------------------------------------------- - -// modifiers for the opcode definition table: - -#define L "L" // long -#define X "X" // absolute displacement -#define I "I" // indirect -#define IDX "0123" // indexed (some LDX commands in the DMS source say LDX L0, so accept 0 -#define E "E" // even address -#define NONE "" -#define ALL L X I IDX // hope non-Microsoft C accepts and concatenates strings like this -#define ANY "\xFF" -#define NUMS "0123456789" - -#define IS_DBL 0x0001 // double word operand implies even address -#define IS_ABS 0x0002 // always uses absolute addressing mode (implied X) -#define NO_IDX 0x0004 // even with 1 or 2 modifier, this is not really indexed (for STX/LDX) -#define NO_ARGS 0x0008 // statement takes no arguments -#define IS_1800 0x0010 // 1800-only directive or instruction, flagged if 1800 mode is not enabled -#define TRAP 0x1000 // debug this instruction - -struct tag_op { // OPCODE TABLE - char *mnem; - int opcode; - void (*handler)(struct tag_op *op, char *label, char *mods, char *arg); - char *mods_allowed; - char *mods_implied; - int flags; -}; - // special opcode handlers -void std_op (struct tag_op *op, char *label, char *mods, char *arg); -void b_op (struct tag_op *op, char *label, char *mods, char *arg); -void bsc_op (struct tag_op *op, char *label, char *mods, char *arg); -void bsi_op (struct tag_op *op, char *label, char *mods, char *arg); -void mdx_op (struct tag_op *op, char *label, char *mods, char *arg); -void shf_op (struct tag_op *op, char *label, char *mods, char *arg); - -void x_aif (struct tag_op *op, char *label, char *mods, char *arg); -void x_aifb (struct tag_op *op, char *label, char *mods, char *arg); -void x_ago (struct tag_op *op, char *label, char *mods, char *arg); -void x_agob (struct tag_op *op, char *label, char *mods, char *arg); -void x_anop (struct tag_op *op, char *label, char *mods, char *arg); -void x_abs (struct tag_op *op, char *label, char *mods, char *arg); -void x_call (struct tag_op *op, char *label, char *mods, char *arg); -void x_dsa (struct tag_op *op, char *label, char *mods, char *arg); -void x_file (struct tag_op *op, char *label, char *mods, char *arg); -void x_link (struct tag_op *op, char *label, char *mods, char *arg); -void x_libf (struct tag_op *op, char *label, char *mods, char *arg); -void x_org (struct tag_op *op, char *label, char *mods, char *arg); -void x_opt (struct tag_op *op, char *label, char *mods, char *arg); -void x_ces (struct tag_op *op, char *label, char *mods, char *arg); -void x_bes (struct tag_op *op, char *label, char *mods, char *arg); -void x_bss (struct tag_op *op, char *label, char *mods, char *arg); -void x_dc (struct tag_op *op, char *label, char *mods, char *arg); -void x_dec (struct tag_op *op, char *label, char *mods, char *arg); -void x_decs (struct tag_op *op, char *label, char *mods, char *arg); -void x_ebc (struct tag_op *op, char *label, char *mods, char *arg); -void x_end (struct tag_op *op, char *label, char *mods, char *arg); -void x_ent (struct tag_op *op, char *label, char *mods, char *arg); -void x_epr (struct tag_op *op, char *label, char *mods, char *arg); -void x_equ (struct tag_op *op, char *label, char *mods, char *arg); -void x_exit (struct tag_op *op, char *label, char *mods, char *arg); -void x_ils (struct tag_op *op, char *label, char *mods, char *arg); -void x_iss (struct tag_op *op, char *label, char *mods, char *arg); -void x_libr (struct tag_op *op, char *label, char *mods, char *arg); -void x_lorg (struct tag_op *op, char *label, char *mods, char *arg); -void x_dmes (struct tag_op *op, char *label, char *mods, char *arg); -void x_dn (struct tag_op *op, char *label, char *mods, char *arg); -void x_dump (struct tag_op *op, char *label, char *mods, char *arg); -void x_pdmp (struct tag_op *op, char *label, char *mods, char *arg); -void x_hdng (struct tag_op *op, char *label, char *mods, char *arg); -void x_list (struct tag_op *op, char *label, char *mods, char *arg); -void x_spac (struct tag_op *op, char *label, char *mods, char *arg); -void x_spr (struct tag_op *op, char *label, char *mods, char *arg); -void x_ejct (struct tag_op *op, char *label, char *mods, char *arg); -void x_trap (struct tag_op *op, char *label, char *mods, char *arg); -void x_xflc (struct tag_op *op, char *label, char *mods, char *arg); - -struct tag_op ops[] = { - ".OPT", 0, x_opt, NONE, NONE, 0, // non-IBM extensions - "TRAP", 0, x_trap, NONE, NONE, 0, // assembler breakpoint trap - ".CES", 0, x_ces, NONE, NONE, 0, // lets us specify simulated console entry switch values for startup - - "ABS", 0, x_abs, NONE, NONE, 0, - "BES", 0, x_bes, E, NONE, 0, // standard pseudo-ops - "BSS", 0, x_bss, E, NONE, 0, - "DC", 0, x_dc, NONE, NONE, 0, - "DEC", 0, x_dec, E, E, IS_DBL, - "DECS", 0, x_decs, E, E, IS_DBL, // this is an IBM 1800 directive - "DMES", 0, x_dmes, ANY, NONE, 0, - "DN", 0, x_dn, NONE, NONE, 0, - "DSA", 0, x_dsa, NONE, NONE, 0, - "DUMP", 0, x_dump, NONE, NONE, 0, - "EBC", 0, x_ebc, NONE, NONE, 0, - "EJCT", 0, x_ejct, NONE, NONE, 0, - "END", 0, x_end, NONE, NONE, 0, - "ENT", 0, x_ent, NONE, NONE, 0, - "EPR", 0, x_epr, NONE, NONE, 0, - "EQU", 0, x_equ, NONE, NONE, 0, - "EXIT", 0, x_exit, NONE, NONE, 0, // alias for call $exit since we don't have macros yet - "FILE", 0, x_file, NONE, NONE, 0, - "HDNG", 0, x_hdng, ANY, NONE, 0, - "ILS", 0, x_ils, NUMS, NONE, 0, - "ISS", 0, x_iss, NUMS, NONE, 0, - "LIBF", 0, x_libf, NONE, NONE, 0, - "LIBR", 0, x_libr, NONE, NONE, 0, - "LINK", 0, x_link, NONE, NONE, 0, - "LIST", 0, x_list, NONE, NONE, 0, - "LORG", 0, x_lorg, NONE, NONE, 0, - "ORG", 0, x_org, NONE, NONE, 0, - "PDMP", 0, x_pdmp, NONE, NONE, 0, - "SPAC", 0, x_spac, NONE, NONE, 0, - "SPR", 0, x_spr, NONE, NONE, 0, - "XFLC", 0, x_xflc, NONE, NONE, 0, - - "A", 0x8000, std_op, ALL, NONE, 0, // standard addressing ops - "AD", 0x8800, std_op, ALL, NONE, IS_DBL, - "AND", 0xE000, std_op, ALL, NONE, 0, - "BSI", 0x4000, bsi_op, ALL, NONE, 0, - "CALL", 0x4000, x_call, ALL, L, 0, // alias for BSI L, or external call - "CMP", 0xB000, std_op, ALL, NONE, IS_1800, // this is an IBM 1800-only instruction - "DCM", 0xB800, std_op, ALL, NONE, IS_1800, // this is an IBM 1800-only instruction - "D" , 0xA800, std_op, ALL, NONE, 0, - "EOR", 0xF000, std_op, ALL, NONE, 0, - "LD", 0xC000, std_op, ALL, NONE, 0, - "LDD", 0xC800, std_op, ALL, NONE, IS_DBL, - "LDS", 0x2000, std_op, NONE, NONE, IS_ABS, - "LDX", 0x6000, std_op, ALL, NONE, IS_ABS|NO_IDX, - "M", 0xA000, std_op, ALL, NONE, 0, - "MDX", 0x7000, mdx_op, ALL, NONE, 0, - "MDM", 0x7000, mdx_op, L, L, 0, // like MDX L - "NOP", 0x1000, std_op, NONE, NONE, NO_ARGS, - "OR", 0xE800, std_op, ALL, NONE, 0, - "S", 0x9000, std_op, ALL, NONE, 0, - "SD", 0x9800, std_op, ALL, NONE, IS_DBL, - "STD", 0xD800, std_op, ALL, NONE, IS_DBL, - "STO", 0xD000, std_op, ALL, NONE, 0, - "STS", 0x2800, std_op, ALL, NONE, 0, - "STX", 0x6800, std_op, ALL, NONE, NO_IDX, - "WAIT", 0x3000, std_op, NONE, NONE, IS_ABS, - "XCH", 0x18D0, std_op, NONE, NONE, 0, // same as RTE 16, 18C0 + 10 - "XIO", 0x0800, std_op, ALL, NONE, IS_DBL, - - "BSC", 0x4800, bsc_op, ALL, NONE, 0, // branch family - "BOSC", 0x4840, bsc_op, ALL, NONE, 0, // is BOSC always long form? No. - "SKP", 0x4800, bsc_op, NONE, NONE, 0, // alias for BSC one word version - - "B", 0x4800, b_op, ALL, NONE, 0, // alias for MDX or BSC L - "BC", 0x4802, std_op, ALL, L, 0, // alias for BSC L - "BN", 0x4828, std_op, ALL, L, 0, // alias for BSC L - "BNN", 0x4810, std_op, ALL, L, 0, // alias for BSC L - "BNP", 0x4808, std_op, ALL, L, 0, // alias for BSC L - "BNZ", 0x4820, std_op, ALL, L, 0, // alias for BSC L - "BO", 0x4801, std_op, ALL, L, 0, // alias for BSC L - "BOD", 0x4840, std_op, ALL, L, 0, // alias for BSC L - "BP", 0x4830, std_op, ALL, L, 0, // alias for BSC L - "BZ", 0x4818, std_op, ALL, L, 0, // alias for BSC L - - "RTE", 0x18C0, shf_op, IDX X, X, 0, // shift family - "SLA", 0x1000, shf_op, IDX X, X, 0, - "SLC", 0x10C0, shf_op, IDX X, X, 0, - "SLCA", 0x1040, shf_op, IDX X, X, 0, - "SLT", 0x1080, shf_op, IDX X, X, 0, - "SRA", 0x1800, shf_op, IDX X, X, 0, - "SRT", 0x1880, shf_op, IDX X, X, 0, - - "AIF", 0, x_aif, NONE, NONE, 0, // assemble if - "AIFB", 0, x_aifb, NONE, NONE, 0, // assemble if - "AGO", 0, x_ago, NONE, NONE, 0, // assemble goto - "AGOB", 0, x_agob, NONE, NONE, 0, // assemble goto - "ANOP", 0, x_anop, NONE, NONE, 0, // assemble target - - NULL // end of table -}; - -// --------------------------------------------------------------------------------- -// addextn - apply file extension 'extn' to filename 'fname' and put result in 'outbuf' -// if outbuf is NULL, we allocate a buffer -// --------------------------------------------------------------------------------- - -char *addextn (char *fname, char *extn, char *outbuf) -{ - char *buf, line[500], *c; - - buf = (outbuf == NULL) ? line : outbuf; - - strcpy(buf, fname); // create listfn from first source filename (e.g. xxx.lst); - if ((c = strrchr(buf, '\\')) == NULL) - if ((c = strrchr(buf, '/')) == NULL) - if ((c = strrchr(buf, ':')) == NULL) - c = buf; - - if ((c = strrchr(c, '.')) == NULL) - strcat(buf, extn); - else - strcpy(c, extn); - - return (outbuf == NULL) ? astring(line) : outbuf; -} - -// --------------------------------------------------------------------------------- -// controlcard - examine an assembler control card (* in column 1) -// --------------------------------------------------------------------------------- - -BOOL controlcard (char *line) -{ - if (strnicmp(line, "*LIST", 5) == 0) { // turn on listing file even if not specified on command line - do_list = list_on = TRUE; - return TRUE; - } - - if (strnicmp(line, "*XREF", 5) == 0) { - do_xref = TRUE; - return TRUE; - } - - if (strnicmp(line, "*PRINT SYMBOL TABLE", 19) == 0) { - do_syms = TRUE; - return TRUE; - } - - if (strnicmp(line, "*SAVE SYMBOL TABLE", 18) == 0) { - savetable = TRUE; - return TRUE; - } - - if (strnicmp(line, "*SYSTEM SYMBOL TABLE", 20) == 0) { - preload = TRUE; - preload_symbols(); - return TRUE; - } - - return FALSE; -} - -// --------------------------------------------------------------------------------- -// stuff - insert characters into a line -// --------------------------------------------------------------------------------- - -void stuff (char *buf, char *tok, int maxchars) -{ - while (*tok) { - *buf++ = *tok++; - - if (maxchars) - if (--maxchars <= 0) - break; - } -} - -// --------------------------------------------------------------------------------- -// format_line - construct a source code input line from components -// --------------------------------------------------------------------------------- - -void format_line (char *buf, char *label, char *op, char *mods, char *args, char *remarks) -{ - int i; - - if (tabformat) { - sprintf(buf, "%s\t%s\t%s\t%s\t%s", label, op, mods, args, remarks); - } - else { - for (i = 0; i < 72; i++) - buf[i] = ' '; - buf[i] = '\0'; - - stuff(buf+20, label, 5); - stuff(buf+26, op, 4); - stuff(buf+31, mods, 2); - stuff(buf+34, args, 72-34); - } -} - -// --------------------------------------------------------------------------------- -// lookup_op - find an opcode -// --------------------------------------------------------------------------------- - -struct tag_op * lookup_op (char *mnem) -{ - struct tag_op *op; - int i; - - for (op = ops; op->mnem != NULL; op++) { - if ((i = strcmp(op->mnem, mnem)) == 0) - return op; - - if (i > 0) - break; - } - return NULL; -} - -// --------------------------------------------------------------------------------- -// bincard - routines to write IBM 1130 Card object format -// --------------------------------------------------------------------------------- - -unsigned short bincard[54]; // the 54 data words that can fit on a binary format card -char binflag[45]; // the relocation flags of the 45 buffered object words (0, 1, 2, 3) -int bincard_n = 0; // number of object words stored in bincard (0-45) -int bincard_seq = 0; // card output sequence number -int bincard_org = 0; // origin of current card-full -int bincard_maxaddr = 0; -BOOL bincard_first = TRUE; // TRUE when we're to write the program type card - -// bincard_init - prepare a new object data output card - -void bincard_init (void) -{ - memset(bincard, 0, sizeof(bincard)); // clear card data - memset(binflag, 0, sizeof(binflag)); // clear relocation data - bincard_n = 0; // no data - bincard[0] = bincard_org; // store load address - bincard_maxaddr = MAX(bincard_maxaddr, bincard_org-1); // save highest address written-to (this may be a BSS) -} - -// binard_writecard - emit a card. sbrk_text = NULL for normal data cards, points to comment text for sbrk card -// note: sbrk_text if not NULL MUST be a writeable buffer of at LEAST 71 characters - -void bincard_writecard (char *sbrk_text) -{ - unsigned short binout[80]; - char ident[12]; - int i, j; - - if (sbrk_text != NULL) { // sbrk card has 4 binary words followed by comment text - for (j = 66; j < 71; j++) // be sure input columns 67..71 are nonblank (have version number) - if (sbrk_text[j] <= ' ') - break; - - if (j < 71) // sbrk card didn't have the info, stuff in current release - for (j = 0; j < 5; j++) - sbrk_text[66+j] = dmsversion[j]; - - binout[0] = 0; - binout[1] = 0; - binout[2] = 0; - binout[3] = 0x1000; - - sbrk_text += 5; // start at the real column 6 (after *SBRK - for (j = 5; j < 72; j++) - binout[j] = (*sbrk_text) ? ascii_to_hollerith(*sbrk_text++) : 0; - - } - else { // binary card format packs 54 words into 72 columns - for (i = j = 0; i < 54; i += 3, j += 4) { - binout[j ] = ( bincard[i] & 0xFFF0); - binout[j+1] = ((bincard[i] << 12) & 0xF000) | ((bincard[i+1] >> 4) & 0x0FF0); - binout[j+2] = ((bincard[i+1] << 8) & 0xFF00) | ((bincard[i+2] >> 8) & 0x00F0); - binout[j+3] = ((bincard[i+2] << 4) & 0xFFF0); - } - } - - sprintf(ident, "%08ld", ++bincard_seq); // append sequence text - memmove(ident, progname, MIN(strlen(progname), 4)); - - for (i = 0; i < 8; i++) - binout[j++] = ascii_to_hollerith(ident[i]); - - fxwrite(binout, sizeof(binout[0]), 80, fout); // write card image -} - -// binard_writedata - emit an object data card - -void bincard_writedata (void) -{ - unsigned short rflag = 0; - int i, j, nflag = 0; - - bincard[1] = 0; // checksum - bincard[2] = 0x0A00 | bincard_n; // data card type + word count - - for (i = 0, j = 3; i < bincard_n; i++) { // construct relocation indicator bitmap - if (nflag == 8) { - bincard[j++] = rflag; - rflag = 0; - nflag = 0; - } - rflag = (rflag << 2) | (binflag[i] & 3); - nflag++; - } - - if (nflag > 0) - bincard[j] = rflag << (16 - 2*nflag); - - bincard_writecard(FALSE); // emit the card -} - -// bincard_flush - flush any pending binary data - -void bincard_flush (void) -{ - if (bincard_n > 0) - bincard_writedata(); - - bincard_init(); -} - -// bincard_sbrk - emit an SBRK card - -void bincard_sbrk (char *line) -{ - if (bincard_first) - bincard_typecard(); - else - bincard_flush(); - - bincard_writecard(line); -} - -// bincard_setorg - set the origin - -void bincard_setorg (int neworg) -{ - bincard_org = neworg; // set origin for next card - bincard_flush(); // flush any current data & store origin -} - -// bincard_endcard - write end of program card - -void bincard_endcard (void) -{ - bincard_flush(); - - bincard[0] = (bincard_maxaddr + 2) & ~1; // effective length: add 1 to max origin, then 1 more to round up - bincard[1] = 0; - bincard[2] = 0x0F00; - bincard[3] = pta & 0xFFFF; - - bincard_writecard(NULL); -} - -// bincard_typecard - write the program type - -void bincard_typecard (void) -{ - int i; - - if (! bincard_first) - return; - - bincard_first = FALSE; - - memset(bincard, 0, sizeof(bincard)); - - bincard[2] = (unsigned short) ((progtype << 8) | intmode | realmode); - -// all indices not listed are documented as 'reserved' - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - case PROGTYPE_RELOCATABLE: -// bincard[ 4] = 0; // length of common (fortran only) - bincard[ 5] = 0x0003; -// bincard[ 6] = 0; // length of work area (fortran only) - bincard[ 8] = ndefined_files; - namecode(&bincard[9], progname); - bincard[11] = (pta < 0) ? 0 : pta; - break; - - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - bincard[ 5] = 3*nentries; - for (i = 0; i < nentries; i++) { - namecode(&bincard[9+3*i], entry[i]->name); - bincard[11+3*i] = entry[i]->value; - } - break; - - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - bincard[ 5] = 6+nintlevels; - namecode(&bincard[9], entry[0]->name); - bincard[11] = entry[0]->value; - bincard[12] = iss_number + ISTV; // magic number ISTV is 0x33 in DMS R2V12 - bincard[13] = iss_number; - bincard[14] = nintlevels; - bincard[15] = intlevel_primary; - bincard[16] = intlevel_secondary; - bincard[29] = 1; - break; - - case PROGTYPE_ILS: - bincard[ 2] = (unsigned short) (progtype << 8); - bincard[ 5] = 4; - bincard[12] = intlevel_primary; - break; - - default: - bail("in bincard_typecard, can't happen"); - } - - bincard[1] = 0; // checksum - - bincard_writecard(NULL); - - bincard_init(); -} - -// bincard_writew - write a word to the current output card. - -void bincard_writew (int word, RELOC relative) -{ - if (pass != 2) - return; - - if (bincard_first) - bincard_typecard(); - else if (bincard_n >= 45) // flush full card buffer - bincard_flush(); - - binflag[bincard_n] = relative & 3; // store relocation bits and data word - bincard[9+bincard_n++] = word; - - if (relative != LIBF) { - bincard_maxaddr = MAX(bincard_maxaddr, bincard_org); - bincard_org++; - } -} - -// writetwo - notification that we are about to write two words which must stay together - -void writetwo (void) -{ - if (pass == 2 && outmode == OUTMODE_BINARY && bincard_n >= 44) - bincard_flush(); -} - -// handle_sbrk - handle an SBRK directive. -// This was not part of the 1130 assembler; they assembled DMS on a 360 - -void handle_sbrk (char *line) -{ - char rline[90]; - - if (pass != 2) - return; - - strncpy(rline, line, 81); // get a copy and pad it if necessary to 80 characters - rline[80] = '\0'; - while (strlen(rline) < 80) - strcat(rline, " "); - - switch (outmode) { - case OUTMODE_LOAD: - fprintf(fout, "#SBRK%s\n", trim(rline+5)); - - case OUTMODE_BINARY: - bincard_sbrk(rline); - break; - - default: - bail("in handle_sbrk, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// namecode - turn a string into a two-word packed name -// --------------------------------------------------------------------------------- - -void namecode (unsigned short *words, char *tok) -{ - long val = 0; - int i, ch; - - for (i = 0; i < 5; i++) { // pick up bits - if (*tok) - ch = *tok++; - else - ch = ' '; - - val = (val << 6) | (ascii_to_ebcdic_table[ch] & 0x3F); - } - - words[0] = (unsigned short) (val >> 16); - words[1] = (unsigned short) val; -} - -// --------------------------------------------------------------------------------- -// parse_line - parse one input line. -// --------------------------------------------------------------------------------- - -void parse_line (char *line) -{ - char label[100], mnem[100], arg[200], mods[20], *c; - struct tag_op *op; - - if (line[0] == '/' && line[1] == '/') // job control card? probably best to ignore it - return; - - if (line[0] == '*') { // control card comment or comment in tab-format file - if (check_control) // pay attention to control cards only at top of file - if (! controlcard(line)) - check_control = FALSE; // first non-control card shuts off sensitivity to them - - if (strnicmp(line+1, "SBRK", 4) == 0) - handle_sbrk(line); - - return; - } - - check_control = FALSE; // non-control card, consider them no more - - label[0] = '\0'; // prepare to extract fields - mods[0] = '\0'; - mnem[0] = '\0'; - arg[0] = '\0'; - - if (tabformat || strchr(line, '\t') != NULL) { // if input line has tabs, parse loosely - tabformat = TRUE; // this is a tab-formatted file - - for (c = line; *c && *c <= ' '; c++) // find first nonblank - ; - - if (*c == '*' || ! *c) // ignore as a comment - return; - - tabtok(line, label, 0, NULL); - tabtok(line, mnem, 1, NULL); - tabtok(line, mods, 2, NULL); - tabtok(line, arg, 3, opfield); - } - else { // if no tabs, use strict card-column format - if (line[20] == '*') // comment - return; - - line[72] = '\0'; // clip off sequence - - coltok(line, label, 21, 25, TRUE, NULL); - coltok(line, mnem, 27, 30, TRUE, NULL); - coltok(line, mods, 32, 33, TRUE, NULL); - coltok(line, arg, 35, 72, FALSE, opfield); - } - -// I don't know where I got this idea, but it's wrong... -// if (strchr(mods, '1') || strchr(mods, '2') || strchr(mods, '3')) { // index + X means ignore X -// if ((c = strchr(mods, 'X')) != NULL) -// strcpy(c, c+1); // remove the X -// } - - if (*label) // display org in any line with a label - setw(0, org, FALSE); - - if (! *mnem) { // label w/o mnemonic, just define the symbol - if (*label) - set_symbol(label, org, TRUE, relocate); - return; - } - - if ((op = lookup_op(mnem)) == NULL) { // look up mnemonic - if (*label) - set_symbol(label, org, TRUE, relocate);// at least define the label - - asm_error("Unknown opcode '%s'", mnem); - return; - } - - if (op->flags & TRAP) // assembler debugging breakpoint - x_trap(op, label, mods, arg); - - if (*op->mods_allowed != '\xFF') { // validate modifiers against list of allowed characters - for (c = mods; *c; ) { - if (strchr(op->mods_allowed, *c) == NULL) { - asm_warning("Modifier '%c' not permitted", *c); - strcpy(c, c+1); // remove it and keep parsing - } - else - c++; - } - } - - strcat(mods, op->mods_implied); // tack on implied modifiers - - if (strchr(mods, 'I')) // indirect implies long - strcat(mods, "L"); - - requires_even_address = op->flags & IS_DBL; - - org_advanced = strchr(mods, 'L') ? 2 : 1; // by default, * means address + 1 or 2. Sometimes it doesn't - (op->handler)(op, label, mods, arg); - - if ((op->flags & IS_1800) && ! enable_1800) - asm_warning("%s is IBM 1800-specific; use the -8 command line option", op->mnem); -} - -// --------------------------------------------------------------------------------- -// get one input line from current file or macro -// --------------------------------------------------------------------------------- - -BOOL get_line (char *buf, int nbuf, BOOL onelevel) -{ - char *retval; - - if (ended) // we hit the END command - return FALSE; - - // if macro active, return line from macro buffer, otherwise read from file - // do not pop end-of-macro if onelevel is TRUE - - if ((retval = fgets(buf, nbuf, fin)) == NULL) - return FALSE; - - lno++; // count the line - return TRUE; -} - -// --------------------------------------------------------------------------------- -// proc - process one pass of one source file -// --------------------------------------------------------------------------------- - -void proc (char *fname) -{ - char line[256], *c; - int i; - - if (strchr(fname, '.') == NULL) // if input file has no extension, - addextn(fname, ".asm", curfn); // set appropriate file extension - else - strcpy(curfn, fname); // otherwise use extension specified - -// let's leave filename case alone even if it doesn't matter -//#if (defined(_WIN32) || defined(VMS)) -// upcase(curfn); // only force uppercase of name on Windows and VMS -//#endif - - if (progname[0] == '\0') { // pick up primary filename - if ((c = strrchr(curfn, '\\')) == NULL) - if ((c = strrchr(curfn, '/')) == NULL) - if ((c = strrchr(curfn, ':')) == NULL) - c = curfn; - - strncpy(progname, c, sizeof(progname)); // take name after path - progname[sizeof(progname)-1] = '\0'; - if ((c = strchr(progname, '.')) != NULL)// remove extension - *c = '\0'; - } - - lno = 0; // reset global input line number - ended = FALSE; // have not seen END statement - - if (listfn == NULL) // if list file name is undefined, - listfn = addextn(fname, ".lst", NULL); // create from first filename - - if (verbose) - fprintf(stderr, "--- Starting file %s pass %d\n", curfn, pass); - - if ((fin = fopen(curfn, "r")) == NULL) { - perror(curfn); // oops - exit(1); - } - - if (flist) { // put banner in listing file - strcpy(listline,"=== FILE ======================================================================"); - for (i = 9, c = curfn; *c;) - listline[i++] = *c++; - listline[i] = ' '; - fputs(listline, flist); - putc('\n', flist); - list_on = TRUE; - } - // read all lines till EOF or END statement - while (get_line(line, sizeof(line), FALSE)) { - prep_line(line); // preform standard line prep - parse_line(line); // parse - listout(FALSE); // complete the listing - } - - fclose(fin); - - if (n_literals > 0) { // force out any pending literal constants at end of file - output_literals(TRUE); - listout(FALSE); - } -} - -// --------------------------------------------------------------------------------- -// prep_line - prepare input line for parsing -// --------------------------------------------------------------------------------- - -void prep_line (char *line) -{ - char *c; - - upcase(line); // uppercase it - nwout = 0; // number of words output so far - line_error = FALSE; // no errors on this line so far - - for (c = line; *c; c++) { // truncate at newline - if (*c == '\r' || *c == '\n') { - *c = '\0'; - break; - } - } - - if (flist && list_on) { // construct beginning of listing line - if (tabformat) - sprintf(listline, LINEFORMAT, lno, detab(line)); - else { - if (strlen(line) > 20) // get the part where the commands start - c = line+20; - else - c = ""; - - sprintf(listline, LINEFORMAT, lno, c); - stuff(listline, line, 20); // stuff the left margin in to the left side - } - } -} - -// --------------------------------------------------------------------------------- -// opcmp - operand name comparison routine for qsort -// --------------------------------------------------------------------------------- - -int opcmp (const void *a, const void *b) -{ - return strcmp(((struct tag_op *) a)->mnem, ((struct tag_op *) b)->mnem); -} - -// --------------------------------------------------------------------------------- -// preload_symbols - load a saved symbol table -// --------------------------------------------------------------------------------- - -void preload_symbols (void) -{ - FILE *fd; - char str[200], sym[20]; - int v; - static BOOL preloaded_already = FALSE; - - if (pass > 1 || preloaded_already) - return; - - preloaded_already = TRUE; - - if ((fd = fopen(SYSTEM_TABLE, "r")) == NULL) // read the system symbol tabl - perror(SYSTEM_TABLE); - else { - while (fgets(str, sizeof(str), fd) != NULL) { - if (sscanf(str, "%s %x", sym, &v) == 2) - set_symbol(sym, v, TRUE, FALSE); - } - fclose(fd); - } -} - -// --------------------------------------------------------------------------------- -// save_symbols - save a symbol table -// --------------------------------------------------------------------------------- - -void save_symbols (void) -{ - FILE *fd; - char str[20]; - PSYMBOL s; - - if (relocate) { - fprintf(stderr, "Can't save symbol table unless ABS assembly\n"); - return; - } - - if ((fd = fopen(SYSTEM_TABLE, "r")) != NULL) { - fclose(fd); - if (saveprompt) { - printf("Overwrite system symbol table %s? ", SYSTEM_TABLE); - fgets(str, sizeof(str), stdin); - if (str[0] != 'y' && str[0] != 'Y') - return; - } - unlink(SYSTEM_TABLE); - } - - if ((fd = fopen(SYSTEM_TABLE, "w")) == NULL) { - perror(SYSTEM_TABLE); - return; - } - - for (s = symbols; s != NULL; s = s->next) - fprintf(fd, "%-5s %04x\n", s->name, s->value); - - fclose(fd); -} - -// --------------------------------------------------------------------------------- -// startpass - initialize data structures, prepare to start a pass -// --------------------------------------------------------------------------------- - -void startpass (int n) -{ - int nops; - struct tag_op *p; - - pass = n; // reset globals: pass number - nerrors = 0; // error count - org = 0; // load address (origin) - lno = 0; // input line number - relocate = TRUE; // relocatable assembly mode - assembled = FALSE; // true if any output has been generated - list_on = do_list; // listing enable - dmes_saved = FALSE; // partial character strings output - - n_literals = 0; // literal values pending output - lit_tag = 0; - - if (pass == 1) { // first pass only - for (nops = 0, p = ops; p->mnem != NULL; p++, nops++) // count opcodes - ; - - qsort(ops, nops, sizeof(*p), opcmp); // sort the opcode table - - if (preload) - preload_symbols(); - } - else { // second pass only - if (outfn == NULL) - outfn = addextn(curfn, (outmode == OUTMODE_LOAD) ? ".out" : ".bin" , NULL); - - if ((fout = fopen(outfn, OUTWRITEMODE)) == NULL) { // open output file - perror(outfn); - exit(1); - } - - if (do_list) { // open listing file - if ((flist = fopen(listfn, "w")) == NULL) { - perror(listfn); - exit(1); - } - listhdr(); // print banner - } - } -} - -// --------------------------------------------------------------------------------- -// x_dc - DC define constant directive -// --------------------------------------------------------------------------------- - -void x_dc (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; -// char *tok; - - org_advanced = 1; // assume * means this address+1 -// doesn't make sense, but I think I found DMS listings to support it - - if (strchr(mods, 'E') != NULL) // force even address - org_even(); - - setw(0, org, FALSE); // display org in listing line - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - -// just one!? - getexpr(arg, FALSE, &expr); - writew(expr.value, expr.relative); // store value - - // pick up values, comma delimited -// for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { -// getexpr(tok, FALSE, &expr); -// writew(expr.value, expr.relative); // store value -// } -} - -// --------------------------------------------------------------------------------- -// x_dec - DEC define double word constant directive. -// --------------------------------------------------------------------------------- - -// wd[0]: 8 unused bits | characteristic (= exponent+128) -// wd[1]: sign + 15 msb of mantissa in 2's complement -// wd[2]: 16 lsb of mantissa - -// NOTE: these are wrong with Fixed point numbers - -void convert_double_to_extended (double d, unsigned short *wd) -{ - int neg, exp; - unsigned long mantissa; - unsigned char *byte = (unsigned char *) &d; - - if (d == 0.) { - wd[0] = wd[1] = wd[2] = 0; - return; - } - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM - - neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias - - exp++; // shift to account for implied 1 we added - - // get 32 bits worth of mantissa. add the implied point - mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); - - if (mantissa & (0x80000000L >> 31)) // keep 31 bits, round if necessary - mantissa += (0x80000000L >> 31); - - mantissa >>= (32-31); // get into low 31 bits - - // now turn into IBM 1130 extended precision - - exp += 128; - - if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement - - wd[0] = (unsigned short) (exp & 0xFF); - wd[1] = (unsigned short) ((neg ? 0x8000 : 0) | ((mantissa >> (31-15)) & 0x7FFF)); - wd[2] = (unsigned short) (mantissa & 0xFFFF); -} - -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- - -void convert_double_to_standard (double d, unsigned short *wd) -{ - int neg, exp; - unsigned long mantissa; - unsigned char *byte = (unsigned char *) &d; - - if (d == 0.) { - wd[0] = wd[1] = 0; - return; - } - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM - - neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias - - exp++; // shift to account for implied 1 we added - - // get 32 bits worth of mantissa. add the implied point - mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); - -// if (mantissa & (0x80000000L >> 23)) // keep 23 bits, round if necessary -// mantissa += (0x80000000L >> 23); - -// DEBUG -// printf("%8.4lf: %08lx %d\n", d, mantissa, exp); - - mantissa >>= (32-23); // get into low 23 bits - - // now turn into IBM 1130 standard precision - - exp += 128; - - if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement - - wd[0] = (unsigned short) ((neg ? 0x8000 : 0) | ((mantissa >> (23-15)) & 0x7FFF)); - wd[1] = (unsigned short) ((mantissa & 0x00FF) << 8) | (exp & 0xFF); - -// DEBUG -// printf(" D %04x%04x\n", wd[0], wd[1]); -} - -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- - -void convert_double_to_fixed (double d, unsigned short *wd, int bexp) -{ - int neg, exp, rshift; - unsigned long mantissa; - unsigned char *byte = (unsigned char *) &d; - - if (d == 0.) { - wd[0] = wd[1] = 0; - return; - } - - // note: we assume that this computer uses ANSI floating point - - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM - - neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias - - exp++; // shift to account for implied 1 we added - - // get 32 bits worth of mantissa. add the implied point - mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); - - mantissa >>= 1; // shift it out of the sign bit - -// DEBUG -// printf("%8.4lf: %08lx %d\n", d, mantissa, exp); - - rshift = bexp - exp; - - if (rshift > 0) { - mantissa >>= rshift; - } - else if (rshift < 0) { - mantissa >>= (-rshift); - asm_warning("Fixed point overflow"); - } - - if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement - -// DEBUG -// printf(" B %08lx\n", mantissa); - - wd[0] = (unsigned short) ((mantissa >> 16) & 0xFFFF); // return all of the bits; no exponent here - wd[1] = (unsigned short) (mantissa & 0xFFFF); -} - -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- - -void getDconstant (char *tok, unsigned short *wd) -{ - unsigned long l; - char *b, *fmt; - double d; - int bexp, fixed; - - wd[0] = 0; - wd[1] = 0; - - if (strchr(tok, '.') == NULL && strchr(tok, 'B') == NULL && strchr(tok, 'E') == NULL) { - fmt = "%ld"; - if (*tok == '/') { // I don't see that this is legal but can't hurt to allow it - fmt = "%lx"; - tok++; - } - if (sscanf(tok, fmt, &l) != 1) { // no decimal means it's an integer? - asm_error("Syntax error in constant"); - } - else { - wd[0] = (unsigned short) ((l >> 16) & 0xFFFF); // high word - wd[1] = (unsigned short) (l & 0xFFFF); // low word - } - return; - } - - fixed = 0; - if ((b = strchr(tok, 'B')) != NULL) { - fixed = 1; - bexp = atoi(b+1); - *b = '\0'; // truncate at the b - } - if (sscanf(tok, "%lg", &d) != 1) { - asm_error("Syntax error in constant"); - return; - } - - if (fixed) - convert_double_to_fixed(d, wd, bexp); - else - convert_double_to_standard(d, wd); -} - -// --------------------------------------------------------------------------------- -// If the input value is an integer with no decimal point and no B or E, -// DEC generates a double INTEGER value. -// IBM documentation ranges from ambiguous to wrong on this point, but -// examination of the DMS microfiche supports this. -// --------------------------------------------------------------------------------- - -void x_dec (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short wd[2]; - - org_advanced = 2; // assume * means address after this location, since it's +1 for dc? - - org_even(); // even address is implied - setw(0, org, FALSE); // display the origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - -// just one!? - getDconstant(arg, wd); - writew(wd[0], FALSE); // write hiword, then loword - writew(wd[1], FALSE); - - // pick up values, comma delimited -// for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { -// getDconstant(tok, wd); -// -// writew(wd[0], FALSE); // write hiword, then loword -// writew(wd[1], FALSE); -} - -// --------------------------------------------------------------------------------- -// DECS directive. Writes just the high word of a DEC value -// --------------------------------------------------------------------------------- - -void x_decs (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short wd[2]; - - org_advanced = 1; // assume * means address after this location - - setw(0, org, FALSE); // display the origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - getDconstant(arg, wd); - writew(wd[0], FALSE); // write hiword ONLY -} - -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- - -void x_xflc (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *tok, *b; - double d; - int bexp, fixed; - unsigned short wd[3]; - - org_advanced = 2; // who knows? - - setw(0, org, FALSE); // display the origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - // pick up values, comma delimited - for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { - bexp = 0; - if ((b = strchr(tok, 'B')) != NULL) { - bexp = atoi(b+1); - fixed = TRUE; - *b = '\0'; // truncate at the b - asm_warning("Fixed point extended floating constant?"); - } - - if (sscanf(tok, "%lg", &d) != 1) { - asm_error("Syntax error in constant"); - d = 0.; - } - - convert_double_to_extended(d, wd); - - writew(wd[0], ABSOLUTE); - writew(wd[1], ABSOLUTE); - writew(wd[2], ABSOLUTE); - } -} - -// --------------------------------------------------------------------------------- -// x_equ - EQU directive -// --------------------------------------------------------------------------------- - -void x_equ (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address, not incremented - - getexpr(arg, FALSE, &expr); - - setw(0, expr.value, expr.relative); // show this as address - - if (*label) // EQU is all about defining labels, better have one - set_symbol(label, expr.value, TRUE, expr.relative); -// else // IBM assembler doesn't complain about this -// asm_error("EQU without label?"); -} - -// --------------------------------------------------------------------------------- -// x_lorg - LORG directive -- output queued literal values -// --------------------------------------------------------------------------------- - -void x_lorg (struct tag_op *op, char *label, char *mods, char *arg) -{ - org_advanced = FALSE; // * means this address (not used, though) - output_literals(FALSE); // generate .DC's for queued literal values -} - -// --------------------------------------------------------------------------------- -// x_abs - ABS directive -// --------------------------------------------------------------------------------- - -void x_abs (struct tag_op *op, char *label, char *mods, char *arg) -{ - if (assembled) - asm_error("ABS must be first statement"); - - relocate = ABSOLUTE; - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - case PROGTYPE_RELOCATABLE: - progtype = PROGTYPE_ABSOLUTE; // change program type, still assumed to be mainline - break; - - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - case PROGTYPE_ILS: - asm_error("ABS not allowed with LIBF, ENT, ILS or ISS"); - break; - - default: - bail("in x_libr, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// x_call - ORG pseudo-op -// --------------------------------------------------------------------------------- - -void x_call (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - static struct tag_op *bsi = NULL; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("CALL missing argument"); - return; - } - - if (pass == 1) { // it will take two words in any case - org += 2; - return; - } - - setw(0, org, FALSE); // display origin - - if (lookup_symbol(arg, FALSE) != NULL) { // it's a defined symbol? - if (bsi == NULL) - if ((bsi = lookup_op("BSI")) == NULL) - bail("Can't find BSI op"); - - (bsi->handler)(bsi, "", "L", arg); - } - else { - namecode(words, arg); // emit namecode for loader - - writetwo(); - writew(words[0], CALL); - writew(words[1], ABSOLUTE); - } -} - -// --------------------------------------------------------------------------------- -// x_org - ORG directive -// --------------------------------------------------------------------------------- - -void x_org (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (*label) // label is defined BEFORE the new origin is set!!! - set_symbol(label, org, TRUE, relocate); - - if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - setorg(expr.value); // set origin to this value -} - -// --------------------------------------------------------------------------------- -// x_end - END directive -// --------------------------------------------------------------------------------- - -void x_end (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (*arg) { // they're specifing the program start address - if (getexpr(arg, FALSE, &expr) == S_DEFINED) - pta = expr.value; - } - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - setw(0, org, FALSE); // display origin - - ended = TRUE; // assembly is done, stop reading file -} - -// --------------------------------------------------------------------------------- -// x_ent - ENT op -// --------------------------------------------------------------------------------- - -void x_ent (struct tag_op *op, char *label, char *mods, char *arg) -{ - PSYMBOL s; - - org_advanced = FALSE; // * means this address - - if (pass < 2) - return; - -// if (*label) // define label -// set_symbol(label, org, TRUE, relocate); -// -// setw(0, org, FALSE); // display origin - - if (! *arg) - asm_error("No entry label specified"); - - else if ((s = lookup_symbol(arg, FALSE)) == NULL) - asm_error("Entry symbol %s not defined", arg); - - else if (nentries >= MAXENTRIES) - asm_error("Too many entries, limit is %d", MAXENTRIES); - - else - entry[nentries++] = s; // save symbol pointer - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("ENT not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - progtype = PROGTYPE_CALL; - break; - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - break; - case PROGTYPE_ILS: - asm_error("Can't mix ENT and ILS, can you?"); - break; - default: - bail("in x_libr, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// declare a libf-type subprogram -// --------------------------------------------------------------------------------- - -void x_libr (struct tag_op *op, char *label, char *mods, char *arg) -{ - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("LIBR not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - progtype = PROGTYPE_LIBF; - break; - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - progtype = PROGTYPE_ISSLIBF; - break; - case PROGTYPE_ILS: - asm_error("Can't use LIBR in an ILS"); - break; - default: - bail("in x_libr, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// x_ils - ILS directive -// --------------------------------------------------------------------------------- - -void x_ils (struct tag_op *op, char *label, char *mods, char *arg) -{ - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("ILS not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - case PROGTYPE_ILS: - progtype = PROGTYPE_ILS; - break; - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - asm_error("Invalid placement of ILS"); - break; - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - break; - default: - bail("in x_libr, can't happen"); - } - - intlevel_primary = atoi(mods); -} - -// --------------------------------------------------------------------------------- -// x_iss - ISS directive -// --------------------------------------------------------------------------------- - -void x_iss (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *tok; - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("ISS not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - case PROGTYPE_CALL: - case PROGTYPE_ISSCALL: - progtype = PROGTYPE_ISSCALL; - break; - case PROGTYPE_LIBF: - case PROGTYPE_ISSLIBF: - progtype = PROGTYPE_ISSLIBF; - break; - case PROGTYPE_ILS: - asm_error("Can't mix ISS and ILS"); - default: - bail("in x_libr, can't happen"); - } - - iss_number = atoi(mods); // get ISS number - - opfield[16] = '\0'; // be sure not to look too far into this - - nintlevels = 0; // # of interrupt levels for ISS - intlevel_primary = 0; // primary level for ISS and level for ILS - intlevel_secondary = 0; // secondary level for ISS - - if ((tok = strtok(opfield, " ")) == NULL) - asm_error("ISS missing entry label"); - else - x_ent(NULL, label, "", arg); // process as an ENT - - if ((tok = strtok(NULL, " ")) != NULL) { // get associated levels - nintlevels++; - intlevel_primary = atoi(tok); - } - - if ((tok = strtok(NULL, " ")) != NULL) { - nintlevels++; - intlevel_secondary = atoi(tok); - } -} - -void x_spr (struct tag_op *op, char *label, char *mods, char *arg) -{ - realmode = REALMODE_STANDARD; -} - -void x_epr (struct tag_op *op, char *label, char *mods, char *arg) -{ - realmode = REALMODE_EXTENDED; -} - -void x_dsa (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("DSA missing filename"); - } - else { - namecode(words, arg); - writetwo(); - writew(words[0], CALL); // special relocation bits here 3 and 1 - writew(words[1], RELATIVE); - } -} - -void x_link (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - char nline[128]; - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("LINK missing program name"); - } - else { - format_line(nline, label, "CALL", "", "$LINK", ""); - parse_line(nline); - - namecode(words, arg); - writew(words[0], ABSOLUTE); // special relocation bits here 3 and 1 - writew(words[1], ABSOLUTE); - } -} - -void x_libf (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("LIBF missing argument"); - return; - } - - if (pass == 1) { // it will take one words in any case - org++; - return; - } - - setw(0, org, FALSE); // display origin - - namecode(words, arg); // emit namecode for loader - - writetwo(); - writew(words[0], LIBF); // this one does NOT advance org! - writew(words[1], ABSOLUTE); -} - -void x_file (struct tag_op *op, char *label, char *mods, char *arg) -{ - int i, n, r; - EXPR vals[5]; - char *tok; - - for (i = 0; i < 5; i++) { - if ((tok = strtok(arg, ",")) == NULL) { - asm_error("FILE has insufficient arguments"); - return; - } - arg = NULL; // for next strtok call - - if (i == 3) { - if (strcmpi(tok, "U") != 0) - asm_error("Argument 4 must be the letter U"); - } - else if (getexpr(tok, FALSE, &vals[i]) == S_DEFINED) { - if (i <= 3 && vals[i].relative) - asm_error("Argument %d must be absolute", i+1); - else if (pass == 2 && vals[i].value == 0) - asm_error("Argument %d must be nonzero", i+1); - } - } - - writew(vals[0].value, ABSOLUTE); - writew(vals[1].value, ABSOLUTE); - writew(vals[2].value, ABSOLUTE); - writew(vals[4].value, vals[i].relative); - writew(0, ABSOLUTE); - n = MAX(1, vals[2].value); - r = 320/n; - writew(r, ABSOLUTE); - r = MAX(1, r); - writew((16*vals[1].value)/r, ABSOLUTE); - - if (pass == 2) - ndefined_files++; -} - -// --------------------------------------------------------------------------------- -// x_trap - place to set a breakpoint -// --------------------------------------------------------------------------------- - -void x_trap (struct tag_op *op, char *label, char *mods, char *arg) -{ - // debugging breakpoint -} - -// --------------------------------------------------------------------------------- -// x_ces - .CES directive (nonstandard). Specify a value for the console entry -// switches. When this program is loaded into the simulator, the switches will -// be set accordingly. Handy for bootstraps and other programs that read -// the switches. -// --------------------------------------------------------------------------------- - -void x_ces (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - if (outmode != OUTMODE_LOAD) // this works only in our loader format - return; - - if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - if (pass == 2) - fprintf(fout, "S%04x" ENDLINE, expr.value & 0xFFFF); -} - -// --------------------------------------------------------------------------------- -// x_bss - BSS directive - reserve space in core -// --------------------------------------------------------------------------------- - -void x_bss (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (! *arg) { - expr.value = 0; - expr.relative = ABSOLUTE; - } - else if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - if (strchr(mods, 'E') != NULL) // force even address - org_even(); - - if (expr.relative) - asm_error("BSS size must be an absolute value"); - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - expr.value &= 0xFFFF; // truncate to 16 bits - - if (expr.value & 0x8000) - asm_warning("Negative BSS size"); - else if (expr.value > 0) { - if (outmode == OUTMODE_LOAD) { - org += expr.value; // advance the origin by appropriate number of words - if (pass == 2) // emit new load address in output file - fprintf(fout, "@%04x%s" ENDLINE, org & 0xFFFF, relocate ? "R" : ""); - } - else { - org += expr.value; // advance the origin by appropriate number of words - if (pass == 2) - bincard_setorg(org); - } - } -} - -// --------------------------------------------------------------------------------- -// x_bes - Block Ended by Symbol directive. Like BSS but label gets address AFTER the space, instead of first address -// --------------------------------------------------------------------------------- - -void x_bes (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (! *arg) { // arg field = space - expr.value = 0; - expr.relative = ABSOLUTE; - } - else if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - if (strchr(mods, 'E') != NULL && (org & 1) != 0) - org_even(); // force even address - - if (expr.relative) - asm_error("BES size must be an absolute value"); - - if (expr.value < 0) - asm_warning("Negative BES size"); - - else if (expr.value > 0) { - setw(0, org+expr.value, FALSE); // display NEW origin - - if (outmode == OUTMODE_LOAD) { - org += expr.value; // advance the origin - if (pass == 2) // emit new load address in output file - fprintf(fout, "@%04x%s" ENDLINE, org & 0xFFFF, relocate ? "R" : ""); - } - else { - org += expr.value; // advance the origin - bincard_setorg(org); - } - } - - if (*label) // NOW define the label - set_symbol(label, org, TRUE, relocate); -} - -// --------------------------------------------------------------------------------- -// x_dmes - DMES define message directive. Various encodings, none pretty. -// --------------------------------------------------------------------------------- - -int dmes_wd; -int dmes_nc; -enum {CODESET_CONSOLE, CODESET_1403, CODESET_1132, CODESET_EBCDIC} dmes_cs; -void stuff_dmes (int ch, int rpt); - -void x_dmes (struct tag_op *op, char *label, char *mods, char *arg) -{ - int rpt; - char *c = opfield; - BOOL cont = FALSE; - - if (dmes_saved) { // previous DMES had an odd character saved - dmes_wd = dmes_savew; - dmes_nc = 1; // stick it into the outbut buffer - } - else - dmes_nc = dmes_wd = 0; // clear output buffer - - trim(opfield); // remove trailing blanks from rest of input line (use whole thing) - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (strchr(mods, '1') != NULL) // determine the encoding scheme - dmes_cs = CODESET_1403; - else if (strchr(mods, '2') != NULL) - dmes_cs = CODESET_1132; - else if (strchr(mods, '0') != NULL || ! *mods) - dmes_cs = CODESET_CONSOLE; - else { - asm_error("Invalid printer code in tag field"); - dmes_cs = CODESET_EBCDIC; - } - - while (*c) { // pick up characters - if (*c == '\'') { // quote (') is the escape character - c++; - - rpt = 0; // get repeat count - while (BETWEEN(*c, '0', '9')) { - rpt = rpt*10 + *c++ - '0'; - } - if (rpt <= 0) // no count = insert one copy - rpt = 1; - - switch (*c) { // handle escape codes - case '\'': - stuff_dmes(*c, 1); - break; - - case 'E': - *c = '\0'; // end - break; - - case 'X': - case 'S': - stuff_dmes(' ', rpt); - break; - - case 'F': - stuff_dmes(*++c, rpt); // repeat character - break; - - case ' ': - case '\0': - cont = TRUE; - *c = '\0'; // end - break; - - case 'T': - if (dmes_cs != CODESET_CONSOLE) { -badcode: asm_error("Invalid ' escape for selected printer"); - break; - } - stuff_dmes(0x41, -rpt); // tab - break; - - case 'D': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x11, -rpt); // backspace - break; - - case 'B': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x05, -rpt); // black - break; - - case 'A': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x09, -rpt); // red - break; - - case 'R': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x81, -rpt); // return - break; - - case 'L': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x03, -rpt); // line feed - break; - - default: - asm_error("Invalid ' escape in DMES"); - *c = '\0'; - break; - } - } - else // just copy literal character - stuff_dmes(*c, 1); - - if (*c) - c++; - } - - dmes_saved = FALSE; - - if (dmes_nc) { // odd number of characters - if (cont) { - dmes_saved = TRUE; - dmes_savew = dmes_wd; // save for next time - } - else - stuff_dmes(' ', 1); // pad with a space to force out even # of characters - } -} - -// --------------------------------------------------------------------------------- -// stuff_dmes - insert 'rpt' copies of character 'ch' into output words -// --------------------------------------------------------------------------------- - -void stuff_dmes (int ch, int rpt) -{ - int nch, i; // nch is translated output value - - if (rpt < 0) { // negative repeat means no translation needed - rpt = -rpt; - nch = ch; - } - else { - switch (dmes_cs) { - case CODESET_CONSOLE: - nch = 0x21; - for (i = 0; i < 256; i++) { - if (conout_to_ascii[i] == ch) { - nch = i; - break; - } - } - break; - - case CODESET_EBCDIC: - nch = ascii_to_ebcdic_table[ch & 0x7F]; - if (nch == 0) - nch = 0x7F; - break; - - case CODESET_1403: - nch = ascii_to_1403_table[ch & 0x7F]; - if (nch == 0) - nch = 0x7F; - break; - - case CODESET_1132: - nch = 0x40; - for (i = 0; i < WHEELCHARS_1132; i++) { - if (codewheel1132[i].ascii == ch) { - nch = codewheel1132[i].ebcdic; - break; - } - } - break; - - default: - bail("bad cs in x_dmes, can't happen"); - break; - } - } - - while (--rpt >= 0) { // pack them into words, output when we have two - if (dmes_nc == 0) { - dmes_wd = (nch & 0xFF) << 8; - dmes_nc = 1; - } - else { - dmes_wd |= (nch & 0xFF); - writew(dmes_wd, FALSE); - dmes_nc = 0; - } - } -} - -// --------------------------------------------------------------------------------- -// x_ebc - handle EBCDIC string definition (delimited with periods) -// --------------------------------------------------------------------------------- - -void x_ebc (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *p; - -// setw(0, org, FALSE); - if (*label) - set_symbol(label, org, TRUE, relocate); - - p = trim(opfield); // remove trailing blanks from rest of input line (use whole thing) - - if (*p != '.') { - asm_error("EBC data must start with ."); - return; - } - p++; // skip leading period - - dmes_nc = dmes_wd = 0; // clear output buffer (we're borrowing the DMES packer) - dmes_cs = CODESET_EBCDIC; - - while (*p && *p != '.') // store packed ebcdic - stuff_dmes(*p++, 1); - - if (dmes_nc) // odd number of characters - stuff_dmes(' ', 1); // pad with a space to force out even # of characters - - if (*p != '.') - asm_error("EBC missing closing ."); -} - -// --------------------------------------------------------------------------------- -// x_dn - define name DN directive. Pack 5 characters into two words. This by the -// way is the reason the language Forth is not Fourth. -// --------------------------------------------------------------------------------- - -void x_dn (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - namecode(words, arg); - - writew(words[0], ABSOLUTE); - writew(words[1], ABSOLUTE); -} - -// --------------------------------------------------------------------------------- -// x_dump - DUMP directive - pretend we saw "call $dump, call $exit" -// --------------------------------------------------------------------------------- - -void x_dump (struct tag_op *op, char *label, char *mods, char *arg) -{ - x_pdmp(op, label, mods, arg); - x_exit(NULL, "", "", ""); // compile "call $exit" -} - -// --------------------------------------------------------------------------------- -// x_pdmp - PDMP directive - like DUMP but without the call $exit -// --------------------------------------------------------------------------------- - -void x_pdmp (struct tag_op *op, char *label, char *mods, char *arg) -{ - char nline[200], *tok; - EXPR addr[3]; - int i; - - for (i = 0, tok = strtok(arg, ","); i < 3 && tok != NULL; i++, tok = strtok(NULL, ",")) { - if (getexpr(tok, FALSE, addr+i) != S_DEFINED) { - addr[i].value = (i == 1) ? 0x3FFF : 0; - addr[i].relative = ABSOLUTE; - } - } - - org_advanced = FALSE; // * means this address+1 - - format_line(nline, label, "BSI", "L", DOLLARDUMP, ""); - parse_line(nline); // compile "call $dump" - - writew(addr[2].value, ABSOLUTE); // append arguments (0, start, end address) - writew(addr[0].value, addr[0].relative); - writew(addr[1].value, addr[1].relative); -} - -// --------------------------------------------------------------------------------- -// x_hdng - HDNG directive -// --------------------------------------------------------------------------------- - -void x_hdng (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *c; - - // label is not entered into the symbol table - - if (flist == NULL || ! list_on) { - line_error = TRUE; // inhibit listing: don't print the HDNG statement - return; - } - - line_error = TRUE; // don't print the statement - - c = skipbl(opfield); - trim(c); - fprintf(flist, "\f%s\n\n", c); // print page header -} - -// --------------------------------------------------------------------------------- -// x_list - LIST directive. enable or disable listing -// --------------------------------------------------------------------------------- - -void x_list (struct tag_op *op, char *label, char *mods, char *arg) -{ - BOOL on; - - // label is not entered into the symbol table - - line_error = TRUE; // don't print the LIST statement - - if (flist == NULL || ! list_on) { - return; - } - - if (strcmpi(arg, "ON") == 0) - on = TRUE; - else if (strcmpi(arg, "OFF") == 0) - on = FALSE; - else - on = do_list; - - list_on = on; -} - -// --------------------------------------------------------------------------------- -// x_spac - SPAC directive. Put blank lines in listing -// --------------------------------------------------------------------------------- - -void x_spac (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - // label is not entered into the symbol table - - if (flist == NULL || ! list_on) { - line_error = TRUE; // don't print the SPAC statement - return; - } - - if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - line_error = TRUE; // don't print the statement - - while (--expr.value >= 0) - putc('\n', flist); -} - -// --------------------------------------------------------------------------------- -// x_ejct - EJCT directive - put formfeed in listing -// --------------------------------------------------------------------------------- - -void x_ejct (struct tag_op *op, char *label, char *mods, char *arg) -{ - // label is not entered into the symbol table - - if (flist == NULL || ! list_on) { - line_error = TRUE; // don't print the EJCT statement - return; - } - - line_error = TRUE; // don't print the statement - - putc('\f', flist); -} - -// --------------------------------------------------------------------------------- -// basic_opcode - construct a standard opcode value from op table entry and modifier chars -// --------------------------------------------------------------------------------- - -int basic_opcode (struct tag_op *op, char *mods) -{ - int opcode = op->opcode; // basic code value - - if (strchr(mods, '1') != 0) // indexing - opcode |= 0x0100; - else if (strchr(mods, '2') != 0) - opcode |= 0x0200; - else if (strchr(mods, '3') != 0) - opcode |= 0x0300; - - if (strchr(mods, 'L')) { // two-word format - opcode |= OP_LONG; - if (strchr(mods, 'I') != 0) // and indirect to boot - opcode |= OP_INDIRECT; - } - - return opcode; -} - -// --------------------------------------------------------------------------------- -// std_op - assemble a vanilla opcode -// --------------------------------------------------------------------------------- - -void std_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - int opcode = basic_opcode(op, mods); - BOOL val_ok = FALSE; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (*arg && ! (op->flags & NO_ARGS)) { // get value argument - if (getexpr(arg, FALSE, &expr) == S_DEFINED) - val_ok = TRUE; - } - else { - expr.value = 0; - expr.relative = FALSE; - } - - if (opcode & OP_LONG) { // two-word format, just write code and value - writew(opcode, FALSE); - writew(expr.value, expr.relative); - } - else { // one-word format - if (strchr(mods, 'I') != 0) - asm_error("Indirect mode not permitted on one-word instructions"); - - if (val_ok && ! (strchr(mods, 'X') || (op->flags & IS_ABS) || ((opcode & OP_INDEXED) && ! (op->flags & NO_IDX)))) - expr.value -= (org+1); // compute displacement - - if (expr.value < -128 || expr.value > 127) {// check range - asm_error("Offset of %d is too large", expr.value); - expr.value = 0; - } - - writew(opcode | (expr.value & 0x00FF), FALSE);// that's the code - } -} - -// --------------------------------------------------------------------------------- -// mdx_op - assemble a MDX family instruction -// --------------------------------------------------------------------------------- - -void mdx_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR dest, incr = {0, FALSE}; - int opcode = basic_opcode(op, mods); - char *tok; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if ((tok = strtok(arg, ",")) == NULL) { // argument format is dest[,increment] -// asm_error("Destination not specified"); // seems not to be an error, IBM omits it sometimes - dest.value = 0; - dest.relative = ABSOLUTE; - } - else - getexpr(tok, FALSE, &dest); // parse the address - - tok = strtok(NULL, ","); // look for second argument - - if (opcode & OP_LONG) { // two word format - if (opcode & OP_INDEXED) { // format: MDX 2 dest - if (tok != NULL) - asm_error("This format takes only one argument"); - } - else { // format: MDX dest,increment - if (opcode & OP_INDIRECT) - asm_error("Indirect can't be used without indexing"); - - if (tok == NULL) { -// asm_error("This format takes two arguments"); - incr.value = 0; - incr.relative = ABSOLUTE; - } - else - getexpr(tok, FALSE, &incr); - - if (incr.value < -128 || incr.value > 127) // displacement style (fixed in ver 1.08) - asm_error("Invalid increment value (8 bits signed)"); - - opcode |= (incr.value & 0xFF); - } - - writew(opcode, ABSOLUTE); - writew(dest.value, dest.relative); - } - else { // one word format MDX val - if (tok != NULL) - asm_error("This format takes only one argument"); - - if (! (strchr(mods, 'X') || (opcode & OP_INDEXED))) - dest.value -= (org+1); // compute displacement - - if (dest.value < -128 || dest.value > 127) - asm_error("Offset/Increment of %d is too large", dest.value); - - writew(opcode | (dest.value & 0xFF), FALSE); - } -} - -// --------------------------------------------------------------------------------- -// bsi_op - BSI long instruction is like a BSC L, short is standard -// --------------------------------------------------------------------------------- - -void bsi_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - if (strchr(mods, 'L') || strchr(mods, 'I')) - bsc_op(op, label, mods, arg); - else - std_op(op, label, mods, arg); -} - -// --------------------------------------------------------------------------------- -// b_op - branch; use short or long version -// -------------------------------------------------------------------------------- - -void b_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - static struct tag_op *mdx = NULL; - - if (strchr(mods, 'L') || strchr(mods, 'I')) { - bsi_op(op, label, mods, arg); - return; - } - - if (mdx == NULL) - if ((mdx = lookup_op("MDX")) == NULL) - bail("Can't find MDX op"); - - (mdx->handler)(mdx, label, mods, arg); -} - -// --------------------------------------------------------------------------------- -// bsc_op - compute a BSC family instruction -// --------------------------------------------------------------------------------- - -void bsc_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR dest; - int opcode = basic_opcode(op, mods); - char *tok, *tests; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (opcode & OP_LONG) { // two word format - if ((tok = strtok(arg, ",")) == NULL) { // format is BSC dest[,tests] - asm_error("Destination not specified"); - dest.value = 0; - dest.relative = ABSOLUTE; - } - else - getexpr(tok, FALSE, &dest); - - tests = strtok(NULL, ","); // get test characters - } - else - tests = arg; // short format is BSC tests - - if (tests != NULL) { // stick in the testing bits - for (; *tests; tests++) { - switch (*tests) { - // bit 0x40 is the BOSC bit - case 'Z': opcode |= 0x20; break; - case '-': opcode |= 0x10; break; - case '+': - case '&': opcode |= 0x08; break; - case 'E': opcode |= 0x04; break; - case 'C': opcode |= 0x02; break; - case 'O': opcode |= 0x01; break; - default: - asm_error("Invalid test flag: '%c'", *tests); - } - } - } - - writew(opcode, ABSOLUTE); // emit code - if (opcode & OP_LONG) - writew(dest.value, dest.relative); -} - -// --------------------------------------------------------------------------------- -// shf_op - assemble a shift instruction -// --------------------------------------------------------------------------------- - -void shf_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - int opcode = basic_opcode(op, mods); - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (opcode & OP_INDEXED) { // shift value comes from index register - expr.value = 0; - expr.relative = ABSOLUTE; - } - else - getexpr(arg, FALSE, &expr); - - if (expr.relative) { - asm_error("Shift value is a relative address"); - expr.relative = ABSOLUTE; - } - - if (expr.value < 0 || expr.value > 32) { // check range - asm_error("Shift count of %d is invalid", expr.value); - expr.value = 0; - } - - writew(opcode | (expr.value & 0x3F), FALSE); // put shift count into displacement field -} - -// --------------------------------------------------------------------------------- -// x_mdm - MDM instruction -// --------------------------------------------------------------------------------- - -void x_mdm (struct tag_op *op, char *label, char *mods, char *arg) -{ - int opcode = basic_opcode(op, mods); - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - // oh dear: bug here - asm_error("'%s' is not yet supported", op->mnem); -} - -// --------------------------------------------------------------------------------- -// x_exit - EXIT directive. Assembler manual says it treats like CALL $EXIT, but -// object code reveals the truth: jump to $EXIT, which is a small value, so we can use LDX. -// --------------------------------------------------------------------------------- - -void x_exit (struct tag_op *op, char *label, char *mods, char *arg) -{ - char nline[120]; - - format_line(nline, label, "LDX", "X", DOLLAREXIT, ""); - parse_line(nline); -} - -// --------------------------------------------------------------------------------- -// x_opt - .OPT directive. Nonstandard. Possible values: -// -// .OPT CEXPR - use C precedence in evaluating expressions rather than strict left-right -// --------------------------------------------------------------------------------- - -void x_opt (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *tok; - - org_advanced = FALSE; // * means this address - - if (*label) { - asm_error("Label not permitted on .OPT statement"); - return; - } - // look for OPT arguments - for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { - if (strcmp(tok, "CEXPR") == 0) { - cexpr = TRUE; // use C expression precedence (untested) - } - else - asm_error("Unknown .OPT: '%s'", tok); - } -} - -// --------------------------------------------------------------------------------- -// askip - skip input lines until a line with the target label appears -// --------------------------------------------------------------------------------- - -void askip (char *target) -{ - char nline[200], cur_label[20], *c; - - while (get_line(nline, sizeof(nline), TRUE)) { // read next line (but don't exit a macro) - listout(FALSE); // end listing of previous input line - - prep_line(nline); // preform standard line prep - - strncpy(cur_label, nline, 6); // get first 5 characters - cur_label[5] = '\0'; - - for (c = cur_label; *c > ' '; c++) // truncate at first whitespace - ; - *c = '\0'; - // stop if there's a match - if ((target == NULL) ? (cur_label[0] == '\0') : strcmp(target, cur_label) == 0) { - parse_line(nline); // process this line - return; - } - } - - if (target != NULL) - asm_error("Label %s not found", target); -} - -// --------------------------------------------------------------------------------- -// x_aif - process conditional assembly jump -// --------------------------------------------------------------------------------- - -void x_aif (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *target, *tok; - EXPR expr1, expr2; - BOOL istrue; - enum {OP_EQ, OP_LT, OP_GT, OP_NE, OP_LE, OP_GE} cmp_op; - - // label is not entered into the symbol table - - arg = skipbl(arg); - if (*arg != '(') { - asm_error("AIF operand must start with ("); - return; - } - - arg++; // skip the paren - - // normally whitespace is never found in the arg string (see tabtok and coltok). - // However, spaces inside parens are permitted. - - if ((tok = strtok(arg, whitespace)) == NULL) { - asm_error("AIF missing first expression"); - return; - } - - getexpr(tok, FALSE, &expr1); - - if ((tok = strtok(NULL, whitespace)) == NULL) { - asm_error("AIF missing conditional operator"); - return; - } - - if (strcmp(tok, "EQ") == 0) - cmp_op = OP_EQ; - else if (strcmp(tok, "LT") == 0) - cmp_op = OP_LT; - else if (strcmp(tok, "GT") == 0) - cmp_op = OP_GT; - else if (strcmp(tok, "NE") == 0) - cmp_op = OP_NE; - else if (strcmp(tok, "LE") == 0) - cmp_op = OP_LE; - else if (strcmp(tok, "GE") == 0) - cmp_op = OP_GE; - else { - asm_error("AIF: %s is not a valid conditional operator", tok); - return; - } - - if ((tok = strtok(NULL, ")")) == NULL) { - asm_error("AIF missing second expression"); - return; - } - - getexpr(tok, FALSE, &expr2); - - switch (cmp_op) { // test the condition - case OP_EQ: istrue = expr1.value == expr2.value; break; - case OP_LT: istrue = expr1.value < expr2.value; break; - case OP_GT: istrue = expr1.value > expr2.value; break; - case OP_NE: istrue = expr1.value != expr2.value; break; - case OP_LE: istrue = expr1.value <= expr2.value; break; - case OP_GE: istrue = expr1.value >= expr2.value; break; - default: bail("in aif, can't happen"); - } - - // After the closing paren coltok and tabtok guarantee we will have no whitespace - - if ((target = strtok(arg, ",")) == NULL) // get target label - asm_warning("Missing target label"); - - if (istrue) - askip(target); // skip to the target -} - -// --------------------------------------------------------------------------------- -// x_aifb - conditional assembly jump back (macro only) -// --------------------------------------------------------------------------------- - -void x_aifb (struct tag_op *op, char *label, char *mods, char *arg) -{ - asm_error("aifb valid in macros only and not implemented in any case"); -} - -// --------------------------------------------------------------------------------- -// x_ago -// --------------------------------------------------------------------------------- - -void x_ago (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *target; - - // label is not entered into the symbol table - - // handle differently in a macro - - if ((target = strtok(arg, ",")) == NULL) // get target label - asm_warning("Missing target label"); - - askip(target); // skip to the target -} - -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- - -void x_agob (struct tag_op *op, char *label, char *mods, char *arg) -{ - asm_error("agob valid in macros only and not implemented in any case"); -} - -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- - -void x_anop (struct tag_op *op, char *label, char *mods, char *arg) -{ - // label is not entered into the symbol table - // do nothing else -} - -// --------------------------------------------------------------------------------- -// expression parser, borrowed from older code, no comments, sorry -// --------------------------------------------------------------------------------- - -char *exprptr, *oexprptr; - -#define GETNEXT (*exprptr++) -#define UNGET --exprptr - -#define LETTER 0 /* character types */ -#define DIGIT 1 -#define ETC 2 -#define ILL 3 -#define SPACE 4 -#define MULOP 5 -#define ADDOP 6 -#define EXPOP 7 - -int getnb (void); -void c_expr (EXPR *ap); -void c_expr_m (EXPR *ap); -void c_expr_e (EXPR *ap); -void c_expr_u (EXPR *ap); -void c_term (EXPR *ap); -int c_number (int c, int r, int nchar); -int digit (int c, int r); -int c_esc (int c); -void exprerr (int n); -void a1130_expr (EXPR *ap); -void a1130_term (EXPR *ap); - -char ctype[128] = { // character types -/*^0ABCDEFG */ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/*^HIJKLMNO */ ILL, SPACE, SPACE, ILL, SPACE, SPACE, ILL, ILL, -/*^PQRSTUVW */ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/*^XYZ */ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/* !"#$%&' */ SPACE, ETC, ETC, LETTER, LETTER, MULOP, MULOP, LETTER, /* $ # @ and ' are letters here */ -/* ()*+,-./ */ ETC, ETC, MULOP, ADDOP, ETC, ADDOP, ETC, MULOP, -/* 01234567 */ DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, -/* 89:;<=>? */ DIGIT, DIGIT, ETC, ETC, MULOP, ETC, MULOP, ETC, -/* @ABCDEFG */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* HIJKLMNO */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* PQRSTUVW */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* XYZ[\]^_ */ LETTER, LETTER, LETTER, ETC, ETC, ETC, EXPOP, LETTER, -/* `abcdefg */ ETC, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* hijklmno */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* pqrstuvw */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* xyz{|}~ */ LETTER, LETTER, LETTER, ETC, ADDOP, ETC, ETC, ETC -}; - -char *errstr[] = { - "Missing exponent", // 0 - "Undefined symbol", // 1 - "Division by zero", // 2 - "Illegal operator", // 3 - ") expected", // 4 - "Char expected after '", // 5 - "Char expected after .", // 6 - "Number expected after =", // 7 - "Syntax error", // 8 - "Number syntax", // 9 - "Char expected after \\", // 10 - "Relocation error" // 11 -}; - -int getnb () { - int c; - - if (cexpr) { // in C mode, handle normally - while (ctype[(c = GETNEXT)] == SPACE) - ; - } // in 1130 mode, a space terminates the expression. Here, eat the rest - else if ((c = GETNEXT) == ' ') { - while ((c = GETNEXT) != '\0') - ; - } - - return c; -} - -int symbest, exprerrno; -jmp_buf exprjmp; - -// --------------------------------------------------------------------------------- -// getexpr -// --------------------------------------------------------------------------------- - -int getexpr (char *pc, BOOL undefined_ok, EXPR *pval) -{ - symbest = S_DEFINED; // assume no questionable symbols - - pval->value = 0; - pval->relative = ABSOLUTE; - - if (! *pc) // blank expression is same as zero, ok? - return S_DEFINED; - - if (setjmp(exprjmp) != 0) { // encountered a syntax error & bailed - pval->value = 0; - pval->relative = ABSOLUTE; - return S_UNDEFINED; - } - - exprptr = oexprptr = pc; // make global the buffer pointer - - c_expr(pval); - - if (GETNEXT) // expression should have been entirely eaten - exprerr(8); // if characters are left, it's an error - - if (pval->relative < 0 || pval->relative > 1) - exprerr(11); // has to work out to an absolute or a single relative term - - if (symbest == S_DEFINED) // tell how it came out - return S_DEFINED; - - pval->value = 0; - pval->relative = ABSOLUTE; - return (pass == 1 && undefined_ok) ? S_PROVISIONAL : S_UNDEFINED; -} - -// --------------------------------------------------------------------------------- -// output_literals - construct .DC assembler lines to assemble pending literal -// constant values that have accumulated. -// --------------------------------------------------------------------------------- - -void output_literals (BOOL eof) -{ - char line[120], label[12], num[20]; - int i; - - for (i = 0; i < n_literals; i++) { // generate DC statements for any pending literal constants - if (literal[i].even && literal[i].hex) // create the value string - sprintf(num, "/%08lx", literal[i].value); - else if (literal[i].even) - sprintf(num, "%ld", literal[i].value); - else if (literal[i].hex) - sprintf(num, "/%04x", literal[i].value & 0xFFFF); - else - sprintf(num, "%d", literal[i].value); - - sprintf(label, "_L%03d", literal[i].tagno); - format_line(line, label, literal[i].even ? "DEC" : "DC", "", num, "GENERATED LITERAL CONSTANT"); - - if (eof) { - eof = FALSE; // at end of file, for first literal, only prepare blank line - sprintf(listline, LEFT_MARGIN, org); - } - else - listout(TRUE); // push out any pending line(s) - - if (flist && list_on) // this makes stuff appear in the listing - sprintf(listline, LEFT_MARGIN " %s", detab(line)); - - nwout = 0; - - parse_line(line); // assemble the constant definition - } - - n_literals = 0; // clear list -} - -// --------------------------------------------------------------------------------- -// a1130_term - extract one term of an expression -// --------------------------------------------------------------------------------- - -void a1130_term (EXPR *ap) -{ - PSYMBOL s; - char token[80], *t; - int c; - - if (cexpr) { // use C syntax - c_term(ap); - return; - } - - c = GETNEXT; - - if (ctype[c] == DIGIT) { /* number */ - ap->value = signextend(c_number(c,10,-1)); - ap->relative = ABSOLUTE; - } - else if (c == '+') { /* unary + */ - a1130_term(ap); - } - else if (c == '-') { /* unary - */ - a1130_term(ap); - ap->value = - ap->value; - } - else if (c == '/') { /* / starts a hex constant */ - ap->value = signextend(c_number(c,16,-1)); - ap->relative = ABSOLUTE; - } - else if (c == '*') { /* asterisk alone = org */ - ap->value = org + org_advanced; // here is where that offset matters! - ap->relative = relocate; - } - else if (c == '.') { /* EBCDIC constant */ - c = GETNEXT; - if (c == '\0') { - UNGET; - c = ' '; - } - c = ascii_to_ebcdic_table[c]; - ap->value = c; // VALUE IS IN LOW BYTE!!! - ap->relative = ABSOLUTE; - } - else if (ctype[c] == LETTER) { /* symbol */ - t = token; - do { - *t++ = c; - c = GETNEXT; - } while (ctype[c] == LETTER || ctype[c] == DIGIT); - UNGET; - *t++ = '\0'; - - s = lookup_symbol(token, TRUE); - add_xref(s, FALSE); - ap->value = s->value; - ap->relative = s->relative; - - symbest = MIN(symbest, s->defined); // this goes to lowest value (undefined < provisional < defined) - if (pass == 2 && s->defined != S_DEFINED) - exprerr(1); - } - else - exprerr(8); -} - -// --------------------------------------------------------------------------------- -// signextend - sign-extend a 16-bit constant value to whatever "int" is. -// --------------------------------------------------------------------------------- - -int signextend (int v) -{ - v &= 0xFFFF; // clip to 16 bits (this may not be necessary, but best to be safe?) - - if (v & 0x8000) // if sign bit is set - v |= ~0xFFFF; // sign extend - - return v; -} - -// --------------------------------------------------------------------------------- -// c_expr - evalate an expression -// --------------------------------------------------------------------------------- - -void c_expr (EXPR *ap) -{ - int c; - EXPR rop; - - c_expr_m(ap); // get combined multiplicative terms - for (;;) { // handle +/- precedence operators - if (ctype[c=getnb()] != ADDOP) { - UNGET; - break; - } - c_expr_m(&rop); // right hand operand - switch (c) { - case '+': - ap->value += rop.value; - ap->relative += rop.relative; - break; - - case '-': - ap->value -= rop.value; - ap->relative -= rop.relative; - break; - - case '|': - if (ap->relative || rop.relative) - exprerr(11); - ap->value = ((long) (ap->value)) | ((long) rop.value); - break; - - default: - printf("In expr, can't happen\n"); - } - } -} - -// --------------------------------------------------------------------------------- -// c_expr_m - get multiplicative precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_expr_m (EXPR *ap) -{ - int c; - EXPR rop; - - c_expr_e(ap); // get exponential precedence term - for (;;) { // get operator - c = getnb(); - if ((c=='<') || (c=='>')) - if (c != getnb()) // << or >> - exprerr(3); - if (ctype[c] != MULOP) { - UNGET; - break; - } - c_expr_e(&rop); // right hand operand - - switch(c) { - case '*': - if (ap->relative && rop.relative) - exprerr(11); - - ap->value *= rop.value; - ap->relative = (ap->relative || rop.relative) ? RELATIVE : ABSOLUTE; - break; - - case '/': - if (rop.value == 0) - exprerr(2); - if (ap->relative || rop.relative) - exprerr(11); - - ap->value /= rop.value; - break; - - case '%': - if (rop.value == 0) - exprerr(2); - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) % ((long) rop.value); - break; - - case '&': - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) & ((long) rop.value); - break; - - case '>': - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) >> ((long) rop.value); - break; - - case '<': - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) << ((long) rop.value); - break; - - default: - printf("In expr_m, can't happen\n"); - } - } -} - -// --------------------------------------------------------------------------------- -// c_expr_e - get exponential precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_expr_e (EXPR *ap) -{ - int c, i, v; - EXPR rop; - - c_expr_u(ap); - for (;;) { - c = getnb(); - if (ctype[c] != EXPOP) { - UNGET; - break; - } - c_expr_u(&rop); - - switch(c) { - case '^': - if (ap->relative || rop.relative) - exprerr(11); - - v = ap->value; - ap->value = 1; - for (i = 0; i < rop.value; i++) - ap->value *= v; - break; - - default: - printf("In expr_e, can't happen\n"); - } - } -} - -// --------------------------------------------------------------------------------- -// c_expr_u - get unary precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_expr_u (EXPR *ap) -{ - int c; - - if ((c = getnb()) == '!') { - a1130_term(ap); - ap->value = ~ ((long)(ap->value)); - if (ap->relative) - exprerr(11); - } - else if (c == '-') { - a1130_term(ap); - ap->value = - ap->value; - if (ap->relative) - exprerr(11); - } - else { - UNGET; - a1130_term(ap); - } -} - -// --------------------------------------------------------------------------------- -// c_term - get basic operand or parenthesized expression. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_term (EXPR *ap) -{ - int c, cc; - PSYMBOL s; - char token[80], *t; - - ap->relative = ABSOLUTE; /* assume absolute */ - - if ((c = getnb()) == '(') { /* parenthesized expr */ - c_expr(ap); /* start over at the top! */ - if ((cc = getnb()) != ')') - exprerr(4); - } - else if (c == '\'') { /* single quote: char */ - if ((c = GETNEXT) == '\0') - c = ' '; - ap->value = c_esc(c); - } - else if (ctype[c] == DIGIT) { /* number */ - ap->value = signextend(c_number(c,10,-1)); - } - else if (c == '0') { /* 0 starts a hex or octal constant */ - if ((c = GETNEXT) == 'x') { - c = GETNEXT; - ap->value = signextend(c_number(c,16,-1)); - } - else { - ap->value = signextend(c_number(c,8,-1)); - } - } - else if (c == '*') { /* asterisk alone = org */ - ap->value = org + org_advanced; - ap->relative = relocate; - } - else if (ctype[c] == LETTER) { /* symbol */ - t = token; - do { - *t++ = c; - c = GETNEXT; - } while (ctype[c] == LETTER || ctype[c] == DIGIT); - UNGET; - *t++ = '\0'; - - s = lookup_symbol(token, TRUE); - ap->value = s->value; - ap->relative = s->relative; - add_xref(s, FALSE); - symbest = MIN(symbest, s->defined); // this goes to lowest value (undefined < provisional < defined) - - if (pass == 2 && s->defined != S_DEFINED) - exprerr(1); - } - else - exprerr(8); -} - -// --------------------------------------------------------------------------------- -// c_number - get a C format constant value. Again, this is not usually used -// --------------------------------------------------------------------------------- - -int c_number (int c, int r, int nchar) -{ - int v, n; - - nchar--; - - if (c == '/' && ! cexpr) { /* special radix stuff */ - r = 16; - c = GETNEXT; - } - else if (r == 10 && c == '0' && cexpr) { /* accept C style 0x## also */ - c = GETNEXT; - if (c == 'x') { - r = 16; - c = GETNEXT; - } - else { - r = 8; - UNGET; - c = '0'; - } - } - - n = 0; /* decode number */ - while ((nchar-- != 0) && (v = digit(c, r)) >= 0) { - if (v >= r) /* out of range! */ - exprerr(9); - - n = r*n + v; - - c = GETNEXT; - if (c == '.') { // maybe make it decimal? - c = GETNEXT; - break; - } - } - - UNGET; - return (n); -} - -// --------------------------------------------------------------------------------- -// digit - get digit value of character c in radix r -// --------------------------------------------------------------------------------- - -int digit (int c, int r) -{ - if (r == 16) { - if (c >= 'A' && c <= 'F') - return (c - 'A' + 10); - } - - if (c >= '0' && c <= '9') - return (c - '0'); - - return (-1); -} - -// --------------------------------------------------------------------------------- -// c_esc - handle C character escape -// --------------------------------------------------------------------------------- - -int c_esc (int c) -{ - if (c != '\\') /* not escaped */ - return(c); - - if ((c = GETNEXT) == '\0') /* must be followed by something */ - exprerr(10); - if ((c >= 'A') && (c <= 'Z')) /* handle upper case */ - c += 'a'-'A'; - if (ctype[c] == LETTER) /* control character abbrevs */ - switch (c) { - case 'b': c = '\b'; break; /* backspace */ - case 'e': c = 27 ; break; /* escape */ - case 'f': c = '\f'; break; /* formfeed */ - case 'n': c = '\n'; break; /* newline */ - case 'r': c = '\r'; break; /* return */ - case 't': c = '\t'; break; /* horiz. tab */ - } - else if (ctype[c] == DIGIT) { /* get character by the numbers */ - c = c_number(c,8,3); /* force octal */ - } - - return c; -} - -// --------------------------------------------------------------------------------- -// exprerr - note an expression syntax error. Longjumps back to caller with failure code -// --------------------------------------------------------------------------------- - -void exprerr (int n) -{ - char msg[256]; - int nex = exprptr-oexprptr; - - strncpy(msg, oexprptr, nex); // show where the problem was - msg[nex] = '\0'; - strcat(msg, " << "); - strcat(msg, errstr[n]); - - asm_error(msg); - - exprerrno = n; - longjmp(exprjmp, 1); -} - -/* ------------------------------------------------------------------------ - * upcase - force a string to uppercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *upcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'a' && *s <= 'z') - *s -= 32; - } - - return str; -} - -/* ------------------------------------------------------------------------ - * hollerith table for IPL card ident field - * ------------------------------------------------------------------------ */ - -typedef struct { - int hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, 'c', // cent - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0x2060, '>', -}; - -int ascii_to_hollerith (int ch) -{ - int i; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].ascii == ch) - return cardcode_029[i].hollerith; - - return 0; -} - -/* ------------------------------------------------------------------------ - * detab - replace tabs with spaces for listing files - * ------------------------------------------------------------------------ */ - -char *detab (char *instr) -{ - static char outstr[256]; - char *out = outstr; - int col = 0; - - while (*instr) { - if (*instr == '\t') { - do { - *out++ = ' '; - col++; - } - while (col & 7); - } - else { - *out++ = *instr; - col++; - } - - instr++; - } - - *out = '\0'; - - return outstr; -} - -#ifndef _WIN32 - -int strnicmp (char *a, char *b, int n) -{ - int ca, cb; - - for (;;) { - if (--n < 0) // still equal after n characters? quit now - return 0; - - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -int strcmpi (char *a, char *b) -{ - int ca, cb; - - for (;;) { - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -#endif - diff --git a/Ibm1130/utils/asm1130.mak b/Ibm1130/utils/asm1130.mak deleted file mode 100644 index f95ef130..00000000 --- a/Ibm1130/utils/asm1130.mak +++ /dev/null @@ -1,175 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "asm1130.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/asm1130.exe $(OUTDIR)/asm1130.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"asm1130.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"asm1130.bsc" -BSC32_SBRS= \ - $(INTDIR)/asm1130.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/asm1130.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:no /PDB:$(OUTDIR)/"asm1130.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"asm1130.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/asm1130.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/asm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/asm1130.exe $(OUTDIR)/asm1130.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"asm1130.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"asm1130.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"asm1130.bsc" -BSC32_SBRS= \ - $(INTDIR)/asm1130.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/asm1130.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:yes /PDB:$(OUTDIR)/"asm1130.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"asm1130.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/asm1130.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/asm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\asm1130.c - -$(INTDIR)/asm1130.obj : $(SOURCE) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\util_io.c -DEP_UTIL_=\ - .\util_io.h - -$(INTDIR)/util_io.obj : $(SOURCE) $(DEP_UTIL_) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/bindump.c b/Ibm1130/utils/bindump.c deleted file mode 100644 index a5f8ea64..00000000 --- a/Ibm1130/utils/bindump.c +++ /dev/null @@ -1,755 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// --------------------------------------------------------------------------------- -// BINDUMP - dumps card deck files in assembler object format -// -// Usage: -/// bindump deckfile lists object header info & sector break cards -// bindump -v deckfile lists object data records as well -// bindump -p deckfile for system program, lists phase IDs in the deck -// bindump -s deckfile >outfile for system program, sorts the phases & writes to stdout - -#include -#include -#ifdef _WIN32 -# include -# include -# include -#endif - -#include "util_io.h" - -#ifndef TRUE - #define BOOL int - #define TRUE 1 - #define FALSE 0 -#endif - -typedef enum {R_ABSOLUTE = 0, R_RELATIVE = 1, R_LIBF = 2, R_CALL = 3} RELOC; - -BOOL verbose = FALSE; -BOOL phid = FALSE; -BOOL sort = FALSE; -unsigned short card[80], buf[54], cardtype; - -// bindump - dump a binary (card format) deck to verify sbrks, etc - -void bail (char *msg); -void dump (char *fname); -void dump_data (char *fname); -void dump_phids (char *fname); -char *getname (unsigned short *ptr); -char *getseq (void); -int hollerith_to_ascii (unsigned short h); -void process (char *fname); -void show_raw (char *name); -void show_data (void); -void show_core (void); -void show_endc (void); -void show_81 (void); -void show_main (void); -void show_sub (void); -void show_ils (void); -void show_iss (void); -void show_end (void); -void sort_phases (char *fname); -void trim (char *s); -void unpack (unsigned short *card, unsigned short *buf); -void verify_checksum(unsigned short *buf); - -int main (int argc, char **argv) -{ - char *arg; - static char usestr[] = "Usage: bindump [-psv] filename..."; - int i; - - for (i = 1; i < argc; i++) { - arg = argv[i]; - if (*arg == '-') { - arg++; - while (*arg) { - switch (*arg++) { - case 'v': - verbose = TRUE; - break; - case 'p': - phid = TRUE; // print only phase ID's - break; - case 's': - sort = TRUE; // sort deck by phases, writing to stdout - break; - default: - bail(usestr); - } - } - } - } - - for (i = 1; i < argc; i++) { - arg = argv[i]; - if (*arg != '-') - process(arg); - } - return 0; -} - -void process (char *nm) -{ -#ifdef _WIN32 - WIN32_FIND_DATA fd; - HANDLE hFind; - char *c, buf[256]; - - if (strchr(nm, '*') == NULL && strchr(nm, '?') == NULL) - dump(nm); - - else if ((hFind = FindFirstFile(nm, &fd)) == INVALID_HANDLE_VALUE) - fprintf(stderr, "No files matching '%s'\n", nm); - - else { - if ((c = strrchr(nm, '\\')) == NULL) - c = strrchr(nm, ':'); - - do { - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - continue; - - if (c == NULL) - dump(fd.cFileName); - else { - strcpy(buf, nm); - strcpy(buf + (c-nm+1), fd.cFileName); - dump(buf); - } - - } while (FindNextFile(hFind, &fd)); - - FindClose(hFind); - } -#else - dump(nm); // on unices, sh globs for us -#endif -} - -void dump (char *fname) -{ - if (sort) - sort_phases(fname); - else if (phid) - dump_phids(fname); - else - dump_data(fname); -} - -struct tag_card { - int phid, seq; - unsigned short card[80]; -}; - -int cardcomp (const void *a, const void *b) -{ - short diff; - - diff = ((struct tag_card *) a)->phid - ((struct tag_card *) b)->phid; - - return diff ? diff : (((struct tag_card *) a)->seq - ((struct tag_card *) b)->seq); -} - -void sort_phases (char *fname) -{ - int i, ncards, cardtype, len, seq = 0, phid; - struct tag_card *deck; - FILE *fd; - BOOL saw_sbrk = TRUE; - - if ((fd = fopen(fname, "rb")) == NULL) { - perror(fname); - return; - } - - fseek(fd, 0, SEEK_END); - len = ftell(fd); // get length of file - fseek(fd, 0, SEEK_SET); - - if (len <= 0 || (len % 160) != 0) { - fprintf(stderr, "%s is not a binard deck image\n"); - fclose(fd); - return; - } - - ncards = len / 160; - - if ((deck = (struct tag_card *) malloc(ncards*sizeof(struct tag_card))) == NULL) { - fprintf(stderr, "%s: can't sort, insufficient memory\n"); - fclose(fd); - return; - } - - phid = 0; - for (i = 0; i < ncards; i++) { - if (fxread(deck[i].card, sizeof(card[0]), 80, fd) != 80) { - free(deck); - fprintf(stderr, "%s: error reading deck\n"); - fclose(fd); - return; - } - - unpack(deck[i].card, buf); - deck[i].seq = seq++; - deck[i].phid = phid; - - verify_checksum(buf); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 || cardtype == 2) { // start of deck is same as sector break - saw_sbrk = TRUE; - } - else if (cardtype == 0) { - fprintf(stderr, "%s is a core image deck\n"); - free(deck); - fclose(fd); - return; - } - else if (cardtype == 0x0A && saw_sbrk) { - phid = (int) (signed short) buf[10]; - if (phid < 0) - phid = -phid; - - deck[i].phid = phid; // this belongs to the new phase - deck[i-1].phid = phid; // as does previous card - saw_sbrk = FALSE; - } - } - fclose(fd); - - qsort(deck, ncards, sizeof(struct tag_card), cardcomp); // sort the deck - -#ifdef _WIN32 - _setmode(_fileno(stdout), _O_BINARY); // set standard output to binary mode -#endif - - for (i = 0; i < ncards; i++) // write to stdout - fxwrite(deck[i].card, sizeof(card[0]), 80, stdout); - - free(deck); -} - -void dump_phids (char *fname) -{ - FILE *fp; - BOOL first = TRUE; - BOOL saw_sbrk = TRUE, neg; - short id; - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - return; - } - - printf("\n%s:\n", fname); - - while (fxread(card, sizeof(card[0]), 80, fp) > 0) { - unpack(card, buf); - verify_checksum(buf); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 && ! first) { // sector break - saw_sbrk = TRUE; - continue; - } - else { - switch (cardtype) { - case 0x00: - printf(" This is a core image deck\n"); - goto done; - break; - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x0F: - break; - - case 0x0A: - if (saw_sbrk) { - id = buf[10]; - if (id < 0) - id = -id, neg = TRUE; - else - neg = FALSE; - printf(" : %3d / %02x%s\n", id, id, neg ? " (neg)" : ""); - saw_sbrk = FALSE; - } - break; - - default: - show_raw("??? "); - } - } -done: - first = FALSE; - } - - fclose(fp); -} - -void dump_data (char *fname) -{ - FILE *fp; - BOOL first = TRUE; - char str[80]; - int i; - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - return; - } - - printf("\n%s:\n", fname); - - while (fxread(card, sizeof(card[0]), 80, fp) > 0) { - unpack(card, buf); - verify_checksum(buf); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 && ! first) { // sector break - for (i = 4; i < 72; i++) - str[i] = hollerith_to_ascii(card[i]); - - str[i] = '\0'; - trim(str+4); - printf("*SBRK %s\n", str+4); - continue; - } - else { - switch (cardtype) { - case 0x00: - if (first) - show_raw("CORE"); - if (verbose) - show_core(); - break; - - case 0x01: - show_raw("ABS "); - show_main(); - break; - case 0x02: - show_raw("REL "); - show_main(); - break; - case 0x03: - show_raw("LIB "); - show_sub(); - break; - case 0x04: - show_raw("SUB "); - show_sub(); - break; - case 0x05: - show_raw("ISSL"); - show_iss(); - break; - case 0x06: - show_raw("ISSC"); - show_iss(); - break; - case 0x07: - show_raw("ILS "); - show_ils(); - break; - case 0x0F: - show_raw("END "); - show_end(); - break; - case 0x80: - show_raw("ENDC"); - show_endc(); - break; - case 0x81: - show_raw("81 "); - show_81(); - break; - case 0x0A: - if (verbose) - show_data(); - break; - default: - show_raw("??? "); - } - } - - first = FALSE; - } - - fclose(fp); -} - -void show_data (void) -{ - int i, n, jrel, rflag, nout, ch, reloc; - BOOL first = TRUE; - - n = buf[2] & 0x00FF; - - printf("%04x: ", buf[0]); - - jrel = 3; - nout = 0; - rflag = buf[jrel++]; - for (i = 0; i < n; i++) { - if (nout >= 8) { - rflag = buf[jrel++]; - if (first) { - printf(" %s", getseq()); - first = FALSE; - } - printf("\n "); - nout = 0; - } - reloc = (rflag >> 14) & 0x03; - ch = (reloc == R_ABSOLUTE) ? ' ' : - (reloc == R_RELATIVE) ? 'R' : - (reloc == R_LIBF) ? 'L' : '@'; - - printf("%04x%c ", buf[9+i], ch); - rflag <<= 2; - nout++; - } - putchar('\n'); -} - -void show_core (void) -{ - int i, n, nout; - BOOL first = TRUE; - - n = buf[2] & 0x00FF; - - printf("%04x: ", buf[0]); - - nout = 0; - for (i = 0; i < n; i++) { - if (nout >= 8) { - if (first) { - printf(" %s", getseq()); - first = FALSE; - } - printf("\n "); - nout = 0; - } - printf("%04x ", buf[9+i]); - nout++; - } - putchar('\n'); -} - -void info (int i, char *nm, char type) -{ - if (nm) - printf("%s ", nm); - - switch (type) { - case 'd': - printf("%d ", buf[i]); - break; - - case 'x': - printf("%04x ", buf[i]); - break; - - case 'b': - printf("%02x ", buf[i] & 0xFF); - break; - - case 'n': - printf("%s ", getname(buf+i)); - break; - - default: - bail("BAD TYPE"); - } -} - -void show_main (void) -{ - printf(" "); - info(2, "prec", 'b'); - info(4, "common", 'd'); - info(6, "work", 'd'); - info(8, "files", 'd'); - info(9, "name", 'n'); - info(11, "pta", 'x'); - putchar('\n'); -} - -void show_sub (void) -{ - int i, n; - - printf(" "); - info( 2, "prec", 'b'); - - n = buf[5] / 3; - for (i = 0; i < n; i++) { - info( 9+3*i, "ent", 'n'); - info(11+3*i, NULL, 'x'); - } - - putchar('\n'); -} - -void show_iss (void) -{ - printf(" "); - info(12, "level", 'd'); - putchar('\n'); -} - -void show_ils (void) -{ - printf(" "); - info( 2, "prec", 'b'); - info( 5, "nint6", 'd'); - info( 9, "ent", 'n'); - info(11, NULL, 'x'); - info(14, "nint", 'd'); - info(15, "il1", 'd'); - info(16, "il2", 'd'); - putchar('\n'); -} - -void show_end (void) -{ - printf(" "); - info(0, "size", 'd'); - info(3, "pta", 'x'); - putchar('\n'); -} - -void show_endc(void) -{ - printf(" "); - info(52, "IX3", 'x'); - info(53, "pta", 'x'); - putchar('\n'); -} - -void show_81(void) -{ -} - -void show_raw (char *name) -{ - int i; - printf("*%s", name); - - for (i = 0; i < 12; i++) - printf(" %04x", buf[i]); - - printf(" %s\n", getseq()); -} - -char * getseq (void) -{ - static char seq[10]; - int i; - - for (i = 0; i < 8; i++) - seq[i] = hollerith_to_ascii(card[72+i]); - - seq[i] = '\0'; - return seq; -} - - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -void unpack (unsigned short *icard, unsigned short *obuf) -{ - int i, j; - unsigned short wd1, wd2, wd3, wd4; - - for (i = j = 0; i < 54; i += 3, j += 4) { - wd1 = icard[j]; - wd2 = icard[j+1]; - wd3 = icard[j+2]; - wd4 = icard[j+3]; - - obuf[i ] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F); - obuf[i+1] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF); - obuf[i+2] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF); - } -} - -void verify_checksum (unsigned short *obuf) -{ -// unsigned short sum; - - if (obuf[1] == 0) // no checksum - return; - -// if (sum != card[1]) -// printf("Checksum %04x doesn't match card %04x\n", sum, card[1]); -} - -typedef struct { - unsigned short hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, 'c', // cent - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0x2060, '>', -}; - -int hollerith_to_ascii (unsigned short h) -{ - int i; - - h &= 0xFFF0; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].hollerith == h) - return cardcode_029[i].ascii; - - return '?'; -} - -// --------------------------------------------------------------------------------- -// trim - remove trailing whitespace from string s -// --------------------------------------------------------------------------------- - -void trim (char *s) -{ - char *nb; - - for (nb = s-1; *s; s++) - if (*s > ' ') - nb = s; - - nb[1] = '\0'; -} - -int ascii_to_ebcdic_table[128] = -{ - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, - - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -char *getname (unsigned short *ptr) -{ - static char str[6]; - int i, j, ch; - long v; - - v = (ptr[0] << 16L) | ptr[1]; - - for (i = 0; i < 5; i++) { - ch = ((v >> 24) & 0x3F) | 0xC0; // recover those lost two bits - v <<= 6; - - str[i] = ' '; - - for (j = 0; j < (sizeof(ascii_to_ebcdic_table)/sizeof(ascii_to_ebcdic_table[0])); j++) { - if (ascii_to_ebcdic_table[j] == ch) { - str[i] = j; - break; - } - } - } - - str[5] = '\0'; - return str; -} - - diff --git a/Ibm1130/utils/bindump.mak b/Ibm1130/utils/bindump.mak deleted file mode 100644 index c2cbab2e..00000000 --- a/Ibm1130/utils/bindump.mak +++ /dev/null @@ -1,175 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "bindump.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/bindump.exe $(OUTDIR)/bindump.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"bindump.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"bindump.bsc" -BSC32_SBRS= \ - $(INTDIR)/bindump.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/bindump.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:$(OUTDIR)/"bindump.pdb"\ - /MACHINE:I386 /OUT:$(OUTDIR)/"bindump.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/bindump.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/bindump.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/bindump.exe $(OUTDIR)/bindump.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"bindump.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"bindump.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"bindump.bsc" -BSC32_SBRS= \ - $(INTDIR)/bindump.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/bindump.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:$(OUTDIR)/"bindump.pdb" /DEBUG\ - /MACHINE:I386 /OUT:$(OUTDIR)/"bindump.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/bindump.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/bindump.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\bindump.c - -$(INTDIR)/bindump.obj : $(SOURCE) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\util_io.c -DEP_UTIL_=\ - .\util_io.h - -$(INTDIR)/util_io.obj : $(SOURCE) $(DEP_UTIL_) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/checkdisk.c b/Ibm1130/utils/checkdisk.c deleted file mode 100644 index bf775d00..00000000 --- a/Ibm1130/utils/checkdisk.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// checkdisk - validates and optionally dumps an IBM1130 DMS2 disk image file -// -// Usage: -// checkdisk [-f] [-d cyl.sec|abssec] [-n count] filename -// -// Examples: -// checkdisk file.dsk -// report any misnumbered sectors in file.dsk -// -// checkdisk -f file.dsk -// report and fix any misnumbered sectors -// -// checkdisk -d 198.0 file.dsk -// dump cylinder 198 sector 0 -// -// checkdisk -d 0 file.dsk -// dump absolute sector 0 -// -// checkdisk -d 198.0 -n 4 file.dsk -// dump 4 sectors starting at m.n -// ----------------------------------------------------------------------------------------- -#include -#include -#include -#include "util_io.h" - -#ifdef _WIN32 -# include -#else - long filelength (int fno); -# include -# include -#endif - -#ifndef TRUE -# define BOOL int -# define TRUE 1 -# define FALSE 0 -#endif - -#define DSK_NUMWD 321 /* words/sector */ -#define DSK_NUMSC 4 /* sectors/surface */ -#define DSK_NUMSF 2 /* surfaces/cylinder */ -#define DSK_NUMCY 203 /* cylinders/drive */ -#define DSK_NUMDR 5 /* drives/controller */ -#define DSK_SIZE (DSK_NUMCY * DSK_NUMSF * DSK_NUMSC * DSK_NUMWD) /* words/drive */ - -char *usestr = "Usage: checkdisk [-f] [-d cyl.sec|abssec] [-n count] diskfile"; -char *baddisk = "Cannot fix this"; - -void bail (char *msg); -char *lowcase (char *str); - -int main (int argc, char **argv) -{ - FILE *fp; - char *fname = NULL, *arg, *argval; - int i, j, cyl, sec, pos, asec, retry, nbad = 0, nfixed = 0, nline; - BOOL fixit = FALSE, dump = FALSE; - int dsec, nsec = 1; - unsigned short wd, buf[DSK_NUMWD]; - - for (i = 1; i < argc;) { - arg = argv[i++]; - if (*arg == '-') { - arg++; - lowcase(arg); - while (*arg) { - switch (*arg++) { - case 'f': - fixit = TRUE; - break; - - case 'd': - dump = TRUE; - - if (i >= argc) - bail(usestr); - - argval = argv[i++]; - if (strchr(argval, '.') != NULL) { - if (sscanf(argval, "%d.%d", &cyl, &sec) != 2) - bail(usestr); - - dsec = cyl*(DSK_NUMSF*DSK_NUMSC) + sec; - } - else if (sscanf(argval, "%d", &dsec) != 1) - bail(usestr); - - if (dsec < 0 || dsec >= (DSK_NUMCY*DSK_NUMSF*DSK_NUMSC)) - bail("No such sector"); - - break; - - case 'n': - if (i >= argc) - bail(usestr); - - argval = argv[i++]; - if (sscanf(argval, "%d", &nsec) != 1) - bail(usestr); - - if (nsec <= 0) - bail(usestr); - - break; - - default: - bail(usestr); - } - } - } - else if (fname == NULL) - fname = arg; - else - bail(usestr); - } - - if (fname == NULL) - bail(usestr); - - if ((fp = fopen(fname, "rb+")) == NULL) { - perror(fname); - return 1; - } - - if (filelength(fileno(fp)) != 2*DSK_SIZE) { - fprintf(stderr, "File is wrong length, expected %d\n", DSK_SIZE); - bail(baddisk); - } - - for (cyl = 0; cyl < DSK_NUMCY; cyl++) { - for (sec = 0; sec < (DSK_NUMSF*DSK_NUMSC); sec++) { - retry = 1; -again: - asec = cyl*(DSK_NUMSF*DSK_NUMSC) + sec; - pos = asec*2*DSK_NUMWD; - - if (fseek(fp, pos, SEEK_SET) != 0) { - fprintf(stderr, "Error seeking to pos %x\n", pos); - bail(baddisk); - } - - if (fxread(&wd, sizeof(wd), 1, fp) != 1) { - fprintf(stderr, "Error reading word at abs sec %x, cyl %x, sec %x at offset %x\n", asec, cyl, sec, pos); - bail(baddisk); - } - - if (wd != asec) { - fprintf(stderr, "Bad sector #%x at abs sec %x, cyl %x, sec %x at offset %x\n", wd, asec, cyl, sec, pos); - nbad++; - - if (fixit) { - if (fseek(fp, pos, SEEK_SET) != 0) { - fprintf(stderr, "Error seeking to pos %x\n", pos); - bail(baddisk); - } - - if (fxwrite(&asec, sizeof(wd), 1, fp) != 1) { - fprintf(stderr, "Error writing sector # to abs sec %x, cyl %x, sec %x at offset %x\n", asec, cyl, sec, pos); - bail(baddisk); - } - - if (retry) { - retry = 0; - nfixed++; - goto again; - } - - fprintf(stderr, "Failed after retry\n"); - bail(baddisk); - } - } - } - } - - if (nbad) - printf("%d bad sector mark%s %s\n", nbad, (nbad == 1) ? "" : "s", fixit ? "fixed" : "found"); - else if (! dump) - printf("All sector marks OK\n"); - - if (! dump) - return 0; - - pos = dsec*2*DSK_NUMWD; - if (fseek(fp, pos, SEEK_SET) != 0) { - fprintf(stderr, "Error seeking to pos %x\n", pos); - bail(baddisk); - } - - for (i = 0; i < nsec; i++) { - cyl = dsec / (DSK_NUMSF*DSK_NUMSC); - sec = dsec - cyl*(DSK_NUMSF*DSK_NUMSC); - - if (fxread(&buf, sizeof(buf[0]), DSK_NUMWD, fp) != DSK_NUMWD) { - fprintf(stderr, "Error reading abs sec %x, cyl %x, sec %x at offset %x\n", dsec, cyl, sec, pos); - bail(baddisk); - } - - printf("\nSector %d.%d - %d - /%04x label %04x\n", cyl, sec, dsec, dsec, buf[0]); - for (nline = 0, j = 1; j < DSK_NUMWD; j++) { - printf("%04x", buf[j]); - if (++nline == 16) { - putchar('\n'); - nline = 0; - } - else - putchar(' '); - } - - dsec++; - } - - return 0; -} - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -/* ------------------------------------------------------------------------ - * lowcase - force a string to lower case (ASCII) - * ------------------------------------------------------------------------ */ - -char *lowcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'A' && *s <= 'Z') - *s += 32; - } - - return str; -} - -#ifndef _WIN32 - -long filelength (int fno) -{ - struct stat sb; - - if (fstat(fno, &sb) != 0) - return 0; - - return (long) sb.st_size; -} -#endif - diff --git a/Ibm1130/utils/checkdisk.mak b/Ibm1130/utils/checkdisk.mak deleted file mode 100644 index e03d955b..00000000 --- a/Ibm1130/utils/checkdisk.mak +++ /dev/null @@ -1,177 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "checkdisk.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Release" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/checkdisk.exe $(OUTDIR)/checkdisk.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"checkdisk.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"checkdisk.bsc" -BSC32_SBRS= \ - $(INTDIR)/checkdisk.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/checkdisk.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO\ - /SUBSYSTEM:console /INCREMENTAL:no /PDB:$(OUTDIR)/"checkdisk.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"checkdisk.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/checkdisk.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/checkdisk.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/checkdisk.exe $(OUTDIR)/checkdisk.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"checkdisk.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"checkdisk.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"checkdisk.bsc" -BSC32_SBRS= \ - $(INTDIR)/checkdisk.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/checkdisk.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO\ - /SUBSYSTEM:console /INCREMENTAL:yes /PDB:$(OUTDIR)/"checkdisk.pdb" /DEBUG\ - /MACHINE:I386 /OUT:$(OUTDIR)/"checkdisk.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/checkdisk.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/checkdisk.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\checkdisk.c -DEP_CHECK=\ - .\util_io.h\ - \MSVC20\INCLUDE\sys\types.h\ - \MSVC20\INCLUDE\sys\stat.h - -$(INTDIR)/checkdisk.obj : $(SOURCE) $(DEP_CHECK) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\util_io.c - -$(INTDIR)/util_io.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/diskview.c b/Ibm1130/utils/diskview.c deleted file mode 100644 index 42fa37d2..00000000 --- a/Ibm1130/utils/diskview.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// DISKVIEW - lists contents of an 1130 system disk image file. Not finished yet. -// needs LET/SLET listing routine. -// -// usage: -// diskview -v diskfile - -#include -#include -#include -#include -#include "util_io.h" - -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#ifndef TRUE -# define TRUE 1 -# define FALSE 0 -# define BOOL int -#endif - -#define NOT_DEF 0x0658 // defective cylinder table entry means no defect - -#define DSK_NUMWD 321 /* words/sector */ -#define DSK_NUMCY 203 /* cylinders/drive */ -#define DSK_SECCYL 8 /* sectors per cylinder */ -#define SECLEN 320 /* data words per sector */ -#define SLETLEN ((3*SECLEN)/4) /* length of slet in records */ - -typedef unsigned short WORD; - -FILE *fp; -WORD buf[DSK_NUMWD]; -WORD dcom[DSK_NUMWD]; - -#pragma pack(2) -struct tag_slet { - WORD phid; - WORD addr; - WORD nwords; - WORD sector; -} slet[SLETLEN]; - -#pragma pack() - -WORD dcyl[3]; -BOOL verbose = FALSE; - -void checksectors (void); -void dump_id (void); -void dump_dcom (void); -void dump_resmon (void); -void dump_slet (void); -void dump_hdng (void); -void dump_scra (void); -void dump_let (void); -void dump_flet (void); -void dump_cib (void); -void getsector (int sec, WORD *sbuf); -void getdcyl (void); -char *lowcase (char *str); - -void bail(char *fmt, ...); -char *trim (char *s); - -int main (int argc, char **argv) -{ - char *fname = NULL, *arg; - static char usestr[] = "Usage: diskview [-v] filename"; - int i; - - for (i = 1; i < argc;) { - arg = argv[i++]; - if (*arg == '-') { - arg++; - lowcase(arg); - while (*arg) { - switch (*arg++) { - case 'v': - verbose = TRUE; - break; - - default: - bail(usestr); - } - } - } - else if (fname == NULL) - fname = arg; - else - bail(usestr); - } - - if (fname == NULL) - bail(usestr); - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - return 2; - } - - printf("%s:\n", fname); - - checksectors(); - getdcyl(); - - dump_id(); // ID & coldstart - dump_dcom(); // DCOM - dump_resmon(); // resident image - dump_slet(); // SLET - dump_hdng(); // heading sector - dump_scra(); - dump_flet(); - dump_cib(); - dump_let(); - - fclose(fp); - return 0; -} - -// checksectors - verify that all sectors are properly numbered - -void checksectors () -{ - WORD sec = 0; - - fseek(fp, 0, SEEK_SET); - - for (sec = 0; sec < DSK_NUMCY*DSK_SECCYL; sec++) { - if (fxread(buf, sizeof(WORD), DSK_NUMWD, fp) != DSK_NUMWD) - bail("File read error or not a disk image file"); - - if (buf[0] != sec) - bail("Sector /%x is misnumbered, run checkdisk [-f]", sec); - } -} - -// get defective cylinder list - -void getdcyl (void) -{ - fseek(fp, sizeof(WORD), SEEK_SET); // skip sector count - if (fxread(dcyl, sizeof(WORD), 3, fp) != 3) - bail("Unable to read defective cylinder table"); -} - -// getsector - read specified absolute sector - -void getsector (int sec, WORD *sbuf) -{ - int i, cyl, ssec; - - sec &= 0x7FF; // mask of drive bits, if any - - cyl = sec / DSK_SECCYL; // get cylinder - ssec = sec & ~(DSK_SECCYL-1); // mask to get starting sector of cylinder - for (i = 0; i < 3; i++) { // map through defective cylinder table - if (dcyl[i] == ssec) { - sec &= (DSK_SECCYL-1); // mask to get base sector - cyl = DSK_NUMCY-3+i; // replacements are last three on disk - sec += cyl*DSK_SECCYL; // add new cylinder offset - break; - } - } - // read the sector - if (fseek(fp, (sec*DSK_NUMWD+1)*sizeof(WORD), SEEK_SET) != 0) - bail("File seek failed"); - - if (fxread(sbuf, sizeof(WORD), DSK_NUMWD, fp) != DSK_NUMWD) - bail("File read error or not a disk image file"); -} - -void dump (int nwords) -{ - int i, nline = 0; - - for (i = 0; i < nwords; i++) { - if (nline == 16) { - putchar('\n'); - nline = 0; - } - - printf("%04x", buf[i]); - nline++; - } - putchar('\n'); -} - -void showmajor (char *label) -{ - int i; - - printf("\n--- %s ", label); - - for (i = strlen(label); i < 40; i++) - putchar('-'); - - putchar('\n'); - putchar('\n'); -} - -void name (char *label) -{ - printf("%-32.32s ", label); -} - -void pbf (char *label, WORD *buf, int nwords) -{ - int i, nout; - - name(label); - - for (i = nout = 0; i < nwords; i++, nout++) { - if (nout == 8) { - putchar('\n'); - name(""); - nout = 0; - } - printf(" %04x", buf[i]); - } - - putchar('\n'); -} - -void prt (char *label, char *fmt, ...) -{ - va_list args; - - name(label); - - putchar(' '); - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); - - putchar('\n'); -} - -void dump_id (void) -{ - showmajor("Sector 0 - ID & coldstart"); - getsector(0, buf); - - pbf("DCYL def cyl table", buf+ 0, 3); - pbf("CIDN cart id", buf+ 3, 1); - pbf(" copy code", buf+ 4, 1); - pbf("DTYP disk type", buf+ 7, 1); - pbf(" diskz copy", buf+ 30, 8); - pbf(" cold start pgm",buf+270, 8); -} - -// EQUIVALENCES FOR DCOM PARAMETERS -#define NAME 4 // NAME OF PROGRAM/CORE LOAD -#define DBCT 6 // BLOCK CT OF PROGRAM/CORE LOAD -#define FCNT 7 // FILES SWITCH -#define SYSC 8 // SYSTEM/NON-SYSTEM CARTRIDGE INDR -#define JBSW 9 // JOBT SWITCH -#define CBSW 10 // CLB-RETURN SWITCH -#define LCNT 11 // NO. OF LOCALS -#define MPSW 12 // CORE MAP SWITCH -#define MDF1 13 // NO. DUP CTRL RECORDS (MODIF) -#define MDF2 14 // ADDR OF MODIF BUFFER -#define NCNT 15 // NO. OF NOCALS -#define ENTY 16 // RLTV ENTRY ADDR OF PROGRAM -#define RP67 17 // 1442-5 SWITCH -#define TODR 18 // OBJECT WORK STORAGE DRIVE CODE -#define FHOL 20 // ADDR LARGEST HOLE IN FIXED AREA -#define FSZE 21 // BLK CNT LARGEST HOLE IN FXA -#define UHOL 22 // ADDR LAST HOLE IN USER AREA 2-10 -#define USZE 23 // BLK CNT LAST HOLE IN UA 2-10 -#define DCSW 24 // DUP CALL SWITCH -#define PIOD 25 // PRINCIPAL I/O DEVICE INDICATOR -#define PPTR 26 // PRINCIPAL PRINT DEVICE INDICATOR -#define CIAD 27 // RLTV ADDR IN @STRT OF CIL ADDR -#define ACIN 28 // AVAILABLE CARTRIDGE INDICATOR -#define GRPH 29 // 2250 INDICATOR 2G2 -#define GCNT 30 // NO. G2250 RECORDS 2G2 -#define LOSW 31 // LOCAL-CALLS-LOCAL SWITCH 2-2 -#define X3SW 32 // SPECIAL ILS SWITCH 2-2 -#define ECNT 33 // NO. OF *EQUAT RCDS 2-4 -#define ANDU 35 // 1+BLK ADDR END OF UA (ADJUSTED) -#define BNDU 40 // 1+BLK ADDR END OF UA (BASE) -#define FPAD 45 // FILE PROTECT ADDR -#define PCID 50 // CARTRIDGE ID, PHYSICAL DRIVE -#define CIDN 55 // CARTRIDGE ID, LOGICAL DRIVE -#define CIBA 60 // SCTR ADDR OF CIB -#define SCRA 65 // SCTR ADDR OF SCRA -#define FMAT 70 // FORMAT OF PROG IN WORKING STG -#define FLET 75 // SCTR ADDR 1ST SCTR OF FLET -#define ULET 80 // SCTR ADDR 1ST SCTR OF LET -#define WSCT 85 // BLK CNT OF PROG IN WORKING STG -#define CSHN 90 // NO. SCTRS IN CUSHION AREA - -struct tag_dcominfo { - char *nm; - int offset; - char *descr; -} dcominfo[] = { - "NAME", 4, "NAME OF PROGRAM/CORE LOAD", - "DBCT", 6, "BLOCK CT OF PROGRAM/CORE LOAD", - "FCNT", 7, "FILES SWITCH", - "SYSC", 8, "SYSTEM/NON-SYSTEM CARTRIDGE INDR", - "JBSW", 9, "JOBT SWITCH", - "CBSW", 10, "CLB-RETURN SWITCH", - "LCNT", 11, "NO. OF LOCALS", - "MPSW", 12, "CORE MAP SWITCH", - "MDF1", 13, "NO. DUP CTRL RECORDS (MODIF)", - "MDF2", 14, "ADDR OF MODIF BUFFER", - "NCNT", 15, "NO. OF NOCALS", - "ENTY", 16, "RLTV ENTRY ADDR OF PROGRAM", - "RP67", 17, "1442-5 SWITCH", - "TODR", 18, "OBJECT WORK STORAGE DRIVE CODE", - "FHOL", 20, "ADDR LARGEST HOLE IN FIXED AREA", - "FSZE", 21, "BLK CNT LARGEST HOLE IN FXA", - "UHOL", 22, "ADDR LAST HOLE IN USER AREA", - "USZE", 23, "BLK CNT LAST HOLE IN UA", - "DCSW", 24, "DUP CALL SWITCH", - "PIOD", 25, "PRINCIPAL I/O DEVICE INDICATOR", - "PPTR", 26, "PRINCIPAL PRINT DEVICE INDICATOR", - "CIAD", 27, "RLTV ADDR IN @STRT OF CIL ADDR", - "ACIN", 28, "AVAILABLE CARTRIDGE INDICATOR", - "GRPH", 29, "2250 INDICATOR", - "GCNT", 30, "NO. G2250 RECORDS", - "LOSW", 31, "LOCAL-CALLS-LOCAL SWITCH", - "X3SW", 32, "SPECIAL ILS SWITCH", - "ECNT", 33, "NO. OF *EQUAT RCDS", - "ANDU", 35, "1+BLK ADDR END OF UA (ADJUSTED)", - "BNDU", 40, "1+BLK ADDR END OF UA (BASE)", - "FPAD", 45, "FILE PROTECT ADDR", - "PCID", 50, "CARTRIDGE ID, PHYSICAL DRIVE", - "CIDN", 55, "CARTRIDGE ID, LOGICAL DRIVE", - "CIBA", 60, "SCTR ADDR OF CIB", - "SCRA", 65, "SCTR ADDR OF SCRA", - "FMAT", 70, "FORMAT OF PROG IN WORKING STG", - "FLET", 75, "SCTR ADDR 1ST SCTR OF FLET", - "ULET", 80, "SCTR ADDR 1ST SCTR OF LET", - "WSCT", 85, "BLK CNT OF PROG IN WORKING STG", - "CSHN", 90, "NO. SCTRS IN CUSHION AREA", - NULL -}; - -void dump_dcom (void) -{ - struct tag_dcominfo *d; - char txt[50]; - - showmajor("Sector 1 - DCOM"); - getsector(1, dcom); - - for (d = dcominfo; d->nm != NULL; d++) { - sprintf(txt, "%-4.4s %s", d->nm, d->descr); - pbf(txt, dcom+d->offset, 1); - } -} - -void dump_resmon (void) -{ - showmajor("Sector 2 - Resident Image"); - getsector(2, buf); - dump(verbose ? SECLEN : 32); -} - -struct { - int pfrom, pto; - int printed; - char *name; -} sletinfo[] = { - 0x01, 0x12, FALSE, "DUP", - 0x1F, 0x39, FALSE, "Fortran", - 0x51, 0x5C, FALSE, "Cobol", - 0x6E, 0x74, FALSE, "Supervisor", - 0x78, 0x84, FALSE, "Core Load Builder", - 0x8C, 0x8C, FALSE, "Sys 1403 prt", - 0x8D, 0x8D, FALSE, "Sys 1132 prt", - 0x8E, 0x8E, FALSE, "Sys console prt", - 0x8F, 0x8F, FALSE, "Sys 2501 rdr", - 0x90, 0x90, FALSE, "Sys 1442 rdr/pun", - 0x91, 0x91, FALSE, "Sys 1134 paper tape", - 0x92, 0x92, FALSE, "Sys kbd", - 0x93, 0x93, FALSE, "Sys 2501/1442 conv", - 0x94, 0x94, FALSE, "Sys 1134 conv", - 0x95, 0x95, FALSE, "Sys kbd conv", - 0x96, 0x96, FALSE, "Sys diskz", - 0x97, 0x97, FALSE, "Sys disk1", - 0x98, 0x98, FALSE, "Sys diskn", - 0x99, 0x99, FALSE, "(primary print)", - 0x9A, 0x9A, FALSE, "(primary input)", - 0x9B, 0x9B, FALSE, "(primary input excl kbd)", - 0x9C, 0x9C, FALSE, "(primary sys conv)", - 0x9D, 0x9D, FALSE, "(primary conv excl kbd)", - 0xA0, 0xA1, FALSE, "Core Image Loader", - 0xB0, 0xCC, FALSE, "RPG", - 0xCD, 0xCE, FALSE, "Dup Part 2", - 0xCF, 0xF6, FALSE, "Macro Assembler", - 0 -}; - -void dump_slet (void) -{ - int i, j, iphase, nsecs, sec, max_sec = 0; - char sstr[16], *smark; - - showmajor("Sectors 3-5 - SLET"); - for (i = 0; i < 3; i++) { - getsector(3+i, buf); - memmove(((WORD *) slet)+SECLEN*i, buf, SECLEN*sizeof(WORD)); - } - - printf("# PHID Addr Len Sector Secs\n"); - printf("------------------------------------------\n"); - for (i = 0; i < SLETLEN; i++) { - if (slet[i].phid == 0) - break; - - sec = slet[i].sector; - iphase = (int) (signed short) slet[i].phid; - nsecs = (slet[i].nwords + SECLEN-1)/SECLEN; - - if (sec & 0xF800) { - smark = "*"; - sec &= 0x7FF; - } - else - smark = " "; - - for (j = 0; sletinfo[j].pfrom != 0; j++) - if (sletinfo[j].pfrom <= iphase && sletinfo[j].pto >= iphase) - break; - - sprintf(sstr, "(%d.%d)", sec / DSK_SECCYL, slet[i].sector % DSK_SECCYL); - - printf("%3d %04x %4d %04x %04x %04x %s %-7s %3x", - i, slet[i].phid, iphase, slet[i].addr, slet[i].nwords, slet[i].sector, smark, sstr, nsecs); - - if (iphase < 0) - iphase = -iphase; - - if (sletinfo[j].pfrom == 0) - printf(" ???"); - else if (! sletinfo[j].printed) { - printf(" %s", sletinfo[j].name); - sletinfo[j].printed = TRUE; - } - - for (j = 0; j < i; j++) { - if (sec == (slet[j].sector & 0x7FF)) { - printf(" (same as %04x)", slet[j].phid); - break; - } - } - - max_sec = MAX(max_sec, sec+nsecs-1); // find last sector used - - putchar('\n'); - - if (i >= 15 && ! verbose) { - printf("...\n"); - break; - } - } -} - -int ascii_to_ebcdic_table[128] = -{ - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, - - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -int ebcdic_to_ascii (int ch) -{ - int j; - - for (j = 32; j < 128; j++) - if (ascii_to_ebcdic_table[j] == ch) - return j; - - return '?'; -} - -#define HDR_LEN 120 - -void dump_hdng(void) -{ - int i; - char str[HDR_LEN+1], *p = str; - - showmajor("Sector 7 - Heading"); - getsector(7, buf); - - for (i = 0; i < (HDR_LEN/2); i++) { - *p++ = ebcdic_to_ascii((buf[i] >> 8) & 0xFF); - *p++ = ebcdic_to_ascii( buf[i] & 0xFF); - } - - *p = '\0'; - trim(str); - printf("%s\n", str); -} - -BOOL mget (int offset, char *name) -{ - char title[80]; - - if (dcom[offset] == 0) - return FALSE; - - getsector(dcom[offset], buf); - sprintf(title, "Sector %x - %s", dcom[offset], name); - showmajor(title); - return TRUE; -} - -void dump_scra (void) -{ - if (! mget(SCRA, "SCRA")) - return; - - dump(verbose ? SECLEN : 32); -} - -void dump_let (void) -{ - if (! mget(ULET, "LET")) - return; -} - -void dump_flet (void) -{ - if (! mget(FLET, "FLET")) - return; -} - -void dump_cib (void) -{ - if (! mget(CIBA, "CIB")) - return; - - dump(verbose ? SECLEN : 32); -} - -#define LFHD 5 // WORD COUNT OF LET/FLET HEADER PMN09970 -#define LFEN 3 // NO OF WDS PER LET/FLET ENTRY PMN09980 -#define SCTN 0 // RLTY ADDR OF LET/FLET SCTR NO. PMN09990 -#define UAFX 1 // RLTV ADDR OF SCTR ADDR OF UA/FXA PMN10000 -#define WDSA 3 // RLTV ADDR OF WDS AVAIL IN SCTR PMN10010 -#define NEXT 4 // RLTV ADDR OF ADDR NEXT SCTR PMN10020 -#define LFNM 0 // RLTV ADDR OF LET/FLET ENTRY NAME PMN10030 -#define BLCT 2 // RLTV ADDR OF LET/FLET ENTRY DBCT PMN10040 - -void bail (char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - fprintf(stderr, fmt, args); - va_end(args); - putchar('\n'); - - exit(1); -} - -// --------------------------------------------------------------------------------- -// trim - remove trailing whitespace from string s -// --------------------------------------------------------------------------------- - -char *trim (char *s) -{ - char *os = s, *nb; - - for (nb = s-1; *s; s++) - if (*s > ' ') - nb = s; - - nb[1] = '\0'; - return os; -} - -/* ------------------------------------------------------------------------ - * lowcase - force a string to lowercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *lowcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'A' && *s <= 'Z') - *s += 32; - } - - return str; -} - diff --git a/Ibm1130/utils/diskview.mak b/Ibm1130/utils/diskview.mak deleted file mode 100644 index ef9a8cf3..00000000 --- a/Ibm1130/utils/diskview.mak +++ /dev/null @@ -1,175 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "diskview.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/diskview.exe $(OUTDIR)/diskview.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"diskview.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"diskview.bsc" -BSC32_SBRS= \ - $(INTDIR)/diskview.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/diskview.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:no /PDB:$(OUTDIR)/"diskview.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"diskview.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/diskview.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/diskview.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/diskview.exe $(OUTDIR)/diskview.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"diskview.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"diskview.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"diskview.bsc" -BSC32_SBRS= \ - $(INTDIR)/diskview.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/diskview.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:yes /PDB:$(OUTDIR)/"diskview.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"diskview.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/diskview.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/diskview.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\diskview.c - -$(INTDIR)/diskview.obj : $(SOURCE) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\util_io.c -DEP_UTIL_=\ - .\util_io.h - -$(INTDIR)/util_io.obj : $(SOURCE) $(DEP_UTIL_) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/makefile b/Ibm1130/utils/makefile deleted file mode 100644 index 612b3c67..00000000 --- a/Ibm1130/utils/makefile +++ /dev/null @@ -1,47 +0,0 @@ -# (This makefile is for operating systems other than Windows, -# or compilers other than Microsoft's. For MS builds, use the -# .mak files). -# -# CC Command -# -# Note: -O2 is sometimes broken in GCC when setjump/longjump is being -# used. Try -O2 only with released simulators. -# - -CC = gcc -O0 -lm -I . -#CC = gcc -O2 -g -lm -I . - -BIN = - -IOLIB_DEP = util_io.c util_io.h -IOLIB_SRC = util_io.c - -# -# Build everything -# - -all : ${BIN}asm1130 ${BIN}bindump ${BIN}checkdisk \ - ${BIN}diskview ${BIN}mkboot ${BIN}viewdeck - -# -# Individual builds -# - -${BIN}asm1130 : asm1130.c ${IOLIB_DEP} - ${CC} asm1130.c ${IOLIB_SRC} -o $@ - -${BIN}bindump : bindump.c ${IOLIB_DEP} - ${CC} bindump.c ${IOLIB_SRC} -o $@ - -${BIN}checkdisk : checkdisk.c ${IOLIB_DEP} - ${CC} checkdisk.c ${IOLIB_SRC} -o $@ - -${BIN}diskview : diskview.c ${IOLIB_DEP} - ${CC} diskview.c ${IOLIB_SRC} -o $@ - -${BIN}mkboot : mkboot.c ${IOLIB_DEP} - ${CC} mkboot.c ${IOLIB_SRC} -o $@ - -${BIN}viewdeck : viewdeck.c ${IOLIB_DEP} - ${CC} viewdeck.c ${IOLIB_SRC} -o $@ - diff --git a/Ibm1130/utils/mkboot.c b/Ibm1130/utils/mkboot.c deleted file mode 100644 index 470e21fb..00000000 --- a/Ibm1130/utils/mkboot.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// --------------------------------------------------------------------------------- -// MKBOOT - reads card loader format cards and produces an absolute core image that -// can then be dumped out in 1130 IPL, 1800 IPL or Core Image loader formats. -// -// Usage: mkboot [-v] binfile outfile [1130|1800|core [loaddr [hiaddr [ident]]]]" -// -// Arguments: -// binfile - name of assembler output file (card loader format, absolute output) -// outfile - name of output file to create -// mode - output mode, default is 1130 IPL format -// loaddr - low address to dump. Default is lowest address loaded from binfile -// hiaddr - high address to dump. Defult is highest address loaded from binfile -// ident - ident string to write in last 8 columns. Omit when when writing an -// 1130 IPL card that requires all 80 columns of data. -// -// Examples: -// mkboot somefile.bin somefile.ipl 1130 -// -// loads somefile.bin, writes object in 1130 IPL format to somefile.ipl -// Up to 80 columns will be written depending on what the object actually uses -// -// mkboot somefile.bin somefile.ipl 1130 /0 /47 SOMEF -// -// loads somefile.bin. Writes 72 columns (hex 0 to hex 47), with ident columns 73-80 = SOMEF001 -// -// mkboot somefile.bin somefile.dat core 0 0 SOMEF001 -// -// loads somefile.bin and writes a core image format deck with ident SOMEF001, SOMEF002, etc -// -// For other examples of usage, see MKDMS.BAT -// -// 1.00 - 2002Apr18 - first release. Tested only under Win32. The core image -// loader format is almost certainly wrong. Cannot handle -// relocatable input decks, but it works well enough to -// load DSYSLDR1 which is what we are after here. -// --------------------------------------------------------------------------------- - -#include -#include -#include -#include -#include "util_io.h" - -#ifndef TRUE - #define BOOL int - #define TRUE 1 - #define FALSE 0 -#endif - -#ifndef _WIN32 - int strnicmp (char *a, char *b, int n); - int strcmpi (char *a, char *b); -#endif - -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#define MAXADDR 4096 - -typedef enum {R_ABSOLUTE = 0, R_RELATIVE = 1, R_LIBF = 2, R_CALL = 3} RELOC; - -typedef enum {B_1130, B_1800, B_CORE} BOOTMODE; - -BOOL verbose = FALSE; -char *infile = NULL, *outfile = NULL; -BOOTMODE mode = B_1130; -int addr_from = 0, addr_to = 79; -int outcols = 0; // columns written in using card output -int maxiplcols = 80; -char cardid[9]; // characters used for IPL card ID -int pta = 0; -int load_low = 0x7FFFFFF; -int load_high = 0; -unsigned short mem[MAXADDR]; // small core! - -// mkboot - load a binary object deck into core and dump requested bytes as a boot card - -void bail (char *msg); -void verify_checksum(unsigned short *card); -char *upcase (char *str); -void unpack (unsigned short *card, unsigned short *buf); -void dump (char *fname); -void loaddata (char *fname); -void write_1130 (void); -void write_1800 (void); -void write_core (void); -void flushcard(void); -int ascii_to_hollerith (int ch); -void corecard_init (void); -void corecard_writecard (char *sbrk_text); -void corecard_writedata (void); -void corecard_flush (void); -void corecard_setorg (int neworg); -void corecard_writew (int word, RELOC relative); -void corecard_endcard (void); - -char *fname = NULL; -FILE *fout; - -int main (int argc, char **argv) -{ - char *arg; - static char usestr[] = "Usage: mkboot [-v] binfile outfile [1130|1800|core [loaddr [hiaddr [ident]]]]"; - int i, ano = 0, ok; - - for (i = 1; i < argc; i++) { - arg = argv[i]; - if (*arg == '-') { - arg++; - while (*arg) { - switch (*arg++) { - case 'v': - verbose = TRUE; - break; - default: - bail(usestr); - } - } - } - else { - switch (ano++) { - case 0: - infile = arg; - break; - - case 1: - outfile = arg; - break; - - case 2: - if (strcmp(arg, "1130") == 0) mode = B_1130; - else if (strcmp(arg, "1800") == 0) mode = B_1800; - else if (strcmpi(arg, "core") == 0) mode = B_CORE; - else bail(usestr); - break; - - case 3: - if (strnicmp(arg, "0x", 2) == 0) ok = sscanf(arg+2, "%x", &addr_from); - else if (arg[0] == '/') ok = sscanf(arg+1, "%x", &addr_from); - else ok = sscanf(arg, "%d", &addr_from); - if (ok != 1) bail(usestr); - break; - - case 4: - if (strnicmp(arg, "0x", 2) == 0) ok = sscanf(arg+2, "%x", &addr_to); - else if (arg[0] == '/') ok = sscanf(arg+1, "%x", &addr_to); - else ok = sscanf(arg, "%d", &addr_to); - if (ok != 1) bail(usestr); - break; - - case 5: - strncpy(cardid, arg, 9); - cardid[8] = '\0'; - upcase(cardid); - break; - - default: - bail(usestr); - } - } - } - - if (*cardid == '\0') - maxiplcols = (mode == B_1130) ? 80 : 72; - else { - while (strlen(cardid) < 8) - strcat(cardid, "0"); - maxiplcols = 72; - } - - loaddata(infile); - - if (mode == B_1800) - write_1800(); - else if (mode == B_CORE) - write_core(); - else - write_1130(); - - return 0; -} - -void write_1130 (void) -{ - int addr; - unsigned short word; - - if ((fout = fopen(outfile, "wb")) == NULL) { - perror(outfile); - exit(1); - } - - for (addr = addr_from; addr <= addr_to; addr++) { - if (outcols >= maxiplcols) - flushcard(); - - word = mem[addr]; - - // if F or L bits are set, or if high 2 bits of displacement are unequal, it's bad - if ((word & 0x0700) || ! (((word & 0x00C0) == 0) || ((word & 0x00C0) == 0x00C0))) - printf("Warning: word %04x @ %04x may not IPL properly\n", word & 0xFFFF, addr); - - word = ((word & 0xF800) >> 4) | (word & 0x7F); // convert to 1130 IPL format - - putc((word & 0x000F) << 4, fout); // write the 12 bits in little-endian binary AABBCC00 as CC00 AABB - putc((word & 0x0FF0) >> 4, fout); - outcols++; - } - flushcard(); - fclose(fout); -} - -void write_1800 (void) -{ - int addr; - unsigned short word; - - if ((fout = fopen(outfile, "wb")) == NULL) { - perror(outfile); - exit(1); - } - - for (addr = addr_from; addr <= addr_to; addr++) { - word = mem[addr]; - - if (outcols >= maxiplcols) - flushcard(); - - putc(0, fout); - putc(word & 0xFF, fout); // write the low 8 bits in little-endian binary - outcols++; - - putc(0, fout); - putc((word >> 8) & 0xFF, fout); // write the high 8 bits in little-endian binary - outcols++; - } - flushcard(); - fclose(fout); -} - -void write_core (void) -{ - int addr; - - if ((fout = fopen(outfile, "wb")) == NULL) { - perror(outfile); - exit(1); - } - - addr_from = load_low; - addr_to = load_high; - - maxiplcols = 72; - corecard_init(); - corecard_setorg(addr_from); - - for (addr = addr_from; addr <= addr_to; addr++) { - corecard_writew(mem[addr], 0); - } - - corecard_flush(); - corecard_endcard(); - fclose(fout); -} - -void flushcard (void) -{ - int i, hol, ndig; - char fmt[20], newdig[20]; - - if (outcols <= 0) - return; // nothing to flush - - while (outcols < maxiplcols) { // pad to required number of columns with blanks (no punches) - putc(0, fout); - putc(0, fout); - outcols++; - } - - if (*cardid) { // add label - for (i = 0; i < 8; i++) { // write label as specified - hol = ascii_to_hollerith(cardid[i] & 0x7F); - putc(hol & 0xFF, fout); - putc((hol >> 8) & 0xFF, fout); - } - - ndig = 0; // count trailing digits in the label - for (i = 8; --i >= 0; ndig++) - if (! isdigit(cardid[i])) - break; - - i++; // index of first digit in trailing sequence - - if (ndig > 0) { // if any, increment them - sprintf(fmt, "%%0%dd", ndig); // make, e.g. %03d - sprintf(newdig, fmt, atoi(cardid+i)+1); - newdig[ndig] = '\0'; // clip if necessary - strcpy(cardid+i, newdig); // replace for next card's sequence number - } - } - - outcols = 0; -} - -void show_data (unsigned short *buf) -{ - int i, n, jrel, rflag, nout, ch, reloc; - - n = buf[2] & 0x00FF; - - printf("%04x: ", buf[0]); - - jrel = 3; - nout = 0; - rflag = buf[jrel++]; - for (i = 0; i < n; i++) { - if (nout >= 8) { - rflag = buf[jrel++]; - putchar('\n'); - printf(" "); - nout = 0; - } - reloc = (rflag >> 14) & 0x03; - ch = (reloc == R_ABSOLUTE) ? ' ' : - (reloc == R_RELATIVE) ? 'R' : - (reloc == R_LIBF) ? 'L' : '@'; - - printf("%04x%c ", buf[9+i], ch); - rflag <<= 2; - nout++; - } - putchar('\n'); -} - -void loadcard (unsigned short *buf) -{ - int addr, n, i; - - addr = buf[0]; - n = buf[2] & 0x00FF; - - for (i = 0; i < n; i++) { - if (addr >= MAXADDR) - bail("Program doesn't fit into 4K"); - mem[addr] = buf[9+i]; - - load_low = MIN(addr, load_low); - load_high = MAX(addr, load_high); - addr++; - } -} - -void loaddata (char *fname) -{ - FILE *fp; - BOOL first = TRUE; - unsigned short card[80], buf[54], cardtype; - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - exit(1); - } - - if (verbose) - printf("\n%s:\n", fname); - - while (fxread(card, sizeof(card[0]), 80, fp) > 0) { - unpack(card, buf); - verify_checksum(card); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 && ! first) { // sector break - if (verbose) - printf("*SBRK\n"); - continue; - } - else { - switch (cardtype) { - case 0x01: - if (verbose) - printf("*ABS\n"); - break; - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - bail("Data must be in absolute format"); - break; - - case 0x0F: - pta = buf[3]; // save program transfer address - if (verbose) - printf("*END\n"); - break; - - case 0x0A: - if (verbose) - show_data(buf); - loadcard(buf); - break; - default: - bail("Unexpected card type"); - } - } - first = FALSE; - } - - fclose(fp); -} - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -void unpack (unsigned short *card, unsigned short *buf) -{ - int i, j; - unsigned short wd1, wd2, wd3, wd4; - - for (i = j = 0; i < 54; i += 3, j += 4) { - wd1 = card[j]; - wd2 = card[j+1]; - wd3 = card[j+2]; - wd4 = card[j+3]; - - buf[i ] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F); - buf[i+1] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF); - buf[i+2] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF); - } -} - -void verify_checksum (unsigned short *card) -{ -// unsigned short sum; - - if (card[1] == 0) // no checksum - return; - -// if (sum != card[1]) -// printf("Checksum %04x doesn't match card %04x\n", sum, card[1]); -} - -typedef struct { - int hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, 'c', // cent - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0x2060, '>', -}; - -int ascii_to_hollerith (int ch) -{ - int i; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].ascii == ch) - return cardcode_029[i].hollerith; - - return 0; -} - -// --------------------------------------------------------------------------------- -// corecard - routines to write IBM 1130 Card object format -// --------------------------------------------------------------------------------- - -unsigned short corecard[54]; // the 54 data words that can fit on a binary format card -int corecard_n = 0; // number of object words stored in corecard (0-45) -int corecard_seq = 1; // card output sequence number -int corecard_org = 0; // origin of current card-full -int corecard_maxaddr = 0; -BOOL corecard_first = TRUE; // TRUE when we're to write the program type card - -// corecard_init - prepare a new object data output card - -void corecard_init (void) -{ - memset(corecard, 0, sizeof(corecard)); // clear card data - corecard_n = 0; // no data - corecard[0] = corecard_org; // store load address - corecard_maxaddr = MAX(corecard_maxaddr, corecard_org-1); // save highest address written-to (this may be a BSS) -} - -// binard_writecard - emit a card. sbrk_text = NULL for normal data cards, points to comment text for sbrk card - -void corecard_writecard (char *sbrk_text) -{ - unsigned short binout[80]; - int i, j; - - for (i = j = 0; i < 54; i += 3, j += 4) { - binout[j ] = ( corecard[i] & 0xFFF0); - binout[j+1] = ((corecard[i] << 12) & 0xF000) | ((corecard[i+1] >> 4) & 0x0FF0); - binout[j+2] = ((corecard[i+1] << 8) & 0xFF00) | ((corecard[i+2] >> 8) & 0x00F0); - binout[j+3] = ((corecard[i+2] << 4) & 0xFFF0); - } - - for (i = 0; i < 72; i++) { - putc(binout[i] & 0xFF, fout); - putc((binout[i] >> 8) & 0xFF, fout); - } - - outcols = 72; // add the ident - flushcard(); -} - -// binard_writedata - emit an object data card - -void corecard_writedata (void) -{ - corecard[1] = 0; // checksum - corecard[2] = 0x0000 | corecard_n; // data card type + word count - corecard_writecard(FALSE); // emit the card -} - -// corecard_flush - flush any pending binary data - -void corecard_flush (void) -{ - if (corecard_n > 0) - corecard_writedata(); - - corecard_init(); -} - -// corecard_setorg - set the origin - -void corecard_setorg (int neworg) -{ - corecard_org = neworg; // set origin for next card - corecard_flush(); // flush any current data & store origin -} - -// corecard_writew - write a word to the current output card. - -void corecard_writew (int word, RELOC relative) -{ - if (corecard_n >= 50) // flush full card buffer (must be even) - corecard_flush(); - - corecard[3+corecard_n++] = word; - corecard_org++; -} - -// corecard_endcard - write end of program card - -void corecard_endcard (void) -{ - corecard_flush(); - - corecard[0] = 0; // effective length: add 1 to max origin, then 1 more to round up - corecard[1] = 0; - corecard[2] = 0x8000; // they look for negative bit but all else must be zero - corecard[52] = 0xabcd; // index register 3 value, this is for fun - corecard[53] = pta; // hmmm - - corecard_writecard(NULL); -} - -/* ------------------------------------------------------------------------ - * upcase - force a string to uppercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *upcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'a' && *s <= 'z') - *s -= 32; - } - - return str; -} - -#ifndef _WIN32 - -int strnicmp (char *a, char *b, int n) -{ - int ca, cb; - - for (;;) { - if (--n < 0) // still equal after n characters? quit now - return 0; - - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -int strcmpi (char *a, char *b) -{ - int ca, cb; - - for (;;) { - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -#endif diff --git a/Ibm1130/utils/mkboot.mak b/Ibm1130/utils/mkboot.mak deleted file mode 100644 index 15715362..00000000 --- a/Ibm1130/utils/mkboot.mak +++ /dev/null @@ -1,175 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "mkboot.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/mkboot.exe $(OUTDIR)/mkboot.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"mkboot.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"mkboot.bsc" -BSC32_SBRS= \ - $(INTDIR)/mkboot.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/mkboot.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:no /PDB:$(OUTDIR)/"mkboot.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"mkboot.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/mkboot.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/mkboot.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/mkboot.exe $(OUTDIR)/mkboot.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"mkboot.pch" /Fo$(INTDIR)/ /Fd$(OUTDIR)/"mkboot.pdb"\ - /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"mkboot.bsc" -BSC32_SBRS= \ - $(INTDIR)/mkboot.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/mkboot.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:yes /PDB:$(OUTDIR)/"mkboot.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"mkboot.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/mkboot.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/mkboot.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\mkboot.c - -$(INTDIR)/mkboot.obj : $(SOURCE) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\util_io.c -DEP_UTIL_=\ - .\util_io.h - -$(INTDIR)/util_io.obj : $(SOURCE) $(DEP_UTIL_) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/viewdeck.c b/Ibm1130/utils/viewdeck.c deleted file mode 100644 index 894d7aea..00000000 --- a/Ibm1130/utils/viewdeck.c +++ /dev/null @@ -1,243 +0,0 @@ -/* Simple program to display a binary card-image file in ASCII. - * We assume the deck was written with one card per 16-bit word, left-justified, - * and written in PC little-endian order - * - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -#include -#include -#include "util_io.h" - -#define TRUE 1 -#define FALSE 0 -typedef int BOOL; - -int hollerith_to_ascii (unsigned short h); -void bail (char *msg); -void format_coldstart (unsigned short *buf); - -int main (int argc, char **argv) -{ - FILE *fd; - char *fname = NULL, line[82], *arg; - BOOL coldstart = FALSE; - unsigned short buf[80]; - int i, lastnb; - static char usestr[] = - "Usage: viewdeck [-c] deckfile\n" - "\n" - "-c: convert cold start card to 16-bit format as a C array initializer\n"; - - for (i = 1; i < argc; i++) { // process command line arguments - arg = argv[i]; - - if (*arg == '-') { - arg++; - while (*arg) { - switch (*arg++) { - case 'c': - coldstart = TRUE; - break; - default: - bail(usestr); - } - } - } - else if (fname == NULL) // first non-switch arg is file name - fname = arg; - else - bail(usestr); // there can be only one name - } - - if (fname == NULL) // there must be a name - bail(usestr); - - if ((fd = fopen(fname, "rb")) == NULL) { - perror(fname); - return 1; - } - - while (fxread(buf, sizeof(short), 80, fd) == 80) { - if (coldstart) { - format_coldstart(buf); - break; - } - - lastnb = -1; - for (i = 0; i < 80; i++) { - line[i] = hollerith_to_ascii(buf[i]); - if (line[i] > ' ') - lastnb = i; - } - line[++lastnb] = '\n'; - line[++lastnb] = '\0'; - fputs(line, stdout); - } - - if (coldstart) { - if (fxread(buf, sizeof(short), 1, fd) == 1) - bail("Coldstart deck has more than one card"); - } - - fclose(fd); - - return 0; -} - -void format_coldstart (unsigned short *buf) -{ - int i, nout = 0; - unsigned short word; - - for (i = 0; i < 80; i++) { - word = buf[i]; // expand 12-bit card data to 16-bit instruction - word = (word & 0xF800) | ((word & 0x0400) ? 0x00C0 : 0x0000) | ((word & 0x03F0) >> 4); - - if (nout >= 8) { - fputs(",\n", stdout); - nout = 0; - } - else if (i > 0) - fputs(", ", stdout); - - printf("0x%04x", word); - nout++; - } - - putchar('\n'); -} - -typedef struct { - unsigned short hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, '\xA2', // cent, in MS-DOS encoding - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, '\xAC', // not, in MS-DOS encoding - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0xB000, 'a', - 0xA800, 'b', - 0xA400, 'c', - 0xA200, 'd', - 0xA100, 'e', - 0xA080, 'f', - 0xA040, 'g', - 0xA020, 'h', - 0xA010, 'i', - 0xD000, 'j', - 0xC800, 'k', - 0xC400, 'l', - 0xC200, 'm', - 0xC100, 'n', - 0xC080, 'o', - 0xC040, 'p', - 0xC020, 'q', - 0xC010, 'r', - 0x6800, 's', - 0x6400, 't', - 0x6200, 'u', - 0x6100, 'v', - 0x6080, 'w', - 0x6040, 'x', - 0x6020, 'y', - 0x6010, 'z', // these odd punch codes are used by APL: - 0x1010, '\001', // no corresponding ASCII using ^A - 0x0810, '\002', // SYN using ^B - 0x0410, '\003', // no corresponding ASCII using ^C - 0x0210, '\004', // PUNCH ON using ^D - 0x0110, '\005', // READER STOP using ^E - 0x0090, '\006', // UPPER CASE using ^F - 0x0050, '\013', // EOT using ^K - 0x0030, '\016', // no corresponding ASCII using ^N - 0x1030, '\017', // no corresponding ASCII using ^O - 0x0830, '\020', // no corresponding ASCII using ^P -}; - -int hollerith_to_ascii (unsigned short h) -{ - int i; - - h &= 0xFFF0; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].hollerith == h) - return cardcode_029[i].ascii; - - return '?'; -} - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - diff --git a/Ibm1130/utils/viewdeck.mak b/Ibm1130/utils/viewdeck.mak deleted file mode 100644 index 3ee6f6aa..00000000 --- a/Ibm1130/utils/viewdeck.mak +++ /dev/null @@ -1,176 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "viewdeck.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/viewdeck.exe $(OUTDIR)/viewdeck.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"viewdeck.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"viewdeck.bsc" -BSC32_SBRS= \ - $(INTDIR)/viewdeck.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/viewdeck.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\ - /PDB:$(OUTDIR)/"viewdeck.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"viewdeck.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/viewdeck.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/viewdeck.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/viewdeck.exe $(OUTDIR)/viewdeck.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"viewdeck.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"viewdeck.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"viewdeck.bsc" -BSC32_SBRS= \ - $(INTDIR)/viewdeck.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/viewdeck.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\ - /PDB:$(OUTDIR)/"viewdeck.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"viewdeck.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/viewdeck.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/viewdeck.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\viewdeck.c - -$(INTDIR)/viewdeck.obj : $(SOURCE) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\util_io.c -DEP_UTIL_=\ - .\util_io.h - -$(INTDIR)/util_io.obj : $(SOURCE) $(DEP_UTIL_) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Visual Studio Projects/AltairZ80.vcproj b/Visual Studio Projects/AltairZ80.vcproj deleted file mode 100644 index 9125307d..00000000 --- a/Visual Studio Projects/AltairZ80.vcproj +++ /dev/null @@ -1,406 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Visual Studio Projects/swtp6800mp-a.vcproj b/Visual Studio Projects/swtp6800mp-a.vcproj deleted file mode 100644 index bf86be0d..00000000 --- a/Visual Studio Projects/swtp6800mp-a.vcproj +++ /dev/null @@ -1,314 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Visual Studio Projects/swtp6800mp-a2.vcproj b/Visual Studio Projects/swtp6800mp-a2.vcproj deleted file mode 100644 index b3230803..00000000 --- a/Visual Studio Projects/swtp6800mp-a2.vcproj +++ /dev/null @@ -1,318 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/altairz80_doc.pdf b/doc/altairz80_doc.pdf deleted file mode 100644 index 3497e9b3..00000000 Binary files a/doc/altairz80_doc.pdf and /dev/null differ diff --git a/doc/swtp6800MP-A.png b/doc/swtp6800MP-A.png deleted file mode 100644 index 4c2e4b58..00000000 Binary files a/doc/swtp6800MP-A.png and /dev/null differ diff --git a/doc/swtp6800MP-A2.png b/doc/swtp6800MP-A2.png deleted file mode 100644 index c1f46daa..00000000 Binary files a/doc/swtp6800MP-A2.png and /dev/null differ diff --git a/doc/swtp6800_doc.doc b/doc/swtp6800_doc.doc deleted file mode 100644 index 986f08c0..00000000 Binary files a/doc/swtp6800_doc.doc and /dev/null differ diff --git a/swtp6800/common/bootrom.c b/swtp6800/common/bootrom.c deleted file mode 100644 index c3ecc6e8..00000000 --- a/swtp6800/common/bootrom.c +++ /dev/null @@ -1,231 +0,0 @@ -/* bootrom.c: Boot ROM simulator for Motorola processors - - Copyright (c) 2010-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 single simulated 2704 to 2764 EPROM device on - an 8-bit computer system.. This device allows the the device buffer to - be loaded from a binary file containing the emulated EPROM code. - - These functions support a simulated 2704, 2708, 2716, 2732 or 2764 EPROM - device on a CPU board. The byte get and put routines use an offset into - the boot EPROM image to locate the proper byte. This allows another device - to set the base address for the boot EPROM. The device type is stored as - a binary number in the first three unit flag bits. - - This device uses a dynamically allocated buffer to hold the EPROM image. - A call to BOOTROM_config will free the current buffer. A call to - BOOTROM_reset will allocate a new buffer of BOOTROM_unit.capac bytes. A - call to BOOTROM_attach will load the buffer with the EPROM image. -*/ - -#include -#include "swtp_defs.h" - -#define UNIT_V_MSIZE (UNIT_V_UF) /* ROM Size */ -#define UNIT_MSIZE (0x7 << UNIT_V_MSIZE) -#define UNIT_NONE (0 << UNIT_V_MSIZE) /* No EPROM */ -#define UNIT_2704 (1 << UNIT_V_MSIZE) /* 2704 mode */ -#define UNIT_2708 (2 << UNIT_V_MSIZE) /* 2708 mode */ -#define UNIT_2716 (3 << UNIT_V_MSIZE) /* 2716 mode */ -#define UNIT_2732 (4 << UNIT_V_MSIZE) /* 2732 mode */ -#define UNIT_2764 (5 << UNIT_V_MSIZE) /* 2764 mode */ - -/* function prototypes */ - -t_stat BOOTROM_svc (UNIT *uptr); -t_stat BOOTROM_config (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat BOOTROM_attach (UNIT *uptr, char *cptr); -t_stat BOOTROM_reset (DEVICE *dptr); -int32 BOOTROM_get_mbyte(int32 offset); - -/* SIMH Standard I/O Data Structures */ - -UNIT BOOTROM_unit = { UDATA (NULL, - UNIT_ATTABLE+UNIT_BINK+UNIT_ROABLE+UNIT_RO, 0), - KBD_POLL_WAIT }; - -MTAB BOOTROM_mod[] = { - { UNIT_MSIZE, UNIT_NONE, "None", "NONE", &BOOTROM_config }, - { UNIT_MSIZE, UNIT_2704, "2704", "2704", &BOOTROM_config }, - { UNIT_MSIZE, UNIT_2708, "2708", "2708", &BOOTROM_config }, - { UNIT_MSIZE, UNIT_2716, "2716", "2716", &BOOTROM_config }, - { UNIT_MSIZE, UNIT_2732, "2732", "2732", &BOOTROM_config }, - { UNIT_MSIZE, UNIT_2764, "2764", "2764", &BOOTROM_config }, - { 0 } -}; - -DEBTAB BOOTROM_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE BOOTROM_dev = { - "BOOTROM", /* name */ - &BOOTROM_unit, /* units */ - NULL, /* registers */ - BOOTROM_mod, /* modifiers */ - 1, /* numunits */ - 16, /* aradix */ - 32, /* awidth */ - 1, /* aincr */ - 16, /* dradix */ - 8, /* dwidth */ - NULL, /* examine */ - NULL, /* deposit */ - &BOOTROM_reset, /* reset */ - NULL, /* boot */ - &BOOTROM_attach, /* attach */ - NULL, /* detach */ - NULL, /* ctxt */ - DEV_DEBUG, /* flags */ - 0, /* dctrl */ - BOOTROM_debug, /* debflags */ - NULL, /* msize */ - NULL /* lname */ -}; - -/* global variables */ - -/* BOOTROM_attach - attach file to EPROM unit */ - -t_stat BOOTROM_attach (UNIT *uptr, char *cptr) -{ - t_stat r; - - if (BOOTROM_dev.dctrl & DEBUG_flow) - printf("BOOTROM_attach: cptr=%s\n", cptr); - if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { - if (BOOTROM_dev.dctrl & DEBUG_flow) - printf("BOOTROM_attach: Error\n"); - return r; - } - if (BOOTROM_dev.dctrl & DEBUG_flow) - printf("BOOTROM_attach: Done\n"); - return (BOOTROM_reset (NULL)); -} - -/* BOOTROM_config = None, 2704, 2708, 2716, 2732 or 2764 */ - -t_stat BOOTROM_config (UNIT *uptr, int32 val, char *cptr, void *desc) -{ - if (BOOTROM_dev.dctrl & DEBUG_flow) /* entry message */ - printf("BOOTROM_config: val=%d\n", val); - if ((val < UNIT_NONE) || (val > UNIT_2764)) { /* valid param? */ - if (BOOTROM_dev.dctrl & DEBUG_flow) /* No */ - printf("BOOTROM_config: Parameter error\n"); - return SCPE_ARG; - } - if (val == UNIT_NONE) - BOOTROM_unit.capac = 0; /* set EPROM size */ - else - BOOTROM_unit.capac = 0x200 << ((val >> UNIT_V_MSIZE) - 1); /* set EPROM size */ - if (BOOTROM_unit.filebuf) { /* free buffer */ - free (BOOTROM_unit.filebuf); - BOOTROM_unit.filebuf = NULL; - } - if (BOOTROM_dev.dctrl & DEBUG_flow) /* status message */ - printf("BOOTROM_config: BOOTROM_unit.capac=%d\n", - BOOTROM_unit.capac); - if (BOOTROM_dev.dctrl & DEBUG_flow) /* exit message */ - printf("BOOTROM_config: Done\n"); - return SCPE_OK; -} - -/* EPROM reset */ - -t_stat BOOTROM_reset (DEVICE *dptr) -{ - t_addr j; - int c; - FILE *fp; - - if (BOOTROM_dev.dctrl & DEBUG_flow) - printf("BOOTROM_reset: \n"); - if ((BOOTROM_unit.flags & UNIT_MSIZE) == 0) { /* if none selected */ -// printf(" EPROM: Defaulted to None\n"); -// printf(" \"set eprom NONE | 2704 | 2708 | 2716 | 2732 | 2764\"\n"); -// printf(" \"att eprom \"\n"); - BOOTROM_unit.capac = 0; /* set EPROM size to 0 */ - if (BOOTROM_dev.dctrl & DEBUG_flow) - printf("BOOTROM_reset: Done1\n"); - return SCPE_OK; - } /* if attached */ -// printf(" EPROM: Initializing [%04X-%04XH]\n", -// 0xE000, 0xE000 + BOOTROM_unit.capac - 1); - if (BOOTROM_unit.filebuf == NULL) { /* no buffer allocated */ - BOOTROM_unit.filebuf = malloc(BOOTROM_unit.capac); /* allocate EPROM buffer */ - if (BOOTROM_unit.filebuf == NULL) { - if (BOOTROM_dev.dctrl & DEBUG_flow) - printf("BOOTROM_reset: Malloc error\n"); - return SCPE_MEM; - } - } - fp = fopen(BOOTROM_unit.filename, "rb"); /* open EPROM file */ - if (fp == NULL) { - printf("\tUnable to open ROM file %s\n",BOOTROM_unit.filename); - printf("\tNo ROM image loaded!!!\n"); - return SCPE_OK; - } - j = 0; /* load EPROM file */ - c = fgetc(fp); - while (c != EOF) { - *((uint8 *)(BOOTROM_unit.filebuf) + j++) = c & 0xFF; - c = fgetc(fp); - if (j > BOOTROM_unit.capac) { - printf("\tImage is too large - Load truncated!!!\n"); - break; - } - } - fclose(fp); -// printf("\t%d bytes of ROM image %s loaded\n", j, BOOTROM_unit.filename); - if (BOOTROM_dev.dctrl & DEBUG_flow) - printf("BOOTROM_reset: Done2\n"); - return SCPE_OK; -} - -/* get a byte from memory - byte offset of image */ - -int32 BOOTROM_get_mbyte(int32 offset) -{ - int32 val; - - if (BOOTROM_unit.filebuf == NULL) { - if (BOOTROM_dev.dctrl & DEBUG_read) - printf("BOOTROM_get_mbyte: EPROM not configured\n"); - return 0xFF; - } - if (BOOTROM_dev.dctrl & DEBUG_read) - printf("BOOTROM_get_mbyte: offset=%04X\n", offset); - val = *((uint8 *)(BOOTROM_unit.filebuf) + offset) & 0xFF; - if (BOOTROM_dev.dctrl & DEBUG_read) - printf("BOOTROM_get_mbyte: Normal val=%02X\n", val); - return val; -} - -/* end of bootrom.c */ diff --git a/swtp6800/common/dc-4.c b/swtp6800/common/dc-4.c deleted file mode 100644 index 204d40a8..00000000 --- a/swtp6800/common/dc-4.c +++ /dev/null @@ -1,568 +0,0 @@ -/* dc4.c: SWTP DC-4 FDC Simulator - - Copyright (c) 2005-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. - - The DC-4 is a 5-inch floppy controller which can control up - to 4 daisy-chained 5-inch floppy drives. The controller is based on - the Western Digital 1797 Floppy Disk Controller (FDC) chip. This - file only emulates the minimum DC-4 functionality to interface with - the virtual disk file. - - The floppy controller is interfaced to the CPU by use of 5 memory - addreses. These are SS-30 slot numbers 5 and 6 (0x8014-0x801B). - - Address Mode Function - ------- ---- -------- - - 0x8014 Read Returns FDC interrupt status - 0x8014 Write Selects the drive/head/motor control - 0x8018 Read Returns status of FDC - 0x8018 Write FDC command register - 0x8019 Read Returns FDC track register - 0x8019 Write Set FDC track register - 0x801A Read Returns FDC sector register - 0x801A Write Set FDC sector register - 0x801B Read Read data - 0x801B Write Write data - - Drive Select Read (0x8014): - - +---+---+---+---+---+---+---+---+ - | I | D | X | X | X | X | X | X | - +---+---+---+---+---+---+---+---+ - - I = Set indicates an interrupt request from the FDC pending. - D = DRQ pending - same as bit 1 of FDC status register. - - Drive Select Write (0x8014): - - +---+---+---+---+---+---+---+---+ - | M | S | X | X | X | X | Device| - +---+---+---+---+---+---+---+---+ - - M = If this bit is 1, the one-shot is triggered/retriggered to - start/keep the motors on. - S = Side select. If set, side one is selected otherwise side zero - is selected. - X = not used - Device = value 0 thru 3, selects drive 0-3 to be controlled. - - Drive Status Read (0x8018): - - +---+---+---+---+---+---+---+---+ - | R | P | H | S | C | L | D | B | - +---+---+---+---+---+---+---+---+ - - B - When 1, the controller is busy. - D - When 1, index mark detected (type I) or data request - read data - ready/write data empty (type II or III). - H - When 1, track 0 (type I) or lost data (type II or III). - C - When 1, crc error detected. - S - When 1, seek (type I) or RNF (type II or III) error. - H - When 1, head is currently loaded (type I) or record type/ - write fault (type II or III). - P - When 1, indicates that diskette is write-protected. - R - When 1, drive is not ready. - - Drive Control Write (0x8018) for type I commands: - - +---+---+---+---+---+---+---+---+ - | 0 | S2| S1| S0| H | V | R1| R0| - +---+---+---+---+---+---+---+---+ - - R0/R1 - Selects the step rate. - V - When 1, verify on destination track. - H - When 1, loads head to drive surface. - S0/S1/S2 = 000 - home. - 001 - seek track in data register. - 010 - step without updating track register. - 011 - step and update track register. - 100 - step in without updating track register. - 101 - step in and update track register. - 110 - step out without updating track register. - 111 - step out and update track register. - - Drive Control Write (0x8018) for type II commands: - - +---+---+---+---+---+---+---+---+ - | 1 | 0 | T | M | S | E | B | A | - +---+---+---+---+---+---+---+---+ - - A - Zero for read, 1 on write deleted data mark else data mark. - B - When 1, shifts sector length field definitions one place. - E - When, delay operation 15 ms, 0 no delay. - S - When 1, select side 1, 0 select side 0. - M - When 1, multiple records, 0 for single record. - T - When 1, write command, 0 for read. - - Drive Control Write (0x8018) for type III commands: - - +---+---+---+---+---+---+---+---+ - | 1 | 1 | T0| T1| 0 | E | 0 | 0 | - +---+---+---+---+---+---+---+---+ - - E - When, delay operation 15 ms, 0 no delay. - T0/T1 - 00 - read address command. - 10 - read track command. - 11 - write track command. - - Tracks are numbered from 0 up to one minus the last track in the 1797! - - Track Register Read (0x8019): - - +---+---+---+---+---+---+---+---+ - | Track Number | - +---+---+---+---+---+---+---+---+ - - Reads the current 8-bit value from the track position. - - Track Register Write (0x8019): - - +---+---+---+---+---+---+---+---+ - | Track Number | - +---+---+---+---+---+---+---+---+ - - Writes the 8-bit value to the track register. - - Sectors are numbers from 1 up to the last sector in the 1797! - - Sector Register Read (0x801A): - - +---+---+---+---+---+---+---+---+ - | Sector Number | - +---+---+---+---+---+---+---+---+ - - Reads the current 8-bit value from the sector position. - - Sector Register Write (0x801A): - - +---+---+---+---+---+---+---+---+ - | Sector Number | - +---+---+---+---+---+---+---+---+ - - Writes the 8-bit value to the sector register. - - Data Register Read (0x801B): - - +---+---+---+---+---+---+---+---+ - | Data | - +---+---+---+---+---+---+---+---+ - - Reads the current 8-bit value from the data register. - - Data Register Write (0x801B): - - +---+---+---+---+---+---+---+---+ - | Data | - +---+---+---+---+---+---+---+---+ - - Writes the 8-bit value to the data register. - - A FLEX disk is defined as follows: - - Track Sector Use - 0 1 Boot sector - 0 2 Boot sector (cont) - 0 3 Unused - 0 4 System Identity Record (explained below) - 0 5 Unused - 0 6-last Directory - 10 entries/sector (explained below) - 1 1 First available data sector - last-1 last Last available data sector - - System Identity Record - - Byte Use - 0x00 Two bytes of zeroes (Clears forward link) - 0x10 Volume name in ASCII(11 bytes) - 0x1B Volume number in binary (2 bytes) - 0x1D Address of first free data sector (Track-Sector) (2 bytes) - 0x1F Address of last free data sector (Track-Sector) (2 bytes) - 0x21 Total number of data sectors in binary (2 bytes) - 0x23 Current date (Month-Day-Year) in binary - 0x26 Highest track number on disk in binary (byte) - 0x27 Highest sector number on a track in binary (byte) - - The following unit registers are used by this controller emulation: - - dsk_unit[cur_drv].u3 unit current flags - dsk_unit[cur_drv].u4 unit current track - dsk_unit[cur_drv].u5 unit current sector - dsk_unit[cur_drv].pos unit current sector byte index into buffer - dsk_unit[cur_drv].filebuf unit current sector buffer - dsk_unit[cur_drv].fileref unit current attached file reference -*/ - -#include -#include "swtp_defs.h" - -#define DEBUG 0 - -#define UNIT_V_ENABLE (UNIT_V_UF + 0) /* Write Enable */ -#define UNIT_ENABLE (1 << UNIT_V_ENABLE) - -/* emulate a SS FLEX disk with 72 sectors and 80 tracks */ - -#define NUM_DISK 4 /* standard 1797 maximum */ -#define SECT_SIZE 256 /* standard FLEX sector */ -#define NUM_SECT 72 /* sectors/track */ -#define TRAK_SIZE (SECT_SIZE * NUM_SECT) /* trk size (bytes) */ -#define HEADS 1 /* handle as SS with twice the sectors */ -#define NUM_CYL 80 /* maximum tracks */ -#define DSK_SIZE (NUM_SECT * HEADS * NUM_CYL * SECT_SIZE) /* dsk size (bytes) */ - -#define SECSIZ 256 /* standard FLEX sector */ - -/* SIR offsets */ -#define MAXCYL 0x26 /* last cylinder # */ -#define MAXSEC 0x27 /* last sector # */ - -/* 1797 status bits */ - -#define BUSY 0x01 -#define DRQ 0x02 -#define WRPROT 0x40 -#define NOTRDY 0x80 - -/* function prototypes */ - -t_stat dsk_reset (DEVICE *dptr); - -/* SS-50 I/O address space functions */ - -int32 fdcdrv(int32 io, int32 data); -int32 fdccmd(int32 io, int32 data); -int32 fdctrk(int32 io, int32 data); -int32 fdcsec(int32 io, int32 data); -int32 fdcdata(int32 io, int32 data); - -/* Local Variables */ - -int32 fdcbyte; -int32 intrq = 0; /* interrupt request flag */ -int32 cur_dsk; /* Currently selected drive */ -int32 wrt_flag = 0; /* FDC write flag */ - -int32 spt; /* sectors/track */ -int32 trksiz; /* trk size (bytes) */ -int32 heds; /* number of heads */ -int32 cpd; /* cylinders/disk */ -int32 dsksiz; /* dsk size (bytes) */ - -/* Floppy Disk Controller data structures - - dsk_dev Mother Board device descriptor - dsk_unit Mother Board unit descriptor - dsk_reg Mother Board register list - dsk_mod Mother Board modifiers list -*/ - -UNIT dsk_unit[] = { - { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) }, - { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) }, - { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) }, - { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) } -}; - -REG dsk_reg[] = { - { HRDATA (DISK, cur_dsk, 4) }, - { NULL } -}; - -MTAB dsk_mod[] = { - { UNIT_ENABLE, UNIT_ENABLE, "RW", "RW", NULL }, - { UNIT_ENABLE, 0, "RO", "RO", NULL }, - { 0 } -}; - -DEBTAB dsk_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE dsk_dev = { - "DC-4", //name - dsk_unit, //units - dsk_reg, //registers - dsk_mod, //modifiers - 4, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - &dsk_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - dsk_debug, /* debflags */ - NULL, //msize - NULL //lname -}; - -/* Reset routine */ - -t_stat dsk_reset (DEVICE *dptr) -{ - int i; - - cur_dsk = 5; /* force initial SIR read */ - for (i=0; i -#include "swtp_defs.h" - -#define I2716_NUM 4 /* number of 2716 EPROMS */ - -extern int32 get_base(void); - -/* function prototypes */ - -t_stat i2716_attach (UNIT *uptr, char *cptr); -t_stat i2716_reset (DEVICE *dptr); -int32 i2716_get_mbyte(int32 offset); - -/* SIMH EPROM Standard I/O Data Structures */ - -UNIT i2716_unit[] = { - { UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 }, - { UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 }, - { UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 }, - { UDATA (NULL,UNIT_ATTABLE+UNIT_ROABLE+UNIT_RO, 0), 0 } -}; - -MTAB i2716_mod[] = { - { 0 } -}; - -DEBTAB i2716_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE i2716_dev = { - "I2716", /* name */ - i2716_unit, /* units */ - NULL, /* registers */ - i2716_mod, /* modifiers */ - I2716_NUM, /* numunits */ - 16, /* aradix */ - 32, /* awidth */ - 1, /* aincr */ - 16, /* dradix */ - 8, /* dwidth */ - NULL, /* examine */ - NULL, /* deposit */ - &i2716_reset, /* reset */ - NULL, /* boot */ - &i2716_attach, /* attach */ - NULL, /* detach */ - NULL, /* ctxt */ - DEV_DEBUG, /* flags */ - 0, /* dctrl */ - i2716_debug, /* debflags */ - NULL, /* msize */ - NULL /* lname */ -}; - -/* global variables */ - -/* i2716_attach - attach file to EPROM unit - force EPROM reset at completion */ - -t_stat i2716_attach (UNIT *uptr, char *cptr) -{ - int32 j, c; - t_stat r; - FILE *fp; - - if (i2716_dev.dctrl & DEBUG_flow) - printf("i2716_attach: cptr=%s\n", cptr); - if ((r = attach_unit (uptr, cptr)) != SCPE_OK) { - if (i2716_dev.dctrl & DEBUG_flow) - printf("i2716_attach: Error\n"); - return r; - } - if (i2716_dev.dctrl & DEBUG_read) - printf("\tOpen file\n"); - fp = fopen(uptr->filename, "rb"); /* open EPROM file */ - if (fp == NULL) { - printf("i2716%d: Unable to open ROM file %s\n", (int)(uptr - i2716_dev.units), uptr->filename); - printf("\tNo ROM image loaded!!!\n"); - return SCPE_OK; - } - if (i2716_dev.dctrl & DEBUG_read) - printf("\tRead file\n"); - j = 0; /* load EPROM file */ - c = fgetc(fp); - while (c != EOF) { - *((uint8 *)(uptr->filebuf) + j++) = c & 0xFF; - c = fgetc(fp); - if (j > 2048) { - printf("\tImage is too large - Load truncated!!!\n"); - break; - } - } - if (i2716_dev.dctrl & DEBUG_read) - printf("\tClose file\n"); - fclose(fp); -// printf("i2716%d: %d bytes of ROM image %s loaded\n",uptr - i2716_dev.units, j, uptr->filename); - if (i2716_dev.dctrl & DEBUG_flow) - printf("i2716_attach: Done\n"); - return SCPE_OK; -} - -/* EPROM reset */ - -t_stat i2716_reset (DEVICE *dptr) -{ - int32 i, base; - UNIT *uptr; - - if (i2716_dev.dctrl & DEBUG_flow) - printf("i2716_reset: \n"); - for (i = 0; i < I2716_NUM; i++) { /* init all units */ - uptr = i2716_dev.units + i; - if (i2716_dev.dctrl & DEBUG_flow) - printf("i2716 %d unit.flags=%08X\n", i, uptr->flags); - uptr->capac = 2048; - uptr->u3 = 2048 * i; - base = get_base(); - if (uptr->filebuf == NULL) { /* no buffer allocated */ - uptr->filebuf = malloc(2048); /* allocate EPROM buffer */ - if (uptr->filebuf == NULL) { - if (i2716_dev.dctrl & DEBUG_flow) - printf("i2716_reset: Malloc error\n"); - return SCPE_MEM; - } - } - if (base == 0) { -// printf("i2716%d: Not enabled on MP-A2\n", i); - continue; - } -// printf("i2716%d: Initializing [%04X-%04XH]\n", -// i, base+uptr->u3, base+uptr->u3 + uptr->capac); -// if ((uptr->flags & UNIT_ATT) == 0) { -// printf("i2716%d: No file attached\n", i); -// } - } - if (i2716_dev.dctrl & DEBUG_flow) - printf("i2716_reset: Done\n"); - return SCPE_OK; -} - -/* I/O instruction handlers, called from the CPU module when an - EPROM memory read or write is issued. -*/ - -/* get a byte from memory */ - -int32 i2716_get_mbyte(int32 offset) -{ - int32 i, val, org, len; - UNIT *uptr; - - for (i = 0; i < I2716_NUM; i++) { /* find addressed unit */ - uptr = i2716_dev.units + i; - org = uptr->u3; - len = uptr->capac - 1; - if ((offset >= org) && (offset < (org + len))) { - if (uptr->filebuf == NULL) { - if (i2716_dev.dctrl & DEBUG_read) - printf("i2716_get_mbyte: EPROM not configured\n"); - return 0xFF; - } else { - val = *((uint8 *)(uptr->filebuf) + (offset - org)); - if (i2716_dev.dctrl & DEBUG_read) - printf(" val=%04X\n", val); - return (val & 0xFF); - } - } - } - if (i2716_dev.dctrl & DEBUG_read) - printf("i2716_get_mbyte: Out of range\n"); - return 0xFF; -} - -/* end of i2716.c */ diff --git a/swtp6800/common/m6800.c b/swtp6800/common/m6800.c deleted file mode 100644 index 31c658e9..00000000 --- a/swtp6800/common/m6800.c +++ /dev/null @@ -1,2013 +0,0 @@ -/* m6800.c: SWTP 6800 CPU simulator - - Copyright (c) 2005-2011, William 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 Motorola M6800 CPU - - The register state for the M6800 CPU is: - - A<0:7> Accumulator A - B<0:7> Accumulator B - IX<0:15> Index Register - CCR<0:7> Condition Code Register - HF half-carry flag - IF interrupt flag - NF negative flag - ZF zero flag - VF overflow flag - CF carry flag - PC<0:15> program counter - SP<0:15> Stack Pointer - - The M6800 is an 8-bit CPU, which uses 16-bit registers to address - up to 64KB of memory. - - The 72 basic instructions come in 1, 2, and 3-byte flavors. - - This routine is the instruction decode routine for the M6800. - It is called from the CPU board simulator 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: - - WAI instruction - I/O error in I/O simulator - Invalid OP code (if ITRAP is set on CPU) - Invalid mamory address (if MTRAP is set on CPU) - - 2. Interrupts. - There are 4 types of interrupt, and in effect they do a - hardware CALL instruction to one of 4 possible high memory addresses. - - 3. Non-existent memory. - On the SWTP 6800, reads to non-existent memory - return 0FFH, and writes are ignored. -*/ - -#include - -#include "swtp_defs.h" - -#define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */ -#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) -#define UNIT_V_MSTOP (UNIT_V_UF+1) /* Stop on Invalid memory? */ -#define UNIT_MSTOP (1 << UNIT_V_MSTOP) - -/* Flag values to set proper positions in CCR */ -#define HF 0x20 -#define IF 0x10 -#define NF 0x08 -#define ZF 0x04 -#define VF 0x02 -#define CF 0x01 - -/* Macros to handle the flags in the CCR */ -#define CCR_ALWAYS_ON (0xC0) /* for 6800 */ -#define CCR_MSK (HF|IF|NF|ZF|VF|CF) -#define TOGGLE_FLAG(FLAG) (CCR ^= (FLAG)) -#define SET_FLAG(FLAG) (CCR |= (FLAG)) -#define CLR_FLAG(FLAG) (CCR &= ~(FLAG)) -#define GET_FLAG(FLAG) (CCR & (FLAG)) -#define COND_SET_FLAG(COND,FLAG) \ - if (COND) SET_FLAG(FLAG); else CLR_FLAG(FLAG) -#define COND_SET_FLAG_N(VAR) \ - if ((VAR) & 0x80) SET_FLAG(NF); else CLR_FLAG(NF) -#define COND_SET_FLAG_Z(VAR) \ - if ((VAR) == 0) SET_FLAG(ZF); else CLR_FLAG(ZF) -#define COND_SET_FLAG_H(VAR) \ - if ((VAR) & 0x10) SET_FLAG(HF); else CLR_FLAG(HF) -#define COND_SET_FLAG_C(VAR) \ - if ((VAR) & 0x100) SET_FLAG(CF); else CLR_FLAG(CF) -#define COND_SET_FLAG_V(COND) \ - if (COND) SET_FLAG(VF); else CLR_FLAG(VF) - -/* local global variables */ - -int32 A = 0; /* Accumulator A */ -int32 B = 0; /* Accumulator B */ -int32 IX = 0; /* Index register */ -int32 SP = 0; /* Stack pointer */ -int32 CCR = CCR_ALWAYS_ON | IF; /* Condition Code Register */ -int32 saved_PC = 0; /* Program counter */ -int32 PC; /* global for the helper routines */ -int32 INTE = 0; /* Interrupt Enable */ -int32 int_req = 0; /* Interrupt request */ - -int32 mem_fault = 0; /* memory fault flag */ - -/* function prototypes */ - -t_stat m6800_reset (DEVICE *dptr); -void dump_regs(void); -void dump_regs1(void); -int32 fetch_byte(int32 flag); -int32 fetch_word(void); -uint8 pop_byte(void); -uint16 pop_word(void); -void push_byte(uint8 val); -void push_word(uint16 val); -void go_rel(int32 cond); -int32 get_rel_addr(void); -int32 get_dir_val(void); -int32 get_dir_addr(void); -int32 get_indir_val(void); -int32 get_indir_addr(void); -int32 get_ext_val(void); -int32 get_ext_addr(void); -int32 get_flag(int32 flag); -void condevalVa(int32 op1, int32 op2); -void condevalVs(int32 op1, int32 op2); - -/* external routines */ - -extern void CPU_BD_put_mbyte(int32 addr, int32 val); -extern void CPU_BD_put_mword(int32 addr, int32 val); -extern int32 CPU_BD_get_mbyte(int32 addr); -extern int32 CPU_BD_get_mword(int32 addr); - -/* CPU data structures - - m6800_dev CPU device descriptor - m6800_unit CPU unit descriptor - m6800_reg CPU register list - m6800_mod CPU modifiers list */ - -UNIT m6800_unit = { UDATA (NULL, 0, 0) }; - -REG m6800_reg[] = { - { HRDATA (PC, saved_PC, 16) }, - { HRDATA (A, A, 8) }, - { HRDATA (B, B, 8) }, - { HRDATA (IX, IX, 16) }, - { HRDATA (SP, SP, 16) }, - { HRDATA (CCR, CCR, 8) }, - { FLDATA (INTE, INTE, 16) }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB m6800_mod[] = { - { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL }, - { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL }, - { UNIT_MSTOP, UNIT_MSTOP, "MTRAP", "MTRAP", NULL }, - { UNIT_MSTOP, 0, "NOMTRAP", "NOMTRAP", NULL }, - { 0 } }; - -DEBTAB m6800_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 m6800_dev = { - "CPU", //name - &m6800_unit, //units - m6800_reg, //registers - m6800_mod, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - &m6800_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - m6800_debug, //debflags - NULL, //msize - NULL //lname -}; - -static const char *opcode[] = { -"???", "NOP", "???", "???", //0x00 -"???", "???", "TAP", "TPA", -"INX", "DEX", "CLV", "SEV", -"CLC", "SEC", "CLI", "SEI", -"SBA", "CBA", "???", "???", //0x10 -"???", "???", "TAB", "TBA", -"???", "DAA", "???", "ABA", -"???", "???", "???", "???", -"BRA", "???", "BHI", "BLS", //0x20 -"BCC", "BCS", "BNE", "BEQ", -"BVC", "BVS", "BPL", "BMI", -"BGE", "BLT", "BGT", "BLE", -"TSX", "INS", "PULA", "PULB", //0x30 -"DES", "TXS", "PSHA", "PSHB", -"???", "RTS", "???", "RTI", -"???", "???", "WAI", "SWI", -"NEGA", "???", "???", "COMA", //0x40 -"LSRA", "???", "RORA", "ASRA", -"ASLA", "ROLA", "DECA", "???", -"INCA", "TSTA", "???", "CLRA", -"NEGB", "???", "???", "COMB", //0x50 -"LSRB", "???", "RORB", "ASRB", -"ASLB", "ROLB", "DECB", "???", -"INCB", "TSTB", "???", "CLRB", -"NEG", "???", "???", "COM", //0x60 -"LSR", "???", "ROR", "ASR", -"ASL", "ROL", "DEC", "???", -"INC", "TST", "JMP", "CLR", -"NEG", "???", "???", "COM", //0x70 -"LSR", "???", "ROR", "ASR", -"ASL", "ROL", "DEC", "???", -"INC", "TST", "JMP", "CLR", -"SUBA", "CMPA", "SBCA", "???", //0x80 -"ANDA", "BITA", "LDAA", "???", -"EORA", "ADCA", "ORAA", "ADDA", -"CPX", "BSR", "LDS", "???", -"SUBA", "CMPA", "SBCA", "???", //0x90 -"ANDA", "BITA", "LDAA", "STAA", -"EORA", "ADCA", "ORAA", "ADDA", -"CPX", "???", "LDS", "STS", -"SUBA", "CMPA", "SBCA", "???", //0xA0 -"ANDA", "BITA", "LDAA", "STAA", -"EORA", "ADCA", "ORAA", "ADDA", -"CPX X", "JSR X", "LDS X", "STS X", -"SUBA", "CMPA", "SBCA", "???", //0xB0 -"ANDA", "BITA", "LDAA", "STAA", -"EORA", "ADCA", "ORAA", "ADDA", -"CPX", "JSR", "LDS", "STS", -"SUBB", "CMPB", "SBCB", "???", //0xC0 -"ANDB", "BITB", "LDAB", "???", -"EORB", "ADCB", "ORAB", "ADDB", -"???", "???", "LDX", "???", -"SUBB", "CMPB", "SBCB", "???", //0xD0 -"ANDB", "BITB", "LDAB", "STAB", -"EORB", "ADCB", "ORAB", "ADDB", -"???", "???", "LDX", "STX", -"SUBB", "CMPB", "SBCB", "???", //0xE0 -"ANDB", "BITB", "LDAB", "STAB", -"EORB", "ADCB", "ORAB", "ADDB", -"???", "???", "LDX", "STX", -"SUBB", "CMPB", "SBCB", "???", //0xF0 -"ANDB", "BITB", "LDAB", "STAB", -"EORB", "ADCB", "ORAB", "ADDB", -"???", "???", "LDX", "STX", -}; - -int32 oplen[256] = { -0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1, //0x00 -1,1,0,0,0,0,1,1,0,1,0,1,0,0,0,0, -2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2, -1,1,1,1,1,1,1,1,0,1,0,1,0,0,1,1, -1,0,0,1,1,0,1,1,1,1,1,0,1,1,0,1, //0x40 -1,0,0,1,1,0,1,1,1,1,1,0,1,1,0,1, -2,0,0,2,2,0,2,2,2,2,2,0,2,2,2,2, -3,0,0,3,3,0,3,3,3,3,3,0,3,3,3,3, -2,2,2,0,2,2,2,0,2,2,2,2,3,2,3,0, //0x80 -2,2,2,0,2,2,2,2,2,2,2,2,2,0,2,2, -2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2, -3,3,3,0,3,3,3,3,3,3,3,3,3,3,3,3, -2,2,2,0,2,2,2,0,2,2,2,2,0,0,3,0, //0xC0 -2,2,2,0,2,2,2,2,2,2,2,2,0,0,2,2, -2,2,2,0,2,2,2,2,2,2,2,2,0,0,2,2, -3,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3 -}; - -t_stat sim_instr (void) -{ - int32 IR, OP, DAR, reason, hi, lo, op1; - - PC = saved_PC & ADDRMASK; /* load local PC */ - reason = 0; - - /* Main instruction fetch/decode loop */ - - while (reason == 0) { /* loop until halted */ -// dump_regs1(); - if (sim_interval <= 0) /* check clock queue */ - if ((reason = sim_process_event ())) - break; - if (mem_fault) { /* memory fault? */ - mem_fault = 0; /* reset fault flag */ - reason = STOP_MEMORY; - break; - } - if (int_req > 0) { /* interrupt? */ - /* 6800 interrupts not implemented yet. None were used, - on a standard SWTP 6800. All I/O is programmed. */ - } /* end interrupt */ - if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - IR = OP = fetch_byte(0); /* fetch instruction */ - sim_interval--; - - /* The Big Instruction Decode Switch */ - - switch (IR) { - - case 0x01: /* NOP */ - break; - case 0x06: /* TAP */ - CCR = A; - break; - case 0x07: /* TPA */ - A = CCR; - break; - case 0x08: /* INX */ - IX = (IX + 1) & ADDRMASK; - COND_SET_FLAG_Z(IX); - break; - case 0x09: /* DEX */ - IX = (IX - 1) & ADDRMASK; - COND_SET_FLAG_Z(IX); - break; - case 0x0A: /* CLV */ - CLR_FLAG(VF); - break; - case 0x0B: /* SEV */ - SET_FLAG(VF); - break; - case 0x0C: /* CLC */ - CLR_FLAG(CF); - break; - case 0x0D: /* SEC */ - SET_FLAG(CF); - break; - case 0x0E: /* CLI */ - CLR_FLAG(IF); - break; - case 0x0F: /* SEI */ - SET_FLAG(IF); - break; - case 0x10: /* SBA */ - op1 = A; - A = A - B; - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - COND_SET_FLAG_C(A); - condevalVs(B, op1); - A &= 0xFF; - break; - case 0x11: /* CBA */ - lo = A - B; - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_C(lo); - condevalVs(B, A); - break; - case 0x16: /* TAB */ - B = A; - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - CLR_FLAG(VF); - break; - case 0x17: /* TBA */ - A = B; - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - CLR_FLAG(VF); - break; - case 0x19: /* DAA */ - DAR = A & 0x0F; - op1 = get_flag(CF); - if (DAR > 9 || get_flag(CF)) { - DAR += 6; - A &= 0xF0; - A |= (DAR & 0x0F); - COND_SET_FLAG(DAR & 0x10,CF); - } - DAR = (A >> 4) & 0x0F; - if (DAR > 9 || get_flag(CF)) { - DAR += 6; - if (get_flag(CF)) - DAR++; - A &= 0x0F; - A |= (DAR << 4); - } - COND_SET_FLAG(op1,CF); - if ((DAR << 4) & 0x100) - SET_FLAG(CF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - A &= 0xFF; - break; - case 0x1B: /* ABA */ - A += B; - COND_SET_FLAG_H(A); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - COND_SET_FLAG_C(A); - condevalVa(A, B); - A &= 0xFF; - break; - case 0x20: /* BRA rel */ - go_rel(1); - break; - case 0x22: /* BHI rel */ - go_rel(!(get_flag(CF) | get_flag(ZF))); - break; - case 0x23: /* BLS rel */ - go_rel(get_flag(CF) | get_flag(ZF)); - break; - case 0x24: /* BCC rel */ - go_rel(!get_flag(CF)); - break; - case 0x25: /* BCS rel */ - go_rel(get_flag(CF)); - break; - case 0x26: /* BNE rel */ - go_rel(!get_flag(ZF)); - break; - case 0x27: /* BEQ rel */ - go_rel(get_flag(ZF)); - break; - case 0x28: /* BVC rel */ - go_rel(!get_flag(VF)); - break; - case 0x29: /* BVS rel */ - go_rel(get_flag(VF)); - break; - case 0x2A: /* BPL rel */ - go_rel(!get_flag(NF)); - break; - case 0x2B: /* BMI rel */ - go_rel(get_flag(NF)); - break; - case 0x2C: /* BGE rel */ - go_rel(!(get_flag(NF) ^ get_flag(VF))); - break; - case 0x2D: /* BLT rel */ - go_rel(get_flag(NF) ^ get_flag(VF)); - break; - case 0x2E: /* BGT rel */ - go_rel(!(get_flag(ZF) | (get_flag(NF) ^ get_flag(VF)))); - break; - case 0x2F: /* BLE rel */ - go_rel(get_flag(ZF) | (get_flag(NF) ^ get_flag(VF))); - break; - case 0x30: /* TSX */ - IX = (SP + 1) & ADDRMASK; - break; - case 0x31: /* INS */ - SP = (SP + 1) & ADDRMASK; - break; - case 0x32: /* PUL A */ - A = pop_byte(); - break; - case 0x33: /* PUL B */ - B = pop_byte(); - break; - case 0x34: /* DES */ - SP = (SP - 1) & ADDRMASK; - break; - case 0x35: /* TXS */ - SP = (IX - 1) & ADDRMASK; - break; - case 0x36: /* PSH A */ - push_byte(A); - break; - case 0x37: /* PSH B */ - push_byte(B); - break; - case 0x39: /* RTS */ - PC = pop_word(); - break; - case 0x3B: /* RTI */ - CCR = pop_byte(); - B = pop_byte(); - A = pop_byte(); - IX = pop_word(); - PC = pop_word(); - break; - case 0x3E: /* WAI */ - push_word(PC); - push_word(IX); - push_byte(A); - push_byte(B); - push_byte(CCR); - if (get_flag(IF)) { - reason = STOP_HALT; - continue; - } else { - SET_FLAG(IF); - PC = CPU_BD_get_mword(0xFFFE) & ADDRMASK; - } - break; - case 0x3F: /* SWI */ - push_word(PC); - push_word(IX); - push_byte(A); - push_byte(B); - push_byte(CCR); - SET_FLAG(IF); - PC = CPU_BD_get_mword(0xFFFB) & ADDRMASK; - break; - case 0x40: /* NEG A */ - A = (0 - A) & 0xFF; - COND_SET_FLAG_V(A & 0x80); - COND_SET_FLAG(A,CF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x43: /* COM A */ - A = ~A & 0xFF; - CLR_FLAG(VF); - SET_FLAG(CF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x44: /* LSR A */ - COND_SET_FLAG(A & 0x01,CF); - A = (A >> 1) & 0xFF; - CLR_FLAG(NF); - COND_SET_FLAG_Z(A); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x46: /* ROR A */ - hi = get_flag(CF); - COND_SET_FLAG(A & 0x01,CF); - A = (A >> 1) & 0xFF; - if (hi) - A |= 0x80; - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x47: /* ASR A */ - COND_SET_FLAG(A & 0x01,CF); - lo = A & 0x80; - A = (A >> 1) & 0xFF; - A |= lo; - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x48: /* ASL A */ - COND_SET_FLAG(A & 0x80,CF); - A = (A << 1) & 0xFF; - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x49: /* ROL A */ - hi = get_flag(CF); - COND_SET_FLAG(A & 0x80,CF); - A = (A << 1) & 0xFF; - if (hi) - A |= 0x01; - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x4A: /* DEC A */ - COND_SET_FLAG_V(A == 0x80); - A = (A - 1) & 0xFF; - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x4C: /* INC A */ - COND_SET_FLAG_V(A == 0x7F); - A = (A + 1) & 0xFF; - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x4D: /* TST A */ - lo = (A - 0) & 0xFF; - CLR_FLAG(VF); - CLR_FLAG(CF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x4F: /* CLR A */ - A = 0; - CLR_FLAG(NF); - CLR_FLAG(VF); - CLR_FLAG(CF); - SET_FLAG(ZF); - break; - case 0x50: /* NEG B */ - B = (0 - B) & 0xFF; - COND_SET_FLAG_V(B & 0x80); - COND_SET_FLAG(B,CF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0x53: /* COM B */ - B = ~B; - B &= 0xFF; - CLR_FLAG(VF); - SET_FLAG(CF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0x54: /* LSR B */ - COND_SET_FLAG(B & 0x01,CF); - B = (B >> 1) & 0xFF; - CLR_FLAG(NF); - COND_SET_FLAG_Z(B); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x56: /* ROR B */ - hi = get_flag(CF); - COND_SET_FLAG(B & 0x01,CF); - B = (B >> 1) & 0xFF; - if (hi) - B |= 0x80; - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x57: /* ASR B */ - COND_SET_FLAG(B & 0x01,CF); - lo = B & 0x80; - B = (B >> 1) & 0xFF; - B |= lo; - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x58: /* ASL B */ - COND_SET_FLAG(B & 0x80,CF); - B = (B << 1) & 0xFF; - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x59: /* ROL B */ - hi = get_flag(CF); - COND_SET_FLAG(B & 0x80,CF); - B = (B << 1) & 0xFF; - if (hi) - B |= 0x01; - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x5A: /* DEC B */ - COND_SET_FLAG_V(B == 0x80); - B = (B - 1) & 0xFF; - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0x5C: /* INC B */ - COND_SET_FLAG_V(B == 0x7F); - B = (B + 1) & 0xFF; - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0x5D: /* TST B */ - lo = (B - 0) & 0xFF; - CLR_FLAG(VF); - CLR_FLAG(CF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x5F: /* CLR B */ - B = 0; - CLR_FLAG(NF); - CLR_FLAG(VF); - CLR_FLAG(CF); - SET_FLAG(ZF); - break; - case 0x60: /* NEG ind */ - DAR = get_indir_addr(); - lo = (0 - CPU_BD_get_mbyte(DAR)) & 0xFF; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_V(lo & 0x80); - COND_SET_FLAG(lo,CF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x63: /* COM ind */ - DAR = get_indir_addr(); - lo = ~CPU_BD_get_mbyte(DAR); - lo &= 0xFF; - CPU_BD_put_mbyte(DAR, lo); - CLR_FLAG(VF); - SET_FLAG(CF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x64: /* LSR ind */ - DAR = get_indir_addr(); - lo = CPU_BD_get_mbyte(DAR); - COND_SET_FLAG(lo & 0x01,CF); - lo >>= 1; - CPU_BD_put_mbyte(DAR, lo); - CLR_FLAG(NF); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x66: /* ROR ind */ - DAR = get_indir_addr(); - lo = CPU_BD_get_mbyte(DAR); - hi = get_flag(CF); - COND_SET_FLAG(lo & 0x01,CF); - lo >>= 1; - if (hi) - lo |= 0x80; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x67: /* ASR ind */ - DAR = get_indir_addr(); - lo = CPU_BD_get_mbyte(DAR); - COND_SET_FLAG(lo & 0x01,CF); - lo = (lo & 0x80) | (lo >> 1); - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x68: /* ASL ind */ - DAR = get_indir_addr(); - lo = CPU_BD_get_mbyte(DAR); - COND_SET_FLAG(lo & 0x80,CF); - lo <<= 1; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x69: /* ROL ind */ - DAR = get_indir_addr(); - lo = CPU_BD_get_mbyte(DAR); - hi = get_flag(CF); - COND_SET_FLAG(lo & 0x80,CF); - lo <<= 1; - if (hi) - lo |= 0x01; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x6A: /* DEC ind */ - DAR = get_indir_addr(); - lo = CPU_BD_get_mbyte(DAR); - COND_SET_FLAG_V(lo == 0x80); - lo = (lo - 1) & 0xFF; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x6C: /* INC ind */ - DAR= get_indir_addr(); - lo = CPU_BD_get_mbyte(DAR); - COND_SET_FLAG_V(lo == 0x7F); - lo = (lo + 1) & 0xFF; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x6D: /* TST ind */ - lo = (get_indir_val() - 0) & 0xFF; - CLR_FLAG(VF); - CLR_FLAG(CF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x6E: /* JMP ind */ - PC = get_indir_addr(); - break; - case 0x6F: /* CLR ind */ - CPU_BD_put_mbyte(get_indir_addr(), 0); - CLR_FLAG(NF); - CLR_FLAG(VF); - CLR_FLAG(CF); - SET_FLAG(ZF); - break; - case 0x70: /* NEG ext */ - DAR = get_ext_addr(); - lo = (0 - CPU_BD_get_mbyte(DAR)) & 0xFF; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_V(lo & 0x80); - CLR_FLAG(CF); - if (lo) - SET_FLAG(CF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x73: /* COM ext */ - DAR = get_ext_addr(); - lo = ~CPU_BD_get_mbyte(DAR); - lo &= 0xFF; - CPU_BD_put_mbyte(DAR, lo); - CLR_FLAG(VF); - SET_FLAG(CF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x74: /* LSR ext */ - DAR = get_ext_addr(); - lo = CPU_BD_get_mbyte(DAR); - COND_SET_FLAG(lo & 0x01,CF); - lo >>= 1; - CPU_BD_put_mbyte(DAR, lo); - CLR_FLAG(NF); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x76: /* ROR ext */ - DAR = get_ext_addr(); - hi = get_flag(CF); - lo = CPU_BD_get_mbyte(DAR); - COND_SET_FLAG(lo & 0x01,CF); - lo >>= 1; - if (hi) - lo |= 0x80; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x77: /* ASR ext */ - DAR = get_ext_addr(); - lo = CPU_BD_get_mbyte(DAR); - COND_SET_FLAG(lo & 0x01,CF); - hi = lo & 0x80; - lo >>= 1; - lo |= hi; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x78: /* ASL ext */ - DAR = get_ext_addr(); - lo = CPU_BD_get_mbyte(DAR); - COND_SET_FLAG(lo & 0x80,CF); - lo <<= 1; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x79: /* ROL ext */ - DAR = get_ext_addr(); - lo = CPU_BD_get_mbyte(DAR); - hi = get_flag(CF); - COND_SET_FLAG(lo & 0x80,CF); - lo <<= 1; - if (hi) - lo |= 0x01; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF)); - break; - case 0x7A: /* DEC ext */ - DAR = get_ext_addr(); - lo = CPU_BD_get_mbyte(DAR); - COND_SET_FLAG_V(lo == 0x80); - lo = (lo - 1) & 0xFF; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x7C: /* INC ext */ - DAR = get_ext_addr(); - lo = CPU_BD_get_mbyte(DAR); - COND_SET_FLAG_V(lo == 0x7F); - lo = (lo + 1) & 0xFF; - CPU_BD_put_mbyte(DAR, lo); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x7D: /* TST ext */ - lo = CPU_BD_get_mbyte(get_ext_addr()) - 0; - CLR_FLAG(VF); - CLR_FLAG(CF); - COND_SET_FLAG_N(lo); - lo &= 0xFF; - COND_SET_FLAG_Z(lo); - break; - case 0x7E: /* JMP ext */ - PC = get_ext_addr() & ADDRMASK; - break; - case 0x7F: /* CLR ext */ - CPU_BD_put_mbyte(get_ext_addr(), 0); - CLR_FLAG(NF); - CLR_FLAG(VF); - CLR_FLAG(CF); - SET_FLAG(ZF); - break; - case 0x80: /* SUB A imm */ - op1 = get_dir_addr(); - A = A - op1; - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVs(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0x81: /* CMP A imm */ - op1 = get_dir_addr(); - lo = A - op1; - COND_SET_FLAG_N(lo); - COND_SET_FLAG_C(lo); - condevalVs(lo, op1); - lo &= 0xFF; - COND_SET_FLAG_Z(lo); - break; - case 0x82: /* SBC A imm */ - op1 = get_dir_addr(); - A = A - op1 - get_flag(CF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVs(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0x84: /* AND A imm */ - A = (A & get_dir_addr()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x85: /* BIT A imm */ - lo = (A & get_dir_addr()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x86: /* LDA A imm */ - A = get_dir_addr(); - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x88: /* EOR A imm */ - A = (A ^ get_dir_addr()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x89: /* ADC A imm */ - op1 = get_dir_addr(); - A = A + op1 + get_flag(CF); - COND_SET_FLAG_H(A); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVa(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0x8A: /* ORA A imm */ - A = (A | get_dir_addr()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x8B: /* ADD A imm */ - op1 = get_dir_addr(); - A = A + op1; - COND_SET_FLAG_H(A); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVa(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0x8C: /* CPX imm */ - op1 = IX - get_ext_addr(); - COND_SET_FLAG_Z(op1); - COND_SET_FLAG_N(op1 >> 8); - COND_SET_FLAG_V(op1 & 0x10000); - break; - case 0x8D: /* BSR rel */ - lo = get_rel_addr(); - push_word(PC); - PC = PC + lo; - PC &= ADDRMASK; - break; - case 0x8E: /* LDS imm */ - SP = get_ext_addr(); - COND_SET_FLAG_N(SP >> 8); - COND_SET_FLAG_Z(SP); - CLR_FLAG(VF); - break; - case 0x90: /* SUB A dir */ - op1 = get_dir_val(); - A = A - op1; - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVs(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0x91: /* CMP A dir */ - op1 = get_dir_val(); - lo = A - op1; - COND_SET_FLAG_N(lo); - COND_SET_FLAG_C(lo); - condevalVs(A, op1); - lo &= 0xFF; - COND_SET_FLAG_Z(lo); - break; - case 0x92: /* SBC A dir */ - op1 = get_dir_val(); - A = A - op1 - get_flag(CF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVs(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0x94: /* AND A dir */ - A = (A & get_dir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x95: /* BIT A dir */ - lo = (A & get_dir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0x96: /* LDA A dir */ - A = get_dir_val(); - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x97: /* STA A dir */ - CPU_BD_put_mbyte(get_dir_addr(), A); - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x98: /* EOR A dir */ - A = (A ^ get_dir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x99: /* ADC A dir */ - op1 = get_dir_val(); - A = A + op1 + get_flag(CF); - COND_SET_FLAG_H(A); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVa(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0x9A: /* ORA A dir */ - A = (A | get_dir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0x9B: /* ADD A dir */ - op1 = get_dir_val(); - A = A + op1; - COND_SET_FLAG_H(A); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVa(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0x9C: /* CPX dir */ - op1 = IX - CPU_BD_get_mword(get_dir_addr()); - COND_SET_FLAG_Z(op1); - COND_SET_FLAG_N(op1 >> 8); - COND_SET_FLAG_V(op1 & 0x10000); - break; - case 0x9E: /* LDS dir */ - SP = CPU_BD_get_mword(get_dir_addr()); - COND_SET_FLAG_N(SP >> 8); - COND_SET_FLAG_Z(SP); - CLR_FLAG(VF); - break; - case 0x9F: /* STS dir */ - CPU_BD_put_mword(get_dir_addr(), SP); - COND_SET_FLAG_N(SP >> 8); - COND_SET_FLAG_Z(SP); - CLR_FLAG(VF); - break; - case 0xA0: /* SUB A ind */ - op1 = get_indir_val(); - A = A - op1; - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVs(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0xA1: /* CMP A ind */ - op1 = get_indir_val(); - lo = A - op1; - COND_SET_FLAG_N(lo); - COND_SET_FLAG_C(lo); - condevalVs(A, op1); - lo &= 0xFF; - COND_SET_FLAG_Z(lo); - break; - case 0xA2: /* SBC A ind */ - op1 = get_indir_val(); - A = A - op1 - get_flag(CF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVs(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0xA4: /* AND A ind */ - A = (A & get_indir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0xA5: /* BIT A ind */ - lo = (A & get_indir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0xA6: /* LDA A ind */ - A = get_indir_val(); - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0xA7: /* STA A ind */ - CPU_BD_put_mbyte(get_indir_addr(), A); - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0xA8: /* EOR A ind */ - A = (A ^ get_indir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0xA9: /* ADC A ind */ - op1 = get_indir_val(); - A = A + op1 + get_flag(CF); - COND_SET_FLAG_H(A); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVa(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0xAA: /* ORA A ind */ - A = (A | get_indir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0xAB: /* ADD A ind */ - op1 = get_indir_val(); - A = A + op1; - COND_SET_FLAG_H(A); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVa(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0xAC: /* CPX ind */ - op1 = (IX - get_indir_addr()) & ADDRMASK; - COND_SET_FLAG_Z(op1); - COND_SET_FLAG_N(op1 >> 8); - COND_SET_FLAG_V(op1 & 0x10000); - break; - case 0xAD: /* JSR ind */ - DAR = get_indir_addr(); - push_word(PC); - PC = DAR; - break; - case 0xAE: /* LDS ind */ - SP = CPU_BD_get_mword(get_indir_addr()); - COND_SET_FLAG_N(SP >> 8); - COND_SET_FLAG_Z(SP); - CLR_FLAG(VF); - break; - case 0xAF: /* STS ind */ - CPU_BD_put_mword(get_indir_addr(), SP); - COND_SET_FLAG_N(SP >> 8); - COND_SET_FLAG_Z(SP); - CLR_FLAG(VF); - break; - case 0xB0: /* SUB A ext */ - op1 = get_ext_val(); - A = A - op1; - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVs(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0xB1: /* CMP A ext */ - op1 = get_ext_val(); - lo = A - op1; - COND_SET_FLAG_N(lo); - COND_SET_FLAG_C(lo); - condevalVs(A, op1); - lo &= 0xFF; - COND_SET_FLAG_Z(lo); - break; - case 0xB2: /* SBC A ext */ - op1 = get_ext_val(); - A = A - op1 - get_flag(CF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVs(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0xB4: /* AND A ext */ - A = (A & get_ext_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0xB5: /* BIT A ext */ - lo = (A & get_ext_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0xB6: /* LDA A ext */ - A = get_ext_val(); - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0xB7: /* STA A ext */ - CPU_BD_put_mbyte(get_ext_addr(), A); - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0xB8: /* EOR A ext */ - A = (A ^ get_ext_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0xB9: /* ADC A ext */ - op1 = get_ext_val(); - A = A + op1 + get_flag(CF); - COND_SET_FLAG_H(A); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVa(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0xBA: /* ORA A ext */ - A = (A | get_ext_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(A); - COND_SET_FLAG_Z(A); - break; - case 0xBB: /* ADD A ext */ - op1 = get_ext_val(); - A = A + op1; - COND_SET_FLAG_H(A); - COND_SET_FLAG_N(A); - COND_SET_FLAG_C(A); - condevalVa(A, op1); - A &= 0xFF; - COND_SET_FLAG_Z(A); - break; - case 0xBC: /* CPX ext */ - op1 = (IX - CPU_BD_get_mword(get_ext_addr()));// & ADDRMASK; - COND_SET_FLAG_Z(op1); - COND_SET_FLAG_N(op1 >> 8); - COND_SET_FLAG_V(op1 & 0x10000); - break; - case 0xBD: /* JSR ext */ - DAR = get_ext_addr(); - push_word(PC); - PC = DAR; - break; - case 0xBE: /* LDS ext */ - SP = CPU_BD_get_mword(get_ext_addr()); - COND_SET_FLAG_N(SP >> 8); - COND_SET_FLAG_Z(SP); - CLR_FLAG(VF); - break; - case 0xBF: /* STS ext */ - CPU_BD_put_mword(get_ext_addr(), SP); - COND_SET_FLAG_N(SP >> 8); - COND_SET_FLAG_Z(SP); - CLR_FLAG(VF); - break; - case 0xC0: /* SUB B imm */ - op1 = get_dir_addr(); - B = B - op1; - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVs(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xC1: /* CMP B imm */ - op1 = get_dir_addr(); - lo = B - op1; - COND_SET_FLAG_N(lo); - COND_SET_FLAG_C(lo); - condevalVs(B, op1); - lo &= 0xFF; - COND_SET_FLAG_Z(lo); - break; - case 0xC2: /* SBC B imm */ - op1 = get_dir_addr(); - B = B - op1 - get_flag(CF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVs(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xC4: /* AND B imm */ - B = (B & get_dir_addr()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xC5: /* BIT B imm */ - lo = (B & get_dir_addr()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0xC6: /* LDA B imm */ - B = get_dir_addr(); - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xC8: /* EOR B imm */ - B = (B ^ get_dir_addr()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xC9: /* ADC B imm */ - op1 = get_dir_addr(); - B = B + op1 + get_flag(CF); - COND_SET_FLAG_H(B); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVa(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xCA: /* ORA B imm */ - B = (B | get_dir_addr()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xCB: /* ADD B imm */ - op1 = get_dir_addr(); - B = B + op1; - COND_SET_FLAG_H(B); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVa(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xCE: /* LDX imm */ - IX = get_ext_addr(); - COND_SET_FLAG_N(IX >> 8); - COND_SET_FLAG_Z(IX); - CLR_FLAG(VF); - break; - case 0xD0: /* SUB B dir */ - op1 = get_dir_val(); - B = B - op1; - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVs(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xD1: /* CMP B dir */ - op1 = get_dir_val(); - lo = B - op1; - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - COND_SET_FLAG_C(lo); - condevalVs(B, op1); - break; - case 0xD2: /* SBC B dir */ - op1 = get_dir_val(); - B = B - op1 - get_flag(CF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVs(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xD4: /* AND B dir */ - B = (B & get_dir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xD5: /* BIT B dir */ - lo = (B & get_dir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0xD6: /* LDA B dir */ - B = get_dir_val(); - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xD7: /* STA B dir */ - CPU_BD_put_mbyte(get_dir_addr(), B); - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xD8: /* EOR B dir */ - B = (B ^ get_dir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xD9: /* ADC B dir */ - op1 = get_dir_val(); - B = B + op1 + get_flag(CF); - COND_SET_FLAG_H(B); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVa(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xDA: /* ORA B dir */ - B = (B | get_dir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xDB: /* ADD B dir */ - op1 = get_dir_val(); - B = B + op1; - COND_SET_FLAG_H(B); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVa(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xDE: /* LDX dir */ - IX = CPU_BD_get_mword(get_dir_addr()); - COND_SET_FLAG_N(IX >> 8); - COND_SET_FLAG_Z(IX); - CLR_FLAG(VF); - break; - case 0xDF: /* STX dir */ - CPU_BD_put_mword(get_dir_addr(), IX); - COND_SET_FLAG_N(IX >> 8); - COND_SET_FLAG_Z(IX); - CLR_FLAG(VF); - break; - case 0xE0: /* SUB B ind */ - op1 = get_indir_val(); - B = B - op1; - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVs(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xE1: /* CMP B ind */ - op1 = get_indir_val(); - lo = B - op1; - COND_SET_FLAG_N(lo); - COND_SET_FLAG_C(lo); - condevalVs(B, op1); - lo &= 0xFF; - COND_SET_FLAG_Z(lo); - break; - case 0xE2: /* SBC B ind */ - op1 = get_indir_val(); - B = B - op1 - get_flag(CF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVs(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xE4: /* AND B ind */ - B = (B & get_indir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xE5: /* BIT B ind */ - lo = (B & get_indir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0xE6: /* LDA B ind */ - B = get_indir_val(); - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xE7: /* STA B ind */ - CPU_BD_put_mbyte(get_indir_addr(), B); - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xE8: /* EOR B ind */ - B = (B ^ get_indir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xE9: /* ADC B ind */ - op1 = get_indir_val(); - B = B + op1 + get_flag(CF); - COND_SET_FLAG_H(B); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVa(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xEA: /* ORA B ind */ - B = (B | get_indir_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xEB: /* ADD B ind */ - op1 = get_indir_val(); - B = B + op1; - COND_SET_FLAG_H(B); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVa(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xEE: /* LDX ind */ - IX = CPU_BD_get_mword(get_indir_addr()); - COND_SET_FLAG_N(IX >> 8); - COND_SET_FLAG_Z(IX); - CLR_FLAG(VF); - break; - case 0xEF: /* STX ind */ - CPU_BD_put_mword(get_indir_addr(), IX); - COND_SET_FLAG_N(IX >> 8); - COND_SET_FLAG_Z(IX); - CLR_FLAG(VF); - break; - case 0xF0: /* SUB B ext */ - op1 = get_ext_val(); - B = B - op1; - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVs(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xF1: /* CMP B ext */ - op1 = get_ext_val(); - lo = B - op1; - COND_SET_FLAG_N(lo); - COND_SET_FLAG_C(lo); - condevalVs(B, op1); - lo &= 0xFF; - COND_SET_FLAG_Z(lo); - break; - case 0xF2: /* SBC B ext */ - op1 = get_ext_val(); - B = B - op1 - get_flag(CF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVs(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xF4: /* AND B ext */ - B = (B & get_ext_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xF5: /* BIT B ext */ - lo = (B & get_ext_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(lo); - COND_SET_FLAG_Z(lo); - break; - case 0xF6: /* LDA B ext */ - B = get_ext_val(); - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xF7: /* STA B ext */ - CPU_BD_put_mbyte(get_ext_addr(), B); - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xF8: /* EOR B ext */ - B = (B ^ get_ext_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xF9: /* ADC B ext */ - op1 = get_ext_val(); - B = B + op1 + get_flag(CF); - COND_SET_FLAG_H(B); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVa(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xFA: /* ORA B ext */ - B = (B | get_ext_val()) & 0xFF; - CLR_FLAG(VF); - COND_SET_FLAG_N(B); - COND_SET_FLAG_Z(B); - break; - case 0xFB: /* ADD B ext */ - op1 = get_ext_val(); - B = B + op1; - COND_SET_FLAG_H(B); - COND_SET_FLAG_N(B); - COND_SET_FLAG_C(B); - condevalVa(B, op1); - B &= 0xFF; - COND_SET_FLAG_Z(B); - break; - case 0xFE: /* LDX ext */ - IX = CPU_BD_get_mword(get_ext_addr()); - COND_SET_FLAG_N(IX >> 8); - COND_SET_FLAG_Z(IX); - CLR_FLAG(VF); - break; - case 0xFF: /* STX ext */ - CPU_BD_put_mword(get_ext_addr(), IX); - COND_SET_FLAG_N(IX >> 8); - COND_SET_FLAG_Z(IX); - CLR_FLAG(VF); - break; - - default: { /* Unassigned */ - if (m6800_unit.flags & UNIT_OPSTOP) { - reason = STOP_OPCODE; - PC--; - } - break; - } - } - } - /* Simulation halted - lets dump all the registers! */ - dump_regs(); - saved_PC = PC; - return reason; -} - -/* dump the working registers */ - -void dump_regs(void) -{ - printf("\r\nPC=%04X SP=%04X IX=%04X ", PC, SP, IX); - printf("A=%02X B=%02X CCR=%02X", A, B, CCR); -} - -void dump_regs1(void) -{ - printf("PC=%04X SP=%04X IX=%04X ", PC, SP, IX); - printf("A=%02X B=%02X CCR=%02X\n", A, B, CCR); -} - -/* fetch an instruction or byte */ -int32 fetch_byte(int32 flag) -{ - uint8 val; - - val = CPU_BD_get_mbyte(PC) & 0xFF; /* fetch byte */ - if (m6800_dev.dctrl & DEBUG_asm) { /* display source code */ - switch (flag) { - case 0: /* opcode fetch */ - printf("\n%04X %s", PC, opcode[val]); - break; - case 1: /* byte operand fetch */ - printf("0%02XH", val); - break; - } - } - PC = (PC + 1) & ADDRMASK; /* increment PC */ - return val; -} - -/* fetch a word */ -int32 fetch_word(void) -{ - uint16 val; - - val = CPU_BD_get_mbyte(PC) << 8; /* fetch high byte */ - val |= CPU_BD_get_mbyte(PC + 1) & 0xFF; /* fetch low byte */ - if (m6800_dev.dctrl & DEBUG_asm) - printf("0%04XH", val); - PC = (PC + 2) & ADDRMASK; /* increment PC */ - return val; -} - -/* push a byte to the stack */ -void push_byte(uint8 val) -{ - CPU_BD_put_mbyte(SP, val & 0xFF); - SP = (SP - 1) & ADDRMASK; -} - -/* push a word to the stack */ -void push_word(uint16 val) -{ - push_byte(val & 0xFF); - push_byte(val >> 8); -} - -/* pop a byte from the stack */ -uint8 pop_byte(void) -{ - register uint8 res; - - SP = (SP + 1) & ADDRMASK; - res = CPU_BD_get_mbyte(SP); - return res; -} - -/* pop a word from the stack */ -uint16 pop_word(void) -{ - register uint16 res; - - res = pop_byte() << 8; - res |= pop_byte(); - return res; -} - -/* this routine does the jump to relative offset if the condition is - met. Otherwise, execution continues at the current PC. */ - -void go_rel(int32 cond) -{ - int32 temp; - - temp = get_rel_addr(); - if (cond) - PC += temp; - PC &= ADDRMASK; -} - -/* returns the relative offset sign-extended */ - -int32 get_rel_addr(void) -{ - int32 temp; - - temp = fetch_byte(1); - if (temp & 0x80) - temp |= 0xFF00; - return temp & ADDRMASK; -} - -/* returns the value at the direct address pointed to by PC */ - -int32 get_dir_val(void) -{ - return CPU_BD_get_mbyte(get_dir_addr()); -} - -/* returns the direct address pointed to by PC */ - -int32 get_dir_addr(void) -{ - int32 temp; - - temp = fetch_byte(1); - return temp & 0xFF; -} - -/* returns the value at the indirect address pointed to by PC */ - -int32 get_indir_val(void) -{ - return CPU_BD_get_mbyte(get_indir_addr()); -} - -/* returns the indirect address pointed to by PC or immediate byte */ - -int32 get_indir_addr(void) -{ - int32 temp; - - temp = (fetch_byte(1) + IX) & ADDRMASK; - return temp; -} - -/* returns the value at the extended address pointed to by PC */ - -int32 get_ext_val(void) -{ - return CPU_BD_get_mbyte(get_ext_addr()); -} - -/* returns the extended address pointed to by PC or immediate word */ - -int32 get_ext_addr(void) -{ - int32 temp; - - temp = fetch_word(); - return temp; -} - -/* return 1 for flag set or 0 for flag clear */ - -int32 get_flag(int32 flg) -{ - if (CCR & flg) - return 1; - else - return 0; -} - -/* test and set V for addition */ - -void condevalVa(int32 op1, int32 op2) -{ - if (get_flag(CF)) { - COND_SET_FLAG_V((op1 & op2 & 0x80) || (((op1 | op2) & 0x80) == 0)); - } -} - -/* test and set V for subtraction */ - -void condevalVs(int32 op1, int32 op2) -{ - if (get_flag(CF)) { - COND_SET_FLAG_V(op1 & op2 & 0x80); - } -} - -/* calls from the simulator */ - -/* Reset routine */ - -t_stat m6800_reset (DEVICE *dptr) -{ - CCR = CCR_ALWAYS_ON | IF; - int_req = 0; - sim_brk_types = sim_brk_dflt = SWMASK ('E'); - saved_PC = CPU_BD_get_mword(0xFFFE); -// if (saved_PC == 0xFFFF) -// printf("No EPROM image found - M6800 reset incomplete!\n"); -// else -// printf("EPROM vector=%04X\n", saved_PC); - return SCPE_OK; -} - - -/* This is the dumper/loader. This command uses the -h to signify a - hex dump/load vice a binary one. If no address is given to load, it - takes the address from the hex record or the current PC for binary. -*/ - -t_stat 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) { - CPU_BD_put_mbyte(addr, i); - addr++; - cnt++; - } // end while - 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 - for M6800 -*/ - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) -{ - int32 i, inst, inst1; - - if (sw & SWMASK ('D')) { // dump memory - for (i=0; i<16; i++) - fprintf(of, "%02X ", val[i]); - fprintf(of, " "); - for (i=0; i<16; i++) - if (isprint(val[i])) - fprintf(of, "%c", val[i]); - else - fprintf(of, "."); - return -15; - } else if (sw & SWMASK ('M')) { // dump instruction mnemonic - inst = val[0]; - if (!oplen[inst]) { // invalid opcode - fprintf(of, "%02X", inst); - return 0; - } - inst1 = inst & 0xF0; - fprintf (of, "%s", opcode[inst]); // mnemonic - if (strlen(opcode[inst]) == 3) - fprintf(of, " "); - if (inst1 == 0x20 || inst == 0x8D) { // rel operand - inst1 = val[1]; - if (val[1] & 0x80) - inst1 |= 0xFF00; - fprintf(of, " $%04X", (addr + inst1 + 2) & ADDRMASK); - } else if (inst1 == 0x80 || inst1 == 0xC0) { // imm operand - if ((inst & 0x0F) < 0x0C) - fprintf(of, " #$%02X", val[1]); - else - fprintf(of, " #$%02X%02X", val[1], val[2]); - } else if (inst1 == 0x60 || inst1 == 0xA0 || inst1 == 0xE0) // ind operand - fprintf(of, " %d,X", val[1]); - else if (inst1 == 0x70 || inst1 == 0xb0 || inst1 == 0xF0) // ext operand - fprintf(of, " $%02X%02X", val[1], val[2]); - return (-(oplen[inst] - 1)); - } else - return SCPE_ARG; -} - -/* 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) -{ - return (-2); -} - -/* end of m6800.c */ diff --git a/swtp6800/common/m6810.c b/swtp6800/common/m6810.c deleted file mode 100644 index 3bb5660a..00000000 --- a/swtp6800/common/m6810.c +++ /dev/null @@ -1,146 +0,0 @@ -/* m6810.c: Motorola m6810 RAM emulator - - 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 m6810 RAM device on a CPU board. The - byte get and put routines use an offset into the RAM image to locate the - proper byte. This allows another device to set the base address for the - M6810. -*/ - -#include -#include "swtp_defs.h" - -/* function prototypes */ - -t_stat m6810_reset (DEVICE *dptr); -int32 m6810_get_mbyte(int32 offset); -void m6810_put_mbyte(int32 offset, int32 val); - -/* SIMH RAM Standard I/O Data Structures */ - -UNIT m6810_unit = { UDATA (NULL, UNIT_BINK, 128), - 0 }; - -MTAB m6810_mod[] = { - { 0 } -}; - -DEBTAB m6810_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE m6810_dev = { - "M6810", //name - &m6810_unit, //units - NULL, //registers - m6810_mod, //modifiers - 1, //numunits - 16, //aradix - 32, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - &m6810_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - m6810_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* global variables */ - -/* m6810_reset */ - -t_stat m6810_reset (DEVICE *dptr) -{ - if (m6810_dev.dctrl & DEBUG_flow) - printf("m6810_reset: \n"); - if (m6810_unit.filebuf == NULL) { - m6810_unit.filebuf = malloc(128); - if (m6810_unit.filebuf == NULL) { - printf("m6810_reset: Malloc error\n"); - return SCPE_MEM; - } - m6810_unit.capac = 128; - } - if (m6810_dev.dctrl & DEBUG_flow) - printf("m6810_reset: Done\n"); - return SCPE_OK; -} - -/* I/O instruction handlers, called from the CPU module when an - RAM memory read or write is issued. -*/ - -/* get a byte from memory - from offset from start of RAM*/ - -int32 m6810_get_mbyte(int32 offset) -{ - int32 val; - - if (m6810_dev.dctrl & DEBUG_read) - printf("m6810_get_mbyte: offset=%04X\n", offset); - if (((t_addr)offset) < m6810_unit.capac) { - val = *((uint8 *)(m6810_unit.filebuf) + offset) & 0xFF; - if (m6810_dev.dctrl & DEBUG_read) - printf("val=%04X\n", val); - return val; - } else { - if (m6810_dev.dctrl & DEBUG_read) - printf("m6810_get_mbyte: out of range\n"); - return 0xFF; - } -} - -/* put a byte to memory */ - -void m6810_put_mbyte(int32 offset, int32 val) -{ - if (m6810_dev.dctrl & DEBUG_write) - printf("m6810_put_mbyte: offset=%04X, val=%02X\n", offset, val); - if ((t_addr)offset < m6810_unit.capac) { - *((uint8 *)(m6810_unit.filebuf) + offset) = val & 0xFF; - return; - } else { - if (m6810_dev.dctrl & DEBUG_write) - printf("m6810_put_mbyte: out of range\n"); - return; - } -} - -/* end of m6810.c */ diff --git a/swtp6800/common/mp-8m.c b/swtp6800/common/mp-8m.c deleted file mode 100644 index 9126b05a..00000000 --- a/swtp6800/common/mp-8m.c +++ /dev/null @@ -1,209 +0,0 @@ -/* mp-8m.c: SWTP 8K Byte Memory Card emulator - - 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 6 simulated MP-8M memory cards on an SS-50 system. - - Each unit uses a dynamically allocated 8192 byte buffer to hold the data. - Each unit contains the base address in mp_8m_unit.u3. The unit capacity is - held in mp_8m_unit.capac. Each unit can be enabled or disabled to reconfigure - the RAM for the system. -*/ - -#include -#include "swtp_defs.h" - -#define MP_8M_NUM 6 /* number of MP-*m boards */ - -/* prototypes */ - -t_stat mp_8m_reset (DEVICE *dptr); -int32 mp_8m_get_mbyte(int32 addr); -int32 mp_8m_get_mword(int32 addr); -void mp_8m_put_mbyte(int32 addr, int32 val); -void mp_8m_put_mword(int32 addr, int32 val); - -/* isbc064 Standard I/O Data Structures */ - -UNIT mp_8m_unit[] = { - { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 }, - { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 }, - { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 }, - { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 }, - { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 }, - { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_DISABLE, 0),0 } -}; - -MTAB mp_8m_mod[] = { - { 0 } -}; - -DEBTAB mp_8m_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE mp_8m_dev = { - "MP-8M", //name - mp_8m_unit, //units - NULL, //registers - mp_8m_mod, //modifiers - MP_8M_NUM, //numunits - 16, //aradix - 8, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposite - &mp_8m_reset, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - mp_8m_debug, //debflags - NULL, //msize - NULL //lname -}; - -/* Reset routine */ - -t_stat mp_8m_reset (DEVICE *dptr) -{ - int32 i, j, val; - UNIT *uptr; - - if (mp_8m_dev.dctrl & DEBUG_flow) - printf("mp_8m_reset: \n"); - for (i = 0; i < MP_8M_NUM; i++) { /* init all units */ - uptr = mp_8m_dev.units + i; - if (mp_8m_dev.dctrl & DEBUG_flow) - printf("MP-8M %d unit.flags=%08X\n", i, uptr->flags); - uptr->capac = 0x2000; - if (i < 4) - uptr->u3 = 0x2000 * i; - else - uptr->u3 = 0x2000 * (i + 1); - if (uptr->filebuf == NULL) { - uptr->filebuf = malloc(0x2000); - if (uptr->filebuf == NULL) { - printf("mp_8m_reset: Malloc error\n"); - return SCPE_MEM; - } - for (j=0; j<8192; j++) { /* fill pattern for testing */ - val = (0xA0 | i); - *((uint8 *)(uptr->filebuf) + j) = val & 0xFF; - } - } - if (mp_8m_dev.dctrl & DEBUG_flow) - printf("MP-8M %d initialized at [%04X-%04XH]\n", i, uptr->u3, - uptr->u3 + uptr->capac - 1); - } - if (mp_8m_dev.dctrl & DEBUG_flow) - printf("mp_8m_reset: Done\n"); - return SCPE_OK; -} - -/* I/O instruction handlers, called from the mp-b2 module when an - external memory read or write is issued. -*/ - -/* get a byte from memory */ - -int32 mp_8m_get_mbyte(int32 addr) -{ - int32 val, org, len; - int32 i; - UNIT *uptr; - - if (mp_8m_dev.dctrl & DEBUG_read) - printf("mp_8m_get_mbyte: addr=%04X", addr); - for (i = 0; i < MP_8M_NUM; i++) { /* find addressed unit */ - uptr = mp_8m_dev.units + i; - org = uptr->u3; - len = uptr->capac - 1; - if ((addr >= org) && (addr <= org + len)) { - val = *((uint8 *)(uptr->filebuf) + (addr - org)); - if (mp_8m_dev.dctrl & DEBUG_read) - printf(" val=%04X\n", val); - return (val & 0xFF); - } - } - if (mp_8m_dev.dctrl & DEBUG_read) - printf("mp_8m_get_mbyte: Out of range\n"); - return 0xFF; /* multibus has active high pullups */ -} - -/* get a word from memory */ - -int32 mp_8m_get_mword(int32 addr) -{ - int32 val; - - val = (mp_8m_get_mbyte(addr) << 8); - val |= mp_8m_get_mbyte(addr+1); - return val; -} - -/* put a byte into memory */ - -void mp_8m_put_mbyte(int32 addr, int32 val) -{ - int32 org, len; - int32 i; - UNIT *uptr; - - if (mp_8m_dev.dctrl & DEBUG_write) - printf("mp_8m_put_mbyte: addr=%04X, val=%02X", addr, val); - for (i = 0; i < MP_8M_NUM; i++) { /* find addressed unit */ - uptr = mp_8m_dev.units + i; - org = uptr->u3; - len = uptr->capac - 1; - if ((addr >= org) && (addr < org + len)) { - *((uint8 *)(uptr->filebuf) + (addr - org)) = val & 0xFF; - if (mp_8m_dev.dctrl & DEBUG_write) - printf("\n"); - return; - } - } - if (mp_8m_dev.dctrl & DEBUG_write) - printf("mp_8m_put_mbyte: Out of range\n"); -} - -/* put a word into memory */ - -void mp_8m_put_mword(int32 addr, int32 val) -{ - mp_8m_put_mbyte(addr, val >> 8); - mp_8m_put_mbyte(addr+1, val); -} - -/* end of mp-8m.c */ diff --git a/swtp6800/common/mp-a.c b/swtp6800/common/mp-a.c deleted file mode 100644 index 6dd77509..00000000 --- a/swtp6800/common/mp-a.c +++ /dev/null @@ -1,211 +0,0 @@ -/* mp-a.c: SWTP MP-A M6800 CPU simulator - - Copyright (c) 2011, William 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. - - The MP-A CPU Board contains the following devices [mp-a.c]: - M6800 processor [m6800.c]. - M6810 128 byte RAM at 0xA000 [m6810.c]. - M6830, SWTBUG, or custom boot ROM at 0xE000 [bootrom.c]. - Interface to the SS-50 bus and the MP-B2 Mother Board for I/O - and memory boards [mp-b2.c]. - Note: The file names of the emulator source programs for each device are - contained in "[]". -*/ - -#include -#include "swtp_defs.h" - -#define UNIT_V_SWT (UNIT_V_UF) /* on SWTBUG, off MIKBUG */ -#define UNIT_SWT (1 << UNIT_V_SWT) -#define UNIT_V_RAM (UNIT_V_UF+1) /* off disables 6810 RAM */ -#define UNIT_RAM (1 << UNIT_V_RAM) - -/* local global variables */ - -/* function prototypes */ - -int32 CPU_BD_get_mbyte(int32 addr); -int32 CPU_BD_get_mword(int32 addr); -void CPU_BD_put_mbyte(int32 addr, int32 val); -void CPU_BD_put_mword(int32 addr, int32 val); - -/* external routines */ - -/* MP-B2 bus routines */ -extern int32 MB_get_mbyte(int32 addr); -extern int32 MB_get_mword(int32 addr); -extern void MB_put_mbyte(int32 addr, int32 val); -extern void MB_put_mword(int32 addr, int32 val); - -/* M6810 bus routines */ -extern int32 m6810_get_mbyte(int32 addr); -extern void m6810_put_mbyte(int32 addr, int32 val); - -/* BOOTROM bus routines */ -extern UNIT BOOTROM_unit; -extern int32 BOOTROM_get_mbyte(int32 offset); - -/* MP-A data structures - - CPU_BD_dev MP-A2 device descriptor - CPU_BD_unit MP-A2 unit descriptor - CPU_BD_reg MP-A2 register list - CPU_BD_mod MP-A2 modifiers list */ - -UNIT CPU_BD_unit = { UDATA (NULL, 0, 0) }; - -REG CPU_BD_reg[] = { - { NULL } -}; - -MTAB CPU_BD_mod[] = { - { UNIT_SWT, UNIT_SWT, "SWT", "SWT", NULL }, - { UNIT_SWT, 0, "NOSWT", "NOSWT", NULL }, - { UNIT_RAM, UNIT_RAM, "RAM", "RAM", NULL }, - { UNIT_RAM, 0, "NORAM", "NORAM", NULL }, - { 0 } -}; - -DEBTAB CPU_BD_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE CPU_BD_dev = { - "MP-A", //name - &CPU_BD_unit, //units - CPU_BD_reg, //registers - CPU_BD_mod, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - CPU_BD_debug, /* debflags */ - NULL, //msize - NULL //lname -}; - -/* get a byte from memory */ - -int32 CPU_BD_get_mbyte(int32 addr) -{ - int32 val; - - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: addr=%04X\n", addr); - switch(addr & 0xF000) { - case 0xA000: - if (CPU_BD_unit.flags & UNIT_RAM) { - val = m6810_get_mbyte(addr - 0xA000) & 0xFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: m6810 val=%02X\n", val); - return val; - } else { - val = MB_get_mbyte(addr) & 0xFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: m6810 val=%02X\n", val); - return val; - } - case 0xE000: - val = BOOTROM_get_mbyte(addr - 0xE000) & 0xFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: EPROM=%02X\n", val); - return val; - case 0xF000: - val = BOOTROM_get_mbyte(addr - (0x10000 - BOOTROM_unit.capac)) & 0xFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: EPROM=%02X\n", val); - return val; - default: - val = MB_get_mbyte(addr) & 0xFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: mp_b2 val=%02X\n", val); - return val; - } -} - -/* get a word from memory */ - -int32 CPU_BD_get_mword(int32 addr) -{ - int32 val; - - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mword: addr=%04X\n", addr); - val = (CPU_BD_get_mbyte(addr) << 8); - val |= CPU_BD_get_mbyte(addr+1); - val &= 0xFFFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mword: val=%04X\n", val); - return val; -} - -/* put a byte to memory */ - -void CPU_BD_put_mbyte(int32 addr, int32 val) -{ - if (CPU_BD_dev.dctrl & DEBUG_write) - printf("CPU_BD_put_mbyte: addr=%04X, val=%02X\n", addr, val); - switch(addr & 0xF000) { - case 0xA000: - if (CPU_BD_unit.flags & UNIT_RAM) { - m6810_put_mbyte(addr - 0xA000, val); - return; - } else { - MB_put_mbyte(addr, val); - return; - } - default: - MB_put_mbyte(addr, val); - return; - } -} - -/* put a word to memory */ - -void CPU_BD_put_mword(int32 addr, int32 val) -{ - if (CPU_BD_dev.dctrl & DEBUG_write) - printf("CPU_BD_put_mword: addr=%04X, val=%04X\n", addr, val); - CPU_BD_put_mbyte(addr, val >> 8); - CPU_BD_put_mbyte(addr+1, val); -} - -/* end of mp-a.c */ diff --git a/swtp6800/common/mp-a2.c b/swtp6800/common/mp-a2.c deleted file mode 100644 index 21805dcb..00000000 --- a/swtp6800/common/mp-a2.c +++ /dev/null @@ -1,263 +0,0 @@ -/* mp-a2.c: SWTP MP-A2 M6800 CPU simulator - - Copyright (c) 2011, William 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. - - The MP-A2 CPU Board contains the following devices [mp-a2.c]: - M6800 processor [m6800.c]. - M6810 128 byte RAM at 0xA000 [m6810.c]. - M6830, SWTBUG, or custom boot ROM at 0xE000 [bootrom.c]. - 4 ea 2716 EPROMs at either 0xC000, 0xC800, 0xD000 and 0xD800 (LO_PROM)or - 0xE000, 0xE800, 0xF000 and 0xF800 (HI_PROM) [eprom.c]. - Interface to the SS-50 bus and the MP-B2 Mother Board for I/O - and memory boards [mp-b2.c]. - Note: The file names of the emulator source programs for each device are - contained in "[]". -*/ - -#include -#include "swtp_defs.h" - -#define UNIT_V_USER_D (UNIT_V_UF) /* user defined switch */ -#define UNIT_USER_D (1 << UNIT_V_USER_D) -#define UNIT_V_4K_8K (UNIT_V_UF+1) /* off if HI_PROM and only 2K EPROM */ -#define UNIT_4K_8K (1 << UNIT_V_4K_8K) -#define UNIT_V_SWT (UNIT_V_UF+2) /* on SWTBUG, off MIKBUG */ -#define UNIT_SWT (1 << UNIT_V_SWT) -#define UNIT_V_8K (UNIT_V_UF+3) /* off if HI_PROM and only 2K or 4k EPROM */ -#define UNIT_8K (1 << UNIT_V_8K) -#define UNIT_V_RAM (UNIT_V_UF+4) /* off disables 6810 RAM */ -#define UNIT_RAM (1 << UNIT_V_RAM) -#define UNIT_V_LO_PROM (UNIT_V_UF+5) /* on EPROMS @ C000-CFFFH, off no EPROMS */ -#define UNIT_LO_PROM (1 << UNIT_V_LO_PROM) -#define UNIT_V_HI_PROM (UNIT_V_UF+6) /* on EPROMS @ F000-FFFFH, off fo LO_PROM, MON, or no EPROMS */ -#define UNIT_HI_PROM (1 << UNIT_V_HI_PROM) -#define UNIT_V_MON (UNIT_V_UF+7) /* on for monitor vectors in high memory */ -#define UNIT_MON (1 << UNIT_V_MON) - -/* local global variables */ - -/* function prototypes */ - -int32 get_base(void); -int32 CPU_BD_get_mbyte(int32 addr); -int32 CPU_BD_get_mword(int32 addr); -void CPU_BD_put_mbyte(int32 addr, int32 val); -void CPU_BD_put_mword(int32 addr, int32 val); - -/* external routines */ - -/* MP-B2 bus routines */ -extern int32 MB_get_mbyte(int32 addr); -extern int32 MB_get_mword(int32 addr); -extern void MB_put_mbyte(int32 addr, int32 val); -extern void MB_put_mword(int32 addr, int32 val); - -/* M6810 bus routines */ -extern int32 m6810_get_mbyte(int32 addr); -extern void m6810_put_mbyte(int32 addr, int32 val); - -/* BOOTROM bus routines */ -extern UNIT BOOTROM_unit; -extern int32 BOOTROM_get_mbyte(int32 offset); - -/* I2716 bus routines */ -extern int32 i2716_get_mbyte(int32 offset); - -/* MP-A2 data structures - - CPU_BD_dev MP-A2 device descriptor - CPU_BD_unit MP-A2 unit descriptor - CPU_BD_reg MP-A2 register list - CPU_BD_mod MP-A2 modifiers list */ - -UNIT CPU_BD_unit = { UDATA (NULL, 0, 0) }; - -REG CPU_BD_reg[] = { - { NULL } -}; - -MTAB CPU_BD_mod[] = { - { UNIT_USER_D, UNIT_USER_D, "USER_D", "USER_D", NULL }, - { UNIT_USER_D, 0, "NOUSER_D", "NOUSER_D", NULL }, - { UNIT_4K_8K, UNIT_4K_8K, "4K_8K", "4K_8K", NULL }, - { UNIT_4K_8K, 0, "NO4K_8K", "NO4K_8K", NULL }, - { UNIT_SWT, UNIT_SWT, "SWT", "SWT", NULL }, - { UNIT_SWT, 0, "NOSWT", "NOSWT", NULL }, - { UNIT_8K, UNIT_8K, "8K", "8K", NULL }, - { UNIT_8K, 0, "NO8K", "NO8K", NULL }, - { UNIT_RAM, UNIT_RAM, "RAM", "RAM", NULL }, - { UNIT_RAM, 0, "NORAM", "NORAM", NULL }, - { UNIT_LO_PROM, UNIT_LO_PROM, "LO_PROM", "LO_PROM", NULL }, - { UNIT_LO_PROM, 0, "NOLO_PROM", "NOLO_PROM", NULL }, - { UNIT_HI_PROM, UNIT_HI_PROM, "HI_PROM", "HI_PROM", NULL }, - { UNIT_HI_PROM, 0, "NOHI_PROM", "NOHI_PROM", NULL }, - { UNIT_MON, UNIT_MON, "MON", "MON", NULL }, - { UNIT_MON, 0, "NOMON", "NOMON", NULL }, - { 0 } -}; - -DEBTAB CPU_BD_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE CPU_BD_dev = { - "MP-A2", //name - &CPU_BD_unit, //units - CPU_BD_reg, //registers - CPU_BD_mod, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - CPU_BD_debug, /* debflags */ - NULL, //msize - NULL //lname -}; - -/* get base address of 2716's */ - -int32 get_base(void) -{ - if (CPU_BD_unit.flags & UNIT_LO_PROM) - return 0xC000; - else if (CPU_BD_unit.flags & UNIT_HI_PROM) - return 0xF000; - return 0; -} - -/* get a byte from memory */ - -int32 CPU_BD_get_mbyte(int32 addr) -{ - int32 val; - - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: addr=%04X\n", addr); - switch(addr & 0xF000) { - case 0xA000: - if (CPU_BD_unit.flags & UNIT_RAM) { - val = m6810_get_mbyte(addr - 0xA000) & 0xFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: m6810 val=%02X\n", val); - return val; - } else { - val = MB_get_mbyte(addr) & 0xFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: m6810 val=%02X\n", val); - return val; - } - case 0xC000: - if (CPU_BD_unit.flags & UNIT_LO_PROM) { - val = i2716_get_mbyte(addr - 0xC000) & 0xFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: 2716=%02X\n", val); - return val; - } else - return 0xFF; - break; - case 0xE000: - val = BOOTROM_get_mbyte(addr - 0xE000) & 0xFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: EPROM=%02X\n", val); - return val; - case 0xF000: - if (CPU_BD_unit.flags & UNIT_MON) { - val = BOOTROM_get_mbyte(addr - (0x10000 - BOOTROM_unit.capac)) & 0xFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: EPROM=%02X\n", val); - return val; - } - default: - val = MB_get_mbyte(addr) & 0xFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mbyte: mp_b2 val=%02X\n", val); - return val; - } -} - -/* get a word from memory */ - -int32 CPU_BD_get_mword(int32 addr) -{ - int32 val; - - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mword: addr=%04X\n", addr); - val = (CPU_BD_get_mbyte(addr) << 8); - val |= CPU_BD_get_mbyte(addr+1); - val &= 0xFFFF; - if (CPU_BD_dev.dctrl & DEBUG_read) - printf("CPU_BD_get_mword: val=%04X\n", val); - return val; -} - -/* put a byte to memory */ - -void CPU_BD_put_mbyte(int32 addr, int32 val) -{ - if (CPU_BD_dev.dctrl & DEBUG_write) - printf("CPU_BD_put_mbyte: addr=%04X, val=%02X\n", addr, val); - switch(addr & 0xF000) { - case 0xA000: - if (CPU_BD_unit.flags & UNIT_RAM) { - m6810_put_mbyte(addr - 0xA000, val); - return; - } else { - MB_put_mbyte(addr, val); - return; - } - default: - MB_put_mbyte(addr, val); - return; - } -} - -/* put a word to memory */ - -void CPU_BD_put_mword(int32 addr, int32 val) -{ - if (CPU_BD_dev.dctrl & DEBUG_write) - printf("CPU_BD_put_mword: addr=%04X, val=%04X\n", addr, val); - CPU_BD_put_mbyte(addr, val >> 8); - CPU_BD_put_mbyte(addr+1, val); -} - -/* end of mp-a2.c */ diff --git a/swtp6800/common/mp-b2.c b/swtp6800/common/mp-b2.c deleted file mode 100644 index bcab28bd..00000000 --- a/swtp6800/common/mp-b2.c +++ /dev/null @@ -1,327 +0,0 @@ -/* mp-b2.c: SWTP SS-50/SS-30 MP-B2 Mother Board - - 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. -*/ - -#include -#include "swtp_defs.h" - -#define UNIT_V_RAM_0000 (UNIT_V_UF) /* MP-8M board 0 enable */ -#define UNIT_RAM_0000 (1 << UNIT_V_RAM_0000) -#define UNIT_V_RAM_2000 (UNIT_V_UF+1) /* MP-8M board 1 enable */ -#define UNIT_RAM_2000 (1 << UNIT_V_RAM_2000) -#define UNIT_V_RAM_4000 (UNIT_V_UF+2) /* MP-8M board 2 enable */ -#define UNIT_RAM_4000 (1 << UNIT_V_RAM_4000) -#define UNIT_V_RAM_6000 (UNIT_V_UF+3) /* MP-8M board 3 enable */ -#define UNIT_RAM_6000 (1 << UNIT_V_RAM_6000) -#define UNIT_V_RAM_A000 (UNIT_V_UF+4) /* MP-8M board 4 enable */ -#define UNIT_RAM_A000 (1 << UNIT_V_RAM_A000) -#define UNIT_V_RAM_C000 (UNIT_V_UF+5) /* MP-8M board 5 enable */ -#define UNIT_RAM_C000 (1 << UNIT_V_RAM_C000) - -/* function prototypes */ - -/* empty I/O device routine */ -int32 nulldev(int32 io, int32 data); - -/* SS-50 bus routines */ -int32 MB_get_mbyte(int32 addr); -int32 MB_get_mword(int32 addr); -void MB_put_mbyte(int32 addr, int32 val); -void MB_put_mword(int32 addr, int32 val); - -/* MP-8M bus routines */ -extern int32 mp_8m_get_mbyte(int32 addr); -extern void mp_8m_put_mbyte(int32 addr, int32 val); - -/* SS-50 I/O address space functions */ - -/* MP-S serial I/O routines */ -extern int32 sio0s(int32 io, int32 data); -extern int32 sio0d(int32 io, int32 data); -extern int32 sio1s(int32 io, int32 data); -extern int32 sio1d(int32 io, int32 data); - -/* DC-4 FDC I/O routines */ -extern int32 fdcdrv(int32 io, int32 data); -extern int32 fdccmd(int32 io, int32 data); -extern int32 fdctrk(int32 io, int32 data); -extern int32 fdcsec(int32 io, int32 data); -extern int32 fdcdata(int32 io, int32 data); - -/* This is the I/O configuration table. There are 32 possible -device addresses, if a device is plugged into a port it's routine -address is here, 'nulldev' means no device is available -*/ - -struct idev { - int32 (*routine)(int32, int32); -}; - -struct idev dev_table[32] = { - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 0 8000-8003 */ - {&sio0s}, {&sio0d}, {&sio1s}, {&sio1d}, /*Port 1 8004-8007 */ -/* sio1x routines just return the last value read on the matching - sio0x routine. SWTBUG tests for the MP-C with most port reads! */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 2 8008-800B*/ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 3 800C-800F*/ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 4 8010-8013*/ - {&fdcdrv}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 5 8014-8017*/ - {&fdccmd}, {&fdctrk}, {&fdcsec}, {&fdcdata}, /*Port 6 8018-801B*/ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /*Port 7 801C-801F*/ -}; - -/* dummy i/o device */ - -int32 nulldev(int32 io, int32 data) -{ - if (io == 0) - return (0xFF); - return 0; -} - -/* Mother Board data structures - - MB_dev Mother Board device descriptor - MB_unit Mother Board unit descriptor - MB_reg Mother Board register list - MB_mod Mother Board modifiers list -*/ - -UNIT MB_unit = { - UDATA (NULL, 0, 0) -}; - -REG MB_reg[] = { - { NULL } -}; - -MTAB MB_mod[] = { - { UNIT_RAM_0000, UNIT_RAM_0000, "BD0 On", "BD0", NULL }, - { UNIT_RAM_0000, 0, "BD0 Off", "NOBD0", NULL }, - { UNIT_RAM_2000, UNIT_RAM_2000, "BD1 On", "BD1", NULL }, - { UNIT_RAM_2000, 0, "BD1 Off", "NOBD1", NULL }, - { UNIT_RAM_4000, UNIT_RAM_4000, "BD2 On", "BD2", NULL }, - { UNIT_RAM_4000, 0, "BD2 Off", "NOBD2", NULL }, - { UNIT_RAM_6000, UNIT_RAM_6000, "BD3 On", "BD3", NULL }, - { UNIT_RAM_6000, 0, "BD3 Off", "NOBD3", NULL }, - { UNIT_RAM_A000, UNIT_RAM_A000, "BD4 On", "BD4", NULL }, - { UNIT_RAM_A000, 0, "BD4 Off", "NOBD4", NULL }, - { UNIT_RAM_C000, UNIT_RAM_C000, "BD5 On", "BD5", NULL }, - { UNIT_RAM_C000, 0, "BD5 Off", "NOBD5", NULL }, - { 0 } -}; - -DEBTAB MB_debug[] = { - { "ALL", DEBUG_all }, - { "FLOW", DEBUG_flow }, - { "READ", DEBUG_read }, - { "WRITE", DEBUG_write }, - { "LEV1", DEBUG_level1 }, - { "LEV2", DEBUG_level2 }, - { NULL } -}; - -DEVICE MB_dev = { - "MP-B2", //name - &MB_unit, //units - MB_reg, //registers - MB_mod, //modifiers - 1, //numunits - 16, //aradix - 16, //awidth - 1, //aincr - 16, //dradix - 8, //dwidth - NULL, //examine - NULL, //deposit - NULL, //reset - NULL, //boot - NULL, //attach - NULL, //detach - NULL, //ctxt - DEV_DEBUG, //flags - 0, //dctrl - MB_debug, /* debflags */ - NULL, //msize - NULL //lname -}; - -/* get a byte from memory */ - -int32 MB_get_mbyte(int32 addr) -{ - int32 val; - - if (MB_dev.dctrl & DEBUG_read) - printf("MB_get_mbyte: addr=%04X\n", addr); - switch(addr & 0xF000) { - case 0x0000: - case 0x1000: - if (MB_unit.flags & UNIT_RAM_0000) { - val = mp_8m_get_mbyte(addr) & 0xFF; - if (MB_dev.dctrl & DEBUG_read) - printf("MB_get_mbyte: mp_8m val=%02X\n", val); - return val; - } else - return 0xFF; - case 0x2000: - case 0x3000: - if (MB_unit.flags & UNIT_RAM_2000) { - val = mp_8m_get_mbyte(addr) & 0xFF; - if (MB_dev.dctrl & DEBUG_read) - printf("MB_get_mbyte: mp_8m val=%02X\n", val); - return val; - } else - return 0xFF; - case 0x4000: - case 0x5000: - if (MB_unit.flags & UNIT_RAM_4000) { - val = mp_8m_get_mbyte(addr) & 0xFF; - if (MB_dev.dctrl & DEBUG_read) - printf("MB_get_mbyte: mp_8m val=%02X\n", val); - return val; - } else - return 0xFF; - case 0x6000: - case 0x7000: - if (MB_unit.flags & UNIT_RAM_6000) { - val = mp_8m_get_mbyte(addr) & 0xFF; - if (MB_dev.dctrl & DEBUG_read) - printf("MB_get_mbyte: mp_8m val=%02X\n", val); - return val; - } else - return 0xFF; - case 0x8000: - if (addr < 0x8020) - val = (dev_table[addr - 0x8000].routine(0, 0)) & 0xFF; - else - val = 0xFF; - if (MB_dev.dctrl & DEBUG_read) - printf("MB_get_mbyte: I/O addr=%04X val=%02X\n", addr, val); - return val; - case 0xA000: - case 0xB000: - if (MB_unit.flags & UNIT_RAM_A000) { - val = mp_8m_get_mbyte(addr) & 0xFF; - if (MB_dev.dctrl & DEBUG_read) - printf("MB_get_mbyte: mp_8m val=%02X\n", val); - return val; - } else - return 0xFF; - case 0xC000: - case 0xD000: - if (MB_unit.flags & UNIT_RAM_C000) { - val = mp_8m_get_mbyte(addr) & 0xFF; - if (MB_dev.dctrl & DEBUG_read) - printf("MB_get_mbyte: mp_8m val=%02X\n", val); - return val; - } else - return 0xFF; - default: - return 0xFF; - } -} - -/* get a word from memory */ - -int32 MB_get_mword(int32 addr) -{ - int32 val; - - - if (MB_dev.dctrl & DEBUG_read) - printf("MB_get_mword: addr=%04X\n", addr); - val = (MB_get_mbyte(addr) << 8); - val |= MB_get_mbyte(addr+1); - val &= 0xFFFF; - if (MB_dev.dctrl & DEBUG_read) - printf("MB_get_mword: val=%04X\n", val); - return val; -} - -/* put a byte to memory */ - -void MB_put_mbyte(int32 addr, int32 val) -{ - if (MB_dev.dctrl & DEBUG_write) - printf("MB_put_mbyte: addr=%04X, val=%02X\n", addr, val); - switch(addr & 0xF000) { - case 0x0000: - case 0x1000: - if (MB_unit.flags & UNIT_RAM_0000) { - mp_8m_put_mbyte(addr, val); - return; - } - case 0x2000: - case 0x3000: - if (MB_unit.flags & UNIT_RAM_2000) { - mp_8m_put_mbyte(addr, val); - return; - } - case 0x4000: - case 0x5000: - if (MB_unit.flags & UNIT_RAM_4000) { - mp_8m_put_mbyte(addr, val); - return; - } - case 0x6000: - case 0x7000: - if (MB_unit.flags & UNIT_RAM_6000) { - mp_8m_put_mbyte(addr, val); - return; - } - case 0x8000: - if (addr < 0x8020) - dev_table[addr - 0x8000].routine(1, val); - return; - case 0xA000: - case 0xB000: - if (MB_unit.flags & UNIT_RAM_A000) { - mp_8m_put_mbyte(addr, val); - return; - } - case 0xC000: - case 0xD000: - if (MB_unit.flags & UNIT_RAM_C000) { - mp_8m_put_mbyte(addr, val); - return; - } - default: - return; - } -} - -/* put a word to memory */ - -void MB_put_mword(int32 addr, int32 val) -{ - if (MB_dev.dctrl & DEBUG_write) - printf("MB_ptt_mword: addr=%04X, val=%04X\n", addr, val); - MB_put_mbyte(addr, val >> 8); - MB_put_mbyte(addr+1, val); -} - -/* end of mp-b2.c */ - diff --git a/swtp6800/common/mp-s.c b/swtp6800/common/mp-s.c deleted file mode 100644 index e3603c7d..00000000 --- a/swtp6800/common/mp-s.c +++ /dev/null @@ -1,331 +0,0 @@ -/* mp-s.c: SWTP MP-S serial I/O card simulator - - Copyright (c) 2005-2011, William 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 - Willaim 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 SWTP MP-S interface card. - The card contains one M6850 ACIA. The ACIA implements one complete - serial port. It provides 7 or 8-bit ASCII RS-232 interface to Terminals - or 20 mA current loop interface to a model 33 or 37 Teletype. It is not - compatible with baudot Teletypes. Baud rates from 110 to 1200 are - switch selectable from S! on the MP-S. The ACIA ports appear at all - 4 addresses. This fact is used by SWTBUG to determine the presence of the - MP-S vice MP-C serial card. The ACIA interrupt request line can be connected - to the IRQ or NMI interrupt lines by a jumper on the MP-S. - - All I/O is via either programmed I/O or interrupt controlled I/O. - It has a status port and a data port. A write to the status port - can select some options for the device (0x03 will reset the port). - A read of the status port gets the port status: - - +---+---+---+---+---+---+---+---+ - | I | P | O | F |CTS|DCD|TXE|RXF| - +---+---+---+---+---+---+---+---+ - - RXF - A 1 in this bit position means a character has been received - on the data port and is ready to be read. - TXE - A 1 in this bit means the port is ready to receive a character - on the data port and transmit it out over the serial line. - - A read to the data port gets the buffered character, a write - to the data port writes the character to the device. -*/ - -#include -#include -#include "swtp_defs.h" - -#define UNIT_V_TTY (UNIT_V_UF) // TTY or ANSI mode -#define UNIT_TTY (1 << UNIT_V_TTY) - -/* local global variables */ - -int32 ptr_stopioe = 0; // stop on error -int32 ptp_stopioe = 0; // stop on error -int32 odata; -int32 status; - -int32 ptp_flag = 0; -int32 ptr_flag = 0; - -/* function prototypes */ - -t_stat sio_svc (UNIT *uptr); -t_stat ptr_svc (UNIT *uptr); -t_stat ptp_svc (UNIT *uptr); -t_stat sio_reset (DEVICE *dptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptp_reset (DEVICE *dptr); -int32 sio0s(int32 io, int32 data); -int32 sio0d(int32 io, int32 data); -int32 sio1s(int32 io, int32 data); -int32 sio1d(int32 io, int32 data); - -/* sio data structures - - sio_dev SIO device descriptor - sio_unit SIO unit descriptor - sio_reg SIO register list - sio_mod SIO modifiers list */ - -UNIT sio_unit = { UDATA (&sio_svc, 0, 0), KBD_POLL_WAIT -}; - -REG sio_reg[] = { - { ORDATA (DATA, sio_unit.buf, 8) }, - { ORDATA (STAT, sio_unit.u3, 8) }, - { NULL } -}; - -MTAB sio_mod[] = { - { UNIT_TTY, UNIT_TTY, "TTY", "TTY", NULL }, - { UNIT_TTY, 0, "ANSI", "ANSI", NULL }, - { 0 } -}; - -DEVICE sio_dev = { - "MP-S", &sio_unit, sio_reg, sio_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &sio_reset, - NULL, NULL, NULL -}; - -/* paper tape reader data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_reg PTR register list - ptr_mod PTR modifiers list */ - -UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ + UNIT_ATTABLE, 0), KBD_POLL_WAIT -}; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, NULL, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - NULL, NULL, NULL -}; - -/* paper tape punch data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_reg PTP register list - ptp_mod PTP modifiers list */ - -UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ + UNIT_ATTABLE, 0), KBD_POLL_WAIT -}; -DEVICE ptp_dev = { - "PTP", &ptp_unit, NULL, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL -}; - -/* console input service routine */ - -t_stat sio_svc (UNIT *uptr) -{ - int32 temp; - - sim_activate (&sio_unit, sio_unit.wait); // continue poll - if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) - return temp; // no char or error? - sio_unit.buf = temp & 0xFF; // Save char - sio_unit.u3 |= 0x01; // Set RXF flag - /* Do any special character handling here */ - sio_unit.pos++; // step character count - return SCPE_OK; -} - -/* paper tape reader input service routine */ - -t_stat ptr_svc (UNIT *uptr) -{ - int32 temp; - - sim_activate (&ptr_unit, ptr_unit.wait); // continue poll - if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) - return temp; // no char or error? - ptr_unit.buf = temp & 0xFF; // Save char - ptr_unit.u3 |= 0x01; // Set RXF flag - /* Do any special character handling here */ - ptr_unit.pos++; // step character count - return SCPE_OK; -} - -/* paper tape punch output service routine */ - -t_stat ptp_svc (UNIT *uptr) -{ - return SCPE_OK; -} - -/* Reset console */ - -t_stat sio_reset (DEVICE *dptr) -{ - sio_unit.buf = 0; // Data buffer - sio_unit.u3 = 0x02; // Status buffer - sio_unit.wait = 10000; - sim_activate (&sio_unit, sio_unit.wait); // activate unit - return SCPE_OK; -} - -/* Reset paper tape reader */ - -t_stat ptr_reset (DEVICE *dptr) -{ - ptr_unit.buf = 0; - ptr_unit.u3 = 0x02; -// sim_activate (&ptr_unit, ptr_unit.wait); // activate unit - sim_cancel (&ptr_unit); // deactivate unit - return SCPE_OK; -} - -/* Reset paper tape punch */ - -t_stat ptp_reset (DEVICE *dptr) -{ - ptp_unit.buf = 0; - ptp_unit.u3 = 0x02; -// sim_activate (&ptp_unit, ptp_unit.wait); // activate unit - sim_cancel (&ptp_unit); // deactivate unit - return SCPE_OK; -} - -/* I/O instruction handlers, called from the MP-B2 module when a - read or write occur to addresses 0x8004-0x8007. */ - -int32 sio0s(int32 io, int32 data) -{ - if (io == 0) { // control register read - if (ptr_flag) { // reader enabled? - if ((ptr_unit.flags & UNIT_ATT) == 0) { // attached? - ptr_unit.u3 &= 0xFE; // no, clear RXF flag - ptr_flag = 0; // clear reader flag - printf("Reader not attached to file\n"); - } else { // attached - if (feof(ptr_unit.fileref)) { // EOF - ptr_unit.u3 &= 0xFE; // clear RXF flag - ptr_flag = 0; // clear reader flag - } else // not EOF - ptr_unit.u3 |= 0x01; // set ready - } - return (status = ptr_unit.u3); // return ptr status - } else { - return (status = sio_unit.u3); // return console status - } - } else { // control register write - if (data == 0x03) { // reset port! - sio_unit.u3 = 0x02; // reset console - sio_unit.buf = 0; - sio_unit.pos = 0; - ptr_unit.u3 = 0x02; // reset reader - ptr_unit.buf = 0; - ptr_unit.pos = 0; - ptp_unit.u3 = 0x02; // reset punch - ptp_unit.buf = 0; - ptp_unit.pos = 0; - } - return (status = 0); // invalid io - } -} - -int32 sio0d(int32 io, int32 data) -{ - if (io == 0) { // data register read - if (ptr_flag) { // RDR enabled? - if ((ptr_unit.flags & UNIT_ATT) == 0) // attached? - return 0; // no, done -// printf("ptr_unit.u3=%02X\n", ptr_unit.u3); - if ((ptr_unit.u3 & 0x01) == 0) { // yes, more data? -// printf("Returning old %02X\n", odata); // no, return previous byte - return (odata & 0xFF); - } - if ((odata = getc(ptr_unit.fileref)) == EOF) { // end of file? -// printf("Got EOF\n"); - ptr_unit.u3 &= 0xFE; // clear RXF flag - return (odata = 0); // no data - } -// printf("Returning new %02X\n", odata); - ptr_unit.pos++; // step character count - ptr_unit.u3 &= 0xFE; // clear RXF flag - return (odata & 0xFF); // return character - } else { - sio_unit.u3 &= 0xFE; // clear RXF flag - return (odata = sio_unit.buf); // return next char - } - } else { // data register write - if (isprint(data) || data == '\r' || data == '\n') { // printable? - sim_putchar(data); // print character on console - if (ptp_flag && ptp_unit.flags & UNIT_ATT) { // PTP enabled & attached? - putc(data, ptp_unit.fileref); - ptp_unit.pos++; // step character counter - } - } else { // DC1-DC4 control Reader/Punch - switch (data) { - case 0x11: // PTR on - ptr_flag = 1; - ptr_unit.u3 |= 0x01; -// printf("Reader on\n"); - break; - case 0x12: // PTP on - ptp_flag = 1; - ptp_unit.u3 |= 0x02; -// printf("Punch on\n"); - break; - case 0x13: // PTR off - ptr_flag = 0; -// printf("Reader off-%d bytes read\n", ptr_unit.pos); - break; - case 0x14: // PTP off - ptp_flag = 0; -// printf("Punch off-%d bytes written\n", ptp_unit.pos); - break; - default: // ignore all other characters - break; - } - } - } - return (odata = 0); -} - -/* Because each port appears at 2 addresses and this fact is used - to determine if it is a MP-C or MP-S repeatedly in the SWTBUG - monitor, this code assures that reads of the high ports return - the same data as was read the last time on the low ports. -*/ - -int32 sio1s(int32 io, int32 data) -{ - return status; -} - -int32 sio1d(int32 io, int32 data) -{ - return odata; -} - -/* end of mp-s.c */ diff --git a/swtp6800/swtp6800/mp-a2_sys.c b/swtp6800/swtp6800/mp-a2_sys.c deleted file mode 100644 index 8a043061..00000000 --- a/swtp6800/swtp6800/mp-a2_sys.c +++ /dev/null @@ -1,87 +0,0 @@ -/* mp-a_sys.c: SWTP 6800 system interface - - Copyright (c) 2005, William 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. -*/ - -#include -#include -#include "swtp_defs.h" - -/* externals */ - -extern DEVICE CPU_BD_dev; -extern DEVICE m6800_dev; -extern REG m6800_reg[]; -extern DEVICE BOOTROM_dev; -extern DEVICE m6810_dev; -extern DEVICE i2716_dev; - -extern DEVICE MB_dev; -extern DEVICE sio_dev; -extern DEVICE ptr_dev; -extern DEVICE ptp_dev; -extern DEVICE mp_8m_dev; -extern DEVICE dsk_dev; - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "SWTP 6800, V2, MP-A2 CPU Board"; - -REG *sim_PC = &m6800_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &CPU_BD_dev, - &m6800_dev, - &BOOTROM_dev, - &m6810_dev, - &i2716_dev, - &MB_dev, - &sio_dev, - &ptr_dev, - &ptp_dev, - &mp_8m_dev, - &dsk_dev, - NULL -}; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode", - "Invalid Memory" -}; - -/* end of mp-a_sys.c */ diff --git a/swtp6800/swtp6800/mp-a_sys.c b/swtp6800/swtp6800/mp-a_sys.c deleted file mode 100644 index 2bc1afc2..00000000 --- a/swtp6800/swtp6800/mp-a_sys.c +++ /dev/null @@ -1,85 +0,0 @@ -/* mp-a_sys.c: SWTP 6800 system interface - - Copyright (c) 2005, William 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. -*/ - -#include -#include -#include "swtp_defs.h" - -/* externals */ - -extern DEVICE CPU_BD_dev; -extern DEVICE m6800_dev; -extern REG m6800_reg[]; -extern DEVICE BOOTROM_dev; -extern DEVICE m6810_dev; - -extern DEVICE MB_dev; -extern DEVICE sio_dev; -extern DEVICE ptr_dev; -extern DEVICE ptp_dev; -extern DEVICE mp_8m_dev; -extern DEVICE dsk_dev; - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "SWTP 6800, V2, MP-A CPU Board"; - -REG *sim_PC = &m6800_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &CPU_BD_dev, - &m6800_dev, - &BOOTROM_dev, - &m6810_dev, - &MB_dev, - &sio_dev, - &ptr_dev, - &ptp_dev, - &mp_8m_dev, - &dsk_dev, - NULL -}; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode", - "Invalid Memory" -}; - -/* end of mp-a_sys.c */ diff --git a/swtp6800/swtp6800/swtbug.bin b/swtp6800/swtp6800/swtbug.bin deleted file mode 100644 index 8cef56ad..00000000 Binary files a/swtp6800/swtp6800/swtbug.bin and /dev/null differ diff --git a/swtp6800/swtp6800/swtp6800mp-a.ini b/swtp6800/swtp6800/swtp6800mp-a.ini deleted file mode 100644 index 7b775df0..00000000 --- a/swtp6800/swtp6800/swtp6800mp-a.ini +++ /dev/null @@ -1,8 +0,0 @@ -set bootrom 2708 -attach bootrom swtbug.bin -set cpu hex -set cpu itrap -set cpu mtrap -reset -set mp-b2 bd0, bd1, bd2, bd3, bd4, bd5 -g diff --git a/swtp6800/swtp6800/swtp6800mp-a2.ini b/swtp6800/swtp6800/swtp6800mp-a2.ini deleted file mode 100644 index 5f26385a..00000000 --- a/swtp6800/swtp6800/swtp6800mp-a2.ini +++ /dev/null @@ -1,9 +0,0 @@ -set bootrom 2708 -attach bootrom swtbug.bin -set mp-a2 mon, lo_prom -set cpu hex -set cpu itrap -set cpu mtrap -reset -set mp-b2 bd0, bd1, bd2, bd3, bd4, bd5 -g diff --git a/swtp6800/swtp6800/swtp_defs.h b/swtp6800/swtp6800/swtp_defs.h deleted file mode 100644 index 1cbb5232..00000000 --- a/swtp6800/swtp6800/swtp_defs.h +++ /dev/null @@ -1,55 +0,0 @@ -/* swtp_defs.h: SWTP 6800 simulator definitions - -Copyright (c) 2005-2012, William 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. -*/ - -#include -#include "sim_defs.h" // simulator defs - -/* Memory */ - -#define MAXMEMSIZE 65536 // max memory size -#define MEMSIZE (m6800_unit.capac) // actual memory size -#define ADDRMASK (MAXMEMSIZE - 1) // 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-really WAI -#define STOP_IBKPT 3 // breakpoint -#define STOP_OPCODE 4 // invalid opcode -#define STOP_MEMORY 5 // invalid memory address -