OSDN Git Service

57f9e62fe6f940e5f6397d17b7438b101abf5894
[chnosproject/AI004.git] / elcc / elcc.js
1 // ELCHNOSCompiler for AI004
2
3 //手順:
4 //トークン分割
5 //構造解析・式の逆ポーランド化
6 //中間バイナリ化
7
8 function ELCHNOSCompiler_CompileException(errno, infoArray, lineCount){
9         this.errno = errno;
10         this.infoArray = infoArray;
11         this.lineCount = lineCount;
12 }
13 ELCHNOSCompiler_CompileException.prototype = {
14         errorMessageList: [
15                 "Trap.",
16                 "Incompatible value attribute.",
17                 "Unexpected identifier.",
18                 "Unknown assembly language type.",
19                 "Invalid expression of OSECPU Binary.",
20                 "Binary translation error.",
21         ],
22         getMessageString: function(){
23                 var s = "";
24                 if(!isNaN(this.lineCount)){
25                         s += this.lineCount + ":";
26                 }
27                 s += "Error" + this.errno.toString().toUpperCase();
28                 if(this.errno < 0 || this.errorMessageList.length <= this.errno){
29                         s += ":Unknown\n";
30                 } else{
31                         s += ":" + this.errorMessageList[this.errno] + "\n";
32                 }
33                 if(this.infoArray){
34                         s += "  >" + this.infoArray.toString() + "\n";
35                 }
36                 return s;
37         },
38 }
39 // throw new ELCHNOSCompiler_CompileException(5, [""], this.lineCount);
40
41
42 function ELCHNOSCompiler(env){
43         this.env = env;
44         
45         this.line = null;
46         this.separated = null;
47         this.bin = new Array();
48         
49         this.structure = new Array();
50         this.currentStructure = this.structure;
51         this.structureStack = new Array();
52         
53         //0はエントリポイント(main)用に予約
54         this.nextLabelID = 1;
55         this.integerRegisterAllocationTable = new Array();
56         this.pointerRegisterAllocationTable = new Array();
57 }
58 ELCHNOSCompiler.prototype = {
59         keyWordList: [
60                 "@asm",
61                 "@end",
62                 "//",
63                 "/*",
64                 "*/",
65                 "!=",
66                 "==",
67                 "+=",
68                 "-=",
69                 "*=",
70                 "/=",
71                 "<=",
72                 "++",
73                 "--",
74                 "\n",
75                 "\t",
76                 " ",
77                 "{",
78                 "}",
79                 "(",
80                 ")",
81                 ";",
82                 ",",
83                 "[",
84                 "]",
85                 "=",
86                 "+",
87                 "-",
88                 "*",
89                 "/",
90         ],
91         errorMessageList: [
92                 "Trap.",
93                 "Incompatible value attribute.",
94                 "Unexpected identifier.",
95                 "Unknown assembly language type.",
96                 "Invalid expression of OSECPU Binary.",
97                 "Binary translation error.",
98         ],
99         
100         Flag_Sign_Signed                        : 0x00000001,
101         Flag_Sign_Unsigned                      : 0x00000002,
102         
103         compile: function(str){
104                 this.line = str.split("\n");
105                 //分割
106                 this.separated = str.splitByArraySeparatorSeparatedLong(this.keyWordList);
107                 //コメント除去
108                 this.compile_removeComment();
109                 
110                 //不要な文字を削除
111                 this.separated.removeAllObject("\t");
112                 this.separated.removeAllObject(" ");
113                 
114                 //メイン処理
115                 var currentExpression = null;
116                 var numValSignFlag = 0;
117                 var numValBits = 0;
118                 var pointerCount = 0;
119                 var lineCount = 1;
120                 var mode = 0;
121                 var o;
122                 var f;
123                         //次に期待する値を示す。
124                         // 0: 何が来るかわからない
125                         //
126                         //10: 変数・定数の前置属性・型・または識別子
127                         //11: 変数・定数の識別子またはポインタ属性
128                         //12: 変数・定数の後置属性・初期化式または終端記号、もしくは連続した変数宣言の区切り
129                         //13: 変数・定数の初期化式または終端記号、もしくは連続した変数宣言の区切り
130                         //14: 配列長の数値部分
131                         //15: 配列長指定終了の閉じ括弧
132                         //16: 初期化式の開始括弧もしくは値
133                         //17: 初期化式の値部分または終了括弧
134                         //18: 初期化式の区切りまたは終了括弧
135                         //19: 終端記号
136                         //
137                         //50: 関数名または関数属性
138                         //51: 引数開始括弧
139                         //52: 引数or引数終了括弧
140                         //53: 引数区切りor引数終了括弧
141                         //54: 関数内部開始括弧
142                         //
143                         //60: 評価式の内容または終端記号
144                         //
145                         //70: OSECPUアセンブリ直接記述モード
146                         //71: OSECPUアセンブリ評価式の内容または終端記号
147                 try{
148                         for(var i = 0, iLen = this.separated.length; i < iLen; i++){
149                                 var s = this.separated[i].toLowerCase();
150                                 
151                                 if(s == "\n"){
152                                         //デバッグ用行数カウント
153                                         lineCount++;
154                                         continue;
155                                 //予約語
156                                 } else if(s == "signed" && (mode == 0 || mode == 10)){
157                                         //符号あり
158                                         if(numValSignFlag != 0){
159                                                 throw new ELCHNOSCompiler_CompileException(1, [s], lineCount);
160                                         }
161                                         numValSignFlag |= this.Flag_Sign_Signed;
162                                         mode = 10;
163                                 } else if(s == "unsigned" && (mode == 0 || mode == 10)){
164                                         //符号なし
165                                         if(numValSignFlag != 0){
166                                                 throw new ELCHNOSCompiler_CompileException(1, [s], lineCount);
167                                         }
168                                         numValSignFlag |= this.Flag_Sign_Unsigned;
169                                         mode = 10;
170                                 } else if(s == "char"  && (mode == 0 || mode == 10 || mode == 11 || mode == 52)){
171                                         //char 8bit符号あり
172                                         numValBits = 8;
173                                         if(mode == 0 || mode == 10 || mode == 11){
174                                                 mode = 11;
175                                         }
176                                 } else if(s == "int" && (mode == 0 || mode == 10 || mode == 11 || mode == 52)){
177                                         //int 32bit符号あり
178                                         numValBits = 32;
179                                         if(mode == 0 || mode == 10 || mode == 11){
180                                                 mode = 11;
181                                         }
182                                 } else if(s == ";" && (mode == 0 || mode == 12 || mode == 13 || mode == 19 || mode == 60 || mode == 71)){
183                                         if(mode == 12 || mode == 13 || mode == 19){
184                                                 //変数または定数の定義終了
185                                                 numValBits = 0;
186                                                 numValSignFlag = 0;
187                                                 currentExpression = null;
188                                                 mode = 0;
189                                         } else if(mode == 60 || mode == 71){
190                                                 //評価式終端
191                                                 currentExpression = null;
192                                                 if(mode == 60){
193                                                         mode = 0;
194                                                 } else if(mode == 71){
195                                                         mode = 70;
196                                                 }
197                                         } else{
198                                                 throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
199                                         }
200                                 } else if(s == "=" && (mode == 13)){
201                                         if(mode == 13){
202                                                 //変数・定数初期化式開始
203                                                 mode = 16;
204                                         } else{
205                                                 throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
206                                         }
207                                 } else if(s == "*" && (mode == 11)){
208                                         //ポインタ属性の付加
209                                         pointerCount++;
210                                 } else if(s == "," && (mode == 18 || mode == 12 || mode == 13 || mode == 53)){
211                                         if(mode == 18){
212                                                 //初期化式の区切り
213                                                 mode = 17;
214                                         } else if(mode == 12 || mode == 13 || mode == 53){
215                                                 //連続した変数宣言の区切り
216                                                 if(mode == 12 || mode == 13){
217                                                         mode = 11;
218                                                 } else if(mode == 53){
219                                                         mode = 52;
220                                                 }
221                                                 currentExpression = null;
222                                         } else{
223                                                 throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
224                                         }
225                                 //括弧系
226                                 } else if(s == "[" && (mode == 12)){
227                                         //配列の長さの定義開始
228                                         mode = 14;
229                                 } else if(s == "]" && (mode == 15)){
230                                         //配列の長さの定義終了
231                                         mode = 13;
232                                 } else if(s == "{" && (mode == 16 || mode == 54)){
233                                         if(mode == 16){
234                                                 //初期化式の開始括弧
235                                                 mode = 17;
236                                         } else if(mode == 54){
237                                                 //54: 関数内部開始括弧
238                                                 currentExpression = null;
239                                                 mode = 0;
240                                         } else{
241                                                 throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
242                                         }
243                                 } else if(s == "}" && (mode == 17 || mode == 18 || mode == 0)){
244                                         if(mode == 17 || mode == 18){
245                                                 //初期化式の終了括弧
246                                                 mode = 19;
247                                         } else if(mode == 0){
248                                                 if(this.structureStack.length > 0){
249                                                         this.restoreCurrentStructure();
250                                                 } else{
251                                                         throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
252                                                 }
253                                         }
254                                 } else if(s == "(" && (mode == 51)){
255                                         //51: 引数開始括弧
256                                         mode = 52;
257                                 } else if(s == ")" && (mode == 52 || mode == 53)){
258                                         //52: 引数or引数終了括弧
259                                         //53: 引数区切りor引数終了括弧
260                                         currentExpression = null;
261                                         for(var j = 0, jLen = this.currentStructure.length; j < jLen; j++){
262                                                 //引数番号を付与
263                                                 this.currentStructure[j].argumentIndex = j;
264                                         }
265                                         mode = 54;
266                                 } else if(s == "@asm" && (mode == 0)){
267                                         i++;
268                                         s = this.separated[i].toLowerCase();
269                                         if(s == "osecpu"){
270                                                 mode = 70;
271                                         } else{
272                                                 throw new ELCHNOSCompiler_CompileException(3, [s], lineCount);
273                                         }
274                                 } else if(s == "@end" && (mode == 70)){
275                                         mode = 0;
276                                 //リストにない予約語
277                                 } else if(s == "procedure" && (mode == 0)){
278                                         //関数宣言
279                                         var f = new ELCHNOSCompiler_ExpressionStructure_Function(this, lineCount);
280                                         this.currentStructure.push(f);
281                                         this.changeCurrentStructure(f.structure);
282                                         currentExpression = f;
283                                         
284                                         mode = 50;
285                                 } else if(s == "inline" && (mode == 50)){
286                                         currentExpression.isInline = true;
287                                 } else if(s == "for" && (mode == 0)){
288                                         //forループ
289                                         i++;
290                                         s = this.separated[i];
291                                         if(s == "("){
292                                                 var f = new ELCHNOSCompiler_ExpressionStructure_Loop_for(this, lineCount);
293                                                 this.currentStructure.push(f);
294                                                 this.changeCurrentStructure(f.structure);
295                                                 currentExpression = f;
296                                                 //初期化式
297                                                 f.initializer = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
298                                                 i = f.initializer.readExpressionToTerminator(i, ";");
299                                                 //条件評価式
300                                                 f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
301                                                 i = f.conditonalExpression.readExpressionToTerminator(i, ";");
302                                                 //更新式
303                                                 f.incrementalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
304                                                 i = f.incrementalExpression.readExpressionToTerminator(i, ")");
305                                                 //開始括弧
306                                                 i++;
307                                                 if(this.separated[i] != "{"){
308                                                         throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
309                                                 }
310                                                 currentExpression = null;
311                                         } else{
312                                                 throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
313                                         }
314                                 } else if(s == "if" && (mode == 0)){
315                                         //if文
316                                         //条件評価式-?>L2
317                                         //実行部分
318                                         //(break->L2)
319                                         //L2:
320                                         i++;
321                                         s = this.separated[i];
322                                         if(s == "("){
323                                                 var f = new ELCHNOSCompiler_ExpressionStructure_if(this, lineCount);
324                                                 this.currentStructure.push(f);
325                                                 this.changeCurrentStructure(f.structure);
326                                                 currentExpression = f;
327                                                 //条件評価式
328                                                 f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
329                                                 i = f.conditonalExpression.readExpressionToTerminator(i, ")");
330                                                 //開始括弧
331                                                 i++;
332                                                 if(this.separated[i] != "{"){
333                                                         throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
334                                                 }
335                                                 currentExpression = null;
336                                         } else{
337                                                 throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
338                                         }
339                                 //OSECPUアセンブリ
340                                 } else if(s == "remark" && (mode == 70)){
341                                         //超手抜き
342                                         var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this, lineCount);
343                                         this.currentStructure.push(b);
344                                         //FE    len     ...
345                                         b.bin.push(0xfe);
346                                         //len
347                                         i++;
348                                         s = this.separated[i];
349                                         if(s.length == 2){
350                                                 var len = parseInt(s, 16);
351                                                 b.bin.push(len);
352                                         } else{
353                                                 throw new ELCHNOSCompiler_CompileException(4, [s], lineCount);
354                                         }
355                                         //data
356                                         i++;
357                                         s = this.separated[i];
358                                         if(s.length == len * 2){
359                                                 for(var j = 0; j < len; j++){
360                                                         b.bin.push(parseInt(s.substr(j * 2, 2), 16));
361                                                 }
362                                         } else{
363                                                 throw new ELCHNOSCompiler_CompileException(4, [s], lineCount);
364                                         }
365                                         //終端
366                                         i++;
367                                         if(this.separated[i] != ";"){
368                                                 throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
369                                         } else{
370                                                 //この命令は定数のみで構成されているのでコンパイル済みとマークする
371                                                 b.isCompiled = true;
372                                                 b = null;
373                                         }
374                                 } else if(s == "call" && (mode == 70)){
375                                         //超手抜き
376                                         var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this, lineCount);
377                                         this.currentStructure.push(b);
378                                         
379                                         //第二引数が何か確認する
380                                         i++;
381                                         s = this.separated[i].toLowerCase();
382                                         if((s.indexOf("p") == 0) && s.length == 3){
383                                                 //ポインタレジスタをcall
384                                                 //新しいラベル番号をもらう
385                                                 var labelID = this.allocateLabelID();
386                                                 //PLIMM(P30, labelID)
387                                                         //03    reg0    imm32
388                                                 b.bin.push(0x03);
389                                                 b.bin.push(0x30);
390                                                 b.appendInstruction_UINT32BE(labelID);
391                                                 //PCP(P3F, Pxx)
392                                                         //1E    reg0P   reg1P
393                                                 b.bin.push(0x1e);
394                                                 b.bin.push(0x3f);
395                                                 b.bin.push(parseInt(s.substr(1),16));
396                                                 
397                                                 b.appendInstruction_LB(0x01, labelID);
398                                                 //[FE] [01] [00]
399                                                 b.bin.push(0xfe);
400                                                 b.bin.push(0x01);
401                                                 b.bin.push(0x00);
402                                                 //終端記号
403                                                 i++;
404                                                 if(this.separated[i] != ";"){
405                                                         throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
406                                                 } else{
407                                                         //この命令は定数のみで構成されているのでコンパイル済みとマークする
408                                                         b.isCompiled = true;
409                                                         b = null;
410                                                 }
411                                         } else{
412                                                 throw new ELCHNOSCompiler_CompileException(0, [s], lineCount);
413                                         }
414                                 //予約語以外
415                                 } else if(mode == 11 || mode == 52){
416                                         //変数または定数の宣言
417                                         //52: 引数名
418                                         var v = new ELCHNOSCompiler_ExpressionStructure_Variable(this, lineCount);
419                                         v.bits = numValBits;
420                                         v.isSigned = (numValSignFlag == 0) ? false : (0 != (numValSignFlag & this.Flag_Sign_Signed));
421                                         s = this.separated[i];
422                                         v.isPointer = (pointerCount != 0) ? true : false;
423                                         pointerCount = 0;
424                                         if(s.length <= 0){
425                                                 throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
426                                         }
427                                         v.identifier = s;
428                                         this.currentStructure.push(v);
429                                         currentExpression = v;
430                                         //mode:11->12
431                                         //mode:52->53
432                                         mode++;
433                                 } else if(mode == 14){
434                                         currentExpression.length = parseInt(s);
435                                         mode = 15;
436                                 } else if(mode == 17){
437                                         //定数値のみ対応
438                                         currentExpression.initValue.push(parseInt(s));
439                                         mode = 18;
440                                 } else if(mode == 50){
441                                         //関数名
442                                         //大文字小文字を区別
443                                         currentExpression.identifier = this.separated[i];
444                                         mode = 51;
445                                 } else{
446                                         if(mode == 0 || mode == 70 || mode == 60 || mode == 71){
447                                                 //大文字小文字を区別
448                                                 s = this.separated[i];
449                                                 if(mode == 0 || mode == 70){
450                                                         //最初の左辺だったら追加処理
451                                                         var f = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
452                                                         this.currentStructure.push(f);
453                                                         currentExpression = f;
454                                                 }
455                                                 currentExpression.pushIdentifier(s);
456                                                 if(mode == 0){
457                                                         mode = 60;
458                                                 } else if(mode == 70){
459                                                         mode = 71;
460                                                 }
461                                         }
462                                 }
463                         }
464                         //中間バイナリ生成
465                         //バックエンドコードの中間表現を出力。
466                         //0x00-0xff: そのまま使えるバイナリ
467                         //0x10000000-0x1fffffff: 未決定の仮想整数レジスタ番号
468                         //0x20000000-0x2fffffff: 未決定の仮想ポインタレジスタ番号
469                         this.errno = 5;
470                         
471                         //OSECPUフロントエンドコードヘッダ
472                         this.bin.push(0x05, 0xe1, 0x00);
473                         
474                         for(var i = 0, iLen = this.structure.length; i < iLen; i++){
475                                 var b = this.structure[i].createBinary();
476                                 if(b !== undefined){
477                                         this.bin.push(b);
478                                 }
479                         }
480                         this.expandBinaryString();
481                         this.assignRegister();
482                         this.bin.logAsHexByte();
483                         var cpu = new WebCPU();
484                         cpu.loadBinaryText(this.bin.stringAsHexByte());
485                         cpu.staticOptimize();
486                         console.log(cpu.createBackendBinaryString());
487                         this.saveBinary();
488                 } catch(e){
489                         //全エラー処理
490                         if(e instanceof ELCHNOSCompiler_CompileException){
491                                 this.env.debug(e.getMessageString());
492                         } else{
493                                 throw e;
494                         }
495                 }
496         },
497         compile_removeComment: function(){
498                 //コメント削除
499                 var commentLineStartIndex = -1;
500                 var commentBlockStartIndex = -1;
501                 var commentBlockCount = 0;
502                 var linesInCommentBlock = 0;
503                 
504                 for(var i = 0, iLen = this.separated.length; i < iLen; i++){
505                         var s = this.separated[i];
506                         if(commentLineStartIndex == -1){
507                                 if(s == "//"){
508                                         //行コメント開始
509                                         commentLineStartIndex = i;
510                                 }
511                         } else{
512                                 if(s == "\n"){
513                                         //行コメント終了
514                                         var len = i - commentLineStartIndex;
515                                         this.separated.splice(commentLineStartIndex, len);
516                                         iLen -= len;
517                                         i -= len;
518                                         commentLineStartIndex = -1;
519                                 }
520                         }
521                         if(s == "/*"){
522                                 //ブロックコメント開始
523                                 if(commentBlockCount == 0){
524                                         commentBlockStartIndex = i;
525                                 }
526                                 commentBlockCount++;
527                         } else if(s == "*/"){
528                                 //ブロックコメント終了
529                                 commentBlockCount--;
530                                 if(commentBlockCount == 0){
531                                         var len = i - commentBlockStartIndex + 1;
532                                         var padding = new Array();
533                                         padding.push(commentBlockStartIndex);
534                                         padding.push(len);
535                                         for(var j = 0, jLen = linesInCommentBlock; j < jLen; j++){
536                                                 padding.push("\n");
537                                         }
538                                         this.separated.splice.apply(this.separated, padding);
539                                         i -= len - linesInCommentBlock;
540                                         iLen -= len - linesInCommentBlock;
541                                         linesInCommentBlock = 0;
542                                 } else if(commentBlockCount < 0){
543                                         this.env.debug("Too many block comment closure [].\n");
544                                         return;
545                                 }
546                         } else if(commentBlockCount > 0 && s == "\n"){
547                                 linesInCommentBlock++;
548                         }
549                 }
550         },
551         raiseError: function(errno, lineCount, infoArray){
552                 if(errno < 0 || this.errorMessageList.length <= errno){
553                         this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":Unknown\n");
554                 } else{
555                         this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":" + this.errorMessageList[errno] + "\n");
556                 }
557                 if(infoArray){
558                         this.env.debug("  >" + infoArray.toString() + "\n");
559                 }
560         },
561         changeCurrentStructure: function(newstructure){
562                 this.structureStack.push(this.currentStructure);
563                 this.currentStructure = newstructure;
564         },
565         restoreCurrentStructure: function(){
566                 this.currentStructure = this.structureStack.pop();
567         },
568         searchIdentifier: function(identifier){
569                 var o;
570                 var cf = function(aryobj, obj){ return (aryobj.identifier == obj) };
571                 
572                 o = this.currentStructure.isIncluded(identifier, cf);
573                 if(!o){
574                         for(var i = this.structureStack.length - 1; i >= 0; i--){
575                                 o = this.structureStack[i].isIncluded(identifier, cf);
576                                 if(o){
577                                         break;
578                                 }
579                         }
580                 }
581                 return o;
582         },
583         isOperator: function(s){
584                 return (
585                         s == "=" ||
586                         s == "+" ||
587                         s == "-" ||
588                         s == "*" ||
589                         s == "/" ||
590                         s == "!=" ||
591                         s == "++" ||
592                         s == "<" ||
593                         s == "(" ||
594                         s == ")"||
595                         s == "," ||
596                         false
597                 );
598         },
599         allocateLabelID: function(){
600                 this.nextLabelID++;
601                 return this.nextLabelID - 1;
602         },
603         virtualIntegerRegisterOffset: 0x10000000,
604         allocateIntegerRegister: function(owner){
605                 //レジスタテーブルは先頭から番号の小さい順につめて格納する。
606                 //[regID, owner]
607                 //0x10000000-0x1fffffff: 未決定の仮想整数レジスタ番号
608                 var freeRegID = 0;
609                 for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
610                         if(this.integerRegisterAllocationTable[i][0] != i + this.virtualIntegerRegisterOffset){
611                                 //空いているレジスタ番号を見つけた
612                                 if(i > 0x20){
613                                         this.integerRegisterAllocationTable.splice(i, 0, [i + this.virtualIntegerRegisterOffset, owner]);
614                                 }
615                         }
616                 }
617                 if(i == iLen){
618                         //途中に空いているレジスタはなかったので追加
619                         this.integerRegisterAllocationTable.push([i + this.virtualIntegerRegisterOffset, owner]);
620                 }
621                 return i + this.virtualIntegerRegisterOffset;
622         },
623         freeIntegerRegister: function(regID, owner){
624                 for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
625                         if(this.integerRegisterAllocationTable[i][0] == regID){
626                                 //レジスタ番号を見つけた
627                                 //オーナーが一致するか確認
628                                 if(this.integerRegisterAllocationTable[i][1] == owner){
629                                         //一致したので解放する
630                                         this.integerRegisterAllocationTable.splice(i, 1);
631                                 }
632                                 break;
633                         }
634                 }
635                 if(i == iLen){
636                         throw new ELCHNOSCompiler_CompileException(0, ["freeIntegerRegister:regID not found."], -1);
637                 }
638         },
639         virtualPointerRegisterOffset: 0x20000000,
640         allocatePointerRegister: function(owner){
641                 //レジスタテーブルは先頭から番号の小さい順につめて格納する。
642                 //[regID, owner]
643                 //0x20000000-0x2fffffff: 未決定の仮想ポインタレジスタ番号
644                 var freeRegID = 0;
645                 for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
646                         if(this.pointerRegisterAllocationTable[i][0] != i + this.virtualPointerRegisterOffset){
647                                 //空いているレジスタ番号を見つけた
648                                 this.pointerRegisterAllocationTable.splice(i, 0, [i + this.virtualPointerRegisterOffset, owner]);
649                         }
650                 }
651                 if(i == iLen){
652                         //途中に空いているレジスタはなかったので追加
653                         this.pointerRegisterAllocationTable.push([i + this.virtualPointerRegisterOffset, owner]);
654                 }
655                 return i + this.virtualPointerRegisterOffset;
656         },
657         freePointerRegister: function(regID, owner){
658                 for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
659                         if(this.pointerRegisterAllocationTable[i][0] == regID){
660                                 //レジスタ番号を見つけた
661                                 //オーナーが一致するか確認
662                                 if(this.pointerRegisterAllocationTable[i][1] == owner){
663                                         //一致したので解放する
664                                         this.pointerRegisterAllocationTable.splice(i, 1);
665                                 }
666                                 break;
667                         }
668                 }
669                 if(i == iLen){
670                         throw new ELCHNOSCompiler_CompileException(0, ["freePointerRegister:regID not found."], -1);
671                 }
672         },
673         freeAllRegisterOfOwner: function(owner){
674                 //ownerが確保しているレジスタをすべて解放する
675                 //IntegerRegister
676                 for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
677                         if(this.integerRegisterAllocationTable[i][1] == owner){
678                                 //見つけた
679                                 this.integerRegisterAllocationTable.splice(i, 1);
680                                 iLen--;
681                         }
682                 }
683                 //PointerRegister
684                 for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
685                         if(this.pointerRegisterAllocationTable[i][1] == owner){
686                                 //見つけた
687                                 this.pointerRegisterAllocationTable.splice(i, 1);
688                                 iLen--;
689                         }
690                 }
691         },
692         expandBinaryString: function(){
693                 var ary = this.bin;
694                 var b = new Array();
695                 var aryStack = new Array();
696                 var indexStack = new Array();
697                 for(var i = 0; ; i++){
698                         if(ary[i] === undefined){
699                                 ary = aryStack.pop();
700                                 if(ary === undefined){
701                                         break;
702                                 }
703                                 i = indexStack.pop();
704                         }
705                         if(ary[i] instanceof Array){
706                                         aryStack.push(ary);
707                                         indexStack.push(i + 1);
708                                         ary = ary[i];
709                                         i = -1;
710                         } else if(ary[i] !== undefined){
711                                         b.push(ary[i]);
712                         }
713                 }
714                 this.bin = b;
715         },
716         assignRegister: function(){
717                 for(var i = 0, iLen = this.bin.length; i < iLen; i++){
718                         if(this.bin[i] > 0xff){
719                                 if(this.virtualIntegerRegisterOffset <= this.bin[i] && this.bin[i] <= this.virtualIntegerRegisterOffset + 0x1f){
720                                         //R00-R1fは無条件で割り当ててOK
721                                         this.bin[i] -= this.virtualIntegerRegisterOffset;
722                                 } else if(this.virtualPointerRegisterOffset <= this.bin[i] && this.bin[i] <= this.virtualPointerRegisterOffset + 0x1f - 1){
723                                         //P01-P1fは無条件で割り当ててOK
724                                         this.bin[i] -= this.virtualPointerRegisterOffset;
725                                         this.bin[i] += 1;
726                                 } else{
727                                         throw new ELCHNOSCompiler_CompileException(0, ["Sorry, but no more register."]);
728                                 }
729                         }
730                 }
731         },
732         saveBinary: function(){
733                 var m = this.env.IOManager;
734                 var cl = this.bin;
735                 var v = new Uint8Array(this.bin);
736                 var d = new Blob([v]);
737                 if(d){
738                         m.showDownloadLink(d);
739                 }
740         },
741         
742 }
743