Debugger now restricts opcodes to the current CPU model
This commit is contained in:
parent
2ce661e141
commit
b79146880d
6 changed files with 263 additions and 152 deletions
57
devices/pdp11/loader/README.md
Normal file
57
devices/pdp11/loader/README.md
Normal 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
|
||||
|
||||
4
devices/pdp11/loader/bootstrap.json
Normal file
4
devices/pdp11/loader/bootstrap.json
Normal 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*/]
|
||||
}
|
||||
9
devices/pdp11/loader/bootstrap.lst
Normal file
9
devices/pdp11/loader/bootstrap.lst
Normal 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
|
||||
|
|
@ -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)) {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in a new issue