OSDN Git Service

WebCPUを統合。同時にファイル分割と、エラー処理に例外を利用するようにした。
authorhikarupsp <hikarupsp@users.sourceforge.jp>
Sun, 3 Nov 2013 15:47:20 +0000 (00:47 +0900)
committerhikarupsp <hikarupsp@users.sourceforge.jp>
Sun, 3 Nov 2013 15:47:20 +0000 (00:47 +0900)
ELCHNOS-OSECPU:連続するラベル命令を除去するようにした。最適化処理はWebCPUとの連携による。

17 files changed:
aiext.js
document/elchnos.txt [new file with mode: 0644]
elcc/elcc.js [new file with mode: 0644]
elcc/elcexpr.js [moved from elcc.js with 57% similarity]
header.js [new file with mode: 0644]
index.html
testdata/elc/bball.elc [moved from test.elc with 97% similarity]
webcpu/api.js [new file with mode: 0644]
webcpu/const.js [new file with mode: 0644]
webcpu/decoder.js [new file with mode: 0644]
webcpu/ext.js [new file with mode: 0644]
webcpu/header.js [new file with mode: 0644]
webcpu/index.html [new file with mode: 0755]
webcpu/instr.js [new file with mode: 0644]
webcpu/instrbas.js [new file with mode: 0644]
webcpu/memory.js [new file with mode: 0644]
webcpu/webcpu.js [new file with mode: 0755]

index 9d41aaf..3633696 100644 (file)
--- a/aiext.js
+++ b/aiext.js
@@ -144,6 +144,15 @@ Array.prototype.logAsHexByte = function(){
        console.log(ds);
 }
 
