Some PDP-10 disassembler clean-up
This commit is contained in:
parent
cb4d054ead
commit
3e30bde786
3 changed files with 94 additions and 78 deletions
|
|
@ -3790,7 +3790,7 @@ PDP10.opUndefined = function(opCode)
|
||||||
*/
|
*/
|
||||||
PDP10.opKA10 = function(opCode)
|
PDP10.opKA10 = function(opCode)
|
||||||
{
|
{
|
||||||
var op = (opCode / PDP10.OPCODE.SHIFT)|0;
|
var op = (opCode / PDP10.OPCODE.O_SHIFT)|0;
|
||||||
PDP10.aOpXXX_KA10[op].call(this, opCode);
|
PDP10.aOpXXX_KA10[op].call(this, opCode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3456,50 +3456,62 @@ class DebuggerPDP10 extends Debugger {
|
||||||
/**
|
/**
|
||||||
* doTest()
|
* doTest()
|
||||||
*
|
*
|
||||||
|
* This function exercises the disassembler by performing look-ups for all possible operation codes
|
||||||
|
* and displaying the results. It's not intended to be included in the compiled version of the Debugger
|
||||||
|
* (DEBUG only).
|
||||||
|
*
|
||||||
* @this {DebuggerPDP10}
|
* @this {DebuggerPDP10}
|
||||||
*/
|
*/
|
||||||
doTest()
|
doTest()
|
||||||
{
|
{
|
||||||
var ops = {}, aOpXXX = [];
|
if (DEBUG) {
|
||||||
var op, opXXX, opCode, sOperation;
|
var ops = {}, aOpXXX = [];
|
||||||
for (op = 0o00000; op <= 0o77774; op += 4) {
|
var op, opXXX, opCode, sOperation;
|
||||||
opCode = op * Math.pow(2, 21);
|
for (op = 0o00000; op <= 0o77774; op += 4) {
|
||||||
sOperation = this.findInstruction(opCode, false);
|
opCode = op * Math.pow(2, 21);
|
||||||
if (!sOperation) continue;
|
sOperation = this.findInstruction(opCode, false);
|
||||||
if (ops[sOperation] === undefined) {
|
if (!sOperation) continue;
|
||||||
ops[sOperation] = op;
|
if (ops[sOperation] === undefined) {
|
||||||
} else {
|
ops[sOperation] = op;
|
||||||
ops[sOperation] &= op;
|
} else {
|
||||||
|
ops[sOperation] &= op;
|
||||||
|
}
|
||||||
|
opXXX = op >> 6;
|
||||||
|
if (!aOpXXX[opXXX]) {
|
||||||
|
aOpXXX[opXXX] = sOperation;
|
||||||
|
} else if (aOpXXX[opXXX] != sOperation) {
|
||||||
|
aOpXXX[opXXX] = "XXX";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
opXXX = op >> 6;
|
for (sOperation in ops) {
|
||||||
if (!aOpXXX[opXXX]) {
|
op = ops[sOperation];
|
||||||
aOpXXX[opXXX] = sOperation;
|
this.println(Str.pad(sOperation + ":", 8) + this.toStrWord(op * Math.pow(2, 21)));
|
||||||
} else if (aOpXXX[opXXX] != sOperation) {
|
//
|
||||||
aOpXXX[opXXX] = "XXX";
|
// The following code leveraged the disassembler to generate opcode handlers for all known opcodes.
|
||||||
|
//
|
||||||
|
// this.println("/**");
|
||||||
|
// this.println(" * op" + sOperation + "(" + this.toStrWord(op * Math.pow(2, 21)) + ")");
|
||||||
|
// this.println(" *");
|
||||||
|
// this.println(" * @this {CPUStatePDP10}");
|
||||||
|
// this.println(" * @param {number} opCode");
|
||||||
|
// this.println(" */");
|
||||||
|
// this.println("PDP10.op" + sOperation + " = function(opCode)");
|
||||||
|
// this.println("{");
|
||||||
|
// this.println("};\n");
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// The following code leveraged the disassembler to generate an opcode dispatch table for all known opcodes.
|
||||||
|
//
|
||||||
|
// this.println("PDP10.aOpXXX = [");
|
||||||
|
// for (opXXX = 0o000; opXXX <= 0o777; opXXX++) {
|
||||||
|
// sOperation = aOpXXX[opXXX];
|
||||||
|
// sOperation = sOperation? (" PDP10.op" + sOperation + ",") : " PDP10.opUndefined,";
|
||||||
|
// sOperation = Str.pad(sOperation, 32);
|
||||||
|
// sOperation += "// " + Str.toOct(opXXX, 3, true) + "xxx yyyyyy";
|
||||||
|
// this.println(sOperation);
|
||||||
|
// }
|
||||||
|
// this.println("];");
|
||||||
}
|
}
|
||||||
for (sOperation in ops) {
|
|
||||||
op = ops[sOperation];
|
|
||||||
this.println(sOperation + ": " + this.toStrWord(op * Math.pow(2, 21)));
|
|
||||||
// this.println("/**");
|
|
||||||
// this.println(" * op" + sOperation + "(" + this.toStrWord(op * Math.pow(2, 21)) + ")");
|
|
||||||
// this.println(" *");
|
|
||||||
// this.println(" * @this {CPUStatePDP10}");
|
|
||||||
// this.println(" * @param {number} opCode");
|
|
||||||
// this.println(" */");
|
|
||||||
// this.println("PDP10.op" + sOperation + " = function(opCode)");
|
|
||||||
// this.println("{");
|
|
||||||
// this.println("};\n");
|
|
||||||
}
|
|
||||||
// this.println("PDP10.aOpXXX = [");
|
|
||||||
// for (opXXX = 0o000; opXXX <= 0o777; opXXX++) {
|
|
||||||
// sOperation = aOpXXX[opXXX];
|
|
||||||
// sOperation = sOperation? (" PDP10.op" + sOperation + ",") : " PDP10.opUndefined,";
|
|
||||||
// sOperation = Str.pad(sOperation, 32);
|
|
||||||
// sOperation += "// " + Str.toOct(opXXX, 3, true) + "xxx yyyyyy";
|
|
||||||
// this.println(sOperation);
|
|
||||||
// }
|
|
||||||
// this.println("];");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -3634,37 +3646,10 @@ if (DEBUGGER) {
|
||||||
];
|
];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PDP-10 opcodes are 36-bit values, many of which use the following layout:
|
* OPTABLE is a collection of masks, and each mask refers to a collection of opcode
|
||||||
*
|
* patterns associated with that mask; the disassembler applies each mask to the opcode,
|
||||||
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3
|
* and when a masked opcode matches one of the associated patterns, the corresponding
|
||||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
* instruction is considered a match.
|
||||||
* O O O O O O O M M A A A A I X X X X Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
|
|
||||||
*
|
|
||||||
* or using modern bit-numbering:
|
|
||||||
*
|
|
||||||
* 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
|
||||||
* 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
|
||||||
* O O O O O O O M M A A A A I X X X X Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
|
|
||||||
*
|
|
||||||
* where OOOOOOOMM represents the operation, and MM (if used) represents the mode:
|
|
||||||
*
|
|
||||||
* Mode Suffix Source Destination
|
|
||||||
* ---- ------ ----- -----------
|
|
||||||
* 0: BASIC None E AC
|
|
||||||
* 1: IMMEDIATE I 0,E AC
|
|
||||||
* 2: MEMORY M AC E
|
|
||||||
* 3: SELF S E E (and AC if A is non-zero)
|
|
||||||
*
|
|
||||||
* Input-output instructions look like:
|
|
||||||
*
|
|
||||||
* 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
|
||||||
* 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
|
||||||
* 1 1 1 D D D D D D D O O O I X X X X Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
|
|
||||||
*
|
|
||||||
* Bits 0-22 (I,X,Y) contain what we call a "reference address" (R), which is used to
|
|
||||||
* calculate the "effective address" (E). To determine E from R, we must extract I, X,
|
|
||||||
* and Y from R, set E to Y, then add [X] to E if X is non-zero. If I is zero, then
|
|
||||||
* we're done; otherwise, we must set set R to [E] and repeat the process.
|
|
||||||
*/
|
*/
|
||||||
DebuggerPDP10.OPTABLE = {
|
DebuggerPDP10.OPTABLE = {
|
||||||
[PDP10.OPCODE.OPUUO]: { // 0o70000
|
[PDP10.OPCODE.OPUUO]: { // 0o70000
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,37 @@ var PDP10 = {
|
||||||
DATA_LIMIT: Math.pow(2, 36),
|
DATA_LIMIT: Math.pow(2, 36),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Opcode definitions
|
* PDP-10 opcodes are 36-bit values, most of which use the following layout:
|
||||||
|
*
|
||||||
|
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3
|
||||||
|
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||||
|
* O O O O O O O M M A A A A I X X X X Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
|
||||||
|
*
|
||||||
|
* or using modern bit-numbering:
|
||||||
|
*
|
||||||
|
* 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||||
|
* 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||||
|
* O O O O O O O M M A A A A I X X X X Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
|
||||||
|
*
|
||||||
|
* where OOOOOOOMM represents the operation, and MM (if used) represents the mode:
|
||||||
|
*
|
||||||
|
* Mode Suffix Source Destination
|
||||||
|
* ---- ------ ----- -----------
|
||||||
|
* 0: BASIC None E AC
|
||||||
|
* 1: IMMEDIATE I 0,E AC
|
||||||
|
* 2: MEMORY M AC E
|
||||||
|
* 3: SELF S E E (and AC if A is non-zero)
|
||||||
|
*
|
||||||
|
* Input-output instructions look like:
|
||||||
|
*
|
||||||
|
* 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||||
|
* 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||||
|
* 1 1 1 D D D D D D D O O O I X X X X Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
|
||||||
|
*
|
||||||
|
* Bits 0-22 (I,X,Y) contain what we call a "reference address" (R), which is used to
|
||||||
|
* calculate the "effective address" (E). To determine E from R, we must extract I, X,
|
||||||
|
* and Y from R, set E to Y, then add [X] to E if X is non-zero. If I is zero, then
|
||||||
|
* we're done; otherwise, we must set set R to [E] and repeat the process.
|
||||||
*/
|
*/
|
||||||
OPCODE: {
|
OPCODE: {
|
||||||
OPMASK: 0o77700, // operation mask
|
OPMASK: 0o77700, // operation mask
|
||||||
|
|
@ -115,11 +145,12 @@ var PDP10 = {
|
||||||
FNMASK: 0o17, // accumulator/function mask (after shift)
|
FNMASK: 0o17, // accumulator/function mask (after shift)
|
||||||
IOSHIFT: Math.pow(2, 26), // input-output device code shift
|
IOSHIFT: Math.pow(2, 26), // input-output device code shift
|
||||||
IOMASK: 0o177, // input-output device code mask (after shift)
|
IOMASK: 0o177, // input-output device code mask (after shift)
|
||||||
SHIFT: Math.pow(2, 27), // operation code shift
|
O_SHIFT: Math.pow(2, 27), // operation shift
|
||||||
Y_MASK: 0o777777,
|
O_MASK: 0o777, // operation mask (after shift)
|
||||||
X_SHIFT: 18,
|
I_BIT: 0o20000000, // indirect bit
|
||||||
X_MASK: 0o17,
|
X_SHIFT: 18, // X shift
|
||||||
I_BIT: 0o20000000,
|
X_MASK: 0o17, // X mask (after shift)
|
||||||
|
Y_MASK: 0o777777, // Y mask
|
||||||
HALT: 0o5304 // operation code for HALT
|
HALT: 0o5304 // operation code for HALT
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue