From adc347c15f603a3867e200249faf0ab21e1ef694 Mon Sep 17 00:00:00 2001 From: Bob Supnik Date: Mon, 4 Jun 2018 08:02:34 -0700 Subject: [PATCH] AltairZ80, IBM1130, SWTP6800: simh 3.10 removed simulators These sources have moved on to the 4.0 base. --- AltairZ80/altairz80_cpu.c | 6952 ------------------- AltairZ80/altairz80_cpu_nommu.c | 4215 ----------- AltairZ80/altairz80_defs.h | 102 - AltairZ80/altairz80_dsk.c | 595 -- AltairZ80/altairz80_hdsk.c | 957 --- AltairZ80/altairz80_net.c | 321 - AltairZ80/altairz80_sio.c | 1880 ----- AltairZ80/altairz80_sys.c | 889 --- AltairZ80/disasm.c | 1426 ---- AltairZ80/flashwriter2.c | 315 - AltairZ80/i8272.c | 972 --- AltairZ80/i8272.h | 49 - AltairZ80/i86.h | 296 - AltairZ80/i86_decode.c | 958 --- AltairZ80/i86_ops.c | 5488 --------------- AltairZ80/i86_prim_ops.c | 1527 ---- AltairZ80/insns.h | 661 -- AltairZ80/insnsd.c | 4550 ------------ AltairZ80/mfdc.c | 680 -- AltairZ80/mfdc.h | 46 - AltairZ80/n8vem.c | 492 -- AltairZ80/nasm.h | 357 - AltairZ80/s100_64fdc.c | 1786 ----- AltairZ80/s100_adcs6.c | 711 -- AltairZ80/s100_disk1a.c | 890 --- AltairZ80/s100_disk2.c | 627 -- AltairZ80/s100_disk3.c | 662 -- AltairZ80/s100_fif.c | 472 -- AltairZ80/s100_hdc1001.c | 579 -- AltairZ80/s100_if3.c | 361 - AltairZ80/s100_mdriveh.c | 263 - AltairZ80/s100_mdsad.c | 780 --- AltairZ80/s100_scp300f.c | 450 -- AltairZ80/s100_selchan.c | 209 - AltairZ80/s100_ss1.c | 664 -- AltairZ80/sim_imd.c | 802 --- AltairZ80/sim_imd.h | 128 - AltairZ80/vfdhd.c | 658 -- AltairZ80/vfdhd.h | 43 - AltairZ80/wd179x.c | 1138 --- AltairZ80/wd179x.h | 67 - Ibm1130/1130consoleblank.bmp | Bin 381318 -> 0 bytes Ibm1130/1132empty.bmp | Bin 6278 -> 0 bytes Ibm1130/1132full.bmp | Bin 6278 -> 0 bytes Ibm1130/1442empty.bmp | Bin 6278 -> 0 bytes Ibm1130/1442eof.bmp | Bin 6278 -> 0 bytes Ibm1130/1442full.bmp | Bin 6278 -> 0 bytes Ibm1130/1442middle.bmp | Bin 6278 -> 0 bytes Ibm1130/HAND.CUR | Bin 326 -> 0 bytes Ibm1130/dmsr2v12phases.h | 171 - Ibm1130/dmsr2v12slet.h | 129 - Ibm1130/ibm1130.mak | 435 -- Ibm1130/ibm1130.rc | 72 - Ibm1130/ibm1130_conin.h | 43 - Ibm1130/ibm1130_conout.h | 58 - Ibm1130/ibm1130_cpu.c | 1883 ----- Ibm1130/ibm1130_cr.c | 2636 ------- Ibm1130/ibm1130_defs.h | 311 - Ibm1130/ibm1130_disk.c | 889 --- Ibm1130/ibm1130_fmt.c | 313 - Ibm1130/ibm1130_fmt.h | 17 - Ibm1130/ibm1130_gdu.c | 1128 --- Ibm1130/ibm1130_gui.c | 1657 ----- Ibm1130/ibm1130_plot.c | 634 -- Ibm1130/ibm1130_prt.c | 819 --- Ibm1130/ibm1130_prtwheel.h | 126 - Ibm1130/ibm1130_ptrp.c | 309 - Ibm1130/ibm1130_sca.c | 1165 ---- Ibm1130/ibm1130_stddev.c | 1319 ---- Ibm1130/ibm1130_sys.c | 507 -- Ibm1130/ibm1130_t2741.c | 388 -- Ibm1130/ibm1130res.h | 17 - Ibm1130/makefile | 74 - Ibm1130/readme1130.txt | 189 - Ibm1130/readme_update.txt | 60 - Ibm1130/utils/asm1130.c | 4585 ------------ Ibm1130/utils/asm1130.mak | 175 - Ibm1130/utils/bindump.c | 755 -- Ibm1130/utils/bindump.mak | 175 - Ibm1130/utils/checkdisk.c | 262 - Ibm1130/utils/checkdisk.mak | 177 - Ibm1130/utils/diskview.c | 612 -- Ibm1130/utils/diskview.mak | 175 - Ibm1130/utils/makefile | 47 - Ibm1130/utils/mkboot.c | 706 -- Ibm1130/utils/mkboot.mak | 175 - Ibm1130/utils/viewdeck.c | 243 - Ibm1130/utils/viewdeck.mak | 176 - Visual Studio Projects/AltairZ80.vcproj | 406 -- Visual Studio Projects/swtp6800mp-a.vcproj | 314 - Visual Studio Projects/swtp6800mp-a2.vcproj | 318 - doc/altairz80_doc.pdf | Bin 555471 -> 0 bytes doc/swtp6800MP-A.png | Bin 20448 -> 0 bytes doc/swtp6800MP-A2.png | Bin 21821 -> 0 bytes doc/swtp6800_doc.doc | Bin 76800 -> 0 bytes swtp6800/common/bootrom.c | 231 - swtp6800/common/dc-4.c | 568 -- swtp6800/common/i2716.c | 221 - swtp6800/common/m6800.c | 2013 ------ swtp6800/common/m6810.c | 146 - swtp6800/common/mp-8m.c | 209 - swtp6800/common/mp-a.c | 211 - swtp6800/common/mp-a2.c | 263 - swtp6800/common/mp-b2.c | 327 - swtp6800/common/mp-s.c | 331 - swtp6800/swtp6800/mp-a2_sys.c | 87 - swtp6800/swtp6800/mp-a_sys.c | 85 - swtp6800/swtp6800/swtbug.bin | Bin 1024 -> 0 bytes swtp6800/swtp6800/swtp6800mp-a.ini | 8 - swtp6800/swtp6800/swtp6800mp-a2.ini | 9 - swtp6800/swtp6800/swtp_defs.h | 55 - 111 files changed, 74432 deletions(-) delete mode 100644 AltairZ80/altairz80_cpu.c delete mode 100644 AltairZ80/altairz80_cpu_nommu.c delete mode 100644 AltairZ80/altairz80_defs.h delete mode 100644 AltairZ80/altairz80_dsk.c delete mode 100644 AltairZ80/altairz80_hdsk.c delete mode 100644 AltairZ80/altairz80_net.c delete mode 100644 AltairZ80/altairz80_sio.c delete mode 100644 AltairZ80/altairz80_sys.c delete mode 100644 AltairZ80/disasm.c delete mode 100644 AltairZ80/flashwriter2.c delete mode 100644 AltairZ80/i8272.c delete mode 100644 AltairZ80/i8272.h delete mode 100644 AltairZ80/i86.h delete mode 100644 AltairZ80/i86_decode.c delete mode 100644 AltairZ80/i86_ops.c delete mode 100644 AltairZ80/i86_prim_ops.c delete mode 100644 AltairZ80/insns.h delete mode 100644 AltairZ80/insnsd.c delete mode 100644 AltairZ80/mfdc.c delete mode 100644 AltairZ80/mfdc.h delete mode 100644 AltairZ80/n8vem.c delete mode 100644 AltairZ80/nasm.h delete mode 100644 AltairZ80/s100_64fdc.c delete mode 100644 AltairZ80/s100_adcs6.c delete mode 100644 AltairZ80/s100_disk1a.c delete mode 100644 AltairZ80/s100_disk2.c delete mode 100644 AltairZ80/s100_disk3.c delete mode 100644 AltairZ80/s100_fif.c delete mode 100644 AltairZ80/s100_hdc1001.c delete mode 100644 AltairZ80/s100_if3.c delete mode 100644 AltairZ80/s100_mdriveh.c delete mode 100644 AltairZ80/s100_mdsad.c delete mode 100644 AltairZ80/s100_scp300f.c delete mode 100644 AltairZ80/s100_selchan.c delete mode 100644 AltairZ80/s100_ss1.c delete mode 100644 AltairZ80/sim_imd.c delete mode 100644 AltairZ80/sim_imd.h delete mode 100644 AltairZ80/vfdhd.c delete mode 100644 AltairZ80/vfdhd.h delete mode 100644 AltairZ80/wd179x.c delete mode 100644 AltairZ80/wd179x.h delete mode 100644 Ibm1130/1130consoleblank.bmp delete mode 100644 Ibm1130/1132empty.bmp delete mode 100644 Ibm1130/1132full.bmp delete mode 100644 Ibm1130/1442empty.bmp delete mode 100644 Ibm1130/1442eof.bmp delete mode 100644 Ibm1130/1442full.bmp delete mode 100644 Ibm1130/1442middle.bmp delete mode 100644 Ibm1130/HAND.CUR delete mode 100644 Ibm1130/dmsr2v12phases.h delete mode 100644 Ibm1130/dmsr2v12slet.h delete mode 100644 Ibm1130/ibm1130.mak delete mode 100644 Ibm1130/ibm1130.rc delete mode 100644 Ibm1130/ibm1130_conin.h delete mode 100644 Ibm1130/ibm1130_conout.h delete mode 100644 Ibm1130/ibm1130_cpu.c delete mode 100644 Ibm1130/ibm1130_cr.c delete mode 100644 Ibm1130/ibm1130_defs.h delete mode 100644 Ibm1130/ibm1130_disk.c delete mode 100644 Ibm1130/ibm1130_fmt.c delete mode 100644 Ibm1130/ibm1130_fmt.h delete mode 100644 Ibm1130/ibm1130_gdu.c delete mode 100644 Ibm1130/ibm1130_gui.c delete mode 100644 Ibm1130/ibm1130_plot.c delete mode 100644 Ibm1130/ibm1130_prt.c delete mode 100644 Ibm1130/ibm1130_prtwheel.h delete mode 100644 Ibm1130/ibm1130_ptrp.c delete mode 100644 Ibm1130/ibm1130_sca.c delete mode 100644 Ibm1130/ibm1130_stddev.c delete mode 100644 Ibm1130/ibm1130_sys.c delete mode 100644 Ibm1130/ibm1130_t2741.c delete mode 100644 Ibm1130/ibm1130res.h delete mode 100644 Ibm1130/makefile delete mode 100644 Ibm1130/readme1130.txt delete mode 100644 Ibm1130/readme_update.txt delete mode 100644 Ibm1130/utils/asm1130.c delete mode 100644 Ibm1130/utils/asm1130.mak delete mode 100644 Ibm1130/utils/bindump.c delete mode 100644 Ibm1130/utils/bindump.mak delete mode 100644 Ibm1130/utils/checkdisk.c delete mode 100644 Ibm1130/utils/checkdisk.mak delete mode 100644 Ibm1130/utils/diskview.c delete mode 100644 Ibm1130/utils/diskview.mak delete mode 100644 Ibm1130/utils/makefile delete mode 100644 Ibm1130/utils/mkboot.c delete mode 100644 Ibm1130/utils/mkboot.mak delete mode 100644 Ibm1130/utils/viewdeck.c delete mode 100644 Ibm1130/utils/viewdeck.mak delete mode 100644 Visual Studio Projects/AltairZ80.vcproj delete mode 100644 Visual Studio Projects/swtp6800mp-a.vcproj delete mode 100644 Visual Studio Projects/swtp6800mp-a2.vcproj delete mode 100644 doc/altairz80_doc.pdf delete mode 100644 doc/swtp6800MP-A.png delete mode 100644 doc/swtp6800MP-A2.png delete mode 100644 doc/swtp6800_doc.doc delete mode 100644 swtp6800/common/bootrom.c delete mode 100644 swtp6800/common/dc-4.c delete mode 100644 swtp6800/common/i2716.c delete mode 100644 swtp6800/common/m6800.c delete mode 100644 swtp6800/common/m6810.c delete mode 100644 swtp6800/common/mp-8m.c delete mode 100644 swtp6800/common/mp-a.c delete mode 100644 swtp6800/common/mp-a2.c delete mode 100644 swtp6800/common/mp-b2.c delete mode 100644 swtp6800/common/mp-s.c delete mode 100644 swtp6800/swtp6800/mp-a2_sys.c delete mode 100644 swtp6800/swtp6800/mp-a_sys.c delete mode 100644 swtp6800/swtp6800/swtbug.bin delete mode 100644 swtp6800/swtp6800/swtp6800mp-a.ini delete mode 100644 swtp6800/swtp6800/swtp6800mp-a2.ini delete mode 100644 swtp6800/swtp6800/swtp_defs.h 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 4b989529d09942d6dc50365a6dd6a62e7b5a97e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 381318 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 diff --git a/Ibm1130/1132empty.bmp b/Ibm1130/1132empty.bmp deleted file mode 100644 index 3ccc082ca1b32ffac655f94182ead642299e8bcd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6278 zcmeI0F^k7H#2wPLpZ<8Z&1M}?!2TPL#M`96Z zhInF6_@42LL4@_@@I~Hs@IPqVx{YY;q|D?N>nYum{X(okAu5+kvaGmpCr2Jc)Bc9Fe3G+ss{9<^W z>9)L?IL_BCGkLS8YF$*$BZErUlZU_jivK70O1h&`C(lQ?2p66JAC>(gTzCR}RQ5{? Fmn-Y;#o7P> diff --git a/Ibm1130/1132full.bmp b/Ibm1130/1132full.bmp deleted file mode 100644 index 4705d1b6f88b8e9e512d24283a33e4564a4fc638..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6278 zcmeHLu};G<5H%7?3k+doWMt$U*!hP{&W1YGV?7~{d;&8QJ4-*Q8>4x49LLvQCvPtUJ+!rL141IkM%7vj>7-#_}sSGTBL=}ZfOLulPKsNte$vE6QQ z!ums4>pT?v+z=`=&;A03j3(IYkqU8~5j*QEKKd#<>3D<`?H9rJtszy$Zb1rUnoY(K5{JQxhdJfAI z=Os?PGdxbgR)({MJ5>)8Q@$K-*i!*V!Wq-)aD8Oj#VK1yt5ot7^7m)jqlgHJ-DYbE_Z7e)b zpW}lt?BhAdr`0N^mpY6rBtPJ&j$sjVII~z;q;+5;a1tV}15Ip3;Gp3Foz3Gaw>u*b w9LLVdNpvxK*e(fcx;0F1WKi=rQGadP5?p#B;};w+P|>C6!Yja!p3Q#w0bm)?H~;_u diff --git a/Ibm1130/1442empty.bmp b/Ibm1130/1442empty.bmp deleted file mode 100644 index 8b9f667b5459a0f9c06b6431fb779f3840618643..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6278 zcmeHLy-vh13=R?!9T^!J8F>bF-l0=R=)^H*f{v_g%uKi6(nq>CC|~}XxC%XN(1DQM z#Q+3(RY*aV@}j(C26P|ke#on# zw3L^Ujch9~nTyg=UP?By&FAIbz4i*uX(=w`%Fpvha2qN;bt_)Xll5}#I!7EnBY5)7 zc$E?KDS@*}<0i(dG${_>0m{pQftB@=_6T>KEh12NB_8d#@D#ToB)ZDWpXVj*qv~^I z{&N2zO0G%gQDyLb?giNMBUG*t;JUVJUtgN=AB7Q5iVMkpDPB4WJ!H4tZKwV5aMC;n z`~D`$Q;L)3NpQjWOp|#iaaemRViT?*oeutQRUF}KcEr4-d1cPS9GDsh=Z|)uy`$qk E0EFM~IsgCw diff --git a/Ibm1130/1442eof.bmp b/Ibm1130/1442eof.bmp deleted file mode 100644 index 2bf679a9ed8efc2445c0e998dc7dc8f725d51b61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6278 zcmeHLy-vh13=R^~b!6lbc#hk7hfW=#6UUedIt%aDRD^>eY|_#Ht%_rOt%jHvTGz^TSRHfa==$;L It95eRC%ZZIQUCw| diff --git a/Ibm1130/1442full.bmp b/Ibm1130/1442full.bmp deleted file mode 100644 index e6ba0c5b653e49b0ac3d7eca1319e61815dafb9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6278 zcmeHLF>b>!3}k=;$=I<^=sU9a51u?Wo|=xDT8~}3b?%hii=UJqxF=hJB!h84Hb{$r zj75`@4kS+!Y-juQ_CTY&KtG~Ahqj`-vHw1dk4~W+5iW9Wx!tt;J2b%JaMkZeL1Mx{Md{6un&g$pMGY2$}pc9#cUR z6Ie5Y`w)*AG911GjF%Y$3;QLW5$QggMJU~cc;&>IXSf+5!8Km~JumSbvG;}bOY^%R zsV6>>ms_lXFU++-L2g qxQN4|WpeiaRu}V-;t=Hh73x-T@y$?LpOQ~7$;sLE<3Q-UI_?Ld^33u8 diff --git a/Ibm1130/1442middle.bmp b/Ibm1130/1442middle.bmp deleted file mode 100644 index af45289fadc0ae1661d2928531ce303e746622da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6278 zcmeHLu~Ne@3^jM$wId^+z<03o51BGTCd%lkWMpMyX6o)GpTr-eFOD5cjY*@BgQF)k zb|hQxBt6@gr1uZ|TjS*!{TSgj5I8-E(ElTV1yl|YfJYzr%c(Emyf}0sjaT!uDq`W9Ei2*%FdLGhlpqlbR z*+{zblDMFn@T6qAvWT+%<1g^t%_rO4aQ<#;*tv2VF=8X Mv+Kv*2kX~yNA{WFA^-pY diff --git a/Ibm1130/HAND.CUR b/Ibm1130/HAND.CUR deleted file mode 100644 index eb0796dd30b18ae73defe98172ce1b6f3802dd91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326 zcmb7;K@Ng26h!A+lkQ|^Vl={%r6&-M#03;?qDScsyaGq)k_9qO!GxWO)4cZow0}Cl z28N=*tcwAARi!9IElg|H_gI>BC%HENRLReEz){=++&dtfdYtb)4s75b4R-Al_UhoT zz;;lU0C - -///////////////////////////////////////////////////////////////////////////// -#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 3497e9b35277686784df49ae5c847dc9522e7791..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 555471 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≶Ou~rp}|VAbsN`FFUhY?=b4>C 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%0DXhsPE+ppIxCb$YehncK4y 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 D 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 z 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

    NCkZpZ8(u!I2MZ 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 z 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 diff --git a/doc/swtp6800MP-A.png b/doc/swtp6800MP-A.png deleted file mode 100644 index 4c2e4b581d8ef20040f04ea888fa0471ac886dc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20448 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 Z)j<>Krsv5MV85xFpSS<<#$yrJ{{cj;0W|;s diff --git a/doc/swtp6800_doc.doc b/doc/swtp6800_doc.doc deleted file mode 100644 index 986f08c0eae61179e284cb21dde235519edc7773..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76800 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 -#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 8cef56ad69bb15ad2ce9f2c3e0e24b140853491c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmXX_U1%It6uxtJvOBxkb$65Pv`uZjHJh25lyuhy!c?K5-R{~FQL;!v9u%LXF-aea zJ`|nZ!7zx)sTN;bIYHfdDIy5jmyQv%Ln-OB1rb_7W_BTY5KXI?)NPsdZtA^oe>mrS z_dDOYCqOb!U~HbGWYKPpz&l1+X~EluroLe0l?N3}LcU7tSb}Ha&;=~1QHv}SMUvQq z4=}0THjhJIZ~P4LIwl}e$7cdeXi$EI4;jYy$&WF)jY+M*$3k*3XK4L&F{1l-b^j_n zl4`^dm2FM;&w%avS76iSC?gyK@_hbkFtueQRL^*m9Ts4%nj0E7qDNvzdZ=K?!(-Km zRwM9LjY#ZE_y_(r8TLuM9`yM5B zdKD$JZ8s&iD%y>O8d;`1Vy~i^A&Z!4i?AaCcgf9#6*|*36Xq;!PY+O%;36!+Ct$*Y zi<0f#2(V|#?^pM71{|x6u?oiFyc)6_AKJ~b-7LBOWgZHe+q}yajM(1VpTazmBx$Mn zNcn@Ua)5bK*2F|?7a^pa7ki(cvLYJ~Fg#D#nC+F?DDu_z-jHjArcjkvhueaf@&Z9MJuD1I(p*AWlI~BO$GDkx81&ixJykScwnCcO>!euB>~TaUni+@xhxcs%7gaXt zO#$K{nbZ+B2v9R@@m&j$wy^-WSFr0_Jhg@5UszB?BQ-$H -#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 -

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