Backporting from concurrent project
This commit is contained in:
parent
386f4a904f
commit
77c256f2e0
36
core/cpu.c
36
core/cpu.c
|
@ -483,7 +483,7 @@ static int exaFloating1(VB *sim) {
|
||||||
/* Reserved operand */
|
/* Reserved operand */
|
||||||
reg1 = sim->cpu.program[sim->cpu.inst.code[0] & 31];
|
reg1 = sim->cpu.program[sim->cpu.inst.code[0] & 31];
|
||||||
if (cpuFRO(reg1)) {
|
if (cpuFRO(reg1)) {
|
||||||
sim->cpu.fp_flags = 0x00000200; /* FRO */
|
sim->cpu.fpFlags = 0x00000200; /* FRO */
|
||||||
sim->cpu.exception = 0xFF60;
|
sim->cpu.exception = 0xFF60;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -506,7 +506,7 @@ static int exaFloating1(VB *sim) {
|
||||||
|
|
||||||
/* Invalid operation */
|
/* Invalid operation */
|
||||||
if (bits > 7) {
|
if (bits > 7) {
|
||||||
sim->cpu.fp_flags = 0x00000100; /* FIV */
|
sim->cpu.fpFlags = 0x00000100; /* FIV */
|
||||||
sim->cpu.exception = 0xFF70;
|
sim->cpu.exception = 0xFF70;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -529,7 +529,7 @@ static int exaFloating1(VB *sim) {
|
||||||
result = -result;
|
result = -result;
|
||||||
|
|
||||||
/* Stage updates */
|
/* Stage updates */
|
||||||
sim->cpu.fp_flags = result==*(float *)®1 ? 0 : 0x00000010; /* FPR */
|
sim->cpu.fpFlags = result==*(float *)®1 ? 0 : 0x00000010; /* FPR */
|
||||||
sim->cpu.inst.aux[0] = result;
|
sim->cpu.inst.aux[0] = result;
|
||||||
sim->cpu.inst.aux[1] = subop;
|
sim->cpu.inst.aux[1] = subop;
|
||||||
sim->cpu.clocks += ((OpDef *) sim->cpu.inst.def)->aux;
|
sim->cpu.clocks += ((OpDef *) sim->cpu.inst.def)->aux;
|
||||||
|
@ -549,7 +549,7 @@ static int exaFloating2(VB *sim) {
|
||||||
reg1 = sim->cpu.program[sim->cpu.inst.code[0] & 31];
|
reg1 = sim->cpu.program[sim->cpu.inst.code[0] & 31];
|
||||||
reg2 = sim->cpu.program[sim->cpu.inst.code[0] >> 5 & 31];
|
reg2 = sim->cpu.program[sim->cpu.inst.code[0] >> 5 & 31];
|
||||||
if (cpuFRO(reg1) || cpuFRO(reg2)) {
|
if (cpuFRO(reg1) || cpuFRO(reg2)) {
|
||||||
sim->cpu.fp_flags = 0x00000200; /* FRO */
|
sim->cpu.fpFlags = 0x00000200; /* FRO */
|
||||||
sim->cpu.exception = 0xFF60;
|
sim->cpu.exception = 0xFF60;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -564,14 +564,14 @@ static int exaFloating2(VB *sim) {
|
||||||
bits = 0x7F7FFFFF; /* Maximum value */
|
bits = 0x7F7FFFFF; /* Maximum value */
|
||||||
test = *(float *)&bits;
|
test = *(float *)&bits;
|
||||||
if (aux->f64 > test || aux->f64 < -test) {
|
if (aux->f64 > test || aux->f64 < -test) {
|
||||||
sim->cpu.fp_flags = 0x00000040; /* FOV */
|
sim->cpu.fpFlags = 0x00000040; /* FOV */
|
||||||
sim->cpu.exception = 0xFF64;
|
sim->cpu.exception = 0xFF64;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process result */
|
/* Process result */
|
||||||
bits = *(int32_t *)&aux->f32;
|
bits = *(int32_t *)&aux->f32;
|
||||||
sim->cpu.fp_flags = 0;
|
sim->cpu.fpFlags = 0;
|
||||||
|
|
||||||
/* Zero */
|
/* Zero */
|
||||||
if ((bits & 0x7FFFFFFF) == 0x00000000)
|
if ((bits & 0x7FFFFFFF) == 0x00000000)
|
||||||
|
@ -579,13 +579,13 @@ static int exaFloating2(VB *sim) {
|
||||||
|
|
||||||
/* Underflow */
|
/* Underflow */
|
||||||
else if ((bits & 0x7F800000) == 0x00000000) {
|
else if ((bits & 0x7F800000) == 0x00000000) {
|
||||||
sim->cpu.fp_flags = 0x00000020; /* FUD */
|
sim->cpu.fpFlags = 0x00000020; /* FUD */
|
||||||
aux->f32 = bits = 0;
|
aux->f32 = bits = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Precision degradation */
|
/* Precision degradation */
|
||||||
if (aux->f32 != aux->f64)
|
if (aux->f32 != aux->f64)
|
||||||
sim->cpu.fp_flags |= 0x00000010; /* FPR */
|
sim->cpu.fpFlags |= 0x00000010; /* FPR */
|
||||||
|
|
||||||
/* Other state */
|
/* Other state */
|
||||||
sim->cpu.inst.aux[0] = bits;
|
sim->cpu.inst.aux[0] = bits;
|
||||||
|
@ -770,10 +770,10 @@ static void exbException(VB *sim) {
|
||||||
int x; /* Iterator */
|
int x; /* Iterator */
|
||||||
|
|
||||||
/* Apply staged floating-point flags */
|
/* Apply staged floating-point flags */
|
||||||
if (sim->cpu.fp_flags != 0) {
|
if (sim->cpu.fpFlags != 0) {
|
||||||
cpuSetSystemRegister(sim, VB_PSW, sim->cpu.fp_flags |
|
cpuSetSystemRegister(sim, VB_PSW, sim->cpu.fpFlags |
|
||||||
cpuGetSystemRegister(sim, VB_PSW), 0);
|
cpuGetSystemRegister(sim, VB_PSW), 0);
|
||||||
sim->cpu.fp_flags = 0;
|
sim->cpu.fpFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fatal exception */
|
/* Fatal exception */
|
||||||
|
@ -826,10 +826,10 @@ static void exbFloating(VB *sim) {
|
||||||
int32_t subop = sim->cpu.inst.aux[1]; /* Sub-opcode */
|
int32_t subop = sim->cpu.inst.aux[1]; /* Sub-opcode */
|
||||||
|
|
||||||
/* Apply staged floating-point flags */
|
/* Apply staged floating-point flags */
|
||||||
if (sim->cpu.fp_flags != 0) {
|
if (sim->cpu.fpFlags != 0) {
|
||||||
cpuSetSystemRegister(sim, VB_PSW, sim->cpu.fp_flags |
|
cpuSetSystemRegister(sim, VB_PSW, sim->cpu.fpFlags |
|
||||||
cpuGetSystemRegister(sim, VB_PSW), 0);
|
cpuGetSystemRegister(sim, VB_PSW), 0);
|
||||||
sim->cpu.fp_flags = 0;
|
sim->cpu.fpFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update state */
|
/* Update state */
|
||||||
|
@ -985,13 +985,13 @@ static void opDIVF_S(VB *sim, int32_t *dest, int32_t src) {
|
||||||
|
|
||||||
/* Invalid operation */
|
/* Invalid operation */
|
||||||
if (src == 0) {
|
if (src == 0) {
|
||||||
sim->cpu.fp_flags = 0x00000100; /* FIV */
|
sim->cpu.fpFlags = 0x00000100; /* FIV */
|
||||||
sim->cpu.exception = 0xFF70;
|
sim->cpu.exception = 0xFF70;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zero division */
|
/* Zero division */
|
||||||
else {
|
else {
|
||||||
sim->cpu.fp_flags = 0x00000080; /* FZD */
|
sim->cpu.fpFlags = 0x00000080; /* FZD */
|
||||||
sim->cpu.exception = 0xFF68;
|
sim->cpu.exception = 0xFF68;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,7 @@ struct VB {
|
||||||
|
|
||||||
/* Other state */
|
/* Other state */
|
||||||
uint32_t clocks; /* Clocks until next activity */
|
uint32_t clocks; /* Clocks until next activity */
|
||||||
uint32_t fp_flags; /* Floating-point exception flags */
|
uint32_t fpFlags; /* Floating-point exception flags */
|
||||||
uint16_t exception; /* Current exception cause code */
|
uint16_t exception; /* Current exception cause code */
|
||||||
uint8_t irq[5]; /* Interrupt requests */
|
uint8_t irq[5]; /* Interrupt requests */
|
||||||
uint8_t bitstring; /* Processing a bit string instruction */
|
uint8_t bitstring; /* Processing a bit string instruction */
|
||||||
|
|
|
@ -139,7 +139,7 @@ class Disassembler {
|
||||||
];
|
];
|
||||||
|
|
||||||
// Program register names
|
// Program register names
|
||||||
static PRONAMES = [
|
static REG_PROGRAM = [
|
||||||
"r0" , "r1" , "hp" , "sp" , "gp" , "tp" , "r6" , "r7" ,
|
"r0" , "r1" , "hp" , "sp" , "gp" , "tp" , "r6" , "r7" ,
|
||||||
"r8" , "r9" , "r10", "r11", "r12", "r13", "r14", "r15",
|
"r8" , "r9" , "r10", "r11", "r12", "r13", "r14", "r15",
|
||||||
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
||||||
|
@ -147,13 +147,16 @@ class Disassembler {
|
||||||
];
|
];
|
||||||
|
|
||||||
// System register names
|
// System register names
|
||||||
static SYSNAMES = [
|
static REG_SYSTEM = [
|
||||||
"EIPC", "EIPSW", "FEPC", "FEPSW", "ECR", "PSW", "PIR", "TKCW",
|
"EIPC", "EIPSW", "FEPC", "FEPSW", "ECR", "PSW", "PIR", "TKCW",
|
||||||
"8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" ,
|
"8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" ,
|
||||||
"16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" ,
|
"16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" ,
|
||||||
"CHCW", "ADTRE", "26" , "27" , "28" , "29" , "30" , "31"
|
"CHCW", "ADTRE", "26" , "27" , "28" , "29" , "30" , "31"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Other register names
|
||||||
|
static REG_OTHER = [ "PC", "PSW" ];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////// Static Methods //////////////////////////////
|
///////////////////////////// Static Methods //////////////////////////////
|
||||||
|
@ -522,7 +525,8 @@ class Disassembler {
|
||||||
|
|
||||||
// Format a program register
|
// Format a program register
|
||||||
programRegister(index) {
|
programRegister(index) {
|
||||||
let ret = this.proNames ? Disassembler.PRONAMES[index] : "r" + index;
|
let ret = this.proNames ?
|
||||||
|
Disassembler.REG_PROGRAM[index] : "r" + index;
|
||||||
if (this.proUppercase)
|
if (this.proUppercase)
|
||||||
ret = ret.toUpperCase();
|
ret = ret.toUpperCase();
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -531,7 +535,7 @@ class Disassembler {
|
||||||
// Format a system register
|
// Format a system register
|
||||||
systemRegister(index) {
|
systemRegister(index) {
|
||||||
let ret = this.sysNames ?
|
let ret = this.sysNames ?
|
||||||
Disassembler.SYSNAMES[index] : index.toString();
|
Disassembler.REG_SYSTEM[index] : index.toString();
|
||||||
if (!this.sysUppercase && this.sysNames)
|
if (!this.sysUppercase && this.sysNames)
|
||||||
ret = ret.toLowerCase();
|
ret = ret.toLowerCase();
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -72,7 +72,8 @@ class CPU extends Toolkit.Window {
|
||||||
break;
|
break;
|
||||||
case "g": case "G":
|
case "g": case "G":
|
||||||
this.disassembler.goto();
|
this.disassembler.goto();
|
||||||
return;
|
break;
|
||||||
|
default: return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Processing by key: CTRL up
|
// Processing by key: CTRL up
|
||||||
|
@ -112,6 +113,20 @@ class CPU extends Toolkit.Window {
|
||||||
|
|
||||||
///////////////////////////// Package Methods /////////////////////////////
|
///////////////////////////// Package Methods /////////////////////////////
|
||||||
|
|
||||||
|
// Disassembler configuration has changed
|
||||||
|
dasmConfigured() {
|
||||||
|
|
||||||
|
// Disassembler
|
||||||
|
this.disassembler.fetch();
|
||||||
|
|
||||||
|
// Registers
|
||||||
|
for (let reg of this.registers.list) {
|
||||||
|
reg.chkExpand.element.style.removeProperty("min-width");
|
||||||
|
reg.dasmConfigured();
|
||||||
|
}
|
||||||
|
this.registers.regResize();
|
||||||
|
}
|
||||||
|
|
||||||
// Window is being shown for the first time
|
// Window is being shown for the first time
|
||||||
firstShow() {
|
firstShow() {
|
||||||
this.disassembler.firstShow();
|
this.disassembler.firstShow();
|
||||||
|
@ -139,7 +154,7 @@ class DisassemblerPane extends Toolkit.ScrollPane {
|
||||||
|
|
||||||
// Configure instance fields
|
// Configure instance fields
|
||||||
this._bytesColumn = true;
|
this._bytesColumn = true;
|
||||||
this.columnWidths = [ 0, 0, 0, 0, 0, 0 ];
|
this.columnWidths = new Array(6);
|
||||||
this.cpu = cpu;
|
this.cpu = cpu;
|
||||||
this.delta = 0;
|
this.delta = 0;
|
||||||
this.dasm = null;
|
this.dasm = null;
|
||||||
|
@ -149,6 +164,10 @@ class DisassemblerPane extends Toolkit.ScrollPane {
|
||||||
this.viewAddress = 0xFFFFFFF0;
|
this.viewAddress = 0xFFFFFFF0;
|
||||||
this.viewLine = 10;
|
this.viewLine = 10;
|
||||||
|
|
||||||
|
// Initialize column widths
|
||||||
|
for (let x = 0; x < this.columnWidths.length; x++)
|
||||||
|
this.columnWidths[x] = 0;
|
||||||
|
|
||||||
// Client area
|
// Client area
|
||||||
let view = this.view = new Toolkit.Component(cpu.debug.app, {
|
let view = this.view = new Toolkit.Component(cpu.debug.app, {
|
||||||
class : "tk mono disassembler",
|
class : "tk mono disassembler",
|
||||||
|
@ -251,19 +270,19 @@ class DisassemblerPane extends Toolkit.ScrollPane {
|
||||||
|
|
||||||
let line = {
|
let line = {
|
||||||
lblAddress : document.createElement("div"),
|
lblAddress : document.createElement("div"),
|
||||||
lblBytes : [],
|
lblBytes : new Array(4),
|
||||||
lblMnemonic: document.createElement("div"),
|
lblMnemonic: document.createElement("div"),
|
||||||
lblOperands: document.createElement("div")
|
lblOperands: document.createElement("div")
|
||||||
};
|
};
|
||||||
|
|
||||||
// Address label
|
// Address label
|
||||||
line.lblAddress.className = "addr";
|
line.lblAddress.className = "address";
|
||||||
if (y == 0)
|
if (y == 0)
|
||||||
resizer.observe(line.lblAddress);
|
resizer.observe(line.lblAddress);
|
||||||
this.view.append(line.lblAddress);
|
this.view.append(line.lblAddress);
|
||||||
|
|
||||||
// Byte labels
|
// Byte labels
|
||||||
for (let x = 0; x < 4; x++) {
|
for (let x = 0; x < line.lblBytes.length; x++) {
|
||||||
let lbl = line.lblBytes[x] = document.createElement("div");
|
let lbl = line.lblBytes[x] = document.createElement("div");
|
||||||
lbl.className = "byte" + (x == 0 ? " b0" : "");
|
lbl.className = "byte" + (x == 0 ? " b0" : "");
|
||||||
if (y == 0) {
|
if (y == 0) {
|
||||||
|
@ -274,13 +293,13 @@ class DisassemblerPane extends Toolkit.ScrollPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mnemonic label
|
// Mnemonic label
|
||||||
line.lblMnemonic.className = "inst";
|
line.lblMnemonic.className = "mnemonic";
|
||||||
if (y == 0)
|
if (y == 0)
|
||||||
resizer.observe(line.lblMnemonic);
|
resizer.observe(line.lblMnemonic);
|
||||||
this.view.append(line.lblMnemonic);
|
this.view.append(line.lblMnemonic);
|
||||||
|
|
||||||
// Operand label
|
// Operand label
|
||||||
line.lblOperands.className = "ops";
|
line.lblOperands.className = "operands";
|
||||||
this.view.append(line.lblOperands);
|
this.view.append(line.lblOperands);
|
||||||
|
|
||||||
// All elements
|
// All elements
|
||||||
|
@ -428,10 +447,11 @@ class DisassemblerPane extends Toolkit.ScrollPane {
|
||||||
for (let x = 0; x < this.columnWidths.length; x++)
|
for (let x = 0; x < this.columnWidths.length; x++)
|
||||||
this.columnWidths[x] = 0;
|
this.columnWidths[x] = 0;
|
||||||
this.refresh();
|
this.refresh();
|
||||||
|
this.colResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure PC is visible in the view
|
// Ensure PC is visible in the view
|
||||||
followPC(pc = null) {
|
followPC(pc) {
|
||||||
let tall = this.tall(true);
|
let tall = this.tall(true);
|
||||||
let count = !this.dasm ? 0 : Math.min(this.dasm.length - 10, tall);
|
let count = !this.dasm ? 0 : Math.min(this.dasm.length - 10, tall);
|
||||||
|
|
||||||
|
@ -498,15 +518,17 @@ class DisassemblerPane extends Toolkit.ScrollPane {
|
||||||
|
|
||||||
// Determine an initial number of visible byte columns
|
// Determine an initial number of visible byte columns
|
||||||
let showBytes = 0;
|
let showBytes = 0;
|
||||||
if (this.bytesColumn)
|
if (this.bytesColumn) {
|
||||||
for (let x = 0; x<4 && this.columnWidths[x]!=0; x++, showBytes++);
|
for (let x = 0; x < 4 &&
|
||||||
|
this.columnWidths[x] != 0; x++, showBytes++);
|
||||||
|
}
|
||||||
|
|
||||||
// Working variables
|
// Working variables
|
||||||
let foundPC = false;
|
let foundPC = false;
|
||||||
let lineHeight = this.pc.element.getBoundingClientRect().height;
|
let lineHeight = this.pc.element.getBoundingClientRect().height;
|
||||||
|
|
||||||
// Process all lines
|
// Process all lines
|
||||||
let index = 20 - this.viewLine;
|
let index = 20 - this.viewLine;
|
||||||
for (let y = 0; y < this.lines.length; y++, index++) {
|
for (let y = 0; y < this.lines.length; y++, index++) {
|
||||||
let line = this.lines[y];
|
let line = this.lines[y];
|
||||||
let isPC = false;
|
let isPC = false;
|
||||||
|
@ -517,7 +539,7 @@ class DisassemblerPane extends Toolkit.ScrollPane {
|
||||||
line.lblBytes[0].innerText = "--";
|
line.lblBytes[0].innerText = "--";
|
||||||
line.lblMnemonic.innerText = "---";
|
line.lblMnemonic.innerText = "---";
|
||||||
line.lblOperands.innerText = "";
|
line.lblOperands.innerText = "";
|
||||||
for (let x = 1; x < 4; x++)
|
for (let x = 1; x < line.lblBytes.length; x++)
|
||||||
line.lblBytes[x].innerText = "";
|
line.lblBytes[x].innerText = "";
|
||||||
if (this.bytesColumn)
|
if (this.bytesColumn)
|
||||||
showBytes = Math.max(showBytes, 1);
|
showBytes = Math.max(showBytes, 1);
|
||||||
|
@ -529,7 +551,7 @@ class DisassemblerPane extends Toolkit.ScrollPane {
|
||||||
line.lblAddress .innerText = dasm.address;
|
line.lblAddress .innerText = dasm.address;
|
||||||
line.lblMnemonic.innerText = dasm.mnemonic;
|
line.lblMnemonic.innerText = dasm.mnemonic;
|
||||||
line.lblOperands.innerText = dasm.operands.join(", ");
|
line.lblOperands.innerText = dasm.operands.join(", ");
|
||||||
for (let x = 0; x < 4; x++)
|
for (let x = 0; x < line.lblBytes.length; x++)
|
||||||
line.lblBytes[x].innerText = dasm.bytes[x] || "";
|
line.lblBytes[x].innerText = dasm.bytes[x] || "";
|
||||||
isPC = this.cpu.registers.pc == dasm.rawAddress;
|
isPC = this.cpu.registers.pc == dasm.rawAddress;
|
||||||
if (this.bytesColumn)
|
if (this.bytesColumn)
|
||||||
|
@ -554,7 +576,7 @@ class DisassemblerPane extends Toolkit.ScrollPane {
|
||||||
|
|
||||||
// Configure which byte columns are visible
|
// Configure which byte columns are visible
|
||||||
for (let line of this.lines) {
|
for (let line of this.lines) {
|
||||||
for (let x = 0; x < 4; x++) {
|
for (let x = 0; x < line.lblBytes.length; x++) {
|
||||||
line.lblBytes[x].style
|
line.lblBytes[x].style
|
||||||
[x < showBytes ? "removeProperty" : "setProperty"]
|
[x < showBytes ? "removeProperty" : "setProperty"]
|
||||||
("display", "none")
|
("display", "none")
|
||||||
|
@ -599,8 +621,8 @@ class Register {
|
||||||
//////////////////////////////// Constants ////////////////////////////////
|
//////////////////////////////// Constants ////////////////////////////////
|
||||||
|
|
||||||
// Register types
|
// Register types
|
||||||
static PROGRAM = 0;
|
static PLAIN = 0;
|
||||||
static PLAIN = 1;
|
static PROGRAM = 1;
|
||||||
static CHCW = 2;
|
static CHCW = 2;
|
||||||
static ECR = 3;
|
static ECR = 3;
|
||||||
static PSW = 4;
|
static PSW = 4;
|
||||||
|
@ -626,31 +648,20 @@ class Register {
|
||||||
[ "texth", "PT", 0, 16 ]
|
[ "texth", "PT", 0, 16 ]
|
||||||
],
|
],
|
||||||
[this.PSW]: [
|
[this.PSW]: [
|
||||||
[ "check", "CY" , 3 ],
|
[ "check", "CY" , 3 ], [ "check", "FRO", 9 ],
|
||||||
[ "check", "FRO", 9 ],
|
[ "check", "OV" , 2 ], [ "check", "FIV", 8 ],
|
||||||
[ "check", "OV" , 2 ],
|
[ "check", "S" , 1 ], [ "check", "FZD", 7 ],
|
||||||
[ "check", "FIV", 8 ],
|
[ "check", "Z" , 0 ], [ "check", "FOV", 6 ],
|
||||||
[ "check", "S" , 1 ],
|
[ "check", "NP" , 15 ], [ "check", "FUD", 5 ],
|
||||||
[ "check", "FZD", 7 ],
|
[ "check", "EP" , 14 ], [ "check", "FPR", 4 ],
|
||||||
[ "check", "Z" , 0 ],
|
[ "check", "ID" , 12 ], [ "textd", "I" , 16, 4 ],
|
||||||
[ "check", "FOV", 6 ],
|
|
||||||
[ "check", "NP" , 15 ],
|
|
||||||
[ "check", "FUD", 5 ],
|
|
||||||
[ "check", "EP" , 14 ],
|
|
||||||
[ "check", "FPR", 4 ],
|
|
||||||
[ "check", "ID" , 12 ],
|
|
||||||
[ "textd", "I" , 16, 4 ],
|
|
||||||
[ "check", "AE" , 13 ]
|
[ "check", "AE" , 13 ]
|
||||||
],
|
],
|
||||||
[this.TKCW]: [
|
[this.TKCW]: [
|
||||||
[ "check", "FIT", 7 ],
|
[ "check", "FIT", 7 ], [ "check", "FUT", 4 ],
|
||||||
[ "check", "FUT", 4 ],
|
[ "check", "FZT", 6 ], [ "check", "FPT", 3 ],
|
||||||
[ "check", "FZT", 6 ],
|
[ "check", "FVT", 5 ], [ "check", "OTM", 8 ],
|
||||||
[ "check", "FPT", 3 ],
|
[ "check", "RDI", 2 ], [ "textd", "RD" , 0, 2 ]
|
||||||
[ "check", "FVT", 5 ],
|
|
||||||
[ "check", "OTM", 8 ],
|
|
||||||
[ "check", "RDI", 2 ],
|
|
||||||
[ "textd", "RD" , 0, 2 ]
|
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -668,47 +679,37 @@ class Register {
|
||||||
this.dasm = registers.cpu.debug.app.dasm;
|
this.dasm = registers.cpu.debug.app.dasm;
|
||||||
this.debug = registers.cpu.debug;
|
this.debug = registers.cpu.debug;
|
||||||
this.expansion = null;
|
this.expansion = null;
|
||||||
|
this.format = Register.HEX;
|
||||||
|
this.key = key;
|
||||||
this.registers = registers;
|
this.registers = registers;
|
||||||
this.target = registers;
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
// Resolve the register reference
|
// Resolve the target object
|
||||||
key = key.slice();
|
switch (apiType) {
|
||||||
while (key.length != 1)
|
case Core.VB_PROGRAM: this.target = registers.program; break;
|
||||||
this.target = this.target[key.shift()];
|
case Core.VB_SYSTEM : this.target = registers.system ; break;
|
||||||
this.key = key[0];
|
case Core.VB_OTHER : this.target = registers ; break;
|
||||||
|
}
|
||||||
|
|
||||||
// Main controls
|
// Main controls
|
||||||
this.main = new Toolkit.Component(app, {
|
this.main = new Toolkit.Component(app, {
|
||||||
class: "main",
|
class : "main",
|
||||||
style: {
|
visibility: true,
|
||||||
|
style : {
|
||||||
alignItems : "center",
|
alignItems : "center",
|
||||||
display : "grid",
|
display : "grid",
|
||||||
gridTemplateColumns: "max-content auto"
|
gridTemplateColumns: "max-content auto"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Expand/collapse button
|
// Expand/collapse check box
|
||||||
this.btnExpand = new Toolkit.Component(app, {
|
this.chkExpand = new Toolkit.Checkbox(app, {
|
||||||
class: "tk expand",
|
class : "tk expand",
|
||||||
style: {
|
disabled: true,
|
||||||
alignItems : "center",
|
instant : true,
|
||||||
display : "grid",
|
role : ""
|
||||||
gridTemplateColumns: "max-content auto"
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
this.main.add(this.btnExpand);
|
this.main.add(this.chkExpand);
|
||||||
|
|
||||||
// Expand/collapse icon
|
|
||||||
this.icon = new Toolkit.Component(app, { class: "icon" });
|
|
||||||
this.btnExpand.add(this.icon);
|
|
||||||
|
|
||||||
// Register name
|
|
||||||
this.label = new Toolkit.Label(app, {
|
|
||||||
class: "label",
|
|
||||||
id : Toolkit.id()
|
|
||||||
});
|
|
||||||
this.btnExpand.add(this.label);
|
|
||||||
|
|
||||||
// Value text box
|
// Value text box
|
||||||
this.txtValue = new Toolkit.TextBox(app, {
|
this.txtValue = new Toolkit.TextBox(app, {
|
||||||
|
@ -728,34 +729,29 @@ class Register {
|
||||||
else this.initSystem(app, Register.FIELDS[type]);
|
else this.initSystem(app, Register.FIELDS[type]);
|
||||||
if (this.expansion != null) {
|
if (this.expansion != null) {
|
||||||
|
|
||||||
// Expand/collapse button
|
// Expand/collapse check box
|
||||||
this.btnExpand.element.setAttribute("aria-expanded", "false" );
|
this.chkExpand.addEventListener("input", e=>this.chkInput(e));
|
||||||
this.btnExpand.element.setAttribute("tabindex" , "0" );
|
this.chkExpand.disabled = false;
|
||||||
this.btnExpand.element.setAttribute("role" , "button");
|
this.chkExpand.element.setAttribute("role", "checkbox");
|
||||||
this.btnExpand.element
|
this.chkExpand.element.setAttribute("tabindex", "0");
|
||||||
|
this.chkExpand.element
|
||||||
.setAttribute("aria-controls", this.expansion.element.id);
|
.setAttribute("aria-controls", this.expansion.element.id);
|
||||||
|
|
||||||
// Expansion area
|
// Expansion area
|
||||||
this.btnExpand.addEventListener("keydown",
|
|
||||||
e=>this.expKeyDown (e));
|
|
||||||
this.btnExpand.addEventListener("pointerdown",
|
|
||||||
e=>this.expPointerDown(e));
|
|
||||||
this.expansion.visible = false;
|
this.expansion.visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update controls
|
// Update controls
|
||||||
|
this.dasmConfigured();
|
||||||
this.refresh();
|
this.refresh();
|
||||||
|
|
||||||
// PSW is initially expanded
|
// PSW is initially expanded
|
||||||
if (type == Register.PSW && key == 5)
|
if (apiType == Core.VB_SYSTEM && apiId == Core.VB_PSW)
|
||||||
this.expanded = true;
|
this.expanded = true;
|
||||||
|
|
||||||
// System registers after PSW are initially hidden
|
// System registers after PSW are initially hidden
|
||||||
else if (key != "pc" && key != 5 && type != Register.PROGRAM) {
|
else if (apiType == Core.VB_SYSTEM)
|
||||||
this.main.style.position = "absolute";
|
this.visible = false;
|
||||||
this.main.style.visibility = "hidden";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expansion controls for program registers
|
// Expansion controls for program registers
|
||||||
|
@ -774,8 +770,7 @@ class Register {
|
||||||
exp.setLabel("{debug.cpu.format}", true);
|
exp.setLabel("{debug.cpu.format}", true);
|
||||||
|
|
||||||
// Radio group
|
// Radio group
|
||||||
let group = new Toolkit.RadioGroup(app);
|
let group = new Toolkit.RadioGroup(app);
|
||||||
this.format = Register.HEX;
|
|
||||||
|
|
||||||
// Hex radio button
|
// Hex radio button
|
||||||
let opt = new Toolkit.Radio(app, {
|
let opt = new Toolkit.Radio(app, {
|
||||||
|
@ -934,21 +929,9 @@ class Register {
|
||||||
|
|
||||||
///////////////////////////// Event Handlers //////////////////////////////
|
///////////////////////////// Event Handlers //////////////////////////////
|
||||||
|
|
||||||
// Expand/collapse button key press
|
// Expand/collapse check box input
|
||||||
expKeyDown(e) {
|
chkInput(e) {
|
||||||
if (
|
this.expanded = this.chkExpand.checked;
|
||||||
!(e.altKey || e.ctrlKey || e.shiftKey) &&
|
|
||||||
(e.key == " " || e.key == "Enter")
|
|
||||||
) this.expanded = !this.expanded;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expand/collapse button pointer down
|
|
||||||
expPointerDown(e) {
|
|
||||||
this.btnExpand.element.focus();
|
|
||||||
if (e.button != 0)
|
|
||||||
return;
|
|
||||||
Toolkit.handle(e);
|
|
||||||
this.expanded = !this.expanded;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Program register format changed
|
// Program register format changed
|
||||||
|
@ -956,7 +939,7 @@ class Register {
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.txtValue.element.classList
|
this.txtValue.element.classList
|
||||||
[format == Register.HEX ? "add" : "remove"]("mono");
|
[format == Register.HEX ? "add" : "remove"]("mono");
|
||||||
this.formatValue();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bit check box input
|
// Bit check box input
|
||||||
|
@ -975,14 +958,16 @@ class Register {
|
||||||
|
|
||||||
// Text box commit
|
// Text box commit
|
||||||
onText(e) {
|
onText(e) {
|
||||||
let oldValue = this.target[this.key];
|
|
||||||
let target = e.target.component;
|
|
||||||
let newValue = parseInt(target.value, target.isHex ? 16 : 10);
|
|
||||||
|
|
||||||
// Cannot change the value
|
// Cannot change the value
|
||||||
if (e.disabled)
|
if (e.disabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Working variables
|
||||||
|
let oldValue = this.target[this.key];
|
||||||
|
let target = e.target.component;
|
||||||
|
let newValue = parseInt(target.value, target.isHex ? 16 : 10);
|
||||||
|
|
||||||
// The provided value is invalid
|
// The provided value is invalid
|
||||||
if (!Number.isInteger(newValue)) {
|
if (!Number.isInteger(newValue)) {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
|
@ -996,54 +981,10 @@ class Register {
|
||||||
|
|
||||||
// Value text box commit
|
// Value text box commit
|
||||||
valAction(e) {
|
valAction(e) {
|
||||||
let text = this.txtValue.value;
|
|
||||||
let value = null;
|
|
||||||
|
|
||||||
Toolkit.handle(e);
|
Toolkit.handle(e);
|
||||||
|
let value = this.parseValue(this.txtValue.value);
|
||||||
// Program register with non-default format
|
|
||||||
if (this.type == Register.PROGRAM && this.format != Register.HEX) {
|
|
||||||
switch (this.format) {
|
|
||||||
case Register.SIGNED:
|
|
||||||
value = parseInt(text);
|
|
||||||
if (
|
|
||||||
!Number.isInteger(value) ||
|
|
||||||
value < -2147483648 ||
|
|
||||||
value > +2147483647
|
|
||||||
) value = null;
|
|
||||||
break;
|
|
||||||
case Register.UNSIGNED:
|
|
||||||
value = parseInt(text);
|
|
||||||
if (
|
|
||||||
!Number.isInteger(value) ||
|
|
||||||
value < 0 ||
|
|
||||||
value > 4294967295
|
|
||||||
) value = null;
|
|
||||||
break;
|
|
||||||
case Register.FLOAT:
|
|
||||||
value = parseFloat(text);
|
|
||||||
value =
|
|
||||||
!Number.isFinite(value) ||
|
|
||||||
value < Debugger.ixf(0xFF7FFFFF) ||
|
|
||||||
value > Debugger.ixf(0x7F7FFFFF)
|
|
||||||
? null : Debugger.fxi(value) >>> 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default hexadecimal format
|
|
||||||
else {
|
|
||||||
value = parseInt(text, 16);
|
|
||||||
if (
|
|
||||||
!Number.isInteger(value) ||
|
|
||||||
value < 0 ||
|
|
||||||
value > 4294967295
|
|
||||||
) value = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply the new value
|
|
||||||
if (value === null)
|
if (value === null)
|
||||||
this.formatValue();
|
this.refresh();
|
||||||
else this.setValue(value);
|
else this.setValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1052,8 +993,7 @@ class Register {
|
||||||
if (e.altKey || e.ctrlKey || e.shiftKey || e.key != "Escape")
|
if (e.altKey || e.ctrlKey || e.shiftKey || e.key != "Escape")
|
||||||
return;
|
return;
|
||||||
Toolkit.handle(e);
|
Toolkit.handle(e);
|
||||||
this.txtValue.value =
|
this.refresh();
|
||||||
this.debug.dasm.hex(this.target[this.key], 8, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1061,34 +1001,45 @@ class Register {
|
||||||
///////////////////////////// Public Methods //////////////////////////////
|
///////////////////////////// Public Methods //////////////////////////////
|
||||||
|
|
||||||
// The expansion area is visible
|
// The expansion area is visible
|
||||||
get expanded() {
|
get expanded() { return this.chkExpand.checked; }
|
||||||
return this.btnExpand.element.getAttribute("aria-expanded") == "true";
|
|
||||||
}
|
|
||||||
set expanded(expanded) {
|
set expanded(expanded) {
|
||||||
expanded = !!expanded;
|
this.chkExpand.checked = expanded;
|
||||||
if (this.expansion == null || expanded == this.expanded)
|
this.setVisible(this.main.visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specify whether the element is visible
|
||||||
|
get visible() { return this.main.visible; }
|
||||||
|
set visible(visible) {
|
||||||
|
visible = !!visible;
|
||||||
|
if (visible == this.main.visible)
|
||||||
return;
|
return;
|
||||||
this.btnExpand.element.setAttribute("aria-expanded", expanded);
|
this.main.element.style[visible ? "removeProperty" : "setProperty"]
|
||||||
this.expansion.visible = expanded;
|
("position", "absolute");
|
||||||
|
this.main.visible = visible;
|
||||||
|
this.setVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////// Package Methods /////////////////////////////
|
///////////////////////////// Package Methods /////////////////////////////
|
||||||
|
|
||||||
|
// Disassembler configuration has changed
|
||||||
|
dasmConfigured() {
|
||||||
|
let names;
|
||||||
|
switch (this.apiType) {
|
||||||
|
case Core.VB_SYSTEM: names = Disassembler.REG_SYSTEM; break;
|
||||||
|
case Core.VB_OTHER : names = Disassembler.REG_OTHER ; break;
|
||||||
|
}
|
||||||
|
this.chkExpand.uiLabel.setText(this.apiType != Core.VB_PROGRAM ?
|
||||||
|
names[this.apiId] : this.dasm.programRegister(this.key));
|
||||||
|
}
|
||||||
|
|
||||||
// Update controls from simulation state
|
// Update controls from simulation state
|
||||||
refresh() {
|
refresh() {
|
||||||
|
|
||||||
// Name label
|
|
||||||
this.label.setText(
|
|
||||||
this.key == "pc" ? "PC" :
|
|
||||||
this.type != Register.PROGRAM ? Disassembler.SYSNAMES[this.key] :
|
|
||||||
this.dasm.programRegister(this.key)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Value text box
|
// Value text box
|
||||||
let value = this.target[this.key];
|
let value = this.target[this.key];
|
||||||
this.formatValue();
|
this.txtValue.value = this.formatValue(value);
|
||||||
|
|
||||||
// Expansion controls
|
// Expansion controls
|
||||||
for (let ctrl of this.controls) {
|
for (let ctrl of this.controls) {
|
||||||
|
@ -1117,45 +1068,74 @@ class Register {
|
||||||
|
|
||||||
///////////////////////////// Private Methods /////////////////////////////
|
///////////////////////////// Private Methods /////////////////////////////
|
||||||
|
|
||||||
// Format the value as a string in the text box
|
// Format a register value as text
|
||||||
formatValue() {
|
formatValue(value) {
|
||||||
let text = "";
|
switch (this.format) {
|
||||||
let value = this.target[this.key];
|
case Register.HEX:
|
||||||
|
return this.debug.hex(value >>> 0, 8, false);
|
||||||
// Program register with non-default format
|
case Register.SIGNED:
|
||||||
if (this.type == Register.PROGRAM && this.format != Register.HEX) {
|
return (value >> 0).toString();
|
||||||
switch (this.format) {
|
case Register.UNSIGNED:
|
||||||
case Register.SIGNED:
|
return (value >>> 0).toString();
|
||||||
text = (value >> 0).toString();
|
case Register.FLOAT:
|
||||||
break;
|
value = Debugger.ixf(value);
|
||||||
case Register.UNSIGNED:
|
if (Number.isFinite(value)) {
|
||||||
text = (value >>> 0).toString();
|
let text = value.toFixed(100);
|
||||||
break;
|
if (/[^0-9\-\.]/.test(text))
|
||||||
case Register.FLOAT:
|
text = value.toFixed(6);
|
||||||
value = Debugger.ixf(value);
|
if (text.indexOf(".") != -1) {
|
||||||
if (Number.isFinite(value)) {
|
text = text.replace(/0+$/, "")
|
||||||
text = value.toFixed(100);
|
.replace(/\.$/, ".0");
|
||||||
if (/[^0-9\-\.]/.test(text))
|
} else text += ".0";
|
||||||
text = value.toFixed(6);
|
return text;
|
||||||
if (text.indexOf(".") != -1) {
|
}
|
||||||
text = text.replace(/0+$/, "")
|
if (!Number.isNaN(value)) {
|
||||||
.replace(/\.$/, ".0");
|
return (
|
||||||
} else text += ".0";
|
(value == Number.NEGATIVE_INFINITY ? "-" : "") +
|
||||||
} else if (!Number.isNaN(value)) {
|
this.debug.app.localize("{debug.cpu.infinity}")
|
||||||
text =
|
);
|
||||||
(value == Number.NEGATIVE_INFINITY ? "-" : "") +
|
}
|
||||||
this.debug.app.localize("{debug.cpu.infinity}")
|
return "NaN";
|
||||||
;
|
|
||||||
} else text = "NaN";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Default hexadecimal format
|
// Parse text as a register value
|
||||||
else text = this.dasm.hex(value >>> 0, 8, false);
|
parseValue(value) {
|
||||||
|
switch (this.format) {
|
||||||
// Update the text
|
case Register.HEX:
|
||||||
this.txtValue.value = text;
|
value = parseInt(value, 16);
|
||||||
|
return (
|
||||||
|
!Number.isInteger(value) ||
|
||||||
|
value < 0 ||
|
||||||
|
value > 0xFFFFFFFF ?
|
||||||
|
null : value
|
||||||
|
);
|
||||||
|
case Register.SIGNED:
|
||||||
|
value = parseInt(value);
|
||||||
|
return (
|
||||||
|
!Number.isInteger(value) ||
|
||||||
|
value < -0x80000000 ||
|
||||||
|
value > 0x7FFFFFFF ?
|
||||||
|
null : value
|
||||||
|
);
|
||||||
|
case Register.UNSIGNED:
|
||||||
|
value = parseInt(value);
|
||||||
|
return (
|
||||||
|
!Number.isInteger(value) ||
|
||||||
|
value < 0 ||
|
||||||
|
value > 0xFFFFFFFF ?
|
||||||
|
null : value
|
||||||
|
);
|
||||||
|
case Register.FLOAT:
|
||||||
|
value = parseFloat(value);
|
||||||
|
return (
|
||||||
|
!Number.isFinite(value) ||
|
||||||
|
value < Debugger.ixf(0xFF7FFFFF) ||
|
||||||
|
value > Debugger.ixf(0x7F7FFFFF)
|
||||||
|
? null : Debugger.fxi(value) >>> 0);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specify a new register value
|
// Specify a new register value
|
||||||
|
@ -1175,8 +1155,13 @@ class Register {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// Update visibility for expansion controls
|
||||||
|
setVisible(visible) {
|
||||||
|
if (this.expansion)
|
||||||
|
this.expansion.visible = visible && !!this.expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1191,20 +1176,20 @@ class RegisterPane extends Toolkit.SplitPane {
|
||||||
|
|
||||||
// System register templates
|
// System register templates
|
||||||
static SYSTEMS = [
|
static SYSTEMS = [
|
||||||
[["pc" ],Register.PLAIN,Core.VB_OTHER ,Core.VB_PC ],
|
[ "pc" , Register.PLAIN, Core.VB_OTHER , Core.VB_PC ],
|
||||||
[["system",Core.VB_PSW ],Register.PSW ,Core.VB_SYSTEM,Core.VB_PSW ],
|
[ Core.VB_PSW , Register.PSW , Core.VB_SYSTEM, Core.VB_PSW ],
|
||||||
[["system",Core.VB_ADTRE],Register.PLAIN,Core.VB_SYSTEM,Core.VB_ADTRE],
|
[ Core.VB_ADTRE, Register.PLAIN, Core.VB_SYSTEM, Core.VB_ADTRE ],
|
||||||
[["system",Core.VB_CHCW ],Register.CHCW ,Core.VB_SYSTEM,Core.VB_CHCW ],
|
[ Core.VB_CHCW , Register.CHCW , Core.VB_SYSTEM, Core.VB_CHCW ],
|
||||||
[["system",Core.VB_ECR ],Register.ECR ,Core.VB_SYSTEM,Core.VB_ECR ],
|
[ Core.VB_ECR , Register.ECR , Core.VB_SYSTEM, Core.VB_ECR ],
|
||||||
[["system",Core.VB_EIPC ],Register.PLAIN,Core.VB_SYSTEM,Core.VB_EIPC ],
|
[ Core.VB_EIPC , Register.PLAIN, Core.VB_SYSTEM, Core.VB_EIPC ],
|
||||||
[["system",Core.VB_EIPSW],Register.PSW ,Core.VB_SYSTEM,Core.VB_EIPSW],
|
[ Core.VB_EIPSW, Register.PSW , Core.VB_SYSTEM, Core.VB_EIPSW ],
|
||||||
[["system",Core.VB_FEPC ],Register.PLAIN,Core.VB_SYSTEM,Core.VB_FEPC ],
|
[ Core.VB_FEPC , Register.PLAIN, Core.VB_SYSTEM, Core.VB_FEPC ],
|
||||||
[["system",Core.VB_FEPSW],Register.PSW ,Core.VB_SYSTEM,Core.VB_FEPSW],
|
[ Core.VB_FEPSW, Register.PSW , Core.VB_SYSTEM, Core.VB_FEPSW ],
|
||||||
[["system",Core.VB_PIR ],Register.PIR ,Core.VB_SYSTEM,Core.VB_PIR ],
|
[ Core.VB_PIR , Register.PIR , Core.VB_SYSTEM, Core.VB_PIR ],
|
||||||
[["system",Core.VB_TKCW ],Register.TKCW ,Core.VB_SYSTEM,Core.VB_TKCW ],
|
[ Core.VB_TKCW , Register.TKCW , Core.VB_SYSTEM, Core.VB_TKCW ],
|
||||||
[["system",29 ],Register.PLAIN,Core.VB_SYSTEM,29 ],
|
[ 29 , Register.PLAIN, Core.VB_SYSTEM, 29 ],
|
||||||
[["system",30 ],Register.PLAIN,Core.VB_SYSTEM,30 ],
|
[ 30 , Register.PLAIN, Core.VB_SYSTEM, 30 ],
|
||||||
[["system",31 ],Register.PLAIN,Core.VB_SYSTEM,31 ]
|
[ 31 , Register.PLAIN, Core.VB_SYSTEM, 31 ]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
@ -1222,13 +1207,13 @@ class RegisterPane extends Toolkit.SplitPane {
|
||||||
// Configure instance fields
|
// Configure instance fields
|
||||||
this.cpu = cpu;
|
this.cpu = cpu;
|
||||||
this.list = [];
|
this.list = [];
|
||||||
this.pc = 0xFFFFFFF0;
|
|
||||||
this.program = new Array(32);
|
|
||||||
this.pending = false;
|
this.pending = false;
|
||||||
this.subscription = [ 0, cpu.index, "cpu", "registers", "refresh" ],
|
this.subscription = [ 0, cpu.index, "cpu", "registers", "refresh" ],
|
||||||
this.system = new Array(32);
|
|
||||||
|
|
||||||
// Initialize regsiters
|
// Initialize regsiters
|
||||||
|
this.pc = 0xFFFFFFF0;
|
||||||
|
this.program = new Array(32);
|
||||||
|
this.system = new Array(32);
|
||||||
for (let x = 0; x < 32; x++)
|
for (let x = 0; x < 32; x++)
|
||||||
this.program[x] = this.system[x] = 0;
|
this.program[x] = this.system[x] = 0;
|
||||||
|
|
||||||
|
@ -1245,8 +1230,8 @@ class RegisterPane extends Toolkit.SplitPane {
|
||||||
// System registers scroll pane
|
// System registers scroll pane
|
||||||
this.scrSystem = new Toolkit.ScrollPane(cpu.debug.app, {
|
this.scrSystem = new Toolkit.ScrollPane(cpu.debug.app, {
|
||||||
class : "tk scroll-pane scr-system",
|
class : "tk scroll-pane scr-system",
|
||||||
overflowX: "auto",
|
overflowX: "hidden",
|
||||||
overflowY: "auto",
|
overflowY: "scroll",
|
||||||
view : this.lstSystem,
|
view : this.lstSystem,
|
||||||
style : {
|
style : {
|
||||||
position: "relative"
|
position: "relative"
|
||||||
|
@ -1267,8 +1252,8 @@ class RegisterPane extends Toolkit.SplitPane {
|
||||||
// Program registers scroll pane
|
// Program registers scroll pane
|
||||||
this.scrProgram = new Toolkit.ScrollPane(cpu.debug.app, {
|
this.scrProgram = new Toolkit.ScrollPane(cpu.debug.app, {
|
||||||
class : "tk scroll-pane scr-program",
|
class : "tk scroll-pane scr-program",
|
||||||
overflowX: "auto",
|
overflowX: "hidden",
|
||||||
overflowY: "auto",
|
overflowY: "scroll",
|
||||||
view : this.lstProgram
|
view : this.lstProgram
|
||||||
});
|
});
|
||||||
this.secondary = this.scrProgram;
|
this.secondary = this.scrProgram;
|
||||||
|
@ -1278,7 +1263,7 @@ class RegisterPane extends Toolkit.SplitPane {
|
||||||
this.addRegister(new Register(this, ... sys));
|
this.addRegister(new Register(this, ... sys));
|
||||||
for (let x = 0; x < 32; x++) {
|
for (let x = 0; x < 32; x++) {
|
||||||
this.addRegister(new Register(this,
|
this.addRegister(new Register(this,
|
||||||
[ "program", x ], Register.PROGRAM, Core.VB_PROGRAM, x));
|
x, Register.PROGRAM, Core.VB_PROGRAM, x));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value text box measurer
|
// Value text box measurer
|
||||||
|
@ -1298,7 +1283,7 @@ class RegisterPane extends Toolkit.SplitPane {
|
||||||
// Monitor the bounds of the register names column
|
// Monitor the bounds of the register names column
|
||||||
let resizer = new ResizeObserver(()=>this.regResize());
|
let resizer = new ResizeObserver(()=>this.regResize());
|
||||||
for (let reg of this.list)
|
for (let reg of this.list)
|
||||||
resizer.observe(reg.label.element);
|
resizer.observe(reg.chkExpand.element);
|
||||||
|
|
||||||
// Monitor the bounds of the value text boxes
|
// Monitor the bounds of the value text boxes
|
||||||
this.list[0].txtValue.addEventListener("resize", e=>this.valResize(e));
|
this.list[0].txtValue.addEventListener("resize", e=>this.valResize(e));
|
||||||
|
@ -1330,7 +1315,7 @@ class RegisterPane extends Toolkit.SplitPane {
|
||||||
|
|
||||||
// Measure the widths of all labels
|
// Measure the widths of all labels
|
||||||
for (let x = 0; x < this.list.length; x++) {
|
for (let x = 0; x < this.list.length; x++) {
|
||||||
widths[x] = Math.ceil(this.list[x].label.element
|
widths[x] = Math.ceil(this.list[x].chkExpand.element
|
||||||
.getBoundingClientRect().width);
|
.getBoundingClientRect().width);
|
||||||
max = Math.max(max, widths[x]);
|
max = Math.max(max, widths[x]);
|
||||||
}
|
}
|
||||||
|
@ -1338,7 +1323,7 @@ class RegisterPane extends Toolkit.SplitPane {
|
||||||
// Ensure all labels share the same maximum width
|
// Ensure all labels share the same maximum width
|
||||||
for (let x = 0; x < this.list.length; x++) {
|
for (let x = 0; x < this.list.length; x++) {
|
||||||
if (widths[x] < max)
|
if (widths[x] < max)
|
||||||
this.list[x].label.element.style.minWidth = max + "px";
|
this.list[x].chkExpand.element.style.minWidth = max + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1380,9 +1365,9 @@ class RegisterPane extends Toolkit.SplitPane {
|
||||||
|
|
||||||
// Wait for a transaction to complete
|
// Wait for a transaction to complete
|
||||||
if (promise != null) {
|
if (promise != null) {
|
||||||
this.pending= true;
|
this.pending = true;
|
||||||
data = await promise;
|
data = await promise;
|
||||||
promise = null;
|
promise = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initiate a new transaction
|
// Initiate a new transaction
|
||||||
|
@ -1410,17 +1395,19 @@ class RegisterPane extends Toolkit.SplitPane {
|
||||||
|
|
||||||
// Retrieve the desired dimensions of the system registers list
|
// Retrieve the desired dimensions of the system registers list
|
||||||
let bounds = this.scrSystem.element.getBoundingClientRect();
|
let bounds = this.scrSystem.element.getBoundingClientRect();
|
||||||
for (let reg of this.list) {
|
|
||||||
let style = reg.main.style;
|
// Show all hidden system registers
|
||||||
if (style.visibility) {
|
for (let reg of this.list)
|
||||||
style.removeProperty("position");
|
reg.visible = true;
|
||||||
style.removeProperty("visibility");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare the initial dimensions of the register lists
|
// Prepare the initial dimensions of the register lists
|
||||||
this .element.style.width = Math.ceil(bounds.width ) + "px";
|
this .element.style.width = Math.ceil(bounds.width ) + "px";
|
||||||
this.scrSystem.element.style.height = Math.ceil(bounds.height) + "px";
|
this.scrSystem .element.style.height = Math.ceil(bounds.height) + "px";
|
||||||
|
this.scrSystem .overflowX = "auto";
|
||||||
|
this.scrSystem .overflowY = "auto";
|
||||||
|
this.scrProgram.overflowX = "auto";
|
||||||
|
this.scrProgram.overflowY = "auto";
|
||||||
|
|
||||||
this.fetch();
|
this.fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,12 @@ class Debugger {
|
||||||
|
|
||||||
///////////////////////////// Package Methods /////////////////////////////
|
///////////////////////////// Package Methods /////////////////////////////
|
||||||
|
|
||||||
|
// Disassembler configuration has changed
|
||||||
|
dasmConfigured() {
|
||||||
|
this.cpu .dasmConfigured();
|
||||||
|
this.memory.dasmConfigured();
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure PC is visible in the disassembler
|
// Ensure PC is visible in the disassembler
|
||||||
followPC(pc = null) {
|
followPC(pc = null) {
|
||||||
this.cpu.disassembler.followPC(pc);
|
this.cpu.disassembler.followPC(pc);
|
||||||
|
|
|
@ -130,17 +130,7 @@ class Memory extends Toolkit.Window {
|
||||||
hexKeyDown(e) {
|
hexKeyDown(e) {
|
||||||
|
|
||||||
// Error checking
|
// Error checking
|
||||||
if (e.altKey)
|
if (e.altKey || e.ctrlKey)
|
||||||
return;
|
|
||||||
|
|
||||||
// Processing by key, Ctrl pressed
|
|
||||||
if (e.ctrlKey) switch (e.key) {
|
|
||||||
case "g": case "G":
|
|
||||||
Toolkit.handle(e);
|
|
||||||
this.goto();
|
|
||||||
return;
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Processing by key, scroll lock off
|
// Processing by key, scroll lock off
|
||||||
if (!e.getModifierState("ScrollLock")) switch (e.key) {
|
if (!e.getModifierState("ScrollLock")) switch (e.key) {
|
||||||
|
@ -352,6 +342,23 @@ class Memory extends Toolkit.Window {
|
||||||
this.fetch();
|
this.fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Window key press
|
||||||
|
onKeyDown(e) {
|
||||||
|
super.onKeyDown(e);
|
||||||
|
|
||||||
|
// Error checking
|
||||||
|
if (e.altKey || !e.ctrlKey || e.shiftKey)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Processing by key
|
||||||
|
switch (e.key) {
|
||||||
|
case "g": case "G": this.goto(); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toolkit.handle(e);
|
||||||
|
}
|
||||||
|
|
||||||
// Window visibility
|
// Window visibility
|
||||||
onVisibility(e) {
|
onVisibility(e) {
|
||||||
this.shown = this.shown || e.visible;
|
this.shown = this.shown || e.visible;
|
||||||
|
@ -364,6 +371,11 @@ class Memory extends Toolkit.Window {
|
||||||
|
|
||||||
///////////////////////////// Package Methods /////////////////////////////
|
///////////////////////////// Package Methods /////////////////////////////
|
||||||
|
|
||||||
|
// Disassembler configuration has changed
|
||||||
|
dasmConfigured() {
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
// Prompt the user to navigate to a new editing address
|
// Prompt the user to navigate to a new editing address
|
||||||
goto() {
|
goto() {
|
||||||
|
|
||||||
|
@ -383,6 +395,7 @@ class Memory extends Toolkit.Window {
|
||||||
this.commit();
|
this.commit();
|
||||||
|
|
||||||
// Navigate to the given address
|
// Navigate to the given address
|
||||||
|
this.hexEditor.focus();
|
||||||
this.setEditAddress(addr, 1/3);
|
this.setEditAddress(addr, 1/3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 2.6458 2.6458" version="1.1">
|
||||||
|
<path style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.13229;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" d="m 1.05832,1.653625 1.3229,-1.3229 v 0.66145 l -1.3229,1.3229 -0.79374,-0.79374 v -0.66145 z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 484 B |
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="11" height="11" viewBox="0 0 2.9104166 2.9104168" version="1.1">
|
||||||
|
<rect style="fill:#000000;stroke-width:0.264583;stroke-linecap:square" width="0.26458332" height="1.3229167" x="1.8555599" y="-1.1941016" transform="rotate(60)" />
|
||||||
|
<rect style="fill:#000000;stroke-width:0.264583;stroke-linecap:square" width="1.3229167" height="0.26458332" x="1.3263932" y="0.40035158" transform="rotate(30)" />
|
||||||
|
<rect style="fill:#000000;stroke-width:0.264583;stroke-linecap:square" width="0.26458332" height="1.3229167" x="-1.5875" y="0.79374999" transform="scale(-1,1)" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 710 B |
|
@ -130,6 +130,12 @@ table.tk {
|
||||||
background: currentcolor;
|
background: currentcolor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tk.checkbox[aria-checked="mixed"] .box:before {
|
||||||
|
background : currentcolor;
|
||||||
|
mask : /**/url("./check2.svg") center no-repeat;
|
||||||
|
-webkit-mask: /**/url("./check2.svg") center no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
.tk.checkbox.pushed .box:before {
|
.tk.checkbox.pushed .box:before {
|
||||||
background: var(--tk-control-shadow);
|
background: var(--tk-control-shadow);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tk.window.cpu .disassembler .addr {
|
.tk.window.cpu .disassembler .address {
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,13 +40,13 @@
|
||||||
text-align : center;
|
text-align : center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tk.window.cpu .disassembler .ops {
|
.tk.window.cpu .disassembler .operands {
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tk.window.cpu .disassembler .byte.b0,
|
.tk.window.cpu .disassembler .byte.b0,
|
||||||
.tk.window.cpu .disassembler .inst,
|
.tk.window.cpu .disassembler .mnemonic,
|
||||||
.tk.window.cpu .disassembler .ops {
|
.tk.window.cpu .disassembler .operands {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,33 +81,35 @@
|
||||||
padding-bottom: 1px;
|
padding-bottom: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tk.window.cpu .registers .icon {
|
.tk.window.cpu .registers .expand .box {
|
||||||
|
border : none;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
margin : 0 1px 1px 0;
|
margin : 0 1px 0 0;
|
||||||
|
}
|
||||||
|
.tk.window.cpu .registers .expand .box:before {
|
||||||
|
background: transparent;
|
||||||
|
content : "";
|
||||||
|
display : block;
|
||||||
|
height : 11px;
|
||||||
|
width : 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tk.window.cpu .registers .expand:focus .icon {
|
.tk.window.cpu .registers .expand[role="checkbox"] .box:before {
|
||||||
background: var(--tk-control-active);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tk.window.cpu .registers .expand .icon:before {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
height : 11px;
|
|
||||||
width : 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tk.window.cpu .registers .expand[aria-expanded="false"] .icon:before {
|
|
||||||
background : currentcolor;
|
background : currentcolor;
|
||||||
mask : /**/url("./expand.svg") center no-repeat;
|
mask : /**/url("./expand.svg") center no-repeat;
|
||||||
-webkit-mask: /**/url("./expand.svg") center no-repeat;
|
-webkit-mask: /**/url("./expand.svg") center no-repeat;
|
||||||
}
|
}
|
||||||
|
.tk.window.cpu .registers .expand[aria-checked="true"] .box:before {
|
||||||
.tk.window.cpu .registers .expand[aria-expanded="true"] .icon:before {
|
|
||||||
background : currentcolor;
|
background : currentcolor;
|
||||||
mask : /**/url("./collapse.svg") center no-repeat;
|
mask : /**/url("./collapse.svg") center no-repeat;
|
||||||
-webkit-mask: /**/url("./collapse.svg") center no-repeat;
|
-webkit-mask: /**/url("./collapse.svg") center no-repeat;
|
||||||
}
|
}
|
||||||
|
.tk.window.cpu .registers .expand:focus .box {
|
||||||
|
background: var(--tk-control-active);
|
||||||
|
}
|
||||||
|
.tk.window.cpu .registers .main {
|
||||||
|
column-gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.tk.window.cpu .registers .expansion {
|
.tk.window.cpu .registers .expansion {
|
||||||
gap : 1px 1em;
|
gap : 1px 1em;
|
||||||
|
|
|
@ -33,7 +33,9 @@ class Checkbox extends Toolkit.Component {
|
||||||
this.add(this.uiLabel);
|
this.add(this.uiLabel);
|
||||||
|
|
||||||
// Configure options
|
// Configure options
|
||||||
this.checked = options.checked;
|
this.checked = options.checked;
|
||||||
|
this.disabled = !!options.disabled;
|
||||||
|
this.instant = !!options.instant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,6 +67,12 @@ class Checkbox extends Toolkit.Component {
|
||||||
|
|
||||||
// Begin dragging
|
// Begin dragging
|
||||||
this.element.setPointerCapture(e.pointerId);
|
this.element.setPointerCapture(e.pointerId);
|
||||||
|
|
||||||
|
// Use instant activation
|
||||||
|
if (this.instant)
|
||||||
|
return this.onPointerUp(e);
|
||||||
|
|
||||||
|
// Do not use instant activation
|
||||||
this.element.classList.add("pushed");
|
this.element.classList.add("pushed");
|
||||||
Toolkit.handle(e);
|
Toolkit.handle(e);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +103,7 @@ class Checkbox extends Toolkit.Component {
|
||||||
|
|
||||||
// Activate the check box if applicable
|
// Activate the check box if applicable
|
||||||
if (this.isWithin(e))
|
if (this.isWithin(e))
|
||||||
this.setChecked(!this.checked);
|
this.setChecked(this.checked !== true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,9 +111,12 @@ class Checkbox extends Toolkit.Component {
|
||||||
///////////////////////////// Public Methods //////////////////////////////
|
///////////////////////////// Public Methods //////////////////////////////
|
||||||
|
|
||||||
// The check box is checked
|
// The check box is checked
|
||||||
get checked() { return this.element.getAttribute("aria-checked")=="true"; }
|
get checked() {
|
||||||
|
let ret = this.element.getAttribute("aria-checked");
|
||||||
|
return ret == "mixed" ? ret : ret == "true";
|
||||||
|
}
|
||||||
set checked(checked) {
|
set checked(checked) {
|
||||||
checked = !!checked;
|
checked = checked == "mixed" ? checked : !!checked;
|
||||||
if (checked == this.checked)
|
if (checked == this.checked)
|
||||||
return;
|
return;
|
||||||
this.element.setAttribute("aria-checked", checked);
|
this.element.setAttribute("aria-checked", checked);
|
||||||
|
@ -135,8 +146,10 @@ class Checkbox extends Toolkit.Component {
|
||||||
checked = !!checked;
|
checked = !!checked;
|
||||||
if (checked == this.checked)
|
if (checked == this.checked)
|
||||||
return;
|
return;
|
||||||
|
let previous = this.checked
|
||||||
this.checked = checked;
|
this.checked = checked;
|
||||||
this.element.dispatchEvent(new Event("input"));
|
this.element.dispatchEvent(
|
||||||
|
Object.assign(new Event("input"), { previous: previous }));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,8 @@ class TextBox extends Toolkit.Component {
|
||||||
onKeyDown(e) {
|
onKeyDown(e) {
|
||||||
if (e.altKey || e.ctrlKey || e.shiftKey || this.disabled)
|
if (e.altKey || e.ctrlKey || e.shiftKey || this.disabled)
|
||||||
return;
|
return;
|
||||||
e.stopPropagation();
|
if (e.key != "Tab")
|
||||||
|
e.stopPropagation();
|
||||||
if (e.key == "Enter")
|
if (e.key == "Enter")
|
||||||
this.commit();
|
this.commit();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue