OSDN Git Service

webcpuの高速化と描画処理の実装変更(直接bmpに描画するようになった。)
[chnosproject/AI004.git] / webcpu / instrbas.js
1 //
2 // Instruction baseclass
3 //
4
5 function WebCPU_Instruction(instrID){
6         //命令クラス共通部分
7         //バックエンドバイナリでの命令先頭バイトのオフセット
8         this.binOffset = 0;
9 }
10 WebCPU_Instruction.prototype = {
11         // loadArguments, execute, toStringが必須。
12         loadArguments: function(argBinStr, baseIndex){
13                 //戻り値は、読み込み成功時はその命令の占めるバイト数、失敗時はエラー文字列を返す。
14                 //常に読み込みエラー
15                 return this.toString();
16         },
17         setParameter: function(){
18         
19         },
20         execute: function(env){
21                 //printXXXはデバッグ用
22                 if(this.isEnabledPrintSourceRegister && this.printSourceRegister){
23                         this.printSourceRegister(env);
24                 }
25                 this.instruction(env);
26                 if(this.isEnabledPrintDestinationRegister && this.printDestinationRegister){
27                         this.printDestinationRegister(env);
28                 }
29         },
30         instruction: function(env){
31                 //envはCPUのインスタンス
32                 throw new WebCPU_Exception(0, ["Not implemented:" + this.toString()]);
33         },
34         createBinaryString: function(env){
35                 //envはCPUのインスタンス
36                 throw new WebCPU_Exception(0, ["Not implemented:" + this.toString()]);
37         },
38         toString: function(){
39                 return "Undefined()[0x" + this.instrID.toString(16).toUpperCase() + "];";
40         },
41         //
42         makeUnaryOperandString: function(mnemonic, typestr0, arg0){
43                 return mnemonic + "(" + typestr0 + arg0.toString(16).toUpperCase() + ");";
44         },
45         makeBinaryOperandString: function(mnemonic, typestr0, arg0, typestr1, arg1){
46                 return mnemonic + "(" + typestr0 + arg0.toString(16).toUpperCase() + ", " + typestr1 + arg1.toString(16).toUpperCase() + ");";
47         },
48         makeTernaryOperandString: function(mnemonic, typestr0, arg0, typestr1, arg1, typestr2, arg2){
49                 return mnemonic + "(" + typestr0 + arg0.toString(16).toUpperCase() + ", " + typestr1 + arg1.toString(16).toUpperCase() + ", " + typestr2 + arg2.toString(16).toUpperCase() + ");";
50         },
51         makeQuaternaryOperandString: function(mnemonic, typestr0, arg0, typestr1, arg1, typestr2, arg2, typestr3, arg3){
52                 return mnemonic + "(" + typestr0 + arg0.toString(16).toUpperCase() + ", " + typestr1 + arg1.toString(16).toUpperCase() + ", " + typestr2 + arg2.toString(16).toUpperCase() + ", " + typestr3 + arg3.toString(16).toUpperCase() + ");";
53         },
54         //
55         makeRRegString: function(env, reg){
56                 return "R" + reg.toString(16).toUpperCase() + ":0x" +  env.registers.Integer[reg].toString(16).toUpperCase();
57         },
58         makePRegString: function(env, reg){
59                 return "P" + reg.toString(16).toUpperCase() + ":0x" + env.registers.Pointer[reg].addressOffset.toString(16).toUpperCase();
60         },
61         printRReg: function(env, reg){
62                 env.message(this.makeRRegString(env, reg) + "\n");
63         },
64         printPReg: function(env, reg){
65                 env.message(this.makePRegString(env, reg) + "\n");
66         },
67         //
68         fetchUnsignedInteger: function(argBinStr, baseIndex, offset, bytes){
69                 return parseInt(argBinStr.substr(baseIndex + offset * 2, bytes * 2), 16);
70         },
71         fetchSignedInteger: function(argBinStr, baseIndex, offset, bytes){
72                 return parseSignedInt32(argBinStr.substr(baseIndex + offset * 2, bytes * 2), 16);
73         },
74         //
75         isEnabledPrintSourceRegister: true,
76         isEnabledPrintDestinationRegister: true,
77         printSourceRegister: null,
78         printDestinationRegister: null,
79 }
80
81 var WebCPU_Instruction_MEM_Base = function(instrID){
82         //メモリ関連命令共通部分
83         this.reg0R = 0;
84         this.typ32 = 0;
85         this.reg1P = 0;
86         this.reserved = 0;
87 }.extend(WebCPU_Instruction, {
88         loadArguments: function(argBinStr, baseIndex){
89                 this.setParameter(
90                         this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
91                         this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 4),
92                         this.fetchUnsignedInteger(argBinStr, baseIndex, 5, 1),
93                         this.fetchUnsignedInteger(argBinStr, baseIndex, 6, 1)
94                 );
95                 return 8;
96         },
97         setParameter: function(regR, pType, regP, reserved){
98                 this.reg0R = regR;
99                 this.typ32 = pType;
100                 this.reg1P = regP;
101                 this.reserved = reserved;
102         },
103 });
104
105 var WebCPU_Instruction_TernaryOperation = function(instrID){
106         //単純代入命令
107         //三項演算命令
108         //整数比較命令
109         //演算結果はすべて符号ありであることに注意
110         this.instrID = instrID;
111         this.reg0 = 0;
112         this.reg1 = 0;
113         this.reg2 = 0;
114         this.subfunc = null;
115 }.extend(WebCPU_Instruction, {
116         mnemonicList1: [
117                 "OR",
118                 "XOR",
119                 "AND",
120                 "UD",
121                 "ADD",
122                 "SUB",
123                 "MUL",
124                 "UD",
125                 "SHL",
126                 "SAR",
127                 "DIV",
128                 "MOD",
129         ],
130         mnemonicList2: [
131                 "CMPE",
132                 "CMPNE",
133                 "CMPL",
134                 "CMPGE",
135                 "CMPLE",
136                 "CMPG",
137                 "TSTZ",
138                 "TSTNZ",
139         ],
140         loadArguments: function(argBinStr, baseIndex){
141                 this.setParameter(
142                         this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
143                         this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 1),
144                         this.fetchUnsignedInteger(argBinStr, baseIndex, 2, 1)
145                 );
146                 if(this.instruction == WebCPU_Instruction_TernaryOperation.base.prototype.instruction){
147                         return 1;
148                 }
149                 return 4;
150         },
151         setParameter: function(destReg, srcReg0, srcReg1){
152                 if(this.instrID === undefined){
153                         throw "setParameter:instrID undefined";
154                 }
155                 this.reg0 = destReg;
156                 this.reg1 = srcReg0;
157                 this.reg2 = srcReg1;
158                 if(this.instrID == 0x10){
159                         if(srcReg1 == 0xFF){
160                                 //CP
161                                 this.mnemonic = "CP";
162                                 this.instruction = this.instrCP;
163                                 this.printSourceRegister = this.printSourceRegisterCP;
164                         } else{
165                                 //OR
166                                 this.mnemonic = this.mnemonicList1[0];
167                                 this.instruction = this.instrOR;
168                         }
169                 } else if(0x11 <= this.instrID && this.instrID <= 0x1B){
170                         // list1
171                         this.mnemonic = this.mnemonicList1[this.instrID - 0x10];
172                         this.instruction = eval("this.instr" + this.mnemonic);
173                 } else if(0x20 <= this.instrID && this.instrID <= 0x27){
174                         //list2
175                         this.mnemonic = this.mnemonicList2[this.instrID - 0x20];
176                         this.instruction = eval("this.instr" + this.mnemonic);
177                 } else if(0x28 <= this.instrID && this.instrID <= 0x2D){
178                         //list2P
179                         this.mnemonic = "P" + this.mnemonicList2[this.instrID - 0x28];
180                         this.instruction = this.instrP;
181                         this.subfunc = eval("this.instr" + this.mnemonic);
182                         this.printSourceRegister = this.printSourceRegisterP;
183                 }
184         },
185         //
186         instrCP: function(env){
187                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1];
188         },
189         instrOR: function(env){
190                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] | env.registers.Integer[this.reg2];
191         },
192         instrXOR: function(env){
193                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] ^ env.registers.Integer[this.reg2];
194         },
195         instrAND: function(env){
196                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2];
197         },
198         instrADD: function(env){
199                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] + env.registers.Integer[this.reg2];
200         },
201         instrSUB: function(env){
202                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] - env.registers.Integer[this.reg2];
203         },
204         instrMUL: function(env){
205                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] * env.registers.Integer[this.reg2];
206         },
207         instrSHL: function(env){
208                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] << env.registers.Integer[this.reg2];
209         },
210         instrSAR: function(env){
211                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] >> env.registers.Integer[this.reg2];
212         },
213         instrDIV: function(env){
214                 env.registers.Integer[this.reg0] = parseInt(env.registers.Integer[this.reg1] / env.registers.Integer[this.reg2]);
215         },
216         instrMOD: function(env){
217                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] % env.registers.Integer[this.reg2];
218         },
219         //
220         instrCMPE: function(env){
221                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] == env.registers.Integer[this.reg2]) ? -1 : 0;
222         },
223         instrCMPNE: function(env){
224                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] != env.registers.Integer[this.reg2]) ? -1 : 0;
225         },
226         instrCMPL: function(env){
227                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] < env.registers.Integer[this.reg2]) ? -1 : 0;
228         },
229         instrCMPGE: function(env){
230                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] >= env.registers.Integer[this.reg2]) ? -1 : 0;
231         },
232         instrCMPLE: function(env){
233                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] <= env.registers.Integer[this.reg2]) ? -1 : 0;
234         },
235         instrCMPG: function(env){
236                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] > env.registers.Integer[this.reg2]) ? -1 : 0;
237         },
238         instrTSTZ: function(env){
239                 env.registers.Integer[this.reg0] = ((env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2]) == 0) ? -1 : 0;
240         },
241         instrTSTNZ: function(env){
242                 env.registers.Integer[this.reg0] = ((env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2]) != 0) ? -1 : 0;
243         },
244         //
245         instrP: function(env){
246                 if(env.registers.Pointer[this.reg1].verifySameMemoryPageAs(env.registers.Pointer[this.reg2])){
247                         this.subfunc(env);
248                 } else{
249                         throw new WebCPU_Exception(2, ["Attempt to compare pointers in different memoyPage."]);
250                 }
251         },
252         //
253         instrPCMPE: function(env){
254                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset == env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
255         },
256         instrPCMPNE: function(env){
257                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset != env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
258         },
259         instrPCMPL: function(env){
260                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset < env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
261         },
262         instrPCMPGE: function(env){
263                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset >= env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
264         },
265         instrPCMPLE: function(env){
266                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset <= env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
267         },
268         instrPCMPG: function(env){
269                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset > env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
270         },
271         //
272         createBinaryString: function(env){
273                 return toHexString8(this.instrID) + toHexString8(this.reg0) + toHexString8(this.reg1) + toHexString8(this.reg2);
274         },
275         toString: function(){
276                 if(this.mnemonic == "CP"){
277                         return this.makeBinaryOperandString("CP", "R", this.reg0, "R", this.reg1);
278                 }
279                 if(this.mnemonic == "UD"){
280                         return "Undefined();";
281                 }
282                 if(0x28 <= this.instrID && this.instrID <= 0x2D){
283                         return this.makeTernaryOperandString(this.mnemonic, "R", this.reg0, "P", this.reg1, "P", this.reg2);
284                 }
285                 return this.makeTernaryOperandString(this.mnemonic, "R", this.reg0, "R", this.reg1, "R", this.reg2);
286         },
287         //
288         printSourceRegister: function(env){
289                 this.printRReg(env, this.reg1);
290                 this.printRReg(env, this.reg2);
291         },
292         printSourceRegisterP: function(env){
293                 this.printPReg(env, this.reg1);
294                 this.printPReg(env, this.reg2);
295         },
296         printSourceRegisterCP: function(env){
297                 this.printPReg(env, this.reg1);
298         },
299         printDestinationRegister: function(env){
300                 this.printRReg(env, this.reg0);
301         },
302 });