mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-04-12 16:06:42 +00:00
1. Implement the four branch on field non-zero syllables.
2. Implement run-until-this-address feature in SyllableDebugger. 3. Continue debugging by stepping through KERNEL bootstrap and MCP initialization code.
This commit is contained in:
@@ -2246,7 +2246,7 @@ B5500Processor.prototype.computeRelativeAddr = function(offset, cEnabled) {
|
||||
break;
|
||||
case 6:
|
||||
if (cEnabled) {
|
||||
this.M = this.C + (offset & 0x7F);
|
||||
this.M = (this.L ? this.C : this.C-1) + (offset & 0x7F); // adjust C for fetch
|
||||
} else {
|
||||
this.M = this.R*64 + (offset & 0x7F);
|
||||
}
|
||||
@@ -2400,7 +2400,7 @@ B5500Processor.prototype.integerStore = function(conditional, destructive) {
|
||||
bt = (be >>> 6) & 0x01;
|
||||
be = (bt ? -(be & 0x3F) : (be & 0x3F));
|
||||
|
||||
if (be != 0) {
|
||||
if (be != 0) { // is B non-integer?
|
||||
if (be < 0) { // B exponent is negative
|
||||
do {
|
||||
this.cycleCount++;
|
||||
@@ -3935,7 +3935,7 @@ B5500Processor.prototype.run = function() {
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.C = this.A % 0x8000;
|
||||
this.L = 0;
|
||||
this.PROF = 0; // require fetch at SEQL
|
||||
this.PROF = 0; // require fetch at SECL
|
||||
this.AROF = 0;
|
||||
}
|
||||
}
|
||||
@@ -3958,7 +3958,7 @@ B5500Processor.prototype.run = function() {
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.C = this.A % 0x8000;
|
||||
this.L = 0;
|
||||
this.PROF = 0; // require fetch at SEQL
|
||||
this.PROF = 0; // require fetch at SECL
|
||||
this.AROF = 0;
|
||||
}
|
||||
}
|
||||
@@ -4002,7 +4002,7 @@ B5500Processor.prototype.run = function() {
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.C = this.A % 0x8000;
|
||||
this.L = 0;
|
||||
this.PROF = 0; // require fetch at SEQL
|
||||
this.PROF = 0; // require fetch at SECL
|
||||
this.AROF = 0;
|
||||
}
|
||||
}
|
||||
@@ -4025,7 +4025,7 @@ B5500Processor.prototype.run = function() {
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.C = this.A % 0x8000;
|
||||
this.L = 0;
|
||||
this.PROF = 0; // require fetch at SEQL
|
||||
this.PROF = 0; // require fetch at SECL
|
||||
this.AROF = 0;
|
||||
}
|
||||
}
|
||||
@@ -4050,7 +4050,7 @@ B5500Processor.prototype.run = function() {
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.C = this.A % 0x8000;
|
||||
this.L = 0;
|
||||
this.PROF = 0; // require fetch at SEQL
|
||||
this.PROF = 0; // require fetch at SECL
|
||||
this.AROF = 0;
|
||||
}
|
||||
}
|
||||
@@ -4068,7 +4068,7 @@ B5500Processor.prototype.run = function() {
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.C = this.A % 0x8000;
|
||||
this.L = 0;
|
||||
this.PROF = 0; // require fetch at SEQL
|
||||
this.PROF = 0; // require fetch at SECL
|
||||
this.AROF = 0;
|
||||
}
|
||||
}
|
||||
@@ -4093,7 +4093,7 @@ B5500Processor.prototype.run = function() {
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.C = this.A % 0x8000;
|
||||
this.L = 0;
|
||||
this.PROF = 0; // require fetch at SEQL
|
||||
this.PROF = 0; // require fetch at SECL
|
||||
this.AROF = 0;
|
||||
}
|
||||
}
|
||||
@@ -4111,7 +4111,7 @@ B5500Processor.prototype.run = function() {
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.C = this.A % 0x8000;
|
||||
this.L = 0;
|
||||
this.PROF = 0; // require fetch at SEQL
|
||||
this.PROF = 0; // require fetch at SECL
|
||||
this.AROF = 0;
|
||||
}
|
||||
}
|
||||
@@ -4127,12 +4127,13 @@ B5500Processor.prototype.run = function() {
|
||||
this.adjustAFull();
|
||||
this.M = this.A % 0x8000;
|
||||
do {
|
||||
this.cycleCount += 2; // approximate the timing
|
||||
this.loadAviaM();
|
||||
if (this.A < 0x800000000000) {
|
||||
this.M = (this.M+1) % 0x8000;
|
||||
} else {
|
||||
this.A = t1 = this.M + 0xA00000000000;
|
||||
break; // flag bit found: stop the search
|
||||
break; // flag bit found: stop the search
|
||||
}
|
||||
} while (true);
|
||||
break;
|
||||
@@ -4269,6 +4270,7 @@ B5500Processor.prototype.run = function() {
|
||||
t1 = this.A % 0x8000000000; // test value
|
||||
this.M = this.B % 0x8000; // starting link address
|
||||
do {
|
||||
this.cycleCount += 2; // approximate the timing
|
||||
this.loadBviaM();
|
||||
t2 = this.B % 0x8000000000;
|
||||
if (t2 < t1) {
|
||||
@@ -4307,7 +4309,7 @@ B5500Processor.prototype.run = function() {
|
||||
break;
|
||||
|
||||
case 0x29: // XX51: delete & conditional branch ops
|
||||
if (variant == 0) { // 0051=DEL: delete TOS
|
||||
if (variant < 4) { // 0051=DEL: delete TOS (or field branch with zero-length field)
|
||||
if (this.AROF) {
|
||||
this.AROF = 0;
|
||||
} else if (this.BROF) {
|
||||
@@ -4316,17 +4318,51 @@ B5500Processor.prototype.run = function() {
|
||||
this.S--;
|
||||
}
|
||||
} else {
|
||||
this.adjustABFull();
|
||||
t2 = variant >>> 2; // field length (1-15 bits)
|
||||
t1 = this.cc.fieldIsolate(this.B, this.G*6+this.H, t2);
|
||||
this.cycleCount += this.G + this.H + (t2 >>> 1); // approximate the shift counts
|
||||
this.AROF = 0; // A is unconditionally empty at end
|
||||
|
||||
switch (variant & 0x03) {
|
||||
case 0x00: // X051/X451: CFN=non-zero field branch forward nondestructive
|
||||
break;
|
||||
|
||||
case 0x01: // X151/X551: CBN=non-zero field branch backward nondestructive
|
||||
break;
|
||||
|
||||
case 0x02: // X251/X651: CFD=non-zero field branch forward destructive
|
||||
this.BROF = 0;
|
||||
// no break: fall through
|
||||
case 0x00: // X051/X451: CFN=non-zero field branch forward nondestructive
|
||||
if (t1) {
|
||||
if (this.A < 0x800000000000) { // simple operand
|
||||
this.jumpSyllables(this.A % 0x1000);
|
||||
} else { // descriptor
|
||||
if (this.L == 0) {
|
||||
this.C--; // adjust for Inhibit Fetch
|
||||
}
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.C = this.A % 0x8000;
|
||||
this.L = 0;
|
||||
this.PROF = 0; // require fetch at SEQL
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03: // X351/X751: CBD=non-zero field branch backward destructive
|
||||
this.BROF = 0;
|
||||
// no break: fall through
|
||||
case 0x01: // X151/X551: CBN=non-zero field branch backward nondestructive
|
||||
if (t1) {
|
||||
if (this.A < 0x800000000000) { // simple operand
|
||||
this.jumpSyllables(-(this.A % 0x1000));
|
||||
} else { // descriptor
|
||||
if (this.L == 0) {
|
||||
this.C--; // adjust for Inhibit Fetch
|
||||
}
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.C = this.A % 0x8000;
|
||||
this.L = 0;
|
||||
this.PROF = 0; // require fetch at SEQL
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +106,11 @@ TH {
|
||||
font-family: "Arial", "Helvetica", sans-serif;
|
||||
font-weight: bold}
|
||||
|
||||
TD#TMnemonic {
|
||||
text-align: center;
|
||||
background-color: #EEF;
|
||||
font-size: smaller}
|
||||
|
||||
INPUT.warn {
|
||||
background-color: yellow}
|
||||
|
||||
@@ -114,6 +119,9 @@ INPUT.warn {
|
||||
|
||||
.center {
|
||||
text-align: center}
|
||||
|
||||
.rj {
|
||||
text-align: right}
|
||||
|
||||
.data {
|
||||
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}
|
||||
@@ -127,4 +135,3 @@ INPUT.warn {
|
||||
color: white;
|
||||
background-color: black;
|
||||
font-weight: bold}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
f<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<title>B5500 Processor Syllable Debugger</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
@@ -22,6 +22,7 @@ f<!DOCTYPE html>
|
||||
var cc;
|
||||
var injected = false; // true if syllable manually injected into T
|
||||
var memAddr = 0x40; // @100
|
||||
var stopAddress = 0; // run-until-address stop point
|
||||
|
||||
var accessor = { // Memory access control block
|
||||
requestorID: "A", // Memory requestor ID
|
||||
@@ -649,16 +650,32 @@ function stepIt(ev) {
|
||||
displayProcessorState();
|
||||
}
|
||||
|
||||
function execIt(ev) {
|
||||
/* Executes one instruction from the drop-down syllable options list, then
|
||||
backs up C and L to prepare for the original instruction in the stream */
|
||||
var opList = $$("OpList")
|
||||
var value;
|
||||
function runIt(ev) {
|
||||
/* Steps through instructions continuously until the C register matches the
|
||||
StopAddr address. StopAddr can be changed while running. Setting it to zero
|
||||
(or blank) will halt the continuous stepping */
|
||||
var stopAddr = $$("StopAddr");
|
||||
|
||||
value = opList.options[opList.selectedIndex].value;
|
||||
cc.P1.T = parseInt(value, 8);
|
||||
injected = true;
|
||||
stepIt();
|
||||
function syllabicate() {
|
||||
if (stopAddress && cc.P1.C != stopAddress) {
|
||||
cc.P1.step();
|
||||
displayProcessorState();
|
||||
if (isNaN(stopAddress)) {
|
||||
stopAddr.style.backgroundColor = "red";
|
||||
stopAddress = 0; // bad address -- kill the loop
|
||||
} else {
|
||||
setTimeout(syllabicate, 1);
|
||||
}
|
||||
} else {
|
||||
stopAddr.style.backgroundColor = "";
|
||||
}
|
||||
}
|
||||
|
||||
setText("ARegOrig", "");
|
||||
setText("BRegOrig", "");
|
||||
injected = false;
|
||||
stopAddr.style.backgroundColor = "green";
|
||||
syllabicate();
|
||||
}
|
||||
|
||||
function word_onChange(ev) {
|
||||
@@ -928,10 +945,14 @@ function initialize() {
|
||||
$$("MWordP3").onchange = word_onChange;
|
||||
$$("MWordP4").onchange = word_onChange;
|
||||
|
||||
$$("StopAddr").onchange = function(ev) {
|
||||
stopAddress = reg_onChange(ev);
|
||||
};
|
||||
|
||||
$$("FileSelector").addEventListener("change", fileSelector_onChange, false);
|
||||
$$("GoBtn").addEventListener("click", goIt, false);
|
||||
$$("Step").addEventListener("click", stepIt, false);
|
||||
$$("Exec").addEventListener("click", execIt, false);
|
||||
$$("StepBtn").addEventListener("click", stepIt, false);
|
||||
$$("RunBtn").addEventListener("click", runIt, false);
|
||||
|
||||
cc = new B5500CentralControl();
|
||||
cc.powerOn();
|
||||
@@ -944,11 +965,12 @@ function initialize() {
|
||||
cc.P1.loadPviaC();
|
||||
cc.P1.T = cc.fieldIsolate(cc.P1.P, 0, 12);
|
||||
cc.P1.TROF = 1;
|
||||
cc.P1.L = 1; // point to the next instruction
|
||||
cc.P1.L = 1; // point to the next syllable
|
||||
|
||||
cc.P1.NCSF = 0; // initiate test in control state
|
||||
|
||||
displayProcessorState();
|
||||
displayOctal("StopAddr", stopAddress, 5);
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
@@ -1253,30 +1275,15 @@ window.onload = function() {
|
||||
|
||||
<input id=VARF name=VARF type=checkbox value=1><label for=VARF>VARF</label>
|
||||
<tr>
|
||||
<td colspan=6>
|
||||
<td colspan=6 class=revcaption>Manual Control
|
||||
<tr>
|
||||
<td colspan=6>
|
||||
<input id=Step name=Step type=button value="Step" accesskey=P>
|
||||
Syllable:
|
||||
<select id=OpList name=OpList>
|
||||
<option value="0055" selected>NOP : No Operation
|
||||
<option value="0101">ADD : Add
|
||||
<option value="0301">SUB : Subtract
|
||||
<option value="0401">MUL : Multiply
|
||||
<option value="1001">DIV : Divide
|
||||
<option value="3001">IDV : Integer Divide
|
||||
<option value="7001">RDV : Remainder Divide
|
||||
<option value="0105">DLA : Add DP
|
||||
<option value="0305">DLS : Subtract DP
|
||||
<option value="0125">GEQ : B GEQ A
|
||||
<option value="0225">GTR : B GTR A
|
||||
<option value="0425">NEQ : B NEQ A
|
||||
<option value="4125">LEQ : B LEQ A
|
||||
<option value="4225">LSS : B LSS A
|
||||
<option value="4425">EQL : B EQL A
|
||||
</select>
|
||||
<td colspan=2 class=center>
|
||||
<input id=StepBtn name=StepBtn type=button value="Step" accesskey=P>
|
||||
<td colspan=4 class=rj>
|
||||
Stop at
|
||||
<input id=StopAddr name=StopAddr type=text class=number size=5 maxlength=5>
|
||||
|
||||
<input id=Exec name=Exec type=button value="Exec" accesskey=X>
|
||||
<input id=RunBtn name=RunBtn type=button value="Run" accesskey=X>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user