Debugger now restricts opcodes to the current CPU model

This commit is contained in:
Jeff Parsons 2016-10-15 15:01:39 -07:00 • committed by Jeff Parsons
commit b79146880d
6 changed files with 263 additions and 152 deletions

View file

@ -0,0 +1,57 @@
---
layout: page
title: PDP-11 Loaders
permalink: /devices/pdp11/loader/
---
PDP-11 Loaders
--------------
The blog post "[PDP-11 Paper Tape BASIC](http://avitech.com.au/?page_id=709)" describes the *Bootstrap Loader*,
a small program used to load the *Absolute Loader*, which in turn loads the *PDP-11 BASIC Paper Tape*.
Here's what the *Bootstrap Loader* looks like:
Location Instruction
037744 016701
037746 000026
037750 012702
037752 000352
037754 005211
037756 105711
037760 100376
037762 116162
037764 000002
037766 037400
037770 005267
037772 177756
037774 000765
037776 177550
Using a [PDPjs](/modules/pdpjs/) machine such as the [PDP-11/20 Test Machine with Debugger](/devices/pdp11/machine/1120/test/debugger/),
the *Bootstrap Loader* is easily entered with a single Debugger "edit" command:
e 037744 016701 000026 012702 000352 005211 105711 100376 116162 000002 037400 005267 177756 000765 177550
You can immediately disassemble the code using `u 037744 040000`:
037744: 016701 000026 MOV 26(PC),R1 ; @037776
037750: 012702 000352 MOV #352,R2
037754: 005211 INC @R1
037756: 105711 TSTB @R1
037760: 100376 BPL 037756
037762: 116162 000002 037400 MOVB 2(R1),37400(R2)
037770: 005267 177756 INC 177756(PC) ; @037752
037774: 000765 BR 037750
037776: 177550 .WORD 177550
I also pasted the disassembled code into a listing file, [bootstrap.lst](bootstrap.lst), and ran [FileDump](/modules/filedump)
to produce a [bootstrap.json](bootstrap.json) that can be pre-loaded into any machine:
filedump --file=bootstrap.lst --format=octal --output=bootstrap.json
To run the *Bootstrap Loader*, set the PC to 037744 and start the machine:
r pc=037744
g

View file

@ -0,0 +1,4 @@
{"words":[
0x1DC1 /*016701*/,0x0016 /*000026*/,0x15C2 /*012702*/,0x00EA /*000352*/,0x0A89 /*005211*/,0x8BC9 /*105711*/,0x80FE /*100376*/,0x9C72 /*116162*/,
0x0002 /*000002*/,0x3F00 /*037400*/,0x0AB7 /*005267*/,0xFFEE /*177756*/,0x01F5 /*000765*/,0xFF68 /*177550*/]
}

View file

@ -0,0 +1,9 @@
037744: 016701 000026 MOV 26(PC),R1 ; @037776
037750: 012702 000352 MOV #352,R2
037754: 005211 INC @R1
037756: 105711 TSTB @R1
037760: 100376 BPL 037756
037762: 116162 000002 037400 MOVB 2(R1),37400(R2)
037770: 005267 177756 INC 177756(PC) ; @037752
037774: 000765 BR 037750
037776: 177550 .WORD 177550

View file

