Implemented branches and RTS

This commit is contained in:
Jeff 2016-09-26 11:27:32 -07:00 committed by Jeff Parsons
commit 6af956b8f0
8 changed files with 1932 additions and 1922 deletions

View file

@ -6091,11 +6091,16 @@ if (DEBUGGER) {
var data = 0, iByte = 0, i;
var sData = "", sChars = "";
sAddr = this.toHexAddr(dbgAddr);
for (i = 16; i > 0 && cb > 0; i--) {
/*
* It's just coincidence that we want to dump 8 bytes per line when using base 8 and 16 bytes
* per line when using base 16, because octal requires more digits.
*/
var nBytes = (size == 4? 16 : this.nBase);
for (i = nBytes; i > 0 && cb > 0; i--) {
var b = this.getByte(dbgAddr, 1);
data |= (b << (iByte++ << 3));
if (iByte == size) {
sData += str.toHex(data, size * 2);
sData += (this.nBase == 8? str.toOct(data, size * 3) : str.toHex(data, size * 2));
sData += (size == 1? (i == 9? '-' : ' ') : " ");
data = iByte = 0;
}

View file

@ -267,10 +267,7 @@ PDP11.opASRB = function(opCode)
*/
PDP11.opBCC = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (!this.getCF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -282,10 +279,7 @@ PDP11.opBCC = function(opCode)
*/
PDP11.opBCS = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (this.getCF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -369,10 +363,7 @@ PDP11.opBITB = function(opCode)
*/
PDP11.opBEQ = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (this.getZF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -384,10 +375,7 @@ PDP11.opBEQ = function(opCode)
*/
PDP11.opBGE = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (!this.getNF() == !this.getVF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -399,10 +387,7 @@ PDP11.opBGE = function(opCode)
*/
PDP11.opBGT = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (!this.getZF() && (!this.getNF() == !this.getVF())) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -414,10 +399,7 @@ PDP11.opBGT = function(opCode)
*/
PDP11.opBHI = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (!this.getCF() && !this.getZF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -429,10 +411,7 @@ PDP11.opBHI = function(opCode)
*/
PDP11.opBLE = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (this.getZF() || (!this.getNF() != !this.getVF())) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -444,10 +423,7 @@ PDP11.opBLE = function(opCode)
*/
PDP11.opBLOS = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (this.getCF() || this.getZF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -459,10 +435,7 @@ PDP11.opBLOS = function(opCode)
*/
PDP11.opBLT = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (!this.getNF() != !this.getVF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -474,10 +447,7 @@ PDP11.opBLT = function(opCode)
*/
PDP11.opBMI = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (this.getNF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -489,10 +459,7 @@ PDP11.opBMI = function(opCode)
*/
PDP11.opBNE = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (!this.getZF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -504,10 +471,7 @@ PDP11.opBNE = function(opCode)
*/
PDP11.opBPL = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (!this.getNF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -534,10 +498,7 @@ PDP11.opBPT = function(opCode)
*/
PDP11.opBR = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -549,10 +510,7 @@ PDP11.opBR = function(opCode)
*/
PDP11.opBVC = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (!this.getVF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -564,10 +522,7 @@ PDP11.opBVC = function(opCode)
*/
PDP11.opBVS = function(opCode)
{
/*
* TODO: Implement
*/
this.regOp = -1;
if (this.getVF()) this.regsGen[7] = this.branch(opCode);
this.nStepCycles -= 1;
};
@ -1154,6 +1109,22 @@ PDP11.opRTI = function(opCode)
this.nStepCycles -= 1;
};
/**
* opRTS(opCode)
*
* @this {CPUStatePDP11}
* @param {number} opCode
*/
PDP11.opRTS = function(opCode)
{
this.assert(!(opCode & 0x08));
var src = this.popWord();
var reg = opCode & PDP11.OPREG.MASK;
this.regsGen[PDP11.REG.PC] = this.regsGen[reg];
this.regsGen[reg] = src;
this.nStepCycles -= 1;
};
/**
* opRTT(opCode)
*
@ -1277,6 +1248,22 @@ PDP11.opSOB = function(opCode)
this.nStepCycles -= 1;
};
/**
* opSPL(opCode)
*
* @this {CPUStatePDP11}
* @param {number} opCode
*/
PDP11.opSPL = function(opCode)
{
this.assert(opCode & 0x08);
if (!(this.PSW & PDP11.PSW.CMODE)) {
this.PSW = (this.PSW & ~(PDP11.PSW.UNUSED | PDP11.PSW.PRI)) | ((opCode & 0x7) << PDP11.PSW.SHIFT.PRI);
this.priorityReview = 1;
}
this.nStepCycles -= 1;
};
/**
* opSUB(opCode)
*
@ -1467,6 +1454,17 @@ PDP11.op00Xn_1170 = function(opCode)
PDP11.aOps00Xn_1170[(opCode >> 4) & 0xf].call(this, opCode);
};
/**
* op008X_1170(opCode)
*
* @this {CPUStatePDP11}
* @param {number} opCode
*/
PDP11.op008X_1170 = function(opCode)
{
PDP11.aOps00AX_1170[opCode & 0xf].call(this, opCode);
};
/**
* op00AX_1170(opCode)
*
@ -1568,20 +1566,20 @@ PDP11.op8DXn_1170 = function(opCode)
PDP11.aOpsXnnn_1170 = [
PDP11.op0Xnn_1170, // 0x0nnn
PDP11.opMOV, // 0x1nnn MOV 01SSDD
PDP11.opCMP, // 0x2nnn CMP 02SSDD
PDP11.opBIT, // 0x3nnn BIT 03SSDD
PDP11.opBIC, // 0x4nnn BIC 04SSDD
PDP11.opBIS, // 0x5nnn BIS 05SSDD
PDP11.opADD, // 0x6nnn ADD 06SSDD
PDP11.opMOV, // 0x1nnn 01SSDD
PDP11.opCMP, // 0x2nnn 02SSDD
PDP11.opBIT, // 0x3nnn 03SSDD
PDP11.opBIC, // 0x4nnn 04SSDD
PDP11.opBIS, // 0x5nnn 05SSDD
PDP11.opADD, // 0x6nnn 06SSDD
PDP11.op7Xnn_1170, // 0x7nnn
PDP11.op8Xnn_1170, // 0x8nnn
PDP11.opMOVB, // 0x9nnn MOVB 11SSDD
PDP11.opCMPB, // 0xAnnn CMPB 12SSDD
PDP11.opBITB, // 0xBnnn BITB 13SSDD
PDP11.opBICB, // 0xCnnn BICB 14SSDD
PDP11.opBISB, // 0xDnnn BISB 15SSDD
PDP11.opSUB, // 0xEnnn SUB 16SSDD
PDP11.opMOVB, // 0x9nnn 11SSDD
PDP11.opCMPB, // 0xAnnn 12SSDD
PDP11.opBITB, // 0xBnnn 13SSDD
PDP11.opBICB, // 0xCnnn 14SSDD
PDP11.opBISB, // 0xDnnn 15SSDD
PDP11.opSUB, // 0xEnnn 16SSDD
PDP11.opUndefined // 0xFnnn
];
@ -1613,10 +1611,10 @@ PDP11.aOps00Xn_1170 = [
PDP11.opUndefined, // 0x005n
PDP11.opUndefined, // 0x006n
PDP11.opUndefined, // 0x007n
PDP11.opUndefined, // 0x008n
PDP11.opUndefined, // 0x009n
PDP11.op00AX_1170, // 0x00An
PDP11.op00BX_1170, // 0x00Bn
PDP11.opRTS, // 0x008n 00020R (technically, bit 3 should also be CLR for the RTS opCode)
PDP11.opSPL, // 0x009n 00023N (technically, bit 3 should also be SET for the SPL opCode)
PDP11.op00AX_1170, // 0x00An 000240-000257
PDP11.op00BX_1170, // 0x00Bn 000260-000277
PDP11.opUndefined, // 0x00Cn
PDP11.opUndefined, // 0x00Dn
PDP11.opUndefined, // 0x00En
@ -1624,7 +1622,7 @@ PDP11.aOps00Xn_1170 = [
];
PDP11.aOps00AX_1170 = [
PDP11.opNOP, // 0x00A0
PDP11.opNOP, // 0x00A0 000240
PDP11.opCLC, // 0x00A1
PDP11.opCLV, // 0x00A2
PDP11.opCLx, // 0x00A3
@ -1639,11 +1637,11 @@ PDP11.aOps00AX_1170 = [
PDP11.opCLx, // 0x00AC
PDP11.opCLx, // 0x00AD
PDP11.opCLx, // 0x00AE
PDP11.opCLx // 0x00AF
PDP11.opCLx // 0x00AF 000257
];
PDP11.aOps00BX_1170 = [
PDP11.opNOP, // 0x00B0
PDP11.opNOP, // 0x00B0 000260
PDP11.opSEC, // 0x00B1
PDP11.opSEV, // 0x00B2
PDP11.opSEx, // 0x00B3
@ -1658,7 +1656,7 @@ PDP11.aOps00BX_1170 = [
PDP11.opSEx, // 0x00BC
PDP11.opSEx, // 0x00BD
PDP11.opSEx, // 0x00BE
PDP11.opSEx // 0x00BF
PDP11.opSEx // 0x00BF 000277
];
PDP11.aOps000X_1170 = [

View file

@ -125,7 +125,7 @@ CPUStatePDP11.prototype.initRegs = function()
/*
* TODO: Verify the initial state of all PDP-11 flags and registers (are they well-documented?)
*/
this.flagC = 0x10000; // PSW C bit
this.flagC = 0x10000; // PSW C bit
this.flagV = 0x8000; // PSW V bit
this.flagZ = 0xffff; // ~ PSW Z bit (TODO: Why do we clear instead of set Z, like other flags?)
this.flagN = 0x8000; // PSW N bit
@ -1469,21 +1469,15 @@ CPUStatePDP11.prototype.writeByteByMode = function(addressMode, data, writeFlags
};
/**
* branch(PC, instruction)
* branch(opCode)
*
* @this {CPUStatePDP11}
* @param {number} PC
* @param {number} instruction
* @return {number}
* @param {number} opCode
* @return {number} (PC +/- the word delta specified in the opCode)
*/
CPUStatePDP11.prototype.branch = function(PC, instruction)
CPUStatePDP11.prototype.branch = function(opCode)
{
if (instruction & 0x80) { /*0200*/
instruction |= 0xff00;
} else {
instruction &= 0xff;
}
return ((instruction << 1) + PC) & 0xffff;
return (this.regsGen[PDP11.REG.PC] + ((opCode << 24) >> 23)) & 0xffff;
};
/**
@ -1972,70 +1966,70 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
// switch (opCode & 0xFF00) /*0177400*/ { // Program control instructions & traps
// case 0x100: /*0000400*/ // BR
// //LOG_INSTRUCTION(opCode, 4, "BR");
// this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// this.regsGen[7] = this.branch(opCode);
// break;
// case 0x200: /*0001000*/ // BNE
// //LOG_INSTRUCTION(opCode, 4, "BNE");
// if (this.flagZ & 0xffff) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// if (this.flagZ & 0xffff) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x300: /*0001400*/ // BEQ
// //LOG_INSTRUCTION(opCode, 4, "BEQ");
// if (!(this.flagZ & 0xffff)) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// if (!(this.flagZ & 0xffff)) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x400: /*0002000*/ // BGE
// //LOG_INSTRUCTION(opCode, 4, "BGE");
// if ((this.flagN & 0x8000) ===
// (this.flagV & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// (this.flagV & 0x8000)) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x500: /*0002400*/ // BLT
// //LOG_INSTRUCTION(opCode, 4, "BLT");
// if ((this.flagN & 0x8000) !==
// (this.flagV & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// (this.flagV & 0x8000)) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x600: /*0003000*/ // BGT
// //LOG_INSTRUCTION(opCode, 4, "BGT");
// if ((this.flagZ & 0xffff) && ((this.flagN & 0x8000) ===
// (this.flagV & 0x8000))) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// (this.flagV & 0x8000))) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x700: /*0003400*/ // BLE
// //LOG_INSTRUCTION(opCode, 4, "BLE");
// if (!(this.flagZ & 0xffff) || ((this.flagN & 0x8000) !==
// (this.flagV & 0x8000))) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// (this.flagV & 0x8000))) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x8000: /*0100000*/ // BPL
// //LOG_INSTRUCTION(opCode, 4, "BPL");
// if (!(this.flagN & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// if (!(this.flagN & 0x8000)) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x8200: /*0101000*/ // BHI
// //LOG_INSTRUCTION(opCode, 4, "BHI");
// if (!(this.flagC & 0x10000) &&
// (this.flagZ & 0xffff)) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// (this.flagZ & 0xffff)) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x8100: /*0100400*/ // BMI
// //LOG_INSTRUCTION(opCode, 4, "BMI");
// if ((this.flagN & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// if ((this.flagN & 0x8000)) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x8300: /*0101400*/ // BLOS
// //LOG_INSTRUCTION(opCode, 4, "BLOS");
// if ((this.flagC & 0x10000) ||
// !(this.flagZ & 0xffff)) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// !(this.flagZ & 0xffff)) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x8400: /*0102000*/ // BVC
// //LOG_INSTRUCTION(opCode, 4, "BVC");
// if (!(this.flagV & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// if (!(this.flagV & 0x8000)) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x8500: /*0102400*/ // BVS
// //LOG_INSTRUCTION(opCode, 4, "BVS");
// if ((this.flagV & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// if ((this.flagV & 0x8000)) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x8600: /*0103000*/ // BCC
// //LOG_INSTRUCTION(opCode, 4, "BCC");
// if (!(this.flagC &
// 0x10000)) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// 0x10000)) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x8700: /*0103400*/ // BCS
// //LOG_INSTRUCTION(opCode, 4, "BCS");
// if (this.flagC & 0x10000) this.regsGen[7] = this.branch(this.regsGen[7], opCode);
// if (this.flagC & 0x10000) this.regsGen[7] = this.branch(opCode);
// break;
// case 0x8800: /*0104000*/ // EMT 104000 -> 104377
// //LOG_INSTRUCTION(opCode, 7, "EMT");

View file

@ -2728,11 +2728,16 @@ if (DEBUGGER) {
var data = 0, iByte = 0, i;
var sData = "", sChars = "";
sAddr = this.toStrAddr(dbgAddr);
for (i = 16; i > 0 && cb > 0; i--) {
/*
* It's just coincidence that we want to dump 8 bytes per line when using base 8 and 16 bytes
* per line when using base 16, because octal requires more digits.
*/
var nBytes = (size == 4? 16 : this.nBase);
for (i = nBytes; i > 0 && cb > 0; i--) {
var b = this.getByte(dbgAddr, 1);
data |= (b << (iByte++ << 3));
if (iByte == size) {
sData += str.toHex(data, size * 2);
sData += (this.nBase == 8? str.toOct(data, size * 3) : str.toHex(data, size * 2));
sData += (size == 1? (i == 9? '-' : ' ') : " ");
data = iByte = 0;
}