1
0
mirror of https://github.com/livingcomputermuseum/UniBone.git synced 2026-03-09 20:18:37 +00:00

Test "MultiArb": parallel INTR and DMA of DL11,RL11,RK11.

Also MSCP IOX.
This commit is contained in:
Joerg Hoppe
2019-09-02 15:46:54 +02:00
parent cc42d60409
commit 92714c1ebe
78 changed files with 1325 additions and 6041 deletions

View File

@@ -75,6 +75,16 @@ unibusadapter_c *unibusadapter; // another Singleton
bool unibusadapter_debug_flag = 0;
// encode signal bit for PRU from BR/NPR level.
// index is one of PRIORITY_LEVEL_INDEX_*
static uint8_t priority_level_idx_to_arbitration_bit[PRIORITY_LEVEL_COUNT] = {
PRIORITY_ARBITRATION_BIT_B4,
PRIORITY_ARBITRATION_BIT_B5,
PRIORITY_ARBITRATION_BIT_B6,
PRIORITY_ARBITRATION_BIT_B7,
PRIORITY_ARBITRATION_BIT_NP };
unibusadapter_c::unibusadapter_c() :
device_c() {
unsigned i;
@@ -106,6 +116,10 @@ void unibusadapter_c::on_power_changed(void) {
}
void unibusadapter_c::on_init_changed(void) {
requests_init();
// clear all pending BR and NPR lines on PRU
mailbox->intr.priority_arbitration_bit = PRIORITY_ARBITRATION_BIT_MASK;
mailbox_execute(ARM2PRU_INTR_CANCEL);
}
// register_device ... "plug" the device into UNIBUs backplane
@@ -392,6 +406,7 @@ void unibusadapter_c::request_execute_active_on_PRU(unsigned level_index) {
// Must run under pthread_mutex_lock(&requests_mutex);
// DEBUG("request_execute_active_on_PRU(level_idx=%u)", level_index);
if (level_index == PRIORITY_LEVEL_INDEX_NPR) {
dma_request_c *dmareq = dynamic_cast<dma_request_c *>(prl->active);
assert(dmareq);
@@ -443,6 +458,7 @@ void unibusadapter_c::request_execute_active_on_PRU(unsigned level_index) {
// Not DMA? must be INTR
intr_request_c *intrreq = dynamic_cast<intr_request_c *>(prl->active);
assert(intrreq);
// Handle interrupt request to PRU. Setup mailbox:
mailbox->intr.level_index = intrreq->level_index;
mailbox->intr.vector[intrreq->level_index] = intrreq->vector;
@@ -452,25 +468,11 @@ void unibusadapter_c::request_execute_active_on_PRU(unsigned level_index) {
else
mailbox->intr.iopage_register_handle = 0; // none
mailbox->intr.iopage_register_value = intrreq->interrupt_register_value;
// decode index 0..3 = BR4..BR7 => PRU signal register bit
switch (intrreq->level_index) {
case PRIORITY_LEVEL_INDEX_BR4:
mailbox->intr.priority_arbitration_bit = PRIORITY_ARBITRATION_BIT_B4;
break;
case PRIORITY_LEVEL_INDEX_BR5:
mailbox->intr.priority_arbitration_bit = PRIORITY_ARBITRATION_BIT_B5;
break;
case PRIORITY_LEVEL_INDEX_BR6:
mailbox->intr.priority_arbitration_bit = PRIORITY_ARBITRATION_BIT_B6;
break;
case PRIORITY_LEVEL_INDEX_BR7:
mailbox->intr.priority_arbitration_bit = PRIORITY_ARBITRATION_BIT_B7;
break;
default:
ERROR("Request_INTR(): Illegal priority %u, aborting", intrreq->level_index);
return;
}
// decode index 0..3 = BR4..BR7 => PRU signal register bit
assert(intrreq->level_index <= PRIORITY_LEVEL_INDEX_BR7);
mailbox->intr.priority_arbitration_bit =
priority_level_idx_to_arbitration_bit[intrreq->level_index];
// start on PRU
// PRU have got arbitration for an INTR of different level in the mean time:
@@ -494,7 +496,7 @@ void unibusadapter_c::request_active_complete(unsigned level_index) {
// Must run under pthread_mutex_lock(&requests_mutex);
priority_request_level_c *prl = &request_levels[level_index];
if (!prl->active) // PRU compelted after INIT cleared the tables
if (!prl->active) // PRU completed after INIT cleared the tables
return;
// DEBUG("request_active_complete") ;
@@ -538,6 +540,11 @@ void unibusadapter_c::DMA(dma_request_c& dma_request, bool blocking, uint8_t uni
// setup device request
assert(wordcount > 0);
assert((unibus_addr + 2*wordcount) <= 2*UNIBUS_WORDCOUNT);
// ignore calls if INIT cndition
if (line_INIT) {
dma_request.complete = true;
return;
}
pthread_mutex_lock(&requests_mutex); // lock schedule table operations
@@ -602,13 +609,18 @@ void unibusadapter_c::INTR(intr_request_c& intr_request,
assert(intr_request.level_index <= 3);
assert((intr_request.vector & 3) == 0); // multiple of 2 words
// ignore calls if INIT cndition
if (line_INIT) {
intr_request.complete = true;
return;
}
priority_request_level_c *prl = &request_levels[intr_request.level_index];
pthread_mutex_lock(&requests_mutex); // lock schedule table operations
_DEBUG("INTR() req: dev %s, slot/level/vector= %d/%d/%03o",
intr_request.device->name.value.c_str(), (unsigned) intr_request.slot,
intr_request.level_index + 4, intr_request.vector);
// Is an INTR with same slot and level already executed on PRU
// or waiting in the schedule table?
// If yes: do not re-raise, will be completed at some time later.
@@ -702,6 +714,9 @@ void unibusadapter_c::cancel_INTR(intr_request_c& intr_request) {
pthread_mutex_lock(&requests_mutex); // lock schedule table operations
if (&intr_request == prl->active) {
// already on PRU
assert(level_index <= PRIORITY_LEVEL_INDEX_BR7);
mailbox->intr.priority_arbitration_bit =
priority_level_idx_to_arbitration_bit[level_index];
mailbox_execute(ARM2PRU_INTR_CANCEL);
request_active_complete(level_index);
@@ -785,9 +800,11 @@ void unibusadapter_c::worker_init_event() {
device->on_init_changed();
}
// Clear bus request queues
// Clear bus request queues,
pthread_mutex_lock(&requests_mutex);
requests_cancel_scheduled();
// reset all scheduled tables, also requests on PRU
requests_init();
pthread_mutex_unlock(&requests_mutex);
}
@@ -802,9 +819,11 @@ void unibusadapter_c::worker_power_event(bool power_down) {
device->on_power_changed();
}
// Clear bus request queues
// Clear bus request queues,
pthread_mutex_lock(&requests_mutex);
requests_cancel_scheduled();
// reset all scheduled tables, also requests on PRU
requests_init();
pthread_mutex_unlock(&requests_mutex);
}
@@ -813,16 +832,16 @@ void unibusadapter_c::worker_power_event(bool power_down) {
void unibusadapter_c::worker_deviceregister_event() {
unsigned device_handle;
unibusdevice_c *device;
device_handle = mailbox->events.deviceregister_device_handle;
device_handle = mailbox->events.deviceregister.device_handle;
assert(device_handle);
device = devices[device_handle];
unsigned evt_idx = mailbox->events.device_register_idx;
uint32_t evt_addr = mailbox->events.deviceregister_addr;
unsigned evt_idx = mailbox->events.deviceregister.register_idx;
uint32_t evt_addr = mailbox->events.deviceregister.addr;
// normally evt_data == device_reg->shared_register->value
// but shared value gets desorted if INIT in same event clears the registers before DATO
uint16_t evt_data = mailbox->events.deviceregister_data;
uint16_t evt_data = mailbox->events.deviceregister.data;
unibusdevice_register_t *device_reg = &(device->registers[evt_idx]);
uint8_t unibus_control = mailbox->events.deviceregister_unibus_control;
uint8_t unibus_control = mailbox->events.deviceregister.unibus_control;
/* call device event callback
@@ -889,8 +908,6 @@ void unibusadapter_c::worker_deviceregister_event() {
// Called for device DMA() chunk,
// or cpu_DATA_transfer()
void unibusadapter_c::worker_dma_chunk_complete_event(bool cpu_DATA_transfer) {
dbg_dma_event_count++;
if (cpu_DATA_transfer) {
// cpu_DATA_transfer() started independent of request_levels table,
// prl->active == NULL
@@ -963,6 +980,7 @@ void unibusadapter_c::worker_dma_chunk_complete_event(bool cpu_DATA_transfer) {
// check and execute DMA on other priority_slot
if (request_activate_lowest_slot(PRIORITY_LEVEL_INDEX_NPR))
request_execute_active_on_PRU(PRIORITY_LEVEL_INDEX_NPR);
}
}
}
@@ -1111,7 +1129,7 @@ void unibusadapter_c::worker(unsigned instance) {
if (!EVENT_IS_ACKED(*mailbox, dma)) {
any_event = true;
pthread_mutex_lock(&requests_mutex);
worker_dma_chunk_complete_event(mailbox->events.dma_cpu_transfer);
worker_dma_chunk_complete_event(mailbox->events.dma.cpu_transfer);
pthread_mutex_unlock(&requests_mutex);
// rpu may have set again event_dma again, if this is called before EVENT signal??
// call this only on singal, not on timeout!
@@ -1119,20 +1137,25 @@ void unibusadapter_c::worker(unsigned instance) {
// this may clear reraised PRU event flag!
EVENT_ACK(*mailbox, dma); // PRU may re-raise and change mailbox now
}
if (!EVENT_IS_ACKED(*mailbox, intr_master)) {
// Device INTR was transmitted. INTRs are granted unpredictable by Arbitrator
any_event = true;
// INTR of which level? the .active rquest of the"
pthread_mutex_lock(&requests_mutex);
worker_intr_complete_event(mailbox->events.intr_level_index);
pthread_mutex_unlock(&requests_mutex);
EVENT_ACK(*mailbox, intr_master); // PRU may re-raise and change mailbox now
// 4 events for each BG4,5,6,7
for (unsigned level_index = 0; level_index < 4; level_index++) {
if (!EVENT_IS_ACKED(*mailbox, intr_master[level_index])) {
// Device INTR was transmitted. INTRs are granted unpredictable by Arbitrator
any_event = true;
// INTR of which level? the .active rquest of the"
pthread_mutex_lock(&requests_mutex);
worker_intr_complete_event(level_index);
pthread_mutex_unlock(&requests_mutex);
EVENT_ACK(*mailbox, intr_master[level_index]); // PRU may re-raise and change mailbox now
}
}
if (!EVENT_IS_ACKED(*mailbox, intr_slave)) {
// If CPU emulation enabled: a device INTR was detected on bus,
assert(the_cpu); // if INTR events are enabled, cpu must be instantiated
// see register_device()
the_cpu->on_interrupt(mailbox->events.intr_vector);
the_cpu->on_interrupt(mailbox->events.intr_slave.vector);
// clear SSYN, INTR cycle completes
EVENT_ACK(*mailbox, intr_slave);
// mailbox->arbitrator.cpu_priority_level now CPU_PRIORITY_LEVEL_FETCHING
@@ -1212,14 +1235,13 @@ mailbox_t mailbox_snapshot;
// reset measurements and timeouts
void unibusadapter_c::debug_init() {
// count events both on ARM and PRU, must be same!
dbg_dma_event_count = 0;
mailbox->events.dma_dbg_count = 0;
}
// look into data strucures
void unibusadapter_c::debug_snapshot(void) {
// copy PRU mailbox state to space visible in Debugger (why necessary?)
memcpy(&mailbox_snapshot, (void *) mailbox, sizeof(mailbox_t));
//mailbox_snapshot = *(mailbox_t *)mailbox;
break_here(); // pos for breakpoint
}

View File

@@ -116,8 +116,6 @@ public:
void debug_init(void) ;
void debug_snapshot(void) ;
uint32_t dbg_dma_event_count ; // count dba evets on ARM side
};
extern unibusadapter_c *unibusadapter; // another Singleton

View File

@@ -394,16 +394,16 @@ void buslatches_test(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
uint8_t resvar;
// echo DATA0 read only
buslatches_test_get(2,resvar);
PRU_DEBUG_PIN(buslatches_getbyte(2) != a);
PRU_DEBUG_PIN0(buslatches_getbyte(2) != a);
// buslatches_debug_set(resvar & 1);
buslatches_test_get(3,resvar);
PRU_DEBUG_PIN(buslatches_getbyte(3) != b);
PRU_DEBUG_PIN0(buslatches_getbyte(3) != b);
//buslatches_debug_set(resvar & 1);
buslatches_test_get(5,resvar);
PRU_DEBUG_PIN(buslatches_getbyte(5) != c);
PRU_DEBUG_PIN0(buslatches_getbyte(5) != c);
//buslatches_debug_set(resvar & 1);
buslatches_test_get(6,resvar);
PRU_DEBUG_PIN(buslatches_getbyte(6) != d);
PRU_DEBUG_PIN0(buslatches_getbyte(6) != d);
//buslatches_debug_set(resvar & 1);
}
#endif
@@ -421,16 +421,15 @@ void buslatches_test(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
buslatches_setbyte(5, c)
;
if (buslatches_getbyte(2) != a)
PRU_DEBUG_PIN_PULSE_100NS
;// show error flag. cleared by next reg_sel
PRU_DEBUG_PIN0_PULSE(100);// show error flag. cleared by next reg_sel
buslatches_setbyte(6, d)
;
if (buslatches_getbyte(3) != b)
PRU_DEBUG_PIN_PULSE_100NS;
PRU_DEBUG_PIN0_PULSE(100);
if (buslatches_getbyte(5) != c)
PRU_DEBUG_PIN_PULSE_100NS;
PRU_DEBUG_PIN0_PULSE(100);
if (buslatches_getbyte(6) != d)
PRU_DEBUG_PIN_PULSE_100NS;
PRU_DEBUG_PIN0_PULSE(100);
a++;
b++;
c++;

View File

@@ -30,7 +30,7 @@
#include <stdint.h>
#include "pru1_utils.h"
#include "pru1_buslatches.h" // PRU_DEBUG_PIN
#include "pru1_buslatches.h" // PRU_DEBUG_PIN0
#include "mailbox.h"
#include "iopageregister.h"
#include "ddrmem.h"

View File

@@ -144,6 +144,7 @@ void main(void) {
}
// signal INT or PWR FAIL to ARM
// before arb_worker(), so BR/NPR requests are canceled on INIT
do_event_initializationsignals();
// Priority Arbitration
@@ -238,7 +239,7 @@ void main(void) {
// start one INTR cycle. May be raised in midst of slave cycle
// by ARM, if access to "active" register triggers INTR.
sm_arb.request_mask |= mailbox.intr.priority_arbitration_bit;
// sm_arb_worker() evaluates this, extern Arbitrator raises Grant,
// sm_arb_worker() evaluates this, extern Arbitrator raises Grant,
// vector of GRANted level is transfered with statemachine sm_intr_master
// Atomically change state in a device's associates interrupt register.
@@ -251,10 +252,10 @@ void main(void) {
// end of INTR is signaled to ARM with signal
break;
case ARM2PRU_INTR_CANCEL:
// cancels an INTR request. If already Granted, the GRANT is forwarded,
// cancels one or more INTR requests. If already Granted, the GRANT is forwarded,
// and canceled by reaching a "SACK turnaround terminator" or "No SACK TIMEOUT" in the arbitrator.
sm_arb.request_mask &= ~mailbox.intr.priority_arbitration_bit;
// no completion event, could interfer with othe INTRs?
// no completion event, could interfer with other INTRs?
mailbox.arm2pru_req = ARM2PRU_NONE; // done
break;
case ARM2PRU_INITALIZATIONSIGNAL_SET:

View File

@@ -88,6 +88,7 @@
#include "pru1_timeouts.h"
#include "pru1_buslatches.h"
#include "pru1_timeouts.h"
#include "pru1_statemachine_arbitration.h"
statemachine_arbitration_t sm_arb;
@@ -143,11 +144,13 @@ uint8_t sm_arb_worker_client() {
// Always update UNIBUS BR/NPR lines, are ORed with requests from other devices.
buslatches_setbits(1, PRIORITY_ARBITRATION_BIT_MASK, sm_arb.request_mask)
;
// read GRANT IN lines from CPU (Arbitrator). Only one at a time may be active
// Arbitrator asserts SACK is inactive
// latch[0]: BG signals are inverted, "get" is non-inverting: bit = active signal.
// "set" is inverting!
grant_mask = buslatches_getbyte(0) & PRIORITY_ARBITRATION_BIT_MASK; // read GRANT IN
// forward un-requested GRANT IN to GRANT OUT for other cards on neighbor slots
buslatches_setbits(0, PRIORITY_ARBITRATION_BIT_MASK & ~sm_arb.request_mask, ~grant_mask)
;
@@ -221,10 +224,7 @@ uint8_t sm_arb_worker_master() {
timeout_cleanup(TIMEOUT_SACK);
} else if (latch1val & PRIORITY_ARBITRATION_BIT_NP) {
// device NPR
PRU_DEBUG_PIN_PULSE_100NS ;
if (sm_arb.arbitrator_grant_mask == 0) {
PRU_DEBUG_PIN_PULSE_100NS ;
// no 2nd device's request may modify GRANT before 1st device acks with SACK
sm_arb.arbitrator_grant_mask = PRIORITY_ARBITRATION_BIT_NP;
timeout_set(TIMEOUT_SACK, MILLISECS(ARB_MASTER_SACK_TIMOUT_MS));

View File

@@ -46,7 +46,7 @@ typedef struct {
// When arbitrator GRANts a request, we set SACK, GRAMT is cleared and we wait
// for BBSY clear.
// 0: not waitong for BBSY.
// != saves GRANTed reqiest and idnicates BBSY wait state
// != saves GRANTed request and indicates BBSY wait state
uint8_t bbsy_wait_grant_mask;
/*** master ****/

View File

@@ -207,7 +207,5 @@ static statemachine_state_func sm_data_slave_state_99() {
if (buslatches_getbyte(4) & BIT(4)) {
return (statemachine_state_func) &sm_data_slave_state_99; // wait, MSYN still active
}
// PRU_DEBUG_PIN(1) ;
return NULL; // ready
}

View File

@@ -332,7 +332,7 @@ static statemachine_state_func sm_dma_state_99() {
timeout_cleanup(TIMEOUT_DMA);
// device or cpu cycle ended: now CPU may become UNIBUS master again
mailbox.events.dma_cpu_transfer = mailbox.arbitrator.cpu_BBSY ;
mailbox.events.dma.cpu_transfer = mailbox.arbitrator.cpu_BBSY ;
mailbox.arbitrator.device_BBSY = false;
mailbox.arbitrator.cpu_BBSY = false;
@@ -340,7 +340,6 @@ static statemachine_state_func sm_dma_state_99() {
mailbox.dma.cur_status = final_dma_state; // signal to ARM
// signal to ARM
mailbox.events.dma_dbg_count++ ; //DBG
EVENT_SIGNAL(mailbox,dma) ;
// ARM is clearing this, before requesting new DMA.
// no concurrent ARM+PRU access

View File

@@ -85,7 +85,7 @@ static statemachine_state_func sm_intr_master_state_2() {
// Complete and signal this INTR transaction only after ARM has processed the previous event.
// INTR may come faster than ARM Linux can process,
// especially if Arbitrator grants INTRs of multiple levels almost simultaneaously in parallel.
if (! EVENT_IS_ACKED(mailbox,intr_master))
if (! EVENT_IS_ACKED(mailbox,intr_master[sm_intr_master.level_index]))
return (statemachine_state_func) &sm_intr_master_state_2; // wait
// remove vector
@@ -104,8 +104,8 @@ static statemachine_state_func sm_intr_master_state_2() {
// signal to ARM which INTR was completed
// change mailbox only after ARM has ack'ed mailbox.events.event_intr
mailbox.events.intr_level_index = sm_intr_master.level_index;
EVENT_SIGNAL(mailbox,intr_master);
// mailbox.events.intr_master.level_index = sm_intr_master.level_index;
EVENT_SIGNAL(mailbox,intr_master[sm_intr_master.level_index]);
// ARM is clearing this, before requesting new interrupt of same level
// so no concurrent ARP+PRU access
PRU2ARM_INTERRUPT

View File

@@ -64,7 +64,7 @@ statemachine_state_func sm_intr_slave_start() {
mailbox.arbitrator.cpu_priority_level = CPU_PRIORITY_LEVEL_FETCHING ;
// signal ARM, wait for event to be processed
mailbox.events.intr_vector = (uint16_t) latch6val << 8 | latch5val ;
mailbox.events.intr_slave.vector = (uint16_t) latch6val << 8 | latch5val ;
PRU2ARM_INTERRUPT ;
// wait until ARM acked
return (statemachine_state_func) &sm_intr_slave_state_1;

View File

@@ -79,7 +79,12 @@ void timeout_set(uint32_t *target_cycles_var, uint32_t delta_cycles) {
timeouts_active++; // now one more active
}
// must be called, if timeout not polled anymore for "timeout-reached()
bool timeout_active(uint32_t *target_cycles_var) {
return (*target_cycles_var > 0) ;
}
// must be called, if timeout not polled anymore for "timeout_reached()
void timeout_cleanup(uint32_t *target_cycles_var) {
if (*target_cycles_var > 0) {
*target_cycles_var = 0;
@@ -89,14 +94,14 @@ void timeout_cleanup(uint32_t *target_cycles_var) {
//
// test a timeout, wehter it reached its arg count nor or earlier
// test a timeout, wether it reached its arg count nor or earlier
bool timeout_reached(uint32_t *target_cycles_var) {
// fast path: assume timeout_reached() is called
// because timeout is active
if (PRU1_CTRL.CYCLE < *target_cycles_var)
return false;
else if (*target_cycles_var == 0)
return true; // already inactive
return true; // already "reached" if inactive
else {
// switched from "running" to "timeout reached"
*target_cycles_var = 0;

View File

@@ -29,11 +29,12 @@
#include <stdbool.h>
// predefined timeouts
#define TIMEOUT_COUNT 2
#define TIMEOUT_COUNT 3
// fixed pointers
#define TIMEOUT_DMA (&timeout_target_cycles[0])
#define TIMEOUT_SACK (&timeout_target_cycles[1])
//#define TIMEOUT_TEST (&timeout_target_cycles[2])
// cycle end count for each active timeoput.
extern uint32_t timeout_target_cycles[TIMEOUT_COUNT];
@@ -43,6 +44,7 @@ extern uint32_t timeout_target_cycles[TIMEOUT_COUNT];
void timeout_init(void);
void timeout_set(uint32_t *target_cycles_var, uint32_t delta_cycles);
bool timeout_active(uint32_t *target_cycles_var) ;
bool timeout_reached(uint32_t *target_cycles_var);
void timeout_cleanup(uint32_t *target_cycles_var);

View File

@@ -27,6 +27,7 @@
#define _PRU1_UTILS_C_
#include <stdint.h>
#include <stdbool.h>
#include "mailbox.h"
#include "pru1_buslatches.h"
@@ -42,21 +43,24 @@ void do_event_initializationsignals() {
uint8_t mb_cur = mailbox.events.init_signals_cur; // as saved
uint8_t bus_cur = buslatches_getbyte(7) & 0x38; // now sampled
if (bus_cur & INITIALIZATIONSIGNAL_INIT)
sm_arb.request_mask = 0 ; // INIT clears all PRIORITY request signals
if (bus_cur & INITIALIZATIONSIGNAL_INIT) {
sm_arb.request_mask = 0 ; // INIT clears all PRIORITY request signals
// SACK cleared later on end of INTR/DMA transaction
}
if (bus_cur != mb_cur) {
// save old state, so ARM can detect what changed
mailbox.events.init_signals_prev = mb_cur;
mailbox.events.init_signals_cur = bus_cur;
// trigger the correct event: power and/or INIT
if ((mb_cur ^ bus_cur) & (INITIALIZATIONSIGNAL_DCLO | INITIALIZATIONSIGNAL_ACLO))
if ((mb_cur ^ bus_cur) & (INITIALIZATIONSIGNAL_DCLO | INITIALIZATIONSIGNAL_ACLO)) {
// AC_LO or DC_LO changed
EVENT_SIGNAL(mailbox,power) ;
if ((mb_cur ^ bus_cur) & INITIALIZATIONSIGNAL_INIT)
}
if ((mb_cur ^ bus_cur) & INITIALIZATIONSIGNAL_INIT) {
// INIT changed
EVENT_SIGNAL(mailbox,init);
}
PRU2ARM_INTERRUPT
;
}

View File

@@ -93,15 +93,30 @@ typedef void * (*statemachine_state_func)(void);
*/
// set PRU1_12 to 0 or 1
#define PRU_DEBUG_PIN(val) ( (val) ? (__R30 |= (1 << 12) ) : (__R30 &= ~(1<< 12)) )
#define PRU_DEBUG_PIN0(val) ( (val) ? (__R30 |= (1 << 12) ) : (__R30 &= ~(1<< 12)) )
// set PRU1_13 to 0 or 1. BBB must have "eMMC trace cut"!
// PinMUX: Temporarly change this
// 0x084 0x07 // Force constant level on eMMC CMD pin. P8.20 output gpio1_31, pulldown, mode=7
// to this
// 0x084 0x05 // PRU1_13 on P8.20: pr1_pru1_pru_r30_13, fast, output, pulldown, mode=5
// in UniBone.dts
#define PRU_DEBUG_PIN1(val) ( (val) ? (__R30 |= (1 << 13) ) : (__R30 &= ~(1<< 13)) )
// 100ns pulse an PRU1_12
#define PRU_DEBUG_PIN_PULSE_100NS do { \
#define PRU_DEBUG_PIN0_PULSE(ns) do { \
__R30 |= (1 << 12) ; \
__delay_cycles(18) ; \
__delay_cycles(NANOSECS(ns)-2) ; \
__R30 &= ~(1 << 12) ; \
} while(0)
#define PRU_DEBUG_PIN1_PULSE(ns) do { \
__R30 |= (1 << 13) ; \
__delay_cycles(NANOSECS(ns)-2) ; \
__R30 &= ~(1 << 13) ; \
} while(0)
#ifdef TRASH
// set DEBUG PIN and value to PRU0 outputs
// output appear delayed by PRU0!

View File

@@ -52,14 +52,12 @@
#define ARM2PRU_DDR_FILL_PATTERN 19 // fill DDR with test pattern
#define ARM2PRU_DDR_SLAVE_MEMORY 20 // use DDR as UNIBUS slave memory
// signal IDs for ARM2PRU_INITALIZATIONSIGNAL_*
// states of initialization section lines. Bitmask = latch[7]
#define INITIALIZATIONSIGNAL_INIT (1 << 3)
#define INITIALIZATIONSIGNAL_ACLO (1 << 4)
#define INITIALIZATIONSIGNAL_DCLO (1 << 5)
// possible states of DMA machine
#define DMA_STATE_READY 0 // idle
#define DMA_STATE_ARBITRATING 1 // in NPR/NPG/SACK arbitration
@@ -80,7 +78,6 @@
// CPU pririty level invalid between INTR receive and fetch of next PSW
#define CPU_PRIORITY_LEVEL_FETCHING 0xff
// data for a requested DMA operation
#define PRU_MAX_DMA_WORDCOUNT 512
@@ -124,30 +121,28 @@ typedef struct {
uint16_t val; // value set/get.
} mailbox_initializationsignal_t;
// data for bus arbitrator
typedef struct {
// arbitrator.device_BBSY indicates a device wants or has acquired the UNIBUS
// cpu DATA transfer must be delayed until == 00
// set by arbitration logic
uint8_t device_BBSY ;
uint8_t device_BBSY;
// Command by ARM on DMA start: DATA transfer as CPU, else as device
uint8_t cpu_BBSY ;
uint8_t cpu_BBSY;
uint8_t cpu_priority_level ; // Priority level of CPU, visible in PSW. 7,6,5,4 <4.
uint8_t cpu_priority_level; // Priority level of CPU, visible in PSW. 7,6,5,4 <4.
uint8_t _dummy1 ; // keep 32 bit borders
} mailbox_arbitrator_t ;
uint8_t _dummy1; // keep 32 bit borders
} mailbox_arbitrator_t;
// data for a requested DMA operation
typedef struct {
// take care of 32 bit word borders for struct members
uint8_t cur_status; // 0 = idle, 1 = DMA running, 2 = timeout error
// 0x80: set on start to indicate CPU access
uint8_t control; // cycle to perform: only DATO, DATI allowed
uint16_t wordcount; // # of remaining words transmit/receive, static
// ---dword---
@@ -176,78 +171,100 @@ typedef struct {
} mailbox_intr_t;
/* PRU->ARM event signaling is a signal/acknowledge protocoll.
There are no shared mutexes for PRU / ARM mailbox protection.
So protocol must be implmeneted with the "single writer -multiple reader" pattern,
where only a single writer modifes shared variables.
For each event source there are 2 channels (variables)
- signal: PRU arites, ARM reads
- acknowledge: ARM writes, PRU reads.
Both variables are rollaround-counters, which are simply updated on event.
PRU raises event with "signaled++", and checks for ARM ack with
"if (signaled != acked) ..."
ARM checks for pending signals with
"if (signaled != acked) ..."
and acknowledees an event with "acked++".
*/
#define EVENT_SIGNAL(mailbox,source) ((mailbox).events.source##_signaled++)
#define EVENT_ACK(mailbox,source) ((mailbox).events.source##_acked++)
#define EVENT_IS_ACKED(mailbox,source) ((mailbox).events.source##_signaled == (mailbox).events.source##_acked)
There are no shared mutexes for PRU / ARM mailbox protection.
So protocol must be implmeneted with the "single writer -multiple reader" pattern,
where only a single writer modifes shared variables.
For each event source there are 2 channels (variables)
- signal: PRU arites, ARM reads
- acknowledge: ARM writes, PRU reads.
Both variables are rollaround-counters, which are simply updated on event.
PRU raises event with "signaled++", and checks for ARM ack with
"if (signaled != acked) ..."
ARM checks for pending signals with
"if (signaled != acked) ..."
and acknowledees an event with "acked++".
*/
#define EVENT_SIGNAL(mailbox,source) ((mailbox).events.source.signaled++)
#define EVENT_ACK(mailbox,source) ((mailbox).events.source.acked++)
#define EVENT_IS_ACKED(mailbox,source) ((mailbox).events.source.signaled == (mailbox).events.source.acked)
// Access to device register detected
typedef struct {
uint8_t signaled; // PRU->ARM
uint8_t acked; // ARM->PRU
// info about register access
uint8_t unibus_control; // DATI,DATO,DATOB
// handle of controller
uint8_t device_handle;
// ---dword---
uint16_t data; // deviceregister_data value for DATO event
uint8_t register_idx; // # of register in device space
uint8_t _dummy1;
// ---dword---
// UNIBUS address accessed
uint32_t addr; // accessed address: odd/even important for DATOB
} mailbox_event_deviceregister_t;
// DMA transfer complete
typedef struct {
/* After ARM2PRU_DMA_*, NPR/NPG/SACK protocll was executed and
Data trasnfered accoring to mailbox_dma_t.
After that, mailbox_dma_t is updated and signal raised.
*/
uint8_t signaled; // PRU->ARM
uint8_t acked; // ARM->PRU
uint8_t cpu_transfer; // 1: ARM must process DMA as completed cpu DATA transfer
uint8_t _dummy2;
} mailbox_event_dma_t;
// INTR raised by device
typedef struct {
/* Event priority arbitration INTR transfer complete
After ARM2PRU_INTR, one of BR4/5/6/7 NP was requested,
granted, and the deviceregister.data transfer was handled as bus master.
*/
uint8_t signaled; // PRU->ARM, one of BR4,5,6,7 vector on UNIBUS
uint8_t acked; // ARM->PRU
//uint8_t level_index; // 0..3 -> BR4..BR7
uint8_t _dummy[2];
} mailbox_event_intr_master_t;
// INTR received by CPU
typedef struct {
uint8_t signaled; // PRU->ARM, one of BR4,5,6,7 vector on UNIBUS
uint8_t acked; // ARM->PRU
uint16_t vector; // received vector
} mailbox_event_intr_slave_t;
// change of INIT signal
typedef struct {
uint8_t signaled; // PRU->ARM
uint8_t acked; // ARM->PRU
uint8_t _dummy[2];
} mailbox_event_init_t;
// change of ACLO/DCLO signals
typedef struct {
uint8_t signaled; // PRU->ARM
uint8_t acked; // ARM->PRU
uint8_t _dummy[2];
} mailbox_event_power_t;
typedef struct {
// different events can be raised asynchronically and concurrent,
// but a single event type is sequentially signaled by PRU and acked by ARM.
mailbox_event_deviceregister_t deviceregister;
mailbox_event_dma_t dma;
/*** Access to device register ***/
uint8_t deviceregister_signaled; // PRU->ARM
uint8_t deviceregister_acked; // ARM->PRU
// info about register access
uint8_t deviceregister_unibus_control; // DATI,DATO,DATOB
// handle of controller
uint8_t deviceregister_device_handle;
// ---dword---
// # of register in device space
uint8_t device_register_idx;
uint8_t _dummy1 ;
uint16_t deviceregister_data; // deviceregister_data value for DATO event
// ---dword---
// UNIBUS address accessed
uint32_t deviceregister_addr; // accessed address: odd/even important for DATOB
// one event for each BG4,5,6,7
mailbox_event_intr_master_t intr_master[4];
/*** DMA transfer complete
After ARM2PRU_DMA_*, NPR/NPG/SACK protocll was executed and
Data trasnfered accoring to mailbox_dma_t.
After that, mailbox_dma_t is updated and signal raised.
*/
uint8_t dma_signaled; // PRU->ARM
uint8_t dma_acked; // ARM->PRU
uint8_t dma_cpu_transfer ; // 1: ARM must process DMA as completed cpu DATA transfer
uint8_t _dummy2 ;
// ---dword---
uint32_t dma_dbg_count ; //DBG
/*** Event priority arbitration INTR transfer complete
After ARM2PRU_INTR, one of BR4/5/6/7 NP was requested,
granted, and the deviceregister_data transfer was handled as bus master.
*/
// ---dword---
uint8_t intr_master_signaled; // PRU->ARM, one of BR4,5,6,7 vector on UNIBUS
uint8_t intr_master_acked; // ARM->PRU
uint8_t intr_level_index; // 0..3 -> BR4..BR7
/*** INTR transmitted by devices as master was received by CPU as slave ***/
uint8_t intr_slave_signaled; // PRU->ARM, one of BR4,5,6,7 vector on UNIBUS
// ---dword---
uint8_t intr_slave_acked; // ARM->PRU
uint8_t _dummy3 ;
uint16_t intr_vector ; // received vector
// ---dword---
mailbox_event_intr_slave_t intr_slave;
/*** INIT or Power cycle seen on UNIBUS ***/
uint8_t init_signaled; // PRU->ARM
uint8_t init_acked; // ARM->PRU
uint8_t power_signaled; // PRU->ARM
uint8_t power_acked; // ARM->PRU
// ---dword---
mailbox_event_init_t init;
mailbox_event_power_t power;
uint8_t init_signals_prev; // on event: a signal changed from this ...
uint8_t init_signals_cur; // ... to this
@@ -264,7 +281,6 @@ typedef struct {
mailbox_arbitrator_t arbitrator;
// set by PRU, read by ARM on event
mailbox_events_t events;
@@ -278,8 +294,8 @@ typedef struct {
mailbox_buslatch_t buslatch;
mailbox_buslatch_test_t buslatch_test;
mailbox_buslatch_exerciser_t buslatch_exerciser;
mailbox_initializationsignal_t initializationsignal ;
uint32_t cpu_enable;
mailbox_initializationsignal_t initializationsignal;
uint32_t cpu_enable;
};
} mailbox_t;
@@ -311,17 +327,19 @@ extern volatile far mailbox_t mailbox;
// iopageregister_t *reg
#define DO_EVENT_DEVICEREGISTER(_reg,_unibus_control,_addr,_data) do { \
/* register read changes device state: signal to ARM */ \
mailbox.events.deviceregister_unibus_control = _unibus_control ; \
mailbox.events.deviceregister_device_handle = _reg->event_device_handle ;\
mailbox.events.device_register_idx = _reg->event_device_register_idx ; \
mailbox.events.deviceregister_addr = _addr ; \
mailbox.events.deviceregister_data = _data ; \
mailbox.events.deviceregister.unibus_control = _unibus_control ; \
mailbox.events.deviceregister.device_handle = _reg->event_device_handle ;\
mailbox.events.deviceregister.register_idx = _reg->event_device_register_idx ; \
mailbox.events.deviceregister.addr = _addr ; \
mailbox.events.deviceregister.data = _data ; \
EVENT_SIGNAL(mailbox,deviceregister) ; \
/* data for ARM valid now*/ \
PRU2ARM_INTERRUPT ; \
/* leave SSYN asserted until mailbox.event.signal ACKEd to 0 */ \
} while(0)
#endif
#endif // _MAILBOX_H_

View File

@@ -0,0 +1,35 @@
.title ma_du - MSCP test driver
; MSCP DMA is generated by reading block 0
duvect = 154 ; vector of UDA controller
dubase = 772150 ; base addr of UDA controller
dulabl = 'U ; label char
; --- ISRs, increment Interrupt FLags
duiflg: .word 1 ; Interrupt flags
dubuff: .blkw 1000+1 ; data buffer: 512 words
duecnt: .word 1 ; event counter
duisr:
inc duiflg ; set ISR flag
rti
; --- Initialize device after RESET
duinit:
clr duecnt
return
; --- Restart new DMA transmission
dugo:
mov #dubase,r1 ; r1 = controller base address
; TODO: read block 0 like boot loader
inc duecnt ; register as event
return

View File

@@ -0,0 +1,83 @@
# "demo" test of parallel DMA/INTR
# runs multiarb.mac
#
# Execute this with active PDP-11 CPU and in halted state
d # active PDP-11 CPU, devices
# tm # HALTed
en dl11 # work with simulated DL11
sd dl11
p rb 300 # "type" slowly
p # show params
pwr
#.wait 1000 # wait for CPU to start
m i # emulate memory
### Enable KW11 clock
en kw11
sd kw11
p freq 100
### Enable 2 RL drives
en rl # enable RL11 controller
sd rl
p il 4 # use BR4
en rl0 # enable drive #0
sd rl0 # select
p emulation_speed 10 # 10x speed. Load disk in 5 seconds
# set type to "rl02"
p runstopbutton 0 # released: "LOAD"
p powerswitch 1 # power on, now in "load" state
p image scratch0.rl02 # mount image file with test pattern
p runstopbutton 1 # press RUN/STOP, will start
#.end
en rl1 # enable drive #1
sd rl1 # select
p emulation_speed 10 # 10x speed. Load disk in 5 seconds
# set type to "rl02"
p runstopbutton 0 # released: "LOAD"
p powerswitch 1 # power on, now in "load" state
p image scratch1.rl02 # mount image file with test pattern
p runstopbutton 1 # press RUN/STOP, will start
### Enable 2 RK05 drives
en rk # enable RK11 controller
en rk0 # enable drive #0
sd rk0 # select
p image scratch0.rk
en rk1 # enable drive #1
sd rk1 # select
p image scratch1.rk
### Enable 2 MSCP drives
en uda0 # enable drive #0
sd uda0 # select
# set type to "RA80"
p type RA80
p image scratch0.ra80 # mount image file with test pattern
en uda1 # enable drive #1
sd uda1 # select
p type RA80
p image scratch1.ra80
##########################################
m ll multiarb.lst # load test program
.print Now starting test program at 1000 via PDP-11 console
dl11 rcv 1000 L\x201000\r
# dl11 rcv 500 S\r
.wait 5000
dbg c
.print Debug logs cleared.

View File

@@ -4,8 +4,8 @@
4 ; Exercises several devices in parallel,
5 ; each with INTR and DMA
6 ; For a device XX we have
7 ; XXENAB - flag to enable devcie
8 ; XXBASE - base address of devcie
7 ; XXENAB - flag to enable device
8 ; XXBASE - base address of device
9 ; XXVEC - the INTR vector
10 ; XXISR - Interrupt Service
11 ; XXIFLG - flag which is incremented in ISR
@@ -20,166 +20,189 @@
20 ; RK - RK11/RK05 disk
21 ; RL - RL11/RL02 disk
22 ; RY - Serial RX211 Floppy,
23
24 ; enable tests
25 000001 kwenab = 1
26 000000 rkenab = 0
27 000000 rlenab = 0
28 000000 ryenab = 0
29
30 .enable AMA
31 .asect
32
33 ; *************************************************
34 ; Vectors
35
36 000060 . = corvec
37 000060 001166 .word corisr ; RCV interrupt
38 000062 000340 .word 340
39 000064 . = coxvec
40 000064 001202 .word coxisr ; XMT interrupt
41 000066 000340 .word 340
42
43 000001 .if ne kwenab
44 000100 . = kwvect
45 000100 001426 .word kwisr ; periodic interrupt
46 000102 000340 .word 340
47 .endc
48
49 000000 .if ne rlenab
50 . = rlvect ; RL11
51 .word rlisr
52 .word 340
53 .endc
54
55 000000 .if ne rkenab
56 . = rkvect ; RK11
57 .word rkisr
58 .word 340
59 .endc
60
61 000000 .if ne ryenab
62 . = ryvect ; RX211
63 .word ryisr
64 .word 340
65 .endc
66
67 177776 psw = 177776
68 165020 monitr = 165020 ; Monitor addr for back jump
69
70 ; *************************************************
71 ; Main
72 001000 . = 1000
73 000776 stack = .-2
74 start:
75 001000 012706 000776 mov #stack,sp
76 001004 005037 177776 clr @#psw ; priorty level 0, allow INTR
77 ; Initialize devices
78 001010 000005 reset
79 001012 004737 001210 call corini
80 001016 004737 001224 call coxini
81 000001 .if ne kwenab
82 001022 004737 001440 call kwinit
83 .endc
84 000000 .if ne rkenab
85 call rkinit
86 .endc
87 000000 .if ne rlenab
88 call rlinit
89 .endc
90 000000 .if ne ryenab
91 call ryinit
92 .endc
93
94 001026 012701 001456 mov #shello,r1 ; Print "Hello" message
95 001032 004737 001240 call puts
96
97 ; main loop: check interrupt flags, restart DMA
98 ; process serial input
99 loop:
100 001036 004737 001050 call dokbd ; check keyboard input
101 001042 004737 001106 call dodev ; check device activities
102 001046 000773 br loop
103
23 ; DU - MSCP disk drive on UDA controller
24
25 ; enable tests
26 000001 kwenab = 1
27 000001 rkenab = 1
28 000001 rlenab = 1
29 000000 ryenab = 0 ; not yet tested
30 000000 duenab = 0 ; not yet implemeneted
31
32 .enable AMA
33 .asect
34
35 ; *************************************************
36 ; Vectors
37
38 000060 . = corvec
39 000060 001262 .word corisr ; RCV interrupt
40 000062 000340 .word 340
41 000064 . = coxvec
42 000064 001276 .word coxisr ; XMT interrupt
43 000066 000340 .word 340
44
45 000001 .if ne kwenab
46 000100 . = kwvect
47 000100 001522 .word kwisr ; periodic interrupt
48 000102 000340 .word 340
49 .endc
50
51 000001 .if ne rlenab
52 000160 . = rlvect ; RL11
53 000160 004644 .word rlisr
54 000162 000340 .word 340
55 .endc
56
57 000001 .if ne rkenab
58 000220 . = rkvect ; RK11
59 000220 002566 .word rkisr
60 000222 000340 .word 340
61 .endc
62
63 000000 .if ne ryenab
64 . = ryvect ; RX211
65 .word ryisr
66 .word 340
67 .endc
68
69 000000 .if ne duenab
70 . = duvect ; UDA MSCP controller
71 .word duisr
72 .word 340
73 .endc
74
75 177776 psw = 177776
76 165020 monitr = 165020 ; Monitor addr for back jump
77
78 ; *************************************************
79 ; Main
80 001000 . = 1000
81 000776 stack = .-2
82 start:
83 001000 012706 000776 mov #stack,sp
84 001004 005037 177776 clr @#psw ; priorty level 0, allow INTR
85 ; Initialize devices
86 001010 000005 reset
87 001012 004737 001304 call corini
88 001016 004737 001320 call coxini
89 000001 .if ne kwenab
90 001022 004737 001534 call kwinit
91 .endc
92 000001 .if ne rkenab
93 001026 004737 002574 call rkinit
94 .endc
95 000001 .if ne rlenab
96 001032 004737 004652 call rlinit
97 .endc
98 000000 .if ne ryenab
99 call ryinit
100 .endc
101 000000 .if ne duenab
102 call duinit
103 .endc
104
105
106 ; --- check keyboard input
107 dokbd:
108 001050 004737 001372 call getc
109 001054 103013 bcc 9$ ; nothing received
110 ; process char in r0
111 001056 120027 000003 cmpb r0,#3
112 001062 001006 bne 1$
113 001064 012701 001547 mov #sbye,r1 ; ^C: print "Bye", back to monitor
114 001070 004737 001240 call puts
115 001074 000137 165020 jmp monitr
116 1$:
117 ; echo chars without special meaning
118 001100 004737 001352 call putc
119 9$:
120 001104 000207 return
121
122 ; -- check device activities
123 dodev:
124 ; For all devices: restart device DMA if Interrupt received
125 000001 .if ne kwenab
126 001106 005737 001422 tst kwiflg
127 001112 001412 beq 1$
128 001114 005037 001422 clr kwiflg
129 001120 004737 001454 call kwgo
130 001124 012700 000127 mov #kwlabl,r0 ; progress printout
131 001130 012701 001424 mov #kwecnt,r1
132 001134 004737 001142 call progrs
133 1$:
134 .endc
135
136 000000 .if ne rkenab
137 tst rkiflg
138 beq 2$
139 clr rkiflg
140 call rkgo
141 mov #rklabl,r0 ; progress printout
142 mov #rkecnt,r1
143 call progrs
144 2$:
105 001036 012701 004772 mov #shello,r1 ; Print "Hello" message
106 001042 004737 001334 call puts
107
108 ; main loop: check interrupt flags, restart DMA
109 ; process serial input
110 loop:
111 001046 004737 001060 call dokbd ; check keyboard input
112 001052 004737 001116 call dodev ; check device activities
113 001056 000773 br loop
114
115
116
117 ; --- check keyboard input
118 dokbd:
119 001060 004737 001466 call getc
120 001064 103013 bcc 9$ ; nothing received
121 ; process char in r0
122 001066 120027 000003 cmpb r0,#3
123 001072 001006 bne 1$
124 001074 012701 005063 mov #sbye,r1 ; ^C: print "Bye", back to monitor
125 001100 004737 001334 call puts
126 001104 000137 165020 jmp monitr
127 1$:
128 ; echo chars without special meaning
129 001110 004737 001446 call putc
130 9$:
131 001114 000207 return
132
133 ; -- check device activities
134 dodev:
135 ; For all devices: restart device DMA if Interrupt received
136 000001 .if ne kwenab
137 001116 005737 001516 tst kwiflg
138 001122 001412 beq 1$
139 001124 005037 001516 clr kwiflg
140 001130 004737 001550 call kwgo
141 001134 012700 000127 mov #kwlabl,r0 ; progress printout
142 001140 012701 001520 mov #kwecnt,r1
143 001144 004737 001236 call progrs
144 1$:
145 .endc
146 000000 .if ne rlenab
147 tst rliflg
148 beq 3$
149 clr rliflg
150 call rlgo
151 mov #rllabl,r0 ; progress printout
152 mov #rlecnt,r1
153 call progrs
154 3$:
155 .endc
156 000000 .if ne ryenab
157 tst ryiflg
158 beq 4$
159 clr ryiflg
160 call rygo
161 mov #rylabl,r0 ; progress printout
162 mov #ryecnt,r1
163 call progrs
164 4$:
165 .endc
166
167 001140 000207 return
168
169
170 ; progress
171 ; check if the counter with address in r1 is at
172 ; 1024. if yes, print the char in r0
173 progrs:
174 001142 042711 176000 bic #776000,(r1) ; mask counter to 0..1023
175 001146 001002 bne 9$
176 001150 004737 001352 call putc ; is at 0: print label character
177 9$:
178 001154 000207 return
179
180
181
182 .include ma_cons.mac
146
147 000001 .if ne rkenab
148 001150 005737 001560 tst rkiflg
149 001154 001412 beq 2$
150 001156 005037 001560 clr rkiflg
151 001162 004737 002602 call rkgo
152 001166 012700 000113 mov #rklabl,r0 ; progress printout
153 001172 012701 002564 mov #rkecnt,r1
154 001176 004737 001236 call progrs
155 2$:
156 .endc
157 000001 .if ne rlenab
158 001202 005737 002636 tst rliflg
159 001206 001412 beq 3$
160 001210 005037 002636 clr rliflg
161 001214 004737 004660 call rlgo
162 001220 012700 000114 mov #rllabl,r0 ; progress printout
163 001224 012701 004642 mov #rlecnt,r1
164 001230 004737 001236 call progrs
165 3$:
166 .endc
167 000000 .if ne ryenab
168 tst ryiflg
169 beq 4$
170 clr ryiflg
171 call rygo
172 mov #rylabl,r0 ; progress printout
173 mov #ryecnt,r1
174 call progrs
175 4$:
176 .endc
177 000000 .if ne ryenab
178 tst duiflg
179 beq 5$
180 clr duiflg
181 call dugo
182 mov #dulabl,r0 ; progress printout
183 mov #duecnt,r1
184 call progrs
185 5$:
186 .endc
187
188 001234 000207 return
189
190
191 ; progress
192 ; check if the counter with address in r1 is at
193 ; 1024. if yes, print the char in r0
194 progrs:
195 ; bic #777700,(r1) ; mask counter to 0..63
196 001236 042711 177400 bic #777400,(r1) ; mask counter to 0..255
197 ; bic #776000,(r1) ; mask counter to 0..1023
198 001242 001002 bne 9$
199 001244 004737 001446 call putc ; is at 0: print label character
200 9$:
201 001250 000207 return
202
203
204
205 .include ma_cons.mac
1
2 .title ma_cons - Serial Console I/O
3 000060 corvec= 060 ; vector for Receiver
@@ -192,30 +215,30 @@
10
11 ; -- ISRs, increment Interrupt FLags
12
13 001156 000001 corifl: .word 1 ; Interrupt flags
14 001160 000001 coxifl: .word 1
13 001252 000001 corifl: .word 1 ; Interrupt flags
14 001254 000001 coxifl: .word 1
15
16 001162 corbuf: .blkw 1 ; data buffer
17 001164 coxbuf: .blkw 1
16 001256 corbuf: .blkw 1 ; data buffer
17 001260 coxbuf: .blkw 1
18
19 corisr:
20 001166 013737 177562 001162 mov @#corbas+2,corbuf ; read char, clear INTR
21 001174 005237 001156 inc corifl
22 001200 000002 rti
20 001262 013737 177562 001256 mov @#corbas+2,corbuf ; read char, clear INTR
21 001270 005237 001252 inc corifl
22 001274 000002 rti
23
24 coxisr:
25 001202 005237 001160 inc coxifl
26 001206 000002 rti
25 001276 005237 001254 inc coxifl
26 001302 000002 rti
27
28 ; -- Initialize device after RESET
29 corini:
30 001210 012737 000100 177560 mov #100,@#corbas ; Bit 6 = Receiver Interrupt Enable
31 001216 005037 001156 clr corifl
32 001222 000207 return
30 001304 012737 000100 177560 mov #100,@#corbas ; Bit 6 = Receiver Interrupt Enable
31 001312 005037 001252 clr corifl
32 001316 000207 return
33 coxini:
34 001224 012737 000100 177564 mov #100,@#coxbas ; Bit 6 = Transmitter Interrupt Enable
35 001232 005037 001160 clr coxifl
36 001236 000207 return
34 001320 012737 000100 177564 mov #100,@#coxbas ; Bit 6 = Transmitter Interrupt Enable
35 001326 005037 001254 clr coxifl
36 001332 000207 return
37
38
39
@@ -224,69 +247,69 @@
42 ; puts - print a string
43 ; r1 = pointer, r0,r1 changed
44 puts:
45 001240 112100 movb (r1)+,r0 ; load xmt char
46 001242 001403 beq 1$ ; string ends with 0
47 001244 004737 001352 call @#putc
48 001250 000773 br puts ; transmit nxt char of string
49 001252 000207 1$: return
45 001334 112100 movb (r1)+,r0 ; load xmt char
46 001336 001403 beq 1$ ; string ends with 0
47 001340 004737 001446 call @#putc
48 001344 000773 br puts ; transmit nxt char of string
49 001346 000207 1$: return
50
51
52 ; putnum - print the octal number in r0
53 001254 numbf0: .blkw 10 ; space to mount number string
54 001274 numbf1 =.
53 001350 numbf0: .blkw 10 ; space to mount number string
54 001370 numbf1 =.
55 putnum:
56 001274 010346 mov r3,-(sp)
57 001276 010002 mov r0,r2 ; r2 = shifter
58 001300 012701 001274 mov #numbf1,r1 ; r1 = buffer pointer, backwards
59 001304 112741 000000 movb #0,-(r1) ; set terminating 0
56 001370 010346 mov r3,-(sp)
57 001372 010002 mov r0,r2 ; r2 = shifter
58 001374 012701 001370 mov #numbf1,r1 ; r1 = buffer pointer, backwards
59 001400 112741 000000 movb #0,-(r1) ; set terminating 0
60 ; repeat 6 times
61 001310 012703 000006 mov #6,r3
61 001404 012703 000006 mov #6,r3
62 1$:
63 001314 010200 mov r2,r0
63 001410 010200 mov r2,r0
64 ; extract lower 3 bits = octal digit
65 001316 042700 177770 bic #177770,r0 ; r0 &= 0x07
66 001322 062700 000060 add #60,r0 ; r0 += '0'
67 001326 110041 movb r0,-(r1) ; write in buffer
68 001330 000241 clc
69 001332 006202 asr r2 ; shift to next digit
70 001334 006202 asr r2
71 001336 006202 asr r2
72 001340 077313 sob r3,1$ ; loop for all 6 digits
65 001412 042700 177770 bic #177770,r0 ; r0 &= 0x07
66 001416 062700 000060 add #60,r0 ; r0 += '0'
67 001422 110041 movb r0,-(r1) ; write in buffer
68 001424 000241 clc
69 001426 006202 asr r2 ; shift to next digit
70 001430 006202 asr r2
71 001432 006202 asr r2
72 001434 077313 sob r3,1$ ; loop for all 6 digits
73
74 001342 004737 001240 call @#puts
75 001346 012603 mov (sp)+,r3
76 001350 000207 return
74 001436 004737 001334 call @#puts
75 001442 012603 mov (sp)+,r3
76 001444 000207 return
77
78
79 ; putc - output a single char
80 ; r0 = char
81 putc:
82 001352 005037 001160 clr coxifl ; reset interrupt flag
83 001356 010037 177566 mov r0,@#coxbas+2 ; char into transmit buffer
84 001362 005737 001160 1$: tst coxifl ; XMT RDY?
85 001366 001775 beq 1$ ; no, loop
82 001446 005037 001254 clr coxifl ; reset interrupt flag
83 001452 010037 177566 mov r0,@#coxbas+2 ; char into transmit buffer
84 001456 005737 001254 1$: tst coxifl ; XMT RDY?
85 001462 001775 beq 1$ ; no, loop
86 ; UART is buffering: char only started to sent now
87 ; interrupt active until next putc
88 001370 000207 return
88 001464 000207 return
89
90 ; getc - poll and input a single char
91 ; result in r0
92 ; carry clear : nothing received
93 ; carry set: char received
94 getc:
95 001372 005000 clr r0
96 001374 005737 001156 tst corifl
97 001400 001002 bne 1$
98 001402 000241 clc ; Carry clear, no Interrupt, nothing received
99 001404 000207 return
95 001466 005000 clr r0
96 001470 005737 001252 tst corifl
97 001474 001002 bne 1$
98 001476 000241 clc ; Carry clear, no Interrupt, nothing received
99 001500 000207 return
100 1$:
101 001406 013700 001162 mov corbuf,r0 ; Interrupt, return char
102 001412 005037 001156 clr corifl ; reset interrupt flag
103 001416 000261 sec ; Carry Set
104 001420 000207 return
101 001502 013700 001256 mov corbuf,r0 ; Interrupt, return char
102 001506 005037 001252 clr corifl ; reset interrupt flag
103 001512 000261 sec ; Carry Set
104 001514 000207 return
104
183 000001 .if ne kwenab
184 .include ma_kw.mac
206 000001 .if ne kwenab
207 .include ma_kw.mac
1 .title ma_kw - KW11 test driver
2
3 ; KW11 raises INTR at 50 Hz
@@ -297,75 +320,171 @@
8
9
10 ; --- ISRs, increment Interrupt FLags
11 001422 000001 kwiflg: .word 1 ; Interrupt flags
11 001516 000001 kwiflg: .word 1 ; Interrupt flags
12
13 001424 000001 kwecnt: .word 1 ; event counter
13 001520 000001 kwecnt: .word 1 ; event counter
14
15 kwisr:
16 001426 005237 001424 inc kwecnt ; register as event
17 001432 005237 001422 inc kwiflg ; set ISR flag
18 001436 000002 rti
16 001522 005237 001520 inc kwecnt ; register as event
17 001526 005237 001516 inc kwiflg ; set ISR flag
18 001532 000002 rti
19
20 ; --- Initialize device after RESET
21 kwinit:
22 001440 012737 000100 177546 mov #100,@#kwbase ; set interrupt enable
23 001446 005037 001424 clr kwecnt
24 001452 000207 return
22 001534 012737 000100 177546 mov #100,@#kwbase ; set interrupt enable
23 001542 005037 001520 clr kwecnt
24 001546 000207 return
25
26 ; --- Restart new INTR
27 kwgo:
28 001454 000207 return
28 001550 042737 000200 177546 bic #200,@#kwbase ; clear INTERRUPT MONITOR bit
29 001556 000207 return
30
30
208 .endc
209 000001 .if ne rkenab
210 .include ma_rk.mac
1
2 .title ma_rk - RK11/RK05 test driver
3 ; RK11 DMA is generated by reading cylinder 0, head 0, sector 0
4
5 000220 rkvect = 220 ; vector of RK11 controller
6 177400 rkbase = 777400 ; base addr of RK11 controller
7 000113 rklabl = 'K ; label char
8
9 ; --- ISRs, increment Interrupt FLags
10 001560 000001 rkiflg: .word 1 ; Interrupt flags
11
12 001562 rkbuff: .blkw 400+1 ; data buffer: 1 sector = 256 words
13
14 002564 000001 rkecnt: .word 1 ; event counter
15
16 rkisr:
17 002566 005237 001560 inc rkiflg ; set ISR flag
18 002572 000002 rti
19
20 ; --- Initialize device after RESET
21 rkinit:
22 002574 005037 002564 clr rkecnt
23 002600 000207 return
24
25 ; --- Restart new DMA transmission
26 rkgo:
27 ; read first sector into rkbuff
28 002602 005037 177412 clr @#rkbase+12 ; DA disk address = 0: unit 0, cyl/hd/sec=0
29 002606 012737 001562 177410 mov #rkbuff,@#rkbase+10 ; BA bus address of DMA
30 002614 012737 177400 177406 mov #-400,@#rkbase+6 ; WC word count = 256 words
31 002622 012737 000105 177404 mov #100+4+1,@#rkbase+4 ; Command INT ENABLE + "READ" + GO
32 002630 005237 002564 inc rkecnt ; register as event
33 002634 000207 return
34
34
211 .endc
212 000001 .if ne rlenab
213 .include ma_rl.mac
1 .title ma_rl - RL11/RL01/2 test driver
2
3 ; RL11 DMA is generated by reading cylinder 0, head0, sector 0
4
5 000160 rlvect = 160 ; vector of RL11 controller
6 174400 rlbase = 774400 ; base addr of RL11 controller
7 000114 rllabl = 'L ; label char
8
9
10 ; --- ISRs, increment Interrupt FLags
11 002636 000001 rliflg: .word 1 ; Interrupt flags
12
13 002640 rlbuff: .blkw 2*400+1 ; data buffer: 2 sector = 256 words
14
15 004642 000001 rlecnt: .word 1 ; event counter
16
17 rlisr:
18 004644 005237 002636 inc rliflg ; set ISR flag
19 004650 000002 rti
20
21 ; --- Initialize device after RESET
22 rlinit:
23 004652 005037 004642 clr rlecnt
24 004656 000207 return
25
26 ; --- Restart new DMA transmission
27 rlgo:
28 004660 012701 174400 mov #rlbase,r1 ; r1 = controller base address
29
29
185 .endc
186 000000 .if ne rkenab
187 .include ma_rk.mac
188 .endc
189 000000 .if ne rlenab
190 .include ma_rl.mac
191 .endc
192 000000 .if ne ryenab
193 .include ma_ry.mac
194 .endc
195 .include ma_strings.mac
30 ; sequence from boot loader 23-751A9, lot of testing
31 ; 1. get status
32 004664 012761 000013 000004 mov #013,4(r1) ; DA subcmd reset+getstatus
33 004672 012711 000004 mov #4,(r1) ; CSR do "GET STATUS"
34 004676 105711 1$: tstb (r1) ; test for ready
35 004700 100376 bpl 1$ ; wait
36 ; 2. read current track
37 004702 012711 000010 mov #10,(r1) ; CSR read header cmd
38 004706 105711 2$: tstb (r1) ; test for ready
39 004710 100376 bpl 2$ ; wait
40 ; 3. seek
41 004712 016102 000006 mov 6(r1),r2 ; MP retrieve cyl/head/sector
42 004716 042702 000077 bic #77,r2 ; set sector to zero
43 004722 005202 inc r2 ; set seek flag, head 0, seek to cyl 0
44 004724 010261 000004 mov r2,4(r1) ; DA for seek
45 004730 012711 000006 mov #6,(r1) ; CSR seek cmd
46 004734 105711 3$: tstb (r1) ; test for ready
47 004736 100376 bpl 3$ ; wait
48 ; 4. read sector 0+1 and interrupt
49 004740 012761 002640 000002 mov #rlbuff,2(r1) ; BA bus address of DMA
50 004746 005061 000004 clr 4(r1) ; DA select cyl0/head0/sector0
51 004752 012761 177000 000006 mov #-512.,6(r1) ; MP set word count
52 004760 012711 000114 mov #100+14,(r1) ; CSR read data cmd with Interrupt Enable
53
54 004764 005237 004642 inc rlecnt ; register as event
55 004770 000207 return
56
56
214 .endc
215 000000 .if ne ryenab
216 .include ma_ry.mac
217 .endc
218 000000 .if ne duenab
219 .include ma_du.mac
220 .endc
221 .include ma_strings.mac
1
2 .title ma_strings - String constants
3 shello:
4 001456 015 012 .byte 15,12 ; space, CR, LF,
5 001460 052 052 052 .ascii /*** Multi Device Interrupt&DMA test ***/
001463 040 115 165
001466 154 164 151
001471 040 104 145
001474 166 151 143
001477 145 040 111
001502 156 164 145
001505 162 162 165
001510 160 164 046
001513 104 115 101
001516 040 164 145
001521 163 164 040
001524 052 052 052
6 001527 015 012 .byte 15,12 ; CR, LF
7 001531 136 103 040 .ascii /^C to stop./
001534 164 157 040
001537 163 164 157
001542 160 056
8 001544 015 012 .byte 15,12 ; CR, LF
9 001546 000 .byte 0
4 004772 015 012 .byte 15,12 ; space, CR, LF,
5 004774 052 052 052 .ascii /*** Multi Device Interrupt&DMA test ***/
004777 040 115 165
005002 154 164 151
005005 040 104 145
005010 166 151 143
005013 145 040 111
005016 156 164 145
005021 162 162 165
005024 160 164 046
005027 104 115 101
005032 040 164 145
005035 163 164 040
005040 052 052 052
6 005043 015 012 .byte 15,12 ; CR, LF
7 005045 136 103 040 .ascii /^C to stop./
005050 164 157 040
005053 163 164 157
005056 160 056
8 005060 015 012 .byte 15,12 ; CR, LF
9 005062 000 .byte 0
10
11
12 sbye:
13 001547 015 012 .byte 15,12
14 001551 107 157 157 .ascii /Good Bye!/
001554 144 040 102
001557 171 145 041
15 001562 015 012 .byte 15,12 ; CR, LF
16 001564 000 .byte 0
13 005063 015 012 .byte 15,12
14 005065 107 157 157 .ascii /Good Bye!/
005070 144 040 102
005073 171 145 041
15 005076 015 012 .byte 15,12 ; CR, LF
16 005100 000 .byte 0
17
17
196
197 .end
198
199
200
200
222
223 .end
224
225
226
226

View File

@@ -4,8 +4,8 @@
; Exercises several devices in parallel,
; each with INTR and DMA
; For a device XX we have
; XXENAB - flag to enable devcie
; XXBASE - base address of devcie
; XXENAB - flag to enable device
; XXBASE - base address of device
; XXVEC - the INTR vector
; XXISR - Interrupt Service
; XXIFLG - flag which is incremented in ISR
@@ -20,12 +20,14 @@
; RK - RK11/RK05 disk
; RL - RL11/RL02 disk
; RY - Serial RX211 Floppy,
; DU - MSCP disk drive on UDA controller
; enable tests
kwenab = 1
rkenab = 0
rlenab = 0
ryenab = 0
rkenab = 1
rlenab = 1
ryenab = 0 ; not yet tested
duenab = 0 ; not yet implemeneted
.enable AMA
.asect
@@ -64,6 +66,12 @@ ryenab = 0
.word 340
.endc
.if ne duenab
. = duvect ; UDA MSCP controller
.word duisr
.word 340
.endc
psw = 177776
monitr = 165020 ; Monitor addr for back jump
@@ -90,6 +98,9 @@ start:
.if ne ryenab
call ryinit
.endc
.if ne duenab
call duinit
.endc
mov #shello,r1 ; Print "Hello" message
call puts
@@ -110,7 +121,7 @@ dokbd:
; process char in r0
cmpb r0,#3
bne 1$
mov #sbye,r1 ; ^C: print "Bye", back to monitor
mov #sbye,r1 ; ^C: print "Bye", back to monitor
call puts
jmp monitr
1$:
@@ -162,6 +173,16 @@ dodev:
mov #ryecnt,r1
call progrs
4$:
.endc
.if ne ryenab
tst duiflg
beq 5$
clr duiflg
call dugo
mov #dulabl,r0 ; progress printout
mov #duecnt,r1
call progrs
5$:
.endc
return
@@ -171,7 +192,9 @@ dodev:
; check if the counter with address in r1 is at
; 1024. if yes, print the char in r0
progrs:
bic #776000,(r1) ; mask counter to 0..1023
; bic #777700,(r1) ; mask counter to 0..63
bic #777400,(r1) ; mask counter to 0..255
; bic #776000,(r1) ; mask counter to 0..1023
bne 9$
call putc ; is at 0: print label character
9$:
@@ -191,6 +214,9 @@ progrs:
.endc
.if ne ryenab
.include ma_ry.mac
.endc
.if ne duenab
.include ma_du.mac
.endc
.include ma_strings.mac

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="cdt.managedbuild.toolchain.gnu.cross.base.632390496" name="Default">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-42900845109078397" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
</extension>
</configuration>
</project>

View File

@@ -161,8 +161,6 @@ void cpu_c::on_after_register_access(unibusdevice_register_t *device_reg,
UNUSED(unibus_control);
}
// CPU received interrupt vector from UNIBUS
// PRU triggers this via unibusadapter,
// mailbox->arbitrator.cpu_priority_level is CPU_PRIORITY_LEVEL_FETCHING

View File

@@ -1,249 +0,0 @@
#include "11.h"
#include "kd11b.h"
#include "args.h"
// in words
#define MEMSIZE (12*1024)
uint16 memory[MEMSIZE];
void
busadddev(Bus *bus, Busdev *dev)
{
Busdev **bp;
for(bp = &bus->devs; *bp; bp = &(*bp)->next)
;
*bp = dev;
dev->next = nil;
}
int
dati_bus(Bus *bus)
{
Busdev *bd;
for(bd = bus->devs; bd; bd = bd->next)
if(bd->dati(bus, bd->dev) == 0)
return 0;
return 1;
}
int
dato_bus(Bus *bus)
{
Busdev *bd;
for(bd = bus->devs; bd; bd = bd->next)
if(bd->dato(bus, bd->dev) == 0)
return 0;
return 1;
}
int
datob_bus(Bus *bus)
{
Busdev *bd;
for(bd = bus->devs; bd; bd = bd->next)
if(bd->datob(bus, bd->dev) == 0)
return 0;
return 1;
}
int dati_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 1; }
int dato_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 1; }
int datob_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 1; }
void reset_null(void *dev) { (void)dev; }
int svc_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 0; }
word
sgn(word w)
{
return (w>>15)&1;
}
word
sxt(byte b)
{
return (word)(int8_t)b;
}
void
loadmem(char *filename)
{
FILE *f;
char line[100], *s;
word w;
w = 0;
f = fopen(filename, "r");
if(f == nil)
return;
while(s = fgets(line, 100, f)){
while(isspace(*s)) s++;
if(*s == ':')
w = strtol(s+1, nil, 8)>>1;
if(*s >= '0' && *s <= '7')
memory[w++] = strtol(s, nil, 8);
}
fclose(f);
}
int
loadpt(char *filename)
{
FILE *f;
byte hi, lo, s;
word n, a, w;
f = fopen(filename, "rb");
if(f == nil){
printf("can't open %s\n", filename);
return 1;
}
for(;;){
s = 0;
if(fread(&lo, 1, 1, f) < 1) break;
if(lo != 1)
continue;
s += lo;
if(fread(&hi, 1, 1, f) < 1) break;
s += hi;
w = WD(hi, lo);
if(w != 1)
continue;
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(fread(&hi, 1, 1, f) < 1) goto botch;
s += hi;
n = WD(hi, lo);
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(fread(&hi, 1, 1, f) < 1) goto botch;
s += hi;
a = WD(hi, lo);
if(a == 1)
break;
if(n == 0)
continue;
n -= 6;
/* odd number of bytes is probably allowed but we can't do it */
if(n&1)
goto botch;
n >>= 1;
a >>= 1;
while(n--){
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(fread(&hi, 1, 1, f) < 1) goto botch;
s += hi;
w = WD(hi, lo);
memory[a++] = w;
}
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(s)
goto botch;
}
fclose(f);
return 0;
botch:
printf("paper tape botch\n");
fclose(f);
return 1;
}
void
dumpmem(word start, word end)
{
start >>= 1;
end >>= 1;
for(; start != end; start++)
printf("%06o: %06o\n", start<<1, memory[start]);
}
KD11B cpu;
Bus bus;
Memory memdev = { memory, 0, MEMSIZE };
Busdev membusdev = { nil, &memdev, dati_mem, dato_mem, datob_mem, svc_null, nil, reset_null };
KE11 ke11;
Busdev kebusdev = { nil, &ke11, dati_ke11, dato_ke11, datob_ke11, svc_null, nil, reset_ke11 };
char *argv0;
void
usage(void)
{
fprintf(stderr, "usage: %s\n", argv0);
exit(0);
}
#ifdef AUTODIAG
int diagpassed;
int
rundiag(KD11B *cpu, char *ptfile)
{
if(loadpt(ptfile)){
fprintf(stderr, "couldn't open file '%s'\n", ptfile);
return 1;
}
reset(cpu);
diagpassed = 0;
cpu->r[7] = 0200;
run(cpu);
if(diagpassed){
printf("passed %s\n", ptfile);
return 0;
}
return 1;
}
#endif
int
main(int argc, char *argv[])
{
memset(&cpu, 0, sizeof(KD11B));
memset(&bus, 0, sizeof(Bus));
cpu.bus = &bus;
busadddev(&bus, &membusdev);
busadddev(&bus, &kebusdev);
ARGBEGIN{
}ARGEND;
if(argc < 0)
usage();
loadmem("mem.txt");
reset(&cpu);
/* open a tty if it exists */
cpu.ttyfd = open("/tmp/tty", O_RDWR);
printf("tty connected to %d\n", cpu.ttyfd);
#ifdef AUTODIAG
if(rundiag(&cpu, "maindec/ZKAAA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKABA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKACA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKADA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAEA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAFA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAGA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAHA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAIA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAJA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAKA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKALA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAMA0.BIN")) return 0;
// if(rundiag(&cpu, "maindec/maindec-11-d0nc.pb.bin")) return 0;
printf("passed all diagnostics\n");
return 0;
#endif
cpu.r[7] = 0200;
// cpu.sw = 0104000;
run(&cpu);
return 0;
}

View File

@@ -1,775 +0,0 @@
#include "11.h"
#include "kd11b.h"
enum {
PSW_PR = 0340,
PSW_T = 020,
PSW_N = 010,
PSW_Z = 004,
PSW_V = 002,
PSW_C = 001,
};
enum {
TRAP_STACK = 1,
TRAP_PWR = 2, // can't happen
TRAP_BR7 = 4,
TRAP_BR6 = 010,
TRAP_CLK = 020,
TRAP_BR5 = 040,
TRAP_BR4 = 0100,
TRAP_RX = 0200,
TRAP_TX = 0400,
TRAP_CSTOP = 01000 // can't happen?
};
#define ISSET(f) ((cpu->psw&(f)) != 0)
enum {
STATE_HALTED = 0,
STATE_RUNNING,
STATE_WAITING
};
#define CLOCKFREQ (1000000000/60)
static struct timespec oldtime, newtime;
static void
initclock(void)
{
clock_gettime(CLOCK_REALTIME, &newtime);
oldtime = newtime;
}
static void
handleclock(KD11B *cpu)
{
struct timespec diff;
clock_gettime(CLOCK_REALTIME, &newtime);
diff.tv_sec = newtime.tv_sec - oldtime.tv_sec;
diff.tv_nsec = newtime.tv_nsec - oldtime.tv_nsec;
if(diff.tv_nsec < 0){
diff.tv_nsec += 1000000000;
diff.tv_sec -= 1;
}
if(diff.tv_nsec >= CLOCKFREQ){
cpu->lc_clock = 1;
cpu->lc_int = 1;
oldtime.tv_nsec += CLOCKFREQ;
if(oldtime.tv_nsec >= 1000000000){
oldtime.tv_nsec -= 1000000000;
oldtime.tv_sec += 1;
}
}
}
static uint32
ubxt(word a)
{
return (a&0160000)==0160000 ? a|0600000 : a;
}
void
tracestate(KD11B *cpu)
{
(void)cpu;
trace(" R0 %06o R1 %06o R2 %06o R3 %06o R4 %06o R5 %06o R6 %06o R7 %06o\n"
" 10 %06o 11 %06o 12 %06o 13 %06o 14 %06o 15 %06o 16 %06o 17 %06o\n"
" BA %06o IR %06o PSW %03o\n"
,
cpu->r[0], cpu->r[1], cpu->r[2], cpu->r[3],
cpu->r[4], cpu->r[5], cpu->r[6], cpu->r[7],
cpu->r[8], cpu->r[9], cpu->r[10], cpu->r[11],
cpu->r[12], cpu->r[13], cpu->r[14], cpu->r[15],
cpu->ba, cpu->ir, cpu->psw);
}
void
printstate(KD11B *cpu)
{
(void)cpu;
printf(" R0 %06o R1 %06o R2 %06o R3 %06o R4 %06o R5 %06o R6 %06o R7 %06o\n"
" 10 %06o 11 %06o 12 %06o 13 %06o 14 %06o 15 %06o 16 %06o 17 %06o\n"
" BA %06o IR %06o PSW %03o\n"
,
cpu->r[0], cpu->r[1], cpu->r[2], cpu->r[3],
cpu->r[4], cpu->r[5], cpu->r[6], cpu->r[7],
cpu->r[8], cpu->r[9], cpu->r[10], cpu->r[11],
cpu->r[12], cpu->r[13], cpu->r[14], cpu->r[15],
cpu->ba, cpu->ir, cpu->psw);
}
void
reset(KD11B *cpu)
{
Busdev *bd;
cpu->rcd_busy = 0;
cpu->rcd_rdr_enab = 0;
cpu->rcd_int_enab = 0;
cpu->rcd_int = 0;
cpu->rcd_da = 0;
cpu->rcd_b = 0;
cpu->xmit_int_enab = 0;
cpu->xmit_maint = 0;
cpu->xmit_int = 1;
cpu->xmit_tbmt = 1;
cpu->xmit_b = 0;
cpu->lc_int_enab = 0;
// TODO: 1?
cpu->lc_clock = 0;
cpu->lc_int = 0;
cpu->traps = 0;
for(bd = cpu->bus->devs; bd; bd = bd->next)
bd->reset(bd->dev);
}
int
dati(KD11B *cpu, int b)
{
trace("dati %06o: ", cpu->ba);
/* allow odd addresses for bytes and registers */
int alodd = b || cpu->ba >= 0177700 && cpu->ba < 0177720;
if(!alodd && cpu->ba&1)
goto be;
/* internal registers */
if((cpu->ba&0177400) == 0177400){
if((cpu->ba&0360) == 0300){
cpu->bus->data = cpu->r[cpu->ba&017];
goto ok;
}
switch(cpu->ba&0377){
/* Line clock */
case 0146:
cpu->bus->data = cpu->lc_int_enab<<6 |
cpu->lc_clock<<7;
goto ok;
/* Receive */
case 0160:
cpu->bus->data = cpu->rcd_int_enab<<6 |
cpu->rcd_int<<7 |
cpu->rcd_busy<<1;
goto ok;
case 0162:
cpu->bus->data = cpu->rcd_b;
cpu->rcd_b = 0;
cpu->rcd_da = 0;
cpu->rcd_int = 0;
goto ok;
/* Transmit */
case 0164:
cpu->bus->data = cpu->xmit_maint<<2 |
cpu->xmit_int_enab<<6 |
cpu->xmit_int<<7;
goto ok;
case 0166:
/* write only */
cpu->bus->data = 0;
goto ok;
case 0170: case 0171:
cpu->bus->data = cpu->sw;
goto ok;
case 0376: case 0377:
cpu->bus->data = cpu->psw;
goto ok;
/* respond but don't return real data */
case 0147:
case 0161:
case 0163:
case 0165:
case 0167:
cpu->bus->data = 0;
goto ok;
}
}
cpu->bus->addr = ubxt(cpu->ba)&~1;
if(dati_bus(cpu->bus))
goto be;
ok:
trace("%06o\n", cpu->bus->data);
cpu->be = 0;
return 0;
be:
trace("BE\n");
cpu->be++;
return 1;
}
int
dato(KD11B *cpu, int b)
{
trace("dato %06o %06o %d\n", cpu->ba, cpu->bus->data, b);
/* allow odd addresses for bytes and registers */
int alodd = b || cpu->ba >= 0177700 && cpu->ba < 0177720;
if(!alodd && cpu->ba&1)
goto be;
/* internal registers */
if((cpu->ba&0177400) == 0177400){
if((cpu->ba&0360) == 0300){
/* no idea if byte access even makes sense here */
cpu->r[cpu->ba&017] = cpu->bus->data;
goto ok;
}
switch(cpu->ba&0377){
/* Line clock */
case 0146:
cpu->lc_int_enab = cpu->bus->data>>6 & 1;
if((cpu->bus->data & 0200) == 0){
cpu->lc_clock = 0;
cpu->lc_int = 0;
}
goto ok;
/* Receive */
case 0160:
// TODO: RDR ENAB
cpu->rcd_rdr_enab = cpu->bus->data & 1;
if(!cpu->rcd_int_enab && cpu->bus->data&0100 && cpu->rcd_da)
cpu->rcd_int = 1;
cpu->rcd_int_enab = cpu->bus->data>>6 & 1;
goto ok;
case 0162:
/* read only */
goto ok;
/* Transmit */
case 0164:
// TODO: MAINT
cpu->xmit_maint = cpu->bus->data>>2 & 1;
if(!cpu->xmit_int_enab && cpu->bus->data&0100 && cpu->xmit_tbmt)
cpu->xmit_int = 1;
cpu->xmit_int_enab = cpu->bus->data>>6 & 1;
goto ok;
case 0166:
cpu->xmit_b = cpu->bus->data;
cpu->xmit_tbmt = 0;
cpu->xmit_int = 0;
goto ok;
case 0170: case 0171:
/* can't write switches */
goto ok;
case 0376: case 0377:
/* writes 0 for the odd byte.
I think this is correct. */
cpu->psw = cpu->bus->data;
goto ok;
/* respond but don't do anything */
case 0147:
case 0161:
case 0163:
case 0165:
case 0167:
goto ok;
}
}
if(b){
cpu->bus->addr = ubxt(cpu->ba);
if(datob_bus(cpu->bus))
goto be;
}else{
cpu->bus->addr = ubxt(cpu->ba)&~1;
if(dato_bus(cpu->bus))
goto be;
}
ok:
cpu->be = 0;
return 0;
be:
cpu->be++;
return 1;
}
static void
svc(KD11B *cpu, Bus *bus)
{
int l;
Busdev *bd;
static int brtraps[4] = { TRAP_BR4, TRAP_BR5, TRAP_BR6, TRAP_BR7 };
for(l = 0; l < 4; l++){
cpu->br[l].bg = nil;
cpu->br[l].dev = nil;
}
cpu->traps &= ~(TRAP_BR4|TRAP_BR5|TRAP_BR6|TRAP_BR7);
for(bd = bus->devs; bd; bd = bd->next){
l = bd->svc(bus, bd->dev);
if(l >= 4 && l <= 7 && cpu->br[l-4].bg == nil){
cpu->br[l-4].bg = bd->bg;
cpu->br[l-4].dev = bd->dev;
cpu->traps |= brtraps[l-4];
}
}
}
static int
addrop(KD11B *cpu, int m, int b)
{
int r;
int ai;
r = m&7;
m >>= 3;
ai = 1 + (!b || (r&6)==6 || m&1);
if(m == 0)
return 0;
switch(m&6){
case 0: // REG
cpu->b = cpu->ba = cpu->r[r];
return 0; // this already is mode 1
case 2: // INC
cpu->ba = cpu->r[r];
cpu->b = cpu->r[r] = cpu->r[r] + ai;
break;
case 4: // DEC
cpu->b = cpu->ba = cpu->r[r]-ai;
if(r == 6 && (cpu->ba&~0377) == 0) cpu->traps |= TRAP_STACK;
cpu->r[r] = cpu->ba;
break;
case 6: // INDEX
cpu->ba = cpu->r[7];
cpu->r[7] += 2;
if(dati(cpu, 0)) return 1;
cpu->b = cpu->ba = cpu->bus->data + cpu->r[r];
break;
}
if(m&1){
if(dati(cpu, 0)) return 1;
cpu->b = cpu->ba = cpu->bus->data;
}
return 0;
}
static int
fetchop(KD11B *cpu, int t, int m, int b)
{
int r;
r = m&7;
if((m&070) == 0)
cpu->r[t] = cpu->r[r];
else{
if(dati(cpu, b)) return 1;
cpu->r[t] = cpu->bus->data;
if(b && cpu->ba&1) cpu->r[t] = cpu->r[t]>>8;
}
if(b) cpu->r[t] = sxt(cpu->r[t]);
return 0;
}
static int
readop(KD11B *cpu, int t, int m, int b)
{
return !(addrop(cpu, m, b) == 0 && fetchop(cpu, t, m, b) == 0);
}
static int
writedest(KD11B *cpu, word v, int b)
{
int d;
if((cpu->ir & 070) == 0){
d = cpu->ir & 7;
if(b) SETMASK(cpu->r[d], v, 0377);
else cpu->r[d] = v;
}else{
if(cpu->ba&1) v <<= 8;
cpu->bus->data = v;
if(dato(cpu, b)) return 1;
}
return 0;
}
static void
setnz(KD11B *cpu, word w)
{
cpu->psw &= ~(PSW_N|PSW_Z);
if(w & 0100000) cpu->psw |= PSW_N;
if(w == 0) cpu->psw |= PSW_Z;
}
void
step(KD11B *cpu)
{
uint by;
uint br;
uint b;
uint c;
uint src, dst, sf, df, dm;
word mask, sign;
int inhov;
byte oldpsw;
// trace("fetch from %06o\n", cpu->r[7]);
// printstate(cpu);
#define SP cpu->r[6]
#define PC cpu->r[7]
#define SR cpu->r[010]
#define DR cpu->r[011]
#define TV cpu->r[012]
#define BA cpu->ba
#define PSW cpu->psw
#define RD_B if(readop(cpu, 010, src, by)) goto be; if(readop(cpu, 011, dst, by)) goto be
#define RD_U if(readop(cpu, 011, dst, by)) goto be; SR = DR
#define WR if(writedest(cpu, b, by)) goto be
#define NZ setnz(cpu, b)
#define SVC goto service
#define TRAP(v) TV = v; goto trap
#define CLV cpu->psw &= ~PSW_V
#define CLCV cpu->psw &= ~(PSW_V|PSW_C)
#define SEV cpu->psw |= PSW_V
#define SEC cpu->psw |= PSW_C
#define C if(b & 0200000) SEC
#define NC if((b & 0200000) == 0) SEC
#define BXT if(by) b = sxt(b)
#define BR PC += br
#define CBR(c) if(((c)>>(cpu->psw&017)) & 1) BR
#define PUSH SP -= 2; if(!inhov && (SP&~0377) == 0) cpu->traps |= TRAP_STACK
#define POP SP += 2
#define OUT(a,d) cpu->ba = (a); cpu->bus->data = (d); if(dato(cpu, 0)) goto be
#define IN(d) if(dati(cpu, 0)) goto be; d = cpu->bus->data
#define INA(a,d) cpu->ba = a; if(dati(cpu, 0)) goto be; d = cpu->bus->data
#define TR(m) trace("%06o "#m"\n", PC-2)
#define TRB(m) trace("%06o "#m"%s\n", PC-2, by ? "B" : "")
oldpsw = PSW;
INA(PC, cpu->ir);
PC += 2; /* don't increment on bus error! */
by = !!(cpu->ir&B15);
br = sxt(cpu->ir)<<1;
src = cpu->ir>>6 & 077;
sf = src & 7;
dst = cpu->ir & 077;
df = dst & 7;
dm = dst>>3 & 7;
if(by) mask = M8, sign = B7;
else mask = M16, sign = B15;
inhov = 0;
/* Binary */
switch(cpu->ir & 0170000){
case 0110000: case 0010000: TRB(MOV);
if(readop(cpu, 010, src, by)) goto be;
if(addrop(cpu, dst, by)) goto be;
if(dm && fetchop(cpu, 011, dst, by)) goto be;
CLV;
b = SR; NZ;
if(dm==0) cpu->r[df] = SR;
else writedest(cpu, SR, by);
SVC;
case 0120000: case 0020000: TRB(CMP);
RD_B; CLCV;
b = SR + W(~DR) + 1; NC; BXT;
if(sgn((SR ^ DR) & ~(DR ^ b))) SEV;
NZ; SVC;
case 0130000: case 0030000: TRB(BIT);
RD_B; CLV;
b = DR & SR;
NZ; SVC;
case 0140000: case 0040000: TRB(BIC);
RD_B; CLV;
b = DR & ~SR;
NZ; WR; SVC;
case 0150000: case 0050000: TRB(BIS);
RD_B; CLV;
b = DR | SR;
NZ; WR; SVC;
case 0060000: TR(ADD);
by = 0; RD_B; CLCV;
b = SR + DR; C;
if(sgn(~(SR ^ DR) & (DR ^ b))) SEV;
NZ; WR; SVC;
case 0160000: TR(SUB);
by = 0; RD_B; CLCV;
b = DR + W(~SR) + 1; NC;
if(sgn((SR ^ DR) & (DR ^ b))) SEV;
NZ; WR; SVC;
/* Reserved instructions */
case 0170000: case 0070000: goto ri;
}
/* Unary */
switch(cpu->ir & 0007700){
case 0005000: TRB(CLR);
RD_U; CLCV;
b = 0;
NZ; WR; SVC;
case 0005100: TRB(COM);
RD_U; CLV; SEC;
b = W(~SR);
NZ; WR; SVC;
case 0005200: TRB(INC);
RD_U; CLV;
b = W(SR+1); BXT;
if(sgn(~SR&b)) SEV;
NZ; WR; SVC;
case 0005300: TRB(DEC);
RD_U; CLV;
b = W(SR+~0); BXT;
if(sgn(SR&~b)) SEV;
NZ; WR; SVC;
case 0005400: TRB(NEG);
RD_U; CLCV;
b = W(~SR+1); BXT; if(b) SEC;
if(sgn(b&SR)) SEV;
NZ; WR; SVC;
case 0005500: TRB(ADC);
RD_U; c = ISSET(PSW_C); CLCV;
b = SR + c; C; BXT;
if(sgn(~SR&b)) SEV;
NZ; WR; SVC;
case 0005600: TRB(SBC);
RD_U; c = !ISSET(PSW_C)-1; CLCV;
b = W(SR+c); if(c && SR == 0) SEC; BXT;
if(sgn(SR&~b)) SEV;
NZ; WR; SVC;
case 0005700: TRB(TST);
RD_U; CLCV;
b = SR;
NZ; SVC;
case 0006000: TRB(ROR);
RD_U; c = ISSET(PSW_C); CLCV;
b = (SR&mask) >> 1; if(c) b |= sign; if(SR & 1) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006100: TRB(ROL);
RD_U; c = ISSET(PSW_C); CLCV;
b = (SR<<1) & mask; if(c) b |= 1; if(SR & B15) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006200: TRB(ASR);
RD_U; c = ISSET(PSW_C); CLCV;
b = W(SR>>1) | SR&B15; if(SR & 1) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006300: TRB(ASL);
RD_U; CLCV;
b = W(SR<<1); if(SR & B15) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006400:
case 0006500:
case 0006600:
case 0006700:
goto ri;
}
switch(cpu->ir & 0107400){
case 0004000:
case 0004400: TR(JSR);
if(dm == 0) goto ill;
if(addrop(cpu, dst, 0)) goto be;
DR = cpu->b;
PUSH; OUT(SP, cpu->r[sf]);
cpu->r[sf] = PC; PC = DR;
SVC;
case 0104000: TR(EMT); TRAP(030);
case 0104400: TR(TRAP); TRAP(034);
}
/* Branches */
switch(cpu->ir & 0103400){
case 0000400: TR(BR); BR; SVC;
case 0001000: TR(BNE); CBR(0x0F0F); SVC;
case 0001400: TR(BEQ); CBR(0xF0F0); SVC;
case 0002000: TR(BGE); CBR(0xCC33); SVC;
case 0002400: TR(BLT); CBR(0x33CC); SVC;
case 0003000: TR(BGT); CBR(0x0C03); SVC;
case 0003400: TR(BLE); CBR(0xF3FC); SVC;
case 0100000: TR(BPL); CBR(0x00FF); SVC;
case 0100400: TR(BMI); CBR(0xFF00); SVC;
case 0101000: TR(BHI); CBR(0x0505); SVC;
case 0101400: TR(BLOS); CBR(0xFAFA); SVC;
case 0102000: TR(BVC); CBR(0x3333); SVC;
case 0102400: TR(BVS); CBR(0xCCCC); SVC;
case 0103000: TR(BCC); CBR(0x5555); SVC;
case 0103400: TR(BCS); CBR(0xAAAA); SVC;
}
// Hope we caught all instructions we meant to
assert((cpu->ir & 0177400) == 0);
/* Misc */
switch(cpu->ir & 0300){
case 0100: TR(JMP);
if(dm == 0) goto ill;
if(addrop(cpu, dst, 0)) goto be;
PC = cpu->b;
SVC;
case 0200:
switch(cpu->ir&070){
case 000: TR(RTS);
BA = SP; POP;
PC = cpu->r[df];
IN(cpu->r[df]);
SVC;
case 010: case 020: case 030:
goto ri;
case 040: case 050: TR(CCC); PSW &= ~(cpu->ir&017); SVC;
case 060: case 070: TR(SEC); PSW |= cpu->ir&017; SVC;
}
case 0300: TR(SWAB);
if(readop(cpu, 011, dst, by)) goto be;
CLCV;
b = WD(DR & 0377, (DR>>8) & 0377);
NZ; WR; SVC;
}
/* Operate */
switch(cpu->ir & 7){
case 0: TR(HALT); cpu->state = STATE_HALTED; return;
case 1: TR(WAIT); cpu->state = STATE_WAITING; return;
case 2: TR(RTI);
BA = SP; POP; IN(PC);
BA = SP; POP; IN(PSW);
SVC;
case 3: TR(BPT); TRAP(014);
case 4: TR(IOT); TRAP(020);
case 5: TR(RESET); reset(cpu); SVC;
}
// All other instructions should be reserved now
ri: TRAP(010);
ill: TRAP(4);
be: if(cpu->be > 1){
printf("double bus error, HALT\n");
cpu->state = STATE_HALTED;
return;
}
printf("bus error\n");
TRAP(4);
trap:
trace("TRAP %o\n", TV);
PUSH; OUT(SP, PSW);
PUSH; OUT(SP, PC);
INA(TV, PC);
INA(TV+2, PSW);
/* no trace trap after a trap */
oldpsw = PSW;
tracestate(cpu);
SVC;
service:
c = PSW >> 5;
if(oldpsw & PSW_T){
oldpsw &= ~PSW_T;
TRAP(014);
}else if(cpu->traps & TRAP_STACK){
cpu->traps &= ~TRAP_STACK;
inhov = 1;
TRAP(4);
}else if(cpu->traps & TRAP_PWR){
cpu->traps &= ~TRAP_PWR;
TRAP(024);
}else if(c < 7 && cpu->traps & TRAP_BR7){
cpu->traps &= ~TRAP_BR7;
TRAP(cpu->br[3].bg(cpu->br[3].dev));
}else if(c < 6 && cpu->traps & TRAP_BR6){
cpu->traps &= ~TRAP_BR6;
TRAP(cpu->br[2].bg(cpu->br[2].dev));
}else if(c < 6 && cpu->traps & TRAP_CLK){
cpu->traps &= ~TRAP_CLK;
cpu->lc_int = 0;
TRAP(0100);
}else if(c < 5 && cpu->traps & TRAP_BR5){
cpu->traps &= ~TRAP_BR5;
TRAP(cpu->br[1].bg(cpu->br[1].dev));
}else if(c < 4 && cpu->traps & TRAP_BR4){
cpu->traps &= ~TRAP_BR4;
TRAP(cpu->br[0].bg(cpu->br[0].dev));
}else if(c < 4 && cpu->traps & TRAP_RX){
cpu->traps &= ~TRAP_RX;
cpu->rcd_int = 0;
TRAP(060);
}else if(c < 4 && cpu->traps & TRAP_TX){
cpu->traps &= ~TRAP_TX;
cpu->xmit_int = 0;
TRAP(064);
}else
// TODO? console stop
/* fetch next instruction */
return;
}
void
run(KD11B *cpu)
{
int n;
cpu->state = STATE_RUNNING;
initclock();
n = 0;
while(cpu->state != STATE_HALTED){
handleclock(cpu);
cpu->traps &= ~TRAP_CLK;
if(cpu->lc_int && cpu->lc_int_enab)
cpu->traps |= TRAP_CLK;
cpu->traps &= ~TRAP_TX;
if(cpu->xmit_int && cpu->xmit_int_enab)
cpu->traps |= TRAP_TX;
cpu->traps &= ~TRAP_RX;
if(cpu->rcd_int && cpu->rcd_int_enab)
cpu->traps |= TRAP_RX;
svc(cpu, cpu->bus);
if(cpu->state == STATE_RUNNING ||
cpu->state == STATE_WAITING && cpu->traps){
cpu->state = STATE_RUNNING;
step(cpu);
}
// Don't handle IO all the time
n++;
if(n != 20)
continue;
n = 0;
/* transmit */
if(!cpu->xmit_tbmt){
uint8 c = cpu->xmit_b & 0177;
write(cpu->ttyfd, &c, 1);
#ifdef AUTODIAG
extern int diagpassed;
if(c == '\a'){
diagpassed = 1;
return;
}
#endif
cpu->xmit_tbmt = 1;
cpu->xmit_int = 1;
}
/* receive */
if(hasinput(cpu->ttyfd)){
cpu->rcd_busy = 1;
cpu->rcd_rdr_enab = 0;
read(cpu->ttyfd, &cpu->rcd_b, 1);
cpu->rcd_da = 1;
cpu->rcd_busy = 0;
cpu->rcd_int = 1;
}
}
printstate(cpu);
}

View File

@@ -1,45 +0,0 @@
// 11/05 cpu
typedef struct KD11B KD11B;
struct KD11B
{
word r[16];
word b; // B register before BUT JSRJMP
word ba;
word ir;
Bus *bus;
byte psw;
int traps;
int be;
int state;
struct {
int (*bg)(void *dev);
void *dev;
} br[4];
word sw;
/* line clock */
int lc_int_enab;
int lc_clock;
int lc_int;
/* keyboard */
int rcd_busy;
int rcd_rdr_enab;
int rcd_int_enab;
int rcd_int;
int rcd_da;
byte rcd_b;
/* printer */
int xmit_int_enab;
int xmit_maint;
int xmit_int;
int xmit_tbmt;
byte xmit_b;
int ttyfd;
};
void run(KD11B *cpu);
void reset(KD11B *cpu);

View File

@@ -1,85 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
typedef uint8_t uint8, byte;
typedef uint16_t uint16, word;
typedef uint32_t uint32;
#define WD(hi, lo) W((hi)<<8 | (lo))
#define W(w) ((word)(w))
#define M8 0377
#define M16 0177777
#define B7 0000200
#define B15 0100000
#define nil NULL
#define SETMASK(l, r, m) l = ((l)&~(m) | (r)&(m))
//#define trace printf
#define trace(...)
int hasinput(int fd);
int dial(char *host, int port);
void serve(int port, void (*handlecon)(int, void*), void *arg);
void nodelay(int fd);
word sgn(word w);
word sxt(byte b);
typedef struct Bus Bus;
typedef struct Busdev Busdev;
struct Busdev
{
Busdev *next;
void *dev;
int (*dati)(Bus *bus, void *dev);
int (*dato)(Bus *bus, void *dev);
int (*datob)(Bus *bus, void *dev);
int (*svc)(Bus *bus, void *dev);
int (*bg)(void *dev);
void (*reset)(void *dev);
};
void reset_null(void *dev);
struct Bus
{
Busdev *devs;
uint32 addr;
word data;
};
int dati_bus(Bus *bus);
int dato_bus(Bus *bus);
int datob_bus(Bus *bus);
typedef struct Memory Memory;
struct Memory
{
word *mem;
uint32 start, end;
};
int dati_mem(Bus *bus, void *dev);
int dato_mem(Bus *bus, void *dev);
int datob_mem(Bus *bus, void *dev);
typedef struct KE11 KE11;
struct KE11
{
word ac;
word mq;
word x;
byte sc; /* 6 bits */
byte sr;
};
int dati_ke11(Bus *bus, void *dev);
int dato_ke11(Bus *bus, void *dev);
int datob_ke11(Bus *bus, void *dev);
void reset_ke11(void *dev);

View File

@@ -1,249 +0,0 @@
#include "11.h"
#include "kd11b.h"
#include "args.h"
// in words
#define MEMSIZE (12*1024)
uint16 memory[MEMSIZE];
void
busadddev(Bus *bus, Busdev *dev)
{
Busdev **bp;
for(bp = &bus->devs; *bp; bp = &(*bp)->next)
;
*bp = dev;
dev->next = nil;
}
int
dati_bus(Bus *bus)
{
Busdev *bd;
for(bd = bus->devs; bd; bd = bd->next)
if(bd->dati(bus, bd->dev) == 0)
return 0;
return 1;
}
int
dato_bus(Bus *bus)
{
Busdev *bd;
for(bd = bus->devs; bd; bd = bd->next)
if(bd->dato(bus, bd->dev) == 0)
return 0;
return 1;
}
int
datob_bus(Bus *bus)
{
Busdev *bd;
for(bd = bus->devs; bd; bd = bd->next)
if(bd->datob(bus, bd->dev) == 0)
return 0;
return 1;
}
int dati_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 1; }
int dato_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 1; }
int datob_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 1; }
void reset_null(void *dev) { (void)dev; }
int svc_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 0; }
word
sgn(word w)
{
return (w>>15)&1;
}
word
sxt(byte b)
{
return (word)(int8_t)b;
}
void
loadmem(char *filename)
{
FILE *f;
char line[100], *s;
word w;
w = 0;
f = fopen(filename, "r");
if(f == nil)
return;
while(s = fgets(line, 100, f)){
while(isspace(*s)) s++;
if(*s == ':')
w = strtol(s+1, nil, 8)>>1;
if(*s >= '0' && *s <= '7')
memory[w++] = strtol(s, nil, 8);
}
fclose(f);
}
int
loadpt(char *filename)
{
FILE *f;
byte hi, lo, s;
word n, a, w;
f = fopen(filename, "rb");
if(f == nil){
printf("can't open %s\n", filename);
return 1;
}
for(;;){
s = 0;
if(fread(&lo, 1, 1, f) < 1) break;
if(lo != 1)
continue;
s += lo;
if(fread(&hi, 1, 1, f) < 1) break;
s += hi;
w = WD(hi, lo);
if(w != 1)
continue;
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(fread(&hi, 1, 1, f) < 1) goto botch;
s += hi;
n = WD(hi, lo);
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(fread(&hi, 1, 1, f) < 1) goto botch;
s += hi;
a = WD(hi, lo);
if(a == 1)
break;
if(n == 0)
continue;
n -= 6;
/* odd number of bytes is probably allowed but we can't do it */
if(n&1)
goto botch;
n >>= 1;
a >>= 1;
while(n--){
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(fread(&hi, 1, 1, f) < 1) goto botch;
s += hi;
w = WD(hi, lo);
memory[a++] = w;
}
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(s)
goto botch;
}
fclose(f);
return 0;
botch:
printf("paper tape botch\n");
fclose(f);
return 1;
}
void
dumpmem(word start, word end)
{
start >>= 1;
end >>= 1;
for(; start != end; start++)
printf("%06o: %06o\n", start<<1, memory[start]);
}
KD11B cpu;
Bus bus;
Memory memdev = { memory, 0, MEMSIZE };
Busdev membusdev = { nil, &memdev, dati_mem, dato_mem, datob_mem, svc_null, nil, reset_null };
KE11 ke11;
Busdev kebusdev = { nil, &ke11, dati_ke11, dato_ke11, datob_ke11, svc_null, nil, reset_ke11 };
char *argv0;
void
usage(void)
{
fprintf(stderr, "usage: %s\n", argv0);
exit(0);
}
#ifdef AUTODIAG
int diagpassed;
int
rundiag(KD11B *cpu, char *ptfile)
{
if(loadpt(ptfile)){
fprintf(stderr, "couldn't open file '%s'\n", ptfile);
return 1;
}
reset(cpu);
diagpassed = 0;
cpu->r[7] = 0200;
run(cpu);
if(diagpassed){
printf("passed %s\n", ptfile);
return 0;
}
return 1;
}
#endif
int
main(int argc, char *argv[])
{
memset(&cpu, 0, sizeof(KD11B));
memset(&bus, 0, sizeof(Bus));
cpu.bus = &bus;
busadddev(&bus, &membusdev);
busadddev(&bus, &kebusdev);
ARGBEGIN{
}ARGEND;
if(argc < 0)
usage();
loadmem("mem.txt");
reset(&cpu);
/* open a tty if it exists */
cpu.ttyfd = open("/tmp/tty", O_RDWR);
printf("tty connected to %d\n", cpu.ttyfd);
#ifdef AUTODIAG
if(rundiag(&cpu, "maindec/ZKAAA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKABA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKACA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKADA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAEA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAFA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAGA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAHA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAIA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAJA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAKA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKALA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAMA0.BIN")) return 0;
// if(rundiag(&cpu, "maindec/maindec-11-d0nc.pb.bin")) return 0;
printf("passed all diagnostics\n");
return 0;
#endif
cpu.r[7] = 0200;
// cpu.sw = 0104000;
run(&cpu);
return 0;
}

View File

@@ -1,257 +0,0 @@
#include "11.h"
#include "ka11.h"
#include "kw11.h"
#include "kl11.h"
#include "args.h"
// in words
#define MEMSIZE (12*1024)
uint16 memory[MEMSIZE];
void
busadddev(Bus *bus, Busdev *dev)
{
Busdev **bp;
for(bp = &bus->devs; *bp; bp = &(*bp)->next)
;
*bp = dev;
dev->next = nil;
}
int
dati_bus(Bus *bus)
{
Busdev *bd;
for(bd = bus->devs; bd; bd = bd->next)
if(bd->dati(bus, bd->dev) == 0)
return 0;
return 1;
}
int
dato_bus(Bus *bus)
{
Busdev *bd;
for(bd = bus->devs; bd; bd = bd->next)
if(bd->dato(bus, bd->dev) == 0)
return 0;
return 1;
}
int
datob_bus(Bus *bus)
{
Busdev *bd;
for(bd = bus->devs; bd; bd = bd->next)
if(bd->datob(bus, bd->dev) == 0)
return 0;
return 1;
}
int dati_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 1; }
int dato_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 1; }
int datob_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 1; }
void reset_null(void *dev) { (void)dev; }
int svc_null(Bus *bus, void *dev) { (void)bus; (void)dev; return 0; }
word
sgn(word w)
{
return (w>>15)&1;
}
word
sxt(byte b)
{
return (word)(int8_t)b;
}
void
loadmem(char *filename)
{
FILE *f;
char line[100], *s;
word w;
w = 0;
f = fopen(filename, "r");
if(f == nil)
return;
while(s = fgets(line, 100, f)){
while(isspace(*s)) s++;
if(*s == ':')
w = strtol(s+1, nil, 8)>>1;
if(*s >= '0' && *s <= '7')
memory[w++] = strtol(s, nil, 8);
}
fclose(f);
}
int
loadpt(char *filename)
{
FILE *f;
byte hi, lo, s;
word n, a, w;
f = fopen(filename, "rb");
if(f == nil){
printf("can't open %s\n", filename);
return 1;
}
for(;;){
s = 0;
if(fread(&lo, 1, 1, f) < 1) break;
if(lo != 1)
continue;
s += lo;
if(fread(&hi, 1, 1, f) < 1) break;
s += hi;
w = WD(hi, lo);
if(w != 1)
continue;
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(fread(&hi, 1, 1, f) < 1) goto botch;
s += hi;
n = WD(hi, lo);
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(fread(&hi, 1, 1, f) < 1) goto botch;
s += hi;
a = WD(hi, lo);
if(a == 1)
break;
if(n == 0)
continue;
n -= 6;
/* odd number of bytes is probably allowed but we can't do it */
if(n&1)
goto botch;
n >>= 1;
a >>= 1;
while(n--){
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(fread(&hi, 1, 1, f) < 1) goto botch;
s += hi;
w = WD(hi, lo);
memory[a++] = w;
}
if(fread(&lo, 1, 1, f) < 1) goto botch;
s += lo;
if(s)
goto botch;
}
fclose(f);
return 0;
botch:
printf("paper tape botch\n");
fclose(f);
return 1;
}
void
dumpmem(word start, word end)
{
start >>= 1;
end >>= 1;
for(; start != end; start++)
printf("%06o: %06o\n", start<<1, memory[start]);
}
KA11 cpu;
Bus bus;
KW11 kw11;
KL11 kl11;
Memory memdev = { memory, 0, MEMSIZE };
Busdev membusdev = { nil, &memdev, dati_mem, dato_mem, datob_mem, svc_null, nil, reset_null };
KE11 ke11;
Busdev kebusdev = { nil, &ke11, dati_ke11, dato_ke11, datob_ke11, svc_null, nil, reset_ke11 };
Busdev klbusdev = { nil, &kl11, dati_kl11, dato_kl11, datob_kl11, svc_kl11, bg_kl11, reset_kl11 };
Busdev kwbusdev = { nil, &kw11, dati_kw11, dato_kw11, datob_kw11, svc_kw11, bg_kw11, reset_kw11 };
char *argv0;
void
usage(void)
{
fprintf(stderr, "usage: %s\n", argv0);
exit(0);
}
#ifdef AUTODIAG
int diagpassed;
int
rundiag(KA11 *cpu, char *ptfile)
{
if(loadpt(ptfile)){
fprintf(stderr, "couldn't open file '%s'\n", ptfile);
return 1;
}
reset(cpu);
diagpassed = 0;
cpu->r[7] = 0200;
run(cpu);
if(diagpassed){
printf("passed %s\n", ptfile);
return 0;
}
return 1;
}
#endif
int
main(int argc, char *argv[])
{
memset(&cpu, 0, sizeof(KA11));
memset(&bus, 0, sizeof(Bus));
cpu.bus = &bus;
busadddev(&bus, &membusdev);
busadddev(&bus, &kwbusdev);
busadddev(&bus, &klbusdev);
busadddev(&bus, &kebusdev);
ARGBEGIN{
}ARGEND;
if(argc < 0)
usage();
loadmem("mem.txt");
reset(&cpu);
/* open a tty if it exists */
kl11.ttyfd = open("/tmp/tty", O_RDWR);
printf("tty connected to %d\n", kl11.ttyfd);
#ifdef AUTODIAG
if(rundiag(&cpu, "maindec/ZKAAA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKABA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKACA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKADA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAEA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAFA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAGA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAHA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAIA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAJA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAKA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKALA0.BIN")) return 0;
if(rundiag(&cpu, "maindec/ZKAMA0.BIN")) return 0;
// if(rundiag(&cpu, "maindec/maindec-11-d0nc.pb.bin")) return 0;
printf("passed all diagnostics\n");
return 0;
#endif
cpu.r[7] = 0200;
// cpu.sw = 0104000;
run(&cpu);
return 0;
}

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2019
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,22 +0,0 @@
CFLAGS=-fno-diagnostics-color -fno-diagnostics-show-caret -DAUTODIAG -O3
all: pdp1145 pdp1105 pdp1120
pdp1145: u_kb11a.o
$(CC) $(CFLAGS) -o $@ $^
pdp1105: 1105.o kd11b.o eae.o mem.o util.o
$(CC) $(CFLAGS) -o $@ $^
1105.o: 11.h kd11b.h
pdp1120: 1120.o ka11.o kw11.o kl11.o eae.o mem.o util.o
$(CC) $(CFLAGS) -o $@ $^
1120.o: 11.h ka11.h
ka11.o: 11.h ka11.h
kd11b.o: 11.h kd11b.h
kw11.o: 11.h kw11.h
kl11.o: 11.h kl11.h
eae.o: 11.h
mem.o: 11.h
util.o: 11.h

View File

@@ -1,42 +0,0 @@
This repo contains the source code for my PDP-11 emulation endeavours.
Contents
========
* a PDP-11/05 cpu (KD11B) implemented from the microcode listing, but not emulating the actual microcode. Passing ZKAAA-ZKAMA.
This is based on the code I wrote for the [Knight TV emulation](https://github.com/aap/tv11)
* a PDP-11/20 cpu (KA11) as a modified KD11B. Not implemented from the schematics (yet?). Passing ZKAAA-ZKAMA.
* the beginnings of a PDP-11/45 (KB11A) cpu. Implemented from the schematics and running the microcode. This machine is a beast so it doesn't do a whole lot at all yet.
* KL11 console
* KW11 line clock
* KE11 extended arithmetic unit implemented from the algorithm explanation in the manual. Not tested terribly well.
* simple memory
Plan
====
What I'd like is accurate emulation of the early PDP-11 cpus,
i.e. 11/05, 11/20, 11/40, 11/45, 11/70,
and at least the most important peripherals.
For the 11/45 and /70 (KB11 based) I want microcode emulation
to drive a [PiDP-11](http://obsolescence.wixsite.com/obsolescence/pidp-11) panel super duper accurately.
For the other machines microcode emulation would be interesting as well
but it's not quite as important to me.
Another goal is to have these work on an actual Unibus with
Jörg Hoppe's [Unibone](http://retrocmp.com/projects/unibone).
In fact, the 11/20 was made to work in a couple of hours
when we noticed we had implemented almost the same unibus interface
and could just hook up my code as a unibone device.
Notes
=====
The style in which I've written the KA11 and KD11B is a bit idiosyncratic.
The idea was to try and see how compact the code could be.
I have to say I like it but apologize if you don't.
To-do
=====
* implement DATIP for the Unibone
* introduce #ifdef UNIBONE so we can maintain the code in one repo

View File

@@ -1,23 +0,0 @@
#define USED(x) ((void)x)
#define SET(x) ((x)=0)
#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
argv[0] && argv[0][0]=='-' && argv[0][1];\
argc--, argv++) {\
char *_args, *_argt;\
char _argc;\
_args = &argv[0][1];\
if(_args[0]=='-' && _args[1]==0){\
argc--; argv++; break;\
}\
_argc = 0;\
while(*_args && (_argc = *_args++))\
switch(_argc)
#define ARGEND SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
#define ARGF() (_argt=_args, _args=(char*)"",\
(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
#define EARGF(x) (_argt=_args, _args=(char*)"",\
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
#define ARGC() _argc

View File

@@ -1,476 +0,0 @@
#include "11.h"
enum {
SR_C = 1,
SR_AC_EQ_MQ15 = 2,
SR_AC_MQ_0 = 4,
SR_MQ_0 = 010,
SR_AC_0 = 020,
SR_AC_1 = 040,
SR_NEG = 0100,
SR_OV = 0200
};
enum {
KE_DIV = 0777300,
KE_AC = 0777302,
KE_MQ = 0777304,
KE_MULT = 0777306,
KE_SCSR = 0777310,
KE_NORM = 0777312,
KE_LSH = 0777314,
KE_ASH = 0777316,
};
#define B31 (1<<31)
#define B30 (1<<30)
static void
setflags(KE11 *ke)
{
ke->sr &= ~(SR_AC_EQ_MQ15|SR_AC_MQ_0|SR_MQ_0|SR_AC_0|SR_AC_1);
if(ke->ac == 0 && sgn(ke->mq)==0 ||
ke->ac == 0177777 && sgn(ke->mq))
ke->sr |= SR_AC_EQ_MQ15;
if(ke->mq == 0 && ke->ac == 0)
ke->sr |= SR_AC_MQ_0;
if(ke->mq == 0)
ke->sr |= SR_MQ_0;
if(ke->ac == 0)
ke->sr |= SR_AC_0;
if(ke->ac == 0177777)
ke->sr |= SR_AC_1;
}
static void
setflag(KE11 *ke, int flg, uint32 c)
{
if(c)
ke->sr |= flg;
else
ke->sr &= ~flg;
}
/* Functions are a transcription of the flow charts in the manual.
May be a bit inefficient but it's nice to be accurate. */
static void
mult(KE11 *ke)
{
uint32 sum, md;
int c;
sum = 0;
md = ke->ac<<16 | ke->mq;
c = 0;
ke->sc = 16;
do{
if((ke->x & 1) != c){
if(ke->x&1)
sum += ~md + 1;
else
sum += md;
}
md <<= 1;
c = ke->x&1;
ke->x >>= 1;
ke->sc--;
}while(ke->sc);
ke->ac = sum>>16;
ke->mq = sum;
ke->sr &= ~SR_C;
setflags(ke);
}
static uint32
abs32(uint32 x)
{
return x&B31 ? ~x + 1 : x;
}
static void
divide(KE11 *ke)
{
uint32 dd, dr;
uint16 q;
int c;
int s;
int ov;
dd = ke->ac<<16 | ke->mq;
dr = ke->x<<16;
q = 0;
ov = 0;
ke->sr &= ~SR_C;
s = !!(dd&B31);
ke->sc = 16;
do{
c = (dr&B31) == (dd&B31);
dr >>= 1;
if(dr&B30)
dr |= B31;
q <<= 1;
q |= c;
if(c)
dd += ~dr + 1;
else
dd += dr;
if(ke->sc == 16 && dd != 0 && !!(dd>>31 & 1) == s)
goto ov;
ke->sc--;
}while(ke->sc);
if(dd == 0 ||
/* is this correct? */
dd + abs32(dr) != 0 && !!(dd>>31 & 1) == s){
c = 1;
q <<= 1;
q |= c;
}else{
c = (dd&B31) == (dr&B31);
if(c)
dd += ~dr + 1;
else
dd += dr;
q += c;
c = 0;
q <<= 1;
}
/* DOCU manual says DD in one place and DR in another...
* which is correct? have to check */
if((dr>>31 & 1) != (q>>15 & 1) != s)
ov:
ov = 1;
ke->ac = dd;
ke->mq = q;
setflag(ke, SR_OV, ov != (ke->sr>>6 & 1));
setflags(ke);
if(ov)
setflag(ke, SR_NEG, s);
return;
}
static void
norm(KE11 *ke)
{
uint32 sh;
sh = ke->ac<<16 | ke->mq;
ke->sc = 0;
ke->sr &= ~(SR_OV|SR_C);
setflag(ke, SR_NEG, sh & B31);
if(ke->sr & SR_NEG)
ke->sr |= SR_OV;
loop:
if((sh>>31 & 1) != (sh>>30 & 1))
goto done;
if(sh == (3U<<30))
goto done;
if(ke->sc == 31)
goto done;
sh <<= 1;
ke->sc++;
goto loop;
done:
ke->ac = sh>>16;
ke->mq = sh;
setflags(ke);
}
static void
lsh(KE11 *ke)
{
uint32 sh;
int ov;
sh = ke->ac<<16 | ke->mq;
setflag(ke, SR_NEG, sh&B31);
ov = 0;
loop:
ke->sc &= 077;
if(ke->sc == 0)
goto done;
if(ke->sc&040){
/* negative, shift right */
setflag(ke, SR_C, sh&1);
sh >>= 1;
ke->sr &= ~SR_NEG;
ke->sc++;
}else{
/* positive, shift left */
setflag(ke, SR_C, sh&B31);
sh <<= 1;
if((ke->sr>>6 & 1) != (sh>>31 & 1))
ov = 1; /* sign changed */
setflag(ke, SR_NEG, sh&B31);
ke->sc--;
}
goto loop;
done:
setflag(ke, SR_OV, ov != (ke->sr>>6 & 1));
ke->ac = sh>>16;
ke->mq = sh;
setflags(ke);
}
static void
ash(KE11 *ke)
{
uint32 sh;
int ov;
sh = ke->ac<<16 | ke->mq;
setflag(ke, SR_NEG, sh&B31);
ov = 0;
loop:
ke->sc &= 077;
if(ke->sc == 0)
goto done;
if(ke->sc&040){
/* negative, shift right */
setflag(ke, SR_C, sh&1);
sh >>= 1;
if(ke->sr & SR_NEG)
sh |= B31;
ke->sc++;
}else{
/* positive, shift left */
sh <<= 1;
setflag(ke, SR_C, sh&B31);
if(ke->sr & SR_NEG)
sh |= B31;
else
sh &= ~B31;
if((ke->sr & SR_C) != (ke->sr>>6 & 1))
ov = 1; /* sign changed */
ke->sc--;
}
goto loop;
done:
setflag(ke, SR_OV, ov != (ke->sr>>6 & 1));
ke->ac = sh>>16;
ke->mq = sh;
setflags(ke);
}
int
dato_ke11(Bus *bus, void *dev)
{
KE11 *ke = dev;
if(bus->addr >= 0777300 && bus->addr < 0777320){
// printf("EAE DATO %o %o\n", bus->addr, bus->data);
switch(bus->addr){
case KE_DIV:
ke->x = bus->data;
divide(ke);
break;
case KE_AC:
ke->ac = bus->data;
break;
case KE_MQ:
ke->mq = bus->data;
/* sign extend into AC */
if(ke->mq&0100000)
ke->ac = 0177777;
else
ke->ac = 0;
break;
case KE_MULT:
ke->x = bus->data;
mult(ke);
break;
case KE_SCSR:
ke->sc = bus->data & 077;
SETMASK(ke->sr, bus->data>>8, 0301);
break;
case KE_NORM:
norm(ke);
break;
case KE_LSH:
ke->sc = bus->data & 077;
lsh(ke);
break;
case KE_ASH:
ke->sc = bus->data & 077;
ash(ke);
break;
default: assert(0); /* can't happen */
}
return 0;
}
return 1;
}
int
datob_ke11(Bus *bus, void *dev)
{
KE11 *ke = dev;
if(bus->addr >= 0777300 && bus->addr < 0777320){
// printf("EAE DATOB %o %o\n", bus->addr, bus->data);
switch(bus->addr){
case KE_DIV:
ke->x = sxt(bus->data);
divide(ke);
break;
case KE_AC:
ke->ac = sxt(bus->data);
break;
case KE_AC+1:
SETMASK(ke->ac, bus->data, 0177400);
break;
case KE_MQ:
ke->mq = sxt(bus->data);
/* sign extend into AC */
if(ke->mq&0100000)
ke->ac = 0177777;
else
ke->ac = 0;
break;
case KE_MQ+1:
SETMASK(ke->mq, bus->data, 0177400);
/* sign extend into AC */
if(ke->mq&0100000)
ke->ac = 0177777;
else
ke->ac = 0;
break;
case KE_MULT:
ke->x = sxt(bus->data);
mult(ke);
break;
case KE_SCSR:
break;
case KE_NORM:
norm(ke);
break;
case KE_LSH:
ke->sc = bus->data & 077;
lsh(ke);
break;
case KE_ASH:
ke->sc = bus->data & 077;
ash(ke);
break;
case KE_DIV+1:
case KE_MULT+1:
case KE_SCSR+1:
case KE_NORM+1:
case KE_LSH+1:
case KE_ASH+1:
break;
default: assert(0); /* can't happen */
}
return 0;
}
return 1;
}
int
dati_ke11(Bus *bus, void *dev)
{
KE11 *ke = dev;
if(bus->addr >= 0777300 && bus->addr < 0777320){
// printf("EAE DATI %o\n", bus->addr);
switch(bus->addr){
case KE_DIV:
case KE_MULT:
case KE_LSH:
case KE_ASH:
bus->data = 0;
break;
case KE_AC:
bus->data = ke->ac;
break;
case KE_MQ:
bus->data = ke->mq;
break;
case KE_SCSR:
bus->data = WD(ke->sr, ke->sc);
break;
case KE_NORM:
bus->data = ke->sc & 077;
break;
default: assert(0); /* can't happen */
}
return 0;
}
return 1;
}
void
reset_ke11(void *dev)
{
KE11 *ke = dev;
ke->ac = 0;
ke->mq = 0;
ke->x = 0;
ke->sc = 0;
ke->sr = 0;
setflags(ke);
}
void
eaetest(KE11 *ke)
{
/*
// normalize
// ke->ac = ~0; ke->mq = ~0;
// ke->ac = 0177770; ke->mq = 0;
// ke->ac = 0100000; ke->mq = 0;
ke->ac = 0; ke->mq = 0;
norm(ke);
*/
/*
ke->sc = 0100-3;
ke->ac = 0123456; ke->mq = 0111222;
ash(ke);
*/
/*
ke->ac = 0; ke->mq = 00123;
ke->x = 0321;
mult(ke);
*/
/*
ke->ac = 00021; ke->mq = 0;
ke->x = 0321;
divide(ke);
*/
/* int a, b, c, d;
//some multiplication test
for(a = 0; a < 0077777; a++){
for(b = 0; b < 0077777; b++){
c = a * b;
ke->ac = 0; ke->mq = a;
ke->x = b;
mult(ke);
d = ke->ac<<16 | ke->mq;
assert(c == d);
if(a == 0)
continue;
ke->x = a;
divide(ke);
assert(ke->ac == 0);
assert(ke->mq == b);
}
printf("%o\n", a);
}
// division
for(a = 0; a < 0077777; a++){
printf("%o\n", a);
for(b = 1; b < 0077777; b++){
ke->ac = 0; ke->mq = a;
ke->x = b;
divide(ke);
assert(ke->mq == a / b);
assert(ke->ac == a % b);
}
}
*/
// printf("%06o %06o %d %o\n", ke->ac, ke->mq, ke->sc, ke->sr);
}

View File

@@ -1,587 +0,0 @@
#include "11.h"
#include "ka11.h"
enum {
PSW_PR = 0340,
PSW_T = 020,
PSW_N = 010,
PSW_Z = 004,
PSW_V = 002,
PSW_C = 001,
};
enum {
TRAP_STACK = 1,
TRAP_PWR = 2, // can't happen
TRAP_BR7 = 4,
TRAP_BR6 = 010,
TRAP_BR5 = 040,
TRAP_BR4 = 0100,
TRAP_CSTOP = 01000 // can't happen?
};
#define ISSET(f) ((cpu->psw&(f)) != 0)
enum {
STATE_HALTED = 0,
STATE_RUNNING,
STATE_WAITING
};
static uint32
ubxt(word a)
{
return (a&0160000)==0160000 ? a|0600000 : a;
}
void
tracestate(KA11 *cpu)
{
(void)cpu;
trace(" R0 %06o R1 %06o R2 %06o R3 %06o R4 %06o R5 %06o R6 %06o R7 %06o\n"
" 10 %06o 11 %06o 12 %06o 13 %06o 14 %06o 15 %06o 16 %06o 17 %06o\n"
" BA %06o IR %06o PSW %03o\n"
,
cpu->r[0], cpu->r[1], cpu->r[2], cpu->r[3],
cpu->r[4], cpu->r[5], cpu->r[6], cpu->r[7],
cpu->r[8], cpu->r[9], cpu->r[10], cpu->r[11],
cpu->r[12], cpu->r[13], cpu->r[14], cpu->r[15],
cpu->ba, cpu->ir, cpu->psw);
}
void
printstate(KA11 *cpu)
{
(void)cpu;
printf(" R0 %06o R1 %06o R2 %06o R3 %06o R4 %06o R5 %06o R6 %06o R7 %06o\n"
" 10 %06o 11 %06o 12 %06o 13 %06o 14 %06o 15 %06o 16 %06o 17 %06o\n"
" BA %06o IR %06o PSW %03o\n"
,
cpu->r[0], cpu->r[1], cpu->r[2], cpu->r[3],
cpu->r[4], cpu->r[5], cpu->r[6], cpu->r[7],
cpu->r[8], cpu->r[9], cpu->r[10], cpu->r[11],
cpu->r[12], cpu->r[13], cpu->r[14], cpu->r[15],
cpu->ba, cpu->ir, cpu->psw);
}
void
reset(KA11 *cpu)
{
Busdev *bd;
cpu->traps = 0;
for(bd = cpu->bus->devs; bd; bd = bd->next)
bd->reset(bd->dev);
}
int
dati(KA11 *cpu, int b)
{
trace("dati %06o: ", cpu->ba);
if(!b && cpu->ba&1)
goto be;
/* internal registers */
if((cpu->ba&0177400) == 0177400){
switch(cpu->ba&0377){
case 0170: case 0171:
cpu->bus->data = cpu->sw;
goto ok;
case 0376: case 0377:
cpu->bus->data = cpu->psw;
goto ok;
/* respond but don't return real data */
case 0147:
cpu->bus->data = 0;
goto ok;
}
}
cpu->bus->addr = ubxt(cpu->ba)&~1;
if(dati_bus(cpu->bus))
goto be;
ok:
trace("%06o\n", cpu->bus->data);
cpu->be = 0;
return 0;
be:
trace("BE\n");
cpu->be++;
return 1;
}
int
dato(KA11 *cpu, int b)
{
trace("dato %06o %06o %d\n", cpu->ba, cpu->bus->data, b);
if(!b && cpu->ba&1)
goto be;
/* internal registers */
if((cpu->ba&0177400) == 0177400){
switch(cpu->ba&0377){
case 0170: case 0171:
/* can't write switches */
goto ok;
case 0376: case 0377:
/* writes 0 for the odd byte.
I think this is correct. */
cpu->psw = cpu->bus->data;
goto ok;
}
}
if(b){
cpu->bus->addr = ubxt(cpu->ba);
if(datob_bus(cpu->bus))
goto be;
}else{
cpu->bus->addr = ubxt(cpu->ba)&~1;
if(dato_bus(cpu->bus))
goto be;
}
ok:
cpu->be = 0;
return 0;
be:
cpu->be++;
return 1;
}
static void
svc(KA11 *cpu, Bus *bus)
{
int l;
Busdev *bd;
static int brtraps[4] = { TRAP_BR4, TRAP_BR5, TRAP_BR6, TRAP_BR7 };
for(l = 0; l < 4; l++){
cpu->br[l].bg = nil;
cpu->br[l].dev = nil;
}
cpu->traps &= ~(TRAP_BR4|TRAP_BR5|TRAP_BR6|TRAP_BR7);
for(bd = bus->devs; bd; bd = bd->next){
l = bd->svc(bus, bd->dev);
if(l >= 4 && l <= 7 && cpu->br[l-4].bg == nil){
cpu->br[l-4].bg = bd->bg;
cpu->br[l-4].dev = bd->dev;
cpu->traps |= brtraps[l-4];
}
}
}
static int
addrop(KA11 *cpu, int m, int b)
{
int r;
int ai;
r = m&7;
m >>= 3;
ai = 1 + (!b || (r&6)==6 || m&1);
if(m == 0){
assert(0);
return 0;
}
switch(m&6){
case 0: // REG
cpu->b = cpu->ba = cpu->r[r];
return 0; // this already is mode 1
case 2: // INC
cpu->ba = cpu->r[r];
cpu->b = cpu->r[r] = cpu->r[r] + ai;
break;
case 4: // DEC
cpu->b = cpu->ba = cpu->r[r]-ai;
if(r == 6 && (cpu->ba&~0377) == 0) cpu->traps |= TRAP_STACK;
cpu->r[r] = cpu->ba;
break;
case 6: // INDEX
cpu->ba = cpu->r[7];
cpu->r[7] += 2;
if(dati(cpu, 0)) return 1;
cpu->b = cpu->ba = cpu->bus->data + cpu->r[r];
break;
}
if(m&1){
if(dati(cpu, 0)) return 1;
cpu->b = cpu->ba = cpu->bus->data;
}
return 0;
}
static int
fetchop(KA11 *cpu, int t, int m, int b)
{
int r;
r = m&7;
if((m&070) == 0)
cpu->r[t] = cpu->r[r];
else{
if(dati(cpu, b)) return 1;
cpu->r[t] = cpu->bus->data;
if(b && cpu->ba&1) cpu->r[t] = cpu->r[t]>>8;
}
if(b) cpu->r[t] = sxt(cpu->r[t]);
return 0;
}
static int
readop(KA11 *cpu, int t, int m, int b)
{
return !(addrop(cpu, m, b) == 0 && fetchop(cpu, t, m, b) == 0);
}
static int
writedest(KA11 *cpu, word v, int b)
{
int d;
if((cpu->ir & 070) == 0){
d = cpu->ir & 7;
if(b) SETMASK(cpu->r[d], v, 0377);
else cpu->r[d] = v;
}else{
if(cpu->ba&1) v <<= 8;
cpu->bus->data = v;
if(dato(cpu, b)) return 1;
}
return 0;
}
static void
setnz(KA11 *cpu, word w)
{
cpu->psw &= ~(PSW_N|PSW_Z);
if(w & 0100000) cpu->psw |= PSW_N;
if(w == 0) cpu->psw |= PSW_Z;
}
void
step(KA11 *cpu)
{
uint by;
uint br;
uint b;
uint c;
uint src, dst, sf, df, sm, dm;
word mask, sign;
int inhov;
byte oldpsw;
// printf("fetch from %06o\n", cpu->r[7]);
// printstate(cpu);
#define SP cpu->r[6]
#define PC cpu->r[7]
#define SR cpu->r[010]
#define DR cpu->r[011]
#define TV cpu->r[012]
#define BA cpu->ba
#define PSW cpu->psw
#define RD_B if(sm != 0) if(readop(cpu, 010, src, by)) goto be;\
if(dm != 0) if(readop(cpu, 011, dst, by)) goto be;\
if(sm == 0) fetchop(cpu, 010, src, by);\
if(dm == 0) fetchop(cpu, 011, dst, by)
#define RD_U if(dm != 0) if(readop(cpu, 011, dst, by)) goto be;\
if(dm == 0) fetchop(cpu, 011, dst, by);\
SR = DR
#define WR if(writedest(cpu, b, by)) goto be
#define NZ setnz(cpu, b)
#define SVC goto service
#define TRAP(v) TV = v; goto trap
#define CLC cpu->psw &= ~PSW_C
#define CLV cpu->psw &= ~PSW_V
#define CLCV cpu->psw &= ~(PSW_V|PSW_C)
#define SEV cpu->psw |= PSW_V
#define SEC cpu->psw |= PSW_C
#define C if(b & 0200000) SEC
#define NC if((b & 0200000) == 0) SEC
#define BXT if(by) b = sxt(b)
#define BR PC += br
#define CBR(c) if(((c)>>(cpu->psw&017)) & 1) BR
#define PUSH SP -= 2; if(!inhov && (SP&~0377) == 0) cpu->traps |= TRAP_STACK
#define POP SP += 2
#define OUT(a,d) cpu->ba = (a); cpu->bus->data = (d); if(dato(cpu, 0)) goto be
#define IN(d) if(dati(cpu, 0)) goto be; d = cpu->bus->data
#define INA(a,d) cpu->ba = a; if(dati(cpu, 0)) goto be; d = cpu->bus->data
#define TR(m) trace("%06o "#m"\n", PC-2)
#define TRB(m) trace("%06o "#m"%s\n", PC-2, by ? "B" : "")
oldpsw = PSW;
INA(PC, cpu->ir);
PC += 2; /* don't increment on bus error! */
by = !!(cpu->ir&B15);
br = sxt(cpu->ir)<<1;
src = cpu->ir>>6 & 077;
sf = src & 7;
sm = src>>3 & 7;
dst = cpu->ir & 077;
df = dst & 7;
dm = dst>>3 & 7;
if(by) mask = M8, sign = B7;
else mask = M16, sign = B15;
inhov = 0;
/* Binary */
switch(cpu->ir & 0170000){
case 0110000: case 0010000: TRB(MOV);
RD_B; CLV;
b = SR; NZ;
if(dm==0) cpu->r[df] = SR;
else writedest(cpu, SR, by);
SVC;
case 0120000: case 0020000: TRB(CMP);
RD_B; CLCV;
b = SR + W(~DR) + 1; NC; BXT;
if(sgn((SR ^ DR) & ~(DR ^ b))) SEV;
NZ; SVC;
case 0130000: case 0030000: TRB(BIT);
RD_B; CLV;
b = DR & SR;
NZ; SVC;
case 0140000: case 0040000: TRB(BIC);
RD_B; CLV;
b = DR & ~SR;
NZ; WR; SVC;
case 0150000: case 0050000: TRB(BIS);
RD_B; CLV;
b = DR | SR;
NZ; WR; SVC;
case 0060000: TR(ADD);
by = 0; RD_B; CLCV;
b = SR + DR; C;
if(sgn(~(SR ^ DR) & (DR ^ b))) SEV;
NZ; WR; SVC;
case 0160000: TR(SUB);
by = 0; RD_B; CLCV;
b = DR + W(~SR) + 1; NC;
if(sgn((SR ^ DR) & (DR ^ b))) SEV;
NZ; WR; SVC;
/* Reserved instructions */
case 0170000: case 0070000: goto ri;
}
/* Unary */
switch(cpu->ir & 0007700){
case 0005000: TRB(CLR);
RD_U; CLCV;
b = 0;
NZ; WR; SVC;
case 0005100: TRB(COM);
RD_U; CLV; SEC;
b = W(~SR);
NZ; WR; SVC;
case 0005200: TRB(INC);
RD_U; CLV;
b = W(SR+1); BXT;
if(sgn(~SR&b)) SEV;
NZ; WR; SVC;
case 0005300: TRB(DEC);
RD_U; CLV;
b = W(SR+~0); BXT;
if(sgn(SR&~b)) SEV;
NZ; WR; SVC;
case 0005400: TRB(NEG);
RD_U; CLCV;
b = W(~SR+1); BXT; if(b) SEC;
if(sgn(b&SR)) SEV;
NZ; WR; SVC;
case 0005500: TRB(ADC);
RD_U; c = ISSET(PSW_C); CLCV;
b = SR + c; C; BXT;
if(sgn(~SR&b)) SEV;
NZ; WR; SVC;
case 0005600: TRB(SBC);
RD_U; c = !ISSET(PSW_C)-1; CLCV;
b = W(SR+c); if(c && SR == 0) SEC; BXT;
if(sgn(SR&~b)) SEV;
NZ; WR; SVC;
case 0005700: TRB(TST);
RD_U; CLCV;
b = SR;
NZ; SVC;
case 0006000: TRB(ROR);
RD_U; c = ISSET(PSW_C); CLCV;
b = (SR&mask) >> 1; if(c) b |= sign; if(SR & 1) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006100: TRB(ROL);
RD_U; c = ISSET(PSW_C); CLCV;
b = (SR<<1) & mask; if(c) b |= 1; if(SR & B15) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006200: TRB(ASR);
RD_U; c = ISSET(PSW_C); CLCV;
b = W(SR>>1) | SR&B15; if(SR & 1) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006300: TRB(ASL);
RD_U; CLCV;
b = W(SR<<1); if(SR & B15) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006400:
case 0006500:
case 0006600:
case 0006700:
goto ri;
}
switch(cpu->ir & 0107400){
case 0004000:
case 0004400: TR(JSR);
if(dm == 0) goto ill;
if(addrop(cpu, dst, 0)) goto be;
DR = cpu->b;
PUSH; OUT(SP, cpu->r[sf]);
cpu->r[sf] = PC; PC = DR;
SVC;
case 0104000: TR(EMT); TRAP(030);
case 0104400: TR(TRAP); TRAP(034);
}
/* Branches */
switch(cpu->ir & 0103400){
case 0000400: TR(BR); BR; SVC;
case 0001000: TR(BNE); CBR(0x0F0F); SVC;
case 0001400: TR(BEQ); CBR(0xF0F0); SVC;
case 0002000: TR(BGE); CBR(0xCC33); SVC;
case 0002400: TR(BLT); CBR(0x33CC); SVC;
case 0003000: TR(BGT); CBR(0x0C03); SVC;
case 0003400: TR(BLE); CBR(0xF3FC); SVC;
case 0100000: TR(BPL); CBR(0x00FF); SVC;
case 0100400: TR(BMI); CBR(0xFF00); SVC;
case 0101000: TR(BHI); CBR(0x0505); SVC;
case 0101400: TR(BLOS); CBR(0xFAFA); SVC;
case 0102000: TR(BVC); CBR(0x3333); SVC;
case 0102400: TR(BVS); CBR(0xCCCC); SVC;
case 0103000: TR(BCC); CBR(0x5555); SVC;
case 0103400: TR(BCS); CBR(0xAAAA); SVC;
}
// Hope we caught all instructions we meant to
assert((cpu->ir & 0177400) == 0);
/* Misc */
switch(cpu->ir & 0300){
case 0100: TR(JMP);
if(dm == 0) goto ill;
if(addrop(cpu, dst, 0)) goto be;
PC = cpu->b;
SVC;
case 0200:
switch(cpu->ir&070){
case 000: TR(RTS);
BA = SP; POP;
PC = cpu->r[df];
IN(cpu->r[df]);
SVC;
case 010: case 020: case 030:
goto ri;
case 040: case 050: TR(CCC); PSW &= ~(cpu->ir&017); SVC;
case 060: case 070: TR(SEC); PSW |= cpu->ir&017; SVC;
}
case 0300: TR(SWAB);
RD_U; CLC;
b = WD(DR & 0377, (DR>>8) & 0377);
NZ; WR; SVC;
}
/* Operate */
switch(cpu->ir & 7){
case 0: TR(HALT); cpu->state = STATE_HALTED; return;
case 1: TR(WAIT); cpu->state = STATE_WAITING; return;
case 2: TR(RTI);
BA = SP; POP; IN(PC);
BA = SP; POP; IN(PSW);
SVC;
case 3: TR(BPT); TRAP(014);
case 4: TR(IOT); TRAP(020);
case 5: TR(RESET); reset(cpu); SVC;
}
// All other instructions should be reserved now
ri: TRAP(010);
ill: TRAP(4);
be: if(cpu->be > 1){
printf("double bus error, HALT\n");
cpu->state = STATE_HALTED;
return;
}
printf("bus error\n");
TRAP(4);
trap:
trace("TRAP %o\n", TV);
PUSH; OUT(SP, PSW);
PUSH; OUT(SP, PC);
INA(TV, PC);
INA(TV+2, PSW);
/* no trace trap after a trap */
oldpsw = PSW;
tracestate(cpu);
return; // TODO: is this correct?
// SVC;
service:
c = PSW >> 5;
if(oldpsw & PSW_T){
oldpsw &= ~PSW_T;
TRAP(014);
}else if(cpu->traps & TRAP_STACK){
cpu->traps &= ~TRAP_STACK;
inhov = 1;
TRAP(4);
}else if(cpu->traps & TRAP_PWR){
cpu->traps &= ~TRAP_PWR;
TRAP(024);
}else if(c < 7 && cpu->traps & TRAP_BR7){
cpu->traps &= ~TRAP_BR7;
TRAP(cpu->br[3].bg(cpu->br[3].dev));
}else if(c < 6 && cpu->traps & TRAP_BR6){
cpu->traps &= ~TRAP_BR6;
TRAP(cpu->br[2].bg(cpu->br[2].dev));
}else if(c < 5 && cpu->traps & TRAP_BR5){
cpu->traps &= ~TRAP_BR5;
TRAP(cpu->br[1].bg(cpu->br[1].dev));
}else if(c < 4 && cpu->traps & TRAP_BR4){
cpu->traps &= ~TRAP_BR4;
TRAP(cpu->br[0].bg(cpu->br[0].dev));
}else
// TODO? console stop
/* fetch next instruction */
return;
}
void
run(KA11 *cpu)
{
cpu->state = STATE_RUNNING;
while(cpu->state != STATE_HALTED){
svc(cpu, cpu->bus);
#ifdef AUTODIAG
extern int diagpassed;
if(diagpassed)
return;
#endif
if(cpu->state == STATE_RUNNING ||
cpu->state == STATE_WAITING && cpu->traps){
cpu->state = STATE_RUNNING;
step(cpu);
}
}
printstate(cpu);
}

View File

@@ -1,23 +0,0 @@
// 11/20 cpu - TODO
typedef struct KA11 KA11;
struct KA11
{
word r[16];
word b; // B register before BUT JSRJMP
word ba;
word ir;
Bus *bus;
byte psw;
int traps;
int be;
int state;
struct {
int (*bg)(void *dev);
void *dev;
} br[4];
word sw;
};
void run(KA11 *cpu);
void reset(KA11 *cpu);

View File

@@ -1,775 +0,0 @@
#include "11.h"
#include "kd11b.h"
enum {
PSW_PR = 0340,
PSW_T = 020,
PSW_N = 010,
PSW_Z = 004,
PSW_V = 002,
PSW_C = 001,
};
enum {
TRAP_STACK = 1,
TRAP_PWR = 2, // can't happen
TRAP_BR7 = 4,
TRAP_BR6 = 010,
TRAP_CLK = 020,
TRAP_BR5 = 040,
TRAP_BR4 = 0100,
TRAP_RX = 0200,
TRAP_TX = 0400,
TRAP_CSTOP = 01000 // can't happen?
};
#define ISSET(f) ((cpu->psw&(f)) != 0)
enum {
STATE_HALTED = 0,
STATE_RUNNING,
STATE_WAITING
};
#define CLOCKFREQ (1000000000/60)
static struct timespec oldtime, newtime;
static void
initclock(void)
{
clock_gettime(CLOCK_REALTIME, &newtime);
oldtime = newtime;
}
static void
handleclock(KD11B *cpu)
{
struct timespec diff;
clock_gettime(CLOCK_REALTIME, &newtime);
diff.tv_sec = newtime.tv_sec - oldtime.tv_sec;
diff.tv_nsec = newtime.tv_nsec - oldtime.tv_nsec;
if(diff.tv_nsec < 0){
diff.tv_nsec += 1000000000;
diff.tv_sec -= 1;
}
if(diff.tv_nsec >= CLOCKFREQ){
cpu->lc_clock = 1;
cpu->lc_int = 1;
oldtime.tv_nsec += CLOCKFREQ;
if(oldtime.tv_nsec >= 1000000000){
oldtime.tv_nsec -= 1000000000;
oldtime.tv_sec += 1;
}
}
}
static uint32
ubxt(word a)
{
return (a&0160000)==0160000 ? a|0600000 : a;
}
void
tracestate(KD11B *cpu)
{
(void)cpu;
trace(" R0 %06o R1 %06o R2 %06o R3 %06o R4 %06o R5 %06o R6 %06o R7 %06o\n"
" 10 %06o 11 %06o 12 %06o 13 %06o 14 %06o 15 %06o 16 %06o 17 %06o\n"
" BA %06o IR %06o PSW %03o\n"
,
cpu->r[0], cpu->r[1], cpu->r[2], cpu->r[3],
cpu->r[4], cpu->r[5], cpu->r[6], cpu->r[7],
cpu->r[8], cpu->r[9], cpu->r[10], cpu->r[11],
cpu->r[12], cpu->r[13], cpu->r[14], cpu->r[15],
cpu->ba, cpu->ir, cpu->psw);
}
void
printstate(KD11B *cpu)
{
(void)cpu;
printf(" R0 %06o R1 %06o R2 %06o R3 %06o R4 %06o R5 %06o R6 %06o R7 %06o\n"
" 10 %06o 11 %06o 12 %06o 13 %06o 14 %06o 15 %06o 16 %06o 17 %06o\n"
" BA %06o IR %06o PSW %03o\n"
,
cpu->r[0], cpu->r[1], cpu->r[2], cpu->r[3],
cpu->r[4], cpu->r[5], cpu->r[6], cpu->r[7],
cpu->r[8], cpu->r[9], cpu->r[10], cpu->r[11],
cpu->r[12], cpu->r[13], cpu->r[14], cpu->r[15],
cpu->ba, cpu->ir, cpu->psw);
}
void
reset(KD11B *cpu)
{
Busdev *bd;
cpu->rcd_busy = 0;
cpu->rcd_rdr_enab = 0;
cpu->rcd_int_enab = 0;
cpu->rcd_int = 0;
cpu->rcd_da = 0;
cpu->rcd_b = 0;
cpu->xmit_int_enab = 0;
cpu->xmit_maint = 0;
cpu->xmit_int = 1;
cpu->xmit_tbmt = 1;
cpu->xmit_b = 0;
cpu->lc_int_enab = 0;
// TODO: 1?
cpu->lc_clock = 0;
cpu->lc_int = 0;
cpu->traps = 0;
for(bd = cpu->bus->devs; bd; bd = bd->next)
bd->reset(bd->dev);
}
int
dati(KD11B *cpu, int b)
{
trace("dati %06o: ", cpu->ba);
/* allow odd addresses for bytes and registers */
int alodd = b || cpu->ba >= 0177700 && cpu->ba < 0177720;
if(!alodd && cpu->ba&1)
goto be;
/* internal registers */
if((cpu->ba&0177400) == 0177400){
if((cpu->ba&0360) == 0300){
cpu->bus->data = cpu->r[cpu->ba&017];
goto ok;
}
switch(cpu->ba&0377){
/* Line clock */
case 0146:
cpu->bus->data = cpu->lc_int_enab<<6 |
cpu->lc_clock<<7;
goto ok;
/* Receive */
case 0160:
cpu->bus->data = cpu->rcd_int_enab<<6 |
cpu->rcd_int<<7 |
cpu->rcd_busy<<1;
goto ok;
case 0162:
cpu->bus->data = cpu->rcd_b;
cpu->rcd_b = 0;
cpu->rcd_da = 0;
cpu->rcd_int = 0;
goto ok;
/* Transmit */
case 0164:
cpu->bus->data = cpu->xmit_maint<<2 |
cpu->xmit_int_enab<<6 |
cpu->xmit_int<<7;
goto ok;
case 0166:
/* write only */
cpu->bus->data = 0;
goto ok;
case 0170: case 0171:
cpu->bus->data = cpu->sw;
goto ok;
case 0376: case 0377:
cpu->bus->data = cpu->psw;
goto ok;
/* respond but don't return real data */
case 0147:
case 0161:
case 0163:
case 0165:
case 0167:
cpu->bus->data = 0;
goto ok;
}
}
cpu->bus->addr = ubxt(cpu->ba)&~1;
if(dati_bus(cpu->bus))
goto be;
ok:
trace("%06o\n", cpu->bus->data);
cpu->be = 0;
return 0;
be:
trace("BE\n");
cpu->be++;
return 1;
}
int
dato(KD11B *cpu, int b)
{
trace("dato %06o %06o %d\n", cpu->ba, cpu->bus->data, b);
/* allow odd addresses for bytes and registers */
int alodd = b || cpu->ba >= 0177700 && cpu->ba < 0177720;
if(!alodd && cpu->ba&1)
goto be;
/* internal registers */
if((cpu->ba&0177400) == 0177400){
if((cpu->ba&0360) == 0300){
/* no idea if byte access even makes sense here */
cpu->r[cpu->ba&017] = cpu->bus->data;
goto ok;
}
switch(cpu->ba&0377){
/* Line clock */
case 0146:
cpu->lc_int_enab = cpu->bus->data>>6 & 1;
if((cpu->bus->data & 0200) == 0){
cpu->lc_clock = 0;
cpu->lc_int = 0;
}
goto ok;
/* Receive */
case 0160:
// TODO: RDR ENAB
cpu->rcd_rdr_enab = cpu->bus->data & 1;
if(!cpu->rcd_int_enab && cpu->bus->data&0100 && cpu->rcd_da)
cpu->rcd_int = 1;
cpu->rcd_int_enab = cpu->bus->data>>6 & 1;
goto ok;
case 0162:
/* read only */
goto ok;
/* Transmit */
case 0164:
// TODO: MAINT
cpu->xmit_maint = cpu->bus->data>>2 & 1;
if(!cpu->xmit_int_enab && cpu->bus->data&0100 && cpu->xmit_tbmt)
cpu->xmit_int = 1;
cpu->xmit_int_enab = cpu->bus->data>>6 & 1;
goto ok;
case 0166:
cpu->xmit_b = cpu->bus->data;
cpu->xmit_tbmt = 0;
cpu->xmit_int = 0;
goto ok;
case 0170: case 0171:
/* can't write switches */
goto ok;
case 0376: case 0377:
/* writes 0 for the odd byte.
I think this is correct. */
cpu->psw = cpu->bus->data;
goto ok;
/* respond but don't do anything */
case 0147:
case 0161:
case 0163:
case 0165:
case 0167:
goto ok;
}
}
if(b){
cpu->bus->addr = ubxt(cpu->ba);
if(datob_bus(cpu->bus))
goto be;
}else{
cpu->bus->addr = ubxt(cpu->ba)&~1;
if(dato_bus(cpu->bus))
goto be;
}
ok:
cpu->be = 0;
return 0;
be:
cpu->be++;
return 1;
}
static void
svc(KD11B *cpu, Bus *bus)
{
int l;
Busdev *bd;
static int brtraps[4] = { TRAP_BR4, TRAP_BR5, TRAP_BR6, TRAP_BR7 };
for(l = 0; l < 4; l++){
cpu->br[l].bg = nil;
cpu->br[l].dev = nil;
}
cpu->traps &= ~(TRAP_BR4|TRAP_BR5|TRAP_BR6|TRAP_BR7);
for(bd = bus->devs; bd; bd = bd->next){
l = bd->svc(bus, bd->dev);
if(l >= 4 && l <= 7 && cpu->br[l-4].bg == nil){
cpu->br[l-4].bg = bd->bg;
cpu->br[l-4].dev = bd->dev;
cpu->traps |= brtraps[l-4];
}
}
}
static int
addrop(KD11B *cpu, int m, int b)
{
int r;
int ai;
r = m&7;
m >>= 3;
ai = 1 + (!b || (r&6)==6 || m&1);
if(m == 0)
return 0;
switch(m&6){
case 0: // REG
cpu->b = cpu->ba = cpu->r[r];
return 0; // this already is mode 1
case 2: // INC
cpu->ba = cpu->r[r];
cpu->b = cpu->r[r] = cpu->r[r] + ai;
break;
case 4: // DEC
cpu->b = cpu->ba = cpu->r[r]-ai;
if(r == 6 && (cpu->ba&~0377) == 0) cpu->traps |= TRAP_STACK;
cpu->r[r] = cpu->ba;
break;
case 6: // INDEX
cpu->ba = cpu->r[7];
cpu->r[7] += 2;
if(dati(cpu, 0)) return 1;
cpu->b = cpu->ba = cpu->bus->data + cpu->r[r];
break;
}
if(m&1){
if(dati(cpu, 0)) return 1;
cpu->b = cpu->ba = cpu->bus->data;
}
return 0;
}
static int
fetchop(KD11B *cpu, int t, int m, int b)
{
int r;
r = m&7;
if((m&070) == 0)
cpu->r[t] = cpu->r[r];
else{
if(dati(cpu, b)) return 1;
cpu->r[t] = cpu->bus->data;
if(b && cpu->ba&1) cpu->r[t] = cpu->r[t]>>8;
}
if(b) cpu->r[t] = sxt(cpu->r[t]);
return 0;
}
static int
readop(KD11B *cpu, int t, int m, int b)
{
return !(addrop(cpu, m, b) == 0 && fetchop(cpu, t, m, b) == 0);
}
static int
writedest(KD11B *cpu, word v, int b)
{
int d;
if((cpu->ir & 070) == 0){
d = cpu->ir & 7;
if(b) SETMASK(cpu->r[d], v, 0377);
else cpu->r[d] = v;
}else{
if(cpu->ba&1) v <<= 8;
cpu->bus->data = v;
if(dato(cpu, b)) return 1;
}
return 0;
}
static void
setnz(KD11B *cpu, word w)
{
cpu->psw &= ~(PSW_N|PSW_Z);
if(w & 0100000) cpu->psw |= PSW_N;
if(w == 0) cpu->psw |= PSW_Z;
}
void
step(KD11B *cpu)
{
uint by;
uint br;
uint b;
uint c;
uint src, dst, sf, df, dm;
word mask, sign;
int inhov;
byte oldpsw;
// trace("fetch from %06o\n", cpu->r[7]);
// printstate(cpu);
#define SP cpu->r[6]
#define PC cpu->r[7]
#define SR cpu->r[010]
#define DR cpu->r[011]
#define TV cpu->r[012]
#define BA cpu->ba
#define PSW cpu->psw
#define RD_B if(readop(cpu, 010, src, by)) goto be; if(readop(cpu, 011, dst, by)) goto be
#define RD_U if(readop(cpu, 011, dst, by)) goto be; SR = DR
#define WR if(writedest(cpu, b, by)) goto be
#define NZ setnz(cpu, b)
#define SVC goto service
#define TRAP(v) TV = v; goto trap
#define CLV cpu->psw &= ~PSW_V
#define CLCV cpu->psw &= ~(PSW_V|PSW_C)
#define SEV cpu->psw |= PSW_V
#define SEC cpu->psw |= PSW_C
#define C if(b & 0200000) SEC
#define NC if((b & 0200000) == 0) SEC
#define BXT if(by) b = sxt(b)
#define BR PC += br
#define CBR(c) if(((c)>>(cpu->psw&017)) & 1) BR
#define PUSH SP -= 2; if(!inhov && (SP&~0377) == 0) cpu->traps |= TRAP_STACK
#define POP SP += 2
#define OUT(a,d) cpu->ba = (a); cpu->bus->data = (d); if(dato(cpu, 0)) goto be
#define IN(d) if(dati(cpu, 0)) goto be; d = cpu->bus->data
#define INA(a,d) cpu->ba = a; if(dati(cpu, 0)) goto be; d = cpu->bus->data
#define TR(m) trace("%06o "#m"\n", PC-2)
#define TRB(m) trace("%06o "#m"%s\n", PC-2, by ? "B" : "")
oldpsw = PSW;
INA(PC, cpu->ir);
PC += 2; /* don't increment on bus error! */
by = !!(cpu->ir&B15);
br = sxt(cpu->ir)<<1;
src = cpu->ir>>6 & 077;
sf = src & 7;
dst = cpu->ir & 077;
df = dst & 7;
dm = dst>>3 & 7;
if(by) mask = M8, sign = B7;
else mask = M16, sign = B15;
inhov = 0;
/* Binary */
switch(cpu->ir & 0170000){
case 0110000: case 0010000: TRB(MOV);
if(readop(cpu, 010, src, by)) goto be;
if(addrop(cpu, dst, by)) goto be;
if(dm && fetchop(cpu, 011, dst, by)) goto be;
CLV;
b = SR; NZ;
if(dm==0) cpu->r[df] = SR;
else writedest(cpu, SR, by);
SVC;
case 0120000: case 0020000: TRB(CMP);
RD_B; CLCV;
b = SR + W(~DR) + 1; NC; BXT;
if(sgn((SR ^ DR) & ~(DR ^ b))) SEV;
NZ; SVC;
case 0130000: case 0030000: TRB(BIT);
RD_B; CLV;
b = DR & SR;
NZ; SVC;
case 0140000: case 0040000: TRB(BIC);
RD_B; CLV;
b = DR & ~SR;
NZ; WR; SVC;
case 0150000: case 0050000: TRB(BIS);
RD_B; CLV;
b = DR | SR;
NZ; WR; SVC;
case 0060000: TR(ADD);
by = 0; RD_B; CLCV;
b = SR + DR; C;
if(sgn(~(SR ^ DR) & (DR ^ b))) SEV;
NZ; WR; SVC;
case 0160000: TR(SUB);
by = 0; RD_B; CLCV;
b = DR + W(~SR) + 1; NC;
if(sgn((SR ^ DR) & (DR ^ b))) SEV;
NZ; WR; SVC;
/* Reserved instructions */
case 0170000: case 0070000: goto ri;
}
/* Unary */
switch(cpu->ir & 0007700){
case 0005000: TRB(CLR);
RD_U; CLCV;
b = 0;
NZ; WR; SVC;
case 0005100: TRB(COM);
RD_U; CLV; SEC;
b = W(~SR);
NZ; WR; SVC;
case 0005200: TRB(INC);
RD_U; CLV;
b = W(SR+1); BXT;
if(sgn(~SR&b)) SEV;
NZ; WR; SVC;
case 0005300: TRB(DEC);
RD_U; CLV;
b = W(SR+~0); BXT;
if(sgn(SR&~b)) SEV;
NZ; WR; SVC;
case 0005400: TRB(NEG);
RD_U; CLCV;
b = W(~SR+1); BXT; if(b) SEC;
if(sgn(b&SR)) SEV;
NZ; WR; SVC;
case 0005500: TRB(ADC);
RD_U; c = ISSET(PSW_C); CLCV;
b = SR + c; C; BXT;
if(sgn(~SR&b)) SEV;
NZ; WR; SVC;
case 0005600: TRB(SBC);
RD_U; c = !ISSET(PSW_C)-1; CLCV;
b = W(SR+c); if(c && SR == 0) SEC; BXT;
if(sgn(SR&~b)) SEV;
NZ; WR; SVC;
case 0005700: TRB(TST);
RD_U; CLCV;
b = SR;
NZ; SVC;
case 0006000: TRB(ROR);
RD_U; c = ISSET(PSW_C); CLCV;
b = (SR&mask) >> 1; if(c) b |= sign; if(SR & 1) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006100: TRB(ROL);
RD_U; c = ISSET(PSW_C); CLCV;
b = (SR<<1) & mask; if(c) b |= 1; if(SR & B15) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006200: TRB(ASR);
RD_U; c = ISSET(PSW_C); CLCV;
b = W(SR>>1) | SR&B15; if(SR & 1) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006300: TRB(ASL);
RD_U; CLCV;
b = W(SR<<1); if(SR & B15) SEC; BXT;
if((PSW>>3^PSW)&1) SEV;
NZ; WR; SVC;
case 0006400:
case 0006500:
case 0006600:
case 0006700:
goto ri;
}
switch(cpu->ir & 0107400){
case 0004000:
case 0004400: TR(JSR);
if(dm == 0) goto ill;
if(addrop(cpu, dst, 0)) goto be;
DR = cpu->b;
PUSH; OUT(SP, cpu->r[sf]);
cpu->r[sf] = PC; PC = DR;
SVC;
case 0104000: TR(EMT); TRAP(030);
case 0104400: TR(TRAP); TRAP(034);
}
/* Branches */
switch(cpu->ir & 0103400){
case 0000400: TR(BR); BR; SVC;
case 0001000: TR(BNE); CBR(0x0F0F); SVC;
case 0001400: TR(BEQ); CBR(0xF0F0); SVC;
case 0002000: TR(BGE); CBR(0xCC33); SVC;
case 0002400: TR(BLT); CBR(0x33CC); SVC;
case 0003000: TR(BGT); CBR(0x0C03); SVC;
case 0003400: TR(BLE); CBR(0xF3FC); SVC;
case 0100000: TR(BPL); CBR(0x00FF); SVC;
case 0100400: TR(BMI); CBR(0xFF00); SVC;
case 0101000: TR(BHI); CBR(0x0505); SVC;
case 0101400: TR(BLOS); CBR(0xFAFA); SVC;
case 0102000: TR(BVC); CBR(0x3333); SVC;
case 0102400: TR(BVS); CBR(0xCCCC); SVC;
case 0103000: TR(BCC); CBR(0x5555); SVC;
case 0103400: TR(BCS); CBR(0xAAAA); SVC;
}
// Hope we caught all instructions we meant to
assert((cpu->ir & 0177400) == 0);
/* Misc */
switch(cpu->ir & 0300){
case 0100: TR(JMP);
if(dm == 0) goto ill;
if(addrop(cpu, dst, 0)) goto be;
PC = cpu->b;
SVC;
case 0200:
switch(cpu->ir&070){
case 000: TR(RTS);
BA = SP; POP;
PC = cpu->r[df];
IN(cpu->r[df]);
SVC;
case 010: case 020: case 030:
goto ri;
case 040: case 050: TR(CCC); PSW &= ~(cpu->ir&017); SVC;
case 060: case 070: TR(SEC); PSW |= cpu->ir&017; SVC;
}
case 0300: TR(SWAB);
if(readop(cpu, 011, dst, by)) goto be;
CLCV;
b = WD(DR & 0377, (DR>>8) & 0377);
NZ; WR; SVC;
}
/* Operate */
switch(cpu->ir & 7){
case 0: TR(HALT); cpu->state = STATE_HALTED; return;
case 1: TR(WAIT); cpu->state = STATE_WAITING; return;
case 2: TR(RTI);
BA = SP; POP; IN(PC);
BA = SP; POP; IN(PSW);
SVC;
case 3: TR(BPT); TRAP(014);
case 4: TR(IOT); TRAP(020);
case 5: TR(RESET); reset(cpu); SVC;
}
// All other instructions should be reserved now
ri: TRAP(010);
ill: TRAP(4);
be: if(cpu->be > 1){
printf("double bus error, HALT\n");
cpu->state = STATE_HALTED;
return;
}
printf("bus error\n");
TRAP(4);
trap:
trace("TRAP %o\n", TV);
PUSH; OUT(SP, PSW);
PUSH; OUT(SP, PC);
INA(TV, PC);
INA(TV+2, PSW);
/* no trace trap after a trap */
oldpsw = PSW;
tracestate(cpu);
SVC;
service:
c = PSW >> 5;
if(oldpsw & PSW_T){
oldpsw &= ~PSW_T;
TRAP(014);
}else if(cpu->traps & TRAP_STACK){
cpu->traps &= ~TRAP_STACK;
inhov = 1;
TRAP(4);
}else if(cpu->traps & TRAP_PWR){
cpu->traps &= ~TRAP_PWR;
TRAP(024);
}else if(c < 7 && cpu->traps & TRAP_BR7){
cpu->traps &= ~TRAP_BR7;
TRAP(cpu->br[3].bg(cpu->br[3].dev));
}else if(c < 6 && cpu->traps & TRAP_BR6){
cpu->traps &= ~TRAP_BR6;
TRAP(cpu->br[2].bg(cpu->br[2].dev));
}else if(c < 6 && cpu->traps & TRAP_CLK){
cpu->traps &= ~TRAP_CLK;
cpu->lc_int = 0;
TRAP(0100);
}else if(c < 5 && cpu->traps & TRAP_BR5){
cpu->traps &= ~TRAP_BR5;
TRAP(cpu->br[1].bg(cpu->br[1].dev));
}else if(c < 4 && cpu->traps & TRAP_BR4){
cpu->traps &= ~TRAP_BR4;
TRAP(cpu->br[0].bg(cpu->br[0].dev));
}else if(c < 4 && cpu->traps & TRAP_RX){
cpu->traps &= ~TRAP_RX;
cpu->rcd_int = 0;
TRAP(060);
}else if(c < 4 && cpu->traps & TRAP_TX){
cpu->traps &= ~TRAP_TX;
cpu->xmit_int = 0;
TRAP(064);
}else
// TODO? console stop
/* fetch next instruction */
return;
}
void
run(KD11B *cpu)
{
int n;
cpu->state = STATE_RUNNING;
initclock();
n = 0;
while(cpu->state != STATE_HALTED){
handleclock(cpu);
cpu->traps &= ~TRAP_CLK;
if(cpu->lc_int && cpu->lc_int_enab)
cpu->traps |= TRAP_CLK;
cpu->traps &= ~TRAP_TX;
if(cpu->xmit_int && cpu->xmit_int_enab)
cpu->traps |= TRAP_TX;
cpu->traps &= ~TRAP_RX;
if(cpu->rcd_int && cpu->rcd_int_enab)
cpu->traps |= TRAP_RX;
svc(cpu, cpu->bus);
if(cpu->state == STATE_RUNNING ||
cpu->state == STATE_WAITING && cpu->traps){
cpu->state = STATE_RUNNING;
step(cpu);
}
// Don't handle IO all the time
n++;
if(n != 20)
continue;
n = 0;
/* transmit */
if(!cpu->xmit_tbmt){
uint8 c = cpu->xmit_b & 0177;
write(cpu->ttyfd, &c, 1);
#ifdef AUTODIAG
extern int diagpassed;
if(c == '\a'){
diagpassed = 1;
return;
}
#endif
cpu->xmit_tbmt = 1;
cpu->xmit_int = 1;
}
/* receive */
if(hasinput(cpu->ttyfd)){
cpu->rcd_busy = 1;
cpu->rcd_rdr_enab = 0;
read(cpu->ttyfd, &cpu->rcd_b, 1);
cpu->rcd_da = 1;
cpu->rcd_busy = 0;
cpu->rcd_int = 1;
}
}
printstate(cpu);
}

View File

@@ -1,45 +0,0 @@
// 11/05 cpu
typedef struct KD11B KD11B;
struct KD11B
{
word r[16];
word b; // B register before BUT JSRJMP
word ba;
word ir;
Bus *bus;
byte psw;
int traps;
int be;
int state;
struct {
int (*bg)(void *dev);
void *dev;
} br[4];
word sw;
/* line clock */
int lc_int_enab;
int lc_clock;
int lc_int;
/* keyboard */
int rcd_busy;
int rcd_rdr_enab;
int rcd_int_enab;
int rcd_int;
int rcd_da;
byte rcd_b;
/* printer */
int xmit_int_enab;
int xmit_maint;
int xmit_int;
int xmit_tbmt;
byte xmit_b;
int ttyfd;
};
void run(KD11B *cpu);
void reset(KD11B *cpu);

View File

@@ -1,165 +0,0 @@
#include "11.h"
#include "kl11.h"
int
dati_kl11(Bus *bus, void *dev)
{
KL11 *kl = dev;
if(bus->addr >= 0777560 && bus->addr < 0777570){
switch(bus->addr&6){
/* Receive */
case 0:
bus->data = kl->rcd_int_enab<<6 |
kl->rcd_int<<7 |
kl->rcd_busy<<1;
break;
case 2:
bus->data = kl->rcd_b;
kl->rcd_b = 0;
kl->rcd_da = 0;
kl->rcd_int = 0;
break;
/* Transmit */
case 4:
bus->data = kl->xmit_maint<<2 |
kl->xmit_int_enab<<6 |
kl->xmit_int<<7;
break;
case 6:
/* write only */
bus->data = 0;
break;
default: assert(0); /* can't happen */
}
return 0;
}
return 1;
}
int
dato_kl11(Bus *bus, void *dev)
{
KL11 *kl = dev;
if(bus->addr >= 0777560 && bus->addr < 0777570){
switch(bus->addr&7){
/* Receive */
case 0:
// TODO: RDR ENAB
kl->rcd_rdr_enab = bus->data & 1;
if(!kl->rcd_int_enab && bus->data&0100 && kl->rcd_da)
kl->rcd_int = 1;
kl->rcd_int_enab = bus->data>>6 & 1;
break;
case 2:
/* read only */
break;
/* Transmit */
case 4:
// TODO: MAINT
kl->xmit_maint = bus->data>>2 & 1;
if(!kl->xmit_int_enab && bus->data&0100 && kl->xmit_tbmt)
kl->xmit_int = 1;
kl->xmit_int_enab = bus->data>>6 & 1;
break;
case 6:
kl->xmit_b = bus->data;
kl->xmit_tbmt = 0;
kl->xmit_int = 0;
break;
/* respond but don't do anything */
case 1:
case 3:
case 5:
case 7:
break;
default: assert(0); /* can't happen */
}
return 0;
}
return 1;
}
int
datob_kl11(Bus *bus, void *dev)
{
return dato_kl11(bus, dev);
}
int NNN;
int
svc_kl11(Bus *bus, void *dev)
{
KL11 *kl = dev;
NNN++;
if(NNN == 20){
/* transmit */
if(!kl->xmit_tbmt){
uint8 c = kl->xmit_b & 0177;
write(kl->ttyfd, &c, 1);
#ifdef AUTODIAG
extern int diagpassed;
if(c == '\a')
diagpassed = 1;
#endif
kl->xmit_tbmt = 1;
kl->xmit_int = 1;
}
/* receive */
if(hasinput(kl->ttyfd)){
kl->rcd_busy = 1;
kl->rcd_rdr_enab = 0;
read(kl->ttyfd, &kl->rcd_b, 1);
kl->rcd_da = 1;
kl->rcd_busy = 0;
kl->rcd_int = 1;
}
NNN = 0;
}
return kl->rcd_int && kl->rcd_int_enab ||
kl->xmit_int && kl->xmit_int_enab ? 4 : 0;
}
int
bg_kl11(void *dev)
{
KL11 *kl = dev;
if(kl->rcd_int && kl->rcd_int_enab){
kl->rcd_int = 0;
printf("rx trap\n");
return 060;
}
if(kl->xmit_int && kl->xmit_int_enab){
kl->xmit_int = 0;
printf("tx trap\n");
return 064;
}
assert(0); // can't happen
return 0;
}
void
reset_kl11(void *dev)
{
KL11 *kl = dev;
kl->rcd_busy = 0;
kl->rcd_rdr_enab = 0;
kl->rcd_int_enab = 0;
kl->rcd_int = 0;
kl->rcd_da = 0;
kl->rcd_b = 0;
kl->xmit_int_enab = 0;
kl->xmit_maint = 0;
kl->xmit_int = 1;
kl->xmit_tbmt = 1;
kl->xmit_b = 0;
}

View File

@@ -1,28 +0,0 @@
// stolen from KD11-B for now
typedef struct KL11 KL11;
struct KL11
{
/* keyboard */
int rcd_busy;
int rcd_rdr_enab;
int rcd_int_enab;
int rcd_int;
int rcd_da;
byte rcd_b;
/* printer */
int xmit_int_enab;
int xmit_maint;
int xmit_int;
int xmit_tbmt;
byte xmit_b;
int ttyfd;
};
int dati_kl11(Bus *bus, void *dev);
int dato_kl11(Bus *bus, void *dev);
int datob_kl11(Bus *bus, void *dev);
int svc_kl11(Bus *bus, void *dev);
int bg_kl11(void *dev);
void reset_kl11(void *dev);

View File

@@ -1,101 +0,0 @@
#include "11.h"
#include "kw11.h"
int
dati_kw11(Bus *bus, void *dev)
{
KW11 *kw = dev;
if(bus->addr == 777746){
bus->data = kw->lc_int_enab<<6 |
kw->lc_clock<<7;
return 0;
}
return 1;
}
int
dato_kw11(Bus *bus, void *dev)
{
KW11 *kw = dev;
if(bus->addr == 777546){
kw->lc_int_enab = bus->data>>6 & 1;
if((bus->data & 0200) == 0){
kw->lc_clock = 0;
kw->lc_int = 0;
}
return 0;
}
return 1;
}
int
datob_kw11(Bus *bus, void *dev)
{
/* ignore odd bytes */
if(bus->addr & 1)
return 0;
return dato_kw11(bus, dev);
}
#define CLOCKFREQ (1000000000/60)
static struct timespec oldtime, newtime;
static void
initclock(void)
{
clock_gettime(CLOCK_REALTIME, &newtime);
oldtime = newtime;
}
static void
handleclock(KW11 *kw)
{
struct timespec diff;
clock_gettime(CLOCK_REALTIME, &newtime);
diff.tv_sec = newtime.tv_sec - oldtime.tv_sec;
diff.tv_nsec = newtime.tv_nsec - oldtime.tv_nsec;
if(diff.tv_nsec < 0){
diff.tv_nsec += 1000000000;
diff.tv_sec -= 1;
}
if(diff.tv_nsec >= CLOCKFREQ){
kw->lc_clock = 1;
kw->lc_int = 1;
oldtime.tv_nsec += CLOCKFREQ;
if(oldtime.tv_nsec >= 1000000000){
oldtime.tv_nsec -= 1000000000;
oldtime.tv_sec += 1;
}
}
}
int
svc_kw11(Bus *bus, void *dev)
{
KW11 *kw = dev;
handleclock(kw);
return kw->lc_int && kw->lc_int_enab ? 6 : 0;
}
int
bg_kw11(void *dev)
{
KW11 *kw = dev;
kw->lc_int = 0;
return 0100;
}
void
reset_kw11(void *dev)
{
KW11 *kw = dev;
kw->lc_int_enab = 0;
// TODO: 1?
kw->lc_clock = 0;
kw->lc_int = 0;
initclock();
}

View File

@@ -1,16 +0,0 @@
// stolen from KD11-B for now
typedef struct KW11 KW11;
struct KW11
{
/* line clock */
int lc_int_enab;
int lc_clock;
int lc_int;
};
int dati_kw11(Bus *bus, void *dev);
int dato_kw11(Bus *bus, void *dev);
int datob_kw11(Bus *bus, void *dev);
int svc_kw11(Bus *bus, void *dev);
int bg_kw11(void *dev);
void reset_kw11(void *dev);

View File

@@ -1,38 +0,0 @@
#include "11.h"
int
dati_mem(Bus *bus, void *dev)
{
Memory *mem = dev;
uint32 waddr = bus->addr>>1;
if(waddr >= mem->start && waddr < mem->end){
bus->data = mem->mem[waddr-mem->start];
return 0;
}
return 1;
}
int
dato_mem(Bus *bus, void *dev)
{
Memory *mem = dev;
uint32 waddr = bus->addr>>1;
if(waddr >= mem->start && waddr < mem->end){
mem->mem[waddr-mem->start] = bus->data;
return 0;
}
return 1;
}
int
datob_mem(Bus *bus, void *dev)
{
Memory *mem = dev;
uint32 waddr = bus->addr>>1;
if(waddr >= mem->start && waddr < mem->end){
mem->mem[waddr-mem->start] &= (bus->addr&1) ? 0377 : ~0377;
mem->mem[waddr-mem->start] |= bus->data & ((bus->addr&1) ? ~0377 : 0377);
return 0;
}
return 1;
}

View File

@@ -1,773 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>
typedef uint8_t byte;
typedef uint16_t word;
typedef uint32_t lword;
enum
{
M8 = 0377,
M16 = 0177777
};
enum
{
PS_CM = 0140000,
PS_CM1 = 0100000, /* user */
PS_CM0 = 0040000, /* not kernel */
PS_PM = 0030000,
PS_PM1 = 0020000,
PS_PM0 = 0010000,
PS_GPR = 0004000,
PS_PL = 0000340,
PS_T = 0000020,
PS_N = 0000010,
PS_Z = 0000004,
PS_V = 0000002,
PS_C = 0000001
};
enum
{
SUBROM_ENV = 1,
SUBROM_VMOD0 = 2,
SUBROM_VMOD1 = 4,
SUBROM_ENC = 010,
SUBROM_CMOD0 = 020,
SUBROM_CMOD1 = 040,
SUBROM_ENZN = 0100,
SUBROM_MODZN = 0200,
SUBROM_R_PART_PCLASS = 0400,
SUBROM_R_ICLASS = 01000,
SUBROM_R_KCLASS = 02000,
SUBROM_R_MUL_ASHC_MFP = 04000,
SUBROM_R_MFP_MTP = 010000,
SUBROM_R_ROR_B_MUL = 020000,
SUBROM_DIV_ASHC = 040000,
SUBROM_SXT = 0100000
};
word subrom[32] = {
0020707, // ROR.B
0000705, // ROL.B
0000707, // ASR.B
0000705, // ASL.B
0000000, // MARK
0015351, // MFP
0010351, // MTP
0100751, // SXT
0000741, // CLR.B
0000721, // COM.B
0000750, // INC.B
0000752, // DEC.B
0000724, // NEG.B
0000740, // ADC.B
0000722, // SBC.B
0003341, // TST.B
0000726, // SUB
0000351, // MOV.B
0003146, // CMP.B
0003351, // BIT.B
0000751, // BIC.B
0000751, // BIS.B
0000744, // ADD
0000000, // NOT USED
0025231, // MUL
0045061, // DIV
0004341, // ASH
0044311, // ASHC
0000751, // XOR
0000000, // NOT USED
0000000, // NOT USED
0000000, // SOB
};
byte alucntl[32] = {
0060, // ROR.B
0354, // ROL.B
0060, // ASR.B
0054, // ASL.B
0000, // MARK
0252, // MFP
0252, // MTP
0243, // SXT
0243, // CLR.B
0240, // COM.B
0140, // INC.B
0057, // DEC.B
0240, // NEG.B
0340, // ADC.B
0357, // SBC.B
0040, // TST.B
0146, // SUB
0252, // MOV.B
0046, // CMP.B
0253, // BIT.B
0247, // BIC.B
0256, // BIS.B
0051, // ADD
0000, // -
0166, // MUL
0154, // DIV
0020, // ASH
0154, // ASHC
0246, // XOR
0000, // -
0000, // -
0000, // SOB
};
typedef struct Uword Uword;
struct Uword
{
int brk;
int brx;
int srx, drx;
int srk, drk;
int ccl;
int pca, pcb;
int shf;
int irk;
int pwe;
int pad;
int bsd;
int bax;
int ibs;
int shc;
int bct;
int msc;
int bsc;
int amx, bmx;
int kmx;
int alu;
// not buffered
int fen;
int bef;
int adr;
};
enum
{
INTR_PAUSE = 1,
BUS_PAUSE,
BUS_LONG_PAUSE
};
Uword urom[256] = {
#include "ucode.inc"
};
// TODO: is this even necessary?
typedef struct KB11Aregs KB11Aregs;
struct KB11Aregs
{
word br;
word pca, pcb;
word sr;
word dr;
word sc; // 6 bits
word ir;
word lr;
word bra;
byte sl;
byte pb;
word d;
byte rar;
Uword rbr;
word ps;
};
typedef struct KB11A KB11A;
struct KB11A
{
KB11Aregs c;
KB11Aregs n;
word gs[16];
word gd[16];
word radr;
Uword rom;
byte alucntl;
/* data path */
byte destcon;
byte srccon;
byte tv;
word k0mx;
word k1mx;
word amx;
word bmx;
word bamx;
word shfr;
word brmx;
int alu;
/* IR decode */
int sf;
int df;
int dm0_mfp_mtp;
/* ROM decode */
int dm0_mfp_mtp_cond;
/* various flip flops that probably don't
have to be in the Regs struct */
int grab_obd;
// TODO
int conf;
int brq_true;
int cnsl_act;
int sel_int;
int sel_mem;
// TMP, KT11 placeholders
int ps_restore;
// other placeholders
word unibusd;
word intbus;
// console or hardcoded
int sv;
lword sw;
};
void
dumpromw(Uword w)
{
printf("%o\t%o\t%o\t%o\t%o\t%o\t%o\t%o\t%o"
"\t%o\t%o\t%o\t%o\t%o\t%o\t%o\t%o\t%o"
"\t%o\t%o\t%o\t%o\t%o\t%o\t%o\t%o\t%o\n",
w.brk,
w.brx,
w.srx,
w.drx,
w.srk,
w.drk,
w.ccl,
w.pca,
w.pcb,
w.shf,
w.irk,
w.pwe,
w.pad,
w.bsd,
w.bax,
w.ibs,
w.shc,
w.bct,
w.msc,
w.bsc,
w.amx,
w.bmx,
w.kmx,
w.alu,
w.fen,
w.bef,
w.adr);
}
void
dumpstate(KB11A *kb)
{
printf("A/%06o B/%06o BA/%06o\n",
kb->amx, kb->bmx, kb->bamx);
printf("ALU/%07o SHFR/%06o\n",
kb->alu, kb->shfr);
printf("PCA/%06o PCB/%06o\n",
kb->c.pca, kb->c.pcb);
printf("SR/%06o DR/%06o\n",
kb->c.sr, kb->c.dr);
printf("BR/%06o IR/%06o\n",
kb->c.br, kb->c.ir);
}
word sxt(byte b) { return b & 0200 ? 0177400|b : b; }
// TODO: move things outta here
void
ir_decodeXXXX(KB11A *kb)
{
printf("IR/%06o\n", kb->c.ir);
// IRCH
int irch_bin = (kb->c.ir&0070000) != 0070000 &&
(kb->c.ir&0070000) != 0000000;
int irch_sub = (kb->c.ir&0170000) == 0160000;
int irch_subroma;
switch(kb->c.ir & 0070000){
case 0000000: irch_subroma = kb->c.ir>>6 & 017; break;
case 0010000: irch_subroma = 021; break;
case 0020000: irch_subroma = 022; break;
case 0030000: irch_subroma = 023; break;
case 0040000: irch_subroma = 024; break;
case 0050000: irch_subroma = 025; break;
case 0060000: irch_subroma = irch_sub ? 020 : 026; break;
case 0070000: irch_subroma = 030 | kb->c.ir>>9 & 7; break;
}
word irch_subword = subrom[irch_subroma];
kb->alucntl = alucntl[irch_subroma];
int ircc_rom_dec_ena = (kb->c.ir&0170000) == 0070000 ||
(kb->c.ir&0077000) == 0005000 ||
(kb->c.ir&0077000) == 0006000 ||
irch_bin;
// IRCB
int ircb_swab = (kb->c.ir&0177700) == 0000300;
int ircb_movb = (kb->c.ir&0170000) == 0110000;
int ircb_fclass = (kb->c.ir&0170000) == 0170000;
int ircb_jmp_jsr = (kb->c.ir&0177700) == 0000100 ||
(kb->c.ir&0177000) == 0004000;
int ircb_fjclass = ircb_fclass || ircb_jmp_jsr;
int ircb_neg_b = (kb->c.ir&0077700) == 0005400;
int ircb_obd_asrb_rorb = kb->grab_obd &&
((kb->c.ir&0177700) == 0106000 ||
(kb->c.ir&0177700) == 0106200);
int ircb_mul_ashc_mfp = ircc_rom_dec_ena &&
irch_subword&SUBROM_R_MUL_ASHC_MFP;
int ircb_part_pclass = ircc_rom_dec_ena &&
irch_subword&SUBROM_R_PART_PCLASS;
int ircb_pclass = ircb_part_pclass || ircb_swab || ircb_movb;
int ircb_iclass = ircc_rom_dec_ena &&
irch_subword&SUBROM_R_ICLASS;
int ircb_kclass = ircc_rom_dec_ena &&
irch_subword&SUBROM_R_KCLASS;
// IRCC
int ircc_mfp_mtp = ircc_rom_dec_ena && irch_subword&SUBROM_R_MFP_MTP;
int ircc_dm0_mfp_mtp = ircc_mfp_mtp && (kb->c.ir&0000077) == 0000000;
int ircc_oclass = (kb->c.ir&0170000) == 0010000 ||
(kb->c.ir&0077700) == 0006600;
// IRCD
int nobyte = (kb->c.ir&0070000) == 0060000 ||
(kb->c.ir&0177400) == 0106400;
int ircd_wdin = (kb->c.ir&0100000) == 0 || nobyte;
int ircd_byin = (kb->c.ir&0100000) != 0 && !nobyte && !ircb_fclass;
int ircd_sbyn = ircd_byin &&
(kb->c.ir&0077000) != 0005000 &&
(kb->c.ir&0077000) != 0006000;
int ircd_rtt = kb->c.ir == 0000006;
// TODO: these are inhibited by TMCB TRAP INH
int ircd_iot = kb->c.ir == 0000004;
int ircd_opcode3 = kb->c.ir == 0000003;
int ircd_trap = (kb->c.ir&01777400) == 0104400;
int ircd_emt = (kb->c.ir&01777400) == 0104000;
printf("%o %o\n", irch_subroma, irch_subword);
}
int
get_gsa(KB11A *kb)
{
int set1 = !kb->cnsl_act && kb->c.ps&PS_GPR && kb->sf<6 ||
kb->c.ps&PS_CM0 && kb->sf==6;
int gsa;
switch(kb->c.rbr.pad){
case 0:
case 1: gsa = kb->sf | (kb->c.ps&PS_CM1 && kb->sf==6); break;
case 4: gsa = kb->sf | 1; break;
case 2:
case 3: gsa = 5; break;
case 6: gsa = 0; break;
case 5: gsa = kb->df | (!kb->cnsl_act && kb->df==6 &&
kb->dm0_mfp_mtp_cond ? kb->c.ps&PS_PM1 : kb->c.ps&PS_CM1);
break;
case 7: gsa = kb->c.ps&PS_CM1 ? 7 : 6; break;
}
return gsa|set1<<3;
}
int
get_gda(KB11A *kb)
{
int set1 = !kb->cnsl_act && kb->c.ps&PS_GPR && kb->df<6 ||
kb->c.ps&PS_CM0 && kb->df==6 && !kb->dm0_mfp_mtp_cond;
int gda;
switch(kb->c.rbr.pad){
case 0: gda = kb->sf | (kb->c.ps&PS_CM1 && kb->sf==6); break;
case 4: gda = kb->sf | 1; break;
case 1:
case 5: gda = kb->df | (!kb->cnsl_act && kb->df==6 &&
kb->dm0_mfp_mtp_cond ? kb->c.ps&PS_PM1 : kb->c.ps&PS_CM1);
break;
case 2: gda = 5; break;
case 6: gda = 0; break;
case 3:
case 7: gda = kb->c.ps&PS_CM1 ? 7 : 6; break;
}
return gda|set1<<3;
}
void
load_sr(KB11A *kb)
{
if(kb->c.rbr.srk){
// TODO: don't set here
kb->sf = kb->c.ir>>6 & 7;
int srsel = kb->c.rbr.srx == 1 || kb->c.rbr.srx&2 && kb->sf!=7;
kb->n.sr = srsel ? kb->gs[get_gsa(kb)] : kb->shfr;
}
}
void
load_dr(KB11A *kb)
{
switch(kb->c.rbr.drk){
case 0: break;
case 1: kb->n.dr = kb->c.dr>>1 | kb->alu<<15; break;
case 2: kb->n.dr = kb->c.dr<<1; break; // TODO
case 3:
if(kb->c.rbr.drx == 3)
// TODO: this his held low until 5 even, do we need that?
kb->n.dr = 0;
else{
// TODO: don't set here, wrong too
kb->df = kb->c.ir & 7;
int drsel = kb->c.rbr.drx == 1 || kb->c.rbr.drx&2 && kb->df!=7;
kb->n.dr = drsel ? kb->gd[get_gda(kb)] : kb->shfr;
}
break;
}
}
void
update_state(KB11A *kb)
{
// TODO: tv
switch(kb->c.rbr.kmx){
case 0:
kb->k0mx = 1;
kb->k1mx = sxt(kb->sv);
break;
case 1:
kb->k0mx = 2; // TODO: correct?
kb->k1mx = kb->tv;
break;
case 2:
kb->k0mx = kb->srccon;
if(kb->c.sr & 0200) kb->k0mx |= 0177400;
kb->k1mx = kb->c.br & 0377;
break;
case 3:
kb->k0mx = kb->destcon;
if(kb->c.br & 0200) kb->k0mx |= 0177400;
kb->k1mx = sxt(kb->c.br) & 0173377;
break;
default: assert(0);
}
kb->k1mx &= ~1;
switch(kb->c.rbr.amx){
case 0: kb->amx = kb->c.dr; break;
case 1: kb->amx = kb->c.pcb; break;
case 2: kb->amx = kb->c.sr; break;
case 3: kb->amx = kb->c.br; break;
default: assert(0);
}
switch(kb->c.rbr.bmx){
case 0: kb->bmx = kb->k0mx; break;
case 1: kb->bmx = kb->k1mx; break;
case 2: kb->bmx = kb->c.sr; break;
case 3: kb->bmx = kb->c.br; break;
default: assert(0);
}
switch(kb->c.rbr.bax){
case 0: kb->bamx = kb->c.dr; break;
case 1: kb->bamx = kb->c.pcb; break;
case 2: kb->bamx = kb->c.sr; break;
case 3: kb->bamx = 0; break; // TODO: EALU
default: assert(0);
}
int shf = kb->c.rbr.shf;
switch(kb->c.rbr.alu){
case 0: kb->alu = ~kb->amx&M16; break;
case 1: kb->alu = kb->bmx; break;
case 2: kb->alu = kb->amx; break;
case 3: kb->alu = kb->amx + kb->bmx; break;
case 4: kb->alu = kb->amx + (kb->amx&(~kb->bmx&M16)); break;
case 5: kb->alu = kb->amx + kb->amx; break;
case 6: kb->alu = kb->amx + (~kb->bmx&M16) + 1; break;
case 7:
// change shf
assert(0 && "yikes, not implemented yet");
default: assert(0);
}
switch(shf){
case 0: kb->shfr = kb->alu<<8 | kb->alu>>8; break;
case 1: kb->shfr = kb->c.pcb; break;
case 2: kb->shfr = kb->alu; break;
// TODO: this is wrong
case 3: kb->shfr = kb->alu>>1;
assert(0); break;
default: assert(0);
}
switch(kb->c.rbr.ibs){
case 0: kb->intbus = 0; break;
case 1: kb->intbus = kb->sw; break;
case 2: kb->intbus = 0; break;
case 3: kb->intbus = kb->c.ps; break;
default: assert(0);
}
int wantunibus = kb->c.rbr.bsd==INTR_PAUSE; // TODO: DDC STOP?
int wantintbus = kb->c.rbr.ibs&1; // TODO: SW, KT11, FP
kb->sel_int = !wantunibus && wantintbus;
// we don't have fast mem
kb->sel_mem = !wantunibus && !wantintbus && 0;
switch(kb->c.rbr.brx<<2 | kb->sel_int<<1 | kb->sel_mem){
case 0: case 1: case 2: case 3: case 7:
kb->brmx = kb->shfr;
break;
case 4: kb->brmx = kb->unibusd; break;
case 5: kb->brmx = 0; break; // membus, we don't have it
case 6: kb->brmx = kb->intbus; break;
default: assert(0);
}
}
void
update_rom(KB11A *kb)
{
kb->rom = urom[kb->c.rar];
dumpromw(kb->rom);
// TODO: update state
}
byte
get_afork(KB11A *kb)
{
// TODO
return 0;
}
byte
get_bfork(KB11A *kb)
{
// TODO
return 0;
}
byte
get_cfork(KB11A *kb)
{
// TODO
return 0;
}
byte
get_brcab(KB11A *kb)
{
// TODO
switch(kb->rom.bef){
case 0: return 0;
case 1: assert(0); return 0; // TODO
case 2: assert(0); return 0; // TODO
case 3: assert(0); return 0; // TODO
case 4: assert(0); return 0; // TODO
case 5: assert(0); return 0; // TODO
case 6: return ~kb->c.br>>9 & 040 | kb->ps_restore<<4;
case 7: assert(0); return 0; // TODO
case 010: assert(0); return 0; // TODO
case 011: assert(0); return 0; // TODO
case 012: return kb->conf<<5 | !kb->brq_true<<4;
case 013: assert(0); return 0; // TODO
case 014: return 0; // TODO
case 015: assert(0); return 0; // TODO
case 016: assert(0); return 0; // TODO
case 017: assert(0); return 0; // TODO
default: assert(0);
}
return 0;
}
void
update_radr(KB11A *kb)
{
byte af = kb->c.rbr.fen & 1 ? get_afork(kb) : M8;
byte bf = kb->c.rbr.fen & 2 ? get_bfork(kb) : M8;
byte cf = kb->c.rbr.fen & 4 ? get_cfork(kb) : M8;
kb->radr = (kb->rom.adr | get_brcab(kb)) & cf & bf & af;
printf("getting new address %o\n", kb->radr);
}
void
t1(KB11A *kb)
{
printf("T1\n");
kb->n.rbr.bsd = kb->rom.bsd;
kb->n.rbr.bax = kb->rom.bax;
kb->n.rbr.ibs = kb->rom.ibs;
kb->n.rbr.shc = kb->rom.shc;
kb->n.rbr.bct = kb->rom.bct;
kb->n.rbr.msc = kb->rom.msc;
kb->n.rbr.bsc = kb->rom.bsc;
kb->n.rbr.amx = kb->rom.amx;
kb->n.rbr.bmx = kb->rom.bmx;
kb->n.rbr.kmx = kb->rom.kmx;
kb->n.rbr.alu = kb->rom.alu;
load_sr(kb);
load_dr(kb);
if(kb->c.rbr.drk == 3)
/* not quite correct, but should be ok */
kb->grab_obd = kb->n.dr & 1;
if(kb->c.rbr.brk)
printf("load BR %o %o\n", kb->c.rbr.brx<<2 | kb->sel_int<<1 | kb->sel_mem, kb->brmx);
kb->n.br = kb->brmx;
/* falling edge */
kb->n.rbr.pwe = kb->rom.pwe;
kb->n.rbr.pad = kb->rom.pad;
kb->c = kb->n;
update_state(kb);
}
void
t2(KB11A *kb)
{
printf("T2\n");
kb->n.rbr.brk = kb->rom.brk;
kb->n.rbr.brx = kb->rom.brx;
kb->n.rbr.srx = kb->rom.srx;
kb->n.rbr.drx = kb->rom.drx;
kb->n.rbr.srk = kb->rom.srk;
kb->n.rbr.drk = kb->rom.drk;
kb->n.rbr.ccl = kb->rom.ccl;
kb->n.rbr.pca = kb->rom.pca;
kb->n.rbr.pcb = kb->rom.pcb;
kb->n.rbr.shf = kb->rom.shf;
kb->n.rbr.irk = kb->rom.irk;
kb->c = kb->n;
update_state(kb);
}
void
t3(KB11A *kb)
{
printf("T3\n");
update_radr(kb);
kb->n.rar = kb->radr;
if(kb->c.rbr.bct == 7){ // TODO: or
// TODO: BEND, see UBCB CLR UNI
printf(" BEND (TODO)\n");
}
if(kb->c.rbr.msc == 6){
// TODO: BRQ strobe, TMCE
printf(" BRQ STROBE (TODO)\n");
// CLK CONF
// if(ubcf_s_inst) tmca_conf = 1;
// BRQ CLK
}
kb->c = kb->n;
update_state(kb);
update_rom(kb);
}
void
t4(KB11A *kb)
{
printf("T4\n");
kb->c = kb->n;
update_state(kb);
}
void
t5(KB11A *kb)
{
printf("T5\n");
kb->c = kb->n;
update_state(kb);
}
void
zap(KB11A *kb)
{
kb->n.rar = 0200;
}
void
power(KB11A *kb)
{
// TODO: don't do this
memset(kb, 0, sizeof(KB11A));
kb->ps_restore = 0;
// eh?
kb->conf = 1;
memset(&kb->n.rbr, 0, sizeof(Uword));
zap(kb);
kb->c = kb->n;
update_rom(kb);
}
void
test(KB11A *kb)
{
kb->n.pcb = 01234;
kb->n.dr = 04321;
kb->sw = 0112233;
kb->unibusd = 0123321;
int i;
for(i = 0; i < 3; i++){
t1(kb);
dumpstate(kb);
t2(kb);
dumpstate(kb);
if(kb->c.rbr.bsd == INTR_PAUSE)
printf(" INTR PAUSE\n");
t3(kb);
dumpstate(kb);
t4(kb);
dumpstate(kb);
t5(kb);
dumpstate(kb);
printf("----------\n");
}
t1(kb);
dumpstate(kb);
/*
kb->c.ir = 0012701;
kb->c.ir = 0066700;
ir_decode(kb);
update_state(kb);
*/
}
int
main()
{
KB11A *kb;
kb = malloc(sizeof(KB11A));
power(kb);
test(kb);
return 0;
}

View File

@@ -1,256 +0,0 @@
{ 1, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 1, 3, 0, 7, 0, 0, 0, 1, 1, 1, 0, 000, 0345 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 5, 0, 0, 0, 0, 0, 7, 6, 2, 0, 0, 2, 0, 015, 0115 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 5, 0, 0, 0, 0, 0, 7, 6, 2, 0, 0, 2, 0, 015, 0115 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 5, 0, 0, 0, 0, 0, 7, 0, 2, 0, 0, 2, 0, 000, 0221 },
{ 0, 0, 0, 0, 0, 3, 0, 1, 3, 2, 0, 2, 5, 0, 1, 0, 0, 7, 0, 0, 0, 0, 3, 6, 0, 001, 0122 },
{ 0, 0, 0, 0, 0, 3, 0, 1, 3, 2, 0, 2, 5, 0, 1, 0, 0, 7, 0, 0, 0, 0, 3, 6, 0, 001, 0122 },
{ 1, 1, 0, 2, 0, 3, 0, 1, 0, 2, 0, 0, 5, 2, 1, 0, 0, 0, 0, 0, 1, 0, 1, 3, 0, 000, 0251 },
{ 1, 1, 0, 2, 0, 3, 0, 1, 0, 2, 0, 0, 5, 2, 1, 0, 0, 0, 0, 0, 1, 0, 1, 3, 0, 000, 0251 },
{ 1, 1, 0, 1, 1, 3, 0, 0, 0, 1, 0, 0, 6, 0, 1, 3, 0, 7, 0, 0, 0, 0, 0, 0, 0, 000, 0327 },
{ 0, 0, 0, 1, 0, 3, 0, 0, 0, 2, 0, 0, 6, 0, 1, 0, 0, 7, 0, 0, 0, 0, 0, 2, 0, 012, 0244 },
{ 0, 0, 1, 0, 1, 0, 0, 0, 0, 2, 0, 0, 7, 0, 1, 0, 0, 7, 0, 0, 3, 0, 0, 2, 0, 000, 0156 },
{ 1, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 1, 3, 0, 7, 0, 0, 0, 1, 1, 1, 0, 000, 0354 },
{ 1, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 1, 3, 0, 7, 0, 0, 0, 1, 1, 1, 0, 000, 0354 },
{ 0, 0, 0, 1, 0, 3, 0, 0, 0, 2, 0, 0, 6, 0, 1, 0, 0, 7, 0, 0, 3, 0, 0, 2, 0, 000, 0255 },
{ 0, 0, 1, 0, 1, 0, 0, 0, 0, 2, 0, 0, 7, 0, 1, 0, 0, 7, 0, 0, 3, 0, 0, 2, 0, 000, 0156 },
{ 1, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 1, 3, 0, 7, 0, 0, 0, 1, 1, 1, 0, 000, 0345 },
{ 1, 1, 0, 0, 0, 0, 1, 0, 1, 2, 1, 1, 5, 3, 1, 0, 0, 0, 6, 0, 0, 2, 0, 7, 0, 000, 0343 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 2, 0, 0, 2, 0, 0, 0, 7, 1, 2, 0, 2, 3, 0, 000, 0027 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 2, 0, 0, 2, 0, 0, 0, 7, 1, 2, 0, 2, 3, 0, 000, 0027 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, 000, 0027 },
{ 0, 0, 0, 0, 1, 0, 0, 1, 2, 2, 0, 2, 0, 0, 1, 0, 0, 7, 0, 0, 2, 0, 2, 6, 0, 000, 0023 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 7, 0, 0, 0, 0, 0, 7, 5, 0, 0, 1, 6, 0, 000, 0041 },
{ 1, 1, 2, 2, 1, 3, 0, 0, 0, 2, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 0, 1, 3, 0, 000, 0054 },
{ 1, 1, 0, 2, 0, 3, 0, 0, 0, 1, 0, 0, 5, 3, 2, 0, 0, 0, 6, 1, 0, 0, 0, 0, 4, 014, 0317 },
{ 0, 0, 0, 0, 0, 0, 1, 1, 3, 2, 0, 1, 5, 0, 1, 0, 0, 7, 6, 0, 0, 2, 0, 7, 0, 000, 0217 },
{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 6, 0, 0, 0, 0, 0, 7, 6, 3, 2, 0, 7, 0, 000, 0132 },
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 3, 2, 0, 7, 0, 000, 0217 },
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 5, 0, 1, 0, 0, 0, 7, 0, 3, 2, 0, 7, 0, 012, 0240 },
{ 0, 0, 2, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 0, 000, 0201 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 7, 6, 0, 0, 0, 0, 2, 0, 000, 0217 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 2, 0, 000, 0225 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 000, 0025 },
{ 0, 0, 1, 0, 1, 0, 0, 1, 1, 2, 0, 0, 7, 0, 1, 0, 0, 7, 0, 0, 0, 0, 0, 2, 0, 000, 0223 },
{ 1, 0, 0, 1, 0, 3, 0, 0, 0, 2, 0, 0, 7, 3, 0, 0, 0, 0, 0, 5, 2, 0, 0, 2, 0, 000, 0222 },
{ 1, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 1, 3, 0, 7, 0, 0, 0, 1, 1, 1, 0, 000, 0345 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 7, 4, 0, 3, 0, 0, 2, 0, 000, 0261 },
{ 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 7, 6, 0, 3, 0, 0, 2, 0, 000, 0217 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 7, 0, 1, 0, 0, 7, 0, 0, 2, 0, 1, 3, 0, 000, 0151 },
{ 0, 0, 0, 2, 0, 3, 0, 0, 0, 1, 0, 1, 5, 0, 1, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 000, 0304 },
{ 0, 0, 1, 0, 1, 3, 0, 0, 0, 2, 0, 0, 2, 0, 1, 0, 0, 7, 0, 0, 1, 1, 2, 3, 0, 000, 0252 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 3, 7, 0, 0, 0, 0, 0, 2, 0, 000, 0102 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 7, 0, 0, 0, 0, 0, 2, 0, 000, 0061 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 2, 7, 0, 0, 2, 0, 0, 2, 0, 000, 0305 },
{ 0, 0, 0, 1, 0, 3, 0, 0, 0, 2, 0, 0, 4, 0, 1, 0, 2, 7, 0, 0, 2, 0, 0, 2, 0, 000, 0306 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 3, 0, 3, 0, 000, 0141 },
{ 0, 0, 0, 0, 0, 3, 4, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 0, 000, 0056 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 000, 0306 },
{ 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 7, 6, 0, 1, 1, 2, 6, 0, 001, 0242 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 6, 3, 0, 0, 2, 0, 000, 0102 },
{ 0, 0, 0, 1, 1, 3, 4, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, 2, 0, 000, 0254 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, 2, 0, 000, 0052 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, 2, 0, 000, 0053 },
{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, 7, 0, 000, 0123 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 6, 0, 0, 0, 0, 0, 7, 2, 0, 0, 0, 0, 0, 000, 0357 },
{ 0, 0, 1, 0, 1, 0, 1, 0, 0, 2, 0, 0, 7, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, 2, 0, 000, 0250 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, 7, 0, 000, 0271 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 000, 0153 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 1, 3, 0, 000, 0070 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 000, 0314 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 6, 0, 2, 0, 0, 0, 7, 5, 3, 0, 0, 2, 0, 000, 0303 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 1, 3, 0, 000, 0073 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 000, 0307 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 2, 0, 0, 6, 0, 0, 0, 0, 0, 2, 0, 000, 0015 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 000, 0130 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 6, 0, 0, 0, 1, 0, 1, 0, 000, 0347 },
{ 0, 0, 0, 0, 1, 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 0, 0, 7, 1, 0, 1, 0, 1, 6, 0, 000, 0133 },
{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 6, 0, 011, 0246 },
{ 0, 0, 0, 1, 0, 3, 0, 0, 0, 2, 0, 0, 4, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 2, 0, 000, 0147 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 0, 000, 0105 },
{ 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 0, 000, 0106 },
{ 0, 0, 1, 0, 1, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 000, 0055 },
{ 0, 0, 0, 1, 0, 3, 4, 0, 0, 2, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 000, 0147 },
{ 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 7, 6, 3, 0, 0, 2, 0, 015, 0135 },
{ 0, 0, 0, 0, 1, 0, 3, 0, 0, 2, 0, 0, 5, 0, 0, 0, 0, 0, 7, 6, 3, 0, 0, 2, 0, 015, 0115 },
{ 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 7, 0, 3, 0, 0, 2, 0, 000, 0221 },
{ 0, 0, 0, 0, 1, 0, 3, 0, 0, 2, 0, 0, 5, 0, 0, 0, 0, 0, 7, 0, 3, 0, 0, 2, 0, 000, 0221 },
{ 0, 0, 0, 0, 0, 3, 3, 1, 3, 2, 0, 2, 5, 0, 0, 0, 0, 0, 6, 0, 0, 0, 3, 6, 0, 001, 0131 },
{ 0, 0, 0, 0, 0, 3, 3, 1, 3, 2, 0, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 0, 001, 0121 },
{ 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 6, 0, 1, 0, 0, 0, 7, 0, 3, 0, 0, 2, 0, 000, 0006 },
{ 0, 0, 0, 0, 1, 0, 3, 0, 0, 2, 0, 0, 6, 0, 1, 0, 0, 0, 7, 0, 3, 0, 0, 2, 0, 000, 0006 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 3, 0, 6, 0, 0, 0, 0, 0, 2, 0, 002, 0152 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 5, 0, 0, 0, 0, 0, 7, 6, 3, 0, 0, 2, 2, 015, 0157 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 5, 0, 0, 0, 0, 0, 7, 6, 2, 0, 0, 2, 2, 015, 0157 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 7, 7, 3, 0, 0, 2, 0, 000, 0132 },
{ 1, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 1, 3, 0, 7, 0, 0, 0, 1, 1, 1, 0, 000, 0354 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 016, 0216 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 3, 7, 0, 2, 2, 0, 6, 0, 012, 0240 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 002, 0253 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 013, 0100 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 7, 6, 3, 0, 0, 2, 2, 015, 0177 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 6, 7, 3, 0, 0, 2, 0, 000, 0217 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 007, 0154 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 000, 0230 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 3, 2, 0, 2, 5, 0, 0, 0, 0, 7, 6, 0, 0, 0, 3, 3, 2, 000, 0137 },
{ 0, 0, 0, 0, 0, 0, 6, 0, 0, 2, 0, 2, 4, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 2, 0, 012, 0240 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, 2, 2, 000, 0377 },
{ 1, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 1, 1, 0, 000, 0152 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 6, 0, 2, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, 000, 0142 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 2, 0, 0, 0, 6, 1, 0, 0, 0, 0, 4, 014, 0317 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 6, 0, 2, 0, 0, 0, 7, 3, 0, 0, 0, 0, 0, 000, 0146 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 004, 0353 },
{ 0, 0, 0, 0, 0, 0, 7, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 0, 2, 0, 000, 0164 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 2, 0, 0, 0, 6, 3, 0, 0, 0, 0, 4, 000, 0377 },
{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 7, 0, 016, 0346 },
{ 1, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 1, 4, 0, 0, 1, 3, 0, 000, 0225 },
{ 0, 0, 0, 2, 0, 3, 0, 0, 0, 1, 0, 0, 5, 0, 2, 0, 0, 0, 7, 3, 0, 0, 0, 0, 0, 000, 0146 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 6, 0, 0, 0, 0, 6, 7, 2, 3, 0, 0, 2, 0, 000, 0355 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 000, 0134 },
{ 1, 1, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 012, 0130 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 3, 2, 0, 2, 5, 3, 0, 0, 0, 0, 6, 6, 0, 0, 3, 3, 0, 000, 0312 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 7, 0, 2, 0, 0, 0, 7, 0, 3, 0, 0, 2, 0, 000, 0212 },
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 6, 6, 3, 0, 0, 2, 0, 000, 0331 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 000, 0344 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 5, 0, 0, 0, 0, 0, 7, 0, 3, 0, 0, 2, 0, 000, 0231 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 5, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 000, 0231 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 5, 0, 0, 0, 0, 0, 7, 7, 3, 0, 0, 2, 0, 000, 0132 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 3, 7, 0, 2, 2, 0, 6, 0, 012, 0240 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 7, 0, 004, 0323 },
{ 0, 0, 0, 0, 1, 0, 5, 0, 0, 2, 0, 2, 0, 0, 1, 0, 1, 0, 6, 0, 2, 0, 0, 5, 0, 003, 0126 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 014, 0070 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 014, 0070 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 7, 0, 3, 0, 0, 2, 0, 000, 0231 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 6, 0, 0, 0, 0, 0, 0, 000, 0217 },
{ 1, 1, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 3, 0, 0, 1, 0, 0, 1, 0, 1, 3, 4, 000, 0377 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 6, 0, 3, 0, 0, 2, 0, 010, 0133 },
{ 1, 1, 0, 0, 0, 0, 0, 1, 3, 2, 0, 2, 5, 2, 0, 0, 0, 0, 6, 6, 0, 0, 3, 3, 2, 005, 0137 },
{ 0, 0, 0, 0, 1, 2, 5, 0, 0, 2, 0, 2, 0, 0, 0, 0, 1, 0, 6, 0, 2, 0, 0, 7, 0, 003, 0136 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 6, 6, 3, 0, 0, 2, 2, 005, 0137 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 7, 6, 0, 0, 0, 0, 2, 0, 006, 0352 },
{ 1, 0, 0, 1, 0, 3, 0, 0, 0, 2, 0, 0, 7, 0, 1, 0, 0, 0, 6, 0, 2, 0, 0, 2, 0, 000, 0274 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 000, 0030 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 000, 0030 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0, 0, 2, 0, 000, 0205 },
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 1, 5, 0, 1, 0, 0, 0, 7, 0, 0, 3, 0, 7, 0, 012, 0240 },
{ 1, 0, 0, 0, 0, 1, 4, 0, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0, 0, 2, 0, 000, 0310 },
{ 0, 0, 0, 0, 0, 0, 6, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 2, 0, 012, 0240 },
{ 0, 0, 0, 0, 0, 0, 1, 1, 3, 2, 0, 1, 5, 0, 2, 0, 0, 0, 6, 0, 2, 0, 0, 3, 0, 000, 0217 },
{ 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 7, 0, 0, 0, 0, 0, 2, 0, 000, 0362 },
{ 1, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 2, 7, 3, 2, 0, 0, 0, 0, 0, 2, 0, 1, 3, 0, 000, 0213 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 7, 0, 0, 0, 0, 0, 7, 0, 3, 0, 0, 2, 0, 000, 0214 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 000, 0215 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 000, 0172 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 3, 2, 0, 3, 0, 000, 0256 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 3, 7, 0, 2, 2, 0, 6, 0, 012, 0240 },
{ 0, 0, 0, 0, 0, 0, 4, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 3, 0, 004, 0144 },
{ 1, 1, 0, 0, 0, 0, 0, 1, 3, 2, 0, 2, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 000, 0233 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 7, 0, 0, 0, 0, 0, 7, 5, 0, 0, 0, 0, 0, 000, 0300 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 7, 0, 2, 0, 0, 0, 7, 0, 2, 0, 1, 3, 0, 000, 0224 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 5, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 000, 0342 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 010, 0205 },
{ 1, 0, 0, 0, 0, 1, 4, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 6, 0, 3, 2, 0, 7, 0, 000, 0310 },
{ 0, 0, 0, 0, 0, 0, 6, 0, 0, 2, 0, 2, 4, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 2, 0, 012, 0240 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 000, 0170 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 000, 0233 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 004, 0241 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0, 0, 2, 0, 000, 0311 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 0, 1, 0, 0, 0, 7, 0, 3, 0, 0, 2, 0, 012, 0240 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 7, 3, 0, 0, 0, 0, 6, 0, 0, 0, 1, 3, 0, 000, 0234 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 3, 2, 0, 6, 0, 000, 0276 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 3, 7, 0, 2, 2, 0, 6, 0, 012, 0240 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 7, 0, 0, 0, 0, 0, 2, 0, 000, 0154 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 000, 0103 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 6, 0, 3, 0, 0, 2, 0, 000, 0262 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 000, 0107 },
{ 1, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 012, 0127 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 6, 0, 0, 0, 0, 1, 7, 4, 0, 0, 0, 0, 0, 000, 0150 },
{ 1, 0, 0, 0, 0, 1, 4, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 2, 0, 011, 0206 },
{ 0, 0, 0, 0, 1, 2, 5, 0, 0, 2, 0, 2, 0, 0, 0, 0, 1, 0, 6, 0, 2, 0, 0, 7, 0, 003, 0136 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 2, 7, 0, 0, 0, 0, 7, 0, 0, 2, 0, 1, 6, 0, 000, 0222 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 3, 0, 3, 0, 001, 0122 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 2, 0, 0, 2, 0, 000, 0235 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 013, 0100 },
{ 0, 0, 0, 0, 0, 0, 4, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 002, 0232 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 000, 0374 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 004, 0350 },
{ 0, 0, 0, 0, 1, 0, 5, 0, 0, 2, 0, 2, 0, 0, 1, 0, 1, 0, 6, 0, 2, 0, 0, 5, 0, 003, 0126 },
{ 1, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 0, 3, 1, 0, 0, 0, 6, 0, 1, 0, 1, 3, 0, 000, 0343 },
{ 0, 0, 1, 3, 1, 0, 0, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 000, 0104 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 1, 0, 0, 0, 7, 0, 2, 0, 0, 6, 0, 012, 0240 },
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 000, 0145 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 2, 0, 000, 0011 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 3, 7, 0, 2, 2, 0, 6, 0, 012, 0240 },
{ 1, 0, 0, 0, 0, 1, 4, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 2, 0, 3, 0, 011, 0206 },
{ 0, 0, 0, 0, 1, 1, 1, 0, 0, 3, 0, 2, 0, 0, 0, 0, 1, 0, 6, 0, 2, 0, 0, 2, 0, 003, 0227 },
{ 0, 0, 0, 3, 1, 0, 0, 1, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 000, 0230 },
{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, 3, 0, 005, 0123 },
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 2, 0, 000, 0164 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 2, 0, 000, 0011 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 000, 0275 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 5, 7, 5, 0, 0, 0, 0, 0, 000, 0300 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 004, 0351 },
{ 0, 0, 0, 0, 1, 0, 1, 0, 0, 3, 0, 2, 0, 0, 1, 0, 1, 0, 6, 0, 2, 0, 0, 2, 0, 003, 0237 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 6, 5, 3, 0, 0, 2, 0, 000, 0217 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 7, 0, 0, 0, 0, 0, 7, 0, 000, 0210 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 000, 0154 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 2, 0, 0, 0, 0, 5, 3, 0, 0, 2, 0, 000, 0230 },
{ 1, 0, 1, 0, 1, 0, 1, 0, 0, 2, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 000, 0250 },
{ 0, 0, 0, 0, 0, 0, 4, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 2, 0, 0, 2, 0, 003, 0217 },
{ 0, 0, 0, 0, 0, 0, 4, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 2, 0, 0, 2, 0, 003, 0207 },
{ 0, 0, 0, 0, 0, 3, 0, 1, 3, 2, 0, 2, 5, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 000, 0230 },
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 2, 4, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 2, 0, 012, 0240 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 6, 0, 0, 0, 0, 0, 7, 6, 2, 0, 0, 2, 2, 015, 0157 },
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 5, 0, 1, 0, 0, 0, 7, 0, 3, 0, 0, 2, 0, 012, 0240 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 005, 0145 },
{ 0, 0, 0, 2, 0, 3, 0, 0, 0, 1, 0, 0, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 000, 0230 },
{ 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 000, 0302 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 017, 0316 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 000, 0143 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 0, 0, 7, 6, 0, 1, 1, 3, 3, 0, 000, 0217 },
{ 1, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 0, 3, 1, 0, 0, 0, 6, 0, 1, 0, 1, 3, 0, 000, 0343 },
{ 1, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 0, 3, 1, 0, 0, 0, 6, 0, 1, 0, 1, 3, 0, 000, 0343 },
{ 1, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 2, 0, 6, 0, 003, 0125 },
{ 1, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 0, 3, 1, 0, 0, 0, 6, 0, 1, 0, 1, 3, 0, 000, 0343 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 0, 0, 7, 6, 0, 1, 1, 3, 3, 0, 000, 0217 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 0, 0, 7, 6, 0, 1, 1, 3, 3, 0, 000, 0217 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 3, 0, 0, 2, 0, 006, 0124 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 0, 0, 7, 6, 0, 1, 1, 3, 3, 0, 000, 0217 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 3, 7, 0, 2, 2, 0, 6, 0, 012, 0240 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 3, 7, 0, 2, 2, 0, 6, 0, 012, 0240 },
{ 1, 1, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 000, 0340 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 3, 7, 0, 2, 2, 0, 6, 0, 012, 0240 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 0, 0, 7, 6, 0, 1, 1, 3, 3, 0, 000, 0217 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 0, 0, 7, 6, 0, 1, 1, 3, 3, 0, 000, 0317 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 000, 0337 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 6, 0, 2, 0, 0, 0, 7, 0, 3, 0, 0, 2, 0, 000, 0341 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 000, 0215 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 3, 2, 0, 2, 5, 0, 2, 0, 0, 0, 6, 0, 3, 0, 0, 2, 0, 000, 0217 },
{ 0, 0, 2, 2, 1, 3, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 5, 0, 1, 0, 1, 3, 1, 000, 0377 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 7, 0, 1, 0, 0, 0, 0, 0, 2, 0, 1, 3, 0, 000, 0140 },
{ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 000, 0354 },
{ 1, 0, 0, 0, 0, 2, 6, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 2, 0, 6, 0, 000, 0313 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 6, 0, 0, 0, 0, 0, 7, 0, 0, 1, 0, 1, 0, 000, 0333 },
{ 0, 0, 0, 0, 0, 0, 4, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 2, 0, 000, 0164 },
{ 0, 0, 1, 0, 1, 3, 4, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 000, 0220 },
{ 1, 1, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 012, 0130 },
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 000, 0145 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 6, 0, 0, 0, 0, 0, 7, 2, 3, 0, 0, 2, 0, 000, 0355 },
{ 1, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 2, 0, 0, 1, 3, 0, 000, 0065 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 3, 7, 0, 2, 2, 0, 6, 0, 012, 0240 },
{ 1, 1, 0, 0, 0, 3, 0, 1, 1, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 2, 3, 0, 0, 2, 0, 000, 0360 },
{ 1, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 7, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 000, 0367 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 3, 7, 0, 0, 0, 0, 0, 0, 000, 0260 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 000, 0316 },
{ 1, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 2, 0, 3, 0, 003, 0125 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 000, 0364 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 000, 0365 },
{ 1, 0, 0, 0, 0, 2, 6, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 2, 0, 3, 0, 000, 0313 },
{ 0, 0, 0, 1, 0, 3, 0, 0, 0, 1, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 000, 0037 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 000, 0351 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 000, 0350 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 000, 0315 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 3, 7, 0, 2, 2, 0, 6, 0, 012, 0240 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 2, 6, 0, 0, 0, 0, 2, 0, 010, 0334 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 5, 0, 3, 0, 0, 0, 1, 0, 3, 0, 0, 2, 0, 000, 0316 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 1, 0, 0, 3, 0, 0, 2, 0, 000, 0375 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 000, 0377 },

View File

@@ -1,312 +0,0 @@
FLOW STATE ADR BRK BRX SRX DRX SRK DRK CCL PCA PCB SHF IRK PWE PAD BSD BAX IBS SHC BCT MSC BSC AMX BMX KMX ALU FEN BEN UAD
12 RSD,00 000 1 1 0 0 0 3 0 0 0 2 0 0 0 0 1 3 0 7 0 0 0 1 1 1 0 00 345
5 D12,00 001 1 0 0 0 0 0 0 0 0 2 0 0 5 0 0 0 0 0 7 6 2 0 0 2 0 15 115
5 D12,01 002 1 0 0 0 0 0 0 0 0 2 0 0 5 0 0 0 0 0 7 6 2 0 0 2 0 15 115
5 D30,00 003 0 0 0 0 0 0 0 0 0 2 0 0 5 0 0 0 0 0 7 0 2 0 0 2 0 00 221
6 D45,00 004 0 0 0 0 0 3 0 1 3 2 0 2 5 0 1 0 0 7 0 0 0 0 3 6 0 01 122
6 D45,01 005 0 0 0 0 0 3 0 1 3 2 0 2 5 0 1 0 0 7 0 0 0 0 3 6 0 01 122
6 D67,00 006 1 1 0 2 0 3 0 1 0 2 0 0 5 2 1 0 0 0 0 0 1 0 1 3 0 00 251
6 D67,01 007 1 1 0 2 0 3 0 1 0 2 0 0 5 2 1 0 0 0 0 0 1 0 1 3 0 00 251
3 HLT,00 010 1 1 0 1 1 3 0 0 0 1 0 0 6 0 1 3 0 7 0 0 0 0 0 0 0 00 327
3 WAT,00 011 0 0 0 1 0 3 0 0 0 2 0 0 6 0 1 0 0 7 0 0 0 0 0 2 0 12 244
2 RTI,00 012 0 0 1 0 1 0 0 0 0 2 0 0 7 0 1 0 0 7 0 0 3 0 0 2 0 00 156
12 TRP,01 013 1 1 0 0 0 3 0 0 0 2 0 0 0 0 1 3 0 7 0 0 0 1 1 1 0 00 354
12 TRP,02 014 1 1 0 0 0 3 0 0 0 2 0 0 0 0 1 3 0 7 0 0 0 1 1 1 0 00 354
3 RES,00 015 0 0 0 1 0 3 0 0 0 2 0 0 6 0 1 0 0 7 0 0 3 0 0 2 0 00 255
2 RTI,01 016 0 0 1 0 1 0 0 0 0 2 0 0 7 0 1 0 0 7 0 0 3 0 0 2 0 00 156
12 RSD,01 017 1 1 0 0 0 3 0 0 0 2 0 0 0 0 1 3 0 7 0 0 0 1 1 1 0 00 345
3 EXC,80 020 1 1 0 0 0 0 1 0 1 2 1 1 5 3 1 0 0 0 6 0 0 2 0 7 0 00 343
1 S13,00 021 0 0 0 0 0 0 0 1 2 2 0 2 0 0 2 0 0 0 7 1 2 0 2 3 0 00 027
1 S13,01 022 0 0 0 0 0 0 0 1 2 2 0 2 0 0 2 0 0 0 7 1 2 0 2 3 0 00 027
1 S45,10 023 0 0 0 0 0 0 0 0 0 1 0 0 0 0 2 0 0 0 7 1 0 0 0 0 0 00 027
1 S45,00 024 0 0 0 0 1 0 0 1 2 2 0 2 0 0 1 0 0 7 0 0 2 0 2 6 0 00 023
13 SVC,60 025 0 0 0 0 0 0 0 0 0 2 0 2 7 0 0 0 0 0 7 5 0 0 1 6 0 00 041
2 S67,00 026 1 1 2 2 1 3 0 0 0 2 0 0 1 2 1 0 0 0 0 0 1 0 1 3 0 00 054
1 S13,10 027 1 1 0 2 0 3 0 0 0 1 0 0 5 3 2 0 0 0 6 1 0 0 0 0 4 14 317
3 EXC,90 030 0 0 0 0 0 0 1 1 3 2 0 1 5 0 1 0 0 7 6 0 0 2 0 7 0 00 217
11 EXC,00 031 1 0 0 0 0 0 1 0 0 2 0 0 6 0 0 0 0 0 7 6 3 2 0 7 0 00 132
11 TST,00 032 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 6 6 3 2 0 7 0 00 217
11 TST,10 033 0 0 0 0 0 0 1 0 0 2 0 0 5 0 1 0 0 0 7 0 3 2 0 7 0 12 240
11 JSR,00 034 0 0 2 0 1 0 0 1 0 1 0 0 0 0 0 0 0 7 0 0 0 0 0 2 0 00 201
11 JMP,00 035 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 7 6 0 0 0 0 2 0 00 217
7 FOP,40 036 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 7 1 0 0 0 0 2 0 00 225
13 SVC,50 037 0 0 0 0 0 3 0 0 0 2 0 2 7 0 0 0 0 0 0 0 0 0 1 6 0 00 025
2 RTS,00 040 0 0 1 0 1 0 0 1 1 2 0 0 7 0 1 0 0 7 0 0 0 0 0 2 0 00 223
13 SVC,70 041 1 0 0 1 0 3 0 0 0 2 0 0 7 3 0 0 0 0 0 5 2 0 0 2 0 00 222
12 RSD,02 042 1 1 0 0 0 3 0 0 0 2 0 0 0 0 1 3 0 7 0 0 0 1 1 1 0 00 345
3 SPL,00 043 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 7 4 0 3 0 0 2 0 00 261
3 CCP,00 044 0 0 0 0 0 0 2 0 0 2 0 0 0 0 1 0 0 7 6 0 3 0 0 2 0 00 217
1 MTP,00 045 0 0 0 0 0 0 0 0 0 2 0 2 7 0 1 0 0 7 0 0 2 0 1 3 0 00 151
11 MFP,80 046 0 0 0 2 0 3 0 0 0 1 0 1 5 0 1 0 0 7 0 0 0 0 0 0 0 00 304
2 MRK,00 047 0 0 1 0 1 3 0 0 0 2 0 0 2 0 1 0 0 7 0 0 1 1 2 3 0 00 252
3 MUL,80 050 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 3 7 0 0 0 0 0 2 0 00 102
3 DVS,00 051 1 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 7 0 0 0 0 0 2 0 00 061
7 ASH,10 052 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 2 7 0 0 2 0 0 2 0 00 305
7 ASC,10 053 0 0 0 1 0 3 0 0 0 2 0 0 4 0 1 0 2 7 0 0 2 0 0 2 0 00 306
2 S67,10 054 0 0 0 0 1 0 0 0 1 2 0 0 0 0 1 0 0 0 0 0 2 3 0 3 0 00 141
9 DVN,40 055 0 0 0 0 0 3 4 0 0 2 0 2 0 0 0 0 0 0 0 0 0 2 0 6 0 00 056
9 DVN,50 056 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 00 306
2 SOB,00 057 1 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 7 6 0 1 1 2 6 0 01 242
8 MUL,00 060 0 0 0 0 0 3 0 0 0 2 0 0 0 0 0 0 3 0 0 6 3 0 0 2 0 00 102
9 DIV,00 061 0 0 0 1 1 3 4 0 0 2 0 0 0 0 0 0 0 0 0 6 3 0 0 2 0 00 254
7 ASH,00 062 0 0 0 0 0 3 0 0 0 2 0 0 0 0 0 0 0 0 0 6 3 0 0 2 0 00 052
7 ASC,00 063 0 0 0 0 0 3 0 0 0 2 0 0 0 0 0 0 0 0 0 6 3 0 0 2 0 00 053
11 SHR,00 064 1 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 6 3 0 0 7 0 00 123
13 SVC,10 065 0 0 0 0 1 0 0 0 1 1 0 0 6 0 0 0 0 0 7 2 0 0 0 0 0 00 357
11 MFP,00 066 0 0 1 0 1 0 1 0 0 2 0 0 7 0 0 0 0 0 0 6 3 0 0 2 0 00 250
11 NEG,00 067 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 6 3 0 0 7 0 00 271
14 EXM,10 070 0 0 0 0 0 0 0 0 0 0 0 0 6 0 2 0 0 0 7 0 0 0 0 0 0 00 153
14 EXM,00 071 0 0 0 0 1 0 0 0 0 2 0 0 0 0 2 0 0 0 0 0 2 0 1 3 0 00 070
14 RAD,00 072 0 0 0 0 0 0 0 0 0 2 1 0 0 0 2 0 0 0 0 0 2 0 0 2 0 00 314
14 DEP,10 073 0 0 0 0 0 0 0 0 0 2 0 0 6 0 2 0 0 0 7 5 3 0 0 2 0 00 303
14 DEP,00 074 0 0 0 0 1 0 0 0 0 2 0 0 0 0 2 0 0 0 0 0 2 0 1 3 0 00 073
14 RDP,00 075 0 0 0 0 0 0 0 0 0 2 1 0 0 0 2 0 0 0 0 0 2 0 0 2 0 00 307
14 KST,00 076 0 0 0 0 0 0 0 0 1 2 0 0 0 0 2 0 0 6 0 0 0 0 0 2 0 00 015
14 CON,10 077 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 00 130
12 PUP,00 100 0 0 0 0 0 3 0 0 0 2 0 0 0 0 1 0 0 6 0 0 0 1 0 1 0 00 347
2 FOP,00 101 0 0 0 0 1 0 0 1 1 2 0 0 0 0 1 0 0 7 1 0 1 0 1 6 0 00 133
8 MUL,10 102 1 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 1 0 0 0 3 3 0 6 0 11 246
9 DVP,10 103 0 0 0 1 0 3 0 0 0 2 0 0 4 0 2 0 3 0 0 0 0 0 0 2 0 00 147
9 DVN,10 104 0 0 0 0 0 0 0 0 0 2 0 2 4 0 0 0 0 0 0 0 0 2 0 6 0 00 105
9 DVN,20 105 0 0 0 0 0 2 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 2 0 6 0 00 106
9 DVN,30 106 0 0 1 0 1 3 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 00 055
9 DVN,70 107 0 0 0 1 0 3 4 0 0 2 0 0 4 0 0 0 3 0 0 0 0 0 0 0 0 00 147
5 D12,90 110 0 0 0 0 1 0 3 0 0 0 0 0 5 0 0 0 0 0 7 6 3 0 0 2 0 15 135
5 D12,80 111 0 0 0 0 1 0 3 0 0 2 0 0 5 0 0 0 0 0 7 6 3 0 0 2 0 15 115
5 D30,90 112 0 0 0 0 1 0 3 0 0 0 0 0 5 0 0 0 0 0 7 0 3 0 0 2 0 00 221
5 D30,80 113 0 0 0 0 1 0 3 0 0 2 0 0 5 0 0 0 0 0 7 0 3 0 0 2 0 00 221
6 D45,90 114 0 0 0 0 0 3 3 1 3 2 0 2 5 0 0 0 0 0 6 0 0 0 3 6 0 01 131
6 D45,80 115 0 0 0 0 0 3 3 1 3 2 0 2 5 0 0 0 0 0 0 0 0 0 3 6 0 01 121
6 D67,90 116 0 0 0 0 1 0 3 0 0 0 0 0 6 0 1 0 0 0 7 0 3 0 0 2 0 00 006
6 D67,80 117 0 0 0 0 1 0 3 0 0 2 0 0 6 0 1 0 0 0 7 0 3 0 0 2 0 00 006
12 BRK,20 120 1 1 0 0 0 0 0 0 0 2 0 0 0 0 1 3 0 6 0 0 0 0 0 2 0 02 152
6 D40,20 121 0 0 0 0 1 0 0 0 0 2 0 0 5 0 0 0 0 0 7 6 3 0 0 2 2 15 157
6 D10,30 122 1 0 0 0 0 0 0 0 0 2 0 0 5 0 0 0 0 0 7 6 2 0 0 2 2 15 157
11 SHR,10 123 1 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 7 7 3 0 0 2 0 00 132
12 TRP,02 124 1 1 0 0 0 3 0 0 0 2 0 0 0 0 1 3 0 7 0 0 0 1 1 1 0 00 354
10 DVC,00 125 0 0 0 0 0 0 0 0 0 2 0 2 4 0 0 0 0 0 0 0 3 0 0 2 0 16 216
1 FET,05 126 0 0 0 0 0 0 0 0 0 2 1 0 0 0 1 0 0 3 7 0 2 2 0 6 0 12 240
3 WAT,30 127 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 3 0 0 2 0 02 253
12 BRK,10 130 0 0 0 0 0 3 0 0 0 2 0 0 0 0 1 0 0 0 0 0 3 0 0 2 0 13 100
6 D40,30 131 0 0 0 0 1 0 0 0 0 0 0 0 5 0 0 0 0 0 7 6 3 0 0 2 2 15 177
11 EXC,10 132 0 0 0 0 0 0 0 0 0 2 0 0 0 3 0 0 0 0 6 7 3 0 0 2 0 00 217
2 FOP,10 133 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 3 0 0 2 0 07 154
14 EXM,30 134 0 0 0 0 0 3 0 0 0 2 0 0 0 0 2 0 0 0 0 0 3 0 0 2 0 00 230
5 D12,70 135 0 0 0 0 0 0 0 1 3 2 0 2 5 0 0 0 0 7 6 0 0 0 3 3 2 00 137
7 ASC,61 136 0 0 0 0 0 0 6 0 0 2 0 2 4 0 1 0 0 0 7 0 0 0 0 2 0 12 240
5 D12,30 137 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 3 0 0 2 2 00 377
12 BRK,80 140 1 1 0 0 0 3 0 0 0 2 0 0 0 0 1 3 0 0 0 0 0 1 1 1 0 00 152
2 S67,20 141 0 0 0 0 0 0 0 0 0 1 0 0 6 0 2 0 0 0 7 1 0 0 0 0 0 00 142
2 S67,30 142 1 1 0 0 0 0 0 0 0 1 0 0 0 3 2 0 0 0 6 1 0 0 0 0 4 14 317
2 S13,30 143 0 0 0 0 0 0 0 0 0 1 0 0 6 0 2 0 0 0 7 3 0 0 0 0 0 00 146
10 DVD,00 144 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 2 0 0 2 0 04 353
9 DVE,20 145 0 0 0 0 0 0 7 0 0 2 0 0 0 0 2 0 0 0 6 0 0 0 0 2 0 00 164
2 S13,40 146 1 1 0 0 0 0 0 0 0 1 0 0 0 3 2 0 0 0 6 3 0 0 0 0 4 00 377
9 DIV,30 147 1 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 3 0 0 7 0 16 346
12 FSV,10 150 1 1 0 0 0 3 0 0 0 2 0 0 0 3 0 0 0 0 1 4 0 0 1 3 0 00 225
1 MTP,10 151 0 0 0 2 0 3 0 0 0 1 0 0 5 0 2 0 0 0 7 3 0 0 0 0 0 00 146
12 BRK,30 152 0 0 0 0 0 0 0 1 0 2 0 0 6 0 0 0 0 6 7 2 3 0 0 2 0 00 355
14 EXM,20 153 1 1 0 0 0 0 0 0 0 0 0 0 0 3 2 0 0 0 0 0 0 0 0 0 0 00 134
12 BRK,00 154 1 1 0 0 1 0 0 0 0 2 0 0 0 1 1 0 0 0 0 0 1 0 0 2 0 12 130
5 D12,60 155 0 0 0 0 0 0 0 1 3 2 0 2 5 3 0 0 0 0 6 6 0 0 3 3 0 00 312
2 RTI,10 156 0 0 0 0 0 0 0 0 0 2 0 0 7 0 2 0 0 0 7 0 3 0 0 2 0 00 212
6 D10,40 157 0 0 0 0 0 0 1 0 0 2 0 0 0 3 0 0 0 0 6 6 3 0 0 2 0 00 331
12 SER,00 160 0 0 0 0 1 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 00 344
6 D50,20 161 0 0 0 0 1 0 0 0 0 2 0 0 5 0 0 0 0 0 7 0 3 0 0 2 0 00 231
6 D10,00 162 0 0 0 0 0 0 0 0 0 1 0 0 5 0 0 0 0 0 7 0 0 0 0 0 0 00 231
11 NEG,20 163 0 0 0 0 0 0 0 0 0 2 0 0 5 0 0 0 0 0 7 7 3 0 0 2 0 00 132
1 FET,04 164 0 0 0 0 0 0 0 0 0 2 1 0 0 0 1 0 0 3 7 0 2 2 0 6 0 12 240
9 DIV,70 165 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 3 0 0 7 0 04 323
7 ASH,41 166 0 0 0 0 1 0 5 0 0 2 0 2 0 0 1 0 1 0 6 0 2 0 0 5 0 03 126
14 CON,01 167 1 1 0 0 0 0 0 0 0 2 0 0 0 0 2 1 0 0 0 0 0 0 0 2 0 14 070
14 CON,00 170 1 1 0 0 0 0 0 0 0 2 0 0 0 0 2 1 0 0 0 0 0 0 0 2 0 14 070
6 D50,30 171 0 0 0 0 1 0 0 0 0 0 0 0 5 0 0 0 0 0 7 0 3 0 0 2 0 00 231
2 RTI,20 172 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 2 6 0 0 0 0 0 0 00 217
2 FOP,30 173 1 1 0 0 0 0 0 1 1 2 0 0 0 0 3 0 0 1 0 0 1 0 1 3 4 00 377
2 FOP,20 174 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 6 0 3 0 0 2 0 10 133
5 D12,10 175 1 1 0 0 0 0 0 1 3 2 0 2 5 2 0 0 0 0 6 6 0 0 3 3 2 05 137
7 ASC,31 176 0 0 0 0 1 2 5 0 0 2 0 2 0 0 0 0 1 0 6 0 2 0 0 7 0 03 136
6 D10,60 177 1 1 0 0 0 0 0 0 0 2 0 0 0 2 0 0 0 0 6 6 3 0 0 2 2 05 137
12 ZAP,00 200 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 7 6 0 0 0 0 2 0 06 352
11 JSR,10 201 1 0 0 1 0 3 0 0 0 2 0 0 7 0 1 0 0 0 6 0 2 0 0 2 0 00 274
4 D07,00 202 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 00 030
4 D07,10 203 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 00 030
4 D00,80 204 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 3 0 0 2 0 00 205
4 D00,90 205 0 0 0 0 0 0 1 0 0 2 0 1 5 0 1 0 0 0 7 0 0 3 0 7 0 12 240
8 MUL,40 206 1 0 0 0 0 1 4 0 0 3 0 2 0 0 0 0 0 0 6 0 3 0 0 2 0 00 310
7 ASC,80 207 0 0 0 0 0 0 6 0 0 2 0 0 0 0 1 0 0 0 7 0 0 0 0 2 0 12 240
3 NEG,90 210 0 0 0 0 0 0 1 1 3 2 0 1 5 0 2 0 0 0 6 0 2 0 0 3 0 00 217
4 FOP,50 211 0 0 0 0 0 0 3 0 0 2 0 0 0 0 3 0 0 7 0 0 0 0 0 2 0 00 362
2 RTI,20 212 1 1 0 0 0 3 0 0 0 2 0 2 7 3 2 0 0 0 0 0 2 0 1 3 0 00 213
2 RTI,30 213 0 0 0 0 0 0 0 1 1 1 0 0 7 0 0 0 0 0 7 0 3 0 0 2 0 00 214
2 RTI,40 214 1 1 0 0 0 0 0 0 0 2 0 2 7 2 0 0 0 0 0 0 0 0 1 3 0 00 215
2 RTI,50 215 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 00 172
10 DVC,10 216 1 0 0 0 0 0 0 0 0 2 0 2 4 0 0 0 0 0 0 0 3 2 0 3 0 00 256
1 FET,00 217 0 0 0 0 0 0 0 0 0 2 1 0 0 0 1 0 0 3 7 0 2 2 0 6 0 12 240
10 DVC,90 220 0 0 0 0 0 0 4 0 0 2 0 2 0 0 0 0 0 0 6 0 0 0 0 3 0 04 144
5 D30,10 221 1 1 0 0 0 0 0 1 3 2 0 2 5 2 0 0 0 0 0 0 0 0 3 3 0 00 233
13 SVC,80 222 0 0 0 0 0 0 0 0 0 1 0 0 7 0 0 0 0 0 7 5 0 0 0 0 0 00 300
2 RTS,10 223 0 0 0 0 0 0 0 0 0 2 0 2 7 0 2 0 0 0 7 0 2 0 1 3 0 00 224
2 RTS,20 224 1 1 0 0 0 0 0 0 0 1 0 0 5 2 2 0 0 0 0 0 0 0 0 0 0 00 342
12 FSV,20 225 0 0 0 0 0 0 0 0 0 1 0 0 0 0 3 0 0 0 6 0 0 0 0 0 0 10 205
8 MUL,50 226 1 0 0 0 0 1 4 0 0 2 0 2 0 0 0 0 0 0 6 0 3 2 0 7 0 00 310
7 ASC,60 227 0 0 0 0 0 0 6 0 0 2 0 2 4 0 1 0 0 0 7 0 0 0 0 2 0 12 240
14 CON,20 230 0 0 0 0 0 0 0 0 0 2 0 0 0 0 2 0 0 2 0 0 0 0 0 2 0 00 170
6 D10,10 231 1 1 0 0 0 0 0 0 0 2 0 0 0 2 0 0 0 0 0 0 3 0 0 2 0 00 233
9 DIV,20 232 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 2 0 0 2 0 04 241
6 D10,20 233 0 0 0 0 0 3 0 0 0 2 0 0 0 0 0 0 0 0 6 0 3 0 0 2 0 00 311
2 MRK,30 234 0 0 0 0 0 0 0 0 0 2 0 2 2 0 1 0 0 0 7 0 3 0 0 2 0 12 240
2 MRK,20 235 1 1 0 0 0 0 0 0 0 2 0 2 7 3 0 0 0 0 6 0 0 0 1 3 0 00 234
10 DVC,20 236 1 0 0 0 0 0 0 0 0 2 0 2 4 0 0 0 0 0 0 0 3 2 0 6 0 00 276
1 FET,07 237 0 0 0 0 0 0 0 0 0 2 1 0 0 0 1 0 0 3 7 0 2 2 0 6 0 12 240
12 BRK,90 240 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 7 0 0 0 0 0 2 0 00 154
9 DVP,00 241 1 0 0 0 0 0 0 0 0 2 0 0 0 0 2 0 0 0 0 0 0 0 0 2 0 00 103
2 SOB,10 242 0 0 0 0 0 0 0 1 1 2 0 0 0 0 2 0 0 0 6 0 3 0 0 2 0 00 262
9 DVN,60 243 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 00 107
3 WAT,20 244 1 1 0 0 0 3 0 0 0 2 0 0 0 1 1 0 0 0 0 0 0 1 1 1 0 12 127
12 FSV,00 245 1 1 0 0 0 0 0 0 0 1 0 0 6 0 0 0 0 1 7 4 0 0 0 0 0 00 150
8 MUL,30 246 1 0 0 0 0 1 4 0 0 3 0 0 0 0 0 0 1 0 0 0 3 0 0 2 0 11 206
7 ASC,30 247 0 0 0 0 1 2 5 0 0 2 0 2 0 0 0 0 1 0 6 0 2 0 0 7 0 03 136
11 MFP,10 250 0 0 0 0 0 3 0 0 0 2 0 2 7 0 0 0 0 7 0 0 2 0 1 6 0 00 222
6 D67,10 251 0 0 0 0 0 3 0 0 1 2 0 0 0 0 1 0 0 0 6 0 0 3 0 3 0 01 122
2 MRK,10 252 0 0 0 0 0 0 0 1 1 2 0 0 0 0 0 0 0 0 7 0 2 0 0 2 0 00 235
12 BRK,11 253 0 0 0 0 0 3 0 0 0 2 0 0 0 0 1 0 0 0 0 0 3 0 0 2 0 13 100
9 DIV,10 254 0 0 0 0 0 0 4 0 0 2 0 0 0 0 2 0 0 0 0 0 0 0 0 2 0 02 232
3 RES,10 255 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 4 0 0 0 0 0 2 0 00 374
10 DVC,30 256 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 04 350
7 ASH,40 257 0 0 0 0 1 0 5 0 0 2 0 2 0 0 1 0 1 0 6 0 2 0 0 5 0 03 126
1 FET,10 260 1 1 0 0 0 0 0 1 1 2 1 0 0 3 1 0 0 0 6 0 1 0 1 3 0 00 343
9 DVN,00 261 0 0 1 3 1 0 0 0 0 2 0 0 4 0 0 0 0 0 0 0 2 0 0 2 0 00 104
2 SOB,20 262 0 0 0 0 0 0 0 0 0 2 0 2 0 0 1 0 0 0 7 0 2 0 0 6 0 12 240
9 DVE,10 263 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 00 145
3 WAT,10 264 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 6 0 0 0 0 2 0 00 011
1 FET,09 265 0 0 0 0 0 0 0 0 0 2 1 0 0 0 1 0 0 3 7 0 2 2 0 6 0 12 240
8 MUL,20 266 1 0 0 0 0 1 4 0 0 3 0 0 0 0 0 0 1 0 0 0 3 2 0 3 0 11 206
7 ASC,40 267 0 0 0 0 1 1 1 0 0 3 0 2 0 0 0 0 1 0 6 0 2 0 0 2 0 03 227
14 ADR,00 270 0 0 0 3 1 0 0 1 0 2 0 0 0 0 2 0 0 0 0 0 3 0 0 2 0 00 230
11 NEG,10 271 1 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 6 3 0 0 3 0 05 123
9 DVE,00 272 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 6 0 2 0 0 2 0 00 164
3 WAT,11 273 0 0 0 0 0 3 0 0 0 2 0 0 0 0 1 0 0 0 6 0 0 0 0 2 0 00 011
11 JSR,20 274 0 0 0 0 0 3 0 0 0 2 0 2 7 0 0 0 0 0 0 0 0 0 1 6 0 00 275
11 JSR,30 275 0 0 0 0 0 0 0 0 1 1 0 2 0 0 0 0 0 5 7 5 0 0 0 0 0 00 300
10 DVC,40 276 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 04 351
7 ASH,30 277 0 0 0 0 1 0 1 0 0 3 0 2 0 0 1 0 1 0 6 0 2 0 0 2 0 03 237
13 SVC,90 300 0 0 0 0 0 0 0 0 0 2 0 0 0 3 0 0 0 0 6 5 3 0 0 2 0 00 217
3 NEG,70 301 0 0 0 0 1 0 0 0 0 2 0 0 0 0 1 0 0 7 0 0 0 0 0 7 0 00 210
12 ZAP,30 302 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 00 154
14 DEP,20 303 0 0 0 0 0 3 0 0 0 2 0 0 0 3 2 0 0 0 0 5 3 0 0 2 0 00 230
11 MFP,90 304 1 0 1 0 1 0 1 0 0 2 0 0 7 0 0 0 0 0 0 0 0 0 0 2 0 00 250
7 ASH,20 305 0 0 0 0 0 0 4 0 0 2 0 0 0 0 0 0 1 0 6 0 2 0 0 2 0 03 217
7 ASC,20 306 0 0 0 0 0 0 4 0 0 2 0 0 0 0 0 0 1 0 6 0 2 0 0 2 0 03 207
14 RDP,10 307 0 0 0 0 0 3 0 1 3 2 0 2 5 0 2 0 0 0 0 0 3 0 0 2 0 00 230
8 MUL,60 310 0 0 0 0 0 0 1 0 0 2 0 2 4 0 1 0 0 0 7 0 0 0 0 2 0 12 240
6 D10,50 311 1 0 0 0 0 0 0 0 0 2 0 0 6 0 0 0 0 0 7 6 2 0 0 2 2 15 157
5 D12,20 312 0 0 0 0 0 0 1 0 0 2 0 0 5 0 1 0 0 0 7 0 3 0 0 2 0 12 240
9 DIV,60 313 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 3 0 0 2 0 05 145
14 RAD,10 314 0 0 0 2 0 3 0 0 0 1 0 0 5 0 2 0 0 0 0 0 0 0 0 0 0 00 230
12 ZAP,20 315 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 2 0 0 2 0 00 302
4 FOP,70 316 0 0 0 0 0 0 0 0 0 2 0 0 0 0 3 0 0 0 0 0 3 0 0 2 0 17 316
2 S13,20 317 0 0 0 0 1 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 3 0 0 2 0 00 143
1 BXX,00 320 0 0 0 0 0 0 0 1 1 2 0 0 0 0 1 0 0 7 6 0 1 1 3 3 0 00 217
1 FET,11 321 1 1 0 0 0 0 0 1 1 2 1 0 0 3 1 0 0 0 6 0 1 0 1 3 0 00 343
1 FET,12 322 1 1 0 0 0 0 0 1 1 2 1 0 0 3 1 0 0 0 6 0 1 0 1 3 0 00 343
9 DIV,80 323 1 0 0 0 0 2 0 0 0 2 0 0 0 0 0 0 1 0 0 0 3 2 0 6 0 03 125
1 FET,13 324 1 1 0 0 0 0 0 1 1 2 1 0 0 3 1 0 0 0 6 0 1 0 1 3 0 00 343
1 BXX,01 325 0 0 0 0 0 0 0 1 1 2 0 0 0 0 1 0 0 7 6 0 1 1 3 3 0 00 217
1 BXX,02 326 0 0 0 0 0 0 0 1 1 2 0 0 0 0 1 0 0 7 6 0 1 1 3 3 0 00 217
3 HLT,10 327 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 3 0 3 0 0 2 0 06 124
1 BXX,03 330 0 0 0 0 0 0 0 1 1 2 0 0 0 0 1 0 0 7 6 0 1 1 3 3 0 00 217
1 FET,01 331 0 0 0 0 0 0 0 0 0 2 1 0 0 0 1 0 0 3 7 0 2 2 0 6 0 12 240
1 FET,02 332 0 0 0 0 0 0 0 0 0 2 1 0 0 0 1 0 0 3 7 0 2 2 0 6 0 12 240
12 PUP,20 333 1 1 0 0 1 0 0 0 0 2 0 0 0 3 0 0 0 0 0 0 0 0 1 3 0 00 340
1 FET,03 334 0 0 0 0 0 0 0 0 0 2 1 0 0 0 1 0 0 3 7 0 2 2 0 6 0 12 240
1 BXX,04 335 0 0 0 0 0 0 0 1 1 2 0 0 0 0 1 0 0 7 6 0 1 1 3 3 0 00 217
1 BXX,05 336 0 0 0 0 0 0 0 1 1 2 0 0 0 0 1 0 0 7 6 0 1 1 3 3 0 00 317
13 XXX,XX 337 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 00 337
12 PUP,30 340 0 0 0 0 0 0 0 1 1 2 0 0 6 0 2 0 0 0 7 0 3 0 0 2 0 00 341
12 PUP,40 341 1 1 0 0 0 0 0 0 0 1 0 0 0 3 2 0 0 0 0 0 0 0 0 0 0 00 215
2 RTS,30 342 0 0 0 0 0 0 0 1 3 2 0 2 5 0 2 0 0 0 6 0 3 0 0 2 0 00 217
1 IRD,00 343 0 0 2 2 1 3 0 1 0 1 0 0 1 0 1 0 0 0 5 0 1 0 1 3 1 00 377
12 SER,10 344 0 0 0 0 0 0 0 0 0 2 0 2 7 0 1 0 0 0 0 0 2 0 1 3 0 00 140
12 RSD,10 345 0 0 0 0 0 3 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 00 354
9 DIV,40 346 1 0 0 0 0 2 6 0 0 2 0 0 0 0 0 0 1 0 0 0 3 2 0 6 0 00 313
12 PUP,10 347 0 0 0 0 0 0 0 0 0 2 0 0 6 0 0 0 0 0 7 0 0 1 0 1 0 00 333
10 DVC,70 350 0 0 0 0 0 0 4 0 0 2 0 2 0 0 0 0 0 0 6 0 0 0 0 2 0 00 164
10 DVC,80 351 0 0 1 0 1 3 4 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 220
12 BRK,01 352 1 1 0 0 1 0 0 0 0 2 0 0 0 1 1 0 0 0 0 0 1 0 0 2 0 12 130
10 DVD,10 353 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 2 0 0 2 0 00 145
12 TRP,10 354 0 0 0 0 0 0 0 1 0 2 0 0 6 0 0 0 0 0 7 2 3 0 0 2 0 00 355
13 SVC,00 355 1 1 0 0 0 3 0 0 0 2 0 0 0 3 0 0 0 0 0 2 0 0 1 3 0 00 065
1 FET,08 356 0 0 0 0 0 0 0 0 0 2 1 0 0 0 1 0 0 3 7 0 2 2 0 6 0 12 240
13 SVC,20 357 1 1 0 0 0 3 0 1 1 1 0 0 0 3 0 0 0 0 0 2 3 0 0 2 0 00 360
13 SVC,30 360 1 0 0 0 0 0 0 1 0 2 0 0 7 0 0 2 0 0 0 2 0 0 0 2 0 00 367
3 SPL,10 361 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 3 7 0 0 0 0 0 0 00 260
4 FOP,60 362 1 0 0 0 0 0 0 0 0 2 0 0 0 0 3 0 0 0 1 0 0 0 0 2 0 00 316
9 DIV,90 363 1 0 0 0 0 2 0 0 0 2 0 0 0 0 0 0 1 0 0 0 3 2 0 3 0 03 125
13 XXX,XX 364 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 00 364
13 XXX,XX 365 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 00 365
9 DIV,50 366 1 0 0 0 0 2 6 0 0 2 0 0 0 0 0 0 1 0 0 0 3 2 0 3 0 00 313
13 SVC,40 367 0 0 0 1 0 3 0 0 0 1 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 00 037
10 DVC,50 370 0 0 0 0 0 0 0 0 0 2 0 2 4 0 0 0 0 0 0 0 3 0 0 3 0 00 351
10 DVC,60 371 0 0 0 0 0 0 0 0 0 2 0 2 4 0 0 0 0 0 0 0 3 0 0 3 0 00 350
12 ZAP,10 372 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 315
1 FET,06 373 0 0 0 0 0 0 0 0 0 2 1 0 0 0 1 0 0 3 7 0 2 2 0 6 0 12 240
3 RES,20 374 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 2 6 0 0 0 0 2 0 10 334
4 FOP,90 375 0 0 0 0 0 0 0 0 0 2 0 2 5 0 3 0 0 0 1 0 3 0 0 2 0 00 316
4 FOP,80 376 1 1 0 0 0 0 0 0 0 2 0 0 0 0 3 0 0 1 0 0 3 0 0 2 0 00 375
13 XXX,XX 377 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 00 377

View File

@@ -1,68 +0,0 @@
63 UBRK
62 UBRX
61 USRX01
60 USRX00
59 UDRX01
58 UDRX00
57 USRK
56 UDRK01
55 UDRK00
54 UCCL02
53 UCCL01
52 UCCL00
51 UPCA
50 UPCB01
49 UPCB00
48 USHF01
47 USHF00
46 UIRK
45 UPWE01
44 UPWE00
43 UPAD02
42 UPAD01
41 UPAD00
40 UBSD01
39 UBSD00
38 UBAX01
37 UBAX00
36 UIBS01
35 UIBS00
34 USHC01
33 USHC00
32 UBCT02
31 UBCT01
30 UBCT00
29 UMSC02
28 UMSC01
27 UMSC00
26 UBSC02
25 UBSC01
24 UBSC00
23 UAMX01
22 UAMX00
21 UBMX01
20 UBMX00
19 UKMX01
18 UKMX00
17 UALU2
16 UALU1
15 UALU0
-------------
14 UCFEN
13 UBFEN
12 UAFEN
11 UBEF03
10 UBEF02
09 UBEF01
08 UBEF00
07 UADR07
06 UADR06
05 UADR05
04 UADR04
03 UADR03
02 UADR02
01 UADR01
00 UADR00

View File

@@ -1,48 +0,0 @@
AFORK
021 BIN & SM1
022 BIN & SM23
024 BIN & SM45
045 MTP
320 BXX & BCOK
325
326
330
335
336
321 BXX & -BCOK & -BRQ
322
324
331 BXX & -BCOK & BRQ
332
334
026 BIN & SM67
101 FCLASS
012 RTI
016 RTT
040 RTS
057 SOB
047 MARK
015 RESET
010 HALT
044 CCOP
011 WAIT
042 OP22
043 SPL
000 RSVD | EMT | TRAP
000 ...
301 NEG.B & DM0
052 ASH & DM0
053 ASHC & DM0
046 MFP & DM0
020 ECLASS & -[DF7 | BRQ] & DM0
030 ECLASS & [DF7 | BRQ] & DM0
050 MUL & DM0
051 DIV & DM0
001 DAC & DM1
002 DAC & DM2
004 DAC & DM4
005 DAC & DM5
117 DM67 & SR0(0)
116 DM67 & SR0(1)
006 DAC & DM6
007 DAC & DM7

View File

@@ -1,97 +0,0 @@
#include "11.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
int
hasinput(int fd)
{
fd_set fds;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(fd, &fds);
return select(fd+1, &fds, NULL, NULL, &timeout) > 0;
}
int
dial(char *host, int port)
{
char portstr[32];
int sockfd;
struct addrinfo *result, *rp, hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
snprintf(portstr, 32, "%d", port);
if(getaddrinfo(host, portstr, &hints, &result)){
perror("error: getaddrinfo");
return -1;
}
for(rp = result; rp; rp = rp->ai_next){
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if(sockfd < 0)
continue;
if(connect(sockfd, rp->ai_addr, rp->ai_addrlen) >= 0)
goto win;
close(sockfd);
}
freeaddrinfo(result);
perror("error");
return -1;
win:
freeaddrinfo(result);
return sockfd;
}
void
serve(int port, void (*handlecon)(int, void*), void *arg)
{
int sockfd, confd;
socklen_t len;
struct sockaddr_in server, client;
int x;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
perror("error: socket");
return;
}
x = 1;
setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&x, sizeof x);
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
if(bind(sockfd, (struct sockaddr*)&server, sizeof(server)) < 0){
perror("error: bind");
return;
}
listen(sockfd, 5);
len = sizeof(client);
while(confd = accept(sockfd, (struct sockaddr*)&client, &len),
confd >= 0)
handlecon(confd, arg);
perror("error: accept");
return;
}
void
nodelay(int fd)
{
int flag = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
}

View File

@@ -56,10 +56,12 @@ private:
volatile bool _scp; // Indicates the completion of a seek
uint64_t get_disk_byte_offset(
uint32_t cylinder,
uint32_t surface,
uint32_t sector);
public:
Geometry get_geometry(void);
@@ -94,6 +96,7 @@ public:
bool on_param_changed(parameter_c* param) override;
void on_power_changed(void) override;
void on_init_changed(void) override;
// background worker function

View File

@@ -4,7 +4,7 @@
Copyright Vulcan Inc. 2019 via Living Computers: Museum + Labs, Seattle, WA.
Contributed under the BSD 2-clause license.
*/
*/
#ifndef _RK11_HPP_
#define _RK11_HPP_

View File

@@ -268,11 +268,14 @@ void application_c::menu_devices(bool with_CPU) {
} else if (!strcasecmp(s_opcode, "dbg") && n_fields == 2) {
if (!strcasecmp(s_param[0], "c")) {
logger->clear();
unibusadapter->debug_init(); // special diagnostics
printf("Debug log cleared.\n");
} else if (!strcasecmp(s_param[0], "s"))
} else if (!strcasecmp(s_param[0], "s")) {
unibusadapter->debug_snapshot(); // special diagnostics
logger->dump();
else if (!strcasecmp(s_param[0], "f"))
} else if (!strcasecmp(s_param[0], "f")) {
logger->dump(logger->default_filepath);
}
} else if (!strcasecmp(s_opcode, "m") && n_fields == 2
&& !strcasecmp(s_param[0], "i")) {
// install (emulate) max UNIBUS memory
@@ -420,7 +423,7 @@ void application_c::menu_devices(bool with_CPU) {
} else if (!strcasecmp(s_opcode, "d") && n_fields == 3) {
uint32_t addr;
uint16_t wordbuffer;
unibusdevice_register_t *reg = NULL ;
unibusdevice_register_t *reg = NULL;
if (unibuscontroller)
reg = unibuscontroller->register_by_name(s_param[0]);
if (reg) // register name given
@@ -446,7 +449,7 @@ void application_c::menu_devices(bool with_CPU) {
} else if (!strcasecmp(s_opcode, "e") && n_fields <= 2) {
bool timeout = false;
uint32_t addr;
unibusdevice_register_t *reg = NULL ;
unibusdevice_register_t *reg = NULL;
if (n_fields == 2) { // single reg number or address given
uint16_t wordbuffer; // exam single word
if (unibuscontroller)

View File

@@ -0,0 +1,113 @@
1 .title M9312 'DU' BOOT prom for MSCP compatible controller
2
3 ; This source code is a mdified copy of the DEC M9312 23-767A9 boot PROM.
4 ;
5 ; This boot PROM is for any MSCP compatible controller (DEC UDA50, EMULEX UC17/UC18).
6 ;
7 ; Multiple units and/or CSR addresses are supported via different entry points.
8
9 ;
10 ; Revision history:
11 ; May 2017: Joerg Hoppe
12 ;
13 ; 198?: DEC
14 ; Original ROM 23-767A9 for M9312.
15 ;
16
17
18
19 172150 mscsr =172150 ; std MSCP csrbase
20
21 000000 msip =+0 ; IP register
22 000002 mssa =+2 ; SA register
23
24 .asect
25 010000 .=10000 ; arbitrary position > 3000
26
27 ; --------------------------------------------------
28 001004 rpkt =1004 ; rpkt structure
29 001070 cpkt =1070 ; cpkt structure
30 001200 comm =1200 ; comm structure
31 ;comm =2404 ; comm structure (at 'blt .+12')
32
33 ; register usage:
34 ; r0: unit number 0..3
35 ; r1: MSCP csrbase
36 ; r2: moving buffer pointer
37 ; r3: moving buffer pointer
38 ; r5: init mask
39
40 ; 4 unit numbers => 4 entry addresses
41 start0:
42 010000 012700 000000 mov #0,r0
43 010004 000413 br duNr
44 010006 000240 nop
45 start1:
46 010010 012700 000001 mov #1,r0
47 010014 000407 br duNr
48 010016 000240 nop
49 start2:
50 010020 012700 000002 mov #2,r0
51 010024 000403 br duNr
52 010026 000240 nop
53 start3:
54 010030 012700 000003 mov #3,r0
55
56 ; retry entry
57 010034 012701 172150 duNr: mov #mscsr,r1 ; boot std csr, unit <R0>
58
59 010040 010021 go: mov r0,(r1)+ ; init controller (write IP), bump ptr
60 010042 012705 004000 mov #4000,r5 ; S1 state bitmask
61 010046 012703 010166 mov #mscpdt,r3 ; point to data
62
63 ; write 4 init words, with r5 mask from 4000 to 40000
64 010052 005711 3$: tst (r1) ; error bit set ?
65 010054 100767 bmi duNr ; yes, fail back to begin to retry
66 010056 031105 bit (r1),r5 ; step bit set ?
67 010060 001774 beq 3$ ; not yet, wait loop
68 010062 012311 mov (r3)+,(r1) ; yes, send next init data
69 010064 006305 asl r5 ; next mask
70 010066 100371 bpl 3$ ; s4 done? br if not yet
71
72 010070 005002 4$: clr r2 ; set bufptr to 0
73 010072 005022 5$: clr (r2)+ ; clear buffer [0..2403]
74 010074 020227 001200 cmp r2,#comm ; check for end of buffer
75 010100 001374 bne 5$ ; loop if not done
76
77 010102 010237 001064 mov r2,@#cpkt-4 ; set lnt -- R2=2404
78 010106 112337 001100 movb (r3)+,@#cpkt+10 ; set command
79 010112 111337 001105 movb (r3),@#cpkt+15 ; set bytecnt(hi)
80 010116 010037 001074 mov r0,@#cpkt+4 ; set unit
81 010122 012722 001004 mov #rpkt,(r2)+ ; rq desc addr
82 010126 010522 mov r5,(r2)+ ; rq own bit15
83 010130 012722 001070 mov #cpkt,(r2)+ ; cp desc addr
84 010134 010522 mov r5,(r2)+ ; cq own bit15
85 010136 016102 177776 mov -2(r1),r2 ; wake controller (read IP)
86
87 010142 005737 001202 6$: tst @#comm+2 ; rq own controller ?
88 010146 100775 bmi 6$ ; loop if not done
89
90 010150 105737 001016 tstb @#rpkt+12 ; check for error ?
91 010154 001327 bne duNr ; yup, fail back to begin to retry
92
93 010156 105723 tstb (r3)+ ; check end of table ?
94 010160 001743 beq 4$ ; br if not yet
95
96 010162 005041 clr -(r1) ; init controller (write IP)
97 010164 005007 clr pc ; jmp to bootstrap at zero
98
99 ; MSCP init and command data
100 ; pointed to by r3
101 mscpdt:
102 010166 100000 .word 100000 ; S1: 100000 = no int, ring size 1, no vector
103 010170 001200 .word comm ; S2: 002404 = ringbase lo addr
104 010172 000000 .word 000000 ; S3: 000000 = no purge/poll, ringbase hi addr
105 010174 000001 .word 000001 ; S4: 000001 = go bit
106 ;
107 ; MSCP command data
108 ;
109 010176 011 000 .byte 011,000 ; cmd=011(online), bytecnt_hi=000(0)
110 010200 041 002 .byte 041,002 ; cmd=041(read), bytecnt_hi=002(512)
111
112 .end
112

View File

@@ -0,0 +1,51 @@
set console log=./console.log
set cpu 11/34, FPP, 256K
set cpu idle
set tto 8b
;set console telnet=10000
set rq0 autosize
set rq0 writeenabled
attach rq0 rsx11m_4_8_bl70.dsk
set rq1 autosize
set rq1 writeenabled
attach rq1 rsxm70.dsk
set rq2 autosize
set rq3 autosize
set rl enable
set rl0 rl02
attach rl0 rsxm70.rl02
set rl1 rl02
attach rl1 rsxdl1.rl02
set rl2 rl02
attach rl2 rsxdl2.rl02
set rl3 rl02
attach rl3 rsxdl3.rl02
set rk enable
set rx disable
set ry enable
set tq enable
set tq tu81
set tm enable
set tc enable
set ptr enable
set ptp enable
set dz disable
set rp disable
set lpt disable
set hk disable
set DLI LINES=2
set dli enable
;set dz enable
;set dz lines=8
;attach dz 10001
;sho dz
sho clk
sho dev
sho cpu
sho rq

View File

@@ -0,0 +1,60 @@
# inputfile for demo to select a rl1 device in the "device test" menu.
# Read in with command line option "demo --cmdfile ..."
d # device test menu
pwr
.wait 3000 # wait for PDP-11 to reset
m i # install max UNIBUS memory
# Deposit bootloader into memory
m ll du.lst
en uda # enable UDA50 controller
# mount RSX in MSCP drive #0
en uda0 # enable drive #0
sd uda0 # select
p type RA70
p image rsx11m_4_8_bl70.dsk # mount image
p useimagesize 1
# mount test disk in MSCP drive #1
en uda1 # enable drive #1
sd uda1 # select
p type RA70
p image rsxm70.dsk # mount image
p useimagesize 1
en rl # enable RL11 controller
# mount RSX v4.16 in RL02 #0 and start
en rl0 # enable drive #0
sd rl0 # select
p emulation_speed 10 # 10x speed. Load disk in 5 seconds
p type rl02
p runstopbutton 0 # released: "LOAD"
p powerswitch 1 # power on, now in "load" state
p image rsxm70.rl02 # mount image
p runstopbutton 1 # press RUN/STOP, will start
# mount DL1 in RL02 #1 and start
en rl1 # enable drive #1
sd rl1 # select
p emulation_speed 10 # 10x speed. Load disk in 5 seconds
p type rl02
p runstopbutton 0 # released: "LOAD"
p powerswitch 1 # power on, now in "load" state
p image rsxdl1.rl02 # mount image
p runstopbutton 1 # press RUN/STOP, will start
.print Disk drive now on track after 5 secs
.wait 5000 # wait until drive spins up
p # show all params
.print MSCP drives ready.
.print UDA50 boot loader installed.
.print Start 10000 to boot from drive 0, 10010 for drive 1, ...
.print Reload with "m ll"

View File

@@ -0,0 +1,4 @@
# start RSX4.1 with "demo" application
cd ~/10.03_app_demo/5_applications/rsx11.mscp
~/10.03_app_demo/4_deploy/demo --verbose --debug --cmdfile rsx11m4.8_du+rl_34.cmd

View File

@@ -0,0 +1,4 @@
# start RSX4.1 with "demo" application
cd ~/10.03_app_demo/5_applications/rsx11.mscp
~/10.03_app_demo/4_deploy/demo --verbose --debug --cmdfile rsx11m4.8_du_34.cmd

View File

@@ -0,0 +1,36 @@
# inputfile for demo to select a rl1 device in the "device test" menu.
# Read in with command line option "demo --cmdfile ..."
d # device test menu
pwr
.wait 3000 # wait for PDP-11 to reset
m i # install max UNIBUS memory
# Deposit bootloader into memory
m ll du.lst
en uda # enable UDA50 controller
# mount RSX in MSCP drive #0
en uda0 # enable drive #0
sd uda0 # select
p type RA70
p image rsx11m_4_8_bl70.dsk # mount image
p useimagesize 1
# mount test disk in MSCP drive #1
en uda1 # enable drive #1
sd uda1 # select
p type RA70
p image rsxm70.dsk # mount image
p useimagesize 1
.print Disk drive now on track after 5 secs
.wait 5000 # wait until drive spins up
p # show all params
.print MSCP drives ready.
.print UDA50 boot loader installed.
.print Start 10000 to boot from drive 0, 10010 for drive 1, ...
.print Reload with "m ll"

View File

@@ -0,0 +1,51 @@
set console log=./console.log
set cpu 11/34, FPP, 256K
set cpu idle
set tto 8b
;set console telnet=10000
set rq0 autosize
set rq0 writeenabled
attach rq0 rsx11m_4_8_bl70.dsk
set rq1 autosize
set rq1 writeenabled
attach rq1 rsxm70.dsk
set rq2 autosize
set rq3 autosize
set rl enable
set rl0 rl02
attach rl0 rsxm70.rl02
set rl1 rl02
attach rl1 rsxdl1.rl02
set rl2 rl02
attach rl2 rsxdl2.rl02
set rl3 rl02
attach rl3 rsxdl3.rl02
set rk enable
set rx disable
set ry enable
set tq enable
set tq tu81
set tm enable
set tc enable
set ptr enable
set ptp enable
set dz disable
set rp disable
set lpt disable
set hk disable
set DLI LINES=2
set dli enable
;set dz enable
;set dz lines=8
;attach dz 10001
;sho dz
sho clk
sho dev
sho cpu
sho rq

View File

@@ -0,0 +1,50 @@
set console log=./console.log
set cpu 11/34, 256K
set cpu idle
set tto 8b
;set console telnet=10000
set rq0 autosize
set rq0 writeenabled
attach rq0 rsx11m_4_8_bl70.dsk
set rq1 autosize
set rq1 writeenabled
attach rq1 rsxm70.dsk
set rq2 autosize
set rq3 autosize
set rl enable
set rl0 rl02
attach rl0 rsxm70.rl02
set rl1 rl02
attach rl1 rsxdl1.rl02
set rl2 rl02
attach rl2 rsxdl2.rl02
set rl3 rl02
attach rl3 rsxdl3.rl02
set rk disable
set rx disable
set ry disable
set tq disable
set tq tu81
set tm disable
set tc disable
set ptr disable
set ptp disable
set dz disable
set rp disable
set lpt disable
set hk disable
set DLI LINES=2
set dli enable
;set dz enable
;set dz lines=8
;attach dz 10001
;sho dz
sho clk
sho dev
sho cpu
sho rq

View File

@@ -0,0 +1,39 @@
set console log=./console.log
set cpu 11/34, 256K
set cpu idle
set tto 8b
;set console telnet=10000
set rq0 autosize
set rq0 writeenabled
attach rq0 rsx11m_4_8_bl70.dsk
set rq1 disable
set rq2 disable
set rq3 disable
set cr disable
set rl disable
set rk disable
set rx disable
set ry disable
set tq disable
set tq disable
set tm disable
set tc disable
set ptr disable
set ptp disable
set dz disable
set rp disable
set lpt disable
set hk disable
set DLI disable
;set dz enable
;set dz lines=8
;attach dz 10001
;sho dz
sho clk
sho dev
sho cpu
sho rq

View File

@@ -0,0 +1,51 @@
set console log=./console.log
set cpu 11/34, FPP, 256K
set cpu idle
set tto 8b
;set console telnet=10000
set rq0 autosize
set rq0 writeenabled
attach rq0 rsx11m_4_8_bl70.dsk
set rq1 autosize
set rq1 writeenabled
attach rq1 rsxm70.dsk
set rq2 autosize
set rq3 autosize
set rl enable
set rl0 rl02
attach rl0 rsxm70.rl02
set rl1 rl02
attach rl1 rsxdl1.rl02
set rl2 rl02
attach rl2 rsxdl2.rl02
set rl3 rl02
attach rl3 rsxdl3.rl02
set rk enable
set rx disable
set ry enable
set tq enable
set tq tu81
set tm enable
set tc enable
set ptr enable
set ptp enable
set dz disable
set rp disable
set lpt disable
set hk disable
set DLI LINES=2
set dli enable
;set dz enable
;set dz lines=8
;attach dz 10001
;sho dz
sho clk
sho dev
sho cpu
sho rq

View File

@@ -0,0 +1,85 @@
# inputfile for demo to select a rl1 device in the "device test" menu.
# Read in with command line option "demo --cmdfile ..."
d # device test menu
# Use emulated DL11, for scripting
sd dl11
p p ttyS2 # use "UART2 connector
p rb 300 # "type" injected chars slowly with 300 baud
# en dl11
# en kw11 # RSX11M needs clock
pwr
.wait 3000 # wait for PDP-11 to reset
m i # install max UNIBUS memory
# Deposit bootloader into memory
m ll du.lst
en uda # enable UDA50 controller
# mount RSX in MSCP drive #0
en uda0 # enable drive #0
sd uda0 # select
p type RA70
p image rsx11m_4_8_bl70.dsk # mount image
p useimagesize 1
# mount test disk in MSCP drive #1
en uda1 # enable drive #1
sd uda1 # select
p type RA70
p image rsxm70.dsk # mount image
p useimagesize 1
en rl # enable RL11 controller
# mount RSX v4.16 in RL02 #0 and start
en rl0 # enable drive #0
sd rl0 # select
p emulation_speed 10 # 10x speed. Load disk in 5 seconds
p type rl02
p runstopbutton 0 # released: "LOAD"
p powerswitch 1 # power on, now in "load" state
p image rsxm70.rl02 # mount image
p runstopbutton 1 # press RUN/STOP, will start
# mount DL1 in RL02 #1 and start
en rl1 # enable drive #1
sd rl1 # select
p emulation_speed 10 # 10x speed. Load disk in 5 seconds
p type rl02
p runstopbutton 0 # released: "LOAD"
p powerswitch 1 # power on, now in "load" state
p image rsxdl1.rl02 # mount image
p runstopbutton 1 # press RUN/STOP, will start
.print Disk drive now on track after 5 secs
.wait 5000 # wait until drive spins up
p # show all params
.print MSCP drives ready.
.print UDA50 boot loader installed.
.print Start 10000 to boot from drive 0, 10010 for drive 1, ...
.print Reload with "m ll"
.end
# boot RSX11 from DU
dl11 rcv L\x2010000\r
dl11 rcv 500 S\r
dl11 wait 20000 Please\x20enter\x20time\x20and\x20date
dl11 rcv 500 20:00 27-aug-2019\r
dl11 wait 10000 ENTER\x20LINE\x20WIDTH
dl11 rcv 1000 80\r
dl11 wait 10000 >@
# startup complete
# logout, login as SYSTEM/SYSTEM
dl11 rcv 1000 LOG\r
dl11 rcv 3000 HELLO\x20SYSTEM\r
dl11 rcv 3000 SYSTEM\r

View File

@@ -98,13 +98,14 @@ static int inputline_internal(char *line) {
printf("<<< %s\n", line + 7);
return 1;
} else if (!strncasecmp(line, ".input", 6)) {
char buffer[100] ;
char buffer[100];
printf("<<< Press ENTER to continue.\n");
// flush stuff on stdin. (Eclipse remote debugging)
while (os_kbhit()) ;
fgets(buffer, sizeof(buffer), stdin) ;
return 1 ;
while (os_kbhit())
;
fgets(buffer, sizeof(buffer), stdin);
return 1;
} else if (!strncasecmp(line, ".end", 3)) {
// close input file
fclose(inputline_file);

View File

@@ -76,6 +76,8 @@ public:
logger->log(this, LL_INFO, __FILE__, __LINE__, __VA_ARGS__)
#define DEBUG(...) \
logger->log(this, LL_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
// disables a DEBUG
#define _DEBUG(...)
#endif // _LOGSOURCE_HPP_