OSDN Git Service

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