Merge branch 'from_yyk' of github.com:chyyuu/v8-cpu

This commit is contained in:
Junjie Mao 2015-11-18 13:38:20 +08:00
commit 40b4c1949b
13 changed files with 1274 additions and 0 deletions

223
controller.js Normal file
View File

@ -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:
*/

24
from_yyk/Makefile Normal file
View File

@ -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

70
from_yyk/Simserver.py Normal file
View File

@ -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()

BIN
from_yyk/cucu-dummy.exe Normal file

Binary file not shown.

465
from_yyk/cucu.c Normal file
View File

@ -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;
}

132
from_yyk/cucu.py Normal file
View File

@ -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()

141
from_yyk/gen-dummy/gen.c Normal file
View File

@ -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);
}

191
from_yyk/index.html Normal file
View File

@ -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>

BIN
from_yyk/readme.docx Normal file

Binary file not shown.

5
from_yyk/readme.txt Normal file
View File

@ -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。

6
from_yyk/test1.txt Normal file
View File

@ -0,0 +1,6 @@
int main()
{
int i = 3;
int j = 5;
i = i + j;
}

8
from_yyk/test2.txt Normal file
View File

@ -0,0 +1,8 @@
int main()
{
int i = 5;
while(i != 10)
{
i = i + 1;
}
}

9
from_yyk/test3.txt Normal file
View File

@ -0,0 +1,9 @@
int main()
{
int i = 3;
int j = 5;
if(i != 5)
{
j = 6;
}
}