+Array.prototype.stringAsHexByte = function(){
+       //十六進バイト列として文字列を得る
+       var ds = "";
+       for(var i = 0, iLen = this.length; i < iLen; i++){
+               ds += ("00" + this[i].toString(16).toUpperCase()).slice(-2);
+       }
+       return ds;
+}
+
 //文字列関連
 String.prototype.replaceAll = function(org, dest){
        //String中にある文字列orgを文字列destにすべて置換する。
diff --git a/document/elchnos.txt b/document/elchnos.txt
new file mode 100644 (file)
index 0000000..1053df5
--- /dev/null
@@ -0,0 +1,51 @@
+*ELCHNOS言語仕様
+
+*予約語
+予約語は大文字小文字を区別しません。
++int
++char
++for
++if
++pまたはrの後に数値が続くものすべて(レジスタ名指定)
++バックエンドコードのニーモニック各種
+
+*利用可能な型
+-OSECPUのプリミティブ型は二種類です。
+-整数型とポインタ型の変換(キャスト)はできません。
++整数型
++ポインタ型
+
+*変数
+**スコープ
+-変数は関数スコープとなります。
+-グローバル変数も利用できます。
+**宣言形式
+ [attribute] type [pointerSign][, ...];
+ int x;        //32ビット符号あり整数a, b, cを宣言します。
+ unsigned char a, b, c;        //8ビット符号なし整数a, b, cを宣言します。
+ int p, *q, r; //32ビット符号あり整数p, rと、32ビット符号あり整数に対するポインタqを宣言します。
+ int l, m, unsigned char *n, o;        //32ビット符号あり整数l, mと、8ビット符号なし整数に対するポインタn、そして8ビット符号なし整数oを宣言します。
+*演算子
+**整数演算
++中置二項算術演算子
+ a + b
+ + - * / %
++中置二項代入・算術演算子
+ a += b
+ = += -= *= /= %=
++後置単項算術演算子
+ a++
+ ++ --
++前置単項算術演算子
+ -a
+ -
+*関数
+-関数には二つの種類があります。これは関数型言語の利点を取り入れるためで、現在はprocedureのみが利用可能です。
++procedure
++algorithm
+--引数と戻り値のみをすべての環境とする第一級関数です。
+--この関数の内部からprocedureを呼び出すことはできません。
+--グローバル変数を利用することはできません。
+
+
+
diff --git a/elcc/elcc.js b/elcc/elcc.js
new file mode 100644 (file)
index 0000000..57f9e62
--- /dev/null
@@ -0,0 +1,743 @@
+// ELCHNOSCompiler for AI004
+
+//手順:
+//トークン分割
+//構造解析・式の逆ポーランド化
+//中間バイナリ化
+
+function ELCHNOSCompiler_CompileException(errno, infoArray, lineCount){
+       this.errno = errno;
+       this.infoArray = infoArray;
+       this.lineCount = lineCount;
+}
+ELCHNOSCompiler_CompileException.prototype = {
+       errorMessageList: [
+               "Trap.",
+               "Incompatible value attribute.",
+               "Unexpected identifier.",
+               "Unknown assembly language type.",
+               "Invalid expression of OSECPU Binary.",
+               "Binary translation error.",
+       ],
+       getMessageString: function(){
+               var s = "";
+               if(!isNaN(this.lineCount)){
+                       s += this.lineCount + ":";
+               }
+               s += "Error" + this.errno.toString().toUpperCase();
+               if(this.errno < 0 || this.errorMessageList.length <= this.errno){
+                       s += ":Unknown\n";
+               } else{
+                       s += ":" + this.errorMessageList[this.errno] + "\n";
+               }
+               if(this.infoArray){
+                       s += "  >" + this.infoArray.toString() + "\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();
+       
+       //0はエントリポイント(main)用に予約
+       this.nextLabelID = 1;
+       this.integerRegisterAllocationTable = new Array();
+       this.pointerRegisterAllocationTable = new Array();
+}
+ELCHNOSCompiler.prototype = {
+       keyWordList: [
+               "@asm",
+               "@end",
+               "//",
+               "/*",
+               "*/",
+               "!=",
+               "==",
+               "+=",
+               "-=",
+               "*=",
+               "/=",
+               "<=",
+               "++",
+               "--",
+               "\n",
+               "\t",
+               " ",
+               "{",
+               "}",
+               "(",
+               ")",
+               ";",
+               ",",
+               "[",
+               "]",
+               "=",
+               "+",
+               "-",
+               "*",
+               "/",
+       ],
+       errorMessageList: [
+               "Trap.",
+               "Incompatible value attribute.",
+               "Unexpected identifier.",
+               "Unknown assembly language type.",
+               "Invalid expression of OSECPU Binary.",
+               "Binary translation error.",
+       ],
+       
+       Flag_Sign_Signed                        : 0x00000001,
+       Flag_Sign_Unsigned                      : 0x00000002,
+       
+       compile: function(str){
+               this.line = str.split("\n");
+               //分割
+               this.separated = str.splitByArraySeparatorSeparatedLong(this.keyWordList);
+               //コメント除去
+               this.compile_removeComment();
+               
+               //不要な文字を削除
+               this.separated.removeAllObject("\t");
+               this.separated.removeAllObject(" ");
+               
+               //メイン処理
+               var currentExpression = null;
+               var numValSignFlag = 0;
+               var numValBits = 0;
+               var pointerCount = 0;
+               var lineCount = 1;
+               var mode = 0;
+               var o;
+               var f;
+                       //次に期待する値を示す。
+                       // 0: 何が来るかわからない
+                       //
+                       //10: 変数・定数の前置属性・型・または識別子
+                       //11: 変数・定数の識別子またはポインタ属性
+                       //12: 変数・定数の後置属性・初期化式または終端記号、もしくは連続した変数宣言の区切り
+                       //13: 変数・定数の初期化式または終端記号、もしくは連続した変数宣言の区切り
+                       //14: 配列長の数値部分
+                       //15: 配列長指定終了の閉じ括弧
+                       //16: 初期化式の開始括弧もしくは値
+                       //17: 初期化式の値部分または終了括弧
+                       //18: 初期化式の区切りまたは終了括弧
+                       //19: 終端記号
+                       //
+                       //50: 関数名または関数属性
+                       //51: 引数開始括弧
+                       //52: 引数or引数終了括弧
+                       //53: 引数区切りor引数終了括弧
+                       //54: 関数内部開始括弧
+                       //
+                       //60: 評価式の内容または終端記号
+                       //
+                       //70: OSECPUアセンブリ直接記述モード
+                       //71: OSECPUアセンブリ評価式の内容または終端記号
+               try{
+                       for(var i = 0, iLen = this.separated.length; i < iLen; i++){
+                               var s = this.separated[i].toLowerCase();
+                               
+                               if(s == "\n"){
+                                       //デバッグ用行数カウント
+                                       lineCount++;
+                                       continue;
+                               //予約語
+                               } else if(s == "signed" && (mode == 0 || mode == 10)){
+                                       //符号あり
+                                       if(numValSignFlag != 0){
+                                               throw new ELCHNOSCompiler_CompileException(1, [s], lineCount);
+                                       }
+                                       numValSignFlag |= this.Flag_Sign_Signed;
+                                       mode = 10;
+                               } else if(s == "unsigned" && (mode == 0 || mode == 10)){
+                                       //符号なし
+                                       if(numValSignFlag != 0){
+                                               throw new ELCHNOSCompiler_CompileException(1, [s], lineCount);
+                                       }
+                                       numValSignFlag |= this.Flag_Sign_Unsigned;
+                                       mode = 10;
+                               } else if(s == "char"  && (mode == 0 || mode == 10 || mode == 11 || mode == 52)){
+                                       //char 8bit符号あり
+                                       numValBits = 8;
+                                       if(mode == 0 || mode == 10 || mode == 11){
+                                               mode = 11;
+                                       }
+                               } else if(s == "int" && (mode == 0 || mode == 10 || mode == 11 || mode == 52)){
+                                       //int 32bit符号あり
+                                       numValBits = 32;
+                                       if(mode == 0 || mode == 10 || mode == 11){
+                                               mode = 11;
+                                       }
+                               } else if(s == ";" && (mode == 0 || mode == 12 || mode == 13 || mode == 19 || mode == 60 || mode == 71)){
+                                       if(mode == 12 || mode == 13 || mode == 19){
+                                               //変数または定数の定義終了
+                                               numValBits = 0;
+                                               numValSignFlag = 0;
+                                               currentExpression = null;
+                                               mode = 0;
+                                       } else if(mode == 60 || mode == 71){
+                                               //評価式終端
+                                               currentExpression = null;
+                                               if(mode == 60){
+                                                       mode = 0;
+                                               } else if(mode == 71){
+                                                       mode = 70;
+                                               }
+                                       } else{
+                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                       }
+                               } else if(s == "=" && (mode == 13)){
+                                       if(mode == 13){
+                                               //変数・定数初期化式開始
+                                               mode = 16;
+                                       } else{
+                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                       }
+                               } else if(s == "*" && (mode == 11)){
+                                       //ポインタ属性の付加
+                                       pointerCount++;
+                               } else if(s == "," && (mode == 18 || mode == 12 || mode == 13 || mode == 53)){
+                                       if(mode == 18){
+                                               //初期化式の区切り
+                                               mode = 17;
+                                       } else if(mode == 12 || mode == 13 || mode == 53){
+                                               //連続した変数宣言の区切り
+                                               if(mode == 12 || mode == 13){
+                                                       mode = 11;
+                                               } else if(mode == 53){
+                                                       mode = 52;
+                                               }
+                                               currentExpression = null;
+                                       } else{
+                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                       }
+                               //括弧系
+                               } else if(s == "[" && (mode == 12)){
+                                       //配列の長さの定義開始
+                                       mode = 14;
+                               } else if(s == "]" && (mode == 15)){
+                                       //配列の長さの定義終了
+                                       mode = 13;
+                               } else if(s == "{" && (mode == 16 || mode == 54)){
+                                       if(mode == 16){
+                                               //初期化式の開始括弧
+                                               mode = 17;
+                                       } else if(mode == 54){
+                                               //54: 関数内部開始括弧
+                                               currentExpression = null;
+                                               mode = 0;
+                                       } else{
+                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                       }
+                               } else if(s == "}" && (mode == 17 || mode == 18 || mode == 0)){
+                                       if(mode == 17 || mode == 18){
+                                               //初期化式の終了括弧
+                                               mode = 19;
+                                       } else if(mode == 0){
+                                               if(this.structureStack.length > 0){
+                                                       this.restoreCurrentStructure();
+                                               } else{
+                                                       throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                               }
+                                       }
+                               } else if(s == "(" && (mode == 51)){
+                                       //51: 引数開始括弧
+                                       mode = 52;
+                               } else if(s == ")" && (mode == 52 || mode == 53)){
+                                       //52: 引数or引数終了括弧
+                                       //53: 引数区切りor引数終了括弧
+                                       currentExpression = null;
+                                       for(var j = 0, jLen = this.currentStructure.length; j < jLen; j++){
+                                               //引数番号を付与
+                                               this.currentStructure[j].argumentIndex = j;
+                                       }
+                                       mode = 54;
+                               } else if(s == "@asm" && (mode == 0)){
+                                       i++;
+                                       s = this.separated[i].toLowerCase();
+                                       if(s == "osecpu"){
+                                               mode = 70;
+                                       } else{
+                                               throw new ELCHNOSCompiler_CompileException(3, [s], lineCount);
+                                       }
+                               } else if(s == "@end" && (mode == 70)){
+                                       mode = 0;
+                               //リストにない予約語
+                               } else if(s == "procedure" && (mode == 0)){
+                                       //関数宣言
+                                       var f = new ELCHNOSCompiler_ExpressionStructure_Function(this, lineCount);
+                                       this.currentStructure.push(f);
+                                       this.changeCurrentStructure(f.structure);
+                                       currentExpression = f;
+                                       
+                                       mode = 50;
+                               } else if(s == "inline" && (mode == 50)){
+                                       currentExpression.isInline = true;
+                               } else if(s == "for" && (mode == 0)){
+                                       //forループ
+                                       i++;
+                                       s = this.separated[i];
+                                       if(s == "("){
+                                               var f = new ELCHNOSCompiler_ExpressionStructure_Loop_for(this, lineCount);
+                                               this.currentStructure.push(f);
+                                               this.changeCurrentStructure(f.structure);
+                                               currentExpression = f;
+                                               //初期化式
+                                               f.initializer = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
+                                               i = f.initializer.readExpressionToTerminator(i, ";");
+                                               //条件評価式
+                                               f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
+                                               i = f.conditonalExpression.readExpressionToTerminator(i, ";");
+                                               //更新式
+                                               f.incrementalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
+                                               i = f.incrementalExpression.readExpressionToTerminator(i, ")");
+                                               //開始括弧
+                                               i++;
+                                               if(this.separated[i] != "{"){
+                                                       throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                               }
+                                               currentExpression = null;
+                                       } else{
+                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                       }
+                               } else if(s == "if" && (mode == 0)){
+                                       //if文
+                                       //条件評価式-?>L2
+                                       //実行部分
+                                       //(break->L2)
+                                       //L2:
+                                       i++;
+                                       s = this.separated[i];
+                                       if(s == "("){
+                                               var f = new ELCHNOSCompiler_ExpressionStructure_if(this, lineCount);
+                                               this.currentStructure.push(f);
+                                               this.changeCurrentStructure(f.structure);
+                                               currentExpression = f;
+                                               //条件評価式
+                                               f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
+                                               i = f.conditonalExpression.readExpressionToTerminator(i, ")");
+                                               //開始括弧
+                                               i++;
+                                               if(this.separated[i] != "{"){
+                                                       throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                               }
+                                               currentExpression = null;
+                                       } else{
+                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                       }
+                               //OSECPUアセンブリ
+                               } else if(s == "remark" && (mode == 70)){
+                                       //超手抜き
+                                       var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this, lineCount);
+                                       this.currentStructure.push(b);
+                                       //FE    len     ...
+                                       b.bin.push(0xfe);
+                                       //len
+                                       i++;
+                                       s = this.separated[i];
+                                       if(s.length == 2){
+                                               var len = parseInt(s, 16);
+                                               b.bin.push(len);
+                                       } else{
+                                               throw new ELCHNOSCompiler_CompileException(4, [s], lineCount);
+                                       }
+                                       //data
+                                       i++;
+                                       s = this.separated[i];
+                                       if(s.length == len * 2){
+                                               for(var j = 0; j < len; j++){
+                                                       b.bin.push(parseInt(s.substr(j * 2, 2), 16));
+                                               }
+                                       } else{
+                                               throw new ELCHNOSCompiler_CompileException(4, [s], lineCount);
+                                       }
+                                       //終端
+                                       i++;
+                                       if(this.separated[i] != ";"){
+                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                       } else{
+                                               //この命令は定数のみで構成されているのでコンパイル済みとマークする
+                                               b.isCompiled = true;
+                                               b = null;
+                                       }
+                               } else if(s == "call" && (mode == 70)){
+                                       //超手抜き
+                                       var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this, lineCount);
+                                       this.currentStructure.push(b);
+                                       
+                                       //第二引数が何か確認する
+                                       i++;
+                                       s = this.separated[i].toLowerCase();
+                                       if((s.indexOf("p") == 0) && s.length == 3){
+                                               //ポインタレジスタをcall
+                                               //新しいラベル番号をもらう
+                                               var labelID = this.allocateLabelID();
+                                               //PLIMM(P30, labelID)
+                                                       //03    reg0    imm32
+                                               b.bin.push(0x03);
+                                               b.bin.push(0x30);
+                                               b.appendInstruction_UINT32BE(labelID);
+                                               //PCP(P3F, Pxx)
+                                                       //1E    reg0P   reg1P
+                                               b.bin.push(0x1e);
+                                               b.bin.push(0x3f);
+                                               b.bin.push(parseInt(s.substr(1),16));
+                                               
+                                               b.appendInstruction_LB(0x01, labelID);
+                                               //[FE] [01] [00]
+                                               b.bin.push(0xfe);
+                                               b.bin.push(0x01);
+                                               b.bin.push(0x00);
+                                               //終端記号
+                                               i++;
+                                               if(this.separated[i] != ";"){
+                                                       throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                               } else{
+                                                       //この命令は定数のみで構成されているのでコンパイル済みとマークする
+                                                       b.isCompiled = true;
+                                                       b = null;
+                                               }
+                                       } else{
+                                               throw new ELCHNOSCompiler_CompileException(0, [s], lineCount);
+                                       }
+                               //予約語以外
+                               } else if(mode == 11 || mode == 52){
+                                       //変数または定数の宣言
+                                       //52: 引数名
+                                       var v = new ELCHNOSCompiler_ExpressionStructure_Variable(this, lineCount);
+                                       v.bits = numValBits;
+                                       v.isSigned = (numValSignFlag == 0) ? false : (0 != (numValSignFlag & this.Flag_Sign_Signed));
+                                       s = this.separated[i];
+                                       v.isPointer = (pointerCount != 0) ? true : false;
+                                       pointerCount = 0;
+                                       if(s.length <= 0){
+                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
+                                       }
+                                       v.identifier = s;
+                                       this.currentStructure.push(v);
+                                       currentExpression = v;
+                                       //mode:11->12
+                                       //mode:52->53
+                                       mode++;
+                               } else if(mode == 14){
+                                       currentExpression.length = parseInt(s);
+                                       mode = 15;
+                               } else if(mode == 17){
+                                       //定数値のみ対応
+                                       currentExpression.initValue.push(parseInt(s));
+                                       mode = 18;
+                               } else if(mode == 50){
+                                       //関数名
+                                       //大文字小文字を区別
+                                       currentExpression.identifier = this.separated[i];
+                                       mode = 51;
+                               } else{
+                                       if(mode == 0 || mode == 70 || mode == 60 || mode == 71){
+                                               //大文字小文字を区別
+                                               s = this.separated[i];
+                                               if(mode == 0 || mode == 70){
+                                                       //最初の左辺だったら追加処理
+                                                       var f = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
+                                                       this.currentStructure.push(f);
+                                                       currentExpression = f;
+                                               }
+                                               currentExpression.pushIdentifier(s);
+                                               if(mode == 0){
+                                                       mode = 60;
+                                               } else if(mode == 70){
+                                                       mode = 71;
+                                               }
+                                       }
+                               }
+                       }
+                       //中間バイナリ生成
+                       //バックエンドコードの中間表現を出力。
+                       //0x00-0xff: そのまま使えるバイナリ
+                       //0x10000000-0x1fffffff: 未決定の仮想整数レジスタ番号
+                       //0x20000000-0x2fffffff: 未決定の仮想ポインタレジスタ番号
+                       this.errno = 5;
+                       
+                       //OSECPUフロントエンドコードヘッダ
+                       this.bin.push(0x05, 0xe1, 0x00);
+                       
+                       for(var i = 0, iLen = this.structure.length; i < iLen; i++){
+                               var b = this.structure[i].createBinary();
+                               if(b !== undefined){
+                                       this.bin.push(b);
+                               }
+                       }
+                       this.expandBinaryString();
+                       this.assignRegister();
+                       this.bin.logAsHexByte();
+                       var cpu = new WebCPU();
+                       cpu.loadBinaryText(this.bin.stringAsHexByte());
+                       cpu.staticOptimize();
+                       console.log(cpu.createBackendBinaryString());
+                       this.saveBinary();
+               } catch(e){
+                       //全エラー処理
+                       if(e instanceof ELCHNOSCompiler_CompileException){
+                               this.env.debug(e.getMessageString());
+                       } else{
+                               throw e;
+                       }
+               }
+       },
+       compile_removeComment: function(){
+               //コメント削除
+               var commentLineStartIndex = -1;
+               var commentBlockStartIndex = -1;
+               var commentBlockCount = 0;
+               var linesInCommentBlock = 0;
+               
+               for(var i = 0, iLen = this.separated.length; i < iLen; i++){
+                       var s = this.separated[i];
+                       if(commentLineStartIndex == -1){
+                               if(s == "//"){
+                                       //行コメント開始
+                                       commentLineStartIndex = i;
+                               }
+                       } else{
+                               if(s == "\n"){
+                                       //行コメント終了
+                                       var len = i - commentLineStartIndex;
+                                       this.separated.splice(commentLineStartIndex, len);
+                                       iLen -= len;
+                                       i -= len;
+                                       commentLineStartIndex = -1;
+                               }
+                       }
+                       if(s == "/*"){
+                               //ブロックコメント開始
+                               if(commentBlockCount == 0){
+                                       commentBlockStartIndex = i;
+                               }
+                               commentBlockCount++;
+                       } else if(s == "*/"){
+                               //ブロックコメント終了
+                               commentBlockCount--;
+                               if(commentBlockCount == 0){
+                                       var len = i - commentBlockStartIndex + 1;
+                                       var padding = new Array();
+                                       padding.push(commentBlockStartIndex);
+                                       padding.push(len);
+                                       for(var j = 0, jLen = linesInCommentBlock; j < jLen; j++){
+                                               padding.push("\n");
+                                       }
+                                       this.separated.splice.apply(this.separated, padding);
+                                       i -= len - linesInCommentBlock;
+                                       iLen -= len - linesInCommentBlock;
+                                       linesInCommentBlock = 0;
+                               } else if(commentBlockCount < 0){
+                                       this.env.debug("Too many block comment closure [].\n");
+                                       return;
+                               }
+                       } else if(commentBlockCount > 0 && s == "\n"){
+                               linesInCommentBlock++;
+                       }
+               }
+       },
+       raiseError: function(errno, lineCount, infoArray){
+               if(errno < 0 || this.errorMessageList.length <= errno){
+                       this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":Unknown\n");
+               } else{
+                       this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":" + this.errorMessageList[errno] + "\n");
+               }
+               if(infoArray){
+                       this.env.debug("  >" + infoArray.toString() + "\n");
+               }
+       },
+       changeCurrentStructure: function(newstructure){
+               this.structureStack.push(this.currentStructure);
+               this.currentStructure = newstructure;
+       },
+       restoreCurrentStructure: function(){
+               this.currentStructure = this.structureStack.pop();
+       },
+       searchIdentifier: function(identifier){
+               var o;
+               var cf = function(aryobj, obj){ return (aryobj.identifier == obj) };
+               
+               o = this.currentStructure.isIncluded(identifier, cf);
+               if(!o){
+                       for(var i = this.structureStack.length - 1; i >= 0; i--){
+                               o = this.structureStack[i].isIncluded(identifier, cf);
+                               if(o){
+                                       break;
+                               }
+                       }
+               }
+               return o;
+       },
+       isOperator: function(s){
+               return (
+                       s == "=" ||
+                       s == "+" ||
+                       s == "-" ||
+                       s == "*" ||
+                       s == "/" ||
+                       s == "!=" ||
+                       s == "++" ||
+                       s == "<" ||
+                       s == "(" ||
+                       s == ")"||
+                       s == "," ||
+                       false
+               );
+       },
+       allocateLabelID: function(){
+               this.nextLabelID++;
+               return this.nextLabelID - 1;
+       },
+       virtualIntegerRegisterOffset: 0x10000000,
+       allocateIntegerRegister: function(owner){
+               //レジスタテーブルは先頭から番号の小さい順につめて格納する。
+               //[regID, owner]
+               //0x10000000-0x1fffffff: 未決定の仮想整数レジスタ番号
+               var freeRegID = 0;
+               for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.integerRegisterAllocationTable[i][0] != i + this.virtualIntegerRegisterOffset){
+                               //空いているレジスタ番号を見つけた
+                               if(i > 0x20){
+                                       this.integerRegisterAllocationTable.splice(i, 0, [i + this.virtualIntegerRegisterOffset, owner]);
+                               }
+                       }
+               }
+               if(i == iLen){
+                       //途中に空いているレジスタはなかったので追加
+                       this.integerRegisterAllocationTable.push([i + this.virtualIntegerRegisterOffset, owner]);
+               }
+               return i + this.virtualIntegerRegisterOffset;
+       },
+       freeIntegerRegister: function(regID, owner){
+               for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.integerRegisterAllocationTable[i][0] == regID){
+                               //レジスタ番号を見つけた
+                               //オーナーが一致するか確認
+                               if(this.integerRegisterAllocationTable[i][1] == owner){
+                                       //一致したので解放する
+                                       this.integerRegisterAllocationTable.splice(i, 1);
+                               }
+                               break;
+                       }
+               }
+               if(i == iLen){
+                       throw new ELCHNOSCompiler_CompileException(0, ["freeIntegerRegister:regID not found."], -1);
+               }
+       },
+       virtualPointerRegisterOffset: 0x20000000,
+       allocatePointerRegister: function(owner){
+               //レジスタテーブルは先頭から番号の小さい順につめて格納する。
+               //[regID, owner]
+               //0x20000000-0x2fffffff: 未決定の仮想ポインタレジスタ番号
+               var freeRegID = 0;
+               for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.pointerRegisterAllocationTable[i][0] != i + this.virtualPointerRegisterOffset){
+                               //空いているレジスタ番号を見つけた
+                               this.pointerRegisterAllocationTable.splice(i, 0, [i + this.virtualPointerRegisterOffset, owner]);
+                       }
+               }
+               if(i == iLen){
+                       //途中に空いているレジスタはなかったので追加
+                       this.pointerRegisterAllocationTable.push([i + this.virtualPointerRegisterOffset, owner]);
+               }
+               return i + this.virtualPointerRegisterOffset;
+       },
+       freePointerRegister: function(regID, owner){
+               for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.pointerRegisterAllocationTable[i][0] == regID){
+                               //レジスタ番号を見つけた
+                               //オーナーが一致するか確認
+                               if(this.pointerRegisterAllocationTable[i][1] == owner){
+                                       //一致したので解放する
+                                       this.pointerRegisterAllocationTable.splice(i, 1);
+                               }
+                               break;
+                       }
+               }
+               if(i == iLen){
+                       throw new ELCHNOSCompiler_CompileException(0, ["freePointerRegister:regID not found."], -1);
+               }
+       },
+       freeAllRegisterOfOwner: function(owner){
+               //ownerが確保しているレジスタをすべて解放する
+               //IntegerRegister
+               for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.integerRegisterAllocationTable[i][1] == owner){
+                               //見つけた
+                               this.integerRegisterAllocationTable.splice(i, 1);
+                               iLen--;
+                       }
+               }
+               //PointerRegister
+               for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
+                       if(this.pointerRegisterAllocationTable[i][1] == owner){
+                               //見つけた
+                               this.pointerRegisterAllocationTable.splice(i, 1);
+                               iLen--;
+                       }
+               }
+       },
+       expandBinaryString: function(){
+               var ary = this.bin;
+               var b = new Array();
+               var aryStack = new Array();
+               var indexStack = new Array();
+               for(var i = 0; ; i++){
+                       if(ary[i] === undefined){
+                               ary = aryStack.pop();
+                               if(ary === undefined){
+                                       break;
+                               }
+                               i = indexStack.pop();
+                       }
+                       if(ary[i] instanceof Array){
+                                       aryStack.push(ary);
+                                       indexStack.push(i + 1);
+                                       ary = ary[i];
+                                       i = -1;
+                       } else if(ary[i] !== undefined){
+                                       b.push(ary[i]);
+                       }
+               }
+               this.bin = b;
+       },
+       assignRegister: function(){
+               for(var i = 0, iLen = this.bin.length; i < iLen; i++){
+                       if(this.bin[i] > 0xff){
+                               if(this.virtualIntegerRegisterOffset <= this.bin[i] && this.bin[i] <= this.virtualIntegerRegisterOffset + 0x1f){
+                                       //R00-R1fは無条件で割り当ててOK
+                                       this.bin[i] -= this.virtualIntegerRegisterOffset;
+                               } else if(this.virtualPointerRegisterOffset <= this.bin[i] && this.bin[i] <= this.virtualPointerRegisterOffset + 0x1f - 1){
+                                       //P01-P1fは無条件で割り当ててOK
+                                       this.bin[i] -= this.virtualPointerRegisterOffset;
+                                       this.bin[i] += 1;
+                               } else{
+                                       throw new ELCHNOSCompiler_CompileException(0, ["Sorry, but no more register."]);
+                               }
+                       }
+               }
+       },
+       saveBinary: function(){
+               var m = this.env.IOManager;
+               var cl = this.bin;
+               var v = new Uint8Array(this.bin);
+               var d = new Blob([v]);
+               if(d){
+                       m.showDownloadLink(d);
+               }
+       },
+       
+}
+
similarity index 57%
rename from elcc.js
rename to elcc/elcexpr.js
index 5f4a346..e261d12 100644 (file)
--- a/elcc.js
@@ -1,753 +1,3 @@
-// ELCHNOSCompiler for AI004
-
-//手順:
-//トークン分割
-//構造解析・式の逆ポーランド化
-//中間バイナリ化
-
-function ELCHNOSCompiler_CompileException(errno, infoArray, lineCount){
-       this.errno = errno;
-       this.infoArray = infoArray;
-       this.lineCount = lineCount;
-}
-ELCHNOSCompiler_CompileException.prototype = {
-       errorMessageList: [
-               "Trap.",
-               "Incompatible value attribute.",
-               "Unexpected identifier.",
-               "Unknown assembly language type.",
-               "Invalid expression of OSECPU Binary.",
-               "Binary translation error.",
-       ],
-       getMessageString: function(){
-               var s = "";
-               if(!isNaN(this.lineCount)){
-                       s += this.lineCount + ":";
-               }
-               s += "Error" + this.errno.toString().toUpperCase();
-               if(this.errno < 0 || this.errorMessageList.length <= this.errno){
-                       s += ":Unknown\n";
-               } else{
-                       s += ":" + this.errorMessageList[this.errno] + "\n";
-               }
-               if(this.infoArray){
-                       s += "  >" + this.infoArray.toString() + "\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();
-       
-       //0はエントリポイント(main)用に予約
-       this.nextLabelID = 1;
-       this.integerRegisterAllocationTable = new Array();
-       this.pointerRegisterAllocationTable = new Array();
-}
-ELCHNOSCompiler.prototype = {
-       keyWordList: [
-               "@asm",
-               "@end",
-               "//",
-               "/*",
-               "*/",
-               "!=",
-               "==",
-               "+=",
-               "-=",
-               "*=",
-               "/=",
-               "<=",
-               "++",
-               "--",
-               "\n",
-               "\t",
-               " ",
-               "{",
-               "}",
-               "(",
-               ")",
-               ";",
-               ",",
-               "[",
-               "]",
-               "=",
-               "+",
-               "-",
-               "*",
-               "/",
-       ],
-       errorMessageList: [
-               "Trap.",
-               "Incompatible value attribute.",
-               "Unexpected identifier.",
-               "Unknown assembly language type.",
-               "Invalid expression of OSECPU Binary.",
-               "Binary translation error.",
-       ],
-       
-       Flag_Sign_Signed                        : 0x00000001,
-       Flag_Sign_Unsigned                      : 0x00000002,
-       
-       compile: function(str){
-               this.line = str.split("\n");
-               //分割
-               this.separated = str.splitByArraySeparatorSeparatedLong(this.keyWordList);
-               //コメント除去
-               this.compile_removeComment();
-               
-               //不要な文字を削除
-               this.separated.removeAllObject("\t");
-               this.separated.removeAllObject(" ");
-               
-               console.log(this.separated);
-               
-               //メイン処理
-               var currentExpression = null;
-               var numValSignFlag = 0;
-               var numValBits = 0;
-               var pointerCount = 0;
-               var lineCount = 1;
-               var mode = 0;
-               var o;
-               var f;
-                       //次に期待する値を示す。
-                       // 0: 何が来るかわからない
-                       //
-                       //10: 変数・定数の前置属性・型・または識別子
-                       //11: 変数・定数の識別子またはポインタ属性
-                       //12: 変数・定数の後置属性・初期化式または終端記号、もしくは連続した変数宣言の区切り
-                       //13: 変数・定数の初期化式または終端記号、もしくは連続した変数宣言の区切り
-                       //14: 配列長の数値部分
-                       //15: 配列長指定終了の閉じ括弧
-                       //16: 初期化式の開始括弧もしくは値
-                       //17: 初期化式の値部分または終了括弧
-                       //18: 初期化式の区切りまたは終了括弧
-                       //19: 終端記号
-                       //
-                       //50: 関数名または関数属性
-                       //51: 引数開始括弧
-                       //52: 引数or引数終了括弧
-                       //53: 引数区切りor引数終了括弧
-                       //54: 関数内部開始括弧
-                       //
-                       //60: 評価式の内容または終端記号
-                       //
-                       //70: OSECPUアセンブリ直接記述モード
-                       //71: OSECPUアセンブリ評価式の内容または終端記号
-               try{
-                       for(var i = 0, iLen = this.separated.length; i < iLen; i++){
-                               var s = this.separated[i].toLowerCase();
-                               
-                               if(s == "\n"){
-                                       //デバッグ用行数カウント
-                                       lineCount++;
-                                       continue;
-                               //予約語
-                               } else if(s == "signed" && (mode == 0 || mode == 10)){
-                                       //符号あり
-                                       if(numValSignFlag != 0){
-                                               throw new ELCHNOSCompiler_CompileException(1, [s], lineCount);
-                                       }
-                                       numValSignFlag |= this.Flag_Sign_Signed;
-                                       mode = 10;
-                               } else if(s == "unsigned" && (mode == 0 || mode == 10)){
-                                       //符号なし
-                                       if(numValSignFlag != 0){
-                                               throw new ELCHNOSCompiler_CompileException(1, [s], lineCount);
-                                       }
-                                       numValSignFlag |= this.Flag_Sign_Unsigned;
-                                       mode = 10;
-                               } else if(s == "char"  && (mode == 0 || mode == 10 || mode == 11 || mode == 52)){
-                                       //char 8bit符号あり
-                                       numValBits = 8;
-                                       if(mode == 0 || mode == 10 || mode == 11){
-                                               mode = 11;
-                                       }
-                               } else if(s == "int" && (mode == 0 || mode == 10 || mode == 11 || mode == 52)){
-                                       //int 32bit符号あり
-                                       numValBits = 32;
-                                       if(mode == 0 || mode == 10 || mode == 11){
-                                               mode = 11;
-                                       }
-                               } else if(s == ";" && (mode == 0 || mode == 12 || mode == 13 || mode == 19 || mode == 60 || mode == 71)){
-                                       if(mode == 12 || mode == 13 || mode == 19){
-                                               //変数または定数の定義終了
-                                               numValBits = 0;
-                                               numValSignFlag = 0;
-                                               //console.log(currentExpression);
-                                               currentExpression = null;
-                                               mode = 0;
-                                       } else if(mode == 60 || mode == 71){
-                                               //評価式終端
-                                               //console.log(currentExpression);
-                                               currentExpression = null;
-                                               if(mode == 60){
-                                                       mode = 0;
-                                               } else if(mode == 71){
-                                                       mode = 70;
-                                               }
-                                       } else{
-                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                       }
-                               } else if(s == "=" && (mode == 13)){
-                                       if(mode == 13){
-                                               //変数・定数初期化式開始
-                                               mode = 16;
-                                       } else{
-                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                       }
-                               } else if(s == "*" && (mode == 11)){
-                                       //ポインタ属性の付加
-                                       pointerCount++;
-                               } else if(s == "," && (mode == 18 || mode == 12 || mode == 13 || mode == 53)){
-                                       if(mode == 18){
-                                               //初期化式の区切り
-                                               mode = 17;
-                                       } else if(mode == 12 || mode == 13 || mode == 53){
-                                               //連続した変数宣言の区切り
-                                               if(mode == 12 || mode == 13){
-                                                       mode = 11;
-                                               } else if(mode == 53){
-                                                       mode = 52;
-                                               }
-                                               //console.log(currentExpression);
-                                               currentExpression = null;
-                                       } else{
-                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                       }
-                               //括弧系
-                               } else if(s == "[" && (mode == 12)){
-                                       //配列の長さの定義開始
-                                       mode = 14;
-                               } else if(s == "]" && (mode == 15)){
-                                       //配列の長さの定義終了
-                                       mode = 13;
-                               } else if(s == "{" && (mode == 16 || mode == 54)){
-                                       if(mode == 16){
-                                               //初期化式の開始括弧
-                                               mode = 17;
-                                       } else if(mode == 54){
-                                               //54: 関数内部開始括弧
-                                               currentExpression = null;
-                                               mode = 0;
-                                       } else{
-                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                       }
-                               } else if(s == "}" && (mode == 17 || mode == 18 || mode == 0)){
-                                       if(mode == 17 || mode == 18){
-                                               //初期化式の終了括弧
-                                               mode = 19;
-                                       } else if(mode == 0){
-                                               if(this.structureStack.length > 0){
-                                                       //console.log(this.currentStructure);
-                                                       this.restoreCurrentStructure();
-                                               } else{
-                                                       throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                               }
-                                       }
-                               } else if(s == "(" && (mode == 51)){
-                                       //51: 引数開始括弧
-                                       mode = 52;
-                               } else if(s == ")" && (mode == 52 || mode == 53)){
-                                       //52: 引数or引数終了括弧
-                                       //53: 引数区切りor引数終了括弧
-                                       //console.log(currentExpression);
-                                       currentExpression = null;
-                                       for(var j = 0, jLen = this.currentStructure.length; j < jLen; j++){
-                                               //引数番号を付与
-                                               this.currentStructure[j].argumentIndex = j;
-                                       }
-                                       mode = 54;
-                               } else if(s == "@asm" && (mode == 0)){
-                                       i++;
-                                       s = this.separated[i].toLowerCase();
-                                       if(s == "osecpu"){
-                                               mode = 70;
-                                       } else{
-                                               throw new ELCHNOSCompiler_CompileException(3, [s], lineCount);
-                                       }
-                               } else if(s == "@end" && (mode == 70)){
-                                       mode = 0;
-                               //リストにない予約語
-                               } else if(s == "procedure" && (mode == 0)){
-                                       //関数宣言
-                                       var f = new ELCHNOSCompiler_ExpressionStructure_Function(this, lineCount);
-                                       this.currentStructure.push(f);
-                                       this.changeCurrentStructure(f.structure);
-                                       currentExpression = f;
-                                       
-                                       mode = 50;
-                               } else if(s == "inline" && (mode == 50)){
-                                       currentExpression.isInline = true;
-                               } else if(s == "for" && (mode == 0)){
-                                       //forループ
-                                       i++;
-                                       s = this.separated[i];
-                                       if(s == "("){
-                                               var f = new ELCHNOSCompiler_ExpressionStructure_Loop_for(this, lineCount);
-                                               this.currentStructure.push(f);
-                                               this.changeCurrentStructure(f.structure);
-                                               currentExpression = f;
-                                               //初期化式
-                                               f.initializer = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
-                                               i = f.initializer.readExpressionToTerminator(i, ";");
-                                               //条件評価式
-                                               f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
-                                               i = f.conditonalExpression.readExpressionToTerminator(i, ";");
-                                               //更新式
-                                               f.incrementalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
-                                               i = f.incrementalExpression.readExpressionToTerminator(i, ")");
-                                               //開始括弧
-                                               i++;
-                                               if(this.separated[i] != "{"){
-                                                       throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                               }
-                                               currentExpression = null;
-                                       } else{
-                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                       }
-                               } else if(s == "if" && (mode == 0)){
-                                       //if文
-                                       //条件評価式-?>L2
-                                       //実行部分
-                                       //(break->L2)
-                                       //L2:
-                                       i++;
-                                       s = this.separated[i];
-                                       if(s == "("){
-                                               var f = new ELCHNOSCompiler_ExpressionStructure_if(this, lineCount);
-                                               this.currentStructure.push(f);
-                                               this.changeCurrentStructure(f.structure);
-                                               currentExpression = f;
-                                               //条件評価式
-                                               f.conditonalExpression = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
-                                               i = f.conditonalExpression.readExpressionToTerminator(i, ")");
-                                               //開始括弧
-                                               i++;
-                                               if(this.separated[i] != "{"){
-                                                       throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                               }
-                                               currentExpression = null;
-                                       } else{
-                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                       }
-                               //OSECPUアセンブリ
-                               } else if(s == "remark" && (mode == 70)){
-                                       //超手抜き
-                                       var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this, lineCount);
-                                       this.currentStructure.push(b);
-                                       //FE    len     ...
-                                       b.bin.push(0xfe);
-                                       //len
-                                       i++;
-                                       s = this.separated[i];
-                                       if(s.length == 2){
-                                               var len = parseInt(s, 16);
-                                               b.bin.push(len);
-                                       } else{
-                                               throw new ELCHNOSCompiler_CompileException(4, [s], lineCount);
-                                       }
-                                       //data
-                                       i++;
-                                       s = this.separated[i];
-                                       if(s.length == len * 2){
-                                               for(var j = 0; j < len; j++){
-                                                       b.bin.push(parseInt(s.substr(j * 2, 2), 16));
-                                               }
-                                       } else{
-                                               throw new ELCHNOSCompiler_CompileException(4, [s], lineCount);
-                                       }
-                                       //終端
-                                       i++;
-                                       if(this.separated[i] != ";"){
-                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                       } else{
-                                               //この命令は定数のみで構成されているのでコンパイル済みとマークする
-                                               b.isCompiled = true;
-                                               b = null;
-                                       }
-                               } else if(s == "call" && (mode == 70)){
-                                       //超手抜き
-                                       var b = new ELCHNOSCompiler_ExpressionStructure_OSECPUBinary(this, lineCount);
-                                       this.currentStructure.push(b);
-                                       
-                                       //第二引数が何か確認する
-                                       i++;
-                                       s = this.separated[i].toLowerCase();
-                                       if((s.indexOf("p") == 0) && s.length == 3){
-                                               //ポインタレジスタをcall
-                                               //新しいラベル番号をもらう
-                                               var labelID = this.allocateLabelID();
-                                               //PLIMM(P30, labelID)
-                                                       //03    reg0    imm32
-                                               b.bin.push(0x03);
-                                               b.bin.push(0x30);
-                                               b.appendInstruction_UINT32BE(labelID);
-                                               //PCP(P3F, Pxx)
-                                                       //1E    reg0P   reg1P
-                                               b.bin.push(0x1e);
-                                               b.bin.push(0x3f);
-                                               b.bin.push(parseInt(s.substr(1),16));
-                                               
-                                               b.appendInstruction_LB(0x01, labelID);
-                                               //[FE] [01] [00]
-                                               b.bin.push(0xfe);
-                                               b.bin.push(0x01);
-                                               b.bin.push(0x00);
-                                               //終端記号
-                                               i++;
-                                               if(this.separated[i] != ";"){
-                                                       throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                               } else{
-                                                       //この命令は定数のみで構成されているのでコンパイル済みとマークする
-                                                       b.isCompiled = true;
-                                                       b = null;
-                                               }
-                                       } else{
-                                               throw new ELCHNOSCompiler_CompileException(0, [s], lineCount);
-                                       }
-                               //予約語以外
-                               } else if(mode == 11 || mode == 52){
-                                       //変数または定数の宣言
-                                       //52: 引数名
-                                       var v = new ELCHNOSCompiler_ExpressionStructure_Variable(this, lineCount);
-                                       v.bits = numValBits;
-                                       v.isSigned = (numValSignFlag == 0) ? false : (0 != (numValSignFlag & this.Flag_Sign_Signed));
-                                       s = this.separated[i];
-                                       v.isPointer = (pointerCount != 0) ? true : false;
-                                       pointerCount = 0;
-                                       if(s.length <= 0){
-                                               throw new ELCHNOSCompiler_CompileException(2, [s], lineCount);
-                                       }
-                                       v.identifier = s;
-                                       this.currentStructure.push(v);
-                                       currentExpression = v;
-                                       //mode:11->12
-                                       //mode:52->53
-                                       mode++;
-                               } else if(mode == 14){
-                                       currentExpression.length = parseInt(s);
-                                       mode = 15;
-                               } else if(mode == 17){
-                                       //定数値のみ対応
-                                       currentExpression.initValue.push(parseInt(s));
-                                       mode = 18;
-                               } else if(mode == 50){
-                                       //関数名
-                                       //大文字小文字を区別
-                                       currentExpression.identifier = this.separated[i];
-                                       mode = 51;
-                               } else{
-                                       if(mode == 0 || mode == 70 || mode == 60 || mode == 71){
-                                               //大文字小文字を区別
-                                               s = this.separated[i];
-                                               if(mode == 0 || mode == 70){
-                                                       //最初の左辺だったら追加処理
-                                                       var f = new ELCHNOSCompiler_ExpressionStructure_Expression(this, lineCount);
-                                                       this.currentStructure.push(f);
-                                                       currentExpression = f;
-                                               }
-                                               currentExpression.pushIdentifier(s);
-                                               if(mode == 0){
-                                                       mode = 60;
-                                               } else if(mode == 70){
-                                                       mode = 71;
-                                               }
-                                       }
-                               }
-                       }
-                       console.log(this.structure);
-                       
-                       //中間バイナリ生成
-                       //バックエンドコードの中間表現を出力。
-                       //0x00-0xff: そのまま使えるバイナリ
-                       //0x10000000-0x1fffffff: 未決定の仮想整数レジスタ番号
-                       //0x20000000-0x2fffffff: 未決定の仮想ポインタレジスタ番号
-                       this.errno = 5;
-                       
-                       //OSECPUフロントエンドコードヘッダ
-                       this.bin.push(0x05, 0xe1, 0x00);
-                       
-                       for(var i = 0, iLen = this.structure.length; i < iLen; i++){
-                               var b = this.structure[i].createBinary();
-                               if(b !== undefined){
-                                       this.bin.push(b);
-                               }
-                       }
-                       this.expandBinaryString();
-                       this.assignRegister();
-                       this.bin.logAsHexByte();
-                       this.saveBinary();
-
-                       console.log(this.bin);
-               } catch(e){
-                       //全エラー処理
-                       if(e instanceof ELCHNOSCompiler_CompileException){
-                               this.env.debug(e.getMessageString());
-                       } else{
-                               throw e;
-                       }
-               }
-       },
-       compile_removeComment: function(){
-               //コメント削除
-               var commentLineStartIndex = -1;
-               var commentBlockStartIndex = -1;
-               var commentBlockCount = 0;
-               var linesInCommentBlock = 0;
-               
-               for(var i = 0, iLen = this.separated.length; i < iLen; i++){
-                       var s = this.separated[i];
-                       if(commentLineStartIndex == -1){
-                               if(s == "//"){
-                                       //行コメント開始
-                                       commentLineStartIndex = i;
-                               }
-                       } else{
-                               if(s == "\n"){
-                                       //行コメント終了
-                                       var len = i - commentLineStartIndex;
-                                       this.separated.splice(commentLineStartIndex, len);
-                                       iLen -= len;
-                                       i -= len;
-                                       commentLineStartIndex = -1;
-                               }
-                       }
-                       if(s == "/*"){
-                               //ブロックコメント開始
-                               if(commentBlockCount == 0){
-                                       commentBlockStartIndex = i;
-                               }
-                               commentBlockCount++;
-                       } else if(s == "*/"){
-                               //ブロックコメント終了
-                               commentBlockCount--;
-                               if(commentBlockCount == 0){
-                                       var len = i - commentBlockStartIndex + 1;
-                                       var padding = new Array();
-                                       padding.push(commentBlockStartIndex);
-                                       padding.push(len);
-                                       for(var j = 0, jLen = linesInCommentBlock; j < jLen; j++){
-                                               padding.push("\n");
-                                       }
-                                       this.separated.splice.apply(this.separated, padding);
-                                       i -= len - linesInCommentBlock;
-                                       iLen -= len - linesInCommentBlock;
-                                       linesInCommentBlock = 0;
-                               } else if(commentBlockCount < 0){
-                                       this.env.debug("Too many block comment closure [].\n");
-                                       return;
-                               }
-                       } else if(commentBlockCount > 0 && s == "\n"){
-                               linesInCommentBlock++;
-                       }
-               }
-       },
-       raiseError: function(errno, lineCount, infoArray){
-               if(errno < 0 || this.errorMessageList.length <= errno){
-                       this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":Unknown\n");
-               } else{
-                       this.env.debug(lineCount + ":Error" + errno.toString().toUpperCase() + ":" + this.errorMessageList[errno] + "\n");
-               }
-               if(infoArray){
-                       this.env.debug("  >" + infoArray.toString() + "\n");
-               }
-       },
-       changeCurrentStructure: function(newstructure){
-               this.structureStack.push(this.currentStructure);
-               this.currentStructure = newstructure;
-       },
-       restoreCurrentStructure: function(){
-               this.currentStructure = this.structureStack.pop();
-       },
-       searchIdentifier: function(identifier){
-               var o;
-               var cf = function(aryobj, obj){ return (aryobj.identifier == obj) };
-               
-               o = this.currentStructure.isIncluded(identifier, cf);
-               if(!o){
-                       for(var i = this.structureStack.length - 1; i >= 0; i--){
-                               o = this.structureStack[i].isIncluded(identifier, cf);
-                               if(o){
-                                       break;
-                               }
-                       }
-               }
-               return o;
-       },
-       isOperator: function(s){
-               return (
-                       s == "=" ||
-                       s == "+" ||
-                       s == "-" ||
-                       s == "*" ||
-                       s == "/" ||
-                       s == "!=" ||
-                       s == "++" ||
-                       s == "<" ||
-                       s == "(" ||
-                       s == ")"||
-                       s == "," ||
-                       false
-               );
-       },
-       allocateLabelID: function(){
-               this.nextLabelID++;
-               return this.nextLabelID - 1;
-       },
-       virtualIntegerRegisterOffset: 0x10000000,
-       allocateIntegerRegister: function(owner){
-               //レジスタテーブルは先頭から番号の小さい順につめて格納する。
-               //[regID, owner]
-               //0x10000000-0x1fffffff: 未決定の仮想整数レジスタ番号
-               var freeRegID = 0;
-               for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
-                       if(this.integerRegisterAllocationTable[i][0] != i + this.virtualIntegerRegisterOffset){
-                               //空いているレジスタ番号を見つけた
-                               if(i > 0x20){
-                                       this.integerRegisterAllocationTable.splice(i, 0, [i + this.virtualIntegerRegisterOffset, owner]);
-                               }
-                       }
-               }
-               if(i == iLen){
-                       //途中に空いているレジスタはなかったので追加
-                       this.integerRegisterAllocationTable.push([i + this.virtualIntegerRegisterOffset, owner]);
-               }
-               return i + this.virtualIntegerRegisterOffset;
-       },
-       freeIntegerRegister: function(regID, owner){
-               for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
-                       if(this.integerRegisterAllocationTable[i][0] == regID){
-                               //レジスタ番号を見つけた
-                               //オーナーが一致するか確認
-                               if(this.integerRegisterAllocationTable[i][1] == owner){
-                                       //一致したので解放する
-                                       this.integerRegisterAllocationTable.splice(i, 1);
-                               }
-                               break;
-                       }
-               }
-               if(i == iLen){
-                       console.log("register free error.");
-               }
-       },
-       virtualPointerRegisterOffset: 0x20000000,
-       allocatePointerRegister: function(owner){
-               //レジスタテーブルは先頭から番号の小さい順につめて格納する。
-               //[regID, owner]
-               //0x20000000-0x2fffffff: 未決定の仮想ポインタレジスタ番号
-               var freeRegID = 0;
-               for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
-                       if(this.pointerRegisterAllocationTable[i][0] != i + this.virtualPointerRegisterOffset){
-                               //空いているレジスタ番号を見つけた
-                               this.pointerRegisterAllocationTable.splice(i, 0, [i + this.virtualPointerRegisterOffset, owner]);
-                       }
-               }
-               if(i == iLen){
-                       //途中に空いているレジスタはなかったので追加
-                       this.pointerRegisterAllocationTable.push([i + this.virtualPointerRegisterOffset, owner]);
-               }
-               return i + this.virtualPointerRegisterOffset;
-       },
-       freePointerRegister: function(regID, owner){
-               for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
-                       if(this.pointerRegisterAllocationTable[i][0] == regID){
-                               //レジスタ番号を見つけた
-                               //オーナーが一致するか確認
-                               if(this.pointerRegisterAllocationTable[i][1] == owner){
-                                       //一致したので解放する
-                                       this.pointerRegisterAllocationTable.splice(i, 1);
-                               }
-                               break;
-                       }
-               }
-               if(i == iLen){
-                       console.log("register free error.");
-               }
-       },
-       freeAllRegisterOfOwner: function(owner){
-               //ownerが確保しているレジスタをすべて解放する
-               //IntegerRegister
-               for(var i = 0, iLen = this.integerRegisterAllocationTable.length; i < iLen; i++){
-                       if(this.integerRegisterAllocationTable[i][1] == owner){
-                               //見つけた
-                               this.integerRegisterAllocationTable.splice(i, 1);
-                               iLen--;
-                       }
-               }
-               //PointerRegister
-               for(var i = 0, iLen = this.pointerRegisterAllocationTable.length; i < iLen; i++){
-                       if(this.pointerRegisterAllocationTable[i][1] == owner){
-                               //見つけた
-                               this.pointerRegisterAllocationTable.splice(i, 1);
-                               iLen--;
-                       }
-               }
-       },
-       expandBinaryString: function(){
-               var ary = this.bin;
-               var b = new Array();
-               var aryStack = new Array();
-               var indexStack = new Array();
-               for(var i = 0; ; i++){
-                       if(ary[i] === undefined){
-                               ary = aryStack.pop();
-                               if(ary === undefined){
-                                       break;
-                               }
-                               i = indexStack.pop();
-                       }
-                       if(ary[i] instanceof Array){
-                                       aryStack.push(ary);
-                                       indexStack.push(i + 1);
-                                       ary = ary[i];
-                                       i = -1;
-                       } else if(ary[i] !== undefined){
-                                       b.push(ary[i]);
-                       }
-               }
-               this.bin = b;
-       },
-       assignRegister: function(){
-               for(var i = 0, iLen = this.bin.length; i < iLen; i++){
-                       if(this.bin[i] > 0xff){
-                               if(this.virtualIntegerRegisterOffset <= this.bin[i] && this.bin[i] <= this.virtualIntegerRegisterOffset + 0x1f){
-                                       //R00-R1fは無条件で割り当ててOK
-                                       this.bin[i] -= this.virtualIntegerRegisterOffset;
-                               } else if(this.virtualPointerRegisterOffset <= this.bin[i] && this.bin[i] <= this.virtualPointerRegisterOffset + 0x1f - 1){
-                                       //P01-P1fは無条件で割り当ててOK
-                                       this.bin[i] -= this.virtualPointerRegisterOffset;
-                                       this.bin[i] += 1;
-                               } else{
-                                       console.log("Sorry, but no more register.");
-                               }
-                       }
-               }
-       },
-       saveBinary: function(){
-               var m = this.env.IOManager;
-               var cl = this.bin;
-               var v = new Uint8Array(this.bin);
-               var d = new Blob([v]);
-               if(d){
-                       m.showDownloadLink(d);
-               }
-       },
-       
-}
-
 //
 // 文法構造クラス
 //
