mirror of https://github.com/chyyuu/v8-cpu.git
Merge branch 'from_yyk' of github.com:chyyuu/v8-cpu
This commit is contained in:
commit
40b4c1949b
|
@ -0,0 +1,223 @@
|
|||
app.controller('Ctrl', ['$document', '$scope', '$timeout', '$http', 'cpu', 'memory', 'printer', 'assembler', 'uploader', function ($document, $scope, $timeout, $http, cpu, memory, printer, assembler, uploader) {
|
||||
$scope.printer = printer;
|
||||
$scope.memory = memory;
|
||||
$scope.cpu = cpu;
|
||||
$scope.error = '';
|
||||
$scope.isRunning = false;
|
||||
$scope.displayHex = true;
|
||||
$scope.displayInstr = true;
|
||||
$scope.displayA = false;
|
||||
$scope.displayB = false;
|
||||
$scope.displayC = false;
|
||||
$scope.displayD = false;
|
||||
$scope.speeds = [{speed: 1, desc: "1 HZ"},
|
||||
{speed: 4, desc: "4 HZ"},
|
||||
{speed: 8, desc: "8 HZ"},
|
||||
{speed: 16, desc: "16 HZ"}];
|
||||
$scope.speed = 4;
|
||||
$scope.example = '';
|
||||
$scope.examples = [];
|
||||
|
||||
$scope.code = ";; Choose an example above or write your own code here :)";
|
||||
$scope.reset = function () {
|
||||
cpu.reset();
|
||||
memory.reset();
|
||||
printer.reset();
|
||||
$scope.error = '';
|
||||
$scope.selectedLine = -1;
|
||||
$scope.mapping = undefined;
|
||||
};
|
||||
|
||||
$scope.executeStep = function () {
|
||||
if (!$scope.checkPrgrmLoaded()) {
|
||||
$scope.assemble();
|
||||
}
|
||||
|
||||
try {
|
||||
// Execute
|
||||
var res = cpu.step();
|
||||
|
||||
// Mark in code
|
||||
if (cpu.ip in $scope.mapping) {
|
||||
$scope.selectedLine = $scope.mapping[cpu.ip];
|
||||
}
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
$scope.error = e;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var runner;
|
||||
$scope.run = function () {
|
||||
if (!$scope.checkPrgrmLoaded()) {
|
||||
$scope.assemble();
|
||||
}
|
||||
|
||||
$scope.isRunning = true;
|
||||
runner = $timeout(function () {
|
||||
if ($scope.executeStep() === true) {
|
||||
$scope.run();
|
||||
} else {
|
||||
$scope.isRunning = false;
|
||||
}
|
||||
}, 1000 / $scope.speed);
|
||||
};
|
||||
|
||||
$scope.stop = function () {
|
||||
$timeout.cancel(runner);
|
||||
$scope.isRunning = false;
|
||||
};
|
||||
|
||||
$scope.checkPrgrmLoaded = function () {
|
||||
for (var i = 0, l = memory.data.length; i < l; i++) {
|
||||
if (memory.data[i] !== 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
$scope.getChar = function (value) {
|
||||
var text = String.fromCharCode(value);
|
||||
|
||||
if (text.trim() === '') {
|
||||
return '\u00A0\u00A0';
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.assemble = function () {
|
||||
try {
|
||||
$scope.reset();
|
||||
|
||||
var assembly = assembler.go($scope.code);
|
||||
$scope.mapping = assembly.mapping;
|
||||
var binary = assembly.code;
|
||||
$scope.labels = assembly.labels;
|
||||
|
||||
if (binary.length > memory.data.length)
|
||||
throw "Binary code does not fit into the memory. Max " + memory.data.length + " bytes are allowed";
|
||||
|
||||
for (var i = 0, l = binary.length; i < l; i++) {
|
||||
memory.data[i] = binary[i];
|
||||
}
|
||||
|
||||
if ($scope.labels['.entry'] !== undefined) {
|
||||
cpu.ip = $scope.labels['.entry'];
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.line !== undefined) {
|
||||
$scope.error = e.line + " | " + e.error;
|
||||
$scope.selectedLine = e.line;
|
||||
} else {
|
||||
$scope.error = e.error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.upload = function () {
|
||||
try {
|
||||
$scope.reset();
|
||||
|
||||
var binarycode = uploader.go($scope.code);
|
||||
$scope.mapping = binarycode.mapping;
|
||||
var binary = binarycode.code;
|
||||
$scope.labels = binarycode.labels;
|
||||
|
||||
if (binary.length > memory.data.length)
|
||||
throw "Binary code does not fit into the memory. Max " + memory.data.length + " bytes are allowed";
|
||||
|
||||
for (var i = 0, l = binary.length; i < l; i++) {
|
||||
memory.data[i] = binary[i];
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.line !== undefined) {
|
||||
$scope.error = e.line + " | " + e.error;
|
||||
$scope.selectedLine = e.line;
|
||||
} else {
|
||||
$scope.error = e.error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.compile = function () {
|
||||
$.post('/',{"1":$scope.code},function(response){
|
||||
console.debug("called"); $scope.code = response; $scope.assemble();});
|
||||
};
|
||||
|
||||
$scope.initExamples = function() {
|
||||
var response = $http.get('examples/scandir.php');
|
||||
response.success(function(data, status, headers, config) {
|
||||
var filelist = String(data).split(',');
|
||||
for (var i = 0, l = filelist.length; i < l; i++) {
|
||||
var contents = filelist[i].split('|');
|
||||
var filename = contents[0], desc = contents[1];
|
||||
$scope.examples.push({id: filename, desc: desc});
|
||||
}
|
||||
});
|
||||
response.error(function(data, status, headers, config) {
|
||||
console.error("ajax failed");
|
||||
});
|
||||
};
|
||||
|
||||
$scope.showExample = function(key) {
|
||||
var response = $http.get('examples/' + $scope.example);
|
||||
|
||||
response.success(function(data, status, headers, config) {
|
||||
$scope.code = data;
|
||||
});
|
||||
response.error(function(data, status, headers, config) {
|
||||
console.error("ajax failed");
|
||||
});
|
||||
};
|
||||
|
||||
$scope.jumpToLine = function (index) {
|
||||
$document[0].getElementById('sourceCode').scrollIntoView();
|
||||
$scope.selectedLine = $scope.mapping[index];
|
||||
};
|
||||
|
||||
|
||||
$scope.isInstruction = function (index) {
|
||||
return $scope.mapping !== undefined &&
|
||||
$scope.mapping[index] !== undefined &&
|
||||
$scope.displayInstr;
|
||||
};
|
||||
|
||||
$scope.getMemoryCellCss = function (index) {
|
||||
if ($scope.isInstruction(index)) {
|
||||
return 'instr-bg';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
$scope.getMemoryInnerCellCss = function (index) {
|
||||
if (index === cpu.ip) {
|
||||
return 'marker marker-ip';
|
||||
} else if (index === cpu.sp) {
|
||||
return 'marker marker-sp';
|
||||
} else if (index === cpu.gpr[0] && $scope.displayA) {
|
||||
return 'marker marker-a';
|
||||
} else if (index === cpu.gpr[1] && $scope.displayB) {
|
||||
return 'marker marker-b';
|
||||
} else if (index === cpu.gpr[2] && $scope.displayC) {
|
||||
return 'marker marker-c';
|
||||
} else if (index === cpu.gpr[3] && $scope.displayD) {
|
||||
return 'marker marker-d';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
|
@ -0,0 +1,24 @@
|
|||
#CFLAGS := -Wall -W -std=c89
|
||||
|
||||
all: cucu-dummy
|
||||
|
||||
test: cucu-dummy-test cucu-x86-test
|
||||
|
||||
cucu-dummy: cucu-dummy.o
|
||||
cucu-dummy.o: cucu.c gen-dummy/gen.c
|
||||
$(CC) -c $< -DGEN=\"gen-dummy/gen.c\" -o $@
|
||||
cucu-dummy-test: cucu-dummy
|
||||
python gen-dummy/test.py
|
||||
|
||||
cucu-x86: cucu-x86.o
|
||||
cucu-x86.o: cucu.c gen-x86/gen.c
|
||||
$(CC) -c $< -DGEN=\"gen-x86/gen.c\" -o $@
|
||||
cucu-x86-test: cucu-x86
|
||||
sh gen-x86/test.sh
|
||||
|
||||
clean:
|
||||
rm -f cucu-dummy
|
||||
rm -f cucu-x86
|
||||
rm -f *.o
|
||||
|
||||
.PHONY: all
|
|
@ -0,0 +1,70 @@
|
|||
import BaseHTTPServer
|
||||
import urlparse
|
||||
import os
|
||||
import unittest
|
||||
from cucu import CucuVM
|
||||
class WebRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
#print(self.client_address)
|
||||
code = self.rfile.read(int(self.headers['content-length']))[2:]
|
||||
code = code.replace('+',' ')
|
||||
code = code.replace('%0A','\r\n')
|
||||
code = code.replace('%3B',';')
|
||||
code = code.replace('%2B','+')
|
||||
code = code.replace('%3D','=')
|
||||
code = code.replace('%7B','{')
|
||||
code = code.replace('%7D','}')
|
||||
print code
|
||||
c = CucuVM(code)
|
||||
parsed_path = urlparse.urlparse(self.path)
|
||||
message_parts = [
|
||||
'CLIENT VALUES:',
|
||||
'client_address=%s (%s)' % (self.client_address,
|
||||
self.address_string()),
|
||||
'command=%s' % self.command,
|
||||
'path=%s' % self.path,
|
||||
'real path=%s' % parsed_path.path,
|
||||
'query=%s' % parsed_path.query,
|
||||
'request_version=%s' % self.request_version,
|
||||
'',
|
||||
'SERVER VALUES:',
|
||||
'server_version=%s' % self.server_version,
|
||||
'sys_version=%s' % self.sys_version,
|
||||
'protocol_version=%s' % self.protocol_version,
|
||||
'',
|
||||
'HEADERS RECEIVED:',
|
||||
]
|
||||
for name, value in sorted(self.headers.items()):
|
||||
message_parts.append('%s=%s' % (name, value.rstrip()))
|
||||
message_parts.append('')
|
||||
message = '\r\n'.join(message_parts)
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
self.wfile.write(c.code)
|
||||
def do_GET(self):
|
||||
parsed_path = urlparse.urlparse(self.path)
|
||||
print(self.path);
|
||||
pa = self.path;
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
#print pa;
|
||||
#print pa[0:2]
|
||||
#print pa[0:2] == "/ex"
|
||||
if(pa[0:17] == "/examples/scandir"):
|
||||
print("!!!!!!!!!!!!!!!!!");
|
||||
info = os.getcwd();
|
||||
arr = os.listdir(info+"\examples");
|
||||
#for i in arr:
|
||||
# arr = arr + "|1\r\n";
|
||||
text = '["21-addition.txt|2.1 c = a + b\\r\\n","31-time-sharing-2-processes.txt|3.1 Time-sharing Between Two Processes\\r\\n","51-insertion-sort.txt|5.1 Insertion Sort\\r\\n","52-binary-search.txt|5.2 Binary Search\\r\\n","61-call-by-value.txt|6.1 Passing Parameters by Value\\r\\n","62-call-by-reference.txt|6.2 Passing Parameters by Reference\\r\\n"]';
|
||||
self.wfile.write(text);
|
||||
|
||||
|
||||
else:
|
||||
print(">>>>>>>>>>>>>>>>>");
|
||||
input = open(self.path[1:],"r");
|
||||
self.wfile.write(input.read());
|
||||
input.close()
|
||||
|
||||
server = BaseHTTPServer.HTTPServer(('127.0.0.1',8080), WebRequestHandler)
|
||||
server.serve_forever()
|
Binary file not shown.
|
@ -0,0 +1,465 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
/* print fatal error message and exit */
|
||||
static void error(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* LEXER
|
||||
*/
|
||||
#define MAXTOKSZ 256
|
||||
static FILE *f; /* input source file */
|
||||
static char tok[MAXTOKSZ]; /* current token */
|
||||
static int tokpos; /* offset inside the current token */
|
||||
static int nextc; /* next char to be pushed into token */
|
||||
|
||||
/* read next char */
|
||||
void readchr() {
|
||||
if (tokpos == MAXTOKSZ - 1) {
|
||||
tok[tokpos] = '\0';
|
||||
error("Token too long: %s\n", tok);
|
||||
}
|
||||
tok[tokpos++] = nextc;
|
||||
nextc = fgetc(f);
|
||||
}
|
||||
|
||||
/* read single token */
|
||||
void readtok() {
|
||||
for (;;) {
|
||||
/* skip spaces */
|
||||
while (isspace(nextc)) {
|
||||
nextc = fgetc(f);
|
||||
}
|
||||
/* try to read a literal token */
|
||||
tokpos = 0;
|
||||
while (isalnum(nextc) || nextc == '_') {
|
||||
readchr();
|
||||
}
|
||||
/* if it's not a literal token */
|
||||
if (tokpos == 0) {
|
||||
while (nextc == '<' || nextc == '=' || nextc == '>'
|
||||
|| nextc == '!' || nextc == '&' || nextc == '|') {
|
||||
readchr();
|
||||
}
|
||||
}
|
||||
/* if it's not special chars that looks like an operator */
|
||||
if (tokpos == 0) {
|
||||
/* try strings and chars inside quotes */
|
||||
if (nextc == '\'' || nextc == '"') {
|
||||
char c = nextc;
|
||||
readchr();
|
||||
while (nextc != c) {
|
||||
readchr();
|
||||
}
|
||||
readchr();
|
||||
} else if (nextc == '/') { /* skip comments */
|
||||
readchr();
|
||||
if (nextc == '*') {
|
||||
nextc = fgetc(f);
|
||||
while (nextc != '/') {
|
||||
while (nextc != '*') {
|
||||
nextc = fgetc(f);
|
||||
}
|
||||
nextc = fgetc(f);
|
||||
}
|
||||
nextc = fgetc(f);
|
||||
continue;
|
||||
}
|
||||
} else if (nextc != EOF) {
|
||||
/* otherwise it looks like a single-char symbol, like '+', '-' etc */
|
||||
readchr();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
tok[tokpos] = '\0';
|
||||
}
|
||||
|
||||
/* check if the current token machtes the string */
|
||||
int peek(char *s) {
|
||||
return (strcmp(tok, s) == 0);
|
||||
}
|
||||
|
||||
/* read the next token if the current token machtes the string */
|
||||
int accept(char *s) {
|
||||
if (peek(s)) {
|
||||
readtok();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* throw fatal error if the current token doesn't match the string */
|
||||
void expect(char *s) {
|
||||
if (accept(s) == 0) {
|
||||
error("Error: expected '%s', but found: %s\n", s, tok);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SYMBOLS
|
||||
*/
|
||||
#define MAXSYMBOLS 4096
|
||||
static struct sym {
|
||||
char type;
|
||||
int addr;
|
||||
char name[MAXTOKSZ];
|
||||
} sym[MAXSYMBOLS];
|
||||
static int sympos = 0;
|
||||
|
||||
int stack_pos = 0;
|
||||
|
||||
static struct sym *sym_find(char *s) {
|
||||
int i;
|
||||
struct sym *symbol = NULL;
|
||||
for (i = 0; i < sympos; i++) {
|
||||
if (strcmp(sym[i].name, s) == 0) {
|
||||
symbol = &sym[i];
|
||||
}
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
static struct sym *sym_declare(char *name, char type, int addr) {
|
||||
strncpy(sym[sympos].name, name, MAXTOKSZ);
|
||||
sym[sympos].addr = addr;
|
||||
sym[sympos].type = type;
|
||||
sympos++;
|
||||
if (sympos > MAXSYMBOLS) {
|
||||
error("Too many symbols\n");
|
||||
}
|
||||
return &sym[sympos-1];
|
||||
}
|
||||
|
||||
/*
|
||||
* BACKEND
|
||||
*/
|
||||
#define MAXCODESZ 4096
|
||||
static char code[MAXCODESZ];
|
||||
static int codepos = 0;
|
||||
|
||||
static void emit(void *buf, size_t len) {
|
||||
memcpy(code + codepos, buf, len);
|
||||
codepos += len;
|
||||
}
|
||||
|
||||
#define TYPE_NUM 0
|
||||
#define TYPE_CHARVAR 1
|
||||
#define TYPE_INTVAR 2
|
||||
|
||||
#ifndef GEN
|
||||
#error "A code generator (backend) must be provided (use -DGEN=...)"
|
||||
#endif
|
||||
|
||||
#include GEN
|
||||
|
||||
/*
|
||||
* PARSER AND COMPILER
|
||||
*/
|
||||
|
||||
static int expr();
|
||||
|
||||
/* read type name: int, char and pointers are supported */
|
||||
static int typename() {
|
||||
if (peek("int") || peek("char")) {
|
||||
readtok();
|
||||
while (accept("*"));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prim_expr() {
|
||||
int type = TYPE_NUM;
|
||||
if (isdigit(tok[0])) {
|
||||
int n = strtol(tok, NULL, 10); /* TODO: parse 0x.. */
|
||||
gen_const(n);
|
||||
} else if (isalpha(tok[0])) {
|
||||
struct sym *s = sym_find(tok);
|
||||
//printf("%s",s->addr);
|
||||
if (s == NULL) {
|
||||
error("Undeclared symbol: %s\n", tok);
|
||||
}
|
||||
if (s->type == 'L') {
|
||||
gen_stack_addr(stack_pos - s->addr - 1);
|
||||
//regnow = s->addr;
|
||||
} else {
|
||||
gen_sym_addr(s);
|
||||
}
|
||||
type = TYPE_INTVAR;
|
||||
} else if (accept("(")) {
|
||||
type = expr();
|
||||
expect(")");
|
||||
} else if (tok[0] == '"') {
|
||||
int i, j;
|
||||
i = 0; j = 1;
|
||||
while (tok[j] != '"') {
|
||||
if (tok[j] == '\\' && tok[j+1] == 'x') {
|
||||
char s[3] = {tok[j+2], tok[j+3], 0};
|
||||
uint8_t n = strtol(s, NULL, 16);
|
||||
tok[i++] = n;
|
||||
j += 4;
|
||||
} else {
|
||||
tok[i++] = tok[j++];
|
||||
}
|
||||
}
|
||||
tok[i] = 0;
|
||||
if (i % 2 == 0) {
|
||||
i++;
|
||||
tok[i] = 0;
|
||||
}
|
||||
gen_array(tok, i);
|
||||
type = TYPE_NUM;
|
||||
} else {
|
||||
error("Unexpected primary expression: %s\n", tok);
|
||||
}
|
||||
readtok();
|
||||
return type;
|
||||
}
|
||||
|
||||
static int binary(int type, int (*f)(), char *buf, size_t len) {
|
||||
if (type != TYPE_NUM) {
|
||||
gen_unref(type);
|
||||
}
|
||||
gen_push();
|
||||
type = f();
|
||||
if (type != TYPE_NUM) {
|
||||
gen_unref(type);
|
||||
}
|
||||
emit(buf, len);
|
||||
stack_pos = stack_pos - 1; /* assume that buffer contains a "pop" */
|
||||
return TYPE_NUM;
|
||||
}
|
||||
|
||||
static int postfix_expr() {
|
||||
int type = prim_expr();
|
||||
if (type == TYPE_INTVAR && accept("[")) {
|
||||
binary(type, expr, GEN_ADD, GEN_ADDSZ);
|
||||
expect("]");
|
||||
type = TYPE_CHARVAR;
|
||||
} else if (accept("(")) {
|
||||
int prev_stack_pos = stack_pos;
|
||||
gen_push(); /* store function address */
|
||||
int call_addr = stack_pos - 1;
|
||||
if (accept(")") == 0) {
|
||||
expr();
|
||||
gen_push();
|
||||
while (accept(",")) {
|
||||
expr();
|
||||
gen_push();
|
||||
}
|
||||
expect(")");
|
||||
}
|
||||
type = TYPE_NUM;
|
||||
gen_stack_addr(stack_pos - call_addr - 1);
|
||||
gen_unref(TYPE_INTVAR);
|
||||
gen_call();
|
||||
/* remove function address and args */
|
||||
gen_pop(stack_pos - prev_stack_pos);
|
||||
stack_pos = prev_stack_pos;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static int add_expr() {
|
||||
int type = postfix_expr();
|
||||
while (peek("+") || peek("-")) {
|
||||
if (accept("+")) {
|
||||
type = binary(type, postfix_expr, GEN_ADD, GEN_ADDSZ);
|
||||
} else if (accept("-")) {
|
||||
type = binary(type, postfix_expr, GEN_SUB, GEN_SUBSZ);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static int shift_expr() {
|
||||
int type = add_expr();
|
||||
while (peek("<<") || peek(">>")) {
|
||||
if (accept("<<")) {
|
||||
type = binary(type, add_expr, GEN_SHL, GEN_SHLSZ);
|
||||
} else if (accept(">>")) {
|
||||
type = binary(type, add_expr, GEN_SHR, GEN_SHRSZ);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static int rel_expr() {
|
||||
int type = shift_expr();
|
||||
while (peek("<")) {
|
||||
if (accept("<")) {
|
||||
type = binary(type, shift_expr, GEN_LESS, GEN_LESSSZ);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static int eq_expr() {
|
||||
int type = rel_expr();
|
||||
while (peek("==") || peek("!=")) {
|
||||
if (accept("==")) {
|
||||
type = binary(type, rel_expr, GEN_EQ, GEN_EQSZ);
|
||||
} else if (accept("!=")) {
|
||||
type = binary(type, rel_expr, GEN_NEQ, GEN_NEQSZ);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static int bitwise_expr() {
|
||||
int type = eq_expr();
|
||||
while (peek("|") || peek("&")) {
|
||||
if (accept("|")) {
|
||||
type = binary(type, eq_expr, GEN_OR, GEN_ORSZ);
|
||||
} else if (accept("&")) {
|
||||
type = binary(type, eq_expr, GEN_AND, GEN_ANDSZ);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static int expr() {
|
||||
int type = bitwise_expr();
|
||||
if (type != TYPE_NUM) {
|
||||
if (accept("=")) {
|
||||
gen_push(); expr();
|
||||
if (type == TYPE_INTVAR) {
|
||||
emit(GEN_ASSIGN, GEN_ASSIGNSZ);
|
||||
} else {
|
||||
emit(GEN_ASSIGN8, GEN_ASSIGN8SZ);
|
||||
}
|
||||
stack_pos = stack_pos - 1; /* assume ASSIGN contains pop */
|
||||
type = TYPE_NUM;
|
||||
} else {
|
||||
gen_unref(type);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static void statement() {
|
||||
if (accept("{")) {
|
||||
int prev_stack_pos = stack_pos;
|
||||
while (accept("}") == 0) {
|
||||
statement();
|
||||
}
|
||||
gen_pop(stack_pos-prev_stack_pos);
|
||||
stack_pos = prev_stack_pos;
|
||||
} else if (typename()) {
|
||||
struct sym *var = sym_declare(tok, 'L', stack_pos);
|
||||
readtok();
|
||||
if (accept("=")) {
|
||||
expr();
|
||||
}
|
||||
gen_push(); /* make room for new local variable */
|
||||
var->addr = stack_pos - 1;
|
||||
expect(";");
|
||||
} else if (accept("if")) {
|
||||
expect("(");
|
||||
expr();
|
||||
emit(GEN_JZ, GEN_JZSZ);
|
||||
int p1 = codepos;
|
||||
expect(")");
|
||||
int prev_stack_pos = stack_pos;
|
||||
statement();
|
||||
gen_patch_str(code + p1, ".else");
|
||||
//emits("hello\n");
|
||||
emit(GEN_JMP, GEN_JMPSZ);
|
||||
int p2 = codepos;
|
||||
emits(".else:\n");
|
||||
if (accept("else")) {
|
||||
stack_pos = prev_stack_pos;
|
||||
statement();
|
||||
}
|
||||
emits(".end:\n");
|
||||
stack_pos = prev_stack_pos;
|
||||
gen_patch_str(code + p2, ".end ");
|
||||
} else if (accept("while")) {
|
||||
expect("(");
|
||||
emits(".loop:\n");
|
||||
int p1 = codepos;
|
||||
gen_loop_start();
|
||||
expr();
|
||||
emit(GEN_JZ, GEN_JZSZ);
|
||||
int p2 = codepos;
|
||||
expect(")");
|
||||
statement();
|
||||
emit(GEN_JMP, GEN_JMPSZ);
|
||||
emits(".end:\n");
|
||||
//gen_patch(code + codepos, p1);
|
||||
//gen_patch(code + p2, codepos);
|
||||
gen_patch_str(code + codepos-6, ".loop");
|
||||
gen_patch_str(code + p2, ".end ");
|
||||
} else if (accept("return")) {
|
||||
if (peek(";") == 0) {
|
||||
expr();
|
||||
}
|
||||
expect(";");
|
||||
gen_pop(stack_pos); /* remove all locals from stack (except return address) */
|
||||
gen_ret();
|
||||
} else {
|
||||
expr();
|
||||
expect(";");
|
||||
}
|
||||
}
|
||||
|
||||
static void compile() {
|
||||
while (tok[0] != 0) { /* until EOF */
|
||||
if (typename() == 0) {
|
||||
error("Error: type name expected\n");
|
||||
}
|
||||
struct sym *var = sym_declare(tok, 'U', 0);
|
||||
readtok();
|
||||
if (accept(";")) {
|
||||
var->type = 'G';
|
||||
gen_sym(var);
|
||||
continue;
|
||||
}
|
||||
expect("(");
|
||||
int argc = 0;
|
||||
for (;;) {
|
||||
argc++;
|
||||
if (typename() == 0) {
|
||||
break;
|
||||
}
|
||||
sym_declare(tok, 'L', -argc-1);
|
||||
readtok();
|
||||
if (peek(")")) {
|
||||
break;
|
||||
}
|
||||
expect(",");
|
||||
}
|
||||
expect(")");
|
||||
if (accept(";") == 0) {
|
||||
stack_pos = 0;
|
||||
var->addr = codepos;
|
||||
var->type = 'F';
|
||||
gen_sym(var);
|
||||
statement(); /* function body */
|
||||
//gen_ret(); /* another ret if user forgets to put 'return' */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
f = stdin;
|
||||
/* prefetch first char and first token */
|
||||
nextc = fgetc(f);
|
||||
readtok();
|
||||
gen_start();
|
||||
compile();
|
||||
gen_finish();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
import subprocess
|
||||
|
||||
import time
|
||||
|
||||
#
|
||||
# Interpret VM instruction
|
||||
#
|
||||
class CucuVM:
|
||||
CUCU_PATH='cucu-dummy.exe'
|
||||
def __init__(self, src, debug=False):
|
||||
self.A = 0
|
||||
self.B = 0
|
||||
self.PC = 0
|
||||
self.SP = 16
|
||||
self.mem = [0 for i in range(0, 16)]
|
||||
print(src.encode('ascii'))
|
||||
self.compile(src.encode('ascii'))
|
||||
self.debug = debug
|
||||
#if debug:
|
||||
print(self.code)
|
||||
print(self.PC)
|
||||
print(len(self.code))
|
||||
self.debug = True
|
||||
while (self.PC < len(self.code)):
|
||||
self.step()
|
||||
if debug:
|
||||
self.dump()
|
||||
|
||||
def compile(self, src):
|
||||
p = subprocess.Popen(self.CUCU_PATH, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
|
||||
self.code = p.communicate(input=src)[0].replace('\r\n', '\n')
|
||||
|
||||
def getint(self, addr):
|
||||
return self.mem[addr] + self.mem[addr+1] * 256
|
||||
def putint(self, addr, n):
|
||||
self.mem[addr] = n & 0xff
|
||||
self.mem[addr+1] = (n & 0xff00) >> 8
|
||||
|
||||
def step(self):
|
||||
op = (self.code[self.PC:self.PC+8]).decode('ascii')
|
||||
#op = op.replace('\n','')
|
||||
#op = op.replace('\r','')
|
||||
#op = op.replace(' ', '')
|
||||
if (self.debug):
|
||||
print("op", op)
|
||||
|
||||
self.PC = self.PC + 8
|
||||
if (op.startswith(';')):
|
||||
return
|
||||
elif (op.startswith('ret')):
|
||||
try:
|
||||
addr = self.getint(self.SP)
|
||||
#addr = self.mem[self.SP+1]*256 + self.mem[self.SP]
|
||||
self.SP = self.SP + 2
|
||||
self.PC = addr
|
||||
except IndexError:
|
||||
self.PC = 0xffffff
|
||||
elif (op.startswith('A:=m[A]')):
|
||||
self.A = self.mem[self.A]
|
||||
elif (op.startswith('A:=M[A]')):
|
||||
self.A = self.getint(self.A)
|
||||
#self.A = self.mem[self.A] + self.mem[self.A + 1] * 256
|
||||
elif (op.startswith('m[B]:=A')):
|
||||
self.mem[self.B] = self.A & 0xff
|
||||
elif (op.startswith('M[B]:=A')):
|
||||
self.putint(self.B, self.A)
|
||||
#self.mem[self.B] = self.A & 0xff
|
||||
#self.mem[self.B+1] = (self.A & 0xff00) >> 8
|
||||
elif (op.startswith('push A')):
|
||||
self.SP = self.SP - 2
|
||||
self.putint(self.SP, self.A)
|
||||
#self.mem[self.SP] = self.A & 0xff
|
||||
#self.mem[self.SP+1] = (self.A & 0xff00) >> 8
|
||||
elif (op.startswith('pop B')):
|
||||
self.B = self.getint(self.SP)
|
||||
#self.B = self.mem[self.SP+1]*256 + self.mem[self.SP]
|
||||
self.SP = self.SP + 2
|
||||
elif (op.startswith('A:=B+A')):
|
||||
self.A = (self.B + self.A) & 0xffff
|
||||
elif (op.startswith('A:=B-A')):
|
||||
self.A = (self.B - self.A) & 0xffff
|
||||
elif (op.startswith('A:=B&A')):
|
||||
self.A = (self.B & self.A) & 0xffff
|
||||
elif (op.startswith('A:=B<<A')):
|
||||
self.A = (self.B << self.A) & 0xffff
|
||||
elif (op.startswith('A:=B>>A')):
|
||||
self.A = (self.B >> self.A) & 0xffff
|
||||
elif (op.startswith('A:=B|A')):
|
||||
self.A = (self.B | self.A) & 0xffff
|
||||
elif (op.startswith('A:=B<A')):
|
||||
if self.A > self.B:
|
||||
self.A = 1
|
||||
else:
|
||||
self.A = 0
|
||||
elif (op.startswith('A:=B==A')):
|
||||
if self.A == self.B:
|
||||
self.A = 1
|
||||
else:
|
||||
self.A = 0
|
||||
elif (op.startswith('A:=B!=A')):
|
||||
if self.A != self.B:
|
||||
self.A = 1
|
||||
else:
|
||||
self.A = 0
|
||||
elif (op.startswith('pop')):
|
||||
n = int(op[3:], 16)
|
||||
self.SP = self.SP + n*2
|
||||
elif (op.startswith('A:=')):
|
||||
self.A = int(op[3:], 16)
|
||||
elif (op.startswith('sp@')):
|
||||
self.A = self.SP + int(op[3:], 16)*2 # TODO
|
||||
#print(self.A)
|
||||
elif (op.startswith('jmp')):
|
||||
self.PC = int(op[3:], 16)
|
||||
elif (op.startswith('jmz')):
|
||||
if self.A == 0:
|
||||
self.PC = int(op[3:], 16)
|
||||
elif (op.startswith('call A')):
|
||||
self.SP = self.SP - 2
|
||||
self.putint(self.SP, self.PC)
|
||||
#self.mem[self.SP] = (self.PC & 0xff)
|
||||
#self.mem[self.SP+1] = ((self.PC & 0xff00) >> 8)
|
||||
self.PC = self.A
|
||||
else:
|
||||
print("UNKNOWN OPERATOR STRING: " + op)
|
||||
|
||||
def dump(self):
|
||||
print("A:%04x B:%04x PC:%x SP:%x" % (self.A, self.B, self.PC, self.SP))
|
||||
print("Mem:", self.mem)
|
||||
print()
|
||||
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
#define emits(s) emit(s, strlen(s))
|
||||
|
||||
#define TYPE_NUM_SIZE 2
|
||||
static int mem_pos = 0;
|
||||
|
||||
#define GEN_ADD "LOADP RB,RE\nADDI RE,RE,R1\nADDI RA,RA,RB\n"
|
||||
#define GEN_ADDSZ strlen(GEN_ADD)
|
||||
|
||||
#define GEN_SUB "LOADP RB,RE\nADDI RE,RE,R1\nA:=B-A \n"
|
||||
#define GEN_SUBSZ strlen(GEN_SUB)
|
||||
|
||||
#define GEN_SHL "LOADP RB,RE\nADDI RE,RE,R1\nA:=B<<A\n"
|
||||
#define GEN_SHLSZ strlen(GEN_SHL)
|
||||
|
||||
#define GEN_SHR "LOADP RB,RE\nADDI RE,RE,R1\nROT RA,RB\n"
|
||||
#define GEN_SHRSZ strlen(GEN_SHR)
|
||||
|
||||
#define GEN_LESS "LOADP RB,RE\nADDI RE,RE,R1\nA:=B<A \n"
|
||||
#define GEN_LESSSZ strlen(GEN_LESS)
|
||||
|
||||
#define GEN_EQ "LOADP RB,RE\nADDI RE,RE,R1\nXOR RA,RA,RB\nNOT RA\n"
|
||||
#define GEN_EQSZ strlen(GEN_EQ)
|
||||
#define GEN_NEQ "LOADP RB,RE\nADDI RE,RE,R1\nXOR RA,RA,RB\n"
|
||||
#define GEN_NEQSZ strlen(GEN_NEQ)
|
||||
|
||||
#define GEN_OR "LOADP RB,RE\nADDI RE,RE,R1\nOR RA,RA,RB\n"
|
||||
#define GEN_ORSZ strlen(GEN_OR)
|
||||
#define GEN_AND "LOADP RB,RE\nADDI RE,RE,R1\nAND RA,RA,RB\n"
|
||||
#define GEN_ANDSZ strlen(GEN_AND)
|
||||
|
||||
#define GEN_ASSIGN "LOADP RB,RE\nADDI RE,RE,R1\nSTOREP RA,RB\n"
|
||||
#define GEN_ASSIGNSZ strlen(GEN_ASSIGN)
|
||||
#define GEN_ASSIGN8 "LOADP RB,RE\nADDI RE,RE,R1\nm[B]:=A\n"
|
||||
#define GEN_ASSIGN8SZ strlen(GEN_ASSIGN8)
|
||||
|
||||
#define GEN_JMP "JUMP R0,.....\n"
|
||||
#define GEN_JMPSZ strlen(GEN_JMP)
|
||||
|
||||
#define GEN_JZ "JUMP RA,.....\n"
|
||||
#define GEN_JZSZ strlen(GEN_JZ)
|
||||
|
||||
static void gen_start() {
|
||||
emits("LOADB R1,1\nLOADB R2,-1\nLOADB RE,.stack\nADDI RE,RE,R2\n");
|
||||
//emits("jmpCAFE\n");
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void gen_finish() {
|
||||
struct sym *funcmain = sym_find("main");
|
||||
char s[32];
|
||||
sprintf(s, "%04x", funcmain->addr);
|
||||
//memcpy(code+27, s, 4);
|
||||
emits("HALT \n");
|
||||
emits(".stack@0xC0:");
|
||||
printf("%s", code);
|
||||
FILE* fp = fopen("after.txt", "w");
|
||||
fputs(code, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void gen_ret() {
|
||||
emits("HALT \n");
|
||||
emits(".stack@0xC0:");
|
||||
stack_pos = stack_pos - 1;
|
||||
}
|
||||
|
||||
static void gen_const(int n) {
|
||||
char s[32];
|
||||
sprintf(s, "LOADB RA,%02d\n",n);
|
||||
emits(s);
|
||||
}
|
||||
|
||||
static void gen_sym(struct sym *sym) {
|
||||
if (sym->type == 'G') {
|
||||
sym->addr = mem_pos;
|
||||
mem_pos = mem_pos + TYPE_NUM_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_loop_start() {}
|
||||
|
||||
static void gen_sym_addr(struct sym *sym) {
|
||||
//gen_const(sym->addr);
|
||||
}
|
||||
|
||||
static void gen_push() {
|
||||
emits("ADDI RE,RE,R2\nSTOREP RA,RE\n");
|
||||
stack_pos = stack_pos + 1;
|
||||
}
|
||||
|
||||
static void gen_pop(int n) {
|
||||
char s[32];
|
||||
if (n > 0) {
|
||||
sprintf(s, "ADDI RE,RE,R1\n");
|
||||
emits(s);
|
||||
stack_pos = stack_pos - n;
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_stack_addr(int addr) {
|
||||
char s[32];
|
||||
sprintf(s, "LOADB RC, %02x\nADDI RA,RE,RC\n", addr);
|
||||
emits(s);
|
||||
}
|
||||
|
||||
static void gen_unref(int type) {
|
||||
if (type == TYPE_INTVAR) {
|
||||
emits("LOADP RA,RA\n");
|
||||
} else if (type == TYPE_CHARVAR) {
|
||||
emits("LOADP RA,RA\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_call() {
|
||||
emits("call A\n");
|
||||
}
|
||||
|
||||
static void gen_array(char *array, int size) {
|
||||
int i = size;
|
||||
char *tok = array;
|
||||
/* put token on stack */
|
||||
for (; i >= 0; i-=2) {
|
||||
//gen_const((tok[i] << 8 | tok[i-1]));
|
||||
gen_push();
|
||||
}
|
||||
/* put token address on stack */
|
||||
gen_stack_addr(0);
|
||||
}
|
||||
|
||||
|
||||
static void gen_patch(uint8_t *op, int value) {
|
||||
char s[32];
|
||||
sprintf(s, "%04x", value);
|
||||
memcpy(op-5, s, 4);
|
||||
}
|
||||
|
||||
static void gen_patch_str(uint8_t *op, char* address)
|
||||
{
|
||||
memcpy(op-6,address,5);
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
<!DOCTYPE html>
|
||||
<html ng-app="ASMSimulator">
|
||||
<head>
|
||||
<title>Simple 8-bit V8-CPU in Javascript</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
</head>
|
||||
<body ng-controller="Ctrl">
|
||||
<nav class="navbar navbar-inverse" role="navigation" style="background-color:#428BCA;border:0px;border-radius:0px;">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-success navbar-btn" ng-click="run()" ng-hide="isRunning"><span class="glyphicon glyphicon-play"></span> Run</button>
|
||||
<button type="button" class="btn btn-default navbar-btn" ng-click="stop()" ng-show="isRunning"><span class="glyphicon glyphicon-stop"></span> Stop</button>
|
||||
<button type="button" class="btn btn-default navbar-btn" ng-click="executeStep()" ng-disabled="isRunning"><span class="glyphicon glyphicon-forward"></span> Step</button>
|
||||
</div>
|
||||
<button type="button" class="btn btn-default navbar-btn" ng-click="reset()">Reset</button>
|
||||
</div>
|
||||
<div class="navbar-header navbar-right">
|
||||
<a class="navbar-brand" style="color:#FFFFFF">Simple 8-bit V8-CPU</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<div class="alert alert-danger" ng-hide="error === ''">{{ error }}</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-7 col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Code <small>(<a href="./instruction-set.html" target="_blank" style="color: #337AB7">Instruction Set</a>)</small></h4>
|
||||
</div>
|
||||
<button type="button" class="btn btn-default" ng-click="compile()">Compile</button>
|
||||
<script>
|
||||
function postcode()
|
||||
{
|
||||
var ta = document.getElementById("sourceCode");
|
||||
$.post('/',{"1":ta.value},function(response){
|
||||
ta.value = response;
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
<button type="button" class="btn btn-default" ng-click="assemble()">Assemble</button>
|
||||
<button type="button" class="btn btn-default" ng-click="upload()">Upload</button>
|
||||
Examples:
|
||||
<select ng-model="example" ng-options="item.id as item.desc for item in examples" ng-change="showExample(example)" ng-init="initExamples()"></select>
|
||||
<!-- <select id="examples" ng-change="showExample(x)" ng-model="x"> -->
|
||||
<!-- <option value="haha">haha</option> -->
|
||||
<!-- <option value="hoho">hoho</option> -->
|
||||
<!-- </select> -->
|
||||
<form role="form">
|
||||
<textarea id="sourceCode"
|
||||
class="form-control source-code"
|
||||
style="margin-bottom:5px;"
|
||||
rows="30"
|
||||
tab-support
|
||||
select-line
|
||||
ng-model="code"></textarea>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix visible-xs visible-sm"></div>
|
||||
<div class="col-lg-5 col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Printer</h4>
|
||||
</div>
|
||||
<div class="panel-body source-code">{{ printer.data }}</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">CPU & Memory</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">General Registers</p>
|
||||
<table class="table table-condensed table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:center">0</th>
|
||||
<th style="text-align:center">1</th>
|
||||
<th style="text-align:center">2</th>
|
||||
<th style="text-align:center">3</th>
|
||||
<th style="text-align:center">4</th>
|
||||
<th style="text-align:center">5</th>
|
||||
<th style="text-align:center">6</th>
|
||||
<th style="text-align:center">7</th>
|
||||
<th style="text-align:center">8</th>
|
||||
<th style="text-align:center">9</th>
|
||||
<th style="text-align:center">A</th>
|
||||
<th style="text-align:center">B</th>
|
||||
<th style="text-align:center">C</th>
|
||||
<th style="text-align:center">D</th>
|
||||
<th style="text-align:center">E</th>
|
||||
<th style="text-align:center">F</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr style="text-align:center;" class="source-code">
|
||||
<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>
|
||||
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[3] | number:displayHex }}</small></div></td>
|
||||
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[4] | number:displayHex }}</small></div></td>
|
||||
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[5] | number:displayHex }}</small></div></td>
|
||||
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[6] | number:displayHex }}</small></div></td>
|
||||
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[7] | number:displayHex }}</small></div></td>
|
||||
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[8] | number:displayHex }}</small></div></td>
|
||||
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[9] | number:displayHex }}</small></div></td>
|
||||
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[10] | number:displayHex }}</small></div></td>
|
||||
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[11] | number:displayHex }}</small></div></td>
|
||||
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[12] | number:displayHex }}</small></div></td>
|
||||
<td><div style="margin:auto;" ng-class="displayD && 'marker marker-d'"><small>{{ cpu.gpr[13] | number:displayHex }}</small></div></td>
|
||||
<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>
|
||||
</table>
|
||||
<p class="text-muted">Other Registers</p>
|
||||
<table class="table table-condensed table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align:left">Program counter <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">Instruction register</td>
|
||||
<td style="text-align:center;" class="source-code"><div style="margin:auto;"><small>{{ cpu.ir | 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">
|
||||
<div class="memory-block"
|
||||
ng-repeat="m in memory.data track by $index"
|
||||
ng-class="getMemoryCellCss($index)">
|
||||
<div ng-class="getMemoryInnerCellCss($index)" ng-switch="isInstruction($index)">
|
||||
<small ng-switch-default>{{ m | number:displayHex }}</small>
|
||||
<a ng-switch-when="true" ng-click="jumpToLine($index)">
|
||||
<small>{{ m | number:displayHex }}</small>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin-top:5px;">
|
||||
<small>
|
||||
<span>Clock speed:</span>
|
||||
<select ng-model="speed" ng-options="item.speed as item.desc for item in speeds"></select>
|
||||
<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>
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Labels</h4>
|
||||
</div>
|
||||
<div class="panel-body source-code">
|
||||
<table class="table table-condensed table-striped codelabels">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Address</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
<tr ng-repeat="(name, value) in labels" class="codelabel">
|
||||
<td class="codelabel-name">{{ name }}</td>
|
||||
<td class="codelabel-line"><a ng-click="jumpToLine(value)">{{ value | number:displayHex }}</a></td>
|
||||
<td class="codelabel-value">{{ memory.data[value] | number:displayHex }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr style="margin-top:10px;margin-bottom:10px;"/>
|
||||
<p><small>by Yuanchun Shi, Yu Chen, Junjie Mao, Yukang Yan (2015) | MIT License | <a href="https://www.github.com/chyyuu/v8-cpu" target="_blank">Source Code</a></small></p>
|
||||
<p><small>by Marco Schweighauser (2015) | MIT License | <a href="https://www.mschweighauser.com/make-your-own-assembler-simulator-in-javascript-part1/" target="_blank">Blog</a></small></p>
|
||||
</div>
|
||||
<script src="node_modules/angular/angular.min.js"></script>
|
||||
<script src="assets/asmsimulator.min.js"></script>
|
||||
<script src="/jquery-1.11.3.min.js">
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
cucu.py, cucu-dummy.exe, Simserver.pys三个文件应放置在与index.html同一目录下
|
||||
启动server: Python Simserver.py
|
||||
http://localhost:8080/index.html 为目前的页面url
|
||||
在textarea内编辑c 代码,点击complie返回v8代码,点击assemble后可以run,简单写了两个testcase,是test1.txt和test2.txt。
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
int main()
|
||||
{
|
||||
int i = 3;
|
||||
int j = 5;
|
||||
i = i + j;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
int main()
|
||||
{
|
||||
int i = 5;
|
||||
while(i != 10)
|
||||
{
|
||||
i = i + 1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
int main()
|
||||
{
|
||||
int i = 3;
|
||||
int j = 5;
|
||||
if(i != 5)
|
||||
{
|
||||
j = 6;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue