1 // license:BSD-3-Clause
2 // copyright-holders:Raphael Nabet
3 /*
4 * Note: Original Java source written by:
5 *
6 * Barry Silverman mailto:barry@disus.com or mailto:bss@media.mit.edu
7 * Vadim Gerasimov mailto:vadim@media.mit.edu
8 *
9 * MESS driver by Chris Salomon and Raphael Nabet.
10 *
11 * Basically, it has been rewritten entirely in order to perform cycle-level simulation
12 * (with only a few flip-flops being set one cycle too early or too late). I don't know if
13 * it is a good thing or a bad thing (it makes emulation more accurate, but slower, and
14 * code is more complex and less readable), but it appears to be the only way we could emulate
15 * mid-instruction sequence break. And it enables us to emulate the control panel fairly
16 * accurately.
17 *
18 * Additionally, IOT functions have been modified to be external: IOT callback pointers are set
19 * at emulation initiation, and most IOT callback functions are part of the machine emulation.
20 *
21 *
22 * for the runnable java applet, with applet and Spacewar! source, go to:
23 * http://lcs.www.media.mit.edu/groups/el/projects/spacewar/
24 *
25 * for a complete html version of the pdp1 handbook go to:
26 * http://www.dbit.com/~greeng3/pdp1/index.html
27 *
28 * there is another java simulator (by the same people) which runs the
29 * original pdp1 LISP interpreter, go to:
30 * http://lcs.www.media.mit.edu/groups/el/projects/pdp1
31 *
32 * Another PDP1 emulator (or simulator) is at:
33 * ftp://minnie.cs.adfa.oz.au/pub/PDP-11/Sims/Supnik_2.3
34 * It seems to emulate pdp1 I/O more accurately than we do.
35 * However, there is no CRT emulation.
36 *
37 * and finally, there is a nice article about SPACEWAR!, go to:
38 * http://ars-www.uchicago.edu/~eric/lore/spacewar/spacewar.html
39 *
40 * some extra documentation is available on spies:
41 * http://www.spies.com/~aek/pdf/dec/pdp1/
42 * The file "F17_PDP1Maint.pdf" explains operation procedures and much of the internals of pdp-1.
43 * It was the main reference for this emulator.
44 * The file "F25_PDP1_IO.pdf" has interesting information on the I/O system, too.
45 *
46 * Following is an extract from the handbook:
47 *
48 * INTRODUCTION
49 *
50 * The Programmed Data Processor (PDP-1) is a high speed, solid state digital computer designed to
51 * operate with many types of input-output devices with no internal machine changes. It is a single
52 * address, single instruction, stored program computer with powerful program features. Five-megacycle
53 * circuits, a magnetic core memory and fully parallel processing make possible a computation rate of
54 * 100,000 additions per second. The PDP-1 is unusually versatile. It is easy to install, operate and
55 * maintain. Conventional 110-volt power is used, neither air conditioning nor floor reinforcement is
56 * necessary, and preventive maintenance is provided for by built-in marginal checking circuits.
57 *
58 * PDP-1 circuits are based on the designs of DEC's highly successful and reliable System Modules.
59 * Flip-flops and most switches use saturating transistors. Primary active elements are
60 * Micro-Alloy-Diffused transistors.
61 *
62 * The entire computer occupies only 17 square feet of floor space. It consists of four equipment frames,
63 * one of which is used as the operating station.
64 *
65 * CENTRAL PROCESSOR
66 *
67 * The Central Processor contains the control, arithmetic and memory addressing elements, and the memory
68 * buffer register. The word length is 18 binary digits. Instructions are performed in multiples of the
69 * memory cycle time of five microseconds. Add, subtract, deposit, and load, for example, are two-cycle
70 * instructions requiring 10 microseconds. Multiplication requires and average of 20 microseconds.
71 * Program features include: single address instructions, multiple step indirect addressing and logical
72 * arithmetic commands. Console features include: flip-flop indicators grouped for convenient octal
73 * reading, six program flags for automatic setting and computer sensing, and six sense switches for
74 * manual setting and computer sensing.
75 *
76 * MEMORY SYSTEM
77 *
78 * The coincident-current, magnetic core memory of a standard PDP-1 holds 4096 words of 18 bits each.
79 * Memory capacity may be readily expanded, in increments of 4096 words, to a maximum of 65,536 words.
80 * The read-rewrite time of the memory is five microseconds, the basic computer rate. Driving currents
81 * are automatically adjusted to compensate for temperature variations between 50 and 110 degrees
82 * Fahrenheit. The core memory storage may be supplemented by up to 24 magnetic tape transports.
83 *
84 * INPUT-OUTPUT
85 *
86 * PDP-1 is designed to operate a variety of buffered input-output devices. Standard equipment consistes
87 * of a perforated tape reader with a read speed of 400 lines per second, and alphanuermic typewriter for
88 * on-line operation in both input and output, and a perforated tape punch (alphanumeric or binary) with
89 * a speed of 63 lines per second. A variety of optional equipment is available, including the following:
90 *
91 * Precision CRT Display Type 30
92 * Ultra-Precision CRT Display Type 31
93 * Symbol Generator Type 33
94 * Light Pen Type 32
95 * Oscilloscope Display Type 34
96 * Card Punch Control Type 40-1
97 * Card Reader and Control Type 421
98 * Magnetic Tape Transport Type 50
99 * Programmed Magnetic Tape Control Type 51
100 * Automatic Magnetic Tape Control Type 52
101 * Automatic Magnetic Tape Control Type 510
102 * Parallel Drum Type 23
103 * Automatic Line Printer and Control Type 64
104 * 18-bit Real Time Clock
105 * 18-bit Output Relay Buffer Type 140
106 * Multiplexed A-D Converter Type 138/139
107 *
108 * All in-out operations are performed through the In-Out Register or through the high speed input-output
109 * channels.
110 *
111 * The PDP-1 is also available with the optional Sequence Break System. This is a multi-channel priority
112 * interrupt feature which permits concurrent operation of several in-out devices. A one-channel Sequence
113 * Break System is included in the standard PDP-1. Optional Sequence Break Systems consist of 16, 32, 64,
114 * 128, and 256 channels.
115 *
116 * ...
117 *
118 * BASIC INSTRUCTIONS
119 *
120 * OPER. TIME
121 * INSTRUCTION CODE # EXPLANATION (usec)
122 * ------------------------------------------------------------------------------
123 * add Y 40 Add C(Y) to C(AC) 10
124 * and Y 02 Logical AND C(Y) with C(AC) 10
125 * cal Y 16 Equals jda 100 10
126 * dac Y 24 Deposit C(AC) in Y 10
127 * dap Y 26 Deposit contents of address part of AC in Y 10
128 * dio Y 32 Deposit C(IO) in Y 10
129 * dip Y 30 Deposit contents of instruction part of AC in Y 10
130 * div Y 56 Divide 40 max
131 * dzm Y 34 Deposit zero in Y 10
132 * idx Y 44 Index (add one) C(Y), leave in Y & AC 10
133 * ior Y 04 Inclusive OR C(Y) with C(AC) 10
134 * iot Y 72 In-out transfer, see below
135 * isp Y 46 Index and skip if result is positive 10
136 * jda Y 17 Equals dac Y and jsp Y+1 10
137 * jmp Y 60 Take next instruction from Y 5
138 * jsp Y 62 Jump to Y and save program counter in AC 5
139 * lac Y 20 Load the AC with C(Y) 10
140 * law N 70 Load the AC with the number N 5
141 * law-N 71 Load the AC with the number -N 5
142 * lio Y 22 Load IO with C(Y) 10
143 * mul Y 54 Multiply 25 max
144 * opr 76 Operate, see below 5
145 * sad Y 50 Skip next instruction if C(AC) <> C(Y) 10
146 * sas Y 52 Skip next instruction if C(AC) = C(Y) 10
147 * sft 66 Shift, see below 5
148 * skp 64 Skip, see below 5
149 * sub Y 42 Subtract C(Y) from C(AC) 10
150 * xct Y 10 Execute instruction in Y 5+
151 * xor Y 06 Exclusive OR C(Y) with C(AC) 10
152 *
153 * OPERATE GROUP
154 *
155 * OPER. TIME
156 * INSTRUCTION CODE # EXPLANATION (usec)
157 * ------------------------------------------------------------------------------
158 * cla 760200 Clear AC 5
159 * clf 76000f Clear selected Program Flag (f = flag #) 5
160 * cli 764000 Clear IO 5
161 * cma 761000 Complement AC 5
162 * hlt 760400 Halt 5
163 * lap 760100 Load AC with Program Counter 5
164 * lat 762200 Load AC from Test Word switches 5
165 * nop 760000 No operation 5
166 * stf 76001f Set selected Program Flag 5
167 *
168 * IN-OUT TRANSFER GROUP
169 *
170 * PERFORATED TAPE READER
171 *
172 * INSTRUCTION CODE # EXPLANATION
173 * ------------------------------------------------------------------------------
174 * rpa 720001 Read Perforated Tape Alphanumeric
175 * rpb 720002 Read Perforated Tape Binary
176 * rrb 720030 Read Reader Buffer
177 *
178 * PERFORATED TAPE PUNCH
179 *
180 * INSTRUCTION CODE # EXPLANATION
181 * ------------------------------------------------------------------------------
182 * ppa 720005 Punch Perforated Tape Alphanumeric
183 * ppb 720006 Punch Perforated Tape Binary
184 *
185 * ALPHANUMERIC ON-LINE TYPEWRITER
186 *
187 * INSTRUCTION CODE # EXPLANATION
188 * ------------------------------------------------------------------------------
189 * tyo 720003 Type Out
190 * tyi 720004 Type In
191 *
192 * SEQUENCE BREAK SYSTEM TYPE 120
193 *
194 * INSTRUCTION CODE # EXPLANATION
195 * ------------------------------------------------------------------------------
196 * esm 720055 Enter Sequence Break Mode
197 * lsm 720054 Leave Sequence Break Mode
198 * cbs 720056 Clear Sequence Break System
199 * dsc 72kn50 Deactivate Sequence Break Channel
200 * asc 72kn51 Activate Sequence Break Channel
201 * isb 72kn52 Initiate Sequence Break
202 * cac 720053 Clear All Channels
203 *
204 * HIGH SPEED DATA CONTROL TYPE 131
205 *
206 * INSTRUCTION CODE # EXPLANATION
207 * ------------------------------------------------------------------------------
208 * swc 72x046 Set Word Counter
209 * sia 720346 Set Location Counter
210 * sdf 720146 Stop Data Flow
211 * rlc 720366 Read Location Counter
212 * shr 720446 Set High Speed Channel Request
213 *
214 * PRECISION CRT DISPLAY TYPE 30
215 *
216 * INSTRUCTION CODE # EXPLANATION
217 * ------------------------------------------------------------------------------
218 * dpy 720007 Display One Point
219 *
220 * SYMBOL GENERATOR TYPE 33
221 *
222 * INSTRUCTION CODE # EXPLANATION
223 * ------------------------------------------------------------------------------
224 * gpl 722027 Generator Plot Left
225 * gpr 720027 Generator Plot Right
226 * glf 722026 Load Format
227 * gsp 720026 Space
228 * sdb 722007 Load Buffer, No Intensity
229 *
230 * ULTRA-PRECISION CRT DISPLAY TYPE 31
231 *
232 * INSTRUCTION CODE # EXPLANATION
233 * ------------------------------------------------------------------------------
234 * dpp 720407 Display One Point on Ultra Precision CRT
235 *
236 * CARD PUNCH CONTROL TYPE 40-1
237 *
238 * INSTRUCTION CODE # EXPLANATION
239 * ------------------------------------------------------------------------------
240 * lag 720044 Load a Group
241 * pac 720043 Punch a Card
242 *
243 * CARD READER TYPE 421
244 *
245 * INSTRUCTION CODE # EXPLANATION
246 * ------------------------------------------------------------------------------
247 * rac 720041 Read Card Alpha
248 * rbc 720042 Read Card Binary
249 * rcc 720032 Read Card Column
250 *
251 * PROGRAMMED MAGNETIC TAPE CONTROL TYPE 51
252 *
253 * INSTRUCTION CODE # EXPLANATION
254 * ------------------------------------------------------------------------------
255 * msm 720073 Select Mode
256 * mcs 720034 Check Status
257 * mcb 720070 Clear Buffer
258 * mwc 720071 Write a Character
259 * mrc 720072 Read Character
260 *
261 * AUTOMATIC MAGNETIC TAPE CONTROL TYPE 52
262 *
263 * INSTRUCTION CODE # EXPLANATION
264 * ------------------------------------------------------------------------------
265 * muf 72ue76 Tape Unit and FinalT
266 * mic 72ue75 Initial and Command
267 * mrf 72u067 Reset Final
268 * mri 72ug66 Reset Initial
269 * mes 72u035 Examine States
270 * mel 72u036 Examine Location
271 * inr 72ur67 Initiate a High Speed Channel Request
272 * ccr 72s067 Clear Command Register
273 *
274 * AUTOMATIC MAGNETIC TAPE CONTROL TYPE 510
275 *
276 * INSTRUCTION CODE # EXPLANATION
277 * ------------------------------------------------------------------------------
278 * sfc 720072 Skip if Tape Control Free
279 * rsr 720172 Read State Register
280 * crf 720272 Clear End-of-Record Flip-Flop
281 * cpm 720472 Clear Proceed Mode
282 * dur 72xx70 Load Density, Unit, Rewind
283 * mtf 73xx71 Load Tape Function Register
284 * cgo 720073 Clear Go
285 *
286 * MULTIPLEXED A-D CONVERTER TYPE 138/139
287 *
288 * INSTRUCTION CODE # EXPLANATION
289 * ------------------------------------------------------------------------------
290 * rcb 720031 Read Converter Buffer
291 * cad 720040 Convert a Voltage
292 * scv 72mm47 Select Multiplexer (1 of 64 Channels)
293 * icv 720060 Index Multiplexer
294 *
295 * AUTOMATIC LINE PRINTER TYPE 64
296 *
297 * INSTRUCTION CODE # EXPLANATION
298 * ------------------------------------------------------------------------------
299 * clrbuf 722045 Clear Buffer
300 * lpb 720045 Load Printer Buffer
301 * pas 721x45 Print and Space
302 *
303 * SKIP GROUP
304 *
305 * OPER. TIME
306 * INSTRUCTION CODE # EXPLANATION (usec)
307 * ------------------------------------------------------------------------------
308 * sma 640400 Dkip on minus AC 5
309 * spa 640200 Skip on plus AC 5
310 * spi 642000 Skip on plus IO 5
311 * sza 640100 Skip on ZERO (+0) AC 5
312 * szf 6400f Skip on ZERO flag 5
313 * szo 641000 Skip on ZERO overflow (and clear overflow) 5
314 * szs 6400s0 Skip on ZERO sense switch 5
315 *
316 * SHIFT/ROTATE GROUP
317 *
318 * OPER. TIME
319 * INSTRUCTION CODE # EXPLANATION (usec)
320 * ------------------------------------------------------------------------------
321 * ral 661 Rotate AC left 5
322 * rar 671 Rotate AC right 5
323 * rcl 663 Rotate Combined AC & IO left 5
324 * rcr 673 Rotate Combined AC & IO right 5
325 * ril 662 Rotate IO left 5
326 * rir 672 Rotate IO right 5
327 * sal 665 Shift AC left 5
328 * sar 675 Shift AC right 5
329 * scl 667 Shift Combined AC & IO left 5
330 * scr 677 Shift Combined AC & IO right 5
331 * sil 666 Shift IO left 5
332 * sir 676 Shift IO right 5
333 */
334
335
336 /*
337 TODO:
338 * support other extensions as time permits
339 */
340
341
342 #include "emu.h"
343 #include "debugger.h"
344 #include "pdp1.h"
345 #include "pdp1dasm.h"
346
347 #define LOG 0
348 #define LOG_EXTRA 0
349 #define LOG_IOT_EXTRA 0
350
351 #define READ_PDP_18BIT(A) ((signed)m_program->read_dword(A))
352 #define WRITE_PDP_18BIT(A,V) (m_program->write_dword((A),(V)))
353
354
355 #define PC m_pc
356 #define IR m_ir
357 #define MB m_mb
358 #define MA m_ma
359 #define AC m_ac
360 #define IO m_io
361 #define OV m_ov
362 #define EXD m_exd
363 /* note that we start counting flags/sense switches at 1, therefore n is in [1,6] */
364 #define FLAGS m_pf
365 #define READFLAG(n) ((m_pf >> (6-(n))) & 1)
366 #define WRITEFLAG(n, data) (m_pf = (m_pf & ~(1 << (6-(n)))) | (((data) & 1) << (6-(n))))
367 #define SENSE_SW m_ss
368 #define READSENSE(n) ((m_ss >> (6-(n))) & 1)
369 #define WRITESENSE(n, data) (m_ss = (m_ss & ~(1 << (6-(n)))) | (((data) & 1) << (6-(n))))
370
371 #define EXTENDED_ADDRESS_MASK m_extended_address_mask
372 #define ADDRESS_EXTENSION_MASK m_address_extension_mask
373 #define BASE_ADDRESS_MASK 0007777
374
375 #define INCREMENT_PC (PC = (PC & ADDRESS_EXTENSION_MASK) | ((PC+1) & BASE_ADDRESS_MASK))
376 #define DECREMENT_PC (PC = (PC & ADDRESS_EXTENSION_MASK) | ((PC-1) & BASE_ADDRESS_MASK))
377 #define INCREMENT_MA (MA = (MA & ADDRESS_EXTENSION_MASK) | ((MA+1) & BASE_ADDRESS_MASK))
378 #define PREVIOUS_PC ((PC & ADDRESS_EXTENSION_MASK) | ((PC-1) & BASE_ADDRESS_MASK))
379
380
381 DEFINE_DEVICE_TYPE(PDP1, pdp1_device, "pdp1_cpu", "DEC PDP-1 Central Processor")
382
383
pdp1_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)384 pdp1_device::pdp1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
385 : cpu_device(mconfig, PDP1, tag, owner, clock)
386 , m_program_config("program", ENDIANNESS_BIG, 32, 18, -2) // data is actually 18 bits wide
387 , m_extern_iot(*this)
388 , m_io_sc_callback(*this)
389 , m_program(nullptr)
390 , m_reset_param(nullptr)
391 {
392 m_program_config.m_is_octal = true;
393 }
394
memory_space_config() const395 device_memory_interface::space_config_vector pdp1_device::memory_space_config() const
396 {
397 return space_config_vector {
398 std::make_pair(AS_PROGRAM, &m_program_config)
399 };
400 }
401
device_config_complete()402 void pdp1_device::device_config_complete()
403 {
404 // inherit a copy of the static data
405 const pdp1_reset_param_t *intf = m_reset_param;
406 if (intf != nullptr)
407 *static_cast<pdp1_reset_param_t *>(this) = *intf;
408
409 // or initialize to defaults if none provided
410 else
411 {
412 extend_support = 0;
413 hw_mul_div = 0;
414 type_20_sbs = 0;
415 }
416 }
417
418
create_disassembler()419 std::unique_ptr<util::disasm_interface> pdp1_device::create_disassembler()
420 {
421 return std::make_unique<pdp1_disassembler>();
422 }
423
424
425 /*
426 Interrupts are called "sequence break" in pdp1, but the general idea is the same.
427
428 There are several interrupt lines. With the standard sequence break system, all lines
429 are logically or'ed to trigger a single interrupt level. Interrupts can be triggered
430 by either a pulse or a level on the interrupt lines. With the optional type 120 sequence
431 break system, each of 16 lines triggers is wired to a different priority level: additionally,
432 each interrupt line can be masked out, and interrupt can be triggered through software.
433
434 Also, instructions can be interrupted in the middle of execution. This is done by
435 decrementing the PC register: therefore the instruction is re-executed from start.
436
437 Interrupt routines should not execute most IOT, as the interrupt may interrupt another.
438
439 More details can be found in the handbook and the maintenance manual.
440 */
441 /*
442 This function MUST be called every time m_sbm, m_b4, m_irq_state or m_b2 change.
443 */
field_interrupt()444 void pdp1_device::field_interrupt()
445 {
446 /* current_irq: 1 bit for each active pending interrupt request
447 Pending interrupts are in b3 (simulated by (m_irq_state & m_b1) | m_b2)), but they
448 are only honored if no higher priority interrupt routine is in execution (one bit set in b4
449 for each routine in execution). The relevant mask is created with (m_b4 | (- m_b4)),
450 as the carry chain (remember that -b4 = (~ b4) + 1) does precisely what we want.
451 b4: 0001001001000
452 -b4: 1110110111000
453 b4|-b4:1111111111000
454 Neat, uh?
455 */
456 int current_irq = ((m_irq_state & m_b1) | m_b2) & ~ (m_b4 | (- m_b4));
457 int i;
458
459 if (m_sbm && current_irq)
460 {
461 m_sbs_request = 1;
462 for (i=0; /*i<16 &&*/ (! ((current_irq >> i) & 1)); i++)
463 ;
464 m_sbs_level = i;
465 }
466 else
467 m_sbs_request = 0;
468 }
469
execute_set_input(int irqline,int state)470 void pdp1_device::execute_set_input(int irqline, int state)
471 {
472 if (irqline == INPUT_LINE_NMI)
473 {
474 /* no specific NMI line */
475 }
476 else if ((irqline >= 0) && (irqline < (m_type_20_sbs ? 1 : 16)))
477 {
478 unsigned int new_state = state ? 1 : 0;
479
480 if (((m_irq_state >> irqline) & 1) != new_state)
481 {
482 m_irq_state = (m_irq_state & ~ (1 << irqline)) | (new_state << irqline);
483
484 if ((new_state) && ((m_b1 >> irqline) & 1))
485 m_b2 |= (new_state << irqline);
486
487 /*m_b3 = m_irq_state | m_b2;*/
488
489 field_interrupt(); /* interrupt state has changed */
490 }
491 }
492 }
493
494
device_start()495 void pdp1_device::device_start()
496 {
497 int i;
498
499 /* clean-up */
500 m_pc = 0;
501 m_ir = 0;
502 m_mb = 0;
503 m_ma = 0;
504 m_ac = 0;
505 m_io = 0;
506 m_pf = 0;
507 m_ta = 0;
508 m_tw = 0;
509 m_ss = 0;
510 m_sngl_step = 0;
511 m_sngl_inst = 0;
512 m_extend_sw = 0;
513 m_run = 0;
514 m_cycle = 0;
515 m_defer = 0;
516 m_brk_ctr = 0;
517 m_ov = 0;
518 m_rim = 0;
519 m_sbm = 0;
520 m_exd = 0;
521 m_exc = 0;
522 m_ioc = 0;
523 m_ioh = 0;
524 m_ios = 0;
525 m_irq_state = 0;
526 m_b1 = 0;
527 m_b2 = 0;
528 m_b4 = 0;
529 m_rim_step = 0;
530 m_sbs_request = 0;
531 m_sbs_level = 0;
532 m_sbs_restore = 0;
533 m_no_sequence_break = 0;
534 m_debugger_temp = 0;
535
536 m_program = &space(AS_PROGRAM);
537
538 /* set up params and callbacks */
539 for (i=0; i<64; i++)
540 {
541 m_extern_iot[i].resolve();
542 if (m_extern_iot[i].isnull())
543 m_extern_iot[i] = iot_delegate(*this, FUNC(pdp1_device::null_iot));
544 }
545 m_io_sc_callback.resolve();
546 m_extend_support = extend_support;
547 m_hw_mul_div = hw_mul_div;
548 m_type_20_sbs = type_20_sbs;
549
550 switch (m_extend_support)
551 {
552 default:
553 m_extend_support = 0;
554 case 0: /* no extension */
555 m_extended_address_mask = 07777;
556 m_address_extension_mask = 00000;
557 break;
558 case 1: /* 15-bit extension */
559 m_extended_address_mask = 077777;
560 m_address_extension_mask = 070000;
561 break;
562 case 2: /* 16-bit extension */
563 m_extended_address_mask = 0177777;
564 m_address_extension_mask = 0170000;
565 break;
566 }
567
568 if (m_extend_support)
569 {
570 m_extern_iot[074] = iot_delegate(*this, FUNC(pdp1_device::lem_eem_iot));
571 }
572 m_extern_iot[054] = m_extern_iot[055] = m_extern_iot[056] = iot_delegate(*this, FUNC(pdp1_device::sbs_iot));
573 if (m_type_20_sbs)
574 {
575 m_extern_iot[050] = m_extern_iot[051] = m_extern_iot[052] = m_extern_iot[053]
576 = iot_delegate(*this, FUNC(pdp1_device::type_20_sbs_iot));
577 }
578
579 state_add( PDP1_PC, "PC", m_pc).formatstr("%06O");
580 state_add( PDP1_IR, "IR", m_ir).formatstr("%02O");
581 state_add( PDP1_MB, "MB", m_mb).formatstr("%06O");
582 state_add( PDP1_MA, "MA", m_ma).formatstr("%06O");
583 state_add( PDP1_AC, "AC", m_ac).formatstr("%06O");
584 state_add( PDP1_IO, "IO", m_io).formatstr("%06O");
585 state_add( PDP1_OV, "OV", m_ov).formatstr("%1X");
586 state_add( PDP1_PF, "FLAGS", m_pf).formatstr("%02O");
587 state_add( PDP1_PF1, "FLAG1", m_debugger_temp).callimport().callexport().formatstr("%1X");
588 state_add( PDP1_PF2, "FLAG2", m_debugger_temp).callimport().callexport().formatstr("%1X");
589 state_add( PDP1_PF3, "FLAG3", m_debugger_temp).callimport().callexport().formatstr("%1X");
590 state_add( PDP1_PF4, "FLAG4", m_debugger_temp).callimport().callexport().formatstr("%1X");
591 state_add( PDP1_PF5, "FLAG5", m_debugger_temp).callimport().callexport().formatstr("%1X");
592 state_add( PDP1_PF6, "FLAG6", m_debugger_temp).callimport().callexport().formatstr("%1X");
593 state_add( PDP1_TA, "TA", m_ta).formatstr("%06O");
594 state_add( PDP1_TW, "TW", m_tw).formatstr("%06O");
595 state_add( PDP1_SS, "SS", m_ss).formatstr("%02O");
596 state_add( PDP1_SS1, "SENSE1", m_debugger_temp).callimport().callexport().formatstr("%1X");
597 state_add( PDP1_SS2, "SENSE2", m_debugger_temp).callimport().callexport().formatstr("%1X");
598 state_add( PDP1_SS3, "SENSE3", m_debugger_temp).callimport().callexport().formatstr("%1X");
599 state_add( PDP1_SS4, "SENSE4", m_debugger_temp).callimport().callexport().formatstr("%1X");
600 state_add( PDP1_SS5, "SENSE5", m_debugger_temp).callimport().callexport().formatstr("%1X");
601 state_add( PDP1_SS6, "SENSE6", m_debugger_temp).callimport().callexport().formatstr("%1X");
602 state_add( PDP1_SNGL_STEP, "SNGLSTEP", m_sngl_step).mask(1).formatstr("%1X");
603 state_add( PDP1_SNGL_INST, "SNGLINST", m_sngl_inst).mask(1).formatstr("%1X");
604 state_add( PDP1_EXTEND_SW, "EXS", m_extend_sw).mask(1).formatstr("%1X");
605 state_add( PDP1_RUN, "RUN", m_run).mask(1).formatstr("%1X");
606 state_add( PDP1_CYC, "CYC", m_cycle).mask(1).formatstr("%1X");
607 state_add( PDP1_DEFER, "DF", m_defer).mask(1).formatstr("%1X");
608 state_add( PDP1_BRK_CTR, "BRKCTR", m_brk_ctr).mask(3).formatstr("%1X");
609 state_add( PDP1_RIM, "RIM", m_rim).mask(1).formatstr("%1X");
610 state_add( PDP1_SBM, "SBM", m_sbm).mask(1).formatstr("%1X");
611 state_add( PDP1_EXD, "EXD", m_exd).mask(1).formatstr("%1X");
612 state_add( PDP1_IOC, "IOC", m_ioc).mask(1).formatstr("%1X");
613 state_add( PDP1_IOH, "IOH", m_ioh).mask(1).formatstr("%1X");
614 state_add( PDP1_IOS, "IOS", m_ios).mask(1).formatstr("%1X");
615
616 state_add( STATE_GENPC, "GENPC", m_pc ).noshow();
617 state_add( STATE_GENPCBASE, "CURPC", m_pc ).noshow();
618 state_add( STATE_GENFLAGS, "GENFLAGS", m_pf ).formatstr("%13s").noshow();
619
620 set_icountptr(m_icount);
621
622 /* reset CPU flip-flops */
623 pulse_start_clear();
624 }
625
626
state_import(const device_state_entry & entry)627 void pdp1_device::state_import(const device_state_entry &entry)
628 {
629 switch (entry.index())
630 {
631 case PDP1_PF1:
632 WRITEFLAG(1, m_debugger_temp ? 1 : 0);
633 break;
634 case PDP1_PF2:
635 WRITEFLAG(2, m_debugger_temp ? 1 : 0);
636 break;
637 case PDP1_PF3:
638 WRITEFLAG(3, m_debugger_temp ? 1 : 0);
639 break;
640 case PDP1_PF4:
641 WRITEFLAG(4, m_debugger_temp ? 1 : 0);
642 break;
643 case PDP1_PF5:
644 WRITEFLAG(5, m_debugger_temp ? 1 : 0);
645 break;
646 case PDP1_PF6:
647 WRITEFLAG(6, m_debugger_temp ? 1 : 0);
648 break;
649 case PDP1_SS1:
650 WRITESENSE(1, m_debugger_temp ? 1 : 0);
651 break;
652 case PDP1_SS2:
653 WRITESENSE(2, m_debugger_temp ? 1 : 0);
654 break;
655 case PDP1_SS3:
656 WRITESENSE(3, m_debugger_temp ? 1 : 0);
657 break;
658 case PDP1_SS4:
659 WRITESENSE(4, m_debugger_temp ? 1 : 0);
660 break;
661 case PDP1_SS5:
662 WRITESENSE(5, m_debugger_temp ? 1 : 0);
663 break;
664 case PDP1_SS6:
665 WRITESENSE(6, m_debugger_temp ? 1 : 0);
666 break;
667 }
668 }
669
670
state_export(const device_state_entry & entry)671 void pdp1_device::state_export(const device_state_entry &entry)
672 {
673 switch (entry.index())
674 {
675 case PDP1_PF1:
676 m_debugger_temp = READFLAG(1);
677 break;
678 case PDP1_PF2:
679 m_debugger_temp = READFLAG(2);
680 break;
681 case PDP1_PF3:
682 m_debugger_temp = READFLAG(3);
683 break;
684 case PDP1_PF4:
685 m_debugger_temp = READFLAG(4);
686 break;
687 case PDP1_PF5:
688 m_debugger_temp = READFLAG(5);
689 break;
690 case PDP1_PF6:
691 m_debugger_temp = READFLAG(6);
692 break;
693 case PDP1_SS1:
694 m_debugger_temp = READSENSE(1);
695 break;
696 case PDP1_SS2:
697 m_debugger_temp = READSENSE(2);
698 break;
699 case PDP1_SS3:
700 m_debugger_temp = READSENSE(3);
701 break;
702 case PDP1_SS4:
703 m_debugger_temp = READSENSE(4);
704 break;
705 case PDP1_SS5:
706 m_debugger_temp = READSENSE(5);
707 break;
708 case PDP1_SS6:
709 m_debugger_temp = READSENSE(6);
710 break;
711 }
712 }
713
714
state_string_export(const device_state_entry & entry,std::string & str) const715 void pdp1_device::state_string_export(const device_state_entry &entry, std::string &str) const
716 {
717 switch (entry.index())
718 {
719 case STATE_GENFLAGS:
720 str = string_format("%c%c%c%c%c%c-%c%c%c%c%c%c",
721 (FLAGS & 040) ? '1' : '.',
722 (FLAGS & 020) ? '2' : '.',
723 (FLAGS & 010) ? '3' : '.',
724 (FLAGS & 004) ? '4' : '.',
725 (FLAGS & 002) ? '5' : '.',
726 (FLAGS & 001) ? '6' : '.',
727 (SENSE_SW & 040) ? '1' : '.',
728 (SENSE_SW & 020) ? '2' : '.',
729 (SENSE_SW & 010) ? '3' : '.',
730 (SENSE_SW & 004) ? '4' : '.',
731 (SENSE_SW & 002) ? '5' : '.',
732 (SENSE_SW & 001) ? '6' : '.');
733 break;
734 }
735 }
736
737
device_reset()738 void pdp1_device::device_reset()
739 {
740 // Nothing to do??
741 }
742
743 /*
744 flags:
745 * 1 for each instruction which supports indirect addressing (memory reference instructions,
746 except cal and jda, and with the addition of jmp and jsp)
747 * 2 for memory reference instructions
748 */
749 static const uint8_t instruction_kind[32] =
750 {
751 /* and ior xor xct cal/jda */
752 0, 3, 3, 3, 3, 0, 0, 2,
753 /* lac lio dac dap dip dio dzm */
754 3, 3, 3, 3, 3, 3, 3, 0,
755 /* add sub idx isp sad sas mus dis */
756 3, 3, 3, 3, 3, 3, 3, 3,
757 /* jmp jsp skp sft law iot opr */
758 1, 1, 0, 0, 0, 0, 0, 0
759 };
760
761
762 /* execute instructions on this CPU until icount expires */
execute_run()763 void pdp1_device::execute_run()
764 {
765 do
766 {
767 /* ioh should be cleared at the end of the instruction cycle, and ios at the
768 start of next instruction cycle, but who cares? */
769 if (m_ioh && m_ios)
770 {
771 m_ioh = 0;
772 }
773
774
775 if ((! m_run) && (! m_rim))
776 {
777 debugger_instruction_hook(PC);
778 m_icount = 0; /* if processor is stopped, just burn cycles */
779 }
780 else if (m_rim)
781 {
782 switch (m_rim_step)
783 {
784 case 0:
785 /* read first word as instruction */
786 MB = 0;
787 /* data will be transferred to IO register in response to RPB */
788 m_extern_iot[2](2, 1, MB, IO, AC);
789 m_rim_step = 1;
790 m_ios = 0;
791 break;
792
793 case 1:
794 if (! m_ios)
795 { /* transfer incomplete: wait some more */
796 m_icount = 0;
797 }
798 else
799 { /* data transfer complete */
800 m_ios = 0;
801
802 MB = IO;
803 IR = MB >> 13; /* basic opcode */
804 if (IR == JMP) /* jmp instruction ? */
805 {
806 PC = (MA & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
807 m_rim = 0; /* exit read-in mode */
808 m_run = 1;
809 m_rim_step = 0;
810 }
811 else if ((IR == DIO) || (IR == DAC)) /* dio or dac instruction ? */
812 { /* there is a discrepancy: the pdp1 handbook tells that only dio should be used,
813 but the lisp tape uses the dac instruction instead */
814 /* Yet maintenance manual p. 6-25 states clearly that the data is located
815 in IO and transferred to MB, so DAC is likely to be a mistake. */
816 m_rim_step = 2;
817 }
818 else
819 {
820 /* what the heck? */
821 if (LOG)
822 logerror("It seems this tape should not be operated in read-in mode\n");
823
824 m_rim = 0; /* exit read-in mode (right???) */
825 m_rim_step = 0;
826 }
827 }
828 break;
829
830 case 2:
831 /* read second word as data */
832 /* data will be transferred to IO register in response to RPB */
833 m_extern_iot[2](2, 1, MB, IO, AC);
834 m_rim_step = 3;
835 m_ios = 0;
836 break;
837
838 case 3:
839 if (! m_ios)
840 { /* transfer incomplete: wait some more */
841 m_icount = 0;
842 }
843 else
844 { /* data transfer complete */
845 m_ios = 0;
846
847 MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
848
849 MB = IO;
850 WRITE_PDP_18BIT(MA, MB);
851
852 m_rim_step = 0;
853 }
854 break;
855 }
856 }
857 else
858 {
859 /* yes, interrupt can occur in the midst of an instruction (impressing, huh?) */
860 /* Note that break cannot occur during a one-cycle jump that is deferred only once,
861 or another break cycle. Also, it cannot interrupt the long cycle 1 of automatic
862 multiply/divide. (maintenance manual 6-19) */
863 if (m_sbs_request && (! m_no_sequence_break) && (! m_brk_ctr))
864 { /* begin sequence break */
865 m_brk_ctr = 1;
866 }
867 if (m_brk_ctr)
868 { /* sequence break in progress */
869 switch (m_brk_ctr)
870 {
871 case 1:
872 if (m_cycle)
873 DECREMENT_PC; /* set PC to point to aborted instruction, so that it can be re-run */
874
875 m_b4 |= (1 << m_sbs_level); /* set "interrupt in progress" flag */
876 m_b2 &= ~(1 << m_sbs_level); /* clear interrupt request */
877 field_interrupt();
878 MA = m_sbs_level << 2; /* always 0 with standard sequence break system */
879 MB = AC; /* save AC to MB */
880 AC = (OV << 17) | (EXD << 16) | PC; /* save OV/EXD/PC to AC */
881 EXD = OV = 0; /* according to maintenance manual p. 8-17 and ?-?? */
882 m_cycle = m_defer = m_exc = 0; /* mere guess */
883 WRITE_PDP_18BIT(MA, MB); /* save former AC to memory */
884 INCREMENT_MA;
885 m_icount -= 5;
886 m_brk_ctr++;
887 break;
888
889 case 2:
890 WRITE_PDP_18BIT(MA, MB = AC); /* save former OV/EXD/PC to memory */
891 INCREMENT_MA;
892 m_icount -= 5;
893 m_brk_ctr++;
894 break;
895
896 case 3:
897 WRITE_PDP_18BIT(MA, MB = IO); /* save IO to memory */
898 INCREMENT_MA;
899 PC = MA;
900 m_icount -= 5;
901 m_brk_ctr = 0;
902 break;
903 }
904 }
905 else
906 {
907 if (m_no_sequence_break)
908 m_no_sequence_break = 0;
909
910 if (! m_cycle)
911 { /* no instruction in progress: time to fetch a new instruction, I guess */
912 debugger_instruction_hook(PC);
913 MB = READ_PDP_18BIT(MA = PC);
914 INCREMENT_PC;
915 IR = MB >> 13; /* basic opcode */
916
917 if ((instruction_kind[IR] & 1) && (MB & 010000))
918 {
919 m_defer = 1;
920 m_cycle = 1; /* instruction shall be executed later */
921
922 /* detect deferred one-cycle jumps */
923 if ((IR == JMP) || (IR == JSP))
924 {
925 m_no_sequence_break = 1;
926 /* detect JMP *(4*n+1) to memory module 0 if in sequence break mode */
927 if (((MB & 0777703) == 0610001) && (m_sbm) && ! (MA & 0170000))
928 {
929 int level = (MB & 0000074) >> 2;
930
931 if ((m_type_20_sbs) || (level == 0))
932 {
933 m_b4 &= ~(1 << level);
934 field_interrupt();
935 if (m_extend_support)
936 EXD = 1; /* according to maintenance manual p. 6-33 */
937 m_sbs_restore = 1;
938 }
939 }
940 }
941 }
942 else if (instruction_kind[IR] & 2)
943 m_cycle = 1; /* instruction shall be executed later */
944 else
945 execute_instruction(); /* execute instruction at once */
946
947 m_icount -= 5;
948 }
949 else if (m_defer)
950 { /* defer cycle : handle indirect addressing */
951 MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
952
953 MB = READ_PDP_18BIT(MA);
954
955 /* determinate new value of m_defer */
956 if (EXD)
957 {
958 m_defer = 0;
959 m_exc = 1;
960 }
961 else
962 m_defer = (MB & 010000) ? 1 : 0;
963
964 /* execute JMP and JSP immediately if applicable */
965 if ((! m_defer) && (! (instruction_kind[IR] & 2)))
966 {
967 execute_instruction(); /* execute instruction at once */
968 /*m_cycle = 0;*/
969 m_exc = 0;
970
971 if (m_sbs_restore)
972 { /* interrupt return: according to maintenance manual p. 6-33 */
973 if (m_extend_support)
974 EXD = (MB >> 16) & 1;
975 OV = (MB >> 17) & 1;
976 m_sbs_restore = 0;
977 }
978 }
979
980 m_icount -= 5;
981 }
982 else
983 { /* memory reference instruction in cycle 1 */
984 if (m_exc)
985 {
986 MA = MB & EXTENDED_ADDRESS_MASK;
987 m_exc = 0;
988 }
989 else
990 MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
991
992 execute_instruction(); /* execute instruction */
993
994 m_icount -= 5;
995 }
996
997 if ((m_sngl_inst) && (! m_cycle))
998 m_run = 0;
999 }
1000 if (m_sngl_step)
1001 m_run = 0;
1002 }
1003 }
1004 while (m_icount > 0);
1005 }
1006
1007
1008 /* execute one instruction */
execute_instruction()1009 void pdp1_device::execute_instruction()
1010 {
1011 switch (IR)
1012 {
1013 case AND: /* Logical And */
1014 AC &= (MB = READ_PDP_18BIT(MA));
1015 break;
1016 case IOR: /* Inclusive Or */
1017 AC |= (MB = READ_PDP_18BIT(MA));
1018 break;
1019 case XOR: /* Exclusive Or */
1020 AC ^= (MB = READ_PDP_18BIT(MA));
1021 break;
1022 case XCT: /* Execute */
1023 MB = READ_PDP_18BIT(MA);
1024 IR = MB >> 13; /* basic opcode */
1025 if ((instruction_kind[IR] & 1) && (MB & 010000))
1026 {
1027 m_defer = 1;
1028 /*m_cycle = 1;*/ /* instruction shall be executed later */
1029 goto no_fetch; /* fall through to next instruction */
1030 }
1031 else if (instruction_kind[IR] & 2)
1032 {
1033 /*m_cycle = 1;*/ /* instruction shall be executed later */
1034 goto no_fetch; /* fall through to next instruction */
1035 }
1036 else
1037 execute_instruction(); /* execute instruction at once */
1038 break;
1039 case CALJDA: /* Call subroutine and Jump and Deposit Accumulator instructions */
1040 if (MB & 010000)
1041 /* JDA */
1042 MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
1043 else
1044 /* CAL: equivalent to JDA 100 */
1045 /* Note that I cannot tell for sure what happens to extension bits, but I did notice
1046 that setting the extension bits to 0 would make cal basically useless, since
1047 there would be no simple way the call routine could return to the callee
1048 if it were located in another module with extend mode off (i.e. exd == 0). */
1049 MA = (PC & ADDRESS_EXTENSION_MASK) | 0100;
1050
1051 WRITE_PDP_18BIT(MA, (MB = AC));
1052 INCREMENT_MA;
1053 AC = (OV << 17) | (EXD << 16) | PC;
1054 PC = MA;
1055 break;
1056 case LAC: /* Load Accumulator */
1057 AC = (MB = READ_PDP_18BIT(MA));
1058 break;
1059 case LIO: /* Load i/o register */
1060 IO = (MB = READ_PDP_18BIT(MA));
1061 break;
1062 case DAC: /* Deposit Accumulator */
1063 WRITE_PDP_18BIT(MA, (MB = AC));
1064 break;
1065 case DAP: /* Deposit Address Part */
1066 WRITE_PDP_18BIT(MA, (MB = ((READ_PDP_18BIT(MA) & 0770000) | (AC & 0007777))));
1067 break;
1068 case DIP: /* Deposit Instruction Part */
1069 WRITE_PDP_18BIT(MA, (MB = ((READ_PDP_18BIT(MA) & 0007777) | (AC & 0770000))));
1070 break;
1071 case DIO: /* Deposit I/O Register */
1072 WRITE_PDP_18BIT(MA, (MB = IO));
1073 break;
1074 case DZM: /* Deposit Zero in Memory */
1075 WRITE_PDP_18BIT(MA, (MB = 0));
1076 break;
1077 case ADD: /* Add */
1078 {
1079 /* overflow is set if the 2 operands have the same sign and the final result has another */
1080 int ov2; /* 1 if the operands have the same sign*/
1081
1082 MB = READ_PDP_18BIT(MA);
1083
1084 ov2 = ((AC & 0400000) == (MB & 0400000));
1085
1086 AC = AC + MB;
1087 AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
1088
1089 /* I think we need to check for overflow before checking for -0,
1090 because the sum -0+-0 = -0 = +0 would generate an overflow
1091 otherwise. */
1092 if (ov2 && ((AC & 0400000) != (MB & 0400000)))
1093 OV = 1;
1094
1095 if (AC == 0777777) /* check for -0 */
1096 AC = 0;
1097
1098 break;
1099 }
1100 case SUB: /* Subtract */
1101 { /* maintenance manual 7-14 seems to imply that substract does not test for -0.
1102 The sim 2.3 source says so explicitely, though they do not give a reference.
1103 It sounds a bit weird, but the reason is probably that doing so would
1104 require additional logic that does not exist. */
1105 /* overflow is set if the 2 operands have the same sign and the final result has another */
1106 int ov2; /* 1 if the operands have the same sign*/
1107
1108 AC ^= 0777777;
1109
1110 MB = READ_PDP_18BIT(MA);
1111
1112 ov2 = ((AC & 0400000) == (MB & 0400000));
1113
1114 AC = AC + MB;
1115 AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
1116
1117 if (ov2 && ((AC & 0400000) != (MB & 0400000)))
1118 OV = 1;
1119
1120 AC ^= 0777777;
1121
1122 break;
1123 }
1124 case IDX: /* Index */
1125 AC = READ_PDP_18BIT(MA) + 1;
1126
1127 #if 0
1128 AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
1129 if (AC == 0777777) /* check for -0 */
1130 AC = 0;
1131 #else
1132 if (AC >= 0777777)
1133 AC = (AC + 1) & 0777777;
1134 #endif
1135
1136 WRITE_PDP_18BIT(MA, (MB = AC));
1137 break;
1138 case ISP: /* Index and Skip if Positive */
1139 AC = READ_PDP_18BIT(MA) + 1;
1140
1141 #if 0
1142 AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
1143 if (AC == 0777777) /* check for -0 */
1144 AC = 0;
1145 #else
1146 if (AC >= 0777777)
1147 AC = (AC + 1) & 0777777;
1148 #endif
1149
1150 WRITE_PDP_18BIT(MA, (MB = AC));
1151 if ((AC & 0400000) == 0)
1152 INCREMENT_PC;
1153 break;
1154 case SAD: /* Skip if Accumulator and Y differ */
1155 if (AC != (MB = READ_PDP_18BIT(MA)))
1156 INCREMENT_PC;
1157 break;
1158 case SAS: /* Skip if Accumulator and Y are the same */
1159 if (AC == (MB = READ_PDP_18BIT(MA)))
1160 INCREMENT_PC;
1161 break;
1162 case MUS_MUL: /* Multiply Step or Multiply */
1163 if (m_hw_mul_div)
1164 { /* MUL */
1165 int scr;
1166 int smb, srm;
1167 double etime = 4.; /* approximative */
1168
1169 IO = MB = AC;
1170 MB = READ_PDP_18BIT(MA);
1171 scr = 0;
1172 if (MB & 0400000)
1173 {
1174 smb = 1;
1175 MB = MB ^ 0777777;
1176 }
1177 else
1178 smb = 0;
1179 if (IO & 0400000)
1180 {
1181 srm = 1;
1182 IO = IO ^ 0777777;
1183 }
1184 else
1185 srm = 0;
1186 AC = 0;
1187 scr++;
1188 while (scr < 022)
1189 {
1190 if (IO & 1)
1191 {
1192 /*assert(! (AC & 0400000));*/
1193 AC = AC + MB;
1194 /* we can save carry around since both numbers are positive */
1195 /*AC = (AC + (AC >> 18)) & 0777777;*/
1196 etime += .65; /* approximative */
1197 }
1198 IO = (IO >> 1) | ((AC & 1) << 17);
1199 AC = AC >> 1;
1200 scr++;
1201 }
1202 if (smb ^ srm)
1203 {
1204 AC = AC ^ 0777777;
1205 IO = IO ^ 0777777;
1206 }
1207
1208 m_icount -= etime+.5; /* round to closest */
1209 }
1210 else
1211 { /* MUS */
1212 /* should we check for -0??? (Maintenance manual 7-14 seems to imply we should not:
1213 as a matter of fact, since the MUS instruction is supposed to have positive operands,
1214 there is no need to check for -0, therefore such a simplification does not sound
1215 absurd.) */
1216 if ((IO & 1) == 1)
1217 {
1218 AC = AC + (MB = READ_PDP_18BIT(MA));
1219 AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
1220 }
1221 IO = (IO >> 1 | AC << 17) & 0777777;
1222 AC >>= 1;
1223 }
1224 break;
1225 case DIS_DIV: /* Divide Step or Divide */
1226 if (m_hw_mul_div)
1227 { /* DIV */
1228 /* As a side note, the order of -0 detection and overflow checking does not matter,
1229 because the sum of two positive number cannot give 0777777 (since positive
1230 numbers are 0377777 at most, their sum is 0777776 at most).
1231 Additionally, we cannot have carry set and a result equal to 0777777 (since numbers
1232 are 0777777 at most, their sum is 01777776 at most): this is nice, because it makes
1233 the sequence:
1234 AC = (AC + (AC >> 18)) & 0777777; // propagate carry around
1235 if (AC == 0777777) // check for -0
1236 AC = 0;
1237 equivalent to:
1238 if (AC >= 0777777)
1239 AC = (AC + 1) & 0777777;
1240 which is a bit more efficient. */
1241 int acl;
1242 int scr;
1243 int smb, srm;
1244 double etime = 0; /* approximative */
1245
1246 MB = READ_PDP_18BIT(MA);
1247 scr = 0;
1248 if (MB & 0400000)
1249 {
1250 smb = 1;
1251 }
1252 else
1253 {
1254 smb = 0;
1255 MB = MB ^ 0777777;
1256 }
1257 if (AC & 0400000)
1258 {
1259 srm = 1;
1260 AC = AC ^ 0777777;
1261 IO = IO ^ 0777777;
1262 }
1263 else
1264 srm = 0;
1265 while (1)
1266 {
1267 AC = (AC + MB);
1268 #if 1
1269 AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
1270 if (AC == 0777777) /* check for -0 */
1271 AC = 0;
1272 #else
1273 if (AC >= 0777777)
1274 AC = (AC + 1) & 0777777;
1275 #endif
1276 if (MB & 0400000)
1277 MB = MB ^ 0777777;
1278
1279 if (((scr == 0) && ! (AC & 0400000))
1280 || (scr == 022))
1281 break;
1282
1283 scr++;
1284
1285 if (! (AC & 0400000))
1286 MB = MB ^ 0777777;
1287
1288 acl = AC >> 17;
1289 AC = (AC << 1 | IO >> 17) & 0777777;
1290 IO = ((IO << 1 | acl) & 0777777) ^ 1;
1291 if (acl)
1292 {
1293 AC++;
1294 AC = (AC + (AC >> 18)) & 0777777;
1295 etime += .6; /* approximative */
1296 }
1297 }
1298
1299 AC = (AC + MB);
1300 #if 1
1301 AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
1302 if (AC == 0777777) /* check for -0 */
1303 AC = 0;
1304 #else
1305 if (AC >= 0777777)
1306 AC = (AC + 1) & 0777777;
1307 #endif
1308
1309 if (scr)
1310 {
1311 INCREMENT_PC;
1312 AC = AC >> 1;
1313 }
1314
1315 if (srm && (AC != 0))
1316 AC = AC ^ 0777777;
1317
1318 if (((! scr) && (srm))
1319 || (scr && (srm ^ smb) && (IO != 0)))
1320 IO = IO ^ 0777777;
1321
1322 if (scr)
1323 {
1324 MB = AC;
1325 AC = IO;
1326 IO = MB;
1327 }
1328 if (scr)
1329 etime += 20; /* approximative */
1330 else
1331 etime += 2; /* approximative */
1332
1333 m_icount -= etime+.5; /* round to closest */
1334 }
1335 else
1336 { /* DIS */
1337 int acl;
1338
1339 acl = AC >> 17;
1340 AC = (AC << 1 | IO >> 17) & 0777777;
1341 IO = ((IO << 1 | acl) & 0777777) ^ 1;
1342 MB = READ_PDP_18BIT(MA);
1343 if (IO & 1)
1344 AC += (MB ^ 0777777);
1345 else
1346 /* Note that if AC+MB = 0777777, we are in trouble. I don't
1347 know how a real PDP-1 behaves in this case. */
1348 AC += MB + 1;
1349 AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
1350 if (AC == 0777777) /* check for -0 */
1351 AC = 0;
1352 }
1353 break;
1354 case JMP: /* Jump */
1355 if (m_exc)
1356 PC = MB & EXTENDED_ADDRESS_MASK;
1357 else
1358 PC = (MA & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
1359 break;
1360 case JSP: /* Jump and Save Program Counter */
1361 AC = (OV << 17) | (EXD << 16) | PC;
1362 if (m_exc)
1363 PC = MB & EXTENDED_ADDRESS_MASK;
1364 else
1365 PC = (MA & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
1366 break;
1367 case SKP: /* Skip Instruction Group */
1368 {
1369 int cond = ((MB & 0100) && (AC == 0)) /* ZERO Accumulator */
1370 || ((MB & 0200) && (AC >> 17 == 0)) /* Plus Accumulator */
1371 || ((MB & 0400) && (AC >> 17 == 1)) /* Minus Accumulator */
1372 || ((MB & 01000) && (OV == 0)) /* ZERO Overflow */
1373 || ((MB & 02000) && (IO >> 17 == 0)) /* Plus I/O Register */
1374 || (((MB & 7) != 0) && (((MB & 7) == 7) ? ! FLAGS : ! READFLAG(MB & 7))) /* ZERO Flag (deleted by mistake in PDP-1 handbook) */
1375 || (((MB & 070) != 0) && (((MB & 070) == 070) ? ! SENSE_SW : ! READSENSE((MB & 070) >> 3))); /* ZERO Switch */
1376
1377 if (! (MB & 010000))
1378 {
1379 if (cond)
1380 INCREMENT_PC;
1381 }
1382 else
1383 {
1384 if (!cond)
1385 INCREMENT_PC;
1386 }
1387 if (MB & 01000)
1388 OV = 0;
1389 break;
1390 }
1391 case SFT: /* Shift Instruction Group */
1392 {
1393 /* Bit 5 specifies direction of shift, Bit 6 specifies the character of the shift
1394 (arithmetic or logical), Bits 7 and 8 enable the registers (01 = AC, 10 = IO,
1395 and 11 = both) and Bits 9 through 17 specify the number of steps. */
1396 int nshift = 0;
1397 int mask = MB & 0777;
1398
1399 while (mask != 0)
1400 {
1401 nshift += mask & 1;
1402 mask >>= 1;
1403 }
1404 switch ((MB >> 9) & 017)
1405 {
1406 int i;
1407
1408 case 1: /* ral rotate accumulator left */
1409 for (i = 0; i < nshift; i++)
1410 AC = (AC << 1 | AC >> 17) & 0777777;
1411 break;
1412 case 2: /* ril rotate i/o register left */
1413 for (i = 0; i < nshift; i++)
1414 IO = (IO << 1 | IO >> 17) & 0777777;
1415 break;
1416 case 3: /* rcl rotate AC and IO left */
1417 for (i = 0; i < nshift; i++)
1418 {
1419 int tmp = AC;
1420
1421 AC = (AC << 1 | IO >> 17) & 0777777;
1422 IO = (IO << 1 | tmp >> 17) & 0777777;
1423 }
1424 break;
1425 case 5: /* sal shift accumulator left */
1426 for (i = 0; i < nshift; i++)
1427 AC = ((AC << 1 | AC >> 17) & 0377777) + (AC & 0400000);
1428 break;
1429 case 6: /* sil shift i/o register left */
1430 for (i = 0; i < nshift; i++)
1431 IO = ((IO << 1 | IO >> 17) & 0377777) + (IO & 0400000);
1432 break;
1433 case 7: /* scl shift AC and IO left */
1434 for (i = 0; i < nshift; i++)
1435 {
1436 int tmp = AC;
1437
1438 AC = ((AC << 1 | IO >> 17) & 0377777) + (AC & 0400000); /* shouldn't that be IO?, no it is the sign! */
1439 IO = (IO << 1 | tmp >> 17) & 0777777;
1440 }
1441 break;
1442 case 9: /* rar rotate accumulator right */
1443 for (i = 0; i < nshift; i++)
1444 AC = (AC >> 1 | AC << 17) & 0777777;
1445 break;
1446 case 10: /* rir rotate i/o register right */
1447 for (i = 0; i < nshift; i++)
1448 IO = (IO >> 1 | IO << 17) & 0777777;
1449 break;
1450 case 11: /* rcr rotate AC and IO right */
1451 for (i = 0; i < nshift; i++)
1452 {
1453 int tmp = AC;
1454
1455 AC = (AC >> 1 | IO << 17) & 0777777;
1456 IO = (IO >> 1 | tmp << 17) & 0777777;
1457 }
1458 break;
1459 case 13: /* sar shift accumulator right */
1460 for (i = 0; i < nshift; i++)
1461 AC = (AC >> 1) + (AC & 0400000);
1462 break;
1463 case 14: /* sir shift i/o register right */
1464 for (i = 0; i < nshift; i++)
1465 IO = (IO >> 1) + (IO & 0400000);
1466 break;
1467 case 15: /* scr shift AC and IO right */
1468 for (i = 0; i < nshift; i++)
1469 {
1470 int tmp = AC;
1471
1472 AC = (AC >> 1) + (AC & 0400000); /* shouldn't that be IO, no it is the sign */
1473 IO = (IO >> 1 | tmp << 17) & 0777777;
1474 }
1475 break;
1476 default:
1477 if (LOG)
1478 logerror("Undefined shift: 0%06o at 0%06o\n", MB, PREVIOUS_PC);
1479 break;
1480 }
1481 break;
1482 }
1483 case LAW: /* Load Accumulator with N */
1484 AC = MB & 07777;
1485 if (MB & 010000)
1486 AC ^= 0777777;
1487 break;
1488 case IOT: /* In-Out Transfer Instruction Group */
1489 /*
1490 The variations within this group of instructions perform all the in-out control
1491 and information transfer functions. If Bit 5 (normally the Indirect Address bit)
1492 is a ONE, the computer will enter a special waiting state until the completion pulse
1493 from the activated device has returned. When this device delivers its completion,
1494 the computer will resume operation of the instruction sequence.
1495
1496 The computer may be interrupted from the special waiting state to serve a sequence
1497 break request or a high speed channel request.
1498
1499 Most in-out operations require a known minimum time before completion. This time
1500 may be utilized for programming. The appropriate In-Out Transfer can be given with
1501 no in-out wait (Bit 5 a ZERO and Bit 6 a ONE). The instruction sequence then
1502 continues. This sequence must include an iot instruction 730000 which performs
1503 nothing but the in-out wait. The computer will then enter the special waiting state
1504 until the device returns the in-out restart pulse. If the device has already
1505 returned the completion pulse before the instruction 730000, the computer will
1506 proceed immediately.
1507
1508 Bit 6 determines whether a completion pulse will or will not be received from
1509 the in-out device. When it is different than Bit 5, a completion pulse will be
1510 received. When it is the same as Bit 5, a completion pulse will not be received.
1511
1512 In addition to the control function of Bits 5 and 6, Bits 7 through 11 are also
1513 used as control bits serving to extend greatly the power of the iot instructions.
1514 For example, Bits 12 through 17, which are used to designate a class of input or
1515 output devices such as typewriters, may be further defined by Bits 7 through 11
1516 as referring to Typewriter 1, 2, 3, etc. In several of the optional in-out devices,
1517 in particular the magnetic tape, Bits 7 through 11 specify particular functions
1518 such as forward, backward etc. If a large number of specialized devices are to
1519 be attached, these bits may be used to further the in-out transfer instruction
1520 to perform totally distinct functions.
1521
1522 Note that ioc is supposed to be set at the beggining of the memory cycle after
1523 ioh is cleared.
1524 However, we cannot set ioc at the beggining of every memory cycle as we
1525 did before, because it breaks in the following case:
1526 a) IOT instruction enables IO wait
1527 b) sequence break in the middle of IO-halt
1528 c) ioh is cleared in middle of sequence break routine
1529 d) re-execute IOT instruction. Unfortunately, ioc has been cleared, therefore
1530 we perform an IOT command pulse and IO wait again, which is completely WRONG.
1531 Therefore ioc is cleared only after a IOT with wait is executed.
1532 */
1533 if (MB & 010000)
1534 { /* IOT with IO wait */
1535 if (m_ioc)
1536 { /* the iot command line is pulsed only if ioc is asserted */
1537 m_extern_iot[MB & 0000077](MB & 0000077, (MB & 0004000) == 0, MB, IO, AC);
1538
1539 m_ioh = 1; /* enable io wait */
1540
1541 m_ioc = 0; /* actually happens at the start of next memory cycle */
1542
1543 /* test ios now in case the IOT callback has sent a completion pulse immediately */
1544 if (m_ioh && m_ios)
1545 {
1546 /* ioh should be cleared at the end of the instruction cycle, and ios at the
1547 start of next instruction cycle, but who cares? */
1548 m_ioh = 0;
1549 //m_ios = 0;
1550 }
1551 }
1552
1553 if (m_ioh)
1554 DECREMENT_PC;
1555 else
1556 m_ioc = 1; /* actually happens at the start of next memory cycle */
1557 }
1558 else
1559 { /* IOT with no IO wait */
1560 m_extern_iot[MB & 0000077](MB & 0000077, (MB & 0004000) != 0, MB, IO, AC);
1561 }
1562 break;
1563 case OPR: /* Operate Instruction Group */
1564 {
1565 int nflag;
1566
1567 if (MB & 00200) /* clear AC */
1568 AC = 0;
1569 if (MB & 04000) /* clear I/O register */
1570 IO = 0;
1571 if (MB & 02000) /* load Accumulator from Test Word */
1572 AC |= m_tw;
1573 if (MB & 00100) /* load Accumulator with Program Counter */
1574 AC |= (OV << 17) | (EXD << 16) | PC;
1575 nflag = MB & 7;
1576 if (nflag)
1577 {
1578 if (nflag == 7)
1579 FLAGS = (MB & 010) ? 077 : 000;
1580 else
1581 WRITEFLAG(nflag, (MB & 010) ? 1 : 0);
1582 }
1583 if (MB & 01000) /* Complement AC */
1584 AC ^= 0777777;
1585 if (MB & 00400) /* Halt */
1586 {
1587 if (LOG_EXTRA)
1588 logerror("PDP1 Program executed HALT: at 0%06o\n", PREVIOUS_PC);
1589
1590 m_run = 0;
1591 }
1592 break;
1593 }
1594 default:
1595 if (LOG)
1596 logerror("Illegal instruction: 0%06o at 0%06o\n", MB, PREVIOUS_PC);
1597
1598 /* let us stop the CPU, like a real pdp-1 */
1599 m_run = 0;
1600
1601 break;
1602 }
1603 m_cycle = 0;
1604 no_fetch:
1605 ;
1606 }
1607
1608
1609 /*
1610 Handle unimplemented IOT
1611 */
null_iot(int op2,int nac,int mb,int & io,int ac)1612 void pdp1_device::null_iot(int op2, int nac, int mb, int &io, int ac)
1613 {
1614 /* Note that the dummy IOT 0 is used to wait for the completion pulse
1615 generated by the a pending IOT (IOT with completion pulse but no IO wait) */
1616 if (LOG_IOT_EXTRA)
1617 {
1618 if (op2 == 000)
1619 logerror("IOT sync instruction: mb=0%06o, pc=0%06o\n", (unsigned) mb, (unsigned) m_pc);
1620 }
1621 if (LOG)
1622 {
1623 if (op2 != 000)
1624 logerror("Not supported IOT command (no external IOT function given) 0%06o at 0%06o\n", mb, m_pc);
1625 }
1626 }
1627
1628
1629 /*
1630 Memory expansion control (type 15)
1631
1632 IOT 74: LEM/EEM
1633 */
lem_eem_iot(int op2,int nac,int mb,int & io,int ac)1634 void pdp1_device::lem_eem_iot(int op2, int nac, int mb, int &io, int ac)
1635 {
1636 if (! m_extend_support) /* extend mode supported? */
1637 {
1638 if (LOG)
1639 logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
1640 return;
1641 }
1642 if (LOG_EXTRA)
1643 {
1644 logerror("EEM/LEM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
1645 }
1646 EXD = (mb & 0004000) ? 1 : 0;
1647 }
1648
1649
1650 /*
1651 Standard sequence break system
1652
1653 IOT 54: lsm
1654 IOT 55: esm
1655 IOT 56: cbs
1656 */
sbs_iot(int op2,int nac,int mb,int & io,int ac)1657 void pdp1_device::sbs_iot(int op2, int nac, int mb, int &io, int ac)
1658 {
1659 switch (op2)
1660 {
1661 case 054: /* LSM */
1662 if (LOG_EXTRA)
1663 logerror("LSM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
1664
1665 m_sbm = 0;
1666 field_interrupt();
1667 break;
1668 case 055: /* ESM */
1669 if (LOG_EXTRA)
1670 logerror("ESM instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
1671
1672 m_sbm = 1;
1673 field_interrupt();
1674 break;
1675 case 056: /* CBS */
1676 if (LOG_EXTRA)
1677 logerror("CBS instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
1678
1679 /*m_b3 = 0;*/
1680 m_b4 = 0;
1681 field_interrupt();
1682 break;
1683 default:
1684 if (LOG)
1685 logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
1686
1687 break;
1688 }
1689 }
1690
1691
1692 /*
1693 type 20 sequence break system
1694
1695 IOT 50: dsc
1696 IOT 51: asc
1697 IOT 52: isb
1698 IOT 53: cac
1699 */
type_20_sbs_iot(int op2,int nac,int mb,int & io,int ac)1700 void pdp1_device::type_20_sbs_iot(int op2, int nac, int mb, int &io, int ac)
1701 {
1702 int channel, mask;
1703 if (! m_type_20_sbs) /* type 20 sequence break system supported? */
1704 {
1705 if (LOG)
1706 logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
1707 return;
1708 }
1709 channel = (mb >> 6) & 017;
1710 mask = 1 << channel;
1711 switch (op2)
1712 {
1713 case 050: /* DSC */
1714 if (LOG_EXTRA)
1715 logerror("DSC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
1716
1717 m_b1 &= ~mask;
1718 field_interrupt();
1719 break;
1720 case 051: /* ASC */
1721 if (LOG_EXTRA)
1722 logerror("ASC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
1723
1724 m_b1 |= mask;
1725 field_interrupt();
1726 break;
1727 case 052: /* ISB */
1728 if (LOG_EXTRA)
1729 logerror("ISB instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
1730
1731 m_b2 |= mask;
1732 field_interrupt();
1733 break;
1734 case 053: /* CAC */
1735 if (LOG_EXTRA)
1736 logerror("CAC instruction: mb=0%06o, pc=0%06o\n", mb, m_pc);
1737
1738 m_b1 = 0;
1739 field_interrupt();
1740 break;
1741 default:
1742 if (LOG)
1743 logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
1744
1745 break;
1746 }
1747
1748 }
1749
1750
1751 /*
1752 Simulate a pulse on start/clear line:
1753 reset most registers and flip-flops, and initialize a few emulator state
1754 variables.
1755 */
pulse_start_clear()1756 void pdp1_device::pulse_start_clear()
1757 {
1758 /* processor registers */
1759 PC = 0; /* according to maintenance manual p. 6-17 */
1760 IR = 0; /* according to maintenance manual p. 6-13 */
1761 /*MB = 0;*/ /* ??? */
1762 /*MA = 0;*/ /* ??? */
1763 /*AC = 0;*/ /* ??? */
1764 /*IO = 0;*/ /* ??? */
1765 /*PF = 0;*/ /* ??? */
1766
1767 /* processor state flip-flops */
1768 m_run = 0; /* ??? */
1769 m_cycle = 0; /* mere guess */
1770 m_defer = 0; /* mere guess */
1771 m_brk_ctr = 0; /* mere guess */
1772 m_ov = 0; /* according to maintenance manual p. 7-18 */
1773 m_rim = 0; /* ??? */
1774 m_sbm = 0; /* ??? */
1775 EXD = 0; /* according to maintenance manual p. 8-16 */
1776 m_exc = 0; /* according to maintenance manual p. 8-16 */
1777 m_ioc = 1; /* according to maintenance manual p. 6-10 */
1778 m_ioh = 0; /* according to maintenance manual p. 6-10 */
1779 m_ios = 0; /* according to maintenance manual p. 6-10 */
1780
1781 m_b1 = m_type_20_sbs ? 0 : 1; /* mere guess */
1782 m_b2 = 0; /* mere guess */
1783 m_b4 = 0; /* mere guess */
1784
1785
1786 m_rim_step = 0;
1787 m_sbs_restore = 0; /* mere guess */
1788 m_no_sequence_break = 0; /* mere guess */
1789
1790 field_interrupt();
1791
1792 /* now, we kindly ask IO devices to reset, too */
1793 if (!m_io_sc_callback.isnull())
1794 m_io_sc_callback();
1795 }
1796