OSDN Git Service

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