Bugfixes and more examples

Signed-off-by: Junjie Mao <junjie.mao@enight.me>
This commit is contained in:
Junjie Mao 2015-09-17 16:11:08 +08:00
parent 05cb80c0b1
commit fedc22763e
10 changed files with 425 additions and 29 deletions

View File

@ -1,4 +1,4 @@
; c = a + b
; 2.1 c = a + b
.data@0x6C:
DB 0x01

View File

@ -1 +1,90 @@
; TODO Time-sharing between two processes
; 3.1 Time-sharing Between Two Processes
.programA@0x00:
LOADB R0, 0x00
LOADB R1, 0x00
LOADB R2, 0x01
loop_a:
ADDI R0, R0, R1
ADDI R1, R1, R2
JUMP R0, loop_a
.programB@0x40:
LOADB R0, 0x00
LOADB R1, 0x00
LOADB R2, 0x58
loop_b:
ADDF R0, R0, R1
ADDF R1, R1, R2
JUMP R0, loop_b
interrupt_handler@0x80:
STOREM R0, tmp2
LOADM R0, saved_regs
STOREM R0, tmp1
LOADM R0, tmp2
STOREM R0, saved_regs
LOADM R0, saved_pc
STOREM R0, jmp+1
LOADM R0, interrupted_pc
STOREM R0, saved_pc
MOVE R0, R1
LOADM R1, saved_regs+1
STOREM R0, saved_regs+1
MOVE R0, R2
LOADM R2, saved_regs+2
STOREM R0, saved_regs+2
MOVE R0, R3
LOADM R3, saved_regs+3
STOREM R0, saved_regs+3
MOVE R0, R4
LOADM R4, saved_regs+4
STOREM R0, saved_regs+4
MOVE R0, R5
LOADM R5, saved_regs+5
STOREM R0, saved_regs+5
MOVE R0, R6
LOADM R6, saved_regs+6
STOREM R0, saved_regs+6
MOVE R0, R7
LOADM R7, saved_regs+7
STOREM R0, saved_regs+7
MOVE R0, R8
LOADM R8, saved_regs+8
STOREM R0, saved_regs+8
MOVE R0, R9
LOADM R9, saved_regs+9
STOREM R0, saved_regs+9
MOVE R0, RA
LOADM RA, saved_regs+10
STOREM R0, saved_regs+10
MOVE R0, RB
LOADM RB, saved_regs+11
STOREM R0, saved_regs+11
MOVE R0, RC
LOADM RC, saved_regs+12
STOREM R0, saved_regs+12
MOVE R0, RD
LOADM RD, saved_regs+13
STOREM R0, saved_regs+13
MOVE R0, RE
LOADM RE, saved_regs+14
STOREM R0, saved_regs+14
LOADM R0, tmp1
jmp: JUMP R0, 00
saved_regs@0xEA:
saved_pc@0xF9:
tmp1@0xFA:
tmp2@0xFB:
interrupted_pc@0xFD:
.entry@0xF0:
LOADB RF, 0x80
LOADB R0, 0x40
STOREM R0, saved_pc
JUMP R0, 0x00

View File

@ -0,0 +1,46 @@
; 5.1 Insertion Sort
;
; The list of numbers to be sorted is stored from .data
.entry:
;; Initialize some constants:
LOADB R1, 0x01
LOADB R2, 0xFF
LOADB R3, .data+1 ;; loop variable of the outer loop
outer_loop:
LOADB R0, .data_end
JUMP R3, outer_loop_end
LOADP R4, R3 ;; the pivot
MOVE R5, R3 ;; loop variable of the outer loop
inner_loop:
LOADB R0, .data
JUMP R5, inner_loop_end
MOVE R6, R5
ADDI R5, R5, R2
LOADP R0, R5
JUMPL R4, tmp1
ADDI R5, R5, R1
JUMP R0, inner_loop_end
tmp1: STOREP R0, R6
JUMP R0, inner_loop
inner_loop_end:
STOREP R4, R5
ADDI R3, R3, R1
JUMP R0, outer_loop
outer_loop_end:
HALT
.data@0x40:
DB 0x20
DB 0x34
DB 0xDE
DB 0x65
DB 0xAA
DB 0xC0
DB 0x00
DB 0xF1
.data_end:

View File

