2 // Instruction baseclass
5 function WebCPU_Instruction(instrID){
7 //バックエンドバイナリでの命令先頭バイトのオフセット
10 WebCPU_Instruction.prototype = {
11 // loadArguments, execute, toStringが必須。
12 loadArguments: function(argBinStr, baseIndex){
13 //戻り値は、読み込み成功時はその命令の占めるバイト数、失敗時はエラー文字列を返す。
15 return this.toString();
17 setParameter: function(){
20 execute: function(env){
22 if(this.printSourceRegister){
23 this.printSourceRegister(env);
25 this.instruction(env);
26 if(this.printDestinationRegister){
27 this.printDestinationRegister(env);
30 instruction: function(env){
32 throw new WebCPU_Exception(0, ["Not implemented:" + this.toString()]);
34 createBinaryString: function(env){
36 throw new WebCPU_Exception(0, ["Not implemented:" + this.toString()]);
39 return "Undefined()[0x" + this.instrID.toString(16).toUpperCase() + "];";
42 makeUnaryOperandString: function(mnemonic, typestr0, arg0){
43 return mnemonic + "(" + typestr0 + arg0.toString(16).toUpperCase() + ");";
45 makeBinaryOperandString: function(mnemonic, typestr0, arg0, typestr1, arg1){
46 return mnemonic + "(" + typestr0 + arg0.toString(16).toUpperCase() + ", " + typestr1 + arg1.toString(16).toUpperCase() + ");";
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() + ");";
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() + ");";
55 makeRRegString: function(env, reg){
56 return "R" + reg.toString(16).toUpperCase() + ":0x" + env.registers.Integer[reg].toString(16).toUpperCase();
58 makePRegString: function(env, reg){
59 return "P" + reg.toString(16).toUpperCase() + ":0x" + env.registers.Pointer[reg].addressOffset.toString(16).toUpperCase();
61 printRReg: function(env, reg){
62 env.message(this.makeRRegString(env, reg) + "\n");
64 printPReg: function(env, reg){
65 env.message(this.makePRegString(env, reg) + "\n");
68 fetchUnsignedInteger: function(argBinStr, baseIndex, offset, bytes){
69 return parseInt(argBinStr.substr(baseIndex + offset * 2, bytes * 2), 16);
71 fetchSignedInteger: function(argBinStr, baseIndex, offset, bytes){
72 return parseSignedInt32(argBinStr.substr(baseIndex + offset * 2, bytes * 2), 16);
75 printSourceRegister: null,
76 printDestinationRegister: null,
79 var WebCPU_Instruction_MEM_Base = function(instrID){
85 }.extend(WebCPU_Instruction, {
86 loadArguments: function(argBinStr, baseIndex){
88 this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
89 this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 4),
90 this.fetchUnsignedInteger(argBinStr, baseIndex, 5, 1),
91 this.fetchUnsignedInteger(argBinStr, baseIndex, 6, 1)
95 setParameter: function(regR, pType, regP, reserved){
99 this.reserved = reserved;
103 var WebCPU_Instruction_TernaryOperation = function(instrID){
107 //演算結果はすべて符号ありであることに注意
108 this.instrID = instrID;
113 }.extend(WebCPU_Instruction, {
138 loadArguments: function(argBinStr, baseIndex){
140 this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
141 this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 1),
142 this.fetchUnsignedInteger(argBinStr, baseIndex, 2, 1)
144 if(this.instruction == WebCPU_Instruction_TernaryOperation.base.prototype.instruction){
149 setParameter: function(destReg, srcReg0, srcReg1){
150 if(this.instrID === undefined){
151 throw "setParameter:instrID undefined";
156 if(this.instrID == 0x10){
159 this.mnemonic = "CP";
160 this.instruction = this.instrCP;
161 this.printSourceRegister = this.printSourceRegisterCP;
164 this.mnemonic = this.mnemonicList1[0];
165 this.instruction = this.instrOR;
167 } else if(0x11 <= this.instrID && this.instrID <= 0x1B){
169 this.mnemonic = this.mnemonicList1[this.instrID - 0x10];
170 this.instruction = eval("this.instr" + this.mnemonic);
171 } else if(0x20 <= this.instrID && this.instrID <= 0x27){
173 this.mnemonic = this.mnemonicList2[this.instrID - 0x20];
174 this.instruction = eval("this.instr" + this.mnemonic);
175 } else if(0x28 <= this.instrID && this.instrID <= 0x2D){
177 this.mnemonic = "P" + this.mnemonicList2[this.instrID - 0x28];
178 this.instruction = this.instrP;
179 this.subfunc = eval("this.instr" + this.mnemonic);
180 this.printSourceRegister = this.printSourceRegisterP;
184 instrCP: function(env){
185 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1];
187 instrOR: function(env){
188 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] | env.registers.Integer[this.reg2];
190 instrXOR: function(env){
191 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] ^ env.registers.Integer[this.reg2];
193 instrAND: function(env){
194 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2];
196 instrADD: function(env){
197 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] + env.registers.Integer[this.reg2];
199 instrSUB: function(env){
200 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] - env.registers.Integer[this.reg2];
202 instrMUL: function(env){
203 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] * env.registers.Integer[this.reg2];
205 instrSHL: function(env){
206 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] << env.registers.Integer[this.reg2];
208 instrSAR: function(env){
209 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] >> env.registers.Integer[this.reg2];
211 instrDIV: function(env){
212 env.registers.Integer[this.reg0] = parseInt(env.registers.Integer[this.reg1] / env.registers.Integer[this.reg2]);
214 instrMOD: function(env){
215 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] % env.registers.Integer[this.reg2];
218 instrCMPE: function(env){
219 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] == env.registers.Integer[this.reg2]) ? -1 : 0;
221 instrCMPNE: function(env){
222 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] != env.registers.Integer[this.reg2]) ? -1 : 0;
224 instrCMPL: function(env){
225 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] < env.registers.Integer[this.reg2]) ? -1 : 0;
227 instrCMPGE: function(env){
228 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] >= env.registers.Integer[this.reg2]) ? -1 : 0;
230 instrCMPLE: function(env){
231 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] <= env.registers.Integer[this.reg2]) ? -1 : 0;
233 instrCMPG: function(env){
234 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] > env.registers.Integer[this.reg2]) ? -1 : 0;
236 instrTSTZ: function(env){
237 env.registers.Integer[this.reg0] = ((env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2]) == 0) ? -1 : 0;
239 instrTSTNZ: function(env){
240 env.registers.Integer[this.reg0] = ((env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2]) != 0) ? -1 : 0;
243 instrP: function(env){
244 if(env.registers.Pointer[this.reg1].verifySameMemoryPageAs(env.registers.Pointer[this.reg2])){
247 throw new WebCPU_Exception(2, ["Attempt to compare pointers in different memoyPage."]);
251 instrPCMPE: function(env){
252 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset == env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
254 instrPCMPNE: function(env){
255 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset != env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
257 instrPCMPL: function(env){
258 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset < env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
260 instrPCMPGE: function(env){
261 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset >= env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
263 instrPCMPLE: function(env){
264 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset <= env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
266 instrPCMPG: function(env){
267 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset > env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
270 createBinaryString: function(env){
271 return toHexString8(this.instrID) + toHexString8(this.reg0) + toHexString8(this.reg1) + toHexString8(this.reg2);
273 toString: function(){
274 if(this.mnemonic == "CP"){
275 return this.makeBinaryOperandString("CP", "R", this.reg0, "R", this.reg1);
277 if(this.mnemonic == "UD"){
278 return "Undefined();";
280 if(0x28 <= this.instrID && this.instrID <= 0x2D){
281 return this.makeTernaryOperandString(this.mnemonic, "R", this.reg0, "P", this.reg1, "P", this.reg2);
283 return this.makeTernaryOperandString(this.mnemonic, "R", this.reg0, "R", this.reg1, "R", this.reg2);
286 printSourceRegister: function(env){
287 this.printRReg(env, this.reg1);
288 this.printRReg(env, this.reg2);
290 printSourceRegisterP: function(env){
291 this.printPReg(env, this.reg1);
292 this.printPReg(env, this.reg2);
294 printSourceRegisterCP: function(env){
295 this.printPReg(env, this.reg1);
297 printDestinationRegister: function(env){
298 this.printRReg(env, this.reg0);