@@ -784,6 +34,8 @@ ELCHNOSCompiler_ExpressionStructure.prototype = {
                throw new ELCHNOSCompiler_CompileException(5, ["Translation undefined."], this.lineCount);
        },
        appendInstruction_LB: function(opt, labelID){
+               //var instr = new WebCPU_Instruction_LB();
+               
                this.bin.push(0x01, opt);
                this.appendInstruction_UINT32BE(labelID);
        },
@@ -1341,7 +593,7 @@ var ELCHNOSCompiler_ExpressionStructure_Expression = function(compiler, lineCoun
                for(var i = 0, iLen = this.evalStack.length; i < iLen; i++){
                        stack.push(this.evalStack.pop());
                }
-               console.log(stack.join(","));
+               //console.log(stack.join(","));
                for(var i = 0, iLen = stack.length; i < iLen; i++){
                        var o = stack.pop();
                        if(this.isOperator(o)){
@@ -1640,4 +892,4 @@ var ELCHNOSCompiler_ExpressionStructure_OSECPUBinary = function(compiler, lineCo
                }
                return this.bin;
        },
-});
\ No newline at end of file
+});
diff --git a/header.js b/header.js
new file mode 100644 (file)
index 0000000..683c6e9
--- /dev/null
+++ b/header.js
@@ -0,0 +1,24 @@
+include = function(relpath){\r
+       document.write("<script type='text/javascript' src=" + relpath + " charset='UTF-8'></script>");\r
+}\r
+//AICore\r
+include("./ai.js");\r
+include("./aiext.js");\r
+include("./aisub.js");\r
+include("./aimemory.js");\r
+include("./aimtbase.js");\r
+include("./aimemtag.js");\r
+include("./aithink.js");\r
+include("./aiwrcgnz.js");\r
+//ELCC\r
+include("./elcc/elcc.js");\r
+include("./elcc/elcexpr.js");\r
+//WebCPU\r
+include("./webcpu/ext.js");\r
+include("./webcpu/api.js");\r
+include("./webcpu/decoder.js");\r
+include("./webcpu/memory.js");\r
+include("./webcpu/instrbas.js");\r
+include("./webcpu/instr.js");\r
+include("./webcpu/webcpu.js");\r
+include("./webcpu/const.js");\r
index 153d112..2547aaa 100644 (file)
                line-height: 1.2;
        }
 </style>
-<script type="text/javascript" src="./ai.js" charset="UTF-8"></script>
-<script type="text/javascript" src="./aisub.js" charset="UTF-8"></script>
-<script type="text/javascript" src="./aiext.js" charset="UTF-8"></script>
-<script type="text/javascript" src="./aimemory.js" charset="UTF-8"></script>
-<script type="text/javascript" src="./aimtbase.js" charset="UTF-8"></script>
-<script type="text/javascript" src="./aimemtag.js" charset="UTF-8"></script>
-<script type="text/javascript" src="./aithink.js" charset="UTF-8"></script>
-<script type="text/javascript" src="./aiwrcgnz.js" charset="UTF-8"></script>
-<script type="text/javascript" src="./elcc.js" charset="UTF-8"></script>
+<script type="text/javascript" src="./header.js" charset="UTF-8"></script>
 <script type="text/javascript">
 var mainAI = null;
 var inputBoxObj = null;
similarity index 97%
rename from test.elc
rename to testdata/elc/bball.elc
index 44b3111..c2c947f 100644 (file)
--- a/test.elc
@@ -1,4 +1,6 @@
 #17ddde48-7d4c-498f-98d8-3e73f8845028