@ -115,8 +115,7 @@ FileDump.asBadExts = [
* in "strict" mode. Prefixing them with "0o" is the new convention for ES6 and up, which is great, but we still
* have no octal format that works across the board. We can use the new octal format in code, because we always
* compile browser-based code back to ES5 (converting all numeric constants to decimal), and current versions of
* Node support it as well (we don't care about old versions of Node). But what we store in data files is more
* problematic.
* Node supported the new format for quite a while. But what we store in data files is more problematic.
*
* When a second file is "merged", the first file sets all even bytes and the second file sets all odd bytes.
* In fact, any number of files can be merged: if there are N files, file #1 sets bytes at "offset mod N == 0",
@ -297,7 +296,7 @@ FileDump.prototype.parseListing = function(sListing)
{
var ab = [];
var matchLine;
var re = /^([0-9 ]{9})([0-7]{6})[ ]+([0-7]+)[ ]*([0-7']+|)[ ]+([0-7']+|)[ ]+(.*)$/gm;
var re = /^( [0-9 ]{8}|)([0-7]{6})[: ]+([0-7]+)[ ]*([0-7']+|)[ ]+([0-7']+|)[ ]+(.*)$/gm;
var addrStart = null;
while (matchLine = re.exec(sListing)) {
/*

View file

@ -245,7 +245,7 @@ if (DEBUGGER) {
* CPU opcode names, indexed by CPU opcode ordinal (above)
*/
DebuggerPDP11.OPNAMES = [
"NONE", "ADC", "ADCB", "ADD", "ASL", "ASLB", "ASR", "ASRB",
".WORD", "ADC", "ADCB", "ADD", "ASL", "ASLB", "ASR", "ASRB",
"BCC", "BCS", "BEQ", "BGE", "BGT", "BHI", "BIC", "BICB",
"BIS", "BISB", "BIT", "BITB", "BLE", "BLOS", "BLT", "BMI",
"BNE", "BPL", "BPT", "BR", "BVC", "BVS", "CCC", "CLC",
@ -282,7 +282,7 @@ if (DEBUGGER) {
DebuggerPDP11.OP_OTHER = 0xF000;
/*
* The opTable contains opcode masks, and each mask refers to table of possible values, and each
* The OPTABLE contains opcode masks, and each mask refers to table of possible values, and each
* value refers to an array that contains:
*
* [0]: {number} of the opcode name (see OP.*)
@ -298,7 +298,7 @@ if (DEBUGGER) {
* that the opcode's destination operand is being listed first, but rather that the bits describing the source
* operand are in the opcode's OP_DST field.
*/
DebuggerPDP11.opTable = {
DebuggerPDP11.OPTABLE = {
0xF000: {
0x1000: [DebuggerPDP11.OPS.MOV, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 01SSDD
0x2000: [DebuggerPDP11.OPS.CMP, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 02SSDD
@ -425,6 +425,28 @@ if (DEBUGGER) {
}
};
DebuggerPDP11.OPNONE = [DebuggerPDP11.OPS.NONE];
/*
* Table of opcodes that are specific to the 11/45 and higher
*/
DebuggerPDP11.OP1145 = [
DebuggerPDP11.OPS.MARK,
DebuggerPDP11.OPS.MFPI,
DebuggerPDP11.OPS.MTPI,
DebuggerPDP11.OPS.SXT,
DebuggerPDP11.OPS.SPL,
DebuggerPDP11.OPS.RTT,
DebuggerPDP11.OPS.MUL,
DebuggerPDP11.OPS.DIV,
DebuggerPDP11.OPS.ASH,
DebuggerPDP11.OPS.ASHC,
DebuggerPDP11.OPS.XOR,
DebuggerPDP11.OPS.SOB,
DebuggerPDP11.OPS.MFPD,
DebuggerPDP11.OPS.MTPD
];
DebuggerPDP11.HISTORY_LIMIT = DEBUG? 100000 : 1000;
/**
@ -448,7 +470,8 @@ if (DEBUGGER) {
var sMessages = cmp.getMachineParm('messages');
if (sMessages) this.messageInit(sMessages);
this.opTable = DebuggerPDP11.opTable;
this.opTable = DebuggerPDP11.OPTABLE;
this.aOpReserved = this.cpu.model < PDP11.MODEL_1145? DebuggerPDP11.OP1145 : [];
this.messageDump(MessagesPDP11.BUS, function onDumpBus(asArgs) { dbg.dumpBus(asArgs); });
@ -2016,12 +2039,24 @@ if (DEBUGGER) {
if (opDesc) break;
}
if (!opDesc) opDesc = [DebuggerPDP11.OPS.NONE];
if (!opDesc) {
opDesc = DebuggerPDP11.OPNONE;
}
var opNum = opDesc[0];
if (this.aOpReserved.indexOf(opNum) >= 0) {
opDesc = DebuggerPDP11.OPNONE;
opNum = opDesc[0];
}
var sOperands = "", sTarget = "";
var sOpName = opNames[opDesc[0]];
var sOpName = opNames[opNum];
var cOperands = opDesc.length - 1;
if (!opNum && !cOperands) {
sOperands = this.toStrBase(opCode);
}
for (var iOperand = 1; iOperand <= cOperands; iOperand++) {
var opType = opDesc[iOperand];
@ -3550,43 +3585,49 @@ if (DEBUGGER) {
};
/**
* doUnassemble(sAddr, sAddrEnd, n)
* doUnassemble(sAddr, sAddrEnd, nLines)
*
* @this {DebuggerPDP11}
* @param {string} [sAddr]
* @param {string} [sAddrEnd]
* @param {number} [n]
* @param {number} [nLines]
*/
DebuggerPDP11.prototype.doUnassemble = function(sAddr, sAddrEnd, n)
DebuggerPDP11.prototype.doUnassemble = function(sAddr, sAddrEnd, nLines)
{
var dbgAddr = this.parseAddr(sAddr, true);
if (!dbgAddr) return;
if (n === undefined) n = 1;
if (nLines === undefined) nLines = 1;
var nBytes = 0x100;
if (sAddrEnd !== undefined) {
var dbgAddrEnd = this.parseAddr(sAddrEnd, true);
if (!dbgAddrEnd || dbgAddrEnd.addr < dbgAddr.addr) return;
nBytes = dbgAddrEnd.addr - dbgAddr.addr;
if (!DEBUG && nBytes > 0x100) {
/*
* Limiting the amount of disassembled code to 256 bytes in non-DEBUG builds is partly to
* prevent the user from wedging the browser by dumping too many lines, but also a recognition
* that, in non-DEBUG builds, this.println() keeps print output buffer truncated to 8Kb anyway.
*/
this.println("range too large");
return;
if (sAddrEnd.charAt(0) == 'l') {
var n = this.parseValue(sAddrEnd.substr(1));
if (n != null) nLines = n;
}
else {
var dbgAddrEnd = this.parseAddr(sAddrEnd, true);
if (!dbgAddrEnd || dbgAddrEnd.addr < dbgAddr.addr) return;
nBytes = dbgAddrEnd.addr - dbgAddr.addr;
if (!DEBUG && nBytes > 0x100) {
/*
* Limiting the amount of disassembled code to 256 bytes in non-DEBUG builds is partly to
* prevent the user from wedging the browser by dumping too many lines, but also a recognition
* that, in non-DEBUG builds, this.println() keeps print output buffer truncated to 8Kb anyway.
*/
this.println("range too large");
return;
}
nLines = -1;
}
n = -1;
}
var nLines = 0;
var nPrinted = 0;
var sInstruction;
while (nBytes > 0 && n--) {
while (nBytes > 0 && nLines--) {
var nSequence = (this.isBusy(false) || this.nStep)? this.nCycles : null;
var sComment = (nSequence != null? "cycles" : null);
@ -3594,8 +3635,8 @@ if (DEBUGGER) {
var addr = dbgAddr.addr; // we snap dbgAddr.addr *after* calling findSymbol(), which re-evaluates it
if (aSymbol[0] && n) {
if (!nLines && n || aSymbol[0].indexOf('+') < 0) {
if (aSymbol[0] && nLines) {
if (!nPrinted && nLines || aSymbol[0].indexOf('+') < 0) {
var sLabel = aSymbol[0] + ':';
if (aSymbol[2]) sLabel += ' ' + aSymbol[2];
this.println(sLabel);
@ -3612,7 +3653,7 @@ if (DEBUGGER) {
this.println(sInstruction);
this.dbgAddrNextCode = dbgAddr;
nBytes -= dbgAddr.addr - addr;
nLines++;
nPrinted++;
}
};

File diff suppressed because one or more lines are too long