1 // $Id: opcodes.c,v 1.20 2004/12/22 12:40:07 iain Exp $
6 static void parseModeNibbles (git_uint32* pc, int numModes, int * modeBuffer)
8 int * mode = modeBuffer;
13 git_uint32 byte = memRead8((*pc)++);
16 *mode++ = byte & 0x0f;
19 // Check whether we need to load any more.
24 *mode++ = (byte >> 4) & 0x0f;
29 static void parseLS (git_uint32* pc, Label op)
32 parseModeNibbles (pc, 2, modes);
34 parseLoad (pc, reg_L1, modes [0], size32, NULL);
36 parseStore (pc, reg_S1, modes [1], size32);
38 static void parseLLS (git_uint32* pc, Label op)
41 parseModeNibbles (pc, 3, modes);
43 parseLoad (pc, reg_L1, modes [0], size32, NULL);
44 parseLoad (pc, reg_L2, modes [1], size32, NULL);
46 parseStore (pc, reg_S1, modes [2], size32);
48 static void parseLLSS (git_uint32* pc, Label op)
51 parseModeNibbles (pc, 4, modes);
53 parseLoad (pc, reg_L1, modes [0], size32, NULL);
54 parseLoad (pc, reg_L2, modes [1], size32, NULL);
56 parseStore (pc, reg_S1, modes [2], size32);
57 parseStore (pc, reg_S2, modes [3], size32);
59 static void parseL (git_uint32* pc, Label op)
62 parseModeNibbles (pc, 1, modes);
64 parseLoad (pc, reg_L1, modes [0], size32, NULL);
67 static void parseLL (git_uint32* pc, Label op)
70 parseModeNibbles (pc, 2, modes);
72 parseLoad (pc, reg_L1, modes [0], size32, NULL);
73 parseLoad (pc, reg_L2, modes [1], size32, NULL);
76 static void parse_finish_branch (git_uint32* pc, Label op, LoadReg reg, int mode)
79 if (parseLoad (pc, reg, mode, size32, &val))
81 // The branch offset is a constant, so we can
82 // check for the special values 0 and 1 right here.
86 emitCode (op - label_jeq_var + label_jeq_return0);
90 emitCode (op - label_jeq_var + label_jeq_return1);
94 // Calculate the destination address and
95 // emit a constant branch opcode.
96 emitConstBranch (op - label_jeq_var + label_jeq_const, *pc + val - 2);
101 // The branch offset isn't a constant, so just
102 // emit the normal opcode plus the current PC.
108 static void parseLLLL_branch (git_uint32* pc, Label op)
111 parseModeNibbles (pc, 4, modes);
113 parseLoad (pc, reg_L1, modes [0], size32, NULL);
114 parseLoad (pc, reg_L2, modes [1], size32, NULL);
115 parseLoad (pc, reg_L3, modes [2], size32, NULL);
116 parse_finish_branch (pc, op, reg_L4, modes [3]);
118 static void parseLLL_branch (git_uint32* pc, Label op)
121 parseModeNibbles (pc, 3, modes);
123 parseLoad (pc, reg_L1, modes [0], size32, NULL);
124 parseLoad (pc, reg_L2, modes [1], size32, NULL);
125 parse_finish_branch (pc, op, reg_L3, modes [2]);
127 static void parseLL_branch (git_uint32* pc, Label op)
130 parseModeNibbles (pc, 2, modes);
132 parseLoad (pc, reg_L1, modes [0], size32, NULL);
133 parse_finish_branch (pc, op, reg_L2, modes [1]);
135 static void parseL_branch (git_uint32* pc, Label op)
138 parseModeNibbles (pc, 1, modes);
140 parse_finish_branch (pc, op, reg_L1, modes [0]);
142 static void parseLLL (git_uint32* pc, Label op)
145 parseModeNibbles (pc, 3, modes);
147 parseLoad (pc, reg_L1, modes [0], size32, NULL);
148 parseLoad (pc, reg_L2, modes [1], size32, NULL);
149 parseLoad (pc, reg_L3, modes [2], size32, NULL);
152 static void parseS (git_uint32* pc, Label op)
155 parseModeNibbles (pc, 1, modes);
158 parseStore (pc, reg_S1, modes [0], size32);
160 static void parseSS (git_uint32* pc, Label op)
163 parseModeNibbles (pc, 2, modes);
166 parseStore (pc, reg_S1, modes [0], size32);
167 parseStore (pc, reg_S2, modes [1], size32);
169 static void parseCatch (git_uint32 * pc)
172 parseModeNibbles (pc, 2, modes);
174 parseCatchStub (pc, modes);
176 void parseInstruction (git_uint32* pc, int * done)
178 git_uint32 pcStart = *pc;
186 opcode = memRead8((*pc)++);
188 // Check for multi-byte opcode.
195 opcode = (opcode << 8) | memRead8((*pc)++);
196 opcode = (opcode << 8) | memRead8((*pc)++);
197 opcode = (opcode << 8) | memRead8((*pc)++);
203 opcode = (opcode << 8) | memRead8((*pc)++);
209 emitCode (label_debug_step);
214 // printf (" opcode=0x%x", opcode);
216 // Now we have an opcode number,
217 // parse the operands and emit code.
221 case op_nop: emitCode (label_nop); break;
223 // Arithmetic and logic
225 case op_add: parseLLS (pc, label_add_discard); break;
226 case op_sub: parseLLS (pc, label_sub_discard); break;
227 case op_mul: parseLLS (pc, label_mul_discard); break;
228 case op_div: parseLLS (pc, label_div_discard); break;
229 case op_mod: parseLLS (pc, label_mod_discard); break;
231 case op_bitand: parseLLS (pc, label_bitand_discard); break;
232 case op_bitor: parseLLS (pc, label_bitor_discard); break;
233 case op_bitxor: parseLLS (pc, label_bitxor_discard); break;
235 case op_neg: parseLS (pc, label_neg_discard); break;
236 case op_bitnot: parseLS (pc, label_bitnot_discard); break;
238 case op_shiftl: parseLLS (pc, label_shiftl_discard); break;
239 case op_ushiftr: parseLLS (pc, label_ushiftr_discard); break;
240 case op_sshiftr: parseLLS (pc, label_sshiftr_discard); break;
244 case op_jump: parseL_branch (pc, label_jump_var); *done = 1; break;
245 case op_jz: parseLL_branch (pc, label_jz_var); break;
246 case op_jnz: parseLL_branch (pc, label_jnz_var); break;
247 case op_jeq: parseLLL_branch (pc, label_jeq_var); break;
248 case op_jne: parseLLL_branch (pc, label_jne_var); break;
249 case op_jlt: parseLLL_branch (pc, label_jlt_var); break;
250 case op_jgt: parseLLL_branch (pc, label_jgt_var); break;
251 case op_jle: parseLLL_branch (pc, label_jle_var); break;
252 case op_jge: parseLLL_branch (pc, label_jge_var); break;
253 case op_jltu: parseLLL_branch (pc, label_jltu_var); break;
254 case op_jgtu: parseLLL_branch (pc, label_jgtu_var); break;
255 case op_jleu: parseLLL_branch (pc, label_jleu_var); break;
256 case op_jgeu: parseLLL_branch (pc, label_jgeu_var); break;
258 case op_jumpabs: parseL (pc, label_jumpabs); *done = 1; break;
263 parseModeNibbles (pc, 2, modes);
264 parseLoad (pc, reg_L1, modes [0], size32, NULL);
265 parseStore (pc, reg_S1, modes [1], size32);
269 parseModeNibbles (pc, 2, modes);
270 parseLoad (pc, reg_L1, modes [0], size16, NULL);
271 emitCode (label_copys_discard);
272 parseStore (pc, reg_S1, modes [1], size16);
276 parseModeNibbles (pc, 2, modes);
277 parseLoad (pc, reg_L1, modes [0], size8, NULL);
278 emitCode (label_copyb_discard);
279 parseStore (pc, reg_S1, modes [1], size8);
282 case op_sexs: parseLS (pc, label_sexs_discard); break;
283 case op_sexb: parseLS (pc, label_sexb_discard); break;
287 case op_aload: parseLLS (pc, label_aload_discard); break;
288 case op_aloads: parseLLS (pc, label_aloads_discard); break;
289 case op_aloadb: parseLLS (pc, label_aloadb_discard); break;
290 case op_aloadbit: parseLLS (pc, label_aloadbit_discard); break;
292 case op_astore: parseLLL (pc, label_astore); break;
293 case op_astores: parseLLL (pc, label_astores); break;
294 case op_astoreb: parseLLL (pc, label_astoreb); break;
295 case op_astorebit: parseLLL (pc, label_astorebit); break;
299 case op_stkcount: parseS (pc, label_stkcount); break;
300 case op_stkpeek: parseLS (pc, label_stkpeek); break;
301 case op_stkswap: emitCode (label_stkswap); break;
302 case op_stkcopy: parseL (pc, label_stkcopy); break;
303 case op_stkroll: parseLL (pc, label_stkroll); break;
308 parseModeNibbles (pc, 3, modes);
309 parseLoad (pc, reg_L1, modes [0], size32, NULL);
310 parseLoad (pc, reg_L2, modes [1], size32, NULL);
311 emitCode (label_args_stack);
312 parseCallStub (pc, modes [2]);
316 parseModeNibbles (pc, 2, modes);
317 parseLoad (pc, reg_L1, modes [0], size32, NULL);
318 emitCode (label_args_0);
319 parseCallStub (pc, modes [1]);
323 parseModeNibbles (pc, 3, modes);
324 parseLoad (pc, reg_L1, modes [0], size32, NULL);
325 parseLoad (pc, reg_L2, modes [1], size32, NULL);
326 emitCode (label_args_1);
327 parseCallStub (pc, modes [2]);
331 parseModeNibbles (pc, 4, modes);
332 parseLoad (pc, reg_L1, modes [0], size32, NULL);
333 parseLoad (pc, reg_L2, modes [1], size32, NULL);
334 parseLoad (pc, reg_L3, modes [2], size32, NULL);
335 emitCode (label_args_2);
336 parseCallStub (pc, modes [3]);
340 parseModeNibbles (pc, 5, modes);
341 parseLoad (pc, reg_L1, modes [0], size32, NULL);
342 parseLoad (pc, reg_L2, modes [1], size32, NULL);
343 parseLoad (pc, reg_L3, modes [2], size32, NULL);
344 parseLoad (pc, reg_L4, modes [3], size32, NULL);
345 emitCode (label_args_3);
346 parseCallStub (pc, modes [4]);
350 parseL (pc, label_return);
355 parseModeNibbles (pc, 2, modes);
356 parseLoad (pc, reg_L1, modes [0], size32, NULL);
357 parseLoad (pc, reg_L2, modes [1], size32, NULL);
358 emitCode (label_args_stack);
359 emitCode (label_tailcall);
365 case op_catch: parseCatch (pc); break;
367 parseLL (pc, label_throw);
371 case op_random: parseLS (pc, label_random); break;
372 case op_setrandom: parseL (pc, label_setrandom); break;
374 case op_getmemsize: parseS (pc, label_getmemsize); break;
375 case op_setmemsize: parseLS (pc, label_setmemsize); break;
378 emitCode (label_quit);
383 emitCode (label_restart);
387 case op_restore: parseLS (pc, label_restore); break;
388 case op_restoreundo: parseS (pc, label_restoreundo); break;
389 case op_protect: parseLL (pc, label_protect); break;
390 case op_verify: parseS (pc, label_verify); break;
393 parseModeNibbles (pc, 2, modes);
394 parseLoad (pc, reg_L1, modes [0], size32, NULL);
395 parseSaveStub (pc, modes [1]);
399 parseModeNibbles (pc, 1, modes);
400 parseUndoStub (pc, modes [0]);
403 case op_getiosys: parseSS (pc, label_getiosys); break;
404 case op_setiosys: parseLL (pc, label_setiosys); break;
406 case op_getstringtbl: parseS (pc, label_getstringtbl); break;
407 case op_setstringtbl: parseL (pc, label_setstringtbl); break;
409 case op_streamchar: parseL (pc, label_streamchar); emitData(*pc); break;
410 case op_streamnum: parseL (pc, label_streamnum); emitData(*pc); break;
411 case op_streamstr: parseL (pc, label_streamstr); emitData(*pc); break;
412 case op_streamunichar: parseL (pc, label_streamunichar); emitData(*pc); break;
414 case op_glk: parseLLS (pc, label_glk); break;
415 case op_gestalt: parseLLS (pc, label_gestalt); break;
417 case op_binarysearch:
418 case op_linearsearch:
419 parseModeNibbles (pc, 8, modes);
420 parseLoad (pc, reg_L1, modes [0], size32, NULL);
421 parseLoad (pc, reg_L2, modes [1], size32, NULL);
422 parseLoad (pc, reg_L3, modes [2], size32, NULL);
423 parseLoad (pc, reg_L4, modes [3], size32, NULL);
424 parseLoad (pc, reg_L5, modes [4], size32, NULL);
425 parseLoad (pc, reg_L6, modes [5], size32, NULL);
426 parseLoad (pc, reg_L7, modes [6], size32, NULL);
427 emitCode (opcode == op_linearsearch ? label_linearsearch : label_binarysearch);
428 parseStore (pc, reg_S1, modes [7], size32);
431 case op_linkedsearch:
432 parseModeNibbles (pc, 7, modes);
433 parseLoad (pc, reg_L1, modes [0], size32, NULL);
434 parseLoad (pc, reg_L2, modes [1], size32, NULL);
435 parseLoad (pc, reg_L3, modes [2], size32, NULL);
436 parseLoad (pc, reg_L4, modes [3], size32, NULL);
437 parseLoad (pc, reg_L5, modes [4], size32, NULL);
438 parseLoad (pc, reg_L6, modes [5], size32, NULL);
439 emitCode (label_linkedsearch);
440 parseStore (pc, reg_S1, modes [6], size32);
444 parseL (pc, label_debugtrap);
449 case op_mzero: parseLL (pc, label_mzero); break;
450 case op_mcopy: parseLLL (pc, label_mcopy); break;
452 case op_malloc: parseLS (pc, label_malloc); break;
453 case op_mfree: parseL (pc, label_mfree); break;
455 // Function acceleration
457 case op_accelfunc: parseLL (pc, label_accelfunc); break;
458 case op_accelparam: parseLL (pc, label_accelparam); break;
462 case op_numtof: parseLS (pc, label_numtof); break;
463 case op_ftonumz: parseLS (pc, label_ftonumz); break;
464 case op_ftonumn: parseLS (pc, label_ftonumn); break;
465 case op_ceil: parseLS (pc, label_ceil); break;
466 case op_floor: parseLS (pc, label_floor); break;
467 case op_sqrt: parseLS (pc, label_sqrt); break;
468 case op_exp: parseLS (pc, label_exp); break;
469 case op_log: parseLS (pc, label_log); break;
471 case op_fadd: parseLLS (pc, label_fadd_discard); break;
472 case op_fsub: parseLLS (pc, label_fsub_discard); break;
473 case op_fmul: parseLLS (pc, label_fmul_discard); break;
474 case op_fdiv: parseLLS (pc, label_fdiv_discard); break;
475 case op_pow: parseLLS (pc, label_pow); break;
476 case op_atan2: parseLLS (pc, label_atan2); break;
478 case op_fmod: parseLLSS (pc, label_fmod); break;
480 case op_sin: parseLS (pc, label_sin); break;
481 case op_cos: parseLS (pc, label_cos); break;
482 case op_tan: parseLS (pc, label_tan); break;
483 case op_asin: parseLS (pc, label_asin); break;
484 case op_acos: parseLS (pc, label_acos); break;
485 case op_atan: parseLS (pc, label_atan); break;
487 case op_jfeq: parseLLLL_branch (pc, label_jfeq_var); break;
488 case op_jfne: parseLLLL_branch (pc, label_jfne_var); break;
490 case op_jflt: parseLLL_branch (pc, label_jflt_var); break;
491 case op_jfle: parseLLL_branch (pc, label_jfle_var); break;
492 case op_jfgt: parseLLL_branch (pc, label_jfgt_var); break;
493 case op_jfge: parseLLL_branch (pc, label_jfge_var); break;
495 case op_jisnan: parseLL_branch (pc, label_jisnan_var); break;
496 case op_jisinf: parseLL_branch (pc, label_jisinf_var); break;
498 // Special Git opcodes
500 case op_git_setcacheram: parseL (pc, label_git_setcacheram); break;
501 case op_git_prunecache: parseLL (pc, label_git_prunecache); break;