OSDN Git Service

ccd51c20898b7f92b322fb6cfbdc3840f65173aa
[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.printSourceRegister){
23                         this.printSourceRegister(env);
24                 }
25                 this.instruction(env);
26                 if(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         printSourceRegister: null,
76         printDestinationRegister: null,
77 }
78
79 var WebCPU_Instruction_MEM_Base = function(instrID){
80         //メモリ関連命令共通部分
81         this.reg0R = 0;
82         this.typ32 = 0;
83         this.reg1P = 0;
84         this.reserved = 0;
85 }.extend(WebCPU_Instruction, {
86         loadArguments: function(argBinStr, baseIndex){
87                 this.setParameter(
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)
92                 );
93                 return 8;
94         },
95         setParameter: function(regR, pType, regP, reserved){
96                 this.reg0R = regR;
97                 this.typ32 = pType;
98                 this.reg1P = regP;
99                 this.reserved = reserved;
100         },
101 });
102
103 var WebCPU_Instruction_TernaryOperation = function(instrID){
104         //単純代入命令
105         //三項演算命令
106         //整数比較命令
107         //演算結果はすべて符号ありであることに注意
108         this.instrID = instrID;
109         this.reg0 = 0;
110         this.reg1 = 0;
111         this.reg2 = 0;
112         this.subfunc = null;
113 }.extend(WebCPU_Instruction, {
114         mnemonicList1: [
115                 "OR",
116                 "XOR",
117                 "AND",
118                 "UD",
119                 "ADD",
120                 "SUB",
121                 "MUL",
122                 "UD",
123                 "SHL",
124                 "SAR",
125                 "DIV",
126                 "MOD",
127         ],
128         mnemonicList2: [
129                 "CMPE",
130                 "CMPNE",
131                 "CMPL",
132                 "CMPGE",
133                 "CMPLE",
134                 "CMPG",
135                 "TSTZ",
136                 "TSTNZ",
137         ],
138         loadArguments: function(argBinStr, baseIndex){
139                 this.setParameter(
140                         this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
141                         this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 1),
142                         this.fetchUnsignedInteger(argBinStr, baseIndex, 2, 1)
143                 );
144                 if(this.instruction == WebCPU_Instruction_TernaryOperation.base.prototype.instruction){
145                         return 1;
146                 }
147                 return 4;
148         },
149         setParameter: function(destReg, srcReg0, srcReg1){
150                 if(this.instrID === undefined){
151                         throw "setParameter:instrID undefined";
152                 }
153                 this.reg0 = destReg;
154                 this.reg1 = srcReg0;
155                 this.reg2 = srcReg1;
156                 if(this.instrID == 0x10){
157                         if(srcReg1 == 0xFF){
158                                 //CP
159                                 this.mnemonic = "CP";
160                                 this.instruction = this.instrCP;
161                                 this.printSourceRegister = this.printSourceRegisterCP;
162                         } else{
163                                 //OR
164                                 this.mnemonic = this.mnemonicList1[0];
165                                 this.instruction = this.instrOR;
166                         }
167                 } else if(0x11 <= this.instrID && this.instrID <= 0x1B){
168                         // list1
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){
172                         //list2
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){
176                         //list2P
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;
181                 }
182         },
183         //
184         instrCP: function(env){
185                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1];
186         },
187         instrOR: function(env){
188                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] | env.registers.Integer[this.reg2];
189         },
190         instrXOR: function(env){
191                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] ^ env.registers.Integer[this.reg2];
192         },
193         instrAND: function(env){
194                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2];
195         },
196         instrADD: function(env){
197                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] + env.registers.Integer[this.reg2];
198         },
199         instrSUB: function(env){
200                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] - env.registers.Integer[this.reg2];
201         },
202         instrMUL: function(env){
203                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] * env.registers.Integer[this.reg2];
204         },
205         instrSHL: function(env){
206                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] << env.registers.Integer[this.reg2];
207         },
208         instrSAR: function(env){
209                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] >> env.registers.Integer[this.reg2];
210         },
211         instrDIV: function(env){
212                 env.registers.Integer[this.reg0] = parseInt(env.registers.Integer[this.reg1] / env.registers.Integer[this.reg2]);
213         },
214         instrMOD: function(env){
215                 env.registers.Integer[this.reg0] = env.registers.Integer[this.reg1] % env.registers.Integer[this.reg2];
216         },
217         //
218         instrCMPE: function(env){
219                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] == env.registers.Integer[this.reg2]) ? -1 : 0;
220         },
221         instrCMPNE: function(env){
222                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] != env.registers.Integer[this.reg2]) ? -1 : 0;
223         },
224         instrCMPL: function(env){
225                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] < env.registers.Integer[this.reg2]) ? -1 : 0;
226         },
227         instrCMPGE: function(env){
228                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] >= env.registers.Integer[this.reg2]) ? -1 : 0;
229         },
230         instrCMPLE: function(env){
231                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] <= env.registers.Integer[this.reg2]) ? -1 : 0;
232         },
233         instrCMPG: function(env){
234                 env.registers.Integer[this.reg0] = (env.registers.Integer[this.reg1] > env.registers.Integer[this.reg2]) ? -1 : 0;
235         },
236         instrTSTZ: function(env){
237                 env.registers.Integer[this.reg0] = ((env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2]) == 0) ? -1 : 0;
238         },
239         instrTSTNZ: function(env){
240                 env.registers.Integer[this.reg0] = ((env.registers.Integer[this.reg1] & env.registers.Integer[this.reg2]) != 0) ? -1 : 0;
241         },
242         //
243         instrP: function(env){
244                 if(env.registers.Pointer[this.reg1].verifySameMemoryPageAs(env.registers.Pointer[this.reg2])){
245                         this.subfunc(env);
246                 } else{
247                         throw new WebCPU_Exception(2, ["Attempt to compare pointers in different memoyPage."]);
248                 }
249         },
250         //
251         instrPCMPE: function(env){
252                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset == env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
253         },
254         instrPCMPNE: function(env){
255                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset != env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
256         },
257         instrPCMPL: function(env){
258                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset < env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
259         },
260         instrPCMPGE: function(env){
261                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset >= env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
262         },
263         instrPCMPLE: function(env){
264                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset <= env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
265         },
266         instrPCMPG: function(env){
267                 env.registers.Integer[this.reg0] = (env.registers.Pointer[this.reg1].addressOffset > env.registers.Pointer[this.reg2].addressOffset) ? -1 : 0;
268         },
269         //
270         createBinaryString: function(env){
271                 return toHexString8(this.instrID) + toHexString8(this.reg0) + toHexString8(this.reg1) + toHexString8(this.reg2);
272         },
273         toString: function(){
274                 if(this.mnemonic == "CP"){
275                         return this.makeBinaryOperandString("CP", "R", this.reg0, "R", this.reg1);
276                 }
277                 if(this.mnemonic == "UD"){
278                         return "Undefined();";
279                 }
280                 if(0x28 <= this.instrID && this.instrID <= 0x2D){
281                         return this.makeTernaryOperandString(this.mnemonic, "R", this.reg0, "P", this.reg1, "P", this.reg2);
282                 }
283                 return this.makeTernaryOperandString(this.mnemonic, "R", this.reg0, "R", this.reg1, "R", this.reg2);
284         },
285         //
286         printSourceRegister: function(env){
287                 this.printRReg(env, this.reg1);
288                 this.printRReg(env, this.reg2);
289         },
290         printSourceRegisterP: function(env){
291                 this.printPReg(env, this.reg1);
292                 this.printPReg(env, this.reg2);
293         },
294         printSourceRegisterCP: function(env){
295                 this.printPReg(env, this.reg1);
296         },
297         printDestinationRegister: function(env){
298                 this.printRReg(env, this.reg0);
299         },
300 });