Permalink
Browse files

Implement an in-browser Beta terminal.

  • Loading branch information...
nelhage committed May 30, 2011
1 parent 4027403 commit c92e5ace49a1ad583fb596d66367fe7d3e4bf868
View
21 CPU.js
@@ -1,5 +1,3 @@
-var sprintf = require('./sprintf.js');
-
const XP = 30;
const PC_SUPERVISOR = 0x80000000;
const ISR_RESET = (PC_SUPERVISOR | 0x00000000);
@@ -154,6 +152,7 @@ function arithc(fn) {
}
var CPU = {
+ PC_SUPERVISOR: PC_SUPERVISOR,
/*
* Registers are maintained as integers in [-2**31, 2**31), and
* converted appropriately if an unsigned interpretation is needed
@@ -198,16 +197,16 @@ var CPU = {
},
step: function() {
- debug(sprintf.sprintf("PC: %d:%08x",
- (CPU.PC & PC_SUPERVISOR) ? 1 : 0,
- (CPU.PC & ~PC_SUPERVISOR)));
+ debug("PC: %d:%08x",
+ (CPU.PC & PC_SUPERVISOR) ? 1 : 0,
+ (CPU.PC & ~PC_SUPERVISOR));
var opcode = MMU.read(CPU.PC);
var inst = CPU.decode(opcode);
debug("decode:", inst);
- debug(sprintf.sprintf("regs: %x %x %x",
- CPU.regs[inst.ra],
- CPU.regs[inst.rb],
- CPU.regs[inst.rc]));
+ debug("regs: %x %x %x",
+ CPU.regs[inst.ra],
+ CPU.regs[inst.rb],
+ CPU.regs[inst.rc]);
CPU.PC += 4;
CPU.regs[31] = 0;
debug("decode: ", CPU.instructions[inst.opcode]);
@@ -327,7 +326,7 @@ var CPU = {
]
};
-if (module !== undefined) {
+try {
module.exports = CPU;
var MMU = require('./MMU.js');
-}
+} catch (e) {};
View
15 MMU.js
@@ -1,26 +1,25 @@
-const PC_SUPERVISOR = 0x80000000;
-
var MMU = {
memory: [],
load: function (mem) {
MMU.memory = mem.map(function(x){return x;});
},
read: function(addr) {
- var ea = (addr & ~PC_SUPERVISOR) >> 2;
+ var ea = (addr & ~CPU.PC_SUPERVISOR) >> 2;
if (ea > MMU.memory.length) {
- throw new Error("Invalid read: " + (addr & ~PC_SUPERVISOR));
+ throw new Error("Invalid read: " + (addr & ~CPU.PC_SUPERVISOR));
}
return MMU.memory[ea];
},
write: function(addr, data) {
- var ea = (addr & ~PC_SUPERVISOR) >> 2;
+ var ea = (addr & ~CPU.PC_SUPERVISOR) >> 2;
if (ea > MMU.memory.length) {
- throw new Error("Invalid read: " + (addr & ~PC_SUPERVISOR));
+ throw new Error("Invalid read: " + (addr & ~CPU.PC_SUPERVISOR));
}
MMU.memory[ea] = data;
}
};
-if (module !== undefined) {
+try {
module.exports = MMU;
-}
+ var CPU = require('./CPU.js');
+} catch (e) {}
View
@@ -0,0 +1,2 @@
+%.js: %.bin
+ perl bin2js.pl $< > $@
View
@@ -0,0 +1,48 @@
+<html>
+ <head>
+ <title>Beta emulator</title>
+ <script language="javascript" type="text/javascript" src="termlib/termlib.js"></script>
+ <script language="javascript" type="text/javascript" src="CPU.js"></script>
+ <script language="javascript" type="text/javascript" src="MMU.js"></script>
+ <script language="javascript" type="text/javascript" src="tests/hello.js"></script>
+ <script language="javascript" type="text/javascript" src="tests/lab8.js"></script>
+ <link rel="stylesheet" type="text/css" href="termlib/term_styles.css" />
+ <script language="javascript">
+ var term;
+
+ function openTerm() {
+ term = new Terminal( {handler: termHandler, initHandler: initTerm} );
+ term.charMode = true;
+ term.open();
+
+ MMU.load(lab8_rom);
+ CPU.reset();
+ CPU.run({timer: true,
+ write: function(ch){
+ if (ch == 10)
+ term.newLine();
+ else
+ term.type(String.fromCharCode(ch));
+ }
+ },
+ function() {
+ term.type("--- Program terminated ----");
+ });
+ }
+
+ function initTerm() {
+ this.lock = false;
+ }
+ function termHandler() {
+ var ch = this.inputChar;
+ if (ch == 13) ch = 10;
+ CPU.press_key(ch);
+ }
+
+ </script>
+ </head>
+ <body onload="openTerm();">
+ <div id='termDiv'>
+ </div>
+ </body>
+</html>
View
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use File::Basename;
+
+my $data = do {local $/; <>};
+my $name = basename($ARGV);
+my @values = unpack("L<*", $data);
+
+$name =~ s{\.bin$}{};
+
+print "var ${name}_rom = [\n";
+for my $b (@values) {
+ printf " 0x%08x, \n", $b;
+}
+print " 0x00000000\n];\n";

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,33 @@
+/*
+ termlib_parser.js v.1.1 (source compacted using jsmin.php)
+ command line parser for termlib.js
+ (c) Norbert Landsteiner 2005-2010
+ mass:werk - media environments
+ <http://www.masswerk.at>
+
+ you are free to use this parser under the "termlib.js" license:
+ http://www.masswerk.at/termlib/
+*/
+function Parser(){this.whiteSpace={' ':true,'\t':true};this.quoteChars={'"':true,"'":true,'`':true};this.singleEscapes={'\\':true};this.optionChars={'-':true};this.escapeExpressions={'%':Parser.prototype.plugins.hexExpression};}
+Parser.prototype={version:'1.1',plugins:{hexExpression:function(termref,charindex,escapechar,quotelevel){if(termref.lineBuffer.length>charindex+2){var hi=termref.lineBuffer.charAt(charindex+1);var lo=termref.lineBuffer.charAt(charindex+2);lo=lo.toUpperCase();hi=hi.toUpperCase();if((((hi>='0')&&(hi<='9'))||((hi>='A')&&((hi<='F'))))&&(((lo>='0')&&(lo<='9'))||((lo>='A')&&((lo<='F'))))){Parser.prototype.plugins._escExprStrip(termref,charindex+1,charindex+3);return String.fromCharCode(parseInt(hi+lo,16));}}
+return escapechar;},_escExprStrip:function(termref,from,to){termref.lineBuffer=termref.lineBuffer.substring(0,from)+
+termref.lineBuffer.substring(to);}},getopt:function(termref,optsstring){var opts={'illegals':[]};while((termref.argc<termref.argv.length)&&(termref.argQL[termref.argc]=='')){var a=termref.argv[termref.argc];if((a.length>0)&&(this.optionChars[a.charAt(0)])){var i=1;while(i<a.length){var c=a.charAt(i);var v='';while(i<a.length-1){var nc=a.charAt(i+1);if((nc=='.')||((nc>='0')&&(nc<='9'))){v+=nc;i++;}
+else{break;}}
+if(optsstring.indexOf(c)>=0){opts[c]=(v=='')?{value:-1}:(isNaN(v))?{value:0}:{value:parseFloat(v)};}
+else{opts.illegals[opts.illegals.length]=c;}
+i++;}
+termref.argc++;}
+else{break;}}
+return opts;},parseLine:function(termref){var argv=[''];var argQL=[''];var argc=0;var escape=false;for(var i=0;i<termref.lineBuffer.length;i++){var ch=termref.lineBuffer.charAt(i);if(escape){argv[argc]+=ch;escape=false;}
+else if(this.escapeExpressions[ch]){var v=this.escapeExpressions[ch](termref,i,ch,argQL[argc]);if(typeof v!='undefined')argv[argc]+=v;}
+else if(this.quoteChars[ch]){if(argQL[argc]){if(argQL[argc]==ch){argc++;argv[argc]=argQL[argc]='';}
+else{argv[argc]+=ch;}}
+else{if(argv[argc]!=''){argc++;argv[argc]='';argQL[argc]=ch;}
+else{argQL[argc]=ch;}}}
+else if(this.whiteSpace[ch]){if(argQL[argc]){argv[argc]+=ch;}
+else if(argv[argc]!=''){argc++;argv[argc]=argQL[argc]='';}}
+else if(this.singleEscapes[ch]){escape=true;}
+else{argv[argc]+=ch;}}
+if((argv[argc]=='')&&(!argQL[argc])){argv.length--;argQL.length--;}
+termref.argv=argv;termref.argQL=argQL;termref.argc=0;}}
+// eof
Oops, something went wrong.

0 comments on commit c92e5ac

Please sign in to comment.