@ -0,0 +1,147 @@
; 5.2 Binary Search
;
; This example implements the following function:
;
; int list[];
; int binary_search(int begin, int end, int target) {
; if (end < begin)
; return -1;
; int mid = begin + (end - begin) / 2;
; int mid_val = list[mid];
; if (target == mid_val)
; return mid;
; else if (target < mid_val)
; return binary_search(begin, mid - 1, target);
; else
; return binary_search(mid + 1, end, target);
; }
;
; which will search for 'target' in the range [begin, end]
; of the global list. The function returns the index of the
; element if 'target' is found in the list. Otherwise it
; returns -1.
.entry:
;; initialize some constants
LOADB R1, 0x01
LOADB R2, 0xFF
;; initialize the stack
LOADB RE, .stack
ADDI RE, RE, R2
;; 3rd parameter 'target' = 0x34
ADDI RE, RE, R2
LOADB R3, 0x34
STOREP R3, RE
;; 2nd parameter 'end' = .data_end - .data - 1
ADDI RE, RE, R2
LOADB R3, .data
XOR R3, R3, R2
LOADB R4, .data_end
ADDI R3, R3, R4
STOREP R3, RE
;; 1st parameter 'begin' = 0
ADDI RE, RE, R2
LOADB R3, 0x00
STOREP R3, RE
;; return address
ADDI RE, RE, R2
LOADB R3, tmp1
STOREP R3, RE
JUMP R0, binary_search
tmp1: LOADB R3, 0x04
ADDI RE, RE, R3
LOADP R0, RE
ADDI RE, RE, R1
HALT
binary_search:
ADDI R3, RE, R1
LOADP RA, R3 ; 1st argument 'begin'
ADDI R3, R3, R1
LOADP RB, R3 ; 2nd argument 'end'
ADDI R3, R3, R1
LOADP RC, R3 ; 3rd argument 'target'
LOADB RD, 0xFF ; RD has value to be returned
;; if (end < begin)
;; return -1;
MOVE R0, RA
JUMPL RB, end
;; int mid = begin + (end - begin) / 2;
XOR R4, RA, R2
ADDI R4, R4, R1
ADDI R4, R4, RB
LOADB R3, 0xFE
AND R4, R4, R3
ROT R4, 1
ADDI R4, R4, RA
;; int mid_val = list[middle];
LOADB R5, .data
ADDI R5, R5, R4
LOADP R5, R5
MOVE R0, R5
JUMP RC, equal
JUMPL RC, target_less_than_mid
JUMP R0, target_greater_than_mid
equal:
;; if (target == mid_val)
;; return mid;
MOVE RD, R4
JUMP R0, end
target_less_than_mid:
;; else if (target < mid_val)
;; return binary_search(begin, mid - 1, target);
MOVE R8, RA
MOVE R9, R4
ADDI R9, R9, R2
JUMP R0, recursive_call
target_greater_than_mid:
;; else
;; return binary_search(mid + 1, end, target);
MOVE R8, R4
ADDI R8, R8, R1
MOVE R9, RB
recursive_call:
ADDI RE, RE, R2
ADDI RE, RE, R2
STOREP RC, RE
ADDI RE, RE, R2
STOREP R9, RE
ADDI RE, RE, R2
STOREP R8, RE
ADDI RE, RE, R2
LOADB R4, tmp2
STOREP R4, RE
JUMP R0, binary_search
tmp2: LOADB R4, 0x04
ADDI RE, RE, R4
LOADP RD, RE
ADDI RE, RE, R1
end:
LOADB R3, 0x04
ADDI R3, RE, R3
STOREP RD, R3
LOADP R3, RE
STOREM R3, ret+1
ret: JUMP R0, 0x00
.data@0xA0:
DB 0xAA
DB 0xC0
DB 0xDE
DB 0xF1
DB 0x00
DB 0x20
DB 0x34
DB 0x65
.data_end:
.stack@0xF8:

View File

@ -0,0 +1,64 @@
; 6.1 Passing Parameters by Value
;
; The corresponding C code looks like this:
;
; int a = 0xDE, b = 0xFA;
; int swap (int a, int b) {
; int c = a;
; a = b;
; b = c;
; return (a + b);
; }
; main() {
; swap(a, b);
; }
.entry:
;; initialize some constants
LOADB R1, 0x01
LOADB R2, 0xFF
;; initialize the stack
LOADB RE, .stack
;; push a slot for the return value
ADDI RE, RE, R2
;; push the second parameter
ADDI RE, RE, R2
LOADM R3, .data+1
STOREP R3, RE
;; push the first parameter
ADDI RE, RE, R2
LOADM R3, .data
STOREP R3, RE
;; push the return address
ADDI RE, RE, R2
LOADB R3, next
STOREP R3, RE
JUMP R0, swap
next: LOADB R4, 0x04
ADDI RE, RE, R4
HALT
swap@0x40:
ADDI R8, RE, R1
LOADP RA, R8 ; the first parameter
ADDI R8, R8, R1
LOADP RB, R8 ; the second parameter
;; int c = a;
MOVE RC, RA
;; a = b;
MOVE RA, RB
;; b = c;
MOVE RB, RC
;; return (a + b);
ADDI RD, RA, RB
ADDI R8, R8, R1
STOREP RD, R8
LOADP R8, RE
STOREM R8, ret+1
ret: JUMP R0, 00
.stack@0x80:
.data@0x80:
DB 0xDE
DB 0xFA

