inputProcess_CompileELCHNOS_OSECPU: function(str, srctype){
this.debug("**** Start Processing (CompileELCHNOS_OSECPU) ****\n");
- var cc = new ELCHNOSCompiler(this);
- cc.compile(str);
+ var that = this;
+ var cc = new ELCHNOSCompiler(function(s){ that.debug(s); }, this.downloadBox);
+ if(cc.compile(str) == null){
+ cc.saveBinary();
+ }
this.debug("**** End Processing (CompileELCHNOS_OSECPU) ****\n");
},
}
return retArray;
}
-Array.prototype.logAsHexByte = function(){
+Array.prototype.logAsHexByte = function(logfunc){
//十六進バイト列としてデバッグ出力する。
+ //logfuncは省略時はconsole.logとなる。
+ if(logfunc === undefined){
+ logfunc = function(s){ console.log(s); };
+ }
var ds = "";
for(var i = 0, iLen = this.length; i < iLen; i++){
ds += ("00" + this[i].toString(16).toUpperCase()).slice(-2);
}
- console.log(ds);
+ logfunc(ds);
}
Array.prototype.stringAsHexByte = function(){
//十六進バイト列として文字列を得る
// ELCHNOSCompiler for AI004
+// AI004(WebCPU)がなければ動作しない。
//手順:
//トークン分割
s += ":" + this.errorMessageList[this.errno] + "\n";
}
if(this.infoArray){
- s += " >" + this.infoArray.toString() + "\n";
+ s += " >" + this.infoArray.join("\n > ") + "\n";
}
return s;
},
// throw new ELCHNOSCompiler_CompileException(5, [""], this.lineCount);
-function ELCHNOSCompiler(env){
- this.env = env;
-
- this.line = null;
- this.separated = null;
- this.bin = new Array();
-
- this.structure = new Array();
- this.currentStructure = this.structure;
- this.structureStack = new Array();
+function ELCHNOSCompiler(printFunc, downloadBoxDOMObject){
+ //printFunc省略時はconsole.logに出力。
+ if(printFunc){
+ this.debug = printFunc;
+ } else{
+ this.debug = function(s){ console.log(s); };
+ }
+ this.downloadBoxDOMObject = downloadBoxDOMObject;
+ this.reset();
//0はエントリポイント(main)用に予約
this.nextLabelID = 1;
this.integerRegisterAllocationTable = new Array();
Flag_Sign_Signed : 0x00000001,
Flag_Sign_Unsigned : 0x00000002,
-
+ reset: function(){
+ this.line = null;
+ this.separated = null;
+ this.bin = new Array();
+
+ this.structure = new Array();
+ this.currentStructure = this.structure;
+ this.structureStack = new Array();
+
+ //0はエントリポイント(main)用に予約
+ this.nextLabelID = 1;
+ this.integerRegisterAllocationTable = new Array();
+ this.pointerRegisterAllocationTable = new Array();
+ },
compile: function(str){
+ //戻り値nullでコンパイル成功
+ this.reset();
+ //
this.line = str.split("\n");
//分割
this.separated = str.splitByArraySeparatorSeparatedLong(this.keyWordList);
}
this.expandBinaryString();
this.assignRegister();
- this.bin.logAsHexByte();
+ this.bin.logAsHexByte(this.debug);
+ this.debug("\n");
+ //
+
+ //
var cpu = new WebCPU();
cpu.loadBinaryText(this.bin.stringAsHexByte());
cpu.staticOptimize();
- console.log(cpu.createBackendBinaryString());
- this.saveBinary();
+ this.debug(cpu.createBackendBinaryString());
+ this.debug("\n");
+ //
} catch(e){
//全エラー処理
if(e instanceof ELCHNOSCompiler_CompileException){
- this.env.debug(e.getMessageString());
+ this.debug(e.getMessageString());
+ return e;
} else{
throw e;
}
}
+ return null;
},
compile_removeComment: function(){
//コメント削除
iLen -= len - linesInCommentBlock;
linesInCommentBlock = 0;
} else if(commentBlockCount < 0){
- this.env.debug("Too many block comment closure [].\n");
+ this.debug("Too many block comment closure [].\n");
return;
}
} else if(commentBlockCount > 0 && s == "\n"){
},
raiseError: function(errno, lineCount, infoArray){
if(errno < 0 || this.errorMessageList.length <= errno){
- this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":Unknown\n");
+ this.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":Unknown\n");
} else{
- this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":" + this.errorMessageList[errno] + "\n");
+ this.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":" + this.errorMessageList[errno] + "\n");
}
if(infoArray){
- this.env.debug(" >" + infoArray.toString() + "\n");
+ this.debug(" >" + infoArray.toString() + "\n");
}
},
changeCurrentStructure: function(newstructure){
}
},
saveBinary: function(){
- var m = this.env.IOManager;
var cl = this.bin;
var v = new Uint8Array(this.bin);
var d = new Blob([v]);
+ var url;
if(d){
- m.showDownloadLink(d);
+ if(window.URL){
+ url = window.URL.createObjectURL(d);
+ } else if(window.webkitURL){
+ url = window.webkitURL.createObjectURL(d);
+ } else{
+ window.alert("Can't create URL");
+ }
+ if(url){
+ if(this.downloadBoxDOMObject){
+ this.downloadBoxDOMObject.innerHTML = "<a href='" + url + "' target='_blank'>ダウンロード</a>";
+ } else{
+ this.debug("BinarySaved: " + url + "\n");
+ }
+ }
}
},
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=9">
+<meta charset="UTF-8">
+<title>ELCC-IDE</title>
+<style type="text/css">
+ h1, h2, h3 {
+ margin:0px;
+ }
+ body, textarea {
+ font-family: Consolas, 'Courier New', Courier, Monaco, monospace;
+ font-size: 14px;
+ line-height: 1.2;
+ }
+ #fileDropZone {
+ border: 2px dashed #bbb;
+ padding: 25px;
+ text-align: center;
+ font: 20pt bold;
+ color: #bbb;
+ }
+</style>
+<script type="text/javascript" src="./header.js" charset="UTF-8"></script>
+<script type="text/javascript">
+
+var mainCPU = null;
+var mainCompiler = null;
+var codeTextArea = null;
+var debugMessageTextArea = null;
+var maxDebugMessageLength = 0x1000;
+var binStr = null;
+
+onload = function(){
+ debugMessageTextArea = document.getElementById('debugMessageText');
+ mainCPU = new WebCPU();
+ mainCompiler = new ELCHNOSCompiler(messageOut);
+
+ mainCPU.setMainWindowCanvasDOMObject("mainWindowCanvas");
+ enableDebugMode();
+
+ // Setup the dnd listeners.
+ var dropZone = document.getElementById('fileDropZone');
+ dropZone.addEventListener('dragover', handleDragOver, false);
+ dropZone.addEventListener('drop', handleFileSelect, false);
+
+ //Enable Tab key in textarea
+ codeTextArea = document.getElementById('codeText');
+ //http://d.hatena.ne.jp/hokaccha/20111028/1319814792
+ codeTextArea.addEventListener("keydown", function(e) {
+ if (e.keyCode === 9) {
+ e.preventDefault();
+ var elem = e.target;
+ var val = elem.value;
+ var pos = elem.selectionStart;
+ elem.value = val.substr(0, pos) + '\t' + val.substr(pos, val.length);
+ elem.setSelectionRange(pos + 1, pos + 1);
+ }
+ });
+
+}
+
+function messageOut(s){
+ var str = debugMessageTextArea.value + s;
+ if(str.length > maxDebugMessageLength){
+ str = str.slice(str.length - (maxDebugMessageLength >> 1));
+ }
+ debugMessageTextArea.value = str;
+ debugMessageTextArea.scrollTop = debugMessageTextArea.scrollHeight;
+}
+
+function compile(){
+ debugMessageTextArea.value += "****Compile Started****\n";
+ if(mainCompiler.compile(codeTextArea.value) == null){
+ messageOut("*\n****Compile Succeeded!****\n*\n");
+ binStr = mainCompiler.bin.stringAsHexByte()
+ } else{
+ messageOut("*\n****Compile Failed...****\n*\n");
+ binStr = null;
+ }
+}
+
+function run(){
+ if(binStr){
+ mainCPU.loadBinaryText(binStr);
+ mainCPU.execute();
+ }
+}
+
+function enableDebugMode(){
+ mainCPU.setDebugMessageDOMObject("debugMessageText");
+ mainCPU.message("****Debug mode enabled.\n");
+}
+
+function disableDebugMode(){
+ mainCPU.message("****Debug mode disabled.\n");
+ mainCPU.setDebugMessageDOMObject(null);
+}
+
+// http://www.html5rocks.com/ja/tutorials/file/dndfiles/
+function handleFileSelect(evt){
+ evt.stopPropagation();
+ evt.preventDefault();
+
+ var files = evt.dataTransfer.files; // FileList object.
+
+ // files is a FileList of File objects. List some properties.
+ var output = [];
+ for(var i = 0, f; f = files[i]; i++){
+ output.push('<li><strong>', escape(f.name), '</strong> ', f.size, ' bytes, last modified: ', f.lastModifiedDate.toLocaleDateString(), '</li>');
+ var r = new FileReader();
+ r.onload = (function(file){
+ return function(e){
+ var a = r.result;
+ codeTextArea.value = a;
+ }
+ })(f);
+ r.readAsArrayBuffer(f);
+ }
+}
+
+function handleDragOver(evt){
+ evt.stopPropagation();
+ evt.preventDefault();
+ evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
+}
+</script>
+</head>
+<body>
+<h1>ELCC-IDE</h1>
+<div style="float:left;">
+ <h2>mainWindow</h2>
+ <canvas id="mainWindowCanvas" width="640" height="480" style="border:1px solid #000000;"></canvas>
+ <h2>Internal Information</h2>
+ <input type="checkbox" onchange="">message</input><br />
+ <textarea id="debugMessageText" cols="66" rows="16"></textarea>
+ <form onsubmit="return false;">
+ <button onclick="compile();">Compile</button>
+ <button onclick="run();">Run</button>
+ <button onclick="mainCPU.stopFlag = true;">Break</button><br />
+ <button onclick="enableDebugMode();">EnableDebugMode</button>
+ <button onclick="disableDebugMode();">DisableDebugMode</button>
+ </form>
+</div>
+<div style="float:left;">
+ <h2>Code</h2>
+ <textarea id="codeText" cols="80" rows="48" wrap="off">
+unsigned char table[32] = {
+ 196, 100, 187, 61, 164, 29, 129, 9,
+ 90, 5, 53, 17, 23, 44, 7, 81,
+ 7, 119, 23, 156, 53, 183, 90, 195,
+ 129, 191, 164, 171, 187, 139, 196, 100,
+};
+
+procedure inline drawLine(int mode, x0, y0, x1, y1, col){
+ @asm OSECPU
+ REMARK 05 0100000003;
+ R30 = 0xff45;
+ R31 = mode;
+ R32 = x0;
+ R33 = y0;
+ R34 = x1;
+ R35 = y1;
+ R36 = col;
+ CALL P28;
+ REMARK 01 00;
+ @end
+}
+
+procedure main()
+{
+ int x0, y0, x1, y1, col, i, j;
+ unsigned char *p, *q;
+
+ p = table;
+ for (i = 0; i != 15; i++) {
+ x0 = *p;
+ p++;
+ y0 = *p;
+ p++;
+
+ q = table;
+ for (j = -8; j != 8; j++) {
+ x1 = *q;
+ q++;
+ y1 = *q;
+ q++;
+ col = i - j;
+ if (col <= 0){
+ col = 1 - col;
+ }
+ if (col <= 7) {
+ drawLine(1 + 4, x0, y0, x1, y1, col);
+ }
+ }
+ }
+}
+ </textarea>
+ <div id="fileDropZone">Drop SourceCode.elc here</div>
+ <div id="fileList"></div>
+</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+include = function(relpath){
+ document.write("<script type='text/javascript' src=" + relpath + " charset='UTF-8'></script>");
+}
+//AI004
+include("./../aiext.js");
+//WebCPU
+include("./../webcpu/api.js");
+include("./../webcpu/ext.js");
+include("./../webcpu/api.js");
+include("./../webcpu/decoder.js");
+include("./../webcpu/memory.js");
+include("./../webcpu/instrbas.js");
+include("./../webcpu/instr.js");
+include("./../webcpu/webcpu.js");
+include("./../webcpu/const.js");
+//ELCC
+include("./elcc.js");
+include("./elcexpr.js");
+
this.height = this.canvasDOMObject.height;
this.bufferImageData = this.canvasContext.getImageData(0, 0, this.width, this.height);
this.bmp = this.bufferImageData.data;
- console.log(this.bufferImageData);
- //
- /*
- for(var i = 0; i < 100; i += 2){
- this.drawLine(0, i, 100, i, 0xffffff, 0);
- }
- var x0 = 10;
- var y0 = 10;
- var x1 = 60;
- var y1 = 11;
- this.drawLine(x0, y0, x1, y1, 0xff0000, 0);
- this.drawLine(x1, y1, x0, y0, 0x00ff00, 1);
- */
- this.flush();
} else{
this.bmp = null;
this.canvasContext = null;
//命令クラス共通部分
//バックエンドバイナリでの命令先頭バイトのオフセット
this.binOffset = 0;
+ this.instrID = instrID;
}
WebCPU_Instruction.prototype = {
// loadArguments, execute, toStringが必須。
*WebCPU-VM
-By hikarupsp 2013-2014 for OSECPU-VM
+By [[hikarupsp]] 2013-2014 for OSECPU-VM
**これは何?
-OSECPU-VMのJavaScript実装です。
-JavaScriptは、ほとんどの場合ウェブブラウザさえあれば実行できる言語なので、より多くの環境でOSECPUコードを実行させることができます。
-また、HTML5技術(Canvas)と連携することで、ウェブページに直接OSECPUコードを埋め込むこともできるようになるでしょう。
-これは、テキストを直接転送しているHTMLにとって、データの転送量を削減することにもつながります。
+-OSECPU-VMのJavaScript実装です。
+-テストページ
+--準備中です…
+-Gitリポジトリ
+--http://sourceforge.jp/projects/chnosproject/scm/git/AI004/
+--webcpuディレクトリにすべてが入っています。(index.htmlがフロントエンド)
+--webcpuディレクトリ単体で動作します。elcc(OSECPU用コンパイラ)との関係でリポジトリは統合しました
+-JavaScriptは、ほとんどの場合ウェブブラウザさえあれば実行できる言語なので、より多くの環境でOSECPUコードを実行させることができます。
+-また、HTML5技術(Canvas)と連携することで、ウェブページに直接OSECPUコードを埋め込むこともできるようになるでしょう。
+--これは、テキストを直接転送しているHTMLにとって、データの転送量を削減することにもつながります。
**動作環境
動作を確認している環境は以下の通りです。(app0023フロントエンドコードテキストのStepInMs実行にて確認。)
-Chrome (Mac OSX, Windows)
+
+以下の環境でも動作するかもしれません。
-Safari (Mac OSX, iOS)
-Browser (Android)
-InternetExplorer9 (Windows)
-**現在の状況は?
--アプリケーションバイナリのフロントエンドコードHex文字列を実行し、その結果を表示することができます。
--実行バイナリをドラッグ&ドロップで直接読み込ませ、実行させることができます(HTML5FileAPI対応ブラウザに限ります)。
--バックエンド命令はほとんどが実装されていますが、APIおよびメモリ関連の一部の命令は未実装です。
+**できるようになったこと
+-フロントエンドコードの実行(decoder.oseを利用)
+-グラフィック関連APIのmode指定の反映(PSET,OR,XOR,AND等)
+-バイナリファイルの直接実行
+--FileAPI対応ブラウザ(Chrome等)が必要です。
+**今はできないこと(できる範囲で実装します)
+-半分くらいのAPI
+--ユーザー入力が必要なAPI
+--メモリ操作が必要なAPI
**使い方は?
組み込んで使用する方は、index.htmlのサンプルコードを見ていただければ、だいたいはわかると思います。
-デバッグモードについて
デバッグモード時は、実行中のレジスタ情報と現在実行中の命令について詳細を確認しながら実行できます。
負荷のかかるアプリケーションを実行する際は、デバッグモードを無効にするのがよいでしょう。
+
+**技術情報
+[[hikarupsp_WebCPU-VM_internal]]を参照してください。
+
+
this.memoryPageCounter = 0;
this.memoryInstructionCounter = 0;
+ this.reset();
},
loadFrontEndBinaryText: function(binStr){
//引数はフロントエンドコードのHex文字列表現でスペースなどの他の文字の混入は認められない。
this.memoryPageCounter = 0;
this.memoryInstructionCounter = 0;
this.stopFlag = false;
- //
+ //reset window
+ if(this.API.mainWindowCanvas){
+ this.API.setMainWindowCanvasDOMObject(this.API.mainWindowCanvas);
+ }
this.message("<<< Reset >>>\n");
},
fetchMemoryNext: function(){
this.API.setMainWindowCanvasDOMObject(document.getElementById(id));
},
setDebugMessageDOMObject: function(name){
- this.debugMessageText = document.getElementsByName(name)[0];
+ if(name){
+ this.debugMessageText = document.getElementsByName(name)[0];
+ if(!this.debugMessageText){
+ this.debugMessageText = document.getElementById(name);
+ }
+ } else{
+ this.debugMessageText = null;
+ }
this.setDebugTimer();
},
setDebugIntegerRegisterDOMObject: function(name){
- this.debugIntegerRegisterText = document.getElementsByName(name)[0];
+ if(name){
+ this.debugIntegerRegisterText = document.getElementsByName(name)[0];
+ if(!this.debugIntegerRegisterText){
+ this.debugIntegerRegisterText = document.getElementById(name);
+ }
+ } else{
+ this.debugIntegerRegisterText = null;
+ }
this.setDebugTimer();
},
setDebugPointerRegisterDOMObject: function(name){
this.debugPointerRegisterText = document.getElementsByName(name)[0];
+ if(name){
+ this.debugPointerRegisterText = document.getElementsByName(name)[0];
+ if(!this.debugPointerRegisterText){
+ this.debugPointerRegisterText = document.getElementById(name);
+ }
+ } else{
+ this.debugPointerRegisterText = null;
+ }
this.setDebugTimer();
},
setDebugTimer: function(){