diff --git a/3B2/3b2_cpu.c b/3B2/3b2_cpu.c new file mode 100644 index 00000000..edd06337 --- /dev/null +++ b/3B2/3b2_cpu.c @@ -0,0 +1,3402 @@ +/* 3b2_cpu.c: AT&T 3B2 Model 400 CPU (WE32100) Implementation + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#include + +#include "3b2_cpu.h" +#include "rom_400_bin.h" + +#define MAX_SUB_RETURN_SKIP 9 + +/* RO memory. */ +uint32 *ROM = NULL; + +/* Main memory. */ +uint32 *RAM = NULL; + +/* Save environment for setjmp/longjmp */ +jmp_buf save_env; +volatile uint32 abort_context; + +/* The last decoded instruction */ +instr cpu_instr; + +/* Circular buffer of instructions */ +instr *INST = NULL; +uint32 cpu_hist_size = 0; +uint32 cpu_hist_p = 0; + +t_bool cpu_in_wait = FALSE; + +volatile size_t cpu_exception_stack_depth = 0; +volatile int32 stop_reason; +volatile uint32 abort_reason; + +extern uint16 csr_data; + +/* Register data */ +uint32 R[16]; + +/* Other global CPU state */ +int8 cpu_dtype = -1; /* Default datatype for the current + instruction */ +int8 cpu_etype = -1; /* Currently set expanded datatype */ + +t_bool cpu_nmi = FALSE; /* If set, there has been an NMI */ + +uint8 cpu_ilen = 0; /* Length (in bytes) of instruction + currently being executed */ +t_bool cpu_ex_halt = FALSE; /* Flag to halt on exceptions / + traps */ +t_bool cpu_km = FALSE; /* If true, kernel mode has been forced + for memory access */ + +BITFIELD psw_bits[] = { + BITFFMT(ET,2,%d), /* Exception Type */ + BIT(TM), /* Trace Mask */ + BITFFMT(ISC,4,%d), /* Internal State Code */ + BIT(I), /* Register Initial Context (I) */ + BIT(R), /* Register Initial Context (R) */ + BITFFMT(PM,2,%d), /* Previous Execution Level */ + BITFFMT(CM,2,%d), /* Current Execution Level */ + BITFFMT(IPL,4,%d), /* Interrupt Priority Level */ + BIT(TE), /* Trace Enable */ + BIT(C), /* Carry */ + BIT(V), /* Overflow */ + BIT(Z), /* Zero */ + BIT(N), /* Negative */ + BIT(OE), /* Enable Overflow Trap */ + BIT(CD), /* Cache Disable */ + BIT(QIE), /* Quick-Interrupt Enable */ + BIT(CFD), /* Cache Flush Disable */ + BITNCF(6), /* Unused */ + ENDBITS +}; + +/* Registers. */ +REG cpu_reg[] = { + { HRDATAD (PC, R[NUM_PC], 32, "Program Counter") }, + { HRDATAD (R0, R[0], 32, "General purpose register 0") }, + { HRDATAD (R1, R[1], 32, "General purpose register 1") }, + { HRDATAD (R2, R[2], 32, "General purpose register 2") }, + { HRDATAD (R3, R[3], 32, "General purpose register 3") }, + { HRDATAD (R4, R[4], 32, "General purpose register 4") }, + { HRDATAD (R5, R[5], 32, "General purpose register 5") }, + { HRDATAD (R6, R[6], 32, "General purpose register 6") }, + { HRDATAD (R7, R[7], 32, "General purpose register 7") }, + { HRDATAD (R8, R[8], 32, "General purpose register 8") }, + { HRDATAD (FP, R[NUM_FP], 32, "Frame Pointer") }, + { HRDATAD (AP, R[NUM_AP], 32, "Argument Pointer") }, + { HRDATADF (PSW, R[NUM_PSW], 32, "Processor Status Word", psw_bits) }, + { HRDATAD (SP, R[NUM_SP], 32, "Stack Pointer") }, + { HRDATAD (PCBP, R[NUM_PCBP], 32, "Process Control Block Pointer") }, + { HRDATAD (ISP, R[NUM_ISP], 32, "Interrupt Stack Pointer") }, + { NULL } +}; + +static DEBTAB cpu_deb_tab[] = { + { "READ", READ_MSG, "Memory read activity" }, + { "WRITE", WRITE_MSG, "Memory write activity" }, + { "DECODE", DECODE_MSG, "Instruction decode" }, + { "EXECUTE", EXECUTE_MSG, "Instruction execute" }, + { "INIT", INIT_MSG, "Initialization" }, + { "IRQ", IRQ_MSG, "Interrupt Handling" }, + { "IO", IO_D_MSG, "I/O Dispatch" }, + { "TRACE", TRACE_MSG, "Call Trace" }, + { NULL, 0 } +}; + +UNIT cpu_unit = { UDATA (NULL, UNIT_FIX|UNIT_BINK|UNIT_IDLE, MAXMEMSIZE) }; + +#define UNIT_V_EXHALT (UNIT_V_UF + 0) /* halt to console */ +#define UNIT_EXHALT (1u << UNIT_V_EXHALT) + +MTAB cpu_mod[] = { + { UNIT_MSIZE, (1u << 20), NULL, "1M", + &cpu_set_size, NULL, NULL, "Set Memory to 1M bytes" }, + { UNIT_MSIZE, (1u << 21), NULL, "2M", + &cpu_set_size, NULL, NULL, "Set Memory to 2M bytes" }, + { UNIT_MSIZE, (1u << 22), NULL, "4M", + &cpu_set_size, NULL, NULL, "Set Memory to 4M bytes" }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist, NULL, "Displays instruction history" }, + { MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL }, + { UNIT_EXHALT, UNIT_EXHALT, "Halt on Exception", "EX_HALT", + NULL, NULL, NULL, "Enables Halt on exceptions and traps" }, + { UNIT_EXHALT, 0, "No halt on exception", "NOEX_HALT", + NULL, NULL, NULL, "Disables Halt on exceptions and traps" }, + { 0 } +}; + +DEVICE cpu_dev = { + "CPU", /* Name */ + &cpu_unit, /* Units */ + cpu_reg, /* Registers */ + cpu_mod, /* Modifiers */ + 1, /* Number of Units */ + 16, /* Address radix */ + 32, /* Address width */ + 1, /* Addr increment */ + 16, /* Data radix */ + 8, /* Data width */ + &cpu_ex, /* Examine routine */ + &cpu_dep, /* Deposit routine */ + &cpu_reset, /* Reset routine */ + &cpu_boot, /* Boot routine */ + NULL, /* Attach routine */ + NULL, /* Detach routine */ + NULL, /* Context */ + DEV_DYNM|DEV_DEBUG, /* Flags */ + 0, /* Debug control flags */ + cpu_deb_tab, /* Debug flag names */ + &cpu_set_size, /* Memory size change */ + NULL /* Logical names */ +}; + +#define HWORD_OP_COUNT 11 + +mnemonic hword_ops[HWORD_OP_COUNT] = { + {0x3009, 0, OP_NONE, NA, "MVERNO", -1, -1, -1, -1}, + {0x300d, 0, OP_NONE, NA, "ENBVJMP", -1, -1, -1, -1}, + {0x3013, 0, OP_NONE, NA, "DISVJMP", -1, -1, -1, -1}, + {0x3019, 0, OP_NONE, NA, "MOVBLW", -1, -1, -1, -1}, + {0x301f, 0, OP_NONE, NA, "STREND", -1, -1, -1, -1}, + {0x302f, 1, OP_DESC, WD, "INTACK", -1, -1, -1, -1}, + {0x3035, 0, OP_NONE, NA, "STRCPY", -1, -1, -1, -1}, + {0x3045, 0, OP_NONE, NA, "RETG", -1, -1, -1, -1}, + {0x3061, 0, OP_NONE, NA, "GATE", -1, -1, -1, -1}, + {0x30ac, 0, OP_NONE, NA, "CALLPS", -1, -1, -1, -1}, + {0x30c8, 0, OP_NONE, NA, "RETPS", -1, -1, -1, -1} +}; + +/* Lookup table of operand types. */ +mnemonic ops[256] = { + {0x00, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x01, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x02, 2, OP_COPR, WD, "SPOPRD", -1, -1, -1, -1}, + {0x03, 3, OP_COPR, WD, "SPOPD2", -1, -1, -1, -1}, + {0x04, 2, OP_DESC, WD, "MOVAW", 0, -1, -1, 1}, + {0x05, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x06, 2, OP_COPR, WD, "SPOPRT", -1, -1, -1, -1}, + {0x07, 3, OP_COPR, WD, "SPOPT2", -1, -1, -1, -1}, + {0x08, 0, OP_NONE, NA, "RET", -1, -1, -1, -1}, + {0x09, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x0a, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x0b, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x0c, 2, OP_DESC, WD, "MOVTRW", 0, -1, -1, 1}, + {0x0d, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x0e, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x0f, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x10, 1, OP_DESC, WD, "SAVE", 0, -1, -1, -1}, + {0x11, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x12, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x13, 2, OP_COPR, WD, "SPOPWD", -1, -1, -1, -1}, + {0x14, 1, OP_BYTE, NA, "EXTOP", -1, -1, -1, -1}, + {0x15, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x16, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x17, 2, OP_COPR, WD, "SPOPWT", -1, -1, -1, -1}, + {0x18, 1, OP_DESC, WD, "RESTORE", 0, -1, -1, -1}, + {0x19, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x1a, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x1b, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x1c, 1, OP_DESC, WD, "SWAPWI", -1, -1, -1, 0}, /* 3-122 252 */ + {0x1d, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x1e, 1, OP_DESC, HW, "SWAPHI", -1, -1, -1, 0}, /* 3-122 252 */ + {0x1f, 1, OP_DESC, BT, "SWAPBI", -1, -1, -1, 0}, /* 3-122 252 */ + {0x20, 1, OP_DESC, WD, "POPW", -1, -1, -1, 0}, + {0x21, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x22, 2, OP_COPR, WD, "SPOPRS", -1, -1, -1, -1}, + {0x23, 3, OP_COPR, WD, "SPOPS2", -1, -1, -1, -1}, + {0x24, 1, OP_DESC, NA, "JMP", -1, -1, -1, 0}, + {0x25, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x26, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x27, 0, OP_NONE, NA, "CFLUSH", -1, -1, -1, -1}, + {0x28, 1, OP_DESC, WD, "TSTW", 0, -1, -1, -1}, + {0x29, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x2a, 1, OP_DESC, HW, "TSTH", 0, -1, -1, -1}, + {0x2b, 1, OP_DESC, BT, "TSTB", 0, -1, -1, -1}, + {0x2c, 2, OP_DESC, WD, "CALL", 0, -1, -1, 1}, + {0x2d, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x2e, 0, OP_NONE, NA, "BPT", -1, -1, -1, -1}, + {0x2f, 0, OP_NONE, NA, "WAIT", -1, -1, -1, -1}, + {0x30, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, /* Two-byte instructions */ + {0x31, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x32, 1, OP_COPR, WD, "SPOP", -1, -1, -1, -1}, + {0x33, 2, OP_COPR, WD, "SPOPWS", -1, -1, -1, -1}, + {0x34, 1, OP_DESC, WD, "JSB", -1, -1, -1, 0}, + {0x35, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x36, 1, OP_HALF, NA, "BSBH", -1, -1, -1, 0}, + {0x37, 1, OP_BYTE, NA, "BSBB", -1, -1, -1, 0}, + {0x38, 2, OP_DESC, WD, "BITW", 0, 1, -1, -1}, + {0x39, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x3a, 2, OP_DESC, HW, "BITH", 0, 1, -1, -1}, + {0x3b, 2, OP_DESC, BT, "BITB", 0, 1, -1, -1}, + {0x3c, 2, OP_DESC, WD, "CMPW", 0, 1, -1, -1}, + {0x3d, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x3e, 2, OP_DESC, HW, "CMPH", 0, 1, -1, -1}, + {0x3f, 2, OP_DESC, BT, "CMPB", 0, 1, -1, -1}, + {0x40, 0, OP_NONE, NA, "RGEQ", -1, -1, -1, -1}, + {0x41, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x42, 1, OP_HALF, NA, "BGEH", -1, -1, -1, 0}, + {0x43, 1, OP_BYTE, NA, "BGEB", -1, -1, -1, 0}, + {0x44, 0, OP_NONE, NA, "RGTR", -1, -1, -1, -1}, + {0x45, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x46, 1, OP_HALF, NA, "BGH", -1, -1, -1, 0}, + {0x47, 1, OP_BYTE, NA, "BGB", -1, -1, -1, 0}, + {0x48, 0, OP_NONE, NA, "RLSS", -1, -1, -1, 0}, + {0x49, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x4a, 1, OP_HALF, NA, "BLH", -1, -1, -1, 0}, + {0x4b, 1, OP_BYTE, NA, "BLB", -1, -1, -1, 0}, + {0x4c, 0, OP_NONE, NA, "RLEQ", -1, -1, -1, -1}, + {0x4d, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x4e, 1, OP_HALF, NA, "BLEH", -1, -1, -1, 0}, + {0x4f, 1, OP_BYTE, NA, "BLEB", -1, -1, -1, 0}, + {0x50, 0, OP_NONE, NA, "BGEQU", -1, -1, -1, 0}, /* aka BCC */ + {0x51, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x52, 1, OP_HALF, NA, "BGEUH", -1, -1, -1, 0}, /* aka BCCH */ + {0x53, 1, OP_BYTE, NA, "BGEUB", -1, -1, -1, 0}, /* aka BCCB */ + {0x54, 0, OP_NONE, NA, "RGTRU", -1, -1, -1, -1}, + {0x55, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x56, 1, OP_HALF, NA, "BGUH", -1, -1, -1, 0}, + {0x57, 1, OP_BYTE, NA, "BGUB", -1, -1, -1, 0}, + {0x58, 0, OP_NONE, NA, "RLSSU", -1, -1, -1, 0}, /* aka BCS */ + {0x59, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x5a, 1, OP_HALF, NA, "BLUH", -1, -1, -1, 0}, /* aka BCSH */ + {0x5b, 1, OP_BYTE, NA, "BLUB", -1, -1, -1, 0}, /* aka BCSB */ + {0x5c, 0, OP_NONE, NA, "RLEQU", -1, -1, -1, -1}, + {0x5d, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x5e, 1, OP_HALF, NA, "BLEUH", -1, -1, -1, 0}, + {0x5f, 1, OP_BYTE, NA, "BLEUB", -1, -1, -1, 0}, + {0x60, 0, OP_NONE, NA, "RVC", -1, -1, -1, -1}, + {0x61, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x62, 1, OP_HALF, NA, "BVCH", -1, -1, -1, 0}, + {0x63, 1, OP_BYTE, NA, "BVCB", -1, -1, -1, 0}, + {0x64, 0, OP_NONE, NA, "RNEQU", -1, -1, -1, -1}, + {0x65, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x66, 1, OP_HALF, NA, "BNEH", -1, -1, -1, 0}, /* duplicate of 76 */ + {0x67, 1, OP_BYTE, NA, "BNEB", -1, -1, -1, 0}, /* duplicate of 77*/ + {0x68, 0, OP_NONE, NA, "RVS", -1, -1, -1, -1}, + {0x69, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x6a, 1, OP_HALF, NA, "BVSH", -1, -1, -1, 0}, + {0x6b, 1, OP_BYTE, NA, "BVSB", -1, -1, -1, 0}, + {0x6c, 0, OP_NONE, NA, "REQLU", -1, -1, -1, -1}, + {0x6d, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x6e, 1, OP_HALF, NA, "BEH", -1, -1, -1, 0}, /* duplicate of 7e */ + {0x6f, 1, OP_BYTE, NA, "BEB", -1, -1, -1, 0}, /* duplicate of 7f */ + {0x70, 0, OP_NONE, NA, "NOP", -1, -1, -1, -1}, + {0x71, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x72, 0, OP_NONE, NA, "NOP3", -1, -1, -1, -1}, + {0x73, 0, OP_NONE, NA, "NOP2", -1, -1, -1, -1}, + {0x74, 0, OP_NONE, NA, "RNEQ", -1, -1, -1, -1}, + {0x75, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x76, 1, OP_HALF, NA, "BNEH", -1, -1, -1, 0}, /* duplicate of 66 */ + {0x77, 1, OP_BYTE, NA, "BNEB", -1, -1, -1, 0}, /* duplicate of 67 */ + {0x78, 0, OP_NONE, NA, "RSB", -1, -1, -1, -1}, + {0x79, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x7a, 1, OP_HALF, NA, "BRH", -1, -1, -1, 0}, + {0x7b, 1, OP_BYTE, NA, "BRB", -1, -1, -1, 0}, + {0x7c, 0, OP_NONE, NA, "REQL", -1, -1, -1, -1}, + {0x7d, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x7e, 1, OP_HALF, NA, "BEH", -1, -1, -1, 0}, /* duplicate of 6e */ + {0x7f, 1, OP_BYTE, NA, "BEB", -1, -1, -1, 0}, /* duplicate of 6f */ + {0x80, 1, OP_DESC, WD, "CLRW", -1, -1, -1, 0}, + {0x81, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x82, 1, OP_DESC, HW, "CLRH", -1, -1, -1, 0}, + {0x83, 1, OP_DESC, BT, "CLRB", -1, -1, -1, 0}, + {0x84, 2, OP_DESC, WD, "MOVW", 0, -1, -1, 1}, + {0x85, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x86, 2, OP_DESC, HW, "MOVH", 0, -1, -1, 1}, + {0x87, 2, OP_DESC, BT, "MOVB", 0, -1, -1, 1}, + {0x88, 2, OP_DESC, WD, "MCOMW", 0, -1, -1, 1}, + {0x89, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x8a, 2, OP_DESC, HW, "MCOMH", 0, -1, -1, 1}, + {0x8b, 2, OP_DESC, BT, "MCOMB", 0, -1, -1, 1}, + {0x8c, 2, OP_DESC, WD, "MNEGW", 0, -1, -1, 1}, + {0x8d, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x8e, 2, OP_DESC, HW, "MNEGH", 0, -1, -1, 1}, + {0x8f, 2, OP_DESC, BT, "MNEGB", 0, -1, -1, 1}, + {0x90, 1, OP_DESC, WD, "INCW", -1, -1, -1, 0}, + {0x91, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x92, 1, OP_DESC, HW, "INCH", -1, -1, -1, 0}, + {0x93, 1, OP_DESC, BT, "INCB", -1, -1, -1, 0}, + {0x94, 1, OP_DESC, WD, "DECW", -1, -1, -1, 0}, + {0x95, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x96, 1, OP_DESC, HW, "DECH", -1, -1, -1, 0}, + {0x97, 1, OP_DESC, BT, "DECB", -1, -1, -1, 0}, + {0x98, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x99, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x9a, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x9b, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x9c, 2, OP_DESC, WD, "ADDW2", 0, -1, -1, 1}, + {0x9d, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x9e, 2, OP_DESC, HW, "ADDH2", 0, -1, -1, 1}, + {0x9f, 2, OP_DESC, BT, "ADDB2", 0, -1, -1, 1}, + {0xa0, 1, OP_DESC, WD, "PUSHW", 0, -1, -1, -1}, + {0xa1, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xa2, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xa3, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xa4, 2, OP_DESC, WD, "MODW2", 0, -1, -1, 1}, + {0xa5, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xa6, 2, OP_DESC, HW, "MODH2", 0, -1, -1, 1}, + {0xa7, 2, OP_DESC, BT, "MODB2", 0, -1, -1, 1}, + {0xa8, 2, OP_DESC, WD, "MULW2", 0, -1, -1, 1}, + {0xa9, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xaa, 2, OP_DESC, HW, "MULH2", 0, -1, -1, 1}, + {0xab, 2, OP_DESC, BT, "MULB2", 0, -1, -1, 1}, + {0xac, 2, OP_DESC, WD, "DIVW2", 0, -1, -1, 1}, + {0xad, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xae, 2, OP_DESC, HW, "DIVH2", 0, -1, -1, 1}, + {0xaf, 2, OP_DESC, BT, "DIVB2", 0, -1, -1, 1}, + {0xb0, 2, OP_DESC, WD, "ORW2", 0, -1, -1, 1}, + {0xb1, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xb2, 2, OP_DESC, HW, "ORH2", 0, -1, -1, 1}, + {0xb3, 2, OP_DESC, BT, "ORB2", 0, -1, -1, 1}, + {0xb4, 2, OP_DESC, WD, "XORW2", 0, -1, -1, 1}, + {0xb5, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xb6, 2, OP_DESC, HW, "XORH2", 0, -1, -1, 1}, + {0xb7, 2, OP_DESC, BT, "XORB2", 0, -1, -1, 1}, + {0xb8, 2, OP_DESC, WD, "ANDW2", 0, -1, -1, 1}, + {0xb9, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xba, 2, OP_DESC, HW, "ANDH2", 0, -1, -1, 1}, + {0xbb, 2, OP_DESC, BT, "ANDB2", 0, -1, -1, 1}, + {0xbc, 2, OP_DESC, WD, "SUBW2", 0, -1, -1, 1}, + {0xbd, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xbe, 2, OP_DESC, HW, "SUBH2", 0, -1, -1, 1}, + {0xbf, 2, OP_DESC, BT, "SUBB2", 0, -1, -1, 1}, + {0xc0, 3, OP_DESC, WD, "ALSW3", 0, 1, -1, 2}, + {0xc1, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xc2, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xc3, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xc4, 3, OP_DESC, WD, "ARSW3", 0, 1, -1, 2}, + {0xc5, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xc6, 3, OP_DESC, HW, "ARSH3", 0, 1, -1, 2}, + {0xc7, 3, OP_DESC, BT, "ARSB3", 0, 1, -1, 2}, + {0xc8, 4, OP_DESC, WD, "INSFW", 0, 1, 2, 3}, + {0xc9, -1, OP_DESC, NA, "???", -1, -1, -1, -1}, + {0xca, 4, OP_DESC, HW, "INSFH", 0, 1, 2, 3}, + {0xcb, 4, OP_DESC, BT, "INSFB", 0, 1, 2, 3}, + {0xcc, 4, OP_DESC, WD, "EXTFW", 0, 1, 2, 3}, + {0xcd, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xce, 4, OP_DESC, HW, "EXTFH", 0, 1, 2, 3}, + {0xcf, 4, OP_DESC, BT, "EXTFB", 0, 1, 2, 3}, + {0xd0, 3, OP_DESC, WD, "LLSW3", 0, 1, -1, 2}, + {0xd1, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xd2, 3, OP_DESC, HW, "LLSH3", 0, 1, -1, 2}, + {0xd3, 3, OP_DESC, BT, "LLSB3", 0, 1, -1, 2}, + {0xd4, 3, OP_DESC, WD, "LRSW3", 0, 1, -1, 2}, + {0xd5, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xd6, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xd7, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xd8, 3, OP_DESC, WD, "ROTW", 0, 1, -1, 2}, /* 3-108 238 */ + {0xd9, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xda, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xdb, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xdc, 3, OP_DESC, WD, "ADDW3", 0, 1, -1, 2}, + {0xdd, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xde, 3, OP_DESC, HW, "ADDH3", 0, 1, -1, 2}, + {0xdf, 3, OP_DESC, BT, "ADDB3", 0, 1, -1, 2}, + {0xe0, 1, OP_DESC, WD, "PUSHAW", 0, -1, -1, -1}, + {0xe1, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xe2, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xe3, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xe4, 3, OP_DESC, WD, "MODW3", 0, 1, -1, 2}, + {0xe5, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xe6, 3, OP_DESC, HW, "MODH3", 0, 1, -1, 2}, + {0xe7, 3, OP_DESC, BT, "MODB3", 0, 1, -1, 2}, + {0xe8, 3, OP_DESC, WD, "MULW3", 0, 1, -1, 2}, + {0xe9, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xea, 3, OP_DESC, HW, "MULH3", 0, 1, -1, 2}, + {0xeb, 3, OP_DESC, BT, "MULB3", 0, 1, -1, 2}, + {0xec, 3, OP_DESC, WD, "DIVW3", 0, 1, -1, 2}, + {0xed, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xee, 3, OP_DESC, HW, "DIVH3", 0, 1, -1, 2}, + {0xef, 3, OP_DESC, BT, "DIVB3", 0, 1, -1, 2}, + {0xf0, 3, OP_DESC, WD, "ORW3", 0, 1, -1, 2}, + {0xf1, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xf2, 3, OP_DESC, HW, "ORH3", 0, 1, -1, 2}, + {0xf3, 3, OP_DESC, BT, "ORB3", 0, 1, -1, 2}, + {0xf4, 3, OP_DESC, WD, "XORW3", 0, 1, -1, 2}, + {0xf5, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xf6, 3, OP_DESC, HW, "XORH3", 0, 1, -1, 2}, + {0xf7, 3, OP_DESC, BT, "XORB3", 0, 1, -1, 2}, + {0xf8, 3, OP_DESC, WD, "ANDW3", 0, 1, -1, 2}, + {0xf9, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xfa, 3, OP_DESC, HW, "ANDH3", 0, 1, -1, 2}, + {0xfb, 3, OP_DESC, BT, "ANDB3", 0, 1, -1, 2}, + {0xfc, 3, OP_DESC, WD, "SUBW3", 0, 1, -1, 2}, + {0xfd, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0xfe, 3, OP_DESC, HW, "SUBH3", 0, 1, -1, 2}, + {0xff, 3, OP_DESC, BT, "SUBB3", 0, 1, -1, 2} +}; + +/* from MAME (src/devices/cpu/m68000/m68kcpu.c) */ +const uint8 shift_8_table[65] = +{ + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff +}; +const uint16 shift_16_table[65] = +{ + 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, + 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff +}; +const uint32 shift_32_table[65] = +{ + 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, + 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, + 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000, + 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, + 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, + 0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff +}; + +void cpu_load_rom() +{ + uint32 i, index, sc, mask, val; + + if (ROM == NULL) { + return; + } + + for (i = 0; i < BOOT_CODE_SIZE; i++) { + val = BOOT_CODE_ARRAY[i]; + sc = (~(i & 3) << 3) & 0x1f; + mask = 0xffu << sc; + index = i >> 2; + + ROM[index] = (ROM[index] & ~mask) | (val << sc); + } +} + +t_stat cpu_boot(int32 unit_num, DEVICE *dptr) +{ + /* + * page 2-52 (pdf page 85) + * + * 1. Change to physical address mode + * 2. Fetch the word at physical address 0x80 and store it in + * the PCBP register. + * 3. Fetch the word at the PCB address and store it in the + * PSW. + * 4. Fetch the word at PCB address + 4 bytes and store it + * in the PC. + * 5. Fetch the word at PCB address + 8 bytes and store it + * in the SP. + * 6. Fetch the word at PCB address + 12 bytes and store it + * in the PCB, if bit I in PSW is set. + */ + + mmu_disable(); + + R[NUM_PCBP] = pread_w(0x80); + R[NUM_PSW] = pread_w(R[NUM_PCBP]); + R[NUM_PC] = pread_w(R[NUM_PCBP] + 4); + R[NUM_SP] = pread_w(R[NUM_PCBP] + 8); + + if (R[NUM_PSW] & PSW_I_MASK) { + R[NUM_PSW] &= ~PSW_I_MASK; + R[NUM_PCBP] += 12; + } + + /* set ISC to External Reset */ + R[NUM_PSW] &= ~PSW_ISC_MASK; + R[NUM_PSW] |= 3 << PSW_ISC ; + + sim_debug(EXECUTE_MSG, &cpu_dev, + ">>> CPU BOOT/RESET COMPLETE. PC=%08x SP=%08x\n", + R[NUM_PC], R[NUM_SP]); + + return SCPE_OK; +} + +t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) +{ + uint32 uaddr = (uint32) addr; + uint8 value; + t_stat succ; + + if (vptr == NULL) { + return SCPE_ARG; + } + + if (sw & EX_V_FLAG) { + succ = examine(uaddr, &value); + *vptr = value; + return succ; + } else { + if (!(addr_is_rom(uaddr) || addr_is_mem(uaddr) || addr_is_io(uaddr))) { + *vptr = 0; + return SCPE_NXM; + } + *vptr = (uint32) pread_b(uaddr); + return SCPE_OK; + } +} + +t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) +{ + uint32 uaddr = (uint32) addr; + + if (sw & EX_V_FLAG) { + return deposit(uaddr, (uint8) val); + } else { + if (!(addr_is_rom(uaddr) || addr_is_mem(uaddr) || addr_is_io(uaddr))) { + return SCPE_NXM; + } + pwrite_b(uaddr, (uint8) val); + return SCPE_OK; + } +} + +t_stat cpu_reset(DEVICE *dptr) +{ + int i; + + if (!sim_is_running) { + /* Clear registers */ + for (i = 0; i < 16; i++) { + R[i] = 0; + } + + /* Allocate memory */ + if (ROM == NULL) { + ROM = (uint32 *) calloc(BOOT_CODE_SIZE >> 2, sizeof(uint32)); + if (ROM == NULL) { + return SCPE_MEM; + } + + memset(ROM, 0, BOOT_CODE_SIZE >> 2); + } + + if (RAM == NULL) { + RAM = (uint32 *) calloc((size_t)(MEM_SIZE >> 2), sizeof(uint32)); + if (RAM == NULL) { + return SCPE_MEM; + } + + memset(RAM, 0, (size_t)(MEM_SIZE >> 2)); + + sim_vm_is_subroutine_call = cpu_is_pc_a_subroutine_call; + } + + cpu_load_rom(); + } + + abort_context = C_NONE; + cpu_nmi = FALSE; + + cpu_hist_p = 0; + cpu_in_wait = FALSE; + + sim_brk_types = SWMASK('E'); + sim_brk_dflt = SWMASK('E'); + + return SCPE_OK; +} + +static const char *cpu_next_caveats = +"The NEXT command in this 3B2 architecture simulator currently will\n" +"enable stepping across subroutine calls which are initiated by the\n" +"JSB, CALL and CALLPS instructions.\n" +"This stepping works by dynamically establishing breakpoints at the\n" +"memory address immediately following the instruction which initiated\n" +"the subroutine call. These dynamic breakpoints are automatically\n" +"removed once the simulator returns to the sim> prompt for any reason.\n" +"If the called routine returns somewhere other than one of these\n" +"locations due to a trap, stack unwind or any other reason, instruction\n" +"execution will continue until some other reason causes execution to stop.\n"; + +t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs) +{ + static t_addr returns[MAX_SUB_RETURN_SKIP+1] = {0}; + static t_bool caveats_displayed = FALSE; + int i; + + if (!caveats_displayed) { + caveats_displayed = TRUE; + sim_printf ("%s", cpu_next_caveats); + } + + /* get data */ + if (SCPE_OK != get_aval (R[NUM_PC], &cpu_dev, &cpu_unit)) { + return FALSE; + } + + switch (sim_eval[0]) { + case JSB: + case CALL: + case CALLPS: + returns[0] = R[NUM_PC] + (unsigned int) (1 - fprint_sym(stdnul, R[NUM_PC], + sim_eval, &cpu_unit, + SWMASK ('M'))); + for (i=1; i 0) { + if (INST != NULL) { + free(INST); + } + INST = (instr *)calloc(size, sizeof(instr)); + if (INST == NULL) { + return SCPE_MEM; + } + memset(INST, 0, sizeof(instr) * size); + cpu_hist_size = size; + } + + return SCPE_OK; +} + +void fprint_sym_m(FILE *st, instr *ip) +{ + int32 i; + + if (ip == NULL || ip->mn == NULL) { + fprintf(st, "???"); + return; + } + + fprintf(st, "%s", ip->mn->mnemonic); + + if (ip->mn->op_count > 0) { + fputc(' ', st); + } + + /* Show the operand mnemonics */ + for (i = 0; i < ip->mn->op_count; i++) { + cpu_show_operand(st, &ip->operands[i]); + if (i < ip->mn->op_count - 1) { + fputc(',', st); + } + } +} + +t_stat cpu_show_hist(FILE *st, UNIT *uptr, int32 val, CONST void *desc) +{ + uint32 i; + size_t j, count; + char *cptr = (char *) desc; + t_stat result; + instr *ip; + + int32 di; + + if (cpu_hist_size == 0) { + return SCPE_NOFNC; + } + + /* 'count' is the number of history entries the user wants */ + + if (cptr) { + count = (size_t) get_uint(cptr, 10, cpu_hist_size, &result); + if ((result != SCPE_OK) || (count == 0)) { + return SCPE_ARG; + } + } else { + count = cpu_hist_size; + } + + /* Position for reading from ring buffer */ + di = (int32) (cpu_hist_p - count); + + if (di < 0) { + di = di + (int32) cpu_hist_size; + } + + fprintf(st, "PSW SP PC IR\n"); + + for (i = 0; i < count; i++) { + ip = &INST[(di++) % (int32) cpu_hist_size]; + if (ip->valid) { + /* Show the opcode mnemonic */ + fprintf(st, "%08x %08x %08x ", ip->psw, ip->sp, ip->pc); + /* Show the operand data */ + if (ip->mn == NULL || ip->mn->op_count < 0) { + fprintf(st, "???"); + } else { + fprint_sym_m(st, ip); + if (ip->mn->op_count > 0 && ip->mn->mode == OP_DESC) { + fprintf(st, "\n "); + for (j = 0; j < (uint32) ip->mn->op_count; j++) { + fprintf(st, "%08x", ip->operands[j].data); + if (j < (uint32) ip->mn->op_count - 1) { + fputc(' ', st); + } + } + } + } + fputc('\n', st); + } + } + + + return SCPE_OK; +} + +void cpu_register_name(uint8 reg, char *buf, size_t len) { + switch(reg) { + case 9: + snprintf(buf, len, "%%fp"); + break; + case 10: + snprintf(buf, len, "%%ap"); + break; + case 11: + snprintf(buf, len, "%%psw"); + break; + case 12: + snprintf(buf, len, "%%sp"); + break; + case 13: + snprintf(buf, len, "%%pcbp"); + break; + case 14: + snprintf(buf, len, "%%isp"); + break; + case 15: + snprintf(buf, len, "%%pc"); + break; + default: + snprintf(buf, len, "%%r%d", reg); + break; + } +} + +void cpu_show_operand(FILE *st, operand *op) +{ + char reg_name[8]; + + if (op->etype != -1) { + switch(op->etype) { + case 0: + fprintf(st, "{uword}"); + break; + case 2: + fprintf(st, "{uhalf}"); + break; + case 3: + fprintf(st, "{ubyte}"); + break; + case 4: + fprintf(st, "{word}"); + break; + case 6: + fprintf(st, "{half}"); + break; + case 7: + fprintf(st, "{sbyte}"); + break; + } + } + + switch(op->mode) { + case 0: + case 1: + case 2: + case 3: + fprintf(st, "&0x%x", op->embedded.b); + break; + case 4: + if (op->reg == 15) { + fprintf(st, "&0x%x", op->embedded.w); + } else { + cpu_register_name(op->reg, reg_name, 8); + fprintf(st, "%s", reg_name); + } + break; + case 5: + if (op->reg == 15) { + fprintf(st, "&0x%x", op->embedded.w); + } else { + cpu_register_name(op->reg, reg_name, 8); + fprintf(st, "(%s)", reg_name); + } + break; + case 6: /* FP Short Offset */ + if (op->reg == 15) { + fprintf(st, "&0x%x", op->embedded.w); + } else { + fprintf(st, "%d(%%fp)", op->reg); + } + break; + case 7: /* AP Short Offset */ + if (op->reg == 15) { + fprintf(st, "$0x%x", op->embedded.w); + } else { + fprintf(st, "%d(%%ap)", op->embedded.w); + } + break; + case 8: + cpu_register_name(op->reg, reg_name, 8); + fprintf(st, "0x%x(%s)", (int32)op->embedded.w, reg_name); + break; + case 9: + cpu_register_name(op->reg, reg_name, 8); + fprintf(st, "*0x%x(%s)", (int32)op->embedded.w, reg_name); + break; + case 10: + cpu_register_name(op->reg, reg_name, 8); + fprintf(st, "0x%x(%s)", (int16)op->embedded.w, reg_name); + break; + case 11: + cpu_register_name(op->reg, reg_name, 8); + fprintf(st, "*0x%x(%s)", (int16)op->embedded.w, reg_name); + break; + case 12: + cpu_register_name(op->reg, reg_name, 8); + fprintf(st, "%d(%s)", (int8)op->embedded.w, reg_name); + break; + case 13: + cpu_register_name(op->reg, reg_name, 8); + fprintf(st, "*%d(%s)", (int8)op->embedded.w, reg_name); + break; + case 14: + if (op->reg == 15) { + fprintf(st, "*$0x%x", op->embedded.w); + } + break; + case 15: + fprintf(st, "&%d", (int32)op->embedded.w); + break; + } +} + +t_stat cpu_set_size(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + uint32 *nRAM = NULL; + uint32 uval = (uint32) val; + + if ((val <= 0) || (val > MAXMEMSIZE)) { + return SCPE_ARG; + } + + /* Do (re-)allocation for memory. */ + + nRAM = (uint32 *) calloc(uval >> 2, sizeof(uint32)); + + if (nRAM == NULL) { + return SCPE_MEM; + } + + free(RAM); + RAM = nRAM; + + MEM_SIZE = uval; + + memset(RAM, 0, (size_t)(MEM_SIZE >> 2)); + + return SCPE_OK; +} + +static SIM_INLINE void clear_instruction(instr *inst) +{ + uint8 i; + + inst->mn = NULL; + inst->psw = 0; + inst->sp = 0; + inst->pc = 0; + + for (i = 0; i < 4; i++) { + inst->operands[i].mode = 0; + inst->operands[i].reg = 0; + inst->operands[i].dtype = -1; + inst->operands[i].etype = -1; + inst->operands[i].embedded.w = 0; + inst->operands[i].data = 0; + } +} + +/* + * Decode a single descriptor-defined operand from the instruction + * stream. Returns the number of bytes consumed during decode. + */ +static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number) +{ + uint8 desc; + uint8 offset = 0; + operand *oper = &instr->operands[op_number]; + + /* Set the default data type if none is already set */ + if (cpu_dtype == -1) { + cpu_dtype = instr->mn->dtype; + } + + /* Read in the descriptor byte */ + desc = read_b(pa + offset++, ACC_OF); + + oper->mode = (desc >> 4) & 0xf; + oper->reg = desc & 0xf; + oper->dtype = instr->mn->dtype; + oper->etype = cpu_etype; + + switch (oper->mode) { + case 0: /* Positive Literal */ + case 1: /* Positive Literal */ + case 2: /* Positive Literal */ + case 3: /* Positive Literal */ + case 15: /* Negative literal */ + oper->embedded.b = (uint8)desc; + oper->data = oper->embedded.b; + break; + case 4: /* Word Immediate, Register Mode */ + switch (oper->reg) { + case 15: /* Word Immediate */ + oper->embedded.w = (uint32) read_b(pa + offset++, ACC_OF); + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 8u; + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 16u; + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 24u; + oper->data = oper->embedded.w; + break; + default: /* Register mode */ + oper->data = R[oper->reg]; + break; + } + break; + case 5: /* Halfword Immediate, Register Deferred Mode */ + switch (oper->reg) { + case 15: /* Halfword Immediate */ + oper->embedded.h = (uint16) read_b(pa + offset++, ACC_OF); + oper->embedded.h |= ((uint16) read_b(pa + offset++, ACC_OF)) << 8u; + oper->data = oper->embedded.h; + break; + case 11: /* INVALID */ + cpu_abort(NORMAL_EXCEPTION, INVALID_DESCRIPTOR); + return offset; + default: /* Register deferred mode */ + oper->data = R[oper->reg]; + break; + } + break; + case 6: /* Byte Immediate, FP Short Offset */ + switch (oper->reg) { + case 15: /* Byte Immediate */ + oper->embedded.b = read_b(pa + offset++, ACC_OF); + oper->data = oper->embedded.b; + break; + default: /* FP Short Offset */ + oper->embedded.b = oper->reg; + oper->data = oper->embedded.b; + break; + } + break; + case 7: /* Absolute, AP Short Offset */ + switch (oper->reg) { + case 15: /* Absolute */ + oper->embedded.w = (uint32) read_b(pa + offset++, ACC_OF); + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 8u; + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 16u; + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 24u; + oper->data = oper->embedded.w; + break; + default: /* AP Short Offset */ + oper->embedded.b = oper->reg; + oper->data = oper->embedded.b; + break; + } + break; + case 8: /* Word Displacement */ + case 9: /* Word Displacement Deferred */ + oper->embedded.w = (uint32) read_b(pa + offset++, ACC_OF); + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 8u; + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 16u; + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 24u; + oper->data = oper->embedded.w; + break; + case 10: /* Halfword Displacement */ + case 11: /* Halfword Displacement Deferred */ + oper->embedded.h = read_b(pa + offset++, ACC_OF); + oper->embedded.h |= ((uint16) read_b(pa + offset++, ACC_OF)) << 8u; + oper->data = oper->embedded.h; + break; + case 12: /* Byte Displacement */ + case 13: /* Byte Displacement Deferred */ + oper->embedded.b = read_b(pa + offset++, ACC_OF); + oper->data = oper->embedded.b; + break; + case 14: /* Absolute Deferred, Extended-Operand */ + switch (oper->reg) { + case 15: /* Absolute Deferred */ + oper->embedded.w = (uint32) read_b(pa + offset++, ACC_OF); + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 8u; + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 16u; + oper->embedded.w |= ((uint32) read_b(pa + offset++, ACC_OF)) << 24u; + break; + case 0: + case 2: + case 3: + case 4: + case 6: + case 7: /* Expanded Datatype */ + /* Recursively decode the remainder of the operand after + storing the expanded datatype */ + cpu_etype = (int8) oper->reg; + oper->etype = cpu_etype; + offset += decode_operand(pa + offset, instr, op_number); + break; + default: + cpu_abort(NORMAL_EXCEPTION, RESERVED_DATATYPE); + break; + } + break; + default: + cpu_abort(NORMAL_EXCEPTION, INVALID_DESCRIPTOR); + } + + return offset; +} + +/* + * Decode the instruction currently being pointed at by the PC. + * This routine does the following: + * 1. Read the opcode. + * 2. Determine the number of operands to decode based on + * the opcode type. + * 3. Fetch each opcode from main memory. + * + * This routine may alter the PSW's ET (Exception Type) and + * ISC (Internal State Code) registers if an exceptional condition + * is encountered during decode. + */ +uint8 decode_instruction(instr *instr) +{ + uint8 offset = 0; + uint8 b1, b2; + uint16 hword_op; + uint32 pa; + mnemonic *mn = NULL; + int i; + + pa = R[NUM_PC]; + + /* Store off the PC and and PSW for history keeping */ + instr->psw = R[NUM_PSW]; + instr->sp = R[NUM_SP]; + instr->pc = pa; + + /* Reset our data types */ + cpu_etype = -1; + cpu_dtype = -1; + + if (read_operand(pa + offset++, &b1) != SCPE_OK) { + /* We tried to read out of a page that doesn't exist. We + need to let the operating system handle it.*/ + cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); + return offset; + } + + /* It should never, ever happen that operand fetch + would cause a page fault. */ + + if (b1 == 0x30) { + read_operand(pa + offset++, &b2); + hword_op = (uint16) ((uint16)b1 << 8) | (uint16) b2; + for (i = 0; i < HWORD_OP_COUNT; i++) { + if (hword_ops[i].opcode == hword_op) { + mn = &hword_ops[i]; + break; + } + } + } else { + mn = &ops[b1]; + } + + if (mn == NULL) { + cpu_abort(NORMAL_EXCEPTION, ILLEGAL_OPCODE); + return offset; + } + + instr->mn = mn; + + if (mn->op_count < 0) { + cpu_abort(NORMAL_EXCEPTION, ILLEGAL_OPCODE); + return offset; + } + + if (mn->op_count == 0) { + /* Nothing else to do, we're done decoding. */ + return offset; + } + + switch (mn->mode) { + case OP_NONE: + break; + case OP_BYTE: + instr->operands[0].embedded.b = read_b(pa + offset++, ACC_OF); + instr->operands[0].mode = 6; + instr->operands[0].reg = 15; + break; + case OP_HALF: + instr->operands[0].embedded.h = read_b(pa + offset++, ACC_OF); + instr->operands[0].embedded.h |= read_b(pa + offset++, ACC_OF) << 8; + instr->operands[0].mode = 5; + instr->operands[0].reg = 15; + break; + case OP_COPR: + instr->operands[0].embedded.w = (uint32) read_b(pa + offset++, ACC_OF); + instr->operands[0].embedded.w |= (uint32) read_b(pa + offset++, ACC_OF) << 8; + instr->operands[0].embedded.w |= (uint32) read_b(pa + offset++, ACC_OF) << 16; + instr->operands[0].embedded.w |= (uint32) read_b(pa + offset++, ACC_OF) << 24; + instr->operands[0].mode = 4; + instr->operands[0].reg = 15; + + /* Decode subsequent operands */ + for (i = 1; i < mn->op_count; i++) { + offset += decode_operand(pa + offset, instr, (uint8) i); + } + + break; + case OP_DESC: + for (i = 0; i < mn->op_count; i++) { + offset += decode_operand(pa + offset, instr, (uint8) i); + } + break; + } + + return offset; +} + +static SIM_INLINE void cpu_context_switch_3(uint32 new_pcbp) +{ + if (R[NUM_PSW] & PSW_R_MASK) { + + R[0] = R[NUM_PCBP] + 64; + R[2] = read_w(R[0], ACC_AF); + R[0] += 4; + + while (R[2] != 0) { + R[1] = read_w(R[0], ACC_AF); + R[0] += 4; + + /* Execute MOVBLW instruction inside this loop */ + while (R[2] != 0) { + write_w(R[1], read_w(R[0], ACC_AF)); + R[2]--; + R[0] += 4; + R[1] += 4; + } + + R[2] = read_w(R[0], ACC_AF); + R[0] += 4; + } + + R[0] = R[0] + 4; + } +} + +static SIM_INLINE void cpu_context_switch_2(uint32 new_pcbp) +{ + R[NUM_PCBP] = new_pcbp; + + /* Put new PSW, PC and SP values from PCB into registers */ + R[NUM_PSW] = read_w(R[NUM_PCBP], ACC_AF); + R[NUM_PSW] &= ~PSW_TM_MASK; /* Clear TM */ + R[NUM_PC] = read_w(R[NUM_PCBP] + 4, ACC_AF); + R[NUM_SP] = read_w(R[NUM_PCBP] + 8, ACC_AF); + + /* If i-bit is set, increment PCBP past initial context area */ + if (R[NUM_PSW] & PSW_I_MASK) { + R[NUM_PSW] &= ~PSW_I_MASK; + R[NUM_PCBP] += 12; + } +} + +static SIM_INLINE void cpu_context_switch_1(uint32 new_pcbp) +{ + /* Save the current PC in PCB */ + write_w(R[NUM_PCBP] + 4, R[NUM_PC]); + + /* Copy the 'R' flag from the new PSW to the old PSW */ + R[NUM_PSW] &= ~PSW_R_MASK; + R[NUM_PSW] |= (read_w(new_pcbp, ACC_AF) & PSW_R_MASK); + + /* Save current PSW and SP in PCB */ + write_w(R[NUM_PCBP], R[NUM_PSW]); + write_w(R[NUM_PCBP] + 8, R[NUM_SP]); + + /* If R is set, save current R0-R8/FP/AP in PCB */ + if (R[NUM_PSW] & PSW_R_MASK) { + write_w(R[NUM_PCBP] + 24, R[NUM_FP]); + write_w(R[NUM_PCBP] + 28, R[0]); + write_w(R[NUM_PCBP] + 32, R[1]); + write_w(R[NUM_PCBP] + 36, R[2]); + write_w(R[NUM_PCBP] + 40, R[3]); + write_w(R[NUM_PCBP] + 44, R[4]); + write_w(R[NUM_PCBP] + 48, R[5]); + write_w(R[NUM_PCBP] + 52, R[6]); + write_w(R[NUM_PCBP] + 56, R[7]); + write_w(R[NUM_PCBP] + 60, R[8]); + write_w(R[NUM_PCBP] + 20, R[NUM_AP]); + + R[NUM_FP] = R[NUM_PCBP] + 52; + } +} + +t_bool cpu_on_interrupt(uint8 ipl) +{ + uint32 new_pcbp; + uint16 id = ipl; /* TODO: Does this need to be uint16? */ + + /* + * "If a nonmaskable interrupt request is received, an auto-vector + * interrupt acknowledge cycle is performed (as if an autovector + * interrupt at level 0 was being acknowledged) and no + * Interrupt-ID is fetched. The value 0 is used as the ID." + */ + if (cpu_nmi) { + id = 0; + } + + cpu_km = TRUE; + + if ((R[NUM_PSW] & PSW_QIE_MASK) >> PSW_QIE) { + /* TODO: Maybe implement quick interrupts at some point, but + the 3B2 ROM and SVR3 don't appear to use them. */ + assert(0); + } + + new_pcbp = read_w(0x8c + (4 * id), ACC_AF); + + /* Save the old PCBP */ + irq_push_word(R[NUM_PCBP]); + + /* Set ISC, TM, and ET to 0, 0, 1 before saving */ + R[NUM_PSW] &= ~(PSW_ISC_MASK|PSW_TM_MASK|PSW_ET_MASK); + R[NUM_PSW] |= (1 << PSW_ET); + + /* Context switch */ + cpu_context_switch_1(new_pcbp); + cpu_context_switch_2(new_pcbp); + + /* Set ISC, TM, and ET to 7, 0, 3 in new PSW */ + R[NUM_PSW] &= ~(PSW_ISC_MASK|PSW_TM_MASK|PSW_ET_MASK); + R[NUM_PSW] |= (7 << PSW_ISC); + R[NUM_PSW] |= (3 << PSW_ET); + + cpu_context_switch_3(new_pcbp); + + cpu_km = FALSE; + + return TRUE; +} + +t_stat sim_instr(void) +{ + uint8 et, isc; + + /* Temporary register used for overflow detection */ + t_uint64 result; + + /* Scratch space */ + uint32 a, b, c, d; + + /* Used for field calculation */ + uint32 width, offset; + t_uint64 mask; + + operand *src1, *src2, *src3, *dst; + + stop_reason = 0; + + abort_reason = (uint32) setjmp(save_env); + + /* Exception handler. + * + * This gets a little messy because of exception contexts. If a + * normal-exception happens while we're handling a + * normal-exception, it needs to be treated as a stack-exception. + */ + if (abort_reason != 0) { + if (cpu_exception_stack_depth++ >= 10) { + return STOP_ESTK; + } + + if (cpu_unit.flags & UNIT_EXHALT) { + return STOP_EX; + } + + if (abort_reason == ABORT_EXC) { + et = R[NUM_PSW] & PSW_ET_MASK; + isc = (R[NUM_PSW] & PSW_ISC_MASK) >> PSW_ISC; + + switch(abort_context) { + case C_NORMAL_GATE_VECTOR: + cpu_on_normal_exception(N_GATE_VECTOR); + break; + case C_PROCESS_GATE_PCB: + cpu_on_process_exception(GATE_PCB_FAULT); + break; + case C_PROCESS_OLD_PCB: + cpu_on_process_exception(OLD_PCB_FAULT); + break; + case C_PROCESS_NEW_PCB: + cpu_on_process_exception(NEW_PCB_FAULT); + break; + case C_STACK_FAULT: + cpu_on_stack_exception(STACK_FAULT); + break; + case C_RESET_GATE_VECTOR: + cpu_on_reset_exception(GATE_VECTOR_FAULT); + break; + case C_RESET_SYSTEM_DATA: + cpu_on_reset_exception(SYSTEM_DATA_FAULT); + break; + case C_RESET_INT_STACK: + cpu_on_reset_exception(INTERRUPT_STACK_FAULT); + break; + default: + switch(et) { + case NORMAL_EXCEPTION: + cpu_on_normal_exception(isc); + break; + case STACK_EXCEPTION: + cpu_on_stack_exception(isc); + break; + case RESET_EXCEPTION: + cpu_on_reset_exception(isc); + break; + default: + stop_reason = STOP_EX; + break; + } + break; + } + } else { + /* TODO: Handle traps */ + stop_reason = STOP_EX; + } + } + + while (stop_reason == 0) { + abort_context = C_NONE; + + if (sim_brk_summ && sim_brk_test(R[NUM_PC], SWMASK ('E'))) { + stop_reason = STOP_IBKPT; + break; + } + + if (cpu_exception_stack_depth > 0) { + cpu_exception_stack_depth--; + } + + if (sim_interval-- <= 0) { + if ((stop_reason = sim_process_event())) { + break; + } + } + + /* Process DMA requests */ + dmac_service_drqs(); + + + /* + * Post-increment IU mode pointers (if needed). + * + * This is essentially a colossal hack. We never want to + * increment these pointers during an interlocked Read/Write + * operation, so we only increment after a CPU step has + * occured. + */ + if (iu_increment_a) { + increment_modep_a(); + } + if (iu_increment_b) { + increment_modep_b(); + } + + /* Process pending IRQ, if applicable */ + if (PSW_CUR_IPL < cpu_ipl()) { + cpu_on_interrupt(cpu_ipl()); + cpu_nmi = FALSE; + cpu_in_wait = FALSE; + continue; + } + + if (cpu_in_wait) { + if (sim_idle_enab) { + sim_idle(TMR_CLK, TRUE); + } + continue; + } + + /* Reset the TM bits */ + R[NUM_PSW] &= ~PSW_TM; + R[NUM_PSW] |= PSW_TM_MASK; + + /* Decode the instruction */ + memset(&cpu_instr, 0, sizeof(instr)); + cpu_ilen = decode_instruction(&cpu_instr); + + /* Record the instruction for history */ + if (cpu_hist_size > 0) { + /* Shallow copy */ + INST[cpu_hist_p] = cpu_instr; + INST[cpu_hist_p].valid = TRUE; + cpu_hist_p = (cpu_hist_p + 1) % cpu_hist_size; + } + + /* + * Operate on the decoded instruction. + */ + + /* Get the operands */ + if (cpu_instr.mn->src_op1 >= 0) { + src1 = &cpu_instr.operands[cpu_instr.mn->src_op1]; + } + + if (cpu_instr.mn->src_op2 >= 0) { + src2 = &cpu_instr.operands[cpu_instr.mn->src_op2]; + } + + if (cpu_instr.mn->src_op3 >= 0) { + src3 = &cpu_instr.operands[cpu_instr.mn->src_op3]; + } + + if (cpu_instr.mn->dst_op >= 0) { + dst = &cpu_instr.operands[cpu_instr.mn->dst_op]; + } + + switch (cpu_instr.mn->opcode) { + case ADDW2: + case ADDH2: + case ADDB2: + a = cpu_read_op(src1); + b = cpu_read_op(dst); + add(a, b, dst); + break; + case ADDW3: + case ADDH3: + case ADDB3: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + add(a, b, dst); + break; + case ALSW3: + a = cpu_read_op(src2); + b = cpu_read_op(src1); + result = a << (b & 0x1f); + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + case ANDW2: + case ANDH2: + case ANDB2: + a = cpu_read_op(src1); + b = cpu_read_op(dst); + c = a & b; + cpu_write_op(dst, c); + cpu_set_nz_flags(c, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(c, dst); + break; + case ANDW3: + case ANDH3: + case ANDB3: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + c = a & b; + cpu_write_op(dst, c); + cpu_set_nz_flags(c, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(c, dst); + break; + case BEH: + case BEH_D: + if (cpu_z_flag() == 1) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BEB: + case BEB_D: + if (cpu_z_flag() == 1) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case BGH: + if ((cpu_n_flag() | cpu_z_flag()) == 0) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BGB: + if ((cpu_n_flag() | cpu_z_flag()) == 0) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case BGEH: + if ((cpu_n_flag() == 0) | (cpu_z_flag() == 1)) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BGEB: + if ((cpu_n_flag() == 0) | (cpu_z_flag() == 1)) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case BGEUH: + if (cpu_c_flag() == 0) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BGEUB: + if (cpu_c_flag() == 0) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case BGUH: + if ((cpu_c_flag() | cpu_z_flag()) == 0) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BGUB: + if ((cpu_c_flag() | cpu_z_flag()) == 0) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case BITW: + case BITH: + case BITB: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + c = a & b; + cpu_set_nz_flags(c, src1); + cpu_set_c_flag(0); + cpu_set_v_flag(0); + break; + case BLH: + if ((cpu_n_flag() == 1) && (cpu_z_flag() == 0)) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BLB: + if ((cpu_n_flag() == 1) && (cpu_z_flag() == 0)) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case BLEH: + if ((cpu_n_flag() | cpu_z_flag()) == 1) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BLEB: + if ((cpu_n_flag() | cpu_z_flag()) == 1) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case BLEUH: + if ((cpu_c_flag() | cpu_z_flag()) == 1) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BLEUB: + if ((cpu_c_flag() | cpu_z_flag()) == 1) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case BLUH: + if (cpu_c_flag() == 1) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BLUB: + if (cpu_c_flag() == 1) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case BNEH: + case BNEH_D: + if (cpu_z_flag() == 0) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BNEB: + case BNEB_D: + if (cpu_z_flag() == 0) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case BPT: + /* TODO: Confirm that a breakpoint trap will increment the + PC. Otherwise, change 'break' to 'continue' */ + cpu_abort(NORMAL_EXCEPTION, BREAKPOINT_TRAP); + break; + case BRH: + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + case BRB: + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + case BSBH: + cpu_push_word(R[NUM_PC] + cpu_ilen); + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + case BSBB: + cpu_push_word(R[NUM_PC] + cpu_ilen); + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + case BVCH: + if (cpu_v_flag() == 0) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BVCB: + if (cpu_v_flag() == 0) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case BVSH: + if (cpu_v_flag() == 1) { + R[NUM_PC] += sign_extend_h(dst->embedded.h); + continue; + } + break; + case BVSB: + if (cpu_v_flag() == 1) { + R[NUM_PC] += sign_extend_b(dst->embedded.b); + continue; + } + break; + case CALL: + a = cpu_effective_address(src1); + b = cpu_effective_address(dst); + write_w(R[NUM_SP] + 4, R[NUM_AP]); + write_w(R[NUM_SP], R[NUM_PC] + cpu_ilen); + R[NUM_SP] += 8; + R[NUM_PC] = b; + R[NUM_AP] = a; + continue; + case CFLUSH: + break; + case CALLPS: + if (cpu_execution_level() != EX_LVL_KERN) { + cpu_abort(NORMAL_EXCEPTION, PRIVILEGED_OPCODE); + break; + } + + a = R[0]; + + cpu_km = TRUE; + + abort_context = C_RESET_INT_STACK; + + irq_push_word(R[NUM_PCBP]); + + /* Set current PC to start of next instruction (always PC+2) */ + R[NUM_PC] += 2; + + /* Set old PSW ISC, TM, and ET to 0, 0, 1 */ + R[NUM_PSW] &= ~(PSW_ISC_MASK|PSW_TM_MASK|PSW_ET_MASK); + R[NUM_PSW] |= (1 << PSW_ET); + + cpu_context_switch_1(a); + cpu_context_switch_2(a); + + R[NUM_PSW] &= ~(PSW_ISC_MASK|PSW_TM_MASK|PSW_ET_MASK); + R[NUM_PSW] |= (7 << PSW_ISC); + R[NUM_PSW] |= (3 << PSW_ET); + + cpu_context_switch_3(a); + + abort_context = C_NONE; + + cpu_km = FALSE; + continue; + case CLRW: + case CLRH: + case CLRB: + cpu_write_op(dst, 0); + cpu_set_n_flag(0); + cpu_set_z_flag(1); + cpu_set_c_flag(0); + cpu_set_v_flag(0); + break; + case CMPW: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + + cpu_set_z_flag((uint32)b == (uint32)a); + cpu_set_n_flag((int32)b < (int32)a); + cpu_set_c_flag((uint32)b < (uint32)a); + cpu_set_v_flag(0); + break; + case CMPH: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + + cpu_set_z_flag((uint16)b == (uint16)a); + cpu_set_n_flag((int16)b < (int16)a); + cpu_set_c_flag((uint16)b < (uint16)a); + cpu_set_v_flag(0); + break; + case CMPB: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + + cpu_set_z_flag((uint8)b == (uint8)a); + cpu_set_n_flag((int8)b < (int8)a); + cpu_set_c_flag((uint8)b < (uint8)a); + cpu_set_v_flag(0); + break; + case DECW: + case DECH: + case DECB: + a = cpu_read_op(dst); + sub(a, 1, dst); + break; + case DIVW2: + a = cpu_read_op(src1); + b = cpu_read_op(dst); + + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + + if (a == WORD_MASK && b == WD_MSB) { + cpu_set_v_flag(1); + } + + DIV(a, b, src1, dst, int32); + + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + break; + case DIVH2: + a = cpu_read_op(src1); + b = cpu_read_op(dst); + + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + + if (a == HALF_MASK && b == HW_MSB) { + cpu_set_v_flag(1); + } + + DIV(a, b, src1, dst, int16); + + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + break; + case DIVB2: + a = cpu_read_op(src1); + b = cpu_read_op(dst); + + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + + if (a == BYTE_MASK && b == BT_MSB) { + cpu_set_v_flag(1); + } + + result = (uint8)b / (uint8)a; + + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + break; + case DIVW3: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + + if (a == WORD_MASK && b == WD_MSB) { + cpu_set_v_flag(1); + } + + DIV(a, b, src1, src2, int32); + + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + break; + case DIVH3: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + + if (a == HALF_MASK && b == HW_MSB) { + cpu_set_v_flag(1); + } + + DIV(a, b, src1, src2, int16); + + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + break; + case DIVB3: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + + if (a == BYTE_MASK && b == BT_MSB) { + cpu_set_v_flag(1); + } + + result = (uint8)b / (uint8)a; + + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + break; + case MVERNO: + R[0] = WE32100_VER; + break; + case ENBVJMP: + if (cpu_execution_level() != EX_LVL_KERN) { + cpu_abort(NORMAL_EXCEPTION, PRIVILEGED_OPCODE); + break; + } + mmu_enable(); + R[NUM_PC] = R[0]; + continue; + case DISVJMP: + if (cpu_execution_level() != EX_LVL_KERN) { + cpu_abort(NORMAL_EXCEPTION, PRIVILEGED_OPCODE); + break; + } + mmu_disable(); + R[NUM_PC] = R[0]; + continue; + case EXTFW: + case EXTFH: + case EXTFB: + width = (cpu_read_op(src1) & 0x1f) + 1; + offset = cpu_read_op(src2) & 0x1f; + mask = (1ul << width) - 1; + mask = (mask << offset) & WORD_MASK; + + if (width + offset > 32) { + mask |= (1ul << ((width + offset) - 32)) - 1; + } + + a = cpu_read_op(src3); /* src */ + a &= mask; + a = a >> offset; + + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(a, dst); + break; + case INCW: + case INCH: + case INCB: + a = cpu_read_op(dst); + add(a, 1, dst); + break; + case INSFW: + case INSFH: + case INSFB: + width = (cpu_read_op(src1) & 0x1f) + 1; + offset = cpu_read_op(src2) & 0x1f; + mask = ((1ul << width) - 1) & WORD_MASK; + + a = cpu_read_op(src3) & mask; /* src */ + b = cpu_read_op(dst); /* dst */ + + b &= ~(mask << offset); + b |= (a << offset); + + cpu_write_op(dst, b); + cpu_set_nz_flags(b, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(b, dst); + break; + case JMP: + R[NUM_PC] = cpu_effective_address(dst); + continue; + case JSB: + cpu_push_word(R[NUM_PC] + cpu_ilen); + R[NUM_PC] = cpu_effective_address(dst); + continue; + case LLSW3: + result = cpu_read_op(src2) << (cpu_read_op(src1) & 0x1f); + cpu_write_op(dst, (uint32)(result & WORD_MASK)); + cpu_set_nz_flags((uint32)(result & WORD_MASK), dst); + break; + case LLSH3: + a = cpu_read_op(src2) << (cpu_read_op(src1) & 0x1f); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + break; + case LLSB3: + a = cpu_read_op(src2) << (cpu_read_op(src1) & 0x1f); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(a, dst); + break; + case ARSW3: + case ARSH3: + case ARSB3: + a = cpu_read_op(src2); + b = cpu_read_op(src1) & 0x1f; + result = a >> b; + /* Ensure the MSB is copied appropriately */ + switch (op_type(src2)) { + case WD: + if (a & 0x80000000) { + result |= shift_32_table[b + 1]; + } + break; + case HW: + if (a & 0x8000) { + result |= shift_16_table[b + 1]; + } + break; + case BT: + if (a & 0x80) { + result |= shift_8_table[b + 1]; + } + break; + } + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + cpu_set_v_flag(0); + break; + case LRSW3: + a = (uint32) cpu_read_op(src2) >> (cpu_read_op(src1) & 0x1f); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(a, dst); + break; + case GATE: + cpu_km = TRUE; + abort_context = C_PROCESS_GATE_PCB; + if (R[NUM_SP] < read_w(R[NUM_PCBP] + 12, ACC_AF) || + R[NUM_SP] >= read_w(R[NUM_PCBP] + 16, ACC_AF)) { + sim_debug(EXECUTE_MSG, &cpu_dev, + "[%08x] STACK OUT OF BOUNDS IN GATE. " + "SP=%08x, R[NUM_PCBP]+12=%08x, " + "R[NUM_PCBP]+16=%08x\n", + R[NUM_PC], + R[NUM_SP], + read_w(R[NUM_PCBP] + 12, ACC_AF), + read_w(R[NUM_PCBP] + 16, ACC_AF)); + cpu_abort(STACK_EXCEPTION, STACK_BOUND); + } + cpu_km = FALSE; + + abort_context = C_STACK_FAULT; + + /* Push PC+2 onto stack */ + write_w(R[NUM_SP], R[NUM_PC] + 2); + + /* Write 1, 0, 2 to ISC, TM, ET */ + R[NUM_PSW] &= ~(PSW_ISC_MASK|PSW_TM_MASK|PSW_ET_MASK); + R[NUM_PSW] |= (1 << PSW_ISC); + R[NUM_PSW] |= (2 << PSW_ET); + + /* Push PSW onto stack */ + write_w(R[NUM_SP] + 4, R[NUM_PSW]); + + abort_context = C_NONE; + + /* Perform gate entry-point 2 */ + cpu_perform_gate(R[0] & 0x7c, + R[1] & 0x7ff8); + + /* Finish push of PC and PSW */ + R[NUM_SP] += 8; + continue; + case MCOMW: + case MCOMH: + case MCOMB: + a = ~(cpu_read_op(src1)); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(a, dst); + break; + case MNEGW: + case MNEGH: + case MNEGB: + a = ~cpu_read_op(src1) + 1; + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(a, dst); + break; + case MOVBLW: + while (R[2] != 0) { + a = read_w(R[0], ACC_AF); + write_w(R[1], a); + R[2]--; + R[0] += 4; + R[1] += 4; + } + break; + case STREND: + while (read_b(R[0], ACC_AF) != 0) { + R[0]++; + } + break; + case SWAPWI: + case SWAPHI: + case SWAPBI: + a = cpu_read_op(dst); + cpu_write_op(dst, R[0]); + R[0] = a; + cpu_set_nz_flags(a, dst); + cpu_set_v_flag(0); + cpu_set_c_flag(0); + break; + case ROTW: + a = cpu_read_op(src1) & 31; + b = (uint32) cpu_read_op(src2); + mask = (CHAR_BIT * sizeof(a) - 1); + d = (b >> a) | (b << ((~a + 1) & mask)); + cpu_write_op(dst, d); + cpu_set_nz_flags(d, dst); + cpu_set_v_flag(0); + cpu_set_c_flag(0); + break; + case MOVAW: + a = cpu_effective_address(src1); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_v_flag(0); + cpu_set_c_flag(0); + break; + case MOVTRW: + a = cpu_effective_address(src1); + result = mmu_xlate_addr(a, ACC_MT); + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_v_flag(0); + cpu_set_c_flag(0); + break; + case MOVW: + case MOVH: + case MOVB: + a = cpu_read_op(src1); + cpu_write_op(dst, a); + + /* Flags are never set if the source or destination is the + PSW */ + if (!(op_is_psw(src1) || op_is_psw(dst))) { + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(a, dst); + } + + /* However, if a move to PSW set the O bit, we have to + generate an overflow exception trap */ + if (op_is_psw(dst) && (R[NUM_PSW] & PSW_OE_MASK)) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_OVERFLOW); + } + break; + case MODW2: + a = cpu_read_op(src1); + b = cpu_read_op(dst); + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + MOD(a, b, src1, dst, int32); + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + case MODH2: + a = cpu_read_op(src1); + b = cpu_read_op(dst); + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + MOD(a, b, src1, dst, int16); + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + case MODB2: + a = cpu_read_op(src1); + b = cpu_read_op(dst); + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + result = (uint8)b % (uint8)a; + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + break; + case MODW3: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + MOD(a, b, src1, src2, int32); + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + case MODH3: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + MOD(a, b, src1, src2, int16); + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + case MODB3: + a = cpu_read_op(src1); + b = cpu_read_op(src2); + if (a == 0) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_ZERO_DIVIDE); + break; + } + result = (uint8)b % (uint8)a; + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + case MULW2: + result = cpu_read_op(src1) * cpu_read_op(dst); + cpu_write_op(dst, (uint32)(result & WORD_MASK)); + cpu_set_nz_flags((uint32)(result & WORD_MASK), dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + case MULH2: + a = cpu_read_op(src1) * cpu_read_op(dst); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + case MULB2: + a = cpu_read_op(src1) * cpu_read_op(dst); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, src1); + break; + case MULW3: + result = cpu_read_op(src1) * cpu_read_op(src2); + cpu_write_op(dst, (uint32)(result & WORD_MASK)); + cpu_set_nz_flags((uint32)(result & WORD_MASK), dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + case MULH3: + a = cpu_read_op(src1) * cpu_read_op(src2); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + case MULB3: + a = cpu_read_op(src1) * cpu_read_op(src2); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(result, dst); + break; + case NOP: + break; + case NOP2: + cpu_ilen += 1; + break; + case NOP3: + cpu_ilen += 2; + break; + case ORW2: + case ORH2: + case ORB2: + a = (cpu_read_op(src1) | cpu_read_op(dst)); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(a, dst); + break; + case ORW3: + case ORH3: + case ORB3: + a = (cpu_read_op(src1) | cpu_read_op(src2)); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(a, dst); + break; + case POPW: + /* N.B. "If dst is the stack pointer (%sp), the results + are indeterminate". The ordering here is important. If + we decrement SP before writing the results, we end up + in a weird, bad state. */ + a = read_w(R[NUM_SP] - 4, ACC_AF); + cpu_write_op(dst, a); + R[NUM_SP] -= 4; + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag(0); + break; + case PUSHAW: + a = cpu_effective_address(src1); + cpu_push_word(a); + cpu_set_nz_flags(a, src1); + cpu_set_c_flag(0); + cpu_set_v_flag(0); + break; + case PUSHW: + a = cpu_read_op(src1); + cpu_push_word(a); + cpu_set_nz_flags(a, src1); + cpu_set_c_flag(0); + cpu_set_v_flag(0); + break; + case RGEQ: + if (cpu_n_flag() == 0 || cpu_z_flag() == 1) { + R[NUM_PC] = cpu_pop_word(); + continue; + } + break; + case RGEQU: + if (cpu_c_flag() == 0) { + R[NUM_PC] = cpu_pop_word(); + continue; + } + break; + case RGTR: + if ((cpu_n_flag() | cpu_z_flag()) == 0) { + R[NUM_PC] = cpu_pop_word(); + continue; + } + break; + case RNEQ: + case RNEQU: + if (cpu_z_flag() == 0) { + R[NUM_PC] = cpu_pop_word(); + continue; + } + break; + case RET: + a = R[NUM_AP]; + b = read_w(R[NUM_SP] - 4, ACC_AF); + c = read_w(R[NUM_SP] - 8, ACC_AF); + R[NUM_AP] = b; + R[NUM_PC] = c; + R[NUM_SP] = a; + continue; + case RETG: + abort_context = C_STACK_FAULT; + a = read_w(R[NUM_SP] - 4, ACC_AF); /* PSW */ + b = read_w(R[NUM_SP] - 8, ACC_AF); /* PC */ + abort_context = C_NONE; + if ((a & PSW_CM_MASK) < (R[NUM_PSW] & PSW_CM_MASK)) { + sim_debug(EXECUTE_MSG, &cpu_dev, + "[%08x] Illegal level change. New level=%d, Cur level=%d\n", + R[NUM_PC], + (a & PSW_CM_MASK) >> PSW_CM, + (R[NUM_PSW] & PSW_CM_MASK) >> PSW_CM); + cpu_abort(NORMAL_EXCEPTION, ILLEGAL_LEVEL_CHANGE); + break; + } + /* Clear some state and move it from the current PSW */ + a &= ~PSW_IPL_MASK; + a &= ~PSW_CFD_MASK; + a &= ~PSW_QIE_MASK; + a &= ~PSW_CD_MASK; + a &= ~PSW_R_MASK; + a &= ~PSW_ISC_MASK; + a &= ~PSW_TM_MASK; + a &= ~PSW_ET_MASK; + + a |= (R[NUM_PSW] & PSW_IPL_MASK); + a |= (R[NUM_PSW] & PSW_CFD_MASK); + a |= (R[NUM_PSW] & PSW_QIE_MASK); + a |= (R[NUM_PSW] & PSW_CD_MASK); + a |= (R[NUM_PSW] & PSW_R_MASK); + a |= (7 << PSW_ISC); + a |= (3 << PSW_ET); + + R[NUM_PSW] = a; + R[NUM_PC] = b; + + R[NUM_SP] -= 8; + continue; + case RETPS: + if (cpu_execution_level() != EX_LVL_KERN) { + cpu_abort(NORMAL_EXCEPTION, PRIVILEGED_OPCODE); + break; + } + + /* Force kernel memory access */ + cpu_km = TRUE; + + abort_context = C_RESET_INT_STACK; + /* Restore process state */ + a = irq_pop_word(); /* New process PCBP */ + + abort_context = C_PROCESS_OLD_PCB; + b = read_w(a, ACC_AF); /* New PSW */ + + abort_context = C_PROCESS_NEW_PCB; + /* Copy the 'R' flag from the new PSW to the old PSW */ + R[NUM_PSW] &= ~PSW_R_MASK; + R[NUM_PSW] |= (b & PSW_R_MASK); + + /* a now holds the new PCBP */ + cpu_context_switch_2(a); + + /* Perform block moves, if any */ + cpu_context_switch_3(a); + + /* Restore registers if R bit is set */ + if (R[NUM_PSW] & PSW_R_MASK) { + R[NUM_FP] = read_w(a + 24, ACC_AF); + R[0] = read_w(a + 28, ACC_AF); + R[1] = read_w(a + 32, ACC_AF); + R[2] = read_w(a + 36, ACC_AF); + R[3] = read_w(a + 40, ACC_AF); + R[4] = read_w(a + 44, ACC_AF); + R[5] = read_w(a + 48, ACC_AF); + R[6] = read_w(a + 52, ACC_AF); + R[7] = read_w(a + 56, ACC_AF); + R[8] = read_w(a + 60, ACC_AF); + R[NUM_AP] = read_w(a + 20, ACC_AF); + } + + abort_context = C_NONE; + + /* Un-force kernel memory access */ + cpu_km = FALSE; + continue; + case SPOP: + case SPOPRD: + case SPOPRS: + /* Memory fault is signaled when no support processor is + active */ + cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); + break; + case SUBW2: + case SUBH2: + case SUBB2: + a = cpu_read_op(dst); + b = cpu_read_op(src1); + sub(a, b, dst); + break; + case SUBW3: + case SUBH3: + case SUBB3: + a = cpu_read_op(src2); + b = cpu_read_op(src1); + sub(a, b, dst); + break; + case RESTORE: + a = R[NUM_FP] - 28; /* Old FP */ + b = read_w(a, ACC_AF); /* Old FP */ + c = R[NUM_FP] - 24; /* Old save point */ + + for (d = src1->reg; d < NUM_FP; d++) { + R[d] = read_w(c, ACC_AF); + c += 4; + } + + R[NUM_FP] = b; /* Restore FP */ + R[NUM_SP] = a; /* Restore SP */ + break; + case RLEQ: + if ((cpu_n_flag() | cpu_z_flag()) == 1) { + R[NUM_PC] = cpu_pop_word(); + continue; + } + break; + case RLEQU: + if ((cpu_c_flag() | cpu_z_flag()) == 1) { + R[NUM_PC] = cpu_pop_word(); + continue; + } + break; + case RLSS: + if ((cpu_n_flag() == 1) & (cpu_z_flag() == 0)) { + R[NUM_PC] = cpu_pop_word(); + continue; + } + break; + case REQL: + if (cpu_z_flag() == 1) { + R[NUM_PC] = cpu_pop_word(); + continue; + } + break; + case REQLU: + if (cpu_z_flag() == 1) { + R[NUM_PC] = cpu_pop_word(); + continue; + } + break; + case RSB: + R[NUM_PC] = cpu_pop_word(); + continue; + case SAVE: + /* Save the FP register */ + write_w(R[NUM_SP], R[NUM_FP]); + + /* Save all the registers from the one identified by the + src operand up to FP (exclusive) */ + for (a = src1->reg, b = 4; a < NUM_FP; a++, b += 4) { + write_w(R[NUM_SP] + b, R[a]); + } + + R[NUM_SP] = R[NUM_SP] + 28; + R[NUM_FP] = R[NUM_SP]; + break; + case STRCPY: + a = 0; + b = 0; + + do { + b = read_b(R[0] + a, ACC_AF); + write_b(R[1] + a, (uint8) b); + a++; + } while (b != '\0'); + + break; + case TSTW: + a = cpu_read_op(src1); + cpu_set_n_flag((int32)a < 0); + cpu_set_z_flag(a == 0); + cpu_set_c_flag(0); + cpu_set_v_flag(0); + break; + case TSTH: + a = cpu_read_op(src1); + cpu_set_n_flag((int16)a < 0); + cpu_set_z_flag(a == 0); + cpu_set_c_flag(0); + cpu_set_v_flag(0); + break; + case TSTB: + a = cpu_read_op(src1); + cpu_set_n_flag((int8)a < 0); + cpu_set_z_flag(a == 0); + cpu_set_c_flag(0); + cpu_set_v_flag(0); + break; + case WAIT: + cpu_in_wait = TRUE; + break; + case XORW2: + case XORH2: + case XORB2: + a = (cpu_read_op(src1) ^ cpu_read_op(dst)); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(a, dst); + break; + case XORW3: + case XORH3: + case XORB3: + a = (cpu_read_op(src1) ^ cpu_read_op(src2)); + cpu_write_op(dst, a); + cpu_set_nz_flags(a, dst); + cpu_set_c_flag(0); + cpu_set_v_flag_op(a, dst); + break; + default: + stop_reason = STOP_OPCODE; + break; + }; + + /* Increment the PC appropriately */ + R[NUM_PC] += cpu_ilen; + } + + return stop_reason; +} + +static SIM_INLINE void cpu_on_process_exception(uint8 isc) +{ + /* TODO: Handle */ + stop_reason = STOP_EX; + return; +} + +static SIM_INLINE void cpu_on_reset_exception(uint8 isc) +{ + uint32 new_pcbp; + + sim_debug(EXECUTE_MSG, &cpu_dev, + "[%08x] [cpu_on_reset_exception %d] SP=%08x PCBP=%08x ISP=%08x\n", + R[NUM_PC], isc, R[NUM_SP], R[NUM_PCBP], R[NUM_ISP]); + + if (isc == EXTERNAL_RESET) { + R[NUM_PSW] &= ~(PSW_R_MASK); + } + + cpu_km = TRUE; + + mmu_disable(); + + abort_context = C_RESET_SYSTEM_DATA; + new_pcbp = read_w(0x80, ACC_AF); + + abort_context = C_RESET_NEW_PCB; + cpu_context_switch_2(new_pcbp); + + cpu_km = FALSE; + abort_context = C_NONE; +} + +static SIM_INLINE void cpu_on_stack_exception(uint8 isc) +{ + uint32 new_pcbp; + + sim_debug(EXECUTE_MSG, &cpu_dev, + "[%08x] [cpu_on_stack_exception %d] SP=%08x PCBP=%08x ISP=%08x\n", + R[NUM_PC], isc, R[NUM_SP], R[NUM_PCBP], R[NUM_ISP]); + + abort_context = C_RESET_SYSTEM_DATA; + cpu_km = TRUE; + new_pcbp = read_w(0x88, ACC_AF); + + abort_context = C_RESET_INT_STACK; + irq_push_word(R[NUM_PCBP]); + + abort_context = C_PROCESS_OLD_PCB; + R[NUM_PSW] &= ~(PSW_ET_MASK|PSW_ISC_MASK); + R[NUM_PSW] |= (2 << PSW_ET); + R[NUM_PSW] |= (uint32) (isc << PSW_ISC); + + cpu_context_switch_1(new_pcbp); + cpu_context_switch_2(new_pcbp); + + /* Set ISC, TM, and ET to 7, 0, 3 in new PSW */ + R[NUM_PSW] &= ~(PSW_ISC_MASK|PSW_TM_MASK|PSW_ET_MASK); + R[NUM_PSW] |= (7 << PSW_ISC); + R[NUM_PSW] |= (3 << PSW_ET); + + cpu_km = FALSE; + abort_context = C_NONE; +} + +static SIM_INLINE void cpu_on_normal_exception(uint8 isc) +{ + sim_debug(EXECUTE_MSG, &cpu_dev, + "[%08x] [cpu_on_normal_exception %d] %%sp=%08x abort_context=%d\n", + R[NUM_PC], isc, R[NUM_SP], abort_context); + + abort_context = C_PROCESS_GATE_PCB; + + cpu_km = TRUE; + + if (R[NUM_SP] < read_w(R[NUM_PCBP] + 12, ACC_AF) || + R[NUM_SP] >= read_w(R[NUM_PCBP] + 16, ACC_AF)) { + sim_debug(EXECUTE_MSG, &cpu_dev, + "[%08x] STACK OUT OF BOUNDS IN EXCEPTION HANDLER. " + "SP=%08x, R[NUM_PCBP]+12=%08x, " + "R[NUM_PCBP]+16=%08x\n", + R[NUM_PC], + R[NUM_SP], + read_w(R[NUM_PCBP] + 12, ACC_AF), + read_w(R[NUM_PCBP] + 16, ACC_AF)); + abort_context = C_NONE; + cpu_abort(STACK_EXCEPTION, STACK_BOUND); + } + + cpu_km = FALSE; + + /* Set context for STACK (FAULT) */ + abort_context = C_STACK_FAULT; + write_w(R[NUM_SP], R[NUM_PC]); + + /* Write 0, 3 to TM, ET fields of PSW */ + R[NUM_PSW] &= ~(PSW_TM_MASK|PSW_ET_MASK); + R[NUM_PSW] |= (3 << PSW_ET); + + /* Save address of next instruction and PSW to stack */ + write_w(R[NUM_SP] + 4, R[NUM_PSW]); + + /* Set context for RESET (GATE VECTOR) */ + abort_context = C_RESET_GATE_VECTOR; + cpu_perform_gate(0, ((uint32) isc) << 3); + + /* Finish push of old PC and PSW */ + R[NUM_SP] += 8; + abort_context = C_NONE; +} + +static SIM_INLINE void cpu_perform_gate(uint32 index1, uint32 index2) +{ + uint32 gate_l2, new_psw; + + cpu_km = TRUE; + + gate_l2 = read_w(index1, ACC_AF) + index2; + + /* Get new PSW from second-level table */ + new_psw = read_w(gate_l2, ACC_AF); + + /* Clear state in PSW */ + new_psw &= ~(PSW_PM_MASK|PSW_IPL_MASK|PSW_R_MASK| + PSW_ISC_MASK|PSW_TM_MASK|PSW_ET_MASK); + + /* Set PM in new PSW */ + new_psw |= (R[NUM_PSW] & PSW_CM_MASK) >> 2; /* PM */ + new_psw |= (R[NUM_PSW] & PSW_IPL_MASK); /* IPL */ + new_psw |= (R[NUM_PSW] & PSW_R_MASK); /* R */ + + /* Set new PSW ISC, TM, and ET to 7, 1, 3 */ + new_psw |= (7 << PSW_ISC); /* ISC */ + new_psw |= (1 << PSW_TM); /* TM */ + new_psw |= (3 << PSW_ET); /* ET */ + + R[NUM_PC] = read_w(gate_l2 + 4, ACC_AF); + R[NUM_PSW] = new_psw; + + cpu_km = FALSE; +} + +/* + * TODO: Setting 'data' to the effective address is bogus. We're only + * doing it because we want to get the address when we trace the + * instructions using "SHOW CPU HISTORY". We should just put + * effective_address as a field in the operand struct and make + * cpu_show_hist smarter. + */ +static uint32 cpu_effective_address(operand *op) +{ + /* Register Deferred */ + if (op->mode == 5 && op->reg != 11) { + return R[op->reg]; + } + + /* Absolute */ + if (op->mode == 7 && op->reg == 15) { + return op->embedded.w; + } + + /* Absolute Deferred */ + if (op->mode == 14 && op->reg == 15) { + /* May cause exception */ + return read_w(op->embedded.w, ACC_AF); + } + + /* FP Short Offset */ + if (op->mode == 6 && op->reg != 15) { + return R[NUM_FP] + sign_extend_b(op->embedded.b); + } + + /* AP Short Offset */ + if (op->mode == 7 && op->reg != 15) { + return R[NUM_AP] + sign_extend_b(op->embedded.b); + } + + /* Word Displacement */ + if (op->mode == 8) { + return R[op->reg] + op->embedded.w; + } + + /* Word Displacement Deferred */ + if (op->mode == 9) { + return read_w(R[op->reg] + op->embedded.w, ACC_AF); + } + + /* Halfword Displacement */ + if (op->mode == 10) { + return R[op->reg] + sign_extend_h(op->embedded.h); + } + + /* Halfword Displacement Deferred */ + if (op->mode == 11) { + return read_w(R[op->reg] + sign_extend_h(op->embedded.h), ACC_AF); + } + + /* Byte Displacement */ + if (op->mode == 12) { + return R[op->reg] + sign_extend_b(op->embedded.b); + } + + /* Byte Displacement Deferred */ + if (op->mode == 13) { + return read_w(R[op->reg] + sign_extend_b(op->embedded.b), ACC_AF); + } + + assert(0); + + return 0; +} + +/* + * Read and Write routines for operands. + * + * The rules for dealing with the type (signed/unsigned, + * byte/halfword/word) of operands are fairly complex. + * + * 1. The expanded operand mode does not affect the treatment of + * Literal Mode operands. All literals are signed. + * + * 2. The expanded operand mode does not affect the length of + * Immediate Mode operands, but does affect whether they are signed + * or unsigned. + * + * 3. When using expanded-mode operands, the new type remains in + * effect for the operands that folow in the instruction unless + * another expanded operand mode overrides it. (This rule in + * particular is managed by decode_instruction()) + * + * 4. The expanded operand mode is illegal with coprocessor instructions + * and CALL, SAVE, RESTORE, SWAP INTERLOCKED, PUSAHW, PUSHAW, POPW, + * and JSB. (Illegal Operand Fault) + * + * 5. When writing a byte, the Negative (N) flag is set based on the + * high bit of the data type being written, regardless of the SIGN + * of the extended datatype. e.g.: {ubyte} and {sbyte} both check + * for bit 7, {uhalf} and {shalf} both check for bit 15, and + * {uword} and {sword} both check for bit 31. + * + * 6. For instructions with a signed destination, V is set if the sign + * bit of the output value is different from any truncated bit of + * the result. For instructions with an unsigned destination, V is + * set if any truncated bit is 1. + */ + + +/* + * Read the data referenced by an operand. Performs sign or zero + * extension as required by the read width and operand type, then + * returns the read value. + * + * "All operations are performed only on 32-bit quantities even though + * an instruction may specify a byte or halfword operand. The WE + * 32100 Microprocessor reads in the correct number of bits for the + * operand and extends the data automatically to 32 bits. It uses + * sign extension when reading signed data or halfwords and zero + * extension when reading unsigned data or bytes (or bit fields that + * contain less than 32 bits). The data type of the source operand + * determines how many bits are fetched and what type of extension is + * applied. Bytes are treated as unsigned, while halfwords and words + * are considered signed. The type of extension applied can be + * changed using the expanded-operand type mode as described in 3.4.5 + * Expanded-Operand Type Mode. For sign extension, the value of the + * MSB or sign bit of the data fills the high-order bits to form a + * 32-bit value. In zero extension, zeros fill the high order bits. + * The microprocessor automatically extends a byte or halfword to 32 + * bits before performing an operation. Figure 3-3 illustrates sign + * and zero extension. An arithmetic, logical, data transfer, or bit + * field operation always yields an intermediate result that is 32 + * bits in length. If the result is to be stored in a register, the + * processor writes all 32 bits to that register. The processor + * automatically strips any surplus high-order bits from a result + * when writing bytes or halfwords to memory." -- "WE 32100 + * Microprocessor Information Manual", Section 3.1.1 + * + */ +static uint32 cpu_read_op(operand * op) +{ + uint32 eff; + uint32 data; + + /* Register */ + if (op->mode == 4 && op->reg < 15) { + switch (op_type(op)) { + case WD: + case UW: + data = R[op->reg]; + break; + case HW: + data = sign_extend_h(R[op->reg] & HALF_MASK); + break; + case UH: + data = R[op->reg] & HALF_MASK; + break; + case BT: + data = R[op->reg] & BYTE_MASK; + break; + case SB: + data = sign_extend_b(R[op->reg] & BYTE_MASK); + break; + default: + assert(0); + } + + op->data = data; + return data; + } + + /* Literal */ + if (op->mode < 4 || op->mode == 15) { + /* Both positive and negative literals are _always_ treated as + signed bytes, and they are _always_ sign extended. They + simply ignore expanded datatypes. */ + data = sign_extend_b(op->embedded.b); + op->data = data; + return data; + } + + /* Immediate */ + if (op->reg == 15 && + (op->mode == 4 || op->mode == 5 || op->mode == 6)) { + switch (op->mode) { + case 4: /* Word Immediate */ + data = op->embedded.w; + op->data = data; + return data; + case 5: /* Halfword Immediate */ + data = sign_extend_h(op->embedded.h); + op->data = data; + return data; + case 6: /* Byte Immedaite */ + data = sign_extend_b(op->embedded.b); + op->data = data; + return data; + } + } + + /* At this point, we'll need to find an effective address */ + eff = cpu_effective_address(op); + + switch (op_type(op)) { + case WD: /* Signed Word */ + case UW: /* Unsigned Word */ + data = read_w(eff, ACC_OF); + op->data = data; + return data; + case HW: /* Signed Halfword */ + data = sign_extend_h(read_h(eff, ACC_OF)); + op->data = data; + return data; + case UH: /* Unsigned Halfword */ + data = read_h(eff, ACC_OF); + op->data = data; + return data; + case SB: /* Signed Byte */ + data = sign_extend_b(read_b(eff, ACC_OF)); + op->data = data; + return data; + case BT: /* Unsigned Byte */ + data = read_b(eff, ACC_OF); + op->data = data; + return data; + default: + assert(0); + return 0; + } +} + + +static void cpu_write_op(operand * op, t_uint64 val) +{ + uint32 eff; + op->data = (uint32) val; + + /* Writing to a register. */ + if (op->mode == 4 && op->reg < 15) { + if ((op->reg == NUM_PSW || op->reg == NUM_PCBP || op->reg == NUM_ISP) && + cpu_execution_level() != EX_LVL_KERN) { + cpu_abort(NORMAL_EXCEPTION, PRIVILEGED_REGISTER); + return; + } + + /* Registers always get the full 32-bits written */ + + R[op->reg] = (uint32) val; + + return; + } + + /* Literal mode is not legal. */ + if (op->mode < 4 || op->mode == 15) { + cpu_abort(NORMAL_EXCEPTION, INVALID_DESCRIPTOR); + return; + } + + /* Immediate mode is not legal. */ + if (op->reg == 15 && + (op->mode == 4 || op->mode == 5 || op->mode == 6)) { + cpu_abort(NORMAL_EXCEPTION, INVALID_DESCRIPTOR); + return; + } + + eff = cpu_effective_address(op); + + switch (op_type(op)) { + case UW: + case WD: + write_w(eff, (uint32) val); + break; + case HW: + case UH: + if (val > HALF_MASK) { + cpu_set_v_flag(TRUE); + } + write_h(eff, val & HALF_MASK); + break; + case SB: + case BT: + if (val > BYTE_MASK) { + cpu_set_v_flag(TRUE); + } + write_b(eff, val & BYTE_MASK); + break; + default: + assert(0); + } +} + +/* + * This returns the current state of the IPL (Interrupt + * Priority Level) bus. This is affected by: + * + * - Latched values in the CSR for: + * o CSRCLK 15 + * o CSRDMA 13 + * o CSRUART 13 + * o CSRDISK 11 + * o CSRPIR9 9 + * o CSRPIR8 8 + * - IRQ currently enabled for: + * o HD Ctlr. 11 + */ +static SIM_INLINE uint8 cpu_ipl() +{ + /* CSRPIR9 is cleared by writing to c_pir8 */ + if (csr_data & CSRPIR8) { + return 8; + } + + /* CSRPIR9 is cleared by writing to c_pir9 */ + if (csr_data & CSRPIR9) { + return 9; + } + + /* CSRDISK is cleared when the floppy "if_irq" goes low */ + if (id_irq || (csr_data & CSRDISK)) { + return 11; + } + + /* CSRDMA is cleared by write/read to 0x49011 */ + /* CSRUART is cleared when the uart "iu_irq" goes low */ + if ((csr_data & CSRUART) || (csr_data & CSRDMA)) { + return 13; + } + + /* CSRCLK is cleared by $clrclkint */ + if (csr_data & CSRCLK) { + return 15; + } + + return 0; +} + +/* + * Returns the correct datatype for an operand -- either extended type + * or default type. + */ +static SIM_INLINE int8 op_type(operand *op) { + if (op->etype > -1) { + return op->etype; + } else { + return op->dtype; + } +} + +static SIM_INLINE t_bool op_signed(operand *op) { + return (op_type(op) == WD || op_type(op) == HW || op_type(op) == SB); +} + +static SIM_INLINE t_bool is_byte_immediate(operand * oper) +{ + return oper->mode == 6 && oper->reg == 15; +} + +static SIM_INLINE t_bool is_halfword_immediate(operand * oper) +{ + return oper->mode == 5 && oper->reg == 15; +} + +static SIM_INLINE t_bool is_word_immediate(operand * oper) +{ + return oper->mode == 4 && oper->reg == 15; +} + +static SIM_INLINE t_bool is_positive_literal(operand * oper) +{ + return (oper->mode == 0 || + oper->mode == 1 || + oper->mode == 2); +} + +static SIM_INLINE t_bool is_negative_literal(operand * oper) +{ + return oper->mode == 15; +} + +/* Returns true if the operand may not be used as a destination */ +static SIM_INLINE t_bool invalid_destination(operand * oper) +{ + return (is_byte_immediate(oper) || + is_halfword_immediate(oper) || + is_word_immediate(oper) || + is_positive_literal(oper) || + is_negative_literal(oper)); +} + +static SIM_INLINE uint32 sign_extend_b(uint8 val) +{ + if (val & 0x80) + return ((uint32) val) | 0xffffff00; + return (uint32) val; +} + +static SIM_INLINE uint32 zero_extend_b(uint8 val) +{ + return (uint32) val & BYTE_MASK; +} + +static SIM_INLINE uint32 sign_extend_h(uint16 val) +{ + if (val & 0x8000) + return ((uint32) val) | 0xffff0000; + return (uint32) val; +} + +static SIM_INLINE uint32 zero_extend_h(uint16 val) +{ + return (uint32) val & HALF_MASK; +} + +/* + * Returns the current CPU execution level. + */ +static SIM_INLINE uint8 cpu_execution_level() +{ + return (R[NUM_PSW] & PSW_CM_MASK) >> PSW_CM; +} + +static SIM_INLINE t_bool cpu_z_flag() +{ + return (R[NUM_PSW] & PSW_Z_MASK) != 0; +} + +static SIM_INLINE t_bool cpu_n_flag() +{ + return (R[NUM_PSW] & PSW_N_MASK) != 0; +} + +static SIM_INLINE t_bool cpu_c_flag() +{ + return (R[NUM_PSW] & PSW_C_MASK) != 0; +} + +static SIM_INLINE t_bool cpu_v_flag() +{ + return (R[NUM_PSW] & PSW_V_MASK) != 0; +} + +static SIM_INLINE void cpu_set_z_flag(t_bool val) +{ + if (val) { + R[NUM_PSW] = R[NUM_PSW] | PSW_Z_MASK; + } else { + R[NUM_PSW] = R[NUM_PSW] & ~PSW_Z_MASK; + } +} + +static SIM_INLINE void cpu_set_n_flag(t_bool val) +{ + if (val) { + R[NUM_PSW] = R[NUM_PSW] | PSW_N_MASK; + } else { + R[NUM_PSW] = R[NUM_PSW] & ~PSW_N_MASK; + } +} + +static SIM_INLINE void cpu_set_c_flag(t_bool val) +{ + if (val) { + R[NUM_PSW] = R[NUM_PSW] | PSW_C_MASK; + } else { + R[NUM_PSW] = R[NUM_PSW] & ~PSW_C_MASK; + } +} + +static SIM_INLINE void cpu_set_v_flag_op(t_uint64 val, operand *op) +{ + switch(op_type(op)) { + case WD: + case UW: + cpu_set_v_flag(0); + break; + case HW: + case UH: + cpu_set_v_flag(val > HALF_MASK); + break; + case BT: + case SB: + default: + cpu_set_v_flag(val > BYTE_MASK); + break; + } +} + +static SIM_INLINE void cpu_set_v_flag(t_bool val) +{ + if (val) { + R[NUM_PSW] = R[NUM_PSW] | PSW_V_MASK; + if (R[NUM_PSW] & PSW_OE_MASK) { + cpu_abort(NORMAL_EXCEPTION, INTEGER_OVERFLOW); + } + } else { + R[NUM_PSW] = R[NUM_PSW] & ~PSW_V_MASK; + } +} + +static void cpu_set_nz_flags(t_uint64 data, operand *dst) +{ + int8 type = op_type(dst); + + switch (type) { + case WD: + case UW: + cpu_set_n_flag(!!(WD_MSB & data)); + cpu_set_z_flag((data & WORD_MASK) == 0); + break; + case HW: + case UH: + cpu_set_n_flag(HW_MSB & data); + cpu_set_z_flag((data & HALF_MASK) == 0); + break; + case BT: + case SB: + cpu_set_n_flag(BT_MSB & data); + cpu_set_z_flag((data & BYTE_MASK) == 0); + break; + } +} + +static SIM_INLINE void cpu_push_word(uint32 val) +{ + write_w(R[NUM_SP], val); + R[NUM_SP] += 4; +} + +static SIM_INLINE uint32 cpu_pop_word() +{ + uint32 result; + /* We always read fromthe stack first BEFORE decrementing, + in case this causes a fault. */ + result = read_w(R[NUM_SP] - 4, ACC_AF); + R[NUM_SP] -= 4; + return result; +} + +static SIM_INLINE void irq_push_word(uint32 val) +{ + write_w(R[NUM_ISP], val); + R[NUM_ISP] += 4; +} + +static SIM_INLINE uint32 irq_pop_word() +{ + R[NUM_ISP] -= 4; + return read_w(R[NUM_ISP], ACC_AF); +} + +static SIM_INLINE t_bool op_is_psw(operand *op) +{ + return (op->mode == 4 && op->reg == NUM_PSW); +} + +static SIM_INLINE t_bool op_is_sp(operand *op) +{ + return op->reg == NUM_SP; +} + +static SIM_INLINE void sub(t_uint64 a, t_uint64 b, operand *dst) +{ + t_uint64 result; + + result = a - b; + + cpu_write_op(dst, result); + + cpu_set_nz_flags(result, dst); + cpu_set_c_flag((uint32)b > (uint32)a); + cpu_set_v_flag_op(result, dst); +} + +static SIM_INLINE void add(t_uint64 a, t_uint64 b, operand *dst) +{ + t_uint64 result; + + result = a + b; + + cpu_write_op(dst, result); + + cpu_set_nz_flags(result, dst); + + switch(op_type(dst)) { + case WD: + case UW: + cpu_set_c_flag(result > WORD_MASK); + cpu_set_v_flag(!! (((a ^ ~b) & (a ^ result)) & WD_MSB)); + break; + case HW: + case UH: + cpu_set_c_flag(result > HALF_MASK); + cpu_set_v_flag(((a ^ ~b) & (a ^ result)) & HW_MSB); + break; + case BT: + case SB: + cpu_set_c_flag(result > BYTE_MASK); + cpu_set_v_flag(((a ^ ~b) & (a ^ result)) & BT_MSB); + } +} + +/* + * Set PSW's ET and ISC fields, and store global exception or fault + * state appropriately. + */ +void cpu_abort(uint8 et, uint8 isc) +{ + /* We don't trap Integer Overflow if the OE bit is not set */ + if ((R[NUM_PSW] & PSW_OE_MASK) || isc != INTEGER_OVERFLOW) { + R[NUM_PSW] &= ~(PSW_ISC_MASK); /* Clear ISC */ + R[NUM_PSW] &= ~(PSW_ET_MASK); /* Clear ET */ + R[NUM_PSW] |= et; /* Set ET */ + R[NUM_PSW] |= (uint32) (isc << PSW_ISC); /* Set ISC */ + + if (et == 3 && (isc == BREAKPOINT_TRAP || + isc == INTEGER_OVERFLOW || + isc == TRACE_TRAP)) { + longjmp(save_env, ABORT_TRAP); + } else { + longjmp(save_env, ABORT_EXC); + } + } +} diff --git a/3B2/3b2_cpu.h b/3B2/3b2_cpu.h new file mode 100644 index 00000000..e2a382c0 --- /dev/null +++ b/3B2/3b2_cpu.h @@ -0,0 +1,490 @@ +/* 3b2_cpu.h: AT&T 3B2 Model 400 CPU (WE32100) Header + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#ifndef _3B2_CPU_H_ +#define _3B2_CPU_H_ + +#include "3b2_defs.h" +#include "3b2_io.h" + +/* Execution Modes */ +#define EX_LVL_KERN 0 +#define EX_LVL_EXEC 1 +#define EX_LVL_SUPR 2 +#define EX_LVL_USER 3 + +/* Processor Version Number */ +#define WE32100_VER 0x1A + +/* + * + * Mode Syntax Mode Reg. Bytes Notes + * ---------------------------------------------------------------------- + * Absolute $expr 7 15 5 + * Abs. Deferred *$expr 14 15 5 + * Byte Disp. expr(%rn) 12 0-10,12-15 2 + * Byte Disp. Def. *expr(%rn) 13 0-10,12-15 2 + * Halfword Disp. expr(%rn) 10 0-10,12-15 3 + * Halfword Disp. Def. *expr(%rn) 11 0-10,12-15 3 + * Word Disp. expr(%rn) 8 0-10,12-15 5 + * Word Disp. Def. *expr(%rn) 9 0-10,12-15 5 + * AP Short Offset so(%ap) 7 0-14 1 1 + * FP Short Offset so(%fp) 6 0-14 1 1 + * Byte Immediate &imm8 6 15 2 2,3 + * Halfword Immediate &imm16 5 15 3 2,3 + * Word Immediate &imm32 4 15 5 2,3 + * Positive Literal &lit 0-3 0-15 1 2,3 + * Negative Literal &lit 15 0-15 1 2,3 + * Register %rn 4 0-14 1 1,3 + * Register Deferred (%rn) 5 0-10,12-14 1 1 + * Expanded Op. Type {type}opnd 14 0-14 2-6 4 + * + * Notes: + * + * 1. Mode field has special meaning if register field is 15; see + * absolute or immediate mode. + * 2. Mode may not be used for a destination operand. + * 3. Mode may not be used if the instruction takes effective address + * of the operand. + * 4. 'type' overrides instruction type; 'type' determines the operand + * type, except that it does not determine the length for immediate + * or literals or whether literals are signed or unsigned. 'opnd' + * determines actual address mode. For total bytes, add 1 to byte + * count for address mode determined by 'opnd'. + * + */ + +/* + * Opcodes + */ +typedef enum { + SPOPRD = 0x02, + SPOPD2 = 0x03, + MOVAW = 0x04, + SPOPRT = 0x06, + SPOPT2 = 0x07, + RET = 0x08, + MOVTRW = 0x0C, + SAVE = 0x10, + SPOPWD = 0x13, + EXTOP = 0x14, + SPOPWT = 0x17, + RESTORE = 0x18, + SWAPWI = 0x1C, + SWAPHI = 0x1E, + SWAPBI = 0x1F, + POPW = 0x20, + SPOPRS = 0x22, + SPOPS2 = 0x23, + JMP = 0x24, + CFLUSH = 0x27, + TSTW = 0x28, + TSTH = 0x2A, + TSTB = 0x2B, + CALL = 0x2C, + BPT = 0x2E, + WAIT = 0x2F, + EMB = 0x30, // Multi-byte + SPOP = 0x32, + SPOPWS = 0x33, + JSB = 0x34, + BSBH = 0x36, + BSBB = 0x37, + BITW = 0x38, + BITH = 0x3A, + BITB = 0x3B, + CMPW = 0x3C, + CMPH = 0x3E, + CMPB = 0x3F, + RGEQ = 0x40, + BGEH = 0x42, + BGEB = 0x43, + RGTR = 0x44, + BGH = 0x46, + BGB = 0x47, + RLSS = 0x48, + BLH = 0x4A, + BLB = 0x4B, + RLEQ = 0x4C, + BLEH = 0x4E, + BLEB = 0x4F, + RGEQU = 0x50, + BGEUH = 0x52, // Also BCCH + BGEUB = 0x53, // Also BCCB + RGTRU = 0x54, + BGUH = 0x56, + BGUB = 0x57, + BLSSU = 0x58, // Also BCS + BLUH = 0x5A, // Also BCSH + BLUB = 0x5B, // Also BCSB + RLEQU = 0x5C, + BLEUH = 0x5E, + BLEUB = 0x5F, + RVC = 0x60, + BVCH = 0x62, + BVCB = 0x63, + RNEQU = 0x64, + BNEH_D = 0x66, // Duplicate of 0x76 + BNEB_D = 0x67, // Duplicate of 0x77 + RVS = 0x68, + BVSH = 0x6A, + BVSB = 0x6B, + REQLU = 0x6C, + BEH_D = 0x6E, // Duplicate of 0x7E + BEB_D = 0x6F, // Duplicate of 0x7F + NOP = 0x70, + NOP3 = 0x72, + NOP2 = 0x73, + BNEQ = 0x74, + RNEQ = 0x74, + BNEH = 0x76, + BNEB = 0x77, + RSB = 0x78, + BRH = 0x7A, + BRB = 0x7B, + REQL = 0x7C, + BEH = 0x7E, + BEB = 0x7F, + CLRW = 0x80, + CLRH = 0x82, + CLRB = 0x83, + MOVW = 0x84, /* done */ + MOVH = 0x86, /* done */ + MOVB = 0x87, /* done */ + MCOMW = 0x88, + MCOMH = 0x8A, + MCOMB = 0x8B, + MNEGW = 0x8C, + MNEGH = 0x8E, + MNEGB = 0x8F, + INCW = 0x90, + INCH = 0x92, + INCB = 0x93, + DECW = 0x94, + DECH = 0x96, + DECB = 0x97, + ADDW2 = 0x9C, + ADDH2 = 0x9E, + ADDB2 = 0x9F, + PUSHW = 0xA0, + MODW2 = 0xA4, + MODH2 = 0xA6, + MODB2 = 0xA7, + MULW2 = 0xA8, + MULH2 = 0xAA, + MULB2 = 0xAB, + DIVW2 = 0xAC, + DIVH2 = 0xAE, + DIVB2 = 0xAF, + ORW2 = 0xB0, + ORH2 = 0xB2, + ORB2 = 0xB3, + XORW2 = 0xB4, + XORH2 = 0xB6, + XORB2 = 0xB7, + ANDW2 = 0xB8, + ANDH2 = 0xBA, + ANDB2 = 0xBB, + SUBW2 = 0xBC, + SUBH2 = 0xBE, + SUBB2 = 0xBF, + ALSW3 = 0xC0, + ARSW3 = 0xC4, + ARSH3 = 0xC6, + ARSB3 = 0xC7, + INSFW = 0xC8, + INSFH = 0xCA, + INSFB = 0xCB, + EXTFW = 0xCC, + EXTFH = 0xCE, + EXTFB = 0xCF, + LLSW3 = 0xD0, + LLSH3 = 0xD2, + LLSB3 = 0xD3, + LRSW3 = 0xD4, + ROTW = 0xD8, + ADDW3 = 0xDC, + ADDH3 = 0xDE, + ADDB3 = 0xDF, + PUSHAW = 0xE0, + MODW3 = 0xE4, + MODH3 = 0xE6, + MODB3 = 0xE7, + MULW3 = 0xE8, + MULH3 = 0xEA, + MULB3 = 0xEB, + DIVW3 = 0xEC, + DIVH3 = 0xEE, + DIVB3 = 0xEF, + ORW3 = 0xF0, + ORH3 = 0xF2, + ORB3 = 0xF3, + XORW3 = 0xF4, + XORH3 = 0xF6, + XORB3 = 0xF7, + ANDW3 = 0xF8, + ANDH3 = 0xFA, + ANDB3 = 0xFB, + SUBW3 = 0xFC, + SUBH3 = 0xFE, + SUBB3 = 0xFF, + MVERNO = 0x3009, + ENBVJMP = 0x300d, + DISVJMP = 0x3013, + MOVBLW = 0x3019, + STREND = 0x301f, + INTACK = 0x302f, + STRCPY = 0x3035, + RETG = 0x3045, + GATE = 0x3061, + CALLPS = 0x30ac, + RETPS = 0x30c8 +} opcode; + +typedef enum { + DECODE_SUCCESS, + DECODE_ERROR +} decode_result; + +/* Addressing Mode enum */ +typedef enum { + ABS, // Absolute + ABS_DEF, // Absolute Deferred + BYTE_DISP, // Byte Displacement + BYTE_DISP_DEF, // Byte Displacement Deferred + HFWD_DISP, // Halfword Displacement + HFWD_DISP_DEF, // Halfword Displacement Deferred + WORD_DISP, // Word Displacement + WORD_DISP_DEF, // Word Displacement Deferred + AP_SHORT_OFF, // AP Short Offset + FP_SHORT_OFF, // FP Short Offset + BYTE_IMM, // Byte Immediate + HFWD_IMM, // Halfword Immediate + WORD_IMM, // Word Immediate + POS_LIT, // Positive Literal + NEG_LIT, // Negative Literal + REGISTER, // Register + REGISTER_DEF, // Register Deferred + EXP // Expanded-operand type +} addr_mode; + +/* + * Each instruction expects operands of a certain type. + * + * The large majority of instructions expect operands that have a + * descriptor as the first byte. This descriptor carries all the + * information necessary to compute the addressing mode of the + * operand. + * + * e.g.: + * + * MOVB 6(%r1),%r0 + * +------+------+------+------+ + * | 0x87 | 0xc1 | 0x06 | 0x40 | + * +------+------+------+------+ + * ^^^^^^ + * Descriptor byte. mode = 13 (0x0c), register = 1 (0x01) + * + * + * Branch instructions have either an 8-bit or a 16-bit signed + * displacement value, and lack a descriptor byte. + * + * e.g.: + * + * BCCB 0x03 + * +------+------+ + * | 0x53 | 0x03 | 8-bit displacement + * +------+------+ + * + * BCCH 0x01ff + * +------+------+------+ + * | 0x52 | 0xff | 0x01 | 16-bit displacement + * +------+------+------+ + * + * + * TODO: Describe coprocessor instructions + * + */ +typedef enum { + OP_NONE, /* NULL type */ + OP_DESC, /* Descriptor byte */ + OP_BYTE, /* 8-bit signed value */ + OP_HALF, /* 16-bit signed value */ + OP_COPR /* Coprocessor instruction */ +} op_mode; + +/* Describes a mnemonic */ +typedef struct _mnemonic { + uint16 opcode; + int8 op_count; /* Number of operands */ + op_mode mode; /* Dispatch mode */ + int8 dtype; /* Default data type */ + char mnemonic[8]; + int8 src_op1; + int8 src_op2; + int8 src_op3; + int8 dst_op; +} mnemonic; + +/* + * Structure that describes each operand in a decoded instruction + */ +typedef struct _operand { + uint8 mode; /* Embedded data addressing mode */ + uint8 reg; /* Operand register (0-15) */ + int8 dtype; /* Default type for the operand */ + int8 etype; /* Expanded type (-1 if none) */ + union { + uint32 w; + uint16 h; + uint8 b; + } embedded; /* Data consumed as part of the instruction + stream, i.e. literals, displacement, + etc. */ + uint32 data; /* Data either read or written during + instruction execution */ +} operand; + +/* + * An inst is a combination of a decoded instruction and + * 0 to 4 operands. Also used for history record keeping. + */ +typedef struct _instr { + mnemonic *mn; + uint32 psw; + uint32 sp; + uint32 pc; + t_bool valid; + operand operands[4]; +} instr; + +/* Function prototypes */ + +t_stat cpu_svc(UNIT *uptr); +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_set_size(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat cpu_set_hist(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat cpu_show_hist(FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat cpu_set_halt(UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_clear_halt(UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_boot(int32 unit_num, DEVICE *dptr); + +t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs); + +void cpu_register_name(uint8 reg, char *buf, size_t len); +void cpu_show_operand(FILE *st, operand *op); +void fprint_sym_m(FILE *st, instr *ip); + +instr *cpu_next_instruction(void); + +uint8 decode_instruction(instr *instr); +t_bool cpu_on_interrupt(uint8 ipl); + +static uint32 cpu_effective_address(operand * op); +static uint32 cpu_read_op(operand * op); +static void cpu_write_op(operand * op, t_uint64 val); +static void cpu_set_nz_flags(t_uint64 data, operand * op); + +static SIM_INLINE uint8 cpu_ipl(); +static SIM_INLINE void cpu_on_normal_exception(uint8 isc); +static SIM_INLINE void cpu_on_stack_exception(uint8 isc); +static SIM_INLINE void cpu_on_process_exception(uint8 isc); +static SIM_INLINE void cpu_on_reset_exception(uint8 isc); +static SIM_INLINE void cpu_perform_gate(uint32 index1, uint32 index2); +static SIM_INLINE t_bool mem_exception(); +static SIM_INLINE void clear_exceptions(); +static SIM_INLINE void set_psw_tm(t_bool val); +static SIM_INLINE void clear_instruction(instr *inst); +static SIM_INLINE int8 op_type(operand *op); +static SIM_INLINE t_bool op_signed(operand *op); +static SIM_INLINE t_bool is_byte_immediate(operand * oper); +static SIM_INLINE t_bool is_halfword_immediate(operand * oper); +static SIM_INLINE t_bool is_word_immediate(operand * oper); +static SIM_INLINE t_bool is_positive_literal(operand * oper); +static SIM_INLINE t_bool is_negative_literal(operand * oper); +static SIM_INLINE t_bool invalid_destination(operand * oper); +static SIM_INLINE uint32 sign_extend_n(uint8 val); +static SIM_INLINE uint32 sign_extend_b(uint8 val); +static SIM_INLINE uint32 zero_extend_b(uint8 val); +static SIM_INLINE uint32 sign_extend_h(uint16 val); +static SIM_INLINE uint32 zero_extend_h(uint16 val); +static SIM_INLINE t_bool cpu_z_flag(); +static SIM_INLINE t_bool cpu_n_flag(); +static SIM_INLINE t_bool cpu_c_flag(); +static SIM_INLINE t_bool cpu_v_flag(); +static SIM_INLINE void cpu_set_z_flag(t_bool val); +static SIM_INLINE void cpu_set_n_flag(t_bool val); +static SIM_INLINE void cpu_set_c_flag(t_bool val); +static SIM_INLINE void cpu_set_v_flag(t_bool val); +static SIM_INLINE void cpu_set_v_flag_op(t_uint64 val, operand *op); +static SIM_INLINE uint8 cpu_execution_level(); +static SIM_INLINE void cpu_set_execution_level(uint8 level); +static SIM_INLINE void cpu_push_word(uint32 val); +static SIM_INLINE uint32 cpu_pop_word(); +static SIM_INLINE void irq_push_word(uint32 val); +static SIM_INLINE uint32 irq_pop_word(); +static SIM_INLINE void cpu_context_switch_1(uint32 pcbp); +static SIM_INLINE void cpu_context_switch_2(uint32 pcbp); +static SIM_INLINE void cpu_context_switch_3(uint32 pcbp); +static SIM_INLINE t_bool op_is_psw(operand *op); +static SIM_INLINE t_bool op_is_sp(operand *op); +static SIM_INLINE uint32 cpu_next_pc(); +static SIM_INLINE void add(t_uint64 a, t_uint64 b, operand *dst); +static SIM_INLINE void sub(t_uint64 a, t_uint64 b, operand *dst); + +/* Helper macros */ + +#define MOD(A,B,OP1,OP2,SZ) { \ + if (op_signed(OP1) && !op_signed(OP2)) { \ + result = (SZ)(B) % (A); \ + } else if (!op_signed(OP1) && op_signed(OP2)) { \ + result = (B) % (SZ)(A); \ + } else if (op_signed(OP1) && op_signed(OP2)) { \ + result = (SZ)(B) % (SZ)(A); \ + } else { \ + result = (B) % (A); \ + } \ + } + +#define DIV(A,B,OP1,OP2,SZ) { \ + if (op_signed(OP1) && !op_signed(OP2)) { \ + result = (SZ)(B) / (A); \ + } else if (!op_signed(OP1) && op_signed(OP2)) { \ + result = (B) / (SZ)(A); \ + } else if (op_signed(OP1) && op_signed(OP2)) { \ + result = (SZ)(B) / (SZ)(A); \ + } else { \ + result = (B) / (A); \ + } \ + } + +#endif diff --git a/3B2/3b2_defs.h b/3B2/3b2_defs.h new file mode 100644 index 00000000..7eee2fc6 --- /dev/null +++ b/3B2/3b2_defs.h @@ -0,0 +1,362 @@ +/* 3b2_defs.h: AT&T 3B2 Model 400 Simulator Definitions + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#ifndef _3B2_DEFS_H_ +#define _3B2_DEFS_H_ + +#include "sim_defs.h" +#include "sim_tmxr.h" +#include + +#define FALSE 0 +#define TRUE 1 + +#if defined (__GNUC__) +#define noret void __attribute__((noreturn)) +#else +#define noret void +#endif + +#if defined(__GLIBC__) && !defined(__cplusplus) +/* use glibc internal longjmp to bypass fortify checks */ +noret __libc_longjmp (jmp_buf buf, int val); +#define longjmp __libc_longjmp +#endif + +/* -v flag for examine routine */ +#define EX_V_FLAG 1 << 21 + +#define MAX_HIST_SIZE 1000000 +#define MIN_HIST_SIZE 64 +#define MAXMEMSIZE (1 << 22) /* 4 MB */ +#define MEM_SIZE (cpu_unit.capac) /* actual memory size */ +#define UNIT_V_MSIZE (UNIT_V_UF) + +#define UNIT_MSIZE (1 << UNIT_V_MSIZE) + +#define WD_MSB 0x80000000 +#define HW_MSB 0x8000 +#define BT_MSB 0x80 +#define WORD_MASK 0xffffffff +#define HALF_MASK 0xffffu +#define BYTE_MASK 0xff + +/* + * + * Physical memory in the 3B2 is arranged as follows: + * + * 0x00000000 - 0x0000FFFF: 64KB ROM (32K used) + * 0x00040000 - 0x0004FFFF: IO + * 0x02000000 - 0x023FFFFF: 4MB RAM ("Mainstore"), + * + */ + +#define PHYS_MEM_BASE 0x2000000 + +#define ROM_BASE 0 +#define IO_BASE 0x40000 +#define IO_SIZE 0x10000 +#define IOB_BASE 0x200000 +#define IOB_SIZE 0x1E00000 + +/* Register numbers */ +#define NUM_FP 9 +#define NUM_AP 10 +#define NUM_PSW 11 +#define NUM_SP 12 +#define NUM_PCBP 13 +#define NUM_ISP 14 +#define NUM_PC 15 + +#define CPU_CM (cpu_km ? L_KERNEL : ((R[NUM_PSW] >> PSW_CM) & 3)) + +/* Simulator stop codes */ +#define STOP_RSRV 1 +#define STOP_IBKPT 2 /* Breakpoint encountered */ +#define STOP_OPCODE 3 /* Invalid opcode */ +#define STOP_IRQ 4 /* Interrupt */ +#define STOP_EX 5 /* Exception */ +#define STOP_ESTK 6 /* Exception stack too deep */ +#define STOP_MMU 7 /* Unimplemented MMU Feature */ + +/* Exceptional conditions handled within the instruction loop */ +#define ABORT_EXC 1 /* CPU exception */ +#define ABORT_TRAP 2 /* CPU trap */ + +/* Contexts for aborts */ +#define C_NONE 0 /* No context. Normal handling. */ +#define C_NORMAL_GATE_VECTOR 1 +#define C_PROCESS_GATE_PCB 2 +#define C_PROCESS_OLD_PCB 3 +#define C_PROCESS_NEW_PCB 4 +#define C_RESET_GATE_VECTOR 5 +#define C_RESET_INT_STACK 6 +#define C_RESET_NEW_PCB 7 +#define C_RESET_SYSTEM_DATA 8 +#define C_STACK_FAULT 9 + +/* Debug flags */ +#define READ_MSG 0x01 +#define WRITE_MSG 0x02 +#define DECODE_MSG 0x04 +#define EXECUTE_MSG 0x08 +#define INIT_MSG 0x10 +#define IRQ_MSG 0x20 +#define IO_D_MSG 0x40 +#define TRACE_MSG 0x80 + +/* Data types operated on by instructions. NB: These integer values + have meaning when decoding instructions, so this is not just an + enum. Please don't change them. */ +#define UW 0 /* Unsigned Word */ +#define UH 2 /* Unsigned Halfword */ +#define BT 3 /* Unsigned Byte */ +#define WD 4 /* Signed Word */ +#define HW 6 /* Signed Halfword */ +#define SB 7 /* Signed Byte */ + +#define NA -1 + +/* + * Exceptions are described on page 2-66 of the WE32100 manual + */ + +/* Exception Types */ + +#define RESET_EXCEPTION 0 +#define PROCESS_EXCEPTION 1 +#define STACK_EXCEPTION 2 +#define NORMAL_EXCEPTION 3 + +/* Reset Exceptions */ +#define OLD_PCB_FAULT 0 +#define SYSTEM_DATA_FAULT 1 +#define INTERRUPT_STACK_FAULT 2 +#define EXTERNAL_RESET 3 +#define NEW_PCB_FAULT 4 +#define GATE_VECTOR_FAULT 6 + +/* Processor Exceptions */ +#define GATE_PCB_FAULT 1 + +/* Stack Exceptions */ +#define STACK_BOUND 0 +#define STACK_FAULT 1 +#define INTERRUPT_ID_FETCH 3 + +/* Normal Exceptions */ +#define INTEGER_ZERO_DIVIDE 0 +#define TRACE_TRAP 1 +#define ILLEGAL_OPCODE 2 +#define RESERVED_OPCODE 3 +#define INVALID_DESCRIPTOR 4 +#define EXTERNAL_MEMORY_FAULT 5 +#define N_GATE_VECTOR 6 +#define ILLEGAL_LEVEL_CHANGE 7 +#define RESERVED_DATATYPE 8 +#define INTEGER_OVERFLOW 9 +#define PRIVILEGED_OPCODE 10 +#define BREAKPOINT_TRAP 14 +#define PRIVILEGED_REGISTER 15 + +#define PSW_ET 0 +#define PSW_TM 2u +#define PSW_ISC 3u +#define PSW_I 7 +#define PSW_R 8 +#define PSW_PM 9 +#define PSW_CM 11 +#define PSW_IPL 13 +#define PSW_TE 17 +#define PSW_C 18 +#define PSW_V 19 +#define PSW_Z 20 +#define PSW_N 21 +#define PSW_OE 22 +#define PSW_CD 23 +#define PSW_QIE 24 +#define PSW_CFD 25 + +/* Access Request types */ +#define ACC_MT 0 /* Move Translated */ +#define ACC_SPW 1 /* Support processor write */ +#define ACC_SPF 3 /* Support processor fetch */ +#define ACC_IR 7 /* Interlocked read */ +#define ACC_AF 8 /* Address fetch */ +#define ACC_OF 9 /* Operand fetch */ +#define ACC_W 10 /* Write */ +#define ACC_IFAD 12 /* Instruction fetch after discontinuity */ +#define ACC_IF 13 /* Instruction fetch */ + + +#define L_KERNEL 0 +#define L_EXEC 1 +#define L_SUPER 2 +#define L_USER 3 + +#define PSW_ET_MASK 3u +#define PSW_TM_MASK (1u << PSW_TM) +#define PSW_ISC_MASK (15u << PSW_ISC) +#define PSW_I_MASK (1u << PSW_I) +#define PSW_R_MASK (1u << PSW_R) +#define PSW_PM_MASK (3u << PSW_PM) +#define PSW_CM_MASK (3u << PSW_CM) +#define PSW_IPL_MASK (15u << PSW_IPL) +#define PSW_TE_MASK (1u << PSW_TE) +#define PSW_C_MASK (1u << PSW_C) +#define PSW_V_MASK (1u << PSW_V) +#define PSW_N_MASK (1u << PSW_N) +#define PSW_Z_MASK (1u << PSW_Z) +#define PSW_OE_MASK (1u << PSW_OE) +#define PSW_CD_MASK (1u << PSW_CD) +#define PSW_QIE_MASK (1u << PSW_QIE) +#define PSW_CFD_MASK (1u << PSW_CFD) + +#define PSW_CUR_IPL (((R[NUM_PSW] & PSW_IPL_MASK) >> PSW_IPL) & 0xf) + +#define TODBASE 0x41000 +#define TODSIZE 0x40 +#define TIMERBASE 0x42000 +#define TIMERSIZE 0x20 +#define NVRAMBASE 0x43000 +#define NVRAMSIZE 0x1000 +#define CSRBASE 0x44000 +#define CSRSIZE 0x100 + +#define CSRTIMO 0x8000 /* Bus Timeout Error */ +#define CSRPARE 0x4000 /* Memory Parity Error */ +#define CSRRRST 0x2000 /* System Reset Request */ +#define CSRALGN 0x1000 /* Memory Alignment Fault */ +#define CSRLED 0x0800 /* Failure LED */ +#define CSRFLOP 0x0400 /* Floppy Motor On */ +#define CSRRES 0x0200 /* Reserved */ +#define CSRITIM 0x0100 /* Inhibit Timers */ +#define CSRIFLT 0x0080 /* Inhibit Faults */ +#define CSRCLK 0x0040 /* Clock Interrupt */ +#define CSRPIR8 0x0020 /* Programmed Interrupt 8 */ +#define CSRPIR9 0x0010 /* Programmed Interrupt 9 */ +#define CSRUART 0x0008 /* UART Interrupt */ +#define CSRDISK 0x0004 /* Floppy Interrupt */ +#define CSRDMA 0x0002 /* DMA Interrupt */ +#define CSRIOF 0x0001 /* I/O Board Fail */ + +#define TIMER_REG_DIVA 0x03 +#define TIMER_REG_DIVB 0x07 +#define TIMER_REG_DIVC 0x0b +#define TIMER_REG_CTRL 0x0f +#define TIMER_CLR_LATCH 0x13 + +/* Clock state bitmasks */ +#define CLK_MD 0x0E /* Mode mask */ +#define CLK_RW 0x30 /* RW mask */ +#define CLK_SC 0xC0 /* SC mask */ + +#define CLK_LAT 0x00 +#define CLK_LSB 0x10 +#define CLK_MSB 0x20 +#define CLK_LMB 0x30 + +#define CLK_MD0 0x00 +#define CLK_MD1 0x02 +#define CLK_MD2 0x04 +#define CLK_MD3 0x06 +#define CLK_MD4 0x08 +#define CLK_MD5 0x0a + +/* Timer definitions */ + +#define TMR_CLK 0 /* The clock responsible for IPL 15 interrupts */ +#define TMR_TOD 1 /* The Time-of-Day clock */ + +#define TPS_CLK 100 +#define TPS_TOD 10 + + +/* TIMING SECTION */ +/* ----------------------------------------------- */ +/* Calculate delays (in simulator steps) for times */ +/* System clock runs at 10MHz; 100ns period. */ + +#define US_PER_INST 0.9 + +#define INST_PER_MS (1000.0 / US_PER_INST) + +#define DELAY_US(us) ((uint32)((us) / US_PER_INST)) +#define DELAY_MS(ms) ((uint32)(((ms) * 1000) / US_PER_INST)) + +/* global symbols from the CPU */ + +extern jmp_buf save_env; +extern uint32 *ROM; +extern uint32 *RAM; +extern uint32 R[16]; +extern REG cpu_reg[]; +extern DEVICE cpu_dev; +extern UNIT cpu_unit; +extern uint8 fault; +extern DEBTAB sys_deb_tab[]; +extern t_bool cpu_km; + +/* Generic callback function */ +typedef void (*callback)(void); + +/* global symbols from the DMAC */ +extern DEVICE dmac_dev; + +/* global symbols from the CSR */ +extern uint16 csr_data; + +/* global symbols from the IU */ +extern t_bool iu_increment_a; +extern t_bool iu_increment_b; +extern void increment_modep_a(); +extern void increment_modep_b(); + +/* global symbols from the MMU */ +extern t_bool mmu_enabled(); +extern void mmu_enable(); +extern void mmu_disable(); +extern uint8 read_b(uint32 va, uint8 acc); +extern uint16 read_h(uint32 va, uint8 acc); +extern uint32 read_w(uint32 va, uint8 acc); +extern void write_b(uint32 va, uint8 val); +extern void write_h(uint32 va, uint16 val); +extern void write_w(uint32 va, uint32 val); + +/* Globally scoped CPU functions */ +void cpu_abort(uint8 et, uint8 isc); +void cpu_set_irq(uint8 ipl, uint8 id, uint16 csr_flags); +void cpu_clear_irq(uint8 ipl, uint16 csr_flags); + +/* Globally scoped IO functions */ +uint32 io_read(uint32 pa, size_t size); +void io_write(uint32 pa, uint32 val, size_t size); + +#endif diff --git a/3B2/3b2_dmac.c b/3B2/3b2_dmac.c new file mode 100644 index 00000000..f836f355 --- /dev/null +++ b/3B2/3b2_dmac.c @@ -0,0 +1,443 @@ +/* 3b2_dmac.c: AT&T 3B2 Model 400 AM9517A DMA Controller Implementation + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#include "3b2_dmac.h" + +DMA_STATE dma_state; + +UNIT dmac_unit[] = { + { UDATA (NULL, 0, 0), 0, 0 }, + { UDATA (NULL, 0, 0), 0, 1 }, + { UDATA (NULL, 0, 0), 0, 2 }, + { UDATA (NULL, 0, 0), 0, 3 }, + { NULL } +}; + +REG dmac_reg[] = { + { NULL } +}; + +DEVICE dmac_dev = { + "DMAC", dmac_unit, dmac_reg, NULL, + 1, 16, 8, 4, 16, 32, + NULL, NULL, &dmac_reset, + NULL, NULL, NULL, NULL, + DEV_DEBUG, 0, sys_deb_tab +}; + +dmac_drq_handler dmac_drq_handlers[] = { + {DMA_ID_CHAN, IDBASE+ID_DATA_REG, &id_drq, id_drq_handled}, + {DMA_IF_CHAN, IFBASE+IF_DATA_REG, &if_state.drq, if_drq_handled}, + {DMA_IUA_CHAN, IUBASE+IUA_DATA_REG, &iu_state.drqa, iua_drq_handled}, + {DMA_IUB_CHAN, IUBASE+IUB_DATA_REG, &iu_state.drqb, iub_drq_handled}, + {0, 0, NULL, NULL } +}; + +t_stat dmac_reset(DEVICE *dptr) +{ + int i; + + memset(&dma_state, 0, sizeof(dma_state)); + + for (i = 0; i < 4; i++) { + dma_state.channels[i].page = 0; + dma_state.channels[i].addr = 0; + dma_state.channels[i].wcount = 0; + dma_state.channels[i].addr_c = 0; + dma_state.channels[i].wcount_c = 0; + } + + return SCPE_OK; +} + +uint32 dmac_read(uint32 pa, size_t size) +{ + uint8 reg, base, data; + + base =(uint8) (pa >> 12); + reg = pa & 0xff; + + switch (base) { + case DMA_C: /* 0x48xxx */ + switch (reg) { + case 0: /* channel 0 current address reg */ + data = ((dma_state.channels[0].addr_c) >> (dma_state.bff * 8)) & 0xff; + sim_debug(READ_MSG, &dmac_dev, + "[%08x] Reading Channel 0 Addr Reg: %08x\n", + R[NUM_PC], data); + dma_state.bff ^= 1; + break; + case 1: /* channel 0 current address reg */ + data = ((dma_state.channels[0].wcount_c) >> (dma_state.bff * 8)) & 0xff; + sim_debug(READ_MSG, &dmac_dev, + "[%08x] Reading Channel 0 Addr Count Reg: %08x\n", + R[NUM_PC], data); + dma_state.bff ^= 1; + break; + case 2: /* channel 1 current address reg */ + data = ((dma_state.channels[1].addr_c) >> (dma_state.bff * 8)) & 0xff; + sim_debug(READ_MSG, &dmac_dev, + "[%08x] Reading Channel 1 Addr Reg: %08x\n", + R[NUM_PC], data); + dma_state.bff ^= 1; + break; + case 3: /* channel 1 current address reg */ + data = ((dma_state.channels[1].wcount_c) >> (dma_state.bff * 8)) & 0xff; + sim_debug(READ_MSG, &dmac_dev, + "[%08x] Reading Channel 1 Addr Count Reg: %08x\n", + R[NUM_PC], data); + dma_state.bff ^= 1; + break; + case 4: /* channel 2 current address reg */ + data = ((dma_state.channels[2].addr_c) >> (dma_state.bff * 8)) & 0xff; + sim_debug(READ_MSG, &dmac_dev, + "[%08x] Reading Channel 2 Addr Reg: %08x\n", + R[NUM_PC], data); + dma_state.bff ^= 1; + break; + case 5: /* channel 2 current address reg */ + data = ((dma_state.channels[2].wcount_c) >> (dma_state.bff * 8)) & 0xff; + sim_debug(READ_MSG, &dmac_dev, + "[%08x] Reading Channel 2 Addr Count Reg: %08x\n", + R[NUM_PC], data); + dma_state.bff ^= 1; + break; + case 6: /* channel 3 current address reg */ + data = ((dma_state.channels[3].addr_c) >> (dma_state.bff * 8)) & 0xff; + sim_debug(READ_MSG, &dmac_dev, + "[%08x] Reading Channel 3 Addr Reg: %08x\n", + R[NUM_PC], data); + dma_state.bff ^= 1; + break; + case 7: /* channel 3 current address reg */ + data = ((dma_state.channels[3].wcount_c) >> (dma_state.bff * 8)) & 0xff; + sim_debug(READ_MSG, &dmac_dev, + "[%08x] Reading Channel 3 Addr Count Reg: %08x\n", + R[NUM_PC], data); + dma_state.bff ^= 1; + break; + case 8: + data = dma_state.status; + sim_debug(READ_MSG, &dmac_dev, + "[%08x] Reading DMAC Status %08x\n", + R[NUM_PC], data); + dma_state.status = 0; + break; + default: + sim_debug(READ_MSG, &dmac_dev, + "[%08x] DMAC READ %lu B @ %08x\n", + R[NUM_PC], size, pa); + data = 0; + } + + return data; + default: + sim_debug(READ_MSG, &dmac_dev, + "[%08x] [BASE: %08x] DMAC READ %lu B @ %08x\n", + R[NUM_PC], base, size, pa); + return 0; + } +} + +/* + * Program the DMAC + */ +void dmac_program(uint8 reg, uint8 val) +{ + uint8 channel_id, i, chan_num; + dma_channel *channel; + + if (reg < 8) { + switch (reg) { + case 0: + case 1: + chan_num = 0; + break; + case 2: + case 3: + chan_num = 1; + break; + case 4: + case 5: + chan_num = 2; + break; + case 6: + case 7: + chan_num = 3; + break; + } + + channel = &dma_state.channels[chan_num]; + + if (channel == NULL) { + /* This should never happen */ + return; + } + + switch (reg & 1) { + case 0: /* Address */ + channel->addr &= ~(0xff << dma_state.bff * 8); + channel->addr |= (val & 0xff) << (dma_state.bff * 8); + channel->addr_c = channel->addr; + sim_debug(WRITE_MSG, &dmac_dev, + "Set address channel %d byte %d = %08x\n", + chan_num, dma_state.bff, channel->addr); + break; + case 1: /* Word Count */ + channel->wcount &= ~(0xff << dma_state.bff * 8); + channel->wcount |= (val & 0xff) << (dma_state.bff * 8); + channel->wcount_c = channel->wcount; + sim_debug(WRITE_MSG, &dmac_dev, + "Set word count channel %d byte %d = %08x\n", + chan_num, dma_state.bff, channel->wcount); + break; + } + + /* Toggle the byte flip-flop */ + dma_state.bff ^= 1; + + /* Handled. */ + return; + } + + /* If it hasn't been handled, it must be one of the following + registers. */ + + switch (reg) { + case 8: /* Command */ + dma_state.command = val; + sim_debug(WRITE_MSG, &dmac_dev, + "[%08x] Command: val=%02x\n", + R[NUM_PC], val); + break; + case 9: /* Request */ + sim_debug(WRITE_MSG, &dmac_dev, + "[%08x] Request set: val=%02x\n", + R[NUM_PC], val); + dma_state.request = val; + break; + case 10: /* Write Single Mask Register Bit */ + channel_id = val & 3; + + /* "Clear or Set" is bit 2 */ + if ((val >> 2) & 1) { + dma_state.mask |= (1 << channel_id); + } else { + dma_state.mask &= ~(1 << channel_id); + } + + sim_debug(WRITE_MSG, &dmac_dev, + "[%08x] Write Single Mask Register Bit. channel=%d set/clear=%02x\n", + R[NUM_PC], channel_id, (val >> 2) & 1); + break; + case 11: /* Mode */ + sim_debug(WRITE_MSG, &dmac_dev, + "[%08x] Mode Set. val=%02x\n", + R[NUM_PC], val); + dma_state.mode = val; + break; + case 12: /* Clear Byte Pointer Flip/Flop */ + dma_state.bff = 0; + break; + case 13: /* Master Clear */ + dma_state.bff = 0; + dma_state.command = 0; + dma_state.status = 0; + for (i = 0; i < 4; i++) { + dma_state.channels[i].addr = 0; + dma_state.channels[i].wcount = 0; + dma_state.channels[i].page = 0; + } + break; + case 15: /* Write All Mask Register Bits */ + sim_debug(WRITE_MSG, &dmac_dev, + "[%08x] Clear DMAC Interrupt. val=%02x\n", + R[NUM_PC], val); + dma_state.mask = val & 0xf; + break; + case 16: /* Clear DMAC Interrupt */ + sim_debug(WRITE_MSG, &dmac_dev, + "[%08x] Clear DMAC Interrupt in DMAC. val=%02x\n", + R[NUM_PC], val); + break; + default: + sim_debug(WRITE_MSG, &dmac_dev, + "[%08x] Unhandled DMAC write. reg=%x val=%02x\n", + R[NUM_PC], reg, val); + break; + } +} + +void dmac_page_update(uint8 base, uint8 reg, uint8 val) +{ + uint8 shift = 0; + + /* Sanity check */ + if (reg > 3) { + return; + } + + /* The actual register is a 32-bit, byte-addressed register, so + that address 4x000 is the highest byte, 4x003 is the lowest + byte. */ + + shift = -(reg - 3) * 8; + + switch (base) { + case DMA_ID: + sim_debug(WRITE_MSG, &dmac_dev, "Set page channel 0 = %x\n", val); + dma_state.channels[DMA_ID_CHAN].page &= ~(0xff << shift); + dma_state.channels[DMA_ID_CHAN].page |= (val << shift); + break; + case DMA_IF: + sim_debug(WRITE_MSG, &dmac_dev, "Set page channel 1 = %x\n", val); + dma_state.channels[DMA_IF_CHAN].page &= ~(0xff << shift); + dma_state.channels[DMA_IF_CHAN].page |= (val << shift); + break; + case DMA_IUA: + sim_debug(WRITE_MSG, &dmac_dev, "Set page channel 2 = %x\n", val); + dma_state.channels[DMA_IUA_CHAN].page &= ~(0xff << shift); + dma_state.channels[DMA_IUA_CHAN].page |= (val << shift); + break; + case DMA_IUB: + sim_debug(WRITE_MSG, &dmac_dev, "Set page channel 3 = %x\n", val); + dma_state.channels[DMA_IUB_CHAN].page &= ~(0xff << shift); + dma_state.channels[DMA_IUB_CHAN].page |= (val << shift); + break; + } +} + +void dmac_write(uint32 pa, uint32 val, size_t size) +{ + uint8 reg, base; + + base = (uint8) (pa >> 12); + reg = pa & 0xff; + + switch (base) { + case DMA_C: /* 0x48xxx */ + dmac_program(reg, (uint8) val); + break; + + case DMA_ID: /* 0x45xxx */ + case DMA_IUA: /* 0x46xxx */ + case DMA_IUB: /* 0x47xxx */ + case DMA_IF: /* 0x4Exxx */ + dmac_page_update(base, reg, (uint8) val); + break; + } +} + +static SIM_INLINE uint32 dma_address(uint8 channel, uint32 offset, t_bool r) { + uint32 addr; + + addr = (PHYS_MEM_BASE + + dma_state.channels[channel].addr + + offset); + + /* The top bit of the page address is a R/W bit, so we mask it here */ + addr |= (uint32) (((uint32)dma_state.channels[channel].page & 0x7f) << 16); + + return addr; +} + +void dmac_transfer(uint8 channel, uint32 service_address) +{ + uint8 data; + int32 i; + uint16 offset; + uint32 addr; + + dma_channel *chan = &dma_state.channels[channel]; + + /* TODO: This does not handle decrement-mode transfers, + which don't seem to be used in SVR3 */ + + switch ((dma_state.mode >> 2) & 0xf) { + case DMA_MODE_VERIFY: + sim_debug(EXECUTE_MSG, &dmac_dev, + "[%08x] [dmac_transfer channel=%d] unhandled VERIFY request.\n", + R[NUM_PC], channel); + break; + case DMA_MODE_WRITE: + sim_debug(EXECUTE_MSG, &dmac_dev, + "[%08x] [dmac_transfer channel=%d] write: %d bytes from %08x\n", + R[NUM_PC], channel, + chan->wcount + 1, + dma_address(channel, 0, TRUE)); + offset = 0; + for (i = chan->wcount; i >= 0; i--) { + addr = dma_address(channel, offset, TRUE); + chan->addr_c = dma_state.channels[channel].addr + offset; + offset++; + data = pread_b(service_address); + write_b(addr, data); + } + break; + case DMA_MODE_READ: + sim_debug(EXECUTE_MSG, &dmac_dev, + "[%08x] [dmac_transfer channel=%d] read: %d bytes to %08x\n", + R[NUM_PC], channel, + chan->wcount + 1, + dma_address(channel, 0, TRUE)); + offset = 0; + for (i = chan->wcount; i >= 0; i--) { + addr = dma_address(channel, offset++, TRUE); + chan->addr_c = dma_state.channels[channel].addr + offset; + data = pread_b(addr); + write_b(service_address, data); + } + break; + } + + /* End of Process must set the IF channel's mask bit */ + dma_state.mask |= (1 << channel); + dma_state.status |= (1 << channel); +} + +/* + * Service pending DRQs + */ +void dmac_service_drqs() +{ + dmac_drq_handler *h; + + for (h = &dmac_drq_handlers[0]; h->drq != NULL; h++) { + /* Only trigger if the channel has a DRQ set and its channel's + mask bit is 0 */ + if (*h->drq && ((dma_state.mask >> h->channel) & 0x1) == 0) { + dmac_transfer(h->channel, h->service_address); + *h->drq = FALSE; /* Immediately clear DRQ state */ + if (h->handled_callback != NULL) { + h->handled_callback(); + } + } + } +} diff --git a/3B2/3b2_dmac.h b/3B2/3b2_dmac.h new file mode 100644 index 00000000..55bc30a9 --- /dev/null +++ b/3B2/3b2_dmac.h @@ -0,0 +1,113 @@ +/* 3b2_dmac.h: AT&T 3B2 Model 400 AM9517A DMA Controller Header + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#ifndef _3B2_DMAC_H_ +#define _3B2_DMAC_H_ + +#include "3b2_sysdev.h" +#include "3b2_id.h" +#include "3b2_if.h" + +/* DMA Controller */ +#define DMACBASE 0x48000 +#define DMACSIZE 0x11 + +/* DMA integrated disk page buffer */ +#define DMAIDBASE 0x45000 +#define DMAIDSIZE 0x5 + +/* DMA integrated uart A page buffer */ +#define DMAIUABASE 0x46000 +#define DMAIUASIZE 0x5 + +/* DMA integrated uart B page buffer */ +#define DMAIUBBASE 0x47000 +#define DMAIUBSIZE 0x5 + +/* DMA integrated floppy page buffer */ +#define DMAIFBASE 0x4E000 +#define DMAIFSIZE 0x5 + +#define DMA_ID_CHAN 0 +#define DMA_IF_CHAN 1 +#define DMA_IUA_CHAN 2 +#define DMA_IUB_CHAN 3 + +#define DMA_ID 0x45 +#define DMA_IUA 0x46 +#define DMA_IUB 0x47 +#define DMA_C 0x48 +#define DMA_IF 0x4E + +#define DMA_MODE_VERIFY 0 +#define DMA_MODE_WRITE 1 /* Write to memory from device */ +#define DMA_MODE_READ 2 /* Read from memory to device */ + +#define DMA_IF_READ (IFBASE + IF_DATA_REG) + + +typedef struct { + uint8 page; + uint16 addr; /* Original addr */ + uint16 wcount; /* Original wcount */ + uint16 addr_c; /* Current addr */ + uint16 wcount_c; /* Current word-count */ +} dma_channel; + +typedef struct { + /* Byte (high/low) flip-flop */ + uint8 bff; + + /* Address and count registers for channels 0-3 */ + dma_channel channels[4]; + + /* DMAC programmable registers */ + uint8 command; + uint8 mode; + uint8 request; + uint8 mask; + uint8 status; +} DMA_STATE; + +typedef struct { + uint8 channel; + uint32 service_address; + t_bool *drq; + void (*handled_callback)(); +} dmac_drq_handler; + +/* DMAC */ +t_stat dmac_reset(DEVICE *dptr); +uint32 dmac_read(uint32 pa, size_t size); +void dmac_write(uint32 pa, uint32 val, size_t size); +void dmac_service_drqs(); +void dmac_transfer(uint8 channel, uint32 service_address); + +#endif diff --git a/3B2/3b2_id.c b/3B2/3b2_id.c new file mode 100644 index 00000000..298d5e47 --- /dev/null +++ b/3B2/3b2_id.c @@ -0,0 +1,844 @@ +/* 3b2_cpu.h: AT&T 3B2 Model 400 Hard Disk (uPD7261) Implementation + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +/* + * The larger of the two hard drive options shipped with the AT&T 3B2 + * was a 72MB Wren II ST-506 MFM hard disk. That's what we emulate + * here, as a start. + * + * Formatted Capacity: 76,723,200 Bytes + * + * Cylinders: 925 + * Sectors/Track: 18 + * Heads: 9 + * Bytes/Sector: 512 + * Avg. seek: 28 ms + * Seek/track: 5 ms + * + * Drive Information from the 3B2 FAQ: + * + * Drive type drv id cyls trk/cyl sec/trk byte/cyl abbrev + * --------------- ------ ---- ------- ------- -------- ------ + * Wren II 30MB 3 697 5 18 512 HD30 + * Wren II 72MB 5 925 9 18 512 HD72 + * Fujitsu M2243AS 8 754 11 18 512 HD72C + * Micropolis 1325 5 1024 8 18 512 HD72 + * Maxtor 1140 4* 918= 15 18 512 HD120 + * Maxtor 1190 11 1224+ 15 18 512 HD135 + * + */ + +#include +#include "3b2_id.h" + +/* Wait times, in CPU steps, for various actions */ + +/* Each step is 50 us in buffered mode */ +#define ID_SEEK_WAIT 100 /* us */ +#define ID_SEEK_BASE 700 /* us */ +#define ID_RECAL_WAIT 6000 /* us */ + +/* Reading data takes about 8ms per sector, plus time to seek if not + on cylinder */ +#define ID_RW_WAIT 8000 /* us */ + +/* Sense Unit Status completes in about 200 us */ +#define ID_SUS_WAIT 200 /* us */ + +/* Specify takes a bit longer, 1.25 ms */ +#define ID_SPEC_WAIT 1250 /* us */ + +/* Sense Interrupt Status is about 142 us */ +#define ID_SIS_WAIT 142 /* us */ + +/* The catch-all command wait time is about 140 us */ +#define ID_CMD_WAIT 140 /* us */ + +/* State. The DP7261 supports four MFM (winchester) disks connected + simultaneously. There is only one set of registers, however, so + commands must be completed for one unit before they can begin on + another unit. */ + +/* Data FIFO pointer - Read */ +uint8 id_dpr = 0; +/* Data FIFO pointer - Write */ +uint8 id_dpw = 0; +/* Selected unit */ +uint8 id_sel = 0; +/* Controller Status Register */ +uint8 id_status = 0; +/* Unit Interrupt Status */ +uint8 id_int_status; +/* Last command received */ +uint8 id_cmd = 0; +/* DMAC request */ +t_bool id_drq = FALSE; +/* 8-byte FIFO */ +uint8 id_data[ID_FIFO_LEN] = {0}; +/* INT output pin */ +t_bool id_irq = FALSE; +/* Special flag for seek end SIS */ +t_bool id_seek_sis = FALSE; + +/* State of each drive */ + +/* Cylinder the drive is positioned on */ +uint16 id_cyl[ID_NUM_UNITS] = {0}; + +/* DTLH byte for each drive */ +uint8 id_dtlh[ID_NUM_UNITS] = {0}; + +/* Arguments of last READ, WRITE, VERIFY ID, or READ ID command */ + +/* Ending Track Number (from Specify) */ +uint8 id_etn = 0; +/* Ending Sector Number (from Specify) */ +uint8 id_esn = 0; +/* Physical sector number */ +uint8 id_psn = 0; +/* Physical head number */ +uint8 id_phn = 0; +/* Logical cylinder number, high byte */ +uint8 id_lcnh = 0; +/* Logical cylinder number, low byte */ +uint8 id_lcnl = 0; +/* Logical head number */ +uint8 id_lhn = 0; +/* Logical sector number */ +uint8 id_lsn = 0; +/* Number of sectors to transfer, decremented after each sector */ +uint8 id_scnt = 0; +/* Sector buffer */ +uint8 id_buf[ID_SEC_SIZE]; +/* Buffer pointer */ +size_t id_buf_ptr = 0; + +uint8 id_idfield[ID_IDFIELD_LEN]; +uint8 id_idfield_ptr = 0; + +/* + * TODO: Macros used for debugging timers. Remove when debugging is complete. + */ +double id_start_time; + +#define ID_START_TIME() { id_start_time = sim_gtime(); } +#define ID_DIFF_MS() ((sim_gtime() - id_start_time) / INST_PER_MS) + +UNIT id_unit[] = { + {UDATA (&id_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BINK, ID_DSK_SIZE), 0, 0 }, + {UDATA (&id_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BINK, ID_DSK_SIZE), 0, 1 }, + { NULL } +}; + +/* The currently selected drive number */ +UNIT *id_sel_unit = &id_unit[0]; + +REG id_reg[] = { + { HRDATAD(CMD, id_cmd, 8, "Command") }, + { HRDATAD(STAT, id_status, 8, "Status") }, + { BRDATAD(CYL, id_cyl, 8, 8, ID_NUM_UNITS, "Track") }, + { NULL } +}; + +DEVICE id_dev = { + "ID", id_unit, id_reg, NULL, + ID_NUM_UNITS, 16, 32, 1, 16, 8, + NULL, NULL, &id_reset, + NULL, &id_attach, &id_detach, NULL, + DEV_DEBUG|DEV_SECTORS, 0, sys_deb_tab, + NULL, NULL, &id_help, NULL, NULL, + &id_description +}; + +/* Function implementation */ + +static SIM_INLINE void id_activate(uint32 delay) +{ + ID_START_TIME(); + sim_activate_abs(id_sel_unit, (int32) delay); +} + +static SIM_INLINE void id_clear_fifo() +{ + id_dpr = 0; + id_dpw = 0; +} + +t_stat id_svc(UNIT *uptr) +{ + /* Complete the last command */ + id_status = ID_STAT_CEH; + + switch (CMD_NUM) { + case ID_CMD_SEEK: /* fall-through */ + case ID_CMD_RECAL: + /* SRQ is only set in polling mode (POL bit is 0) */ + if ((id_dtlh[UNIT_NUM] & ID_DTLH_POLL) == 0) { + id_status |= ID_STAT_SRQ; + } + if (uptr->flags & UNIT_ATT) { + id_int_status = ID_IST_SEN|(uint8)uptr->ID_UNIT_NUM; + } else { + id_int_status = ID_IST_NR|(uint8)uptr->ID_UNIT_NUM; + } + break; + case ID_CMD_SIS: + if (!id_seek_sis) { + id_status = ID_STAT_CEL; + } + id_seek_sis = FALSE; + id_data[0] = id_int_status; + id_status &= ~ID_STAT_SRQ; + break; + case ID_CMD_SUS: + if ((id_sel_unit->flags & UNIT_ATT) == 0) { + /* If no HD is attached, SUS puts 0x00 into the data + buffer */ + id_data[0] = 0; + } else { + /* Put Unit Status into byte 0 */ + id_data[0] = (ID_UST_DSEL|ID_UST_SCL|ID_UST_RDY); + if (id_cyl[UNIT_NUM] == 0) { + id_data[0] |= ID_UST_TK0; + } + } + break; + default: + break; + } + + sim_debug(EXECUTE_MSG, &id_dev, + "[%08x] \tINTR\t\tDELTA=%f ms\n", + R[NUM_PC], ID_DIFF_MS()); + + id_irq = TRUE; + + return SCPE_OK; +} + +t_stat id_reset(DEVICE *dptr) +{ + id_clear_fifo(); + return SCPE_OK; +} + +t_stat id_attach(UNIT *uptr, CONST char *cptr) +{ + return sim_disk_attach(uptr, cptr, 512, 1, TRUE, 0, "HD72", 0, 0); +} + +t_stat id_detach(UNIT *uptr) +{ + return sim_disk_detach(uptr); +} + +/* Return the logical block address of the given sector */ +static SIM_INLINE t_lba id_lba(uint16 cyl, uint8 head, uint8 sec) +{ + return((ID_SEC_CNT * ID_HEADS * cyl) + + (ID_SEC_CNT * head) + + sec); +} + +/* At the end of each sector read or write, we update the FIFO + * with the correct return parameters. */ +static void SIM_INLINE id_end_rw(uint8 est) { + sim_debug(EXECUTE_MSG, &id_dev, + ">>> ending R/W with status: %02x\n", + est); + id_dpr = 0; + id_dpw = 0; + id_data[0] = est; + id_data[1] = id_phn; + id_data[2] = ~(id_lcnh); + id_data[3] = id_lcnl; + id_data[4] = id_lhn; + id_data[5] = id_lsn; + id_data[6] = id_scnt; +} + +/* The controller wraps id_lsn, id_lhn, and id_lcnl on each sector + * read, so that they point to the next C/H/S */ +static void SIM_INLINE id_update_chs() { + sim_debug(EXECUTE_MSG, &id_dev, + ">>> id_update_chs(): id_esn=%02x id_etn=%02x\n", + id_esn, id_etn); + + if (id_lsn++ >= id_esn) { + sim_debug(EXECUTE_MSG, &id_dev, + ">>> id_update_chs(): id_lsn reset to 0. id_lhn is %02x\n", + id_lhn); + id_lsn = 0; + if (id_lhn++ >= id_etn) { + sim_debug(EXECUTE_MSG, &id_dev, + ">>> id_update_chs(): id_lhn reset to 0. id_lcnl is %02x\n", + id_lcnl); + id_lhn = 0; + if (id_lcnl == 0xff) { + id_lcnl = 0; + id_lcnh++; + } else { + id_lcnl++; + } + } + } +} + +uint32 id_read(uint32 pa, size_t size) { + uint8 reg; + uint16 cyl; + t_lba lba; + uint32 data; + t_seccnt sectsread; + + reg = (uint8) (pa - IDBASE); + + switch(reg) { + case ID_DATA_REG: /* Data Buffer Register */ + /* If we're in a DMA transfer, we need to be reading data from + * the disk buffer. Otherwise, we're reading from the FIFO. */ + + if (id_drq) { + /* If the drive isn't attached, there's really nothing we + can do. */ + if ((id_sel_unit->flags & UNIT_ATT) == 0) { + id_end_rw(ID_EST_NR); + return 0; + } + + /* We could be in one of these commands: + * - Read Data + * - Read ID + */ + + if (CMD_NUM == ID_CMD_RDATA) { + /* If we're still in DRQ but we've read all our sectors, + * that's an error state. */ + if (id_scnt == 0) { + sim_debug(READ_MSG, &id_dev, + "[%08x] ERROR\tid_scnt = 0 but still in dma\n", + R[NUM_PC]); + id_end_rw(ID_EST_OVR); + return 0; + } + + /* If the disk buffer is empty, fill it. */ + if (id_buf_ptr == 0 || id_buf_ptr >= ID_SEC_SIZE) { + /* It's time to read a new sector into our sector buf */ + id_buf_ptr = 0; + cyl = (uint16) (((uint16)id_lcnh << 8)|(uint16)id_lcnl); + id_cyl[UNIT_NUM] = cyl; + lba = id_lba(cyl, id_lhn, id_lsn); + if (sim_disk_rdsect(id_sel_unit, lba, id_buf, §sread, 1) == SCPE_OK) { + if (sectsread !=1) { + sim_debug(READ_MSG, &id_dev, + "[%08x]\tERROR: ASKED TO READ ONE SECTOR, READ: %d\n", + R[NUM_PC], sectsread); + } + sim_debug(READ_MSG, &id_dev, + "[%08x] \tRDATA\tCYL=%d PHN=%d LCNH=%02x " + "LCNL=%02x LHN=%d LSN=%d SCNT=%d LBA=%04x\n", + R[NUM_PC], cyl, id_phn, id_lcnh, id_lcnl, + id_lhn, id_lsn, id_scnt-1, lba); + id_update_chs(); + } else { + /* Uh-oh! */ + sim_debug(READ_MSG, &id_dev, + "[%08x]\tRDATA READ ERROR. Failure from sim_disk_rdsect!\n", + R[NUM_PC]); + id_end_rw(ID_EST_DER); + return 0; + } + } + + data = id_buf[id_buf_ptr++]; + + sim_debug(READ_MSG, &id_dev, + "[%08x]\tSECTOR DATA\t%02x\t(%c)\n", + R[NUM_PC], data, (data >= 0x20 && data < 0x7f) ? data : '.'); + + /* Done with this current sector, update id_scnt */ + if (id_buf_ptr >= ID_SEC_SIZE) { + if (--id_scnt == 0) { + id_end_rw(0); + } + } + } else if (CMD_NUM == ID_CMD_RID) { + /* We have to return the ID bytes for the current C/H/S */ + if (id_idfield_ptr == 0 || id_idfield_ptr >= ID_IDFIELD_LEN) { + id_idfield[0] = ~(id_lcnh); + id_idfield[1] = id_lcnl; + id_idfield[2] = id_lhn; + id_idfield[3] = id_lsn; + id_idfield_ptr = 0; + } + + data = id_idfield[id_idfield_ptr++]; + sim_debug(READ_MSG, &id_dev, + "[%08x]\tID DATA\t%02x\n", + R[NUM_PC], data); + + if (id_idfield_ptr >= ID_IDFIELD_LEN) { + if (id_scnt-- > 0) { + /* Another sector to ID */ + id_idfield_ptr = 0; + } else { + /* All done, set return codes */ + id_dpr = 0; + id_dpw = 0; + id_data[0] = 0; + id_data[1] = id_scnt; + } + } + } else { + assert(0); // cmd not Read Data or Read ID + } + + return data; + } else { + if (id_dpr < ID_FIFO_LEN) { + sim_debug(READ_MSG, &id_dev, + "[%08x]\tDATA\t%02x\n", + R[NUM_PC], id_data[id_dpr]); + return id_data[id_dpr++]; + } else { + sim_debug(READ_MSG, &id_dev, + "[%08x] ERROR\tFIFO OVERRUN\n", + R[NUM_PC]); + return 0; + } + } + + break; + case ID_CMD_STAT_REG: /* Status Register */ + sim_debug(READ_MSG, &id_dev, + "[%08x]\tSTATUS\t%02x\n", + R[NUM_PC], id_status|id_drq); + return id_status|(id_drq ? 1u : 0); + } + + sim_debug(READ_MSG, &id_dev, + "[%08x] Read of unsuported register %x\n", + R[NUM_PC], id_status); + + return 0; +} + +void id_write(uint32 pa, uint32 val, size_t size) +{ + uint8 reg; + uint16 cyl; + t_lba lba; + t_seccnt sectswritten; + + reg = (uint8) (pa - IDBASE); + + switch(reg) { + case ID_DATA_REG: + /* If we're in a DMA transfer, we need to be writing data to + * the disk buffer. Otherwise, we're writing to the FIFO. */ + + if (id_drq) { + /* If we're still in DRQ but we've written all our sectors, + * that's an error state. */ + if (id_scnt == 0) { + sim_debug(WRITE_MSG, &id_dev, + "[%08x] ERROR\tid_scnt = 0 but still in dma\n", + R[NUM_PC]); + id_end_rw(ID_EST_OVR); + return; + } + + /* Write to the disk buffer */ + if (id_buf_ptr < ID_SEC_SIZE) { + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tSECTOR DATA\t%02x\t(%c)\n", + R[NUM_PC], val, (val >= 0x20 && val < 0x7f) ? val : '.'); + id_buf[id_buf_ptr++] = (uint8)(val & 0xff); + } else { + sim_debug(WRITE_MSG, &id_dev, + "[%08x] ERROR\tWDATA OVERRUN\n", + R[NUM_PC]); + id_end_rw(ID_EST_OVR); + return; + } + + /* If we've hit the end of a sector, flush it */ + if (id_buf_ptr >= ID_SEC_SIZE) { + /* It's time to start the next sector, and flush the old. */ + id_buf_ptr = 0; + cyl = (uint16) (((uint16) id_lcnh << 8)|(uint16)id_lcnl); + id_cyl[UNIT_NUM] = cyl; + lba = id_lba(cyl, id_lhn, id_lsn); + if (sim_disk_wrsect(id_sel_unit, lba, id_buf, §swritten, 1) == SCPE_OK) { + if (sectswritten !=1) { + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tERROR: ASKED TO WRITE ONE SECTOR, WROTE: %d\n", + R[NUM_PC], sectswritten); + } + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tWDATA\tCYL=%d PHN=%d LCNH=%02x " + "LCNL=%02x LHN=%d LSN=%d SCNT=%d LBA=%04x\n", + R[NUM_PC], cyl, id_phn, id_lcnh, id_lcnl, + id_lhn, id_lsn, id_scnt, lba); + id_update_chs(); + if (--id_scnt == 0) { + id_end_rw(0); + } + } else { + /* Uh-oh! */ + sim_debug(WRITE_MSG, &id_dev, + "[%08x] ERROR\tWDATA WRITE ERROR. lba=%04x\n", + R[NUM_PC], lba); + id_end_rw(ID_EST_DER); + return; + } + } + + return; + } else { + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tDATA\t%02x\n", + R[NUM_PC], val); + + if (id_dpw < ID_FIFO_LEN) { + id_data[id_dpw++] = (uint8) val; + } else { + sim_debug(WRITE_MSG, &id_dev, + "[%08x] ERROR\tFIFO OVERRUN\n", + R[NUM_PC]); + } + } + return; + case ID_CMD_STAT_REG: + id_handle_command((uint8) val); + return; + default: + return; + } +} + +void id_handle_command(uint8 val) +{ + uint8 cmd, aux_cmd, sec, pattern; + uint16 cyl; + uint32 time; + t_lba lba; + + /* Save the full command byte */ + id_cmd = val; + + /* Reset the FIFO pointer */ + id_dpr = 0; + id_dpw = 0; + + /* Writing a command always de-asserts INT output, UNLESS + the SRQ bit is set. */ + if ((id_status & ID_STAT_SRQ) != ID_STAT_SRQ) { + id_irq = FALSE; + } + + /* Is this an aux command or a full command? */ + if ((val & 0xf0) == 0) { + aux_cmd = val & 0x0f; + id_status &= ~(ID_STAT_CB); + + if (aux_cmd & ID_AUX_CLCE) { + sim_debug(WRITE_MSG, &id_dev, + "[%08x] \tCOMMAND\t%02x\tAUX:CLCE\n", + R[NUM_PC], val); + id_status &= ~(ID_STAT_CEL|ID_STAT_CEH); + sim_cancel(id_sel_unit); + } + + if (aux_cmd & ID_AUX_HSRQ) { + sim_debug(WRITE_MSG, &id_dev, + "[%08x] \tCOMMAND\t%02x\tAUX:HSRQ\n", + R[NUM_PC], val); + id_status &= ~ID_STAT_SRQ; + sim_cancel(id_sel_unit); + } + + if (aux_cmd & ID_AUX_CLB) { + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tAUX:CLBUF\n", + R[NUM_PC], val); + id_clear_fifo(); + } + + if (aux_cmd & ID_AUX_RST) { + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tAUX:RESET\n", + R[NUM_PC], val); + sim_cancel(id_sel_unit); + id_clear_fifo(); + } + + /* Just return early */ + return; + } + + /* Now that we know it's not an aux command, get the unit number + this command is for */ + id_sel_unit = &id_unit[UNIT_NUM]; + + cmd = (id_cmd >> 4) & 0xf; + + /* If this command is anything BUT a sense interrupt status, set + * the seek flag to false. + */ + if (cmd != ID_CMD_SIS) { + id_seek_sis = FALSE; + } + + id_status = ID_STAT_CB; + + switch(cmd) { + case ID_CMD_SIS: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tSense Int. Status - %d\n", + R[NUM_PC], val, UNIT_NUM); + id_activate(DELAY_US(ID_SIS_WAIT)); + break; + case ID_CMD_SPEC: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tSpecify - %d - ETN=%02x ESN=%02x\n", + R[NUM_PC], val, UNIT_NUM, id_data[3], id_data[4]); + id_dtlh[UNIT_NUM] = id_data[1]; + id_etn = id_data[3]; + id_esn = id_data[4]; + id_activate(DELAY_US(ID_SPEC_WAIT)); + break; + case ID_CMD_SUS: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tSense Unit Status - %d\n", + R[NUM_PC], val, UNIT_NUM); + id_activate(DELAY_US(ID_SUS_WAIT)); + break; + case ID_CMD_DERR: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tDetect Error - %d\n", + R[NUM_PC], val, UNIT_NUM); + id_status |= ID_STAT_CEH; + id_activate(DELAY_US(ID_CMD_WAIT)); + break; + case ID_CMD_RECAL: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tRecalibrate - %d\n", + R[NUM_PC], val, UNIT_NUM); + id_cyl[UNIT_NUM] = 0; + time = id_cyl[UNIT_NUM]; + id_activate(DELAY_US(ID_RECAL_WAIT + (time * ID_SEEK_WAIT))); + id_seek_sis = TRUE; + break; + case ID_CMD_SEEK: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tSeek - %d\n", + R[NUM_PC], val, UNIT_NUM); + id_lcnh = id_data[0]; + id_lcnl = id_data[1]; + cyl = id_lcnh << 8 | id_lcnl; + time = (uint32) abs(id_cyl[UNIT_NUM] - cyl); + id_activate(DELAY_US(ID_SEEK_BASE + (ID_SEEK_WAIT * time))); + id_cyl[UNIT_NUM] = cyl; + id_seek_sis = TRUE; + break; + case ID_CMD_FMT: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tFormat - %d\n", + R[NUM_PC], val, UNIT_NUM); + + id_phn = id_data[0]; + id_scnt = id_data[1]; + pattern = id_data[2]; + + /* Format scnt sectors with the given pattern, if attached */ + if (id_sel_unit->flags & UNIT_ATT) { + /* Formatting soft-sectored disks always begins at sector 0 */ + sec = 0; + + while (id_scnt-- > 0) { + /* Write one sector of pattern */ + for (id_buf_ptr = 0; id_buf_ptr < ID_SEC_SIZE; id_buf_ptr++) { + id_buf[id_buf_ptr] = pattern; + } + lba = id_lba(id_cyl[UNIT_NUM], id_phn, sec++); + if (sim_disk_wrsect(id_sel_unit, lba, id_buf, NULL, 1) == SCPE_OK) { + sim_debug(EXECUTE_MSG, &id_dev, + "[%08x]\tFORMAT: PHN=%d SCNT=%d PAT=%02x LBA=%04x\n", + R[NUM_PC], id_phn, id_scnt, pattern, lba); + } else { + sim_debug(EXECUTE_MSG, &id_dev, + "[%08x]\tFORMAT FAILED! PHN=%d SCNT=%d PAT=%02x LBA=%04x\n", + R[NUM_PC], id_phn, id_scnt, pattern, lba); + break; + } + } + + id_data[0] = 0; + } else { + /* Not attached */ + id_data[0] = ID_EST_NR; + } + + id_data[1] = id_scnt; + + id_activate(DELAY_US(ID_CMD_WAIT)); + break; + case ID_CMD_VID: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tVerify ID - %d\n", + R[NUM_PC], val, UNIT_NUM); + id_data[0] = 0; + id_data[1] = 0x05; /* What do we put here? */ + id_activate(DELAY_US(ID_CMD_WAIT)); + break; + case ID_CMD_RID: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tRead ID - %d\n", + R[NUM_PC], val, UNIT_NUM); + if (id_sel_unit->flags & UNIT_ATT) { + id_drq = TRUE; + + /* Grab our arguments */ + id_phn = id_data[0]; + id_scnt = id_data[1]; + + /* Compute logical values used by ID verification */ + id_lhn = id_phn; + id_lsn = 0; + } else { + sim_debug(EXECUTE_MSG, &id_dev, + "[%08x]\tUNIT %d NOT ATTACHED, CANNOT READ ID.\n", + R[NUM_PC], UNIT_NUM); + } + id_activate(DELAY_US(ID_CMD_WAIT)); + break; + case ID_CMD_RDIAG: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tRead Diag - %d\n", + R[NUM_PC], val, UNIT_NUM); + id_activate(DELAY_US(ID_CMD_WAIT)); + break; + case ID_CMD_RDATA: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tRead Data - %d\n", + R[NUM_PC], val, UNIT_NUM); + if (id_sel_unit->flags & UNIT_ATT) { + id_drq = TRUE; + id_buf_ptr = 0; + + /* Grab our arguments */ + id_phn = id_data[0]; + id_lcnh = ~(id_data[1]); + id_lcnl = id_data[2]; + id_lhn = id_data[3]; + id_lsn = id_data[4]; + id_scnt = id_data[5]; + } else { + sim_debug(EXECUTE_MSG, &id_dev, + "[%08x]\tUNIT %d NOT ATTACHED, CANNOT READ DATA.\n", + R[NUM_PC], UNIT_NUM); + } + + time = (uint32) abs(id_cyl[UNIT_NUM] - ((id_lcnh<<8)|id_lcnl)); + if (time == 0) { + time++; + } + time = time * ID_SEEK_WAIT; + id_activate(DELAY_US(time + ID_RW_WAIT)); + break; + case ID_CMD_CHECK: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tCheck - %d\n", + R[NUM_PC], val, UNIT_NUM); + id_activate(DELAY_US(ID_CMD_WAIT)); + break; + case ID_CMD_SCAN: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tScan - %d\n", + R[NUM_PC], val, UNIT_NUM); + id_activate(DELAY_US(ID_CMD_WAIT)); + break; + case ID_CMD_VDATA: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tVerify Data - %d\n", + R[NUM_PC], val, UNIT_NUM); + id_activate(DELAY_US(ID_CMD_WAIT)); + break; + case ID_CMD_WDATA: + sim_debug(WRITE_MSG, &id_dev, + "[%08x]\tCOMMAND\t%02x\tWrite Data - %d\n", + R[NUM_PC], val, UNIT_NUM); + if (id_sel_unit->flags & UNIT_ATT) { + id_drq = TRUE; + id_buf_ptr = 0; + + /* Grab our arguments */ + id_phn = id_data[0]; + id_lcnh = ~(id_data[1]); + id_lcnl = id_data[2]; + id_lhn = id_data[3]; + id_lsn = id_data[4]; + id_scnt = id_data[5]; + } else { + sim_debug(EXECUTE_MSG, &id_dev, + "[%08x]\tUNIT %d NOT ATTACHED, CANNOT WRITE.\n", + R[NUM_PC], UNIT_NUM); + } + time = (uint32) abs(id_cyl[UNIT_NUM] - ((id_lcnh<<8)|id_lcnl)); + if (time == 0) { + time++; + } + time = time * ID_SEEK_WAIT; + id_activate(DELAY_US(time + ID_RW_WAIT)); + break; + } +} + +void id_drq_handled() +{ + id_status &= ~ID_STAT_DRQ; + id_drq = FALSE; +} + +CONST char *id_description(DEVICE *dptr) +{ + return "72MB MFM Hard Disk"; +} + +t_stat id_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ + fprintf(st, "71MB MFM Integrated Hard Disk (ID)\n\n"); + fprintf(st, + "The ID controller implements the integrated MFM hard disk controller\n" + "of the 3B2/400. Up to four drives are supported on a single controller.\n"); + return SCPE_OK; +} diff --git a/3B2/3b2_id.h b/3B2/3b2_id.h new file mode 100644 index 00000000..a142bb7c --- /dev/null +++ b/3B2/3b2_id.h @@ -0,0 +1,146 @@ +/* 3b2_cpu.h: AT&T 3B2 Model 400 Hard Disk (uPD7261) Header + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#ifndef __3B2_ID_H__ +#define __3B2_ID_H__ + +#include "3b2_defs.h" +#include "3b2_sysdev.h" +#include "sim_disk.h" + +/* Command Codes (bits 3-7 of command byte) */ + +#define ID_DATA_REG 0 +#define ID_CMD_STAT_REG 1 + +#define ID_CMD_AUX 0x00 /* Auxiliary Command */ +#define ID_CMD_SIS 0x01 /* Sense int. status */ +#define ID_CMD_SPEC 0x02 /* Specify */ +#define ID_CMD_SUS 0x03 /* Sense unit status */ +#define ID_CMD_DERR 0x04 /* Detect Error */ +#define ID_CMD_RECAL 0x05 /* Recalibrate */ +#define ID_CMD_SEEK 0x06 /* Seek */ +#define ID_CMD_FMT 0x07 /* Format */ +#define ID_CMD_VID 0x08 /* Verify ID */ +#define ID_CMD_RID 0x09 /* Read ID */ +#define ID_CMD_RDIAG 0x0A /* Read Diagnostic */ +#define ID_CMD_RDATA 0x0B /* Read Data */ +#define ID_CMD_CHECK 0x0C /* Check */ +#define ID_CMD_SCAN 0x0D /* Scan */ +#define ID_CMD_VDATA 0x0E /* Verify Data */ +#define ID_CMD_WDATA 0x0F /* Write Data */ + +#define ID_AUX_RST 0x01 +#define ID_AUX_CLB 0x02 +#define ID_AUX_HSRQ 0x04 +#define ID_AUX_CLCE 0x08 + +#define ID_STAT_DRQ 0x01 +#define ID_STAT_NCI 0x02 +#define ID_STAT_IER 0x04 +#define ID_STAT_RRQ 0x08 +#define ID_STAT_SRQ 0x10 +#define ID_STAT_CEL 0x20 +#define ID_STAT_CEH 0x40 +#define ID_STAT_CB 0x80 + +#define ID_IST_SEN 0x80 +#define ID_IST_RC 0x40 +#define ID_IST_SER 0x20 +#define ID_IST_EQC 0x10 +#define ID_IST_NR 0x08 + +#define ID_UST_DSEL 0x10 +#define ID_UST_SCL 0x08 +#define ID_UST_TK0 0x04 +#define ID_UST_RDY 0x02 +#define ID_UST_WFL 0x01 + +#define ID_EST_ENC 0x80 +#define ID_EST_OVR 0x40 +#define ID_EST_DER 0x20 +#define ID_EST_EQC 0x10 +#define ID_EST_NR 0x08 +#define ID_EST_ND 0x04 +#define ID_EST_NWR 0x02 +#define ID_EST_MAM 0x01 + +#define ID_DTLH_POLL 0x10 + +/* Geometry */ + +#define ID_CYL 925 +#define ID_SEC_SIZE 512 /* Bytes per sector */ +#define ID_SEC_CNT 18 /* Sectors per track */ +#define ID_HEADS 9 +#define ID_CYL_SIZE 512 * 18 + +/* Unit, Register, Device descriptions */ + +#define ID_FIFO_LEN 8 +#define ID_IDFIELD_LEN 4 + +#define ID_NUM_UNITS 2 + +/* Unit number field in UNIT structure */ +#define ID_UNIT_NUM u3 + +extern DEVICE id_dev; +extern DEBTAB sys_deb_tab[]; +extern t_bool id_drq; +extern t_bool id_irq; + +#define IDBASE 0x4a000 +#define IDSIZE 0x2 + +/* Total disk size, in sectors */ +#define ID_DSK_SIZE ID_CYL * ID_SEC_CNT * ID_HEADS + +#define CMD_NUM ((id_cmd >> 4) & 0xf) +#define UNIT_NUM (id_cmd & 1) /* We intentionally ignore the top unit address bit */ + +/* Function prototypes */ + +t_stat id_svc(UNIT *uptr); +t_stat id_reset(DEVICE *dptr); +t_stat id_attach(UNIT *uptr, CONST char *cptr); +t_stat id_detach(UNIT *uptr); +uint32 id_read(uint32 pa, size_t size); +void id_write(uint32 pa, uint32 val, size_t size); +CONST char *id_description(DEVICE *dptr); +t_stat id_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +void id_handle_data(uint8 val); +void id_handle_command(uint8 val); + +static SIM_INLINE t_lba id_lba(uint16 cyl, uint8 head, uint8 sec); + +void id_drq_handled(); + +#endif diff --git a/3B2/3b2_if.c b/3B2/3b2_if.c new file mode 100644 index 00000000..cd9f9913 --- /dev/null +++ b/3B2/3b2_if.c @@ -0,0 +1,526 @@ +/* 3b2_cpu.h: AT&T 3B2 Model 400 Floppy (TMS2797NL) Implementation + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#include "3b2_if.h" +#include + +/* + * TODO: Macros used for debugging timers. Remove when debugging is complete. + */ +double if_start_time; + +#define IF_START_TIME() { if_start_time = sim_gtime(); } +#define IF_DIFF_MS() ((sim_gtime() - if_start_time) / INST_PER_MS) +#ifndef max +#define max(x,y) ((x) > (y) ? (x) : (y)) +#endif +#ifndef min +#define min(x,y) ((x) < (y) ? (x) : (y)) +#endif + +/* + * Disk Format: + * ------------ + * + * - 80 Tracks + * - 9 Sectors per track + * - 2 heads + * - 512 bytes per sector + * + * 80 * 9 * 2 * 512 = 720KB + * + * The clock on pin 24 runs at 1.000 MHz, meaning that each + * step is 6ms and head settling time is 30ms. + */ + +#define IF_STEP_DELAY 6 /* ms */ +#define IF_R_DELAY 85 /* ms */ +#define IF_W_DELAY 90 /* ms */ +#define IF_VERIFY_DELAY 30 /* ms */ +#define IF_HLD_DELAY 80 /* ms */ +#define IF_HSW_DELAY 60 /* ms */ + +UNIT if_unit = { + UDATA (&if_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+ + UNIT_MUSTBUF+UNIT_BINK, IF_DSK_SIZE) +}; + +REG if_reg[] = { + { NULL } +}; + +DEVICE if_dev = { + "IF", &if_unit, if_reg, NULL, + 1, 16, 8, 1, 16, 8, + NULL, NULL, &if_reset, + NULL, NULL, NULL, NULL, + DEV_DEBUG, 0, sys_deb_tab +}; + +IF_STATE if_state; +uint32 if_sec_ptr; +t_bool if_irq; + +/* Function implementation */ + +static SIM_INLINE void if_set_irq() +{ + if_irq = TRUE; + csr_data |= CSRDISK; +} + +static SIM_INLINE void if_clear_irq() +{ + if_irq = FALSE; + csr_data &= ~CSRDISK; +} + +static SIM_INLINE void if_activate(uint32 delay) +{ + IF_START_TIME(); + sim_activate_abs(&if_unit, (int32) DELAY_MS(delay)); +} + +static SIM_INLINE void if_cancel_pending_irq() +{ + sim_cancel(&if_unit); +} + +t_stat if_svc(UNIT *uptr) +{ + if_state.status &= ~(IF_BUSY); + + switch(if_state.cmd & 0xf0) { + case IF_RESTORE: + if_state.status = (IF_TK_0|IF_HEAD_LOADED); + break; + case IF_SEEK: + if_state.status = IF_HEAD_LOADED; + if (if_state.track == 0) { + if_state.status |= IF_TK_0; + } + break; + } + + if_state.cmd = 0; + + /* Request an interrupt */ + sim_debug(IRQ_MSG, &if_dev, "\tINTR\t\tDELTA=%f ms\n", IF_DIFF_MS()); + if_set_irq(); + + return SCPE_OK; +} + +t_stat if_reset(DEVICE *dptr) +{ + if_state.status = IF_TK_0; + if_state.track = 0; + if_state.sector = 1; + if_sec_ptr = 0; + return SCPE_OK; +} + +uint32 if_read(uint32 pa, size_t size) { + uint8 reg, data; + uint32 pos, pc; + UNIT *uptr; + uint8 *fbuf; + + uptr = &(if_dev.units[0]); + reg = (uint8)(pa - IFBASE); + pc = R[NUM_PC]; + fbuf = (uint8 *)uptr->filebuf; + + switch (reg) { + case IF_STATUS_REG: + data = if_state.status; + /* If there's no image attached, we're not ready */ + if ((uptr->flags & (UNIT_ATT|UNIT_BUF)) == 0) { + data |= IF_NRDY; + } + /* Reading the status register always de-asserts the IRQ line */ + if_clear_irq(); + sim_debug(READ_MSG, &if_dev, "\tSTATUS\t%02x\n", data); + break; + case IF_TRACK_REG: + data = if_state.track; + sim_debug(READ_MSG, &if_dev, "\tTRACK\t%02x\n", data); + break; + case IF_SECTOR_REG: + data = if_state.sector; + sim_debug(READ_MSG, &if_dev, "\tSECTOR\t%02x\n", data); + break; + case IF_DATA_REG: + if_state.status &= ~IF_DRQ; + + if (((uptr->flags & (UNIT_ATT|UNIT_BUF)) == 0) || + ((if_state.cmd & 0xf0) != IF_READ_SEC && + (if_state.cmd & 0xf0) != IF_READ_SEC_M)) { + /* Not attached, or not a read command */ + + switch (if_state.cmd & 0xf0) { + case IF_READ_ADDR: + /* Special state machine. */ + switch (if_state.read_addr_ptr++) { + case 0: + if_state.data = if_state.track; + break; + case 1: + if_state.data = if_state.side; + break; + case 2: + if_state.data = if_state.sector; + break; + case 3: + if_state.data = 2; /* 512 byte */ + break; + case 4: + /* TODO: Checksum */ + if_state.data = 0; + break; + case 5: + /* TODO: Checksum */ + if_state.data = 0; + if_state.read_addr_ptr = 0; + break; + } + } + + sim_debug(READ_MSG, &if_dev, "\tDATA\t%02x\n", if_state.data); + return if_state.data; + } + + pos = if_buf_offset(); + data = fbuf[pos + if_sec_ptr++]; + sim_debug(READ_MSG, &if_dev, "\tDATA\t%02x\n", data); + + if (if_sec_ptr >= IF_SECTOR_SIZE) { + if_sec_ptr = 0; + } + + break; + default: + data = 0xffu; // Compiler warning + break; + } + + return data; +} + +/* Handle the most recently received command */ +void if_handle_command() +{ + uint32 delay_ms = 0; + uint32 head_switch_delay = 0; + uint32 head_load_delay = 0; + + if_sec_ptr = 0; + + /* We're starting a new command. */ + if_state.status = IF_BUSY; + + /* Clear read addr state */ + if_state.read_addr_ptr = 0; + + switch(if_state.cmd & 0xf0) { + case IF_RESTORE: + case IF_SEEK: + case IF_STEP: + case IF_STEP_T: + case IF_STEP_IN: + case IF_STEP_IN_T: + case IF_STEP_OUT: + case IF_STEP_OUT_T: + if_state.cmd_type = 1; + if (if_state.cmd & IF_H_FLAG) { + head_load_delay = IF_HLD_DELAY; + } + break; + + case IF_READ_SEC: + case IF_READ_SEC_M: + case IF_WRITE_SEC: + case IF_WRITE_SEC_M: + if_state.cmd_type = 2; + if (((if_state.cmd & IF_U_FLAG) >> 1) != if_state.side) { + head_switch_delay = IF_HSW_DELAY; + if_state.side = (if_state.cmd & IF_U_FLAG) >> 1; + } + break; + + case IF_READ_ADDR: + case IF_READ_TRACK: + case IF_WRITE_TRACK: + if_state.cmd_type = 3; + if (((if_state.cmd & IF_U_FLAG) >> 1) != if_state.side) { + head_switch_delay = IF_HSW_DELAY; + if_state.side = (if_state.cmd & IF_U_FLAG) >> 1; + } + break; + + case IF_FORCE_INT: + if_state.cmd_type = 4; + break; + } + + switch(if_state.cmd & 0xf0) { + case IF_RESTORE: + sim_debug(EXECUTE_MSG, &if_dev, "\tCOMMAND\t%02x\tRestore\n", if_state.cmd); + + /* Reset HLT */ + if_state.status &= ~IF_HEAD_LOADED; + + /* If head should be loaded immediately, do so now */ + if (if_state.cmd & IF_H_FLAG) { + if_state.status |= IF_HEAD_LOADED; + } + + if (if_state.track == 0) { + if_state.status |= IF_TK_0; + if_state.track = 1; /* Kind of a gross hack */ + } + + if (if_state.cmd & IF_V_FLAG) { + delay_ms = (IF_STEP_DELAY * if_state.track) + IF_VERIFY_DELAY; + } else { + delay_ms = IF_STEP_DELAY * if_state.track; + } + + if_activate(delay_ms); + + if_state.data = 0; + if_state.track = 0; + break; + + case IF_STEP: + case IF_STEP_T: + sim_debug(EXECUTE_MSG, &if_dev, "\tCOMMAND\t%02x\tStep\n", if_state.cmd); + if_activate(IF_STEP_DELAY); + if_state.track = (uint8) min(max((int) if_state.track + if_state.step_dir, 0), 0x4f); + break; + case IF_STEP_IN: + case IF_STEP_IN_T: + sim_debug(EXECUTE_MSG, &if_dev, "\tCOMMAND\t%02x\tStep In\n", if_state.cmd); + if_state.step_dir = IF_STEP_IN_DIR; + if_state.track = (uint8) max((int) if_state.track + if_state.step_dir, 0); + if_activate(IF_STEP_DELAY); + break; + case IF_STEP_OUT: + case IF_STEP_OUT_T: + sim_debug(EXECUTE_MSG, &if_dev, "\tCOMMAND\t%02x\tStep Out\n", if_state.cmd); + if_state.step_dir = IF_STEP_OUT_DIR; + if_state.track = (uint8) min((int) if_state.track + if_state.step_dir, 0x4f); + if_activate(IF_STEP_DELAY); + break; + case IF_SEEK: + sim_debug(EXECUTE_MSG, &if_dev, "\tCOMMAND\t%02x\tSeek\n", if_state.cmd); + + /* Reset HLT */ + if_state.status &= ~IF_HEAD_LOADED; + + /* If head should be loaded immediately, do so now */ + if (if_state.cmd & IF_H_FLAG) { + if_state.status |= IF_HEAD_LOADED; + } + + /* Save the direction for stepping */ + if (if_state.data > if_state.track) { + if_state.step_dir = IF_STEP_IN_DIR; + } else if (if_state.data < if_state.track) { + if_state.step_dir = IF_STEP_OUT_DIR; + } + + /* The new track is in the data register */ + + if (if_state.data > IF_TRACK_COUNT-1) { + if_state.data = IF_TRACK_COUNT-1; + } + + if (if_state.data == 0) { + if_state.status |= IF_TK_0; + } else { + if_state.status &= ~(IF_TK_0); + } + + delay_ms = (uint32) abs(if_state.data - if_state.track); + + if (delay_ms == 0) { + delay_ms++; + } + + if (if_state.cmd & IF_V_FLAG) { + if_activate((IF_STEP_DELAY * delay_ms) + IF_VERIFY_DELAY + head_load_delay); + } else { + if_activate((IF_STEP_DELAY * delay_ms) + head_load_delay); + } + + if_state.track = if_state.data; + break; + + case IF_READ_SEC: + sim_debug(EXECUTE_MSG, &if_dev, "\tCOMMAND\t%02x\tRead Sector %d/%d/%d\n", + if_state.cmd, if_state.track, if_state.side, if_state.sector); + /* We set DRQ right away to request the transfer. */ + if_state.drq = TRUE; + if_state.status |= IF_DRQ; + if (if_state.cmd & IF_E_FLAG) { + if_activate(IF_R_DELAY + IF_VERIFY_DELAY + head_switch_delay); + } else { + if_activate(IF_R_DELAY + head_switch_delay); + } + break; + case IF_READ_SEC_M: + assert(0); + case IF_WRITE_SEC: + sim_debug(EXECUTE_MSG, &if_dev, "\tCOMMAND\t%02x\tWrite Sector %d/%d/%d\n", + if_state.cmd, if_state.track, if_state.side, if_state.sector); + /* We set DRQ right away to request the transfer. */ + if_state.drq = TRUE; + if_state.status |= IF_DRQ; + if (if_state.cmd & IF_E_FLAG) { + if_activate(IF_W_DELAY + IF_VERIFY_DELAY + head_switch_delay); + } else { + if_activate(IF_W_DELAY + head_switch_delay); + } + break; + case IF_WRITE_SEC_M: + assert(0); + break; + case IF_READ_ADDR: + sim_debug(EXECUTE_MSG, &if_dev, "\tCOMMAND\t%02x\tRead Address\n", if_state.cmd); + if_state.drq = TRUE; + if_state.status |= IF_DRQ; + if_activate(IF_R_DELAY); + break; + case IF_READ_TRACK: + sim_debug(EXECUTE_MSG, &if_dev, "\tCOMMAND\t%02x\tRead Track\n", if_state.cmd); + assert(0); /* NOT YET IMPLEMENTED */ + break; + case IF_WRITE_TRACK: + sim_debug(EXECUTE_MSG, &if_dev, "\tCOMMAND\t%02x\tWrite Track\n", if_state.cmd); + assert(0); /* NOT YET IMPLEMENTED */ + break; + case IF_FORCE_INT: + sim_debug(EXECUTE_MSG, &if_dev, "\tCOMMAND\t%02x\tForce Interrupt\n", if_state.cmd); + if_state.status = 0; + + if (if_state.track == 0) { + if_state.status |= (IF_TK_0|IF_HEAD_LOADED); + } + + if ((if_state.cmd & 0xf) == 0) { + if_cancel_pending_irq(); + if_clear_irq(); /* TODO: Confirm this is right */ + } else if ((if_state.cmd & 0x8) == 0x8) { + if_state.status |= IF_DRQ; + if_set_irq(); + } + + break; + + } +} + +void if_write(uint32 pa, uint32 val, size_t size) +{ + UNIT *uptr; + uint8 reg; + uint32 pos; + uint8 *fbuf; + + val = val & 0xff; + + uptr = &(if_dev.units[0]); + reg = (uint8) (pa - IFBASE); + fbuf = (uint8 *)uptr->filebuf; + + switch (reg) { + case IF_CMD_REG: + if_state.cmd = (uint8) val; + /* Writing to the command register always de-asserts the IRQ line */ + if_clear_irq(); + if_handle_command(); + break; + case IF_TRACK_REG: + if_state.track = (uint8) val; + sim_debug(WRITE_MSG, &if_dev, "\tTRACK\t%02x\n", val); + break; + case IF_SECTOR_REG: + if_state.sector = (uint8) val; + sim_debug(WRITE_MSG, &if_dev, "\tSECTOR\t%02x\n", val); + break; + case IF_DATA_REG: + if_state.data = (uint8) val; + + sim_debug(WRITE_MSG, &if_dev, "\tDATA\t%02x\n", val); + + if (uptr->fileref == NULL || + ((if_state.cmd & 0xf0) != IF_WRITE_SEC && + (if_state.cmd & 0xf0) != IF_WRITE_SEC_M)) { + /* Not attached, or not a write command */ + break; + } + + /* Find the right offset, and update the value. */ + pos = if_buf_offset(); + fbuf[pos + if_sec_ptr++] = (uint8) val; + + if (if_sec_ptr >= IF_SECTOR_SIZE) { + if_sec_ptr = 0; + } + + break; + default: + break; + } +} + +/* + * Compute the offset of the currently selected C/H/S + */ +SIM_INLINE uint32 if_buf_offset() +{ + uint32 pos; + + pos = IF_TRACK_SIZE * if_state.track * 2; + + if (if_state.side == 1) { + pos += IF_TRACK_SIZE; + } + + pos += IF_SECTOR_SIZE * (if_state.sector - 1); + + return pos; +} + +void if_drq_handled() +{ + if_state.status &= ~IF_DRQ; +} diff --git a/3B2/3b2_if.h b/3B2/3b2_if.h new file mode 100644 index 00000000..aae85ee1 --- /dev/null +++ b/3B2/3b2_if.h @@ -0,0 +1,138 @@ +/* 3b2_cpu.h: AT&T 3B2 Model 400 Floppy (TMS2797NL) Header + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#ifndef __3B2_IF_H__ +#define __3B2_IF_H__ + +#include "3b2_defs.h" +#include "3b2_sysdev.h" +#include "3b2_sys.h" + +typedef struct { + uint8 data; + uint8 cmd; + uint8 cmd_type; + uint8 status; + uint8 track; + uint8 sector; + uint8 side; + uint8 read_addr_ptr; + int8 step_dir; + t_bool drq; +} IF_STATE; + + +extern DEVICE if_dev; +extern DEBTAB sys_deb_tab[]; +extern IF_STATE if_state; +extern t_bool if_irq; + +#define IFBASE 0x4d000 +#define IFSIZE 0x10 + +#define IF_STATUS_REG 0 +#define IF_CMD_REG 0 +#define IF_TRACK_REG 1 +#define IF_SECTOR_REG 2 +#define IF_DATA_REG 3 + +/* Status Bits */ +#define IF_BUSY 0x01 +#define IF_DRQ 0x02 +#define IF_INDEX 0x02 +#define IF_TK_0 0x04 +#define IF_LOST_DATA 0x04 +#define IF_CRC_ERR 0x08 +#define IF_SEEK_ERR 0x10 +#define IF_RNF 0x10 +#define IF_HEAD_LOADED 0x20 +#define IF_RECORD_TYPE 0x20 +#define IF_WP 0x40 +#define IF_NRDY 0x80 + +/* Type I Commands */ +#define IF_RESTORE 0x00 +#define IF_SEEK 0x10 +#define IF_STEP 0x20 +#define IF_STEP_T 0x30 +#define IF_STEP_IN 0x40 +#define IF_STEP_IN_T 0x50 +#define IF_STEP_OUT 0x60 +#define IF_STEP_OUT_T 0x70 + +/* Type II Commands */ +#define IF_READ_SEC 0x80 +#define IF_READ_SEC_M 0x90 +#define IF_WRITE_SEC 0xA0 +#define IF_WRITE_SEC_M 0xB0 + +/* Type III Commands */ +#define IF_READ_ADDR 0xC0 +#define IF_READ_TRACK 0xE0 +#define IF_WRITE_TRACK 0xF0 + +/* Type IV Command */ +#define IF_FORCE_INT 0xD0 + +/* Command flags */ + +#define IF_C_FLAG 0x02 +#define IF_V_FLAG 0x04 +#define IF_E_FLAG 0x04 +#define IF_U_FLAG 0x02 +#define IF_H_FLAG 0x08 +#define IF_S_FLAG 0x10 + +/* Constants */ + +#define IF_SIDES 2 +#define IF_TRACK_SIZE 4608 +#define IF_SECTOR_SIZE 512 +#define IF_TRACK_COUNT 80 + +#define IF_STEP_IN_DIR 1 +#define IF_STEP_OUT_DIR -1 + +#define IF_DSK_SIZE (IF_SIDES * IF_TRACK_SIZE * IF_TRACK_COUNT) + +/* Function prototypes */ + +static SIM_INLINE void if_set_irq(); +static SIM_INLINE void if_clear_irq(); +static SIM_INLINE void if_cancel_pending_irq(); +t_stat if_svc(UNIT *uptr); +t_stat if_reset(DEVICE *dptr); +uint32 if_read(uint32 pa, size_t size); +void if_write(uint32 pa, uint32 val, size_t size); +void if_drq_handled(); +void if_handle_command(); +uint32 if_buf_offset(); + +#endif diff --git a/3B2/3b2_io.c b/3B2/3b2_io.c new file mode 100644 index 00000000..91cea14a --- /dev/null +++ b/3B2/3b2_io.c @@ -0,0 +1,135 @@ +/* 3b2_cpu.h: AT&T 3B2 Model 400 IO dispatch implemenation + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#include "3b2_io.h" + +struct iolink iotable[] = { + { MMUBASE, MMUBASE+MMUSIZE, &mmu_read, &mmu_write }, + { IFBASE, IFBASE+IFSIZE, &if_read, &if_write }, + { IDBASE, IDBASE+IDSIZE, &id_read, &id_write }, + { TIMERBASE, TIMERBASE+TIMERSIZE, &timer_read, &timer_write }, + { NVRAMBASE, NVRAMBASE+NVRAMSIZE, &nvram_read, &nvram_write }, + { CSRBASE, CSRBASE+CSRSIZE, &csr_read, &csr_write }, + { IUBASE, IUBASE+IUSIZE, &iu_read, &iu_write }, + { DMAIDBASE, DMAIDBASE+DMAIDSIZE, &dmac_read, &dmac_write }, + { DMAIUABASE, DMAIUABASE+DMAIUASIZE, &dmac_read, &dmac_write }, + { DMAIUBBASE, DMAIUBBASE+DMAIUBSIZE, &dmac_read, &dmac_write }, + { DMACBASE, DMACBASE+DMACSIZE, &dmac_read, &dmac_write }, + { DMAIFBASE, DMAIFBASE+DMAIFSIZE, &dmac_read, &dmac_write }, + { TODBASE, TODBASE+TODSIZE, &tod_read, &tod_write }, + { 0, 0, NULL, NULL} +}; + +uint32 io_read(uint32 pa, size_t size) +{ + struct iolink *p; + + /* Special devices */ + if (pa == 0x4c003) { + /* MEMSIZE register */ + + /* It appears that the following values map to memory sizes: + 0x00: 512KB ( 524,288 B) + 0x01: 2MB (2,097,152 B) + 0x02: 1MB (1,048,576 B) + 0x03: 4MB (4,194,304 B) + */ + switch(MEM_SIZE) { + case 0x80000: /* 512KB */ + return 0; + case 0x100000: /* 1MB */ + return 2; + case 0x200000: /* 2MB */ + return 1; + case 0x400000: /* 4MB */ + return 3; + default: + return 0; + } + } + + /* IO Board Area - Unimplemented */ + if (pa >= 0x200000 && pa < 0x2000000) { + sim_debug(IO_D_MSG, &cpu_dev, "[%08x] [IO BOARD READ] ADDR=%08x\n", R[NUM_PC], pa); + /* When we implement boards, register them here + N.B.: High byte of board ID is read at 0xnnnnn0, + low byte at 0xnnnnn1 */ + + /* Since we have no cards in our system, there's nothing + to read. We indicate that our bus read timed out with + CSRTIMO, then abort.*/ + csr_data |= CSRTIMO; + cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); + return 0; + } + + for (p = &iotable[0]; p->low != 0; p++) { + if ((pa >= p->low) && (pa < p->high) && p->read) { + return p->read(pa, size); + } + } + + /* Not found. */ + sim_debug(IO_D_MSG, &cpu_dev, + "[%08x] [io_read] ADDR=%08x: No device found.\n", + R[NUM_PC], pa); + csr_data |= CSRTIMO; + cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); + return 0; +} + +void io_write(uint32 pa, uint32 val, size_t size) +{ + struct iolink *p; + + /* IO Board Area - Unimplemented */ + if (pa >= 0x200000 && pa < 0x2000000) { + sim_debug(IO_D_MSG, &cpu_dev, + "[%08x] ADDR=%08x, DATA=%08x\n", + R[NUM_PC], pa, val); + csr_data |= CSRTIMO; + cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); + return; + } + + for (p = &iotable[0]; p->low != 0; p++) { + if ((pa >= p->low) && (pa < p->high) && p->write) { + p->write(pa, val, size); + return; + } + } + + /* Not found. */ + sim_debug(IO_D_MSG, &cpu_dev, + "[%08x] [io_write] ADDR=%08x: No device found.\n", + R[NUM_PC], pa); + csr_data |= CSRTIMO; + cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); +} diff --git a/3B2/3b2_io.h b/3B2/3b2_io.h new file mode 100644 index 00000000..c32289f5 --- /dev/null +++ b/3B2/3b2_io.h @@ -0,0 +1,48 @@ +/* 3b2_cpu.h: AT&T 3B2 Model 400 IO dispatch (Header) + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#ifndef _3B2_IO_H_ +#define _3B2_IO_H_ + +#include "3b2_sysdev.h" +#include "3b2_iu.h" +#include "3b2_if.h" +#include "3b2_id.h" +#include "3b2_dmac.h" +#include "3b2_mmu.h" + +struct iolink { + uint32 low; + uint32 high; + uint32 (*read)(uint32 pa, size_t size); + void (*write)(uint32 pa, uint32 val, size_t size); +}; + +#endif diff --git a/3B2/3b2_iu.c b/3B2/3b2_iu.c new file mode 100644 index 00000000..4e7a03d9 --- /dev/null +++ b/3B2/3b2_iu.c @@ -0,0 +1,546 @@ +/* 3b2_iu.c: SCN2681A Dual UART Implementation + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#include "3b2_iu.h" + +/* + * Registers + */ + +/* The IU state */ +IU_STATE iu_state; + +t_bool iu_increment_a = FALSE; +t_bool iu_increment_b = FALSE; + +extern uint16 csr_data; + +UNIT iu_unit[] = { + { UDATA(&iu_svc_tti, UNIT_IDLE, 0), TMLN_SPD_9600_BPS }, + { UDATA(&iu_svc_tto, TT_MODE_8B, 0), SERIAL_OUT_WAIT }, + { UDATA(&iu_svc_timer, 0, 0) }, + { NULL } +}; + +BITFIELD sr_bits[] = { + BIT(RXRDY), + BIT(FFULL), + BIT(TXRDY), + BIT(TXEMT), + BIT(OVRN_E), + BIT(PRTY_E), + BIT(FRM_E), + BIT(BRK), + ENDBITS +}; + +BITFIELD isr_bits[] = { + BIT(TXRDYA), + BIT(RXRDY_FFA), + BIT(DLTA_BRKA), + BIT(CTR_RDY), + BIT(TXRDYB), + BIT(RXRDY_FFB), + BIT(DLTA_BRKB), + BIT(IPC), + ENDBITS +}; + +BITFIELD acr_bits[] = { + BIT(BRG_SET), + BITFFMT(TMR_MODE,3,%d), + BIT(DLTA_IP3), + BIT(DLTA_IP2), + BIT(DLTA_IP1), + BIT(DLTA_IP0), + ENDBITS +}; + +BITFIELD conf_bits[] = { + BIT(TX_EN), + BIT(RX_EN), + ENDBITS +}; + +REG iu_reg[] = { + { HRDATADF(ISTAT, iu_state.istat, 8, "Interrupt Status", isr_bits) }, + { HRDATAD(IMR, iu_state.imr, 8, "Interrupt Mask") }, + { HRDATADF(ACR, iu_state.acr, 8, "Auxiliary Control Register", acr_bits) }, + { HRDATAD(CTR, iu_state.c_set, 16, "Counter Setting") }, + { HRDATAD(IP, iu_state.inprt, 8, "Input Port") }, + { HRDATADF(STAT_A, iu_state.port[0].stat, 8, "Status (Port A)", sr_bits) }, + { HRDATAD(DATA_A, iu_state.port[0].buf, 8, "Data (Port A)") }, + { HRDATADF(CONF_A, iu_state.port[0].conf, 8, "Config (Port A)", conf_bits) }, + { HRDATADF(STAT_B, iu_state.port[1].stat, 8, "Status (Port B)", sr_bits) }, + { HRDATAD(DATA_B, iu_state.port[1].buf, 8, "Data (Port B)") }, + { HRDATADF(CONF_B, iu_state.port[1].conf, 8, "Config (Port B)", conf_bits) }, + { NULL } +}; + +DEVICE iu_dev = { + "IU", iu_unit, iu_reg, NULL, + 3, 8, 32, 1, 8, 8, + NULL, NULL, &iu_reset, + NULL, NULL, NULL, NULL, + DEV_DEBUG, 0, sys_deb_tab +}; + +void increment_modep_a() +{ + iu_increment_a = FALSE; + iu_state.port[PORT_A].modep++; + + if (iu_state.port[PORT_A].modep > 1) { + iu_state.port[PORT_A].modep = 0; + } +} + +void increment_modep_b() +{ + iu_increment_b = FALSE; + iu_state.port[PORT_B].modep++; + + if (iu_state.port[PORT_B].modep > 1) { + iu_state.port[PORT_B].modep = 0; + } +} + +void iu_txrdy_irq(uint8 portno) { + uint8 irq_mask = (uint8) (1u << (portno * 4)); + + if ((iu_state.imr & irq_mask) && + (iu_state.port[portno].conf & TX_EN) && + (iu_state.port[portno].stat & STS_TXR)) { + sim_debug(EXECUTE_MSG, &iu_dev, + "Firing IU TTY IRQ 13 ON TX/State Change\n"); + csr_data |= CSRUART; + } +} + +t_stat iu_reset(DEVICE *dptr) +{ + uint8 portno; + + memset(&iu_state, 0, sizeof(struct iu_state)); + + iu_state.opcr = 0; + + if (!sim_is_active(&iu_unit[UNIT_CONSOLE_TTI])) { + iu_unit[UNIT_CONSOLE_TTI].wait = IU_TTY_DELAY; + sim_activate(&iu_unit[UNIT_CONSOLE_TTI], + iu_unit[UNIT_CONSOLE_TTI].wait); + } + + for (portno = 0; portno < 2; portno++) { + iu_state.port[portno].buf = 0; + iu_state.port[portno].modep = 0; + iu_state.port[portno].conf = 0; + iu_state.port[portno].stat = 0; + } + + return SCPE_OK; +} + +t_stat iu_svc_tti(UNIT *uptr) +{ + int32 temp; + + sim_clock_coschedule_tmr_abs(uptr, TMR_CLK, 2); + + /* TODO: + + - If there has been a change on IP0-IP3, set the corresponding + bits in IPCR, if configured to do so. We'll need to figure out + how these are wired (DCD pin, etc?) + + - Update the Output Port pins (which are logically inverted) + based on the contents of the OPR, OPCR, MR, and CR registers. + */ + + if ((temp = sim_poll_kbd()) < SCPE_KFLAG) { + return temp; + } + + if (iu_state.port[PORT_A].conf & RX_EN) { + iu_state.port[PORT_A].buf = (temp & 0xff); + iu_state.port[PORT_A].stat |= STS_RXR; + iu_state.istat |= ISTS_RAI; + if (iu_state.imr & 0x02) { + sim_debug(EXECUTE_MSG, &iu_dev, + "Firing IU TTY IRQ 13 ON RECEIVE (%c)\n", + (temp & 0xff)); + csr_data |= CSRUART; + } + } + + return SCPE_OK; +} + +t_stat iu_svc_tto(UNIT *uptr) +{ + sim_debug(EXECUTE_MSG, &iu_dev, + "Calling iu_txrdy_irq on iu_svc_tto\n"); + + iu_txrdy_irq(PORT_A); + + return SCPE_OK; +} + +t_stat iu_svc_timer(UNIT *uptr) +{ + iu_state.istat |= ISTS_CRI; + + if (iu_state.imr & 0x08) { + csr_data |= CSRUART; + } + + return SCPE_OK; +} + +/* + * Reg | Name (Read) | Name (Write) + * -----+-------------------------+---------------------------- + * 0 | Mode Register 1/2 A | Mode Register 1/2 A + * 1 | Status Register A | Clock Select Register A + * 2 | BRG Test | Command Register A + * 3 | Rx Holding Register A | Tx Holding Register A + * 4 | Input Port Change Reg. | Aux. Control Register + * 5 | Interrupt Status Reg. | Interrupt Mask Register + * 6 | Counter/Timer Upper Val | C/T Upper Preset Val. + * 7 | Counter/Timer Lower Val | C/T Lower Preset Val. + * 8 | Mode Register B | Mode Register B + * 9 | Status Register B | Clock Select Register B + * 10 | 1X/16X Test | Command Register B + * 11 | Rx Holding Register B | Tx Holding Register B + * 12 | *Reserved* | *Reserved* + * 13 | Input Ports IP0 to IP6 | Output Port Conf. Reg. + * 14 | Start Counter Command | Set Output Port Bits Cmd. + * 15 | Stop Counter Command | Reset Output Port Bits Cmd. + */ + + +uint32 iu_read(uint32 pa, size_t size) +{ + uint8 reg, modep; + uint32 data, delay; + + reg = (uint8) (pa - IUBASE); + + switch (reg) { + case MR12A: + modep = iu_state.port[PORT_A].modep; + data = iu_state.port[PORT_A].mode[modep]; + iu_increment_a = TRUE; + break; + case SRA: + data = iu_state.port[PORT_A].stat; + break; + case RHRA: + data = iu_state.port[PORT_A].buf; + iu_state.port[PORT_A].stat &= ~STS_RXR; + iu_state.istat &= ~ISTS_RAI; + csr_data &= ~CSRUART; + break; + case IPCR: + data = iu_state.ipcr; + /* Reading the port resets the upper four bits */ + iu_state.ipcr &= 0x0f; + csr_data &= ~CSRUART; + break; + case ISR: + data = iu_state.istat; + break; + case CTU: + data = (iu_state.c_set >> 8) & 0xff; + break; + case CTL: + data = iu_state.c_set & 0xff; + break; + case MR12B: + modep = iu_state.port[PORT_B].modep; + data = iu_state.port[PORT_B].mode[modep]; + iu_increment_b = TRUE; + break; + case SRB: + data = iu_state.port[PORT_B].stat; + break; + case RHRB: + data = iu_state.port[PORT_B].buf; + iu_state.port[PORT_B].stat &= ~STS_RXR; + iu_state.istat &= ~ISTS_RBI; + break; + case INPRT: + /* TODO: Correct behavior for DCD on contty */ + /* For now, this enables DCD/DTR on console only */ + data = 0x8e; + break; + case START_CTR: + data = 0; + iu_state.istat &= ~ISTS_CRI; + delay = (uint32) (IU_TIMER_STP * iu_state.c_set); + sim_activate_abs(&iu_unit[UNIT_IU_TIMER], (int32) DELAY_US(delay)); + break; + case STOP_CTR: + data = 0; + iu_state.istat &= ~ISTS_CRI; + csr_data &= ~CSRUART; + sim_cancel(&iu_unit[UNIT_IU_TIMER]); + break; + case 17: /* Clear DMAC interrupt */ + data = 0; + iu_state.drqa = FALSE; + iu_state.drqb = FALSE; + csr_data &= ~CSRDMA; + break; + default: + data = 0; + break; + } + + return data; +} + +void iu_write(uint32 pa, uint32 val, size_t size) +{ + uint8 reg; + uint8 modep; + + reg = (uint8) (pa - IUBASE); + + switch (reg) { + case MR12A: + modep = iu_state.port[PORT_A].modep; + iu_state.port[PORT_A].mode[modep] = val & 0xff; + iu_increment_a = TRUE; + break; + case CSRA: + /* Set baud rate - not implemented */ + break; + case CRA: /* Command A */ + iu_w_cmd(PORT_A, (uint8) val); + break; + case THRA: /* TX/RX Buf A */ + /* Loopback mode */ + if ((iu_state.port[PORT_A].mode[1] & 0xc0) == 0x80) { + iu_state.port[PORT_A].buf = (uint8) val; + iu_state.port[PORT_A].stat |= STS_RXR; + iu_state.istat |= ISTS_RAI; + } else { + iu_tx(PORT_A, (uint8) val); + } + csr_data &= ~CSRUART; + break; + case ACR: /* Auxiliary Control Register */ + iu_state.acr = (uint8) val; + break; + case IMR: + iu_state.imr = (uint8) val; + csr_data &= ~CSRUART; + /* Possibly cause an interrupt */ + sim_debug(EXECUTE_MSG, &iu_dev, + ">>> calling iu_txrdy_irq() on IMR write.\n"); + iu_txrdy_irq(PORT_A); + iu_txrdy_irq(PORT_B); + break; + case CTUR: /* Counter/Timer Upper Preset Value */ + /* Clear out high byte */ + iu_state.c_set &= 0x00ff; + /* Set high byte */ + iu_state.c_set |= (val & 0xff) << 8; + break; + case CTLR: /* Counter/Timer Lower Preset Value */ + /* Clear out low byte */ + iu_state.c_set &= 0xff00; + /* Set low byte */ + iu_state.c_set |= (val & 0xff); + break; + case MR12B: + modep = iu_state.port[PORT_B].modep; + iu_state.port[PORT_B].mode[modep] = val & 0xff; + iu_increment_b = TRUE; + break; + case CRB: /* Command B */ + iu_w_cmd(PORT_B, (uint8) val); + break; + case CSRB: + break; + case THRB: /* TX/RX Buf B */ + /* Loopback mode */ + if ((iu_state.port[PORT_B].mode[1] & 0xc0) == 0x80) { + iu_state.port[PORT_B].buf = (uint8) val; + iu_state.port[PORT_B].stat |= STS_RXR; + iu_state.istat |= ISTS_RAI; + } else { + iu_tx(PORT_B, (uint8) val); + } + break; + case OPCR: + iu_state.opcr = (uint8) val; + break; + case SOPR: + break; + case ROPR: + break; + default: + break; + } +} + +void iua_drq_handled() +{ + sim_debug(EXECUTE_MSG, &iu_dev, + "Firing IU TTY IRQ 13 On DRQ Handled\n"); + + csr_data |= CSRDMA; +} + +void iub_drq_handled() +{ + sim_debug(EXECUTE_MSG, &iu_dev, + ">>> DRQB handled.\n"); +} + +static SIM_INLINE void iu_tx(uint8 portno, uint8 val) +{ + struct port *p; + + p = &iu_state.port[portno]; + + p->buf = val; + + if (p->conf & TX_EN) { + sim_debug(EXECUTE_MSG, &iu_dev, + "[%08x] TRANSMIT: %02x (%c)\n", + R[NUM_PC], val, val); + p->stat &= ~(STS_TXR|STS_TXE); + iu_state.istat &= ~(1 << (portno*4)); + + /* Write the character to the SIMH console */ + sim_putchar(p->buf); + + /* The buffer is now empty, we've transmitted, so set TXR */ + p->stat |= STS_TXR; + iu_state.istat |= (1 << (portno*4)); + + /* Possibly cause an interrupt */ + sim_activate_abs(&iu_unit[UNIT_CONSOLE_TTO], + iu_unit[UNIT_CONSOLE_TTO].wait); + } +} + +static SIM_INLINE void iu_w_cmd(uint8 portno, uint8 cmd) +{ + /* Enable or disable transmitter */ + /* Disable always wins, if both are set */ + if (cmd & CMD_DTX) { + iu_state.port[portno].conf &= ~TX_EN; + iu_state.port[portno].stat &= ~STS_TXR; + iu_state.port[portno].stat &= ~STS_TXE; + iu_state.drqa = FALSE; + sim_debug(EXECUTE_MSG, &iu_dev, + ">>> Disabling transmitter.\n"); + } else if (cmd & CMD_ETX) { + iu_state.port[portno].conf |= TX_EN; + /* TXE and TXR are always set by an ENABLE */ + iu_state.port[portno].stat |= STS_TXR; + iu_state.port[portno].stat |= STS_TXE; + iu_state.istat |= 1 << (portno*4); + iu_state.drqa = TRUE; + sim_debug(EXECUTE_MSG, &iu_dev, + ">>> Calling iu_txrdy_irq() on TX Enable\n"); + iu_txrdy_irq(portno); + } + + /* Enable or disable receiver. */ + /* Disable always wins, if both are set */ + if (cmd & CMD_DRX) { + iu_state.port[portno].conf &= ~RX_EN; + iu_state.port[portno].stat &= ~STS_RXR; + } else if (cmd & CMD_ERX) { + iu_state.port[portno].conf |= RX_EN; + } + + /* Command register bits 6-4 have special meaning */ + switch ((cmd >> CMD_MISC_SHIFT) & CMD_MISC_MASK) { + case 1: + /* Causes the Channel A MR pointer to point to MR1. */ + iu_state.port[portno].modep = 0; + break; + case 2: + /* Reset receiver. Resets the Channel's receiver as if a + hardware reset had been applied. The receiver is disabled + and the FIFO is flushed. */ + iu_state.port[portno].stat &= ~STS_RXR; + iu_state.port[portno].conf &= ~RX_EN; + iu_state.port[portno].buf = 0; + break; + case 3: + /* Reset transmitter. Resets the Channel's transmitter as if a + hardware reset had been applied. */ + iu_state.port[portno].stat &= ~STS_TXR; + iu_state.port[portno].stat &= ~STS_TXE; + iu_state.port[portno].conf &= ~TX_EN; + iu_state.port[portno].buf = 0; + break; + case 4: + /* Reset error status. Clears the Channel's Received Break, + Parity Error, and Overrun Error bits in the status register + (SRA[7:4]). Used in character mode to clear OE status + (although RB, PE and FE bits will also be cleared) and in + block mode to clear all error status after a block of data + has been received. */ + iu_state.port[portno].stat &= ~(STS_FER|STS_PER|STS_OER); + break; + case 5: + /* Reset Channel's break change interrupt. Causes the Channel + A break detect change bit in the interrupt status register + (ISR[2] for Chan. A, ISR[6] for Chan. B) to be cleared to + zero. */ + iu_state.istat &= ~(1 << (2 + portno*4)); + break; + case 6: + /* Start break. Forces the TxDA output LOW (spacing). If the + transmitter is empty the start of the break condition will + be delayed up to two bit times. If the transmitter is + active the break begins when transmission of the character + is completed. If a character is in the THR, the start of + the break will be delayed until that character, or any + other loaded subsequently are transmitted. The transmitter + must be enabled for this command to be accepted. */ + /* Not Implemented */ + break; + case 7: + /* Stop break. The TxDA line will go HIGH (marking) within two + bit times. TxDA will remain HIGH for one bit time before + the next character, if any, is transmitted. */ + /* Not Implemented */ + break; + } +} diff --git a/3B2/3b2_iu.h b/3B2/3b2_iu.h new file mode 100644 index 00000000..4db16d95 --- /dev/null +++ b/3B2/3b2_iu.h @@ -0,0 +1,192 @@ +/* 3b2_iu.h: SCN2681A Dual UART Header + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#ifndef __3B2_IU_H__ +#define __3B2_IU_H__ + +#include "3b2_defs.h" +#include "3b2_sysdev.h" + +#define CMD_ERX 0x01 /* Enable receiver */ +#define CMD_DRX 0x02 /* Disable receiver */ +#define CMD_ETX 0x04 /* Enable transmitter */ +#define CMD_DTX 0x08 /* Disable transmitter */ +#define CMD_MISC_SHIFT 4 /* Command */ +#define CMD_MISC_MASK 0x7 + +#define STS_RXR 0x01 /* Receiver ready */ +#define STS_FFL 0x02 /* FIFO full */ +#define STS_TXR 0x04 /* Transmitter ready */ +#define STS_TXE 0x08 /* Transmitter empty */ +#define STS_OER 0x10 /* Overrun error */ +#define STS_PER 0x20 /* Parity error */ +#define STS_FER 0x40 /* Framing error */ +#define STS_RXB 0x80 /* Received break */ + +#define ISTS_TAI 0x01 /* Transmitter ready A */ +#define ISTS_RAI 0x02 /* Receiver ready A */ +#define ISTS_CBA 0x04 /* Change in break A */ +#define ISTS_CRI 0x08 /* Counter ready */ +#define ISTS_TBI 0x10 /* Transmitter ready B */ +#define ISTS_RBI 0x20 /* Receiver ready B */ +#define ISTS_CBB 0x40 /* Change in break B */ +#define ISTS_IPC 0x80 /* Interrupt port change */ + +#define MODE_V_CHM 6 /* Channel mode */ +#define MODE_M_CHM 0x3 + +#define PORT_A 0 +#define PORT_B 1 + +/* Used by the DMAC */ +#define IUA_DATA_REG 3 +#define IUB_DATA_REG 11 + +/* Registers - Read */ +#define SRA 1 +#define RHRA 3 +#define IPCR 4 +#define ISR 5 +#define CTU 6 +#define CTL 7 +#define SRB 9 +#define RHRB 11 +#define INPRT 13 /* Input port data */ +#define START_CTR 14 +#define STOP_CTR 15 + +/* Registers - Write */ +#define CSRA 1 +#define CRA 2 +#define THRA 3 +#define ACR 4 +#define IMR 5 +#define CTUR 6 +#define CTLR 7 +#define CSRB 9 +#define CRB 10 +#define THRB 11 +#define OPCR 13 +#define SOPR 14 +#define ROPR 15 + +#define UNIT_CONSOLE_TTI 0 +#define UNIT_CONSOLE_TTO 1 +#define UNIT_IU_TIMER 2 + +/* Registers - R/W */ +#define MR12A 0 +#define MR12B 8 + +/* Port configuration */ +#define TX_EN 1 +#define RX_EN 2 + +#define UM_CTR_EXT 0 +#define UM_CTR_TXCA 1 +#define UM_CTR_TXCB 2 +#define UM_CTR_DIV16 3 +#define UM_TMR_EXT 4 +#define UM_TMR_EXT16 5 +#define UM_TMR_XTL 6 +#define UM_TMR_XTL16 7 +#define UM_MASK 0x70 +#define UM_SHIFT 4 + +#define IU_MODE(x) ((x & UM_MASK) >> UM_SHIFT) + +extern DEVICE iu_dev; + +#define IU_TTY_DELAY 25000 + +#define IUBASE 0x49000 +#define IUSIZE 0x100 + +/* The UART is driven by a 3.6864 MHz crystal. This is divided by 16 + to clock the timer. (One peculiarity: 3.6864 MHz /16 is 230400 Hz, + but the SVR3 source code claims the /16 clock is actually 230525 + Hz. So, we'll go with 230525 Hz until proven otherwise.) + + UART clock period = 4338ns + System clock period = 100ns + + That means the system ticks 43.3792 times for every one tick of the + UART clock. + + But this is a simulated system, where each simulator step is + CYCLES_PER_INST long. So we take that into account. +*/ + +#define IU_TIMER_STP 4.33792 + +struct port { + uint8 stat; /* Port Status */ + uint8 cmd; /* Command */ + uint8 mode[2]; /* Two mode buffers */ + uint8 modep; /* Point to mode[0] or mode[1] */ + uint8 conf; /* Configuration bits */ + uint8 buf; /* Character data */ +}; + +typedef struct iu_state { + uint8 istat; /* Interrupt Status */ + uint8 imr; /* Interrupt Mask Register */ + uint16 c_set; /* Timer / Counter Setting */ + int32 c_val; /* Timer / Counter Value */ + t_bool c_en; /* Counter Enabled */ + t_bool drqa; /* Port A DRQ */ + t_bool drqb; /* Port B DRQ */ + uint8 acr; + uint8 opcr; /* Output Port Configuration */ + uint8 inprt; /* Input Port Data */ + uint8 ipcr; /* Input Port Change Register */ + struct port port[2]; /* Port A and B */ +} IU_STATE; + +extern IU_STATE iu_state; + +/* Function prototypes */ + +t_stat iu_reset(DEVICE *dptr); +t_stat iu_svc_tti(UNIT *uptr); +t_stat iu_svc_tto(UNIT *uptr); +t_stat iu_svc_timer(UNIT *uptr); +uint32 iu_read(uint32 pa, size_t size); +void iu_write(uint32 pa, uint32 val, size_t size); +void iua_drq_handled(); +void iub_drq_handled(); + +static SIM_INLINE void iu_tx(uint8 portno, uint8 val); +static SIM_INLINE void iu_w_buf(uint8 portno, uint8 val); +static SIM_INLINE void iu_w_cmd(uint8 portno, uint8 val); +static SIM_INLINE void iu_update_rxi(uint8 c); +static SIM_INLINE void iu_update_txi(); + +#endif diff --git a/3B2/3b2_mmu.c b/3B2/3b2_mmu.c new file mode 100644 index 00000000..2d4c7352 --- /dev/null +++ b/3B2/3b2_mmu.c @@ -0,0 +1,882 @@ +/* 3b2_mmu.c: AT&T 3B2 Model 400 MMU (WE32101) Implementation + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#include "3b2_mmu.h" + +UNIT mmu_unit = { UDATA(NULL, 0, 0) }; + +MMU_STATE mmu_state; + +REG mmu_reg[] = { + { HRDATAD (ENABLE, mmu_state.enabled, 1, "Enabled?") }, + { HRDATAD (CONFIG, mmu_state.conf, 32, "Configuration") }, + { HRDATAD (VAR, mmu_state.var, 32, "Virtual Address") }, + { HRDATAD (FCODE, mmu_state.fcode, 32, "Fault Code") }, + { HRDATAD (FADDR, mmu_state.faddr, 32, "Fault Address") }, + { BRDATA (SDCL, mmu_state.sdcl, 16, 32, MMU_SDCS) }, + { BRDATA (SDCR, mmu_state.sdch, 16, 32, MMU_SDCS) }, + { BRDATA (PDCLL, mmu_state.pdcll, 16, 32, MMU_PDCS) }, + { BRDATA (PDCLH, mmu_state.pdclh, 16, 32, MMU_PDCS) }, + { BRDATA (PDCRL, mmu_state.pdcrl, 16, 32, MMU_PDCS) }, + { BRDATA (PDCRH, mmu_state.pdcrh, 16, 32, MMU_PDCS) }, + { BRDATA (SRAMA, mmu_state.sra, 16, 32, MMU_SRS) }, + { BRDATA (SRAMB, mmu_state.srb, 16, 32, MMU_SRS) }, + { NULL } +}; + +DEVICE mmu_dev = { + "MMU", &mmu_unit, mmu_reg, NULL, + 1, 16, 8, 4, 16, 32, + NULL, NULL, &mmu_init, + NULL, NULL, NULL, NULL, + DEV_DEBUG, 0, sys_deb_tab +}; + +t_stat mmu_init(DEVICE *dptr) +{ + flush_caches(); + return SCPE_OK; +} + +uint32 mmu_read(uint32 pa, size_t size) +{ + uint32 offset; + uint32 data = 0; + + offset = (pa >> 2) & 0x1f; + + switch ((pa >> 8) & 0xf) { + case MMU_SDCL: + data = mmu_state.sdcl[offset]; + sim_debug(READ_MSG, &mmu_dev, + "MMU_SDCL[%d] = %08x\n", + offset, data); + break; + case MMU_SDCH: + data = mmu_state.sdch[offset]; + sim_debug(READ_MSG, &mmu_dev, + "MMU_SDCH[%d] = %08x\n", + offset, data); + break; + case MMU_PDCRL: + data = mmu_state.pdcrl[offset]; + sim_debug(READ_MSG, &mmu_dev, + "MMU_PDCRL[%d] = %08x\n", + offset, data); + break; + case MMU_PDCRH: + data = mmu_state.pdcrh[offset]; + sim_debug(READ_MSG, &mmu_dev, + "MMU_PDCRH[%d] = %08x\n", + offset, data); + break; + case MMU_PDCLL: + data = mmu_state.pdcll[offset]; + sim_debug(READ_MSG, &mmu_dev, + "MMU_PDCLL[%d] = %08x\n", + offset, data); + break; + case MMU_PDCLH: + data = mmu_state.pdclh[offset]; + sim_debug(READ_MSG, &mmu_dev, + "MMU_PDCLH[%d] = %08x\n", + offset, data); + break; + case MMU_SRAMA: + data = mmu_state.sra[offset]; + sim_debug(READ_MSG, &mmu_dev, + "[%08x] MMU_SRAMA[%d] = %08x\n", + R[NUM_PC], offset, data); + break; + case MMU_SRAMB: + data = mmu_state.srb[offset]; + sim_debug(READ_MSG, &mmu_dev, + "[%08x] MMU_SRAMB[%d] = %08x\n", + R[NUM_PC], offset, data); + break; + case MMU_FC: + data = mmu_state.fcode; + break; + case MMU_FA: + data = mmu_state.faddr; + break; + case MMU_CONF: + data = mmu_state.conf & 0x7; + sim_debug(READ_MSG, &mmu_dev, + "[%08x] MMU_CONF = %08x\n", + R[NUM_PC], data); + break; + case MMU_VAR: + data = mmu_state.var; + sim_debug(READ_MSG, &mmu_dev, + "[%08x] MMU_VAR = %08x\n", + R[NUM_PC], data); + break; + } + + return data; +} + +void mmu_write(uint32 pa, uint32 val, size_t size) +{ + uint32 offset; + + offset = (pa >> 2) & 0x1f; + + switch ((pa >> 8) & 0xf) { + case MMU_SDCL: + sim_debug(WRITE_MSG, &mmu_dev, + "MMU_SDCL[%d] = %08x\n", + offset, val); + mmu_state.sdcl[offset] = val; + break; + case MMU_SDCH: + sim_debug(WRITE_MSG, &mmu_dev, + "MMU_SDCH[%d] = %08x\n", + offset, val); + mmu_state.sdch[offset] = val; + break; + case MMU_PDCRL: + sim_debug(WRITE_MSG, &mmu_dev, + "MMU_PDCRL[%d] = %08x\n", + offset, val); + mmu_state.pdcrl[offset] = val; + break; + case MMU_PDCRH: + sim_debug(WRITE_MSG, &mmu_dev, + "MMU_PDCRH[%d] = %08x\n", + offset, val); + mmu_state.pdcrh[offset] = val; + break; + case MMU_PDCLL: + sim_debug(WRITE_MSG, &mmu_dev, + "MMU_PDCLL[%d] = %08x\n", + offset, val); + mmu_state.pdcll[offset] = val; + break; + case MMU_PDCLH: + sim_debug(WRITE_MSG, &mmu_dev, + "MMU_PDCLH[%d] = %08x\n", + offset, val); + mmu_state.pdclh[offset] = val; + break; + case MMU_SRAMA: + offset = offset & 3; + mmu_state.sra[offset] = val; + mmu_state.sec[offset].addr = val & 0xffffffe0; + /* We flush the entire section on writing SRAMA */ + flush_cache_sec((uint8) offset); + sim_debug(WRITE_MSG, &mmu_dev, + "[%08x] MMU_SRAMA[%d] = %08x (addr=%08x)\n", + R[NUM_PC], offset, val, mmu_state.sec[offset].addr); + break; + case MMU_SRAMB: + offset = offset & 3; + mmu_state.srb[offset] = val; + mmu_state.sec[offset].len = (val >> 10) & 0x1fff; + /* We do not flush the cache on writing SRAMB */ + sim_debug(WRITE_MSG, &mmu_dev, + "[%08x] MMU_SRAMB[%d] = %08x (len=%06x)\n", + R[NUM_PC], offset, val, mmu_state.sec[offset].len); + break; + case MMU_FC: + mmu_state.fcode = val; + break; + case MMU_FA: + mmu_state.faddr = val; + sim_debug(WRITE_MSG, &mmu_dev, + "[%08x] MMU_FAULT_ADDR = %08x\n", + R[NUM_PC], val); + break; + case MMU_CONF: + mmu_state.conf = val & 0x7; + sim_debug(WRITE_MSG, &mmu_dev, + "[%08x] MMU_CONF = %08x\n", + R[NUM_PC], val); + break; + case MMU_VAR: + mmu_state.var = val; + flush_sdce(val); + flush_pdce(val); + sim_debug(WRITE_MSG, &mmu_dev, + "[%08x] MMU_VAR = %08x\n", + R[NUM_PC], val); + break; + } +} + +t_bool addr_is_rom(uint32 pa) +{ + return (pa < BOOT_CODE_SIZE); +} + +t_bool addr_is_mem(uint32 pa) +{ + return (pa >= PHYS_MEM_BASE && + pa < (PHYS_MEM_BASE + MEM_SIZE)); +} + +t_bool addr_is_io(uint32 pa) +{ + return ((pa >= IO_BASE && pa < IO_BASE + IO_SIZE) || + (pa >= IOB_BASE && pa < IOB_BASE + IOB_SIZE)); +} + +/* + * Raw physical reads and writes. + * + * The WE32100 is a BIG-endian machine, meaning that words are + * arranged in increasing address from most-significant byte to + * least-significant byte. + */ + +/* + * Read Word (Physical Address) + */ +uint32 pread_w(uint32 pa) +{ + uint32 *m; + uint32 index; + + if (pa & 3) { + sim_debug(READ_MSG, &mmu_dev, + "[%08x] Cannot read physical address. ALIGNMENT ISSUE: %08x\n", + R[NUM_PC], pa); + csr_data |= CSRALGN; + cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); + } + + if (addr_is_io(pa)) { + return io_read(pa, 32); + } + + if (addr_is_rom(pa)) { + m = ROM; + index = pa >> 2; + } else if (addr_is_mem(pa)) { + m = RAM; + index = (pa - PHYS_MEM_BASE) >> 2; + } else { + return 0; + } + + return m[index]; +} + +/* + * Write Word (Physical Address) + */ +void pwrite_w(uint32 pa, uint32 val) +{ + if (pa & 3) { + sim_debug(WRITE_MSG, &mmu_dev, + "[%08x] Cannot write physical address. ALIGNMENT ISSUE: %08x\n", + R[NUM_PC], pa); + csr_data |= CSRALGN; + cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); + } + + if (addr_is_io(pa)) { + io_write(pa, val, 32); + return; + } + + if (addr_is_mem(pa)) { + RAM[(pa - PHYS_MEM_BASE) >> 2] = val; + return; + } +} + +/* + * Read Halfword (Physical Address) + */ +uint16 pread_h(uint32 pa) +{ + uint32 *m; + uint32 index; + + if (pa & 1) { + sim_debug(READ_MSG, &mmu_dev, + "[%08x] Cannot read physical address. ALIGNMENT ISSUE %08x\n", + R[NUM_PC], pa); + csr_data |= CSRALGN; + cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); + } + + if (addr_is_io(pa)) { + return (uint16) io_read(pa, 16); + } + + if (addr_is_rom(pa)) { + m = ROM; + index = pa >> 2; + } else if (addr_is_mem(pa)) { + m = RAM; + index = (pa - PHYS_MEM_BASE) >> 2; + } else { + return 0; + } + + if (pa & 2) { + return m[index] & HALF_MASK; + } else { + return (m[index] >> 16) & HALF_MASK; + } +} + +/* + * Write Halfword (Physical Address) + */ +void pwrite_h(uint32 pa, uint16 val) +{ + uint32 *m; + uint32 index; + uint32 wval = (uint32)val; + + if (pa & 1) { + sim_debug(WRITE_MSG, &mmu_dev, + "[%08x] Cannot write physical address %08x, ALIGNMENT ISSUE\n", + R[NUM_PC], pa); + csr_data |= CSRALGN; + cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); + } + + if (addr_is_io(pa)) { + io_write(pa, val, 16); + return; + } + + if (addr_is_mem(pa)) { + m = RAM; + index = (pa - PHYS_MEM_BASE) >> 2; + } else { + return; + } + + if (pa & 2) { + m[index] = (m[index] & ~HALF_MASK) | wval; + } else { + m[index] = (m[index] & HALF_MASK) | (wval << 16); + } +} + +/* + * Read Byte (Physical Address) + */ +uint8 pread_b(uint32 pa) +{ + uint32 data; + int32 sc = (~(pa & 3) << 3) & 0x1f; + + if (addr_is_io(pa)) { + return (uint8)(io_read(pa, 8)); + } + + if (addr_is_rom(pa)) { + data = ROM[pa >> 2]; + } else if (addr_is_mem(pa)) { + data = RAM[(pa - PHYS_MEM_BASE) >> 2]; + } else { + return 0; + } + + return (data >> sc) & BYTE_MASK; +} + +/* + * Write Byte (Physical Address) + */ +void pwrite_b(uint32 pa, uint8 val) +{ + uint32 *m; + int32 index; + int32 sc = (~(pa & 3) << 3) & 0x1f; + uint32 mask = 0xffu << sc; + + if (addr_is_io(pa)) { + io_write(pa, val, 8); + return; + } + + if (addr_is_mem(pa)) { + m = RAM; + index = (pa - PHYS_MEM_BASE) >> 2; + m[index] = (m[index] & ~mask) | (uint32) (val << sc); + return; + } +} + +/* Helper functions for MMU decode. */ + +/* + * Get the Segment Descriptor for a virtual address on a cache miss. + * + * Returns SCPE_OK on success, SCPE_NXM on failure. + * + * If SCPE_NXM is returned, a failure code and fault address will be + * set in the appropriate registers. + * + * As always, the flag 'fc' may be set to FALSE to avoid certain + * typses of fault checking. + * + */ +t_stat mmu_get_sd(uint32 va, uint8 r_acc, t_bool fc, + uint32 *sd0, uint32 *sd1) +{ + /* We immediately do some bounds checking (fc flag is not checked + * because this is a fatal error) */ + if (SSL(va) > SRAMB_LEN(va)) { + MMU_FAULT(MMU_F_SDTLEN); + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] SDT Length Fault. sramb_len=%x ssl=%x va=%08x\n", + R[NUM_PC], SRAMB_LEN(va), SSL(va), va); + return SCPE_NXM; + } + + /* sd0 contains the segment descriptor, sd1 contains a pointer to + the PDT or Segment */ + *sd0 = pread_w(SD_ADDR(va)); + *sd1 = pread_w(SD_ADDR(va) + 4); + + if (!SD_VALID(*sd0)) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Invalid Segment Descriptor. va=%08x sd0=%08x\n", + R[NUM_PC], va, *sd0); + MMU_FAULT(MMU_F_INV_SD); + return SCPE_NXM; + } + + /* TODO: Handle indirect lookups. */ + if (SD_INDIRECT(*sd0)) { + stop_reason = STOP_MMU; + return SCPE_NXM; + } + + /* If the segment descriptor isn't present, we need to + * fail out */ + if (!SD_PRESENT(*sd0)) { + if (SD_CONTIG(*sd0)) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Segment Not Present. va=%08x", + R[NUM_PC], va); + MMU_FAULT(MMU_F_SEG_NOT_PRES); + return SCPE_NXM; + } else { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] PDT Not Present. va=%08x", + R[NUM_PC], va); + MMU_FAULT(MMU_F_PDT_NOT_PRES); + return SCPE_NXM; + } + } + + if (SHOULD_CACHE_SD(*sd0)) { + put_sdce(va, *sd0, *sd1); + } + + return SCPE_OK; +} + +/* + * Load a page descriptor from memory + */ +t_stat mmu_get_pd(uint32 va, uint8 r_acc, t_bool fc, + uint32 sd0, uint32 sd1, + uint32 *pd, uint8 *pd_acc) +{ + uint32 pd_addr; + + /* Where do we find the page descriptor? */ + pd_addr = SD_SEG_ADDR(sd1) + (PSL(va) * 4); + + /* Bounds checking on length */ + if ((PSL(va) * 4) > MAX_OFFSET(sd0)) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] PDT Length Fault. " + "PDT Offset=%08x Max Offset=%08x va=%08x\n", + R[NUM_PC], (PSL(va) * 4), + MAX_OFFSET(sd0), va); + MMU_FAULT(MMU_F_PDTLEN); + return SCPE_NXM; + } + + *pd = pread_w(pd_addr); + + /* Copy the access flags from the SD */ + *pd_acc = SD_ACC(sd0); + + /* Cache it */ + if (SHOULD_CACHE_PD(*pd)) { + put_pdce(va, sd0, *pd); + } + + return SCPE_OK; +} + +/* + * Decode an address from a contiguous segment. + */ +t_stat mmu_decode_contig(uint32 va, uint8 r_acc, + uint32 sd0, uint32 sd1, + t_bool fc, uint32 *pa) +{ + if (fc) { + /* Verify permissions */ + if (mmu_check_perm(SD_ACC(sd0), r_acc) != SCPE_OK) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] SEGMENT: NO ACCESS TO MEMORY AT %08x.\n" + "\t\tcpu_cm=%d acc_req=%x sd_acc=%02x\n", + R[NUM_PC], va, CPU_CM, r_acc, SD_ACC(sd0)); + MMU_FAULT(MMU_F_ACC); + return SCPE_NXM; + } + } + + /* Do max segment offset check outside any 'fc' checks because we + want this to fail even if fc is false. */ + + if (SOT(va) > MAX_OFFSET(sd0)) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] CONTIGUOUS: Segment Offset Fault. " + "sd0=%08x SOT=%08x len=%08x va=%08x\n", + R[NUM_PC], sd0, SOT(va), + (SD_MAX_OFF(sd0) * 8), va); + MMU_FAULT(MMU_F_SEG_OFFSET); + return SCPE_NXM; + } + + + /* TODO: It's possible to have BOTH a segment offset violation AND + an access violation. We need to cover that instance. */ + + + if (fc) { + /* Update R and M bits if configured */ + if (SHOULD_UPDATE_SD_R_BIT(sd0)) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Updating R bit in SD\n", + R[NUM_PC]); + mmu_update_sd(va, SD_R_MASK); + } + + if (SHOULD_UPDATE_SD_M_BIT(sd0)) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Updating M bit in SD\n", + R[NUM_PC]); + mmu_update_sd(va, SD_M_MASK); + } + + /* Generate object trap if needed */ + if (SD_TRAP(sd0)) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Object Trap. va=%08x", + R[NUM_PC], va); + MMU_FAULT(MMU_F_OTRAP); + return SCPE_NXM; + } + } + + *pa = SD_SEG_ADDR(sd1) + SOT(va); + return SCPE_OK; +} + +t_stat mmu_decode_paged(uint32 va, uint8 r_acc, t_bool fc, + uint32 sd1, uint32 pd, + uint8 pd_acc, uint32 *pa) +{ + if (fc && mmu_check_perm(pd_acc, r_acc) != SCPE_OK) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] PAGE: NO ACCESS TO MEMORY AT %08x.\n" + "\t\tcpu_cm=%d r_acc=%x pd_acc=%02x\n" + "\t\tpd=%08x psw=%08x\n", + R[NUM_PC], va, CPU_CM, r_acc, pd_acc, + pd, R[NUM_PSW]); + MMU_FAULT(MMU_F_ACC); + return SCPE_NXM; + } + + /* If the PD is not marked present, fail */ + if (!PD_PRESENT(pd)) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Page Not Present. " + "pd=%08x r_acc=%x va=%08x\n", + R[NUM_PC], pd, r_acc, va); + MMU_FAULT(MMU_F_PAGE_NOT_PRES); + return SCPE_NXM; + } + + if (fc) { + /* If this is a write or interlocked read access, and + the 'W' bit is set, trigger a write fault */ + if ((r_acc == ACC_W || r_acc == ACC_IR) && PD_WFAULT(pd)) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Page Write Fault. va=%08x\n", + R[NUM_PC], va); + MMU_FAULT(MMU_F_PW); + return SCPE_NXM; + } + + /* If this is a write, modify the M bit */ + if (SHOULD_UPDATE_PD_M_BIT(pd)) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Updating M bit in PD\n", + R[NUM_PC]); + mmu_update_pd(va, PD_LOC(sd1, va), PD_M_MASK); + } + + /* Modify the R bit and write it back */ + if (SHOULD_UPDATE_PD_R_BIT(pd)) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Updating R bit in PD\n", + R[NUM_PC]); + mmu_update_pd(va, PD_LOC(sd1, va), PD_R_MASK); + } + } + + *pa = PD_ADDR(pd) + POT(va); + return SCPE_OK; +} + +/* + * Translate a virtual address into a physical address. + * + * If "fc" is false, this function will bypass: + * + * - Access flag checks + * - Cache insertion + * - Setting MMU fault registers + * - Modifying segment and page descriptor bits + */ + +t_stat mmu_decode_va(uint32 va, uint8 r_acc, t_bool fc, uint32 *pa) +{ + uint32 sd0, sd1, pd; + uint8 pd_acc; + t_stat sd_cached, pd_cached; + + if (!mmu_enabled()) { + *pa = va; + return SCPE_OK; + } + + /* We must check both caches first to determine what kind of miss + processing to do. */ + + sd_cached = get_sdce(va, &sd0, &sd1); + pd_cached = get_pdce(va, &pd, &pd_acc); + + /* Now, potentially, do miss processing */ + + if (sd_cached != SCPE_OK && pd_cached != SCPE_OK) { + /* Full miss processing. We have to load both the SD and PD + * from main memory, and potentially cache them. */ + if (mmu_get_sd(va, r_acc, fc, &sd0, &sd1) != SCPE_OK) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Could not get SD (full miss). r_acc=%d, fc=%d, va=%08x\n", + R[NUM_PC], r_acc, fc, va); + return SCPE_NXM; + } + + if (!SD_CONTIG(sd0)) { + if (mmu_get_pd(va, r_acc, fc, sd0, sd1, &pd, &pd_acc) != SCPE_OK) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Could not get PD (full miss). r_acc=%d, fc=%d, va=%08x\n", + R[NUM_PC], r_acc, fc, va); + return SCPE_NXM; + } + } + } else if (sd_cached == SCPE_OK && pd_cached != SCPE_OK && !SD_CONTIG(sd0)) { + /* Partial miss processing - SDC hit and PDC miss - but only + * if segment is paged. */ + if (mmu_get_pd(va, r_acc, fc, sd0, sd1, &pd, &pd_acc) != SCPE_OK) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Could not get PD (partial miss). r_acc=%d, fc=%d, va=%08x\n", + R[NUM_PC], r_acc, fc, va); + return SCPE_NXM; + } + } else if (sd_cached != SCPE_OK && pd_cached == SCPE_OK) { + /* Partial miss processing - SDC miss and PDC hit. This is + * always paged translation */ + + /* First we must bring the SD into cache so that the SD + * R & M bits may be updated, if needed. */ + + if (mmu_get_sd(va, r_acc, fc, &sd0, &sd1) != SCPE_OK) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Could not get SD (partial miss). r_acc=%d, fc=%d, va=%08x\n", + R[NUM_PC], r_acc, fc, va); + return SCPE_NXM; + } + + /* If the 'L' bit is set in the page descriptor, we need to + * do some bounds checking */ + if (PD_LAST(pd)) { + if ((PD_ADDR(pd) + POT(va)) > (SD_SEG_ADDR(sd1) + MAX_OFFSET(sd0))) { + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] PAGED: Segment Offset Fault.\n", + R[NUM_PC]); + MMU_FAULT(MMU_F_SEG_OFFSET); + return SCPE_NXM; + } + } + + return mmu_decode_paged(va, r_acc, fc, sd1, pd, pd_acc, pa); + } + + if (SD_CONTIG(sd0)) { + return mmu_decode_contig(va, r_acc, sd0, sd1, fc, pa); + } else { + return mmu_decode_paged(va, r_acc, fc, sd1, pd, pd_acc, pa); + } +} + +t_stat examine(uint32 va, uint8 *val) { + uint32 pa; + t_stat succ; + + succ = mmu_decode_va(va, 0, FALSE, &pa); + + if (succ == SCPE_OK) { + if (addr_is_rom(pa) || addr_is_io(pa) || addr_is_mem(pa)) { + *val = pread_b(pa); + return SCPE_OK; + } else { + *val = 0; + return SCPE_NXM; + } + } else { + *val = 0; + return succ; + } +} + +t_stat deposit(uint32 va, uint8 val) { + uint32 pa; + t_stat succ; + + succ = mmu_decode_va(va, 0, FALSE, &pa); + + if (succ == SCPE_OK) { + if (addr_is_mem(pa) || addr_is_io(pa)) { + pwrite_b(pa, val); + return SCPE_OK; + } else { + return SCPE_NXM; + } + } else { + return succ; + } +} + +t_stat read_operand(uint32 va, uint8 *val) { + uint32 pa; + t_stat succ; + + succ = mmu_decode_va(va, ACC_OF, TRUE, &pa); + + if (succ == SCPE_OK) { + *val = pread_b(pa); + } else { + *val = 0; + } + + return succ; +} + +uint32 mmu_xlate_addr(uint32 va, uint8 r_acc) +{ + uint32 pa; + t_stat succ; + + succ = mmu_decode_va(va, r_acc, TRUE, &pa); + + if (succ == SCPE_OK) { + mmu_state.var = va; + return pa; + } else { + cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); + return 0; + } +} + +SIM_INLINE t_bool mmu_enabled() +{ + return mmu_state.enabled; +} + +void mmu_enable() +{ + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Enabling MMU.\n", + R[NUM_PC]); + mmu_state.enabled = TRUE; +} + +void mmu_disable() +{ + sim_debug(EXECUTE_MSG, &mmu_dev, + "[%08x] Disabling MMU.\n", + R[NUM_PC]); + mmu_state.enabled = FALSE; +} + +/* + * MMU Virtual Read and Write Functions + */ + +uint8 read_b(uint32 va, uint8 r_acc) +{ + return pread_b(mmu_xlate_addr(va, r_acc)); +} + +uint16 read_h(uint32 va, uint8 r_acc) +{ + return pread_h(mmu_xlate_addr(va, r_acc)); +} + +uint32 read_w(uint32 va, uint8 r_acc) +{ + return pread_w(mmu_xlate_addr(va, r_acc)); +} + +void write_b(uint32 va, uint8 val) +{ + pwrite_b(mmu_xlate_addr(va, ACC_W), val); +} + +void write_h(uint32 va, uint16 val) +{ + pwrite_h(mmu_xlate_addr(va, ACC_W), val); +} + +void write_w(uint32 va, uint32 val) +{ + pwrite_w(mmu_xlate_addr(va, ACC_W), val); +} diff --git a/3B2/3b2_mmu.h b/3B2/3b2_mmu.h new file mode 100644 index 00000000..82a63a06 --- /dev/null +++ b/3B2/3b2_mmu.h @@ -0,0 +1,612 @@ +/* 3b2_mmu.c: AT&T 3B2 Model 400 MMU (WE32101) Header + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#ifndef _3B2_MMU_H +#define _3B2_MMU_H + +#include "3b2_defs.h" + + +/************************************************************************ + * + * Vocabulary + * ---------- + * + * PD: Page Descriptor (in main memory) + * PDT: Page Descriptor Table (in main memory) + * POT: Page Offset. Bits 0-10 of a Paged virtual address. + * PSL: Page Select. Bits 11-16 of a Paged virtual address. + * SD: Segment Descriptor (in main memory) + * SDT: Segment Descriptor Table (in main memory) + * SID: Section ID. Bits 30-31 of all virtual addresses + * SOT: Segment Offset. Bits 0-16 of a Contiguous virtual address. + * SSL: Segment Select. Bits 17-29 of all virtual addresses. + * + * + * The WE32101 MMU divides the virtual address space into four + * Sections with 8K Segments per section. Virtual address bits 30 and + * 31 determine the section, bits 17-29 determine the Segment within + * the section. + * + * There are two kinds of address translation: Contiguous Translation + * and Paged Translation. Contiguous Translation just uses an offset + * (bits 0-16 of the virtual address) into each Segment to find an + * address, allowing for 128K bytes per Segment. Paged translation + * further break Segments down into 64 Pages of 2K each. + * + * Details about how to do translation are held in main memory in + * Segment Descriptors and Page Descriptors. These are located in + * Segment Descriptor Tables and Page Descriptor Tables set up by the + * computer before enabling the MMU. + * + * In addition to details in main memory, the MMU has a small cache + * of both Segment Descriptors and Page Descriptors. This is NOT just + * used for performance reasons! Various features of the cache, + * such as updating R and M bits in Segment and Page Descriptors, + * are used by various operating system features. + * + * + * Virtual Address Fields + * ---------------------- + * + * 31 30 29 17 16 0 + * +-----+-------------------+-----------------------------+ + * Contig: | SID | SSL | SOT | + * +-----+-------------------+-----------------------------+ + * + * 31 30 29 17 16 11 10 0 + * +-----+-------------------+---------+-------------------+ + * Paged: | SID | SSL | PSL | POT | + * +-----+-------------------+---------+-------------------+ + * + * + * Segment Descriptor Fields + * ------------------------- + * + * 31 24 23 10 9 8 7 6 5 4 3 2 1 0 + * +-------+---------+-----+---+---+---+---+---+---+---+---+ + * sd0: | Acc | Max Off | Res | I | V | R | T | $ | C | M | P | + * +-------+---------+-----+---+---+---+---+---+---+---+---+ + * + * +-----------------------------------------------+-------+ + * sd1: | Address (high-order 27 or 29 bits) | Soft | + * +-----------------------------------------------+-------+ + * + * + * Segment Descriptor Cache Entry + * ------------------------------ + * + * 31 24 23 10 9 0 + * +-------+-------------------------+---------------------+ + * Low: | Acc | Max Off | Tag | + * +-------+-------------------------+---------------------+ + * + * 31 5 4 3 2 1 0 + * +-----------------------------------+---+---+---+---+---+ + * High: | Address | T | $ | C | M | G | + * +-----------------------------------+---+---+---+---+---+ + * + * + * Page Descriptor Fields + * ---------------------- + * + * 31 11 10 8 7 6 5 4 3 2 1 0 + * +----------------+------+-----+---+---+-----+---+---+---+ + * | Page Address | Soft | Res | R | W | Res | L | M | P | + * +----------------+------+-----+---+---+-----+---+---+---+ + * + * + * Page Descriptor Cache Entry + * --------------------------- + * + * 31 24 23 16 15 0 + * +-----+------------------+------------------------------+ + * Low: | Acc | Res | Tag | + * +-----+------------------+------------------------------+ + * + * 31 11 10 7 6 5 4 3 2 1 0 + * +---------------------+-----+---+---+---+---+---+---+---+ + * High: | Address | Res | U | R | W | $ | L | M | G | + * +---------------------+-----+---+---+---+---+---+---+---+ + * + * "U" is only set in the left cache entry, and indicates + * which slot (left or right) was most recently updated. + * + ***********************************************************************/ + +#define MMUBASE 0x40000 +#define MMUSIZE 0x1000 + +#define MMU_SRS 0x04 /* Section RAM array size (words) */ +#define MMU_SDCS 0x20 /* Segment Descriptor Cache H/L array size + (words) */ +#define MMU_PDCS 0x20 /* Page Descriptor Cache H/L array size + (words) */ + +/* Register address offsets */ +#define MMU_SDCL 0 +#define MMU_SDCH 1 +#define MMU_PDCRL 2 +#define MMU_PDCRH 3 +#define MMU_PDCLL 4 +#define MMU_PDCLH 5 +#define MMU_SRAMA 6 +#define MMU_SRAMB 7 +#define MMU_FC 8 +#define MMU_FA 9 +#define MMU_CONF 10 +#define MMU_VAR 11 + +#define MMU_CONF_M (mmu_state.conf & 0x1) +#define MMU_CONF_R (mmu_state.conf & 0x2) + +/* Caching */ +#define NUM_SEC 4u /* Number of memory sections */ +#define NUM_SDCE 8 /* SD cache entries per section */ +#define NUM_PDCE 8 /* PD cache entries per section per side (l/r) */ +#define SET_SIZE 2 /* PDs are held in a 2-way associative set */ + +/* Cache Tag for SDs */ +#define SD_TAG(vaddr) ((vaddr >> 20) & 0x3ff) + +/* Cache Tag for PDs */ +#define PD_TAG(vaddr) (((vaddr >> 13) & 0xf) | ((vaddr >> 14) & 0xfff0)) + +/* Index of entry in the SD cache */ +#define SD_IDX(vaddr) ((vaddr >> 17) & 7) + +/* Index of entry in the PD cache */ +#define PD_IDX(vaddr) (((vaddr >> 11) & 3) | ((vaddr >> 15) & 4)) + +/* Shift and mask the flag bits for the current CPU mode */ +#define MMU_PERM(f) ((f >> ((3 - CPU_CM) * 2)) & 3) + +#define ROM_SIZE 0x10000 +#define BOOT_CODE_SIZE 0x8000 + +/* Codes set in the MMU Fault register */ +#define MMU_F_SDTLEN 0x03 +#define MMU_F_PW 0x04 +#define MMU_F_PDTLEN 0x05 +#define MMU_F_INV_SD 0x06 +#define MMU_F_SEG_NOT_PRES 0x07 +#define MMU_F_OTRAP 0x08 +#define MMU_F_PDT_NOT_PRES 0x09 +#define MMU_F_PAGE_NOT_PRES 0x0a +#define MMU_F_ACC 0x0d +#define MMU_F_SEG_OFFSET 0x0e + +/* Pluck out Virtual Address fields */ +#define SID(va) (((va) >> 30) & 3) +#define SSL(va) (((va) >> 17) & 0x1fff) +#define SOT(va) (va & 0x1ffff) +#define PSL(va) (((va) >> 11) & 0x3f) +#define POT(va) (va & 0x7ff) + +/* Get the maximum length of an SSL from SRAMB */ +#define SRAMB_LEN(va) (mmu_state.sec[SID(va)].len + 1) + +/* Pluck out Segment Descriptor fields */ +#define SD_PRESENT(sd0) ((sd0) & 1) +#define SD_MODIFIED(sd0) (((sd0) >> 1) & 1) +#define SD_CONTIG(sd0) (((sd0) >> 2) & 1) +#define SD_CACHE(sd0) (((sd0) >> 3) & 1) +#define SD_TRAP(sd0) (((sd0) >> 4) & 1) +#define SD_REF(sd0) (((sd0) >> 5) & 1) +#define SD_VALID(sd0) (((sd0) >> 6) & 1) +#define SD_INDIRECT(sd0) (((sd0) >> 7) & 1) +#define SD_SEG_ADDR(sd1) ((sd1) & 0xffffffe0) +#define SD_MAX_OFF(sd0) (((sd0) >> 10) & 0x3fff) +#define SD_ACC(sd0) (((sd0) >> 24) & 0xff) +#define SD_R_MASK 0x20 +#define SD_M_MASK 0x2 +#define SD_GOOD_MASK 0x1u +#define SDCE_TAG(sdcl) ((sdcl) & 0x3ff) + +#define SD_ADDR(va) (mmu_state.sec[SID(va)].addr + (SSL(va) * 8)) + + +/* Convert from sd to sd cache entry */ +#define SD_TO_SDCL(va,sd0) ((sd0 & 0xfffffc00)|SD_TAG(va)) +#define SD_TO_SDCH(sd0,sd1) (SD_SEG_ADDR(sd1)|(sd0 & 0x1e)|1) + +/* Note that this is a lossy transform. We will lose the state of the + I and R flags, as well as the software flags. We don't need them. + The V and P flags can be inferred as set. */ + +#define SDCE_TO_SD0(sdch,sdcl) ((sdcl & 0xfffffc00)|0x40|(sdch & 0x1e)|1) +#define SDCE_TO_SD1(sdch) (sdch & 0xffffffe0) + +/* Maximum size (in bytes) of a segment */ +#define MAX_OFFSET(sd0) ((SD_MAX_OFF(sd0) + 1) << 3) + +#define PD_PRESENT(pd) (pd & 1) +#define PD_MODIFIED(pd) ((pd >> 1) & 1) +#define PD_LAST(pd) ((pd >> 2) & 1) +#define PD_WFAULT(pd) ((pd >> 4) & 1) +#define PD_REF(pd) ((pd >> 5) & 1) +#define PD_ADDR(pd) (pd & 0xfffff800) /* Address portion of PD */ +#define PD_USED_MASK 0x40 +#define PD_R_MASK 0x20 +#define PD_M_MASK 0x2 +#define PD_GOOD_MASK 0x1u +#define PDCXL_TAG(pdcxl) (pdcxl & 0xffff) + +#define PD_LOC(sd1,va) SD_SEG_ADDR(sd1) + (PSL(va) * 4) + +/* Page Descriptor Cache Entry + * + */ + +/* Convert from pd to pd cache entry. Alwasy sets "Good" bit. */ +#define SD_TO_PDCXL(va,sd0) ((sd0 & 0xff000000)|PD_TAG(va)) +#define PD_TO_PDCXH(pd,sd0) ((pd & 0xfffff836)|(sd0 & 0x8)|1) + +/* Always set 'present' to true on conversion */ +#define PDCXH_TO_PD(pdch) ((pdch & 0xfffff836)|1) +#define PDCXL_TO_ACC(pdcl) (((pdcl & 0xff000000) >> 24) & 0xff) + +#define PDCLH_USED_MASK 0x40u + +/* Fault codes */ +#define MMU_FAULT(f) { \ + if (fc) { \ + mmu_state.fcode = ((((uint32)r_acc)<<7)|(((uint32)(CPU_CM))<<5)|f); \ + mmu_state.faddr = va; \ + } \ + } + +typedef struct _mmu_sec { + uint32 addr; + uint32 len; +} mmu_sec; + +typedef struct _mmu_state { + t_bool enabled; /* Global enabled/disabled flag */ + + uint32 sdcl[MMU_SDCS]; /* SDC low bits (0-31) */ + uint32 sdch[MMU_SDCS]; /* SDC high bits (32-63) */ + + uint32 pdcll[MMU_PDCS]; /* PDC low bits (left) (0-31) */ + uint32 pdclh[MMU_PDCS]; /* PDC high bits (left) (32-63) */ + + uint32 pdcrl[MMU_PDCS]; /* PDC low bits (right) (0-31) */ + uint32 pdcrh[MMU_PDCS]; /* PDC high bits (right) (32-63) */ + + uint32 sra[MMU_SRS]; /* Section RAM A */ + uint32 srb[MMU_SRS]; /* Section RAM B */ + + mmu_sec sec[MMU_SRS]; /* Section descriptors decoded from + Section RAM A and B */ + + uint32 fcode; /* Fault Code Register */ + uint32 faddr; /* Fault Address Register */ + uint32 conf; /* Configuration Register */ + uint32 var; /* Virtual Address Register */ + +} MMU_STATE; + +extern MMU_STATE mmu_state; + +extern volatile int32 stop_reason; +extern DEVICE mmu_dev; + +t_stat mmu_init(DEVICE *dptr); +uint32 mmu_read(uint32 pa, size_t size); +void mmu_write(uint32 pa, uint32 val, size_t size); + +/* Physical memory read/write */ +uint8 pread_b(uint32 pa); +uint16 pread_h(uint32 pa); +uint32 pread_w(uint32 pa); +uint32 pread_w_u(uint32 pa); +void pwrite_b(uint32 pa, uint8 val); +void pwrite_h(uint32 pa, uint16 val); +void pwrite_w(uint32 pa, uint32 val); + +/* Virtual memory translation */ +uint32 mmu_xlate_addr(uint32 va, uint8 r_acc); +t_stat mmu_decode_vaddr(uint32 vaddr, uint8 r_acc, + t_bool fc, uint32 *pa); + +#define SHOULD_CACHE_PD(pd) \ + (fc && PD_PRESENT(pd)) + +#define SHOULD_CACHE_SD(sd) \ + (fc && SD_VALID(sd) && SD_PRESENT(sd)) + +#define SHOULD_UPDATE_SD_R_BIT(sd) \ + (MMU_CONF_R && !((sd) & SD_R_MASK)) + +#define SHOULD_UPDATE_SD_M_BIT(sd) \ + (MMU_CONF_M && r_acc == ACC_W && !((sd) & SD_M_MASK)) + +#define SHOULD_UPDATE_PD_R_BIT(pd) \ + (!((pd) & PD_R_MASK)) + +#define SHOULD_UPDATE_PD_M_BIT(pd) \ + (r_acc == ACC_W && !((pd) & PD_M_MASK)) + +/* + * Find an SD in the cache. + */ +static SIM_INLINE t_stat get_sdce(uint32 va, uint32 *sd0, uint32 *sd1) +{ + uint32 tag, sdch, sdcl; + uint8 ci; + + ci = (SID(va) * NUM_SDCE) + SD_IDX(va); + tag = SD_TAG(va); + + sdch = mmu_state.sdch[ci]; + sdcl = mmu_state.sdcl[ci]; + + if ((sdch & SD_GOOD_MASK) && SDCE_TAG(sdcl) == tag) { + *sd0 = SDCE_TO_SD0(sdch, sdcl); + *sd1 = SDCE_TO_SD1(sdch); + return SCPE_OK; + } + + return SCPE_NXM; +} + +/* + * Find a PD in the cache. Sets both the PD and the cached access + * permissions. + */ +static SIM_INLINE t_stat get_pdce(uint32 va, uint32 *pd, uint8 *pd_acc) +{ + uint32 tag, pdcll, pdclh, pdcrl, pdcrh; + uint8 ci; + + ci = (SID(va) * NUM_PDCE) + PD_IDX(va); + tag = PD_TAG(va); + + /* Left side */ + pdcll = mmu_state.pdcll[ci]; + pdclh = mmu_state.pdclh[ci]; + + /* Right side */ + pdcrl = mmu_state.pdcrl[ci]; + pdcrh = mmu_state.pdcrh[ci]; + + /* Search L and R to find a good entry with a matching tag. */ + if ((pdclh & PD_GOOD_MASK) && PDCXL_TAG(pdcll) == tag) { + *pd = PDCXH_TO_PD(pdclh); + *pd_acc = PDCXL_TO_ACC(pdcll); + return SCPE_OK; + } else if ((pdcrh & PD_GOOD_MASK) && PDCXL_TAG(pdcrl) == tag) { + *pd = PDCXH_TO_PD(pdcrh); + *pd_acc = PDCXL_TO_ACC(pdcrl); + return SCPE_OK; + } + + return SCPE_NXM; +} + +static SIM_INLINE void put_sdce(uint32 va, uint32 sd0, uint32 sd1) +{ + uint32 tag; + uint8 ci; + + tag = SD_TAG(va); + ci = (SID(va) * NUM_SDCE) + SD_IDX(va); + + mmu_state.sdcl[ci] = SD_TO_SDCL(va, sd0); + mmu_state.sdch[ci] = SD_TO_SDCH(sd0, sd1); +} + + +static SIM_INLINE void put_pdce(uint32 va, uint32 sd0, uint32 pd) +{ + uint32 tag, pdclh, pdcrh; + uint8 ci; + + tag = PD_TAG(va); + ci = (SID(va) * NUM_PDCE) + PD_IDX(va); + + /* Left side contains the 'U' bit we care about */ + pdclh = mmu_state.pdclh[ci]; + + /* Right side */ + pdcrh = mmu_state.pdcrh[ci]; + + /* Pick the least-recently-replaced side */ + if (pdclh & PDCLH_USED_MASK) { /* Right side replaced more recently */ + /* Add to left side of cache without the U bit set */ + mmu_state.pdcll[ci] = SD_TO_PDCXL(va, sd0); + mmu_state.pdclh[ci] = PD_TO_PDCXH(pd, sd0); + mmu_state.pdcll[ci] &= ~PDCLH_USED_MASK; + } else { /* Left side replaced more recently */ + /* Add to right side of cache and set the U bit on the left side */ + mmu_state.pdcrl[ci] = SD_TO_PDCXL(va, sd0); + mmu_state.pdcrh[ci] = PD_TO_PDCXH(pd, sd0); + mmu_state.pdcll[ci] |= PDCLH_USED_MASK; + } +} + +static SIM_INLINE void flush_sdce(uint32 va) +{ + uint32 tag; + uint8 ci; + + ci = (SID(va) * NUM_SDCE) + SD_IDX(va); + tag = SD_TAG(va); + + if (mmu_state.sdch[ci] & SD_GOOD_MASK) { + mmu_state.sdch[ci] &= ~SD_GOOD_MASK; + } +} + +static SIM_INLINE void flush_pdce(uint32 va) +{ + uint32 tag, pdcll, pdclh, pdcrl, pdcrh; + uint8 ci; + + ci = (SID(va) * NUM_PDCE) + PD_IDX(va); + tag = PD_TAG(va); + + /* Left side */ + pdcll = mmu_state.pdcll[ci]; + pdclh = mmu_state.pdclh[ci]; + /* Right side */ + pdcrl = mmu_state.pdcrl[ci]; + pdcrh = mmu_state.pdcrh[ci]; + + /* Search L and R to find a good entry with a matching tag. */ + if ((pdclh & PD_GOOD_MASK) && PDCXL_TAG(pdcll) == tag) { + mmu_state.pdclh[ci] &= ~PD_GOOD_MASK; + } else if ((pdcrh & PD_GOOD_MASK) && PDCXL_TAG(pdcrl) == tag) { + mmu_state.pdcrh[ci] &= ~PD_GOOD_MASK; + } +} + +static SIM_INLINE void flush_cache_sec(uint8 sec) +{ + int i; + + for (i = 0; i < MMU_SDCS; i++) { + mmu_state.sdch[(sec * NUM_SDCE) + i] &= ~SD_GOOD_MASK; + } + for (i = 0; i < MMU_PDCS; i++) { + mmu_state.pdclh[(sec * NUM_PDCE) + i] |= PD_USED_MASK; + mmu_state.pdclh[(sec * NUM_PDCE) + i] &= ~PD_GOOD_MASK; + mmu_state.pdcrh[(sec * NUM_PDCE) + i] &= ~PD_GOOD_MASK; + } +} + +static SIM_INLINE void flush_caches() +{ + uint8 i; + + for (i = 0; i < NUM_SEC; i++) { + flush_cache_sec(i); + } +} + +static SIM_INLINE t_stat mmu_check_perm(uint8 flags, uint8 r_acc) +{ + switch(MMU_PERM(flags)) { + case 0: /* No Access */ + return SCPE_NXM; + case 1: /* Exec Only */ + if (r_acc != ACC_IF && r_acc != ACC_IFAD) { + return SCPE_NXM; + } + return SCPE_OK; + case 2: /* Read / Execute */ + if (r_acc != ACC_AF && r_acc != ACC_OF && + r_acc != ACC_IF && r_acc != ACC_IFAD && + r_acc != ACC_MT) { + return SCPE_NXM; + } + return SCPE_OK; + default: + return SCPE_OK; + } +} + +/* + * Update the M (modified) or R (referenced) bit the SD and cache + */ +static SIM_INLINE void mmu_update_sd(uint32 va, uint32 mask) +{ + uint32 sd0, tag; + uint8 ci; + + tag = SD_TAG(va); + ci = (SID(va) * NUM_SDCE) + SD_IDX(va); + + /* We go back to main memory to find the SD because the SD may + have been loaded from cache, which is lossy. */ + sd0 = pread_w(SD_ADDR(va)); + pwrite_w(SD_ADDR(va), sd0|mask); + + /* There is no 'R' bit in the SD cache, only an 'M' bit. */ + if (mask == SD_M_MASK) { + mmu_state.sdch[ci] |= mask; + } +} + +/* + * Update the M (modified) or R (referenced) bit the PD and cache + */ +static SIM_INLINE void mmu_update_pd(uint32 va, uint32 pd_addr, uint32 mask) +{ + uint32 pd, tag, pdcll, pdclh, pdcrl, pdcrh; + uint8 ci; + + tag = PD_TAG(va); + ci = (SID(va) * NUM_PDCE) + PD_IDX(va); + + /* We go back to main memory to find the PD because the PD may + have been loaded from cache, which is lossy. */ + pd = pread_w(pd_addr); + pwrite_w(pd_addr, pd|mask); + + /* Update in the cache */ + + /* Left side */ + pdcll = mmu_state.pdcll[ci]; + pdclh = mmu_state.pdclh[ci]; + + /* Right side */ + pdcrl = mmu_state.pdcrl[ci]; + pdcrh = mmu_state.pdcrh[ci]; + + /* Search L and R to find a good entry with a matching tag, then + update the appropriate bit */ + if ((pdclh & PD_GOOD_MASK) && PDCXL_TAG(pdcll) == tag) { + mmu_state.pdclh[ci] |= mask; + } else if ((pdcrh & PD_GOOD_MASK) && PDCXL_TAG(pdcrl) == tag) { + mmu_state.pdcrh[ci] |= mask; + } +} + +/* Special functions for reading operands and examining memory + safely */ +t_stat read_operand(uint32 va, uint8 *val); +t_stat examine(uint32 va, uint8 *val); +t_stat deposit(uint32 va, uint8 val); + +/* Dispatch to the MMU when enabled, or to physical RW when + disabled */ +uint8 read_b(uint32 va, uint8 r_acc); +uint16 read_h(uint32 va, uint8 r_acc); +uint32 read_w(uint32 va, uint8 r_acc); +void write_b(uint32 va, uint8 val); +void write_h(uint32 va, uint16 val); +void write_w(uint32 va, uint32 val); + +t_bool addr_is_rom(uint32 pa); +t_bool addr_is_mem(uint32 pa); +t_bool addr_is_io(uint32 pa); + +#endif diff --git a/3B2/3b2_sys.c b/3B2/3b2_sys.c new file mode 100644 index 00000000..986ea394 --- /dev/null +++ b/3B2/3b2_sys.c @@ -0,0 +1,180 @@ +/* 3b2_defs.h: AT&T 3B2 Model 400 system-specific logic implementation + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#include "3b2_sys.h" + +#include "3b2_cpu.h" +#include "3b2_iu.h" +#include "3b2_if.h" +#include "3b2_id.h" +#include "3b2_mmu.h" +#include "3b2_sysdev.h" + +char sim_name[] = "AT&T 3B2 Model 400"; + +REG *sim_PC = &cpu_reg[0]; + +/* All opcodes are 1 or 2 bytes. Operands may be up to 6 bytes, and + there may be up to 3 operands, for a maximum of 20 bytes */ +int32 sim_emax = 20; + +extern instr cpu_instr; + +DEVICE *sim_devices[] = { + &cpu_dev, + &mmu_dev, + &timer_dev, + &tod_dev, + &nvram_dev, + &csr_dev, + &iu_dev, + &dmac_dev, + &if_dev, + &id_dev, + NULL +}; + +const char *sim_stop_messages[] = { + "Unknown error", + "Reserved Instruction", + "Breakpoint", + "Invalid Opcode", + "IRQ", + "Exception/Trap", + "Exception Stack Too Deep", + "Unimplemented MMU Feature" +}; + +t_stat sim_load(FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) +{ + int32 i; + uint32 addr = 0; + int32 cnt = 0; + + if ((*cptr != 0) || (flag != 0)) { + return SCPE_ARG; + } + + addr = R[NUM_PC]; + + while ((i = getc (fileref)) != EOF) { + pwrite_b(addr, (uint8)i); + addr++; + cnt++; + } + + printf ("%d Bytes loaded.\n", cnt); + + return SCPE_OK; +} + +t_stat parse_sym(CONST char *cptr, t_addr exta, UNIT *uptr, t_value *val, int32 sw) +{ + DEVICE *dptr; + t_stat r; + int32 k, num, vp; + int32 len = 4; + + if (sw & (int32) SWMASK ('B')) { + len = 1; + } else if (sw & (int32) SWMASK ('H')) { + len = 2; + } else if (sw & (int32) SWMASK ('W')) { + len = 4; + } + + // Parse cptr + num = (int32) get_uint(cptr, 16, WORD_MASK, &r); + + if (r != SCPE_OK) { + return r; + } + + if (uptr == NULL) { + uptr = &cpu_unit; + } + + dptr = find_dev_from_unit(uptr); + + if (dptr == NULL) { + return SCPE_IERR; + } + + vp = 0; + for (k = len - 1; k >= 0; k--) { + val[vp++] = (num >> (k * 8)) & 0xff; + } + + return -(vp - 1); +} + +t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) +{ + uint32 len = 4; + int32 k, vp, num; + unsigned int c; + + num = 0; + vp = 0; + + if (sw & (int32) SWMASK ('B')) { + len = 1; + } else if (sw & (int32) SWMASK ('H')) { + len = 2; + } else if (sw & (int32) SWMASK ('W')) { + len = 4; + } + + if (sw & (int32) SWMASK('M')) { + fprint_sym_m(of, &cpu_instr); + return SCPE_OK; + } + + if (sw & (int32) SWMASK('C')) { + len = 16; + for (k = (int32) len - 1; k >= 0; k--) { + c = (unsigned int)val[vp++]; + if (c >= 0x20 && c < 0x7f) { + fprintf(of, "%c", c); + } else { + fprintf(of, "."); + } + } + return -(vp - 1); + } + + for (k = len - 1; k >= 0; k--) { + num = num | (((int32) val[vp++]) << (k * 8)); + } + + fprint_val(of, (uint32) num, 16, len * 8, PV_RZRO); + + return -(vp - 1); +} diff --git a/3B2/3b2_sys.h b/3B2/3b2_sys.h new file mode 100644 index 00000000..7407e08d --- /dev/null +++ b/3B2/3b2_sys.h @@ -0,0 +1,47 @@ +/* 3b2_sys.h: AT&T 3B2 Model 400 system-specific logic headers + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#ifndef _3B2_SYS_H +#define _3B2_SYS_H + +#include "3b2_defs.h" + +extern uint32 R[16]; +extern char sim_name[]; +extern REG *sim_PC; +extern int32 sim_emax; +extern DEVICE *sim_devices[]; + +t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag); +t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, + int32 sw); +t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw); + +#endif diff --git a/3B2/3b2_sysdev.c b/3B2/3b2_sysdev.c new file mode 100644 index 00000000..d828ab31 --- /dev/null +++ b/3B2/3b2_sysdev.c @@ -0,0 +1,711 @@ +/* 3b2_cpu.h: AT&T 3B2 Model 400 System Devices implementation + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +/* + This file contains system-specific registers and devices for the + following 3B2 devices: + + - timer 8253 interval timer + - nvram Non-Volatile RAM + - csr Control Status Registers + - tod MM58174A Real-Time-Clock +*/ + +#include "3b2_sysdev.h" +#include "3b2_iu.h" + +DEBTAB sys_deb_tab[] = { + { "INIT", INIT_MSG, "Init" }, + { "READ", READ_MSG, "Read activity" }, + { "WRITE", WRITE_MSG, "Write activity" }, + { "EXECUTE", EXECUTE_MSG, "Execute activity" }, + { "IRQ", IRQ_MSG, "Interrupt activity"}, + { "TRACE", TRACE_MSG, "Detailed activity" }, + { NULL, 0 } +}; + +uint32 *NVRAM = NULL; + +extern DEVICE cpu_dev; + +/* CSR */ + +uint16 csr_data; + +BITFIELD csr_bits[] = { + BIT(IOF), + BIT(DMA), + BIT(DISK), + BIT(UART), + BIT(PIR9), + BIT(PIR8), + BIT(CLK), + BIT(IFLT), + BIT(ITIM), + BIT(FLOP), + BIT(NA), + BIT(LED), + BIT(ALGN), + BIT(RRST), + BIT(PARE), + BIT(TIMO), + ENDBITS +}; + +UNIT csr_unit = { + UDATA(&csr_svc, UNIT_FIX, CSRSIZE) +}; + +REG csr_reg[] = { + { HRDATADF(DATA, csr_data, 16, "CSR Data", csr_bits) } +}; + +DEVICE csr_dev = { + "CSR", &csr_unit, csr_reg, NULL, + 1, 16, 8, 4, 16, 32, + &csr_ex, &csr_dep, &csr_reset, + NULL, NULL, NULL, NULL, + DEV_DEBUG, 0, sys_deb_tab +}; + +t_stat csr_ex(t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) +{ + return SCPE_OK; +} + +t_stat csr_dep(t_value val, t_addr exta, UNIT *uptr, int32 sw) +{ + return SCPE_OK; +} + +t_stat csr_reset(DEVICE *dptr) +{ + csr_data = 0; + return SCPE_OK; +} + +uint32 csr_read(uint32 pa, size_t size) +{ + uint32 reg = pa - CSRBASE; + + sim_debug(READ_MSG, &csr_dev, + "[%08x] CSR=%04x\n", + R[NUM_PC], csr_data); + + switch (reg) { + case 0x2: + if (size == 8) { + return (csr_data >> 8) & 0xff; + } else { + return csr_data; + } + case 0x3: + return csr_data & 0xff; + default: + return 0; + } +} + +/* TODO: Remove once we confirm we don't need it */ +t_stat csr_svc(UNIT *uptr) +{ + return SCPE_OK; +} + +void csr_write(uint32 pa, uint32 val, size_t size) +{ + uint32 reg = pa - CSRBASE; + + switch (reg) { + case 0x03: /* Clear Bus Timeout Error */ + csr_data &= ~CSRTIMO; + break; + case 0x07: /* Clear Memory Parity Error */ + csr_data &= ~CSRPARE; + break; + case 0x0b: /* Set System Reset Request */ + iu_reset(&iu_dev); + cpu_reset(&cpu_dev); + cpu_boot(0, &cpu_dev); + break; + case 0x0f: /* Clear Memory Alignment Fault */ + csr_data &= ~CSRALGN; + break; + case 0x13: /* Set Failure LED */ + csr_data |= CSRLED; + break; + case 0x17: /* Clear Failure LED */ + csr_data &= ~CSRLED; + break; + case 0x1b: /* Set Floppy Motor On */ + csr_data |= CSRFLOP; + break; + case 0x1f: /* Clear Floppy Motor On */ + csr_data &= ~CSRFLOP; + break; + case 0x23: /* Set Inhibit Timers */ + csr_data |= CSRITIM; + break; + case 0x27: /* Clear Inhibit Timers */ + csr_data &= ~CSRITIM; + break; + case 0x2b: /* Set Inhibit Faults */ + csr_data |= CSRIFLT; + break; + case 0x2f: /* Clear Inhibit Faults */ + csr_data &= ~CSRIFLT; + break; + case 0x33: /* Set PIR9 */ + csr_data |= CSRPIR9; + break; + case 0x37: /* Clear PIR9 */ + csr_data &= ~CSRPIR9; + break; + case 0x3b: /* Set PIR8 */ + csr_data |= CSRPIR8; + break; + case 0x3f: /* Clear PIR8 */ + csr_data &= ~CSRPIR8; + break; + default: + break; + } +} + +/* NVRAM */ + +UNIT nvram_unit = { + UDATA(NULL, UNIT_FIX+UNIT_BINK, NVRAMSIZE) +}; + +REG nvram_reg[] = { + { NULL } +}; + +DEVICE nvram_dev = { + "NVRAM", &nvram_unit, nvram_reg, NULL, + 1, 16, 8, 4, 16, 32, + &nvram_ex, &nvram_dep, &nvram_reset, + NULL, &nvram_attach, &nvram_detach, + NULL, DEV_DEBUG, 0, sys_deb_tab, NULL, NULL, + NULL, NULL, NULL, + &nvram_description +}; + +t_stat nvram_ex(t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) +{ + uint32 addr = (uint32) exta; + + if ((vptr == NULL) || (addr & 03)) { + return SCPE_ARG; + } + + if (addr >= NVRAMSIZE) { + return SCPE_NXM; + } + + *vptr = NVRAM[addr >> 2]; + + return SCPE_OK; +} + +t_stat nvram_dep(t_value val, t_addr exta, UNIT *uptr, int32 sw) +{ + uint32 addr = (uint32) exta; + + if (addr & 03) { + return SCPE_ARG; + } + + if (addr >= NVRAMSIZE) { + return SCPE_NXM; + } + + NVRAM[addr >> 2] = (uint32) val; + + return SCPE_OK; +} + +t_stat nvram_reset(DEVICE *dptr) +{ + if (NVRAM == NULL) { + NVRAM = (uint32 *)calloc(NVRAMSIZE >> 2, sizeof(uint32)); + memset(NVRAM, 0, sizeof(uint32) * NVRAMSIZE >> 2); + nvram_unit.filebuf = NVRAM; + } + + if (NVRAM == NULL) { + return SCPE_MEM; + } + + return SCPE_OK; +} + +const char *nvram_description(DEVICE *dptr) +{ + return "Non-volatile memory"; +} + +t_stat nvram_attach(UNIT *uptr, CONST char *cptr) +{ + t_stat r; + + /* If we've been asked to attach, make sure the ATTABLE + and BUFABLE flags are set on the unit */ + uptr->flags = uptr->flags | (UNIT_ATTABLE | UNIT_BUFABLE); + + r = attach_unit(uptr, cptr); + + if (r != SCPE_OK) { + /* Unset the ATTABLE and BUFABLE flags if we failed. */ + uptr->flags = uptr->flags & (uint32) ~(UNIT_ATTABLE | UNIT_BUFABLE); + } else { + uptr->hwmark = (uint32) uptr->capac; + } + + return r; +} + +t_stat nvram_detach(UNIT *uptr) +{ + t_stat r; + + r = detach_unit(uptr); + + if ((uptr->flags & UNIT_ATT) == 0) { + uptr->flags = uptr->flags & (uint32) ~(UNIT_ATTABLE | UNIT_BUFABLE); + } + + return r; +} + + +uint32 nvram_read(uint32 pa, size_t size) +{ + uint32 offset = pa - NVRAMBASE; + uint32 data; + uint32 sc = (~(offset & 3) << 3) & 0x1f; + + switch(size) { + case 8: + data = (NVRAM[offset >> 2] >> sc) & BYTE_MASK; + break; + case 16: + if (offset & 2) { + data = NVRAM[offset >> 2] & HALF_MASK; + } else { + data = (NVRAM[offset >> 2] >> 16) & HALF_MASK; + } + break; + case 32: + data = NVRAM[offset >> 2]; + break; + } + + return data; +} + +void nvram_write(uint32 pa, uint32 val, size_t size) +{ + uint32 offset = pa - NVRAMBASE; + uint32 index = offset >> 2; + uint32 sc, mask; + + switch(size) { + case 8: + sc = (~(pa & 3) << 3) & 0x1f; + mask = (uint32) (0xff << sc); + NVRAM[index] = (NVRAM[index] & ~mask) | (val << sc); + break; + case 16: + if (offset & 2) { + NVRAM[index] = (NVRAM[index] & ~HALF_MASK) | val; + } else { + NVRAM[index] = (NVRAM[index] & HALF_MASK) | (val << 16); + } + break; + case 32: + NVRAM[index] = val; + break; + } +} + +/* + * 8253 Timer. + * + * The 8253 Timer IC has three interval timers, which we treat here as + * three units. + * + * Note that this simulation is very specific to the 3B2, and not + * usable as a general purpose 8253 simulator. + * + */ + +struct timer_ctr TIMERS[3]; + +/* + * The three timers, (A, B, C) run at different + * programmatially controlled frequencies, so each must be + * handled through a different service routine. + */ + +UNIT timer_unit[] = { + { UDATA(&timer0_svc, 0, 0) }, + { UDATA(&timer1_svc, UNIT_IDLE, 0) }, + { UDATA(&timer2_svc, 0, 0) }, + { NULL } +}; + +REG timer_reg[] = { + { HRDATAD(DIVA, TIMERS[0].divider, 16, "Divider A") }, + { HRDATAD(STA, TIMERS[0].mode, 16, "Mode A") }, + { HRDATAD(DIVB, TIMERS[1].divider, 16, "Divider B") }, + { HRDATAD(STB, TIMERS[1].mode, 16, "Mode B") }, + { HRDATAD(DIVC, TIMERS[2].divider, 16, "Divider C") }, + { HRDATAD(STC, TIMERS[2].mode, 16, "Mode C") }, + { NULL } +}; + +DEVICE timer_dev = { + "TIMER", timer_unit, timer_reg, NULL, + 1, 16, 8, 4, 16, 32, + NULL, NULL, &timer_reset, + NULL, NULL, NULL, NULL, + DEV_DEBUG, 0, sys_deb_tab +}; + +#define TIMER_STP_US 10 /* 10 us delay per timer step */ + +#define tmrnum u3 +#define tmr up7 +#define DECR_STEPS 400 + +/* + * This is a hack to make diagnostics pass. If read immediately after + * being set, a counter should always return the initial value. If a + * certain number of steps have passed, it should have decremented a + * little bit, so we return a value one less than the initial value. + * This is not 100% accurate, but it makes SVR3 and DGMON tests happy. + */ +static SIM_INLINE uint16 timer_current_val(struct timer_ctr *ctr) +{ + if ((sim_gtime() - ctr->stime) > DECR_STEPS) { + return ctr->divider - 1; + } else { + return ctr->divider; + } +} + +t_stat timer_reset(DEVICE *dptr) { + int32 i, t; + + memset(&TIMERS, 0, sizeof(struct timer_ctr) * 3); + + for (i = 0; i < 3; i++) { + timer_unit[i].tmrnum = i; + timer_unit[i].tmr = &TIMERS[i]; + } + + /* Timer 1 gate is always active */ + TIMERS[1].gate = 1; + + if (!sim_is_running) { + t = sim_rtcn_init_unit(&timer_unit[1], TPS_CLK, TMR_CLK); + sim_activate_after(&timer_unit[1], 1000000 / t); + } + + return SCPE_OK; +} + +t_stat timer0_svc(UNIT *uptr) +{ + struct timer_ctr *ctr; + int32 time; + + ctr = (struct timer_ctr *)uptr->tmr; + + time = ctr->divider * TIMER_STP_US; + + if (time == 0) { + time = TIMER_STP_US; + } + + sim_activate_abs(uptr, (int32) DELAY_US(time)); + + return SCPE_OK; +} + +t_stat timer1_svc(UNIT *uptr) +{ + struct timer_ctr *ctr; + int32 t, ticks; + + ctr = (struct timer_ctr *)uptr->tmr; + + if (ctr->enabled && !(csr_data & CSRITIM)) { + /* Fire the IPL 15 clock interrupt */ + csr_data |= CSRCLK; + } + + ticks = ctr->divider / TIMER_STP_US; + if (ticks == 0) { + ticks = TPS_CLK; + } + t = sim_rtcn_calb(ticks, TMR_CLK); + sim_activate_after(uptr, (uint32) (1000000 / ticks)); + + return SCPE_OK; +} + +t_stat timer2_svc(UNIT *uptr) +{ + struct timer_ctr *ctr; + int32 time; + + ctr = (struct timer_ctr *)uptr->tmr; + + time = ctr->divider * TIMER_STP_US; + + if (time == 0) { + time = TIMER_STP_US; + } + + sim_activate_abs(uptr, (int32) DELAY_US(time)); + + return SCPE_OK; +} + +uint32 timer_read(uint32 pa, size_t size) +{ + uint32 reg; + uint16 ctr_val; + uint8 ctrnum; + struct timer_ctr *ctr; + + reg = pa - TIMERBASE; + ctrnum = (reg >> 2) & 0x3; + ctr = &TIMERS[ctrnum]; + + switch (reg) { + case TIMER_REG_DIVA: + case TIMER_REG_DIVB: + case TIMER_REG_DIVC: + if (ctr->enabled && ctr->gate) { + ctr_val = timer_current_val(ctr); + } else { + ctr_val = ctr->divider; + } + + switch (ctr->mode & CLK_RW) { + case CLK_LSB: + return ctr_val & 0xff; + case CLK_MSB: + return (ctr_val & 0xff00) >> 8; + case CLK_LMB: + if (ctr->lmb) { + ctr->lmb = FALSE; + return (ctr_val & 0xff00) >> 8; + } else { + ctr->lmb = TRUE; + return ctr_val & 0xff; + } + default: + return 0; + } + break; + case TIMER_REG_CTRL: + return ctr->mode; + case TIMER_CLR_LATCH: + /* Clearing the timer latch has a side-effect + of also clearing pending interrupts */ + csr_data &= ~CSRCLK; + return 0; + default: + /* Unhandled */ + sim_debug(READ_MSG, &timer_dev, + "[%08x] UNHANDLED TIMER READ. ADDR=%08x\n", + R[NUM_PC], pa); + return 0; + } +} + +void handle_timer_write(uint8 ctrnum, uint32 val) +{ + struct timer_ctr *ctr; + + ctr = &TIMERS[ctrnum]; + switch(ctr->mode & 0x30) { + case 0x10: + ctr->divider &= 0xff00; + ctr->divider |= val & 0xff; + ctr->enabled = TRUE; + ctr->stime = sim_gtime(); + break; + case 0x20: + ctr->divider &= 0x00ff; + ctr->divider |= (val & 0xff) << 8; + ctr->enabled = TRUE; + ctr->stime = sim_gtime(); + break; + case 0x30: + if (ctr->lmb) { + ctr->lmb = FALSE; + ctr->divider = (uint16) ((ctr->divider & 0x00ff) | ((val & 0xff) << 8)); + ctr->enabled = TRUE; + ctr->stime = sim_gtime(); + } else { + ctr->lmb = TRUE; + ctr->divider = (ctr->divider & 0xff00) | (val & 0xff); + } + break; + default: + break; + + } +} + +void timer_write(uint32 pa, uint32 val, size_t size) +{ + uint8 reg, ctrnum; + struct timer_ctr *ctr; + + reg = (uint8) (pa - TIMERBASE); + + switch(reg) { + case TIMER_REG_DIVA: + handle_timer_write(0, val); + break; + case TIMER_REG_DIVB: + handle_timer_write(1, val); + break; + case TIMER_REG_DIVC: + handle_timer_write(2, val); + break; + case TIMER_REG_CTRL: + /* The counter number is in bits 6 and 7 */ + ctrnum = (val >> 6) & 3; + if (ctrnum > 2) { + sim_debug(WRITE_MSG, &timer_dev, + "[%08x] WARNING: Write to invalid counter: %d\n", + R[NUM_PC], ctrnum); + return; + } + ctr = &TIMERS[ctrnum]; + ctr->mode = (uint8) val; + ctr->enabled = FALSE; + ctr->lmb = FALSE; + break; + case TIMER_CLR_LATCH: + sim_debug(WRITE_MSG, &timer_dev, + "[%08x] unexpected write to clear timer latch\n", + R[NUM_PC]); + break; + } +} + +/* + * MM58174A Real-Time-Clock + */ + +UNIT tod_unit = { UDATA(&tod_svc, UNIT_IDLE+UNIT_FIX, 0) }; + +uint32 tod_reg = 0; + +DEVICE tod_dev = { + "TOD", &tod_unit, NULL, NULL, + 1, 16, 8, 4, 16, 32, + NULL, NULL, &tod_reset, + NULL, NULL, NULL, NULL, + DEV_DEBUG, 0, sys_deb_tab +}; + +t_stat tod_reset(DEVICE *dptr) +{ + int32 t; + + if (!sim_is_running) { + t = sim_rtcn_init_unit(&tod_unit, TPS_TOD, TMR_TOD); + sim_activate_after(&tod_unit, 1000000 / TPS_TOD); + } + + return SCPE_OK; +} + +t_stat tod_svc(UNIT *uptr) +{ + int32 t; + + t = sim_rtcn_calb(TPS_TOD, TMR_TOD); + sim_activate_after(&tod_unit, 1000000 / TPS_TOD); + + tod_reg++; + return SCPE_OK; +} + +uint32 tod_read(uint32 pa, size_t size) +{ + uint32 reg; + + reg = pa - TODBASE; + + sim_debug(READ_MSG, &tod_dev, + "[%08x] READ TOD: reg=%02x\n", + R[NUM_PC], reg); + + switch(reg) { + case 0x04: /* 1/10 Sec */ + case 0x08: /* 1 Sec */ + case 0x0c: /* 10 Sec */ + case 0x10: /* 1 Min */ + case 0x14: /* 10 Min */ + case 0x18: /* 1 Hour */ + case 0x1c: /* 10 Hour */ + case 0x20: /* 1 Day */ + case 0x24: /* 10 Day */ + case 0x28: /* Day of Week */ + case 0x2c: /* 1 Month */ + case 0x30: /* 10 Month */ + default: + break; + } + + return 0; +} + +void tod_write(uint32 pa, uint32 val, size_t size) +{ + uint32 reg; + + reg = pa - TODBASE; + + sim_debug(WRITE_MSG, &tod_dev, + "[%08x] WRITE TOD: reg=%02x val=%d\n", + R[NUM_PC], reg, val); +} diff --git a/3B2/3b2_sysdev.h b/3B2/3b2_sysdev.h new file mode 100644 index 00000000..10430554 --- /dev/null +++ b/3B2/3b2_sysdev.h @@ -0,0 +1,84 @@ +/* 3b2_cpu.h: AT&T 3B2 Model 400 System Devices (Header) + + Copyright (c) 2017, Seth J. Morabito + + 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 THE AUTHORS OR COPYRIGHT HOLDERS + 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 the author shall + not be used in advertising or otherwise to promote the sale, use or + other dealings in this Software without prior written authorization + from the author. +*/ + +#ifndef _3B2_SYSDEV_H_ +#define _3B2_SYSDEV_H_ + +#include "3b2_defs.h" +#include "3b2_sys.h" +#include "3b2_cpu.h" + +extern DEVICE nvram_dev; +extern DEVICE timer_dev; +extern DEVICE csr_dev; +extern DEVICE tod_dev; +extern DEBTAB sys_deb_tab[]; + +struct timer_ctr { + uint16 divider; + uint8 mode; + t_bool lmb; + t_bool enabled; + t_bool gate; + double stime; /* Most recent start time of counter */ +}; + +/* NVRAM */ +t_stat nvram_ex(t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); +t_stat nvram_dep(t_value val, t_addr exta, UNIT *uptr, int32 sw); +t_stat nvram_reset(DEVICE *dptr); +uint32 nvram_read(uint32 pa, size_t size); +t_stat nvram_attach(UNIT *uptr, CONST char *cptr); +t_stat nvram_detach(UNIT *uptr); +const char *nvram_description(DEVICE *dptr); +void nvram_write(uint32 pa, uint32 val, size_t size); + +/* 8253 Timer */ +t_stat timer_reset(DEVICE *dptr); +uint32 timer_read(uint32 pa, size_t size); +void timer_write(uint32 pa, uint32 val, size_t size); +t_stat timer0_svc(UNIT *uptr); +t_stat timer1_svc(UNIT *uptr); +t_stat timer2_svc(UNIT *uptr); + +/* CSR */ +t_stat csr_svc(UNIT *uptr); +t_stat csr_ex(t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); +t_stat csr_dep(t_value val, t_addr exta, UNIT *uptr, int32 sw); +t_stat csr_reset(DEVICE *dptr); +uint32 csr_read(uint32 pa, size_t size); +void csr_write(uint32 pa, uint32 val, size_t size); + +/* TOD */ +t_stat tod_svc(UNIT *uptr); +t_stat tod_reset(DEVICE *dptr); +uint32 tod_read(uint32 pa, size_t size); +void tod_write(uint32, uint32 val, size_t size); +#endif diff --git a/3B2/README.md b/3B2/README.md new file mode 100644 index 00000000..03022bff --- /dev/null +++ b/3B2/README.md @@ -0,0 +1,112 @@ +AT&T 3B2 Simulator +================== + +This module contains a simulator for the AT&T 3B2 Model 400 microcomputer. + +*CAUTION*: The simulator is under active and heavy development. It is +usable today, but please consider this emulator to be a beta. + +Devices +------- + +The following devices are simulated. The SIMH names for the simulated +devices are given in parentheses: + + - 3B2 Model 400 System Board with 1MB, 2MB, or 4MB RAM (CSR, NVRAM) + - WE32100 CPU (CPU) + - WE32101 MMU (MMU) + - PD8253 Interval Timer (TIMER) + - AM9517 DMA controller (DMAC) + - SCN2681A Integrated DUART (IU) + - TMS2793 Integrated Floppy Controller (IF) + - uPD7261A Integrated MFM Fixed Disk Controller (ID) + +Usage +----- + +To boot the 3B2 simulator into firmware mode, simply type: + + sim> BOOT CPU + +You will be greeted with the message: + + FW ERROR 1-01: NVRAM SANITY FAILURE + DEFAULT VALUES ASSUMED + IF REPEATED, CHECK THE BATTERY + + FW ERROR 1-02: DISK SANITY FAILURE + EXECUTION HALTED + + SYSTEM FAILURE: CONSULT YOUR SYSTEM ADMINISTRATION UTILITIES GUIDE + +NVRAM can be saved between boots by attaching it to a file. + + sim> ATTACH NVRAM + +On subsequent boots, you will instead see the message + + SELF-CHECK + + + FW ERROR 1-02: DISK SANITY FAILURE + EXECUTION HALTED + + SYSTEM FAILURE: CONSULT YOUR SYSTEM ADMINISTRATION UTILITIES GUIDE + + +Once you see the `SYSTEM FAILURE` message, this is actually an +invisible prompt. To access firmware mode, type the default 3B2 +firmware password `mcp`, then press Enter or carriage return. + +You should then be prompted with: + + Enter name of program to execute [ ]: + +Here, you may type a question mark (?) and press Enter to see a list +of available firmware programs. + +Booting UNIX SVR3 +----------------- + +UNIX SVR3 for the 3B2 partially boots. To boot UNIX, attach the first +disk image from the 3B2 "Essential Utilities" distribution. + + sim> ATTACH IF + sim> BOOT CPU + +Once you reach the `SYSTEM FAILURE` message, type `mcp` to enter +firmware mode. When prompted for the name of a program to boot, enter +`unix`, and confirm the boot device is `FD5` by pressing Enter or +carriage return. + + Enter name of program to execute [ ]: unix + Possible load devices are: + + Option Number Slot Name + --------------------------------------- + 0 0 FD5 + + Enter Load Device Option Number [0 (FD5)]: + +Installing SVR3 +--------------- + +To install SVR3 to the first hard disk, first, attach a new image + + sim> ATTACH ID0 + +Then, boot the file `idtools` from the "3B2 Maintenance Utilities - +Issue 4.0" floppy diskette. + +From `idtools`, select the `formhard` option and low-level format +integrated disk 0. Parameters are: + + Drive Id: 5 + Number cylinders: 925 + Number tracks/cyl: 9 + Number sectors/track: 18 + Number bytes/sector: 512 + +After low-level formatting integrated disk 0, boot the file `unix` +from the first diskette of the 3B2 "Essential Utilities" distribution, +and follow the prompts. diff --git a/3B2/rom_400.bin b/3B2/rom_400.bin new file mode 100644 index 00000000..6ebc5390 Binary files /dev/null and b/3B2/rom_400.bin differ diff --git a/3B2/rom_400_bin.h b/3B2/rom_400_bin.h new file mode 100644 index 00000000..328293ec --- /dev/null +++ b/3B2/rom_400_bin.h @@ -0,0 +1,2061 @@ +#ifndef _ROM_400_bin_H +#define _ROM_400_bin_H +/* + 3B2/rom_400_bin.h produced at Sat Feb 27 20:44:17 2016 + from 3B2/rom_400.bin which was last modified at Sat Feb 27 20:41:02 2016 + file size: 32768 (0x8000) - checksum: 0xFFD55762 + This file is a generated file and should NOT be edited or changed by hand. +*/ +#define BOOT_CODE_SIZE 0x8000 +#define BOOT_CODE_FILENAME "rom_400.bin" +#define BOOT_CODE_ARRAY rom_400_bin +unsigned char rom_400_bin[] = { +0x00,0x00,0x05,0x48,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0x00,0x00,0x05,0xD8,0x02,0x00,0x0B,0x78,0x02,0x00,0x0B,0x78,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0C,0x18, +0x02,0x00,0x0C,0x68,0x02,0x00,0x0C,0xB8,0x02,0x00,0x0D,0x08,0x02,0x00,0x0D,0x58, +0x02,0x00,0x0D,0xA8,0x02,0x00,0x0D,0xA8,0x02,0x00,0x0E,0x48,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8, +0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x0B,0xC8,0x02,0x00,0x08,0x64, +0x02,0x00,0x15,0x14,0x02,0x00,0x11,0xF8,0x02,0x00,0x11,0xF4,0x02,0x00,0x08,0x58, +0x02,0x00,0x12,0x00,0x02,0x00,0x12,0xA8,0x02,0x00,0x12,0x6C,0x00,0x00,0x4D,0xD4, +0x00,0x00,0x44,0xE4,0x00,0x00,0x43,0x60,0x00,0x00,0x4A,0xE4,0x00,0x00,0x7F,0x68, +0x00,0x00,0x2A,0xF8,0x02,0x00,0x12,0x68,0x00,0x00,0x44,0x84,0x00,0x00,0x53,0x20, +0x00,0x00,0x52,0x24,0x00,0x00,0x52,0xA0,0x00,0x00,0x76,0x98,0x00,0x00,0x7B,0x2C, +0x02,0x00,0x11,0xF0,0x02,0x00,0x11,0xEC,0x02,0x00,0x15,0x04,0x00,0x00,0x11,0x68, +0x02,0x00,0x0A,0x80,0x02,0x00,0x12,0x58,0x02,0x00,0x12,0x5C,0x02,0x00,0x11,0xE8, +0x00,0x00,0x3D,0x74,0x02,0x00,0x12,0x64,0x00,0x00,0x7F,0xF0,0x02,0x00,0x12,0xD8, +0x02,0x00,0x12,0xD0,0x02,0x00,0x08,0x6C,0x00,0x00,0x54,0x38,0x00,0x00,0x54,0x50, +0x00,0x00,0x54,0xA1,0x00,0x00,0x4E,0x14,0x00,0x00,0x55,0x04,0x02,0x00,0x12,0xDC, +0x02,0x00,0x12,0xE0,0x02,0x00,0x12,0xE4,0x00,0x00,0x55,0xEC,0x00,0x00,0x5B,0xAA, +0x00,0x00,0x51,0xD2,0x02,0x00,0x0A,0x74,0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F, +0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x59,0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F, +0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F,0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F, +0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F,0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F, +0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F,0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F, +0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F,0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F, +0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F,0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F, +0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F,0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x59, +0x00,0x81,0xE1,0x00,0x00,0x00,0x42,0x1F,0x2F,0x66,0x69,0x6C,0x6C,0x65,0x64,0x74, +0x00,0x46,0x44,0x35,0x00,0x00,0x00,0x00,0x00,0x81,0xE1,0x80,0x00,0x00,0x12,0x74, +0x02,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x02,0x00,0x00,0x08,0x02,0x00,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x42,0x44,0x00,0x0A,0x45,0x6E,0x74, +0x65,0x72,0x20,0x6E,0x61,0x6D,0x65,0x20,0x6F,0x66,0x20,0x70,0x72,0x6F,0x67,0x72, +0x61,0x6D,0x20,0x74,0x6F,0x20,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x20,0x5B,0x20, +0x25,0x73,0x20,0x5D,0x3A,0x20,0x00,0x0A,0x00,0x70,0x61,0x73,0x73,0x77,0x64,0x00, +0x0A,0x65,0x6E,0x74,0x65,0x72,0x20,0x6F,0x6C,0x64,0x20,0x70,0x61,0x73,0x73,0x77, +0x6F,0x72,0x64,0x3A,0x20,0x00,0x0A,0x65,0x6E,0x74,0x65,0x72,0x20,0x6E,0x65,0x77, +0x20,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x3A,0x20,0x00,0x0A,0x63,0x6F,0x6E, +0x66,0x69,0x72,0x6D,0x61,0x74,0x69,0x6F,0x6E,0x3A,0x20,0x00,0x0A,0x00,0x6E,0x65, +0x77,0x6B,0x65,0x79,0x00,0x0A,0x43,0x72,0x65,0x61,0x74,0x69,0x6E,0x67,0x20,0x61, +0x20,0x66,0x6C,0x6F,0x70,0x70,0x79,0x20,0x6B,0x65,0x79,0x20,0x74,0x6F,0x20,0x65, +0x6E,0x61,0x62,0x6C,0x65,0x20,0x63,0x6C,0x65,0x61,0x72,0x69,0x6E,0x67,0x20,0x6F, +0x66,0x20,0x73,0x61,0x76,0x65,0x64,0x20,0x4E,0x56,0x52,0x41,0x4D,0x20,0x69,0x6E, +0x66,0x6F,0x72,0x6D,0x61,0x74,0x69,0x6F,0x6E,0x0A,0x0A,0x00,0x67,0x6F,0x00,0x49, +0x6E,0x73,0x65,0x72,0x74,0x20,0x61,0x20,0x66,0x6F,0x72,0x6D,0x61,0x74,0x74,0x65, +0x64,0x20,0x66,0x6C,0x6F,0x70,0x70,0x79,0x2C,0x20,0x74,0x68,0x65,0x6E,0x20,0x74, +0x79,0x70,0x65,0x20,0x27,0x67,0x6F,0x27,0x20,0x28,0x71,0x20,0x74,0x6F,0x20,0x71, +0x75,0x69,0x74,0x29,0x3A,0x20,0x00,0x0A,0x43,0x72,0x65,0x61,0x74,0x69,0x6F,0x6E, +0x20,0x6F,0x66,0x20,0x66,0x6C,0x6F,0x70,0x70,0x79,0x20,0x6B,0x65,0x79,0x20,0x63, +0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x0A,0x0A,0x00,0x73,0x79,0x73,0x64,0x75,0x6D, +0x70,0x00,0x76,0x65,0x72,0x73,0x69,0x6F,0x6E,0x00,0x0A,0x43,0x72,0x65,0x61,0x74, +0x65,0x64,0x3A,0x20,0x25,0x73,0x0A,0x00,0x49,0x73,0x73,0x75,0x65,0x3A,0x20,0x25, +0x30,0x38,0x6C,0x78,0x0A,0x00,0x52,0x65,0x6C,0x65,0x61,0x73,0x65,0x3A,0x20,0x25, +0x73,0x0A,0x4C,0x6F,0x61,0x64,0x3A,0x20,0x25,0x73,0x0A,0x00,0x53,0x65,0x72,0x69, +0x61,0x6C,0x20,0x4E,0x75,0x6D,0x62,0x65,0x72,0x3A,0x20,0x25,0x30,0x38,0x6C,0x78, +0x0A,0x0A,0x00,0x71,0x00,0x65,0x64,0x74,0x00,0x65,0x72,0x72,0x6F,0x72,0x20,0x69, +0x6E,0x66,0x6F,0x00,0x62,0x61,0x75,0x64,0x00,0x3F,0x00,0x0A,0x45,0x6E,0x74,0x65, +0x72,0x20,0x61,0x6E,0x20,0x65,0x78,0x65,0x63,0x75,0x74,0x61,0x62,0x6C,0x65,0x20, +0x6F,0x72,0x20,0x73,0x79,0x73,0x74,0x65,0x6D,0x20,0x66,0x69,0x6C,0x65,0x2C,0x20, +0x61,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F,0x72,0x79,0x20,0x6E,0x61,0x6D,0x65, +0x2C,0x0A,0x00,0x6F,0x72,0x20,0x6F,0x6E,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65, +0x20,0x70,0x6F,0x73,0x73,0x69,0x62,0x6C,0x65,0x20,0x66,0x69,0x72,0x6D,0x77,0x61, +0x72,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x6E,0x61,0x6D,0x65,0x73, +0x3A,0x0A,0x0A,0x00,0x62,0x61,0x75,0x64,0x20,0x20,0x20,0x20,0x65,0x64,0x74,0x20, +0x20,0x20,0x20,0x6E,0x65,0x77,0x6B,0x65,0x79,0x20,0x20,0x20,0x20,0x70,0x61,0x73, +0x73,0x77,0x64,0x20,0x20,0x20,0x20,0x73,0x79,0x73,0x64,0x75,0x6D,0x70,0x20,0x20, +0x20,0x20,0x76,0x65,0x72,0x73,0x69,0x6F,0x6E,0x20,0x20,0x20,0x20,0x71,0x28,0x75, +0x69,0x74,0x29,0x0A,0x0A,0x00,0x2A,0x56,0x4F,0x49,0x44,0x2A,0x00,0x09,0x50,0x6F, +0x73,0x73,0x69,0x62,0x6C,0x65,0x20,0x6C,0x6F,0x61,0x64,0x20,0x64,0x65,0x76,0x69, +0x63,0x65,0x73,0x20,0x61,0x72,0x65,0x3A,0x0A,0x0A,0x00,0x4F,0x70,0x74,0x69,0x6F, +0x6E,0x20,0x4E,0x75,0x6D,0x62,0x65,0x72,0x20,0x20,0x20,0x20,0x53,0x6C,0x6F,0x74, +0x20,0x20,0x20,0x20,0x20,0x4E,0x61,0x6D,0x65,0x0A,0x00,0x2D,0x2D,0x2D,0x2D,0x2D, +0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D, +0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D, +0x2D,0x2D,0x0A,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x25,0x32,0x64,0x20,0x20,0x20, +0x20,0x20,0x20,0x20,0x20,0x20,0x25,0x32,0x64,0x00,0x2A,0x56,0x4F,0x49,0x44,0x2A, +0x00,0x20,0x20,0x20,0x20,0x20,0x25,0x31,0x30,0x73,0x00,0x0A,0x00,0x0A,0x45,0x6E, +0x74,0x65,0x72,0x20,0x4C,0x6F,0x61,0x64,0x20,0x44,0x65,0x76,0x69,0x63,0x65,0x20, +0x4F,0x70,0x74,0x69,0x6F,0x6E,0x20,0x4E,0x75,0x6D,0x62,0x65,0x72,0x20,0x00,0x5B, +0x25,0x64,0x00,0x2A,0x56,0x4F,0x49,0x44,0x2A,0x00,0x20,0x28,0x25,0x73,0x29,0x00, +0x5D,0x3A,0x20,0x00,0x0A,0x00,0x0A,0x25,0x73,0x20,0x69,0x73,0x20,0x6E,0x6F,0x74, +0x20,0x61,0x20,0x76,0x61,0x6C,0x69,0x64,0x20,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x20, +0x6E,0x75,0x6D,0x62,0x65,0x72,0x2E,0x0A,0x00,0x50,0x6F,0x73,0x73,0x69,0x62,0x6C, +0x65,0x20,0x73,0x75,0x62,0x64,0x65,0x76,0x69,0x63,0x65,0x73,0x20,0x61,0x72,0x65, +0x3A,0x0A,0x0A,0x00,0x4F,0x70,0x74,0x69,0x6F,0x6E,0x20,0x4E,0x75,0x6D,0x62,0x65, +0x72,0x20,0x20,0x20,0x53,0x75,0x62,0x64,0x65,0x76,0x69,0x63,0x65,0x20,0x20,0x20, +0x20,0x4E,0x61,0x6D,0x65,0x0A,0x00,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D, +0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D, +0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D, +0x2D,0x2D,0x2D,0x0A,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x25,0x32,0x64,0x20,0x20, +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x25,0x32,0x64,0x00,0x2A,0x56,0x4F,0x49, +0x44,0x2A,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x25,0x31,0x30,0x73, +0x00,0x0A,0x00,0x0A,0x45,0x6E,0x74,0x65,0x72,0x20,0x53,0x75,0x62,0x64,0x65,0x76, +0x69,0x63,0x65,0x20,0x4F,0x70,0x74,0x69,0x6F,0x6E,0x20,0x4E,0x75,0x6D,0x62,0x65, +0x72,0x20,0x00,0x5B,0x25,0x64,0x00,0x2A,0x56,0x4F,0x49,0x44,0x2A,0x00,0x28,0x25, +0x73,0x29,0x00,0x5D,0x3A,0x20,0x00,0x0A,0x00,0x0A,0x25,0x73,0x20,0x69,0x73,0x20, +0x6E,0x6F,0x74,0x20,0x61,0x20,0x76,0x61,0x6C,0x69,0x64,0x20,0x6F,0x70,0x74,0x69, +0x6F,0x6E,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x2E,0x0A,0x00,0x0A,0x53,0x4F,0x52, +0x52,0x59,0x21,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x32,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0x02,0x00,0x80,0x00,0x00,0x00, +0x00,0x6E,0x03,0x11,0x00,0x00,0x00,0x00,0x00,0x86,0x04,0x22,0x00,0x00,0x00,0x00, +0x00,0x96,0x05,0x33,0x80,0x00,0x00,0x00,0x00,0xC8,0x06,0x33,0x00,0x00,0x00,0x00, +0x01,0x2C,0x07,0x44,0x00,0x00,0x00,0x00,0x02,0x58,0x08,0x55,0x00,0x00,0x00,0x00, +0x04,0xB0,0x09,0x66,0x00,0x00,0x00,0x00,0x07,0x08,0x0A,0xAA,0x80,0x00,0x00,0x00, +0x09,0x60,0x0B,0x88,0x00,0x00,0x00,0x00,0x12,0xC0,0x0C,0x99,0x00,0x00,0x00,0x00, +0x25,0x80,0x0D,0xBB,0x00,0x00,0x00,0x00,0x4B,0x00,0x0E,0xCC,0x80,0x00,0x00,0x00, +0x96,0x00,0x0F,0xCC,0x00,0x00,0x00,0x00,0x55,0x6E,0x73,0x75,0x70,0x70,0x6F,0x72, +0x74,0x65,0x64,0x20,0x42,0x61,0x75,0x64,0x20,0x52,0x61,0x74,0x65,0x3A,0x20,0x25, +0x64,0x0A,0x00,0x45,0x6E,0x74,0x65,0x72,0x20,0x6E,0x65,0x77,0x20,0x72,0x61,0x74, +0x65,0x20,0x5B,0x25,0x64,0x5D,0x3A,0x20,0x00,0x25,0x64,0x00,0x43,0x68,0x61,0x6E, +0x67,0x65,0x20,0x62,0x61,0x75,0x64,0x20,0x72,0x61,0x74,0x65,0x20,0x74,0x6F,0x20, +0x25,0x64,0x0A,0x00,0x20,0x08,0x00,0x0A,0x6D,0x61,0x78,0x20,0x69,0x6E,0x70,0x75, +0x74,0x20,0x6F,0x66,0x20,0x25,0x64,0x20,0x63,0x68,0x61,0x72,0x61,0x63,0x74,0x65, +0x72,0x73,0x2C,0x20,0x72,0x65,0x2D,0x65,0x6E,0x74,0x65,0x72,0x20,0x65,0x6E,0x74, +0x69,0x72,0x65,0x20,0x6C,0x69,0x6E,0x65,0x0A,0x00,0x00,0x00,0x30,0x31,0x32,0x33, +0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x66,0x00,0x00,0x00,0x00, +0x28,0x6E,0x75,0x6C,0x6C,0x20,0x70,0x6F,0x69,0x6E,0x74,0x65,0x72,0x29,0x00,0x00, +0x0A,0x0A,0x43,0x75,0x72,0x72,0x65,0x6E,0x74,0x20,0x53,0x79,0x73,0x74,0x65,0x6D, +0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x0A,0x0A, +0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x20,0x42,0x6F,0x61,0x72,0x64,0x20,0x6D,0x65, +0x6D,0x6F,0x72,0x79,0x20,0x73,0x69,0x7A,0x65,0x3A,0x20,0x00,0x25,0x64,0x20,0x6D, +0x65,0x67,0x61,0x62,0x79,0x74,0x65,0x28,0x73,0x29,0x00,0x25,0x64,0x20,0x6B,0x69, +0x6C,0x6F,0x62,0x79,0x74,0x65,0x73,0x00,0x0A,0x0A,0x25,0x30,0x32,0x64,0x20,0x2D, +0x20,0x64,0x65,0x76,0x69,0x63,0x65,0x20,0x6E,0x61,0x6D,0x65,0x20,0x3D,0x20,0x25, +0x2D,0x39,0x73,0x2C,0x20,0x00,0x6F,0x63,0x63,0x75,0x72,0x72,0x65,0x6E,0x63,0x65, +0x20,0x3D,0x20,0x25,0x32,0x64,0x2C,0x20,0x73,0x6C,0x6F,0x74,0x20,0x3D,0x20,0x25, +0x30,0x32,0x64,0x2C,0x20,0x49,0x44,0x20,0x63,0x6F,0x64,0x65,0x20,0x3D,0x20,0x30, +0x78,0x25,0x30,0x32,0x78,0x0A,0x00,0x20,0x20,0x20,0x20,0x20,0x62,0x6F,0x6F,0x74, +0x20,0x64,0x65,0x76,0x69,0x63,0x65,0x20,0x3D,0x20,0x25,0x63,0x2C,0x20,0x62,0x6F, +0x61,0x72,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x20,0x3D,0x20,0x25,0x73,0x2C,0x20, +0x77,0x6F,0x72,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x20,0x3D,0x20,0x25,0x64,0x20, +0x62,0x79,0x74,0x65,0x28,0x73,0x29,0x2C,0x0A,0x00,0x64,0x6F,0x75,0x62,0x6C,0x65, +0x00,0x73,0x69,0x6E,0x67,0x6C,0x65,0x00,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x71, +0x20,0x51,0x20,0x73,0x69,0x7A,0x65,0x20,0x3D,0x20,0x30,0x78,0x25,0x30,0x32,0x78, +0x2C,0x20,0x63,0x6F,0x6D,0x70,0x20,0x51,0x20,0x73,0x69,0x7A,0x65,0x20,0x3D,0x20, +0x30,0x78,0x25,0x30,0x32,0x78,0x2C,0x20,0x00,0x63,0x6F,0x6E,0x73,0x6F,0x6C,0x65, +0x20,0x61,0x62,0x69,0x6C,0x69,0x74,0x79,0x20,0x3D,0x20,0x25,0x63,0x00,0x2C,0x20, +0x70,0x75,0x6D,0x70,0x20,0x66,0x69,0x6C,0x65,0x20,0x3D,0x20,0x25,0x63,0x00,0x20, +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x0A, +0x20,0x20,0x20,0x20,0x20,0x73,0x75,0x62,0x64,0x65,0x76,0x69,0x63,0x65,0x28,0x73, +0x29,0x00,0x25,0x73,0x23,0x25,0x30,0x32,0x64,0x20,0x3D,0x20,0x25,0x2D,0x39,0x73, +0x2C,0x20,0x49,0x44,0x20,0x63,0x6F,0x64,0x65,0x20,0x3D,0x20,0x30,0x78,0x25,0x30, +0x32,0x78,0x00,0x0A,0x20,0x20,0x20,0x20,0x20,0x00,0x2C,0x20,0x00,0x0A,0x0A,0x50, +0x72,0x65,0x73,0x73,0x20,0x61,0x6E,0x79,0x20,0x6B,0x65,0x79,0x20,0x74,0x6F,0x20, +0x63,0x6F,0x6E,0x74,0x69,0x6E,0x75,0x65,0x0A,0x00,0x0A,0x44,0x4F,0x4E,0x45,0x0A, +0x0A,0x00,0x00,0x00,0x50,0x45,0x52,0x49,0x50,0x48,0x45,0x52,0x41,0x4C,0x20,0x49, +0x2F,0x4F,0x20,0x25,0x73,0x20,0x45,0x52,0x52,0x4F,0x52,0x20,0x41,0x54,0x20,0x42, +0x4C,0x4F,0x43,0x4B,0x20,0x25,0x64,0x2C,0x20,0x53,0x55,0x42,0x44,0x45,0x56,0x49, +0x43,0x45,0x20,0x25,0x64,0x2C,0x20,0x53,0x4C,0x4F,0x54,0x20,0x25,0x64,0x0A,0x00, +0x52,0x45,0x41,0x44,0x00,0x57,0x52,0x49,0x54,0x45,0x00,0x00,0x0A,0x46,0x57,0x20, +0x45,0x52,0x52,0x4F,0x52,0x20,0x31,0x2D,0x25,0x73,0x0A,0x00,0x20,0x20,0x20,0x20, +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x45,0x58,0x45,0x43,0x55, +0x54,0x49,0x4F,0x4E,0x20,0x48,0x41,0x4C,0x54,0x45,0x44,0x0A,0x00,0x00,0x00,0x00, +0x30,0x31,0x3A,0x20,0x4E,0x56,0x52,0x41,0x4D,0x20,0x53,0x41,0x4E,0x49,0x54,0x59, +0x20,0x46,0x41,0x49,0x4C,0x55,0x52,0x45,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20, +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x44,0x45,0x46,0x41,0x55,0x4C,0x54,0x20, +0x56,0x41,0x4C,0x55,0x45,0x53,0x20,0x41,0x53,0x53,0x55,0x4D,0x45,0x44,0x0A,0x20, +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x49,0x46, +0x20,0x52,0x45,0x50,0x45,0x41,0x54,0x45,0x44,0x2C,0x20,0x43,0x48,0x45,0x43,0x4B, +0x20,0x54,0x48,0x45,0x20,0x42,0x41,0x54,0x54,0x45,0x52,0x59,0x0A,0x00,0x0A,0x46, +0x57,0x20,0x57,0x41,0x52,0x4E,0x49,0x4E,0x47,0x3A,0x20,0x4E,0x56,0x52,0x41,0x4D, +0x20,0x44,0x45,0x46,0x41,0x55,0x4C,0x54,0x20,0x56,0x41,0x4C,0x55,0x45,0x53,0x20, +0x41,0x53,0x53,0x55,0x4D,0x45,0x44,0x0A,0x0A,0x00,0x30,0x32,0x3A,0x20,0x44,0x49, +0x53,0x4B,0x20,0x53,0x41,0x4E,0x49,0x54,0x59,0x20,0x46,0x41,0x49,0x4C,0x55,0x52, +0x45,0x00,0x30,0x35,0x3A,0x20,0x53,0x45,0x4C,0x46,0x2D,0x43,0x4F,0x4E,0x46,0x49, +0x47,0x55,0x52,0x41,0x54,0x49,0x4F,0x4E,0x20,0x46,0x41,0x49,0x4C,0x55,0x52,0x45, +0x00,0x30,0x36,0x3A,0x20,0x42,0x4F,0x4F,0x54,0x20,0x46,0x41,0x49,0x4C,0x55,0x52, +0x45,0x00,0x30,0x37,0x3A,0x20,0x46,0x4C,0x4F,0x50,0x50,0x59,0x20,0x4B,0x45,0x59, +0x20,0x43,0x52,0x45,0x41,0x54,0x45,0x20,0x46,0x41,0x49,0x4C,0x55,0x52,0x45,0x00, +0x30,0x38,0x3A,0x20,0x4D,0x45,0x4D,0x4F,0x52,0x59,0x20,0x54,0x45,0x53,0x54,0x20, +0x46,0x41,0x49,0x4C,0x55,0x52,0x45,0x00,0x30,0x39,0x3A,0x20,0x44,0x49,0x53,0x4B, +0x20,0x46,0x4F,0x52,0x4D,0x41,0x54,0x20,0x4E,0x4F,0x54,0x20,0x43,0x4F,0x4D,0x50, +0x41,0x54,0x49,0x42,0x4C,0x45,0x20,0x57,0x49,0x54,0x48,0x20,0x53,0x59,0x53,0x54, +0x45,0x4D,0x00,0x25,0x73,0x00,0x0A,0x0A,0x53,0x45,0x4C,0x46,0x2D,0x43,0x48,0x45, +0x43,0x4B,0x0A,0x00,0x0A,0x4E,0x4F,0x4E,0x45,0x0A,0x0A,0x00,0x0A,0x45,0x58,0x43, +0x45,0x50,0x54,0x49,0x4F,0x4E,0x2C,0x20,0x50,0x43,0x20,0x3D,0x20,0x30,0x78,0x25, +0x30,0x38,0x78,0x2C,0x20,0x50,0x53,0x57,0x20,0x3D,0x20,0x30,0x78,0x25,0x30,0x38, +0x78,0x2C,0x20,0x43,0x53,0x52,0x20,0x3D,0x20,0x30,0x78,0x25,0x30,0x34,0x78,0x0A, +0x0A,0x00,0x0A,0x49,0x4E,0x54,0x45,0x52,0x52,0x55,0x50,0x54,0x2C,0x20,0x50,0x43, +0x20,0x3D,0x20,0x30,0x78,0x25,0x30,0x38,0x78,0x2C,0x20,0x50,0x53,0x57,0x20,0x3D, +0x20,0x30,0x78,0x25,0x30,0x38,0x78,0x2C,0x20,0x43,0x53,0x52,0x20,0x3D,0x20,0x30, +0x78,0x25,0x30,0x34,0x78,0x2C,0x20,0x4C,0x56,0x4C,0x20,0x3D,0x20,0x25,0x64,0x0A, +0x0A,0x00,0x0A,0x53,0x41,0x4E,0x49,0x54,0x59,0x20,0x4F,0x4E,0x20,0x44,0x49,0x53, +0x4B,0x20,0x25,0x64,0x2C,0x20,0x45,0x52,0x52,0x4F,0x52,0x20,0x25,0x64,0x0A,0x00, +0x43,0x4F,0x4D,0x4D,0x41,0x4E,0x44,0x20,0x3D,0x20,0x30,0x78,0x25,0x30,0x32,0x78, +0x2C,0x20,0x55,0x4E,0x49,0x54,0x20,0x53,0x54,0x41,0x54,0x55,0x53,0x20,0x3D,0x20, +0x30,0x78,0x25,0x30,0x32,0x78,0x2C,0x20,0x45,0x52,0x52,0x4F,0x52,0x20,0x53,0x54, +0x41,0x54,0x55,0x53,0x20,0x3D,0x20,0x30,0x78,0x25,0x30,0x32,0x78,0x2C,0x20,0x53, +0x54,0x41,0x54,0x55,0x53,0x20,0x3D,0x20,0x30,0x78,0x25,0x30,0x32,0x78,0x00,0x0A, +0x0A,0x00,0x0A,0x4E,0x4F,0x4E,0x45,0x0A,0x0A,0x00,0x00,0x00,0x30,0x34,0x3A,0x20, +0x55,0x4E,0x45,0x58,0x50,0x45,0x43,0x54,0x45,0x44,0x20,0x49,0x4E,0x54,0x45,0x52, +0x52,0x55,0x50,0x54,0x0A,0x00,0x00,0x00,0x30,0x33,0x3A,0x20,0x55,0x4E,0x45,0x58, +0x50,0x45,0x43,0x54,0x45,0x44,0x20,0x46,0x41,0x55,0x4C,0x54,0x0A,0x00,0x00,0x00, +0x6D,0x63,0x70,0x00,0x2F,0x66,0x69,0x6C,0x6C,0x65,0x64,0x74,0x00,0x0A,0x53,0x59, +0x53,0x54,0x45,0x4D,0x20,0x46,0x41,0x49,0x4C,0x55,0x52,0x45,0x3A,0x20,0x43,0x4F, +0x4E,0x53,0x55,0x4C,0x54,0x20,0x59,0x4F,0x55,0x52,0x20,0x53,0x59,0x53,0x54,0x45, +0x4D,0x20,0x41,0x44,0x4D,0x49,0x4E,0x49,0x53,0x54,0x52,0x41,0x54,0x49,0x4F,0x4E, +0x20,0x55,0x54,0x49,0x4C,0x49,0x54,0x49,0x45,0x53,0x20,0x47,0x55,0x49,0x44,0x45, +0x0A,0x0A,0x00,0x0A,0x46,0x49,0x52,0x4D,0x57,0x41,0x52,0x45,0x20,0x4D,0x4F,0x44, +0x45,0x0A,0x0A,0x00,0x2F,0x66,0x69,0x6C,0x6C,0x65,0x64,0x74,0x00,0x2F,0x64,0x67, +0x6D,0x6F,0x6E,0x00,0x2F,0x75,0x6E,0x69,0x78,0x00,0x00,0x00,0x30,0x34,0x3A,0x20, +0x55,0x4E,0x45,0x58,0x50,0x45,0x43,0x54,0x45,0x44,0x20,0x49,0x4E,0x54,0x45,0x52, +0x52,0x55,0x50,0x54,0x00,0x30,0x33,0x3A,0x20,0x55,0x4E,0x45,0x58,0x50,0x45,0x43, +0x54,0x45,0x44,0x20,0x46,0x41,0x55,0x4C,0x54,0x00,0x00,0x00,0x18,0xF2,0x00,0x03, +0x11,0x0D,0x00,0x80,0x69,0x64,0x25,0x64,0x20,0x43,0x52,0x43,0x20,0x65,0x72,0x72, +0x6F,0x72,0x20,0x61,0x74,0x20,0x64,0x69,0x73,0x6B,0x20,0x61,0x64,0x64,0x72,0x65, +0x73,0x73,0x20,0x25,0x30,0x38,0x78,0x20,0x28,0x25,0x64,0x20,0x72,0x65,0x74,0x72, +0x69,0x65,0x73,0x29,0x0A,0x00,0x00,0x00,0x69,0x66,0x20,0x43,0x52,0x43,0x20,0x65, +0x72,0x72,0x6F,0x72,0x20,0x61,0x74,0x20,0x64,0x69,0x73,0x6B,0x20,0x61,0x64,0x64, +0x72,0x65,0x73,0x73,0x20,0x25,0x30,0x38,0x78,0x20,0x28,0x25,0x64,0x20,0x72,0x65, +0x74,0x72,0x69,0x65,0x73,0x29,0x0A,0x00,0x30,0x35,0x2F,0x33,0x31,0x2F,0x38,0x35, +0x00,0x00,0x00,0x00,0x50,0x46,0x33,0x00,0x31,0x2E,0x32,0x2E,0x31,0x00,0x00,0x00, +0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20, +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, +0x20,0x48,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x10,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x81,0x81,0x81,0x81,0x81,0x81,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10,0x10,0x10,0x10, +0x10,0x10,0x82,0x82,0x82,0x82,0x82,0x82,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x10,0x10,0x10, +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,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x04,0x7F,0x08,0x00,0x00,0x02,0x4C,0x04,0x7F,0x08,0x00,0x00, +0x02,0x49,0x04,0x7F,0x08,0x00,0x00,0x02,0x4A,0x04,0x7F,0x08,0x08,0x00,0x02,0x4E, +0x87,0x16,0x7F,0x0F,0x20,0x04,0x00,0x70,0x87,0x6F,0x64,0x7F,0x03,0x20,0x04,0x00, +0x70,0x87,0x5F,0x94,0x00,0x7F,0x0F,0x20,0x04,0x00,0x70,0x87,0x0A,0x7F,0x0B,0x20, +0x04,0x00,0x70,0x87,0x6F,0x74,0x7F,0x0F,0x20,0x04,0x00,0x70,0x24,0x7F,0xD5,0x12, +0x00,0x00,0x70,0x70,0x10,0x43,0x9C,0x4F,0x08,0x00,0x00,0x00,0x4C,0x87,0x01,0x7F, +0x1B,0x40,0x04,0x00,0x70,0x70,0x84,0x4B,0x40,0xB8,0x4F,0xFF,0xFF,0xC3,0xFF,0x40, +0x84,0x40,0x4B,0x77,0x05,0x7A,0x3E,0x06,0x47,0x05,0x7A,0x39,0x06,0x43,0x05,0x7A, +0x34,0x06,0x57,0x05,0x7A,0x2F,0x06,0x53,0x05,0x7A,0x2A,0x06,0x53,0x05,0x7A,0x25, +0x06,0x63,0x05,0x7A,0x20,0x06,0x70,0x84,0x4B,0x40,0xB0,0x4F,0x00,0x00,0x3C,0x00, +0x40,0x84,0x40,0x4B,0x7F,0x05,0x7A,0x0D,0x06,0x4F,0x05,0x7A,0x08,0x06,0x43,0x05, +0x7A,0x03,0x06,0x5F,0x05,0x7A,0xFE,0x05,0x5B,0x05,0x7A,0xF9,0x05,0x5B,0x05,0x7A, +0xF4,0x05,0x6B,0x05,0x7A,0xEF,0x05,0x70,0x84,0x4B,0x40,0xB8,0x4F,0xFF,0xFF,0xC3, +0xFF,0x40,0xB0,0x4F,0x00,0x00,0x10,0x00,0x40,0x84,0x40,0x4B,0x43,0x05,0x7A,0xD5, +0x05,0x70,0x84,0x4B,0x40,0xB8,0x4F,0xFF,0xFF,0xC3,0xFF,0x40,0xB0,0x4F,0x00,0x00, +0x04,0x00,0x40,0x84,0x40,0x4B,0x5E,0x06,0x00,0x7A,0xBA,0x05,0x70,0x84,0x4B,0x40, +0xB8,0x4F,0xFF,0xFF,0xC3,0xFF,0x40,0xB0,0x4F,0x00,0x00,0x20,0x00,0x40,0x84,0x40, +0x4B,0x4B,0x05,0x7A,0xA0,0x05,0x84,0xFF,0x40,0x84,0x40,0x41,0x84,0x41,0x42,0x84, +0x42,0x43,0x84,0x43,0x44,0x84,0x44,0x45,0x84,0x45,0x46,0x84,0x46,0x47,0x84,0x47, +0x48,0x3C,0x40,0x48,0x76,0x7F,0x05,0xD0,0x01,0x40,0x40,0x43,0x04,0x7B,0xDC,0x84, +0xFE,0x40,0x88,0x40,0x41,0x88,0x41,0x42,0x88,0x42,0x43,0x88,0x43,0x44,0x88,0x44, +0x45,0x88,0x45,0x46,0x88,0x46,0x47,0x88,0x47,0x48,0x88,0x40,0x48,0x88,0x41,0x47, +0x88,0x42,0x46,0x88,0x43,0x45,0x88,0x48,0x41,0x88,0x47,0x42,0x88,0x46,0x43,0x88, +0x44,0x40,0x88,0x41,0x44,0x3C,0x40,0x48,0x76,0x3B,0x05,0xD0,0x01,0x40,0x40,0x4B, +0x07,0x88,0x40,0x40,0x7B,0xBE,0x84,0x49,0x41,0x84,0x4A,0x42,0x84,0x4C,0x43,0x84, +0x4D,0x44,0x84,0x4E,0x45,0x84,0xFF,0x40,0x84,0x40,0x49,0x84,0x49,0x4A,0x84,0x4A, +0x4C,0x84,0x4C,0x4D,0x84,0x4D,0x4E,0x3C,0x49,0x4E,0x76,0x4C,0x00,0xD0,0x01,0x40, +0x40,0x43,0x04,0x7B,0xE5,0x84,0x01,0x40,0x88,0x40,0x49,0x88,0x49,0x4A,0x88,0x4A, +0x4C,0x88,0x4C,0x4D,0x88,0x4D,0x4E,0x88,0x49,0x4E,0x88,0x4A,0x4D,0x88,0x4C,0x49, +0x88,0x4E,0x4A,0x88,0x4D,0x4C,0x3C,0x49,0x4E,0x76,0x1D,0x00,0xD0,0x01,0x40,0x40, +0x4B,0x04,0x7B,0xD6,0x84,0x41,0x49,0x84,0x42,0x4A,0x84,0x43,0x4C,0x84,0x44,0x4D, +0x84,0x45,0x4E,0x7A,0x15,0x00,0x84,0x41,0x49,0x84,0x42,0x4A,0x84,0x43,0x4C,0x84, +0x44,0x4D,0x84,0x45,0x4E,0x7A,0xAE,0x04,0x82,0x48,0x84,0x5F,0xEE,0x7F,0x45,0x80, +0x47,0x7B,0x3F,0x86,0xE2,0x48,0xE0,0x40,0x87,0x57,0xE2,0x41,0xBA,0x5F,0xFF,0x00, +0x41,0x86,0xE2,0x41,0xE0,0x41,0x9C,0x41,0x40,0x86,0x40,0x48,0x86,0xE2,0x48,0xE0, +0x40,0xD0,0x01,0x40,0x40,0x86,0xE2,0x40,0xE0,0x40,0x86,0xE2,0x48,0xE0,0x41,0xD4, +0x0F,0x41,0x41,0x86,0xE2,0x41,0xE0,0x41,0xB0,0x41,0x40,0x86,0x40,0x48,0x90,0x47, +0x3C,0x45,0x47,0x5B,0xC0,0x86,0xE2,0x48,0xE0,0x40,0x88,0x40,0x40,0x86,0x40,0x48, +0x86,0xE2,0x48,0xE0,0x40,0x87,0x57,0xE0,0x41,0x87,0xC7,0x01,0xE0,0x42,0xD0,0x08, +0x42,0x42,0xB0,0x42,0x41,0x3C,0x41,0x40,0x77,0x08,0x24,0x7F,0x6E,0x15,0x00,0x00, +0x86,0xE2,0x48,0xE0,0x40,0x88,0x40,0x40,0x86,0x40,0x48,0x9C,0x4F,0x00,0x80,0x00, +0x00,0x45,0x7B,0x3F,0x86,0xE2,0x48,0xE0,0x40,0x87,0x57,0xE2,0x41,0xBA,0x5F,0xFF, +0x00,0x41,0x86,0xE2,0x41,0xE0,0x41,0x9C,0x41,0x40,0x86,0x40,0x48,0x86,0xE2,0x48, +0xE0,0x40,0xD0,0x01,0x40,0x40,0x86,0xE2,0x40,0xE0,0x40,0x86,0xE2,0x48,0xE0,0x41, +0xD4,0x0F,0x41,0x41,0x86,0xE2,0x41,0xE0,0x41,0xB0,0x41,0x40,0x86,0x40,0x48,0x90, +0x47,0x3C,0x45,0x47,0x5B,0xC0,0x86,0xE2,0x48,0xE0,0x40,0x88,0x40,0x40,0x86,0x40, +0x48,0x86,0xE2,0x48,0xE0,0x40,0x87,0x57,0xE0,0x41,0x87,0xC7,0x01,0xE0,0x42,0xD0, +0x08,0x42,0x42,0xB0,0x42,0x41,0x3C,0x41,0x40,0x7F,0x05,0x7A,0xC1,0x03,0x3C,0x4F, +0xED,0x0D,0x1C,0xA1,0x7F,0x64,0x08,0x00,0x02,0x7F,0x15,0x3C,0x4F,0x0D,0xF0,0xAD, +0x8B,0x7F,0x64,0x08,0x00,0x02,0x7F,0x08,0x24,0x7F,0xBC,0x16,0x00,0x00,0x2C,0x5C, +0x7F,0x90,0x3B,0x00,0x00,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x40,0x3F,0x02,0x50, +0x77,0x07,0x84,0x01,0x40,0x7B,0x04,0x80,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F,0x2C, +0x73,0x00,0x00,0xA0,0x00,0x2C,0xCC,0xFC,0x7F,0x8C,0x79,0x00,0x00,0x87,0x7F,0x00, +0xD0,0x04,0x00,0xE0,0x45,0x87,0x01,0x7F,0x1F,0x40,0x04,0x00,0x70,0x87,0x10,0x7F, +0x0F,0x90,0x04,0x00,0x70,0x87,0x20,0x7F,0x0F,0x90,0x04,0x00,0x70,0x87,0x01,0x7F, +0x68,0x08,0x00,0x02,0x70,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x2B,0x50,0x7F, +0x10,0x2C,0x5C,0x7F,0x72,0x5F,0x00,0x00,0x2C,0x5C,0x7F,0x78,0x63,0x00,0x00,0xDC, +0x04,0x7F,0xA4,0x04,0x00,0x00,0x40,0x3F,0x01,0x50,0x77,0x08,0x24,0x7F,0xA0,0x16, +0x00,0x00,0x2C,0x5C,0x7F,0x72,0x5F,0x00,0x00,0xA0,0x4F,0x0C,0x30,0x04,0x00,0xDC, +0x01,0x7F,0xA0,0x04,0x00,0x00,0x40,0xA0,0x40,0xA0,0x01,0x2C,0xCC,0xF4,0x7F,0x24, +0x52,0x00,0x00,0x28,0x40,0x77,0x28,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x40,0x87, +0x01,0x50,0x70,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x40,0xA0,0x40,0xA0,0x4F,0x0C, +0x30,0x04,0x00,0xA0,0x01,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x84,0x7F,0x64, +0x08,0x00,0x02,0x59,0x70,0x83,0xEF,0xA0,0x04,0x00,0x00,0x70,0xDC,0x02,0x7F,0xA0, +0x04,0x00,0x00,0x40,0xA0,0x40,0xA0,0x4F,0xC8,0x05,0x00,0x00,0x2C,0xCC,0xF8,0x7F, +0xB0,0x7F,0x00,0x00,0x2C,0x5C,0x7F,0x70,0x69,0x00,0x00,0x3C,0x4F,0xEF,0xBE,0xED, +0xFE,0x7F,0x64,0x08,0x00,0x02,0x7F,0x0A,0x84,0x59,0x7F,0x64,0x08,0x00,0x02,0x70, +0x3C,0x4F,0xED,0x0D,0x1C,0xA1,0x7F,0x64,0x08,0x00,0x02,0x77,0x0B,0x2C,0x5C,0xEF, +0x58,0x08,0x00,0x02,0x7B,0x08,0x24,0x7F,0xF0,0x65,0x00,0x00,0x3C,0x4F,0xD0,0xF1, +0x02,0x3B,0x7F,0x6C,0x08,0x00,0x02,0x7F,0x2A,0x87,0x6F,0x70,0x7F,0x04,0x90,0x04, +0x00,0x70,0x87,0x6F,0x40,0x7F,0x06,0x90,0x04,0x00,0x70,0x83,0x7F,0x07,0x90,0x04, +0x00,0x70,0x87,0x04,0x7F,0x0D,0x90,0x04,0x00,0x70,0x80,0x7F,0x5C,0x08,0x00,0x02, +0x70,0x84,0x7F,0x64,0x08,0x00,0x02,0x45,0x84,0x7F,0x6C,0x08,0x00,0x02,0x44,0x84, +0x7F,0x5C,0x08,0x00,0x02,0x43,0x84,0x4F,0x00,0x00,0x00,0x02,0x47,0x84,0x4F,0x04, +0x15,0x00,0x02,0x46,0x7B,0x4B,0x87,0x5F,0xFF,0x00,0x57,0x70,0x3F,0x5F,0xFF,0x00, +0x57,0x7F,0x08,0x24,0x7F,0x35,0x19,0x00,0x00,0x87,0x5F,0xAA,0x00,0x57,0x70,0x3F, +0x5F,0xAA,0x00,0x57,0x7F,0x08,0x24,0x7F,0x35,0x19,0x00,0x00,0x87,0x6F,0x55,0x57, +0x70,0x3F,0x6F,0x55,0x57,0x7F,0x08,0x24,0x7F,0x35,0x19,0x00,0x00,0x83,0x57,0x70, +0x84,0x47,0x40,0x90,0x47,0x2B,0x50,0x7F,0x08,0x24,0x7F,0x35,0x19,0x00,0x00,0x3C, +0x46,0x47,0x5B,0xB4,0x3C,0x4F,0x00,0x40,0x00,0x02,0x47,0x4B,0x04,0x7B,0x40,0x3C, +0x4F,0xEF,0xBE,0xED,0xFE,0x45,0x7F,0x26,0x3C,0x4F,0xD0,0xF1,0x02,0x3B,0x45,0x7F, +0x1D,0x3C,0x4F,0x0D,0xF0,0xAD,0x8B,0x45,0x7F,0x14,0x3C,0x4F,0x1E,0xAC,0xEB,0xAD, +0x45,0x7F,0x0B,0x3C,0x4F,0xED,0x0D,0x1C,0xA1,0x45,0x77,0x09,0x84,0x4F,0x00,0x30, +0x00,0x02,0x47,0x84,0x4F,0x00,0x40,0x00,0x02,0x46,0x7A,0x6A,0xFF,0x84,0x44,0x7F, +0x6C,0x08,0x00,0x02,0x70,0x84,0x45,0x7F,0x64,0x08,0x00,0x02,0x70,0x84,0x43,0x7F, +0x5C,0x08,0x00,0x02,0x70,0x87,0x01,0x7F,0x68,0x08,0x00,0x02,0x70,0x82,0x48,0x84, +0x4F,0x00,0x38,0x04,0x00,0x45,0x84,0x4F,0x00,0x30,0x04,0x00,0x47,0x7B,0x40,0x86, +0xE2,0x48,0xE0,0x40,0x86,0xE2,0xC7,0x02,0xE0,0x41,0xBA,0x0F,0x41,0x86,0xE2,0x41, +0xE0,0x41,0x9C,0x41,0x40,0x86,0x40,0x48,0x86,0xE2,0x48,0xE0,0x40,0xD0,0x01,0x40, +0x40,0x86,0xE2,0x40,0xE0,0x40,0x86,0xE2,0x48,0xE0,0x41,0xD4,0x0F,0x41,0x41,0x86, +0xE2,0x41,0xE0,0x41,0xB0,0x41,0x40,0x86,0x40,0x48,0x9C,0x04,0x47,0x3C,0x45,0x47, +0x5B,0xBF,0x86,0xE2,0x48,0xE0,0x40,0x88,0x40,0x40,0x86,0x40,0x48,0x86,0xE2,0x48, +0xE0,0x40,0xF8,0x0F,0x57,0x41,0xF8,0x0F,0xC7,0x04,0x42,0xD0,0x04,0x42,0x42,0xB0, +0x42,0x41,0xF8,0x0F,0xC7,0x08,0x42,0xD0,0x08,0x42,0x42,0xB0,0x42,0x41,0xF8,0x0F, +0xC7,0x0C,0x42,0xD0,0x0C,0x42,0x42,0xB0,0x42,0x41,0x3C,0x41,0x40,0x77,0x08,0x24, +0x7F,0x1D,0x19,0x00,0x00,0x84,0x4F,0x00,0x30,0x04,0x00,0x47,0x7B,0x08,0x80,0x57, +0x70,0x9C,0x04,0x47,0x3C,0x45,0x47,0x5B,0xF7,0x84,0x01,0x7F,0x60,0x30,0x04,0x00, +0x70,0x80,0x7F,0x64,0x30,0x04,0x00,0x70,0x82,0x48,0x84,0x4F,0x00,0x30,0x04,0x00, +0x47,0x7B,0x40,0x86,0xE2,0x48,0xE0,0x40,0x86,0xE2,0xC7,0x02,0xE0,0x41,0xBA,0x0F, +0x41,0x86,0xE2,0x41,0xE0,0x41,0x9C,0x41,0x40,0x86,0x40,0x48,0x86,0xE2,0x48,0xE0, +0x40,0xD0,0x01,0x40,0x40,0x86,0xE2,0x40,0xE0,0x40,0x86,0xE2,0x48,0xE0,0x41,0xD4, +0x0F,0x41,0x41,0x86,0xE2,0x41,0xE0,0x41,0xB0,0x41,0x40,0x86,0x40,0x48,0x9C,0x04, +0x47,0x3C,0x45,0x47,0x5B,0xBF,0x86,0xE2,0x48,0xE0,0x40,0x88,0x40,0x40,0x86,0x40, +0x48,0x86,0xE2,0x48,0xE0,0x57,0x70,0x86,0xE2,0x48,0xE0,0x40,0xD4,0x04,0x40,0x40, +0x84,0x40,0xC7,0x04,0x70,0x86,0xE2,0x48,0xE0,0x40,0xD4,0x08,0x40,0x40,0x84,0x40, +0xC7,0x08,0x70,0x86,0xE2,0x48,0xE0,0x40,0xD4,0x0C,0x40,0x40,0x84,0x40,0xC7,0x0C, +0x70,0xB0,0x4F,0x00,0x00,0x00,0x20,0x7F,0x5C,0x08,0x00,0x02,0x70,0x24,0x7F,0xB1, +0x21,0x00,0x00,0x84,0x02,0x44,0x24,0x7F,0x41,0x19,0x00,0x00,0x84,0x03,0x44,0x24, +0x7F,0x41,0x19,0x00,0x00,0x84,0x04,0x44,0x24,0x7F,0x41,0x19,0x00,0x00,0x84,0x05, +0x44,0x83,0x7F,0x0D,0x90,0x04,0x00,0x70,0x87,0x08,0x7F,0x0F,0x90,0x04,0x00,0x70, +0x87,0x01,0x7F,0x17,0x40,0x04,0x00,0x70,0x87,0x01,0x7F,0x03,0x40,0x04,0x00,0x70, +0x80,0x45,0x7B,0x32,0x80,0x43,0x7B,0x04,0x90,0x43,0x3C,0x4F,0x50,0xC3,0x00,0x00, +0x43,0x5F,0xF7,0x87,0x01,0x7F,0x13,0x40,0x04,0x00,0x70,0x80,0x43,0x7B,0x04,0x90, +0x43,0x3C,0x4F,0x50,0xC3,0x00,0x00,0x43,0x5F,0xF7,0x87,0x01,0x7F,0x17,0x40,0x04, +0x00,0x70,0x90,0x45,0x3C,0x44,0x45,0x5B,0xCD,0x3F,0x01,0xEF,0x10,0x05,0x00,0x00, +0x7F,0x2B,0x3F,0x6F,0x64,0x7F,0x03,0x20,0x04,0x00,0x7F,0x21,0x80,0xEF,0x8C,0x04, +0x00,0x00,0x70,0x80,0xEF,0x14,0x05,0x00,0x00,0x70,0x83,0x7F,0x0D,0x90,0x04,0x00, +0x70,0x87,0x04,0x7F,0x0E,0x90,0x04,0x00,0x70,0x7B,0x00,0x80,0x43,0x7B,0x04,0x90, +0x43,0xE8,0x4F,0x50,0xC3,0x00,0x00,0x44,0x40,0x3C,0x40,0x43,0x5F,0xF3,0x24,0x7F, +0x60,0x19,0x00,0x00,0x04,0x59,0x4C,0x20,0x48,0x20,0x47,0x20,0x46,0x20,0x45,0x20, +0x44,0x20,0x43,0x20,0x49,0x08,0x70,0x70,0x10,0x43,0x9C,0x4F,0x00,0x00,0x00,0x00, +0x4C,0x87,0x5F,0xD0,0x00,0x7F,0x00,0xD0,0x04,0x00,0x70,0xA0,0x01,0x2C,0xCC,0xFC, +0xEF,0x28,0x05,0x00,0x00,0x87,0x01,0x7F,0x70,0x08,0x00,0x02,0x70,0x87,0x5F,0xFF, +0x00,0x7F,0x71,0x08,0x00,0x02,0x70,0x84,0x4F,0x00,0x38,0x04,0x00,0x43,0xA0,0x00, +0xA0,0x4F,0x74,0x08,0x00,0x02,0xA0,0x00,0xA0,0x03,0x2C,0xCC,0xF0,0x7F,0x2C,0x7B, +0x00,0x00,0x28,0x40,0x77,0x08,0x24,0x7F,0x67,0x1B,0x00,0x00,0xDC,0x03,0x7F,0x08, +0x05,0x00,0x00,0x40,0x3F,0x50,0x7F,0x74,0x08,0x00,0x02,0x7F,0x08,0x24,0x7F,0x67, +0x1B,0x00,0x00,0xDC,0x07,0x7F,0x08,0x05,0x00,0x00,0x40,0x3F,0x50,0x7F,0x75,0x08, +0x00,0x02,0x7F,0x08,0x24,0x7F,0x67,0x1B,0x00,0x00,0xDC,0x0B,0x7F,0x08,0x05,0x00, +0x00,0x40,0x3F,0x50,0x7F,0x76,0x08,0x00,0x02,0x7F,0x08,0x24,0x7F,0x67,0x1B,0x00, +0x00,0xDC,0x0F,0x7F,0x08,0x05,0x00,0x00,0x40,0x3F,0x50,0x7F,0x77,0x08,0x00,0x02, +0x7F,0x08,0x24,0x7F,0x67,0x1B,0x00,0x00,0x84,0x4F,0x00,0x30,0x04,0x00,0x48,0x7B, +0x08,0x80,0x58,0x70,0x9C,0x04,0x48,0x3C,0x43,0x48,0x5B,0xF7,0x84,0x01,0x7F,0x60, +0x30,0x04,0x00,0x70,0x80,0x7F,0x64,0x30,0x04,0x00,0x70,0x82,0x44,0x84,0x4F,0x00, +0x30,0x04,0x00,0x48,0x7B,0x40,0x86,0xE2,0x44,0xE0,0x40,0x86,0xE2,0xC8,0x02,0xE0, +0x41,0xBA,0x0F,0x41,0x86,0xE2,0x41,0xE0,0x41,0x9C,0x41,0x40,0x86,0x40,0x44,0x86, +0xE2,0x44,0xE0,0x40,0xD0,0x01,0x40,0x40,0x86,0xE2,0x40,0xE0,0x40,0x86,0xE2,0x44, +0xE0,0x41,0xD4,0x0F,0x41,0x41,0x86,0xE2,0x41,0xE0,0x41,0xB0,0x41,0x40,0x86,0x40, +0x44,0x9C,0x04,0x48,0x3C,0x43,0x48,0x5B,0xBF,0x86,0xE2,0x44,0xE0,0x40,0x88,0x40, +0x40,0x86,0x40,0x44,0x86,0xE2,0x44,0xE0,0x58,0x70,0x86,0xE2,0x44,0xE0,0x40,0xD4, +0x04,0x40,0x40,0x84,0x40,0xC8,0x04,0x70,0x86,0xE2,0x44,0xE0,0x40,0xD4,0x08,0x40, +0x40,0x84,0x40,0xC8,0x08,0x70,0x86,0xE2,0x44,0xE0,0x40,0xD4,0x0C,0x40,0x40,0x84, +0x40,0xC8,0x0C,0x70,0xB0,0x4F,0x00,0x00,0x00,0x40,0x7F,0x5C,0x08,0x00,0x02,0x70, +0x2C,0x5C,0x7F,0xE0,0x5D,0x00,0x00,0xA0,0x4F,0x0C,0x30,0x04,0x00,0xA0,0x4F,0x61, +0x08,0x00,0x02,0xA0,0x01,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0x28,0x40,0x77, +0x20,0x87,0x01,0x7F,0x61,0x08,0x00,0x02,0x70,0xA0,0x4F,0x61,0x08,0x00,0x02,0xA0, +0x4F,0x0C,0x30,0x04,0x00,0xA0,0x01,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x3F, +0x01,0x7F,0x61,0x08,0x00,0x02,0x7F,0x0B,0x3F,0x02,0x7F,0x61,0x08,0x00,0x02,0x77, +0x12,0x87,0x01,0x45,0xFF,0x01,0x7F,0x61,0x08,0x00,0x02,0x40,0x87,0x40,0x47,0x7B, +0x06,0x83,0x45,0x83,0x47,0x83,0x7F,0x60,0x08,0x00,0x02,0x70,0x82,0x44,0x7B,0x1A, +0x86,0xE2,0x44,0xE0,0x40,0x86,0xE2,0x44,0xE0,0x41,0x87,0x81,0xEC,0x10,0x00,0x00, +0x80,0x74,0x0A,0x00,0x02,0x70,0x92,0x44,0x86,0xE2,0x44,0xE0,0x40,0x3C,0x08,0x40, +0x5B,0xE0,0x82,0x44,0x7B,0x23,0x87,0x47,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F, +0x2C,0x73,0x00,0x00,0x28,0x40,0x7F,0x04,0x7B,0x19,0xA0,0x6F,0x64,0x2C,0xCC,0xFC, +0xEF,0x28,0x05,0x00,0x00,0x92,0x44,0x86,0xE2,0x44,0xE0,0x40,0x3C,0x3C,0x40,0x5B, +0xD7,0x87,0x47,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F,0x28,0x6E,0x00,0x00,0x28, +0x40,0x77,0x39,0xF0,0x02,0x7F,0x7C,0x0A,0x00,0x02,0x40,0x87,0x47,0xE0,0x41,0xD0, +0x17,0x41,0x41,0xB0,0x41,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F,0xC0,0x61,0x00,0x00, +0x87,0x01,0x7F,0x13,0x40,0x04,0x00,0x70,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0xEF,0x8C, +0x04,0x00,0x00,0x70,0x24,0x7F,0x37,0x1E,0x00,0x00,0xEB,0x6F,0x54,0x47,0x40,0x3C, +0x4F,0x0D,0x60,0x5E,0xCA,0x80,0x84,0x0A,0x00,0x02,0x7F,0x08,0x24,0x7F,0xA0,0x1D, +0x00,0x00,0xDF,0x01,0x47,0x40,0xB3,0x40,0x7F,0x60,0x08,0x00,0x02,0x70,0xBB,0x5F, +0xF0,0x00,0x7F,0x75,0x0A,0x00,0x02,0x70,0xEB,0x6F,0x54,0x47,0x40,0xD4,0x08,0x80, +0xA4,0x0A,0x00,0x02,0x40,0xB3,0x40,0x7F,0x75,0x0A,0x00,0x02,0x70,0xEB,0x6F,0x54, +0x47,0x40,0x87,0x80,0xA7,0x0A,0x00,0x02,0x7F,0x76,0x0A,0x00,0x02,0x70,0xEB,0x6F, +0x54,0x47,0x40,0xFF,0x01,0x80,0x9F,0x0A,0x00,0x02,0x40,0x87,0x40,0x7F,0x77,0x0A, +0x00,0x02,0x70,0xEB,0x6F,0x54,0x47,0x40,0xFF,0x01,0x80,0xA3,0x0A,0x00,0x02,0x40, +0x87,0x40,0x7F,0x78,0x0A,0x00,0x02,0x70,0xEB,0x6F,0x54,0x47,0x40,0xD4,0x09,0x80, +0x98,0x0A,0x00,0x02,0x40,0x87,0x40,0x7F,0x7A,0x0A,0x00,0x02,0x70,0xEB,0x6F,0x54, +0x47,0x40,0xD4,0x01,0x80,0x98,0x0A,0x00,0x02,0x40,0x87,0x40,0x7F,0x7B,0x0A,0x00, +0x02,0x70,0x87,0x47,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F,0x2C,0x73,0x00,0x00, +0x28,0x40,0x77,0x35,0x2B,0x45,0x7F,0x31,0x87,0x47,0xE0,0x40,0xD0,0x17,0x40,0x40, +0xB0,0x4F,0x02,0x00,0x04,0x00,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F,0xC0,0x61,0x00, +0x00,0x87,0x01,0x7F,0x13,0x40,0x04,0x00,0x70,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0xEF, +0x8C,0x04,0x00,0x00,0x70,0x7B,0x45,0x2B,0x45,0x7F,0x41,0x87,0x47,0xE0,0x40,0xA0, +0x40,0x2C,0xCC,0xFC,0x7F,0xD4,0x78,0x00,0x00,0x28,0x40,0x77,0x2F,0x87,0x47,0xE0, +0x40,0xD0,0x17,0x40,0x40,0xB0,0x4F,0x02,0x00,0x05,0x00,0x40,0xA0,0x40,0x2C,0xCC, +0xFC,0x7F,0xC0,0x61,0x00,0x00,0x87,0x01,0x7F,0x13,0x40,0x04,0x00,0x70,0x84,0x4F, +0xEF,0xBE,0xED,0xFE,0xEF,0x8C,0x04,0x00,0x00,0x70,0x24,0x7F,0x37,0x1E,0x00,0x00, +0x3C,0x4F,0xEF,0xBE,0xED,0xFE,0x7F,0x78,0x08,0x00,0x02,0x77,0x5B,0x84,0x3D,0x7F, +0x64,0x08,0x00,0x02,0x70,0xA0,0x4F,0x64,0x08,0x00,0x02,0xA0,0x4F,0x0A,0x30,0x04, +0x00,0xA0,0x02,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x2C,0x5C,0x7F,0x90,0x3B, +0x00,0x00,0x87,0x01,0x7F,0x61,0x08,0x00,0x02,0x70,0xA0,0x4F,0x61,0x08,0x00,0x02, +0xA0,0x4F,0x0C,0x30,0x04,0x00,0xA0,0x01,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00, +0x84,0x4F,0x1E,0xAC,0xEB,0xAD,0x7F,0x64,0x08,0x00,0x02,0x70,0xB0,0x10,0x7F,0x5C, +0x08,0x00,0x02,0x70,0x7B,0x33,0x2B,0x45,0x7F,0x2F,0x87,0x47,0xE0,0x40,0xD0,0x17, +0x40,0x40,0xB0,0x4F,0x02,0x00,0x02,0x00,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F,0xC0, +0x61,0x00,0x00,0x87,0x01,0x7F,0x13,0x40,0x04,0x00,0x70,0x84,0x4F,0xEF,0xBE,0xED, +0xFE,0xEF,0x8C,0x04,0x00,0x00,0x70,0xF7,0x01,0x47,0x40,0x87,0x40,0x46,0xA0,0x4F, +0x3A,0x30,0x04,0x00,0xA0,0x4F,0x61,0x08,0x00,0x02,0xA0,0x01,0x2C,0xCC,0xF4,0x7F, +0x24,0x52,0x00,0x00,0x28,0x40,0x77,0x1F,0x83,0x7F,0x61,0x08,0x00,0x02,0x70,0xA0, +0x4F,0x61,0x08,0x00,0x02,0xA0,0x4F,0x3A,0x30,0x04,0x00,0xA0,0x01,0x2C,0xCC,0xF4, +0x7F,0xA0,0x52,0x00,0x00,0x3F,0x01,0x7F,0x61,0x08,0x00,0x02,0x77,0x05,0x86,0x3B, +0x44,0xA0,0x6F,0x64,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x87,0x46,0xE0,0x40, +0xA0,0x40,0x2C,0xCC,0xFC,0x7F,0x80,0x73,0x00,0x00,0x28,0x40,0x7F,0x04,0x7B,0x0E, +0x92,0x44,0x86,0xE2,0x44,0xE0,0x40,0x3C,0x3C,0x40,0x5B,0xD7,0x86,0xE2,0x44,0xE0, +0x40,0x3C,0x3C,0x40,0x5B,0x26,0x87,0x01,0x7F,0x61,0x08,0x00,0x02,0x70,0xA0,0x4F, +0x61,0x08,0x00,0x02,0xA0,0x4F,0x3A,0x30,0x04,0x00,0xA0,0x01,0x2C,0xCC,0xF4,0x7F, +0xA0,0x52,0x00,0x00,0x24,0x7F,0xA9,0x20,0x00,0x00,0x87,0x46,0xE0,0x40,0xA0,0x40, +0x2C,0xCC,0xFC,0x7F,0x28,0x6E,0x00,0x00,0x28,0x40,0x77,0x39,0xF0,0x02,0x7F,0x7C, +0x0A,0x00,0x02,0x40,0x87,0x46,0xE0,0x41,0xD0,0x17,0x41,0x41,0xB0,0x41,0x40,0xA0, +0x40,0x2C,0xCC,0xFC,0x7F,0xC0,0x61,0x00,0x00,0x87,0x01,0x7F,0x13,0x40,0x04,0x00, +0x70,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0xEF,0x8C,0x04,0x00,0x00,0x70,0x24,0x7F,0xA9, +0x20,0x00,0x00,0xEB,0x6F,0x54,0x46,0x40,0x3C,0x4F,0x0D,0x60,0x5E,0xCA,0x80,0x84, +0x0A,0x00,0x02,0x7F,0x35,0x87,0x46,0xE0,0x40,0xD0,0x17,0x40,0x40,0xB0,0x4F,0x02, +0x00,0x02,0x00,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F,0xC0,0x61,0x00,0x00,0x87,0x01, +0x7F,0x13,0x40,0x04,0x00,0x70,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0xEF,0x8C,0x04,0x00, +0x00,0x70,0x24,0x7F,0xA9,0x20,0x00,0x00,0xDF,0x01,0x46,0x40,0xB3,0x40,0x7F,0x60, +0x08,0x00,0x02,0x70,0x80,0x43,0xEB,0x6F,0x54,0x46,0x40,0xEB,0x6F,0x54,0x47,0x41, +0x3C,0x81,0xA4,0x0A,0x00,0x02,0x80,0xA4,0x0A,0x00,0x02,0x5F,0x35,0xBB,0x5F,0xF0, +0x00,0x7F,0x75,0x0A,0x00,0x02,0x70,0xEB,0x6F,0x54,0x46,0x40,0xD4,0x08,0x80,0xA4, +0x0A,0x00,0x02,0x40,0xB3,0x40,0x7F,0x75,0x0A,0x00,0x02,0x70,0xEB,0x6F,0x54,0x46, +0x40,0x87,0x80,0xA7,0x0A,0x00,0x02,0x7F,0x76,0x0A,0x00,0x02,0x70,0x84,0x01,0x43, +0xEB,0x6F,0x54,0x46,0x40,0xEB,0x6F,0x54,0x47,0x41,0x3C,0x81,0x9C,0x0A,0x00,0x02, +0x80,0x9C,0x0A,0x00,0x02,0x5F,0x1A,0xEB,0x6F,0x54,0x46,0x40,0xFF,0x01,0x80,0x9F, +0x0A,0x00,0x02,0x40,0x87,0x40,0x7F,0x77,0x0A,0x00,0x02,0x70,0x84,0x01,0x43,0xEB, +0x6F,0x54,0x46,0x40,0xEB,0x6F,0x54,0x47,0x41,0x3C,0x81,0xA0,0x0A,0x00,0x02,0x80, +0xA0,0x0A,0x00,0x02,0x5F,0x1A,0xEB,0x6F,0x54,0x46,0x40,0xFF,0x01,0x80,0xA3,0x0A, +0x00,0x02,0x40,0x87,0x40,0x7F,0x78,0x0A,0x00,0x02,0x70,0x84,0x01,0x43,0xEB,0x6F, +0x54,0x46,0x40,0xEB,0x6F,0x54,0x47,0x41,0x3C,0x81,0x98,0x0A,0x00,0x02,0x80,0x98, +0x0A,0x00,0x02,0x5F,0x2F,0xEB,0x6F,0x54,0x46,0x40,0xD4,0x09,0x80,0x98,0x0A,0x00, +0x02,0x40,0x87,0x40,0x7F,0x7A,0x0A,0x00,0x02,0x70,0xEB,0x6F,0x54,0x46,0x40,0xD4, +0x01,0x80,0x98,0x0A,0x00,0x02,0x40,0x87,0x40,0x7F,0x7B,0x0A,0x00,0x02,0x70,0x84, +0x01,0x43,0x28,0x43,0x7F,0x45,0x87,0x46,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F, +0x2C,0x73,0x00,0x00,0x28,0x40,0x77,0x33,0x2B,0x45,0x7F,0x2F,0x87,0x46,0xE0,0x40, +0xD0,0x17,0x40,0x40,0xB0,0x4F,0x02,0x00,0x04,0x00,0x40,0xA0,0x40,0x2C,0xCC,0xFC, +0x7F,0xC0,0x61,0x00,0x00,0x87,0x01,0x7F,0x13,0x40,0x04,0x00,0x70,0x84,0x4F,0xEF, +0xBE,0xED,0xFE,0xEF,0x8C,0x04,0x00,0x00,0x70,0x2C,0x5C,0x7F,0xE0,0x5D,0x00,0x00, +0x3F,0x02,0x7F,0x60,0x08,0x00,0x02,0x4F,0x12,0x87,0x7F,0x60,0x08,0x00,0x02,0xE2, +0x40,0xBE,0x01,0x40,0x86,0x40,0x44,0x7B,0x0D,0x87,0x7F,0x60,0x08,0x00,0x02,0xE2, +0x40,0x86,0x40,0x44,0xDC,0x04,0x7F,0x90,0x04,0x00,0x00,0x40,0x86,0xE2,0x44,0xE0, +0x41,0x90,0x41,0xC8,0x03,0x00,0x41,0x50,0x70,0xDC,0x08,0x7F,0x90,0x04,0x00,0x00, +0x40,0x84,0xEF,0xE8,0x04,0x00,0x00,0x50,0x70,0xDC,0x04,0x7F,0x90,0x04,0x00,0x00, +0x40,0xCC,0x03,0x00,0x50,0x40,0xA8,0x0C,0x40,0x9C,0x40,0xEF,0xE8,0x04,0x00,0x00, +0x70,0xDC,0x08,0x7F,0x90,0x04,0x00,0x00,0x40,0x86,0x01,0xD0,0x00,0x70,0xDC,0x08, +0x7F,0x90,0x04,0x00,0x00,0x40,0xDC,0x02,0x50,0x40,0xA0,0x40,0xA0,0x4F,0xD1,0x05, +0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xB0,0x7F,0x00,0x00,0x3B,0x7F,0x60,0x08,0x00,0x02, +0x01,0x7F,0x23,0x3C,0x4F,0x0D,0x60,0x5E,0xCA,0x7F,0x84,0x0A,0x00,0x02,0x77,0x16, +0xDC,0x08,0x7F,0x90,0x04,0x00,0x00,0x40,0x84,0x50,0x40,0x86,0x7F,0x82,0x0A,0x00, +0x02,0xC0,0x0C,0x70,0x3B,0x7F,0x60,0x08,0x00,0x02,0x02,0x7F,0x23,0x3C,0x4F,0x0D, +0x60,0x5E,0xCA,0x7F,0xD8,0x0A,0x00,0x02,0x77,0x16,0xDC,0x08,0x7F,0x90,0x04,0x00, +0x00,0x40,0x84,0x50,0x40,0x86,0x7F,0xD6,0x0A,0x00,0x02,0xC0,0x18,0x70,0x24,0x7F, +0xF0,0x65,0x00,0x00,0x04,0x59,0x4C,0x20,0x48,0x20,0x47,0x20,0x46,0x20,0x45,0x20, +0x44,0x20,0x43,0x20,0x49,0x08,0x70,0x70,0x10,0x45,0x9C,0x4F,0x00,0x00,0x00,0x00, +0x4C,0x84,0x4F,0x28,0x0B,0x00,0x02,0x48,0x84,0x4F,0xE4,0x05,0x00,0x00,0x47,0x80, +0x45,0x7B,0x12,0x84,0x48,0x40,0x90,0x48,0x84,0x47,0x41,0x90,0x47,0x87,0x51,0x50, +0x70,0x90,0x45,0x3C,0x6F,0x44,0x45,0x5B,0xEC,0x84,0x4F,0x80,0xE1,0x81,0x00,0x7F, +0x78,0x0B,0x00,0x02,0x70,0x84,0x4F,0xF8,0x41,0x00,0x00,0x7F,0x7C,0x0B,0x00,0x02, +0x70,0x84,0x4F,0xE8,0x0E,0x00,0x02,0x7F,0x80,0x0B,0x00,0x02,0x70,0x84,0x4F,0xE8, +0x0E,0x00,0x02,0x7F,0x90,0x0B,0x00,0x02,0x70,0x84,0x4F,0xE8,0x10,0x00,0x02,0x7F, +0x94,0x0B,0x00,0x02,0x70,0x80,0x7F,0xC4,0x0B,0x00,0x02,0x70,0x80,0x45,0x7B,0x3A, +0xE8,0x6F,0x50,0x45,0x40,0x9C,0x4F,0xC8,0x0B,0x00,0x02,0x40,0x84,0x40,0x46,0x84, +0x4F,0x80,0xE1,0x81,0x00,0x56,0x70,0x84,0x4F,0xE8,0x10,0x00,0x02,0xC6,0x08,0x70, +0x84,0x4F,0xE8,0x10,0x00,0x02,0xC6,0x18,0x70,0x84,0x4F,0xE8,0x11,0x00,0x02,0xC6, +0x1C,0x70,0x80,0xC6,0x4C,0x70,0x90,0x45,0x3C,0x09,0x45,0x4B,0xC5,0x84,0x4F,0xA0, +0x40,0x00,0x00,0x7F,0xCC,0x0B,0x00,0x02,0x70,0x84,0x4F,0xC6,0x40,0x00,0x00,0x7F, +0x1C,0x0C,0x00,0x02,0x70,0x84,0x4F,0xEC,0x40,0x00,0x00,0x7F,0x6C,0x0C,0x00,0x02, +0x70,0x84,0x4F,0x12,0x41,0x00,0x00,0x7F,0xBC,0x0C,0x00,0x02,0x70,0x84,0x4F,0x38, +0x41,0x00,0x00,0x7F,0x0C,0x0D,0x00,0x02,0x70,0x84,0x4F,0x5E,0x41,0x00,0x00,0x7F, +0x5C,0x0D,0x00,0x02,0x70,0x84,0x4F,0x84,0x41,0x00,0x00,0x7F,0xAC,0x0D,0x00,0x02, +0x70,0x84,0x4F,0xAA,0x41,0x00,0x00,0x7F,0xFC,0x0D,0x00,0x02,0x70,0x84,0x4F,0xD0, +0x41,0x00,0x00,0x7F,0x4C,0x0E,0x00,0x02,0x70,0x84,0x4F,0x80,0xE1,0x81,0x00,0x7F, +0x98,0x0E,0x00,0x02,0x70,0x84,0x4F,0x8E,0x42,0x00,0x00,0x7F,0x9C,0x0E,0x00,0x02, +0x70,0x84,0x4F,0xE8,0x0E,0x00,0x02,0x7F,0xA0,0x0E,0x00,0x02,0x70,0x84,0x4F,0xE8, +0x0E,0x00,0x02,0x7F,0xB0,0x0E,0x00,0x02,0x70,0x84,0x4F,0xE8,0x10,0x00,0x02,0x7F, +0xB4,0x0E,0x00,0x02,0x70,0x80,0x7F,0xE4,0x0E,0x00,0x02,0x70,0x04,0x7F,0x28,0x0B, +0x00,0x02,0x4D,0x24,0x7F,0x31,0x23,0x00,0x00,0x04,0xC9,0xF8,0x4C,0x20,0x48,0x20, +0x47,0x20,0x46,0x20,0x45,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F,0x08,0x00,0x00,0x00, +0x4C,0x84,0x4F,0x00,0x90,0x04,0x00,0x7F,0xE8,0x11,0x00,0x02,0x70,0x2C,0x5C,0x7F, +0x90,0x3B,0x00,0x00,0x2C,0x5C,0xAF,0x7C,0x03,0x87,0x40,0x59,0x70,0x2B,0x59,0x77, +0x0A,0x24,0x7F,0x3E,0x19,0x00,0x00,0x7B,0x0D,0x3F,0x02,0x59,0x77,0x08,0x24,0x7F, +0xD5,0x12,0x00,0x00,0xB0,0x4F,0x00,0x00,0x00,0x80,0x7F,0x5C,0x08,0x00,0x02,0x70, +0x2C,0x5C,0x7F,0xE0,0x5D,0x00,0x00,0x2C,0x5C,0x7F,0x7C,0x29,0x00,0x00,0x84,0x40, +0xEF,0xE4,0x04,0x00,0x00,0x70,0x84,0x4F,0x14,0x15,0x00,0x02,0xEF,0xE8,0x04,0x00, +0x00,0x70,0x9C,0x20,0xEF,0xE8,0x04,0x00,0x00,0x70,0x87,0x00,0xE0,0x40,0xC8,0x03, +0x0C,0x40,0xEF,0x90,0x04,0x00,0x00,0x70,0x87,0x01,0xE0,0x40,0xC8,0x0F,0x10,0x40, +0xEF,0x90,0x04,0x00,0x00,0x70,0xDC,0x04,0x7F,0x90,0x04,0x00,0x00,0x40,0x87,0x01, +0xE0,0x41,0xC8,0x00,0x05,0x41,0x50,0x70,0xDC,0x04,0x7F,0x90,0x04,0x00,0x00,0x40, +0x87,0x01,0xE0,0x41,0xC8,0x00,0x06,0x41,0x50,0x70,0xDC,0x0C,0x7F,0x90,0x04,0x00, +0x00,0x40,0xA0,0x40,0xA0,0x4F,0x28,0x06,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xB0,0x7F, +0x00,0x00,0xDC,0x04,0x7F,0x90,0x04,0x00,0x00,0x40,0x87,0x01,0xE0,0x41,0xC8,0x00, +0x07,0x41,0x50,0x70,0xDC,0x04,0x7F,0x90,0x04,0x00,0x00,0x40,0x87,0x01,0xE0,0x41, +0xC8,0x00,0x09,0x41,0x50,0x70,0x84,0x4F,0xA4,0x65,0x00,0x00,0xEF,0x98,0x04,0x00, +0x00,0x70,0x84,0x4F,0xA4,0x65,0x00,0x00,0xEF,0x0C,0x05,0x00,0x00,0x70,0x2C,0x5C, +0x7F,0x72,0x5F,0x00,0x00,0x87,0x01,0x7F,0x1F,0x40,0x04,0x00,0x70,0x87,0x01,0xEF, +0xE0,0x04,0x00,0x00,0x70,0x83,0x7F,0xF1,0x11,0x00,0x02,0x70,0x84,0x4F,0xE0,0x25, +0x00,0x00,0xEF,0x98,0x04,0x00,0x00,0x70,0x84,0x4F,0xE0,0x25,0x00,0x00,0xEF,0x0C, +0x05,0x00,0x00,0x70,0x2C,0x5C,0xEF,0xC0,0x04,0x00,0x00,0x24,0x7F,0x3A,0x25,0x00, +0x00,0x87,0x7F,0xF1,0x11,0x00,0x02,0xE0,0x40,0xD0,0x15,0x40,0x40,0x83,0xC0,0x05, +0x70,0xA0,0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x87,0xEF,0xE0,0x04,0x00, +0x00,0xE0,0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0x87,0x7F, +0xF1,0x11,0x00,0x02,0xE0,0x41,0xD0,0x15,0x41,0x41,0x87,0xC1,0x01,0xE0,0x42,0xC8, +0x0F,0x10,0x42,0x50,0x70,0x9C,0x20,0xEF,0xE8,0x04,0x00,0x00,0x70,0x87,0xEF,0xE0, +0x04,0x00,0x00,0x40,0x93,0xEF,0xE0,0x04,0x00,0x00,0x70,0x87,0x40,0xE0,0x40,0xD0, +0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0x87,0x7F,0xF1,0x11,0x00,0x02, +0xE0,0x41,0xC8,0x03,0x0C,0x41,0x50,0x70,0x87,0x7F,0xF1,0x11,0x00,0x02,0xE0,0x40, +0xD0,0x15,0x40,0x40,0x87,0x50,0xE2,0x40,0x86,0x40,0x62,0x70,0x97,0xEF,0xE0,0x04, +0x00,0x00,0x70,0x87,0xEF,0xE0,0x04,0x00,0x00,0xE0,0x40,0xD0,0x05,0x40,0x40,0x9C, +0x7F,0x90,0x04,0x00,0x00,0x40,0x84,0x40,0x64,0x70,0xCC,0x0F,0x10,0xD9,0x04,0x40, +0x86,0xE2,0x62,0xE0,0x41,0xD0,0x08,0x41,0x41,0xB0,0x41,0x40,0xC8,0x0F,0x10,0x40, +0xD9,0x04,0x70,0x93,0xEF,0xE0,0x04,0x00,0x00,0x70,0x93,0x7F,0xF1,0x11,0x00,0x02, +0x70,0x3F,0x0C,0x7F,0xF1,0x11,0x00,0x02,0x4E,0x29,0xFF,0x84,0x4F,0xA4,0x65,0x00, +0x00,0xEF,0x98,0x04,0x00,0x00,0x70,0x84,0x4F,0xA4,0x65,0x00,0x00,0xEF,0x0C,0x05, +0x00,0x00,0x70,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x2B,0x50,0x7F,0x28,0x2C, +0x5C,0x7F,0x72,0x5F,0x00,0x00,0x2C,0x5C,0x7F,0x78,0x63,0x00,0x00,0x3C,0x01,0x40, +0x77,0x15,0xB0,0x4F,0x00,0x00,0x00,0x80,0x7F,0x5C,0x08,0x00,0x02,0x70,0x2C,0x5C, +0x7F,0xE0,0x5D,0x00,0x00,0x3C,0x4F,0xEF,0xBE,0xED,0xFE,0x7F,0x64,0x08,0x00,0x02, +0x7F,0x2C,0x3C,0x4F,0x0D,0xF0,0xAD,0x8B,0x7F,0x64,0x08,0x00,0x02,0x7F,0x1F,0x3C, +0x4F,0x1E,0xAC,0xEB,0xAD,0x7F,0x64,0x08,0x00,0x02,0x7F,0x12,0x2C,0x5C,0xAF,0x80, +0x00,0x28,0x40,0x77,0x09,0x2C,0x5C,0x7F,0xE0,0x5D,0x00,0x00,0x2C,0x5C,0x7F,0x72, +0x5F,0x00,0x00,0x24,0x7F,0x01,0x1A,0x00,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08, +0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x86,0xE2,0x7F,0x02,0x40,0x04,0x00, +0xE0,0x40,0x38,0x40,0x4F,0x00,0x80,0x00,0x00,0x7F,0x0C,0x87,0x01,0x7F,0x27,0x40, +0x04,0x00,0x70,0x7B,0x32,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0xEF,0x8C,0x04,0x00,0x00, +0x70,0x2C,0x5C,0x7F,0x72,0x5F,0x00,0x00,0x87,0x01,0x7F,0x1F,0x40,0x04,0x00,0x70, +0xB0,0x01,0x7F,0x5C,0x08,0x00,0x02,0x70,0x2C,0x5C,0x7F,0xE0,0x5D,0x00,0x00,0x24, +0x7F,0xF0,0x65,0x00,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x10,0x47,0x9C,0x4F, +0x00,0x00,0x00,0x00,0x4C,0x84,0x4F,0x00,0x40,0x00,0x02,0x48,0x84,0x4F,0x00,0x00, +0x04,0x02,0x47,0x7B,0x3B,0x87,0x5F,0xFF,0x00,0x58,0x70,0x3F,0x5F,0xFF,0x00,0x58, +0x7F,0x04,0x7B,0x31,0x87,0x5F,0xAA,0x00,0x58,0x70,0x3F,0x5F,0xAA,0x00,0x58,0x7F, +0x04,0x7B,0x22,0x87,0x6F,0x55,0x58,0x70,0x3F,0x6F,0x55,0x58,0x7F,0x04,0x7B,0x15, +0x83,0x58,0x70,0x84,0x48,0x40,0x90,0x48,0x2B,0x50,0x7F,0x04,0x7B,0x07,0x3C,0x47, +0x48,0x5B,0xC4,0x3C,0x47,0x48,0x53,0x1A,0xB0,0x08,0x7F,0x5C,0x08,0x00,0x02,0x70, +0x84,0x4F,0xEF,0xBE,0xED,0xFE,0x7F,0x64,0x08,0x00,0x02,0x70,0x80,0x40,0x7B,0x07, +0x84,0x01,0x40,0x7B,0x02,0x04,0xC9,0xF0,0x4C,0x20,0x48,0x20,0x47,0x20,0x49,0x08, +0x10,0x49,0x9C,0x4F,0x04,0x00,0x00,0x00,0x4C,0x87,0x20,0x7F,0x02,0x90,0x04,0x00, +0x70,0x87,0x30,0x7F,0x02,0x90,0x04,0x00,0x70,0x87,0x10,0x7F,0x02,0x90,0x04,0x00, +0x70,0x87,0x7F,0x00,0x90,0x04,0x00,0xE2,0x40,0x86,0x40,0x59,0x70,0xB3,0x5F,0x80, +0x00,0x7F,0x00,0x90,0x04,0x00,0x70,0x87,0x05,0x7F,0x02,0x90,0x04,0x00,0x70,0xA0, +0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x87,0x6F,0x55,0x7F,0x03,0x90,0x04, +0x00,0x70,0xA0,0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x3B,0x7F,0x01,0x90, +0x04,0x00,0x01,0x77,0x0A,0x80,0x40,0x24,0x7F,0x73,0x29,0x00,0x00,0x3F,0x6F,0x55, +0x7F,0x03,0x90,0x04,0x00,0x7F,0x0A,0x80,0x40,0x24,0x7F,0x73,0x29,0x00,0x00,0x3B, +0x7F,0x01,0x90,0x04,0x00,0x01,0x7F,0x0A,0x80,0x40,0x24,0x7F,0x73,0x29,0x00,0x00, +0x87,0x5F,0xAA,0x00,0x7F,0x03,0x90,0x04,0x00,0x70,0xA0,0x14,0x2C,0xCC,0xFC,0xEF, +0x28,0x05,0x00,0x00,0x3B,0x7F,0x01,0x90,0x04,0x00,0x01,0x77,0x0A,0x80,0x40,0x24, +0x7F,0x73,0x29,0x00,0x00,0x3F,0x5F,0xAA,0x00,0x7F,0x03,0x90,0x04,0x00,0x7F,0x0A, +0x80,0x40,0x24,0x7F,0x73,0x29,0x00,0x00,0x87,0x20,0x7F,0x02,0x90,0x04,0x00,0x70, +0x87,0x30,0x7F,0x02,0x90,0x04,0x00,0x70,0x87,0x10,0x7F,0x02,0x90,0x04,0x00,0x70, +0x87,0x7F,0x00,0x90,0x04,0x00,0xE2,0x40,0x86,0x40,0x59,0x70,0xBB,0x6F,0x7F,0x7F, +0x00,0x90,0x04,0x00,0x70,0x87,0x05,0x7F,0x02,0x90,0x04,0x00,0x70,0xA0,0x14,0x2C, +0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x87,0x20,0x7F,0x0A,0x90,0x04,0x00,0x70,0x87, +0x30,0x7F,0x0A,0x90,0x04,0x00,0x70,0x87,0x10,0x7F,0x0A,0x90,0x04,0x00,0x70,0x87, +0x7F,0x08,0x90,0x04,0x00,0xE2,0x40,0x86,0x40,0x59,0x70,0xB3,0x5F,0x80,0x00,0x7F, +0x08,0x90,0x04,0x00,0x70,0x87,0x05,0x7F,0x0A,0x90,0x04,0x00,0x70,0xA0,0x14,0x2C, +0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x87,0x6F,0x55,0x7F,0x0B,0x90,0x04,0x00,0x70, +0xA0,0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x3B,0x7F,0x09,0x90,0x04,0x00, +0x01,0x77,0x0A,0x80,0x40,0x24,0x7F,0x73,0x29,0x00,0x00,0x3F,0x6F,0x55,0x7F,0x0B, +0x90,0x04,0x00,0x7F,0x0A,0x80,0x40,0x24,0x7F,0x73,0x29,0x00,0x00,0x3B,0x7F,0x09, +0x90,0x04,0x00,0x01,0x7F,0x0A,0x80,0x40,0x24,0x7F,0x73,0x29,0x00,0x00,0x87,0x5F, +0xAA,0x00,0x7F,0x0B,0x90,0x04,0x00,0x70,0xA0,0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05, +0x00,0x00,0x3B,0x7F,0x09,0x90,0x04,0x00,0x01,0x77,0x0A,0x80,0x40,0x24,0x7F,0x73, +0x29,0x00,0x00,0x3F,0x5F,0xAA,0x00,0x7F,0x0B,0x90,0x04,0x00,0x7F,0x0A,0x80,0x40, +0x24,0x7F,0x73,0x29,0x00,0x00,0x87,0x20,0x7F,0x0A,0x90,0x04,0x00,0x70,0x87,0x30, +0x7F,0x0A,0x90,0x04,0x00,0x70,0x87,0x10,0x7F,0x0A,0x90,0x04,0x00,0x70,0x87,0x7F, +0x08,0x90,0x04,0x00,0xE0,0x40,0xD0,0x08,0x40,0x40,0x86,0xE2,0x40,0xE0,0x40,0x87, +0x7F,0x08,0x90,0x04,0x00,0xE0,0x41,0x84,0x4F,0x7F,0xFF,0x00,0x00,0x42,0x86,0xE2, +0x42,0xE0,0x42,0xB8,0x42,0x41,0x86,0xE2,0x41,0xE0,0x41,0xB0,0x41,0x40,0x86,0x40, +0x59,0x70,0x87,0x10,0x7F,0x02,0x90,0x04,0x00,0x70,0x87,0x10,0x7F,0x0A,0x90,0x04, +0x00,0x70,0x87,0x7F,0x00,0x90,0x04,0x00,0x7F,0x08,0x90,0x04,0x00,0x70,0x87,0x7F, +0x00,0x90,0x04,0x00,0x7F,0x08,0x90,0x04,0x00,0x70,0x87,0x05,0x7F,0x0A,0x90,0x04, +0x00,0x70,0xA0,0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x87,0x20,0x7F,0x03, +0x90,0x04,0x00,0x70,0xA0,0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x3B,0x7F, +0x09,0x90,0x04,0x00,0x01,0x7F,0x10,0x3F,0x20,0x7F,0x0B,0x90,0x04,0x00,0x77,0x07, +0x84,0x02,0x40,0x7B,0x40,0x87,0x20,0x7F,0x0A,0x90,0x04,0x00,0x70,0x87,0x30,0x7F, +0x0A,0x90,0x04,0x00,0x70,0x87,0x10,0x7F,0x0A,0x90,0x04,0x00,0x70,0x86,0xE2,0x59, +0xE0,0x40,0xD4,0x08,0x40,0x40,0x87,0x40,0x7F,0x08,0x90,0x04,0x00,0x70,0x87,0x61, +0x7F,0x08,0x90,0x04,0x00,0x70,0x87,0x05,0x7F,0x0A,0x90,0x04,0x00,0x70,0x84,0x01, +0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x10,0x45,0x9C,0x4F, +0x00,0x00,0x00,0x00,0x4C,0x84,0x4F,0xC4,0x2A,0x00,0x00,0x7F,0xF4,0x11,0x00,0x02, +0x70,0x84,0x4F,0xDC,0x2A,0x00,0x00,0x7F,0xF8,0x11,0x00,0x02,0x70,0x83,0xEF,0xC4, +0x04,0x00,0x00,0x70,0x83,0x7F,0xF2,0x11,0x00,0x02,0x70,0x80,0x46,0x3B,0x7F,0x03, +0xC0,0x04,0x00,0x01,0x7F,0x0E,0x84,0x4F,0x00,0x00,0x10,0x00,0x48,0x84,0x48,0x40, +0x7B,0x0C,0x84,0x4F,0x00,0x00,0x04,0x00,0x48,0x84,0x48,0x40,0x3B,0x7F,0x03,0xC0, +0x04,0x00,0x02,0x7F,0x06,0xD0,0x01,0x48,0x48,0x2C,0x5C,0xEF,0xC0,0x04,0x00,0x00, +0x2B,0x7F,0xF2,0x11,0x00,0x02,0x7F,0x08,0x24,0x7F,0x97,0x2A,0x00,0x00,0x3C,0x4F, +0xD0,0xF1,0x02,0x3B,0x7F,0x6C,0x08,0x00,0x02,0x77,0x09,0x84,0x88,0x00,0x00,0x00, +0x02,0x47,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0x88,0x00,0x00,0x00,0x02,0x70,0x3C,0x4F, +0xEF,0xBE,0xED,0xFE,0x88,0x00,0x00,0x00,0x02,0x77,0x05,0x84,0x01,0x46,0x84,0x47, +0x88,0x00,0x00,0x00,0x02,0x70,0x28,0x46,0x7F,0x6F,0x3C,0x4F,0x00,0x00,0x20,0x00, +0x48,0x77,0x66,0xE8,0x03,0x48,0x40,0xAC,0x04,0x40,0x70,0x84,0x40,0x48,0xD0,0x01, +0x48,0x40,0x84,0x40,0x45,0x83,0x7F,0xF2,0x11,0x00,0x02,0x70,0x2C,0x5C,0xEF,0xC0, +0x04,0x00,0x00,0x2B,0x7F,0xF2,0x11,0x00,0x02,0x77,0x3E,0x3C,0x4F,0xD0,0xF1,0x02, +0x3B,0x7F,0x6C,0x08,0x00,0x02,0x77,0x09,0x84,0x85,0x00,0x00,0x00,0x02,0x47,0x84, +0x4F,0xEF,0xBE,0xED,0xFE,0x85,0x00,0x00,0x00,0x02,0x70,0x3C,0x4F,0xEF,0xBE,0xED, +0xFE,0x85,0x00,0x00,0x00,0x02,0x77,0x09,0x84,0x4F,0x00,0x00,0x20,0x00,0x48,0x84, +0x47,0x85,0x00,0x00,0x00,0x02,0x70,0x84,0x4F,0xA4,0x65,0x00,0x00,0x7F,0xF4,0x11, +0x00,0x02,0x70,0x84,0x4F,0x04,0x65,0x00,0x00,0x7F,0xF8,0x11,0x00,0x02,0x70,0xD0, +0x46,0x48,0x40,0x7B,0x02,0x04,0xC9,0xF8,0x4C,0x20,0x48,0x20,0x47,0x20,0x46,0x20, +0x45,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x87,0x01,0x7F, +0xF2,0x11,0x00,0x02,0x70,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F, +0x00,0x00,0x00,0x00,0x4C,0x84,0x4F,0x00,0xE1,0x81,0x00,0xCD,0x0C,0x70,0x04,0xC9, +0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x70,0x84,0xCC,0xF8,0x7F,0xFC,0x11,0x00,0x02, +0x70,0x08,0x70,0x70,0x10,0x49,0x9C,0x4F,0xB8,0x01,0x00,0x00,0x4C,0xA0,0x4F,0x0D, +0x30,0x04,0x00,0xE0,0x59,0xA0,0x2D,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0xA0, +0x4F,0x2C,0x06,0x00,0x00,0xE0,0x59,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0xA0, +0x00,0x2C,0xCC,0xFC,0xEF,0x40,0x05,0x00,0x00,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00, +0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F,0x60,0x43,0x00,0x00,0x3C,0xFF,0x40,0x77,0x20, +0xA0,0x01,0x2C,0xCC,0xFC,0xEF,0x40,0x05,0x00,0x00,0xA0,0x4F,0x57,0x06,0x00,0x00, +0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x24,0x7F,0xAB,0x3A,0x00,0x00,0xA0,0x01, +0x2C,0xCC,0xFC,0xEF,0x40,0x05,0x00,0x00,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00,0x40, +0xA0,0x40,0xA0,0x4F,0x59,0x06,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0x68,0x7F,0x00,0x00, +0x28,0x40,0x7F,0x08,0x24,0x7F,0x6B,0x2C,0x00,0x00,0xA0,0x4F,0x60,0x06,0x00,0x00, +0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xE0,0xC9,0x50,0x2C,0xCC,0xFC,0xAF,0x09, +0x0F,0x28,0x40,0x77,0x07,0x2C,0x5C,0xAF,0x59,0x0F,0xA0,0x4F,0x00,0x30,0x04,0x00, +0xE0,0xC9,0x5A,0xA0,0x09,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0xE0,0xC9,0x50, +0xE0,0xC9,0x5A,0x2C,0xCC,0xF8,0x7F,0x68,0x7F,0x00,0x00,0x28,0x40,0x7F,0x07,0x2C, +0x5C,0xAF,0x2F,0x0F,0xA0,0x4F,0x76,0x06,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44, +0x00,0x00,0xE0,0x59,0x2C,0xCC,0xFC,0xAF,0xC0,0x0E,0x28,0x40,0x77,0x07,0x2C,0x5C, +0xAF,0x10,0x0F,0xA0,0x4F,0x8C,0x06,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00, +0x00,0xE0,0xC9,0x50,0x2C,0xCC,0xFC,0xAF,0xA0,0x0E,0x28,0x40,0x77,0x07,0x2C,0x5C, +0xAF,0xF0,0x0E,0xE0,0xC9,0x50,0xE0,0x59,0x2C,0xCC,0xF8,0x7F,0x68,0x7F,0x00,0x00, +0x28,0x40,0x7F,0x07,0x2C,0x5C,0xAF,0xDA,0x0E,0xA0,0x4F,0x9C,0x06,0x00,0x00,0x2C, +0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xE0,0x59,0xA0,0x4F,0x00,0x30,0x04,0x00,0xE0, +0x59,0x2C,0xCC,0xFC,0x7F,0x98,0x7F,0x00,0x00,0x90,0x40,0xA0,0x40,0x2C,0xCC,0xF4, +0x7F,0xA0,0x52,0x00,0x00,0x24,0x7F,0xA8,0x3A,0x00,0x00,0xDC,0x02,0x7F,0xA0,0x04, +0x00,0x00,0x40,0xA0,0x40,0xA0,0x4F,0x9E,0x06,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0x68, +0x7F,0x00,0x00,0x28,0x40,0x7F,0x08,0x24,0x7F,0x52,0x2D,0x00,0x00,0xA0,0x4F,0xA5, +0x06,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x83,0x59,0x70,0x7B,0x26, +0xA0,0x4F,0xEF,0x06,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xE0,0x59, +0x2C,0xCC,0xFC,0x7F,0x60,0x43,0x00,0x00,0x3F,0x6F,0x71,0x59,0x77,0x08,0x24,0x7F, +0xAB,0x3A,0x00,0x00,0xE0,0x59,0xA0,0x4F,0xEC,0x06,0x00,0x00,0x2C,0xCC,0xF8,0x7F, +0x68,0x7F,0x00,0x00,0x28,0x40,0x77,0xCA,0xDC,0x03,0x7F,0x08,0x05,0x00,0x00,0x40, +0x87,0x50,0xC9,0x5A,0x70,0xDC,0x07,0x7F,0x08,0x05,0x00,0x00,0x40,0x87,0x50,0xC9, +0x5B,0x70,0xDC,0x0B,0x7F,0x08,0x05,0x00,0x00,0x40,0x87,0x50,0xC9,0x5C,0x70,0xDC, +0x0F,0x7F,0x08,0x05,0x00,0x00,0x40,0x87,0x50,0xC9,0x5D,0x70,0xA0,0x00,0xE0,0xC9, +0x5A,0xA0,0x01,0xA0,0x03,0x2C,0xCC,0xF0,0x7F,0x2C,0x7B,0x00,0x00,0x28,0x40,0x77, +0x1F,0xB0,0x20,0x7F,0x5C,0x08,0x00,0x02,0x70,0x2C,0x5C,0x7F,0xE0,0x5D,0x00,0x00, +0xA0,0x4F,0xEF,0xBE,0xED,0xFE,0x2C,0xCC,0xFC,0x7F,0x22,0x63,0x00,0x00,0xA0,0x4F, +0x27,0x07,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x24,0x7F,0xA8,0x3A, +0x00,0x00,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00,0x40,0xA0,0x40,0xA0,0x4F,0x4A,0x07, +0x00,0x00,0x2C,0xCC,0xF8,0x7F,0x68,0x7F,0x00,0x00,0x28,0x40,0x77,0x1D,0x2C,0x5C, +0x7F,0x00,0x40,0x00,0x02,0xA0,0x4F,0xEF,0xBE,0xED,0xFE,0x2C,0xCC,0xFC,0x7F,0x22, +0x63,0x00,0x00,0x24,0x7F,0xA8,0x3A,0x00,0x00,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00, +0x40,0xA0,0x40,0xA0,0x4F,0x52,0x07,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0x68,0x7F,0x00, +0x00,0x28,0x40,0x7F,0x08,0x24,0x7F,0x38,0x2E,0x00,0x00,0xA0,0x4F,0x5A,0x07,0x00, +0x00,0xA0,0x4F,0x58,0x11,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0xA0, +0x4F,0x68,0x07,0x00,0x00,0xA0,0x7F,0xF0,0x7F,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xE4, +0x44,0x00,0x00,0xA0,0x4F,0x76,0x07,0x00,0x00,0xA0,0x4F,0x68,0x11,0x00,0x00,0xA0, +0x4F,0x64,0x11,0x00,0x00,0x2C,0xCC,0xF4,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0x8C, +0x07,0x00,0x00,0x87,0x7F,0xF3,0x7F,0x00,0x00,0xE0,0x40,0xD0,0x08,0x40,0x40,0x87, +0x7F,0xF7,0x7F,0x00,0x00,0xE0,0x41,0xB0,0x41,0x40,0xD0,0x08,0x40,0x40,0x87,0x7F, +0xFB,0x7F,0x00,0x00,0xE0,0x41,0xB0,0x41,0x40,0xD0,0x08,0x40,0x40,0x87,0x7F,0xFF, +0x7F,0x00,0x00,0xE0,0x41,0xB0,0x41,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44, +0x00,0x00,0x24,0x7F,0xA8,0x3A,0x00,0x00,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00,0x40, +0xA0,0x40,0xA0,0x4F,0xA3,0x07,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0x68,0x7F,0x00,0x00, +0x28,0x40,0x77,0x08,0x24,0x7F,0xAB,0x3A,0x00,0x00,0xDC,0x02,0x7F,0xA0,0x04,0x00, +0x00,0x40,0xA0,0x40,0xA0,0x4F,0xA5,0x07,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0x68,0x7F, +0x00,0x00,0x28,0x40,0x77,0x0F,0x2C,0x5C,0x7F,0x14,0x4E,0x00,0x00,0x24,0x7F,0xA8, +0x3A,0x00,0x00,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00,0x40,0xA0,0x40,0xA0,0x4F,0xA9, +0x07,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0x68,0x7F,0x00,0x00,0x28,0x40,0x77,0x0F,0x2C, +0x5C,0x7F,0xE6,0x5F,0x00,0x00,0x24,0x7F,0xA8,0x3A,0x00,0x00,0xDC,0x02,0x7F,0xA0, +0x04,0x00,0x00,0x40,0xA0,0x40,0xA0,0x4F,0xB4,0x07,0x00,0x00,0x2C,0xCC,0xF8,0x7F, +0x68,0x7F,0x00,0x00,0x28,0x40,0x77,0x0F,0x2C,0x5C,0x7F,0xCC,0x3F,0x00,0x00,0x24, +0x7F,0xA8,0x3A,0x00,0x00,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00,0x40,0xA0,0x40,0xA0, +0x4F,0xB9,0x07,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0x68,0x7F,0x00,0x00,0x28,0x40,0x77, +0x32,0xA0,0x4F,0xBB,0x07,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xA0, +0x4F,0xF3,0x07,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0x24, +0x08,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x24,0x7F,0xA8,0x3A,0x00, +0x00,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00,0x40,0x2B,0x50,0x77,0x16,0xDC,0x02,0x7F, +0xA0,0x04,0x00,0x00,0x40,0xA0,0x40,0xE0,0x59,0x2C,0xCC,0xF8,0x7F,0xB0,0x7F,0x00, +0x00,0x82,0xA9,0xB4,0x00,0x70,0x7B,0x5E,0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB4, +0x00,0xE4,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x82,0x50,0x70,0x04,0xA9,0xB8, +0x00,0x40,0x86,0xA9,0xB4,0x00,0xE4,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x82, +0xC0,0x02,0x70,0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB4,0x00,0xE4,0x41,0xD0,0x04, +0x41,0x41,0x9C,0x41,0x40,0x82,0xC0,0x04,0x70,0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9, +0xB4,0x00,0xE4,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x83,0xC0,0x06,0x70,0x92, +0xA9,0xB4,0x00,0x70,0x3E,0x10,0xA9,0xB4,0x00,0x4B,0x9F,0x83,0xA9,0xAC,0x00,0x70, +0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C, +0x41,0x40,0x9C,0x06,0x40,0xA0,0x40,0xDC,0x08,0x7F,0x90,0x04,0x00,0x00,0x40,0xDC, +0x02,0x50,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xB0,0x7F,0x00,0x00,0x04,0xA9,0xB8, +0x00,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86, +0x01,0xC0,0x02,0x70,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0x41,0x93,0xA9, +0xAC,0x00,0x70,0x87,0x41,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x82,0x50, +0x70,0x87,0x7F,0x60,0x08,0x00,0x02,0xE0,0x40,0x24,0x7F,0xB5,0x31,0x00,0x00,0x04, +0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41, +0x40,0x9C,0x06,0x40,0xA0,0x40,0xDC,0x08,0x7F,0x90,0x04,0x00,0x00,0x40,0xDC,0x0E, +0x50,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xB0,0x7F,0x00,0x00,0x04,0xA9,0xB8,0x00, +0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0x01, +0xC0,0x02,0x70,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0x41,0x93,0xA9,0xAC, +0x00,0x70,0x87,0x41,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0x01,0x50, +0x70,0x24,0x7F,0xC7,0x31,0x00,0x00,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00, +0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x9C,0x06,0x40,0xA0,0x40,0xDC,0x08, +0x7F,0x90,0x04,0x00,0x00,0x40,0xDC,0x1A,0x50,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F, +0xB0,0x7F,0x00,0x00,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0xD0, +0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0x01,0xC0,0x02,0x70,0x04,0xA9,0xB8,0x00,0x40, +0x87,0xA9,0xAC,0x00,0x41,0x93,0xA9,0xAC,0x00,0x70,0x87,0x41,0xE0,0x41,0xD0,0x04, +0x41,0x41,0x9C,0x41,0x40,0x86,0x02,0x50,0x70,0x24,0x7F,0xC7,0x31,0x00,0x00,0x04, +0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41, +0x40,0x9C,0x06,0x40,0xA0,0x40,0xDC,0x08,0x7F,0x90,0x04,0x00,0x00,0x40,0xDC,0x0E, +0x50,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xB0,0x7F,0x00,0x00,0x04,0xA9,0xB8,0x00, +0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0x01, +0xC0,0x02,0x70,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0x41,0x93,0xA9,0xAC, +0x00,0x70,0x87,0x41,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0x01,0x50, +0x70,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41, +0x9C,0x41,0x40,0x9C,0x06,0x40,0xA0,0x40,0xDC,0x08,0x7F,0x90,0x04,0x00,0x00,0x40, +0xDC,0x1A,0x50,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xB0,0x7F,0x00,0x00,0x04,0xA9, +0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40, +0x86,0x01,0xC0,0x02,0x70,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0x41,0x93, +0xA9,0xAC,0x00,0x70,0x87,0x41,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86, +0x02,0x50,0x70,0x7B,0x14,0x3C,0x40,0x01,0x7E,0x67,0xFE,0x3C,0x40,0x02,0x7E,0xC9, +0xFE,0x3C,0x40,0x03,0x7E,0x2B,0xFF,0x86,0x01,0xA9,0xB4,0x00,0x70,0x24,0x7F,0x39, +0x33,0x00,0x00,0x86,0xA9,0xB4,0x00,0xE4,0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90, +0x04,0x00,0x00,0x40,0xCC,0x00,0x07,0xC0,0x04,0x40,0x3C,0x00,0x40,0x77,0x08,0x24, +0x7F,0x93,0x32,0x00,0x00,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41, +0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x9C,0x06,0x40,0xA0,0x40,0x86,0xA9,0xB4,0x00, +0xE4,0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0x9C,0x0C,0x40, +0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xB0,0x7F,0x00,0x00,0x04,0xA9,0xB8,0x00,0x40,0x87, +0xA9,0xAC,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x82,0xC0,0x02,0x70, +0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C, +0x41,0x40,0x86,0xA9,0xB4,0x00,0xE4,0x41,0xD0,0x05,0x41,0x41,0x9C,0x7F,0x90,0x04, +0x00,0x00,0x41,0xCC,0x03,0x0C,0x51,0x41,0x86,0x41,0xC0,0x04,0x70,0x04,0xA9,0xB8, +0x00,0x40,0x87,0xA9,0xAC,0x00,0x41,0x93,0xA9,0xAC,0x00,0x70,0x87,0x41,0xE0,0x41, +0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0xA9,0xB4,0x00,0x50,0x70,0x24,0x7F,0x34, +0x33,0x00,0x00,0x86,0xA9,0xB4,0x00,0xE4,0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90, +0x04,0x00,0x00,0x40,0x2B,0xC0,0x0C,0x7F,0x2A,0x86,0xA9,0xB4,0x00,0xE4,0x40,0xD0, +0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0x9C,0x0C,0x40,0xA0,0x40,0xA0, +0x4F,0x66,0x08,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0x68,0x7F,0x00,0x00,0x28,0x40,0x77, +0x65,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41, +0x9C,0x41,0x40,0x82,0xC0,0x02,0x70,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00, +0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0xA9,0xB4,0x00,0xE4,0x41,0xD0, +0x05,0x41,0x41,0x9C,0x7F,0x90,0x04,0x00,0x00,0x41,0xCC,0x03,0x0C,0x51,0x41,0x86, +0x41,0xC0,0x04,0x70,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAC,0x00,0x41,0x93,0xA9, +0xAC,0x00,0x70,0x87,0x41,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0xA9, +0xB4,0x00,0x50,0x70,0x92,0xA9,0xB4,0x00,0x70,0x86,0xA9,0xB4,0x00,0xE4,0x40,0x87, +0xEF,0xE0,0x04,0x00,0x00,0xE0,0x41,0x3C,0x41,0x40,0x4A,0x89,0xFE,0xA0,0x4F,0x6D, +0x08,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0x8B,0x08,0x00, +0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0xAB,0x08,0x00,0x00,0x2C, +0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x82,0xA9,0xB4,0x00,0x70,0x24,0x7F,0x13,0x34, +0x00,0x00,0xA0,0x4F,0xD4,0x08,0x00,0x00,0x86,0xA9,0xB4,0x00,0xE4,0x40,0xA0,0x40, +0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB4,0x00,0xE4,0x41,0xD0,0x04,0x41,0x41,0x9C, +0x41,0x40,0x86,0xE2,0xC0,0x04,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xF4,0x7F,0xE4,0x44, +0x00,0x00,0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB4,0x00,0xE4,0x41,0xD0,0x04,0x41, +0x41,0x9C,0x41,0x40,0x9C,0x06,0x40,0xA0,0x40,0xA0,0x4F,0xEA,0x08,0x00,0x00,0x2C, +0xCC,0xF8,0x7F,0x68,0x7F,0x00,0x00,0x28,0x40,0x7F,0x27,0xA0,0x4F,0xF1,0x08,0x00, +0x00,0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB4,0x00,0xE4,0x41,0xD0,0x04,0x41,0x41, +0x9C,0x41,0x40,0x9C,0x06,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00, +0xA0,0x4F,0xFB,0x08,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x92,0xA9, +0xB4,0x00,0x70,0x86,0xA9,0xB4,0x00,0xE4,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0x3C, +0x41,0x40,0x5A,0x60,0xFF,0xA0,0x4F,0x0C,0x30,0x04,0x00,0xDC,0x01,0x7F,0xA0,0x04, +0x00,0x00,0x40,0xA0,0x40,0xA0,0x01,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0x83, +0xA9,0xAA,0x00,0x70,0x82,0xA9,0xB4,0x00,0x70,0x24,0x7F,0xD5,0x34,0x00,0x00,0x04, +0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB4,0x00,0xE4,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41, +0x40,0x86,0xE2,0xC0,0x02,0xE0,0x40,0x7F,0x34,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00, +0x40,0x87,0x50,0xE0,0x40,0x04,0xA9,0xB8,0x00,0x41,0x86,0xA9,0xB4,0x00,0xE4,0x42, +0xD0,0x04,0x42,0x42,0x9C,0x42,0x41,0x86,0xE2,0x51,0xE0,0x41,0x3C,0x41,0x40,0x77, +0x0A,0x87,0x01,0xA9,0xAA,0x00,0x70,0x7B,0x50,0x7B,0x37,0x04,0xA9,0xB8,0x00,0x40, +0x86,0xA9,0xB4,0x00,0xE4,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0xE2,0xC0, +0x04,0xE0,0x40,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x41,0x87,0x51,0xE0,0x41,0xD4, +0x04,0x41,0x41,0x3C,0x41,0x40,0x77,0x0A,0x87,0x01,0xA9,0xAA,0x00,0x70,0x7B,0x19, +0x92,0xA9,0xB4,0x00,0x70,0x86,0xA9,0xB4,0x00,0xE4,0x40,0x87,0xA9,0xAC,0x00,0xE0, +0x41,0x3C,0x41,0x40,0x5A,0x6B,0xFF,0x2B,0xA9,0xAA,0x00,0x77,0x09,0x83,0xA9,0xAF, +0x00,0x70,0x7B,0x0A,0x87,0xA9,0xB5,0x00,0xA9,0xAF,0x00,0x70,0xA0,0x4F,0xFD,0x08, +0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0x1F,0x09,0x00,0x00, +0x87,0xA9,0xAF,0x00,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00, +0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAF,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C, +0x41,0x40,0x9C,0x06,0x40,0xA0,0x40,0xA0,0x4F,0x23,0x09,0x00,0x00,0x2C,0xCC,0xF8, +0x7F,0x68,0x7F,0x00,0x00,0x28,0x40,0x7F,0x27,0xA0,0x4F,0x2A,0x09,0x00,0x00,0x04, +0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAF,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41, +0x40,0x9C,0x06,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F, +0x30,0x09,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x00,0x2C,0xCC, +0xFC,0xEF,0x40,0x05,0x00,0x00,0xE0,0xC9,0x5A,0x2C,0xCC,0xFC,0x7F,0x60,0x43,0x00, +0x00,0x3C,0xFF,0x40,0x77,0x20,0xA0,0x01,0x2C,0xCC,0xFC,0xEF,0x40,0x05,0x00,0x00, +0xA0,0x4F,0x34,0x09,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x24,0x7F, +0xAB,0x3A,0x00,0x00,0xA0,0x01,0x2C,0xCC,0xFC,0xEF,0x40,0x05,0x00,0x00,0x83,0xA9, +0xAA,0x00,0x70,0x2B,0xC9,0x5A,0x7F,0x5F,0x82,0xA9,0xB4,0x00,0x70,0x7B,0x23,0xE0, +0xC9,0x5A,0x2C,0xCC,0xFC,0xAF,0x68,0x05,0x86,0xA9,0xB4,0x00,0xE4,0x41,0x3C,0x40, +0x41,0x77,0x0A,0x87,0x01,0xA9,0xAA,0x00,0x70,0x7B,0x18,0x92,0xA9,0xB4,0x00,0x70, +0x86,0xA9,0xB4,0x00,0xE4,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0x3C,0x41,0x40,0x5B, +0xD0,0x2B,0xA9,0xAA,0x00,0x77,0x16,0xA0,0x4F,0x36,0x09,0x00,0x00,0xE0,0xC9,0x5A, +0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0x7A,0xE4,0xFE,0x87,0xA9,0xB5,0x00,0xA9, +0xAE,0x00,0x70,0x7B,0x0A,0x87,0xA9,0xAF,0x00,0xA9,0xAE,0x00,0x70,0x04,0xA9,0xB8, +0x00,0x40,0x87,0xA9,0xAE,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86, +0xE2,0xC0,0x02,0xE0,0x40,0x7F,0x27,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x40,0x04, +0xA9,0xB8,0x00,0x41,0x87,0xA9,0xAE,0x00,0xE0,0x42,0xD0,0x04,0x42,0x42,0x9C,0x42, +0x41,0x87,0xC1,0x01,0x50,0x70,0x24,0x7F,0x78,0x3A,0x00,0x00,0x3F,0xA9,0xAF,0x00, +0xA9,0xAE,0x00,0x77,0x16,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x40,0xFB,0x0F,0x50, +0x40,0x87,0x40,0xA9,0xAD,0x00,0x70,0x7B,0x07,0x83,0xA9,0xAD,0x00,0x70,0xDC,0x01, +0x7F,0xA0,0x04,0x00,0x00,0x40,0x04,0xA9,0xB8,0x00,0x41,0x87,0xA9,0xAE,0x00,0xE0, +0x42,0xD0,0x04,0x42,0x42,0x9C,0x42,0x41,0x86,0xE2,0xC1,0x04,0xE0,0x41,0xD0,0x04, +0x41,0x41,0x87,0x41,0x50,0x70,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAE,0x00,0xE0, +0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0x50,0xA9,0xB4,0x00,0x70,0x82,0xA9, +0xB6,0x00,0x70,0x7B,0x5E,0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB6,0x00,0xE4,0x41, +0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x82,0x50,0x70,0x04,0xA9,0xB8,0x00,0x40,0x86, +0xA9,0xB6,0x00,0xE4,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x82,0xC0,0x02,0x70, +0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB6,0x00,0xE4,0x41,0xD0,0x04,0x41,0x41,0x9C, +0x41,0x40,0x82,0xC0,0x04,0x70,0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB6,0x00,0xE4, +0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x83,0xC0,0x06,0x70,0x92,0xA9,0xB6,0x00, +0x70,0x3E,0x10,0xA9,0xB6,0x00,0x4B,0x9F,0x87,0x01,0xA9,0xAB,0x00,0x70,0x86,0xA9, +0xB4,0x00,0xE4,0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0xCC, +0x03,0x00,0xC0,0x04,0x40,0x87,0x40,0xA9,0xAC,0x00,0x70,0x2B,0xA9,0xAC,0x00,0x77, +0x0D,0x87,0x0F,0xA9,0xAC,0x00,0x70,0x83,0xA9,0xAB,0x00,0x70,0x82,0xA9,0xB6,0x00, +0x70,0x7B,0x60,0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB6,0x00,0xE4,0x41,0xD0,0x04, +0x41,0x41,0x9C,0x41,0x40,0x9C,0x06,0x40,0xA0,0x40,0x86,0xA9,0xB4,0x00,0xE4,0x40, +0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0xEA,0x0C,0xA9,0xB6,0x00, +0x41,0xDC,0x41,0xC0,0x08,0x40,0x9C,0x02,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xB0, +0x7F,0x00,0x00,0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB6,0x00,0xE4,0x41,0xD0,0x04, +0x41,0x41,0x9C,0x41,0x40,0x86,0xA9,0xB6,0x00,0xC0,0x04,0x70,0x92,0xA9,0xB6,0x00, +0x70,0x86,0xA9,0xB6,0x00,0xE4,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0x3C,0x41,0x40, +0x5B,0x93,0xA0,0x4F,0x59,0x09,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00, +0xA0,0x4F,0x74,0x09,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F, +0x97,0x09,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x82,0xA9,0xB6,0x00, +0x70,0x24,0x7F,0xAE,0x38,0x00,0x00,0xA0,0x4F,0xC5,0x09,0x00,0x00,0x86,0xA9,0xB6, +0x00,0xE4,0x40,0xA0,0x40,0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB6,0x00,0xE4,0x41, +0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0xE2,0xC0,0x04,0xE0,0x40,0xA0,0x40,0x2C, +0xCC,0xF4,0x7F,0xE4,0x44,0x00,0x00,0x04,0xA9,0xB8,0x00,0x40,0x86,0xA9,0xB6,0x00, +0xE4,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x9C,0x06,0x40,0xA0,0x40,0xA0,0x4F, +0xDC,0x09,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0x68,0x7F,0x00,0x00,0x28,0x40,0x7F,0x2D, +0x2B,0xA9,0xAB,0x00,0x7F,0x27,0xA0,0x4F,0xE3,0x09,0x00,0x00,0x04,0xA9,0xB8,0x00, +0x40,0x86,0xA9,0xB6,0x00,0xE4,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x9C,0x06, +0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0xF1,0x09,0x00, +0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x92,0xA9,0xB6,0x00,0x70,0x86,0xA9, +0xB6,0x00,0xE4,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0x3C,0x41,0x40,0x5A,0x5A,0xFF, +0x83,0xA9,0xAA,0x00,0x70,0x82,0xA9,0xB6,0x00,0x70,0x7B,0x32,0x04,0xA9,0xB8,0x00, +0x40,0x86,0xA9,0xB6,0x00,0xE4,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x86,0xE2, +0xC0,0x04,0xE0,0x40,0x87,0xA9,0xAD,0x00,0xE0,0x41,0x3C,0x41,0x40,0x77,0x0A,0x87, +0x01,0xA9,0xAA,0x00,0x70,0x7B,0x18,0x92,0xA9,0xB6,0x00,0x70,0x86,0xA9,0xB6,0x00, +0xE4,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0x3C,0x41,0x40,0x5B,0xC1,0x2B,0xA9,0xAA, +0x00,0x77,0x09,0x83,0xA9,0xAF,0x00,0x70,0x7B,0x0A,0x87,0xA9,0xB7,0x00,0xA9,0xAF, +0x00,0x70,0xA0,0x4F,0xF3,0x09,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00, +0xA0,0x4F,0x13,0x0A,0x00,0x00,0x87,0xA9,0xAF,0x00,0xE0,0x40,0xA0,0x40,0x2C,0xCC, +0xF8,0x7F,0xE4,0x44,0x00,0x00,0x04,0xA9,0xB8,0x00,0x40,0x87,0xA9,0xAF,0x00,0xE0, +0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x9C,0x06,0x40,0xA0,0x40,0xA0,0x4F,0x17, +0x0A,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0x68,0x7F,0x00,0x00,0x28,0x40,0x7F,0x2D,0x2B, +0xA9,0xAB,0x00,0x7F,0x27,0xA0,0x4F,0x1E,0x0A,0x00,0x00,0x04,0xA9,0xB8,0x00,0x40, +0x87,0xA9,0xAF,0x00,0xE0,0x41,0xD0,0x04,0x41,0x41,0x9C,0x41,0x40,0x9C,0x06,0x40, +0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0x23,0x0A,0x00,0x00, +0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x00,0x2C,0xCC,0xFC,0xEF,0x40,0x05, +0x00,0x00,0xE0,0xC9,0x5A,0x2C,0xCC,0xFC,0x7F,0x60,0x43,0x00,0x00,0x3C,0xFF,0x40, +0x77,0x20,0xA0,0x01,0x2C,0xCC,0xFC,0xEF,0x40,0x05,0x00,0x00,0xA0,0x4F,0x27,0x0A, +0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x24,0x7F,0xAB,0x3A,0x00,0x00, +0xA0,0x01,0x2C,0xCC,0xFC,0xEF,0x40,0x05,0x00,0x00,0x83,0xA9,0xAA,0x00,0x70,0x2B, +0xC9,0x5A,0x7F,0x5F,0x82,0xA9,0xB6,0x00,0x70,0x7B,0x23,0xE0,0xC9,0x5A,0x2C,0xCC, +0xFC,0xAF,0x3C,0x01,0x86,0xA9,0xB6,0x00,0xE4,0x41,0x3C,0x40,0x41,0x77,0x0A,0x87, +0x01,0xA9,0xAA,0x00,0x70,0x7B,0x18,0x92,0xA9,0xB6,0x00,0x70,0x86,0xA9,0xB6,0x00, +0xE4,0x40,0x87,0xA9,0xAC,0x00,0xE0,0x41,0x3C,0x41,0x40,0x5B,0xD0,0x2B,0xA9,0xAA, +0x00,0x77,0x16,0xA0,0x4F,0x29,0x0A,0x00,0x00,0xE0,0xC9,0x5A,0x2C,0xCC,0xF8,0x7F, +0xE4,0x44,0x00,0x00,0x7A,0xDE,0xFE,0x87,0xA9,0xB7,0x00,0xA9,0xAE,0x00,0x70,0x7B, +0x0A,0x87,0xA9,0xAF,0x00,0xA9,0xAE,0x00,0x70,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00, +0x40,0x04,0xA9,0xB8,0x00,0x41,0x87,0xA9,0xAE,0x00,0xE0,0x42,0xD0,0x04,0x42,0x42, +0x9C,0x42,0x41,0xB3,0xC1,0x05,0x50,0x70,0x87,0x01,0xEF,0xA0,0x04,0x00,0x00,0x70, +0x2C,0x5C,0x7F,0x70,0x69,0x00,0x00,0x28,0x40,0x77,0x1F,0xB0,0x04,0x7F,0x5C,0x08, +0x00,0x02,0x70,0x2C,0x5C,0x7F,0xE0,0x5D,0x00,0x00,0xA0,0x4F,0xEF,0xBE,0xED,0xFE, +0x2C,0xCC,0xFC,0x7F,0x22,0x63,0x00,0x00,0x7A,0x65,0xF0,0x04,0xC9,0xE8,0x4C,0x20, +0x49,0x08,0x70,0x70,0x10,0x49,0x9C,0x4F,0x04,0x00,0x00,0x00,0x4C,0x82,0x59,0x70, +0x7B,0x37,0x7B,0x02,0x2C,0x5C,0x7F,0x84,0x44,0x00,0x00,0x87,0x40,0xDA,0x00,0x70, +0x2B,0x40,0x7F,0xF2,0x3F,0x0D,0xDA,0x00,0x7F,0x08,0x3F,0x0A,0xDA,0x00,0x77,0x13, +0x2A,0x59,0x77,0x06,0x80,0x40,0x7B,0x1F,0x83,0xDA,0x00,0x70,0x84,0x01,0x40,0x7B, +0x16,0x90,0x5A,0x70,0x92,0x59,0x70,0x3E,0x08,0x59,0x4B,0xC8,0x83,0xDA,0x00,0x70, +0x84,0x01,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x10,0x49, +0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0xA0,0x4F,0x4C,0x0A,0x00,0x00,0x2C,0xCC,0xFC, +0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0x1E,0xAC,0xEB,0xAD,0x2C,0xCC,0xFC,0x7F,0x22, +0x63,0x00,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F,0x08,0x00, +0x00,0x00,0x4C,0x82,0x64,0x70,0x86,0x64,0x62,0x70,0x7B,0x29,0x3F,0x30,0x59,0x4B, +0x14,0x3F,0x39,0x59,0x47,0x0F,0x87,0x59,0xE2,0x40,0xBE,0x30,0x40,0x86,0x40,0x64, +0x70,0x7B,0x07,0x84,0xFF,0x40,0x7B,0x21,0xEA,0x0A,0x62,0x40,0x9E,0x64,0x40,0x86, +0x40,0x62,0x70,0x84,0x5A,0x40,0x90,0x5A,0x70,0x87,0x50,0x59,0x70,0x2B,0x59,0x77, +0xCD,0x86,0x62,0xE4,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70, +0x10,0x49,0x9C,0x4F,0x04,0x00,0x00,0x00,0x4C,0xDC,0x04,0x7F,0xA4,0x04,0x00,0x00, +0x40,0x83,0x50,0x70,0xA0,0x4F,0x09,0x30,0x04,0x00,0xDC,0x03,0x7F,0xA4,0x04,0x00, +0x00,0x40,0xA0,0x40,0xA0,0x01,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0x3C,0x01, +0x40,0x77,0x51,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0xDC,0x03,0x7F,0xA4,0x04, +0x00,0x00,0x41,0xFB,0x5F,0xF0,0x00,0x51,0x41,0xD4,0x04,0x41,0x41,0x87,0x41,0x50, +0x70,0xDC,0x03,0x7F,0xA4,0x04,0x00,0x00,0x40,0xBB,0x0F,0x50,0x70,0x3C,0x4F,0x00, +0x80,0x00,0x00,0x7F,0x08,0x05,0x00,0x00,0x4F,0x18,0xDC,0x03,0x7F,0xA4,0x04,0x00, +0x00,0x40,0x83,0x50,0x70,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x83,0x50,0x70, +0x7B,0x18,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x83,0x50,0x70,0xDC,0x03,0x7F, +0xA4,0x04,0x00,0x00,0x40,0x83,0x50,0x70,0xA0,0x4F,0x80,0x30,0x04,0x00,0xE0,0x59, +0xA0,0x02,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0x28,0x40,0x7F,0x09,0x86,0xE2, +0x59,0xE0,0x40,0x77,0x1A,0x86,0x5F,0xBD,0x04,0x59,0x70,0xE0,0x59,0xA0,0x4F,0x80, +0x30,0x04,0x00,0xA0,0x02,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x86,0x59,0xEF, +0xA4,0x04,0x00,0x00,0x70,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x2B,0x50,0x7F, +0x08,0x86,0x5F,0xBD,0x04,0x59,0x70,0x86,0xE2,0x59,0xE0,0x40,0xA0,0x40,0xA0,0x4F, +0x00,0x90,0x04,0x00,0x2C,0xCC,0xF8,0x7F,0x84,0x3E,0x00,0x00,0xDC,0x02,0x7F,0xA4, +0x04,0x00,0x00,0x40,0x2B,0x50,0x77,0x19,0xDC,0x03,0x7F,0xA4,0x04,0x00,0x00,0x40, +0x3F,0x01,0x50,0x77,0x0C,0x86,0xEF,0xA4,0x04,0x00,0x00,0x59,0x70,0x7B,0x35,0xA0, +0x4F,0x0A,0x30,0x04,0x00,0xE0,0x59,0xA0,0x02,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00, +0x00,0x28,0x40,0x7F,0x09,0x86,0xE2,0x59,0xE0,0x40,0x77,0x18,0x86,0x3D,0x59,0x70, +0xE0,0x59,0xA0,0x4F,0x0A,0x30,0x04,0x00,0xA0,0x02,0x2C,0xCC,0xF4,0x7F,0xA0,0x52, +0x00,0x00,0x86,0xE2,0x59,0xE0,0x40,0xA0,0x40,0xA0,0x4F,0x08,0x90,0x04,0x00,0x2C, +0xCC,0xF8,0x7F,0x84,0x3E,0x00,0x00,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x2B, +0x50,0x77,0x6B,0xDC,0x03,0x7F,0xA4,0x04,0x00,0x00,0x40,0x2B,0x50,0x77,0x0E,0x8B, +0x7F,0x0D,0x90,0x04,0x00,0x40,0x38,0x40,0x01,0x77,0x1B,0xDC,0x03,0x7F,0xA4,0x04, +0x00,0x00,0x40,0x3F,0x01,0x50,0x77,0x46,0x8B,0x7F,0x0D,0x90,0x04,0x00,0x40,0x38, +0x40,0x02,0x7F,0x3A,0xDC,0x04,0x7F,0xA4,0x04,0x00,0x00,0x40,0x87,0x01,0x50,0x70, +0xDC,0x03,0x7F,0xA4,0x04,0x00,0x00,0x40,0x2B,0x50,0x7F,0x13,0x84,0x4F,0x08,0x90, +0x04,0x00,0x40,0x84,0x40,0xEF,0xFC,0x04,0x00,0x00,0x70,0x7B,0x11,0x84,0x4F,0x00, +0x90,0x04,0x00,0x40,0x84,0x40,0xEF,0xFC,0x04,0x00,0x00,0x70,0x04,0xC9,0xE8,0x4C, +0x20,0x49,0x08,0x70,0x10,0x48,0x9C,0x4F,0x04,0x00,0x00,0x00,0x4C,0x86,0x01,0x48, +0x7B,0x23,0x3E,0x10,0x48,0x5B,0x1C,0xA0,0x4F,0xD8,0x0A,0x00,0x00,0x86,0x72,0xE4, +0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0x24,0x7F,0x7A,0x3E,0x00, +0x00,0x92,0x48,0x86,0x48,0xE4,0x40,0xD0,0x03,0x40,0x40,0x3E,0x72,0x80,0x58,0x0A, +0x00,0x00,0x77,0xD0,0x3C,0x4F,0x08,0x90,0x04,0x00,0x74,0x77,0x31,0x86,0x48,0xE4, +0x40,0xD0,0x03,0x40,0x40,0x87,0x80,0x5A,0x0A,0x00,0x00,0xE2,0x40,0xB2,0x30,0x40, +0x86,0x40,0x59,0x70,0xE0,0x59,0xA0,0x4F,0x0A,0x30,0x04,0x00,0xA0,0x02,0x2C,0xCC, +0xF4,0x7F,0xA0,0x52,0x00,0x00,0x24,0x7F,0x6B,0x3E,0x00,0x00,0xA0,0x4F,0x80,0x30, +0x04,0x00,0xE0,0x59,0xA0,0x02,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0x86,0xE2, +0x59,0xE0,0x40,0x7F,0x38,0x86,0xE2,0x59,0xE0,0x40,0x84,0x4F,0xF0,0xFF,0x00,0x00, +0x41,0x86,0xE2,0x41,0xE0,0x41,0xB8,0x41,0x40,0x86,0x40,0x59,0x70,0x86,0xE2,0x59, +0xE0,0x40,0x86,0x48,0xE4,0x41,0xD0,0x03,0x41,0x41,0x87,0x81,0x5A,0x0A,0x00,0x00, +0xE0,0x41,0xB0,0x41,0x40,0x86,0x40,0x59,0x70,0x7B,0x20,0x86,0x48,0xE4,0x40,0xD0, +0x03,0x40,0x40,0x87,0x80,0x5A,0x0A,0x00,0x00,0xE2,0x40,0xB2,0x5F,0x30,0x04,0x40, +0xB2,0x5F,0x80,0x00,0x40,0x86,0x40,0x59,0x70,0xE0,0x59,0xA0,0x4F,0x80,0x30,0x04, +0x00,0xA0,0x02,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x86,0xE2,0x59,0xE0,0x40, +0xA0,0x40,0xA0,0x74,0x2C,0xCC,0xF8,0xAF,0x10,0x00,0x04,0xC9,0xEC,0x4C,0x20,0x48, +0x20,0x49,0x08,0x70,0x10,0x47,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x86,0x01,0x48, +0x7B,0x17,0x86,0xE2,0x48,0xE0,0x40,0x3C,0x10,0x40,0x5B,0x0B,0x86,0x0D,0x48,0x86, +0x30,0x72,0x70,0x7B,0x22,0x92,0x48,0x86,0xE2,0x48,0xE0,0x40,0xD0,0x03,0x40,0x40, +0x87,0x80,0x5A,0x0A,0x00,0x00,0xE0,0x40,0x86,0xE2,0x72,0xE0,0x41,0xB8,0x0F,0x41, +0x3C,0x41,0x40,0x77,0xCF,0xDC,0x02,0x74,0x40,0x87,0x1A,0x50,0x70,0xDC,0x02,0x74, +0x40,0x87,0x20,0x50,0x70,0xDC,0x02,0x74,0x40,0x87,0x30,0x50,0x70,0xDC,0x02,0x74, +0x40,0x87,0x6F,0x40,0x50,0x70,0xDC,0x02,0x74,0x40,0x87,0x6F,0x70,0x50,0x70,0x86, +0xE2,0x72,0xE0,0x40,0x38,0x40,0x5F,0x00,0x01,0x7F,0x1A,0x86,0xE2,0x72,0xE0,0x40, +0x38,0x40,0x5F,0x00,0x02,0x7F,0x07,0x84,0x04,0x40,0x7B,0x04,0x80,0x40,0xB0,0x00, +0x40,0x7B,0x05,0x84,0x10,0x40,0xB3,0x00,0x40,0x87,0x40,0x47,0x86,0xE2,0x72,0xE0, +0x40,0xB8,0x30,0x40,0x7B,0x13,0x7B,0x22,0xB3,0x01,0x47,0x7B,0x1D,0xB3,0x02,0x47, +0x7B,0x18,0xB3,0x03,0x47,0x7B,0x13,0x3C,0x40,0x00,0x7F,0xEC,0x3C,0x40,0x10,0x7F, +0xE9,0x3C,0x40,0x20,0x7F,0xE9,0x7B,0xEC,0x87,0x47,0xDA,0x04,0x70,0x86,0xE2,0x72, +0xE0,0x40,0x38,0x40,0x6F,0x40,0x7F,0x07,0x84,0x0F,0x40,0x7B,0x05,0x84,0x07,0x40, +0xB3,0x00,0x40,0x87,0x40,0xDA,0x04,0x70,0xDC,0x01,0x74,0x40,0x86,0xE2,0x48,0xE0, +0x41,0xD0,0x03,0x41,0x41,0x87,0x81,0x5B,0x0A,0x00,0x00,0x50,0x70,0x86,0xE2,0x48, +0xE0,0x40,0xD0,0x03,0x40,0x40,0x87,0x80,0x5C,0x0A,0x00,0x00,0x7F,0x54,0x12,0x00, +0x02,0x70,0xDC,0x04,0x74,0x40,0x87,0x7F,0x54,0x12,0x00,0x02,0x50,0x70,0xDC,0x02, +0x74,0x40,0x87,0x15,0x50,0x70,0x87,0x03,0x7F,0x0E,0x90,0x04,0x00,0x70,0xA0,0x01, +0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0xDC,0x03,0x74,0x40,0x87,0x20,0x50,0x70, +0x04,0xC9,0xF0,0x4C,0x20,0x48,0x20,0x47,0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F, +0x54,0x00,0x00,0x00,0x4C,0xA0,0x4F,0x80,0x30,0x04,0x00,0xE0,0x59,0xA0,0x02,0x2C, +0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0xA0,0x4F,0xF3,0x0A,0x00,0x00,0x86,0xE2,0x59, +0xE0,0x40,0xB8,0x0F,0x40,0xD0,0x03,0x40,0x40,0x86,0x80,0x58,0x0A,0x00,0x00,0xE4, +0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0xE0,0x62,0x2C,0xCC,0xFC, +0xEF,0xB4,0x04,0x00,0x00,0x2B,0x62,0x7F,0x3C,0xE0,0x62,0xA0,0x4F,0x09,0x0B,0x00, +0x00,0xE0,0x59,0x2C,0xCC,0xF4,0x7F,0xE4,0x4A,0x00,0x00,0xA0,0x4F,0x0C,0x0B,0x00, +0x00,0x86,0xE2,0x59,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00, +0x86,0xE2,0x59,0xE0,0x40,0xA0,0x40,0xA0,0x4F,0x00,0x90,0x04,0x00,0x2C,0xCC,0xF8, +0xAF,0x27,0xFD,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x10,0x49,0x9C,0x4F, +0x00,0x00,0x00,0x00,0x4C,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F, +0x04,0x00,0x00,0x00,0x4C,0x87,0x7F,0x13,0x20,0x04,0x00,0x59,0x70,0x04,0xC9,0xE8, +0x4C,0x20,0x49,0x08,0x28,0x5D,0x70,0x70,0x70,0x70,0x10,0x49,0x84,0x5A,0x42,0x84, +0x74,0x41,0x84,0x78,0x40,0x30,0x19,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70, +0x84,0xCE,0xFC,0x40,0x84,0x50,0x7F,0x58,0x12,0x00,0x02,0x70,0x84,0xC0,0x04,0x7F, +0x5C,0x12,0x00,0x02,0x70,0x87,0x00,0x7F,0x60,0x12,0x00,0x02,0x70,0x2C,0x5C,0x7F, +0xEC,0x64,0x00,0x00,0x30,0xC8,0x84,0xCE,0xFC,0x40,0x84,0x50,0x7F,0x58,0x12,0x00, +0x02,0x70,0x84,0xC0,0x04,0x7F,0x5C,0x12,0x00,0x02,0x70,0x87,0x08,0x7F,0x60,0x12, +0x00,0x02,0x70,0x2C,0x5C,0x7F,0xEC,0x64,0x00,0x00,0x30,0xC8,0x84,0xCE,0xFC,0x40, +0x84,0x50,0x7F,0x58,0x12,0x00,0x02,0x70,0x84,0xC0,0x04,0x7F,0x5C,0x12,0x00,0x02, +0x70,0x87,0x09,0x7F,0x60,0x12,0x00,0x02,0x70,0x2C,0x5C,0x7F,0xEC,0x64,0x00,0x00, +0x30,0xC8,0x84,0xCE,0xFC,0x40,0x84,0x50,0x7F,0x58,0x12,0x00,0x02,0x70,0x84,0xC0, +0x04,0x7F,0x5C,0x12,0x00,0x02,0x70,0x87,0x0A,0x7F,0x60,0x12,0x00,0x02,0x70,0x2C, +0x5C,0x7F,0xEC,0x64,0x00,0x00,0x30,0xC8,0x84,0xCE,0xFC,0x40,0x84,0x50,0x7F,0x58, +0x12,0x00,0x02,0x70,0x84,0xC0,0x04,0x7F,0x5C,0x12,0x00,0x02,0x70,0x87,0x0B,0x7F, +0x60,0x12,0x00,0x02,0x70,0x2C,0x5C,0x7F,0xEC,0x64,0x00,0x00,0x30,0xC8,0x84,0xCE, +0xFC,0x40,0x84,0x50,0x7F,0x58,0x12,0x00,0x02,0x70,0x84,0xC0,0x04,0x7F,0x5C,0x12, +0x00,0x02,0x70,0x87,0x0C,0x7F,0x60,0x12,0x00,0x02,0x70,0x2C,0x5C,0x7F,0xEC,0x64, +0x00,0x00,0x30,0xC8,0x84,0xCE,0xFC,0x40,0x84,0x50,0x7F,0x58,0x12,0x00,0x02,0x70, +0x84,0xC0,0x04,0x7F,0x5C,0x12,0x00,0x02,0x70,0x87,0x0D,0x7F,0x60,0x12,0x00,0x02, +0x70,0x2C,0x5C,0x7F,0xEC,0x64,0x00,0x00,0x30,0xC8,0x84,0xCE,0xFC,0x40,0x84,0x50, +0x7F,0x58,0x12,0x00,0x02,0x70,0x84,0xC0,0x04,0x7F,0x5C,0x12,0x00,0x02,0x70,0x87, +0x0E,0x7F,0x60,0x12,0x00,0x02,0x70,0x2C,0x5C,0x7F,0xEC,0x64,0x00,0x00,0x30,0xC8, +0x84,0xCE,0xFC,0x40,0x84,0x50,0x7F,0x58,0x12,0x00,0x02,0x70,0x84,0xC0,0x04,0x7F, +0x5C,0x12,0x00,0x02,0x70,0x87,0x0F,0x7F,0x60,0x12,0x00,0x02,0x70,0x2C,0x5C,0x7F, +0xEC,0x64,0x00,0x00,0x30,0xC8,0x70,0x70,0x84,0xCE,0xFC,0x40,0x84,0x50,0x7F,0x58, +0x12,0x00,0x02,0x70,0x84,0xC0,0x04,0x7F,0x5C,0x12,0x00,0x02,0x70,0x84,0xC0,0x1C, +0x7F,0x64,0x12,0x00,0x02,0x70,0x2C,0x5C,0x7F,0x50,0x65,0x00,0x00,0x30,0xC8,0x84, +0xCC,0xFC,0x7F,0x58,0x12,0x00,0x02,0x70,0x84,0xCC,0xF8,0x7F,0x5C,0x12,0x00,0x02, +0x70,0x84,0x40,0x7F,0x64,0x12,0x00,0x02,0x70,0x84,0x4F,0x00,0xE1,0x81,0x00,0x4B, +0x2C,0x5C,0x7F,0x50,0x65,0x00,0x00,0x84,0x7F,0xFC,0x11,0x00,0x02,0xCC,0xF8,0x70, +0x84,0x7F,0x58,0x12,0x00,0x02,0x4B,0x30,0x45,0x84,0x40,0x7F,0x64,0x12,0x00,0x02, +0x70,0x84,0xCC,0xFC,0x7F,0x58,0x12,0x00,0x02,0x70,0x84,0xCC,0xF8,0x7F,0x5C,0x12, +0x00,0x02,0x70,0x04,0x7F,0x98,0x0E,0x00,0x02,0x40,0x30,0xAC,0x84,0x7F,0xFC,0x11, +0x00,0x02,0xCC,0xF8,0x70,0x84,0x7F,0x58,0x12,0x00,0x02,0x4B,0x30,0x45,0x84,0x4F, +0x00,0xE1,0x81,0x00,0x4B,0x2C,0x5C,0x7F,0x50,0x65,0x00,0x00,0x30,0xC8,0x70,0x70, +0x10,0x49,0x9C,0x4F,0x04,0x00,0x00,0x00,0x4C,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00, +0x40,0x2B,0x50,0x7F,0x15,0xDC,0x04,0x7F,0xA4,0x04,0x00,0x00,0x40,0x3F,0x01,0x50, +0x77,0x08,0x24,0x7F,0x48,0x43,0x00,0x00,0x7B,0x09,0x2C,0x5C,0x7F,0xDE,0x62,0x00, +0x00,0xDC,0x01,0x5A,0x40,0x3B,0x50,0x01,0x7F,0xF2,0x3C,0x7F,0xE8,0x11,0x00,0x02, +0x5A,0x77,0x59,0x2B,0x7F,0x68,0x08,0x00,0x02,0x77,0x51,0xDC,0x01,0x5A,0x40,0x3B, +0x50,0x5F,0x80,0x00,0x7F,0x46,0xDC,0x02,0x5A,0x40,0x87,0x6F,0x40,0x50,0x70,0xDC, +0x02,0x5A,0x40,0x87,0x6F,0x50,0x50,0x70,0xDC,0x03,0x5A,0x40,0x87,0x50,0x59,0x70, +0x7B,0x1C,0xDC,0x02,0x5A,0x40,0x87,0x6F,0x40,0x50,0x70,0xDC,0x02,0x5A,0x40,0x87, +0x6F,0x50,0x50,0x70,0xDC,0x03,0x5A,0x40,0x87,0x50,0x59,0x70,0xDC,0x01,0x5A,0x40, +0x3B,0x50,0x01,0x77,0xDF,0x84,0xFF,0x40,0x7B,0x20,0xDC,0x03,0x5A,0x40,0x87,0x50, +0x59,0x70,0x87,0x59,0xE0,0x40,0x7B,0x12,0xA0,0x00,0x2C,0xCC,0xFC,0x7F,0xF8,0x56, +0x00,0x00,0x86,0x40,0xE4,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70, +0x10,0x47,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x2B,0xEF,0xC4,0x04,0x00,0x00,0x77, +0x11,0x2C,0x5C,0x7F,0xDE,0x62,0x00,0x00,0x80,0x40,0x24,0x7F,0x78,0x44,0x00,0x00, +0x84,0x5A,0x48,0x24,0x7F,0x55,0x44,0x00,0x00,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C, +0xCC,0xFC,0x7F,0xA0,0x42,0x00,0x00,0x84,0x40,0x47,0x43,0x0B,0x84,0xFF,0x40,0x24, +0x7F,0x78,0x44,0x00,0x00,0xF8,0x5F,0xFF,0x00,0x47,0xE3,0x40,0x87,0x40,0xDA,0x00, +0x70,0x3F,0x0A,0xDA,0x00,0x7F,0x08,0x3F,0x0D,0xDA,0x00,0x77,0x2C,0x83,0xDA,0x00, +0x70,0xA0,0x0A,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xB8,0x48,0x00, +0x00,0x28,0x40,0x43,0x0B,0x84,0xFF,0x40,0x24,0x7F,0x78,0x44,0x00,0x00,0x84,0x01, +0x40,0x24,0x7F,0x78,0x44,0x00,0x00,0x87,0xDA,0x00,0xE0,0x40,0xA0,0x40,0xA0,0x7F, +0xE8,0x11,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xB8,0x48,0x00,0x00,0x28,0x40,0x43,0x07, +0x84,0xFF,0x40,0x7B,0x75,0x3F,0x08,0xDA,0x00,0x77,0x23,0x3C,0x48,0x5A,0x7F,0x1C, +0xA0,0x4F,0x24,0x0B,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x28,0x40, +0x43,0x07,0x84,0xFF,0x40,0x7B,0x53,0x94,0x5A,0x70,0x7B,0x2B,0x3F,0x6F,0x40,0xDA, +0x00,0x77,0x21,0x84,0x48,0x5A,0x70,0xA0,0x0A,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C, +0xCC,0xF8,0x7F,0xB8,0x48,0x00,0x00,0x28,0x40,0x43,0x07,0x84,0xFF,0x40,0x7B,0x2A, +0x7B,0x05,0x90,0x5A,0x70,0xFC,0x48,0x5A,0x40,0x3C,0x6F,0x50,0x40,0x4A,0x2C,0xFF, +0xA0,0x4F,0x27,0x0B,0x00,0x00,0xA0,0x6F,0x50,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00, +0x00,0x84,0x48,0x5A,0x70,0x7A,0x0E,0xFF,0x04,0xC9,0xF0,0x4C,0x20,0x48,0x20,0x47, +0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x2C,0x5C,0x7F, +0xDE,0x62,0x00,0x00,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x2B,0x50,0x7F,0x0F, +0xDC,0x04,0x7F,0xA4,0x04,0x00,0x00,0x40,0x3F,0x01,0x50,0x7F,0x21,0xDC,0x01,0x7F, +0xE8,0x11,0x00,0x02,0x40,0x3B,0x50,0x01,0x7F,0x10,0xDC,0x03,0x7F,0xE8,0x11,0x00, +0x02,0x40,0x87,0x50,0xE0,0x40,0x7B,0x16,0x80,0x40,0x7B,0x12,0xA0,0x01,0x2C,0xCC, +0xFC,0x7F,0xF8,0x56,0x00,0x00,0x87,0x40,0xE0,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C, +0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F,0x38,0x00,0x00,0x00,0x4C,0x2B,0xEF,0xC4, +0x04,0x00,0x00,0x77,0x11,0x2C,0x5C,0x7F,0xDE,0x62,0x00,0x00,0x80,0x40,0x24,0x7F, +0xAE,0x48,0x00,0x00,0xDC,0x02,0x7F,0xE8,0x11,0x00,0x02,0x40,0x87,0x15,0x50,0x70, +0x80,0xC9,0x28,0x70,0x04,0x74,0x59,0x70,0x24,0x7F,0x88,0x48,0x00,0x00,0x3F,0x25, +0xDA,0x00,0x7F,0x08,0x24,0x7F,0x67,0x48,0x00,0x00,0x84,0x20,0x68,0x70,0x80,0x64, +0x70,0x80,0xC9,0x18,0x70,0x80,0xC9,0x1C,0x70,0x90,0x5A,0x70,0x3F,0x2D,0xDA,0x00, +0x77,0x09,0x84,0x01,0x64,0x70,0x90,0x5A,0x70,0x3F,0x30,0xDA,0x00,0x77,0x0D,0x28, +0x64,0x77,0x06,0x84,0x30,0x68,0x70,0x90,0x5A,0x70,0x7B,0x17,0xE8,0x0A,0xC9,0x1C, +0x40,0xFF,0x30,0xDA,0x00,0x41,0x9C,0x41,0x40,0x84,0x40,0xC9,0x1C,0x70,0x90,0x5A, +0x70,0x3F,0x30,0xDA,0x00,0x4B,0x08,0x3F,0x39,0xDA,0x00,0x4F,0xE1,0x3F,0x6F,0x6C, +0xDA,0x00,0x7F,0x09,0x3F,0x6F,0x68,0xDA,0x00,0x77,0x05,0x90,0x5A,0x70,0x87,0xDA, +0x00,0xE0,0x40,0x24,0x7F,0x12,0x48,0x00,0x00,0xDC,0x03,0x59,0x40,0x87,0x50,0xC9, +0x10,0x70,0x9C,0x04,0x59,0x70,0x2B,0xC9,0x10,0x7F,0x20,0x87,0xC9,0x10,0xE0,0x40, +0xA0,0x40,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xB8,0x48,0x00,0x00, +0x28,0x40,0x43,0x07,0x84,0x01,0xC9,0x28,0x70,0x24,0x7F,0x65,0x48,0x00,0x00,0x84, +0xD9,0x00,0xC9,0x14,0x70,0x9C,0x04,0x59,0x70,0x28,0xC9,0x14,0x77,0x0B,0x84,0x4F, +0x70,0x0B,0x00,0x00,0xC9,0x14,0x70,0x80,0x6C,0x70,0x7B,0x2A,0x90,0x6C,0x70,0x84, +0xC9,0x14,0x40,0x90,0xC9,0x14,0x70,0x87,0x50,0xE0,0x40,0xA0,0x40,0xA0,0x7F,0xE8, +0x11,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xB8,0x48,0x00,0x00,0x28,0x40,0x43,0x07,0x84, +0x01,0xC9,0x28,0x70,0x2B,0xD9,0x14,0x77,0xD5,0x7B,0x1B,0xA0,0x20,0xA0,0x7F,0xE8, +0x11,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xB8,0x48,0x00,0x00,0x28,0x40,0x43,0x07,0x84, +0x01,0xC9,0x28,0x70,0x84,0x6C,0x40,0x90,0x6C,0x70,0x3C,0xC9,0x1C,0x40,0x4B,0xDD, +0x24,0x7F,0x65,0x48,0x00,0x00,0x84,0x10,0xC9,0x24,0x70,0x7B,0x13,0x84,0x01,0xC9, +0x18,0x70,0x84,0x0A,0xC9,0x24,0x70,0x7B,0x07,0x84,0x08,0xC9,0x24,0x70,0x84,0xD9, +0x00,0xC9,0x20,0x70,0x9C,0x04,0x59,0x70,0x28,0xC9,0x20,0x77,0x15,0x84,0x01,0x6C, +0x70,0x87,0x7F,0x5C,0x0B,0x00,0x00,0xC9,0x2C,0x70,0x80,0xC9,0x18,0x70,0x7B,0x74, +0x3C,0x01,0xC9,0x18,0x77,0x17,0xD4,0x1F,0xC9,0x20,0x40,0x7F,0x10,0x88,0xC9,0x20, +0x40,0x9C,0x01,0x40,0x84,0x40,0xC9,0x20,0x70,0x7B,0x06,0x80,0xC9,0x18,0x70,0x80, +0x6C,0x70,0x7B,0x22,0x04,0xC9,0x2C,0x40,0x9C,0x6C,0x40,0xE4,0xE0,0xC9,0x24,0xC9, +0x20,0x41,0x87,0x81,0x5C,0x0B,0x00,0x00,0x50,0x70,0xAC,0xE0,0xC9,0x24,0xC9,0x20, +0x70,0x90,0x6C,0x70,0x28,0xC9,0x20,0x7F,0x07,0x3C,0x0C,0x6C,0x4B,0xD8,0x3C,0x0C, +0x6C,0x4B,0x21,0xA0,0x3F,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xB8, +0x48,0x00,0x00,0x28,0x40,0x43,0x07,0x84,0x01,0xC9,0x28,0x70,0x24,0x7F,0x65,0x48, +0x00,0x00,0x28,0x64,0x77,0x78,0x3C,0x01,0xC9,0x18,0x77,0x24,0x94,0xC9,0x1C,0x70, +0x3C,0x30,0x68,0x77,0x1B,0xA0,0x2D,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C,0xCC,0xF8, +0x7F,0xB8,0x48,0x00,0x00,0x28,0x40,0x43,0x07,0x84,0x01,0xC9,0x28,0x70,0x7B,0x1B, +0xA0,0x68,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xB8,0x48,0x00,0x00, +0x28,0x40,0x43,0x07,0x84,0x01,0xC9,0x28,0x70,0x84,0xC9,0x1C,0x40,0x94,0xC9,0x1C, +0x70,0x3C,0x6C,0x40,0x47,0xDC,0x3C,0x01,0xC9,0x18,0x77,0x20,0x3C,0x20,0x68,0x77, +0x1B,0xA0,0x2D,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xB8,0x48,0x00, +0x00,0x28,0x40,0x43,0x07,0x84,0x01,0xC9,0x28,0x70,0x7B,0x2A,0x3C,0x01,0xC9,0x18, +0x77,0x1F,0x94,0xC9,0x1C,0x70,0xA0,0x2D,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C,0xCC, +0xF8,0x7F,0xB8,0x48,0x00,0x00,0x28,0x40,0x43,0x07,0x84,0x01,0xC9,0x28,0x70,0xBC, +0x6C,0xC9,0x1C,0x70,0x7B,0x26,0x04,0xC9,0x2C,0x40,0x9C,0x6C,0x40,0x87,0x50,0xE0, +0x40,0xA0,0x40,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xB8,0x48,0x00, +0x00,0x28,0x40,0x43,0x07,0x84,0x01,0xC9,0x28,0x70,0x94,0x6C,0x70,0x43,0xD9,0x3C, +0x01,0x64,0x77,0x2E,0x7B,0x1B,0xA0,0x68,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C,0xCC, +0xF8,0x7F,0xB8,0x48,0x00,0x00,0x28,0x40,0x43,0x07,0x84,0x01,0xC9,0x28,0x70,0x84, +0xC9,0x1C,0x40,0x94,0xC9,0x1C,0x70,0xDC,0x01,0x6C,0x41,0x3C,0x41,0x40,0x47,0xD8, +0x7B,0x75,0x87,0xDA,0x00,0xE0,0x40,0xA0,0x40,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C, +0xCC,0xF8,0x7F,0xB8,0x48,0x00,0x00,0x28,0x40,0x43,0x07,0x84,0x01,0xC9,0x28,0x70, +0x7B,0x55,0x3C,0x6F,0x6F,0x40,0x7E,0x43,0xFE,0x47,0x2F,0x3C,0x6F,0x63,0x40,0x7E, +0x7A,0xFD,0x47,0x1D,0x3C,0x6F,0x4F,0x40,0x7E,0x31,0xFE,0x47,0x0B,0x3C,0x6F,0x44, +0x40,0x7E,0x1C,0xFE,0x7B,0xBE,0x3C,0x6F,0x58,0x40,0x7E,0x0C,0xFE,0x7B,0xB5,0x3C, +0x6F,0x64,0x40,0x7E,0x0A,0xFE,0x7B,0xAC,0x3C,0x6F,0x75,0x40,0x7E,0x06,0xFE,0x47, +0x0B,0x3C,0x6F,0x73,0x40,0x7E,0x7A,0xFD,0x7B,0x9A,0x3C,0x6F,0x78,0x40,0x7E,0xE8, +0xFD,0x7B,0x91,0x7B,0x8F,0x7B,0x20,0x87,0xDA,0x00,0xE0,0x40,0xA0,0x40,0xA0,0x7F, +0xE8,0x11,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xB8,0x48,0x00,0x00,0x28,0x40,0x43,0x07, +0x84,0x01,0xC9,0x28,0x70,0x90,0x5A,0x70,0x2B,0xDA,0x00,0x76,0x93,0xFC,0x3C,0x01, +0xC9,0x28,0x77,0x17,0xA0,0x0A,0xA0,0x7F,0xE8,0x11,0x00,0x02,0x2C,0xCC,0xF8,0x7F, +0xB8,0x48,0x00,0x00,0x84,0xFF,0x40,0x7B,0x07,0x84,0x01,0x40,0x7B,0x02,0x04,0xC9, +0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x70,0x10,0x49,0x9C,0x4F,0x04,0x00,0x00,0x00, +0x4C,0x2C,0x5C,0x7F,0xDE,0x62,0x00,0x00,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40, +0x2B,0x50,0x7F,0x15,0xDC,0x04,0x7F,0xA4,0x04,0x00,0x00,0x40,0x3F,0x01,0x50,0x77, +0x08,0x24,0x7F,0x63,0x4A,0x00,0x00,0x87,0x73,0xE2,0x40,0x86,0x40,0x62,0x70,0x3C, +0x7F,0xE8,0x11,0x00,0x02,0x74,0x7F,0x08,0x24,0x7F,0xF0,0x49,0x00,0x00,0x2B,0x7F, +0x68,0x08,0x00,0x02,0x7F,0x08,0x24,0x7F,0xF0,0x49,0x00,0x00,0xDC,0x01,0x74,0x40, +0x3B,0x50,0x01,0x77,0x08,0x24,0x7F,0xF0,0x49,0x00,0x00,0xDC,0x01,0x74,0x40,0x3B, +0x50,0x5F,0x80,0x00,0x7F,0x4F,0xDC,0x02,0x74,0x40,0x87,0x6F,0x40,0x50,0x70,0xDC, +0x02,0x74,0x40,0x87,0x6F,0x50,0x50,0x70,0xDC,0x03,0x74,0x40,0x87,0x50,0xE2,0x40, +0x86,0x40,0x59,0x70,0x7B,0x20,0xDC,0x02,0x74,0x40,0x87,0x6F,0x40,0x50,0x70,0xDC, +0x02,0x74,0x40,0x87,0x6F,0x50,0x50,0x70,0xDC,0x03,0x74,0x40,0x87,0x50,0xE2,0x40, +0x86,0x40,0x59,0x70,0xDC,0x01,0x74,0x40,0x3B,0x50,0x01,0x77,0xDB,0x86,0xFF,0x62, +0x70,0x7B,0x7F,0xDC,0x03,0x74,0x40,0x3F,0x13,0x50,0x77,0x76,0x7B,0x09,0x2C,0x5C, +0x7F,0xDE,0x62,0x00,0x00,0xDC,0x01,0x74,0x40,0x3B,0x50,0x01,0x7F,0xF2,0xDC,0x01, +0x74,0x40,0x3B,0x50,0x5F,0x80,0x00,0x7F,0x4D,0xDC,0x02,0x74,0x40,0x87,0x6F,0x40, +0x50,0x70,0xDC,0x02,0x74,0x40,0x87,0x6F,0x50,0x50,0x70,0xDC,0x03,0x74,0x40,0x87, +0x50,0xE2,0x40,0x86,0x40,0x59,0x70,0x7B,0x20,0xDC,0x02,0x74,0x40,0x87,0x6F,0x40, +0x50,0x70,0xDC,0x02,0x74,0x40,0x87,0x6F,0x50,0x50,0x70,0xDC,0x03,0x74,0x40,0x87, +0x50,0xE2,0x40,0x86,0x40,0x59,0x70,0xDC,0x01,0x74,0x40,0x3B,0x50,0x01,0x77,0xDB, +0x86,0xFF,0x62,0x70,0xDC,0x03,0x74,0x40,0x87,0x50,0xE2,0x40,0x86,0x40,0x59,0x70, +0x7B,0x09,0x2C,0x5C,0x7F,0xDE,0x62,0x00,0x00,0xDC,0x01,0x74,0x40,0x3B,0x50,0x04, +0x7F,0xF2,0x3C,0x7F,0xE8,0x11,0x00,0x02,0x74,0x77,0x2B,0xDC,0x03,0x74,0x40,0x87, +0x73,0x50,0x70,0x3F,0x0A,0x73,0x77,0x1C,0x7B,0x09,0x2C,0x5C,0x7F,0xDE,0x62,0x00, +0x00,0xDC,0x01,0x74,0x40,0x3B,0x50,0x04,0x7F,0xF2,0xDC,0x03,0x74,0x40,0x87,0x0D, +0x50,0x70,0x7B,0x19,0x3F,0x0A,0x73,0x77,0x0C,0xDC,0x03,0x74,0x40,0x87,0x0D,0x50, +0x70,0x7B,0x0A,0xDC,0x03,0x74,0x40,0x87,0x73,0x50,0x70,0x7B,0x09,0x2C,0x5C,0x7F, +0xDE,0x62,0x00,0x00,0xDC,0x01,0x74,0x40,0x3B,0x50,0x04,0x7F,0xF2,0x86,0x62,0xE4, +0x40,0x7B,0x7B,0x87,0x73,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F,0x6A,0x58,0x00, +0x00,0x86,0x40,0x59,0x70,0x3E,0xFF,0x59,0x77,0x08,0x86,0x59,0xE4,0x40,0x7B,0x5E, +0x3E,0x13,0x59,0x77,0x19,0x7B,0x09,0x2C,0x5C,0x7F,0xDE,0x62,0x00,0x00,0xA0,0x01, +0x2C,0xCC,0xFC,0x7F,0xF8,0x56,0x00,0x00,0x28,0x40,0x7F,0xED,0x3F,0x0A,0x73,0x77, +0x37,0xA0,0x0D,0x2C,0xCC,0xFC,0x7F,0x6A,0x58,0x00,0x00,0x86,0x40,0x59,0x70,0x3E, +0xFF,0x59,0x77,0x08,0x86,0x59,0xE4,0x40,0x7B,0x24,0x3E,0x13,0x59,0x77,0x19,0x7B, +0x09,0x2C,0x5C,0x7F,0xDE,0x62,0x00,0x00,0xA0,0x01,0x2C,0xCC,0xFC,0x7F,0xF8,0x56, +0x00,0x00,0x28,0x40,0x7F,0xED,0x86,0x59,0xE4,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C, +0x20,0x49,0x08,0x70,0x10,0x45,0x9C,0x4F,0x1C,0x00,0x00,0x00,0x4C,0x04,0x78,0x68, +0x70,0x24,0x7F,0xC4,0x4C,0x00,0x00,0x80,0x46,0x7B,0x0F,0x2B,0xDA,0x04,0x77,0x07, +0x84,0x01,0x46,0x7B,0x0B,0x90,0x74,0x70,0x3F,0x25,0xDA,0x04,0x77,0xEF,0x28,0x46, +0x7F,0x08,0x24,0x7F,0xCA,0x4C,0x00,0x00,0x7B,0x05,0x90,0x5A,0x70,0x3F,0x20,0xDA, +0x00,0x77,0x07,0x84,0x01,0x40,0x7B,0x04,0x80,0x40,0x84,0x40,0x6C,0x70,0x3F,0x09, +0xDA,0x00,0x77,0x07,0x84,0x01,0x40,0x7B,0x04,0x80,0x40,0x84,0x40,0xC9,0x10,0x70, +0x3F,0x2D,0xDA,0x00,0x77,0x07,0x84,0x01,0x40,0x7B,0x04,0x80,0x40,0x84,0x40,0xC9, +0x14,0x70,0x3F,0x2C,0xDA,0x00,0x77,0x07,0x84,0x01,0x40,0x7B,0x04,0x80,0x40,0x84, +0x40,0xC9,0x18,0x70,0x3F,0x3D,0xDA,0x00,0x77,0x07,0x84,0x01,0x40,0x7B,0x04,0x80, +0x40,0xF0,0xC9,0x10,0x6C,0x41,0xB0,0xC9,0x14,0x41,0xB0,0xC9,0x18,0x41,0xB0,0x41, +0x40,0x77,0x99,0x90,0x74,0x70,0x87,0xDA,0x04,0xE0,0x40,0x24,0x7F,0x96,0x4C,0x00, +0x00,0x84,0x5A,0x48,0xE0,0x5A,0x2C,0xCC,0xFC,0xAF,0x46,0x01,0x7B,0x14,0x84,0xD9, +0x08,0x40,0x70,0x84,0x48,0x41,0x90,0x48,0x87,0x51,0x50,0x70,0x90,0xD9,0x08,0x70, +0x3C,0x5A,0x48,0x77,0xEB,0x84,0xD9,0x08,0x40,0x83,0x50,0x70,0x24,0x7F,0xC0,0x4C, +0x00,0x00,0x84,0xD9,0x08,0x40,0x87,0xDA,0x00,0x50,0x70,0x90,0x5A,0x70,0x24,0x7F, +0xC0,0x4C,0x00,0x00,0x84,0x07,0x46,0x7B,0x0E,0x04,0x59,0x40,0x9C,0x46,0x40,0x87, +0x30,0x50,0x70,0x94,0x46,0x28,0x46,0x43,0xF2,0x84,0x5A,0x48,0x04,0x67,0x47,0xE0, +0x5A,0x2C,0xCC,0xFC,0xAF,0xEB,0x00,0x94,0x5A,0x70,0x87,0xDA,0x00,0x57,0x70,0x3C, +0x48,0x5A,0x77,0x04,0x7B,0x09,0x94,0x47,0x94,0x5A,0x70,0x7B,0xEF,0x80,0x45,0x04, +0x59,0x47,0x84,0x07,0x46,0x7B,0x1D,0x87,0x57,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xFC, +0xAF,0x5F,0x01,0xD0,0x02,0x46,0x41,0xD0,0x41,0x40,0x40,0xB0,0x40,0x45,0x90,0x47, +0x94,0x46,0x28,0x46,0x43,0xE3,0xE0,0x5A,0x2C,0xCC,0xFC,0xAF,0xA4,0x00,0x3F,0x6F, +0x78,0xDA,0x04,0x77,0x12,0x84,0xD9,0x08,0x40,0x84,0x45,0x41,0x86,0x41,0x41,0x86, +0x41,0x50,0x70,0x7B,0x0A,0x84,0xD9,0x08,0x40,0x84,0x45,0x50,0x70,0x7B,0x63,0x3F, +0x6F,0x64,0xDA,0x04,0x77,0x16,0xA0,0x5A,0x2C,0xCC,0xFC,0x7F,0xD0,0x7E,0x00,0x00, +0x84,0xD9,0x08,0x41,0x86,0x40,0x51,0x70,0x7B,0x14,0xA0,0x5A,0x2C,0xCC,0xFC,0x7F, +0x38,0x7E,0x00,0x00,0x84,0xD9,0x08,0x41,0x84,0x40,0x51,0x70,0xE0,0x5A,0x2C,0xCC, +0xFC,0xAF,0x4E,0x00,0x7B,0x2C,0x3C,0x40,0x6F,0x44,0x7F,0xC5,0x3C,0x40,0x6F,0x58, +0x7E,0x34,0xFF,0x3C,0x40,0x6F,0x63,0x7E,0x1B,0xFF,0x3C,0x40,0x6F,0x64,0x7F,0xB1, +0x3C,0x40,0x6F,0x73,0x7E,0xDD,0xFE,0x3C,0x40,0x6F,0x78,0x7E,0x19,0xFF,0x7B,0xD6, +0x9C,0x04,0x68,0x70,0x2B,0xDA,0x04,0x76,0x30,0xFE,0x04,0xC9,0xF8,0x4C,0x20,0x48, +0x20,0x47,0x20,0x46,0x20,0x45,0x20,0x49,0x08,0x70,0x70,0x70,0x10,0x49,0x9C,0x4F, +0x14,0x00,0x00,0x00,0x4C,0x7B,0x06,0x90,0xDA,0x00,0x70,0x84,0xDA,0x00,0x40,0x3F, +0x20,0x50,0x7F,0x07,0x84,0x01,0x40,0x7B,0x04,0x80,0x40,0x84,0x40,0x59,0x70,0x84, +0xDA,0x00,0x40,0x3F,0x09,0x50,0x7F,0x07,0x84,0x01,0x40,0x7B,0x04,0x80,0x40,0x84, +0x40,0x64,0x70,0x84,0xDA,0x00,0x40,0x3F,0x2D,0x50,0x7F,0x07,0x84,0x01,0x40,0x7B, +0x04,0x80,0x40,0x84,0x40,0x68,0x70,0x84,0xDA,0x00,0x40,0x3F,0x2C,0x50,0x7F,0x07, +0x84,0x01,0x40,0x7B,0x04,0x80,0x40,0x84,0x40,0x6C,0x70,0x84,0xDA,0x00,0x40,0x2B, +0x50,0x7F,0x07,0x84,0x01,0x40,0x7B,0x04,0x80,0x40,0x84,0x40,0xC9,0x10,0x70,0x84, +0xDA,0x00,0x40,0x3F,0x3D,0x50,0x7F,0x07,0x84,0x01,0x40,0x7B,0x04,0x80,0x40,0xF8, +0x64,0x59,0x41,0xB8,0x68,0x41,0xB8,0x6C,0x41,0xB8,0xC9,0x10,0x41,0x38,0x41,0x40, +0x76,0x77,0xFF,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x10,0x49,0x9C,0x4F, +0x04,0x00,0x00,0x00,0x4C,0x3F,0x39,0x73,0x57,0x07,0x84,0x01,0x40,0x7B,0x04,0x80, +0x40,0x84,0x40,0x59,0x70,0x3F,0x30,0x73,0x5B,0x07,0x84,0x01,0x40,0x7B,0x04,0x80, +0x40,0x38,0x40,0x59,0x7F,0x0C,0xFF,0x30,0x73,0x40,0x87,0x40,0xE0,0x40,0x7B,0x1D, +0x3F,0x6F,0x61,0x73,0x5B,0x0D,0xFF,0x6F,0x57,0x73,0x40,0x87,0x40,0xE0,0x40,0x7B, +0x0C,0xFF,0x37,0x73,0x40,0x87,0x40,0xE0,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20, +0x49,0x08,0x70,0x70,0x10,0x49,0x9C,0x4F,0x08,0x00,0x00,0x00,0x4C,0x87,0x77,0xE0, +0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0x84,0x40,0x64,0x70, +0x80,0x59,0x70,0x7B,0x15,0x84,0x5A,0x40,0x90,0x5A,0x70,0x84,0x64,0x41,0x90,0x64, +0x70,0x87,0x51,0x50,0x70,0x90,0x59,0x70,0x3C,0x20,0x59,0x5B,0xEA,0x04,0xC9,0xE8, +0x4C,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F,0x08,0x00,0x00,0x00,0x4C,0xA0,0x00,0x2C, +0xCC,0xFC,0xAF,0xB3,0x03,0xA0,0x4F,0x80,0x0B,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4, +0x44,0x00,0x00,0x28,0x40,0x43,0x08,0x24,0x7F,0xC0,0x51,0x00,0x00,0x84,0xEF,0xE4, +0x04,0x00,0x00,0x64,0x70,0xA0,0x4F,0xA1,0x0B,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4, +0x44,0x00,0x00,0x28,0x40,0x43,0x08,0x24,0x7F,0xC0,0x51,0x00,0x00,0x3C,0x4F,0x00, +0x00,0x10,0x00,0x64,0x4B,0x26,0xA0,0x4F,0xBC,0x0B,0x00,0x00,0xD4,0x14,0xEF,0xE4, +0x04,0x00,0x00,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0x28,0x40, +0x43,0x08,0x24,0x7F,0xC0,0x51,0x00,0x00,0x7B,0x24,0xA0,0x4F,0xCB,0x0B,0x00,0x00, +0xD4,0x0A,0xEF,0xE4,0x04,0x00,0x00,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44, +0x00,0x00,0x28,0x40,0x43,0x08,0x24,0x7F,0xC0,0x51,0x00,0x00,0x83,0x59,0x70,0x24, +0x7F,0xA8,0x51,0x00,0x00,0xA0,0x4F,0xD8,0x0B,0x00,0x00,0x87,0x59,0xE0,0x40,0xA0, +0x40,0x87,0x59,0xE0,0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40, +0x9C,0x0C,0x40,0xA0,0x40,0x2C,0xCC,0xF4,0x7F,0xE4,0x44,0x00,0x00,0x28,0x40,0x43, +0x08,0x24,0x7F,0xC0,0x51,0x00,0x00,0xA0,0x4F,0xF6,0x0B,0x00,0x00,0x87,0x59,0xE0, +0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0xCC,0x03,0x08,0x50, +0x40,0xA0,0x40,0x87,0x59,0xE0,0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00, +0x00,0x40,0xCC,0x03,0x0C,0x50,0x40,0xA0,0x40,0x87,0x59,0xE0,0x40,0xD0,0x05,0x40, +0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0xCC,0x0F,0x10,0x50,0x40,0xA0,0x40,0x2C, +0xCC,0xF0,0x7F,0xE4,0x44,0x00,0x00,0x28,0x40,0x43,0x08,0x24,0x7F,0xC0,0x51,0x00, +0x00,0xA0,0x4F,0x27,0x0C,0x00,0x00,0x87,0x59,0xE0,0x40,0xD0,0x05,0x40,0x40,0x9C, +0x7F,0x90,0x04,0x00,0x00,0x40,0xCC,0x00,0x07,0xC0,0x04,0x40,0x3C,0x00,0x40,0x7F, +0x08,0x84,0x6F,0x79,0x40,0x7B,0x06,0x84,0x6F,0x6E,0x40,0xA0,0x40,0x87,0x59,0xE0, +0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0xCC,0x00,0x05,0xC0, +0x04,0x40,0x3C,0x00,0x40,0x7F,0x0B,0x84,0x4F,0x6A,0x0C,0x00,0x00,0x40,0x7B,0x09, +0x84,0x4F,0x71,0x0C,0x00,0x00,0x40,0xA0,0x40,0x87,0x59,0xE0,0x40,0xD0,0x05,0x40, +0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0xCC,0x00,0x06,0xC0,0x04,0x40,0x9C,0x01, +0x40,0xA0,0x40,0x2C,0xCC,0xF0,0x7F,0xE4,0x44,0x00,0x00,0x28,0x40,0x43,0x08,0x24, +0x7F,0xC0,0x51,0x00,0x00,0xA0,0x4F,0x78,0x0C,0x00,0x00,0x87,0x59,0xE0,0x40,0xD0, +0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0xCC,0x07,0x00,0x50,0x40,0xA0, +0x40,0x87,0x59,0xE0,0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40, +0xCC,0x07,0x18,0xC0,0x04,0x40,0xA0,0x40,0x2C,0xCC,0xF4,0x7F,0xE4,0x44,0x00,0x00, +0x28,0x40,0x43,0x08,0x24,0x7F,0xC0,0x51,0x00,0x00,0xA0,0x4F,0xA9,0x0C,0x00,0x00, +0x87,0x59,0xE0,0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0xCC, +0x00,0x09,0xC0,0x04,0x40,0x3C,0x00,0x40,0x7F,0x08,0x84,0x6F,0x79,0x40,0x7B,0x06, +0x84,0x6F,0x6E,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0x28,0x40, +0x43,0x08,0x24,0x7F,0xC0,0x51,0x00,0x00,0x87,0x59,0xE0,0x40,0xD0,0x05,0x40,0x40, +0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0xCC,0x00,0x09,0xC0,0x04,0x40,0x3C,0x00,0x40, +0x7F,0x42,0xA0,0x4F,0xBE,0x0C,0x00,0x00,0x87,0x59,0xE0,0x40,0xD0,0x05,0x40,0x40, +0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0xCC,0x00,0x08,0xC0,0x04,0x40,0x3C,0x00,0x40, +0x7F,0x08,0x84,0x6F,0x79,0x40,0x7B,0x06,0x84,0x6F,0x6E,0x40,0xA0,0x40,0x2C,0xCC, +0xF8,0x7F,0xE4,0x44,0x00,0x00,0x28,0x40,0x43,0x08,0x24,0x7F,0xC0,0x51,0x00,0x00, +0x7B,0x1A,0xA0,0x4F,0xCF,0x0C,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00, +0x28,0x40,0x43,0x08,0x24,0x7F,0xC0,0x51,0x00,0x00,0x83,0x61,0x70,0x24,0x7F,0x54, +0x51,0x00,0x00,0x2B,0x61,0x77,0x1A,0xA0,0x4F,0xDF,0x0C,0x00,0x00,0x2C,0xCC,0xFC, +0x7F,0xE4,0x44,0x00,0x00,0x28,0x40,0x43,0x08,0x24,0x7F,0xC0,0x51,0x00,0x00,0xA0, +0x4F,0xF2,0x0C,0x00,0x00,0x87,0x61,0xE0,0x40,0xA4,0xE0,0x02,0x40,0x77,0x0B,0x84, +0x4F,0x13,0x0D,0x00,0x00,0x40,0x7B,0x09,0x84,0x4F,0x1A,0x0D,0x00,0x00,0x40,0xA0, +0x40,0x87,0x61,0xE0,0x40,0xA0,0x40,0x87,0x59,0xE0,0x40,0xD0,0x05,0x40,0x40,0x9C, +0x7F,0x90,0x04,0x00,0x00,0x40,0xEB,0x0C,0x61,0x41,0xDC,0x41,0xC0,0x08,0x40,0x9C, +0x02,0x40,0xA0,0x40,0x87,0x59,0xE0,0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04, +0x00,0x00,0x40,0xEB,0x0C,0x61,0x41,0xDC,0x41,0xC0,0x08,0x40,0x86,0xE2,0x50,0xE0, +0x40,0xA0,0x40,0x2C,0xCC,0xEC,0x7F,0xE4,0x44,0x00,0x00,0x28,0x40,0x43,0x04,0x7B, +0x71,0x93,0x61,0x70,0x87,0x61,0xE0,0x40,0x87,0x59,0xE0,0x41,0xD0,0x05,0x41,0x41, +0x9C,0x7F,0x90,0x04,0x00,0x00,0x41,0xCC,0x03,0x00,0xC1,0x04,0x41,0x3C,0x41,0x40, +0x5A,0x53,0xFF,0x87,0x59,0xE0,0x40,0xFF,0x01,0xEF,0xE0,0x04,0x00,0x00,0x41,0x3C, +0x41,0x40,0x53,0x23,0xA0,0x4F,0x1D,0x0D,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44, +0x00,0x00,0x28,0x40,0x43,0x04,0x7B,0x2A,0x7B,0x02,0x2C,0x5C,0xEF,0xC8,0x04,0x00, +0x00,0x28,0x40,0x7F,0xF7,0x93,0x59,0x70,0x3F,0xEF,0xE0,0x04,0x00,0x00,0x59,0x5A, +0x06,0xFD,0xA0,0x4F,0x3A,0x0D,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00, +0xA0,0x01,0x2C,0xCC,0xFC,0xAF,0x10,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70, +0x70,0x70,0x10,0x49,0x9C,0x4F,0x04,0x00,0x00,0x00,0x4C,0x87,0x73,0x7F,0x68,0x08, +0x00,0x02,0x70,0x2B,0x73,0x77,0x37,0x7B,0x28,0xDC,0x02,0x7F,0xE8,0x11,0x00,0x02, +0x40,0x87,0x6F,0x40,0x50,0x70,0xDC,0x02,0x7F,0xE8,0x11,0x00,0x02,0x40,0x87,0x6F, +0x50,0x50,0x70,0xDC,0x03,0x7F,0xE8,0x11,0x00,0x02,0x40,0x87,0x50,0x59,0x70,0xDC, +0x01,0x7F,0xE8,0x11,0x00,0x02,0x40,0x3B,0x50,0x01,0x77,0xCF,0x04,0xC9,0xE8,0x4C, +0x20,0x49,0x08,0x70,0x10,0x48,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0xF8,0x5F,0x00, +0xF0,0x5A,0x40,0xF8,0x5F,0xFF,0x0F,0x5A,0x41,0xD0,0x03,0x41,0x41,0x9C,0x41,0x40, +0x84,0x40,0x48,0x7B,0x2A,0x84,0x48,0x40,0x9C,0x04,0x48,0xFB,0x0F,0xC0,0x03,0x40, +0x87,0x40,0xDA,0x04,0x70,0x84,0x74,0x40,0x90,0x74,0x70,0x84,0x48,0x41,0x9C,0x04, +0x48,0xF8,0x0F,0x51,0x41,0xD0,0x04,0x41,0x41,0xB3,0x41,0x50,0x70,0x86,0x7A,0x40, +0x96,0x7A,0x70,0x86,0xE2,0x40,0xE0,0x40,0x77,0xCD,0x80,0x7F,0x70,0x12,0x00,0x02, +0x70,0xA0,0x7F,0x70,0x12,0x00,0x02,0x37,0x04,0x7B,0x0B,0xA0,0x4A,0xFC,0x0C,0x4C, +0x4A,0x7A,0x8F,0x00,0x7B,0x02,0x04,0xC9,0xEC,0x4C,0x20,0x48,0x20,0x49,0x08,0x70, +0x10,0x48,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0xF8,0x5F,0x00,0xF0,0x74,0x40,0xF8, +0x5F,0xFF,0x0F,0x74,0x41,0xD0,0x03,0x41,0x41,0x9C,0x41,0x40,0x84,0x40,0x48,0x7B, +0x2B,0x84,0x48,0x40,0x9C,0x04,0x48,0xFB,0x0F,0xDA,0x00,0x41,0x84,0x41,0x50,0x70, +0x84,0x48,0x40,0x9C,0x04,0x48,0x84,0x5A,0x41,0x90,0x5A,0x70,0xFB,0x5F,0xF0,0x00, +0x51,0x41,0xD4,0x04,0x41,0x41,0x84,0x41,0x50,0x70,0x86,0x7A,0x40,0x96,0x7A,0x70, +0x86,0xE2,0x40,0xE0,0x40,0x77,0xCC,0x84,0x01,0x7F,0x70,0x12,0x00,0x02,0x70,0xA0, +0x7F,0x70,0x12,0x00,0x02,0x37,0x04,0x7B,0x0B,0xA0,0x4A,0xFC,0x0C,0x4C,0x4A,0x7A, +0x11,0x00,0x7B,0x02,0x04,0xC9,0xEC,0x4C,0x20,0x48,0x20,0x49,0x08,0x70,0x70,0x70, +0x10,0x47,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x82,0x48,0x84,0x4F,0x00,0x30,0x04, +0x00,0x47,0x7B,0x40,0x86,0xE2,0x48,0xE0,0x40,0x86,0xE2,0xC7,0x02,0xE0,0x41,0xBA, +0x0F,0x41,0x86,0xE2,0x41,0xE0,0x41,0x9C,0x41,0x40,0x86,0x40,0x48,0x86,0xE2,0x48, +0xE0,0x40,0xD0,0x01,0x40,0x40,0x86,0xE2,0x40,0xE0,0x40,0x86,0xE2,0x48,0xE0,0x41, +0xD4,0x0F,0x41,0x41,0x86,0xE2,0x41,0xE0,0x41,0xB0,0x41,0x40,0x86,0x40,0x48,0x9C, +0x04,0x47,0x3C,0x4F,0x00,0x38,0x04,0x00,0x47,0x5B,0xBB,0x86,0xE2,0x48,0xE0,0x40, +0x88,0x40,0x40,0x86,0x40,0x48,0x3F,0x01,0x73,0x77,0x41,0x86,0xE2,0x48,0xE0,0x40, +0xB8,0x0F,0x40,0x84,0x40,0x57,0x70,0x86,0xE2,0x48,0xE0,0x40,0xD4,0x04,0x40,0x40, +0xB8,0x0F,0x40,0x84,0x40,0xC7,0x04,0x70,0x86,0xE2,0x48,0xE0,0x40,0xD4,0x08,0x40, +0x40,0xB8,0x0F,0x40,0x84,0x40,0xC7,0x08,0x70,0x86,0xE2,0x48,0xE0,0x40,0xD4,0x0C, +0x40,0x40,0xB8,0x0F,0x40,0x84,0x40,0xC7,0x0C,0x70,0x86,0xE2,0x48,0xE0,0x40,0x86, +0xE2,0xC7,0x02,0xE0,0x41,0xBA,0x0F,0x41,0x86,0xE2,0x41,0xE0,0x41,0xF8,0x0F,0xC7, +0x04,0x42,0xD0,0x04,0x42,0x42,0x86,0xE2,0x42,0xE0,0x42,0xB0,0x42,0x41,0x86,0xE2, +0x41,0xE0,0x41,0xF8,0x0F,0xC7,0x08,0x42,0xD0,0x08,0x42,0x42,0x86,0xE2,0x42,0xE0, +0x42,0xB0,0x42,0x41,0x86,0xE2,0x41,0xE0,0x41,0xF8,0x0F,0xC7,0x0C,0x42,0xD0,0x0C, +0x42,0x42,0x86,0xE2,0x42,0xE0,0x42,0xB0,0x42,0x41,0x86,0xE2,0x41,0xE0,0x41,0x3C, +0x41,0x40,0x77,0x07,0x84,0x01,0x40,0x7B,0x06,0x80,0x40,0x7B,0x02,0x04,0xC9,0xF0, +0x4C,0x20,0x48,0x20,0x47,0x20,0x49,0x08,0x84,0x5A,0x40,0x84,0x74,0x42,0xC4,0x02, +0x42,0x42,0x80,0x50,0x70,0x94,0x42,0x4F,0x08,0x04,0xC0,0x04,0x41,0x30,0x19,0x08, +0x84,0x5A,0x40,0x70,0x28,0x40,0x77,0x09,0x04,0x7F,0x74,0x12,0x00,0x02,0x40,0x84, +0x43,0x50,0x70,0x84,0x44,0xC0,0x04,0x70,0x84,0x45,0xC0,0x08,0x70,0x84,0x46,0xC0, +0x0C,0x70,0x84,0x47,0xC0,0x10,0x70,0x84,0x48,0xC0,0x14,0x70,0x84,0xCC,0xFC,0xC0, +0x18,0x70,0x84,0xCC,0xF8,0xC0,0x1C,0x70,0x84,0x4A,0xC0,0x20,0x70,0x84,0x49,0xC0, +0x24,0x70,0x84,0xCD,0x0C,0xC0,0x28,0x70,0x84,0xCD,0x10,0xC0,0x2C,0x70,0x80,0x40, +0x08,0x84,0x5A,0x40,0x70,0x28,0x40,0x77,0x09,0x04,0x7F,0x74,0x12,0x00,0x02,0x40, +0x84,0x50,0x43,0x84,0xC0,0x04,0x44,0x84,0xC0,0x08,0x45,0x84,0xC0,0x0C,0x46,0x84, +0xC0,0x10,0x47,0x84,0xC0,0x14,0x48,0x84,0xC0,0x18,0x4A,0x84,0xC0,0x1C,0x41,0x84, +0xC0,0x20,0x4C,0x84,0xC0,0x24,0x49,0x84,0xC0,0x28,0xCD,0x0C,0x70,0x84,0xC0,0x2C, +0xCD,0x10,0x70,0x80,0x40,0x90,0x40,0x24,0x51,0x70,0x70,0x70,0x10,0x49,0x9C,0x4F, +0x00,0x00,0x00,0x00,0x4C,0x87,0x01,0x7F,0xA4,0x12,0x00,0x02,0x70,0x04,0xC9,0xE8, +0x4C,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x86,0xE2,0x72, +0xE0,0x40,0xA0,0x40,0xA0,0x5F,0xFF,0x08,0x2C,0xCC,0xF8,0xAF,0x14,0x00,0x86,0xE2, +0x40,0xE0,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F, +0x08,0x00,0x00,0x00,0x4C,0x83,0x7F,0xA4,0x12,0x00,0x02,0x70,0x84,0xEF,0x94,0x04, +0x00,0x00,0x64,0x70,0x84,0x4F,0xEC,0x54,0x00,0x00,0xEF,0x94,0x04,0x00,0x00,0x70, +0xF3,0x30,0x7F,0x54,0x12,0x00,0x02,0x40,0x87,0x40,0x7F,0x04,0x90,0x04,0x00,0x70, +0x7B,0x62,0x87,0x7F,0x0F,0x90,0x04,0x00,0x59,0x70,0x86,0xE2,0x76,0xE0,0x40,0xD4, +0x08,0x40,0x40,0x87,0x40,0x7F,0x06,0x90,0x04,0x00,0x70,0xFB,0x5F,0xFF,0x00,0x77, +0x40,0x87,0x40,0x7F,0x07,0x90,0x04,0x00,0x70,0x87,0x7F,0x0E,0x90,0x04,0x00,0x59, +0x70,0x7B,0x28,0x2C,0x5C,0x7F,0xDE,0x62,0x00,0x00,0x2B,0x7F,0xA4,0x12,0x00,0x02, +0x7F,0x19,0x87,0x7F,0x0F,0x90,0x04,0x00,0x59,0x70,0x84,0x64,0xEF,0x94,0x04,0x00, +0x00,0x70,0x86,0xE2,0x72,0xE0,0x40,0x7B,0x2C,0x3B,0x7F,0x05,0x90,0x04,0x00,0x08, +0x7F,0xD3,0x86,0x72,0x40,0x96,0x72,0x70,0x86,0xE2,0x40,0xE0,0x40,0x77,0x95,0x87, +0x7F,0x0F,0x90,0x04,0x00,0x59,0x70,0x84,0x64,0xEF,0x94,0x04,0x00,0x00,0x70,0x80, +0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x10,0x49,0x9C,0x4F, +0x08,0x00,0x00,0x00,0x4C,0x83,0x64,0x70,0x84,0xEF,0x94,0x04,0x00,0x00,0x7F,0xC8, +0x12,0x00,0x02,0x70,0x84,0x4F,0x00,0x5D,0x00,0x00,0xEF,0x94,0x04,0x00,0x00,0x70, +0x70,0xCC,0x03,0x0D,0x4B,0x7F,0xC4,0x12,0x00,0x02,0x70,0xC8,0x03,0x0D,0x0F,0x4B, +0x84,0x4F,0xB8,0x12,0x00,0x02,0x7F,0x00,0x00,0x00,0x02,0x70,0x84,0x4F,0xF4,0x37, +0x00,0x02,0x7F,0xB8,0x12,0x00,0x02,0x70,0x84,0x4F,0xEC,0x37,0x00,0x02,0x7F,0xBC, +0x12,0x00,0x02,0x70,0x87,0x02,0x7F,0xC0,0x12,0x00,0x02,0x70,0x87,0x02,0x7F,0xC1, +0x12,0x00,0x02,0x70,0x87,0x01,0x7F,0xC3,0x12,0x00,0x02,0x70,0xA0,0x4F,0xEC,0x37, +0x00,0x02,0xA0,0x5F,0x14,0x08,0x2C,0xCC,0xF8,0xEF,0x18,0x05,0x00,0x00,0xA0,0x14, +0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0xD0,0x15,0x5A,0x40,0x87,0xC0,0x01,0xE0, +0x59,0x70,0xA0,0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0xD0,0x15,0x5A,0x40, +0x87,0xC0,0x03,0xE0,0x59,0x70,0x80,0x59,0x70,0x7B,0x1E,0x3F,0x03,0x7F,0xEF,0x37, +0x00,0x02,0x77,0x08,0x87,0x01,0x64,0x70,0x7B,0x15,0xA0,0x01,0x2C,0xCC,0xFC,0xEF, +0x28,0x05,0x00,0x00,0x90,0x59,0x70,0x3C,0x6F,0x64,0x59,0x5B,0xE0,0x3C,0x6F,0x64, +0x59,0x5B,0x1B,0xD0,0x15,0x5A,0x40,0x87,0x01,0xC0,0x05,0x70,0xA0,0x14,0x2C,0xCC, +0xFC,0xEF,0x28,0x05,0x00,0x00,0x87,0x64,0xE0,0x40,0x7B,0x15,0x2C,0x5C,0xAF,0x62, +0x06,0x3C,0x01,0x40,0x7F,0x05,0x83,0x64,0x70,0x87,0x64,0xE0,0x40,0x7B,0x02,0x04, +0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x10,0x49,0x9C,0x4F,0x04,0x00,0x00,0x00, +0x4C,0x84,0xEF,0x94,0x04,0x00,0x00,0x7F,0xC8,0x12,0x00,0x02,0x70,0x84,0x4F,0x00, +0x5D,0x00,0x00,0xEF,0x94,0x04,0x00,0x00,0x70,0x70,0xCC,0x03,0x0D,0x4B,0x7F,0xC4, +0x12,0x00,0x02,0x70,0xC8,0x03,0x0D,0x0F,0x4B,0x87,0x08,0x7F,0xF7,0x37,0x00,0x02, +0x70,0x3F,0x01,0x73,0x77,0x18,0xDC,0x03,0x7F,0xA4,0x04,0x00,0x00,0x40,0xF3,0x20, +0x50,0x40,0x87,0x40,0x7F,0xF6,0x37,0x00,0x02,0x70,0x7B,0x19,0xDC,0x03,0x7F,0xA4, +0x04,0x00,0x00,0x40,0x87,0x50,0x7F,0xF6,0x37,0x00,0x02,0x70,0x87,0x7F,0xF6,0x37, +0x00,0x02,0x40,0x87,0x7F,0x68,0x08,0x00,0x02,0xE0,0x7F,0xF8,0x37,0x00,0x02,0x70, +0x87,0x5F,0xFF,0x00,0x7F,0xEF,0x37,0x00,0x02,0x70,0xDC,0x02,0x7F,0xA4,0x04,0x00, +0x00,0x40,0x87,0x50,0xE0,0x40,0xD0,0x15,0x40,0x40,0x87,0xC0,0x01,0xE2,0x40,0x86, +0x40,0x59,0x70,0x82,0x59,0x70,0x24,0x7F,0x56,0x58,0x00,0x00,0xA0,0x01,0xA0,0x5F, +0xE6,0x00,0x2C,0xCC,0xF8,0x7F,0x2C,0x55,0x00,0x00,0x3F,0x5F,0xFF,0x00,0x7F,0xEF, +0x37,0x00,0x02,0x7F,0x6A,0x2B,0x7F,0xEF,0x37,0x00,0x02,0x77,0x4C,0x2C,0x5C,0xAF, +0x81,0x05,0x3C,0x01,0x40,0x7F,0x18,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0xEF,0x8C,0x04, +0x00,0x00,0x70,0x87,0x01,0x7F,0x0B,0x40,0x04,0x00,0x70,0x7B,0x00,0x86,0xE2,0x7F, +0xEC,0x37,0x00,0x02,0xE0,0x40,0xBA,0x5F,0xFF,0x00,0x40,0x86,0x40,0x62,0x70,0x86, +0xE2,0x62,0xE0,0x40,0x3C,0x5F,0xFF,0x00,0x40,0x77,0x07,0x84,0xFF,0x40,0x7B,0x07, +0x86,0xE2,0x62,0xE0,0x40,0x7B,0x5D,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0xEF,0x8C,0x04, +0x00,0x00,0x70,0x87,0x01,0x7F,0x0B,0x40,0x04,0x00,0x70,0x7B,0x00,0x86,0xE2,0x59, +0xE0,0x40,0x3C,0x6F,0x64,0x40,0x5B,0x1F,0x2C,0x5C,0x7F,0xDE,0x62,0x00,0x00,0x84, +0x4F,0xEF,0xBE,0xED,0xFE,0xEF,0x8C,0x04,0x00,0x00,0x70,0x87,0x01,0x7F,0x0B,0x40, +0x04,0x00,0x70,0x7B,0x00,0x3F,0x01,0x73,0x77,0x07,0x92,0x59,0x70,0x7B,0x09,0x2C, +0x5C,0x7F,0xDE,0x62,0x00,0x00,0x86,0xE2,0x59,0xE0,0x40,0x3C,0x6F,0x64,0x40,0x5A, +0x3D,0xFF,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F,0x04,0x00, +0x00,0x00,0x4C,0x84,0xEF,0x94,0x04,0x00,0x00,0x7F,0xC8,0x12,0x00,0x02,0x70,0x84, +0x4F,0x00,0x5D,0x00,0x00,0xEF,0x94,0x04,0x00,0x00,0x70,0x70,0xCC,0x03,0x0D,0x4B, +0x7F,0xC4,0x12,0x00,0x02,0x70,0xC8,0x03,0x0D,0x0F,0x4B,0x87,0x09,0x7F,0xF7,0x37, +0x00,0x02,0x70,0xDC,0x03,0x7F,0xA4,0x04,0x00,0x00,0x40,0x87,0x50,0x7F,0xF6,0x37, +0x00,0x02,0x70,0x87,0x73,0xE2,0x40,0x86,0x40,0x7F,0xF4,0x37,0x00,0x02,0x70,0x87, +0x5F,0xFF,0x00,0x7F,0xEF,0x37,0x00,0x02,0x70,0x87,0x7F,0x68,0x08,0x00,0x02,0xE0, +0x7F,0xF8,0x37,0x00,0x02,0x70,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x87,0x50, +0xE0,0x40,0xD0,0x15,0x40,0x40,0x87,0xC0,0x01,0xE2,0x40,0x86,0x40,0x59,0x70,0x82, +0x59,0x70,0x24,0x7F,0xB2,0x59,0x00,0x00,0xA0,0x01,0xA0,0x5F,0xE6,0x00,0x2C,0xCC, +0xF8,0x7F,0x2C,0x55,0x00,0x00,0x3F,0x5F,0xFF,0x00,0x7F,0xEF,0x37,0x00,0x02,0x7F, +0x78,0x2B,0x7F,0xEF,0x37,0x00,0x02,0x77,0x53,0x2C,0x5C,0xAF,0x25,0x04,0x3C,0x01, +0x40,0x7F,0x1F,0x2C,0x5C,0x7F,0xDE,0x62,0x00,0x00,0x84,0x4F,0xEF,0xBE,0xED,0xFE, +0xEF,0x8C,0x04,0x00,0x00,0x70,0x87,0x01,0x7F,0x0B,0x40,0x04,0x00,0x70,0x7B,0x00, +0x86,0xE2,0x7F,0xEC,0x37,0x00,0x02,0xE0,0x40,0xBA,0x5F,0xFF,0x00,0x40,0x86,0x40, +0x62,0x70,0x86,0xE2,0x62,0xE0,0x40,0x3C,0x5F,0xFF,0x00,0x40,0x77,0x07,0x84,0xFF, +0x40,0x7B,0x07,0x86,0xE2,0x62,0xE0,0x40,0x7B,0x56,0x2C,0x5C,0x7F,0xDE,0x62,0x00, +0x00,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0xEF,0x8C,0x04,0x00,0x00,0x70,0x87,0x01,0x7F, +0x0B,0x40,0x04,0x00,0x70,0x7B,0x00,0x86,0xE2,0x59,0xE0,0x40,0x3C,0x6F,0x64,0x40, +0x5B,0x1F,0x2C,0x5C,0x7F,0xDE,0x62,0x00,0x00,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0xEF, +0x8C,0x04,0x00,0x00,0x70,0x87,0x01,0x7F,0x0B,0x40,0x04,0x00,0x70,0x7B,0x00,0x92, +0x59,0x70,0x86,0xE2,0x59,0xE0,0x40,0x3C,0x6F,0x64,0x40,0x5A,0x3D,0xFF,0x04,0xC9, +0xE8,0x4C,0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F,0x10,0x00,0x00,0x00,0x4C,0x83, +0x64,0x70,0x84,0xEF,0x94,0x04,0x00,0x00,0x7F,0xC8,0x12,0x00,0x02,0x70,0x84,0x4F, +0x00,0x5D,0x00,0x00,0xEF,0x94,0x04,0x00,0x00,0x70,0x70,0xCC,0x03,0x0D,0x4B,0x7F, +0xC4,0x12,0x00,0x02,0x70,0xC8,0x03,0x0D,0x0F,0x4B,0x87,0x07,0x7F,0xF7,0x37,0x00, +0x02,0x70,0x87,0x77,0x7F,0xF6,0x37,0x00,0x02,0x70,0x87,0x5F,0xFF,0x00,0x7F,0xEF, +0x37,0x00,0x02,0x70,0x04,0x68,0x7F,0xF8,0x37,0x00,0x02,0x70,0x86,0xEF,0xA4,0x04, +0x00,0x00,0x68,0x70,0x83,0x6C,0x70,0x87,0x73,0xE0,0x40,0xD0,0x15,0x40,0x40,0x87, +0xC0,0x01,0xE0,0x59,0x70,0x80,0x59,0x70,0x7B,0x5D,0xA0,0x01,0x2C,0xCC,0xFC,0xEF, +0x28,0x05,0x00,0x00,0x2B,0x7F,0xEF,0x37,0x00,0x02,0x77,0x28,0x87,0x01,0x64,0x70, +0xDC,0x03,0x7F,0xA4,0x04,0x00,0x00,0x40,0x87,0x6B,0x50,0x70,0xDC,0x04,0x7F,0xA4, +0x04,0x00,0x00,0x40,0x87,0x01,0x50,0x70,0x86,0x68,0xEF,0xA4,0x04,0x00,0x00,0x70, +0x7B,0x2B,0x3C,0x6F,0x64,0x59,0x5B,0x1C,0x83,0x64,0x70,0x87,0x73,0xE0,0x40,0xD0, +0x15,0x40,0x40,0x87,0x01,0xC0,0x05,0x70,0xA0,0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05, +0x00,0x00,0x90,0x59,0x70,0x3C,0x6F,0x64,0x59,0x5B,0xA1,0x2C,0x5C,0xAF,0xA3,0x02, +0x3C,0x01,0x40,0x7F,0x1C,0x83,0x64,0x70,0x87,0x73,0xE0,0x40,0xD0,0x15,0x40,0x40, +0x87,0x01,0xC0,0x05,0x70,0xA0,0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x87, +0x64,0xE0,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x10,0x49, +0x9C,0x4F,0x08,0x00,0x00,0x00,0x4C,0x87,0x73,0xE0,0x40,0xD0,0x15,0x40,0x40,0x87, +0x01,0xC0,0x05,0x70,0xA0,0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x87,0x73, +0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0xAF,0xF8,0xFA,0x28,0x40,0x77,0x0A,0x80,0x40, +0x24,0x7F,0xA3,0x5B,0x00,0x00,0x84,0xEF,0x94,0x04,0x00,0x00,0x7F,0xC8,0x12,0x00, +0x02,0x70,0x84,0x4F,0x00,0x5D,0x00,0x00,0xEF,0x94,0x04,0x00,0x00,0x70,0x70,0xCC, +0x03,0x0D,0x4B,0x7F,0xC4,0x12,0x00,0x02,0x70,0xC8,0x03,0x0D,0x0F,0x4B,0x87,0x0A, +0x7F,0xF7,0x37,0x00,0x02,0x70,0x87,0x77,0x7F,0xF6,0x37,0x00,0x02,0x70,0x87,0x5F, +0xFF,0x00,0x7F,0xEF,0x37,0x00,0x02,0x70,0x87,0x73,0xE0,0x40,0xD0,0x15,0x40,0x40, +0x87,0xC0,0x01,0xE0,0x64,0x70,0x80,0x64,0x70,0x7B,0x31,0xA0,0x01,0x2C,0xCC,0xFC, +0xEF,0x28,0x05,0x00,0x00,0x3F,0x5F,0xFF,0x00,0x7F,0xEF,0x37,0x00,0x02,0x7F,0x19, +0x2B,0x7F,0xEF,0x37,0x00,0x02,0x77,0x0C,0x84,0x7F,0xF0,0x37,0x00,0x02,0x59,0x70, +0x7B,0x11,0x80,0x59,0x70,0x7B,0x0C,0x90,0x64,0x70,0x3C,0x5F,0x30,0x75,0x64,0x4B, +0xCC,0x2C,0x5C,0xAF,0xAD,0x01,0x28,0x40,0x7F,0x07,0x84,0x59,0x40,0x7B,0x06,0x80, +0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F,0x08,0x00, +0x00,0x00,0x4C,0x70,0xCC,0x03,0x0D,0x4B,0x7F,0xC4,0x12,0x00,0x02,0x70,0xC8,0x03, +0x0D,0x0F,0x4B,0x84,0xEF,0x94,0x04,0x00,0x00,0x7F,0xC8,0x12,0x00,0x02,0x70,0x84, +0x4F,0x00,0x5D,0x00,0x00,0xEF,0x94,0x04,0x00,0x00,0x70,0x83,0x59,0x70,0x84,0x74, +0x7F,0xB0,0x12,0x00,0x02,0x70,0x84,0x78,0x7F,0xB4,0x12,0x00,0x02,0x70,0x3F,0x01, +0xCA,0x0F,0x77,0x0C,0x87,0x0C,0x7F,0xF7,0x37,0x00,0x02,0x70,0x7B,0x2F,0x2B,0xCA, +0x0F,0x77,0x0C,0x87,0x0B,0x7F,0xF7,0x37,0x00,0x02,0x70,0x7B,0x20,0x84,0x7F,0xC8, +0x12,0x00,0x02,0xEF,0x94,0x04,0x00,0x00,0x70,0xC8,0x03,0x0D,0x7F,0xC4,0x12,0x00, +0x02,0x4B,0x84,0x00,0x40,0x24,0x7F,0xF9,0x5C,0x00,0x00,0xFB,0x5F,0xF0,0x00,0x73, +0x40,0xD4,0x04,0x40,0x40,0x87,0x40,0x62,0x70,0x2B,0x62,0x77,0x0A,0x80,0x40,0x24, +0x7F,0xF9,0x5C,0x00,0x00,0xFB,0x0F,0x73,0x40,0x87,0x40,0x61,0x70,0x87,0x61,0x7F, +0xF6,0x37,0x00,0x02,0x70,0x84,0x4F,0xB0,0x12,0x00,0x02,0x7F,0xF8,0x37,0x00,0x02, +0x70,0x87,0x5F,0xFF,0x00,0x7F,0xEF,0x37,0x00,0x02,0x70,0x87,0x62,0xE0,0x40,0xD0, +0x15,0x40,0x40,0x87,0xC0,0x01,0xE0,0x64,0x70,0x80,0x64,0x70,0x7B,0x2D,0xA0,0x01, +0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x3F,0x5F,0xFF,0x00,0x7F,0xEF,0x37,0x00, +0x02,0x7F,0x15,0x2B,0x7F,0xEF,0x37,0x00,0x02,0x77,0x08,0x87,0x01,0x59,0x70,0x7B, +0x11,0x83,0x59,0x70,0x7B,0x0C,0x90,0x64,0x70,0x3C,0x5F,0x28,0x23,0x64,0x4B,0xD0, +0x2C,0x5C,0xAF,0x8E,0x00,0x28,0x40,0x7F,0x06,0x2B,0x59,0x77,0x39,0xA0,0x4F,0x44, +0x0D,0x00,0x00,0x2B,0xCA,0x0F,0x77,0x0B,0x84,0x4F,0x80,0x0D,0x00,0x00,0x40,0x7B, +0x09,0x84,0x4F,0x85,0x0D,0x00,0x00,0x40,0xA0,0x40,0xA0,0x74,0x87,0x61,0xE0,0x40, +0xA0,0x40,0x87,0x62,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xEC,0x7F,0xE4,0x44,0x00,0x00, +0x80,0x40,0x7B,0x07,0x84,0x01,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08, +0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0xC8,0x03,0x0D,0x0F,0x4B,0x2C,0x5C, +0x7F,0xDE,0x62,0x00,0x00,0x86,0xE2,0x7F,0x02,0x40,0x04,0x00,0xE0,0x40,0x38,0x40, +0x6F,0x7E,0x7F,0x0C,0x86,0x01,0x7F,0xCE,0x12,0x00,0x02,0x70,0x7B,0x09,0x82,0x7F, +0xCC,0x12,0x00,0x02,0x70,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x10,0x49, +0x9C,0x4F,0x04,0x00,0x00,0x00,0x4C,0x86,0x01,0x7F,0xCC,0x12,0x00,0x02,0x70,0x80, +0x59,0x70,0x82,0x7F,0xCE,0x12,0x00,0x02,0x70,0xC8,0x03,0x0D,0x00,0x4B,0x70,0x70, +0x70,0x70,0xC8,0x03,0x0D,0x0F,0x4B,0x86,0xE2,0x7F,0xCC,0x12,0x00,0x02,0xE0,0x40, +0x77,0x1C,0x84,0x7F,0xC8,0x12,0x00,0x02,0xEF,0x94,0x04,0x00,0x00,0x70,0xC8,0x03, +0x0D,0x7F,0xC4,0x12,0x00,0x02,0x4B,0x84,0x01,0x40,0x7B,0x4D,0x3C,0x5F,0xFF,0x00, +0x59,0x4F,0x1C,0x84,0x7F,0xC8,0x12,0x00,0x02,0xEF,0x94,0x04,0x00,0x00,0x70,0xC8, +0x03,0x0D,0x7F,0xC4,0x12,0x00,0x02,0x4B,0x84,0x00,0x40,0x7B,0x2C,0x86,0xE2,0x7F, +0xCE,0x12,0x00,0x02,0xE0,0x40,0x7F,0x1C,0x84,0x7F,0xC8,0x12,0x00,0x02,0xEF,0x94, +0x04,0x00,0x00,0x70,0xC8,0x03,0x0D,0x7F,0xC4,0x12,0x00,0x02,0x4B,0x84,0x00,0x40, +0x7B,0x07,0x90,0x59,0x70,0x7B,0x84,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70, +0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x2C,0x5C,0xAF,0x89,0x01,0x87,0x01, +0xEF,0xC4,0x04,0x00,0x00,0x70,0x38,0x7F,0x5C,0x08,0x00,0x02,0x4F,0x00,0x00,0x00, +0x20,0x7F,0x24,0xA0,0x4F,0x8C,0x0D,0x00,0x00,0xA0,0x4F,0xC0,0x0D,0x00,0x00,0x2C, +0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0xD9,0x0D,0x00,0x00,0x2C,0xCC,0xFC, +0x7F,0xE4,0x44,0x00,0x00,0x38,0x7F,0x5C,0x08,0x00,0x02,0x4F,0x00,0x00,0x00,0x40, +0x7F,0x10,0xA0,0x4F,0x2E,0x0E,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00, +0x38,0x7F,0x5C,0x08,0x00,0x02,0x02,0x7F,0x16,0xA0,0x4F,0x8C,0x0D,0x00,0x00,0xA0, +0x4F,0x5A,0x0E,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0x38,0x7F,0x5C, +0x08,0x00,0x02,0x01,0x7F,0x16,0xA0,0x4F,0x8C,0x0D,0x00,0x00,0xA0,0x4F,0x72,0x0E, +0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0x38,0x7F,0x5C,0x08,0x00,0x02, +0x04,0x7F,0x16,0xA0,0x4F,0x8C,0x0D,0x00,0x00,0xA0,0x4F,0x91,0x0E,0x00,0x00,0x2C, +0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0x38,0x7F,0x5C,0x08,0x00,0x02,0x20,0x7F,0x16, +0xA0,0x4F,0x8C,0x0D,0x00,0x00,0xA0,0x4F,0xA2,0x0E,0x00,0x00,0x2C,0xCC,0xF8,0x7F, +0xE4,0x44,0x00,0x00,0x38,0x7F,0x5C,0x08,0x00,0x02,0x08,0x7F,0x16,0xA0,0x4F,0x8C, +0x0D,0x00,0x00,0xA0,0x4F,0xC0,0x0E,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00, +0x00,0x38,0x7F,0x5C,0x08,0x00,0x02,0x10,0x7F,0x16,0xA0,0x4F,0x8C,0x0D,0x00,0x00, +0xA0,0x4F,0xD8,0x0E,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0x28,0x7F, +0x5C,0x08,0x00,0x02,0x7F,0x23,0x3C,0x4F,0x00,0x00,0x00,0x01,0x7F,0x5C,0x08,0x00, +0x02,0x53,0x16,0xA0,0x4F,0x03,0x0F,0x00,0x00,0xA0,0x4F,0x9C,0x0D,0x00,0x00,0x2C, +0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0x3C,0x4F,0x00,0x00,0x00,0x80,0x7F,0x5C,0x08, +0x00,0x02,0x77,0x29,0x3C,0x4F,0xEF,0xBE,0xED,0xFE,0x7F,0x64,0x08,0x00,0x02,0x7F, +0x1C,0xA0,0x4F,0x06,0x0F,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xB8, +0x4F,0xFF,0xFF,0xFF,0x7F,0x7F,0x5C,0x08,0x00,0x02,0x70,0xDC,0x04,0x7F,0xA4,0x04, +0x00,0x00,0x40,0x3F,0x01,0x50,0x77,0x09,0x80,0x7F,0x5C,0x08,0x00,0x02,0x70,0xA0, +0x01,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08, +0x70,0x70,0x10,0x49,0x9C,0x4F,0x04,0x00,0x00,0x00,0x4C,0x87,0x01,0x7F,0x03,0x40, +0x04,0x00,0x70,0x87,0x01,0x7F,0x07,0x40,0x04,0x00,0x70,0x87,0x01,0x7F,0x0F,0x40, +0x04,0x00,0x70,0x87,0x01,0x7F,0x3F,0x40,0x04,0x00,0x70,0x87,0x01,0x7F,0x37,0x40, +0x04,0x00,0x70,0x87,0x01,0x7F,0x0D,0x80,0x04,0x00,0x70,0x87,0x7F,0x11,0x90,0x04, +0x00,0x59,0x70,0x87,0x7F,0x00,0xD0,0x04,0x00,0x59,0x70,0x87,0x6F,0x56,0x7F,0x0F, +0x20,0x04,0x00,0x70,0x87,0x7F,0x13,0x20,0x04,0x00,0x59,0x70,0x87,0x01,0x7F,0x27, +0x40,0x04,0x00,0x70,0x87,0x01,0x7F,0x2F,0x40,0x04,0x00,0x70,0x04,0xC9,0xE8,0x4C, +0x20,0x49,0x08,0x70,0x70,0x70,0x10,0x49,0x9C,0x4F,0x10,0x00,0x00,0x00,0x4C,0xA0, +0x4F,0xEC,0x31,0x04,0x00,0xE0,0x59,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00, +0x00,0x3C,0x4F,0xEF,0xBE,0x0D,0x60,0x59,0x7F,0x08,0x24,0x7F,0x4E,0x61,0x00,0x00, +0xA0,0x4F,0xF0,0x31,0x04,0x00,0xE0,0x59,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0x24,0x52, +0x00,0x00,0x28,0x59,0x77,0x16,0xA0,0x4F,0x14,0x0F,0x00,0x00,0x2C,0xCC,0xFC,0x7F, +0xE4,0x44,0x00,0x00,0x24,0x7F,0xB9,0x61,0x00,0x00,0x38,0x59,0x6F,0x40,0x77,0x0F, +0x38,0x59,0x5F,0x80,0x00,0x77,0x08,0x24,0x7F,0xD0,0x60,0x00,0x00,0xA0,0x4F,0xF4, +0x31,0x04,0x00,0xE0,0x68,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0xA0, +0x4F,0xF8,0x31,0x04,0x00,0xE0,0x64,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00, +0x00,0xA0,0x4F,0xFC,0x31,0x04,0x00,0xE0,0x6C,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0x24, +0x52,0x00,0x00,0x38,0x59,0x6F,0x40,0x7F,0x20,0xA0,0x4F,0x1C,0x0F,0x00,0x00,0xA0, +0x64,0xA0,0x68,0xF8,0x4F,0xFF,0xFF,0x00,0x00,0x6C,0x40,0xA0,0x40,0x2C,0xCC,0xF0, +0x7F,0xE4,0x44,0x00,0x00,0x7B,0x29,0xA0,0x4F,0x52,0x0F,0x00,0x00,0xA0,0x64,0xA0, +0x68,0xF8,0x4F,0xFF,0xFF,0x00,0x00,0x6C,0x40,0xA0,0x40,0xD4,0x10,0x6C,0x40,0xB8, +0x5F,0xFF,0x00,0x40,0xA0,0x40,0x2C,0xCC,0xEC,0x7F,0xE4,0x44,0x00,0x00,0x7B,0x7E, +0x38,0x59,0x02,0x7F,0x79,0xA0,0x4F,0x92,0x0F,0x00,0x00,0xD4,0x17,0x59,0x40,0xB8, +0x01,0x40,0xA0,0x40,0xD4,0x10,0x59,0x40,0xB8,0x6F,0x7F,0x40,0xA0,0x40,0x2C,0xCC, +0xF4,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0xFC,0x31,0x04,0x00,0xE0,0x6C,0xA0,0x04, +0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0x28,0x6C,0x7F,0x34,0xA0,0x4F,0xB0,0x0F, +0x00,0x00,0xD4,0x18,0x6C,0x40,0xA0,0x40,0xD4,0x10,0x6C,0x40,0xB8,0x5F,0xFF,0x00, +0x40,0xA0,0x40,0xD4,0x08,0x6C,0x40,0xB8,0x5F,0xFF,0x00,0x40,0xA0,0x40,0xF8,0x5F, +0xFF,0x00,0x6C,0x40,0xA0,0x40,0x2C,0xCC,0xEC,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F, +0xFF,0x0F,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x7B,0x10,0xA0,0x4F, +0x02,0x10,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0x80,0x59,0x70,0xE0, +0x59,0xA0,0x4F,0xF0,0x31,0x04,0x00,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00, +0x00,0xE0,0x59,0xA0,0x4F,0xF4,0x31,0x04,0x00,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0xA0, +0x52,0x00,0x00,0xE0,0x59,0xA0,0x4F,0xF8,0x31,0x04,0x00,0xA0,0x04,0x2C,0xCC,0xF4, +0x7F,0xA0,0x52,0x00,0x00,0xE0,0x59,0xA0,0x4F,0xFC,0x31,0x04,0x00,0xA0,0x04,0x2C, +0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0xE0,0x59,0xA0,0x4F,0xEC,0x31,0x04,0x00,0xA0, +0x04,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08, +0x10,0x49,0x9C,0x4F,0x0C,0x00,0x00,0x00,0x4C,0xA0,0x4F,0xEC,0x31,0x04,0x00,0xE0, +0x64,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0x3C,0x4F,0xEF,0xBE,0x0D, +0x60,0x64,0x77,0x16,0xA0,0x4F,0xF0,0x31,0x04,0x00,0xE0,0x59,0xA0,0x04,0x2C,0xCC, +0xF4,0x7F,0x24,0x52,0x00,0x00,0x7B,0x0A,0x84,0x7F,0x5C,0x08,0x00,0x02,0x59,0x70, +0x80,0x64,0x70,0xE0,0x64,0xA0,0x4F,0xEC,0x31,0x04,0x00,0xA0,0x04,0x2C,0xCC,0xF4, +0x7F,0xA0,0x52,0x00,0x00,0xB0,0x5A,0x59,0x70,0x84,0x59,0x7F,0x5C,0x08,0x00,0x02, +0x70,0xE0,0x59,0xA0,0x4F,0xF0,0x31,0x04,0x00,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0xA0, +0x52,0x00,0x00,0x38,0x5A,0x6F,0x40,0x77,0x09,0x38,0x5A,0x5F,0x80,0x00,0x7F,0x63, +0xA0,0x4F,0x58,0x12,0x00,0x02,0xA0,0x4F,0xF4,0x31,0x04,0x00,0xA0,0x04,0x2C,0xCC, +0xF4,0x7F,0xA0,0x52,0x00,0x00,0xA0,0x4F,0x5C,0x12,0x00,0x02,0xA0,0x4F,0xF8,0x31, +0x04,0x00,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x86,0xE2,0x7F,0x02, +0x40,0x04,0x00,0xE0,0x68,0x70,0x38,0x5A,0x5F,0x80,0x00,0x7F,0x12,0x87,0x7F,0x60, +0x12,0x00,0x02,0xE0,0x40,0xD0,0x10,0x40,0x40,0xB0,0x40,0x68,0x70,0xE0,0x68,0xA0, +0x4F,0xFC,0x31,0x04,0x00,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x7B, +0x1D,0x38,0x5A,0x02,0x7F,0x18,0xA0,0x4F,0xD4,0x12,0x00,0x02,0xA0,0x4F,0xFC,0x31, +0x04,0x00,0xA0,0x04,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x84,0x4F,0xEF,0xBE, +0x0D,0x60,0x64,0x70,0xE0,0x64,0xA0,0x4F,0xEC,0x31,0x04,0x00,0xA0,0x04,0x2C,0xCC, +0xF4,0x7F,0xA0,0x52,0x00,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x10,0x49, +0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x3F,0x01,0xEF,0x10,0x05,0x00,0x00,0x7F,0x2B, +0x3F,0x6F,0x64,0x7F,0x03,0x20,0x04,0x00,0x7F,0x21,0x80,0xEF,0x8C,0x04,0x00,0x00, +0x70,0x80,0xEF,0x14,0x05,0x00,0x00,0x70,0x83,0x7F,0x0D,0x90,0x04,0x00,0x70,0x87, +0x04,0x7F,0x0E,0x90,0x04,0x00,0x70,0x7B,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08, +0x70,0x70,0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x2C,0x5C,0xCF,0xB3,0x84, +0x5A,0xEF,0x8C,0x04,0x00,0x00,0x70,0x87,0x01,0x7F,0x0B,0x40,0x04,0x00,0x70,0x7B, +0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x10,0x49,0x9C,0x4F,0x00,0x00, +0x00,0x00,0x4C,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0xEF,0x8C,0x04,0x00,0x00,0x70,0x2C, +0x5C,0xAF,0x81,0xFA,0x87,0x01,0x7F,0x0B,0x40,0x04,0x00,0x70,0x7B,0x00,0x04,0xC9, +0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x70,0x10,0x49,0x9C,0x4F,0x04,0x00,0x00,0x00, +0x4C,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x2B,0x50,0x77,0x0B,0x84,0x01,0x40, +0x24,0x7F,0xE5,0x64,0x00,0x00,0x86,0x01,0x59,0x70,0x7B,0x2D,0x86,0xE2,0x59,0xE0, +0x40,0xD0,0x05,0x40,0x40,0x9C,0x7F,0x90,0x04,0x00,0x00,0x40,0xCC,0x03,0x0C,0x50, +0x40,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x41,0x87,0x51,0xE0,0x41,0x3C,0x41,0x40, +0x77,0x04,0x7B,0x17,0x92,0x59,0x70,0x86,0xE2,0x59,0xE0,0x40,0x87,0xEF,0xE0,0x04, +0x00,0x00,0xE0,0x41,0x3C,0x41,0x40,0x5B,0xC5,0x86,0xE2,0x59,0xE0,0x40,0x87,0xEF, +0xE0,0x04,0x00,0x00,0xE0,0x41,0x3C,0x41,0x40,0x5B,0x2A,0xDC,0x02,0x7F,0xA4,0x04, +0x00,0x00,0x40,0x83,0x50,0x70,0xDC,0x03,0x7F,0xA4,0x04,0x00,0x00,0x40,0x83,0x50, +0x70,0x86,0x5F,0xBD,0x04,0xEF,0xA4,0x04,0x00,0x00,0x70,0x80,0x40,0x24,0x7F,0xE5, +0x64,0x00,0x00,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x87,0x50,0xE0,0x40,0xD0, +0x15,0x40,0x40,0x87,0x01,0xC0,0x05,0x70,0xA0,0x14,0x2C,0xCC,0xFC,0xEF,0x28,0x05, +0x00,0x00,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x87,0x50,0xE0,0x40,0xA0,0x40, +0x2C,0xCC,0xFC,0x7F,0xEC,0x55,0x00,0x00,0x3C,0x01,0x40,0x7F,0x08,0x24,0x7F,0xE1, +0x64,0x00,0x00,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x87,0x50,0xE0,0x40,0xA0, +0x40,0xDC,0x03,0x7F,0xA4,0x04,0x00,0x00,0x40,0x87,0x50,0xE0,0x40,0xA0,0x40,0x2C, +0xCC,0xF8,0x7F,0xC6,0x59,0x00,0x00,0x3C,0x01,0x40,0x77,0x67,0xDC,0x04,0x7F,0xA4, +0x04,0x00,0x00,0x40,0x87,0x01,0x50,0x70,0x86,0xEF,0xA4,0x04,0x00,0x00,0x59,0x70, +0xE0,0x59,0xA0,0x4F,0x80,0x30,0x04,0x00,0xA0,0x02,0x2C,0xCC,0xF4,0x7F,0xA0,0x52, +0x00,0x00,0xDC,0x02,0x7F,0xA4,0x04,0x00,0x00,0x40,0x87,0x50,0xE0,0x40,0xD0,0x04, +0x40,0x40,0xBB,0x5F,0xF0,0x00,0x40,0xDC,0x03,0x7F,0xA4,0x04,0x00,0x00,0x41,0xFB, +0x0F,0x51,0x41,0xB3,0x41,0x40,0x87,0x40,0x62,0x70,0xE0,0x62,0xA0,0x4F,0x09,0x30, +0x04,0x00,0xA0,0x01,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x84,0x01,0x40,0x7B, +0x06,0x80,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F, +0x00,0x00,0x00,0x00,0x4C,0x2C,0x5C,0xEF,0xF8,0x11,0x00,0x02,0x04,0xC9,0xE8,0x4C, +0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0xA0,0x5F,0x80, +0x00,0x2C,0xCC,0xFC,0x7F,0xC0,0x61,0x00,0x00,0xA0,0x4F,0x8C,0x0D,0x00,0x00,0xA0, +0x4F,0x0C,0x10,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0x9C, +0x0D,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0xEF,0xBE,0xED, +0xFE,0x2C,0xCC,0xFC,0x7F,0x22,0x63,0x00,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08, +0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0xF8,0x03,0x7F,0x58,0x12,0x00,0x02, +0x40,0x3C,0x03,0x40,0x77,0x31,0xF8,0x6F,0x78,0x7F,0x58,0x12,0x00,0x02,0x40,0x3C, +0x6F,0x70,0x40,0x7F,0x10,0xF8,0x6F,0x78,0x7F,0x58,0x12,0x00,0x02,0x40,0x3C,0x08, +0x40,0x77,0x0B,0x2C,0x5C,0xEF,0xD8,0x12,0x00,0x02,0x7B,0x09,0x2C,0x5C,0xEF,0xF4, +0x11,0x00,0x02,0x7B,0x09,0x2C,0x5C,0xEF,0xF4,0x11,0x00,0x02,0x04,0xC9,0xE8,0x4C, +0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0xA0,0x6F,0x40, +0x2C,0xCC,0xFC,0x7F,0xC0,0x61,0x00,0x00,0xA0,0x4F,0x8C,0x0D,0x00,0x00,0xA0,0x4F, +0x28,0x10,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0x9C,0x0D, +0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xA0,0x4F,0xEF,0xBE,0xED,0xFE, +0x2C,0xCC,0xFC,0x7F,0x22,0x63,0x00,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70, +0x10,0x48,0x9C,0x4F,0x74,0x00,0x00,0x00,0x4C,0x87,0x01,0xEF,0xC4,0x04,0x00,0x00, +0x70,0x84,0x4F,0x04,0x65,0x00,0x00,0x7F,0xF8,0x11,0x00,0x02,0x70,0x84,0x4F,0xA4, +0x65,0x00,0x00,0x7F,0xF4,0x11,0x00,0x02,0x70,0x84,0x7F,0xF4,0x11,0x00,0x02,0x7F, +0xD8,0x12,0x00,0x02,0x70,0x3C,0x4F,0xEF,0xBE,0xED,0xFE,0x7F,0x64,0x08,0x00,0x02, +0x7F,0x09,0x84,0x4F,0x00,0x00,0x80,0x00,0x4B,0x84,0x7F,0x64,0x08,0x00,0x02,0x48, +0x3C,0x4F,0xEF,0xBE,0xED,0xFE,0x7F,0x64,0x08,0x00,0x02,0x7F,0x15,0x3C,0x4F,0x1E, +0xAC,0xEB,0xAD,0x7F,0x64,0x08,0x00,0x02,0x7F,0x08,0x24,0x7F,0x38,0x68,0x00,0x00, +0x84,0x4F,0xD0,0xF1,0x02,0x3B,0x7F,0x64,0x08,0x00,0x02,0x70,0xA0,0x4F,0x00,0x30, +0x04,0x00,0xE0,0xC9,0x64,0xA0,0x09,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0x2B, +0xC9,0x64,0x77,0x26,0xE0,0xC9,0x64,0xA0,0x4F,0x40,0x10,0x00,0x00,0x2C,0xCC,0xF8, +0x7F,0xB0,0x7F,0x00,0x00,0xE0,0xC9,0x64,0xA0,0x4F,0x00,0x30,0x04,0x00,0xA0,0x09, +0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x3C,0x4F,0x0D,0xF0,0xAD,0x8B,0x48,0x77, +0x08,0x24,0x7F,0x3C,0x67,0x00,0x00,0x3C,0x4F,0xEF,0xBE,0xED,0xFE,0x48,0x7F,0x7E, +0xDC,0x04,0x7F,0xA4,0x04,0x00,0x00,0x40,0x2B,0x50,0x77,0x72,0xA0,0x4F,0x0C,0x30, +0x04,0x00,0xE0,0xC9,0x6E,0xA0,0x01,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0x28, +0x40,0x77,0x28,0x87,0x01,0xC9,0x6E,0x70,0xE0,0xC9,0x6E,0xA0,0x4F,0x0C,0x30,0x04, +0x00,0xA0,0x01,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0xDC,0x01,0x7F,0xA0,0x04, +0x00,0x00,0x40,0x87,0x01,0x50,0x70,0x7B,0x0F,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00, +0x40,0x87,0xC9,0x6E,0x50,0x70,0x83,0xEF,0xA0,0x04,0x00,0x00,0x70,0xDC,0x02,0x7F, +0xA0,0x04,0x00,0x00,0x40,0xA0,0x40,0xA0,0x4F,0x44,0x10,0x00,0x00,0x2C,0xCC,0xF8, +0x7F,0xB0,0x7F,0x00,0x00,0x2C,0x5C,0x7F,0x70,0x69,0x00,0x00,0x7B,0x57,0xDC,0x02, +0x7F,0xA4,0x04,0x00,0x00,0x40,0x83,0x50,0x70,0xDC,0x03,0x7F,0xA4,0x04,0x00,0x00, +0x40,0x83,0x50,0x70,0x87,0x01,0x7F,0x13,0x40,0x04,0x00,0x70,0x80,0xC9,0x70,0x70, +0x7B,0x06,0x90,0xC9,0x70,0x70,0x3C,0x4F,0x50,0xC3,0x00,0x00,0xC9,0x70,0x4B,0xF4, +0x87,0x01,0x7F,0x17,0x40,0x04,0x00,0x70,0x80,0xC9,0x70,0x70,0x7B,0x06,0x90,0xC9, +0x70,0x70,0x3C,0x4F,0xF0,0x49,0x02,0x00,0xC9,0x70,0x4B,0xF4,0x2C,0x5C,0x7F,0xDE, +0x62,0x00,0x00,0xDC,0x04,0x7F,0xA4,0x04,0x00,0x00,0x40,0x3F,0x01,0x50,0x7F,0x11, +0x8B,0x7F,0x0D,0x90,0x04,0x00,0x40,0xB8,0x01,0x40,0x3C,0x01,0x40,0x77,0x91,0x2C, +0x5C,0x7F,0xE0,0x5D,0x00,0x00,0x3C,0x4F,0xEF,0xBE,0xED,0xFE,0x48,0x77,0x1A,0x87, +0x01,0x7F,0x13,0x40,0x04,0x00,0x70,0xA0,0x4F,0x4D,0x10,0x00,0x00,0x2C,0xCC,0xFC, +0x7F,0xE4,0x44,0x00,0x00,0x7B,0x18,0x87,0x01,0x7F,0x17,0x40,0x04,0x00,0x70,0xA0, +0x4F,0x93,0x10,0x00,0x00,0x2C,0xCC,0xFC,0x7F,0xE4,0x44,0x00,0x00,0xE0,0x59,0x2C, +0xCC,0xFC,0x7F,0xB4,0x3A,0x00,0x00,0xE0,0x59,0xE0,0xC9,0x64,0x2C,0xCC,0xF8,0x7F, +0x68,0x7F,0x00,0x00,0x28,0x40,0x77,0x2F,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0x7F,0x64, +0x08,0x00,0x02,0x70,0x2C,0x5C,0x7F,0x04,0x2B,0x00,0x00,0x84,0x7F,0x64,0x08,0x00, +0x02,0x48,0xA0,0x4F,0x00,0x30,0x04,0x00,0xE0,0xC9,0x64,0xA0,0x09,0x2C,0xCC,0xF4, +0x7F,0x24,0x52,0x00,0x00,0x7A,0x73,0xFE,0xA0,0x4F,0x0C,0x30,0x04,0x00,0xE0,0xC9, +0x6E,0xA0,0x01,0x2C,0xCC,0xF4,0x7F,0x24,0x52,0x00,0x00,0x28,0x40,0x77,0x28,0x87, +0x01,0xC9,0x6E,0x70,0xE0,0xC9,0x6E,0xA0,0x4F,0x0C,0x30,0x04,0x00,0xA0,0x01,0x2C, +0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x40,0x87, +0x01,0x50,0x70,0x7B,0x0F,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x40,0x87,0xC9,0x6E, +0x50,0x70,0x83,0xEF,0xA0,0x04,0x00,0x00,0x70,0x3C,0x4F,0x0D,0xF0,0xAD,0x8B,0x48, +0x7F,0x56,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00,0x40,0xA0,0x40,0xA0,0x4F,0xA4,0x10, +0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xB0,0x7F,0x00,0x00,0x2C,0x5C,0x7F,0x70,0x69,0x00, +0x00,0x28,0x40,0x77,0x09,0x2C,0x5C,0x7F,0x4A,0x63,0x00,0x00,0xDC,0x02,0x7F,0xA0, +0x04,0x00,0x00,0x40,0xA0,0x40,0xA0,0x4F,0xAD,0x10,0x00,0x00,0x2C,0xCC,0xF8,0x7F, +0xB0,0x7F,0x00,0x00,0x2C,0x5C,0x7F,0x70,0x69,0x00,0x00,0x28,0x40,0x77,0x09,0x2C, +0x5C,0x7F,0x4A,0x63,0x00,0x00,0x3C,0x4F,0xEF,0xBE,0xED,0xFE,0x7F,0x64,0x08,0x00, +0x02,0x7F,0x0A,0x87,0x01,0x7F,0x17,0x40,0x04,0x00,0x70,0xA0,0x4F,0x0D,0x30,0x04, +0x00,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00,0x40,0xA0,0x40,0xA0,0x2D,0x2C,0xCC,0xF4, +0x7F,0x24,0x52,0x00,0x00,0x28,0x40,0x77,0x34,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00, +0x40,0xA0,0x40,0xA0,0x4F,0xB4,0x10,0x00,0x00,0x2C,0xCC,0xF8,0x7F,0xB0,0x7F,0x00, +0x00,0xDC,0x02,0x7F,0xA0,0x04,0x00,0x00,0x40,0xA0,0x40,0xA0,0x4F,0x0D,0x30,0x04, +0x00,0xA0,0x2D,0x2C,0xCC,0xF4,0x7F,0xA0,0x52,0x00,0x00,0x87,0x02,0xEF,0xA0,0x04, +0x00,0x00,0x70,0x2C,0x5C,0x7F,0x70,0x69,0x00,0x00,0x2C,0x5C,0x7F,0x4A,0x63,0x00, +0x00,0x7A,0xD8,0xFC,0x04,0xC9,0xEC,0x4C,0x20,0x48,0x20,0x49,0x08,0x70,0x70,0x70, +0x10,0x49,0x9C,0x4F,0x10,0x00,0x00,0x00,0x4C,0x3F,0x01,0xEF,0xA0,0x04,0x00,0x00, +0x77,0x0F,0x3C,0x4F,0xF0,0xFF,0x00,0x00,0x7F,0x08,0x05,0x00,0x00,0x7F,0x26,0x84, +0x4F,0x52,0x6C,0x00,0x00,0x7F,0xF8,0x11,0x00,0x02,0x70,0x84,0x4F,0x9E,0x6C,0x00, +0x00,0x7F,0xD8,0x12,0x00,0x02,0x70,0x84,0x7F,0xD8,0x12,0x00,0x02,0x7F,0xF4,0x11, +0x00,0x02,0x70,0x3C,0x4F,0xD0,0xF1,0x02,0x3B,0x7F,0x6C,0x08,0x00,0x02,0x7F,0x55, +0x84,0x4F,0xD0,0xF1,0x02,0x3B,0x7F,0x6C,0x08,0x00,0x02,0x70,0x84,0xEF,0xE4,0x04, +0x00,0x00,0x59,0x70,0xDC,0x4F,0x00,0x00,0x00,0x02,0xEF,0xE4,0x04,0x00,0x00,0x40, +0xBC,0xEF,0xE8,0x04,0x00,0x00,0x40,0xD4,0x02,0x40,0x40,0x84,0x40,0x59,0x70,0x84, +0xEF,0xE8,0x04,0x00,0x00,0x40,0x80,0x50,0x70,0xA0,0x59,0xDC,0x04,0xEF,0xE8,0x04, +0x00,0x00,0x40,0xA0,0x40,0xA0,0xEF,0xE8,0x04,0x00,0x00,0x2C,0xCC,0xF4,0x7F,0x84, +0x40,0x00,0x00,0x83,0x7F,0x0D,0x90,0x04,0x00,0x70,0x87,0x08,0x7F,0x0F,0x90,0x04, +0x00,0x70,0x2C,0x5C,0x7F,0x72,0x5F,0x00,0x00,0xA0,0x00,0x2C,0xCC,0xFC,0xEF,0x40, +0x05,0x00,0x00,0x2B,0xEF,0xA0,0x04,0x00,0x00,0x7F,0x0F,0x3C,0x4F,0x00,0x80,0x00, +0x00,0x7F,0x08,0x05,0x00,0x00,0x43,0x10,0x84,0x4F,0xEF,0xBE,0xED,0xFE,0xEF,0x8C, +0x04,0x00,0x00,0x70,0x7B,0x0E,0x84,0x4F,0xED,0x0D,0x1C,0xA1,0xEF,0x8C,0x04,0x00, +0x00,0x70,0x84,0x4F,0x00,0x40,0x00,0x02,0x64,0x70,0xDC,0x01,0x7F,0xA0,0x04,0x00, +0x00,0x40,0x87,0x50,0xE0,0x40,0xD4,0x04,0x40,0x40,0x87,0x40,0x69,0x70,0xDC,0x01, +0x7F,0xA0,0x04,0x00,0x00,0x40,0x3F,0x01,0x50,0x77,0x4A,0x87,0x01,0x7F,0x1F,0x40, +0x04,0x00,0x70,0xA0,0x00,0x2C,0xCC,0xFC,0x7F,0x2C,0x73,0x00,0x00,0x28,0x40,0x77, +0x0A,0x80,0x40,0x24,0x7F,0x4B,0x6C,0x00,0x00,0xA0,0x00,0xA0,0x7F,0xA8,0x0A,0x00, +0x02,0xA0,0x4F,0x00,0x40,0x00,0x02,0xA0,0x00,0x2C,0xCC,0xF0,0x7F,0x98,0x76,0x00, +0x00,0x28,0x40,0x77,0x0A,0x80,0x40,0x24,0x7F,0x4B,0x6C,0x00,0x00,0x24,0x7F,0x99, +0x6B,0x00,0x00,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x40,0x3F,0x02,0x50,0x77,0x46, +0x87,0x01,0x7F,0x1F,0x40,0x04,0x00,0x70,0xA0,0x01,0x2C,0xCC,0xFC,0x7F,0x2C,0x73, +0x00,0x00,0x28,0x40,0x77,0x0A,0x80,0x40,0x24,0x7F,0x4B,0x6C,0x00,0x00,0xA0,0x01, +0xA0,0x7F,0xFC,0x0A,0x00,0x02,0xA0,0x4F,0x00,0x40,0x00,0x02,0xA0,0x00,0x2C,0xCC, +0xF0,0x7F,0x98,0x76,0x00,0x00,0x28,0x40,0x77,0x0A,0x80,0x40,0x24,0x7F,0x4B,0x6C, +0x00,0x00,0x7B,0x77,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x40,0x2B,0x50,0x77,0x2B, +0xA0,0x00,0xA0,0x4F,0x00,0x40,0x00,0x02,0xA0,0x00,0xA0,0x00,0x2C,0xCC,0xF0,0x7F, +0x2C,0x7B,0x00,0x00,0x28,0x40,0x77,0x11,0x2C,0x5C,0x7F,0x34,0x7A,0x00,0x00,0x80, +0x40,0x24,0x7F,0x4B,0x6C,0x00,0x00,0x7B,0x42,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00, +0x40,0xFB,0x0F,0x50,0x40,0x87,0x40,0x68,0x70,0x87,0x69,0xE0,0x40,0xA0,0x40,0x87, +0x68,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F,0xCE,0x5A,0x00,0x00,0x84,0x40,0x64, +0x70,0x28,0x64,0x77,0x16,0x87,0x69,0xE0,0x40,0xD0,0x15,0x40,0x40,0x83,0xC0,0x05, +0x70,0x80,0x40,0x24,0x7F,0x4B,0x6C,0x00,0x00,0xA0,0x00,0x2C,0xCC,0xFC,0xEF,0x1C, +0x05,0x00,0x00,0x28,0x40,0x7F,0x47,0xA0,0x01,0x2C,0xCC,0xFC,0xEF,0x40,0x05,0x00, +0x00,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x40,0x2B,0x50,0x77,0x0B,0x2C,0x5C,0x7F, +0x34,0x7A,0x00,0x00,0x7B,0x12,0x2B,0x69,0x7F,0x0E,0x87,0x69,0xE0,0x40,0xD0,0x15, +0x40,0x40,0x83,0xC0,0x05,0x70,0x3C,0x4F,0xEF,0xBE,0xED,0xFE,0x7F,0x64,0x08,0x00, +0x02,0x77,0x06,0x80,0x40,0x7B,0x05,0x84,0x01,0x40,0x7B,0x61,0xDC,0x04,0x64,0x40, +0x3C,0x50,0xD9,0x04,0x77,0x20,0xDC,0x04,0x64,0x40,0xDC,0x08,0x64,0x41,0x3C,0x51, +0x50,0x77,0x13,0xDC,0x08,0x64,0x40,0xDC,0x0C,0x64,0x41,0x3C,0x51,0x50,0x77,0x06, +0x80,0x40,0x7B,0x39,0x2C,0x5C,0xD9,0x04,0xDC,0x01,0x7F,0xA0,0x04,0x00,0x00,0x40, +0x2B,0x50,0x77,0x09,0x2C,0x5C,0x7F,0x34,0x7A,0x00,0x00,0xA0,0x01,0x2C,0xCC,0xFC, +0xEF,0x40,0x05,0x00,0x00,0x3C,0x4F,0xEF,0xBE,0xED,0xFE,0x7F,0x64,0x08,0x00,0x02, +0x77,0x06,0x80,0x40,0x7B,0x05,0x84,0x01,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20, +0x49,0x08,0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0xA0,0x4F,0x8C,0x0D,0x00, +0x00,0xA0,0x4F,0xBC,0x10,0x00,0x00,0x2C,0xCC,0xF8,0xEF,0xB0,0x04,0x00,0x00,0xA0, +0x4F,0x9C,0x0D,0x00,0x00,0x2C,0xCC,0xFC,0xEF,0xB0,0x04,0x00,0x00,0xA0,0x5F,0x80, +0x00,0x2C,0xCC,0xFC,0x7F,0xC0,0x61,0x00,0x00,0xA0,0x4F,0xEF,0xBE,0xED,0xFE,0x2C, +0xCC,0xFC,0x7F,0x22,0x63,0x00,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x10,0x49, +0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0xA0,0x4F,0x8C,0x0D,0x00,0x00,0xA0,0x4F,0xD5, +0x10,0x00,0x00,0x2C,0xCC,0xF8,0xEF,0xB0,0x04,0x00,0x00,0xA0,0x4F,0x9C,0x0D,0x00, +0x00,0x2C,0xCC,0xFC,0xEF,0xB0,0x04,0x00,0x00,0xA0,0x6F,0x40,0x2C,0xCC,0xFC,0x7F, +0xC0,0x61,0x00,0x00,0xA0,0x4F,0xEF,0xBE,0xED,0xFE,0x2C,0xCC,0xFC,0x7F,0x22,0x63, +0x00,0x00,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x70,0x10,0x49,0x9C,0x4F, +0x00,0x00,0x00,0x00,0x4C,0xEC,0x4F,0x00,0x00,0x01,0x00,0x5A,0x40,0x86,0xE2,0x7A, +0xE0,0x41,0x9C,0x5A,0x41,0xBC,0x01,0x41,0xAC,0xE0,0x4F,0x00,0x00,0x01,0x00,0x41, +0x3C,0x41,0x40,0x53,0x0A,0x80,0x40,0x24,0x7F,0x1F,0x6E,0x00,0x00,0x83,0x7F,0x0D, +0x80,0x04,0x00,0x70,0x83,0x7F,0x08,0x80,0x04,0x00,0x70,0x83,0x7F,0x0C,0x80,0x04, +0x00,0x70,0x3B,0x77,0x01,0x7F,0x35,0x87,0x73,0x7F,0x02,0x80,0x04,0x00,0x70,0x87, +0x72,0x7F,0x02,0x80,0x04,0x00,0x70,0x3B,0x77,0x08,0x7F,0x12,0xF3,0x5F,0x80,0x00, +0x71,0x40,0x87,0x40,0x7F,0x03,0xE0,0x04,0x00,0x70,0x7B,0x0E,0xF3,0x00,0x71,0x40, +0x87,0x40,0x7F,0x03,0xE0,0x04,0x00,0x70,0x7B,0x33,0x87,0x73,0x7F,0x00,0x80,0x04, +0x00,0x70,0x87,0x72,0x7F,0x00,0x80,0x04,0x00,0x70,0x3B,0x77,0x08,0x7F,0x12,0xF3, +0x5F,0x80,0x00,0x71,0x40,0x87,0x40,0x7F,0x03,0x50,0x04,0x00,0x70,0x7B,0x0E,0xF3, +0x00,0x71,0x40,0x87,0x40,0x7F,0x03,0x50,0x04,0x00,0x70,0x83,0x7F,0x0C,0x80,0x04, +0x00,0x70,0x3B,0x77,0x01,0x7F,0x2E,0xFF,0x01,0x7B,0x40,0xBB,0x5F,0xFF,0x00,0x40, +0x87,0x40,0x7F,0x03,0x80,0x04,0x00,0x70,0x86,0xE2,0x7A,0xE0,0x40,0xBC,0x01,0x40, +0xD4,0x08,0x40,0x40,0xBB,0x5F,0xFF,0x00,0x40,0x87,0x40,0x7F,0x03,0x80,0x04,0x00, +0x70,0x7B,0x2C,0xFF,0x01,0x7B,0x40,0xBB,0x5F,0xFF,0x00,0x40,0x87,0x40,0x7F,0x01, +0x80,0x04,0x00,0x70,0x86,0xE2,0x7A,0xE0,0x40,0xBC,0x01,0x40,0xD4,0x08,0x40,0x40, +0xBB,0x5F,0xFF,0x00,0x40,0x87,0x40,0x7F,0x01,0x80,0x04,0x00,0x70,0x87,0x77,0x7F, +0x0B,0x80,0x04,0x00,0x70,0xFB,0x03,0x77,0x40,0x9F,0x01,0x40,0x8B,0x40,0x40,0xBB, +0x0F,0x40,0x87,0x40,0x7F,0x0F,0x80,0x04,0x00,0x70,0x84,0x01,0x40,0x7B,0x02,0x04, +0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x10,0x44,0x9C,0x4F,0x00,0x00,0x00,0x00, +0x4C,0x83,0x7F,0xF0,0x14,0x00,0x02,0x70,0xEB,0x6F,0x54,0x73,0x40,0x84,0x5F,0x00, +0x02,0x80,0xA4,0x0A,0x00,0x02,0x70,0xEB,0x6F,0x54,0x73,0x40,0x84,0x12,0x80,0xA0, +0x0A,0x00,0x02,0x70,0xEB,0x6F,0x54,0x73,0x40,0x84,0x04,0x80,0x9C,0x0A,0x00,0x02, +0x70,0xEB,0x6F,0x54,0x73,0x40,0x84,0x5F,0x32,0x01,0x80,0x98,0x0A,0x00,0x02,0x70, +0x80,0x7F,0x7C,0x0A,0x00,0x02,0x70,0x87,0x73,0xE0,0x40,0xA0,0x40,0xA0,0x00,0xA0, +0x4F,0x74,0x08,0x00,0x02,0xA0,0x00,0x2C,0xCC,0xF0,0x7F,0x98,0x76,0x00,0x00,0x28, +0x40,0x77,0x16,0x84,0x4F,0x00,0x00,0x01,0x00,0x7F,0x7C,0x0A,0x00,0x02,0x70,0x80, +0x40,0x24,0x7F,0xEC,0x70,0x00,0x00,0x3C,0x4F,0x0D,0x60,0x5E,0xCA,0x7F,0x78,0x08, +0x00,0x02,0x7F,0x16,0x84,0x4F,0x00,0x00,0x02,0x00,0x7F,0x7C,0x0A,0x00,0x02,0x70, +0x80,0x40,0x24,0x7F,0xEC,0x70,0x00,0x00,0xEB,0x6F,0x54,0x73,0x40,0x9C,0x4F,0x80, +0x0A,0x00,0x02,0x40,0x84,0x40,0x48,0x84,0x4F,0x74,0x08,0x00,0x02,0x47,0x82,0x46, +0x7B,0x12,0x84,0x48,0x40,0x90,0x48,0x84,0x47,0x41,0x90,0x47,0x87,0x51,0x50,0x70, +0x92,0x46,0x86,0xE2,0x46,0xE0,0x40,0x3C,0x6F,0x54,0x40,0x5B,0xE7,0x87,0x73,0xE0, +0x40,0xD0,0x01,0x40,0x40,0xEB,0x6F,0x54,0x73,0x41,0xEB,0x6F,0x54,0x73,0x42,0xEC, +0xE0,0x82,0xA4,0x0A,0x00,0x02,0x81,0xC0,0x0A,0x00,0x02,0x41,0x86,0x41,0x80,0xE8, +0x14,0x00,0x02,0x70,0x82,0x46,0x7B,0x1E,0x87,0x73,0xE0,0x40,0xD0,0x08,0x40,0x40, +0x9C,0x4F,0xE8,0x12,0x00,0x02,0x40,0x86,0xE2,0x46,0xE0,0x41,0x9C,0x41,0x40,0x83, +0x50,0x70,0x92,0x46,0x86,0xE2,0x46,0xE0,0x40,0x3C,0x5F,0x00,0x01,0x40,0x5B,0xDA, +0xEB,0x6F,0x54,0x73,0x40,0xEC,0xE0,0x08,0x80,0xA4,0x0A,0x00,0x02,0x40,0x86,0x40, +0x44,0x87,0x5F,0xFF,0x00,0x7F,0x71,0x08,0x00,0x02,0x70,0x87,0x73,0xE0,0x40,0xD0, +0x01,0x40,0x40,0x82,0x80,0xEC,0x14,0x00,0x02,0x70,0x24,0x7F,0x8B,0x70,0x00,0x00, +0x87,0x73,0xE0,0x40,0xA0,0x40,0xEB,0x6F,0x54,0x73,0x40,0x87,0x73,0xE0,0x41,0xD0, +0x01,0x41,0x41,0x86,0xE2,0x81,0xEC,0x14,0x00,0x02,0xE0,0x41,0xDC,0x41,0x80,0xBC, +0x0A,0x00,0x02,0x40,0xA0,0x40,0xA0,0x4F,0x74,0x08,0x00,0x02,0xA0,0x00,0x2C,0xCC, +0xF0,0x7F,0x98,0x76,0x00,0x00,0x28,0x40,0x77,0x2A,0x87,0x73,0xE0,0x40,0xD0,0x01, +0x40,0x40,0x86,0xE2,0x80,0xEC,0x14,0x00,0x02,0xE0,0x40,0x9C,0x06,0x40,0xD0,0x10, +0x40,0x40,0x84,0x40,0x7F,0x7C,0x0A,0x00,0x02,0x70,0x80,0x40,0x24,0x7F,0xEC,0x70, +0x00,0x00,0x82,0x45,0x7B,0x77,0x86,0xE2,0x45,0xE0,0x40,0xD0,0x03,0x40,0x40,0x3F, +0x5F,0xFF,0x00,0x80,0x74,0x08,0x00,0x02,0x77,0x04,0x7B,0x71,0x86,0xE2,0x45,0xE0, +0x40,0xD0,0x03,0x40,0x40,0x87,0x80,0x74,0x08,0x00,0x02,0xE0,0x40,0xD0,0x08,0x40, +0x40,0x86,0xE2,0x40,0xE0,0x40,0x86,0xE2,0x45,0xE0,0x41,0xD0,0x03,0x41,0x41,0x87, +0x81,0x75,0x08,0x00,0x02,0xE0,0x41,0x9C,0x41,0x40,0x86,0x40,0x46,0x87,0x73,0xE0, +0x40,0xD0,0x08,0x40,0x40,0x9C,0x4F,0xE8,0x12,0x00,0x02,0x40,0x86,0xE2,0x46,0xE0, +0x41,0xAC,0xE0,0x08,0x41,0x9C,0x41,0x40,0x86,0xE2,0x46,0xE0,0x41,0xA4,0xE0,0x08, +0x41,0xD0,0x41,0x01,0x41,0xB3,0x41,0x50,0x70,0x92,0x45,0x86,0xE2,0x45,0xE0,0x40, +0x86,0xE2,0x44,0xE0,0x41,0x3C,0x41,0x40,0x5A,0x7E,0xFF,0x86,0xE2,0x45,0xE0,0x40, +0x86,0xE2,0x44,0xE0,0x41,0x3C,0x41,0x40,0x53,0x04,0x7B,0x39,0x87,0x73,0xE0,0x40, +0xD0,0x01,0x40,0x40,0x92,0x80,0xEC,0x14,0x00,0x02,0x70,0x87,0x73,0xE0,0x40,0xD0, +0x01,0x40,0x40,0x86,0xE2,0x80,0xEC,0x14,0x00,0x02,0xE0,0x40,0x87,0x73,0xE0,0x41, +0xD0,0x01,0x41,0x41,0x86,0xE2,0x81,0xE8,0x14,0x00,0x02,0xE0,0x41,0x3C,0x41,0x40, +0x5A,0xD0,0xFE,0x87,0x73,0xE0,0x40,0xD0,0x01,0x40,0x40,0x87,0x73,0xE0,0x41,0xD0, +0x01,0x41,0x41,0x86,0xE2,0x81,0xE8,0x14,0x00,0x02,0xE0,0x41,0xBE,0x01,0x41,0x86, +0x41,0x80,0xEC,0x14,0x00,0x02,0x70,0x87,0x73,0x7F,0x71,0x08,0x00,0x02,0x70,0x87, +0x01,0x7F,0xF0,0x14,0x00,0x02,0x70,0x84,0x01,0x40,0x7B,0x02,0x04,0xC9,0xFC,0x4C, +0x20,0x48,0x20,0x47,0x20,0x46,0x20,0x45,0x20,0x44,0x20,0x49,0x08,0x70,0x70,0x70, +0x10,0x48,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x2B,0x7F,0xF0,0x14,0x00,0x02,0x77, +0x0B,0x84,0x01,0x40,0x24,0x7F,0x22,0x73,0x00,0x00,0xEB,0x6F,0x54,0x73,0x40,0x3C, +0x4F,0x0D,0x60,0x5E,0xCA,0x80,0x84,0x0A,0x00,0x02,0x7F,0x0A,0x80,0x40,0x24,0x7F, +0x22,0x73,0x00,0x00,0x87,0xDA,0x04,0xE0,0x40,0xD0,0x08,0x40,0x40,0xDC,0x01,0x74, +0x41,0x87,0x51,0xE2,0x41,0x9E,0x41,0x40,0x86,0x40,0x48,0x87,0x73,0xE0,0x40,0xD0, +0x08,0x40,0x40,0x9C,0x4F,0xE8,0x12,0x00,0x02,0x40,0x86,0x48,0xE4,0x41,0xAC,0x08, +0x41,0x9C,0x41,0x40,0x87,0x50,0xE0,0x40,0x86,0x48,0xE4,0x41,0xA4,0x08,0x41,0xD0, +0x41,0x01,0x41,0x38,0x40,0x41,0x77,0x0B,0x84,0x01,0x40,0x24,0x7F,0x22,0x73,0x00, +0x00,0x3F,0x73,0x7F,0x71,0x08,0x00,0x02,0x7F,0x46,0x87,0x73,0xE0,0x40,0xA0,0x40, +0xEB,0x6F,0x54,0x73,0x40,0xA0,0x80,0xBC,0x0A,0x00,0x02,0xA0,0x4F,0x74,0x08,0x00, +0x02,0xA0,0x00,0x2C,0xCC,0xF0,0x7F,0x98,0x76,0x00,0x00,0x28,0x40,0x77,0x0A,0x80, +0x40,0x24,0x7F,0x22,0x73,0x00,0x00,0x87,0x73,0xE0,0x40,0xD0,0x01,0x40,0x40,0x82, +0x80,0xEC,0x14,0x00,0x02,0x70,0x87,0x73,0x7F,0x71,0x08,0x00,0x02,0x70,0x3C,0xDA, +0x04,0x7F,0x74,0x08,0x00,0x02,0x57,0x08,0x24,0x7F,0x70,0x72,0x00,0x00,0x7B,0x6F, +0x87,0x73,0xE0,0x40,0xD0,0x01,0x40,0x40,0x86,0xE2,0x80,0xEC,0x14,0x00,0x02,0xE0, +0x40,0x77,0x0B,0x84,0x01,0x40,0x24,0x7F,0x22,0x73,0x00,0x00,0x87,0x73,0xE0,0x40, +0xD0,0x01,0x40,0x40,0x96,0x80,0xEC,0x14,0x00,0x02,0x70,0x87,0x73,0xE0,0x40,0xA0, +0x40,0xEB,0x6F,0x54,0x73,0x40,0x87,0x73,0xE0,0x41,0xD0,0x01,0x41,0x41,0x86,0xE2, +0x81,0xEC,0x14,0x00,0x02,0xE0,0x41,0xDC,0x41,0x80,0xBC,0x0A,0x00,0x02,0x40,0xA0, +0x40,0xA0,0x4F,0x74,0x08,0x00,0x02,0xA0,0x00,0x2C,0xCC,0xF0,0x7F,0x98,0x76,0x00, +0x00,0x28,0x40,0x77,0x0A,0x80,0x40,0x24,0x7F,0x22,0x73,0x00,0x00,0x3C,0xDA,0x04, +0x7F,0x74,0x08,0x00,0x02,0x57,0x8B,0xA0,0x74,0xA0,0x4F,0x74,0x08,0x00,0x02,0x2C, +0xCC,0xF8,0x7F,0xD6,0x7D,0x00,0x00,0x84,0x01,0x40,0x24,0x7F,0x22,0x73,0x00,0x00, +0xA0,0x74,0xA0,0x4F,0x74,0x08,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xD6,0x7D,0x00,0x00, +0x28,0x40,0x7F,0x0B,0x84,0x01,0x40,0x24,0x7F,0x22,0x73,0x00,0x00,0x7B,0x68,0x87, +0x73,0xE0,0x40,0xA0,0x40,0xEB,0x6F,0x54,0x73,0x40,0x87,0x73,0xE0,0x41,0xD0,0x01, +0x41,0x41,0x86,0xE2,0x81,0xEC,0x14,0x00,0x02,0xE0,0x41,0xDC,0x41,0x80,0xBC,0x0A, +0x00,0x02,0x40,0xA0,0x40,0xA0,0x4F,0x74,0x08,0x00,0x02,0xA0,0x00,0x2C,0xCC,0xF0, +0x7F,0x98,0x76,0x00,0x00,0x28,0x40,0x77,0x06,0x80,0x40,0x7B,0x57,0xA0,0x74,0xA0, +0x4F,0x74,0x08,0x00,0x02,0x2C,0xCC,0xF8,0x7F,0xD6,0x7D,0x00,0x00,0x28,0x40,0x7F, +0x07,0x84,0x01,0x40,0x7B,0x3E,0x87,0x73,0xE0,0x40,0xD0,0x01,0x40,0x40,0x92,0x80, +0xEC,0x14,0x00,0x02,0x70,0x87,0x73,0xE0,0x40,0xD0,0x01,0x40,0x40,0x86,0xE2,0x80, +0xEC,0x14,0x00,0x02,0xE0,0x40,0x87,0x73,0xE0,0x41,0xD0,0x01,0x41,0x41,0x86,0xE2, +0x81,0xE8,0x14,0x00,0x02,0xE0,0x41,0x3C,0x41,0x40,0x5A,0x75,0xFF,0x84,0x01,0x40, +0x7B,0x02,0x04,0xC9,0xEC,0x4C,0x20,0x48,0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F, +0x00,0x00,0x00,0x00,0x4C,0x87,0x01,0x7F,0x01,0xA0,0x04,0x00,0x70,0xA0,0x01,0x2C, +0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0xA0,0x20,0xA0,0x4F,0x74,0x0A,0x00,0x02,0xA0, +0x08,0x2C,0xCC,0xF4,0xAF,0x83,0x00,0x28,0x40,0x7F,0x1B,0x87,0x73,0xE0,0x40,0xA0, +0x40,0x2C,0xCC,0xFC,0xAF,0x1F,0x00,0x28,0x40,0x7F,0x07,0x84,0x01,0x40,0x7B,0x0A, +0x80,0x40,0x7B,0x06,0x80,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70, +0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x87,0x73,0xE0,0x40,0xA0,0x40,0x2C, +0xCC,0xFC,0xAF,0xA1,0x02,0x28,0x40,0x77,0x06,0x80,0x40,0x7B,0x31,0xF3,0x6F,0x58, +0x73,0x40,0xA0,0x40,0xA0,0x00,0xA0,0x00,0x2C,0xCC,0xF4,0xAF,0x2C,0x00,0xF3,0x6F, +0x58,0x73,0x40,0xA0,0x40,0xA0,0x00,0xA0,0x00,0x2C,0xCC,0xF4,0xAF,0x1B,0x00,0x28, +0x40,0x7F,0x07,0x84,0x01,0x40,0x7B,0x06,0x80,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C, +0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F,0x08,0x00,0x00,0x00,0x4C,0x70,0x84,0x4B, +0x7F,0xFC,0x14,0x00,0x02,0x70,0x70,0xB0,0x4F,0x00,0xE1,0x01,0x00,0x4B,0x87,0x7F, +0x01,0xA0,0x04,0x00,0xE0,0x40,0x84,0x40,0x7F,0xD4,0x12,0x00,0x02,0x70,0x38,0x40, +0x5F,0x80,0x00,0x7F,0x2A,0x87,0x73,0xE0,0x40,0xD0,0x18,0x40,0x40,0xB0,0x40,0x7F, +0xD4,0x12,0x00,0x02,0x70,0x87,0x08,0x7F,0x01,0xA0,0x04,0x00,0x70,0x84,0x7F,0xFC, +0x14,0x00,0x02,0x4B,0x84,0x00,0x40,0x24,0x7F,0x26,0x76,0x00,0x00,0x87,0x02,0x7F, +0x01,0xA0,0x04,0x00,0x70,0x87,0x08,0x7F,0x01,0xA0,0x04,0x00,0x70,0x7B,0x13,0x84, +0x74,0x40,0x90,0x74,0x70,0x87,0x50,0x7F,0x00,0xA0,0x04,0x00,0x70,0x97,0x7B,0x70, +0x2B,0x7B,0x77,0xED,0x87,0x73,0x7F,0x01,0xA0,0x04,0x00,0x70,0x82,0x59,0x70,0x7B, +0x0F,0xA0,0x01,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x92,0x59,0x70,0x86,0xE2, +0x59,0xE0,0x40,0x3C,0x5F,0xC8,0x00,0x40,0x53,0x0D,0x3B,0x7F,0x01,0xA0,0x04,0x00, +0x5F,0x80,0x00,0x77,0xDE,0x87,0x7F,0x01,0xA0,0x04,0x00,0xE0,0x40,0x84,0x40,0x7F, +0xD4,0x12,0x00,0x02,0x70,0x38,0x40,0x5F,0x80,0x00,0x7F,0x2A,0x87,0x73,0xE0,0x40, +0xD0,0x18,0x40,0x40,0xB0,0x40,0x7F,0xD4,0x12,0x00,0x02,0x70,0x87,0x08,0x7F,0x01, +0xA0,0x04,0x00,0x70,0x84,0x7F,0xFC,0x14,0x00,0x02,0x4B,0x84,0x00,0x40,0x24,0x7F, +0x26,0x76,0x00,0x00,0x3B,0x73,0x5F,0xF0,0x00,0x7F,0x2A,0x82,0x59,0x70,0x7B,0x0F, +0xA0,0x01,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x92,0x59,0x70,0x86,0xE2,0x59, +0xE0,0x40,0x3C,0x05,0x40,0x53,0x0C,0x3B,0x7F,0x01,0xA0,0x04,0x00,0x6F,0x60,0x7F, +0xE1,0x7B,0x21,0x80,0x7F,0xD4,0x12,0x00,0x02,0x70,0x87,0x08,0x7F,0x01,0xA0,0x04, +0x00,0x70,0x84,0x7F,0xFC,0x14,0x00,0x02,0x4B,0x84,0x01,0x40,0x24,0x7F,0x26,0x76, +0x00,0x00,0x87,0x7F,0x01,0xA0,0x04,0x00,0xE0,0x40,0x84,0x40,0x7F,0xD4,0x12,0x00, +0x02,0x70,0xB8,0x6F,0x60,0x40,0x3C,0x6F,0x40,0x40,0x77,0x08,0x24,0x7F,0xB7,0x75, +0x00,0x00,0x87,0x73,0xE0,0x40,0xD0,0x18,0x40,0x40,0x87,0x7F,0x00,0xA0,0x04,0x00, +0xE0,0x41,0xD0,0x08,0x41,0x41,0xB0,0x41,0x40,0xB0,0x40,0x7F,0xD4,0x12,0x00,0x02, +0x70,0x38,0x7F,0xD4,0x12,0x00,0x02,0x5F,0x00,0x20,0x7F,0x11,0x3B,0x73,0x5F,0xB0, +0x00,0x7F,0x0A,0x87,0x01,0x7F,0x00,0x15,0x00,0x02,0x70,0x38,0x7F,0xD4,0x12,0x00, +0x02,0x08,0x7F,0x31,0x84,0x7F,0xD4,0x12,0x00,0x02,0x64,0x70,0xFB,0x01,0x73,0x40, +0xA0,0x40,0x2C,0xCC,0xFC,0xAF,0xAA,0xFD,0x28,0x40,0x7F,0x11,0xFB,0x01,0x73,0x40, +0xB4,0x01,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0xAF,0xEB,0xFD,0x84,0x64,0x7F,0xD4,0x12, +0x00,0x02,0x70,0x87,0x08,0x7F,0x01,0xA0,0x04,0x00,0x70,0x84,0x7F,0xFC,0x14,0x00, +0x02,0x4B,0x84,0x00,0x40,0x7B,0x71,0x38,0x7F,0xD4,0x12,0x00,0x02,0x08,0x7F,0x4D, +0x87,0x73,0xE0,0x40,0xD0,0x18,0x40,0x40,0xB0,0x40,0x7F,0xD4,0x12,0x00,0x02,0x70, +0x84,0x7F,0xD4,0x12,0x00,0x02,0x64,0x70,0xFB,0x01,0x73,0x40,0xA0,0x40,0x2C,0xCC, +0xFC,0xAF,0x4E,0xFD,0x28,0x40,0x7F,0x11,0xFB,0x01,0x73,0x40,0xB4,0x01,0x40,0xA0, +0x40,0x2C,0xCC,0xFC,0xAF,0x8F,0xFD,0x84,0x64,0x7F,0xD4,0x12,0x00,0x02,0x70,0x84, +0x7F,0xFC,0x14,0x00,0x02,0x4B,0x84,0x00,0x40,0x7B,0x1D,0x87,0x08,0x7F,0x01,0xA0, +0x04,0x00,0x70,0x80,0x7F,0xD4,0x12,0x00,0x02,0x70,0x84,0x7F,0xFC,0x14,0x00,0x02, +0x4B,0x84,0x01,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x70, +0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0xF3,0x30,0x73,0x40,0xA0,0x40,0xA0, +0x00,0xA0,0x00,0x2C,0xCC,0xF4,0xAF,0x91,0xFD,0x28,0x40,0x77,0x06,0x80,0x40,0x7B, +0x40,0x87,0x7F,0x00,0xA0,0x04,0x00,0xE0,0x40,0x84,0x40,0x7F,0xD4,0x12,0x00,0x02, +0x70,0x38,0x40,0x02,0x7F,0x0E,0x80,0x7F,0xD4,0x12,0x00,0x02,0x70,0x84,0x01,0x40, +0x7B,0x1F,0xD0,0x10,0x7F,0xD4,0x12,0x00,0x02,0x7F,0xD4,0x12,0x00,0x02,0x70,0xB0, +0x4F,0x00,0x00,0x00,0x30,0x7F,0xD4,0x12,0x00,0x02,0x70,0x80,0x40,0x7B,0x02,0x04, +0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x10,0x49,0x9C,0x4F,0x14,0x00,0x00,0x00, +0x4C,0xEB,0x6F,0x54,0x73,0x40,0xEB,0x6F,0x54,0x73,0x41,0xE8,0x81,0xA0,0x0A,0x00, +0x02,0x80,0x9C,0x0A,0x00,0x02,0x40,0xEC,0xE0,0x40,0x74,0x40,0x84,0x40,0x64,0x70, +0xEB,0x6F,0x54,0x73,0x41,0x3C,0x81,0x98,0x0A,0x00,0x02,0x40,0x5B,0x0A,0x80,0x40, +0x24,0x7F,0x79,0x78,0x00,0x00,0xD4,0x08,0x64,0x40,0xBB,0x5F,0xFF,0x00,0x40,0x87, +0x40,0x6C,0x70,0xFB,0x5F,0xFF,0x00,0x67,0x40,0x87,0x40,0x6D,0x70,0xEB,0x6F,0x54, +0x73,0x40,0xEB,0x6F,0x54,0x73,0x41,0xE8,0x81,0xA0,0x0A,0x00,0x02,0x80,0x9C,0x0A, +0x00,0x02,0x40,0xE4,0xE0,0x40,0x74,0x40,0x84,0x40,0x59,0x70,0xEB,0x6F,0x54,0x73, +0x40,0xEC,0xE0,0x80,0xA0,0x0A,0x00,0x02,0x59,0x40,0x87,0x40,0x6E,0x70,0xEB,0x6F, +0x54,0x73,0x40,0xE4,0xE0,0x80,0xA0,0x0A,0x00,0x02,0x59,0x40,0x87,0x40,0xC9,0x0F, +0x70,0x87,0x73,0xE0,0x40,0xA0,0x40,0xE0,0x6C,0x2C,0xCC,0xF8,0x7F,0x00,0x71,0x00, +0x00,0x28,0x40,0x77,0x0A,0x80,0x40,0x24,0x7F,0x79,0x78,0x00,0x00,0x3F,0x07,0x6E, +0x5F,0x0D,0xDF,0x02,0x73,0x40,0x87,0x40,0xC9,0x11,0x70,0x7B,0x07,0x87,0x73,0xC9, +0x11,0x70,0x82,0x68,0x70,0x24,0x7F,0x43,0x78,0x00,0x00,0x86,0xE2,0x68,0xE0,0x40, +0x7F,0x10,0x87,0x73,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0x7F,0x80,0x73,0x00,0x00, +0x87,0x73,0xE0,0x40,0xA0,0x40,0xE0,0x6C,0x2C,0xCC,0xF8,0xAF,0xF8,0x00,0x28,0x40, +0x77,0x08,0x24,0x7F,0x40,0x78,0x00,0x00,0x87,0x6E,0x7F,0xF4,0x14,0x00,0x02,0x70, +0x8B,0x6C,0x40,0x87,0x40,0x7F,0xF5,0x14,0x00,0x02,0x70,0x87,0x6D,0x7F,0xF6,0x14, +0x00,0x02,0x70,0x87,0x6E,0x7F,0xF7,0x14,0x00,0x02,0x70,0x87,0xC9,0x0F,0x7F,0xF8, +0x14,0x00,0x02,0x70,0x87,0x01,0x7F,0xF9,0x14,0x00,0x02,0x70,0x2B,0xCA,0x0F,0x77, +0x07,0x84,0x04,0x40,0x7B,0x05,0x84,0x08,0x40,0xB3,0x00,0x40,0x87,0x40,0xC9,0x10, +0x70,0xA0,0x78,0x87,0xC9,0x10,0xE0,0x40,0xA0,0x40,0xEB,0x6F,0x54,0x73,0x40,0xA0, +0x80,0xA4,0x0A,0x00,0x02,0x2C,0xCC,0xF4,0x7F,0xEC,0x6C,0x00,0x00,0x28,0x40,0x77, +0x06,0x80,0x40,0x7B,0x76,0x83,0x7F,0x00,0x15,0x00,0x02,0x70,0x2B,0xCA,0x0F,0x77, +0x09,0x84,0x5F,0xB0,0x00,0x40,0x7B,0x07,0x84,0x5F,0xF0,0x00,0x40,0x87,0xC9,0x11, +0xE0,0x41,0xB0,0x41,0x40,0xA0,0x40,0xA0,0x4F,0xF4,0x14,0x00,0x02,0xA0,0x06,0x2C, +0xCC,0xF4,0x7F,0xD4,0x73,0x00,0x00,0x28,0x40,0x7F,0x07,0x84,0x01,0x40,0x7B,0x3B, +0x92,0x68,0x70,0x86,0xE2,0x68,0xE0,0x40,0x3C,0x10,0x40,0x5A,0x20,0xFF,0x2B,0x7F, +0x00,0x15,0x00,0x02,0x7F,0x21,0xA0,0x4F,0xF4,0x10,0x00,0x00,0x87,0x73,0xE0,0x40, +0xA0,0x40,0xA0,0x6C,0xA0,0x10,0x2C,0xCC,0xF0,0xEF,0xB0,0x04,0x00,0x00,0x83,0x7F, +0x00,0x15,0x00,0x02,0x70,0x80,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08, +0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x87,0x73,0xE0,0x40,0xA0,0x40,0x2C, +0xCC,0xFC,0x7F,0x30,0x76,0x00,0x00,0x28,0x40,0x77,0x06,0x80,0x40,0x7B,0x30,0x87, +0xDA,0x04,0x7F,0xF4,0x14,0x00,0x02,0x70,0xDC,0x01,0x74,0x40,0x87,0x50,0x7F,0xF5, +0x14,0x00,0x02,0x70,0xF3,0x6F,0x68,0x73,0x40,0xA0,0x40,0xA0,0x4F,0xF4,0x14,0x00, +0x02,0xA0,0x02,0x2C,0xCC,0xF4,0x7F,0xD4,0x73,0x00,0x00,0x7B,0x02,0x04,0xC9,0xE8, +0x4C,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F,0x0C,0x00,0x00,0x00,0x4C,0x84,0x4F,0x74, +0x08,0x00,0x02,0x68,0x70,0x87,0x5F,0xFF,0x00,0x7F,0x71,0x08,0x00,0x02,0x70,0x87, +0x73,0xE0,0x40,0xA0,0x40,0xEB,0x6F,0x54,0x73,0x40,0xFC,0x01,0x80,0x98,0x0A,0x00, +0x02,0x40,0xEB,0x6F,0x54,0x73,0x41,0xA8,0x81,0x9C,0x0A,0x00,0x02,0x40,0xEB,0x6F, +0x54,0x73,0x41,0xA8,0x81,0xA0,0x0A,0x00,0x02,0x40,0xA0,0x40,0xA0,0x68,0xA0,0x00, +0x2C,0xCC,0xF0,0x7F,0x98,0x76,0x00,0x00,0x28,0x40,0x77,0x06,0x80,0x40,0x7B,0x54, +0x80,0x59,0x70,0x7B,0x38,0x80,0x64,0x70,0x7B,0x29,0xE4,0x02,0x59,0x40,0x7F,0x0A, +0xFC,0x64,0x5F,0xFF,0x00,0x40,0x7B,0x05,0x84,0x64,0x40,0x84,0x68,0x41,0x90,0x68, +0x70,0x87,0x51,0xE0,0x41,0x3C,0x40,0x41,0x7F,0x06,0x80,0x40,0x7B,0x26,0x90,0x64, +0x70,0x3C,0x5F,0x00,0x01,0x64,0x4B,0xD4,0x90,0x59,0x70,0xEB,0x6F,0x54,0x73,0x40, +0xD4,0x08,0x80,0xA4,0x0A,0x00,0x02,0x40,0x3C,0x40,0x59,0x5B,0xBA,0x84,0x01,0x40, +0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x70,0x10,0x49,0x9C,0x4F, +0x04,0x00,0x00,0x00,0x4C,0x87,0x10,0x7F,0x0E,0x90,0x04,0x00,0x70,0x87,0x20,0x7F, +0x0E,0x90,0x04,0x00,0x70,0x86,0xE2,0x7F,0x02,0x40,0x04,0x00,0xE0,0x40,0xB8,0x5F, +0x00,0x04,0x40,0x3C,0x5F,0x00,0x04,0x40,0x7F,0x16,0x87,0x01,0x7F,0x1B,0x40,0x04, +0x00,0x70,0xA0,0x5F,0x2C,0x01,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0xA0,0x5F, +0xC8,0x00,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x87,0x5F,0xD0,0x00,0x7F,0x00, +0xD0,0x04,0x00,0x70,0xA0,0x01,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x3B,0x7F, +0x00,0xD0,0x04,0x00,0x5F,0x80,0x00,0x7F,0x0B,0x2C,0x5C,0xAF,0x3B,0x00,0x80,0x40, +0x7B,0x2D,0x3F,0x01,0x73,0x77,0x07,0x84,0x04,0x40,0x7B,0x04,0x80,0x40,0xB0,0x08, +0x40,0xA0,0x40,0xA0,0x10,0x2C,0xCC,0xF8,0xAF,0x47,0x00,0x28,0x40,0x7F,0x07,0x84, +0x01,0x40,0x7B,0x0B,0x2C,0x5C,0xAF,0x10,0x00,0x80,0x40,0x7B,0x02,0x04,0xC9,0xE8, +0x4C,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F,0x00,0x00,0x00,0x00,0x4C,0x87,0x01,0x7F, +0x1F,0x40,0x04,0x00,0x70,0x87,0x10,0x7F,0x0F,0x90,0x04,0x00,0x70,0x87,0x20,0x7F, +0x0F,0x90,0x04,0x00,0x70,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x10,0x49,0x9C,0x4F, +0x04,0x00,0x00,0x00,0x4C,0x3B,0x7F,0x00,0xD0,0x04,0x00,0x01,0x7F,0x0A,0x80,0x40, +0x24,0x7F,0x24,0x7B,0x00,0x00,0x70,0x84,0x4B,0x7F,0xFC,0x14,0x00,0x02,0x70,0x70, +0xB0,0x4F,0x00,0xE1,0x01,0x00,0x4B,0x87,0x73,0x7F,0x00,0xD0,0x04,0x00,0x70,0xA0, +0x01,0xA0,0x5F,0xE6,0x00,0x2C,0xCC,0xF8,0x7F,0x2C,0x55,0x00,0x00,0x80,0x59,0x70, +0x7B,0x21,0x3C,0x6F,0x64,0x59,0x4F,0x0E,0x84,0x7F,0xFC,0x14,0x00,0x02,0x4B,0x84, +0x00,0x40,0x7B,0x72,0xA0,0x01,0x2C,0xCC,0xFC,0xEF,0x28,0x05,0x00,0x00,0x90,0x59, +0x70,0x3B,0x7F,0x00,0xD0,0x04,0x00,0x01,0x77,0xDA,0xFB,0x5F,0xA0,0x00,0x73,0x40, +0x3C,0x5F,0xA0,0x00,0x40,0x7F,0x0F,0xFB,0x5F,0xF0,0x00,0x73,0x40,0x3C,0x5F,0xF0, +0x00,0x40,0x77,0x10,0xA0,0x01,0xA0,0x5F,0xE6,0x00,0x2C,0xCC,0xF8,0x7F,0x2C,0x55, +0x00,0x00,0x3B,0x7F,0x00,0xD0,0x04,0x00,0x77,0x7F,0x1F,0x3B,0x7F,0x00,0xD0,0x04, +0x00,0x08,0x7F,0x0A,0x87,0x01,0x7F,0x00,0x15,0x00,0x02,0x70,0x84,0x7F,0xFC,0x14, +0x00,0x02,0x4B,0x84,0x00,0x40,0x7B,0x0E,0x84,0x7F,0xFC,0x14,0x00,0x02,0x4B,0x84, +0x01,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F, +0x0C,0x00,0x00,0x00,0x4C,0xEC,0xE0,0x12,0x5A,0x40,0x3C,0x6F,0x50,0x40,0x5B,0x0A, +0x80,0x40,0x24,0x7F,0x94,0x7D,0x00,0x00,0x2B,0xCA,0x0F,0x7F,0x08,0x3F,0x03,0xCA, +0x0F,0x77,0x79,0xA0,0x01,0x2C,0xCC,0xFC,0x7F,0x8C,0x79,0x00,0x00,0x28,0x40,0x77, +0x0A,0x80,0x40,0x24,0x7F,0x94,0x7D,0x00,0x00,0x87,0x5F,0xFF,0x00,0x7F,0x71,0x08, +0x00,0x02,0x70,0x83,0x7F,0x70,0x08,0x00,0x02,0x70,0xA0,0x5F,0x8E,0x05,0xA0,0x4F, +0x74,0x08,0x00,0x02,0xA0,0x00,0xA0,0x01,0x2C,0xCC,0xF0,0xCF,0xA4,0x28,0x40,0x77, +0x0A,0x80,0x40,0x24,0x7F,0x94,0x7D,0x00,0x00,0x3C,0x4F,0x0D,0x60,0x5E,0xCA,0x7F, +0x78,0x08,0x00,0x02,0x77,0x18,0x86,0x7F,0xB2,0x08,0x00,0x02,0x7F,0x02,0x15,0x00, +0x02,0x70,0x87,0x01,0x7F,0x70,0x08,0x00,0x02,0x70,0x7B,0x10,0x82,0x7F,0x02,0x15, +0x00,0x02,0x70,0x83,0x7F,0x70,0x08,0x00,0x02,0x70,0x83,0x68,0x70,0xEC,0xE0,0x12, +0x5A,0x40,0x87,0x40,0x69,0x70,0xE4,0xE0,0x12,0x5A,0x40,0xAC,0xE0,0x09,0x40,0x87, +0x40,0x6A,0x70,0xE4,0xE0,0x09,0x5A,0x40,0x87,0x40,0x6B,0x70,0x2B,0x7F,0x70,0x08, +0x00,0x02,0x7F,0x60,0x3F,0x02,0x7F,0x71,0x08,0x00,0x02,0x7F,0x49,0x87,0x5F,0xFF, +0x00,0x7F,0x71,0x08,0x00,0x02,0x70,0x83,0x7F,0x70,0x08,0x00,0x02,0x70,0x86,0x7F, +0x02,0x15,0x00,0x02,0xE4,0x40,0xA0,0x40,0xA0,0x4F,0x74,0x08,0x00,0x02,0xA0,0x00, +0xA0,0x01,0x2C,0xCC,0xF0,0xAF,0x0A,0xFF,0x28,0x40,0x77,0x0A,0x80,0x40,0x24,0x7F, +0x94,0x7D,0x00,0x00,0x87,0x02,0x7F,0x71,0x08,0x00,0x02,0x70,0x87,0x01,0x7F,0x70, +0x08,0x00,0x02,0x70,0xE0,0x68,0xA0,0x4F,0x74,0x08,0x00,0x02,0x2C,0xCC,0xF8,0xAF, +0x8A,0x01,0x87,0x5F,0x9C,0x00,0x66,0x70,0x3F,0x01,0x7B,0x77,0x14,0x87,0x6F,0x49, +0x64,0x70,0x87,0x5F,0xA0,0x00,0x65,0x70,0xB3,0x6F,0x40,0x66,0x70,0x7B,0x0D,0x87, +0x6F,0x45,0x64,0x70,0x87,0x5F,0x80,0x00,0x65,0x70,0x87,0x6A,0xE0,0x40,0xD0,0x01, +0x40,0x40,0xB3,0x08,0x40,0xB3,0x40,0x65,0x70,0x82,0x62,0x70,0x82,0x59,0x70,0x24, +0x7F,0x30,0x7D,0x00,0x00,0x87,0x69,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xFC,0xAF,0x01, +0x01,0x28,0x40,0x77,0x1A,0xA0,0x01,0x2C,0xCC,0xFC,0x7F,0x8C,0x79,0x00,0x00,0x28, +0x40,0x77,0x0A,0x80,0x40,0x24,0x7F,0x94,0x7D,0x00,0x00,0x7B,0x72,0xDF,0x01,0x6B, +0x40,0x87,0x40,0x7F,0x02,0xD0,0x04,0x00,0x70,0xA0,0x74,0x87,0x64,0xE0,0x40,0xA0, +0x40,0xA0,0x5F,0x00,0x02,0x2C,0xCC,0xF4,0x7F,0xEC,0x6C,0x00,0x00,0x28,0x40,0x77, +0x0A,0x80,0x40,0x24,0x7F,0x94,0x7D,0x00,0x00,0x83,0x7F,0x00,0x15,0x00,0x02,0x70, +0x87,0x65,0xE0,0x40,0xA0,0x40,0x87,0x66,0xE0,0x40,0xA0,0x40,0x2C,0xCC,0xF8,0x7F, +0x5C,0x7A,0x00,0x00,0x28,0x40,0x7F,0x08,0x86,0x01,0x62,0x70,0x7B,0x2A,0x3B,0x7F, +0x00,0xD0,0x04,0x00,0x5F,0x80,0x00,0x7F,0x04,0x7B,0x1D,0xA0,0x01,0x2C,0xCC,0xFC, +0x7F,0x8C,0x79,0x00,0x00,0x28,0x40,0x77,0x06,0x80,0x40,0x7B,0x69,0x92,0x59,0x70, +0x3E,0x10,0x59,0x4A,0x62,0xFF,0x2B,0x7F,0x00,0x15,0x00,0x02,0x7F,0x1B,0xA0,0x4F, +0x28,0x11,0x00,0x00,0xA0,0x68,0xA0,0x10,0x2C,0xCC,0xF4,0xEF,0xB0,0x04,0x00,0x00, +0x83,0x7F,0x00,0x15,0x00,0x02,0x70,0x2A,0x62,0x7F,0x0E,0x3F,0x02,0xCA,0x0F,0x7F, +0x08,0x3F,0x03,0xCA,0x0F,0x77,0x29,0x2B,0x7F,0x70,0x08,0x00,0x02,0x7F,0x1A,0x83, +0x7F,0x70,0x08,0x00,0x02,0x70,0x82,0x7F,0x02,0x15,0x00,0x02,0x70,0x87,0x5F,0xFF, +0x00,0x7F,0x71,0x08,0x00,0x02,0x70,0x2C,0x5C,0x7F,0x34,0x7A,0x00,0x00,0x86,0x62, +0xE4,0x40,0x7B,0x02,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F, +0x00,0x00,0x00,0x00,0x4C,0x3F,0x73,0x7F,0x01,0xD0,0x04,0x00,0x77,0x07,0x84,0x01, +0x40,0x7B,0x1D,0x87,0x73,0x7F,0x03,0xD0,0x04,0x00,0x70,0xA0,0x1C,0xA0,0x10,0x2C, +0xCC,0xF8,0x7F,0x5C,0x7A,0x00,0x00,0x86,0xE2,0x40,0xE0,0x40,0x7B,0x02,0x04,0xC9, +0xE8,0x4C,0x20,0x49,0x08,0x70,0x10,0x49,0x9C,0x4F,0x04,0x00,0x00,0x00,0x4C,0x82, +0x59,0x70,0x7B,0x42,0x86,0x59,0xE4,0x40,0xD0,0x03,0x40,0x40,0x9C,0x74,0x40,0x3C, +0xDA,0x00,0x50,0x77,0x18,0x86,0x59,0xE4,0x40,0xD0,0x03,0x40,0x40,0x9C,0x74,0x40, +0x84,0xC0,0x04,0xDA,0x00,0x70,0x84,0x01,0x40,0x7B,0x25,0x86,0x59,0xE4,0x40,0xD0, +0x03,0x40,0x40,0x9C,0x74,0x40,0x3C,0xDA,0x00,0x50,0x5F,0x07,0x84,0x01,0x40,0x7B, +0x0F,0x92,0x59,0x70,0x3E,0x6F,0x40,0x59,0x4B,0xBC,0x80,0x40,0x7B,0x02,0x04,0xC9, +0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x70,0x10,0x47,0x84,0x5A,0x41,0x84,0x00,0x47, +0x87,0x51,0xE0,0x48,0x3B,0x88,0x71,0x11,0x00,0x00,0x04,0x77,0x46,0x7B,0x13,0x04, +0xC9,0xF0,0x4C,0x20,0x48,0x20,0x47,0x20,0x49,0x08,0x90,0x41,0x87,0x51,0xE0,0x48, +0x3B,0x88,0x71,0x11,0x00,0x00,0x08,0x77,0xF3,0x3C,0x48,0x2B,0x7F,0x09,0x3C,0x48, +0x2D,0x77,0x0A,0x90,0x47,0x90,0x41,0x87,0x51,0xE0,0x48,0x3B,0x88,0x71,0x11,0x00, +0x00,0x04,0x77,0x0F,0x80,0x40,0x04,0xC9,0xF0,0x4C,0x20,0x48,0x20,0x47,0x20,0x49, +0x08,0xFC,0x48,0x30,0x42,0x7B,0x0C,0xA8,0x0A,0x42,0xFC,0x48,0x30,0x40,0x9C,0x40, +0x42,0x90,0x41,0x87,0x51,0xE0,0x48,0x3B,0x88,0x71,0x11,0x00,0x00,0x04,0x77,0xE9, +0x28,0x47,0x7F,0x10,0x84,0x42,0x40,0x04,0xC9,0xF0,0x4C,0x20,0x48,0x20,0x47,0x20, +0x49,0x08,0x8C,0x42,0x40,0x04,0xC9,0xF0,0x4C,0x20,0x48,0x20,0x47,0x20,0x49,0x08, +0x10,0x47,0x84,0x5A,0x41,0x84,0x00,0x47,0x87,0x51,0xE0,0x48,0x3B,0x88,0x71,0x11, +0x00,0x00,0x04,0x77,0x46,0x7B,0x13,0x04,0xC9,0xF0,0x4C,0x20,0x48,0x20,0x47,0x20, +0x49,0x08,0x90,0x41,0x87,0x51,0xE0,0x48,0x3B,0x88,0x71,0x11,0x00,0x00,0x08,0x77, +0xF3,0x3C,0x48,0x2B,0x7F,0x09,0x3C,0x48,0x2D,0x77,0x0A,0x90,0x47,0x90,0x41,0x87, +0x51,0xE0,0x48,0x3B,0x88,0x71,0x11,0x00,0x00,0x04,0x77,0x0F,0x80,0x40,0x04,0xC9, +0xF0,0x4C,0x20,0x48,0x20,0x47,0x20,0x49,0x08,0xFC,0x48,0x30,0x42,0x7B,0x0C,0xA8, +0x0A,0x42,0xFC,0x48,0x30,0x40,0x9C,0x40,0x42,0x90,0x41,0x87,0x51,0xE0,0x48,0x3B, +0x88,0x71,0x11,0x00,0x00,0x04,0x77,0xE9,0x28,0x47,0x7F,0x10,0x84,0x42,0x40,0x04, +0xC9,0xF0,0x4C,0x20,0x48,0x20,0x47,0x20,0x49,0x08,0x8C,0x42,0x40,0x04,0xC9,0xF0, +0x4C,0x20,0x48,0x20,0x47,0x20,0x49,0x08,0x10,0x49,0x84,0x5A,0x40,0x84,0x74,0x41, +0x3C,0x41,0x40,0x77,0x08,0x7B,0x10,0x90,0x40,0x90,0x41,0x3F,0x51,0x50,0x77,0x07, +0x3F,0x50,0x00,0x77,0xF4,0xFF,0x51,0x50,0x40,0x87,0xE7,0x40,0xE4,0x40,0x04,0xC9, +0xE8,0x4C,0x20,0x49,0x08,0x70,0x70,0x70,0x10,0x49,0x84,0x5A,0x40,0x7B,0x04,0x90, +0x40,0x2B,0x50,0x77,0xFC,0xBC,0x5A,0x40,0x04,0xC9,0xE8,0x4C,0x20,0x49,0x08,0x70, +0x10,0x49,0x84,0x5A,0x41,0x84,0x74,0x40,0x30,0x35,0x84,0x5A,0x40,0x04,0xC9,0xE8, +0x4C,0x20,0x49,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x72, +0x22,0x22,0x22,0x22,0x03,0x02,0x01,0x30,0x03,0x02,0x01,0x0E,0x03,0x02,0x01,0x0B,}; +#endif /* _ROM_400_bin_H */ diff --git a/README.md b/README.md index 8db50c73..bb20b11d 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ ### New Simulators +#### Seth Morabito has implemented a AT&T 3B2 simulator. + #### Leonid Broukhis and Serge Vakulenko have implemented a simulator for the Soviet mainframe BESM-6 computer. #### Matt Burke has implemented new VAX model simulators: diff --git a/Visual Studio Projects/3B2.vcproj b/Visual Studio Projects/3B2.vcproj new file mode 100644 index 00000000..6cdd7525 --- /dev/null +++ b/Visual Studio Projects/3B2.vcproj @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Visual Studio Projects/Simh.sln b/Visual Studio Projects/Simh.sln index ca9e4c2b..a004b0b0 100644 --- a/Visual Studio Projects/Simh.sln +++ b/Visual Studio Projects/Simh.sln @@ -254,6 +254,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scelbi", "scelbi.vcproj", " {D40F3AF1-EEE7-4432-9807-2AD287B490F8} = {D40F3AF1-EEE7-4432-9807-2AD287B490F8} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "3B2", "3B2.vcproj", "{56178F08-8783-4ADA-820C-20C06412678E}" + ProjectSection(ProjectDependencies) = postProject + {D40F3AF1-EEE7-4432-9807-2AD287B490F8} = {D40F3AF1-EEE7-4432-9807-2AD287B490F8} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -472,6 +477,10 @@ Global {1E92CC4B-9ED5-4CD4-BD35-061F25126523}.Debug|Win32.Build.0 = Debug|Win32 {1E92CC4B-9ED5-4CD4-BD35-061F25126523}.Release|Win32.ActiveCfg = Release|Win32 {1E92CC4B-9ED5-4CD4-BD35-061F25126523}.Release|Win32.Build.0 = Release|Win32 + {56178F08-8783-4ADA-820C-20C06412678E}.Debug|Win32.ActiveCfg = Debug|Win32 + {56178F08-8783-4ADA-820C-20C06412678E}.Debug|Win32.Build.0 = Debug|Win32 + {56178F08-8783-4ADA-820C-20C06412678E}.Release|Win32.ActiveCfg = Release|Win32 + {56178F08-8783-4ADA-820C-20C06412678E}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/descrip.mms b/descrip.mms index 4506097d..a0283606 100644 --- a/descrip.mms +++ b/descrip.mms @@ -16,6 +16,7 @@ # This build script will accept the following build options. # # ALL Just Build "Everything". +# 3B2 Just Build The AT&T 3B2. # ALTAIR Just Build The MITS Altair. # ALTAIRZ80 Just Build The MITS Altair Z80. # BESM6 Just Build The BESM-6. @@ -306,6 +307,17 @@ PCAP_SIMH_INC = /INCL=($(PCAP_DIR)) @ IF (("$(BUILDING_ROMS)".EQS."").AND.(F$SEARCH("$(BIN_DIR)BuildROMs-$(ARCH).EXE").EQS."")) THEN $(MMS) BUILDROMS/MACRO=(BUILDING_ROMS=1$(NEST_DEBUG)) +# AT&T 3B2 Simulator Definitions. +# +ATT3B2_DIR = SYS$DISK:[.3B2] +ATT3B2_LIB = $(LIB_DIR)ATT3B2-$(ARCH).OLB +ATT3B2_SOURCE = $(ATT3B2_DIR)3B2_CPU.C,$(ATT3B2_DIR)3B2_DMAC.C,\ + $(ATT3B2_DIR)3B2_ID.C,$(ATT3B2_DIR)3B2_IF.C,\ + $(ATT3B2_DIR)3B2_IO.C,$(ATT3B2_DIR)3B2_IU.C,\ + $(ATT3B2_DIR)3B2_MMU.C,$(ATT3B2_DIR)3B2_SYS.C,\ + $(ATT3B2_DIR)3B2_SYSDEV.C +ALTAIR_OPTIONS = /INCL=($(SIMH_DIR),$(ATT3B2_DIR))/DEF=($(CC_DEFS)) + # MITS Altair Simulator Definitions. # ALTAIR_DIR = SYS$DISK:[.ALTAIR] @@ -1033,6 +1045,17 @@ $(SIMH_LIB64) : $(SIMH_SOURCE) $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* .ENDIF +$(ATT3B2_LIB) : $(ATT3B2_SOURCE) + $! + $! Building The $(ATT3B2_LIB) Library. + $! + $ $(CC)$(ATT3B2_OPTIONS) - + /OBJ=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + $(ALTAIR_LIB) : $(ALTAIR_SOURCE) $! $! Building The $(ALTAIR_LIB) Library. @@ -1698,6 +1721,33 @@ $(I7094_LIB) : # # Individual Simulator Builds. # + +# +# If Not On VAX, Build The AT&T 3B2 Simulator. +# +.IFDEF ALPHA_OR_IA64 +ATT3B2 : $(BIN_DIR)ATT3B2-$(ARCH).EXE + $! ATT3B2 aka 3B2 done +.ELSE +# +# Else We Are On VAX And Tell The User We Can't Build On VAX +# Due To The Use Of INT64. +# +ATT3B2 : + $! Sorry, Can't Build $(BIN_DIR)ATT3B2-$(ARCH).EXE Simulator + $! Because It Requires The Use Of INT64. +.ENDIF + +$(BIN_DIR)ATT3B2-$(ARCH).EXE : $(SIMH_MAIN) $(SIMH_NONET_LIB) $(ATT3B2_LIB) + $! + $! Building The $(BIN_DIR)ATT3B2-$(ARCH).EXE Simulator. + $! + $ $(CC)$(ATT3B2_OPTIONS)/OBJ=$(BLD_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ATT3B2-$(ARCH).EXE - + $(BLD_DIR)SCP.OBJ,$(ATT3B2_LIB)/LIBRARY,$(SIMH_NONET_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + $ COPY $(BIN_DIR)ATT3B2-$(ARCH).EXE $(BIN_DIR)3B2-$(ARCH).EXE + ALTAIR : $(BIN_DIR)ALTAIR-$(ARCH).EXE $! ALTAIR done diff --git a/makefile b/makefile index 634c3335..d58a7654 100644 --- a/makefile +++ b/makefile @@ -1547,6 +1547,14 @@ PDQ3D = PDQ-3 PDQ3 = ${PDQ3D}/pdq3_cpu.c ${PDQ3D}/pdq3_sys.c ${PDQ3D}/pdq3_stddev.c \ ${PDQ3D}/pdq3_mem.c ${PDQ3D}/pdq3_debug.c ${PDQ3D}/pdq3_fdc.c PDQ3_OPT = -I ${PDQ3D} -DUSE_SIM_IMD + +ATT3B2D = 3B2 +ATT3B2 = ${ATT3B2D}/3b2_cpu.c ${ATT3B2D}/3b2_mmu.c \ + ${ATT3B2D}/3b2_iu.c ${ATT3B2D}/3b2_if.c \ + ${ATT3B2D}/3b2_id.c ${ATT3B2D}/3b2_dmac.c \ + ${ATT3B2D}/3b2_sys.c ${ATT3B2D}/3b2_io.c \ + ${ATT3B2D}/3b2_sysdev.c +ATT3B2_OPT = -I ${ATT3B2D} -DUSE_INT64 -DUSE_ADDR64 # # Build everything (not the unsupported/incomplete or experimental simulators) # @@ -1555,7 +1563,7 @@ ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \ nova eclipse hp2100 hp3000 i1401 i1620 s3 altair altairz80 gri \ i7094 ibm1130 id16 id32 sds lgp h316 cdc1700 \ swtp6800mp-a swtp6800mp-a2 tx-0 ssem b5500 isys8010 isys8020 \ - isys8030 isys8024 imds-225 scelbi + isys8030 isys8024 imds-225 scelbi 3b2 all : ${ALL} @@ -1933,6 +1941,12 @@ ${BIN}b5500${EXE} : ${B5500} ${SIM} ${MKDIRBIN} ${CC} ${B5500} ${SIM} ${B5500_OPT} $(CC_OUTSPEC) ${LDFLAGS} +3b2 : $(BIN)3b2$(EXE) + +${BIN}3b2${EXE} : ${ATT3B2} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${ATT3B2} ${SIM} ${ATT3B2_OPT} $(CC_OUTSPEC) ${LDFLAGS} + # Front Panel API Demo/Test program frontpaneltest : ${BIN}frontpaneltest${EXE} diff --git a/sim_BuildROMs.c b/sim_BuildROMs.c index 2896f8f1..4c473624 100644 --- a/sim_BuildROMs.c +++ b/sim_BuildROMs.c @@ -48,6 +48,7 @@ struct ROM_File_Descriptor { {"VAX/vmb.exe", "VAX/vax_vmb_exe.h", 44544, 0xFFC014BB, "vax_vmb_exe"}, {"PDP11/lunar11/lunar.lda", "PDP11/pdp11_vt_lunar_rom.h", 13824 , 0xFFF15D00, "lunar_lda"}, {"swtp6800/swtp6800/swtbug.bin", "swtp6800/swtp6800/swtp_swtbug_bin.h", 1024, 0xFFFE4FBC, "swtp_swtbug_bin"}, + {"3B2/rom_400.bin", "3B2/rom_400_bin.h", 32768, 0xFFD55762, "rom_400_bin"}, };