View File

@ -0,0 +1,66 @@
; 6.2 Passing Parameters by Reference
;
; The corresponding C code looks like this:
;
; int a = 0xDE, b = 0xFA;
; int swap (int *a, int *b) {
; int c = *a;
; *a = *b;
; *b = c;
; return (*a + *b);
; }
; main() {
; swap(&a, &b);
; }
.entry:
;; initialize some constants
LOADB R1, 0x01
LOADB R2, 0xFF
;; initialize the stack
LOADB RE, .stack
;; push a slot for the return value
ADDI RE, RE, R2
;; push the second parameter
ADDI RE, RE, R2
LOADB R3, .data+1
STOREP R3, RE
;; push the first parameter
ADDI RE, RE, R2
LOADB R3, .data
STOREP R3, RE
;; push the return address
ADDI RE, RE, R2
LOADB R3, next
STOREP R3, RE
JUMP R0, swap
next: LOADB R4, 0x04
ADDI RE, RE, R4
HALT
swap@0x40:
ADDI R8, RE, R1
LOADP RA, R8 ; the first parameter
ADDI R8, R8, R1
LOADP RB, R8 ; the second parameter
;; int c = *a;
LOADP RC, RA
;; *a = *b;
LOADP RD, RB
STOREP RD, RA
;; *b = c;
STOREP RC, RB
;; return (*a + *b);
LOADP RC, RA
LOADP RD, RB
ADDI RD, RC, RD
ADDI R8, R8, R1
STOREP RD, R8
LOADP R8, RE
STOREM R8, ret+1
ret: JUMP R0, 00
.stack@0x80:
.data@0x80:
DB 0xDE
DB 0xFA

View File

@ -136,9 +136,9 @@
<span style="margin-left:5px;">Instructions:</span>
<a ng-click="displayInstr = true" ng-hide="displayInstr">Show</a>
<a ng-click="displayInstr = false" ng-show="displayInstr">Hide</a>
<span style="margin-left:5px;">View:</span>
<a ng-click="displayHex = true" ng-hide="displayHex">Hex</a>
<a ng-click="displayHex = false" ng-show="displayHex">Decimal</a>
<!-- <span style="margin-left:5px;">View:</span> -->
<!-- <a ng-click="displayHex = true" ng-hide="displayHex">Hex</a> -->
<!-- <a ng-click="displayHex = false" ng-show="displayHex">Decimal</a> -->
<!-- <br> -->
<!-- Register addressing: -->
<!-- <span style="margin-left:5px;">A:</span> -->

View File

@ -27,10 +27,7 @@
<p>Valid number formats for constants are:</p>
<pre>
Decimal: 200
Decimal: 200d
Hex: 0xA4
Octal: 0o48
Binary: 101b
</pre>
<p>It is possible to define a number using a character or multiple numbers (see instruction <i>DB</i>) by using a string.</p>
<pre>

View File

