OSDN Git Service

自動追尾を再実装。
[chnosproject/AI004.git] / webcpu / instr.js
1 //
2 // Instructions
3 //
4
5 //未定義の命令(WebCPU_Instructionと同値)
6 var WebCPU_Instruction_Undefined = WebCPU_Instruction;
7
8 var WebCPU_Instruction_NOP = function(instrID){
9         //何もしない命令
10 }.extend(WebCPU_Instruction, {
11         loadArguments: function(argBinStr, baseIndex){
12                 return 1;
13         },
14         instruction: function(env){
15                 //no operation
16         },
17         createBinaryString: function(env){
18                 return "00";
19         },
20         toString: function(){
21                 return "NOP();";
22         },
23 });
24
25 var WebCPU_Instruction_LB = function(instrID){
26         //ラベル定義命令
27         this.opt = 0;
28         this.imm32 = null;
29         this.passCount = 0;
30 }.extend(WebCPU_Instruction, {
31         loadArguments: function(argBinStr, baseIndex){
32                 this.setParameter(
33                         this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1), 
34                         this.fetchSignedInteger(argBinStr, baseIndex, 1, 4)
35                 );
36                 return 6;
37         },
38         setParameter: function(opt, labelID){
39                 this.opt = opt;
40                 this.imm32 = labelID;
41         },
42         instruction: function(env){
43                 this.passCount++;
44         },
45         createBinaryString: function(env){
46                 return "01" + toHexString8(this.opt) + toHexString32(this.imm32);
47         },
48         toString: function(){
49                 return this.makeBinaryOperandString("LB", "opt:0x", this.opt, "0x", this.imm32);
50         },
51 });
52
53 var WebCPU_Instruction_LIMM = function(instrID){
54         //定数即値代入命令
55         this.reg0 = 0;
56         this.imm32 = 0;
57 }.extend(WebCPU_Instruction, {
58         loadArguments: function(argBinStr, baseIndex){
59                 this.setParameter(
60                         this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
61                         this.fetchSignedInteger(argBinStr, baseIndex, 1, 4)
62                 );
63                 return 6;
64         },
65         setParameter: function(destReg, imm32){
66                 this.reg0 = destReg;
67                 this.imm32 = imm32;
68         },
69         instruction: function(env){
70                 env.registers.Integer[this.reg0] = this.imm32;
71         },
72         createBinaryString: function(env){
73                 return "02" + toHexString8(this.reg0) + toHexString32(this.imm32);
74         },
75         toString: function(){
76                 return this.makeBinaryOperandString("LIMM", "R", this.reg0, "0x", this.imm32);
77         },
78 });
79
80 var WebCPU_Instruction_PLIMM = function(instrID){
81         //ラベル番号代入命令
82         this.reg0 = 0;
83         this.imm32 = 0;
84 }.extend(WebCPU_Instruction, {
85         loadArguments: function(argBinStr, baseIndex){
86                 this.setParameter(
87                         this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
88                         this.fetchSignedInteger(argBinStr, baseIndex, 1, 4)
89                 );
90                 return 6;
91         },
92         setParameter: function(destReg, imm32){
93                 this.reg0 = destReg;
94                 this.imm32 = imm32;
95         },
96         instruction: function(env){
97                 var m = env.mainMemory.getMemoryPageInstanceFromLabelNumber(this.imm32);
98                 if(m === undefined){
99                         throw new WebCPU_Exception(2, ["Label#0x" + this.imm32.toString(16).toUpperCase() + " notfound."]);
100                 } else{
101                         env.registers.Pointer[this.reg0] = new WebCPU_Pointer(m);
102                         if(this.reg0 == 0x3F){
103                                 //goto
104                                 env.memoryPageCounter = env.mainMemory.getMemoryPageCountFromMemoryPageInstance(m);
105                                 env.memoryInstructionCounter = 0;
106                                 env.message("JMP:page " + env.memoryPageCounter+ "\n", 20);
107                         }
108                 }
109         },
110         createBinaryString: function(env){
111                 return "03" + toHexString8(this.reg0) + toHexString32(this.imm32);
112         },
113         toString: function(){
114                 return this.makeBinaryOperandString("PLIMM", "P", this.reg0, "0x", this.imm32);
115         },
116 });
117
118 var WebCPU_Instruction_CND = function(instrID){
119         //条件実行プリフィクス命令
120         this.reg0R = 0;
121 }.extend(WebCPU_Instruction, {
122         loadArguments: function(argBinStr, baseIndex){
123                 this.setParameter(
124                         this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1)
125                 );
126                 return 2;
127         },
128         setParameter: function(reg){
129                 this.reg0R = reg;
130         },
131         instruction: function(env){
132                 if((env.registers.Integer[this.reg0R] & 0x01) != 0x01){
133                         env.memoryInstructionCounter++;
134                 }
135         },
136         createBinaryString: function(env){
137                 return "04" + toHexString8(this.reg0R);
138         },
139         toString: function(){
140                 return this.makeUnaryOperandString("CND", "R", this.reg0R);
141         },
142 });
143
144 var WebCPU_Instruction_LMEM = function(instrID){
145         //メモリ読み込み命令
146         WebCPU_Instruction_LMEM.base.apply(this, arguments);
147 }.extend(WebCPU_Instruction_MEM_Base, {
148         instruction: function(env){
149                 var pointer = env.registers.Pointer[this.reg1P];
150                 if(this.typ32 == pointer.memoryType){
151                         var v = env.registers.Pointer[this.reg1P].readData(env);
152                         env.message("Memory:Read:" + pointer.toString() + ":" + v + "\n", 20);
153                         if(v !== undefined){
154                                 env.registers.Integer[this.reg0R] = v;
155                         }
156                 } else{
157                         throw new WebCPU_Exception(2, ["Conflict type of pointer."]);
158                 }
159         },
160         createBinaryString: function(env){
161                 return "08" + toHexString8(this.reg0R) + toHexString32(this.typ32) + toHexString8(this.reg1P) + "00";
162         },
163         toString: function(){
164                 return this.makeQuaternaryOperandString("LMEM", "R", this.reg0R, "typ:0x", this.typ32, "P", this.reg1P, "reserved:0x", this.reserved);
165         },
166 });
167
168 var WebCPU_Instruction_SMEM = function(instrID){
169         //メモリ書き込み命令
170         WebCPU_Instruction_SMEM.base.apply(this, arguments);
171 }.extend(WebCPU_Instruction_MEM_Base, {
172         instruction: function(env){
173                 var pointer = env.registers.Pointer[this.reg1P];
174                 if(this.typ32 == pointer.memoryType){
175                         var d = env.registers.Integer[this.reg0R];
176                         if(this.typ32 == 0x03){
177                                 //UINT8
178                                 d &= 0xff;
179                         } else if(this.typ32 == 0x06){
180                                 //SINT32
181                                 //register native
182                         } else if(this.typ32 == 0x07){
183                                 //UINT32
184                                 if(d < 0){
185                                         d = (0xffffffff >> 1) + d;
186                                 }
187                                 d &= 0xffffffff;
188                         } else if(this.typ32 == 0x09){
189                                 //UINT4
190                                 d &= 0xf;
191                         } else{
192                                 throw new WebCPU_Exception(0, ["Not implemented data type: 0x" + this.typ32.toString(16)]);
193                         }
194                         if(d != env.registers.Integer[this.reg0R]){
195                                 env.message("Data lost in type conversion 0x" + env.registers.Integer[this.reg0R].toString(16) + " to:0x" + d.toString(16));
196                         }
197                         env.message("Memory:Write:" + pointer.toString() + ":" + d +"\n", 20);
198                         env.registers.Pointer[this.reg1P].writeData(env, d);
199                 } else{
200                         throw new WebCPU_Exception(2, ["Conflict type of pointer."]);
201                 }
202         },
203         createBinaryString: function(env){
204                 return "09" + toHexString8(this.reg0R) + toHexString32(this.typ32) + toHexString8(this.reg1P) + "00";
205         },
206         toString: function(){
207                 return this.makeQuaternaryOperandString("SMEM", "R", this.reg0R, "typ:0x", this.typ32, "P", this.reg1P, "reserved:0x", this.reserved);
208         },
209 });
210
211 var WebCPU_Instruction_PADD = function(instrID){
212         //ポインタ演算命令
213         this.reg0P = 0;
214         this.typ32 = 0;
215         this.reg1P = 0;
216         this.reg2R = 0;
217 }.extend(WebCPU_Instruction, {
218         loadArguments: function(argBinStr, baseIndex){
219                 this.setParameter(
220                         this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
221                         this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 4),
222                         this.fetchUnsignedInteger(argBinStr, baseIndex, 5, 1),
223                         this.fetchUnsignedInteger(argBinStr, baseIndex, 6, 1)
224                 );
225                 return 8;
226         },
227         setParameter: function(regPdest, pType, regPsrc, regR){
228                 this.reg0P = regPdest;
229                 this.typ32 = pType;
230                 this.reg1P = regPsrc;
231                 this.reg2R = regR;
232         },
233         instruction: function(env){
234                 if(this.reg0P != this.reg1P){
235                         env.registers.Pointer[this.reg0P] = env.registers.Pointer[this.reg1P].getCopy();
236                 }
237                 env.registers.Pointer[this.reg0P].addressOffset += env.registers.Integer[this.reg2R];
238         },
239         createBinaryString: function(env){
240                 return "0E" + toHexString8(this.reg0P) + toHexString32(this.typ32) + toHexString8(this.reg1P) + toHexString8(this.reg2R);
241         },
242         toString: function(){
243                 return this.makeQuaternaryOperandString("PADD", "P", this.reg0P, "typ:0x", this.typ32, "P", this.reg1P, "R", this.reg2R);
244         },
245 });
246
247 var WebCPU_Instruction_PDIF = function(instrID){
248         //ポインタ演算命令
249         this.reg0R = 0;
250         this.typ32 = 0;
251         this.reg1P = 0;
252         this.reg2P = 0;
253 }.extend(WebCPU_Instruction, {
254         loadArguments: function(argBinStr, baseIndex){
255                 this.setParameter(
256                         this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
257                         this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 4),
258                         this.fetchUnsignedInteger(argBinStr, baseIndex, 5, 1),
259                         this.fetchUnsignedInteger(argBinStr, baseIndex, 6, 1)
260                 );
261                 return 8;
262         },
263         setParameter: function(regR, pType, reg1P, reg2P){
264                 this.reg0R = regR;
265                 this.typ32 = pType;
266                 this.reg1P = reg1P;
267                 this.reg2P = reg2P;
268         },
269         instruction: function(env){
270                 throw new WebCPU_Exception(0, ["Not implemented:" + this.toString()]);
271         },
272         createBinaryString: function(env){
273                 return "0F" + toHexString8(this.reg0R) + toHexString32(this.typ32) + toHexString8(this.reg1P) + toHexString8(this.reg2P);
274         },
275         toString: function(){
276                 return this.makeQuaternaryOperandString("PDIF", "R", this.reg0R, "typ:0x", this.typ32, "P", this.reg1P, "P", this.reg2P);
277         },
278 });
279
280 var WebCPU_Instruction_PCP = function(instrID){
281         //ポインタ代入命令
282         //P3Fへの代入でJMP
283         this.reg0P = 0;
284         this.reg1P = 0;
285 }.extend(WebCPU_Instruction, {
286         loadArguments: function(argBinStr, baseIndex){
287                 this.setParameter(
288                         this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1),
289                         this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 1)
290                 );
291                 return 3;
292         },
293         setParameter: function(regPdest, regPsrc){
294                 this.reg0P = regPdest;
295                 this.reg1P = regPsrc;
296         },
297         instruction: function(env){
298                 if(this.reg0P != this.reg1P){
299                         env.registers.Pointer[this.reg0P] = env.registers.Pointer[this.reg1P].getCopy();
300                         if(this.reg0P == 0x3F){
301                                 //P3Fへの代入でJMP
302                                 var type = env.registers.Pointer[0x3F].memoryType;
303                                 if(type == 0x01){
304                                         //VPtr
305                                         env.goToPointerRegister(0x3F);
306                                 } else if(type == 0xC0FFEE){
307                                         //API
308                                         env.API.executeAPI(env);
309                                 } else{
310                                         throw new WebCPU_Exception(2, ["Attempt transfering execution to data section."]);
311                                 }
312                         }
313                         
314                 }
315         },
316         createBinaryString: function(env){
317                 return "1E" + toHexString8(this.reg0P) + toHexString8(this.reg1P);
318         },
319         toString: function(){
320                 return this.makeBinaryOperandString("PCP", "P", this.reg0P, "P", this.reg1P);
321         },
322 });
323
324 var WebCPU_Instruction_MALLOC = function(instrID){
325         //メモリ確保命令
326         this.reg0P = 0;
327         this.reg1R = 0; //型
328         this.reg2R = 0; //指定された型でのデータの個数
329 }.extend(WebCPU_Instruction, {
330         loadArguments: function(argBinStr, baseIndex){
331                 this.reg0P = this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1);
332                 this.reg1R = this.fetchUnsignedInteger(argBinStr, baseIndex, 1, 1);
333                 this.reg2R = this.fetchUnsignedInteger(argBinStr, baseIndex, 2, 1);
334                 return 4;
335         },
336         instruction: function(env){
337                 var m = env.mainMemory.allocateMemoryPage(env.registers.Integer[this.reg1R], env.registers.Integer[this.reg2R]);
338                 env.registers.Pointer[this.reg0P] = new WebCPU_Pointer(m);
339         },
340         createBinaryString: function(env){
341                 return "32" + toHexString8(this.reg0P) + toHexString8(this.reg1R) + toHexString8(this.reg2R);
342         },
343         toString: function(){
344                 return this.makeTernaryOperandString("MALLOC", "P", this.reg0P, "R", this.reg1R, "R", this.reg2R);
345         },
346 });
347
348 var WebCPU_Instruction_DATA = function(instrID){
349         //データ記述命令
350         this.type = 0;
351         this.length = 0;        //指定された型でのデータの個数
352         this.byteLength = 0;    //バイト単位でのデータ部分の長さ
353         this.dataStr = null;
354         this.data = null;
355 }.extend(WebCPU_Instruction, {
356         loadArguments: function(argBinStr, baseIndex){
357                 this.type = this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 4);
358                 //指定された型での個数
359                 this.length = this.fetchUnsignedInteger(argBinStr, baseIndex, 4, 4);
360                 this.data = new Array();
361                 if(this.type == 0x03){
362                         //UINT8
363                         this.byteLength = this.length;
364                         this.dataStr = argBinStr.substr(baseIndex + 8 * 2, this.byteLength * 2);
365                         for(var i = 0; i < this.length; i++){
366                                 this.data.push(parseInt(this.dataStr.substr(i * 2, 2), 16));
367                         }
368                 } else if(this.type == 0x06){
369                         //SINT32
370                         this.byteLength = this.length * 4;
371                         this.dataStr = argBinStr.substr(baseIndex + 8 * 2, this.byteLength * 2);
372                         for(var i = 0; i < this.length; i++){
373                                 this.data.push(parseSignedInt32(this.dataStr.substr(i * 2 * 4, 4), 16));
374                         }
375                 } else if(this.type == 0x07){
376                         //UINT32
377                         this.byteLength = this.length * 4;
378                         this.dataStr = argBinStr.substr(baseIndex + 8 * 2, this.byteLength * 2);
379                         for(var i = 0; i < this.length; i++){
380                                 this.data.push(parseInt(this.dataStr.substr(i * 2 * 4, 4), 16));
381                         }
382                 } else if(this.type == 0x09){
383                         //UINT4
384                         this.byteLength = Math.ceil(this.length / 2);
385                         this.dataStr = argBinStr.substr(baseIndex + 8 * 2, this.byteLength * 2);
386                         for(var i = 0; i < this.length; i++){
387                                 this.data.push(parseInt(this.dataStr.substr(i, 1), 16));
388                         }
389                 } else{
390                         return ("DATA:Not implemented data type: 0x" + this.type.toString(16));
391                 }
392                 return 1 + 4 + 4 + this.byteLength;
393         },
394         instruction: function(env){
395                 //nothing
396         },
397         createBinaryString: function(env){
398                 return "34" + toHexString32(this.type) + toHexString32(this.length) + this.dataStr;
399         },
400         toString: function(){
401                 return this.makeBinaryOperandString("DATA", "type:0x", this.type, "length:0x", this.length) + "[" + this.dataStr +"]";
402         },
403 });
404
405 var WebCPU_Instruction_REMARK = function(instrID){
406         //リマーク命令
407         this.remLen = 0;
408         this.remStr = null;
409 }.extend(WebCPU_Instruction, {
410         loadArguments: function(argBinStr, baseIndex){
411                 this.remLen = this.fetchUnsignedInteger(argBinStr, baseIndex, 0, 1);
412                 this.remStr = argBinStr.substr(baseIndex + 1 * 2, this.remLen * 2);
413                 return 2 + this.remLen;
414         },
415         instruction: function(env){
416                 //nothing
417         },
418         createBinaryString: function(env){
419                 return "FE" + toHexString8(this.remLen) + this.remStr;
420         },
421         toString: function(){
422                 return this.makeUnaryOperandString("REMARK", "len:0x", this.remLen) + "[" + this.remStr +"]";
423         },
424 });