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.isEnabledPrintSourceRegister && this.printSourceRegister){
23 this.printSourceRegister(env);
25 this.instruction(env);
26 if(this.isEnabledPrintDestinationRegister && 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 isEnabledPrintSourceRegister: true,
76 isEnabledPrintDestinationRegister: true,
77 printSourceRegister: null,
78 printDestinationRegister: null,
81 var WebCPU_Instruction_MEM_Base = function(instrID){
87 }.extend(WebCPU_Instruction, {
88 loadArguments: function(argBinStr, baseIndex){
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)
97 setParameter: function(regR, pType, regP, reserved){
101 this.reserved = reserved;
105 var WebCPU_Instruction_TernaryOperation = function(instrID){
109 //演算結果はすべて符号ありであることに注意
110 this.instrID = instrID;
115 }.extend(WebCPU_Instruction, {
140 loadArguments: function(argBinStr, baseIndex){
142 this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
143 this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 1),
144 this.fetchUnsignedInteger(argBinStr, baseIndex, 2, 1)
146 if(this.instruction == WebCPU_Instruction_TernaryOperation.base.prototype.instruction){
151 setParameter: function(destReg, srcReg0, srcReg1){
152 if(this.instrID === undefined){
153 throw "setParameter:instrID undefined";
158 if(this.instrID == 0x10){
161 this.mnemonic = "CP";
162 this.instruction = this.instrCP;
163 this.printSourceRegister = this.printSourceRegisterCP;
166 this.mnemonic = this.mnemonicList1[0];
167 this.instruction = this.instrOR;
169 } else if(0x11 <= this.instrID && this.instrID <= 0x1B){
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){
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){
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;
186 instrCP: function(env){
187 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1];
189 instrOR: function(env){
190 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] | env.registers.Integer[this.reg2];
192 instrXOR: function(env){
193 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] ^ env.registers.Integer[this.reg2];
195 instrAND: function(env){
196 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2];
198 instrADD: function(env){
199 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] + env.registers.Integer[this.reg2];
201 instrSUB: function(env){
202 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] - env.registers.Integer[this.reg2];
204 instrMUL: function(env){
205 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] * env.registers.Integer[this.reg2];
207 instrSHL: function(env){
208 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] << env.registers.Integer[this.reg2];
210 instrSAR: function(env){
211 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] >> env.registers.Integer[this.reg2];
213 instrDIV: function(env){
214 env.registers.Integer[this.reg0] = parseInt(env.registers.Integer[this.reg1] / env.registers.Integer[this.reg2]);
216 instrMOD: function(env){
217 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] % env.registers.Integer[this.reg2];
220 instrCMPE: function(env){
221 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] == env.registers.Integer[this.reg2]) ? -1 : 0;
223 instrCMPNE: function(env){
224 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] != env.registers.Integer[this.reg2]) ? -1 : 0;
226 instrCMPL: function(env){
227 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] < env.registers.Integer[this.reg2]) ? -1 : 0;
229 instrCMPGE: function(env){
230 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] >= env.registers.Integer[this.reg2]) ? -1 : 0;
232 instrCMPLE: function(env){
233 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] <= env.registers.Integer[this.reg2]) ? -1 : 0;
235 instrCMPG: function(env){
236 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] > env.registers.Integer[this.reg2]) ? -1 : 0;
238 instrTSTZ: function(env){
239 env.registers.Integer[this.reg0] = ((env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2]) == 0) ? -1 : 0;
241 instrTSTNZ: function(env){
242 env.registers.Integer[this.reg0] = ((env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2]) != 0) ? -1 : 0;
245 instrP: function(env){
246 if(env.registers.Pointer[this.reg1].verifySameMemoryPageAs(env.registers.Pointer[this.reg2])){
249 throw new WebCPU_Exception(2, ["Attempt to compare pointers in different memoyPage."]);
253 instrPCMPE: function(env){
254 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset == env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
256 instrPCMPNE: function(env){
257 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset != env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
259 instrPCMPL: function(env){
260 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset < env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
262 instrPCMPGE: function(env){
263 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset >= env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
265 instrPCMPLE: function(env){
266 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset <= env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
268 instrPCMPG: function(env){
269 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset > env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
272 createBinaryString: function(env){
273 return toHexString8(this.instrID) + toHexString8(this.reg0) + toHexString8(this.reg1) + toHexString8(this.reg2);
275 toString: function(){
276 if(this.mnemonic == "CP"){
277 return this.makeBinaryOperandString("CP", "R", this.reg0, "R", this.reg1);
279 if(this.mnemonic == "UD"){
280 return "Undefined();";
282 if(0x28 <= this.instrID && this.instrID <= 0x2D){
283 return this.makeTernaryOperandString(this.mnemonic, "R", this.reg0, "P", this.reg1, "P", this.reg2);
285 return this.makeTernaryOperandString(this.mnemonic, "R", this.reg0, "R", this.reg1, "R", this.reg2);
288 printSourceRegister: function(env){
289 this.printRReg(env, this.reg1);
290 this.printRReg(env, this.reg2);
292 printSourceRegisterP: function(env){
293 this.printPReg(env, this.reg1);
294 this.printPReg(env, this.reg2);
296 printSourceRegisterCP: function(env){
297 this.printPReg(env, this.reg1);
299 printDestinationRegister: function(env){
300 this.printRReg(env, this.reg0);