+//app0023
+//bball
 
 unsigned char table[32] = {
        196, 100, 187,  61, 164,  29, 129,   9,
diff --git a/webcpu/api.js b/webcpu/api.js
new file mode 100644 (file)
index 0000000..e1f1a6c
--- /dev/null
@@ -0,0 +1,126 @@
+function WebCPU_API(){
+       this.mainWindowCanvas = null;
+       this.mainWindowContext = null;
+       this.mainWindowBufferCanvas = document.createElement('canvas');
+       this.mainWindowBufferContext = this.mainWindowBufferCanvas.getContext("2d");
+       //
+       this.mainWindowBufferCanvas.width = 640;
+       this.mainWindowBufferCanvas.height = 480;
+       this.initCanvas(this.mainWindowBufferCanvas);
+}
+WebCPU_API.prototype = {
+       executeAPI: function(env){
+               var r = env.registers.Integer;
+               var APIID = r[0x30];
+               switch(APIID){
+                       case 0xff40:
+                               //openWin
+                               this.API_openWin(env, r[0x31], r[0x32])
+                               break;
+                       case 0xff41:
+                               //openWin
+                               this.API_flushWin(env, r[0x31], r[0x32], r[0x33], r[0x34])
+                               break;
+                       case 0xff44:
+                               //drawPoint
+                               this.API_drawPoint(env, r[0x31], r[0x32], r[0x33], r[0x34]);
+                               break;
+                       case 0xff45:
+                               //drawLine
+                               this.API_drawLine(env, r[0x31], r[0x32], r[0x33], r[0x34], r[0x35], r[0x36]);
+                               break;
+                       case 0xff46:
+                               //fillRect
+                               this.API_fillRect(env, r[0x31], r[0x32], r[0x33], r[0x34], r[0x35], r[0x36]);
+                               break;
+                       case 0xff47:
+                               //fillOval
+                               this.API_fillOval(env, r[0x31], r[0x32], r[0x33], r[0x34], r[0x35], r[0x36]);
+                               break;
+                       default:
+                               throw new WebCPU_Exception(0, ["Unknown API Number " + APIID.toString(16)]);
+               }
+               env.goToPointerRegister(0x30);
+       },
+       colorTable:[
+               0x000000, 
+               0xff0000, 
+               0x00ff00, 
+               0xffff00, 
+               0x0000ff, 
+               0xff00ff, 
+               0x00ffff, 
+               0xffffff
+       ],
+       setMainWindowCanvasDOMObject: function(obj){
+               this.mainWindowCanvas = obj;
+               if(this.mainWindowCanvas){
+                       this.mainWindowContext = this.mainWindowCanvas.getContext('2d')
+                       this.initCanvas(this.mainWindowCanvas);
+               } else{
+                       this.mainWindowContext = null;
+               }
+       },
+       initCanvas: function(c){
+               var d = c.getContext('2d');
+               d.fillStyle = "rgba(0,0,0,1)";
+               d.strokeStyle = "rgba(255, 255, 255, 1)";
+               d.lineWidth = 1;
+               //描画域は必ず黒で初期化されます。
+               d.fillRect(0, 0, c.width, c.height);
+       },
+       //
+       API_openWin: function(env, xSize, ySize){
+               env.message("junkApi_openWin();\n", 20);
+               this.mainWindowCanvas.width = xSize;
+               this.mainWindowCanvas.height = ySize;
+               this.mainWindowBufferCanvas.width = xSize;
+               this.mainWindowBufferCanvas.height = ySize;
+       },
+       API_flushWin: function(env, xSize, ySize, x0, y0){
+               env.message("junkApi_flushWin();\n", 20);
+               this.mainWindowContext.drawImage(this.mainWindowBufferCanvas, x0, y0, xSize, ySize, 0, 0, xSize, ySize);
+       },
+       API_drawPoint: function(env, mode, x, y, col){
+               env.message("junkApi_drawPoint();\n", 20);
+               if((mode & 0x04) != 0){
+                       col = this.colorTable[col];
+               }
+               this.mainWindowBufferContext.fillStyle = "#" + ("000000" + col.toString(16)).slice(-6).toUpperCase();
+               this.mainWindowBufferContext.fillRect(x, y, 1, 1);
+       },
+       API_drawLine: function(env, mode, x0, y0, x1, y1, col){
+               env.message("junkApi_drawLine();\n", 20);
+
+               if((mode & 0x04) != 0){
+                       col = this.colorTable[col];
+               }
+               
+               this.mainWindowBufferContext.strokeStyle = "#" + ("000000" + col.toString(16)).slice(-6).toUpperCase();
+               this.mainWindowBufferContext.beginPath();
+               this.mainWindowBufferContext.moveTo(x0, y0);
+               this.mainWindowBufferContext.lineTo(x1, y1);
+               this.mainWindowBufferContext.closePath();
+               this.mainWindowBufferContext.stroke();
+       },
+       API_fillRect: function(env, mode, xSize, ySize, x0, y0, col){
+               env.message("junkApi_fillRect();\n", 20);
+
+               if((mode & 0x04) != 0){
+                       col = this.colorTable[col];
+               }
+               
+               this.mainWindowBufferContext.fillStyle = "#" + ("000000" + col.toString(16)).slice(-6).toUpperCase();
+               this.mainWindowBufferContext.fillRect(x0, y0, xSize, ySize);
+       },
+       API_fillOval: function(env, mode, xSize, ySize, x0, y0, col){
+               env.message("junkApi_fillRect();\n", 20);
+
+               if((mode & 0x04) != 0){
+                       col = this.colorTable[col];
+               }
+               
+               this.mainWindowBufferContext.fillStyle = "#" + ("000000" + col.toString(16)).slice(-6).toUpperCase();
+               this.mainWindowBufferContext.fillEllipse(x0, y0, xSize, ySize);
+       },
+}
diff --git a/webcpu/const.js b/webcpu/const.js
new file mode 100644 (file)
index 0000000..b594083
--- /dev/null
@@ -0,0 +1,53 @@
+WebCPU.maxDebugStringLength = 0xffff;
+
+WebCPU_Instruction.opcode = {
+       NOP:    0x00,
+       LB:             0x01,
+       LIMM:   0x02,
+       PLIMM:  0x03,
+       CND:    0x04,
+       //
+       LMEM:   0x08,
+       SMEM:   0x09,
+       //
+       PADD:   0x0E,
+       PDIF:   0x0F,
+       //
+       CP:             0x10,
+       OR:             0x10,
+       XOR:    0x11,
+       AND:    0x12,
+       //
+       ADD:    0x14,
+       SUB:    0x15,
+       MUL:    0x16,
+       //
+       SHL:    0x18,
+       SAR:    0x19,
+       //
+       DIV:    0x1A,
+       MOD:    0x1B,
+       //
+       PCP:    0x1E,
+       //
+       CMPE:   0x20,
+       CMPNE:  0x21,
+       CMPL:   0x22,
+       CMPGE:  0x23,
+       CMPLE:  0x24,
+       CMPG:   0x25,
+       TSTZ:   0x26,
+       TSTNZ:  0x27,
+       PCMPE:  0x28,
+       PCMPNE: 0x29,
+       PCMPL:  0x2A,
+       PCMPGE: 0x2B,
+       PCMPLE: 0x2C,
+       PCMPG:  0x2D,
+       //
+       MALLOC: 0x32,
+       //
+       DATA:   0x34,
+       //
+       REMARK: 0xFE,
+}
diff --git a/webcpu/decoder.js b/webcpu/decoder.js
new file mode 100644 (file)
index 0000000..5f9f5f3
--- /dev/null
@@ -0,0 +1,1984 @@
+//decoderバイナリ文字列
+// http://qiita.com/_shimizu/items/837b529de9f3302e315c
+// http://qiita.com/ArcCosine@github/items/c41548ec03a7571defa4
+// http://osecpu.osask.jp/wiki/?page0063
+// @osecpu072d
+var decoderBinaryString = (function () {/*
+05e100021e00000000021f000000011e
+08021e09031e02041e03060100000000
+002b3f0205043f033f00000001080000
+0000030200023f000000010e02000000
+03023f023f0000000f1201003f023f00
+0000041900003f090000000003030002
+3f000000010e0300000003033f090100
+0000030300023f000000010e03000000
+03033f033f0000000001000000000102
+00000000000900000000030300023f00
+0000010e0300000003033f0900000000
+030300023f000000010e030000000303
+3f0900000000030300023f000000010e
+0300000003033f090000000003030002
+3f000000010e0300000003033f1e0206
+1e03080900000000030300023f000000
+010e0300000003033f09000000000303
+00023f000000010e0300000003033f09
+00000000030300023f000000010e0300
+000003033f0900000000030300023f00
+0000010e0300000003033f0900000000
+030300023f000000010e030000000303
+3f0900000000030300023f000000010e
+0300000003033f090000000003030002
+3f000000010e0300000003033f020400
+0000000205ffffffff02270000000002
+26ffffffff0225000000000200000000
+3f0900000000070a00023f000000010e
+0a000000070a3f0900000000070a0002
+3f000000010e0a000000070a3f090000
+0000070a00023f000000010e0a000000
+070a3f0900000000070a00023f000000
+010e0a000000070a3f1e310b02000000
+0000fe05020000004002010000000001
+00000000020900000000063100023f00
+0000010e3100000006313ffe0101023f
+000000011401013f023f00000040213f
+013f043f033f00000002020000000001
+023f000000010e31000000060b3f0900
+0000000631001e310c020000000000fe
+05020000100002010000000001000000
+00030900000000063100023f00000001
+0e3100000006313ffe0101023f000000
+011401013f023f00001000213f013f04
+3f033f00000003fe0502000001000201
+000000000100000000040e3f00000003
+0d010901000000033f00fe0101023f00
+0000011401013f023f00000100213f01
+3f043f033f0000000401000000000503
+3000000006033f000000df0101000000
+06fe0100023f00000000213f003f043f
+033f00000007293f0206043f033f0000
+00c70100000000070e3f000000030d00
+0800000000033f00023f00000001213f
+003f043f033f00000013023f00000000
+203f273f043f033f0000000e01000000
+0008033000000009033f000000df0101
+00000009fe0100023f00000000203f00
+3f043f033f0000000d023f0000000121
+3f003f043f033f0000000bfe05020000
+010002010000000001000000000a0e3f
+000000030d010901000000033f00fe01
+01023f000000011401013f023f000001
+00213f013f043f033f0000000a033f00
+00000801000000000b100100ff033000
+00000c033f000000df01010000000cfe
+01000e3f000000030d00090100000003
+3f000e3f000000030d01090000000003
+3f00033f0000000801000000000d033f
+0000001001000000000e090000000003
+0300023f000000010e0300000003033f
+023f000000011405053f023f00000000
+213f043f043f033f0000001102010000
+00000901000000030300023f00000001
+0e0300000003033f100005ff01000000
+000f100200ff023f000000181901023f
+023f000000ff1201013f090100000003
+0300023f000000010e0300000003033f
+023f000000101901023f023f000000ff
+1201013f0901000000030300023f0000
+00010e0300000003033f023f00000008
+1901023f023f000000ff1201013f0901
+000000030300023f000000010e030000
+0003033f023f000000ff1201023f0901
+000000030300023f000000010e030000
+0003033f010000000010020400000000
+022700000000033f0000000501000000
+00110900000000030300023f00000001
+0e0300000003033f033000000012033f
+000000e8010100000012fe0100023f00
+0000ff1201003f090100000003030002
+3f000000010e0300000003033f023f00
+0000081900003f14000005100500ff03
+3f0000000f010000000013023f000000
+02213f003f043f033f00000017090000
+0000030300023f000000010e03000000
+03033f033000000014033f000000df01
+0100000014fe01000900000000030300
+023f000000010e0300000003033f0330
+00000015033f000000e8010100000015
+fe0100033000000016033f000000ee01
+0100000016fe0100033f0000000f0100
+00000017023f00000003213f003f043f
+033f0000001b0900000000030300023f
+000000010e0300000003033f02000000
+003f023f00000000203f043f043f033f
+00000019033000000018033f000000df
+010100000018fe01000e31000000060b
+00023000000001093000000006310001
+00000000190900000000030300023f00
+0000010e0300000003033f0330000000
+1a033f000000e801010000001afe0100
+14000005033f0000000f01000000001b
+023f00000004213f003f043f033f0000
+001e023f00000000213f043f043f033f
+0000001c020400000001033f00000005
+01000000001c0900000000030300023f
+000000010e0300000003033f03300000
+001d033f000000df01010000001dfe01
+000900000000030300023f000000010e
+0300000003033f033f00000010010000
+00001e023f00000005213f003f043f03
+3f0000004b0201000000fe0901000000
+030300023f000000010e030000000303
+3f020100000005090100000003030002
+3f000000010e0300000003033f020100
+0000010901000000030300023f000000
+010e0300000003033f03300000001f03
+3f000000e801010000001ffe01001002
+00ff023f000000181901023f023f0000
+00ff1201013f0901000000030300023f
+000000010e0300000003033f023f0000
+00101901023f023f000000ff1201013f
+0901000000030300023f000000010e03
+00000003033f023f000000081901023f
+023f000000ff1201013f090100000003
+0300023f000000010e0300000003033f
+023f000000ff1201023f090100000003
+0300023f000000010e0300000003033f
+020f0000003f020e0000003f020d0000
+003f020c0000003f023f00000000203f
+043f043f033f00000024023f00000002
+213f003f043f033f00000020020c0000
+0032010000000020023f00000003213f
+003f043f033f00000021020c00000032
+010000000021023f00000004213f003f
+043f033f00000022020c000000320100
+00000022023f00000005213f003f043f
+033f00000023020c0000003201000000
+0023010000000024023f00000010213f
+003f043f033f0000002602000000ff40
+02070000003302080000000002090000
+0000020a000000000210000000000330
+00000025033f0000015a010100000025
+fe0100033f0000000501000000002602
+3f00000011213f003f043f033f000000
+2802000000ff41020700000035020800
+000000020900000000020a0000000002
+1000000000033000000027033f000001
+5a010100000027fe0100033f00000005
+010000000028023f00000009213f003f
+043f033f0000002a02000000ff420207
+00000033020800000000020900000000
+020a0000000002100000000003300000
+0029033f0000015a010100000029fe01
+00033f0000000501000000002a023f00
+00000d213f003f043f033f0000002c02
+000000ff430207000000320208000000
+00020900000030020a00000000021000
+00000003300000002b033f0000015a01
+010000002bfe0100033f000000050100
+0000002c023f00000002213f003f043f
+033f0000002e02000000ff4402070000
+0035020800000000020900000000020a
+0000000002100000000003300000002d
+033f0000015a01010000002dfe010003
+3f0000000501000000002e023f000000
+03213f003f043f033f00000030020000
+00ff4502070000003702080000000002
+0900000000020a000000000210000000
+0003300000002f033f0000015a010100
+00002ffe0100033f0000000501000000
+0030023f00000004213f003f043f033f
+0000003202000000ff46020700000037
+020800000000020900000000020a0000
+0000021000000000033000000031033f
+0000015a010100000031fe0100033f00
+000005010000000032023f0000000521
+3f003f043f033f0000003402000000ff
+47020700000037020800000000020900
+000000020a0000000002100000000003
+3000000033033f0000015a0101000000
+33fe0100033f00000005010000000034
+023f00000006213f003f043f033f0000
+003602000000ff480207000000370208
+00000031020900000000020a00000000
+021000000001033000000035033f0000
+015a010100000035fe0100033f000000
+05010000000036023f00000740213f00
+3f043f033f0000003802000000ff0102
+07000000320208000000000209000000
+30020a00000031021000000000033000
+000037033f0000015a010100000037fe
+0100033f00000005010000000038023f
+00000741213f003f043f033f0000003a
+02000000ff0202070000003302080000
+0032020900000000020a000000000210
+00000000033000000039033f0000015a
+010100000039fe0100033f0000000501
+000000003a023f00000742213f003f04
+3f033f0000003c02000000ff03020700
+00000002080000000002090000000002
+0a000000310210000000000330000000
+3b033f0000015a01010000003bfe0100
+033f0000000501000000003c023f0000
+0743213f003f043f033f0000003e0200
+0000ff05020700000032020800000032
+020900000000020a0000000002100000
+000003300000003d033f0000015a0101
+0000003dfe0100033f00000005010000
+00003e023f00000001213f003f043f03
+3f0000004002000000ff070207000000
+31020800000031020900000000020a00
+00000002100000000103300000003f03
+3f0000015a01010000003ffe0100033f
+00000005010000000040023f00000013
+213f003f043f033f0000004202000000
+ff490207000000320208000000000209
+00000030020a00000000021000000000
+033000000041033f0000015a01010000
+0041fe0100033f000000050100000000
+42023f00000014213f003f043f033f00
+00004402000000ff4902070000003202
+0800000000020900000000020a000000
+00021000000000033000000043033f00
+00015a010100000043fe0100033f0000
+0005010000000044023f00000015213f
+003f043f033f0000004602000000ff49
+02070000003102080000000002090000
+0030020a000000000210000000000330
+00000045033f0000015a010100000045
+fe0100033f0000000501000000004602
+3f00000016213f003f043f033f000000
+4802000000ff09020700000031020800
+000031020900000000020a0000000002
+1000000003033000000047033f000001
+5a010100000047fe0100033f00000005
+010000000048023f00000017213f003f
+043f033f0000004a02000000ff4c0207
+00000037020800000031020900000000
+020a0000000002100000000303300000
+0049033f0000015a010100000049fe01
+00033f0000000501000000004a023fff
+fffffa0e0300000003033f033f000000
+de01000000004b023f00000006213f00
+3f043f033f0000005103300000004c03
+3f000000df01010000004cfe01001006
+00ff03300000004d033f000000e80101
+0000004dfe010003300000004e033f00
+0000ee01010000004efe0100100700ff
+023f000000011405053f03300000004f
+033f000000e801010000004ffe010003
+3000000050033f000000ee0101000000
+50fe0100100800ff0906000000070a00
+023f000000010e0a000000070a3f0907
+000000070a00023f000000010e0a0000
+00070a3f0905000000070a00023f0000
+00010e0a000000070a3f090800000007
+0a00023f000000010e0a000000070a3f
+0201000000fe0901000000030300023f
+000000010e0300000003033f02010000
+00050901000000030300023f00000001
+0e0300000003033f0201000000020901
+000000030300023f000000010e030000
+0003033f100208ff023f000000181901
+023f023f000000ff1201013f09010000
+00030300023f000000010e0300000003
+033f023f000000101901023f023f0000
+00ff1201013f0901000000030300023f
+000000010e0300000003033f023f0000
+00081901023f023f000000ff1201013f
+0901000000030300023f000000010e03
+00000003033f023f000000ff1201023f
+0901000000030300023f000000010e03
+00000003033f02010000000209010000
+00030300023f000000010e0300000003
+033f0906000000030300023f00000001
+0e0300000003033f100207ff023f0000
+00181901023f023f000000ff1201013f
+0901000000030300023f000000010e03
+00000003033f023f000000101901023f
+023f000000ff1201013f090100000003
+0300023f000000010e0300000003033f
+023f000000081901023f023f000000ff
+1201013f0901000000030300023f0000
+00010e0300000003033f023f000000ff
+1201023f0901000000030300023f0000
+00010e0300000003033f020100000001
+0901000000030300023f000000010e03
+00000003033f02010000000009010000
+00030300023f000000010e0300000003
+033f100005ff033f0000000f01000000
+0051023f00000007213f003f043f033f
+000000530100000000520201000000fe
+0901000000030300023f000000010e03
+00000003033f02010000000109010000
+00030300023f000000010e0300000003
+033f0201000000010901000000030300
+023f000000010e0300000003033f0201
+000000020901000000030300023f0000
+00010e0300000003033f02010000003f
+0901000000030300023f000000010e03
+00000003033f023ffffffffc0e0a0000
+00070a3f0803000000070a00023f0000
+00010e0a000000070a3f080700000007
+0a00023f000000010e0a000000070a3f
+0808000000070a00023f000000010e0a
+000000070a3f0806000000070a00023f
+000000010e0a000000070a3f023fffff
+fffc0e0a000000070a3f15000607023f
+0000001f1900003f023f000000011000
+003f100200ff023f000000181901023f
+023f000000ff1201013f090100000003
+0300023f000000010e0300000003033f
+023f000000101901023f023f000000ff
+1201013f0901000000030300023f0000
+00010e0300000003033f023f00000008
+1901023f023f000000ff1201013f0901
+000000030300023f000000010e030000
+0003033f023f000000ff1201023f0901
+000000030300023f000000010e030000
+0003033f020100000014090100000003
+0300023f000000010e0300000003033f
+0903000000030300023f000000010e03
+00000003033f0903000000030300023f
+000000010e0300000003033f02010000
+003f0901000000030300023f00000001
+0e0300000003033f0201000000020901
+000000030300023f000000010e030000
+0003033f02010000003f090100000003
+0300023f000000010e0300000003033f
+100206ff023f000000181901023f023f
+000000ff1201013f0901000000030300
+023f000000010e0300000003033f023f
+000000101901023f023f000000ff1201
+013f0901000000030300023f00000001
+0e0300000003033f023f000000081901
+023f023f000000ff1201013f09010000
+00030300023f000000010e0300000003
+033f023f000000ff1201023f09010000
+00030300023f000000010e0300000003
+033f0201000000210901000000030300
+023f000000010e0300000003033f0201
+0000003f0901000000030300023f0000
+00010e0300000003033f090300000003
+0300023f000000010e0300000003033f
+02010000003f0901000000030300023f
+000000010e0300000003033f02010000
+00040901000000030300023f00000001
+0e0300000003033f02010000003f0901
+000000030300023f000000010e030000
+0003033f020100000003090100000003
+0300023f000000010e0300000003033f
+02010000003f0901000000030300023f
+000000010e0300000003033f100208ff
+023f000000181901023f023f000000ff
+1201013f0901000000030300023f0000
+00010e0300000003033f023f00000010
+1901023f023f000000ff1201013f0901
+000000030300023f000000010e030000
+0003033f023f000000081901023f023f
+000000ff1201013f0901000000030300
+023f000000010e0300000003033f023f
+000000ff1201023f0901000000030300
+023f000000010e0300000003033f033f
+00000005010000000053023f00000008
+233b003f023f0000000b243a003f123a
+3a3b023fffffffff113a3a3f043a033f
+0000005c0900000000030300023f0000
+00010e0300000003033f100800ff0330
+00000054033f000000df010100000054
+fe01000900000000030300023f000000
+010e0300000003033f100900ff033000
+000055033f000000df010100000055fe
+0100100700ff0e31000000060b000834
+000000063100091f000000063100023f
+00000000203f273f043f033f00000056
+0234000000000100000000560200ffff
+ffff023f00000000213f343f043f033f
+00000058033000000057033f000000df
+010100000057fe010001000000005810
+0200ff023f000000181901023f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000101901023f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f00000008190102
+3f023f000000ff1201013f0901000000
+030300023f000000010e030000000303
+3f023f000000ff1201023f0901000000
+030300023f000000010e030000000303
+3f100600ff0907000000030300023f00
+0000010e0300000003033f0330000000
+59033f000000df010100000059fe0100
+0900000000030300023f000000010e03
+00000003033f023f0000000a213f083f
+043f033f0000005a0231000000000e3f
+000000060b090931000000063f000100
+0000005a023f00000000213f043f043f
+033f0000005b02010000000209010000
+00030300023f000000010e0300000003
+033f02010000003f0901000000030300
+023f000000010e0300000003033f0201
+000000000901000000030300023f0000
+00010e0300000003033f020100000000
+0901000000030300023f000000010e03
+00000003033f02010000000009010000
+00030300023f000000010e0300000003
+033f0201000000010901000000030300
+023f000000010e0300000003033f0201
+0000000e0901000000030300023f0000
+00010e0300000003033f090700000003
+0300023f000000010e0300000003033f
+100206ff023f000000181901023f023f
+000000ff1201013f0901000000030300
+023f000000010e0300000003033f023f
+000000101901023f023f000000ff1201
+013f0901000000030300023f00000001
+0e0300000003033f023f000000081901
+023f023f000000ff1201013f09010000
+00030300023f000000010e0300000003
+033f023f000000ff1201023f09010000
+00030300023f000000010e0300000003
+033f0907000000030300023f00000001
+0e0300000003033f02010000003f0901
+000000030300023f000000010e030000
+0003033f01000000005b033f00000010
+01000000005c023f0000000d213f003f
+043f033f0000005d022700000001033f
+0000000501000000005d023f0000000e
+213f003f043f033f00000066023f0000
+00060e0f00000003033f1e0e0f090000
+0000030f00023f000000010e0f000000
+030f3f03300000005e033f000000df01
+010000005efe01000900000000030f00
+023f000000010e0f000000030f3f1006
+00ff100806ff023f00000000203f043f
+043f033f0000006003300000005f033f
+000000df01010000005ffe0100100800
+ff0100000000600e31000000060b0808
+3400000006310009310000000631000e
+31000000060b06091f00000006310002
+3f00000000203f273f043f033f000000
+610234000000000100000000610200ff
+ffffff023f00000000213f343f043f03
+3f00000063033000000062033f000000
+df010100000062fe0100010000000063
+100200ff023f000000181901023f023f
+000000ff1201013f0901000000030f00
+023f000000010e0f000000030f3f023f
+000000101901023f023f000000ff1201
+013f0901000000030f00023f00000001
+0e0f000000030f3f023f000000081901
+023f023f000000ff1201013f09010000
+00030f00023f000000010e0f00000003
+0f3f023f000000ff1201023f09010000
+00030f00023f000000010e0f00000003
+0f3f0908000000030f00023f00000001
+0e0f000000030f3f033000000064033f
+000000f1010100000064fe0100010000
+0000650801000000030e00023f000000
+010e0e000000030e3f09010000000303
+00023f000000010e0300000003033f29
+3f0e0f043f033f00000065033f000000
+10010000000066023f0000000f213f00
+3f043f033f0000006e09000000000303
+00023f000000010e0300000003033f03
+3000000067033f000000df0101000000
+67fe01000900000000030300023f0000
+00010e0300000003033f033000000068
+033f000000df010100000068fe010010
+0600ff033000000069033f000000df01
+0100000069fe0100100700ff0e310000
+00060b060834000000063100091f0000
+000631000e31000000060b0708320000
+00063100091f000000063100023f0000
+0000213f343f043f033f0000006a1034
+32ff01000000006a023f00000000203f
+273f043f033f0000006b023400000000
+01000000006b0200ffffffff023f0000
+0000213f343f043f033f0000006d0330
+0000006c033f000000df01010000006c
+fe010001000000006d100200ff023f00
+0000181901023f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f00000010190102
+3f023f000000ff1201013f0901000000
+030300023f000000010e030000000303
+3f023f000000081901023f023f000000
+ff1201013f0901000000030300023f00
+0000010e0300000003033f023f000000
+ff1201023f0901000000030300023f00
+0000010e0300000003033f0906000000
+030300023f000000010e030000000303
+3f0907000000030300023f000000010e
+0300000003033f033f00000010010000
+00006e023f00000017213f003f043f03
+3f000000710201000000100901000000
+030300023f000000010e030000000303
+3f03300000006f033f000000df010100
+00006ffe01000900000000030300023f
+000000010e0300000003033f03300000
+0070033f000000df010100000070fe01
+000900000000030300023f000000010e
+0300000003033f0201000000ff090100
+0000030300023f000000010e03000000
+03033f033f0000001001000000007102
+3f00000010233b003f023f0000001b24
+3a003f123a3a3b023fffffffff113a3a
+3f043a033f0000007c023f000000060e
+0f00000003033f1e0e0f090000000003
+0f00023f000000010e0f000000030f3f
+033000000072033f000000df01010000
+0072fe01000900000000030f00023f00
+0000010e0f000000030f3f023f000000
+00203f043f043f033f00000074033000
+000073033f000000df010100000073fe
+01000100000000740900000000030f00
+023f000000010e0f000000030f3f1003
+00ff033000000075033f000000f10101
+00000075fe0100023f0000003f213f03
+3f043f033f0000007a03300000007603
+3f000000e8010100000076fe0100023f
+ffffffb1233b003f023ffffffff0243a
+003f123a3a3b023fffffffff113a3a3f
+043a033f00000077023ffffffff01500
+3f00033f000000790100000000770201
+000000020901000000030300023f0000
+00010e0300000003033f02010000003f
+0901000000030300023f000000010e03
+00000003033f033000000078033f0000
+00ee010100000078fe0100100200ff02
+3f000000181901023f023f000000ff12
+01013f0901000000030300023f000000
+010e0300000003033f023f0000001019
+01023f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000081901023f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000ff1201023f090100000003030002
+3f000000010e0300000003033f010000
+00007901000000007a01000000007b08
+01000000030e00023f000000010e0e00
+0000030e3f0901000000030300023f00
+0000010e0300000003033f293f0e0f04
+3f033f0000007b033f00000010010000
+00007c023f0000001c233b003f023f00
+00001d243a003f123a3a3b023fffffff
+ff113a3a3f043a033f0000007f090000
+0000030300023f000000010e03000000
+03033f03300000007d033f000000df01
+010000007dfe01000900000000030300
+023f000000010e0300000003033f0330
+0000007e033f000000df01010000007e
+fe01000900000000030300023f000000
+010e0300000003033f033f0000001001
+000000007f023f0000001e213f003f04
+3f033f00000082090000000003030002
+3f000000010e0300000003033f033000
+000080033f000000df010100000080fe
+01000900000000030300023f00000001
+0e0300000003033f100600ff03300000
+0081033f000000df010100000081fe01
+000900000000030300023f000000010e
+0300000003033f0e3f000000060b0008
+01000000063f000e3f000000060b0609
+01000000063f00033f00000010010000
+000082023f0000001f213f003f043f03
+3f0000008a0900000000030300023f00
+0000010e0300000003033f0330000000
+83033f000000df010100000083fe0100
+0900000000030300023f000000010e03
+00000003033f100600ff033000000084
+033f000000df010100000084fe010010
+0700ff100200ff023f00000018190102
+3f023f000000ff1201013f0901000000
+030300023f000000010e030000000303
+3f023f000000101901023f023f000000
+ff1201013f0901000000030300023f00
+0000010e0300000003033f023f000000
+081901023f023f000000ff1201013f09
+01000000030300023f000000010e0300
+000003033f023f000000ff1201023f09
+01000000030300023f000000010e0300
+000003033f033000000085033f000000
+df010100000085fe0100090000000003
+0300023f000000010e0300000003033f
+0e31000000060b000834000000063100
+091f000000063100023f00000000203f
+273f043f033f00000086023400000000
+0100000000860200ffffffff023f0000
+0000213f343f043f033f000000880330
+00000087033f000000df010100000087
+fe0100010000000088100200ff023f00
+0000181901023f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f00000010190102
+3f023f000000ff1201013f0901000000
+030300023f000000010e030000000303
+3f023f000000081901023f023f000000
+ff1201013f0901000000030300023f00
+0000010e0300000003033f023f000000
+ff1201023f0901000000030300023f00
+0000010e0300000003033f0231000000
+01023f00000000213f073f043f033f00
+0000890231000000000100000000890e
+3f000000060b060931000000063f0003
+3f0000001001000000008a023f000000
+20233b003f023f00000027243a003f12
+3a3a3b023fffffffff113a3a3f043a03
+3f00000092023f000000060e0f000000
+03033f1e0e0f0900000000030f00023f
+000000010e0f000000030f3f02000000
+003f023f00000000203f043f043f033f
+0000008c03300000008b033f000000df
+01010000008bfe010001000000008c09
+00000000030f00023f000000010e0f00
+0000030f3f100900ff03300000008d03
+3f000000df01010000008dfe01000900
+000000030f00023f000000010e0f0000
+00030f3f03300000008e033f000000f1
+01010000008efe010001000000008f08
+01000000030e00023f000000010e0e00
+0000030e3f0901000000030300023f00
+0000010e0300000003033f293f0e0f04
+3f033f0000008f023f0000003f213f09
+3f043f033f0000009102010000000409
+01000000030300023f000000010e0300
+000003033f02010000003f0901000000
+030300023f000000010e030000000303
+3f020100000003090100000003030002
+3f000000010e0300000003033f020100
+00003f0901000000030300023f000000
+010e0300000003033f03300000009003
+3f000000e8010100000090fe01001400
+0005033f0000000f010000000091033f
+00000010010000000092023f0000002e
+213f003f043f033f00000093023f0000
+00011405053f02010000000109010000
+00030300023f000000010e0300000003
+033f0201000000010901000000030300
+023f000000010e0300000003033f1002
+05ff023f000000181901023f023f0000
+00ff1201013f0901000000030300023f
+000000010e0300000003033f023f0000
+00101901023f023f000000ff1201013f
+0901000000030300023f000000010e03
+00000003033f023f000000081901023f
+023f000000ff1201013f090100000003
+0300023f000000010e0300000003033f
+023f000000ff1201023f090100000003
+0300023f000000010e0300000003033f
+02000000003402040000000001000000
+0093023f00000038233b003f023f0000
+003b243a003f123a3a3b023fffffffff
+113a3a3f043a033f0000009b023f0000
+00301506003f02010000000e09010000
+00030300023f000000010e0300000003
+033f02010000003f0901000000030300
+023f000000010e0300000003033f0330
+00000094033f000000df010100000094
+fe0100100700ff033000000095033f00
+0000df010100000095fe0100100800ff
+0e31000000060b080834000000063100
+091f000000063100023f00000000203f
+273f043f033f00000096023400000000
+0100000000960200ffffffff023f0000
+0000213f343f043f033f000000980330
+00000097033f000000df010100000097
+fe0100010000000098100200ff023f00
+0000181901023f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f00000010190102
+3f023f000000ff1201013f0901000000
+030300023f000000010e030000000303
+3f023f000000081901023f023f000000
+ff1201013f0901000000030300023f00
+0000010e0300000003033f023f000000
+ff1201023f0901000000030300023f00
+0000010e0300000003033f100900ff09
+08000000030300023f000000010e0300
+000003033f033000000099033f000000
+df010100000099fe0100090000000003
+0300023f000000010e0300000003033f
+0906000000030300023f000000010e03
+00000003033f0907000000030300023f
+000000010e0300000003033f100209ff
+023f000000181901023f023f000000ff
+1201013f0901000000030300023f0000
+00010e0300000003033f023f00000010
+1901023f023f000000ff1201013f0901
+000000030300023f000000010e030000
+0003033f023f000000081901023f023f
+000000ff1201013f0901000000030300
+023f000000010e0300000003033f023f
+000000ff1201023f0901000000030300
+023f000000010e0300000003033f0201
+0000003f0901000000030300023f0000
+00010e0300000003033f03300000009a
+033f000000df01010000009afe010009
+00000000030300023f000000010e0300
+000003033f033f000000100100000000
+9b023f0000003c213f003f043f033f00
+00009d023f000000011425253f023f00
+000000213f043f043f033f0000009c02
+3f000000011405053f02010000000109
+01000000030300023f000000010e0300
+000003033f0201000000010901000000
+030300023f000000010e030000000303
+3f100205ff023f000000181901023f02
+3f000000ff1201013f09010000000303
+00023f000000010e0300000003033f02
+3f000000101901023f023f000000ff12
+01013f0901000000030300023f000000
+010e0300000003033f023f0000000819
+01023f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000ff1201023f090100
+0000030300023f000000010e03000000
+03033f0201000000fe09010000000303
+00023f000000010e0300000003033f02
+01000000010901000000030300023f00
+0000010e0300000003033f0201000000
+000901000000030300023f000000010e
+0300000003033f01000000009c020100
+00003c0901000000030300023f000000
+010e0300000003033f02010000000009
+01000000030300023f000000010e0300
+000003033f0201000000200901000000
+030300023f000000010e030000000303
+3f020100000020090100000003030002
+3f000000010e0300000003033f020100
+0000000901000000030300023f000000
+010e0300000003033f02010000000009
+01000000030300023f000000010e0300
+000003033f0201000000000901000000
+030300023f000000010e030000000303
+3f033f0000001001000000009d023f00
+00003d213f003f043f033f000000a101
+000000009e0900000000030300023f00
+0000010e0300000003033f023fffffff
+fc0e0a000000070a3f0802000000070a
+00023f000000010e0a000000070a3f08
+03000000070a00023f000000010e0a00
+0000070a3f0806000000070a00023f00
+0000010e0a000000070a3f0800000000
+070a00023f000000010e0a000000070a
+3f023f0000003f203f023f043f033f00
+00009f023ffffffffe0e020000000302
+3f023fffffffff0e0300000003033f03
+3f0000005201000000009f0201000000
+000901000000030300023f000000010e
+0300000003033f020100000020090100
+0000030300023f000000010e03000000
+03033f02010000002009010000000303
+00023f000000010e0300000003033f02
+01000000000901000000030300023f00
+0000010e0300000003033f0201000000
+000901000000030300023f000000010e
+0300000003033f020100000000090100
+0000030300023f000000010e03000000
+03033f023f00000000203f043f043f03
+3f000000a002010000001e0901000000
+030300023f000000010e030000000303
+3f02010000003f090100000003030002
+3f000000010e0300000003033f020100
+0000300901000000030300023f000000
+010e0300000003033f0100000000a002
+3fffffffff1425253f033f0000001001
+00000000a1023f0000003e213f003f04
+3f033f000000a7023f00000001140505
+3f023f00000000203f043f043f033f00
+0000a50330000000a2033f000000e801
+01000000a2fe010014050500023f0000
+0000213f003f043f033f000000a40330
+000000a3033f000000df0101000000a3
+fe0100100500ff0100000000a4010000
+0000a502010000000309010000000303
+00023f000000010e0300000003033f02
+01000000300901000000030300023f00
+0000010e0300000003033f100205ff02
+3f000000181901023f023f000000ff12
+01013f0901000000030300023f000000
+010e0300000003033f023f0000001019
+01023f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000081901023f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000ff1201023f090100000003030002
+3f000000010e0300000003033f020100
+0000030901000000030300023f000000
+010e0300000003033f02010000003f09
+01000000030300023f000000010e0300
+000003033f0330000000a6033f000000
+e80101000000a6fe0100140000051002
+00ff023f000000181901023f023f0000
+00ff1201013f0901000000030300023f
+000000010e0300000003033f023f0000
+00101901023f023f000000ff1201013f
+0901000000030300023f000000010e03
+00000003033f023f000000081901023f
+023f000000ff1201013f090100000003
+0300023f000000010e0300000003033f
+023f000000ff1201023f090100000003
+0300023f000000010e0300000003033f
+0201000000010901000000030300023f
+000000010e0300000003033f02010000
+00010901000000030300023f00000001
+0e0300000003033f100205ff023f0000
+00181901023f023f000000ff1201013f
+0901000000030300023f000000010e03
+00000003033f023f000000101901023f
+023f000000ff1201013f090100000003
+0300023f000000010e0300000003033f
+023f000000081901023f023f000000ff
+1201013f0901000000030300023f0000
+00010e0300000003033f023f000000ff
+1201023f0901000000030300023f0000
+00010e0300000003033f0201000000fe
+0901000000030300023f000000010e03
+00000003033f02010000000109010000
+00030300023f000000010e0300000003
+033f0201000000000901000000030300
+023f000000010e0300000003033f033f
+000000100100000000a7023f0000003f
+213f003f043f033f000000ad023f0000
+00011405053f023f00000000203f043f
+043f033f000000ab0330000000a8033f
+000000e80101000000a8fe0100140505
+00023f00000000213f003f043f033f00
+0000aa0330000000a9033f000000df01
+01000000a9fe0100100500ff01000000
+00aa0100000000ab0201000000030901
+000000030300023f000000010e030000
+0003033f020100000030090100000003
+0300023f000000010e0300000003033f
+100205ff023f000000181901023f023f
+000000ff1201013f0901000000030300
+023f000000010e0300000003033f023f
+000000101901023f023f000000ff1201
+013f0901000000030300023f00000001
+0e0300000003033f023f000000081901
+023f023f000000ff1201013f09010000
+00030300023f000000010e0300000003
+033f023f000000ff1201023f09010000
+00030300023f000000010e0300000003
+033f02010000001e0901000000030300
+023f000000010e0300000003033f0201
+0000003f0901000000030300023f0000
+00010e0300000003033f0330000000ac
+033f000000df0101000000acfe010009
+00000000030300023f000000010e0300
+000003033f0201000000010901000000
+030300023f000000010e030000000303
+3f020100000001090100000003030002
+3f000000010e0300000003033f100205
+ff023f000000181901023f023f000000
+ff1201013f0901000000030300023f00
+0000010e0300000003033f023f000000
+101901023f023f000000ff1201013f09
+01000000030300023f000000010e0300
+000003033f023f000000081901023f02
+3f000000ff1201013f09010000000303
+00023f000000010e0300000003033f02
+3f000000ff1201023f09010000000303
+00023f000000010e0300000003033f02
+01000000fe0901000000030300023f00
+0000010e0300000003033f0201000000
+010901000000030300023f000000010e
+0300000003033f020100000000090100
+0000030300023f000000010e03000000
+03033f033f000000100100000000ad02
+3f00000034213f003f043f033f000000
+b50900000000030300023f000000010e
+0300000003033f023fffffffff213f26
+3f043f033f000000ae102605ff010000
+0000ae0330000000af033f000000df01
+01000000affe0100100200ff023f0000
+00181901023f023f000000ff1201013f
+0901000000030300023f000000010e03
+00000003033f023f000000101901023f
+023f000000ff1201013f090100000003
+0300023f000000010e0300000003033f
+023f000000081901023f023f000000ff
+1201013f0901000000030300023f0000
+00010e0300000003033f023f000000ff
+1201023f0901000000030300023f0000
+00010e0300000003033f100600ff0e31
+000000060c050801000000063100023f
+00000000213f013f043f033f000000b0
+09000000000631000100000000b00330
+000000b1033f000000df0101000000b1
+fe0100100200ff023f00000018190102
+3f023f000000ff1201013f0901000000
+030300023f000000010e030000000303
+3f023f000000101901023f023f000000
+ff1201013f0901000000030300023f00
+0000010e0300000003033f023f000000
+081901023f023f000000ff1201013f09
+01000000030300023f000000010e0300
+000003033f023f000000ff1201023f09
+01000000030300023f000000010e0300
+000003033f100700ff100006ff033000
+0000b2033f000001620101000000b2fe
+0100023f00000000233f013f043f033f
+000000b3023ffffffff80e0300000003
+033f033f000000de0100000000b31607
+0701023f000000031907073f01000000
+00b40800000000030200023f00000001
+0e0200000003023f0801000000030200
+023f000000010e0200000003023f023f
+00000004183b003f1000013b09000000
+00030300023f000000010e0300000003
+033f023fffffffff1407073f023f0000
+0000213f073f043f033f000000b4033f
+000000100100000000b5023f00000030
+203b003f023f00000032203a003f103a
+3a3b023fffffffff113a3a3f043a033f
+000000bd0900000000030300023f0000
+00010e0300000003033f0330000000b6
+033f000000df0101000000b6fe010009
+00000000030300023f000000010e0300
+000003033f100600ff023f0000000020
+3f043f043f033f000000b90330000000
+b7033f000000df0101000000b7fe0100
+0900000000030300023f000000010e03
+00000003033f0330000000b8033f0000
+00df0101000000b8fe01000900000000
+030300023f000000010e030000000303
+3f033f000000bc0100000000b9033000
+0000ba033f000000df0101000000bafe
+01000900000000030300023f00000001
+0e0300000003033f0330000000bb033f
+000000df0101000000bbfe0100090000
+0000030300023f000000010e03000000
+03033f0100000000bc0200000000000e
+3f000000060b060900000000063f0003
+3f000000100100000000bd023f000000
+31213f003f043f033f000000be090000
+0000030300023f000000010e03000000
+03033f02010000003f09010000000303
+00023f000000010e0300000003033f02
+010000003f0901000000030300023f00
+0000010e0300000003033f0201000000
+3f0901000000030300023f000000010e
+0300000003033f033f00000010010000
+0000be023f00000033213f003f043f03
+3f000000c00900000000030300023f00
+0000010e0300000003033f0330000000
+bf033f000000df0101000000bffe0100
+0900000000030300023f000000010e03
+00000003033f02010000003f09010000
+00030300023f000000010e0300000003
+033f02010000003f0901000000030300
+023f000000010e0300000003033f033f
+000000100100000000c0023f000000fe
+213f003f043f033f000000c609000000
+00030300023f000000010e0300000003
+033f0330000000c1033f000000df0101
+000000c1fe0100090000000003030002
+3f000000010e0300000003033f100600
+ff0330000000c2033f000000df010100
+0000c2fe01000900000000030300023f
+000000010e0300000003033f023f0000
+0001203f063f043f033f000000c5023f
+00000005213f063f043f033f000000c4
+0330000000c3033f000000e801010000
+00c3fe0100100200ff023f0000001819
+01023f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000101901023f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000081901023f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f000000ff120102
+3f0901000000030300023f000000010e
+0300000003033f033f000000c5010000
+0000c4023ffffffffe0e030000000303
+3f033f000000de0100000000c5033f00
+0000100100000000c609000000000303
+00023f000000010e0300000003033f03
+3f000000de033f000000050100000000
+c7023fffffffff0e0200000003023f02
+3f00000000243f253f043f033f000000
+c802040000000102000000003d033f00
+00009e0100000000c8023ffffffffc0e
+0a000000070a3f0802000000070a0002
+3f000000010e0a000000070a3f080300
+0000070a00023f000000010e0a000000
+070a3f0806000000070a00023f000000
+010e0a000000070a3f0800000000070a
+00023f000000010e0a000000070a3f02
+3f0000003f213f023f043f033f000000
+52020100000000090100000003030002
+3f000000010e0300000003033f023fff
+ffffff203f263f043f033f000000c902
+3f000000010e0300000003083f020100
+0000030901000000030300023f000000
+010e0300000003033f02010000000109
+01000000030300023f000000010e0300
+000003033f100226ff023f0000001819
+01023f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000101901023f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000081901023f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f000000ff120102
+3f0901000000030300023f000000010e
+0300000003033f0100000000c9010100
+0000ca34000000090000004005501000
+00000000333333333333000033333333
+0000000033330000000066001e310b02
+00fffffffffe05020000004002010000
+00000100000000cb0900000000063100
+023f000000010e3100000006313ffe01
+01023f000000011401013f023f000000
+40213f013f043f033f000000cb023f00
+0000010e0300000003083f0800000000
+030300023f00000000213f003f043f03
+3f000000cc023f000000060e03000000
+03033f0100000000cc030d000000ca01
+00000000cd0800000000030300023f00
+0000010e0300000003033f023f000000
+00203f003f043f033f000000dd023f00
+0000fe213f003f043f033f000000ce08
+01000000030300023f000000010e0300
+000003033f0e03000000030301033f00
+0000cd0100000000ce023f0000004023
+3f003f043f033f000000cf0e3f000000
+090d000801000000093f000e03000000
+030301023f00000000213f013f043f03
+3f000000cd0100000000cf023f000000
+03213f003f043f033f000000d0080300
+0000030300023f000000010e03000000
+03033f0802000000030300023f000000
+010e0300000003033f08010000000303
+00023f000000010e0300000003033f02
+3f000000081802023f10020201080100
+0000030300023f000000010e03000000
+03033f023f000000081802023f100202
+010801000000030300023f000000010e
+0300000003033f023f00000008180202
+3f10020201100402ff0e3f000000060c
+040805000000063f000e3f000000060b
+030905000000063f00033f000000cd01
+00000000d0023f00000008233b003f02
+3f0000000b243a003f123a3a3b023fff
+ffffff113a3a3f043a033f000000d202
+3f000000010e0300000003033f080200
+0000030300023f000000010e03000000
+03033f0801000000030300023f000000
+010e0300000003033f023f0000000818
+02023f10020201080100000003030002
+3f000000010e0300000003033f023f00
+0000081802023f100202010801000000
+030300023f000000010e030000000303
+3f023f000000081802023f1002020110
+0302ff0804000000030300023f000000
+010e0300000003033f0e02000000060b
+04023fffffffff213f033f043f033f00
+0000d10803000000060200023fffffff
+fb0e0300000003033f100203ff023f00
+0000181901023f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f00000010190102
+3f023f000000ff1201013f0901000000
+030300023f000000010e030000000303
+3f023f000000081901023f023f000000
+ff1201013f0901000000030300023f00
+0000010e0300000003033f023f000000
+ff1201023f0901000000030300023f00
+0000010e0300000003033f023f000000
+010e0300000003033f0100000000d109
+03000000060200023f000000010e0300
+000003033f033f000000cd0100000000
+d2023f0000000e213f003f043f033f00
+0000d40804000000030300023f000000
+010e0300000003033f08020000000303
+00023f000000010e0300000003033f08
+01000000030300023f000000010e0300
+000003033f023f000000081802023f10
+0202010801000000030300023f000000
+010e0300000003033f023f0000000818
+02023f10020201080100000003030002
+3f000000010e0300000003033f023f00
+0000081802023f10020201100302ff08
+05000000030300023f000000010e0300
+000003033f0e02000000060b040e0400
+0000060b05023f000000010e03000000
+03033f023fffffffff213f033f043f03
+3f000000d30803000000060400023fff
+fffffa0e0300000003033f100203ff02
+3f000000181901023f023f000000ff12
+01013f0901000000030300023f000000
+010e0300000003033f023f0000001019
+01023f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000081901023f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000ff1201023f090100000003030002
+3f000000010e0300000003033f023f00
+0000020e0300000003033f0100000000
+d3090300000006020009030000000604
+00033f000000cd0100000000d4023f00
+00000f213f003f043f033f000000d702
+3f000000010e0300000003033f080200
+0000030300023f000000010e03000000
+03033f0801000000030300023f000000
+010e0300000003033f023f0000000818
+02023f10020201080100000003030002
+3f000000010e0300000003033f023f00
+0000081802023f100202010801000000
+030300023f000000010e030000000303
+3f023f000000081802023f1002020110
+0302ff0804000000030300023f000000
+010e0300000003033f08050000000303
+00023f000000010e0300000003033f0e
+02000000060b040e04000000060b0502
+3fffffffff213f033f043f033f000000
+d60803000000060200023fffffffff21
+3f033f043f033f000000d50803000000
+0604000100000000d5023ffffffffa0e
+0300000003033f100203ff023f000000
+181901023f023f000000ff1201013f09
+01000000030300023f000000010e0300
+000003033f023f000000101901023f02
+3f000000ff1201013f09010000000303
+00023f000000010e0300000003033f02
+3f000000081901023f023f000000ff12
+01013f0901000000030300023f000000
+010e0300000003033f023f000000ff12
+01023f0901000000030300023f000000
+010e0300000003033f023f000000020e
+0300000003033f0100000000d6090300
+00000602000903000000060400033f00
+0000cd0100000000d7023f0000001e21
+3f003f043f033f000000d80804000000
+030300023f000000010e030000000303
+3f0805000000030300023f000000010e
+0300000003033f0e3f000000060b0508
+03000000063f000e3f000000060b0409
+03000000063f00033f000000cd010000
+0000d8023f0000001f213f003f043f03
+3f000000da023f000000010e03000000
+03033f0804000000030300023f000000
+010e0300000003033f08020000000303
+00023f000000010e0300000003033f08
+01000000030300023f000000010e0300
+000003033f023f000000081802023f10
+0202010801000000030300023f000000
+010e0300000003033f023f0000000818
+02023f10020201080100000003030002
+3f000000010e0300000003033f023f00
+0000081802023f10020201100502ff08
+06000000030300023f000000010e0300
+000003033f0e02000000060b06080200
+0000030300023f000000010e03000000
+03033f0801000000030300023f000000
+010e0300000003033f023f0000000818
+02023f10020201080100000003030002
+3f000000010e0300000003033f023f00
+0000081802023f100202010801000000
+030300023f000000010e030000000303
+3f023f000000081802023f1002020110
+0302ff023fffffffff213f033f043f03
+3f000000d90803000000060200023fff
+fffffb0e0300000003033f100203ff02
+3f000000181901023f023f000000ff12
+01013f0901000000030300023f000000
+010e0300000003033f023f0000001019
+01023f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000081901023f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000ff1201023f090100000003030002
+3f000000010e0300000003033f023f00
+0000010e0300000003033f0100000000
+d909030000000602000e3f000000060b
+040905000000063f00033f000000cd01
+00000000da023f00000034213f003f04
+3f033f000000dc080200000003030002
+3f000000010e0300000003033f080100
+0000030300023f000000010e03000000
+03033f023f000000081802023f100202
+010801000000030300023f000000010e
+0300000003033f023f00000008180202
+3f100202010801000000030300023f00
+0000010e0300000003033f023f000000
+081802023f10020201100002ff080200
+0000030300023f000000010e03000000
+03033f0801000000030300023f000000
+010e0300000003033f023f0000000818
+02023f10020201080100000003030002
+3f000000010e0300000003033f023f00
+0000081802023f100202010801000000
+030300023f000000010e030000000303
+3f023f000000081802023f1002020110
+0302ff0330000000db033f0000016201
+01000000dbfe010016010103023f0000
+00031901013f0e03000000030301033f
+000000cd0100000000dc020000000002
+033f000001740100000000dd02000000
+0000033f000001740100000000de0200
+00000001033f000001740100000000df
+0100000000e002380000000408000000
+00030200023f000000010e0200000003
+023f023f00000006243f003f043f033f
+000000e7023f00000007213f003f043f
+033f000000e30800000000030200023f
+000000010e0200000003023f023f0000
+0008223f003f043f033f000000e1083a
+000000030200023f000000010e020000
+0003023f023f000000041800003f1000
+003a023f0000003f1200003f01000000
+00e1023f00000001153b003f02380000
+0008083a000000030200023f00000001
+0e0200000003023f023f000000041800
+003f1000003a0100000000e2083a0000
+00030200023f000000010e0200000003
+023f023f000000041800003f1000003a
+023f000000041838383f023fffffffff
+143b3b3f023f00000000213f3b3f043f
+033f000000e2033f000000e701000000
+00e3023f000000031838383f023f0000
+000b253f003f043f033f000000e4083a
+000000030200023f000000010e020000
+0003023f023f000000041800003f1000
+003a033f000000e70100000000e4023f
+000000031838383f023f0000000d253f
+003f043f033f000000e5083a00000003
+0200023f000000010e0200000003023f
+023f000000041800003f1000003a083a
+000000030200023f000000010e020000
+0003023f023f000000041800003f1000
+003a033f000000e70100000000e5023f
+000000031838383f023f0000000e253f
+003f043f033f000000e6083a00000003
+0200023f000000010e0200000003023f
+023f000000041800003f1000003a083a
+000000030200023f000000010e020000
+0003023f023f000000041800003f1000
+003a083a000000030200023f00000001
+0e0200000003023f023f000000041800
+003f1000003a033f000000e701000000
+00e6033f000000e00100000000e7023f
+00000001183a383f023fffffffff143a
+3a3f1200003a1e3f300100000000e81e
+3b300330000000e9033f000000df0101
+000000e9fe0100023f00000004213f38
+3f043f033f000000eb023f0000000422
+3f003f043f033f000000ea023f000000
+071500003f0100000000ea033f000000
+ed0100000000eb223f0038043f033f00
+0000ec15000038150000380100000000
+ec0100000000ed1e3f3b0100000000ee
+023fffffffa8223f003f043f033f0000
+00ef023fffffffb0253f003f043f033f
+000000ef023fffffffb815003f00023f
+0000000118003f000100000000ef023f
+ffffffa0253f003f043f033f000000f0
+023f000000501400003f0100000000f0
+1e3f300100000000f11e3a3003300000
+00f2033f000000e80101000000f2fe01
+00023fffffffb1233b003f023fffffff
+f0243a003f123a3a3b023fffffffff11
+3a3a3f043a033f000000f3023fffffff
+f015003f00033f000000f50100000000
+f3023b00000002093b00000003030002
+3f000000010e0300000003033f023b00
+00003f093b000000030300023f000000
+010e0300000003033f0330000000f403
+3f000000ee0101000000f4fe01001002
+00ff023f000000181901023f023f0000
+00ff1201013f0901000000030300023f
+000000010e0300000003033f023f0000
+00101901023f023f000000ff1201013f
+0901000000030300023f000000010e03
+00000003033f023f000000081901023f
+023f000000ff1201013f090100000003
+0300023f000000010e0300000003033f
+023f000000ff1201023f090100000003
+0300023f000000010e0300000003033f
+02000000003f0100000000f509000000
+00030f00023f000000010e0f00000003
+0f3f1e3f3a0100000000f61e1930020b
+000000000100000000f7233f0607043f
+033f000000fd223f060c043f033f0000
+00f80201000000100901000000030300
+023f000000010e0300000003033f0906
+000000030300023f000000010e030000
+0003033f090b000000030300023f0000
+00010e0300000003033f0201000000ff
+0901000000030300023f000000010e03
+00000003033f023f00000001140b0b3f
+023f000000011406063f033f000000f7
+0100000000f80330000000f9033f0000
+00e80101000000f9fe0100023fffffff
+b1233b003f023ffffffff0243a003f12
+3a3a3b023fffffffff113a3a3f043a03
+3f000000fb023ffffffff015003f0020
+3f0006043f033f000000fa0201000000
+100901000000030300023f000000010e
+0300000003033f090600000003030002
+3f000000010e0300000003033f090000
+0000030300023f000000010e03000000
+03033f0201000000ff09010000000303
+00023f000000010e0300000003033f01
+00000000fa023f000000011406063f03
+3f000000f70100000000fb0330000000
+fc033f000000ee0101000000fcfe0100
+0201000000020901000000030300023f
+000000010e0300000003033f09060000
+00030300023f000000010e0300000003
+033f023f000000181901003f023f0000
+00ff1201013f0901000000030300023f
+000000010e0300000003033f023f0000
+00101901003f023f000000ff1201013f
+0901000000030300023f000000010e03
+00000003033f023f000000081901003f
+023f000000ff1201013f090100000003
+0300023f000000010e0300000003033f
+023f000000ff1201003f090100000003
+0300023f000000010e0300000003033f
+023f000000011406063f033f000000f7
+0100000000fd1e3f190100000000fe1e
+1930020600000031020b000000010100
+000000ff233f0608043f033f00000105
+223f060d043f033f0000010002010000
+001e0901000000030300023f00000001
+0e0300000003033f0906000000030300
+023f000000010e0300000003033f090b
+000000030300023f000000010e030000
+0003033f023f00000001140b0b3f023f
+000000011406063f033f000000ff0100
+00000100033000000101033f000000e8
+010100000101fe0100023fffffffb123
+3b003f023ffffffff0243a003f123a3a
+3b023fffffffff113a3a3f043a033f00
+000103023ffffffff015003f00203f00
+06043f033f0000010202010000001e09
+01000000030300023f000000010e0300
+000003033f0906000000030300023f00
+0000010e0300000003033f0900000000
+030300023f000000010e030000000303
+3f010000000102023f00000001140606
+3f033f000000ff010000000103033000
+000104033f000000ee010100000104fe
+01000201000000030901000000030300
+023f000000010e0300000003033f0906
+000000030300023f000000010e030000
+0003033f023f000000181901003f023f
+000000ff1201013f0901000000030300
+023f000000010e0300000003033f023f
+000000101901003f023f000000ff1201
+013f0901000000030300023f00000001
+0e0300000003033f023f000000081901
+003f023f000000ff1201013f09010000
+00030300023f000000010e0300000003
+033f023f000000ff1201003f09010000
+00030300023f000000010e0300000003
+033f023f000000011406063f033f0000
+00ff0100000001051e3f190100000001
+061e1930100b10ff010000000107023f
+0000000112000b3f023f00000000203f
+003f043f033f00000142023f00000001
+110b0b3f033000000108033f000000df
+010100000108fe0100023f0000000021
+3f003f043f033f0000010e0330000001
+09033f000000df010100000109fe0100
+100600ff03300000010a033f0000016d
+01010000010afe010001000000010b02
+3f00000000243f063f043f033f000001
+0d0800000000030200023f000000010e
+0200000003023f080100000003020002
+3f000000010e0200000003023f023f00
+000004183b003f1000013b0201000000
+020901000000030300023f000000010e
+0300000003033f02010000003b090100
+0000030300023f000000010e03000000
+03033f023f000000181901003f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000101901003f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f00000008190100
+3f023f000000ff1201013f0901000000
+030300023f000000010e030000000303
+3f023f000000ff1201003f0901000000
+030300023f000000010e030000000303
+3f02000000003b03300000010c033f00
+00016e01010000010cfe0100033f0000
+010b01000000010d033f000001070100
+0000010e023f00000001213f003f043f
+033f0000011803300000010f033f0000
+00df01010000010ffe0100100600ff03
+3000000110033f0000016d0101000001
+10fe0100010000000111023f00000000
+243f063f043f033f0000011703300000
+0112033f000000e8010100000112fe01
+00023fffffffb1233b003f023fffffff
+f0243a003f123a3a3b023fffffffff11
+3a3a3f043a033f00000113023fffffff
+f015003f00033f000001150100000001
+13020100000002090100000003030002
+3f000000010e0300000003033f020100
+00003b0901000000030300023f000000
+010e0300000003033f03300000011403
+3f000000ee010100000114fe0100023f
+000000181901003f023f000000ff1201
+013f0901000000030300023f00000001
+0e0300000003033f023f000000101901
+003f023f000000ff1201013f09010000
+00030300023f000000010e0300000003
+033f023f000000081901003f023f0000
+00ff1201013f0901000000030300023f
+000000010e0300000003033f023f0000
+00ff1201003f0901000000030300023f
+000000010e0300000003033f02000000
+003b010000000115033000000116033f
+0000016e010100000116fe0100033f00
+000111010000000117033f0000010701
+0000000118023f00000002213f003f04
+3f033f00000123033000000119033f00
+0000e8010100000119fe0100023fffff
+ffb1233b003f023ffffffff0243a003f
+123a3a3b023fffffffff113a3a3f043a
+033f0000011b023ffffffff015003f00
+203f0007043f033f0000011a02010000
+00100901000000030300023f00000001
+0e0300000003033f0907000000030300
+023f000000010e0300000003033f0900
+000000030300023f000000010e030000
+0003033f0200000000ff090000000003
+0300023f000000010e0300000003033f
+01000000011a033f0000011d01000000
+011b03300000011c033f000000ee0101
+0000011cfe0100020100000002090100
+0000030300023f000000010e03000000
+03033f0907000000030300023f000000
+010e0300000003033f023f0000001819
+01003f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000101901003f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000081901003f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f000000ff120100
+3f0901000000030300023f000000010e
+0300000003033f01000000011d023f00
+0000011407073f03300000011e033f00
+0000e801010000011efe0100023fffff
+ffb1233b003f023ffffffff0243a003f
+123a3a3b023fffffffff113a3a3f043a
+033f00000120023ffffffff015003f00
+203f0008043f033f0000011f02010000
+001e0901000000030300023f00000001
+0e0300000003033f0908000000030300
+023f000000010e0300000003033f0900
+000000030300023f000000010e030000
+0003033f01000000011f033f00000122
+010000000120033000000121033f0000
+00ee010100000121fe01000201000000
+030901000000030300023f000000010e
+0300000003033f090800000003030002
+3f000000010e0300000003033f023f00
+0000181901003f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f00000010190100
+3f023f000000ff1201013f0901000000
+030300023f000000010e030000000303
+3f023f000000081901003f023f000000
+ff1201013f0901000000030300023f00
+0000010e0300000003033f023f000000
+ff1201003f0901000000030300023f00
+0000010e0300000003033f0100000001
+22023f000000011408083f0210000000
+00033f00000107010000000123023f00
+000003213f003f043f033f000001291e
+18020206ffffffff010000000124023f
+000000011406063f0800000000030200
+023f000000010e0200000003023f0801
+000000030200023f000000010e020000
+0003023f10000001023f00000000213f
+003f043f033f000001241e0218033000
+000125033f0000016d010100000125fe
+0100010000000126023f00000000243f
+063f043f033f00000128080000000003
+0200023f000000010e0200000003023f
+0801000000030200023f000000010e02
+00000003023f023f00000004183b003f
+1000013b020100000002090100000003
+0300023f000000010e0300000003033f
+02010000003b0901000000030300023f
+000000010e0300000003033f023f0000
+00181901003f023f000000ff1201013f
+0901000000030300023f000000010e03
+00000003033f023f000000101901003f
+023f000000ff1201013f090100000003
+0300023f000000010e0300000003033f
+023f000000081901003f023f000000ff
+1201013f0901000000030300023f0000
+00010e0300000003033f023f000000ff
+1201003f0901000000030300023f0000
+00010e0300000003033f02000000003b
+033000000127033f0000016e01010000
+0127fe0100033f000001260100000001
+280800000000030200023f000000010e
+0200000003023f080000000003020002
+3f000000010e0200000003023f033f00
+000107010000000129023f0000000421
+3f003f043f033f000001351e18020206
+ffffffff01000000012a023f00000001
+1406063f03300000012b033f000000e8
+01010000012bfe0100023f0000000021
+3f003f043f033f0000012a1e02180330
+0000012c033f0000016d01010000012c
+fe010001000000012d023f0000000024
+3f063f043f033f000001330330000001
+2e033f000000e801010000012efe0100
+023fffffffb1233b003f023ffffffff0
+243a003f123a3a3b023fffffffff113a
+3a3f043a033f0000012f023ffffffff0
+15003f00033f0000013101000000012f
+0201000000020901000000030300023f
+000000010e0300000003033f02010000
+003b0901000000030300023f00000001
+0e0300000003033f033000000130033f
+000000ee010100000130fe0100023f00
+0000181901003f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f00000010190100
+3f023f000000ff1201013f0901000000
+030300023f000000010e030000000303
+3f023f000000081901003f023f000000
+ff1201013f0901000000030300023f00
+0000010e0300000003033f023f000000
+ff1201003f0901000000030300023f00
+0000010e0300000003033f0200000000
+3b010000000131033000000132033f00
+00016e010100000132fe0100033f0000
+012d010000000133033000000134033f
+000000e8010100000134fe0100033f00
+000107010000000135101500ff023f00
+000005213f003f043f033f0000013e08
+06000000030200023f000000010e0200
+000003023f023f000000041406063f01
+00000001360211000000000330000001
+37033f0000016d010100000137fe0100
+010000000138023f00000000243f063f
+043f033f0000013b033000000139033f
+0000016f010100000139fe0100020100
+0000020901000000030300023f000000
+010e0300000003033f02010000003b09
+01000000030300023f000000010e0300
+000003033f023f000000181901003f02
+3f000000ff1201013f09010000000303
+00023f000000010e0300000003033f02
+3f000000101901003f023f000000ff12
+01013f0901000000030300023f000000
+010e0300000003033f023f0000000819
+01003f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000ff1201003f090100
+0000030300023f000000010e03000000
+03033f02000000003b03300000013a03
+3f0000016e01010000013afe0100033f
+0000013801000000013b023f00000006
+213f153f043f033f0000013d03300000
+013c033f0000016f01010000013cfe01
+0001000000013d033f00000107010000
+00013e023f00000006213f003f043f03
+3f000001411e18020206ffffffff0211
+0000000001000000013f023f00000001
+1406063f033000000140033f0000016f
+010100000140fe0100023f0000000021
+3f003f043f033f0000013f1e0218033f
+00000136010000000141020000000001
+0201000000ff0901000000030300023f
+000000010e0300000003033f02010000
+00000901000000030300023f00000001
+0e0300000003033f0900000000030300
+023f000000010e0300000003033f023f
+fffffffd0e0300000003033f033f0000
+00de010000000142010000000143023f
+0000000212000b3f023f00000000203f
+003f043f033f0000014f023f00000002
+110b0b3f033000000144033f000000df
+010100000144fe0100023f0000000121
+3f003f043f033f0000014e0330000001
+45033f000000df010100000145fe0100
+100600ff033000000146033f00000172
+010100000146fe010001000000014702
+3f00000000243f063f043f033f000001
+4d033000000148033f000000e8010100
+000148fe0100023fffffffb1233b003f
+023ffffffff0243a003f123a3a3b023f
+ffffffff113a3a3f043a033f00000149
+023ffffffff015003f00033f0000014b
+01000000014902010000000209010000
+00030300023f000000010e0300000003
+033f02010000003b0901000000030300
+023f000000010e0300000003033f0330
+0000014a033f000000ee01010000014a
+fe0100023f000000181901003f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000101901003f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f00000008190100
+3f023f000000ff1201013f0901000000
+030300023f000000010e030000000303
+3f023f000000ff1201003f0901000000
+030300023f000000010e030000000303
+3f02000000003b01000000014b033000
+00014c033f0000017301010000014cfe
+0100033f0000014701000000014d033f
+0000014301000000014e020000000001
+0201000000ff0901000000030300023f
+000000010e0300000003033f02010000
+00000901000000030300023f00000001
+0e0300000003033f0900000000030300
+023f000000010e0300000003033f023f
+fffffffd0e0300000003033f033f0000
+00de01000000014f1e3f190100000001
+501e1930020600000030010000000151
+253f0609043f033f0000015403300000
+0152033f000000df010100000152fe01
+00203f0006043f033f00000153020100
+0000100901000000030300023f000000
+010e0300000003033f09000000000303
+00023f000000010e0300000003033f09
+06000000030300023f000000010e0300
+000003033f0201000000ff0901000000
+030300023f000000010e030000000303
+3f010000000153023f00000001140606
+3f033f000001510100000001541e3f19
+0100000001551e193002060000003101
+0000000156253f060a043f033f000001
+59033000000157033f000000df010100
+000157fe0100203f0006043f033f0000
+015802010000001e0901000000030300
+023f000000010e0300000003033f0900
+000000030300023f000000010e030000
+0003033f0906000000030300023f0000
+00010e0300000003033f010000000158
+023f000000011406063f033f00000156
+0100000001591e3f1901000000015a1e
+1a300201000000020901000000030300
+023f000000010e0300000003033f0201
+000000300901000000030300023f0000
+00010e0300000003033f023f00000018
+1901003f023f000000ff1201013f0901
+000000030300023f000000010e030000
+0003033f023f000000101901003f023f
+000000ff1201013f0901000000030300
+023f000000010e0300000003033f023f
+000000081901003f023f000000ff1201
+013f0901000000030300023f00000001
+0e0300000003033f023f000000ff1201
+003f0901000000030300023f00000001
+0e0300000003033f0206000000310330
+0000015b033f000000f601010000015b
+fe010003300000015c033f000000fe01
+010000015cfe010003300000015d033f
+0000010601010000015dfe0100023f00
+0000011405053f020000000003090000
+0000030300023f000000010e03000000
+03033f02000000003009000000000303
+00023f000000010e0300000003033f02
+3f000000181901053f023f000000ff12
+01013f0901000000030300023f000000
+010e0300000003033f023f0000001019
+01053f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000081901053f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000ff1201053f090100000003030002
+3f000000010e0300000003033f020000
+00001e0900000000030300023f000000
+010e0300000003033f02000000003f09
+00000000030300023f000000010e0300
+000003033f0200000000280900000000
+030300023f000000010e030000000303
+3f020000000001090000000003030002
+3f000000010e0300000003033f020000
+0000010900000000030300023f000000
+010e0300000003033f023f0000001819
+01053f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000101901053f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000081901053f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f000000ff120105
+3f0901000000030300023f000000010e
+0300000003033f0200000000fe090000
+0000030300023f000000010e03000000
+03033f02000000000109000000000303
+00023f000000010e0300000003033f02
+00000000000900000000030300023f00
+0000010e0300000003033f0330000001
+5e033f0000015001010000015efe0100
+03300000015f033f0000015501010000
+015ffe0100023f000000021200103f02
+3f00000000203f003f043f033f000001
+60020100000002090100000003030002
+3f000000010e0300000003033f020100
+00003a0901000000030300023f000000
+010e0300000003033f023f0000001819
+01143f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000101901143f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000081901143f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f000000ff120114
+3f0901000000030300023f000000010e
+0300000003033f020100000002090100
+0000030300023f000000010e03000000
+03033f02010000003b09010000000303
+00023f000000010e0300000003033f02
+01000000000901000000030300023f00
+0000010e0300000003033f0201000000
+000901000000030300023f000000010e
+0300000003033f020100000000090100
+0000030300023f000000010e03000000
+03033f02010000000609010000000303
+00023f000000010e0300000003033f02
+01000000310901000000030300023f00
+0000010e0300000003033f0201000000
+3b0901000000030300023f000000010e
+0300000003033f02010000003b090100
+0000030300023f000000010e03000000
+03033f02010000003a09010000000303
+00023f000000010e0300000003033f01
+0000000160023f000000011200103f02
+3f00000000203f003f043f033f000001
+61020100000002090100000003030002
+3f000000010e0300000003033f020100
+00003a0901000000030300023f000000
+010e0300000003033f023f0000001819
+01133f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000101901133f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000081901133f023f000000ff120101
+3f0901000000030300023f000000010e
+0300000003033f023f000000ff120113
+3f0901000000030300023f000000010e
+0300000003033f020100000002090100
+0000030300023f000000010e03000000
+03033f02010000003b09010000000303
+00023f000000010e0300000003033f02
+01000000000901000000030300023f00
+0000010e0300000003033f0201000000
+000901000000030300023f000000010e
+0300000003033f020100000000090100
+0000030300023f000000010e03000000
+03033f02010000000309010000000303
+00023f000000010e0300000003033f02
+01000000310901000000030300023f00
+0000010e0300000003033f0201000000
+3b0901000000030300023f000000010e
+0300000003033f02010000003b090100
+0000030300023f000000010e03000000
+03033f02010000003a09010000000303
+00023f000000010e0300000003033f01
+00000001610204000000001e3f1a0100
+000001620201ffffffff023f00000001
+1930003f023f00000001213f303f043f
+033f0000016302010000000801000000
+0163023f00000002213f303f043f033f
+00000164020100000010010000000164
+023f00000003213f303f043f033f0000
+0165020100000020010000000165023f
+00000004213f303f043f033f00000166
+020100000004010000000166023f0000
+0005213f303f043f033f000001670201
+00000002010000000167023f00000006
+213f303f043f033f0000016802010000
+0001010000000168023f00000007213f
+303f043f033f0000016902010000000c
+010000000169023f00000008213f303f
+043f033f0000016a0201000000140100
+0000016a023f00000009213f303f043f
+033f0000016b02010000001801000000
+016b023f0000000a213f303f043f033f
+0000016c02010000001c01000000016c
+1e3f3001000000016d02010000000209
+01000000030300023f000000010e0300
+000003033f100107ff09010000000303
+00023f000000010e0300000003033f02
+3f000000181901063f023f000000ff12
+01013f0901000000030300023f000000
+010e0300000003033f023f0000001019
+01063f023f000000ff1201013f090100
+0000030300023f000000010e03000000
+03033f023f000000081901063f023f00
+0000ff1201013f090100000003030002
+3f000000010e0300000003033f023f00
+0000ff1201063f090100000003030002
+3f000000010e0300000003033f101306
+ff020100000002090100000003030002
+3f000000010e0300000003033f020100
+00003b0901000000030300023f000000
+010e0300000003033f02010000000009
+01000000030300023f000000010e0300
+000003033f0201000000000901000000
+030300023f000000010e030000000303
+3f020100000000090100000003030002
+3f000000010e0300000003033f020100
+0000030901000000030300023f000000
+010e0300000003033f02010000003009
+01000000030300023f000000010e0300
+000003033f0908000000030300023f00
+0000010e0300000003033f0201000000
+3b0901000000030300023f000000010e
+0300000003033f090700000003030002
+3f000000010e0300000003033f020100
+00001e0901000000030300023f000000
+010e0300000003033f02010000003b09
+01000000030300023f000000010e0300
+000003033f0908000000030300023f00
+0000010e0300000003033f023f000000
+011407073f023f000000011408083f1e
+3f3001000000016e0201000000090901
+000000030300023f000000010e030000
+0003033f0900000000030300023f0000
+00010e0300000003033f020100000000
+0901000000030300023f000000010e03
+00000003033f02010000000009010000
+00030300023f000000010e0300000003
+033f0201000000000901000000030300
+023f000000010e0300000003033f0201
+000000030901000000030300023f0000
+00010e0300000003033f02010000003b
+0901000000030300023f000000010e03
+00000003033f02010000000009010000
+00030300023f000000010e0300000003
+033f0201000000020901000000030300
+023f000000010e0300000003033f0201
+0000003f0901000000030300023f0000
+00010e0300000003033f020100000000
+0901000000030300023f000000010e03
+00000003033f02010000000009010000
+00030300023f000000010e0300000003
+033f0201000000000901000000030300
+023f000000010e0300000003033f0201
+000000010901000000030300023f0000
+00010e0300000003033f02010000000e
+0901000000030300023f000000010e03
+00000003033f02010000003b09010000
+00030300023f000000010e0300000003
+033f0201000000000901000000030300
+023f000000010e0300000003033f0201
+000000000901000000030300023f0000
+00010e0300000003033f020100000000
+0901000000030300023f000000010e03
+00000003033f02010000000309010000
+00030300023f000000010e0300000003
+033f02010000003b0901000000030300
+023f000000010e0300000003033f0201
+0000003f0901000000030300023f0000
+00010e0300000003033f023fffffffff
+1406063f1e3f3001000000016f020000
+000000fe050200000007020100000000
+010000000170023f00000000253f113f
+043f033f000001710812000000030200
+023f000000010e0200000003023f0211
+00000004010000000171023f00000003
+1902123f023f000000011202023f023f
+ffffffff1411113f023f000000011812
+123f023f000000011800003f10000002
+fe0101023f000000011401013f023f00
+000007213f013f043f033f000001701e
+3f300100000001720201000000020901
+000000030300023f000000010e030000
+0003033f100107ff0901000000030300
+023f000000010e0300000003033f023f
+000000181901063f023f000000ff1201
+013f0901000000030300023f00000001
+0e0300000003033f023f000000101901
+063f023f000000ff1201013f09010000
+00030300023f000000010e0300000003
+033f023f000000081901063f023f0000
+00ff1201013f0901000000030300023f
+000000010e0300000003033f023f0000
+00ff1201063f0901000000030300023f
+000000010e0300000003033f101406ff
+0201000000020901000000030300023f
+000000010e0300000003033f02010000
+003b0901000000030300023f00000001
+0e0300000003033f0201000000000901
+000000030300023f000000010e030000
+0003033f020100000000090100000003
+0300023f000000010e0300000003033f
+0201000000000901000000030300023f
+000000010e0300000003033f02010000
+00060901000000030300023f00000001
+0e0300000003033f0201000000300901
+000000030300023f000000010e030000
+0003033f0908000000030300023f0000
+00010e0300000003033f02010000003b
+0901000000030300023f000000010e03
+00000003033f0907000000030300023f
+000000010e0300000003033f02010000
+001e0901000000030300023f00000001
+0e0300000003033f02010000003b0901
+000000030300023f000000010e030000
+0003033f0908000000030300023f0000
+00010e0300000003033f023f00000001
+1407073f023f000000011408083f1e3f
+30010000000173020100000009090100
+0000030300023f000000010e03000000
+03033f0900000000030300023f000000
+010e0300000003033f02010000000009
+01000000030300023f000000010e0300
+000003033f0201000000000901000000
+030300023f000000010e030000000303
+3f020100000000090100000003030002
+3f000000010e0300000003033f020100
+0000060901000000030300023f000000
+010e0300000003033f02010000003b09
+01000000030300023f000000010e0300
+000003033f0201000000000901000000
+030300023f000000010e030000000303
+3f020100000002090100000003030002
+3f000000010e0300000003033f020100
+00003f0901000000030300023f000000
+010e0300000003033f02010000000009
+01000000030300023f000000010e0300
+000003033f0201000000000901000000
+030300023f000000010e030000000303
+3f020100000000090100000003030002
+3f000000010e0300000003033f020100
+0000010901000000030300023f000000
+010e0300000003033f02010000000e09
+01000000030300023f000000010e0300
+000003033f02010000003b0901000000
+030300023f000000010e030000000303
+3f020100000000090100000003030002
+3f000000010e0300000003033f020100
+0000000901000000030300023f000000
+010e0300000003033f02010000000009
+01000000030300023f000000010e0300
+000003033f0201000000060901000000
+030300023f000000010e030000000303
+3f02010000003b090100000003030002
+3f000000010e0300000003033f020100
+00003f0901000000030300023f000000
+010e0300000003033f023fffffffff14
+06063f1e3f300100000001741e0203
+*/}).toString().toString().match(/\/\*[\s\S]*\*\//)[0].replace(/\/\*|\*\//g,'');
+
+//safariで動かない版
+//.toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1];
diff --git a/webcpu/ext.js b/webcpu/ext.js
new file mode 100644 (file)
index 0000000..62c6f40
--- /dev/null
@@ -0,0 +1,43 @@
+//既存クラス拡張
+if(!Function.prototype.extend){
+       Function.prototype.extend = function(baseConstructor, newPrototype){
+               // http://sourceforge.jp/projects/h58pcdgame/scm/git/GameScriptCoreLibrary/blobs/master/www/corelib/jsbase.js
+               //最初にベースクラスのプロトタイプを引き継ぐ。
+               var F = function(){};
+               F.prototype = baseConstructor.prototype;
+               this.prototype = new F();
+               //新たなプロトタイプを追加・上書きする。
+               if(newPrototype){
+                       for(var prop in newPrototype){
+                               this.prototype[prop] = newPrototype[prop];
+                       }
+               }
+               //コンストラクタを設定
+               this.prototype.constructor = this;
+               //ベースクラスのコンストラクタを設定
+               this.base = baseConstructor;
+               
+               return this;
+       };
+}
+
+if(!CanvasRenderingContext2D.prototype.fillEllipse){
+       CanvasRenderingContext2D.prototype.fillEllipse = function(x, y, w, h) {
+               //http://spphire9.wordpress.com/2010/03/08/%E3%83%99%E3%82%B8%E3%82%A7%E6%9B%B2%E7%B7%9A%E3%81%A7%E6%A5%95%E5%86%86%E3%82%92%E6%8F%8F%E3%81%8F3/
+               //矩形(x, y, w, h)に内接する楕円を塗りつぶす
+               var halfWidth = w >> 1;
+               var halfHeight = h >> 1;
+               var x0 = x + halfWidth;
+               var y1 = y + halfHeight;
+               this.beginPath();
+               var cw = 4.0 * (Math.sqrt(2.0) - 1.0) * halfWidth / 3.0;
+               var ch = 4.0 * (Math.sqrt(2.0) - 1.0) * halfHeight / 3.0;
+               this.moveTo(x0, y);
+               this.bezierCurveTo(x0 + cw, y, x + w, y1 - ch, x + w, y1);
+               this.bezierCurveTo(x + w, y1 + ch, x0 + cw, y + h, x0, y + h);
+               this.bezierCurveTo(x0 - cw, y + h, x, y1 + ch, x, y1);
+               this.bezierCurveTo(x, y1 - ch, x0 - cw, y, x0, y);
+               this.closePath();
+               this.fill();
+       };
+}
\ No newline at end of file
diff --git a/webcpu/header.js b/webcpu/header.js
new file mode 100644 (file)
index 0000000..3c25d6d
--- /dev/null
@@ -0,0 +1,11 @@
+include = function(relpath){
+       document.write("<script type='text/javascript' src=" + relpath + " charset='UTF-8'></script>");
+}
+include("./ext.js");
+include("./api.js");
+include("./decoder.js");
+include("./memory.js");
+include("./instrbas.js");
+include("./instr.js");
+include("./webcpu.js");
+include("./const.js");
\ No newline at end of file
diff --git a/webcpu/index.html b/webcpu/index.html
new file mode 100755 (executable)
index 0000000..0970880
--- /dev/null
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=9">
+<meta charset="UTF-8">
+<title>webcpu</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;
+// bball backend bin
+var demoBin = "\
+05  e1  ae  3a  0c  46  4b  b3  da  41  d8  10  95  a0  53  51\n\
+11  72  c0  75  10  77  71  79  c3  5b  75  ac  38  1b  fa  4a\n\
+bb  b8  bc  46  46  50  8f  88  01  08  81  10  43  26  66  b8\n\
+88  88  22  08  83  20  49  54  5a  aa  54  01  49  54  bf  ac\n\
+11  a5  48  72  45  38  51\n\
+";
+onload = function(){
+       mainCPU = new WebCPU();
+
+       mainCPU.setMainWindowCanvasDOMObject("mainWindowCanvas");
+       enableDebugMode();
+       document.getElementsByName("binaryCodeText")[0].value = demoBin;
+       
+       // Setup the dnd listeners.
+       var dropZone = document.getElementById('fileDropZone');
+       dropZone.addEventListener('dragover', handleDragOver, false);
+       dropZone.addEventListener('drop', handleFileSelect, false);
+}
+
+function loadBinaryTextToCPU(){
+       mainCPU.loadBinaryText(document.getElementsByName("binaryCodeText")[0].value);
+       return false;
+}
+
+function enableDebugMode(){
+       mainCPU.setDebugMessageDOMObject("debugMessageText");
+       mainCPU.setDebugIntegerRegisterDOMObject("debugIntegerRegisterText");
+       mainCPU.setDebugPointerRegisterDOMObject("debugPointerRegisterText");
+       mainCPU.message("****Debug mode enabled.\n");
+}
+
+function disableDebugMode(){
+       mainCPU.message("****Debug mode disabled.\n");
+       mainCPU.setDebugMessageDOMObject(null);
+       mainCPU.setDebugIntegerRegisterDOMObject(null);
+       mainCPU.setDebugPointerRegisterDOMObject(null);
+       
+}
+
+var stepInTimer = null;
+
+function stepInMs(){
+       stepInTimer = window.setInterval(stepInMs_Tick, 1);
+}
+
+function stepInMs_Tick(){
+       if(mainCPU.executeStepIn() != 0){
+               window.clearTimeout(stepInTimer);
+       }
+}
+
+
+
+// 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;
+                               var v = new DataView(a);
+                               var ds = "";
+                               for(var i = 0; i < a.byteLength; i++){
+                                       ds += ("00" + v.getUint8(i).toString(16).toUpperCase()).slice(-2);
+                               }
+                               document.getElementsByName("binaryCodeText")[0].value = ds;
+                               console.log(ds);
+                       }
+               })(f);
+               r.readAsArrayBuffer(f);
+       }
+       document.getElementById('fileList').innerHTML = '<ul>' + output.join('') + '</ul>';
+}
+
+function handleDragOver(evt){
+       evt.stopPropagation();
+       evt.preventDefault();
+       evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
+}
+</script>
+</head>
+<body>
+<h1>WebCPU</h1>
+<div style="float:left;">
+       <h2>mainWindow</h2>
+       <canvas id="mainWindowCanvas" width="640" height="480" style="border:1px solid #000000;"></canvas>
+</div>
+<div style="float:left;">
+       <h2>binaryCode</h2>
+       <textarea name="binaryCodeText" cols="64" rows="24"></textarea>
+       <div id="fileDropZone">Drop Binary.ose here</div>
+       <div id="fileList"></div>
+</div>
+<div style="clear:both;">
+       <form onsubmit="return false;">
+               <button onclick="loadBinaryTextToCPU();">Load</button><br />
+               <button onclick="mainCPU.executeStepIn();">StepIn</button>
+               <button onclick="stepInMs();">StepInMs</button>
+               <button onclick="for(var i = 0; i < 100; i++){ mainCPU.executeStepIn(); }">StepIn100</button>
+               <button onclick="mainCPU.execute();">Execute</button>
+               <button onclick="mainCPU.stopFlag = true;">Break</button><br />
+               <button onclick="enableDebugMode();">EnableDebugMode</button>
+               <button onclick="disableDebugMode();">DisableDebugMode</button>
+       </form>
+       <h2>Internal Information</h2>
+       <div style="float:left;">
+               <input type="checkbox" onchange="">message</input><br />
+               <textarea name="debugMessageText" cols="66" rows="16"></textarea>
+       </div>
+       <div style="float:left;">
+               <input type="checkbox" onchange="">IntegerRegister</input><br />
+               <textarea name="debugIntegerRegisterText" cols="32" rows="16"></textarea>
+       </div>
+       <div style="float:left;">
+               <input type="checkbox" onchange="">PointerRegister</input><br />
+               <textarea name="debugPointerRegisterText" cols="32" rows="16"></textarea>
+       </div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/webcpu/instr.js b/webcpu/instr.js
new file mode 100644 (file)
index 0000000..f90b3e9
--- /dev/null
@@ -0,0 +1,424 @@
+//
+// Instructions
+//
+
+//未定義の命令(WebCPU_Instructionと同値)
+var WebCPU_Instruction_Undefined = WebCPU_Instruction;
+
+var WebCPU_Instruction_NOP = function(instrID){
+       //何もしない命令
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               return 1;
+       },
+       instruction: function(env){
+               //no operation
+       },
+       createBinaryString: function(env){
+               return "00";
+       },
+       toString: function(){
+               return "NOP();";
+       },
+});
+
+var WebCPU_Instruction_LB = function(instrID){
+       //ラベル定義命令
+       this.opt = 0;
+       this.imm32 = null;
+       this.passCount = 0;
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               this.setParameter(
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1), 
+                       this.fetchSignedInteger(argBinStr, baseIndex, 1, 4)
+               );
+               return 6;
+       },
+       setParameter: function(opt, labelID){
+               this.opt = opt;
+               this.imm32 = labelID;
+       },
+       instruction: function(env){
+               this.passCount++;
+       },
+       createBinaryString: function(env){
+               return "01" + toHexString8(this.opt) + toHexString32(this.imm32);
+       },
+       toString: function(){
+               return this.makeBinaryOperandString("LB", "opt:0x", this.opt, "0x", this.imm32);
+       },
+});
+
+var WebCPU_Instruction_LIMM = function(instrID){
+       //定数即値代入命令
+       this.reg0 = 0;
+       this.imm32 = 0;
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               this.setParameter(
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
+                       this.fetchSignedInteger(argBinStr, baseIndex, 1, 4)
+               );
+               return 6;
+       },
+       setParameter: function(destReg, imm32){
+               this.reg0 = destReg;
+               this.imm32 = imm32;
+       },
+       instruction: function(env){
+               env.registers.Integer[this.reg0] = this.imm32;
+       },
+       createBinaryString: function(env){
+               return "02" + toHexString8(this.reg0) + toHexString32(this.imm32);
+       },
+       toString: function(){
+               return this.makeBinaryOperandString("LIMM", "R", this.reg0, "0x", this.imm32);
+       },
+});
+
+var WebCPU_Instruction_PLIMM = function(instrID){
+       //ラベル番号代入命令
+       this.reg0 = 0;
+       this.imm32 = 0;
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               this.setParameter(
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
+                       this.fetchSignedInteger(argBinStr, baseIndex, 1, 4)
+               );
+               return 6;
+       },
+       setParameter: function(destReg, imm32){
+               this.reg0 = destReg;
+               this.imm32 = imm32;
+       },
+       instruction: function(env){
+               var m = env.mainMemory.getMemoryPageInstanceFromLabelNumber(this.imm32);
+               if(m === undefined){
+                       throw new WebCPU_Exception(2, ["Label#0x" + this.imm32.toString(16).toUpperCase() + " notfound."]);
+               } else{
+                       env.registers.Pointer[this.reg0] = new WebCPU_Pointer(m);
+                       if(this.reg0 == 0x3F){
+                               //goto
+                               env.memoryPageCounter = env.mainMemory.getMemoryPageCountFromMemoryPageInstance(m);
+                               env.memoryInstructionCounter = 0;
+                               env.message("JMP:page " + env.memoryPageCounter+ "\n", 20);
+                       }
+               }
+       },
+       createBinaryString: function(env){
+               return "03" + toHexString8(this.reg0) + toHexString32(this.imm32);
+       },
+       toString: function(){
+               return this.makeBinaryOperandString("PLIMM", "P", this.reg0, "0x", this.imm32);
+       },
+});
+
+var WebCPU_Instruction_CND = function(instrID){
+       //条件実行プリフィクス命令
+       this.reg0R = 0;
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               this.setParameter(
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1)
+               );
+               return 2;
+       },
+       setParameter: function(reg){
+               this.reg0R = reg;
+       },
+       instruction: function(env){
+               if((env.registers.Integer[this.reg0R] & 0x01) != 0x01){
+                       env.memoryInstructionCounter++;
+               }
+       },
+       createBinaryString: function(env){
+               return "04" + toHexString8(this.reg0R);
+       },
+       toString: function(){
+               return this.makeUnaryOperandString("CND", "R", this.reg0R);
+       },
+});
+
+var WebCPU_Instruction_LMEM = function(instrID){
+       //メモリ読み込み命令
+       WebCPU_Instruction_LMEM.base.apply(this, arguments);
+}.extend(WebCPU_Instruction_MEM_Base, {
+       instruction: function(env){
+               var pointer = env.registers.Pointer[this.reg1P];
+               if(this.typ32 == pointer.memoryType){
+                       var v = env.registers.Pointer[this.reg1P].readData(env);
+                       env.message("Memory:Read:" + pointer.toString() + ":" + v + "\n", 20);
+                       if(v !== undefined){
+                               env.registers.Integer[this.reg0R] = v;
+                       }
+               } else{
+                       throw new WebCPU_Exception(2, ["Conflict type of pointer."]);
+               }
+       },
+       createBinaryString: function(env){
+               return "08" + toHexString8(this.reg0R) + toHexString32(this.typ32) + toHexString8(this.reg1P) + "00";
+       },
+       toString: function(){
+               return this.makeQuaternaryOperandString("LMEM", "R", this.reg0R, "typ:0x", this.typ32, "P", this.reg1P, "reserved:0x", this.reserved);
+       },
+});
+
+var WebCPU_Instruction_SMEM = function(instrID){
+       //メモリ書き込み命令
+       WebCPU_Instruction_SMEM.base.apply(this, arguments);
+}.extend(WebCPU_Instruction_MEM_Base, {
+       instruction: function(env){
+               var pointer = env.registers.Pointer[this.reg1P];
+               if(this.typ32 == pointer.memoryType){
+                       var d = env.registers.Integer[this.reg0R];
+                       if(this.typ32 == 0x03){
+                               //UINT8
+                               d &= 0xff;
+                       } else if(this.typ32 == 0x06){
+                               //SINT32
+                               //register native
+                       } else if(this.typ32 == 0x07){
+                               //UINT32
+                               if(d < 0){
+                                       d = (0xffffffff >> 1) + d;
+                               }
+                               d &= 0xffffffff;
+                       } else if(this.typ32 == 0x09){
+                               //UINT4
+                               d &= 0xf;
+                       } else{
+                               throw new WebCPU_Exception(0, ["Not implemented data type: 0x" + this.typ32.toString(16)]);
+                       }
+                       if(d != env.registers.Integer[this.reg0R]){
+                               env.message("Data lost in type conversion 0x" + env.registers.Integer[this.reg0R].toString(16) + " to:0x" + d.toString(16));
+                       }
+                       env.message("Memory:Write:" + pointer.toString() + ":" + d +"\n", 20);
+                       env.registers.Pointer[this.reg1P].writeData(env, d);
+               } else{
+                       throw new WebCPU_Exception(2, ["Conflict type of pointer."]);
+               }
+       },
+       createBinaryString: function(env){
+               return "09" + toHexString8(this.reg0R) + toHexString32(this.typ32) + toHexString8(this.reg1P) + "00";
+       },
+       toString: function(){
+               return this.makeQuaternaryOperandString("SMEM", "R", this.reg0R, "typ:0x", this.typ32, "P", this.reg1P, "reserved:0x", this.reserved);
+       },
+});
+
+var WebCPU_Instruction_PADD = function(instrID){
+       //ポインタ演算命令
+       this.reg0P = 0;
+       this.typ32 = 0;
+       this.reg1P = 0;
+       this.reg2R = 0;
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               this.setParameter(
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 4),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 5, 1),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 6, 1)
+               );
+               return 8;
+       },
+       setParameter: function(regPdest, pType, regPsrc, regR){
+               this.reg0P = regPdest;
+               this.typ32 = pType;
+               this.reg1P = regPsrc;
+               this.reg2R = regR;
+       },
+       instruction: function(env){
+               if(this.reg0P != this.reg1P){
+                       env.registers.Pointer[this.reg0P] = env.registers.Pointer[this.reg1P].getCopy();
+               }
+               env.registers.Pointer[this.reg0P].addressOffset += env.registers.Integer[this.reg2R];
+       },
+       createBinaryString: function(env){
+               return "0E" + toHexString8(this.reg0P) + toHexString32(this.typ32) + toHexString8(this.reg1P) + toHexString8(this.reg2R);
+       },
+       toString: function(){
+               return this.makeQuaternaryOperandString("PADD", "P", this.reg0P, "typ:0x", this.typ32, "P", this.reg1P, "R", this.reg2R);
+       },
+});
+
+var WebCPU_Instruction_PDIF = function(instrID){
+       //ポインタ演算命令
+       this.reg0R = 0;
+       this.typ32 = 0;
+       this.reg1P = 0;
+       this.reg2P = 0;
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               this.setParameter(
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 4),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 5, 1),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 6, 1)
+               );
+               return 8;
+       },
+       setParameter: function(regR, pType, reg1P, reg2P){
+               this.reg0R = regR;
+               this.typ32 = pType;
+               this.reg1P = reg1P;
+               this.reg2P = reg2P;
+       },
+       instruction: function(env){
+               throw new WebCPU_Exception(0, ["Not implemented:" + this.toString()]);
+       },
+       createBinaryString: function(env){
+               return "0F" + toHexString8(this.reg0R) + toHexString32(this.typ32) + toHexString8(this.reg1P) + toHexString8(this.reg2P);
+       },
+       toString: function(){
+               return this.makeQuaternaryOperandString("PDIF", "R", this.reg0R, "typ:0x", this.typ32, "P", this.reg1P, "P", this.reg2P);
+       },
+});
+
+var WebCPU_Instruction_PCP = function(instrID){
+       //ポインタ代入命令
+       //P3Fへの代入でJMP
+       this.reg0P = 0;
+       this.reg1P = 0;
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               this.setParameter(
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 1)
+               );
+               return 3;
+       },
+       setParameter: function(regPdest, regPsrc){
+               this.reg0P = regPdest;
+               this.reg1P = regPsrc;
+       },
+       instruction: function(env){
+               if(this.reg0P != this.reg1P){
+                       env.registers.Pointer[this.reg0P] = env.registers.Pointer[this.reg1P].getCopy();
+                       if(this.reg0P == 0x3F){
+                               //P3Fへの代入でJMP
+                               var type = env.registers.Pointer[0x3F].memoryType;
+                               if(type == 0x01){
+                                       //VPtr
+                                       env.goToPointerRegister(0x3F);
+                               } else if(type == 0xC0FFEE){
+                                       //API
+                                       env.API.executeAPI(env);
+                               } else{
+                                       throw new WebCPU_Exception(2, ["Attempt transfering execution to data section."]);
+                               }
+                       }
+                       
+               }
+       },
+       createBinaryString: function(env){
+               return "1E" + toHexString8(this.reg0P) + toHexString8(this.reg1P);
+       },
+       toString: function(){
+               return this.makeBinaryOperandString("PCP", "P", this.reg0P, "P", this.reg1P);
+       },
+});
+
+var WebCPU_Instruction_MALLOC = function(instrID){
+       //メモリ確保命令
+       this.reg0P = 0;
+       this.reg1R = 0; //型
+       this.reg2R = 0; //指定された型でのデータの個数
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               this.reg0P = this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1);
+               this.reg1R = this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 1);
+               this.reg2R = this.fetchUnsignedInteger(argBinStr, baseIndex, 2, 1);
+               return 4;
+       },
+       instruction: function(env){
+               var m = env.mainMemory.allocateMemoryPage(env.registers.Integer[this.reg1R], env.registers.Integer[this.reg2R]);
+               env.registers.Pointer[this.reg0P] = new WebCPU_Pointer(m);
+       },
+       createBinaryString: function(env){
+               return "32" + toHexString8(this.reg0P) + toHexString8(this.reg1R) + toHexString8(this.reg2R);
+       },
+       toString: function(){
+               return this.makeTernaryOperandString("MALLOC", "P", this.reg0P, "R", this.reg1R, "R", this.reg2R);
+       },
+});
+
+var WebCPU_Instruction_DATA = function(instrID){
+       //データ記述命令
+       this.type = 0;
+       this.length = 0;        //指定された型でのデータの個数
+       this.byteLength = 0;    //バイト単位でのデータ部分の長さ
+       this.dataStr = null;
+       this.data = null;
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               this.type = this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 4);
+               //指定された型での個数
+               this.length = this.fetchUnsignedInteger(argBinStr, baseIndex, 4, 4);
+               this.data = new Array();
+               if(this.type == 0x03){
+                       //UINT8
+                       this.byteLength = this.length;
+                       this.dataStr = argBinStr.substr(baseIndex + 8 * 2, this.byteLength * 2);
+                       for(var i = 0; i < this.length; i++){
+                               this.data.push(parseInt(this.dataStr.substr(i * 2, 2), 16));
+                       }
+               } else if(this.type == 0x06){
+                       //SINT32
+                       this.byteLength = this.length * 4;
+                       this.dataStr = argBinStr.substr(baseIndex + 8 * 2, this.byteLength * 2);
+                       for(var i = 0; i < this.length; i++){
+                               this.data.push(parseSignedInt32(this.dataStr.substr(i * 2 * 4, 4), 16));
+                       }
+               } else if(this.type == 0x07){
+                       //UINT32
+                       this.byteLength = this.length * 4;
+                       this.dataStr = argBinStr.substr(baseIndex + 8 * 2, this.byteLength * 2);
+                       for(var i = 0; i < this.length; i++){
+                               this.data.push(parseInt(this.dataStr.substr(i * 2 * 4, 4), 16));
+                       }
+               } else if(this.type == 0x09){
+                       //UINT4
+                       this.byteLength = Math.ceil(this.length / 2);
+                       this.dataStr = argBinStr.substr(baseIndex + 8 * 2, this.byteLength * 2);
+                       for(var i = 0; i < this.length; i++){
+                               this.data.push(parseInt(this.dataStr.substr(i, 1), 16));
+                       }
+               } else{
+                       return ("DATA:Not implemented data type: 0x" + this.type.toString(16));
+               }
+               return 1 + 4 + 4 + this.byteLength;
+       },
+       instruction: function(env){
+               //nothing
+       },
+       createBinaryString: function(env){
+               return "34" + toHexString32(this.type) + toHexString32(this.length) + this.dataStr;
+       },
+       toString: function(){
+               return this.makeBinaryOperandString("DATA", "type:0x", this.type, "length:0x", this.length) + "[" + this.dataStr +"]";
+       },
+});
+
+var WebCPU_Instruction_REMARK = function(instrID){
+       //リマーク命令
+       this.remLen = 0;
+       this.remStr = null;
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               this.remLen = this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1);
+               this.remStr = argBinStr.substr(baseIndex + 1 * 2, this.remLen * 2);
+               return 2 + this.remLen;
+       },
+       instruction: function(env){
+               //nothing
+       },
+       createBinaryString: function(env){
+               return "FE" + toHexString8(this.remLen) + this.remStr;
+       },
+       toString: function(){
+               return this.makeUnaryOperandString("REMARK", "len:0x", this.remLen) + "[" + this.remStr +"]";
+       },
+});
diff --git a/webcpu/instrbas.js b/webcpu/instrbas.js
new file mode 100644 (file)
index 0000000..ccd51c2
--- /dev/null
@@ -0,0 +1,300 @@
+//
+// Instruction baseclass
+//
+
+function WebCPU_Instruction(instrID){
+       //命令クラス共通部分
+       //バックエンドバイナリでの命令先頭バイトのオフセット
+       this.binOffset = 0;
+}
+WebCPU_Instruction.prototype = {
+       // loadArguments, execute, toStringが必須。
+       loadArguments: function(argBinStr, baseIndex){
+               //戻り値は、読み込み成功時はその命令の占めるバイト数、失敗時はエラー文字列を返す。
+               //常に読み込みエラー
+               return this.toString();
+       },
+       setParameter: function(){
+       
+       },
+       execute: function(env){
+               //printXXXはデバッグ用
+               if(this.printSourceRegister){
+                       this.printSourceRegister(env);
+               }
+               this.instruction(env);
+               if(this.printDestinationRegister){
+                       this.printDestinationRegister(env);
+               }
+       },
+       instruction: function(env){
+               //envはCPUのインスタンス
+               throw new WebCPU_Exception(0, ["Not implemented:" + this.toString()]);
+       },
+       createBinaryString: function(env){
+               //envはCPUのインスタンス
+               throw new WebCPU_Exception(0, ["Not implemented:" + this.toString()]);
+       },
+       toString: function(){
+               return "Undefined()[0x" + this.instrID.toString(16).toUpperCase() + "];";
+       },
+       //
+       makeUnaryOperandString: function(mnemonic, typestr0, arg0){
+               return mnemonic + "(" + typestr0 + arg0.toString(16).toUpperCase() + ");";
+       },
+       makeBinaryOperandString: function(mnemonic, typestr0, arg0, typestr1, arg1){
+               return mnemonic + "(" + typestr0 + arg0.toString(16).toUpperCase() + ", " + typestr1 + arg1.toString(16).toUpperCase() + ");";
+       },
+       makeTernaryOperandString: function(mnemonic, typestr0, arg0, typestr1, arg1, typestr2, arg2){
+               return mnemonic + "(" + typestr0 + arg0.toString(16).toUpperCase() + ", " + typestr1 + arg1.toString(16).toUpperCase() + ", " + typestr2 + arg2.toString(16).toUpperCase() + ");";
+       },
+       makeQuaternaryOperandString: function(mnemonic, typestr0, arg0, typestr1, arg1, typestr2, arg2, typestr3, arg3){
+               return mnemonic + "(" + typestr0 + arg0.toString(16).toUpperCase() + ", " + typestr1 + arg1.toString(16).toUpperCase() + ", " + typestr2 + arg2.toString(16).toUpperCase() + ", " + typestr3 + arg3.toString(16).toUpperCase() + ");";
+       },
+       //
+       makeRRegString: function(env, reg){
+               return "R" + reg.toString(16).toUpperCase() + ":0x" +  env.registers.Integer[reg].toString(16).toUpperCase();
+       },
+       makePRegString: function(env, reg){
+               return "P" + reg.toString(16).toUpperCase() + ":0x" + env.registers.Pointer[reg].addressOffset.toString(16).toUpperCase();
+       },
+       printRReg: function(env, reg){
+               env.message(this.makeRRegString(env, reg) + "\n");
+       },
+       printPReg: function(env, reg){
+               env.message(this.makePRegString(env, reg) + "\n");
+       },
+       //
+       fetchUnsignedInteger: function(argBinStr, baseIndex, offset, bytes){
+               return parseInt(argBinStr.substr(baseIndex + offset * 2, bytes * 2), 16);
+       },
+       fetchSignedInteger: function(argBinStr, baseIndex, offset, bytes){
+               return parseSignedInt32(argBinStr.substr(baseIndex + offset * 2, bytes * 2), 16);
+       },
+       //
+       printSourceRegister: null,
+       printDestinationRegister: null,
+}
+
+var WebCPU_Instruction_MEM_Base = function(instrID){
+       //メモリ関連命令共通部分
+       this.reg0R = 0;
+       this.typ32 = 0;
+       this.reg1P = 0;
+       this.reserved = 0;
+}.extend(WebCPU_Instruction, {
+       loadArguments: function(argBinStr, baseIndex){
+               this.setParameter(
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 4),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 5, 1),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 6, 1)
+               );
+               return 8;
+       },
+       setParameter: function(regR, pType, regP, reserved){
+               this.reg0R = regR;
+               this.typ32 = pType;
+               this.reg1P = regP;
+               this.reserved = reserved;
+       },
+});
+
+var WebCPU_Instruction_TernaryOperation = function(instrID){
+       //単純代入命令
+       //三項演算命令
+       //整数比較命令
+       //演算結果はすべて符号ありであることに注意
+       this.instrID = instrID;
+       this.reg0 = 0;
+       this.reg1 = 0;
+       this.reg2 = 0;
+       this.subfunc = null;
+}.extend(WebCPU_Instruction, {
+       mnemonicList1: [
+               "OR",
+               "XOR",
+               "AND",
+               "UD",
+               "ADD",
+               "SUB",
+               "MUL",
+               "UD",
+               "SHL",
+               "SAR",
+               "DIV",
+               "MOD",
+       ],
+       mnemonicList2: [
+               "CMPE",
+               "CMPNE",
+               "CMPL",
+               "CMPGE",
+               "CMPLE",
+               "CMPG",
+               "TSTZ",
+               "TSTNZ",
+       ],
+       loadArguments: function(argBinStr, baseIndex){
+               this.setParameter(
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 1),
+                       this.fetchUnsignedInteger(argBinStr, baseIndex, 2, 1)
+               );
+               if(this.instruction == WebCPU_Instruction_TernaryOperation.base.prototype.instruction){
+                       return 1;
+               }
+               return 4;
+       },
+       setParameter: function(destReg, srcReg0, srcReg1){
+               if(this.instrID === undefined){
+                       throw "setParameter:instrID undefined";
+               }
+               this.reg0 = destReg;
+               this.reg1 = srcReg0;
+               this.reg2 = srcReg1;
+               if(this.instrID == 0x10){
+                       if(srcReg1 == 0xFF){
+                               //CP
+                               this.mnemonic = "CP";
+                               this.instruction = this.instrCP;
+                               this.printSourceRegister = this.printSourceRegisterCP;
+                       } else{
+                               //OR
+                               this.mnemonic = this.mnemonicList1[0];
+                               this.instruction = this.instrOR;
+                       }
+               } else if(0x11 <= this.instrID && this.instrID <= 0x1B){
+                       // list1
+                       this.mnemonic = this.mnemonicList1[this.instrID - 0x10];
+                       this.instruction = eval("this.instr" + this.mnemonic);
+               } else if(0x20 <= this.instrID && this.instrID <= 0x27){
+                       //list2
+                       this.mnemonic = this.mnemonicList2[this.instrID - 0x20];
+                       this.instruction = eval("this.instr" + this.mnemonic);
+               } else if(0x28 <= this.instrID && this.instrID <= 0x2D){
+                       //list2P
+                       this.mnemonic = "P" + this.mnemonicList2[this.instrID - 0x28];
+                       this.instruction = this.instrP;
+                       this.subfunc = eval("this.instr" + this.mnemonic);
+                       this.printSourceRegister = this.printSourceRegisterP;
+               }
+       },
+       //
+       instrCP: function(env){
+               env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1];
+       },
+       instrOR: function(env){
+               env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] | env.registers.Integer[this.reg2];
+       },
+       instrXOR: function(env){
+               env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] ^ env.registers.Integer[this.reg2];
+       },
+       instrAND: function(env){
+               env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2];
+       },
+       instrADD: function(env){
+               env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] + env.registers.Integer[this.reg2];
+       },
+       instrSUB: function(env){
+               env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] - env.registers.Integer[this.reg2];
+       },
+       instrMUL: function(env){
+               env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] * env.registers.Integer[this.reg2];
+       },
+       instrSHL: function(env){
+               env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] << env.registers.Integer[this.reg2];
+       },
+       instrSAR: function(env){
+               env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] >> env.registers.Integer[this.reg2];
+       },
+       instrDIV: function(env){
+               env.registers.Integer[this.reg0] = parseInt(env.registers.Integer[this.reg1] / env.registers.Integer[this.reg2]);
+       },
+       instrMOD: function(env){
+               env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] % env.registers.Integer[this.reg2];
+       },
+       //
+       instrCMPE: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] == env.registers.Integer[this.reg2]) ? -1 : 0;
+       },
+       instrCMPNE: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] != env.registers.Integer[this.reg2]) ? -1 : 0;
+       },
+       instrCMPL: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] < env.registers.Integer[this.reg2]) ? -1 : 0;
+       },
+       instrCMPGE: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] >= env.registers.Integer[this.reg2]) ? -1 : 0;
+       },
+       instrCMPLE: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] <= env.registers.Integer[this.reg2]) ? -1 : 0;
+       },
+       instrCMPG: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] > env.registers.Integer[this.reg2]) ? -1 : 0;
+       },
+       instrTSTZ: function(env){
+               env.registers.Integer[this.reg0] = ((env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2]) == 0) ? -1 : 0;
+       },
+       instrTSTNZ: function(env){
+               env.registers.Integer[this.reg0] = ((env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2]) != 0) ? -1 : 0;
+       },
+       //
+       instrP: function(env){
+               if(env.registers.Pointer[this.reg1].verifySameMemoryPageAs(env.registers.Pointer[this.reg2])){
+                       this.subfunc(env);
+               } else{
+                       throw new WebCPU_Exception(2, ["Attempt to compare pointers in different memoyPage."]);
+               }
+       },
+       //
+       instrPCMPE: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset == env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
+       },
+       instrPCMPNE: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset != env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
+       },
+       instrPCMPL: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset < env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
+       },
+       instrPCMPGE: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset >= env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
+       },
+       instrPCMPLE: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset <= env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
+       },
+       instrPCMPG: function(env){
+               env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset > env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
+       },
+       //
+       createBinaryString: function(env){
+               return toHexString8(this.instrID) + toHexString8(this.reg0) + toHexString8(this.reg1) + toHexString8(this.reg2);
+       },
+       toString: function(){
+               if(this.mnemonic == "CP"){
+                       return this.makeBinaryOperandString("CP", "R", this.reg0, "R", this.reg1);
+               }
+               if(this.mnemonic == "UD"){
+                       return "Undefined();";
+               }
+               if(0x28 <= this.instrID && this.instrID <= 0x2D){
+                       return this.makeTernaryOperandString(this.mnemonic, "R", this.reg0, "P", this.reg1, "P", this.reg2);
+               }
+               return this.makeTernaryOperandString(this.mnemonic, "R", this.reg0, "R", this.reg1, "R", this.reg2);
+       },
+       //
+       printSourceRegister: function(env){
+               this.printRReg(env, this.reg1);
+               this.printRReg(env, this.reg2);
+       },
+       printSourceRegisterP: function(env){
+               this.printPReg(env, this.reg1);
+               this.printPReg(env, this.reg2);
+       },
+       printSourceRegisterCP: function(env){
+               this.printPReg(env, this.reg1);
+       },
+       printDestinationRegister: function(env){
+               this.printRReg(env, this.reg0);
+       },
+});
diff --git a/webcpu/memory.js b/webcpu/memory.js
new file mode 100644 (file)
index 0000000..c3b7c7a
--- /dev/null
@@ -0,0 +1,171 @@
+function WebCPU_Memory(){
+       this.initMemory();
+}
+WebCPU_Memory.prototype = {
+       addMemoryPage: function(memoryPage){
+               this.root.push(memoryPage);
+       },
+       initMemory: function(){
+               this.root = new Array();
+               this.addMemoryPage(new WebCPU_MemoryPage());
+       },
+       getMemoryPageCountFromMemoryPageInstance: function(memoryPage){
+               for(var i = 0; i < this.root.length; i++){
+                       if(this.root[i] == memoryPage){
+                               return i;
+                       }
+               }
+
+               return undefined;
+       },
+       getMemoryPageInstanceFromLabelNumber: function(labelnum){
+               //ラベルをメモリから探し出す
+               for(var i = 0; i < this.root.length; i++){
+                       if(this.root[i].data[0] instanceof WebCPU_Instruction_LB){
+                               if(this.root[i].data[0].imm32 == labelnum){
+                                       return this.root[i];
+                               }
+                       }
+               }
+               return undefined;
+       },
+       allocateMemoryPage: function(type, length){
+               //指定された型と長さのメモリを確保して返す。
+               length = length ? length : 0;
+               var m = new WebCPU_MemoryPage();
+               m.addMemoryData(new WebCPU_Instruction_LB());
+               m.addMemoryData(new WebCPU_Instruction_DATA());
+               m.data[1].type = type;
+               m.data[1].data = new Array(length);
+               return m;
+       },
+}
+
+function WebCPU_MemoryPage(size){
+       size = size ? size : 0;
+       this.data = new Array(size);
+}
+WebCPU_MemoryPage.prototype = {
+       addMemoryData: function(memoryData){
+               this.data.push(memoryData);
+       },
+}
+
+function WebCPU_Pointer(memoryPage){
+       this.memoryPage = memoryPage;
+       this.memoryType = 0;
+       this.addressOffset = 0;
+       this.labelNumber = null;
+       //ポインタタイプ判別
+       if(this.memoryPage && this.memoryPage.data && this.memoryPage.data.length > 0){
+               if(this.memoryPage.data[0] instanceof WebCPU_Instruction_LB){
+                       //ラベルが直下にあればそのラベル番号をポインタに記憶する
+                       this.labelNumber = this.memoryPage.data[0].imm32;
+                       this.memoryType = this.T_VPtr;
+                       if(this.memoryPage.data[1]){
+                               if(this.memoryPage.data[1] instanceof WebCPU_Instruction_DATA){
+                                       //ラベル直下がDATAだった場合はそのDATAの型に従う
+                                       var type = this.memoryPage.data[1].type;
+                                       if(1 <= type && type < this.memoryTypeStrList.length){
+                                               this.memoryType = type;
+                                       } else{
+                                               console.log("unknown data type.");
+                                       }
+                               }
+                       }
+               }
+       }
+       this.memoryTypeStr = this.memoryTypeStrList[this.memoryType];
+}
+
+WebCPU_Pointer.prototype = {
+       memoryTypeStrList: [
+               "Undefined",
+               "VPtr",         // コードポインタ?
+               "SINT8",        // 8bitの符号付き, いわゆる signed char.
+               "UINT8",
+               "SINT16",       // 16bitの符号付き, いわゆる short.
+               "UINT16",
+               "SINT32",
+               "UINT32",
+               "SINT4",
+               "UINT4",
+               "SINT2",
+               "UINT2",
+               "SINT1",        // 代入できるのは0か-1のみ.
+               "UINT1",
+               "SINT12",
+               "UINT12",
+               "SINT20",
+               "UINT20",
+               "SINT24",
+               "UINT24",
+               "SINT28",
+               "UINT28",       //0x15
+       ],
+       T_VPtr          :0x01,
+       T_SINT8         :0x02,  //8bitの符号付き, いわゆる signed char.
+       T_UINT8         :0x03,
+       T_SINT16        :0x04,  //16bitの符号付き, いわゆる short.
+       T_UINT16        :0x05,
+       T_SINT32        :0x06,
+       T_UINT32        :0x07,
+       T_SINT4         :0x08,
+       T_UINT4         :0x09,
+       T_SINT2         :0x0a,
+       T_UINT2         :0x0b,
+       T_SINT1         :0x0c,  //代入できるのは0か-1のみ.
+       T_UINT1         :0x0d,
+       T_SINT12        :0x0e,
+       T_UINT12        :0x0f,
+       T_SINT20        :0x10,
+       T_UINT20        :0x11,
+       T_SINT24        :0x12,
+       T_UINT24        :0x13,
+       T_SINT28        :0x14,
+       T_UINT28        :0x15,
+       toString: function(){
+               if(this.memoryType == 0xC0FFEE){
+                       //API Address, NOT OFFICIAL
+                       return "#API";
+               }
+               if(this.labelNumber == null){
+                       if(this.memoryPage && this.memoryPage.data && this.memoryPage.data[1].data){
+                               return this.memoryTypeStrList[this.memoryType] + ":" + this.addressOffset + " / " + this.memoryPage.data[1].data.length;
+                       }
+                       return this.memoryTypeStrList[this.memoryType] + ":" + this.addressOffset;
+               }
+               return "Label#0x" + this.labelNumber.toString(16).toUpperCase() + ":" + this.addressOffset + ":" + this.memoryTypeStr;
+       },
+       readData: function(env){
+               if(this.memoryPage.data[1].data.length <= this.addressOffset){
+                       throw new WebCPU_Exception(2, ["Attempt to access to out of pointer range."]);
+               }
+               var data = this.memoryPage.data[1].data[this.addressOffset];
+               if(data === undefined){
+                       throw new WebCPU_Exception(2, ["Attempt to access to undefined value."]);
+               }
+               return data;
+       },
+       writeData: function(env, data){
+               if(this.memoryPage.data[1].data.length <= this.addressOffset){
+                       throw new WebCPU_Exception(2, ["Attempt to access to out of pointer range."]);
+               }
+               this.memoryPage.data[1].data[this.addressOffset] = data;
+       },
+       getCopy: function(){
+               var copy = new WebCPU_Pointer();
+               copy.memoryPage = this.memoryPage;
+               copy.memoryType = this.memoryType;
+               copy.memoryTypeStr = this.memoryTypeStr;
+               copy.addressOffset = this.addressOffset;
+               copy.labelNumber = this.labelNumber;
+               return copy;
+       },
+       verifySameMemoryPageAs: function(p){
+               if(p && p.memoryPage && this.memoryPage && this.memoryPage == p.memoryPage){
+                       return true;
+               }
+               return false;
+       }
+}
diff --git a/webcpu/webcpu.js b/webcpu/webcpu.js
new file mode 100755 (executable)
index 0000000..f8215b2
--- /dev/null
@@ -0,0 +1,565 @@
+function WebCPU_Exception(errno, infoArray){
+       this.errno = errno;
+       this.infoArray = infoArray;
+}
+WebCPU_Exception.prototype = {
+       errorMessageList: [
+               "Trap.",
+               "Pre-compile error.",
+               "Execution error.",
+       ],
+       getMessageString: function(){
+               var s = "";
+               s += "Error" + this.errno.toString().toUpperCase();
+               if(this.errno < 0 || this.errorMessageList.length <= this.errno){
+                       s += ":Unknown\n";
+               } else{
+                       s += ":" + this.errorMessageList[this.errno] + "\n";
+               }
+               if(this.infoArray){
+                       s += "  >" + this.infoArray.toString() + "\n";
+               }
+               return s;
+       },
+}
+// throw new WebCPU_Exception(2, [""]);
+
+function WebCPU(){
+       //APIクラスインスタンス取得
+       this.API = new WebCPU_API();
+
+       //DOMオブジェクト連携
+       this.debugMessageText = null;
+       this.debugIntegerRegisterText = null;
+       this.debugPointerRegisterText = null;
+       //デバッグコンソール設定
+       this.debugMessageBuffer = "";
+       var that = this;
+       this.messageTimer = null;
+       
+       //メモリ
+       //メモリはラベルごとにページとして区切られ、それらの配列が一つのメモリとなる。
+       this.mainMemory = new WebCPU_Memory();
+       this.memoryPageCounter = 0;
+       this.memoryInstructionCounter = 0;
+       this.stopFlag = false;
+       
+       //レジスタ配列
+       this.registers = new Object;
+       this.registers.Integer = new Array(64);
+       
+       //初期化
+       this.reset();
+       
+       //命令リスト
+       this.instruction = new Array(0xFF + 1);
+       //命令テーブル初期化
+       for(var i = 0; i < this.instruction.length; i++){
+               this.instruction[i] = WebCPU_Instruction_Undefined;
+       }
+       //
+       this.instruction[0x00] = WebCPU_Instruction_NOP;
+       this.instruction[0x01] = WebCPU_Instruction_LB;
+       this.instruction[0x02] = WebCPU_Instruction_LIMM;
+       this.instruction[0x03] = WebCPU_Instruction_PLIMM;
+       this.instruction[0x04] = WebCPU_Instruction_CND;
+       this.instruction[0x08] = WebCPU_Instruction_LMEM;
+       this.instruction[0x09] = WebCPU_Instruction_SMEM;
+       this.instruction[0x0E] = WebCPU_Instruction_PADD;
+       this.instruction[0x0F] = WebCPU_Instruction_PDIF;
+       //
+       this.instruction[0x10] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x11] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x12] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x14] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x15] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x16] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x18] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x19] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x1A] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x1B] = WebCPU_Instruction_TernaryOperation;
+       //
+       this.instruction[0x1E] = WebCPU_Instruction_PCP;
+       //
+       this.instruction[0x20] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x21] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x22] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x23] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x24] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x25] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x26] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x27] = WebCPU_Instruction_TernaryOperation;
+       //
+       this.instruction[0x28] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x29] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x2A] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x2B] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x2C] = WebCPU_Instruction_TernaryOperation;
+       this.instruction[0x2D] = WebCPU_Instruction_TernaryOperation;
+       //
+       this.instruction[0x32] = WebCPU_Instruction_MALLOC;
+       this.instruction[0x34] = WebCPU_Instruction_DATA;
+       //
+       this.instruction[0xFE] = WebCPU_Instruction_REMARK;
+       
+       this.message("<<< Initialized >>>\n");
+}
+WebCPU.prototype = {
+       loadBinaryText: function(binStr){
+               //引数はフロントエンドコードのHex文字列も可能。(Not implemented.)
+               //改行やスペースも含まれていてよい。
+               //シグネチャも含まれていてよい
+               binStr = replaceAll(binStr, " ", "");
+               binStr = replaceAll(binStr, "\n", "");
+               binStr = replaceAll(binStr, "\r", "");
+               binStr = replaceAll(binStr, "\t", "");
+               binStr = binStr.toUpperCase();
+               if(binStr.substr(0, 4) == "05E1"){
+                       //シグネチャあり
+                       this.message("LoadBinaryText:OSECPU signature found.\n", 10);
+                       if(binStr.substr(4, 2) == "00"){
+                               //BackEndCode
+                               this.message("LoadBinaryText:This is BackEndCode.\n", 10);
+                               binStr = binStr.substr(6);
+                       } else{
+                               //FrontEndCode
+                               this.message("LoadBinaryText:This is FrontEndCode.\n", 10);
+                               binStr = binStr.substr(4);
+                               this.loadFrontEndBinaryText(binStr);
+                               return;
+                       }
+               } else{
+                       this.message("LoadBinaryText:OSECPU signature NOT found.\n", 1);
+               }
+               this.loadBackEndBinaryText(binStr);
+       },
+       loadBackEndBinaryText: function(binStr){
+               //引数はバックエンドコードのHex文字列表現でスペースなどの他の文字の混入は認められない。
+               this.message("****LoadBackEndBinaryText****\n", 30);
+               this.mainMemory.initMemory();
+               this.memoryPageCounter = 0;
+               this.memoryInstructionCounter = 0;
+               
+               try{
+                       for(var i = 0; i < binStr.length; ){
+                               //命令解釈
+                               var id = parseInt(binStr.substr(i, 2), 16);
+                               i += 2;
+                               var instr = new this.instruction[id](id);
+                               instr.binOffset = (i >> 1) - 1;
+                               var instrarglen = instr.loadArguments(binStr, i);
+                               if(isNaN(parseInt(instrarglen))){
+                                       throw new WebCPU_Exception(1, ["Invalid instrarglen."]);
+                               }
+                               //instrarglenをバイト単位から文字列単位に変換し、さらに引数部分のみのサイズに補正する。
+                               instrarglen = (instrarglen - 1) * 2;
+                               //命令オペランド長チェック
+                               if(instrarglen > binStr.length - i){
+                                       //オペランドの長さ分だけのバイナリがなかった、つまり不完全な状態で途切れている
+                                       throw new WebCPU_Exception(1, ["Invalid instrarglen."]);
+                               }
+                               i+= instrarglen;
+                               
+                               if(id == 0x01){
+                                       //ラベル命令だったのでメモリページを新たにする。
+                                       this.mainMemory.addMemoryPage(new WebCPU_MemoryPage());
+                                       this.memoryPageCounter++;
+                                       this.memoryInstructionCounter = 0;
+                               }
+                               
+                               this.mainMemory.root[this.memoryPageCounter].addMemoryData(instr);
+                       }
+               } catch(e){
+                       this.message("****LoadBackEndBinaryText Abort:\n", 1);
+                       if(e instanceof WebCPU_Exception){
+                               this.message(e.getMessageString(), 1);
+                       } else{
+                               throw e;
+                       }
+                       this.showDisassembledCode();
+                       this.mainMemory.initMemory();
+                       this.memoryPageCounter = 0;
+                       this.memoryInstructionCounter = 0;
+               }
+               this.showDisassembledCode();
+               this.message("****LoadBackEndBinaryText End****\n", 30);
+               
+               this.memoryPageCounter = 0;
+               this.memoryInstructionCounter = 0;
+       },
+       loadFrontEndBinaryText: function(binStr){
+               //引数はフロントエンドコードのHex文字列表現でスペースなどの他の文字の混入は認められない。
+               this.message("****LoadFrontEndBinaryText****\n", 40);
+               this.mainMemory.initMemory();
+               this.memoryPageCounter = 0;
+               this.memoryInstructionCounter = 0;
+               //フロントエンドコードデコーダーの読み込み
+               this.loadBinaryText(decoderBinaryString);
+               //変換準備
+               var backendMaxSize = 65535;
+               var temp0MaxSize = 2 * 1024 * 1024;
+               var temp1MaxSize = 16 * 1024;
+               var temp2MaxSize = 64;
+               var temp3MaxSize = 4 * 1024 + 1;
+               var temp4MaxSize = 256;
+               var m;
+               //P02 = T_UINT8:  &backend[2] (出力バッファ先頭)
+               m = this.mainMemory.allocateMemoryPage(WebCPU_Pointer.prototype.T_UINT8, backendMaxSize);
+               this.registers.Pointer[0x02] = new WebCPU_Pointer(m);
+               //P03 = T_UINT8:  &backend[backend-maxsize] (出力バッファの限界)
+               this.registers.Pointer[0x03] = this.registers.Pointer[0x02].getCopy();
+               this.registers.Pointer[0x03].addressOffset = backendMaxSize;
+               //P04 = T_UINT8:  &frontend[2] (入力データ先頭)
+               m = this.mainMemory.allocateMemoryPage(WebCPU_Pointer.prototype.T_UINT8);
+               this.registers.Pointer[0x04] = new WebCPU_Pointer(m);
+               this.registers.Pointer[0x04].addressOffset = 0;
+               this.registers.Pointer[0x04].memoryPage.data[1].data = new Array();
+               var a = this.registers.Pointer[0x04].memoryPage.data[1].data;
+               var i;
+               for(i = 0; i * 2 < binStr.length; i++){
+                       a.push(parseInt(binStr.substr(i * 2, 2), 16));
+               }
+               //P05 = T_UINT8:  &frontend[frontend-size] (入力データの終端:最終バイトの次のアドレス)
+               this.registers.Pointer[0x05] = this.registers.Pointer[0x04].getCopy();
+               this.registers.Pointer[0x05].addressOffset = i;
+               //P06 = T_UINT8:  &temp0[0] (要素数が2M以上のテンポラリバッファ)
+               m = this.mainMemory.allocateMemoryPage(WebCPU_Pointer.prototype.T_UINT8, temp0MaxSize);
+               this.registers.Pointer[0x06] = new WebCPU_Pointer(m);
+               //P07 = T_UINT8:  &temp0[temp-maxsize]
+               this.registers.Pointer[0x07] = this.registers.Pointer[0x06].getCopy();
+               this.registers.Pointer[0x07].addressOffset = temp0MaxSize;
+               //P0A = T_UINT32: &temp1[0] (要素数が16Kくらいあれば十分なバッファ)
+               m = this.mainMemory.allocateMemoryPage(WebCPU_Pointer.prototype.T_UINT32, temp1MaxSize);
+               this.registers.Pointer[0x0A] = new WebCPU_Pointer(m);
+               //P0B = T_SINT32: &temp2[0] (要素数が64のバッファ:Pxxレジスタの個数)
+               m = this.mainMemory.allocateMemoryPage(WebCPU_Pointer.prototype.T_SINT32, temp2MaxSize);
+               this.registers.Pointer[0x0B] = new WebCPU_Pointer(m);
+               //P0C = T_SINT32: &temp3[0] (要素数が4Kのバッファ:登録可能ラベル数)
+               m = this.mainMemory.allocateMemoryPage(WebCPU_Pointer.prototype.T_SINT32, temp3MaxSize);
+               this.registers.Pointer[0x0C] = new WebCPU_Pointer(m);
+               //P0D = T_UINT8:  &temp4[0] (要素数が256のバッファ)
+               m = this.mainMemory.allocateMemoryPage(WebCPU_Pointer.prototype.T_UINT8, temp4MaxSize);
+               this.registers.Pointer[0x0D] = new WebCPU_Pointer(m);
+               //変換
+               this.execute();
+               /*
+               P02 == バックエンドコードの終端, つまり P02 - &backend[0] = バックエンドコードのサイズ
+               */
+               if(this.registers.Integer[0x00] == 0){
+                       //R00 == 0 正常終了
+                       var binData = this.registers.Pointer[0x02].memoryPage.data[1];
+                       var binStr = "";
+                       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.loadBackEndBinaryText(binStr);
+                       this.reset();
+               } else{
+                       //R00 != 0 変換失敗
+                       this.message("loadFrontEndBinaryText: Translate failed.\n");
+               }
+               
+               this.message("****LoadFrontEndBinaryText End****\n", 40);
+       },
+       executeStepIn: function(){
+               //ステップ実行する。
+               //一回実行するたびに再描画する。
+               var retv = this.executeStepIn_Internal();
+               this.API.API_flushWin(this, this.API.mainWindowBufferCanvas.width, this.API.mainWindowBufferCanvas.height, 0, 0);
+               return retv;
+       },
+       executeStepIn_Internal: function(){
+               //ステップ実行の内部部分。
+               //終端到達時は1を、まだ後続命令がある場合は0を返す。
+               //終了時にのみ再描画を行う
+               if(this.stopFlag){
+                       this.message(">stepIn:Break.\n", 2);
+                       this.stopFlag = false;
+                       this.API.API_flushWin(this, this.API.mainWindowBufferCanvas.width, this.API.mainWindowBufferCanvas.height, 0, 0);
+                       return 2;
+               }
+               var instr = this.fetchMemoryNext();
+               if(instr === undefined){
+                       this.message(">stepIn:control reached end of binary.\n", 2);
+                       this.API.API_flushWin(this, this.API.mainWindowBufferCanvas.width, this.API.mainWindowBufferCanvas.height, 0, 0);
+                       return 1;
+               }
+               this.message(">stepIn:" + this.memoryPageCounter + "-" + (this.memoryInstructionCounter - 1) + ":" + instr.toString() + "\n", 20);
+               instr.execute(this);
+               //これ以降this.memoryInstructionCounterが今実行した命令を指すとは限らない。(JMP系命令のため)
+               /*
+               //ブレークポイント
+               if(this.memoryPageCounter == 233 && this.memoryInstructionCounter == 0){
+                       this.message(">stepIn:Breakpoint.\n", 2);
+                       return 3;
+               }
+               */
+               return 0;
+       },
+       execute: function(){
+               //最速で実行する
+               for(;;){
+                       if(this.executeStepIn_Internal() != 0){
+                               return;
+                       }
+               }
+       },
+       reset: function(){
+               //実行環境をリセットする。メモリ内容は保持される。
+               for(var i = 0; i < this.registers.Integer.length; i++){
+                       this.registers.Integer[i] = 0;
+               }
+               this.registers.Pointer = new Array(64);
+               for(var i = 0; i < this.registers.Pointer.length; i++){
+                       this.registers.Pointer[i] = new WebCPU_Pointer(null);
+               }
+               //Set P28 for API  calling.
+               this.registers.Pointer[0x28].memoryType = 0xC0FFEE;
+               //
+               this.memoryPageCounter = 0;
+               this.memoryInstructionCounter = 0;
+               this.stopFlag = false;
+               //
+               this.message("<<< Reset >>>\n");
+       },
+       fetchMemoryNext: function(){
+               if(this.mainMemory.root[this.memoryPageCounter].data.length <= this.memoryInstructionCounter){
+                       this.memoryPageCounter++;
+                       if(this.mainMemory.root.length <= this.memoryPageCounter){
+                               this.memoryPageCounter--;
+                               return undefined;
+                       }
+                       this.memoryInstructionCounter -= this.mainMemory.root[this.memoryPageCounter - 1].data.length;
+               }
+               var retv = this.mainMemory.root[this.memoryPageCounter].data[this.memoryInstructionCounter];
+               this.memoryInstructionCounter++;
+               return retv;
+       },
+       setMainWindowCanvasDOMObject: function(id){
+               this.API.setMainWindowCanvasDOMObject(document.getElementById(id));
+       },
+       setDebugMessageDOMObject: function(name){
+               this.debugMessageText = document.getElementsByName(name)[0];
+               this.setDebugTimer();
+       },
+       setDebugIntegerRegisterDOMObject: function(name){
+               this.debugIntegerRegisterText = document.getElementsByName(name)[0];
+               this.setDebugTimer();
+       },
+       setDebugPointerRegisterDOMObject: function(name){
+               this.debugPointerRegisterText = document.getElementsByName(name)[0];
+               this.setDebugTimer();
+       },
+       setDebugTimer: function(){
+               if(!this.debugMessageText && !this.debugIntegerRegisterText && !this.debugPointerRegisterText){
+                       //すべて無効だったらタイマーの動作自体を止める
+                       window.clearTimeout(this.messageTimer);
+                       this.messageTimer = null;
+               } else if(!this.messageTimer){
+                       //どれかが有効でかつタイマーが止まっていたらスタートさせる
+                       var that = this;
+                       this.messageTimer = window.setInterval(function(){that.debugShowTick();}, 50);
+               }
+       },
+       debugShowTick: function(){
+               if(this.debugMessageText && this.debugMessageBuffer != ""){
+                       var str = this.debugMessageText.innerHTML + this.debugMessageBuffer;
+                       this.debugMessageBuffer = "";
+                       if(str.length > WebCPU.maxDebugStringLength){
+                               str = str.slice(str.length - (WebCPU.maxDebugStringLength >> 1));
+                       }
+                       this.debugMessageText.innerHTML = str;
+                       this.debugMessageText.scrollTop = this.debugMessageText.scrollHeight;
+               }
+               this.refreshDebugIntegerRegisterText();
+               this.refreshDebugPointerRegisterText();
+       },
+       message: function(str, id){
+               //id:メッセージの種類
+               //省略:常に表示する
+               //1:Error
+               //2:Warning
+               //10:バイナリ読み込みデバッグ
+               //20:実行時詳細情報
+               //30:バックエンドバイナリ読み込みデバッグ
+               //40:フロントエンドバイナリ読み込みデバッグ
+               if(this.debugMessageText != null){
+                       if(
+                               true ||
+                               id == 1 || 
+                               id == 2 || 
+                               id == 30
+                       ){
+                               this.debugMessageBuffer += str;
+                       }
+               } else if(id == 1){
+                       //エラーのときmessageが無効であればalertで表示する。
+                       window.alert(str);
+               }
+       },
+       showDisassembledCode: function(){
+               for(var i = 0; i < this.mainMemory.root.length; i++){
+                       for(var j = 0; j < this.mainMemory.root[i].data.length; j++){
+                               var instr = this.mainMemory.root[i].data[j];
+                               this.message("+0x" + instr.binOffset.toString(16).toUpperCase() + ":" + i + "-" + j + ":" + instr.toString() + "\n", 30);
+                       }
+                       this.message(" - - - - \n", 30);
+               }
+       },
+       refreshDebugIntegerRegisterText: function(){
+               if(this.debugIntegerRegisterText != null){
+                       this.debugIntegerRegisterText.innerHTML = "";
+                       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";
+                       }
+               }
+       },
+       refreshDebugPointerRegisterText: function(){
+               if(this.debugPointerRegisterText != null){
+                       this.debugPointerRegisterText.innerHTML = "";
+                       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";
+                               } else{
+                                       this.debugPointerRegisterText.innerHTML += "P" +  ("00" + i.toString(16)).slice(-2).toUpperCase() + ":(null)\n";
+                               }
+                       }
+               }
+       },
+       goToPointerRegister: function(reg0P){
+               //レジスタはいじらない
+               //goto
+               var p = this.registers.Pointer[reg0P];
+               if(p.memoryType == 1){
+                       //VPtr
+                       this.memoryPageCounter = this.mainMemory.getMemoryPageCountFromMemoryPageInstance(p.memoryPage);
+                       if(this.memoryPageCounter !== undefined){
+                               this.memoryInstructionCounter = 0;
+                               this.message("JMP:page " + this.memoryPageCounter + "\n", 20);
+                       } else{
+                               throw new WebCPU_Exception(2, ["memoryPage not found in mainMemory."]);
+                       }
+               } else{
+                       throw new WebCPU_Exception(2, ["Can't goto Memory page type is not VPtr."]);
+               }
+       },
+       createBackendBinaryString: function(){
+               var s = "05E100";
+               var instr;
+               
+               this.reset();
+               for(;;){
+                       instr = this.fetchMemoryNext();
+                       if(instr === undefined){
+                               break;
+                       }
+                       s += instr.createBinaryString(this);
+               }
+               return s;
+       },
+       staticOptimize: function(){
+               //静的最適化
+               //連続するラベル命令の削除
+               //一つのメモリページにラベル命令のみがある場合は、それを次のメモリページのラベル名に置換する
+               var mpage;
+               var removePageIndexStack = new Array();
+               var labelIDStack = new Array();
+               var labelID;
+               var newLabelID;
+               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.length == 1){
+                                       //ラベルしかないので削除候補に追加
+                                       labelIDStack.push(mpage.data[0].imm32);
+                                       removePageIndexStack.push(i);
+                               } else{
+                                       //これは必要なラベル命令
+                                       if(labelIDStack.length != 0){
+                                               for(;;){
+                                                       labelID = labelIDStack.pop();
+                                                       if(labelID == undefined){
+                                                               break;
+                                                       }
+                                                       this.mainMemory.root.splice(removePageIndexStack[0], 1);
+                                                       i--;
+                                                       this.staticOptimize_ReplaceLabelNumber(labelID, mpage.data[0].imm32);
+                                               }
+                                               removePageIndexStack = new Array();
+                                       }
+                               }
+                       }
+               }
+               if(labelIDStack.length != 0){
+                       //プログラム末尾のラベル命令は削除しないようにする
+                       newLabelID = labelIDStack.pop();
+                       for(;;){
+                               labelID = labelIDStack.pop();
+                               if(labelID == undefined){
+                                       break;
+                               }
+                               this.mainMemory.root.splice(removePageIndexStack[0], 1);
+                               i--;
+                               this.staticOptimize_ReplaceLabelNumber(labelID, newLabelID);
+                       }
+               }
+       },
+       staticOptimize_ReplaceLabelNumber: function(from, to){
+               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){
+                                       if(instr.imm32 == from){
+                                               instr.imm32 = to;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+//数値計算
+function parseSignedInt32(hexStr){
+       //文字列を16進32bit符号あり整数として変換する。
+       var i = parseInt(hexStr, 16);
+       if(i > 0x7fffffff){
+               //-
+               return -(~i + 1);
+       }
+       //+
+       return i;
+}
+
+function parseSignedInt(hexStr, bits){
+       //文字列を16進符号あり整数として変換する。
+       //32bitまで対応
+       var i = parseInt(hexStr, 16);
+       if(i >= (1 << (bits - 1))){
+               //-
+               return -(((0xffffffff >>> (32 - bits)) - i) + 1);
+       }
+       //+
+       return i;
+}
+
+function toHexString8(v){
+       return ("00" + v.toString(16).toUpperCase()).slice(-2);
+}
+
+function toHexString32(v){
+       if(v < 0){
+               v = 0x100000000 + v;
+       }
+       return ("00000000" + v.toString(16).toUpperCase()).slice(-8);
+}
+
+function replaceAll(str, org, dest){
+       //文字列str中にある文字列orgを文字列destにすべて置換する。
+       //http://www.syboos.jp/webjs/doc/string-replace-and-replaceall.html
+       return str.split(org).join(dest);
+}