Add support to timer and timer interrupts

Signed-off-by: Junjie Mao <junjie.mao@enight.me>
This commit is contained in:
Junjie Mao 2015-09-15 15:21:15 +08:00
parent 3536e7e27b
commit bbbbf66ebb
4 changed files with 67 additions and 30 deletions

View File

@ -64,4 +64,4 @@
.codelabel-line a {
cursor: pointer;
}
}

View File

@ -35,7 +35,7 @@
<textarea id="sourceCode"
class="form-control source-code"
style="margin-bottom:5px;"
rows="35"
rows="30"
tab-support
select-line
ng-model="code"></textarea>
@ -52,11 +52,10 @@
<h4 class="panel-title">CPU & Memory</h4>
</div>
<div class="panel-body">
<p class="text-muted">Registers</p>
<p class="text-muted">General Registers</p>
<table class="table table-condensed table-striped">
<thead>
<tr>
<th style="text-align:center">IP</th>
<th style="text-align:center">0</th>
<th style="text-align:center">1</th>
<th style="text-align:center">2</th>
@ -77,7 +76,6 @@
</thead>
<tbody>
<tr style="text-align:center;" class="source-code">
<td><div style="margin:auto;" class="marker marker-ip"><small>{{ cpu.ip | number:displayHex }}</small></div></td>
<td><div style="margin:auto;" ng-class="displayA && 'marker marker-a'"><small>{{ cpu.gpr[0] | number:displayHex }}</small></div></td>
<td><div style="margin:auto;" ng-class="displayB && 'marker marker-b'"><small>{{ cpu.gpr[1] | number:displayHex }}</small></div></td>
<td><div style="margin:auto;" ng-class="displayC && 'marker marker-c'"><small>{{ cpu.gpr[2] | number:displayHex }}</small></div></td>
@ -95,7 +93,20 @@
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[14] | number:displayHex }}</small></div></td>
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[15] | number:displayHex }}</small></div></td>
</tr>
</tbody>
</tbody>
</table>
<p class="text-muted">Other Registers</p>
<table class="table table-condensed table-striped">
<tbody>
<tr>
<td style="text-align:left">IP <font color="E81F1F">{{ cpu.status }}</font> </td>
<td style="text-align:center;" class="source-code"><div style="margin:auto;" class="marker marker-ip"><small>{{ cpu.ip | number:displayHex }}</small></div></td>
</tr>
<tr>
<td style="text-align:left">Timer Countdown</td>
<td style="text-align:center;" class="source-code"><div style="margin:auto;"><small>{{ cpu.countdown | number:displayHex }}</small></div></td>
</tr>
</tbody>
</table>
<p class="text-muted">RAM</p>
<div style="width:29em;" class="source-code">

View File

@ -17,67 +17,93 @@ app.service('cpu', ['opcodes', 'memory', function(opcodes, memory) {
}
};
var readReg = function(id) {
return self.gpr[id];
};
var writeReg = function(id, val) {
self.gpr[id] = val;
if (id == 15) {
self.updateTimer = true;
if (val > 0) {
self.countdown = val;
} else {
self.countdown = 0;
}
}
};
self.updateTimer = false;
self.status = '';
var instr = [memory.load(self.ip), memory.load(self.ip + 1)];
var opcode = instr[0] >> 4;
var regDest = instr[0] & 0x0F, regSource1 = instr[1] >> 4, regSource2 = instr[1] & 0x0F;
var mem = instr[1], num = instr[1];
self.ip = self.ip + 2;
self.ip = (self.ip + 2) & 0xFF;
switch(opcode) {
case opcodes.NONE:
self.ip = self.ip - 2;
return false; // Abort step
case opcodes.LOAD_FROM_MEMORY:
self.gpr[regDest] = memory.load(mem);
writeReg(regDest, memory.load(mem));
break;
case opcodes.LOAD_WITH_CONSTANT:
self.gpr[regDest] = num;
writeReg(regDest, num);
break;
case opcodes.STORE_TO_MEMORY:
memory.store(mem, self.gpr[regDest]);
memory.store(mem, readReg(regDest));
break;
case opcodes.MOVE:
self.gpr[regSource2] = self.gpr[regSource1];
writeReg(regSource2, readReg(regSource1));
break;
case opcodes.ADD_INT:
self.gpr[regDest] = (self.gpr[regSource1] + self.gpr[regSource2]) & 0xFF;
writeReg(regDest, (readReg(regSource1) + readReg(regSource2)) & 0xFF);
break;
case opcodes.ADD_FLOAT:
// TODO
break;
case opcodes.OR:
self.gpr[regDest] = self.gpr[regSource1] | self.gpr[regSource2];
writeReg(regDest, readReg(regSource1) | readReg(regSource2));
break;
case opcodes.AND:
self.gpr[regDest] = self.gpr[regSource1] & self.gpr[regSource2];
writeReg(regDest, readReg(regSource1) & readReg(regSource2));
break;
case opcodes.XOR:
self.gpr[regDest] = self.gpr[regSource1] ^ self.gpr[regSource2];
writeReg(regDest, readReg(regSource1) ^ readReg(regSource2));
break;
case opcodes.ROTATE:
var delta = num % 8, val = self.gpr[regDest];
self.gpr[regDest] = (val >> delta) + ((val & ((1 << delta) - 1)) << (8 - delta));
var delta = num % 8, val = readReg(regDest);
writeReg(regDest, (val >> delta) + ((val & ((1 << delta) - 1)) << (8 - delta)));
break;
case opcodes.JUMP_IF_EQUAL:
if (self.gpr[regDest] == self.gpr[0]) {
if (readReg(regDest) == readReg(0)) {
self.ip = mem;
}
break;
case opcodes.HALT:
self.ip = self.ip - 2;
self.ip = (self.ip - 2) & 0xFF;
return false;
case opcodes.LOAD_FROM_POINTER:
self.gpr[regDest] = memory.load(self.gpr[regSource2]);
writeReg(regDest, memory.load(readReg(regSource2)));
break;
case opcodes.STORE_TO_POINTER:
memory.store(self.gpr[regSource2], self.gpr[regDest]);
memory.store(readReg(regSource2), readReg(regDest));
break;
case opcodes.JUMP_IF_LESS:
if (byteToNumber(self.gpr[regDest]) < byteToNumber(self.gpr[0])) { // TODO
if (byteToNumber(readReg(regDest)) < byteToNumber(readReg(0))) {
self.ip = mem;
}
break;
}
if (self.countdown > 0 && !self.updateTimer) {
self.countdown -= 1;
if (self.countdown === 0) {
memory.store(0xFE, self.ip);
self.ip = 0x80;
self.countdown = readReg(15);
self.status = '(Interrupted!)';
}
}
return true;
},
reset: function() {
@ -85,6 +111,10 @@ app.service('cpu', ['opcodes', 'memory', function(opcodes, memory) {
self.gpr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
self.ip = 0;
self.status = '';
self.countdown = 0;
self.updateTimer = false;
}
};

View File

@ -150,12 +150,8 @@ app.controller('Ctrl', ['$document', '$scope', '$timeout', 'cpu', 'memory', 'ass
};
$scope.getMemoryCellCss = function (index) {
if (index >= $scope.outputStartIndex) {
return 'output-bg';
} else if ($scope.isInstruction(index)) {
if ($scope.isInstruction(index)) {
return 'instr-bg';
} else if (index > cpu.sp && index <= cpu.maxSP) {
return 'stack-bg';
} else {
return '';
}