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:
@@ -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
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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 ****/
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
;
|
||||
}
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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_
|
||||
|
||||
35
10.01_base/3_test/multiarb/ma_du.mac
Normal file
35
10.01_base/3_test/multiarb/ma_du.mac
Normal 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
|
||||
|
||||
83
10.01_base/3_test/multiarb/multiarb.cmd
Normal file
83
10.01_base/3_test/multiarb/multiarb.cmd
Normal 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.
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 "${INPUTS}"" 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>
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 },
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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_
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
113
10.03_app_demo/5_applications/rsx11.mscp/du.lst
Normal file
113
10.03_app_demo/5_applications/rsx11.mscp/du.lst
Normal 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
|
||||
51
10.03_app_demo/5_applications/rsx11.mscp/rsx11m.simh_pdp11
Normal file
51
10.03_app_demo/5_applications/rsx11.mscp/rsx11m.simh_pdp11
Normal 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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
36
10.03_app_demo/5_applications/rsx11.mscp/rsx11m4.8_du_34.cmd
Normal file
36
10.03_app_demo/5_applications/rsx11.mscp/rsx11m4.8_du_34.cmd
Normal 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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
51
10.03_app_demo/5_applications/rsx11.mscp/sim-1134.ini
Normal file
51
10.03_app_demo/5_applications/rsx11.mscp/sim-1134.ini
Normal 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
|
||||
85
10.03_app_demo/5_applications/rsx11.mscp/test.cmd
Normal file
85
10.03_app_demo/5_applications/rsx11.mscp/test.cmd
Normal 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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_
|
||||
|
||||
Reference in New Issue
Block a user