//表示処理
if(this.messageBox && this.messageBoxBuffer != ""){
//messageBox
- var str = this.messageBox.innerHTML + this.messageBoxBuffer;
+ var str = this.messageBox.value + this.messageBoxBuffer;
this.messageBoxBuffer = "";
if(str.length > this.maxMessageStringLength){
str = str.slice(str.length - (this.maxMessageStringLength >> 1));
}
- this.messageBox.innerHTML = str;
+ this.messageBox.value = str;
this.messageBox.scrollTop = this.messageBox.scrollHeight;
}
if(this.debugBox && this.debugBoxBuffer != ""){
//debugBox
- var str = this.debugBox.innerHTML + this.debugBoxBuffer;
+ var str = this.debugBox.value + this.debugBoxBuffer;
this.debugBoxBuffer = "";
if(str.length > this.maxDebugStringLength){
str = str.slice(str.length - (this.maxDebugStringLength >> 1));
}
- this.debugBox.innerHTML = str;
+ this.debugBox.value = str;
this.debugBox.scrollTop = this.debugBox.scrollHeight;
}
},
var that = this;
var cc = new ELCHNOSCompiler(function(s){ that.debug(s); }, this.downloadBox);
- if(cc.compile(str) == null){
+ if(cc.compile(str) != null){
cc.saveBinary();
}
"-",
"*",
"/",
+ "#",
],
errorMessageList: [
"Trap.",
- "Incompatible value attribute.",
+ "Incompatible attribute.",
"Unexpected identifier.",
"Unknown assembly language type.",
"Invalid expression of OSECPU Binary.",
this.pointerRegisterAllocationTable = new Array();
},
compile: function(str){
- //戻り値nullでコンパイル成功
+ //戻り値はコンパイルされたバイナリのHex文字列。nullの場合コンパイル失敗。
this.reset();
//
this.line = str.split("\n");
this.expandBinaryString();
this.assignRegister();
this.bin.logAsHexByte(this.debug);
- this.debug("\n");
+ this.debug("(" + this.bin.length + "Bytes)\n");
//
-
+ //最適化(試験中)
//
var cpu = new WebCPU();
cpu.loadBinaryText(this.bin.stringAsHexByte());
cpu.staticOptimize();
- this.debug(cpu.createBackendBinaryString());
- this.debug("\n");
+ var binStr = cpu.createBackendBinaryString();
+ this.debug(binStr);
+ this.debug("(" + (binStr.length >> 1) + "Bytes)\n");
//
} catch(e){
//全エラー処理
if(e instanceof ELCHNOSCompiler_CompileException){
this.debug(e.getMessageString());
- return e;
+ return null;
} else{
throw e;
}
}
- return null;
+ return binStr;
},
compile_removeComment: function(){
//コメント削除
for(var i = 0, iLen = this.separated.length; i < iLen; i++){
var s = this.separated[i];
if(commentLineStartIndex == -1){
- if(s == "//"){
+ if(s == "//" || s == "#"){
//行コメント開始
commentLineStartIndex = i;
}
}
},
expandBinaryString: function(){
+ //入れ子構造になっている配列を一次元配列に展開して返す。
var ary = this.bin;
var b = new Array();
var aryStack = new Array();
}
if(url){
if(this.downloadBoxDOMObject){
- this.downloadBoxDOMObject.innerHTML = "<a href='" + url + "' target='_blank'>ダウンロード</a>";
+ this.downloadBoxDOMObject.innerHTML = "<a href='" + url + "' target='_blank'>右クリックしてダウンロード</a>";
} else{
this.debug("BinarySaved: " + url + "\n");
}
onload = function(){
debugMessageTextArea = document.getElementById('debugMessageText');
mainCPU = new WebCPU();
- mainCompiler = new ELCHNOSCompiler(messageOut);
+ mainCompiler = new ELCHNOSCompiler(messageOut, document.getElementById('downloadBox'));
mainCPU.setMainWindowCanvasDOMObject("mainWindowCanvas");
enableDebugMode();
function compile(){
debugMessageTextArea.value += "****Compile Started****\n";
- if(mainCompiler.compile(codeTextArea.value) == null){
+ binStr = mainCompiler.compile(codeTextArea.value);
+ if(binStr != null){
messageOut("*\n****Compile Succeeded!****\n*\n");
- binStr = mainCompiler.bin.stringAsHexByte()
} else{
messageOut("*\n****Compile Failed...****\n*\n");
- binStr = null;
}
}
if(binStr){
mainCPU.loadBinaryText(binStr);
mainCPU.execute();
+ } else{
+ messageOut("run: No available binary.\n");
+ }
+}
+
+function showAssembly(){
+ if(binStr){
+ mainCPU.loadBinaryText(binStr);
+ } else{
+ messageOut("showAssembly: No available binary.\n");
}
}
var r = new FileReader();
r.onload = (function(file){
return function(e){
- var a = r.result;
- codeTextArea.value = a;
+ codeTextArea.value = r.result;
}
})(f);
- r.readAsArrayBuffer(f);
+ r.readAsText(f);
}
}
<body>
<h1>ELCC-IDE</h1>
<div style="float:left;">
- <h2>mainWindow</h2>
+ <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 />
+ <h3>Message</h3>
<textarea id="debugMessageText" cols="66" rows="16"></textarea>
<form onsubmit="return false;">
<button onclick="compile();">Compile</button>
+ <button onclick="showAssembly();">Show Assembly</button>
<button onclick="run();">Run</button>
- <button onclick="mainCPU.stopFlag = true;">Break</button><br />
+ <button onclick="mainCPU.stopFlag = true;">Break</button>
+ <br />
<button onclick="enableDebugMode();">EnableDebugMode</button>
<button onclick="disableDebugMode();">DisableDebugMode</button>
+ <br />
+ <button onclick="if(binStr){ mainCompiler.saveBinary(); }">Create bin.ose</button>
+
</form>
+ <h3>Downloads</h3>
+ <div id="downloadBox"></div>
</div>
<div style="float:left;">
<h2>Code</h2>
}
</textarea>
<div id="fileDropZone">Drop SourceCode.elc here</div>
- <div id="fileList"></div>
</div>
</body>
</html>
\ No newline at end of file
for(var i = 0; i < this.registers.Pointer[0x02].addressOffset; i++){
binStr += ("00" + binData.data[i].toString(16)).slice(-2);
}
- this.message("[" + binStr + "]\n");
+ this.message("[" + binStr + "](" + (binStr.length >> 1) + "Bytes)\n");
this.loadBackEndBinaryText(binStr);
this.reset();
} else{
},
debugShowTick: function(){
if(this.debugMessageText && this.debugMessageBuffer != ""){
- var str = this.debugMessageText.innerHTML + this.debugMessageBuffer;
+ var str = this.debugMessageText.value + this.debugMessageBuffer;
this.debugMessageBuffer = "";
if(str.length > WebCPU.maxDebugStringLength){
str = str.slice(str.length - (WebCPU.maxDebugStringLength >> 1));
}
- this.debugMessageText.innerHTML = str;
+ this.debugMessageText.value = str;
this.debugMessageText.scrollTop = this.debugMessageText.scrollHeight;
}
this.refreshDebugIntegerRegisterText();
},
refreshDebugIntegerRegisterText: function(){
if(this.debugIntegerRegisterText != null){
- this.debugIntegerRegisterText.innerHTML = "";
+ this.debugIntegerRegisterText.value = "";
for(var i = 0; i < this.registers.Integer.length; i++){
- this.debugIntegerRegisterText.innerHTML += "R" + ("00" + i.toString(16)).slice(-2).toUpperCase() + ":0x" + this.registers.Integer[i].toString(16).toUpperCase() + "\n";
+ this.debugIntegerRegisterText.value += "R" + ("00" + i.toString(16)).slice(-2).toUpperCase() + ":0x" + this.registers.Integer[i].toString(16).toUpperCase() + "\n";
}
}
},
refreshDebugPointerRegisterText: function(){
if(this.debugPointerRegisterText != null){
- this.debugPointerRegisterText.innerHTML = "";
+ this.debugPointerRegisterText.value = "";
for(var i = 0; i < this.registers.Pointer.length; i++){
if(this.registers.Pointer[i]){
- this.debugPointerRegisterText.innerHTML += "P" + ("00" + i.toString(16)).slice(-2).toUpperCase() + ":" + this.registers.Pointer[i].toString() + "\n";
+ this.debugPointerRegisterText.value += "P" + ("00" + i.toString(16)).slice(-2).toUpperCase() + ":" + this.registers.Pointer[i].toString() + "\n";
} else{
- this.debugPointerRegisterText.innerHTML += "P" + ("00" + i.toString(16)).slice(-2).toUpperCase() + ":(null)\n";
+ this.debugPointerRegisterText.value += "P" + ("00" + i.toString(16)).slice(-2).toUpperCase() + ":(null)\n";
}
}
}
},
staticOptimize: function(){
//静的最適化
+ this.staticOptimize_RemoveDuplicatedLabelNumber();
+ this.staticOptimize_CMPxx_CND_PLIMM_PLIMM_LB();
+ this.staticOptimize_RemoveUnusedLabelNumber();
+ },
+ staticOptimize_RemoveDuplicatedLabelNumber: function(){
//連続するラベル命令の削除
//一つのメモリページにラベル命令のみがある場合は、それを次のメモリページのラベル名に置換する
var mpage;
}
}
if(labelIDStack.length != 0){
- //ã\83\97ã\83ã\82°ã\83©ã\83 æ\9c«å°¾ã\81®ã\83©ã\83\99ã\83«å\91½ä»¤ã\81¯å\89\8aé\99¤ã\81\97ã\81ªã\81\84ã\82\88ã\81\86ã\81«ã\81\99ã\82\8b
+ //ã\83\97ã\83ã\82°ã\83©ã\83 æ\9c«å°¾ã\81®ã\83©ã\83\99ã\83«å\91½ä»¤ã\81¯å\89\8aé\99¤ã\81\97ã\81ªã\81\84ã\80\82
newLabelID = labelIDStack.pop();
for(;;){
labelID = labelIDStack.pop();
}
},
staticOptimize_ReplaceLabelNumber: function(from, to){
+ //PLIMM命令のラベル番号がfromのものをtoに変更する。
var mpage;
var instr;
for(var i = 0, iLen = this.mainMemory.root.length; i < iLen; i++){
}
}
}
- }
+ },
+ staticOptimize_RemoveUnusedLabelNumber: function(){
+ var usedLabelNumberList = new Array();
+ var mpage;
+ var instr;
+ //使われているラベル番号のリスト生成
+ for(var i = 0, iLen = this.mainMemory.root.length; i < iLen; i++){
+ mpage = this.mainMemory.root[i];
+ for(var j = 0, jLen = mpage.data.length; j < jLen; j++){
+ instr = mpage.data[j];
+ if(instr instanceof WebCPU_Instruction_PLIMM){
+ usedLabelNumberList.pushUnique(instr.imm32);
+ }
+ }
+ }
+ //ラベルを走査し、不要なラベル番号を削除
+ for(var i = 0; i < this.mainMemory.root.length; i++){
+ mpage = this.mainMemory.root[i];
+ if(mpage instanceof WebCPU_MemoryPage && mpage.data[0] instanceof WebCPU_Instruction_LB){
+ if(mpage.data[0].opt == 1 || usedLabelNumberList.isIncluded(mpage.data[0].imm32)){
+ //使われている、もしくはグローバルなラベル番号
+ } else{
+ //未参照のローカルラベル番号
+ //ひとまずラベル命令削除
+ mpage.data.splice(0, 1);
+ if(i != 0){
+ //一つ前のページに統合
+ this.mainMemory.root[i - 1].data = this.mainMemory.root[i - 1].data.concat(mpage.data);
+ //このページを削除
+ this.mainMemory.root.splice(i, 1);
+ i--;
+ }
+ }
+ }
+ }
+ },
+ staticOptimize_CMPxx_CND_PLIMM_PLIMM_LB: function(){
+ //From:
+ //>CMPxx(Ra, --, --);
+ //CND(Ra);
+ //>PLIMM(P3F, b);
+ //PLIMM(P3F, --);
+ //----
+ //LB(opt:--, b);
+ //
+ //To:
+ //>CMP!(xx)(Ra, --, --);
+ //CND(Ra);
+ //PLIMM(P3F, --);
+ //----
+ //LB(opt:--, b);
+
+ //これより後にstaticOptimize_RemoveUnusedLabelNumberを実行することを推奨する。
+ //CMP系命令は、InstrIDが偶数の場合+1, 奇数の場合-1することで逆の条件になる。
+ //CMP系:20-2D
+ var mode = 0;
+ var rega;
+ var immb;
+ //0:次は CMPxx(Ra, --, --);
+ //1:次は CND(Ra);
+ //2:次は PLIMM(P3F, b);
+ //3:次は PLIMM(P3F, --);
+ //4:次は LB(opt:--, b);
+ for(var i = 0, iLen = this.mainMemory.root.length; i < iLen; i++){
+ mpage = this.mainMemory.root[i];
+ for(var j = 0, jLen = mpage.data.length; j < jLen; j++){
+ instr = mpage.data[j];
+ switch(mode){
+ case 0:
+ if(instr instanceof WebCPU_Instruction_TernaryOperation && 0x20 <= instr.instrID && instr.instrID <= 0x2D){
+ //CMPxx(Ra, --, --);
+ rega = instr.reg0;
+ mode++;
+ }
+ break;
+ case 1:
+ if(instr instanceof WebCPU_Instruction_CND && instr.reg0R == rega){
+ //CND(Ra);
+ mode++;
+ } else{
+ mode = 0;
+ }
+ break;
+ case 2:
+ if(instr instanceof WebCPU_Instruction_PLIMM && instr.reg0 == 0x3f){
+ //PLIMM(P3F, b);
+ immb = instr.imm32;
+ mode++;
+ } else{
+ mode = 0;
+ }
+ break;
+ case 3:
+ if(instr instanceof WebCPU_Instruction_PLIMM && instr.reg0 == 0x3f){
+ //PLIMM(P3F, --);
+ mode++;
+ } else{
+ mode = 0;
+ }
+ break;
+ case 4:
+ if(instr instanceof WebCPU_Instruction_LB && instr.imm32 == immb){
+ //LB(opt:--, b);
+ //置換対象確定
+ mpage = this.mainMemory.root[i - 1];
+ //CMPxx(Ra, --, --); -> CMP!(xx)(Ra, --, --);
+ instr = mpage.data[mpage.data.length - 4];
+ if((instr.instrID & 0x01) == 0){
+ instr.instrID++;
+ } else{
+ instr.instrID--;
+ }
+ instr.setParameter(instr.reg0, instr.reg1, instr.reg2);
+ //Remove PLIMM(P3F, b);
+ mpage.data.splice(mpage.data.length - 2, 1);
+ }
+ mode = 0;
+ break;
+ }
+ }
+ }
+ },
}
//数値計算