diff options
Diffstat (limited to 'src/emu/cpu/pdp1')
-rw-r--r-- | src/emu/cpu/pdp1/pdp1.c | 1818 | ||||
-rw-r--r-- | src/emu/cpu/pdp1/pdp1.h | 199 | ||||
-rw-r--r-- | src/emu/cpu/pdp1/pdp1dasm.c | 294 | ||||
-rw-r--r-- | src/emu/cpu/pdp1/tx0.c | 1080 | ||||
-rw-r--r-- | src/emu/cpu/pdp1/tx0.h | 179 | ||||
-rw-r--r-- | src/emu/cpu/pdp1/tx0dasm.c | 123 |
6 files changed, 0 insertions, 3693 deletions
diff --git a/src/emu/cpu/pdp1/pdp1.c b/src/emu/cpu/pdp1/pdp1.c deleted file mode 100644 index bb7beee4128..00000000000 --- a/src/emu/cpu/pdp1/pdp1.c +++ /dev/null @@ -1,1818 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Raphael Nabet -/* - * Note: Original Java source written by: - * - * Barry Silverman mailto:barry@disus.com or mailto:bss@media.mit.edu - * Vadim Gerasimov mailto:vadim@media.mit.edu - * - * MESS driver by Chris Salomon and Raphael Nabet. - * - * Basically, it has been rewritten entirely in order to perform cycle-level simulation - * (with only a few flip-flops being set one cycle too early or too late). I don't know if - * it is a good thing or a bad thing (it makes emulation more accurate, but slower, and - * code is more complex and less readable), but it appears to be the only way we could emulate - * mid-instruction sequence break. And it enables us to emulate the control panel fairly - * accurately. - * - * Additionnally, IOT functions have been modified to be external: IOT callback pointers are set - * at emulation initiation, and most IOT callback functions are part of the machine emulation. - * - * - * for the runnable java applet, with applet and Spacewar! source, go to: - * http://lcs.www.media.mit.edu/groups/el/projects/spacewar/ - * - * for a complete html version of the pdp1 handbook go to: - * http://www.dbit.com/~greeng3/pdp1/index.html - * - * there is another java simulator (by the same people) which runs the - * original pdp1 LISP interpreter, go to: - * http://lcs.www.media.mit.edu/groups/el/projects/pdp1 - * - * Another PDP1 emulator (or simulator) is at: - * ftp://minnie.cs.adfa.oz.au/pub/PDP-11/Sims/Supnik_2.3 - * It seems to emulate pdp1 I/O more accurately than we do. - * However, there is no CRT emulation. - * - * and finally, there is a nice article about SPACEWAR!, go to: - * http://ars-www.uchicago.edu/~eric/lore/spacewar/spacewar.html - * - * some extra documentation is available on spies: - * http://www.spies.com/~aek/pdf/dec/pdp1/ - * The file "F17_PDP1Maint.pdf" explains operation procedures and much of the internals of pdp-1. - * It was the main reference for this emulator. - * The file "F25_PDP1_IO.pdf" has interesting information on the I/O system, too. - * - * Following is an extract from the handbook: - * - * INTRODUCTION - * - * The Programmed Data Processor (PDP-1) is a high speed, solid state digital computer designed to - * operate with many types of input-output devices with no internal machine changes. It is a single - * address, single instruction, stored program computer with powerful program features. Five-megacycle - * circuits, a magnetic core memory and fully parallel processing make possible a computation rate of - * 100,000 additions per second. The PDP-1 is unusually versatile. It is easy to install, operate and - * maintain. Conventional 110-volt power is used, neither air conditioning nor floor reinforcement is - * necessary, and preventive maintenance is provided for by built-in marginal checking circuits. - * - * PDP-1 circuits are based on the designs of DEC's highly successful and reliable System Modules. - * Flip-flops and most switches use saturating transistors. Primary active elements are - * Micro-Alloy-Diffused transistors. - * - * The entire computer occupies only 17 square feet of floor space. It consists of four equipment frames, - * one of which is used as the operating station. - * - * CENTRAL PROCESSOR - * - * The Central Processor contains the control, arithmetic and memory addressing elements, and the memory - * buffer register. The word length is 18 binary digits. Instructions are performed in multiples of the - * memory cycle time of five microseconds. Add, subtract, deposit, and load, for example, are two-cycle - * instructions requiring 10 microseconds. Multiplication requires and average of 20 microseconds. - * Program features include: single address instructions, multiple step indirect addressing and logical - * arithmetic commands. Console features include: flip-flop indicators grouped for convenient octal - * reading, six program flags for automatic setting and computer sensing, and six sense switches for - * manual setting and computer sensing. - * - * MEMORY SYSTEM - * - * The coincident-current, magnetic core memory of a standard PDP-1 holds 4096 words of 18 bits each. - * Memory capacity may be readily expanded, in increments of 4096 words, to a maximum of 65,536 words. - * The read-rewrite time of the memory is five microseconds, the basic computer rate. Driving currents - * are automatically adjusted to compensate for temperature variations between 50 and 110 degrees - * Fahrenheit. The core memory storage may be supplemented by up to 24 magnetic tape transports. - * - * INPUT-OUTPUT - * - * PDP-1 is designed to operate a variety of buffered input-output devices. Standard equipment consistes - * of a perforated tape reader with a read speed of 400 lines per second, and alphanuermic typewriter for - * on-line operation in both input and output, and a perforated tape punch (alphanumeric or binary) with - * a speed of 63 lines per second. A variety of optional equipment is available, including the following: - * - * Precision CRT Display Type 30 - * Ultra-Precision CRT Display Type 31 - * Symbol Generator Type 33 - * Light Pen Type 32 - * Oscilloscope Display Type 34 - * Card Punch Control Type 40-1 - * Card Reader and Control Type 421 - * Magnetic Tape Transport Type 50 - * Programmed Magnetic Tape Control Type 51 - * Automatic Magnetic Tape Control Type 52 - * Automatic Magnetic Tape Control Type 510 - * Parallel Drum Type 23 - * Automatic Line Printer and Control Type 64 - * 18-bit Real Time Clock - * 18-bit Output Relay Buffer Type 140 - * Multiplexed A-D Converter Type 138/139 - * - * All in-out operations are performed through the In-Out Register or through the high speed input-output - * channels. - * - * The PDP-1 is also available with the optional Sequence Break System. This is a multi-channel priority - * interrupt feature which permits concurrent operation of several in-out devices. A one-channel Sequence - * Break System is included in the standard PDP-1. Optional Sequence Break Systems consist of 16, 32, 64, - * 128, and 256 channels. - * - * ... - * - * BASIC INSTRUCTIONS - * - * OPER. TIME - * INSTRUCTION CODE # EXPLANATION (usec) - * ------------------------------------------------------------------------------ - * add Y 40 Add C(Y) to C(AC) 10 - * and Y 02 Logical AND C(Y) with C(AC) 10 - * cal Y 16 Equals jda 100 10 - * dac Y 24 Deposit C(AC) in Y 10 - * dap Y 26 Deposit contents of address part of AC in Y 10 - * dio Y 32 Deposit C(IO) in Y 10 - * dip Y 30 Deposit contents of instruction part of AC in Y 10 - * div Y 56 Divide 40 max - * dzm Y 34 Deposit zero in Y 10 - * idx Y 44 Index (add one) C(Y), leave in Y & AC 10 - * ior Y 04 Inclusive OR C(Y) with C(AC) 10 - * iot Y 72 In-out transfer, see below - * isp Y 46 Index and skip if result is positive 10 - * jda Y 17 Equals dac Y and jsp Y+1 10 - * jmp Y 60 Take next instruction from Y 5 - * jsp Y 62 Jump to Y and save program counter in AC 5 - * lac Y 20 Load the AC with C(Y) 10 - * law N 70 Load the AC with the number N 5 - * law-N 71 Load the AC with the number -N 5 - * lio Y 22 Load IO with C(Y) 10 - * mul Y 54 Multiply 25 max - * opr 76 Operate, see below 5 - * sad Y 50 Skip next instruction if C(AC) <> C(Y) 10 - * sas Y 52 Skip next instruction if C(AC) = C(Y) 10 - * sft 66 Shift, see below 5 - * skp 64 Skip, see below 5 - * sub Y 42 Subtract C(Y) from C(AC) 10 - * xct Y 10 Execute instruction in Y 5+ - * xor Y 06 Exclusive OR C(Y) with C(AC) 10 - * - * OPERATE GROUP - * - * OPER. TIME - * INSTRUCTION CODE # EXPLANATION (usec) - * ------------------------------------------------------------------------------ - * cla 760200 Clear AC 5 - * clf 76000f Clear selected Program Flag (f = flag #) 5 - * cli 764000 Clear IO 5 - * cma 761000 Complement AC 5 - * hlt 760400 Halt 5 - * lap 760100 Load AC with Program Counter 5 - * lat 762200 Load AC from Test Word switches 5 - * nop 760000 No operation 5 - * stf 76001f Set selected Program Flag 5 - * - * IN-OUT TRANSFER GROUP - * - * PERFORATED TAPE READER - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * rpa 720001 Read Perforated Tape Alphanumeric - * rpb 720002 Read Perforated Tape Binary - * rrb 720030 Read Reader Buffer - * - * PERFORATED TAPE PUNCH - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * ppa 720005 Punch Perforated Tape Alphanumeric - * ppb 720006 Punch Perforated Tape Binary - * - * ALPHANUMERIC ON-LINE TYPEWRITER - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * tyo 720003 Type Out - * tyi 720004 Type In - * - * SEQUENCE BREAK SYSTEM TYPE 120 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * esm 720055 Enter Sequence Break Mode - * lsm 720054 Leave Sequence Break Mode - * cbs 720056 Clear Sequence Break System - * dsc 72kn50 Deactivate Sequence Break Channel - * asc 72kn51 Activate Sequence Break Channel - * isb 72kn52 Initiate Sequence Break - * cac 720053 Clear All Channels - * - * HIGH SPEED DATA CONTROL TYPE 131 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * swc 72x046 Set Word Counter - * sia 720346 Set Location Counter - * sdf 720146 Stop Data Flow - * rlc 720366 Read Location Counter - * shr 720446 Set High Speed Channel Request - * - * PRECISION CRT DISPLAY TYPE 30 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * dpy 720007 Display One Point - * - * SYMBOL GENERATOR TYPE 33 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * gpl 722027 Generator Plot Left - * gpr 720027 Generator Plot Right - * glf 722026 Load Format - * gsp 720026 Space - * sdb 722007 Load Buffer, No Intensity - * - * ULTRA-PRECISION CRT DISPLAY TYPE 31 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * dpp 720407 Display One Point on Ultra Precision CRT - * - * CARD PUNCH CONTROL TYPE 40-1 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * lag 720044 Load a Group - * pac 720043 Punch a Card - * - * CARD READER TYPE 421 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * rac 720041 Read Card Alpha - * rbc 720042 Read Card Binary - * rcc 720032 Read Card Column - * - * PROGRAMMED MAGNETIC TAPE CONTROL TYPE 51 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * msm 720073 Select Mode - * mcs 720034 Check Status - * mcb 720070 Clear Buffer - * mwc 720071 Write a Character - * mrc 720072 Read Character - * - * AUTOMATIC MAGNETIC TAPE CONTROL TYPE 52 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * muf 72ue76 Tape Unit and FinalT - * mic 72ue75 Initial and Command - * mrf 72u067 Reset Final - * mri 72ug66 Reset Initial - * mes 72u035 Examine States - * mel 72u036 Examine Location - * inr 72ur67 Initiate a High Speed Channel Request - * ccr 72s067 Clear Command Register - * - * AUTOMATIC MAGNETIC TAPE CONTROL TYPE 510 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * sfc 720072 Skip if Tape Control Free - * rsr 720172 Read State Register - * crf 720272 Clear End-of-Record Flip-Flop - * cpm 720472 Clear Proceed Mode - * dur 72xx70 Load Density, Unit, Rewind - * mtf 73xx71 Load Tape Function Register - * cgo 720073 Clear Go - * - * MULTIPLEXED A-D CONVERTER TYPE 138/139 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * rcb 720031 Read Converter Buffer - * cad 720040 Convert a Voltage - * scv 72mm47 Select Multiplexer (1 of 64 Channels) - * icv 720060 Index Multiplexer - * - * AUTOMATIC LINE PRINTER TYPE 64 - * - * INSTRUCTION CODE # EXPLANATION - * ------------------------------------------------------------------------------ - * clrbuf 722045 Clear Buffer - * lpb 720045 Load Printer Buffer - * pas 721x45 Print and Space - * - * SKIP GROUP - * - * OPER. TIME - * INSTRUCTION CODE # EXPLANATION (usec) - * ------------------------------------------------------------------------------ - * sma 640400 Dkip on minus AC 5 - * spa 640200 Skip on plus AC 5 - * spi 642000 Skip on plus IO 5 - * sza 640100 Skip on ZERO (+0) AC 5 - * szf 6400f Skip on ZERO flag 5 - * szo 641000 Skip on ZERO overflow (and clear overflow) 5 - * szs 6400s0 Skip on ZERO sense switch 5 - * - * SHIFT/ROTATE GROUP - * - * OPER. TIME - * INSTRUCTION CODE # EXPLANATION (usec) - * ------------------------------------------------------------------------------ - * ral 661 Rotate AC left 5 - * rar 671 Rotate AC right 5 - * rcl 663 Rotate Combined AC & IO left 5 - * rcr 673 Rotate Combined AC & IO right 5 - * ril 662 Rotate IO left 5 - * rir 672 Rotate IO right 5 - * sal 665 Shift AC left 5 - * sar 675 Shift AC right 5 - * scl 667 Shift Combined AC & IO left 5 - * scr 677 Shift Combined AC & IO right 5 - * sil 666 Shift IO left 5 - * sir 676 Shift IO right 5 - */ - - -/* - TODO: - * support other extensions as time permits -*/ - - -#include "emu.h" -#include "debugger.h" -#include "pdp1.h" - -#define LOG 0 -#define LOG_EXTRA 0 -#define LOG_IOT_EXTRA 0 - -#define READ_PDP_18BIT(A) ((signed)m_program->read_dword((A)<<2)) -#define WRITE_PDP_18BIT(A,V) (m_program->write_dword((A)<<2,(V))) - - -#define PC m_pc -#define IR m_ir -#define MB m_mb -#define MA m_ma -#define AC m_ac -#define IO m_io -#define OV m_ov -#define EXD m_exd -/* note that we start counting flags/sense switches at 1, therefore n is in [1,6] */ -#define FLAGS m_pf -#define READFLAG(n) ((m_pf >> (6-(n))) & 1) -#define WRITEFLAG(n, data) (m_pf = (m_pf & ~(1 << (6-(n)))) | (((data) & 1) << (6-(n)))) -#define SENSE_SW m_ss -#define READSENSE(n) ((m_ss >> (6-(n))) & 1) -#define WRITESENSE(n, data) (m_ss = (m_ss & ~(1 << (6-(n)))) | (((data) & 1) << (6-(n)))) - -#define EXTENDED_ADDRESS_MASK m_extended_address_mask -#define ADDRESS_EXTENSION_MASK m_address_extension_mask -#define BASE_ADDRESS_MASK 0007777 - -#define INCREMENT_PC (PC = (PC & ADDRESS_EXTENSION_MASK) | ((PC+1) & BASE_ADDRESS_MASK)) -#define DECREMENT_PC (PC = (PC & ADDRESS_EXTENSION_MASK) | ((PC-1) & BASE_ADDRESS_MASK)) -#define INCREMENT_MA (MA = (MA & ADDRESS_EXTENSION_MASK) | ((MA+1) & BASE_ADDRESS_MASK)) -#define PREVIOUS_PC ((PC & ADDRESS_EXTENSION_MASK) | ((PC-1) & BASE_ADDRESS_MASK)) - - -const device_type PDP1 = &device_creator<pdp1_device>; - - -pdp1_device::pdp1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : cpu_device(mconfig, PDP1, "PDP1", tag, owner, clock, "pdp1_cpu", __FILE__) - , m_program_config("program", ENDIANNESS_BIG, 32, 18, 0) -{ - m_is_octal = true; -} - - -void pdp1_device::device_config_complete() -{ - // inherit a copy of the static data - const pdp1_reset_param_t *intf = reinterpret_cast<const pdp1_reset_param_t *>(static_config()); - if (intf != NULL) - *static_cast<pdp1_reset_param_t *>(this) = *intf; - - // or initialize to defaults if none provided - else - { - memset(&read_binary_word, 0, sizeof(read_binary_word)); - memset(&io_sc_callback, 0, sizeof(io_sc_callback)); - extend_support = 0; - hw_mul_div = 0; - type_20_sbs = 0; - - for (int i = 0; i < 64; i++) - { - memset(&extern_iot[i], 0, sizeof(extern_iot[i])); - } - } -} - - -offs_t pdp1_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) -{ - extern CPU_DISASSEMBLE( pdp1 ); - return CPU_DISASSEMBLE_NAME(pdp1)(this, buffer, pc, oprom, opram, options); -} - - -/* - Interrupts are called "sequence break" in pdp1, but the general idea is the same. - - There are several interrupt lines. With the standard sequence break system, all lines - are logically or'ed to trigger a single interrupt level. Interrupts can be triggered - by either a pulse or a level on the interrupt lines. With the optional type 120 sequence - break system, each of 16 lines triggers is wired to a different priority level: additionnally, - each interrupt line can be masked out, and interrupt can be triggered through software. - - Also, instructions can be interrupted in the middle of execution. This is done by - decrementing the PC register: therefore the instruction is re-executed from start. - - Interrupt routines should not execute most IOT, as the interrupt may interrupt another. - - More details can be found in the handbook and the maintenance manual. -*/ -/* - This function MUST be called every time m_sbm, m_b4, m_irq_state or m_b2 change. -*/ -void pdp1_device::field_interrupt() -{ - /* current_irq: 1 bit for each active pending interrupt request - Pending interrupts are in b3 (simulated by (m_irq_state & m_b1) | m_b2)), but they - are only honored if no higher priority interrupt routine is in execution (one bit set in b4 - for each routine in execution). The relevant mask is created with (m_b4 | (- m_b4)), - as the carry chain (remember that -b4 = (~ b4) + 1) does precisely what we want. - b4: 0001001001000 - -b4: 1110110111000 - b4|-b4:1111111111000 - Neat, uh? - */ - int current_irq = ((m_irq_state & m_b1) | m_b2) & ~ (m_b4 | (- m_b4)); - int i; - - if (m_sbm && current_irq) - { - m_sbs_request = 1; - for (i=0; /*i<16 &&*/ (! ((current_irq >> i) & 1)); i++) - ; - m_sbs_level = i; - } - else - m_sbs_request = 0; -} - -void pdp1_device::execute_set_input(int irqline, int state) -{ - if (irqline == INPUT_LINE_NMI) - { - /* no specific NMI line */ - } - else if ((irqline >= 0) && (irqline < (m_type_20_sbs ? 1 : 16))) - { - unsigned int new_state = state ? 1 : 0; - - if (((m_irq_state >> irqline) & 1) != new_state) - { - m_irq_state = (m_irq_state & ~ (1 << irqline)) | (new_state << irqline); - - if ((new_state) && ((m_b1 >> irqline) & 1)) - m_b2 |= (new_state << irqline); - - /*m_b3 = m_irq_state | m_b2;*/ - - field_interrupt(); /* interrupt state has changed */ - } - } -} - - -static void null_iot(device_t *device, int op2, int nac, int mb, int *io, int ac) -{ - pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device); - - pdp1->pdp1_null_iot(op2, nac, mb, io, ac); -} - -static void lem_eem_iot(device_t *device, int op2, int nac, int mb, int *io, int ac) -{ - pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device); - - pdp1->pdp1_lem_eem_iot(op2, nac, mb, io, ac); -} - -static void sbs_iot(device_t *device, int op2, int nac, int mb, int *io, int ac) -{ - pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device); - - pdp1->pdp1_sbs_iot(op2, nac, mb, io, ac); -} - -static void type_20_sbs_iot(device_t *device, int op2, int nac, int mb, int *io, int ac) -{ - pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device); - - pdp1->pdp1_type_20_sbs_iot(op2, nac, mb, io, ac); -} - -void pdp1_device::device_start() -{ - int i; - - /* clean-up */ - m_pc = 0; - m_ir = 0; - m_mb = 0; - m_ma = 0; - m_ac = 0; - m_io = 0; - m_pf = 0; - m_ta = 0; - m_tw = 0; - m_ss = 0; - m_sngl_step = 0; - m_sngl_inst = 0; - m_extend_sw = 0; - m_run = 0; - m_cycle = 0; - m_defer = 0; - m_brk_ctr = 0; - m_ov = 0; - m_rim = 0; - m_sbm = 0; - m_exd = 0; - m_exc = 0; - m_ioc = 0; - m_ioh = 0; - m_ios = 0; - m_irq_state = 0; - m_b1 = 0; - m_b2 = 0; - m_b4 = 0; - m_rim_step = 0; - m_sbs_request = 0; - m_sbs_level = 0; - m_sbs_restore = 0; - m_no_sequence_break = 0; - m_debugger_temp = 0; - - m_program = &space(AS_PROGRAM); - - /* set up params and callbacks */ - for (i=0; i<64; i++) - { - m_extern_iot[i] = (extern_iot[i]) - ? extern_iot[i] - : null_iot; - } - m_read_binary_word = read_binary_word; - m_io_sc_callback = io_sc_callback; - m_extend_support = extend_support; - m_hw_mul_div = hw_mul_div; - m_type_20_sbs = type_20_sbs; - - switch (m_extend_support) - { - default: - m_extend_support = 0; - case 0: /* no extension */ - m_extended_address_mask = 07777; - m_address_extension_mask = 00000; - break; - case 1: /* 15-bit extension */ - m_extended_address_mask = 077777; - m_address_extension_mask = 070000; - break; - case 2: /* 16-bit extension */ - m_extended_address_mask = 0177777; - m_address_extension_mask = 0170000; - break; - } - - if (m_extend_support) - { - m_extern_iot[074] = lem_eem_iot; - } - m_extern_iot[054] = m_extern_iot[055] = m_extern_iot[056] = sbs_iot; - if (m_type_20_sbs) - { - m_extern_iot[050] = m_extern_iot[051] = m_extern_iot[052] = m_extern_iot[053] - = type_20_sbs_iot; - } - - state_add( PDP1_PC, "PC", m_pc).formatstr("%06O"); - state_add( PDP1_IR, "IR", m_ir).formatstr("%02O"); - state_add( PDP1_MB, "MB", m_mb).formatstr("%06O"); - state_add( PDP1_MA, "MA", m_ma).formatstr("%06O"); - state_add( PDP1_AC, "AC", m_ac).formatstr("%06O"); - state_add( PDP1_IO, "IO", m_io).formatstr("%06O"); - state_add( PDP1_OV, "OV", m_ov).formatstr("%1X"); - state_add( PDP1_PF, "FLAGS", m_pf).formatstr("%02O"); - state_add( PDP1_PF1, "FLAG1", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_PF2, "FLAG2", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_PF3, "FLAG3", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_PF4, "FLAG4", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_PF5, "FLAG5", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_PF6, "FLAG6", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_TA, "TA", m_ta).formatstr("%06O"); - state_add( PDP1_TW, "TW", m_tw).formatstr("%06O"); - state_add( PDP1_SS, "SS", m_ss).formatstr("%02O"); - state_add( PDP1_SS1, "SENSE1", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_SS2, "SENSE2", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_SS3, "SENSE3", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_SS4, "SENSE4", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_SS5, "SENSE5", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_SS6, "SENSE6", m_debugger_temp).callimport().callexport().formatstr("%1X"); - state_add( PDP1_SNGL_STEP, "SNGLSTEP", m_sngl_step).mask(1).formatstr("%1X"); - state_add( PDP1_SNGL_INST, "SNGLINST", m_sngl_inst).mask(1).formatstr("%1X"); - state_add( PDP1_EXTEND_SW, "EXS", m_extend_sw).mask(1).formatstr("%1X"); - state_add( PDP1_RUN, "RUN", m_run).mask(1).formatstr("%1X"); - state_add( PDP1_CYC, "CYC", m_cycle).mask(1).formatstr("%1X"); - state_add( PDP1_DEFER, "DF", m_defer).mask(1).formatstr("%1X"); - state_add( PDP1_BRK_CTR, "BRKCTR", m_brk_ctr).mask(3).formatstr("%1X"); - state_add( PDP1_RIM, "RIM", m_rim).mask(1).formatstr("%1X"); - state_add( PDP1_SBM, "SBM", m_sbm).mask(1).formatstr("%1X"); - state_add( PDP1_EXD, "EXD", m_exd).mask(1).formatstr("%1X"); - state_add( PDP1_IOC, "IOC", m_ioc).mask(1).formatstr("%1X"); - state_add( PDP1_IOH, "IOH", m_ioh).mask(1).formatstr("%1X"); - state_add( PDP1_IOS, "IOS", m_ios).mask(1).formatstr("%1X"); - - state_add( STATE_GENPC, "GENPC", m_pc ).noshow(); - state_add( STATE_GENFLAGS, "GENFLAGS", m_pf ).formatstr("%13s").noshow(); - - m_icountptr = &m_icount; - - /* reset CPU flip-flops */ - pulse_start_clear(); -} - - -void pdp1_device::state_import(const device_state_entry &entry) -{ - switch (entry.index()) - { - case PDP1_PF1: - WRITEFLAG(1, m_debugger_temp ? 1 : 0); - break; - case PDP1_PF2: - WRITEFLAG(2, m_debugger_temp ? 1 : 0); - break; - case PDP1_PF3: - WRITEFLAG(3, m_debugger_temp ? 1 : 0); - break; - case PDP1_PF4: - WRITEFLAG(4, m_debugger_temp ? 1 : 0); - break; - case PDP1_PF5: - WRITEFLAG(5, m_debugger_temp ? 1 : 0); - break; - case PDP1_PF6: - WRITEFLAG(6, m_debugger_temp ? 1 : 0); - break; - case PDP1_SS1: - WRITESENSE(1, m_debugger_temp ? 1 : 0); - break; - case PDP1_SS2: - WRITESENSE(2, m_debugger_temp ? 1 : 0); - break; - case PDP1_SS3: - WRITESENSE(3, m_debugger_temp ? 1 : 0); - break; - case PDP1_SS4: - WRITESENSE(4, m_debugger_temp ? 1 : 0); - break; - case PDP1_SS5: - WRITESENSE(5, m_debugger_temp ? 1 : 0); - break; - case PDP1_SS6: - WRITESENSE(6, m_debugger_temp ? 1 : 0); - break; - } -} - - -void pdp1_device::state_export(const device_state_entry &entry) -{ - switch (entry.index()) - { - case PDP1_PF1: - m_debugger_temp = READFLAG(1); - break; - case PDP1_PF2: - m_debugger_temp = READFLAG(2); - break; - case PDP1_PF3: - m_debugger_temp = READFLAG(3); - break; - case PDP1_PF4: - m_debugger_temp = READFLAG(4); - break; - case PDP1_PF5: - m_debugger_temp = READFLAG(5); - break; - case PDP1_PF6: - m_debugger_temp = READFLAG(6); - break; - case PDP1_SS1: - m_debugger_temp = READSENSE(1); - break; - case PDP1_SS2: - m_debugger_temp = READSENSE(2); - break; - case PDP1_SS3: - m_debugger_temp = READSENSE(3); - break; - case PDP1_SS4: - m_debugger_temp = READSENSE(4); - break; - case PDP1_SS5: - m_debugger_temp = READSENSE(5); - break; - case PDP1_SS6: - m_debugger_temp = READSENSE(6); - break; - } -} - - -void pdp1_device::state_string_export(const device_state_entry &entry, std::string &str) -{ - switch (entry.index()) - { - case STATE_GENFLAGS: - strprintf(str, "%c%c%c%c%c%c-%c%c%c%c%c%c", - (FLAGS & 040) ? '1' : '.', - (FLAGS & 020) ? '2' : '.', - (FLAGS & 010) ? '3' : '.', - (FLAGS & 004) ? '4' : '.', - (FLAGS & 002) ? '5' : '.', - (FLAGS & 001) ? '6' : '.', - (SENSE_SW & 040) ? '1' : '.', - (SENSE_SW & 020) ? '2' : '.', - (SENSE_SW & 010) ? '3' : '.', - (SENSE_SW & 004) ? '4' : '.', - (SENSE_SW & 002) ? '5' : '.', - (SENSE_SW & 001) ? '6' : '.'); - break; - } -} - - -void pdp1_device::device_reset() -{ - // Nothing to do?? -} - -/* - flags: - * 1 for each instruction which supports indirect addressing (memory reference instructions, - except cal and jda, and with the addition of jmp and jsp) - * 2 for memory reference instructions -*/ -static const UINT8 instruction_kind[32] = -{ -/* and ior xor xct cal/jda */ - 0, 3, 3, 3, 3, 0, 0, 2, -/* lac lio dac dap dip dio dzm */ - 3, 3, 3, 3, 3, 3, 3, 0, -/* add sub idx isp sad sas mus dis */ - 3, 3, 3, 3, 3, 3, 3, 3, -/* jmp jsp skp sft law iot opr */ - 1, 1, 0, 0, 0, 0, 0, 0 -}; - - -/* execute instructions on this CPU until icount expires */ -void pdp1_device::execute_run() -{ - do - { - debugger_instruction_hook(this, PC); - - - /* ioh should be cleared at the end of the instruction cycle, and ios at the - start of next instruction cycle, but who cares? */ - if (m_ioh && m_ios) - { - m_ioh = 0; - } - - - if ((! m_run) && (! m_rim)) - m_icount = 0; /* if processor is stopped, just burn cycles */ - else if (m_rim) - { - switch (m_rim_step) - { - case 0: - /* read first word as instruction */ - if (m_read_binary_word) - (*m_read_binary_word)(this); /* data will be transferred to IO register */ - m_rim_step = 1; - m_ios = 0; - break; - - case 1: - if (! m_ios) - { /* transfer incomplete: wait some more */ - m_icount = 0; - } - else - { /* data transfer complete */ - m_ios = 0; - - MB = IO; - IR = MB >> 13; /* basic opcode */ - if (IR == JMP) /* jmp instruction ? */ - { - PC = (MA & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK); - m_rim = 0; /* exit read-in mode */ - m_run = 1; - m_rim_step = 0; - } - else if ((IR == DIO) || (IR == DAC)) /* dio or dac instruction ? */ - { /* there is a discrepancy: the pdp1 handbook tells that only dio should be used, - but the lisp tape uses the dac instruction instead */ - /* Yet maintenance manual p. 6-25 states clearly that the data is located - in IO and transfered to MB, so DAC is likely to be a mistake. */ - m_rim_step = 2; - } - else - { - /* what the heck? */ - if (LOG) - logerror("It seems this tape should not be operated in read-in mode\n"); - - m_rim = 0; /* exit read-in mode (right???) */ - m_rim_step = 0; - } - } - break; - - case 2: - /* read second word as data */ - if (m_read_binary_word) - (*m_read_binary_word)(this); /* data will be transferred to IO register */ - m_rim_step = 3; - m_ios = 0; - break; - - case 3: - if (! m_ios) - { /* transfer incomplete: wait some more */ - m_icount = 0; - } - else - { /* data transfer complete */ - m_ios = 0; - - MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK); - - MB = IO; - WRITE_PDP_18BIT(MA, MB); - - m_rim_step = 0; - } - break; - } - } - else - { - /* yes, interrupt can occur in the midst of an instruction (impressing, huh?) */ - /* Note that break cannot occur during a one-cycle jump that is deferred only once, - or another break cycle. Also, it cannot interrupt the long cycle 1 of automatic - multiply/divide. (maintenance manual 6-19) */ - if (m_sbs_request && (! m_no_sequence_break) && (! m_brk_ctr)) - { /* begin sequence break */ - m_brk_ctr = 1; - } - if (m_brk_ctr) - { /* sequence break in progress */ - switch (m_brk_ctr) - { - case 1: - if (m_cycle) - DECREMENT_PC; /* set PC to point to aborted instruction, so that it can be re-run */ - - m_b4 |= (1 << m_sbs_level); /* set "interrupt in progress" flag */ - m_b2 &= ~(1 << m_sbs_level); /* clear interrupt request */ - field_interrupt(); - MA = m_sbs_level << 2; /* always 0 with standard sequence break system */ - MB = AC; /* save AC to MB */ - AC = (OV << 17) | (EXD << 16) | PC; /* save OV/EXD/PC to AC */ - EXD = OV = 0; /* according to maintenance manual p. 8-17 and ?-?? */ - m_cycle = m_defer = m_exc = 0; /* mere guess */ - WRITE_PDP_18BIT(MA, MB); /* save former AC to memory */ - INCREMENT_MA; - m_icount -= 5; - m_brk_ctr++; - break; - - case 2: - WRITE_PDP_18BIT(MA, MB = AC); /* save former OV/EXD/PC to memory */ - INCREMENT_MA; - m_icount -= 5; - m_brk_ctr++; - break; - - case 3: - WRITE_PDP_18BIT(MA, MB = IO); /* save IO to memory */ - INCREMENT_MA; - PC = MA; - m_icount -= 5; - m_brk_ctr = 0; - break; - } - } - else - { - if (m_no_sequence_break) - m_no_sequence_break = 0; - - if (! m_cycle) - { /* no instruction in progress: time to fetch a new instruction, I guess */ - MB = READ_PDP_18BIT(MA = PC); - INCREMENT_PC; - IR = MB >> 13; /* basic opcode */ - - if ((instruction_kind[IR] & 1) && (MB & 010000)) - { - m_defer = 1; - m_cycle = 1; /* instruction shall be executed later */ - - /* detect deferred one-cycle jumps */ - if ((IR == JMP) || (IR == JSP)) - { - m_no_sequence_break = 1; - /* detect JMP *(4*n+1) to memory module 0 if in sequence break mode */ - if (((MB & 0777703) == 0610001) && (m_sbm) && ! (MA & 0170000)) - { - int level = (MB & 0000074) >> 2; - - if ((m_type_20_sbs) || (level == 0)) - { - m_b4 &= ~(1 << level); - field_interrupt(); - if (m_extend_support) - EXD = 1; /* according to maintenance manual p. 6-33 */ - m_sbs_restore = 1; - } - } - } - } - else if (instruction_kind[IR] & 2) - m_cycle = 1; /* instruction shall be executed later */ - else - execute_instruction(); /* execute instruction at once */ - - m_icount -= 5; - } - else if (m_defer) - { /* defer cycle : handle indirect addressing */ - MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK); - - MB = READ_PDP_18BIT(MA); - - /* determinate new value of m_defer */ - if (EXD) - { - m_defer = 0; - m_exc = 1; - } - else - m_defer = (MB & 010000) ? 1 : 0; - - /* execute JMP and JSP immediately if applicable */ - if ((! m_defer) && (! (instruction_kind[IR] & 2))) - { - execute_instruction(); /* execute instruction at once */ - /*m_cycle = 0;*/ - m_exc = 0; - - if (m_sbs_restore) - { /* interrupt return: according to maintenance manual p. 6-33 */ - if (m_extend_support) - EXD = (MB >> 16) & 1; - OV = (MB >> 17) & 1; - m_sbs_restore = 0; - } - } - - m_icount -= 5; - } - else - { /* memory reference instruction in cycle 1 */ - if (m_exc) - { - MA = MB & EXTENDED_ADDRESS_MASK; - m_exc = 0; - } - else - MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK); - - execute_instruction(); /* execute instruction */ - - m_icount -= 5; - } - - if ((m_sngl_inst) && (! m_cycle)) - m_run = 0; - } - if (m_sngl_step) - m_run = 0; - } - } - while (m_icount > 0); -} - - -/* execute one instruction */ -void pdp1_device::execute_instruction() -{ - switch (IR) - { - case AND: /* Logical And */ - AC &= (MB = READ_PDP_18BIT(MA)); - break; - case IOR: /* Inclusive Or */ - AC |= (MB = READ_PDP_18BIT(MA)); - break; - case XOR: /* Exclusive Or */ - AC ^= (MB = READ_PDP_18BIT(MA)); - break; - case XCT: /* Execute */ - MB = READ_PDP_18BIT(MA); - IR = MB >> 13; /* basic opcode */ - if ((instruction_kind[IR] & 1) && (MB & 010000)) - { - m_defer = 1; - /*m_cycle = 1;*/ /* instruction shall be executed later */ - goto no_fetch; /* fall through to next instruction */ - } - else if (instruction_kind[IR] & 2) - { - /*m_cycle = 1;*/ /* instruction shall be executed later */ - goto no_fetch; /* fall through to next instruction */ - } - else - execute_instruction(); /* execute instruction at once */ - break; - case CALJDA: /* Call subroutine and Jump and Deposit Accumulator instructions */ - if (MB & 010000) - /* JDA */ - MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK); - else - /* CAL: equivalent to JDA 100 */ - /* Note that I cannot tell for sure what happens to extension bits, but I did notice - that setting the extension bits to 0 would make cal basically useless, since - there would be no simple way the call routine could return to the callee - if it were located in another module with extend mode off (i.e. exd == 0). */ - MA = (PC & ADDRESS_EXTENSION_MASK) | 0100; - - WRITE_PDP_18BIT(MA, (MB = AC)); - INCREMENT_MA; - AC = (OV << 17) | (EXD << 16) | PC; - PC = MA; - break; - case LAC: /* Load Accumulator */ - AC = (MB = READ_PDP_18BIT(MA)); - break; - case LIO: /* Load i/o register */ - IO = (MB = READ_PDP_18BIT(MA)); - break; - case DAC: /* Deposit Accumulator */ - WRITE_PDP_18BIT(MA, (MB = AC)); - break; - case DAP: /* Deposit Address Part */ - WRITE_PDP_18BIT(MA, (MB = ((READ_PDP_18BIT(MA) & 0770000) | (AC & 0007777)))); - break; - case DIP: /* Deposit Instruction Part */ - WRITE_PDP_18BIT(MA, (MB = ((READ_PDP_18BIT(MA) & 0007777) | (AC & 0770000)))); - break; - case DIO: /* Deposit I/O Register */ - WRITE_PDP_18BIT(MA, (MB = IO)); - break; - case DZM: /* Deposit Zero in Memory */ - WRITE_PDP_18BIT(MA, (MB = 0)); - break; - case ADD: /* Add */ - { - /* overflow is set if the 2 operands have the same sign and the final result has another */ - int ov2; /* 1 if the operands have the same sign*/ - - MB = READ_PDP_18BIT(MA); - - ov2 = ((AC & 0400000) == (MB & 0400000)); - - AC = AC + MB; - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - - /* I think we need to check for overflow before checking for -0, - because the sum -0+-0 = -0 = +0 would generate an overflow - otherwise. */ - if (ov2 && ((AC & 0400000) != (MB & 0400000))) - OV = 1; - - if (AC == 0777777) /* check for -0 */ - AC = 0; - - break; - } - case SUB: /* Subtract */ - { /* maintenance manual 7-14 seems to imply that substract does not test for -0. - The sim 2.3 source says so explicitely, though they do not give a reference. - It sounds a bit weird, but the reason is probably that doing so would - require additionnal logic that does not exist. */ - /* overflow is set if the 2 operands have the same sign and the final result has another */ - int ov2; /* 1 if the operands have the same sign*/ - - AC ^= 0777777; - - MB = READ_PDP_18BIT(MA); - - ov2 = ((AC & 0400000) == (MB & 0400000)); - - AC = AC + MB; - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - - if (ov2 && ((AC & 0400000) != (MB & 0400000))) - OV = 1; - - AC ^= 0777777; - - break; - } - case IDX: /* Index */ - AC = READ_PDP_18BIT(MA) + 1; - - #if 0 - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - if (AC == 0777777) /* check for -0 */ - AC = 0; - #else - if (AC >= 0777777) - AC = (AC + 1) & 0777777; - #endif - - WRITE_PDP_18BIT(MA, (MB = AC)); - break; - case ISP: /* Index and Skip if Positive */ - AC = READ_PDP_18BIT(MA) + 1; - - #if 0 - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - if (AC == 0777777) /* check for -0 */ - AC = 0; - #else - if (AC >= 0777777) - AC = (AC + 1) & 0777777; - #endif - - WRITE_PDP_18BIT(MA, (MB = AC)); - if ((AC & 0400000) == 0) - INCREMENT_PC; - break; - case SAD: /* Skip if Accumulator and Y differ */ - if (AC != (MB = READ_PDP_18BIT(MA))) - INCREMENT_PC; - break; - case SAS: /* Skip if Accumulator and Y are the same */ - if (AC == (MB = READ_PDP_18BIT(MA))) - INCREMENT_PC; - break; - case MUS_MUL: /* Multiply Step or Multiply */ - if (m_hw_mul_div) - { /* MUL */ - int scr; - int smb, srm; - double etime = 4.; /* approximative */ - - IO = MB = AC; - MB = READ_PDP_18BIT(MA); - scr = 0; - if (MB & 0400000) - { - smb = 1; - MB = MB ^ 0777777; - } - else - smb = 0; - if (IO & 0400000) - { - srm = 1; - IO = IO ^ 0777777; - } - else - srm = 0; - AC = 0; - scr++; - while (scr < 022) - { - if (IO & 1) - { - /*assert(! (AC & 0400000));*/ - AC = AC + MB; - /* we can save carry around since both numbers are positive */ - /*AC = (AC + (AC >> 18)) & 0777777;*/ - etime += .65; /* approximative */ - } - IO = (IO >> 1) | ((AC & 1) << 17); - AC = AC >> 1; - scr++; - } - if (smb ^ srm) - { - AC = AC ^ 0777777; - IO = IO ^ 0777777; - } - - m_icount -= etime+.5; /* round to closest */ - } - else - { /* MUS */ - /* should we check for -0??? (Maintenance manual 7-14 seems to imply we should not: - as a matter of fact, since the MUS instruction is supposed to have positive operands, - there is no need to check for -0, therefore such a simplification does not sound - absurd.) */ - if ((IO & 1) == 1) - { - AC = AC + (MB = READ_PDP_18BIT(MA)); - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - } - IO = (IO >> 1 | AC << 17) & 0777777; - AC >>= 1; - } - break; - case DIS_DIV: /* Divide Step or Divide */ - if (m_hw_mul_div) - { /* DIV */ - /* As a side note, the order of -0 detection and overflow checking does not matter, - because the sum of two positive number cannot give 0777777 (since positive - numbers are 0377777 at most, their sum is 0777776 at most). - Additionnally, we cannot have carry set and a result equal to 0777777 (since numbers - are 0777777 at most, their sum is 01777776 at most): this is nice, because it makes - the sequence: - AC = (AC + (AC >> 18)) & 0777777; // propagate carry around - if (AC == 0777777) // check for -0 - AC = 0; - equivalent to: - if (AC >= 0777777) - AC = (AC + 1) & 0777777; - which is a bit more efficient. */ - int acl; - int scr; - int smb, srm; - double etime = 0; /* approximative */ - - MB = READ_PDP_18BIT(MA); - scr = 0; - if (MB & 0400000) - { - smb = 1; - } - else - { - smb = 0; - MB = MB ^ 0777777; - } - if (AC & 0400000) - { - srm = 1; - AC = AC ^ 0777777; - IO = IO ^ 0777777; - } - else - srm = 0; - while (1) - { - AC = (AC + MB); - #if 1 - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - if (AC == 0777777) /* check for -0 */ - AC = 0; - #else - if (AC >= 0777777) - AC = (AC + 1) & 0777777; - #endif - if (MB & 0400000) - MB = MB ^ 0777777; - - if (((scr == 0) && ! (AC & 0400000)) - || (scr == 022)) - break; - - scr++; - - if (! (AC & 0400000)) - MB = MB ^ 0777777; - - acl = AC >> 17; - AC = (AC << 1 | IO >> 17) & 0777777; - IO = ((IO << 1 | acl) & 0777777) ^ 1; - if (acl) - { - AC++; - AC = (AC + (AC >> 18)) & 0777777; - etime += .6; /* approximative */ - } - } - - AC = (AC + MB); - #if 1 - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - if (AC == 0777777) /* check for -0 */ - AC = 0; - #else - if (AC >= 0777777) - AC = (AC + 1) & 0777777; - #endif - - if (scr) - { - INCREMENT_PC; - AC = AC >> 1; - } - - if (srm && (AC != 0)) - AC = AC ^ 0777777; - - if (((! scr) && (srm)) - || (scr && (srm ^ smb) && (IO != 0))) - IO = IO ^ 0777777; - - if (scr) - { - MB = AC; - AC = IO; - IO = MB; - } - if (scr) - etime += 20; /* approximative */ - else - etime += 2; /* approximative */ - - m_icount -= etime+.5; /* round to closest */ - } - else - { /* DIS */ - int acl; - - acl = AC >> 17; - AC = (AC << 1 | IO >> 17) & 0777777; - IO = ((IO << 1 | acl) & 0777777) ^ 1; - MB = READ_PDP_18BIT(MA); - if (IO & 1) - AC += (MB ^ 0777777); - else - /* Note that if AC+MB = 0777777, we are in trouble. I don't - know how a real PDP-1 behaves in this case. */ - AC += MB + 1; - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - if (AC == 0777777) /* check for -0 */ - AC = 0; - } - break; - case JMP: /* Jump */ - if (m_exc) - PC = MB & EXTENDED_ADDRESS_MASK; - else - PC = (MA & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK); - break; - case JSP: /* Jump and Save Program Counter */ - AC = (OV << 17) | (EXD << 16) | PC; - if (m_exc) - PC = MB & EXTENDED_ADDRESS_MASK; - else - PC = (MA & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK); - break; - case SKP: /* Skip Instruction Group */ - { - int cond = ((MB & 0100) && (AC == 0)) /* ZERO Accumulator */ - || ((MB & 0200) && (AC >> 17 == 0)) /* Plus Accumulator */ - || ((MB & 0400) && (AC >> 17 == 1)) /* Minus Accumulator */ - || ((MB & 01000) && (OV == 0)) /* ZERO Overflow */ - || ((MB & 02000) && (IO >> 17 == 0)) /* Plus I/O Register */ - || (((MB & 7) != 0) && (((MB & 7) == 7) ? ! FLAGS : ! READFLAG(MB & 7))) /* ZERO Flag (deleted by mistake in PDP-1 handbook) */ - || (((MB & 070) != 0) && (((MB & 070) == 070) ? ! SENSE_SW : ! READSENSE((MB & 070) >> 3))); /* ZERO Switch */ - - if (! (MB & 010000)) - { - if (cond) - INCREMENT_PC; - } - else - { - if (!cond) - INCREMENT_PC; - } - if (MB & 01000) - OV = 0; - break; - } - case SFT: /* Shift Instruction Group */ - { - /* Bit 5 specifies direction of shift, Bit 6 specifies the character of the shift - (arithmetic or logical), Bits 7 and 8 enable the registers (01 = AC, 10 = IO, - and 11 = both) and Bits 9 through 17 specify the number of steps. */ - int nshift = 0; - int mask = MB & 0777; - - while (mask != 0) - { - nshift += mask & 1; - mask >>= 1; - } - switch ((MB >> 9) & 017) - { - int i; - - case 1: /* ral rotate accumulator left */ - for (i = 0; i < nshift; i++) - AC = (AC << 1 | AC >> 17) & 0777777; - break; - case 2: /* ril rotate i/o register left */ - for (i = 0; i < nshift; i++) - IO = (IO << 1 | IO >> 17) & 0777777; - break; - case 3: /* rcl rotate AC and IO left */ - for (i = 0; i < nshift; i++) - { - int tmp = AC; - - AC = (AC << 1 | IO >> 17) & 0777777; - IO = (IO << 1 | tmp >> 17) & 0777777; - } - break; - case 5: /* sal shift accumulator left */ - for (i = 0; i < nshift; i++) - AC = ((AC << 1 | AC >> 17) & 0377777) + (AC & 0400000); - break; - case 6: /* sil shift i/o register left */ - for (i = 0; i < nshift; i++) - IO = ((IO << 1 | IO >> 17) & 0377777) + (IO & 0400000); - break; - case 7: /* scl shift AC and IO left */ - for (i = 0; i < nshift; i++) - { - int tmp = AC; - - AC = ((AC << 1 | IO >> 17) & 0377777) + (AC & 0400000); /* shouldn't that be IO?, no it is the sign! */ - IO = (IO << 1 | tmp >> 17) & 0777777; - } - break; - case 9: /* rar rotate accumulator right */ - for (i = 0; i < nshift; i++) - AC = (AC >> 1 | AC << 17) & 0777777; - break; - case 10: /* rir rotate i/o register right */ - for (i = 0; i < nshift; i++) - IO = (IO >> 1 | IO << 17) & 0777777; - break; - case 11: /* rcr rotate AC and IO right */ - for (i = 0; i < nshift; i++) - { - int tmp = AC; - - AC = (AC >> 1 | IO << 17) & 0777777; - IO = (IO >> 1 | tmp << 17) & 0777777; - } - break; - case 13: /* sar shift accumulator right */ - for (i = 0; i < nshift; i++) - AC = (AC >> 1) + (AC & 0400000); - break; - case 14: /* sir shift i/o register right */ - for (i = 0; i < nshift; i++) - IO = (IO >> 1) + (IO & 0400000); - break; - case 15: /* scr shift AC and IO right */ - for (i = 0; i < nshift; i++) - { - int tmp = AC; - - AC = (AC >> 1) + (AC & 0400000); /* shouldn't that be IO, no it is the sign */ - IO = (IO >> 1 | tmp << 17) & 0777777; - } - break; - default: - if (LOG) - logerror("Undefined shift: 0%06o at 0%06o\n", MB, PREVIOUS_PC); - break; - } - break; - } - case LAW: /* Load Accumulator with N */ - AC = MB & 07777; - if (MB & 010000) - AC ^= 0777777; - break; - case IOT: /* In-Out Transfer Instruction Group */ - /* - The variations within this group of instructions perform all the in-out control - and information transfer functions. If Bit 5 (normally the Indirect Address bit) - is a ONE, the computer will enter a special waiting state until the completion pulse - from the activated device has returned. When this device delivers its completion, - the computer will resume operation of the instruction sequence. - - The computer may be interrupted from the special waiting state to serve a sequence - break request or a high speed channel request. - - Most in-out operations require a known minimum time before completion. This time - may be utilized for programming. The appropriate In-Out Transfer can be given with - no in-out wait (Bit 5 a ZERO and Bit 6 a ONE). The instruction sequence then - continues. This sequence must include an iot instruction 730000 which performs - nothing but the in-out wait. The computer will then enter the special waiting state - until the device returns the in-out restart pulse. If the device has already - returned the completion pulse before the instruction 730000, the computer will - proceed immediately. - - Bit 6 determines whether a completion pulse will or will not be received from - the in-out device. When it is different than Bit 5, a completion pulse will be - received. When it is the same as Bit 5, a completion pulse will not be received. - - In addition to the control function of Bits 5 and 6, Bits 7 through 11 are also - used as control bits serving to extend greatly the power of the iot instructions. - For example, Bits 12 through 17, which are used to designate a class of input or - output devices such as typewriters, may be further defined by Bits 7 through 11 - as referring to Typewriter 1, 2, 3, etc. In several of the optional in-out devices, - in particular the magnetic tape, Bits 7 through 11 specify particular functions - such as forward, backward etc. If a large number of specialized devices are to - be attached, these bits may be used to further the in-out transfer instruction - to perform totally distinct functions. - - Note that ioc is supposed to be set at the beggining of the memory cycle after - ioh is cleared. - However, we cannot set ioc at the beggining of every memory cycle as we - did before, because it breaks in the following case: - a) IOT instruction enables IO wait - b) sequence break in the middle of IO-halt - c) ioh is cleared in middle of sequence break routine - d) re-execute IOT instruction. Unfortunately, ioc has been cleared, therefore - we perform an IOT command pulse and IO wait again, which is completely WRONG. - Therefore ioc is cleared only after a IOT with wait is executed. - */ - if (MB & 010000) - { /* IOT with IO wait */ - if (m_ioc) - { /* the iot command line is pulsed only if ioc is asserted */ - (*m_extern_iot[MB & 0000077])(this, MB & 0000077, (MB & 0004000) == 0, MB, &IO, AC); - - m_ioh = 1; /* enable io wait */ - - m_ioc = 0; /* actually happens at the start of next memory cycle */ - - /* test ios now in case the IOT callback has sent a completion pulse immediately */ - if (m_ioh && m_ios) - { - /* ioh should be cleared at the end of the instruction cycle, and ios at the - start of next instruction cycle, but who cares? */ - m_ioh = 0; - //m_ios = 0; - } - } - - if (m_ioh) - DECREMENT_PC; - else - m_ioc = 1; /* actually happens at the start of next memory cycle */ - } - else - { /* IOT with no IO wait */ - (*m_extern_iot[MB & 0000077])(this, MB & 0000077, (MB & 0004000) != 0, MB, &IO, AC); - } - break; - case OPR: /* Operate Instruction Group */ - { - int nflag; - - if (MB & 00200) /* clear AC */ - AC = 0; - if (MB & 04000) /* clear I/O register */ - IO = 0; - if (MB & 02000) /* load Accumulator from Test Word */ - AC |= m_tw; - if (MB & 00100) /* load Accumulator with Program Counter */ - AC |= (OV << 17) | (EXD << 16) | PC; - nflag = MB & 7; - if (nflag) - { - if (nflag == 7) - FLAGS = (MB & 010) ? 077 : 000; - else - WRITEFLAG(nflag, (MB & 010) ? 1 : 0); - } - if (MB & 01000) /* Complement AC */ - AC ^= 0777777; - if (MB & 00400) /* Halt */ - { - if (LOG_EXTRA) - logerror("PDP1 Program executed HALT: at 0%06o\n", PREVIOUS_PC); - - m_run = 0; - } - break; - } - default: - if (LOG) - logerror("Illegal instruction: 0%06o at 0%06o\n", MB, PREVIOUS_PC); - - /* let us stop the CPU, like a real pdp-1 */ - m_run = 0; - - break; - } - m_cycle = 0; -no_fetch: - ; -} - - -/* - Handle unimplemented IOT -*/ -void pdp1_device::pdp1_null_iot(int op2, int nac, int mb, int *io, int ac) -{ - /* Note that the dummy IOT 0 is used to wait for the completion pulse - generated by the a pending IOT (IOT with completion pulse but no IO wait) */ - if (LOG_IOT_EXTRA) - { - if (op2 == 000) - logerror("IOT sync instruction: mb=0%06o, pc=0%06o\n", (unsigned) mb, (unsigned) m_pc); - } - if (LOG) - { - if (op2 != 000) - logerror("Not supported IOT command (no external IOT function given) 0%06o at 0%06o\n", mb, m_pc); - } -} - - -/* - Memory expansion control (type 15) - - IOT 74: LEM/EEM -*/ -void pdp1_device::pdp1_lem_eem_iot(int op2, int nac, int mb, int *io, int ac) -{ - if (! m_extend_support) /* extend mode supported? */ - { - if (LOG) - logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__); - return; - } - if (LOG_EXTRA) - { - logerror("EEM/LEM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc); - } - EXD = (mb & 0004000) ? 1 : 0; -} - - -/* - Standard sequence break system - - IOT 54: lsm - IOT 55: esm - IOT 56: cbs -*/ -void pdp1_device::pdp1_sbs_iot(int op2, int nac, int mb, int *io, int ac) -{ - switch (op2) - { - case 054: /* LSM */ - if (LOG_EXTRA) - logerror("LSM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc); - - m_sbm = 0; - field_interrupt(); - break; - case 055: /* ESM */ - if (LOG_EXTRA) - logerror("ESM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc); - - m_sbm = 1; - field_interrupt(); - break; - case 056: /* CBS */ - if (LOG_EXTRA) - logerror("CBS instruction: mb=0%06o, pc=0%06o\n", mb, m_pc); - - /*m_b3 = 0;*/ - m_b4 = 0; - field_interrupt(); - break; - default: - if (LOG) - logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__); - - break; - } -} - - -/* - type 20 sequence break system - - IOT 50: dsc - IOT 51: asc - IOT 52: isb - IOT 53: cac -*/ -void pdp1_device::pdp1_type_20_sbs_iot(int op2, int nac, int mb, int *io, int ac) -{ - int channel, mask; - if (! m_type_20_sbs) /* type 20 sequence break system supported? */ - { - if (LOG) - logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__); - return; - } - channel = (mb >> 6) & 017; - mask = 1 << channel; - switch (op2) - { - case 050: /* DSC */ - if (LOG_EXTRA) - logerror("DSC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc); - - m_b1 &= ~mask; - field_interrupt(); - break; - case 051: /* ASC */ - if (LOG_EXTRA) - logerror("ASC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc); - - m_b1 |= mask; - field_interrupt(); - break; - case 052: /* ISB */ - if (LOG_EXTRA) - logerror("ISB instruction: mb=0%06o, pc=0%06o\n", mb, m_pc); - - m_b2 |= mask; - field_interrupt(); - break; - case 053: /* CAC */ - if (LOG_EXTRA) - logerror("CAC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc); - - m_b1 = 0; - field_interrupt(); - break; - default: - if (LOG) - logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__); - - break; - } - -} - - -/* - Simulate a pulse on start/clear line: - reset most registers and flip-flops, and initialize a few emulator state - variables. -*/ -void pdp1_device::pulse_start_clear() -{ - /* processor registers */ - PC = 0; /* according to maintenance manual p. 6-17 */ - IR = 0; /* according to maintenance manual p. 6-13 */ - /*MB = 0;*/ /* ??? */ - /*MA = 0;*/ /* ??? */ - /*AC = 0;*/ /* ??? */ - /*IO = 0;*/ /* ??? */ - /*PF = 0;*/ /* ??? */ - - /* processor state flip-flops */ - m_run = 0; /* ??? */ - m_cycle = 0; /* mere guess */ - m_defer = 0; /* mere guess */ - m_brk_ctr = 0; /* mere guess */ - m_ov = 0; /* according to maintenance manual p. 7-18 */ - m_rim = 0; /* ??? */ - m_sbm = 0; /* ??? */ - EXD = 0; /* according to maintenance manual p. 8-16 */ - m_exc = 0; /* according to maintenance manual p. 8-16 */ - m_ioc = 1; /* according to maintenance manual p. 6-10 */ - m_ioh = 0; /* according to maintenance manual p. 6-10 */ - m_ios = 0; /* according to maintenance manual p. 6-10 */ - - m_b1 = m_type_20_sbs ? 0 : 1; /* mere guess */ - m_b2 = 0; /* mere guess */ - m_b4 = 0; /* mere guess */ - - - m_rim_step = 0; - m_sbs_restore = 0; /* mere guess */ - m_no_sequence_break = 0; /* mere guess */ - - field_interrupt(); - - /* now, we kindly ask IO devices to reset, too */ - if (m_io_sc_callback) - (*m_io_sc_callback)(this); -} diff --git a/src/emu/cpu/pdp1/pdp1.h b/src/emu/cpu/pdp1/pdp1.h deleted file mode 100644 index f4d1281aa07..00000000000 --- a/src/emu/cpu/pdp1/pdp1.h +++ /dev/null @@ -1,199 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Raphael Nabet -#pragma once - -#ifndef __PDP1_H__ -#define __PDP1_H__ - - - -/* register ids for pdp1_get_reg/pdp1_set_reg */ -enum -{ - PDP1_PC=1, PDP1_IR, PDP1_MB, PDP1_MA, PDP1_AC, PDP1_IO, - PDP1_PF, PDP1_PF1, PDP1_PF2, PDP1_PF3, PDP1_PF4, PDP1_PF5, PDP1_PF6, - PDP1_TA, PDP1_TW, - PDP1_SS, PDP1_SS1, PDP1_SS2, PDP1_SS3, PDP1_SS4, PDP1_SS5, PDP1_SS6, - PDP1_SNGL_STEP, PDP1_SNGL_INST, PDP1_EXTEND_SW, - PDP1_RUN, PDP1_CYC, PDP1_DEFER, PDP1_BRK_CTR, PDP1_OV, PDP1_RIM, PDP1_SBM, PDP1_EXD, - PDP1_IOC, PDP1_IOH, PDP1_IOS -}; - - -typedef void (*pdp1_extern_iot_func)(device_t *device, int op2, int nac, int mb, int *io, int ac); -typedef void (*pdp1_read_binary_word_func)(device_t *device); -typedef void (*pdp1_io_sc_func)(device_t *device); - - -struct pdp1_reset_param_t -{ - /* callbacks for iot instructions (required for any I/O) */ - pdp1_extern_iot_func extern_iot[64]; - /* read a word from the perforated tape reader (required for read-in mode) */ - pdp1_read_binary_word_func read_binary_word; - /* callback called when sc is pulsed: IO devices should reset */ - pdp1_io_sc_func io_sc_callback; - - /* 0: no extend support, 1: extend with 15-bit address, 2: extend with 16-bit address */ - int extend_support; - /* 1 to use hardware multiply/divide (MUL, DIV) instead of MUS, DIS */ - int hw_mul_div; - /* 0: standard sequence break system 1: type 20 sequence break system */ - int type_20_sbs; -}; - -#define IOT_NO_COMPLETION_PULSE -1 - - -#define AND 001 -#define IOR 002 -#define XOR 003 -#define XCT 004 -#define CALJDA 007 -#define LAC 010 -#define LIO 011 -#define DAC 012 -#define DAP 013 -#define DIP 014 -#define DIO 015 -#define DZM 016 -#define ADD 020 -#define SUB 021 -#define IDX 022 -#define ISP 023 -#define SAD 024 -#define SAS 025 -#define MUS_MUL 026 -#define DIS_DIV 027 -#define JMP 030 -#define JSP 031 -#define SKP 032 -#define SFT 033 -#define LAW 034 -#define IOT 035 -#define OPR 037 - - -class pdp1_device : public cpu_device - , public pdp1_reset_param_t -{ -public: - // construction/destruction - pdp1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - - void pulse_start_clear(); - void io_complete() { m_ios = 1; } - void pdp1_null_iot(int op2, int nac, int mb, int *io, int ac); - void pdp1_lem_eem_iot(int op2, int nac, int mb, int *io, int ac); - void pdp1_sbs_iot(int op2, int nac, int mb, int *io, int ac); - void pdp1_type_20_sbs_iot(int op2, int nac, int mb, int *io, int ac); - -protected: - // device-level overrides - virtual void device_config_complete(); - virtual void device_start(); - virtual void device_reset(); - - // device_execute_interface overrides - virtual UINT32 execute_min_cycles() const { return 5; } - virtual UINT32 execute_max_cycles() const { return 31; } - virtual UINT32 execute_input_lines() const { return 16; } - virtual void execute_run(); - virtual void execute_set_input(int inputnum, int state); - - // device_memory_interface overrides - virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; } - - // device_state_interface overrides - virtual void state_import(const device_state_entry &entry); - virtual void state_export(const device_state_entry &entry); - void state_string_export(const device_state_entry &entry, std::string &str); - - // device_disasm_interface overrides - virtual UINT32 disasm_min_opcode_bytes() const { return 4; } - virtual UINT32 disasm_max_opcode_bytes() const { return 4; } - virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); - -private: - address_space_config m_program_config; - - /* processor registers */ - UINT32 m_pc; /* program counter (12, 15 or 16 bits) */ - int m_ir; /* basic operation code of current instruction (5 bits) */ - int m_mb; /* memory buffer (used for holding the current instruction only) (18 bits) */ - int m_ma; /* memory address (12, 15 or 16 bits) */ - int m_ac; /* accumulator (18 bits) */ - int m_io; /* i/o register (18 bits) */ - int m_pf; /* program flag register (6 bits) */ - - /* operator panel switches */ - int m_ta; /* current state of the 12 or 16 address switches */ - int m_tw; /* current state of the 18 test word switches */ - int m_ss; /* current state of the 6 sense switches on the operator panel (6 bits) */ - unsigned int m_sngl_step; /* stop every memory cycle */ - unsigned int m_sngl_inst; /* stop every instruction */ - unsigned int m_extend_sw; /* extend switch (loaded into the extend flip-flop on start/read-in) */ - - /* processor state flip-flops */ - unsigned int m_run; /* processor is running */ - unsigned int m_cycle; /* processor is in the midst of an instruction */ - unsigned int m_defer; /* processor is handling deferred (i.e. indirect) addressing */ - unsigned int m_brk_ctr; /* break counter */ - unsigned int m_ov; /* overflow flip-flop */ - unsigned int m_rim; /* processor is in read-in mode */ - - unsigned int m_sbm; /* processor is in sequence break mode (i.e. interrupts are enabled) */ - - unsigned int m_exd; /* extend mode: processor is in extend mode */ - unsigned int m_exc : 1; /* extend-mode cycle: current instruction cycle is done in extend mode */ - unsigned int m_ioc; /* i-o commands: seems to be equivalent to (! ioh) */ - unsigned int m_ioh; /* i-o halt: processor is executing an Input-Output Transfer wait */ - unsigned int m_ios; /* i-o synchronizer: set on i-o operation completion */ - - /* sequence break system */ - UINT16 m_irq_state; /* mirrors the state of the interrupt pins */ - UINT16 m_b1; /* interrupt enable */ - UINT16 m_b2; /* interrupt pulse request pending - asynchronous with computer operation (set by pulses on irq_state, cleared when interrupt is taken) */ - /*UINT16 m_b3;*/ /* interrupt request pending - synchronous with computer operation (logical or of irq_state and b2???) */ - UINT16 m_b4; /* interrupt in progress */ - - /* additional emulator state variables */ - int m_rim_step; /* current step in rim execution */ - int m_sbs_request; /* interrupt request (i.e. (b3 & (~ b4)) && (! sbm)) */ - int m_sbs_level; /* interrupt request level (first bit in (b3 & (~ b4)) */ - int m_sbs_restore; /* set when a jump instruction is an interrupt return */ - int m_no_sequence_break; /* disable sequence break recognition for one cycle */ - - /* callbacks for iot instructions (required for any I/O) */ - pdp1_extern_iot_func m_extern_iot[64]; - /* read a word from the perforated tape reader (required for read-in mode) */ - pdp1_read_binary_word_func m_read_binary_word; - /* callback called when sc is pulsed: IO devices should reset */ - pdp1_io_sc_func m_io_sc_callback; - - /* 0: no extend support, 1: extend with 15-bit address, 2: extend with 16-bit address */ - int m_extend_support; - - int m_extended_address_mask; /* 07777 with no extend support, 077777 or 0177777 with extend support */ - int m_address_extension_mask; /* 00000 with no extend support, 070000 or 0170000 with extend support */ - - /* 1 to use hardware multiply/divide (MUL, DIV) instead of MUS, DIS */ - int m_hw_mul_div; - - /* 1 for 16-line sequence break system, 0 for default break system */ - int m_type_20_sbs; - - address_space *m_program; - int m_icount; - UINT32 m_debugger_temp; - - void field_interrupt(); - void execute_instruction(); - -}; - - -extern const device_type PDP1; - - -#endif /* __PDP1_H__ */ diff --git a/src/emu/cpu/pdp1/pdp1dasm.c b/src/emu/cpu/pdp1/pdp1dasm.c deleted file mode 100644 index c8682ca1491..00000000000 --- a/src/emu/cpu/pdp1/pdp1dasm.c +++ /dev/null @@ -1,294 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Raphael Nabet -#include "emu.h" -#include "cpu/pdp1/pdp1.h" - -/* PDP1 registers */ -static int ib; -static int y; - -INLINE void ea (void) -{ -/* while (1) - { - if (ib == 0) - return; - ib = (READ_PDP_18BIT (y) >> 12) & 1; - y = READ_PDP_18BIT (y) & 07777; - }*/ -} - -#define IN if (ib) sprintf(buffer+strlen(buffer)," i") - -CPU_DISASSEMBLE( pdp1 ) -{ - int md; - //int etime = 0; - - md = oprom[0] << 24 | oprom[1] << 16 | oprom[2] << 8 | oprom[3]; - - y = md & 07777; - ib = (md >> 12) & 1; /* */ - switch (md >> 13) - { - case AND: - ea (); - sprintf (buffer, "AND (0%06o)", y); - IN; - //etime = 10; - break; - case IOR: - ea (); - sprintf (buffer, "IOR (0%06o)", y); - IN; - //etime = 10; - break; - case XOR: - ea (); - sprintf (buffer, "XOR (0%06o)", y); - IN; - //etime = 10; - break; - case XCT: - ea (); - sprintf (buffer, "XCT (0%06o)", y); - IN; - //etime = 5; - break; - case CALJDA: - { - if (ib == 1) - sprintf (buffer, "JDA 0%06o ", y); - if (ib == 0) - sprintf (buffer, "CAL "); - //etime = 10; - break; - } - case LAC: - ea (); - sprintf (buffer, "LAC (0%06o)", y); - IN; - //etime = 10; - break; - case LIO: - ea (); - sprintf (buffer, "LIO (0%06o)", y); - IN; - //etime = 10; - break; - case DAC: - ea (); - sprintf (buffer, "DAC 0%06o ", y); - IN; - //etime = 10; - break; - case DAP: - ea (); - sprintf (buffer, "DAP 0%06o ", y); - IN; - //etime = 10; - break; - case DIP: - ea (); - sprintf (buffer, "DIP 0%06o ", y); - IN; - //etime = 10; - break; - case DIO: - ea (); - sprintf (buffer, "DIO 0%06o ", y); - IN; - //etime = 10; - break; - case DZM: - ea (); - sprintf (buffer, "DZM 0%06o ", y); - IN; - //etime = 10; - break; - case ADD: - ea (); - sprintf (buffer, "ADD (0%06o)", y); - IN; - //etime = 10; - break; - case SUB: - ea (); - sprintf (buffer, "SUB (0%06o)", y); - IN; - //etime = 10; - break; - case IDX: - ea (); - sprintf (buffer, "IDX (0%06o)", y); - IN; - //etime = 10; - break; - case ISP: - ea (); - sprintf (buffer, "ISP (0%06o)", y); - IN; - //etime = 10; - break; - case SAD: - ea (); - sprintf (buffer, "SAD (0%06o)", y); - IN; - //etime = 10; - break; - case SAS: - ea (); - sprintf (buffer, "SAS (0%06o)", y); - IN; - //etime = 10; - break; - case MUS_MUL: - ea (); - sprintf (buffer, "MUS (0%06o)", y); - IN; - //etime = 10; - break; - case DIS_DIV: - ea (); - sprintf (buffer, "DIS (0%06o)", y); - IN; - //etime = 10; - break; - case JMP: - ea (); - sprintf (buffer, "JMP 0%06o ", y); - IN; - //etime = 5; - break; - case JSP: - ea (); - sprintf (buffer, "JSP 0%06o ", y); - IN; - //etime = 5; - break; - case SKP: - { - buffer[0] = 0; - if ((y & 0100) == 0100) - sprintf (buffer, "SZA "); - if ((y & 0200) == 0200) - sprintf (buffer + strlen (buffer), "SPA "); - if ((y & 0400) == 0400) - sprintf (buffer + strlen (buffer), "SMA "); - if ((y & 01000) == 01000) - sprintf (buffer + strlen (buffer), "SZO "); - if ((y & 02000) == 02000) - sprintf (buffer + strlen (buffer), "SPI "); - if (y & 070) - sprintf (buffer + strlen (buffer), "SZS 0%01o ", (y & 070)); - if (y & 7) - sprintf (buffer + strlen (buffer), "SZF 0%01o ", (y & 7)); - IN; - //etime = 5; - break; - } - case SFT: - { - int nshift = 0; - int mask = md & 0777; - - while (mask != 0) - { - nshift += mask & 1; - mask = mask >> 1; - } - switch ((md >> 9) & 017) - { - case 1: - sprintf (buffer, "RAL 0%02o", nshift); - //etime = 5; - break; - case 2: - sprintf (buffer, "RIL 0%02o", nshift); - //etime = 5; - break; - case 3: - sprintf (buffer, "RCL 0%02o", nshift); - //etime = 5; - break; - case 5: - sprintf (buffer, "SAL 0%02o", nshift); - //etime = 5; - break; - case 6: - sprintf (buffer, "SIL 0%02o", nshift); - //etime = 5; - break; - case 7: - sprintf (buffer, "SCL 0%02o", nshift); - //etime = 5; - break; - case 9: - sprintf (buffer, "RAR 0%02o", nshift); - //etime = 5; - break; - case 10: - sprintf (buffer, "RIR 0%02o", nshift); - //etime = 5; - break; - case 11: - sprintf (buffer, "RCR 0%02o", nshift); - //etime = 5; - break; - case 13: - sprintf (buffer, "SAR 0%02o", nshift); - //etime = 5; - break; - case 14: - sprintf (buffer, "SIR 0%02o", nshift); - //etime = 5; - break; - case 15: - sprintf (buffer, "SCR 0%02o", nshift); - //etime = 5; - break; - default: - sprintf (buffer, "SKP ???"); - //etime = 5; - break; - } - break; - } - case LAW: - sprintf (buffer, "LAW 0%06o", y); - IN; - //etime = 5; - break; - case IOT: - sprintf (buffer, "IOT 0%06o", md); - //etime = 10; - break; - case OPR: - { - buffer[0] = 0; - if ((y & 04000) == 04000) - sprintf (buffer + strlen (buffer), "CLI "); - if ((y & 02000) == 02000) - sprintf (buffer + strlen (buffer), "LAT "); - if ((y & 01000) == 01000) - sprintf (buffer + strlen (buffer), "CMA "); - if ((y & 0400) == 0400) - sprintf (buffer + strlen (buffer), "HLT "); - if ((y & 0100) == 0100) - sprintf (buffer + strlen (buffer), "LAP "); - if ((y & 010) && (y & 7)) - sprintf (buffer + strlen (buffer), "STF 0%01o ", (y & 7)); - if ((!(y & 010)) && (y & 7)) - sprintf (buffer + strlen (buffer), "CLF 0%01o ", (y & 7)); - if (!(y)) - sprintf (buffer + strlen (buffer), "NOP "); - //etime = 5; - break; - } - default: - sprintf (buffer, "ILLEGAL"); - //etime = 5; - break; - } - return 4; -} diff --git a/src/emu/cpu/pdp1/tx0.c b/src/emu/cpu/pdp1/tx0.c deleted file mode 100644 index 03c8441d88f..00000000000 --- a/src/emu/cpu/pdp1/tx0.c +++ /dev/null @@ -1,1080 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Raphael Nabet -/* - TX-0 emulator - - Two variants: - * initial model 64kWord RAM - * later model 8kWord RAM - - Raphael Nabet 2004 -*/ - -#include "emu.h" -#include "debugger.h" -#include "tx0.h" - -#define LOG 0 -#define LOG_EXTRA 0 - - -#define READ_TX0_18BIT(A) ((signed)m_program->read_dword((A)<<2)) -#define WRITE_TX0_18BIT(A,V) (m_program->write_dword((A)<<2,(V))) - - -#define io_handler_rim 3 - -#define PC m_pc -#define IR m_ir -#define MBR m_mbr -#define MAR m_mar -#define AC m_ac -#define LR m_lr -#define XR m_xr -#define PF m_pf - -#define ADDRESS_MASK_64KW 0177777 -#define ADDRESS_MASK_8KW 0017777 - -#define INCREMENT_PC_64KW (PC = (PC+1) & ADDRESS_MASK_64KW) -#define INCREMENT_PC_8KW (PC = (PC+1) & ADDRESS_MASK_8KW) - - -const device_type TX0_8KW = &device_creator<tx0_8kw_device>; -const device_type TX0_64KW = &device_creator<tx0_64kw_device>; - - -tx0_device::tx0_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int addr_bits, int address_mask, int ir_mask) - : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) - , m_program_config("program", ENDIANNESS_BIG, 32, addr_bits , -2) - , m_address_mask(address_mask) - , m_ir_mask(ir_mask) - , m_cpy_handler(*this) - , m_r1l_handler(*this) - , m_dis_handler(*this) - , m_r3l_handler(*this) - , m_prt_handler(*this) - , m_rsv_handler(*this) - , m_p6h_handler(*this) - , m_p7h_handler(*this) - , m_sel_handler(*this) - , m_io_reset_callback(*this) -{ - m_is_octal = true; -} - -tx0_8kw_device::tx0_8kw_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : tx0_device(mconfig, TX0_8KW, "TX-0 8KW", tag, owner, clock, "tx0_8w_cpu", __FILE__, 13, ADDRESS_MASK_8KW, 037) -{ -} - - -tx0_64kw_device::tx0_64kw_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : tx0_device(mconfig, TX0_64KW, "TX-0 64KW", tag, owner, clock, "tx0_64kw_cpu", __FILE__, 16, ADDRESS_MASK_64KW, 03) -{ -} - - -int tx0_device::tx0_read(offs_t address) -{ - if ((address >= 16) || (m_gbl_cm_sel) || ((m_cm_sel >> address) & 1)) - /* core memory (CM) */ - return READ_TX0_18BIT(address); - else if ((m_lr_sel >> address) & 1) - /* live register (LR) */ - return LR; - - /* toggle switch storage (TSS) */ - return m_tss[address]; -} - -void tx0_device::tx0_write(offs_t address, int data) -{ - if ((address >= 16) || (m_gbl_cm_sel) || ((m_cm_sel >> address) & 1)) - /* core memory (CM) */ - WRITE_TX0_18BIT(address, data); - else if ((m_lr_sel >> address) & 1) - /* live register (LR) */ - LR = data; - else - /* toggle switch storage (TSS) */ - /* TSS is read-only */ - { - /* nothing */ - } -} - - -void tx0_device::device_start() -{ - m_mbr = 0; - m_ac = 0; - m_mar = 0; - m_lr = 0; - m_xr = 0; - m_pf = 0; - m_tbr = 0; - m_tac = 0; - for ( int i = 0; i < 16; i++ ) - { - m_tss[i] = 0; - } - m_cm_sel = 0; - m_lr_sel = 0; - m_gbl_cm_sel = 0; - m_stop_cyc0 = 0; - m_stop_cyc1 = 0; - m_cycle = 0; - m_pc = 0; - m_ir = 0; - m_run = 0; - m_rim = 0; - m_ioh = 0; - m_ios = 0; - - // Resolve callbacks - m_cpy_handler.resolve(); - m_r1l_handler.resolve(); - m_dis_handler.resolve(); - m_r3l_handler.resolve(); - m_prt_handler.resolve(); - m_rsv_handler.resolve(); - m_p6h_handler.resolve(); - m_p7h_handler.resolve(); - m_sel_handler.resolve(); - m_io_reset_callback.resolve(); - - m_program = &space(AS_PROGRAM); - - save_item(NAME(m_mbr)); - save_item(NAME(m_ac)); - save_item(NAME(m_mar)); - save_item(NAME(m_pc)); - save_item(NAME(m_ir)); - save_item(NAME(m_lr)); - save_item(NAME(m_xr)); - save_item(NAME(m_pf)); - save_item(NAME(m_tbr)); - save_item(NAME(m_tac)); - save_item(NAME(m_tss)); - save_item(NAME(m_cm_sel)); - save_item(NAME(m_lr_sel)); - save_item(NAME(m_gbl_cm_sel)); - save_item(NAME(m_stop_cyc0)); - save_item(NAME(m_stop_cyc1)); - save_item(NAME(m_run)); - save_item(NAME(m_rim)); - save_item(NAME(m_cycle)); - save_item(NAME(m_ioh)); - save_item(NAME(m_ios)); - save_item(NAME(m_rim_step)); - - // Register state for debugger - state_add( TX0_PC, "PC", m_pc ).mask(m_address_mask).formatstr("0%06O"); - state_add( TX0_IR, "IR", m_ir ).mask(m_ir_mask) .formatstr("0%02O"); - state_add( TX0_MBR, "MBR", m_mbr ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_MAR, "MAR", m_mar ).mask(m_address_mask).formatstr("0%06O"); - state_add( TX0_AC, "AC", m_ac ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_LR, "LR", m_lr ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_XR, "XR", m_xr ).mask(0037777) .formatstr("0%05O"); - state_add( TX0_PF, "PF", m_pf ).mask(077) .formatstr("0%02O"); - state_add( TX0_TBR, "TBR", m_tbr ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TAC, "TAC", m_tac ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS00, "TSS00", m_tss[000] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS01, "TSS01", m_tss[001] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS02, "TSS02", m_tss[002] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS03, "TSS03", m_tss[003] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS04, "TSS04", m_tss[004] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS05, "TSS05", m_tss[005] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS06, "TSS06", m_tss[006] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS07, "TSS07", m_tss[007] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS10, "TSS10", m_tss[010] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS11, "TSS11", m_tss[011] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS12, "TSS12", m_tss[012] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS13, "TSS13", m_tss[013] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS14, "TSS14", m_tss[014] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS15, "TSS15", m_tss[015] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS16, "TSS16", m_tss[016] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_TSS17, "TSS17", m_tss[017] ).mask(0777777) .formatstr("0%06O"); - state_add( TX0_CM_SEL, "CMSEL", m_cm_sel ).mask(0177777) .formatstr("0%06O"); - state_add( TX0_LR_SEL, "LRSEL", m_lr_sel ).mask(0177777) .formatstr("0%06O"); - state_add( TX0_GBL_CM_SEL, "GBLCMSEL", m_gbl_cm_sel ).mask(1) .formatstr("%1X"); - state_add( TX0_STOP_CYC0, "STOPCYC0", m_stop_cyc0 ).mask(1) .formatstr("%1X"); - state_add( TX0_STOP_CYC1, "STOPCYC1", m_stop_cyc1 ).mask(1) .formatstr("%1X"); - state_add( TX0_RUN, "RUN", m_run ).mask(1) .formatstr("%1X"); - state_add( TX0_RIM, "RIM", m_rim ).mask(1) .formatstr("%1X"); - state_add( TX0_CYCLE, "CYCLE", m_cycle ) .formatstr("%1X"); - state_add( TX0_IOH, "IOH", m_ioh ) .formatstr("%1X"); - state_add( TX0_IOS, "IOS", m_ios ).mask(1) .formatstr("%1X"); - - state_add(STATE_GENPC, "GENPC", m_pc).formatstr("0%06O").noshow(); - state_add(STATE_GENFLAGS, "GENFLAGS", m_ir).noshow(); - - m_icountptr = &m_icount; -} - - -void tx0_device::device_reset() -{ - /* reset CPU flip-flops */ - pulse_reset(); - - m_gbl_cm_sel = 1; /* HACK */ -} - - -void tx0_device::call_io_handler(int io_handler) -{ - /* data will be transferred to AC */ - switch (io_handler) - { - case 0: m_cpy_handler(ASSERT_LINE); break; - case 1: m_r1l_handler(ASSERT_LINE); break; - case 2: m_dis_handler(ASSERT_LINE); break; - case 3: m_r3l_handler(ASSERT_LINE); break; - case 4: m_prt_handler(ASSERT_LINE); break; - case 5: m_rsv_handler(ASSERT_LINE); break; - case 6: m_p6h_handler(ASSERT_LINE); break; - case 7: m_p7h_handler(ASSERT_LINE); break; - } -} - - -/* execute instructions on this CPU until icount expires */ -void tx0_64kw_device::execute_run() -{ - do - { - debugger_instruction_hook(this, PC); - - - if (m_ioh && m_ios) - { - m_ioh = 0; - } - - - if ((! m_run) && (! m_rim)) - m_icount = 0; /* if processor is stopped, just burn cycles */ - else if (m_rim) - { - switch (m_rim_step) - { - case 0: - /* read first word as instruction */ - AC = 0; - call_io_handler(io_handler_rim); - m_rim_step = 1; - m_ios = 0; - break; - - case 1: - if (! m_ios) - { /* transfer incomplete: wait some more */ - m_icount = 0; - } - else - { /* data transfer complete */ - m_ios = 0; - - MBR = AC; - IR = MBR >> 16; /* basic opcode */ - if ((IR == 2) || (IR == 1)) /* trn or add instruction? */ - { - PC = MBR & ADDRESS_MASK_64KW; - m_rim = 0; /* exit read-in mode */ - m_run = (IR == 2) ? 1 : 0; /* stop if add instruction */ - m_rim_step = 0; - } - else if ((IR == 0) || (IR == 3)) /* sto or opr instruction? */ - { - MAR = MBR & ADDRESS_MASK_64KW; - m_rim_step = 2; - } - } - break; - - case 2: - /* read second word as data */ - AC = 0; - call_io_handler(io_handler_rim); - m_rim_step = 3; - m_ios = 0; - break; - - case 3: - if (! m_ios) - { /* transfer incomplete: wait some more */ - m_icount = 0; - } - else - { /* data transfer complete */ - m_ios = 0; - - tx0_write(MAR, MBR = AC); - - m_rim_step = 0; - } - break; - } - } - else - { - if (m_cycle == 0) - { /* fetch new instruction */ - MBR = tx0_read(MAR = PC); - INCREMENT_PC_64KW; - IR = MBR >> 16; /* basic opcode */ - MAR = MBR & ADDRESS_MASK_64KW; - } - - if (! m_ioh) - { - if ((m_stop_cyc0 && (m_cycle == 0)) - || (m_stop_cyc1 && (m_cycle == 1))) - m_run = 0; - - execute_instruction_64kw(); - } - - m_icount --; - } - } - while (m_icount > 0); -} - -/* execute instructions on this CPU until icount expires */ -void tx0_8kw_device::execute_run() -{ - do - { - debugger_instruction_hook(this, PC); - - - if (m_ioh && m_ios) - { - m_ioh = 0; - } - - - if ((! m_run) && (! m_rim)) - m_icount = 0; /* if processor is stopped, just burn cycles */ - else if (m_rim) - { - switch (m_rim_step) - { - case 0: - /* read first word as instruction */ - AC = 0; - call_io_handler(io_handler_rim); - m_rim_step = 1; - m_ios = 0; - break; - - case 1: - if (! m_ios) - { /* transfer incomplete: wait some more */ - m_icount = 0; - } - else - { /* data transfer complete */ - m_ios = 0; - - MBR = AC; - IR = MBR >> 13; /* basic opcode */ - if ((IR == 16) || (IR == 8)) /* trn or add instruction? */ - { - PC = MBR & ADDRESS_MASK_8KW; - m_rim = 0; /* exit read-in mode */ - m_run = (IR == 16) ? 1 : 0; /* stop if add instruction */ - m_rim_step = 0; - } - else if ((IR == 0) || (IR == 24)) /* sto or opr instruction? */ - { - MAR = MBR & ADDRESS_MASK_8KW; - m_rim_step = 2; - } - } - break; - - case 2: - /* read second word as data */ - AC = 0; - call_io_handler(io_handler_rim); - m_rim_step = 3; - m_ios = 0; - break; - - case 3: - if (! m_ios) - { /* transfer incomplete: wait some more */ - m_icount = 0; - } - else - { /* data transfer complete */ - m_ios = 0; - - tx0_write(MAR, MBR = AC); - - m_rim_step = 0; - } - break; - } - } - else - { - if (m_cycle == 0) - { /* fetch new instruction */ - MBR = tx0_read(MAR = PC); - INCREMENT_PC_8KW; - IR = MBR >> 13; /* basic opcode */ - MAR = MBR & ADDRESS_MASK_8KW; - } - - if (! m_ioh) - { - if ((m_stop_cyc0 && (m_cycle == 0)) - || (m_stop_cyc1 && (m_cycle == 1))) - m_run = 0; - - execute_instruction_8kw(); - } - - m_icount -= 1; - } - } - while (m_icount > 0); -} - - -/* execute one instruction */ -void tx0_64kw_device::execute_instruction_64kw() -{ - if (! m_cycle) - { - m_cycle = 1; /* most frequent case */ - switch (IR) - { - case 0: /* STOre */ - case 1: /* ADD */ - break; - - case 2: /* TRansfer on Negative */ - if (AC & 0400000) - { - PC = MAR & ADDRESS_MASK_64KW; - m_cycle = 0; /* instruction only takes one cycle if branch - is taken */ - } - break; - - case 3: /* OPeRate */ - if (MAR & 0100000) - /* (0.8) CLL = Clear the left nine digital positions of the AC */ - AC &= 0000777; - - if (MAR & 0040000) - /* (0.8) CLR = Clear the right nine digital positions of the AC */ - AC &= 0777000; - - if (((MAR & 0030000) >> 12) == 1) - /* (0.8) IOS In-Out Stop = Stop machine so that an In-Out command - (specified by digits 6 7 8 of MAR) may be executed */ - m_ioh = 1; - - if (((MAR & 0007000) >> 9) != 0) - { - /* ((MAR & 0007000) >> 9) is device ID */ - /* 7: */ - /* (0.8) P7H = Punch holes 1-6 in flexo tape specified by AC - digital positions 2, 5, 8, 11, 14, and 17. Also punches a 7th - hole on tape. */ - /* 6: */ - /* (0.8) P6H = Same as P7H but no seventh hole */ - /* 4: */ - /* (0.8) PNT = Print one flexowriter character specified by AC - digits 2, 5, 8, 11, 14, and 17. */ - /* 1: */ - /* (0.8) R1C = Read one line of flexo tape so that tape positions - 1, 2, 3, 4, 5, and 6 will be put in the AC digital positions 0, - 3, 6, 9, 12 and 15. */ - /* 3: */ - /* (0.8) R3C = Read one line of flexo tape into AC digits 0, 3, 6, - 9, 12 and 15. Then cycle the AC one digital position; read the - next line on tape into AC digits 0, 3, 6, 9, 12 and 15, cycle - the AC right one digital position and read the third and last - line into AC digits 0, 3, 6, 9, 12 and 15. (This command is - equal to a triple CYR-R1C.) */ - /* 2: */ - /* (0.8) DIS = Intensify a point on the scope with x and y - coordinates where x is specified by AC digits 0-8 with digit 0 - being used as the sign and y is specified by AC digits 9-17 - with digit 9 being used as the sign for y. The complement - system is in effect when the signs are negative. */ - /* (5 is undefined) */ - int index = (MAR & 0007000) >> 9; - - call_io_handler(index); - m_ioh = 1; - } - break; - } - } - else - { - m_cycle = 0; /* always true */ - switch (IR) - { - case 0: /* STOre */ - tx0_write(MAR, (MBR = AC)); - break; - - case 1: /* ADD */ - MBR = tx0_read(MAR); - - AC = AC + MBR; - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - - if (AC == 0777777) /* check for -0 */ - AC = 0; - break; - - case 2: /* TRansfer on Negative */ - break; - - case 3: /* OPeRate */ - if ((MAR & 0000104) == 0000100) - /* (1.1) PEN = Read the light pen flip-flops 1 and 2 into AC(0) and - AC(1). */ - /*...*/{ } - - if ((MAR & 0000104) == 0000004) - /* (1.1) TAC = Insert a one in each digital position of the AC - wherever there is a one in the corresponding digital position - of the TAC. */ - /*...*/ { } - - if (MAR & 0000040) - /* (1.2) COM = Complement every digit in the accumulator */ - AC ^= 0777777; - - if ((MAR & 0000003) == 1) - /* (1.2) AMB = Store the contents of the AC in the MBR. */ - MBR = AC; - - if ((MAR & 0000003) == 3) - /* (1.2) TBR = Store the contents of the TBR in the MBR. */ - /*...*/ { } - - if ((MAR & 0000003) == 2) - /* (1.3) LMB = Store the contents of the LR in the MBR. */ - MBR = LR; - break; - - if (((MAR & 0000600) >> 7) == 1) - /* (1.3) MLR = Store the contents of the MBR (memory buffer - register) in the live reg. */ - LR = MBR; - - if (((MAR & 0000600) >> 7) == 2) - /* (1.4) SHR = Shift the AC right one place, i.e. multiply the AC - by 2^-1 */ - AC >>= 1; - - if (((MAR & 0000600) >> 7) == 3) - /* (1.4) CYR = Cycle the AC right one digital position (AC(17) will - become AC(0)) */ - AC = (AC >> 1) | ((AC & 1) << 17); - - if (MAR & 0000020) - /* (1.4) PAD = Partial add AC to MBR, that is, for every digital - position of the MBR that contains a one, complement the digit - in the corresponding digital position of the AC. This is also - called a half add. */ - AC ^= MBR; - - if (MAR & 0000010) - { /* (1.7) CRY = Partial add the 18 digits of the AC to the - corresponding 18 digits of the carry. - - To determine what the 18 digits of the carry are, use the - following rule: - - "Grouping the AC and MBR digits into pairs and proceeding from - right to left, assign the carry digit of the next pair to a one - if in the present pair MBR = 1 and AC = 0 or if in the present - pair AC = 1 and carry 1. - - (Note: the 0th digit pair determines the 17th pair's carry - digit)" */ - AC ^= MBR; - - AC = AC + MBR; - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - - if (AC == 0777777) /* check for -0 */ - AC = 0; - } - - if (((MAR & 0030000) >> 12) == 3) - /* (1.8) Hlt = Halt the computer */ - m_run = 0; - - break; - } - } -} - -void tx0_device::indexed_address_eval() -{ - MAR = MAR + XR; - MAR = (MAR + (MAR >> 14)) & 0037777; /* propagate carry around */ - //if (MAR == 0037777) /* check for -0 */ - // MAR = 0; - if (MAR & 0020000) /* fix negative (right???) */ - MAR = (MAR + 1) & 0017777; -} - -/* execute one instruction */ -void tx0_8kw_device::execute_instruction_8kw() -{ - if (! m_cycle) - { - m_cycle = 1; /* most frequent case */ - switch (IR) - { - case 0: /* STOre */ - case 1: /* STore indeXed */ - case 2: /* Store indeX in Address */ - case 3: /* ADd One */ - case 4: /* Store LR */ - case 5: /* Store Lr indeXed */ - case 6: /* STore Zero */ - case 8: /* ADD */ - case 9: /* ADd indeXed */ - case 10: /* LoaD indeX */ - case 11: /* AUgment indeX */ - case 12: /* Load LR */ - case 13: /* Load Lr indeXed */ - case 14: /* LoaD Ac */ - case 15: /* Load Ac indeXed */ - break; - - case 16: /* TRansfer on Negative */ - if (AC & 0400000) - { - PC = MAR & 0017777; - m_cycle = 0; /* instruction only takes one cycle if branch - is taken */ - } - break; - - case 17: /* Transfer on ZEro */ - if ((AC == 0000000) || (AC == 0777777)) - { - PC = MAR & 0017777; - m_cycle = 0; /* instruction only takes one cycle if branch - is taken */ - } - break; - - case 18: /* Transfer and Set indeX */ - XR = PC; - PC = MAR & 0017777; - m_cycle = 0; /* instruction only takes one cycle if branch - is taken */ - break; - - case 19: /* Transfer and IndeX */ - if ((XR != 0000000) && (XR != 0037777)) - { - if (XR & 0020000) - XR ++; - else - XR--; - PC = MAR & 0017777; - m_cycle = 0; /* instruction only takes one cycle if branch - is taken */ - } - break; - - case 21: /* TRansfer indeXed */ - indexed_address_eval(); - case 20: /* TRAnsfer */ - PC = MAR & 0017777; - m_cycle = 0; /* instruction only takes one cycle if branch - is taken */ - break; - - case 22: /* Transfer on external LeVel */ - /*if (...) - { - PC = MAR & 0017777; - m_cycle = 0;*/ /* instruction only takes one cycle if branch - is taken */ - /*}*/ - break; - - case 24: /* OPeRate */ - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - if (((IR & 001) == 00) && ((MAR & 017000) == 004000)) - { /* Select class instruction */ - if (IR & 004) - /* (0.8???) CLA = CLear Ac */ - AC = 0; - - /* (IOS???) SEL = SELect */ - m_sel_handler(ASSERT_LINE); - } - else - { /* Normal operate class instruction */ - if (((IR & 001) == 01) && ((MAR & 017000) == 011000)) - /* (0.6) CLL = CLear Left 9 bits of ac */ - AC &= 0000777; - - if (((IR & 001) == 01) && ((MAR & 017000) == 012000)) - /* (0.6) CLR = CLear Right 9 bits of ac */ - AC &= 0777000; - - if (IR & 002) - /* (0.7) AMB = transfer Ac to MBr */ - MBR = AC; - - if (IR & 004) - /* (0.8) CLA = CLear Ac */ - AC = 0; - - if (((IR & 001) == 01) && ((MAR & 010000) == 000000)) - { /* (IOS) In-Out group commands */ - /* ((MAR & 0007000) >> 9) is device ID */ - /* 0: */ - /* (***) CPY = CoPY synchronizes transmission of information - between in-out equipment and computer. */ - /* 1: */ - /* (IOS) R1L = Read 1 Line of tape from PETR into AC bits 0, 3, - 6, 9, 12, 15, with CYR before read (inclusive or) */ - /* 3: */ - /* (IOS) R3L = Read 3 Lines of tape from PETR into AC bits 0, - 3, 6, 9, 12, 15, with CYR before each read (inclusive or) */ - /* 2: */ - /* (IOS) DIS = DISplay a point on scope (AC bits 0-8 specify x - coordinate, AC bits 9-17 specify y coordinate). The - coordinate (0, 0) is usually at the lower left hand corner - of the scope. A console switch is available to relocate - (0,0) to the center. */ - /* 6: */ - /* (IOS) P6H = Punch one 6-bit line of flexo tape (without 7th - hole) from ac bits 2, 5, 8, 11, 14, 17. Note: lines - without 7th hole are ignored by PETR. */ - /* 7: */ - /* (IOS) P7H = same as P6H, but with 7th hole */ - /* 4: */ - /* (IOS) PRT = Print one six bit flexo character from AC bits - 2, 5, 8, 11, 14, 17. */ - /* (5 is undefined) */ - int index = (MAR & 0007000) >> 9; - - call_io_handler(index); - m_ioh = 1; - } - - if (((IR & 001) == 00) && ((MAR & 010000) == 010000)) - { /* (IOS) EX0 through EX7 = operate user's EXternal equipment. */ - switch ((MAR & 0007000) >> 9) - { - /* ... */ - } - } - } - break; - } - } - else - { - if (((IR != 2) && (IR != 3)) || (m_cycle == 2)) - m_cycle = 0; - else - m_cycle = 2; /* SXA and ADO have an extra cycle 2 */ - switch (IR) - { - case 1: /* STore indeXed */ - indexed_address_eval(); - case 0: /* STOre */ - tx0_write(MAR, (MBR = AC)); - break; - - case 2: /* Store indeX in Address */ - if (m_cycle) - { /* cycle 1 */ - MBR = tx0_read(MAR); - MBR = (MBR & 0760000) | (XR & 0017777); - } - else - { /* cycle 2 */ - tx0_write(MAR, MBR); - } - break; - - case 3: /* ADd One */ - if (m_cycle) - { /* cycle 1 */ - AC = tx0_read(MAR) + 1; - - #if 0 - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - if (AC == 0777777) /* check for -0 (right???) */ - AC = 0; - #else - if (AC >= 0777777) - AC = (AC + 1) & 0777777; - #endif - } - else - { /* cycle 2 */ - tx0_write(MAR, (MBR = AC)); - } - break; - - case 5: /* Store Lr indeXed */ - indexed_address_eval(); - case 4: /* Store LR */ - tx0_write(MAR, (MBR = LR)); - break; - - case 6: /* STore Zero */ - tx0_write(MAR, (MBR = 0)); - break; - - case 9: /* ADd indeXed */ - indexed_address_eval(); - case 8: /* ADD */ - MBR = tx0_read(MAR); - - AC = AC + MBR; - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - - if (AC == 0777777) /* check for -0 */ - AC = 0; - break; - - case 10: /* LoaD indeX */ - MBR = tx0_read(MAR); - XR = (MBR & 0017777) | ((MBR >> 4) & 0020000); - break; - - case 11: /* AUgment indeX */ - MBR = tx0_read(MAR); - - XR = XR + ((MBR & 0017777) | ((MBR >> 4) & 0020000)); - XR = (XR + (XR >> 14)) & 0037777; /* propagate carry around */ - - //if (XR == 0037777) /* check for -0 */ - // XR = 0; - break; - - case 13: /* Load Lr indeXed */ - indexed_address_eval(); - case 12: /* Load LR */ - LR = MBR = tx0_read(MAR); - break; - - case 15: /* Load Ac indeXed */ - indexed_address_eval(); - case 14: /* LoaD Ac */ - AC = MBR = tx0_read(MAR); - break; - - case 16: /* TRansfer on Negative */ - case 17: /* Transfer on ZEro */ - case 18: /* Transfer and Set indeX */ - case 19: /* Transfer and IndeX */ - case 20: /* TRAnsfer */ - case 21: /* TRansfer indeXed */ - case 22: /* Transfer on external LeVel */ - break; - - case 24: /* OPeRate */ - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - if (((IR & 001) == 00) && ((MAR & 017000) == 004000)) - { /* Select class instruction */ - } - else - { /* Normal operate class instruction */ - if (((IR & 001) == 00) && ((MAR & 017000) == 003000)) - { /* (1.1) PEN = set ac bit 0 from light PEN ff, and ac bit 1 from - light gun ff. (ffs contain one if pen or gun saw displayed - point.) Then clear both light pen and light gun ffs */ - /*AC = (AC & 0177777) |?...;*/ - /*... = 0;*/ - } - - if (((IR & 001) == 00) && ((MAR & 017000) == 001000)) - /* (1.1) TAC = transfer TAC into ac (inclusive or) */ - AC |= m_tac; - - if (((IR & 001) == 00) && ((MAR & 017000) == 002000)) - /* (1.2) TBR = transfer TBR into mbr (inclusive or) */ - MBR |= m_tbr; - - if (((IR & 001) == 00) && ((MAR & 017000) == 006000)) - /* (1.2) RPF = Read Program Flag register into mbr (inclusive or) */ - MBR |= PF << 8; - - if (MAR & 0000040) - /* (1.2) COM = COMplement ac */ - AC ^= 0777777; - - if ((! (MAR & 0000400)) && (MAR & 0000100)) - { /* (1.2) XMB = Transfer XR contents to MBR */ - MBR = XR; - if (XR & 0020000) - MBR |= 0740000; - } - - if (MAR & 0000004) - { - switch (MAR & 0000003) - { - case 0000003: /* (1.2) And LR and MBR */ - MBR &= LR; - break; - - case 0000001: /* (1.3) Or LR into MBR */ - MBR |= LR; - break; - - default: - if (LOG) - logerror("unrecognized instruction"); - break; - } - } - - if (((! (MAR & 0000400)) && (MAR & 0000200)) && ((! (MAR & 0000004)) && (MAR & 0000002))) - { /* LMB and MBL used simultaneously interchange LR and MBR */ - int tmp = MBR; - MBR = LR; - LR = tmp; - } - else if ((! (MAR & 0000400)) && (MAR & 0000200)) - /* (1.4) MBL = Transfer MBR contents to LR */ - LR = MBR; - else if ((! (MAR & 0000004)) && (MAR & 0000002)) - /* (1.4) LMB = Store the contents of the LR in the MBR. */ - MBR = LR; - - if (MAR & 0000020) - /* (1.5) PAD = Partial ADd mbr to ac */ - AC ^= MBR; - - if (MAR & 0000400) - { - switch (MAR & 0000300) - { - case 0000000: /* (1.6) CYR = CYcle ac contents Right one binary - position (AC(17) -> AC(0)) */ - AC = (AC >> 1) | ((AC & 1) << 17); - break; - - case 0000200: /* (1.6) CYcle ac contents Right one binary - position (AC(0) unchanged) */ - AC = (AC >> 1) | (AC & 0400000); - break; - - default: - if (LOG) - logerror("unrecognized instruction"); - break; - } - } - - if (((IR & 001) == 00) && ((MAR & 017000) == 007000)) - /* (1.6) SPF = Set Program Flag register from mbr */ - PF = (MBR >> 8) & 077; - - if (MAR & 0000010) - { /* (1.7?) CRY = Partial ADd the 18 digits of the AC to the - corresponding 18 digits of the carry. */ - AC ^= MBR; - - AC = AC + MBR; - AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ - - if (AC == 0777777) /* check for -0 */ - AC = 0; - } - - if ((! (MAR & 0000004)) && (MAR & 0000001)) - /* (1.8) MBX = Transfer MBR contents to XR */ - XR = (MBR & 0017777) | ((MBR >> 4) & 0020000); - - if (((IR & 001) == 01) && ((MAR & 017000) == 010000)) - /* (1.8) HLT = HaLT the computer and sound chime */ - m_run = 0; - } - break; - - default: /* Illegal */ - /* ... */ - break; - } - } -} - -/* - Simulate a pulse on reset line: - reset most registers and flip-flops, and initialize a few emulator state - variables. -*/ -void tx0_device::pulse_reset() -{ - /* processor registers */ - PC = 0; /* ??? */ - IR = 0; /* ??? */ - /*MBR = 0;*/ /* ??? */ - /*MAR = 0;*/ /* ??? */ - /*AC = 0;*/ /* ??? */ - /*LR = 0;*/ /* ??? */ - - /* processor state flip-flops */ - m_run = 0; /* ??? */ - m_rim = 0; /* ??? */ - m_ioh = 0; /* ??? */ - m_ios = 0; /* ??? */ - - m_rim_step = 0; - - /* now, we kindly ask IO devices to reset, too */ - m_io_reset_callback(ASSERT_LINE); -} - -void tx0_device::io_complete() -{ - m_ios = 1; -} - - -offs_t tx0_8kw_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) -{ - extern CPU_DISASSEMBLE( tx0_8kw ); - return CPU_DISASSEMBLE_NAME(tx0_8kw)(this, buffer, pc, oprom, opram, options); -} - - -offs_t tx0_64kw_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) -{ - extern CPU_DISASSEMBLE( tx0_64kw ); - return CPU_DISASSEMBLE_NAME(tx0_64kw)(this, buffer, pc, oprom, opram, options); -} diff --git a/src/emu/cpu/pdp1/tx0.h b/src/emu/cpu/pdp1/tx0.h deleted file mode 100644 index e88172bc8ff..00000000000 --- a/src/emu/cpu/pdp1/tx0.h +++ /dev/null @@ -1,179 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Raphael Nabet -#pragma once - -#ifndef __TX0_H__ -#define __TX0_H__ - - - -/* register ids for tx0_get_reg/tx0_set_reg */ -enum -{ - TX0_MBR=1, TX0_AC, TX0_MAR, TX0_PC, TX0_IR, TX0_LR, TX0_XR, TX0_PF, - TX0_TBR, TX0_TAC, - TX0_TSS00, TX0_TSS01, TX0_TSS02, TX0_TSS03, TX0_TSS04, TX0_TSS05, TX0_TSS06, TX0_TSS07, - TX0_TSS10, TX0_TSS11, TX0_TSS12, TX0_TSS13, TX0_TSS14, TX0_TSS15, TX0_TSS16, TX0_TSS17, - TX0_CM_SEL, TX0_LR_SEL, TX0_GBL_CM_SEL, - TX0_STOP_CYC0, TX0_STOP_CYC1, - TX0_RUN, TX0_RIM, - TX0_CYCLE, TX0_IOH, TX0_IOS -}; - - -#define MCFG_TX0_CONFIG(_cpy_devcb, _r1l_devcb, _dis_devcb, _r3l_devcb, _prt_devcb, _rsv_devcb, _p6h_devcb, _p7h_devcb, _sel_devcb, _res_devcb) \ - tx0_device::set_cpy_cb(*device, DEVCB_##_cpy_devcb); \ - tx0_device::set_r1l_cb(*device, DEVCB_##_r1l_devcb); \ - tx0_device::set_dis_cb(*device, DEVCB_##_dis_devcb); \ - tx0_device::set_r3l_cb(*device, DEVCB_##_r3l_devcb); \ - tx0_device::set_prt_cb(*device, DEVCB_##_prt_devcb); \ - tx0_device::set_rsv_cb(*device, DEVCB_##_rsv_devcb); \ - tx0_device::set_p6h_cb(*device, DEVCB_##_p6h_devcb); \ - tx0_device::set_p7h_cb(*device, DEVCB_##_p7h_devcb); \ - tx0_device::set_sel_cb(*device, DEVCB_##_sel_devcb); \ - tx0_device::set_res_cb(*device, DEVCB_##_res_devcb); - - -class tx0_device : public cpu_device -{ -public: - // construction/destruction - tx0_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int addr_bits, int address_mask, int ir_mask); - - // static configuration helpers - template<class _Object> static devcb_base &set_cpy_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_cpy_handler.set_callback(object); } - template<class _Object> static devcb_base &set_r1l_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_r1l_handler.set_callback(object); } - template<class _Object> static devcb_base &set_dis_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_dis_handler.set_callback(object); } - template<class _Object> static devcb_base &set_r3l_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_r3l_handler.set_callback(object); } - template<class _Object> static devcb_base &set_prt_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_prt_handler.set_callback(object); } - template<class _Object> static devcb_base &set_rsv_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_rsv_handler.set_callback(object); } - template<class _Object> static devcb_base &set_p6h_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_p6h_handler.set_callback(object); } - template<class _Object> static devcb_base &set_p7h_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_p7h_handler.set_callback(object); } - template<class _Object> static devcb_base &set_sel_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_sel_handler.set_callback(object); } - template<class _Object> static devcb_base &set_res_cb(device_t &device, _Object object) { return downcast<tx0_device &>(device).m_io_reset_callback.set_callback(object); } - - void pulse_reset(); - void io_complete(); - -protected: - // device-level overrides - virtual void device_start(); - virtual void device_reset(); - - // device_execute_interface overrides - virtual UINT32 execute_min_cycles() const { return 1; } - virtual UINT32 execute_max_cycles() const { return 3; } - - // device_memory_interface overrides - virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; } - - // device_disasm_interface overrides - virtual UINT32 disasm_min_opcode_bytes() const { return 4; } - virtual UINT32 disasm_max_opcode_bytes() const { return 4; } - -protected: - address_space_config m_program_config; - - /* processor registers */ - int m_mbr; /* memory buffer register (18 bits) */ - int m_ac; /* accumulator (18 bits) */ - int m_mar; /* memory address register (16 (64kW) or 13 (8kW) bits) */ - int m_pc; /* program counter (16 (64kW) or 13 (8kW) bits) */ - int m_ir; /* instruction register (2 (64kW) or 5 (8kW) bits) */ - int m_lr; /* live register (18 bits) */ - int m_xr; /* index register (14 bits) (8kW only) */ - int m_pf; /* program flags (6 bits expandable to 10) (8kW only) */ - - /* operator panel switches */ - int m_tbr; /* toggle switch buffer register (18 bits) */ - int m_tac; /* toggle switch accumulator (18 bits) */ - int m_tss[16]; /* toggle switch storage (18 bits * 16) */ - UINT16 m_cm_sel; /* individual cm select (1 bit * 16) */ - UINT16 m_lr_sel; /* individual lr select (1 bit * 16) */ - unsigned int m_gbl_cm_sel;/* global cm select (1 bit) */ - unsigned int m_stop_cyc0; /* stop on cycle 0 */ - unsigned int m_stop_cyc1; /* stop on cycle 1 */ - - /* processor state flip-flops */ - unsigned int m_run; /* processor is running */ - unsigned int m_rim; /* processor is in read-in mode */ - unsigned int m_cycle; /* 0 -> fetch */ - /* 1 -> execute (except for taken branches) */ - /* 2 -> extra execute cycle for SXA and ADO */ - - unsigned int m_ioh; /* i-o halt: processor is executing an Input-Output Transfer wait */ - unsigned int m_ios; /* i-o synchronizer: set on i-o operation completion */ - - /* additional emulator state variables */ - int m_rim_step; /* current step in rim execution */ - - int m_address_mask; /* address mask */ - int m_ir_mask; /* IR mask */ - - int m_icount; - - address_space *m_program; - - /* 8 standard I/O handlers: - 0: cpy (8kW only) - 1: r1l - 2: dis - 3: r3l - 4: prt - 5: reserved (for unimplemented typ instruction?) - 6: p6h - 7: p7h */ - devcb_write_line m_cpy_handler; - devcb_write_line m_r1l_handler; - devcb_write_line m_dis_handler; - devcb_write_line m_r3l_handler; - devcb_write_line m_prt_handler; - devcb_write_line m_rsv_handler; - devcb_write_line m_p6h_handler; - devcb_write_line m_p7h_handler; - /* select instruction handler */ - devcb_write_line m_sel_handler; - /* callback called when reset line is pulsed: IO devices should reset */ - devcb_write_line m_io_reset_callback; - - int tx0_read(offs_t address); - void tx0_write(offs_t address, int data); - void call_io_handler(int io_handler); - void indexed_address_eval(); -}; - - -class tx0_8kw_device : public tx0_device -{ -public: - // construction/destruction - tx0_8kw_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock); - -protected: - virtual void execute_run(); - virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); - -private: - void execute_instruction_8kw(); -}; - - -class tx0_64kw_device : public tx0_device -{ -public: - // construction/destruction - tx0_64kw_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock); - -protected: - virtual void execute_run(); - virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); - -private: - void execute_instruction_64kw(); -}; - - -extern const device_type TX0_64KW; -extern const device_type TX0_8KW; - -#endif /* __TX0_H__ */ diff --git a/src/emu/cpu/pdp1/tx0dasm.c b/src/emu/cpu/pdp1/tx0dasm.c deleted file mode 100644 index 3d8a1daf9e1..00000000000 --- a/src/emu/cpu/pdp1/tx0dasm.c +++ /dev/null @@ -1,123 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Raphael Nabet -#include "emu.h" -#include "cpu/pdp1/tx0.h" - -CPU_DISASSEMBLE( tx0_64kw ) -{ - int md; - int x; - - md = oprom[0] << 24 | oprom[1] << 16 | oprom[2] << 8 | oprom[3]; - - x = md & 0177777; - switch (md >> 16) - { - case 0: - sprintf (buffer, "sto 0%06o", x); - break; - case 1: - sprintf (buffer, "add 0%06o", x); - break; - case 2: - sprintf (buffer, "trn 0%06o", x); - break; - case 3: - sprintf (buffer, "opr 0%06o", x); - break; - } - return 1; -} - -CPU_DISASSEMBLE( tx0_8kw ) -{ - int md; - int x; - - md = oprom[0] << 24 | oprom[1] << 16 | oprom[2] << 8 | oprom[3]; - - x = md & 0017777; - switch (md >> 13) - { - case 0: - sprintf (buffer, "sto 0%05o", x); - break; - case 1: - sprintf (buffer, "stx 0%05o", x); - break; - case 2: - sprintf (buffer, "sxa 0%05o", x); - break; - case 3: - sprintf (buffer, "ado 0%05o", x); - break; - case 4: - sprintf (buffer, "slr 0%05o", x); - break; - case 5: - sprintf (buffer, "slx 0%05o", x); - break; - case 6: - sprintf (buffer, "stz 0%05o", x); - break; - case 8: - sprintf (buffer, "add 0%05o", x); - break; - case 9: - sprintf (buffer, "adx 0%05o", x); - break; - case 10: - sprintf (buffer, "ldx 0%05o", x); - break; - case 11: - sprintf (buffer, "aux 0%05o", x); - break; - case 12: - sprintf (buffer, "llr 0%05o", x); - break; - case 13: - sprintf (buffer, "llx 0%05o", x); - break; - case 14: - sprintf (buffer, "lda 0%05o", x); - break; - case 15: - sprintf (buffer, "lax 0%05o", x); - break; - case 16: - sprintf (buffer, "trn 0%05o", x); - break; - case 17: - sprintf (buffer, "tze 0%05o", x); - break; - case 18: - sprintf (buffer, "tsx 0%05o", x); - break; - case 19: - sprintf (buffer, "tix 0%05o", x); - break; - case 20: - sprintf (buffer, "tra 0%05o", x); - break; - case 21: - sprintf (buffer, "trx 0%05o", x); - break; - case 22: - sprintf (buffer, "tlv 0%05o", x); - break; - case 24: - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - sprintf (buffer, "opr 0%06o", md & 0177777); - break; - default: - sprintf (buffer, "illegal"); - break; - } - return 1; -} |