OSDN Git Service

ed3d54ac8f52f31163778d1eb579a84c8a077d74
[chnosproject/AI004.git] / webcpu / webcpu.js
1 //WebCPUは、このディレクトリにあるファイルで完結している。
2
3 function WebCPU_Exception(errno, infoArray){
4         this.errno = errno;
5         this.infoArray = infoArray;
6 }
7 WebCPU_Exception.prototype = {
8         errorMessageList: [
9                 "Trap.",
10                 "Pre-compile error.",
11                 "Execution error.",
12         ],
13         getMessageString: function(){
14                 var s = "";
15                 s += "Error" + this.errno.toString().toUpperCase();
16                 if(this.errno < 0 || this.errorMessageList.length <= this.errno){
17                         s += ":Unknown\n";
18                 } else{
19                         s += ":" + this.errorMessageList[this.errno] + "\n";
20                 }
21                 if(this.infoArray){
22                         s += "  >" + this.infoArray.toString() + "\n";
23                 }
24                 return s;
25         },
26 }
27 // throw new WebCPU_Exception(2, [""]);
28
29 function WebCPU(){
30         //APIクラスインスタンス取得
31         this.API = new WebCPU_API();
32
33         //DOMオブジェクト連携
34         this.debugMessageText = null;
35         this.debugIntegerRegisterText = null;
36         this.debugPointerRegisterText = null;
37         //デバッグコンソール設定
38         this.debugMessageBuffer = "";
39         var that = this;
40         this.messageTimer = null;
41         
42         //メモリ
43         //メモリはラベルごとにページとして区切られ、それらの配列が一つのメモリとなる。
44         this.mainMemory = new WebCPU_Memory();
45         this.memoryPageCounter = 0;
46         this.memoryInstructionCounter = 0;
47         this.stopFlag = false;
48         
49         //レジスタ配列
50         this.registers = new Object;
51         this.registers.Integer = new Array(64);
52         
53         //初期化
54         this.reset();
55         
56         //命令リスト
57         this.instruction = new Array(0xFF + 1);
58         //命令テーブル初期化
59         for(var i = 0; i < this.instruction.length; i++){
60                 this.instruction[i] = WebCPU_Instruction_Undefined;
61         }
62         //
63         this.instruction[0x00] = WebCPU_Instruction_NOP;
64         this.instruction[0x01] = WebCPU_Instruction_LB;
65         this.instruction[0x02] = WebCPU_Instruction_LIMM;
66         this.instruction[0x03] = WebCPU_Instruction_PLIMM;
67         this.instruction[0x04] = WebCPU_Instruction_CND;
68         this.instruction[0x08] = WebCPU_Instruction_LMEM;
69         this.instruction[0x09] = WebCPU_Instruction_SMEM;
70         this.instruction[0x0E] = WebCPU_Instruction_PADD;
71         this.instruction[0x0F] = WebCPU_Instruction_PDIF;
72         //
73         this.instruction[0x10] = WebCPU_Instruction_TernaryOperation;
74         this.instruction[0x11] = WebCPU_Instruction_TernaryOperation;
75         this.instruction[0x12] = WebCPU_Instruction_TernaryOperation;
76         this.instruction[0x14] = WebCPU_Instruction_TernaryOperation;
77         this.instruction[0x15] = WebCPU_Instruction_TernaryOperation;
78         this.instruction[0x16] = WebCPU_Instruction_TernaryOperation;
79         this.instruction[0x18] = WebCPU_Instruction_TernaryOperation;
80         this.instruction[0x19] = WebCPU_Instruction_TernaryOperation;
81         this.instruction[0x1A] = WebCPU_Instruction_TernaryOperation;
82         this.instruction[0x1B] = WebCPU_Instruction_TernaryOperation;
83         //
84         this.instruction[0x1E] = WebCPU_Instruction_PCP;
85         //
86         this.instruction[0x20] = WebCPU_Instruction_TernaryOperation;
87         this.instruction[0x21] = WebCPU_Instruction_TernaryOperation;
88         this.instruction[0x22] = WebCPU_Instruction_TernaryOperation;
89         this.instruction[0x23] = WebCPU_Instruction_TernaryOperation;
90         this.instruction[0x24] = WebCPU_Instruction_TernaryOperation;
91         this.instruction[0x25] = WebCPU_Instruction_TernaryOperation;
92         this.instruction[0x26] = WebCPU_Instruction_TernaryOperation;
93         this.instruction[0x27] = WebCPU_Instruction_TernaryOperation;
94         //
95         this.instruction[0x28] = WebCPU_Instruction_TernaryOperation;
96         this.instruction[0x29] = WebCPU_Instruction_TernaryOperation;
97         this.instruction[0x2A] = WebCPU_Instruction_TernaryOperation;
98         this.instruction[0x2B] = WebCPU_Instruction_TernaryOperation;
99         this.instruction[0x2C] = WebCPU_Instruction_TernaryOperation;
100         this.instruction[0x2D] = WebCPU_Instruction_TernaryOperation;
101         //
102         this.instruction[0x32] = WebCPU_Instruction_MALLOC;
103         this.instruction[0x34] = WebCPU_Instruction_DATA;
104         //
105         this.instruction[0xFE] = WebCPU_Instruction_REMARK;
106         
107         this.message("<<< Initialized >>>\n");
108 }
109 WebCPU.prototype = {
110         loadBinaryText: function(binStr){
111                 //引数はフロントエンドコードのHex文字列も可能。(Not implemented.)
112                 //改行やスペースも含まれていてよい。
113                 //シグネチャも含まれていてよい
114                 binStr = replaceAll(binStr, " ", "");
115                 binStr = replaceAll(binStr, "\n", "");
116                 binStr = replaceAll(binStr, "\r", "");
117                 binStr = replaceAll(binStr, "\t", "");
118                 binStr = binStr.toUpperCase();
119                 if(binStr.substr(0, 4) == "05E1"){
120                         //シグネチャあり
121                         this.message("LoadBinaryText:OSECPU signature found.\n", 10);
122                         if(binStr.substr(4, 2) == "00"){
123                                 //BackEndCode
124                                 this.message("LoadBinaryText:This is BackEndCode.\n", 10);
125                                 binStr = binStr.substr(6);
126                         } else{
127                                 //FrontEndCode
128                                 this.message("LoadBinaryText:This is FrontEndCode.\n", 10);
129                                 binStr = binStr.substr(4);
130                                 this.loadFrontEndBinaryText(binStr);
131                                 return;
132                         }
133                 } else{
134                         this.message("LoadBinaryText:OSECPU signature NOT found.\n", 1);
135                 }
136                 this.loadBackEndBinaryText(binStr);
137         },
138         loadBackEndBinaryText: function(binStr){
139                 //引数はバックエンドコードのHex文字列表現でスペースなどの他の文字の混入は認められない。
140                 this.message("****LoadBackEndBinaryText****\n", 30);
141                 this.mainMemory.initMemory();
142                 this.memoryPageCounter = 0;
143                 this.memoryInstructionCounter = 0;
144                 
145                 try{
146                         for(var i = 0; i < binStr.length; ){
147                                 //命令解釈
148                                 var id = parseInt(binStr.substr(i, 2), 16);
149                                 i += 2;
150                                 var instr = new this.instruction[id](id);
151                                 instr.binOffset = (i >> 1) - 1;
152                                 var instrarglen = instr.loadArguments(binStr, i);
153                                 if(isNaN(parseInt(instrarglen))){
154                                         throw new WebCPU_Exception(1, ["Invalid instrarglen."]);
155                                 }
156                                 //instrarglenをバイト単位から文字列単位に変換し、さらに引数部分のみのサイズに補正する。
157                                 instrarglen = (instrarglen - 1) * 2;
158                                 //命令オペランド長チェック
159                                 if(instrarglen > binStr.length - i){
160                                         //オペランドの長さ分だけのバイナリがなかった、つまり不完全な状態で途切れている
161                                         throw new WebCPU_Exception(1, ["Invalid instrarglen."]);
162                                 }
163                                 i+= instrarglen;
164                                 
165                                 if(id == 0x01){
166                                         //ラベル命令だったのでメモリページを新たにする。
167                                         this.mainMemory.addMemoryPage(new WebCPU_MemoryPage());
168                                         this.memoryPageCounter++;
169                                         this.memoryInstructionCounter = 0;
170                                 }
171                                 
172                                 this.mainMemory.root[this.memoryPageCounter].addMemoryData(instr);
173                         }
174                 } catch(e){
175                         this.message("****LoadBackEndBinaryText Abort:\n", 1);
176                         if(e instanceof WebCPU_Exception){
177                                 this.message(e.getMessageString(), 1);
178                         } else{
179                                 throw e;
180                         }
181                         this.showDisassembledCode();
182                         this.mainMemory.initMemory();
183                         this.memoryPageCounter = 0;
184                         this.memoryInstructionCounter = 0;
185                 }
186                 this.showDisassembledCode();
187                 this.message("****LoadBackEndBinaryText End****\n", 30);
188                 
189                 this.memoryPageCounter = 0;
190                 this.memoryInstructionCounter = 0;
191         },
192         loadFrontEndBinaryText: function(binStr){
193                 //引数はフロントエンドコードのHex文字列表現でスペースなどの他の文字の混入は認められない。
194                 this.message("****LoadFrontEndBinaryText****\n", 40);
195                 this.mainMemory.initMemory();
196                 this.memoryPageCounter = 0;
197                 this.memoryInstructionCounter = 0;
198                 //フロントエンドコードデコーダーの読み込み
199                 this.loadBinaryText(decoderBinaryString);
200                 //変換準備
201                 var backendMaxSize = 65535;
202                 var temp0MaxSize = 2 * 1024 * 1024;
203                 var temp1MaxSize = 16 * 1024;
204                 var temp2MaxSize = 64;
205                 var temp3MaxSize = 4 * 1024 + 1;
206                 var temp4MaxSize = 256;
207                 var m;
208                 //P02 = T_UINT8:  &backend[2] (出力バッファ先頭)
209                 m = this.mainMemory.allocateMemoryPage(WebCPU.pType.UINT8, backendMaxSize);
210                 this.registers.Pointer[0x02] = new WebCPU_Pointer(m);
211                 //P03 = T_UINT8:  &backend[backend-maxsize] (出力バッファの限界)
212                 this.registers.Pointer[0x03] = this.registers.Pointer[0x02].getCopy();
213                 this.registers.Pointer[0x03].addressOffset = backendMaxSize;
214                 //P04 = T_UINT8:  &frontend[2] (入力データ先頭)
215                 m = this.mainMemory.allocateMemoryPage(WebCPU.pType.UINT8);
216                 this.registers.Pointer[0x04] = new WebCPU_Pointer(m);
217                 this.registers.Pointer[0x04].addressOffset = 0;
218                 this.registers.Pointer[0x04].memoryPage.data[1].data = new Array();
219                 var a = this.registers.Pointer[0x04].memoryPage.data[1].data;
220                 var i;
221                 for(i = 0; i * 2 < binStr.length; i++){
222                         a.push(parseInt(binStr.substr(i * 2, 2), 16));
223                 }
224                 //P05 = T_UINT8:  &frontend[frontend-size] (入力データの終端:最終バイトの次のアドレス)
225                 this.registers.Pointer[0x05] = this.registers.Pointer[0x04].getCopy();
226                 this.registers.Pointer[0x05].addressOffset = i;
227                 //P06 = T_UINT8:  &temp0[0] (要素数が2M以上のテンポラリバッファ)
228                 m = this.mainMemory.allocateMemoryPage(WebCPU.pType.UINT8, temp0MaxSize);
229                 this.registers.Pointer[0x06] = new WebCPU_Pointer(m);
230                 //P07 = T_UINT8:  &temp0[temp-maxsize]
231                 this.registers.Pointer[0x07] = this.registers.Pointer[0x06].getCopy();
232                 this.registers.Pointer[0x07].addressOffset = temp0MaxSize;
233                 //P0A = T_UINT32: &temp1[0] (要素数が16Kくらいあれば十分なバッファ)
234                 m = this.mainMemory.allocateMemoryPage(WebCPU.pType.UINT32, temp1MaxSize);
235                 this.registers.Pointer[0x0A] = new WebCPU_Pointer(m);
236                 //P0B = T_SINT32: &temp2[0] (要素数が64のバッファ:Pxxレジスタの個数)
237                 m = this.mainMemory.allocateMemoryPage(WebCPU.pType.SINT32, temp2MaxSize);
238                 this.registers.Pointer[0x0B] = new WebCPU_Pointer(m);
239                 //P0C = T_SINT32: &temp3[0] (要素数が4Kのバッファ:登録可能ラベル数)
240                 m = this.mainMemory.allocateMemoryPage(WebCPU.pType.SINT32, temp3MaxSize);
241                 this.registers.Pointer[0x0C] = new WebCPU_Pointer(m);
242                 //P0D = T_UINT8:  &temp4[0] (要素数が256のバッファ)
243                 m = this.mainMemory.allocateMemoryPage(WebCPU.pType.UINT8, temp4MaxSize);
244                 this.registers.Pointer[0x0D] = new WebCPU_Pointer(m);
245                 //変換
246                 this.execute();
247                 /*
248                 P02 == バックエンドコードの終端, つまり P02 - &backend[0] = バックエンドコードのサイズ
249                 */
250                 if(this.registers.Integer[0x00] == 0){
251                         //R00 == 0 正常終了
252                         var binData = this.registers.Pointer[0x02].memoryPage.data[1];
253                         var binStr = "";
254                         for(var i = 0; i < this.registers.Pointer[0x02].addressOffset; i++){
255                                 binStr += ("00" + binData.data[i].toString(16)).slice(-2);
256                         }
257                         this.message("[" + binStr + "]\n");
258                         this.loadBackEndBinaryText(binStr);
259                         this.reset();
260                 } else{
261                         //R00 != 0 変換失敗
262                         this.message("loadFrontEndBinaryText: Translate failed.\n");
263                 }
264                 
265                 this.message("****LoadFrontEndBinaryText End****\n", 40);
266         },
267         executeStepIn: function(){
268                 //ステップ実行する。
269                 //一回実行するたびに再描画する。
270                 var retv = this.executeStepIn_Internal(true);
271                 this.API.API_flushWin(this, this.API.mainWindowCanvas.width, this.API.mainWindowCanvas.height, 0, 0);
272                 return retv;
273         },
274         executeStepIn_Internal: function(isManualStepIn){
275                 //ステップ実行の内部部分。
276                 //終端到達時は1を、まだ後続命令がある場合は0を返す。
277                 //終了時にのみ再描画を行う
278                 if(this.stopFlag){
279                         this.message(">stepIn:Break.\n", 2);
280                         this.stopFlag = false;
281                         this.API.API_flushWin(this, this.API.mainWindowCanvas.width, this.API.mainWindowCanvas.height, 0, 0);
282                         return 2;
283                 }
284                 var instr = this.fetchMemoryNext();
285                 if(instr === undefined){
286                         this.message(">stepIn:control reached end of binary.\n", 2);
287                         this.API.API_flushWin(this, this.API.mainWindowCanvas.width, this.API.mainWindowCanvas.height, 0, 0);
288                         return 1;
289                 }
290                 if(isManualStepIn){
291                         this.message(">stepIn:" + this.memoryPageCounter + "-" + (this.memoryInstructionCounter - 1) + ":" + instr.toString() + "\n", 20);
292                 }
293                 instr.execute(this);
294                 //これ以降this.memoryInstructionCounterが今実行した命令を指すとは限らない。(JMP系命令のため)
295                 /*
296                 //ブレークポイント
297                 if(this.memoryPageCounter == 233 && this.memoryInstructionCounter == 0){
298                         this.message(">stepIn:Breakpoint.\n", 2);
299                         return 3;
300                 }
301                 */
302                 return 0;
303         },
304         execute: function(){
305                 //最速で実行する
306                 for(;;){
307                         if(this.executeStepIn_Internal(false) != 0){
308                                 return;
309                         }
310                 }
311         },
312         reset: function(){
313                 //実行環境をリセットする。メモリ内容は保持される。
314                 for(var i = 0; i < this.registers.Integer.length; i++){
315                         this.registers.Integer[i] = 0;
316                 }
317                 this.registers.Pointer = new Array(64);
318                 for(var i = 0; i < this.registers.Pointer.length; i++){
319                         this.registers.Pointer[i] = new WebCPU_Pointer(null);
320                 }
321                 //Set P28 for API  calling.
322                 this.registers.Pointer[0x28].memoryType = 0xC0FFEE;
323                 //
324                 this.memoryPageCounter = 0;
325                 this.memoryInstructionCounter = 0;
326                 this.stopFlag = false;
327                 //
328                 this.message("<<< Reset >>>\n");
329         },
330         fetchMemoryNext: function(){
331                 if(this.mainMemory.root[this.memoryPageCounter].data.length <= this.memoryInstructionCounter){
332                         this.memoryPageCounter++;
333                         if(this.mainMemory.root.length <= this.memoryPageCounter){
334                                 this.memoryPageCounter--;
335                                 return undefined;
336                         }
337                         this.memoryInstructionCounter -= this.mainMemory.root[this.memoryPageCounter - 1].data.length;
338                 }
339                 var retv = this.mainMemory.root[this.memoryPageCounter].data[this.memoryInstructionCounter];
340                 this.memoryInstructionCounter++;
341                 return retv;
342         },
343         setMainWindowCanvasDOMObject: function(id){
344                 this.API.setMainWindowCanvasDOMObject(document.getElementById(id));
345         },
346         setDebugMessageDOMObject: function(name){
347                 this.debugMessageText = document.getElementsByName(name)[0];
348                 this.setDebugTimer();
349         },
350         setDebugIntegerRegisterDOMObject: function(name){
351                 this.debugIntegerRegisterText = document.getElementsByName(name)[0];
352                 this.setDebugTimer();
353         },
354         setDebugPointerRegisterDOMObject: function(name){
355                 this.debugPointerRegisterText = document.getElementsByName(name)[0];
356                 this.setDebugTimer();
357         },
358         setDebugTimer: function(){
359                 if(!this.debugMessageText && !this.debugIntegerRegisterText && !this.debugPointerRegisterText){
360                         //すべて無効だったらタイマーの動作自体を止める
361                         window.clearTimeout(this.messageTimer);
362                         this.messageTimer = null;
363                         WebCPU_Instruction.prototype.isEnabledPrintSourceRegister = false;
364                         WebCPU_Instruction.prototype.isEnabledPrintDestinationRegister = false;
365                 } else if(!this.messageTimer){
366                         //どれかが有効でかつタイマーが止まっていたらスタートさせる
367                         var that = this;
368                         this.messageTimer = window.setInterval(function(){that.debugShowTick();}, 50);
369                         WebCPU_Instruction.prototype.isEnabledPrintSourceRegister = true;
370                         WebCPU_Instruction.prototype.isEnabledPrintDestinationRegister = true;
371                 }
372         },
373         debugShowTick: function(){
374                 if(this.debugMessageText && this.debugMessageBuffer != ""){
375                         var str = this.debugMessageText.innerHTML + this.debugMessageBuffer;
376                         this.debugMessageBuffer = "";
377                         if(str.length > WebCPU.maxDebugStringLength){
378                                 str = str.slice(str.length - (WebCPU.maxDebugStringLength >> 1));
379                         }
380                         this.debugMessageText.innerHTML = str;
381                         this.debugMessageText.scrollTop = this.debugMessageText.scrollHeight;
382                 }
383                 this.refreshDebugIntegerRegisterText();
384                 this.refreshDebugPointerRegisterText();
385         },
386         message: function(str, id){
387                 //id:メッセージの種類
388                 //省略:常に表示する
389                 //1:Error
390                 //2:Warning
391                 //10:バイナリ読み込みデバッグ
392                 //20:実行時詳細情報
393                 //30:バックエンドバイナリ読み込みデバッグ
394                 //40:フロントエンドバイナリ読み込みデバッグ
395                 if(this.debugMessageText != null){
396                         if(
397                                 true ||
398                                 id == 1 || 
399                                 id == 2 || 
400                                 id == 30
401                         ){
402                                 this.debugMessageBuffer += str;
403                         }
404                 } else if(id == 1){
405                         //エラーのときmessageが無効であればalertで表示する。
406                         window.alert(str);
407                 }
408         },
409         showDisassembledCode: function(){
410                 for(var i = 0; i < this.mainMemory.root.length; i++){
411                         for(var j = 0; j < this.mainMemory.root[i].data.length; j++){
412                                 var instr = this.mainMemory.root[i].data[j];
413                                 this.message("+0x" + instr.binOffset.toString(16).toUpperCase() + ":" + i + "-" + j + ":" + instr.toString() + "\n", 30);
414                         }
415                         this.message(" - - - - \n", 30);
416                 }
417         },
418         refreshDebugIntegerRegisterText: function(){
419                 if(this.debugIntegerRegisterText != null){
420                         this.debugIntegerRegisterText.innerHTML = "";
421                         for(var i = 0; i < this.registers.Integer.length; i++){
422                                 this.debugIntegerRegisterText.innerHTML += "R" +  ("00" + i.toString(16)).slice(-2).toUpperCase() + ":0x" + this.registers.Integer[i].toString(16).toUpperCase() + "\n";
423                         }
424                 }
425         },
426         refreshDebugPointerRegisterText: function(){
427                 if(this.debugPointerRegisterText != null){
428                         this.debugPointerRegisterText.innerHTML = "";
429                         for(var i = 0; i < this.registers.Pointer.length; i++){
430                                 if(this.registers.Pointer[i]){
431                                         this.debugPointerRegisterText.innerHTML += "P" +  ("00" + i.toString(16)).slice(-2).toUpperCase() + ":" + this.registers.Pointer[i].toString() + "\n";
432                                 } else{
433                                         this.debugPointerRegisterText.innerHTML += "P" +  ("00" + i.toString(16)).slice(-2).toUpperCase() + ":(null)\n";
434                                 }
435                         }
436                 }
437         },
438         goToPointerRegister: function(reg0P){
439                 //レジスタはいじらない
440                 //goto
441                 var p = this.registers.Pointer[reg0P];
442                 if(p.memoryType == 1){
443                         //VPtr
444                         this.memoryPageCounter = this.mainMemory.getMemoryPageCountFromMemoryPageInstance(p.memoryPage);
445                         if(this.memoryPageCounter !== undefined){
446                                 this.memoryInstructionCounter = 0;
447                                 this.message("JMP:page " + this.memoryPageCounter + "\n", 20);
448                         } else{
449                                 throw new WebCPU_Exception(2, ["memoryPage not found in mainMemory."]);
450                         }
451                 } else{
452                         throw new WebCPU_Exception(2, ["Can't goto Memory page type is not VPtr."]);
453                 }
454         },
455         createBackendBinaryString: function(){
456                 var s = "05E100";
457                 var instr;
458                 
459                 this.reset();
460                 for(;;){
461                         instr = this.fetchMemoryNext();
462                         if(instr === undefined){
463                                 break;
464                         }
465                         s += instr.createBinaryString(this);
466                 }
467                 return s;
468         },
469         staticOptimize: function(){
470                 //静的最適化
471                 //連続するラベル命令の削除
472                 //一つのメモリページにラベル命令のみがある場合は、それを次のメモリページのラベル名に置換する
473                 var mpage;
474                 var removePageIndexStack = new Array();
475                 var labelIDStack = new Array();
476                 var labelID;
477                 var newLabelID;
478                 for(var i = 0; i < this.mainMemory.root.length; i++){
479                         mpage = this.mainMemory.root[i];
480                         if(mpage instanceof WebCPU_MemoryPage && mpage.data[0] instanceof WebCPU_Instruction_LB){
481                                 //メモリページ
482                                 if(mpage.data.length == 1){
483                                         //ラベルしかないので削除候補に追加
484                                         labelIDStack.push(mpage.data[0].imm32);
485                                         removePageIndexStack.push(i);
486                                 } else{
487                                         //これは必要なラベル命令
488                                         if(labelIDStack.length != 0){
489                                                 for(;;){
490                                                         labelID = labelIDStack.pop();
491                                                         if(labelID == undefined){
492                                                                 break;
493                                                         }
494                                                         this.mainMemory.root.splice(removePageIndexStack[0], 1);
495                                                         i--;
496                                                         this.staticOptimize_ReplaceLabelNumber(labelID, mpage.data[0].imm32);
497                                                 }
498                                                 removePageIndexStack = new Array();
499                                         }
500                                 }
501                         }
502                 }
503                 if(labelIDStack.length != 0){
504                         //プログラム末尾のラベル命令は削除しないようにする
505                         newLabelID = labelIDStack.pop();
506                         for(;;){
507                                 labelID = labelIDStack.pop();
508                                 if(labelID == undefined){
509                                         break;
510                                 }
511                                 this.mainMemory.root.splice(removePageIndexStack[0], 1);
512                                 i--;
513                                 this.staticOptimize_ReplaceLabelNumber(labelID, newLabelID);
514                         }
515                 }
516         },
517         staticOptimize_ReplaceLabelNumber: function(from, to){
518                 var mpage;
519                 var instr;
520                 for(var i = 0, iLen = this.mainMemory.root.length; i < iLen; i++){
521                         mpage = this.mainMemory.root[i];
522                         for(var j = 0, jLen = mpage.data.length; j < jLen; j++){
523                                 instr = mpage.data[j];
524                                 if(instr instanceof WebCPU_Instruction_PLIMM){
525                                         if(instr.imm32 == from){
526                                                 instr.imm32 = to;
527                                         }
528                                 }
529                         }
530                 }
531         }
532 }
533
534 //数値計算
535 function parseSignedInt32(hexStr){
536         //文字列を16進32bit符号あり整数として変換する。
537         var i = parseInt(hexStr, 16);
538         if(i > 0x7fffffff){
539                 //-
540                 return -(~i + 1);
541         }
542         //+
543         return i;
544 }
545
546 function parseSignedInt(hexStr, bits){
547         //文字列を16進符号あり整数として変換する。
548         //32bitまで対応
549         var i = parseInt(hexStr, 16);
550         if(i >= (1 << (bits - 1))){
551                 //-
552                 return -(((0xffffffff >>> (32 - bits)) - i) + 1);
553         }
554         //+
555         return i;
556 }
557
558 function toHexString8(v){
559         return ("00" + v.toString(16).toUpperCase()).slice(-2);
560 }
561
562 function toHexString32(v){
563         if(v < 0){
564                 v = 0x100000000 + v;
565         }
566         return ("00000000" + v.toString(16).toUpperCase()).slice(-8);
567 }
568
569 function replaceAll(str, org, dest){
570         //文字列str中にある文字列orgを文字列destにすべて置換する。
571         //http://www.syboos.jp/webjs/doc/string-replace-and-replaceall.html
572         return str.split(org).join(dest);
573 }