@ -30,22 +30,18 @@ app.service('assembler', ['opcodes', function (opcodes) {
// Use https://www.debuggex.com/
// Matches: "label: INSTRUCTION OPERAND1, OPERAND2, OPERAND3
// GROUPS: 1 3 4 7 10
//var regex = /^[\t ]*(?:([.A-Za-z]\w*)[:])?(?:[\t ]*([A-Za-z]{2,4})(?:[\t ]+(\[(\w+((\+|-)\d+)?)\]|\".+?\"|\'.+?\'|[.A-Za-z0-9]\w*)(?:[\t ]*[,][\t ]*(\[(\w+((\+|-)\d+)?)\]|\".+?\"|\'.+?\'|[.A-Za-z0-9]\w*))?)?)?/;
//var regex = /^[\t ]*(?:([.A-Za-z]\w*)[:])?(?:[\t ]*([A-Za-z]{2,6})(?:[\t ]+(\[(\w+((\+|-)\d+)?)\]|\".+?\"|\'.+?\'|[.A-Za-z0-9]\w*)(?:[\t ]*[,][\t ]*(\[(\w+((\+|-)\d+)?)\]|\".+?\"|\'.+?\'|[.A-Za-z0-9]\w*)(?:[\t ]*[,][\t ]*(\[(\w+((\+|-)\d+)?)\]|\".+?\"|\'.+?\'|[.A-Za-z0-9]\w*))?)?)?)?/;
//var regex = /^[\t ]*(?:([.A-Za-z]\w*)[:])?(?:[\t ]*([A-Za-z]{2,6})(?:[\t ]+(\[(\w+((\+|-)\d+)?)\]|\".+?\"|\'.+?\'|[.A-Za-z0-9]\w*)(?:[\t ]*[,][\t ]*(\[(\w+((\+|-)\d+)?)\]|\".+?\"|\'.+?\'|[.A-Za-z0-9]\w*)(?:[\t ]*[,][\t ]*(\[(\w+((\+|-)\d+)?)\]|\".+?\"|\'.+?\'|[.A-Za-z0-9]\w*))?)?)?)?/;
var regex = /^[\t ]*(?:([.A-Za-z]\w*)(@\w+)?[:])?(?:[\t ]*([A-Za-z]{2,6})(?:[\t ]+([.A-Za-z0-9]\w*((\+|-)\d+)?)(?:[\t ]*[,][\t ]*([.A-Za-z0-9]\w*((\+|-)\d+)?)(?:[\t ]*[,][\t ]*([.A-Za-z0-9]\w*((\+|-)\d+)?))?)?)?)?/;
//^[\t ]*(?:([.A-Za-z]\w*)[:])? -- label: or nothing
//(?:[\t ]*([A-Za-z]{2,6}) -- instruction
//(?:[\t ]+(\[(\w+((\+|-)\d+)?)\]|\".+?\"|\'.+?\'|[.A-Za-z0-9]\w*)(?:[\t ]* -- (["')OPERAND1(]"')
// Regex group indexes for operands
//^[\t ]*(?:([.A-Za-z]\w*)(@\w+)?[:])? -- label: or nothing
//(?:[\t ]*([A-Za-z]{2,6}) -- instruction
//([.A-Za-z0-9]\w*((\+|-)\d+)?) -- (OPERAND1)
// Regex group indexes for operands
var op1_group = 4;
var op2_group = 7;
var op3_group = 10;
// MATCHES: "(+|-)INTEGER"
var regexNum = /^[-+]?[0-9]+$/;
// MATCHES: "(.L)abel"
var regexLabel = /^[.A-Za-z]\w*$/;
var regexLabelWithOffset = /^([.A-Za-z]\w*)((\+|-)\d+)?$/;
var regexLabel = /^([.A-Za-z_]\w*)((\+|-)\d+)?$/;
// Contains the program code & data generated by the assembler
var memory = [];
// The address where the next instruction/data will be placed at
@ -64,12 +60,6 @@ app.service('assembler', ['opcodes', function (opcodes) {
var parseNumber = function (input) {
if (input.slice(0, 2) === "0x") {
return parseInt(input.slice(2), 16);
} else if (input.slice(0, 2) === "0o") {
return parseInt(input.slice(2), 8);
} else if (input.slice(input.length - 1) === "b") {
return parseInt(input.slice(0, input.length - 1), 2);
} else if (input.slice(input.length - 1) === "d") {
return parseInt(input.slice(0, input.length - 1), 10);
} else if (regexNum.exec(input)) {
return parseInt(input, 10);
} else {
@ -125,7 +115,7 @@ app.service('assembler', ['opcodes', function (opcodes) {
throw "addresses must have a value between 0-255";
}
var match = regexLabelWithOffset.exec(input);
var match = regexLabel.exec(input);
if (match[1] === undefined)
return undefined;
var offset = 0;
@ -141,9 +131,6 @@ app.service('assembler', ['opcodes', function (opcodes) {
if (upperLabel in normalizedLabels)
throw "Duplicate label: " + label;
if (upperLabel === "R0" || upperLabel === "R1" || upperLabel === "R2" || upperLabel === "R3" || upperLabel === "R4" || upperLabel === "R5" || upperLabel === "R6" || upperLabel === "R7" ||upperLabel === "R8" || upperLabel === "R9" || upperLabel === "RA" || upperLabel === "RB" ||upperLabel === "RC" || upperLabel === "RD" || upperLabel === "RE" || upperLabel === "RF")
throw "Label contains keyword: " + upperLabel;
if (address === undefined) {
labels[label] = current;
} else if (address >= 0 && address <= 255) {
@ -249,7 +236,7 @@ app.service('assembler', ['opcodes', function (opcodes) {
break;
case 'LOADB':
p1 = parseRegister(match[op1_group]);
p2 = parseNumber(match[op2_group]);
p2 = parseAddress(match[op2_group]);
checkNoExtraArg('LOADB', match[op3_group]);
if (p1 !== undefined && p2 !== undefined)
generate(opcodes.LOAD_WITH_CONSTANT << 4 | p1, p2);

View File

@ -150,7 +150,7 @@ app.service('cpu', ['opcodes', 'memory', function(opcodes, memory) {
if (self.countdown > 0 && !self.updateTimer) {
self.countdown -= 1;
if (self.countdown === 0) {
memory.store(0xFE, self.ip);
memory.store(0xFD, self.ip);
self.ip = 0x80;
self.countdown = readReg(15);
self.status = '(Interrupted!)';